diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 14 | ||||
-rw-r--r-- | net/sctp/debug.c | 5 | ||||
-rw-r--r-- | net/sctp/input.c | 51 | ||||
-rw-r--r-- | net/sctp/inqueue.c | 8 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 36 | ||||
-rw-r--r-- | net/sctp/output.c | 2 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 12 | ||||
-rw-r--r-- | net/sctp/protocol.c | 20 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 12 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 16 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 30 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 267 | ||||
-rw-r--r-- | net/sctp/transport.c | 2 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 49 | ||||
-rw-r--r-- | net/sctp/ulpqueue.c | 173 |
16 files changed, 532 insertions, 167 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 78d2ddb5ca18..db73ef97485a 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -143,7 +143,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
143 | /* Initialize the maximum mumber of new data packets that can be sent | 143 | /* Initialize the maximum mumber of new data packets that can be sent |
144 | * in a burst. | 144 | * in a burst. |
145 | */ | 145 | */ |
146 | asoc->max_burst = sctp_max_burst; | 146 | asoc->max_burst = sp->max_burst; |
147 | 147 | ||
148 | /* initialize association timers */ | 148 | /* initialize association timers */ |
149 | asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0; | 149 | asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0; |
@@ -714,8 +714,16 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
714 | /* Record the transition on the transport. */ | 714 | /* Record the transition on the transport. */ |
715 | switch (command) { | 715 | switch (command) { |
716 | case SCTP_TRANSPORT_UP: | 716 | case SCTP_TRANSPORT_UP: |
717 | /* If we are moving from UNCONFIRMED state due | ||
718 | * to heartbeat success, report the SCTP_ADDR_CONFIRMED | ||
719 | * state to the user, otherwise report SCTP_ADDR_AVAILABLE. | ||
720 | */ | ||
721 | if (SCTP_UNCONFIRMED == transport->state && | ||
722 | SCTP_HEARTBEAT_SUCCESS == error) | ||
723 | spc_state = SCTP_ADDR_CONFIRMED; | ||
724 | else | ||
725 | spc_state = SCTP_ADDR_AVAILABLE; | ||
717 | transport->state = SCTP_ACTIVE; | 726 | transport->state = SCTP_ACTIVE; |
718 | spc_state = SCTP_ADDR_AVAILABLE; | ||
719 | break; | 727 | break; |
720 | 728 | ||
721 | case SCTP_TRANSPORT_DOWN: | 729 | case SCTP_TRANSPORT_DOWN: |
@@ -725,7 +733,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
725 | 733 | ||
726 | default: | 734 | default: |
727 | return; | 735 | return; |
728 | }; | 736 | } |
729 | 737 | ||
730 | /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the | 738 | /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the |
731 | * user. | 739 | * user. |
diff --git a/net/sctp/debug.c b/net/sctp/debug.c index 5f5ab28977c9..e8c0f7435d7f 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c | |||
@@ -93,8 +93,9 @@ const char *sctp_cname(const sctp_subtype_t cid) | |||
93 | return "FWD_TSN"; | 93 | return "FWD_TSN"; |
94 | 94 | ||
95 | default: | 95 | default: |
96 | return "unknown chunk"; | 96 | break; |
97 | }; | 97 | } |
98 | |||
98 | return "unknown chunk"; | 99 | return "unknown chunk"; |
99 | } | 100 | } |
100 | 101 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index 71db66873695..885109fb3dda 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -79,14 +79,10 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); | |||
79 | /* Calculate the SCTP checksum of an SCTP packet. */ | 79 | /* Calculate the SCTP checksum of an SCTP packet. */ |
80 | static inline int sctp_rcv_checksum(struct sk_buff *skb) | 80 | static inline int sctp_rcv_checksum(struct sk_buff *skb) |
81 | { | 81 | { |
82 | struct sctphdr *sh; | ||
83 | __u32 cmp, val; | ||
84 | struct sk_buff *list = skb_shinfo(skb)->frag_list; | 82 | struct sk_buff *list = skb_shinfo(skb)->frag_list; |
85 | 83 | struct sctphdr *sh = sctp_hdr(skb); | |
86 | sh = (struct sctphdr *) skb->h.raw; | 84 | __u32 cmp = ntohl(sh->checksum); |
87 | cmp = ntohl(sh->checksum); | 85 | __u32 val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); |
88 | |||
89 | val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); | ||
90 | 86 | ||
91 | for (; list; list = list->next) | 87 | for (; list; list = list->next) |
92 | val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), | 88 | val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), |
@@ -138,14 +134,13 @@ int sctp_rcv(struct sk_buff *skb) | |||
138 | if (skb_linearize(skb)) | 134 | if (skb_linearize(skb)) |
139 | goto discard_it; | 135 | goto discard_it; |
140 | 136 | ||
141 | sh = (struct sctphdr *) skb->h.raw; | 137 | sh = sctp_hdr(skb); |
142 | 138 | ||
143 | /* Pull up the IP and SCTP headers. */ | 139 | /* Pull up the IP and SCTP headers. */ |
144 | __skb_pull(skb, skb->h.raw - skb->data); | 140 | __skb_pull(skb, skb_transport_offset(skb)); |
145 | if (skb->len < sizeof(struct sctphdr)) | 141 | if (skb->len < sizeof(struct sctphdr)) |
146 | goto discard_it; | 142 | goto discard_it; |
147 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY) && | 143 | if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0) |
148 | (sctp_rcv_checksum(skb) < 0)) | ||
149 | goto discard_it; | 144 | goto discard_it; |
150 | 145 | ||
151 | skb_pull(skb, sizeof(struct sctphdr)); | 146 | skb_pull(skb, sizeof(struct sctphdr)); |
@@ -154,7 +149,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
154 | if (skb->len < sizeof(struct sctp_chunkhdr)) | 149 | if (skb->len < sizeof(struct sctp_chunkhdr)) |
155 | goto discard_it; | 150 | goto discard_it; |
156 | 151 | ||
157 | family = ipver2af(skb->nh.iph->version); | 152 | family = ipver2af(ip_hdr(skb)->version); |
158 | af = sctp_get_af_specific(family); | 153 | af = sctp_get_af_specific(family); |
159 | if (unlikely(!af)) | 154 | if (unlikely(!af)) |
160 | goto discard_it; | 155 | goto discard_it; |
@@ -510,30 +505,30 @@ void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) | |||
510 | void sctp_v4_err(struct sk_buff *skb, __u32 info) | 505 | void sctp_v4_err(struct sk_buff *skb, __u32 info) |
511 | { | 506 | { |
512 | struct iphdr *iph = (struct iphdr *)skb->data; | 507 | struct iphdr *iph = (struct iphdr *)skb->data; |
513 | struct sctphdr *sh = (struct sctphdr *)(skb->data + (iph->ihl <<2)); | 508 | const int ihlen = iph->ihl * 4; |
514 | int type = skb->h.icmph->type; | 509 | const int type = icmp_hdr(skb)->type; |
515 | int code = skb->h.icmph->code; | 510 | const int code = icmp_hdr(skb)->code; |
516 | struct sock *sk; | 511 | struct sock *sk; |
517 | struct sctp_association *asoc = NULL; | 512 | struct sctp_association *asoc = NULL; |
518 | struct sctp_transport *transport; | 513 | struct sctp_transport *transport; |
519 | struct inet_sock *inet; | 514 | struct inet_sock *inet; |
520 | char *saveip, *savesctp; | 515 | sk_buff_data_t saveip, savesctp; |
521 | int err; | 516 | int err; |
522 | 517 | ||
523 | if (skb->len < ((iph->ihl << 2) + 8)) { | 518 | if (skb->len < ihlen + 8) { |
524 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 519 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
525 | return; | 520 | return; |
526 | } | 521 | } |
527 | 522 | ||
528 | /* Fix up skb to look at the embedded net header. */ | 523 | /* Fix up skb to look at the embedded net header. */ |
529 | saveip = skb->nh.raw; | 524 | saveip = skb->network_header; |
530 | savesctp = skb->h.raw; | 525 | savesctp = skb->transport_header; |
531 | skb->nh.iph = iph; | 526 | skb_reset_network_header(skb); |
532 | skb->h.raw = (char *)sh; | 527 | skb_set_transport_header(skb, ihlen); |
533 | sk = sctp_err_lookup(AF_INET, skb, sh, &asoc, &transport); | 528 | sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport); |
534 | /* Put back, the original pointers. */ | 529 | /* Put back, the original values. */ |
535 | skb->nh.raw = saveip; | 530 | skb->network_header = saveip; |
536 | skb->h.raw = savesctp; | 531 | skb->transport_header = savesctp; |
537 | if (!sk) { | 532 | if (!sk) { |
538 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 533 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
539 | return; | 534 | return; |
@@ -616,7 +611,7 @@ int sctp_rcv_ootb(struct sk_buff *skb) | |||
616 | break; | 611 | break; |
617 | 612 | ||
618 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); | 613 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
619 | if (ch_end > skb->tail) | 614 | if (ch_end > skb_tail_pointer(skb)) |
620 | break; | 615 | break; |
621 | 616 | ||
622 | /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the | 617 | /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the |
@@ -648,7 +643,7 @@ int sctp_rcv_ootb(struct sk_buff *skb) | |||
648 | } | 643 | } |
649 | 644 | ||
650 | ch = (sctp_chunkhdr_t *) ch_end; | 645 | ch = (sctp_chunkhdr_t *) ch_end; |
651 | } while (ch_end < skb->tail); | 646 | } while (ch_end < skb_tail_pointer(skb)); |
652 | 647 | ||
653 | return 0; | 648 | return 0; |
654 | 649 | ||
@@ -905,7 +900,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, | |||
905 | struct sctp_association *asoc; | 900 | struct sctp_association *asoc; |
906 | union sctp_addr addr; | 901 | union sctp_addr addr; |
907 | union sctp_addr *paddr = &addr; | 902 | union sctp_addr *paddr = &addr; |
908 | struct sctphdr *sh = (struct sctphdr *) skb->h.raw; | 903 | struct sctphdr *sh = sctp_hdr(skb); |
909 | sctp_chunkhdr_t *ch; | 904 | sctp_chunkhdr_t *ch; |
910 | union sctp_params params; | 905 | union sctp_params params; |
911 | sctp_init_chunk_t *init; | 906 | sctp_init_chunk_t *init; |
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index c30629e17781..88aa22407549 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c | |||
@@ -159,16 +159,16 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) | |||
159 | * the skb->tail. | 159 | * the skb->tail. |
160 | */ | 160 | */ |
161 | if (unlikely(skb_is_nonlinear(chunk->skb))) { | 161 | if (unlikely(skb_is_nonlinear(chunk->skb))) { |
162 | if (chunk->chunk_end > chunk->skb->tail) | 162 | if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) |
163 | chunk->chunk_end = chunk->skb->tail; | 163 | chunk->chunk_end = skb_tail_pointer(chunk->skb); |
164 | } | 164 | } |
165 | skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); | 165 | skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); |
166 | chunk->subh.v = NULL; /* Subheader is no longer valid. */ | 166 | chunk->subh.v = NULL; /* Subheader is no longer valid. */ |
167 | 167 | ||
168 | if (chunk->chunk_end < chunk->skb->tail) { | 168 | if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) { |
169 | /* This is not a singleton */ | 169 | /* This is not a singleton */ |
170 | chunk->singleton = 0; | 170 | chunk->singleton = 0; |
171 | } else if (chunk->chunk_end > chunk->skb->tail) { | 171 | } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) { |
172 | /* RFC 2960, Section 6.10 Bundling | 172 | /* RFC 2960, Section 6.10 Bundling |
173 | * | 173 | * |
174 | * Partial chunks MUST NOT be placed in an SCTP packet. | 174 | * Partial chunks MUST NOT be placed in an SCTP packet. |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 0b9c49b3a100..ca527a27dd05 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -122,26 +122,24 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
122 | int type, int code, int offset, __be32 info) | 122 | int type, int code, int offset, __be32 info) |
123 | { | 123 | { |
124 | struct inet6_dev *idev; | 124 | struct inet6_dev *idev; |
125 | struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; | ||
126 | struct sctphdr *sh = (struct sctphdr *)(skb->data + offset); | ||
127 | struct sock *sk; | 125 | struct sock *sk; |
128 | struct sctp_association *asoc; | 126 | struct sctp_association *asoc; |
129 | struct sctp_transport *transport; | 127 | struct sctp_transport *transport; |
130 | struct ipv6_pinfo *np; | 128 | struct ipv6_pinfo *np; |
131 | char *saveip, *savesctp; | 129 | sk_buff_data_t saveip, savesctp; |
132 | int err; | 130 | int err; |
133 | 131 | ||
134 | idev = in6_dev_get(skb->dev); | 132 | idev = in6_dev_get(skb->dev); |
135 | 133 | ||
136 | /* Fix up skb to look at the embedded net header. */ | 134 | /* Fix up skb to look at the embedded net header. */ |
137 | saveip = skb->nh.raw; | 135 | saveip = skb->network_header; |
138 | savesctp = skb->h.raw; | 136 | savesctp = skb->transport_header; |
139 | skb->nh.ipv6h = iph; | 137 | skb_reset_network_header(skb); |
140 | skb->h.raw = (char *)sh; | 138 | skb_set_transport_header(skb, offset); |
141 | sk = sctp_err_lookup(AF_INET6, skb, sh, &asoc, &transport); | 139 | sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport); |
142 | /* Put back, the original pointers. */ | 140 | /* Put back, the original pointers. */ |
143 | skb->nh.raw = saveip; | 141 | skb->network_header = saveip; |
144 | skb->h.raw = savesctp; | 142 | skb->transport_header = savesctp; |
145 | if (!sk) { | 143 | if (!sk) { |
146 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS); | 144 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS); |
147 | goto out; | 145 | goto out; |
@@ -391,13 +389,13 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, | |||
391 | addr->v6.sin6_flowinfo = 0; /* FIXME */ | 389 | addr->v6.sin6_flowinfo = 0; /* FIXME */ |
392 | addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif; | 390 | addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif; |
393 | 391 | ||
394 | sh = (struct sctphdr *) skb->h.raw; | 392 | sh = sctp_hdr(skb); |
395 | if (is_saddr) { | 393 | if (is_saddr) { |
396 | *port = sh->source; | 394 | *port = sh->source; |
397 | from = &skb->nh.ipv6h->saddr; | 395 | from = &ipv6_hdr(skb)->saddr; |
398 | } else { | 396 | } else { |
399 | *port = sh->dest; | 397 | *port = sh->dest; |
400 | from = &skb->nh.ipv6h->daddr; | 398 | from = &ipv6_hdr(skb)->daddr; |
401 | } | 399 | } |
402 | ipv6_addr_copy(&addr->v6.sin6_addr, from); | 400 | ipv6_addr_copy(&addr->v6.sin6_addr, from); |
403 | } | 401 | } |
@@ -606,7 +604,7 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr) | |||
606 | default: | 604 | default: |
607 | retval = SCTP_SCOPE_GLOBAL; | 605 | retval = SCTP_SCOPE_GLOBAL; |
608 | break; | 606 | break; |
609 | }; | 607 | } |
610 | 608 | ||
611 | return retval; | 609 | return retval; |
612 | } | 610 | } |
@@ -699,7 +697,7 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb) | |||
699 | /* Was this packet marked by Explicit Congestion Notification? */ | 697 | /* Was this packet marked by Explicit Congestion Notification? */ |
700 | static int sctp_v6_is_ce(const struct sk_buff *skb) | 698 | static int sctp_v6_is_ce(const struct sk_buff *skb) |
701 | { | 699 | { |
702 | return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20); | 700 | return *((__u32 *)(ipv6_hdr(skb))) & htonl(1 << 20); |
703 | } | 701 | } |
704 | 702 | ||
705 | /* Dump the v6 addr to the seq file. */ | 703 | /* Dump the v6 addr to the seq file. */ |
@@ -766,19 +764,19 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, | |||
766 | if (msgname) { | 764 | if (msgname) { |
767 | sctp_inet6_msgname(msgname, addr_len); | 765 | sctp_inet6_msgname(msgname, addr_len); |
768 | sin6 = (struct sockaddr_in6 *)msgname; | 766 | sin6 = (struct sockaddr_in6 *)msgname; |
769 | sh = (struct sctphdr *)skb->h.raw; | 767 | sh = sctp_hdr(skb); |
770 | sin6->sin6_port = sh->source; | 768 | sin6->sin6_port = sh->source; |
771 | 769 | ||
772 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 770 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
773 | if (sctp_sk(skb->sk)->v4mapped && | 771 | if (sctp_sk(skb->sk)->v4mapped && |
774 | skb->nh.iph->version == 4) { | 772 | ip_hdr(skb)->version == 4) { |
775 | sctp_v4_map_v6((union sctp_addr *)sin6); | 773 | sctp_v4_map_v6((union sctp_addr *)sin6); |
776 | sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr; | 774 | sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr; |
777 | return; | 775 | return; |
778 | } | 776 | } |
779 | 777 | ||
780 | /* Otherwise, just copy the v6 address. */ | 778 | /* Otherwise, just copy the v6 address. */ |
781 | ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); | 779 | ipv6_addr_copy(&sin6->sin6_addr, &ipv6_hdr(skb)->saddr); |
782 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { | 780 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { |
783 | struct sctp_ulpevent *ev = sctp_skb2event(skb); | 781 | struct sctp_ulpevent *ev = sctp_skb2event(skb); |
784 | sin6->sin6_scope_id = ev->iif; | 782 | sin6->sin6_scope_id = ev->iif; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index f875fc3ced54..d85543def754 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -176,7 +176,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, | |||
176 | case SCTP_XMIT_OK: | 176 | case SCTP_XMIT_OK: |
177 | case SCTP_XMIT_NAGLE_DELAY: | 177 | case SCTP_XMIT_NAGLE_DELAY: |
178 | break; | 178 | break; |
179 | }; | 179 | } |
180 | 180 | ||
181 | return retval; | 181 | return retval; |
182 | } | 182 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 41abfd17627e..992f361084b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -338,7 +338,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
338 | SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS); | 338 | SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS); |
339 | q->empty = 0; | 339 | q->empty = 0; |
340 | break; | 340 | break; |
341 | }; | 341 | } |
342 | } else { | 342 | } else { |
343 | list_add_tail(&chunk->list, &q->control_chunk_list); | 343 | list_add_tail(&chunk->list, &q->control_chunk_list); |
344 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 344 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); |
@@ -630,7 +630,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
630 | /* Retrieve a new chunk to bundle. */ | 630 | /* Retrieve a new chunk to bundle. */ |
631 | lchunk = sctp_list_dequeue(lqueue); | 631 | lchunk = sctp_list_dequeue(lqueue); |
632 | break; | 632 | break; |
633 | }; | 633 | } |
634 | 634 | ||
635 | /* If we are here due to a retransmit timeout or a fast | 635 | /* If we are here due to a retransmit timeout or a fast |
636 | * retransmit and if there are any chunks left in the retransmit | 636 | * retransmit and if there are any chunks left in the retransmit |
@@ -779,7 +779,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
779 | default: | 779 | default: |
780 | /* We built a chunk with an illegal type! */ | 780 | /* We built a chunk with an illegal type! */ |
781 | BUG(); | 781 | BUG(); |
782 | }; | 782 | } |
783 | } | 783 | } |
784 | 784 | ||
785 | /* Is it OK to send data chunks? */ | 785 | /* Is it OK to send data chunks? */ |
@@ -1397,7 +1397,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1397 | SCTP_DEBUG_PRINTK("ACKed: %08x", tsn); | 1397 | SCTP_DEBUG_PRINTK("ACKed: %08x", tsn); |
1398 | dbg_prt_state = 0; | 1398 | dbg_prt_state = 0; |
1399 | dbg_ack_tsn = tsn; | 1399 | dbg_ack_tsn = tsn; |
1400 | }; | 1400 | } |
1401 | 1401 | ||
1402 | dbg_last_ack_tsn = tsn; | 1402 | dbg_last_ack_tsn = tsn; |
1403 | #endif /* SCTP_DEBUG */ | 1403 | #endif /* SCTP_DEBUG */ |
@@ -1452,7 +1452,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1452 | SCTP_DEBUG_PRINTK("KEPT: %08x",tsn); | 1452 | SCTP_DEBUG_PRINTK("KEPT: %08x",tsn); |
1453 | dbg_prt_state = 1; | 1453 | dbg_prt_state = 1; |
1454 | dbg_kept_tsn = tsn; | 1454 | dbg_kept_tsn = tsn; |
1455 | }; | 1455 | } |
1456 | 1456 | ||
1457 | dbg_last_kept_tsn = tsn; | 1457 | dbg_last_kept_tsn = tsn; |
1458 | #endif /* SCTP_DEBUG */ | 1458 | #endif /* SCTP_DEBUG */ |
@@ -1476,7 +1476,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1476 | } else { | 1476 | } else { |
1477 | SCTP_DEBUG_PRINTK("\n"); | 1477 | SCTP_DEBUG_PRINTK("\n"); |
1478 | } | 1478 | } |
1479 | }; | 1479 | } |
1480 | #endif /* SCTP_DEBUG */ | 1480 | #endif /* SCTP_DEBUG */ |
1481 | if (transport) { | 1481 | if (transport) { |
1482 | if (bytes_acked) { | 1482 | if (bytes_acked) { |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index e17a823ca90f..c361deb6cea9 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -235,13 +235,13 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, | |||
235 | port = &addr->v4.sin_port; | 235 | port = &addr->v4.sin_port; |
236 | addr->v4.sin_family = AF_INET; | 236 | addr->v4.sin_family = AF_INET; |
237 | 237 | ||
238 | sh = (struct sctphdr *) skb->h.raw; | 238 | sh = sctp_hdr(skb); |
239 | if (is_saddr) { | 239 | if (is_saddr) { |
240 | *port = sh->source; | 240 | *port = sh->source; |
241 | from = &skb->nh.iph->saddr; | 241 | from = &ip_hdr(skb)->saddr; |
242 | } else { | 242 | } else { |
243 | *port = sh->dest; | 243 | *port = sh->dest; |
244 | from = &skb->nh.iph->daddr; | 244 | from = &ip_hdr(skb)->daddr; |
245 | } | 245 | } |
246 | memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); | 246 | memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); |
247 | } | 247 | } |
@@ -530,7 +530,7 @@ static int sctp_v4_skb_iif(const struct sk_buff *skb) | |||
530 | /* Was this packet marked by Explicit Congestion Notification? */ | 530 | /* Was this packet marked by Explicit Congestion Notification? */ |
531 | static int sctp_v4_is_ce(const struct sk_buff *skb) | 531 | static int sctp_v4_is_ce(const struct sk_buff *skb) |
532 | { | 532 | { |
533 | return INET_ECN_is_ce(skb->nh.iph->tos); | 533 | return INET_ECN_is_ce(ip_hdr(skb)->tos); |
534 | } | 534 | } |
535 | 535 | ||
536 | /* Create and initialize a new sk for the socket returned by accept(). */ | 536 | /* Create and initialize a new sk for the socket returned by accept(). */ |
@@ -731,15 +731,13 @@ static void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname, | |||
731 | /* Initialize and copy out a msgname from an inbound skb. */ | 731 | /* Initialize and copy out a msgname from an inbound skb. */ |
732 | static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) | 732 | static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) |
733 | { | 733 | { |
734 | struct sctphdr *sh; | ||
735 | struct sockaddr_in *sin; | ||
736 | |||
737 | if (msgname) { | 734 | if (msgname) { |
735 | struct sctphdr *sh = sctp_hdr(skb); | ||
736 | struct sockaddr_in *sin = (struct sockaddr_in *)msgname; | ||
737 | |||
738 | sctp_inet_msgname(msgname, len); | 738 | sctp_inet_msgname(msgname, len); |
739 | sin = (struct sockaddr_in *)msgname; | ||
740 | sh = (struct sctphdr *)skb->h.raw; | ||
741 | sin->sin_port = sh->source; | 739 | sin->sin_port = sh->source; |
742 | sin->sin_addr.s_addr = skb->nh.iph->saddr; | 740 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
743 | } | 741 | } |
744 | } | 742 | } |
745 | 743 | ||
@@ -1044,7 +1042,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1044 | sctp_cookie_preserve_enable = 1; | 1042 | sctp_cookie_preserve_enable = 1; |
1045 | 1043 | ||
1046 | /* Max.Burst - 4 */ | 1044 | /* Max.Burst - 4 */ |
1047 | sctp_max_burst = SCTP_MAX_BURST; | 1045 | sctp_max_burst = SCTP_DEFAULT_MAX_BURST; |
1048 | 1046 | ||
1049 | /* Association.Max.Retrans - 10 attempts | 1047 | /* Association.Max.Retrans - 10 attempts |
1050 | * Path.Max.Retrans - 5 attempts (per destination address) | 1048 | * Path.Max.Retrans - 5 attempts (per destination address) |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f7fb29d5a0c7..be783a3761c4 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -86,7 +86,7 @@ int sctp_chunk_iif(const struct sctp_chunk *chunk) | |||
86 | struct sctp_af *af; | 86 | struct sctp_af *af; |
87 | int iif = 0; | 87 | int iif = 0; |
88 | 88 | ||
89 | af = sctp_get_af_specific(ipver2af(chunk->skb->nh.iph->version)); | 89 | af = sctp_get_af_specific(ipver2af(ip_hdr(chunk->skb)->version)); |
90 | if (af) | 90 | if (af) |
91 | iif = af->skb_iif(chunk->skb); | 91 | iif = af->skb_iif(chunk->skb); |
92 | 92 | ||
@@ -1143,7 +1143,7 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) | |||
1143 | 1143 | ||
1144 | /* Adjust the chunk length field. */ | 1144 | /* Adjust the chunk length field. */ |
1145 | chunk->chunk_hdr->length = htons(chunklen + padlen + len); | 1145 | chunk->chunk_hdr->length = htons(chunklen + padlen + len); |
1146 | chunk->chunk_end = chunk->skb->tail; | 1146 | chunk->chunk_end = skb_tail_pointer(chunk->skb); |
1147 | 1147 | ||
1148 | return target; | 1148 | return target; |
1149 | } | 1149 | } |
@@ -1168,7 +1168,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, | |||
1168 | /* Adjust the chunk length field. */ | 1168 | /* Adjust the chunk length field. */ |
1169 | chunk->chunk_hdr->length = | 1169 | chunk->chunk_hdr->length = |
1170 | htons(ntohs(chunk->chunk_hdr->length) + len); | 1170 | htons(ntohs(chunk->chunk_hdr->length) + len); |
1171 | chunk->chunk_end = chunk->skb->tail; | 1171 | chunk->chunk_end = skb_tail_pointer(chunk->skb); |
1172 | 1172 | ||
1173 | out: | 1173 | out: |
1174 | return err; | 1174 | return err; |
@@ -1233,7 +1233,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, | |||
1233 | asoc->temp = 1; | 1233 | asoc->temp = 1; |
1234 | skb = chunk->skb; | 1234 | skb = chunk->skb; |
1235 | /* Create an entry for the source address of the packet. */ | 1235 | /* Create an entry for the source address of the packet. */ |
1236 | af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); | 1236 | af = sctp_get_af_specific(ipver2af(ip_hdr(skb)->version)); |
1237 | if (unlikely(!af)) | 1237 | if (unlikely(!af)) |
1238 | goto fail; | 1238 | goto fail; |
1239 | af->from_skb(&asoc->c.peer_addr, skb, 1); | 1239 | af->from_skb(&asoc->c.peer_addr, skb, 1); |
@@ -2077,7 +2077,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2077 | 2077 | ||
2078 | default: /* Just ignore anything else. */ | 2078 | default: /* Just ignore anything else. */ |
2079 | break; | 2079 | break; |
2080 | }; | 2080 | } |
2081 | } | 2081 | } |
2082 | break; | 2082 | break; |
2083 | 2083 | ||
@@ -2118,7 +2118,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2118 | SCTP_DEBUG_PRINTK("Ignoring param: %d for association %p.\n", | 2118 | SCTP_DEBUG_PRINTK("Ignoring param: %d for association %p.\n", |
2119 | ntohs(param.p->type), asoc); | 2119 | ntohs(param.p->type), asoc); |
2120 | break; | 2120 | break; |
2121 | }; | 2121 | } |
2122 | 2122 | ||
2123 | return retval; | 2123 | return retval; |
2124 | } | 2124 | } |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 135567493119..b37a7adeb150 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -464,7 +464,7 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands, | |||
464 | struct sctp_ulpevent *event; | 464 | struct sctp_ulpevent *event; |
465 | 465 | ||
466 | event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC, | 466 | event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC, |
467 | (__u16)error, 0, 0, | 467 | (__u16)error, 0, 0, NULL, |
468 | GFP_ATOMIC); | 468 | GFP_ATOMIC); |
469 | 469 | ||
470 | if (event) | 470 | if (event) |
@@ -492,8 +492,13 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, | |||
492 | /* Cancel any partial delivery in progress. */ | 492 | /* Cancel any partial delivery in progress. */ |
493 | sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); | 493 | sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); |
494 | 494 | ||
495 | event = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_LOST, | 495 | if (event_type == SCTP_EVENT_T_CHUNK && subtype.chunk == SCTP_CID_ABORT) |
496 | (__u16)error, 0, 0, | 496 | event = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_LOST, |
497 | (__u16)error, 0, 0, chunk, | ||
498 | GFP_ATOMIC); | ||
499 | else | ||
500 | event = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_LOST, | ||
501 | (__u16)error, 0, 0, NULL, | ||
497 | GFP_ATOMIC); | 502 | GFP_ATOMIC); |
498 | if (event) | 503 | if (event) |
499 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | 504 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
@@ -1004,7 +1009,7 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | |||
1004 | status, state, event_type, subtype.chunk); | 1009 | status, state, event_type, subtype.chunk); |
1005 | BUG(); | 1010 | BUG(); |
1006 | break; | 1011 | break; |
1007 | }; | 1012 | } |
1008 | 1013 | ||
1009 | bail: | 1014 | bail: |
1010 | return error; | 1015 | return error; |
@@ -1484,7 +1489,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1484 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1489 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1485 | cmd->verb, cmd->obj.ptr); | 1490 | cmd->verb, cmd->obj.ptr); |
1486 | break; | 1491 | break; |
1487 | }; | 1492 | } |
1493 | |||
1488 | if (error) | 1494 | if (error) |
1489 | break; | 1495 | break; |
1490 | } | 1496 | } |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index e9097cf614ba..9e28a5d51200 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -186,7 +186,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
186 | * notification is passed to the upper layer. | 186 | * notification is passed to the upper layer. |
187 | */ | 187 | */ |
188 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, | 188 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, |
189 | 0, 0, 0, GFP_ATOMIC); | 189 | 0, 0, 0, NULL, GFP_ATOMIC); |
190 | if (ev) | 190 | if (ev) |
191 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | 191 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
192 | SCTP_ULPEVENT(ev)); | 192 | SCTP_ULPEVENT(ev)); |
@@ -629,7 +629,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
629 | case -SCTP_IERROR_BAD_SIG: | 629 | case -SCTP_IERROR_BAD_SIG: |
630 | default: | 630 | default: |
631 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 631 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
632 | }; | 632 | } |
633 | } | 633 | } |
634 | 634 | ||
635 | 635 | ||
@@ -661,7 +661,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
661 | ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0, | 661 | ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0, |
662 | new_asoc->c.sinit_num_ostreams, | 662 | new_asoc->c.sinit_num_ostreams, |
663 | new_asoc->c.sinit_max_instreams, | 663 | new_asoc->c.sinit_max_instreams, |
664 | GFP_ATOMIC); | 664 | NULL, GFP_ATOMIC); |
665 | if (!ev) | 665 | if (!ev) |
666 | goto nomem_ev; | 666 | goto nomem_ev; |
667 | 667 | ||
@@ -790,7 +790,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
790 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, | 790 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, |
791 | 0, asoc->c.sinit_num_ostreams, | 791 | 0, asoc->c.sinit_num_ostreams, |
792 | asoc->c.sinit_max_instreams, | 792 | asoc->c.sinit_max_instreams, |
793 | GFP_ATOMIC); | 793 | NULL, GFP_ATOMIC); |
794 | 794 | ||
795 | if (!ev) | 795 | if (!ev) |
796 | goto nomem; | 796 | goto nomem; |
@@ -1195,7 +1195,7 @@ static void sctp_tietags_populate(struct sctp_association *new_asoc, | |||
1195 | new_asoc->c.my_ttag = asoc->c.my_vtag; | 1195 | new_asoc->c.my_ttag = asoc->c.my_vtag; |
1196 | new_asoc->c.peer_ttag = asoc->c.peer_vtag; | 1196 | new_asoc->c.peer_ttag = asoc->c.peer_vtag; |
1197 | break; | 1197 | break; |
1198 | }; | 1198 | } |
1199 | 1199 | ||
1200 | /* Other parameters for the endpoint SHOULD be copied from the | 1200 | /* Other parameters for the endpoint SHOULD be copied from the |
1201 | * existing parameters of the association (e.g. number of | 1201 | * existing parameters of the association (e.g. number of |
@@ -1625,7 +1625,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1625 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, | 1625 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, |
1626 | new_asoc->c.sinit_num_ostreams, | 1626 | new_asoc->c.sinit_num_ostreams, |
1627 | new_asoc->c.sinit_max_instreams, | 1627 | new_asoc->c.sinit_max_instreams, |
1628 | GFP_ATOMIC); | 1628 | NULL, GFP_ATOMIC); |
1629 | if (!ev) | 1629 | if (!ev) |
1630 | goto nomem_ev; | 1630 | goto nomem_ev; |
1631 | 1631 | ||
@@ -1691,7 +1691,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1691 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 0, | 1691 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 0, |
1692 | new_asoc->c.sinit_num_ostreams, | 1692 | new_asoc->c.sinit_num_ostreams, |
1693 | new_asoc->c.sinit_max_instreams, | 1693 | new_asoc->c.sinit_max_instreams, |
1694 | GFP_ATOMIC); | 1694 | NULL, GFP_ATOMIC); |
1695 | if (!ev) | 1695 | if (!ev) |
1696 | goto nomem_ev; | 1696 | goto nomem_ev; |
1697 | 1697 | ||
@@ -1786,7 +1786,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1786 | SCTP_COMM_UP, 0, | 1786 | SCTP_COMM_UP, 0, |
1787 | asoc->c.sinit_num_ostreams, | 1787 | asoc->c.sinit_num_ostreams, |
1788 | asoc->c.sinit_max_instreams, | 1788 | asoc->c.sinit_max_instreams, |
1789 | GFP_ATOMIC); | 1789 | NULL, GFP_ATOMIC); |
1790 | if (!ev) | 1790 | if (!ev) |
1791 | goto nomem; | 1791 | goto nomem; |
1792 | 1792 | ||
@@ -1904,7 +1904,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
1904 | case -SCTP_IERROR_BAD_SIG: | 1904 | case -SCTP_IERROR_BAD_SIG: |
1905 | default: | 1905 | default: |
1906 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 1906 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
1907 | }; | 1907 | } |
1908 | } | 1908 | } |
1909 | 1909 | ||
1910 | /* Compare the tie_tag in cookie with the verification tag of | 1910 | /* Compare the tie_tag in cookie with the verification tag of |
@@ -1936,7 +1936,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
1936 | default: /* Discard packet for all others. */ | 1936 | default: /* Discard packet for all others. */ |
1937 | retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 1937 | retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
1938 | break; | 1938 | break; |
1939 | }; | 1939 | } |
1940 | 1940 | ||
1941 | /* Delete the tempory new association. */ | 1941 | /* Delete the tempory new association. */ |
1942 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | 1942 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); |
@@ -3035,7 +3035,7 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3035 | * notification is passed to the upper layer. | 3035 | * notification is passed to the upper layer. |
3036 | */ | 3036 | */ |
3037 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, | 3037 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, |
3038 | 0, 0, 0, GFP_ATOMIC); | 3038 | 0, 0, 0, NULL, GFP_ATOMIC); |
3039 | if (!ev) | 3039 | if (!ev) |
3040 | goto nomem; | 3040 | goto nomem; |
3041 | 3041 | ||
@@ -3115,7 +3115,7 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3115 | break; | 3115 | break; |
3116 | 3116 | ||
3117 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); | 3117 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
3118 | if (ch_end > skb->tail) | 3118 | if (ch_end > skb_tail_pointer(skb)) |
3119 | break; | 3119 | break; |
3120 | 3120 | ||
3121 | if (SCTP_CID_SHUTDOWN_ACK == ch->type) | 3121 | if (SCTP_CID_SHUTDOWN_ACK == ch->type) |
@@ -3130,7 +3130,7 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3130 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3130 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
3131 | 3131 | ||
3132 | ch = (sctp_chunkhdr_t *) ch_end; | 3132 | ch = (sctp_chunkhdr_t *) ch_end; |
3133 | } while (ch_end < skb->tail); | 3133 | } while (ch_end < skb_tail_pointer(skb)); |
3134 | 3134 | ||
3135 | if (ootb_shut_ack) | 3135 | if (ootb_shut_ack) |
3136 | sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); | 3136 | sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); |
@@ -4816,7 +4816,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
4816 | default: | 4816 | default: |
4817 | BUG(); | 4817 | BUG(); |
4818 | break; | 4818 | break; |
4819 | }; | 4819 | } |
4820 | 4820 | ||
4821 | if (!reply) | 4821 | if (!reply) |
4822 | goto nomem; | 4822 | goto nomem; |
@@ -5286,7 +5286,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5286 | chunk->ecn_ce_done = 1; | 5286 | chunk->ecn_ce_done = 1; |
5287 | 5287 | ||
5288 | af = sctp_get_af_specific( | 5288 | af = sctp_get_af_specific( |
5289 | ipver2af(chunk->skb->nh.iph->version)); | 5289 | ipver2af(ip_hdr(chunk->skb)->version)); |
5290 | 5290 | ||
5291 | if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { | 5291 | if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { |
5292 | /* Do real work as sideffect. */ | 5292 | /* Do real work as sideffect. */ |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 5e54b17377f4..523071c7902f 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -101,7 +101,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
101 | default: | 101 | default: |
102 | /* Yikes! We got an illegal event type. */ | 102 | /* Yikes! We got an illegal event type. */ |
103 | return &bug; | 103 | return &bug; |
104 | }; | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | #define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} | 107 | #define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a1d026f12b0e..11938fb20395 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -941,7 +941,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, | |||
941 | default: | 941 | default: |
942 | err = -EINVAL; | 942 | err = -EINVAL; |
943 | break; | 943 | break; |
944 | }; | 944 | } |
945 | 945 | ||
946 | out: | 946 | out: |
947 | kfree(kaddrs); | 947 | kfree(kaddrs); |
@@ -2039,6 +2039,10 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2039 | * SPP_HB_DEMAND - Request a user initiated heartbeat | 2039 | * SPP_HB_DEMAND - Request a user initiated heartbeat |
2040 | * to be made immediately. | 2040 | * to be made immediately. |
2041 | * | 2041 | * |
2042 | * SPP_HB_TIME_IS_ZERO - Specify's that the time for | ||
2043 | * heartbeat delayis to be set to the value of 0 | ||
2044 | * milliseconds. | ||
2045 | * | ||
2042 | * SPP_PMTUD_ENABLE - This field will enable PMTU | 2046 | * SPP_PMTUD_ENABLE - This field will enable PMTU |
2043 | * discovery upon the specified address. Note that | 2047 | * discovery upon the specified address. Note that |
2044 | * if the address feild is empty then all addresses | 2048 | * if the address feild is empty then all addresses |
@@ -2081,13 +2085,30 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2081 | return error; | 2085 | return error; |
2082 | } | 2086 | } |
2083 | 2087 | ||
2084 | if (params->spp_hbinterval) { | 2088 | /* Note that unless the spp_flag is set to SPP_HB_ENABLE the value of |
2085 | if (trans) { | 2089 | * this field is ignored. Note also that a value of zero indicates |
2086 | trans->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | 2090 | * the current setting should be left unchanged. |
2087 | } else if (asoc) { | 2091 | */ |
2088 | asoc->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | 2092 | if (params->spp_flags & SPP_HB_ENABLE) { |
2089 | } else { | 2093 | |
2090 | sp->hbinterval = params->spp_hbinterval; | 2094 | /* Re-zero the interval if the SPP_HB_TIME_IS_ZERO is |
2095 | * set. This lets us use 0 value when this flag | ||
2096 | * is set. | ||
2097 | */ | ||
2098 | if (params->spp_flags & SPP_HB_TIME_IS_ZERO) | ||
2099 | params->spp_hbinterval = 0; | ||
2100 | |||
2101 | if (params->spp_hbinterval || | ||
2102 | (params->spp_flags & SPP_HB_TIME_IS_ZERO)) { | ||
2103 | if (trans) { | ||
2104 | trans->hbinterval = | ||
2105 | msecs_to_jiffies(params->spp_hbinterval); | ||
2106 | } else if (asoc) { | ||
2107 | asoc->hbinterval = | ||
2108 | msecs_to_jiffies(params->spp_hbinterval); | ||
2109 | } else { | ||
2110 | sp->hbinterval = params->spp_hbinterval; | ||
2111 | } | ||
2091 | } | 2112 | } |
2092 | } | 2113 | } |
2093 | 2114 | ||
@@ -2104,7 +2125,12 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2104 | } | 2125 | } |
2105 | } | 2126 | } |
2106 | 2127 | ||
2107 | if (params->spp_pathmtu) { | 2128 | /* When Path MTU discovery is disabled the value specified here will |
2129 | * be the "fixed" path mtu (i.e. the value of the spp_flags field must | ||
2130 | * include the flag SPP_PMTUD_DISABLE for this field to have any | ||
2131 | * effect). | ||
2132 | */ | ||
2133 | if ((params->spp_flags & SPP_PMTUD_DISABLE) && params->spp_pathmtu) { | ||
2108 | if (trans) { | 2134 | if (trans) { |
2109 | trans->pathmtu = params->spp_pathmtu; | 2135 | trans->pathmtu = params->spp_pathmtu; |
2110 | sctp_assoc_sync_pmtu(asoc); | 2136 | sctp_assoc_sync_pmtu(asoc); |
@@ -2135,7 +2161,11 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2135 | } | 2161 | } |
2136 | } | 2162 | } |
2137 | 2163 | ||
2138 | if (params->spp_sackdelay) { | 2164 | /* Note that unless the spp_flag is set to SPP_SACKDELAY_ENABLE the |
2165 | * value of this field is ignored. Note also that a value of zero | ||
2166 | * indicates the current setting should be left unchanged. | ||
2167 | */ | ||
2168 | if ((params->spp_flags & SPP_SACKDELAY_ENABLE) && params->spp_sackdelay) { | ||
2139 | if (trans) { | 2169 | if (trans) { |
2140 | trans->sackdelay = | 2170 | trans->sackdelay = |
2141 | msecs_to_jiffies(params->spp_sackdelay); | 2171 | msecs_to_jiffies(params->spp_sackdelay); |
@@ -2163,7 +2193,11 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2163 | } | 2193 | } |
2164 | } | 2194 | } |
2165 | 2195 | ||
2166 | if (params->spp_pathmaxrxt) { | 2196 | /* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value |
2197 | * of this field is ignored. Note also that a value of zero | ||
2198 | * indicates the current setting should be left unchanged. | ||
2199 | */ | ||
2200 | if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) { | ||
2167 | if (trans) { | 2201 | if (trans) { |
2168 | trans->pathmaxrxt = params->spp_pathmaxrxt; | 2202 | trans->pathmaxrxt = params->spp_pathmaxrxt; |
2169 | } else if (asoc) { | 2203 | } else if (asoc) { |
@@ -2255,7 +2289,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2255 | return 0; | 2289 | return 0; |
2256 | } | 2290 | } |
2257 | 2291 | ||
2258 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 2292 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) |
2259 | * | 2293 | * |
2260 | * This options will get or set the delayed ack timer. The time is set | 2294 | * This options will get or set the delayed ack timer. The time is set |
2261 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 2295 | * in milliseconds. If the assoc_id is 0, then this sets or gets the |
@@ -2792,6 +2826,102 @@ static int sctp_setsockopt_context(struct sock *sk, char __user *optval, | |||
2792 | return 0; | 2826 | return 0; |
2793 | } | 2827 | } |
2794 | 2828 | ||
2829 | /* | ||
2830 | * 7.1.24. Get or set fragmented interleave (SCTP_FRAGMENT_INTERLEAVE) | ||
2831 | * | ||
2832 | * This options will at a minimum specify if the implementation is doing | ||
2833 | * fragmented interleave. Fragmented interleave, for a one to many | ||
2834 | * socket, is when subsequent calls to receive a message may return | ||
2835 | * parts of messages from different associations. Some implementations | ||
2836 | * may allow you to turn this value on or off. If so, when turned off, | ||
2837 | * no fragment interleave will occur (which will cause a head of line | ||
2838 | * blocking amongst multiple associations sharing the same one to many | ||
2839 | * socket). When this option is turned on, then each receive call may | ||
2840 | * come from a different association (thus the user must receive data | ||
2841 | * with the extended calls (e.g. sctp_recvmsg) to keep track of which | ||
2842 | * association each receive belongs to. | ||
2843 | * | ||
2844 | * This option takes a boolean value. A non-zero value indicates that | ||
2845 | * fragmented interleave is on. A value of zero indicates that | ||
2846 | * fragmented interleave is off. | ||
2847 | * | ||
2848 | * Note that it is important that an implementation that allows this | ||
2849 | * option to be turned on, have it off by default. Otherwise an unaware | ||
2850 | * application using the one to many model may become confused and act | ||
2851 | * incorrectly. | ||
2852 | */ | ||
2853 | static int sctp_setsockopt_fragment_interleave(struct sock *sk, | ||
2854 | char __user *optval, | ||
2855 | int optlen) | ||
2856 | { | ||
2857 | int val; | ||
2858 | |||
2859 | if (optlen != sizeof(int)) | ||
2860 | return -EINVAL; | ||
2861 | if (get_user(val, (int __user *)optval)) | ||
2862 | return -EFAULT; | ||
2863 | |||
2864 | sctp_sk(sk)->frag_interleave = (val == 0) ? 0 : 1; | ||
2865 | |||
2866 | return 0; | ||
2867 | } | ||
2868 | |||
2869 | /* | ||
2870 | * 7.1.25. Set or Get the sctp partial delivery point | ||
2871 | * (SCTP_PARTIAL_DELIVERY_POINT) | ||
2872 | * This option will set or get the SCTP partial delivery point. This | ||
2873 | * point is the size of a message where the partial delivery API will be | ||
2874 | * invoked to help free up rwnd space for the peer. Setting this to a | ||
2875 | * lower value will cause partial delivery's to happen more often. The | ||
2876 | * calls argument is an integer that sets or gets the partial delivery | ||
2877 | * point. | ||
2878 | */ | ||
2879 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | ||
2880 | char __user *optval, | ||
2881 | int optlen) | ||
2882 | { | ||
2883 | u32 val; | ||
2884 | |||
2885 | if (optlen != sizeof(u32)) | ||
2886 | return -EINVAL; | ||
2887 | if (get_user(val, (int __user *)optval)) | ||
2888 | return -EFAULT; | ||
2889 | |||
2890 | sctp_sk(sk)->pd_point = val; | ||
2891 | |||
2892 | return 0; /* is this the right error code? */ | ||
2893 | } | ||
2894 | |||
2895 | /* | ||
2896 | * 7.1.28. Set or Get the maximum burst (SCTP_MAX_BURST) | ||
2897 | * | ||
2898 | * This option will allow a user to change the maximum burst of packets | ||
2899 | * that can be emitted by this association. Note that the default value | ||
2900 | * is 4, and some implementations may restrict this setting so that it | ||
2901 | * can only be lowered. | ||
2902 | * | ||
2903 | * NOTE: This text doesn't seem right. Do this on a socket basis with | ||
2904 | * future associations inheriting the socket value. | ||
2905 | */ | ||
2906 | static int sctp_setsockopt_maxburst(struct sock *sk, | ||
2907 | char __user *optval, | ||
2908 | int optlen) | ||
2909 | { | ||
2910 | int val; | ||
2911 | |||
2912 | if (optlen != sizeof(int)) | ||
2913 | return -EINVAL; | ||
2914 | if (get_user(val, (int __user *)optval)) | ||
2915 | return -EFAULT; | ||
2916 | |||
2917 | if (val < 0) | ||
2918 | return -EINVAL; | ||
2919 | |||
2920 | sctp_sk(sk)->max_burst = val; | ||
2921 | |||
2922 | return 0; | ||
2923 | } | ||
2924 | |||
2795 | /* API 6.2 setsockopt(), getsockopt() | 2925 | /* API 6.2 setsockopt(), getsockopt() |
2796 | * | 2926 | * |
2797 | * Applications use setsockopt() and getsockopt() to set or retrieve | 2927 | * Applications use setsockopt() and getsockopt() to set or retrieve |
@@ -2871,6 +3001,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2871 | case SCTP_DELAYED_ACK_TIME: | 3001 | case SCTP_DELAYED_ACK_TIME: |
2872 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | 3002 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); |
2873 | break; | 3003 | break; |
3004 | case SCTP_PARTIAL_DELIVERY_POINT: | ||
3005 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); | ||
3006 | break; | ||
2874 | 3007 | ||
2875 | case SCTP_INITMSG: | 3008 | case SCTP_INITMSG: |
2876 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); | 3009 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); |
@@ -2906,11 +3039,16 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2906 | case SCTP_CONTEXT: | 3039 | case SCTP_CONTEXT: |
2907 | retval = sctp_setsockopt_context(sk, optval, optlen); | 3040 | retval = sctp_setsockopt_context(sk, optval, optlen); |
2908 | break; | 3041 | break; |
2909 | 3042 | case SCTP_FRAGMENT_INTERLEAVE: | |
3043 | retval = sctp_setsockopt_fragment_interleave(sk, optval, optlen); | ||
3044 | break; | ||
3045 | case SCTP_MAX_BURST: | ||
3046 | retval = sctp_setsockopt_maxburst(sk, optval, optlen); | ||
3047 | break; | ||
2910 | default: | 3048 | default: |
2911 | retval = -ENOPROTOOPT; | 3049 | retval = -ENOPROTOOPT; |
2912 | break; | 3050 | break; |
2913 | }; | 3051 | } |
2914 | 3052 | ||
2915 | sctp_release_sock(sk); | 3053 | sctp_release_sock(sk); |
2916 | 3054 | ||
@@ -3066,6 +3204,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3066 | sp->default_timetolive = 0; | 3204 | sp->default_timetolive = 0; |
3067 | 3205 | ||
3068 | sp->default_rcv_context = 0; | 3206 | sp->default_rcv_context = 0; |
3207 | sp->max_burst = sctp_max_burst; | ||
3069 | 3208 | ||
3070 | /* Initialize default setup parameters. These parameters | 3209 | /* Initialize default setup parameters. These parameters |
3071 | * can be modified with the SCTP_INITMSG socket option or | 3210 | * can be modified with the SCTP_INITMSG socket option or |
@@ -3134,8 +3273,9 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3134 | sp->pf = sctp_get_pf_specific(sk->sk_family); | 3273 | sp->pf = sctp_get_pf_specific(sk->sk_family); |
3135 | 3274 | ||
3136 | /* Control variables for partial data delivery. */ | 3275 | /* Control variables for partial data delivery. */ |
3137 | sp->pd_mode = 0; | 3276 | atomic_set(&sp->pd_mode, 0); |
3138 | skb_queue_head_init(&sp->pd_lobby); | 3277 | skb_queue_head_init(&sp->pd_lobby); |
3278 | sp->frag_interleave = 0; | ||
3139 | 3279 | ||
3140 | /* Create a per socket endpoint structure. Even if we | 3280 | /* Create a per socket endpoint structure. Even if we |
3141 | * change the data structure relationships, this may still | 3281 | * change the data structure relationships, this may still |
@@ -3642,7 +3782,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3642 | return 0; | 3782 | return 0; |
3643 | } | 3783 | } |
3644 | 3784 | ||
3645 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 3785 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) |
3646 | * | 3786 | * |
3647 | * This options will get or set the delayed ack timer. The time is set | 3787 | * This options will get or set the delayed ack timer. The time is set |
3648 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 3788 | * in milliseconds. If the assoc_id is 0, then this sets or gets the |
@@ -4536,6 +4676,77 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len, | |||
4536 | return 0; | 4676 | return 0; |
4537 | } | 4677 | } |
4538 | 4678 | ||
4679 | /* | ||
4680 | * 7.1.24. Get or set fragmented interleave (SCTP_FRAGMENT_INTERLEAVE) | ||
4681 | * (chapter and verse is quoted at sctp_setsockopt_fragment_interleave()) | ||
4682 | */ | ||
4683 | static int sctp_getsockopt_fragment_interleave(struct sock *sk, int len, | ||
4684 | char __user *optval, int __user *optlen) | ||
4685 | { | ||
4686 | int val; | ||
4687 | |||
4688 | if (len < sizeof(int)) | ||
4689 | return -EINVAL; | ||
4690 | |||
4691 | len = sizeof(int); | ||
4692 | |||
4693 | val = sctp_sk(sk)->frag_interleave; | ||
4694 | if (put_user(len, optlen)) | ||
4695 | return -EFAULT; | ||
4696 | if (copy_to_user(optval, &val, len)) | ||
4697 | return -EFAULT; | ||
4698 | |||
4699 | return 0; | ||
4700 | } | ||
4701 | |||
4702 | /* | ||
4703 | * 7.1.25. Set or Get the sctp partial delivery point | ||
4704 | * (chapter and verse is quoted at sctp_setsockopt_partial_delivery_point()) | ||
4705 | */ | ||
4706 | static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len, | ||
4707 | char __user *optval, | ||
4708 | int __user *optlen) | ||
4709 | { | ||
4710 | u32 val; | ||
4711 | |||
4712 | if (len < sizeof(u32)) | ||
4713 | return -EINVAL; | ||
4714 | |||
4715 | len = sizeof(u32); | ||
4716 | |||
4717 | val = sctp_sk(sk)->pd_point; | ||
4718 | if (put_user(len, optlen)) | ||
4719 | return -EFAULT; | ||
4720 | if (copy_to_user(optval, &val, len)) | ||
4721 | return -EFAULT; | ||
4722 | |||
4723 | return -ENOTSUPP; | ||
4724 | } | ||
4725 | |||
4726 | /* | ||
4727 | * 7.1.28. Set or Get the maximum burst (SCTP_MAX_BURST) | ||
4728 | * (chapter and verse is quoted at sctp_setsockopt_maxburst()) | ||
4729 | */ | ||
4730 | static int sctp_getsockopt_maxburst(struct sock *sk, int len, | ||
4731 | char __user *optval, | ||
4732 | int __user *optlen) | ||
4733 | { | ||
4734 | int val; | ||
4735 | |||
4736 | if (len < sizeof(int)) | ||
4737 | return -EINVAL; | ||
4738 | |||
4739 | len = sizeof(int); | ||
4740 | |||
4741 | val = sctp_sk(sk)->max_burst; | ||
4742 | if (put_user(len, optlen)) | ||
4743 | return -EFAULT; | ||
4744 | if (copy_to_user(optval, &val, len)) | ||
4745 | return -EFAULT; | ||
4746 | |||
4747 | return -ENOTSUPP; | ||
4748 | } | ||
4749 | |||
4539 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 4750 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
4540 | char __user *optval, int __user *optlen) | 4751 | char __user *optval, int __user *optlen) |
4541 | { | 4752 | { |
@@ -4648,10 +4859,21 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
4648 | case SCTP_CONTEXT: | 4859 | case SCTP_CONTEXT: |
4649 | retval = sctp_getsockopt_context(sk, len, optval, optlen); | 4860 | retval = sctp_getsockopt_context(sk, len, optval, optlen); |
4650 | break; | 4861 | break; |
4862 | case SCTP_FRAGMENT_INTERLEAVE: | ||
4863 | retval = sctp_getsockopt_fragment_interleave(sk, len, optval, | ||
4864 | optlen); | ||
4865 | break; | ||
4866 | case SCTP_PARTIAL_DELIVERY_POINT: | ||
4867 | retval = sctp_getsockopt_partial_delivery_point(sk, len, optval, | ||
4868 | optlen); | ||
4869 | break; | ||
4870 | case SCTP_MAX_BURST: | ||
4871 | retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); | ||
4872 | break; | ||
4651 | default: | 4873 | default: |
4652 | retval = -ENOPROTOOPT; | 4874 | retval = -ENOPROTOOPT; |
4653 | break; | 4875 | break; |
4654 | }; | 4876 | } |
4655 | 4877 | ||
4656 | sctp_release_sock(sk); | 4878 | sctp_release_sock(sk); |
4657 | return retval; | 4879 | return retval; |
@@ -4976,7 +5198,8 @@ int sctp_inet_listen(struct socket *sock, int backlog) | |||
4976 | break; | 5198 | break; |
4977 | default: | 5199 | default: |
4978 | break; | 5200 | break; |
4979 | }; | 5201 | } |
5202 | |||
4980 | if (err) | 5203 | if (err) |
4981 | goto cleanup; | 5204 | goto cleanup; |
4982 | 5205 | ||
@@ -5239,7 +5462,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, | |||
5239 | 5462 | ||
5240 | default: | 5463 | default: |
5241 | return -EINVAL; | 5464 | return -EINVAL; |
5242 | }; | 5465 | } |
5243 | } | 5466 | } |
5244 | return 0; | 5467 | return 0; |
5245 | } | 5468 | } |
@@ -5742,9 +5965,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5742 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. | 5965 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. |
5743 | */ | 5966 | */ |
5744 | skb_queue_head_init(&newsp->pd_lobby); | 5967 | skb_queue_head_init(&newsp->pd_lobby); |
5745 | sctp_sk(newsk)->pd_mode = assoc->ulpq.pd_mode; | 5968 | atomic_set(&sctp_sk(newsk)->pd_mode, assoc->ulpq.pd_mode); |
5746 | 5969 | ||
5747 | if (sctp_sk(oldsk)->pd_mode) { | 5970 | if (atomic_read(&sctp_sk(oldsk)->pd_mode)) { |
5748 | struct sk_buff_head *queue; | 5971 | struct sk_buff_head *queue; |
5749 | 5972 | ||
5750 | /* Decide which queue to move pd_lobby skbs to. */ | 5973 | /* Decide which queue to move pd_lobby skbs to. */ |
@@ -5770,7 +5993,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5770 | * delivery to finish. | 5993 | * delivery to finish. |
5771 | */ | 5994 | */ |
5772 | if (assoc->ulpq.pd_mode) | 5995 | if (assoc->ulpq.pd_mode) |
5773 | sctp_clear_pd(oldsk); | 5996 | sctp_clear_pd(oldsk, NULL); |
5774 | 5997 | ||
5775 | } | 5998 | } |
5776 | 5999 | ||
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 4d8c2ab864fc..961df275d5b9 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -507,7 +507,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
507 | transport->cwnd = max(transport->cwnd/2, | 507 | transport->cwnd = max(transport->cwnd/2, |
508 | 4*transport->asoc->pathmtu); | 508 | 4*transport->asoc->pathmtu); |
509 | break; | 509 | break; |
510 | }; | 510 | } |
511 | 511 | ||
512 | transport->partial_bytes_acked = 0; | 512 | transport->partial_bytes_acked = 0; |
513 | SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: " | 513 | SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: " |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 2e11bc8d5d35..661ea2dd78ba 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -131,19 +131,54 @@ static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) | |||
131 | struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( | 131 | struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( |
132 | const struct sctp_association *asoc, | 132 | const struct sctp_association *asoc, |
133 | __u16 flags, __u16 state, __u16 error, __u16 outbound, | 133 | __u16 flags, __u16 state, __u16 error, __u16 outbound, |
134 | __u16 inbound, gfp_t gfp) | 134 | __u16 inbound, struct sctp_chunk *chunk, gfp_t gfp) |
135 | { | 135 | { |
136 | struct sctp_ulpevent *event; | 136 | struct sctp_ulpevent *event; |
137 | struct sctp_assoc_change *sac; | 137 | struct sctp_assoc_change *sac; |
138 | struct sk_buff *skb; | 138 | struct sk_buff *skb; |
139 | 139 | ||
140 | event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), | 140 | /* If the lower layer passed in the chunk, it will be |
141 | * an ABORT, so we need to include it in the sac_info. | ||
142 | */ | ||
143 | if (chunk) { | ||
144 | /* sctp_inqu_pop() has allready pulled off the chunk | ||
145 | * header. We need to put it back temporarily | ||
146 | */ | ||
147 | skb_push(chunk->skb, sizeof(sctp_chunkhdr_t)); | ||
148 | |||
149 | /* Copy the chunk data to a new skb and reserve enough | ||
150 | * head room to use as notification. | ||
151 | */ | ||
152 | skb = skb_copy_expand(chunk->skb, | ||
153 | sizeof(struct sctp_assoc_change), 0, gfp); | ||
154 | |||
155 | if (!skb) | ||
156 | goto fail; | ||
157 | |||
158 | /* put back the chunk header now that we have a copy */ | ||
159 | skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); | ||
160 | |||
161 | /* Embed the event fields inside the cloned skb. */ | ||
162 | event = sctp_skb2event(skb); | ||
163 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); | ||
164 | |||
165 | /* Include the notification structure */ | ||
166 | sac = (struct sctp_assoc_change *) | ||
167 | skb_push(skb, sizeof(struct sctp_assoc_change)); | ||
168 | |||
169 | /* Trim the buffer to the right length. */ | ||
170 | skb_trim(skb, sizeof(struct sctp_assoc_change) + | ||
171 | ntohs(chunk->chunk_hdr->length)); | ||
172 | } else { | ||
173 | event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), | ||
141 | MSG_NOTIFICATION, gfp); | 174 | MSG_NOTIFICATION, gfp); |
142 | if (!event) | 175 | if (!event) |
143 | goto fail; | 176 | goto fail; |
144 | skb = sctp_event2skb(event); | 177 | |
145 | sac = (struct sctp_assoc_change *) | 178 | skb = sctp_event2skb(event); |
146 | skb_put(skb, sizeof(struct sctp_assoc_change)); | 179 | sac = (struct sctp_assoc_change *) skb_put(skb, |
180 | sizeof(struct sctp_assoc_change)); | ||
181 | } | ||
147 | 182 | ||
148 | /* Socket Extensions for SCTP | 183 | /* Socket Extensions for SCTP |
149 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 184 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index b29e3e4b72c9..34eb977a204d 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -138,26 +138,59 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
138 | /* Clear the partial delivery mode for this socket. Note: This | 138 | /* Clear the partial delivery mode for this socket. Note: This |
139 | * assumes that no association is currently in partial delivery mode. | 139 | * assumes that no association is currently in partial delivery mode. |
140 | */ | 140 | */ |
141 | int sctp_clear_pd(struct sock *sk) | 141 | int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc) |
142 | { | 142 | { |
143 | struct sctp_sock *sp = sctp_sk(sk); | 143 | struct sctp_sock *sp = sctp_sk(sk); |
144 | 144 | ||
145 | sp->pd_mode = 0; | 145 | if (atomic_dec_and_test(&sp->pd_mode)) { |
146 | if (!skb_queue_empty(&sp->pd_lobby)) { | 146 | /* This means there are no other associations in PD, so |
147 | struct list_head *list; | 147 | * we can go ahead and clear out the lobby in one shot |
148 | sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue); | 148 | */ |
149 | list = (struct list_head *)&sctp_sk(sk)->pd_lobby; | 149 | if (!skb_queue_empty(&sp->pd_lobby)) { |
150 | INIT_LIST_HEAD(list); | 150 | struct list_head *list; |
151 | return 1; | 151 | sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue); |
152 | list = (struct list_head *)&sctp_sk(sk)->pd_lobby; | ||
153 | INIT_LIST_HEAD(list); | ||
154 | return 1; | ||
155 | } | ||
156 | } else { | ||
157 | /* There are other associations in PD, so we only need to | ||
158 | * pull stuff out of the lobby that belongs to the | ||
159 | * associations that is exiting PD (all of its notifications | ||
160 | * are posted here). | ||
161 | */ | ||
162 | if (!skb_queue_empty(&sp->pd_lobby) && asoc) { | ||
163 | struct sk_buff *skb, *tmp; | ||
164 | struct sctp_ulpevent *event; | ||
165 | |||
166 | sctp_skb_for_each(skb, &sp->pd_lobby, tmp) { | ||
167 | event = sctp_skb2event(skb); | ||
168 | if (event->asoc == asoc) { | ||
169 | __skb_unlink(skb, &sp->pd_lobby); | ||
170 | __skb_queue_tail(&sk->sk_receive_queue, | ||
171 | skb); | ||
172 | } | ||
173 | } | ||
174 | } | ||
152 | } | 175 | } |
176 | |||
153 | return 0; | 177 | return 0; |
154 | } | 178 | } |
155 | 179 | ||
180 | /* Set the pd_mode on the socket and ulpq */ | ||
181 | static void sctp_ulpq_set_pd(struct sctp_ulpq *ulpq) | ||
182 | { | ||
183 | struct sctp_sock *sp = sctp_sk(ulpq->asoc->base.sk); | ||
184 | |||
185 | atomic_inc(&sp->pd_mode); | ||
186 | ulpq->pd_mode = 1; | ||
187 | } | ||
188 | |||
156 | /* Clear the pd_mode and restart any pending messages waiting for delivery. */ | 189 | /* Clear the pd_mode and restart any pending messages waiting for delivery. */ |
157 | static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq) | 190 | static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq) |
158 | { | 191 | { |
159 | ulpq->pd_mode = 0; | 192 | ulpq->pd_mode = 0; |
160 | return sctp_clear_pd(ulpq->asoc->base.sk); | 193 | return sctp_clear_pd(ulpq->asoc->base.sk, ulpq->asoc); |
161 | } | 194 | } |
162 | 195 | ||
163 | /* If the SKB of 'event' is on a list, it is the first such member | 196 | /* If the SKB of 'event' is on a list, it is the first such member |
@@ -187,25 +220,35 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
187 | * the association the cause of the partial delivery. | 220 | * the association the cause of the partial delivery. |
188 | */ | 221 | */ |
189 | 222 | ||
190 | if (!sctp_sk(sk)->pd_mode) { | 223 | if (atomic_read(&sctp_sk(sk)->pd_mode) == 0) { |
191 | queue = &sk->sk_receive_queue; | 224 | queue = &sk->sk_receive_queue; |
192 | } else if (ulpq->pd_mode) { | 225 | } else { |
193 | /* If the association is in partial delivery, we | 226 | if (ulpq->pd_mode) { |
194 | * need to finish delivering the partially processed | 227 | /* If the association is in partial delivery, we |
195 | * packet before passing any other data. This is | 228 | * need to finish delivering the partially processed |
196 | * because we don't truly support stream interleaving. | 229 | * packet before passing any other data. This is |
197 | */ | 230 | * because we don't truly support stream interleaving. |
198 | if ((event->msg_flags & MSG_NOTIFICATION) || | 231 | */ |
199 | (SCTP_DATA_NOT_FRAG == | 232 | if ((event->msg_flags & MSG_NOTIFICATION) || |
200 | (event->msg_flags & SCTP_DATA_FRAG_MASK))) | 233 | (SCTP_DATA_NOT_FRAG == |
201 | queue = &sctp_sk(sk)->pd_lobby; | 234 | (event->msg_flags & SCTP_DATA_FRAG_MASK))) |
202 | else { | 235 | queue = &sctp_sk(sk)->pd_lobby; |
203 | clear_pd = event->msg_flags & MSG_EOR; | 236 | else { |
204 | queue = &sk->sk_receive_queue; | 237 | clear_pd = event->msg_flags & MSG_EOR; |
238 | queue = &sk->sk_receive_queue; | ||
239 | } | ||
240 | } else { | ||
241 | /* | ||
242 | * If fragment interleave is enabled, we | ||
243 | * can queue this to the recieve queue instead | ||
244 | * of the lobby. | ||
245 | */ | ||
246 | if (sctp_sk(sk)->frag_interleave) | ||
247 | queue = &sk->sk_receive_queue; | ||
248 | else | ||
249 | queue = &sctp_sk(sk)->pd_lobby; | ||
205 | } | 250 | } |
206 | } else | 251 | } |
207 | queue = &sctp_sk(sk)->pd_lobby; | ||
208 | |||
209 | 252 | ||
210 | /* If we are harvesting multiple skbs they will be | 253 | /* If we are harvesting multiple skbs they will be |
211 | * collected on a list. | 254 | * collected on a list. |
@@ -348,7 +391,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu | |||
348 | break; | 391 | break; |
349 | pos->next = pnext; | 392 | pos->next = pnext; |
350 | pos = pnext; | 393 | pos = pnext; |
351 | }; | 394 | } |
352 | 395 | ||
353 | event = sctp_skb2event(f_frag); | 396 | event = sctp_skb2event(f_frag); |
354 | SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS); | 397 | SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS); |
@@ -367,6 +410,11 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u | |||
367 | struct sk_buff *first_frag = NULL; | 410 | struct sk_buff *first_frag = NULL; |
368 | __u32 ctsn, next_tsn; | 411 | __u32 ctsn, next_tsn; |
369 | struct sctp_ulpevent *retval = NULL; | 412 | struct sctp_ulpevent *retval = NULL; |
413 | struct sk_buff *pd_first = NULL; | ||
414 | struct sk_buff *pd_last = NULL; | ||
415 | size_t pd_len = 0; | ||
416 | struct sctp_association *asoc; | ||
417 | u32 pd_point; | ||
370 | 418 | ||
371 | /* Initialized to 0 just to avoid compiler warning message. Will | 419 | /* Initialized to 0 just to avoid compiler warning message. Will |
372 | * never be used with this value. It is referenced only after it | 420 | * never be used with this value. It is referenced only after it |
@@ -382,6 +430,10 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u | |||
382 | * we expect to find the remaining middle fragments and the last | 430 | * we expect to find the remaining middle fragments and the last |
383 | * fragment in order. If not, first_frag is reset to NULL and we | 431 | * fragment in order. If not, first_frag is reset to NULL and we |
384 | * start the next pass when we find another first fragment. | 432 | * start the next pass when we find another first fragment. |
433 | * | ||
434 | * There is a potential to do partial delivery if user sets | ||
435 | * SCTP_PARTIAL_DELIVERY_POINT option. Lets count some things here | ||
436 | * to see if can do PD. | ||
385 | */ | 437 | */ |
386 | skb_queue_walk(&ulpq->reasm, pos) { | 438 | skb_queue_walk(&ulpq->reasm, pos) { |
387 | cevent = sctp_skb2event(pos); | 439 | cevent = sctp_skb2event(pos); |
@@ -389,14 +441,32 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u | |||
389 | 441 | ||
390 | switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { | 442 | switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { |
391 | case SCTP_DATA_FIRST_FRAG: | 443 | case SCTP_DATA_FIRST_FRAG: |
444 | /* If this "FIRST_FRAG" is the first | ||
445 | * element in the queue, then count it towards | ||
446 | * possible PD. | ||
447 | */ | ||
448 | if (pos == ulpq->reasm.next) { | ||
449 | pd_first = pos; | ||
450 | pd_last = pos; | ||
451 | pd_len = pos->len; | ||
452 | } else { | ||
453 | pd_first = NULL; | ||
454 | pd_last = NULL; | ||
455 | pd_len = 0; | ||
456 | } | ||
457 | |||
392 | first_frag = pos; | 458 | first_frag = pos; |
393 | next_tsn = ctsn + 1; | 459 | next_tsn = ctsn + 1; |
394 | break; | 460 | break; |
395 | 461 | ||
396 | case SCTP_DATA_MIDDLE_FRAG: | 462 | case SCTP_DATA_MIDDLE_FRAG: |
397 | if ((first_frag) && (ctsn == next_tsn)) | 463 | if ((first_frag) && (ctsn == next_tsn)) { |
398 | next_tsn++; | 464 | next_tsn++; |
399 | else | 465 | if (pd_first) { |
466 | pd_last = pos; | ||
467 | pd_len += pos->len; | ||
468 | } | ||
469 | } else | ||
400 | first_frag = NULL; | 470 | first_frag = NULL; |
401 | break; | 471 | break; |
402 | 472 | ||
@@ -406,8 +476,29 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u | |||
406 | else | 476 | else |
407 | first_frag = NULL; | 477 | first_frag = NULL; |
408 | break; | 478 | break; |
409 | }; | 479 | } |
480 | } | ||
410 | 481 | ||
482 | asoc = ulpq->asoc; | ||
483 | if (pd_first) { | ||
484 | /* Make sure we can enter partial deliver. | ||
485 | * We can trigger partial delivery only if framgent | ||
486 | * interleave is set, or the socket is not already | ||
487 | * in partial delivery. | ||
488 | */ | ||
489 | if (!sctp_sk(asoc->base.sk)->frag_interleave && | ||
490 | atomic_read(&sctp_sk(asoc->base.sk)->pd_mode)) | ||
491 | goto done; | ||
492 | |||
493 | cevent = sctp_skb2event(pd_first); | ||
494 | pd_point = sctp_sk(asoc->base.sk)->pd_point; | ||
495 | if (pd_point && pd_point <= pd_len) { | ||
496 | retval = sctp_make_reassembled_event(&ulpq->reasm, | ||
497 | pd_first, | ||
498 | pd_last); | ||
499 | if (retval) | ||
500 | sctp_ulpq_set_pd(ulpq); | ||
501 | } | ||
411 | } | 502 | } |
412 | done: | 503 | done: |
413 | return retval; | 504 | return retval; |
@@ -465,7 +556,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq | |||
465 | goto done; | 556 | goto done; |
466 | default: | 557 | default: |
467 | return NULL; | 558 | return NULL; |
468 | }; | 559 | } |
469 | } | 560 | } |
470 | 561 | ||
471 | /* We have the reassembled event. There is no need to look | 562 | /* We have the reassembled event. There is no need to look |
@@ -557,7 +648,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *u | |||
557 | break; | 648 | break; |
558 | default: | 649 | default: |
559 | return NULL; | 650 | return NULL; |
560 | }; | 651 | } |
561 | } | 652 | } |
562 | 653 | ||
563 | /* We have the reassembled event. There is no need to look | 654 | /* We have the reassembled event. There is no need to look |
@@ -826,19 +917,29 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, | |||
826 | { | 917 | { |
827 | struct sctp_ulpevent *event; | 918 | struct sctp_ulpevent *event; |
828 | struct sctp_association *asoc; | 919 | struct sctp_association *asoc; |
920 | struct sctp_sock *sp; | ||
829 | 921 | ||
830 | asoc = ulpq->asoc; | 922 | asoc = ulpq->asoc; |
923 | sp = sctp_sk(asoc->base.sk); | ||
831 | 924 | ||
832 | /* Are we already in partial delivery mode? */ | 925 | /* If the association is already in Partial Delivery mode |
833 | if (!sctp_sk(asoc->base.sk)->pd_mode) { | 926 | * we have noting to do. |
927 | */ | ||
928 | if (ulpq->pd_mode) | ||
929 | return; | ||
834 | 930 | ||
931 | /* If the user enabled fragment interleave socket option, | ||
932 | * multiple associations can enter partial delivery. | ||
933 | * Otherwise, we can only enter partial delivery if the | ||
934 | * socket is not in partial deliver mode. | ||
935 | */ | ||
936 | if (sp->frag_interleave || atomic_read(&sp->pd_mode) == 0) { | ||
835 | /* Is partial delivery possible? */ | 937 | /* Is partial delivery possible? */ |
836 | event = sctp_ulpq_retrieve_first(ulpq); | 938 | event = sctp_ulpq_retrieve_first(ulpq); |
837 | /* Send event to the ULP. */ | 939 | /* Send event to the ULP. */ |
838 | if (event) { | 940 | if (event) { |
839 | sctp_ulpq_tail_event(ulpq, event); | 941 | sctp_ulpq_tail_event(ulpq, event); |
840 | sctp_sk(asoc->base.sk)->pd_mode = 1; | 942 | sctp_ulpq_set_pd(ulpq); |
841 | ulpq->pd_mode = 1; | ||
842 | return; | 943 | return; |
843 | } | 944 | } |
844 | } | 945 | } |