···8383/* Skip over an SSN. */8484void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn);85858686+void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *, __u32);8687#endif /* __sctp_ulpqueue_h__ */87888889
+6-1
net/sctp/associola.c
···727727 break;728728729729 case SCTP_TRANSPORT_DOWN:730730- transport->state = SCTP_INACTIVE;730730+ /* if the transort was never confirmed, do not transition it731731+ * to inactive state.732732+ */733733+ if (transport->state != SCTP_UNCONFIRMED)734734+ transport->state = SCTP_INACTIVE;735735+731736 spc_state = SCTP_ADDR_UNREACHABLE;732737 break;733738
+7
net/sctp/outqueue.c
···421421 */422422 if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||423423 (!fast_retransmit && !chunk->tsn_gap_acked)) {424424+ /* If this chunk was sent less then 1 rto ago, do not425425+ * retransmit this chunk, but give the peer time426426+ * to acknowlege it.427427+ */428428+ if ((jiffies - chunk->sent_at) < transport->rto)429429+ continue;430430+424431 /* RFC 2960 6.2.1 Processing a Received SACK425432 *426433 * C) Any time a DATA chunk is marked for
+77-35
net/sctp/sm_make_chunk.c
···110110 * abort chunk.111111 */112112void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,113113- const void *payload, size_t paylen)113113+ size_t paylen)114114{115115 sctp_errhdr_t err;116116 __u16 len;···120120 len = sizeof(sctp_errhdr_t) + paylen;121121 err.length = htons(len);122122 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);123123- sctp_addto_chunk(chunk, paylen, payload);124123}125124126125/* 3.3.2 Initiation (INIT) (1)···779780780781 /* Put the tsn back into network byte order. */781782 payload = htonl(tsn);782782- sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload,783783- sizeof(payload));783783+ sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));784784+ sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);784785785786 /* RFC 2960 6.4 Multi-homed SCTP Endpoints786787 *···822823 goto err_copy;823824 }824825825825- sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);826826+ sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);827827+ sctp_addto_chunk(retval, paylen, payload);826828827829 if (paylen)828830 kfree(payload);···850850 struct sctp_paramhdr phdr;851851852852 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen853853- + sizeof(sctp_chunkhdr_t));853853+ + sizeof(sctp_paramhdr_t));854854 if (!retval)855855 goto end;856856857857- sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen);857857+ sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen858858+ + sizeof(sctp_paramhdr_t));858859859860 phdr.type = htons(chunk->chunk_hdr->type);860861 phdr.length = chunk->chunk_hdr->length;861861- sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr);862862+ sctp_addto_chunk(retval, paylen, payload);863863+ sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);862864863865end:864866 return retval;···957955 if (!retval)958956 goto nodata;959957960960- sctp_init_cause(retval, cause_code, payload, paylen);958958+ sctp_init_cause(retval, cause_code, paylen);959959+ sctp_addto_chunk(retval, paylen, payload);961960962961nodata:963962 return retval;···11311128 void *target;11321129 void *padding;11331130 int chunklen = ntohs(chunk->chunk_hdr->length);11341134- int padlen = chunklen % 4;11311131+ int padlen = WORD_ROUND(chunklen) - chunklen;1135113211361133 padding = skb_put(chunk->skb, padlen);11371134 target = skb_put(chunk->skb, len);···1141113811421139 /* Adjust the chunk length field. */11431140 chunk->chunk_hdr->length = htons(chunklen + padlen + len);11411141+ chunk->chunk_end = skb_tail_pointer(chunk->skb);11421142+11431143+ return target;11441144+}11451145+11461146+/* Append bytes to the end of a parameter. Will panic if chunk is not big11471147+ * enough.11481148+ */11491149+void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data)11501150+{11511151+ void *target;11521152+ int chunklen = ntohs(chunk->chunk_hdr->length);11531153+11541154+ target = skb_put(chunk->skb, len);11551155+11561156+ memcpy(target, data, len);11571157+11581158+ /* Adjust the chunk length field. */11591159+ chunk->chunk_hdr->length = htons(chunklen + len);11441160 chunk->chunk_end = skb_tail_pointer(chunk->skb);1145116111461162 return target;···11961174 */11971175void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)11981176{11771177+ struct sctp_datamsg *msg;11781178+ struct sctp_chunk *lchunk;11791179+ struct sctp_stream *stream;11991180 __u16 ssn;12001181 __u16 sid;1201118212021183 if (chunk->has_ssn)12031184 return;1204118512051205- /* This is the last possible instant to assign a SSN. */12061206- if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {12071207- ssn = 0;12081208- } else {12091209- sid = ntohs(chunk->subh.data_hdr->stream);12101210- if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)12111211- ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);12121212- else12131213- ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);12141214- }11861186+ /* All fragments will be on the same stream */11871187+ sid = ntohs(chunk->subh.data_hdr->stream);11881188+ stream = &chunk->asoc->ssnmap->out;1215118912161216- chunk->subh.data_hdr->ssn = htons(ssn);12171217- chunk->has_ssn = 1;11901190+ /* Now assign the sequence number to the entire message.11911191+ * All fragments must have the same stream sequence number.11921192+ */11931193+ msg = chunk->msg;11941194+ list_for_each_entry(lchunk, &msg->chunks, frag_list) {11951195+ if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {11961196+ ssn = 0;11971197+ } else {11981198+ if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)11991199+ ssn = sctp_ssn_next(stream, sid);12001200+ else12011201+ ssn = sctp_ssn_peek(stream, sid);12021202+ }12031203+12041204+ lchunk->subh.data_hdr->ssn = htons(ssn);12051205+ lchunk->has_ssn = 1;12061206+ }12181207}1219120812201209/* Helper function to assign a TSN if needed. This assumes that both···14991466 __be32 n = htonl(usecs);1500146715011468 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,15021502- &n, sizeof(n));14691469+ sizeof(n));14701470+ sctp_addto_chunk(*errp, sizeof(n), &n);15031471 *error = -SCTP_IERROR_STALE_COOKIE;15041472 } else15051473 *error = -SCTP_IERROR_NOMEM;···15901556 report.num_missing = htonl(1);15911557 report.type = paramtype;15921558 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,15931593- &report, sizeof(report));15591559+ sizeof(report));15601560+ sctp_addto_chunk(*errp, sizeof(report), &report);15941561 }1595156215961563 /* Stop processing this chunk. */···16091574 *errp = sctp_make_op_error_space(asoc, chunk, 0);1610157516111576 if (*errp)16121612- sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);15771577+ sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0);1613157816141579 /* Stop processing this chunk. */16151580 return 0;···16301595 *errp = sctp_make_op_error_space(asoc, chunk, payload_len);1631159616321597 if (*errp) {16331633- sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,16341634- sizeof(error));16351635- sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);15981598+ sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,15991599+ sizeof(error) + sizeof(sctp_paramhdr_t));16001600+ sctp_addto_chunk(*errp, sizeof(error), error);16011601+ sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);16361602 }1637160316381604 return 0;···16541618 if (!*errp)16551619 *errp = sctp_make_op_error_space(asoc, chunk, len);1656162016571657- if (*errp)16581658- sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,16591659- param.v, len);16211621+ if (*errp) {16221622+ sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);16231623+ sctp_addto_chunk(*errp, len, param.v);16241624+ }1660162516611626 /* Stop processing this chunk. */16621627 return 0;···17091672 *errp = sctp_make_op_error_space(asoc, chunk,17101673 ntohs(chunk->chunk_hdr->length));1711167417121712- if (*errp)16751675+ if (*errp) {17131676 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,17141714- param.v,17151677 WORD_ROUND(ntohs(param.p->length)));16781678+ sctp_addto_chunk(*errp,16791679+ WORD_ROUND(ntohs(param.p->length)),16801680+ param.v);16811681+ }1716168217171683 break;17181684 case SCTP_PARAM_ACTION_SKIP:···1730169017311691 if (*errp) {17321692 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,17331733- param.v,17341693 WORD_ROUND(ntohs(param.p->length)));16941694+ sctp_addto_chunk(*errp,16951695+ WORD_ROUND(ntohs(param.p->length)),16961696+ param.v);17351697 } else {17361698 /* If there is no memory for generating the ERROR17371699 * report as specified, an ABORT will be triggered···18331791 * VIOLATION error. We build the ERROR chunk here and let the normal18341792 * error handling code build and send the packet.18351793 */18361836- if (param.v < (void*)chunk->chunk_end - sizeof(sctp_paramhdr_t)) {17941794+ if (param.v != (void*)chunk->chunk_end) {18371795 sctp_process_inv_paramlength(asoc, param.p, chunk, errp);18381796 return 0;18391797 }
+6-2
net/sctp/sm_sideeffect.c
···10131013 break;1014101410151015 case SCTP_DISPOSITION_VIOLATION:10161016- printk(KERN_ERR "sctp protocol violation state %d "10171017- "chunkid %d\n", state, subtype.chunk);10161016+ if (net_ratelimit())10171017+ printk(KERN_ERR "sctp protocol violation state %d "10181018+ "chunkid %d\n", state, subtype.chunk);10181019 break;1019102010201021 case SCTP_DISPOSITION_NOT_IMPL:···11301129 case SCTP_CMD_REPORT_FWDTSN:11311130 /* Move the Cumulattive TSN Ack ahead. */11321131 sctp_tsnmap_skip(&asoc->peer.tsn_map, cmd->obj.u32);11321132+11331133+ /* purge the fragmentation queue */11341134+ sctp_ulpq_reasm_flushtsn(&asoc->ulpq, cmd->obj.u32);1133113511341136 /* Abort any in progress partial delivery. */11351137 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
+26-25
net/sctp/sm_statefuns.c
···264264 struct sctp_chunk *err_chunk;265265 struct sctp_packet *packet;266266 sctp_unrecognized_param_t *unk_param;267267- struct sock *sk;268267 int len;269268270269 /* 6.10 Bundling···282283 * control endpoint, respond with an ABORT.283284 */284285 if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)285285- return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);286286-287287- sk = ep->base.sk;288288- /* If the endpoint is not listening or if the number of associations289289- * on the TCP-style socket exceed the max backlog, respond with an290290- * ABORT.291291- */292292- if (!sctp_sstate(sk, LISTENING) ||293293- (sctp_style(sk, TCP) &&294294- sk_acceptq_is_full(sk)))295286 return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);296287297288 /* 3.1 A packet containing an INIT chunk MUST have a zero Verification···579590 struct sctp_ulpevent *ev, *ai_ev = NULL;580591 int error = 0;581592 struct sctp_chunk *err_chk_p;593593+ struct sock *sk;582594583595 /* If the packet is an OOTB packet which is temporarily on the584596 * control endpoint, respond with an ABORT.···594604 */595605 if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))596606 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);607607+608608+ /* If the endpoint is not listening or if the number of associations609609+ * on the TCP-style socket exceed the max backlog, respond with an610610+ * ABORT.611611+ */612612+ sk = ep->base.sk;613613+ if (!sctp_sstate(sk, LISTENING) ||614614+ (sctp_style(sk, TCP) && sk_acceptq_is_full(sk)))615615+ return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);597616598617 /* "Decode" the chunk. We have no optional parameters so we599618 * are in good shape.···10311032 /* This should never happen, but lets log it if so. */10321033 if (unlikely(!link)) {10331034 if (from_addr.sa.sa_family == AF_INET6) {10341034- printk(KERN_WARNING10351035- "%s association %p could not find address "10361036- NIP6_FMT "\n",10371037- __FUNCTION__,10381038- asoc,10391039- NIP6(from_addr.v6.sin6_addr));10351035+ if (net_ratelimit())10361036+ printk(KERN_WARNING10371037+ "%s association %p could not find address "10381038+ NIP6_FMT "\n",10391039+ __FUNCTION__,10401040+ asoc,10411041+ NIP6(from_addr.v6.sin6_addr));10401042 } else {10411041- printk(KERN_WARNING10421042- "%s association %p could not find address "10431043- NIPQUAD_FMT "\n",10441044- __FUNCTION__,10451045- asoc,10461046- NIPQUAD(from_addr.v4.sin_addr.s_addr));10431043+ if (net_ratelimit())10441044+ printk(KERN_WARNING10451045+ "%s association %p could not find address "10461046+ NIPQUAD_FMT "\n",10471047+ __FUNCTION__,10481048+ asoc,10491049+ NIPQUAD(from_addr.v4.sin_addr.s_addr));10471050 }10481051 return SCTP_DISPOSITION_DISCARD;10491052 }···33633362 abort = sctp_make_abort(asoc, asconf_ack,33643363 sizeof(sctp_errhdr_t));33653364 if (abort) {33663366- sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0);33653365+ sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0);33673366 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,33683367 SCTP_CHUNK(abort));33693368 }···33933392 abort = sctp_make_abort(asoc, asconf_ack,33943393 sizeof(sctp_errhdr_t));33953394 if (abort) {33963396- sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0);33953395+ sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0);33973396 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,33983397 SCTP_CHUNK(abort));33993398 }
+3
net/sctp/socket.c
···353353 * The function sctp_get_port_local() does duplicate address354354 * detection.355355 */356356+ addr->v4.sin_port = htons(snum);356357 if ((ret = sctp_get_port_local(sk, addr))) {357358 if (ret == (long) sk) {358359 /* This endpoint has a conflicting address. */···5203520252045203 sctp_unhash_endpoint(ep);52055204 sk->sk_state = SCTP_SS_CLOSED;52055205+ return 0;52065206 }5207520752085208 /* Return if we are already listening. */···5251524952525250 sctp_unhash_endpoint(ep);52535251 sk->sk_state = SCTP_SS_CLOSED;52525252+ return 0;52545253 }5255525452565255 if (sctp_sstate(sk, LISTENING))
+62-13
net/sctp/ulpqueue.c
···659659 return retval;660660}661661662662+/*663663+ * Flush out stale fragments from the reassembly queue when processing664664+ * a Forward TSN.665665+ *666666+ * RFC 3758, Section 3.6667667+ *668668+ * After receiving and processing a FORWARD TSN, the data receiver MUST669669+ * take cautions in updating its re-assembly queue. The receiver MUST670670+ * remove any partially reassembled message, which is still missing one671671+ * or more TSNs earlier than or equal to the new cumulative TSN point.672672+ * In the event that the receiver has invoked the partial delivery API,673673+ * a notification SHOULD also be generated to inform the upper layer API674674+ * that the message being partially delivered will NOT be completed.675675+ */676676+void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *ulpq, __u32 fwd_tsn)677677+{678678+ struct sk_buff *pos, *tmp;679679+ struct sctp_ulpevent *event;680680+ __u32 tsn;681681+682682+ if (skb_queue_empty(&ulpq->reasm))683683+ return;684684+685685+ skb_queue_walk_safe(&ulpq->reasm, pos, tmp) {686686+ event = sctp_skb2event(pos);687687+ tsn = event->tsn;688688+689689+ /* Since the entire message must be abandoned by the690690+ * sender (item A3 in Section 3.5, RFC 3758), we can691691+ * free all fragments on the list that are less then692692+ * or equal to ctsn_point693693+ */694694+ if (TSN_lte(tsn, fwd_tsn)) {695695+ __skb_unlink(pos, &ulpq->reasm);696696+ sctp_ulpevent_free(event);697697+ } else698698+ break;699699+ }700700+}701701+662702/* Helper function to gather skbs that have possibly become663703 * ordered by an an incoming chunk.664704 */···834794/* Helper function to gather skbs that have possibly become835795 * ordered by forward tsn skipping their dependencies.836796 */837837-static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq)797797+static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)838798{839799 struct sk_buff *pos, *tmp;840800 struct sctp_ulpevent *cevent;···853813 csid = cevent->stream;854814 cssn = cevent->ssn;855815856856- if (cssn != sctp_ssn_peek(in, csid))816816+ /* Have we gone too far? */817817+ if (csid > sid)857818 break;858819859859- /* Found it, so mark in the ssnmap. */860860- sctp_ssn_next(in, csid);820820+ /* Have we not gone far enough? */821821+ if (csid < sid)822822+ continue;823823+824824+ /* see if this ssn has been marked by skipping */825825+ if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))826826+ break;861827862828 __skb_unlink(pos, &ulpq->lobby);863863- if (!event) {829829+ if (!event)864830 /* Create a temporary list to collect chunks on. */865831 event = sctp_skb2event(pos);866866- __skb_queue_tail(&temp, sctp_event2skb(event));867867- } else {868868- /* Attach all gathered skbs to the event. */869869- __skb_queue_tail(&temp, pos);870870- }832832+833833+ /* Attach all gathered skbs to the event. */834834+ __skb_queue_tail(&temp, pos);871835 }872836873837 /* Send event to the ULP. 'event' is the sctp_ulpevent for874838 * very first SKB on the 'temp' list.875839 */876876- if (event)840840+ if (event) {841841+ /* see if we have more ordered that we can deliver */842842+ sctp_ulpq_retrieve_ordered(ulpq, event);877843 sctp_ulpq_tail_event(ulpq, event);844844+ }878845}879846880880-/* Skip over an SSN. */847847+/* Skip over an SSN. This is used during the processing of848848+ * Forwared TSN chunk to skip over the abandoned ordered data849849+ */881850void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn)882851{883852 struct sctp_stream *in;···904855 /* Go find any other chunks that were waiting for905856 * ordering and deliver them if needed.906857 */907907- sctp_ulpq_reap_ordered(ulpq);858858+ sctp_ulpq_reap_ordered(ulpq, sid);908859 return;909860}910861