diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 64 | ||||
-rw-r--r-- | net/sctp/input.c | 4 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 2 | ||||
-rw-r--r-- | net/sctp/output.c | 23 | ||||
-rw-r--r-- | net/sctp/protocol.c | 10 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 16 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 8 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 14 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 75 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 6 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 7 |
12 files changed, 131 insertions, 100 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f4b23043b610..525864bf4f07 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -293,7 +293,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
293 | * told otherwise. | 293 | * told otherwise. |
294 | */ | 294 | */ |
295 | asoc->peer.ipv4_address = 1; | 295 | asoc->peer.ipv4_address = 1; |
296 | asoc->peer.ipv6_address = 1; | 296 | if (asoc->base.sk->sk_family == PF_INET6) |
297 | asoc->peer.ipv6_address = 1; | ||
297 | INIT_LIST_HEAD(&asoc->asocs); | 298 | INIT_LIST_HEAD(&asoc->asocs); |
298 | 299 | ||
299 | asoc->autoclose = sp->autoclose; | 300 | asoc->autoclose = sp->autoclose; |
@@ -566,6 +567,21 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, | |||
566 | if (asoc->init_last_sent_to == peer) | 567 | if (asoc->init_last_sent_to == peer) |
567 | asoc->init_last_sent_to = NULL; | 568 | asoc->init_last_sent_to = NULL; |
568 | 569 | ||
570 | /* If we remove the transport an SHUTDOWN was last sent to, set it | ||
571 | * to NULL. Combined with the update of the retran path above, this | ||
572 | * will cause the next SHUTDOWN to be sent to the next available | ||
573 | * transport, maintaining the cycle. | ||
574 | */ | ||
575 | if (asoc->shutdown_last_sent_to == peer) | ||
576 | asoc->shutdown_last_sent_to = NULL; | ||
577 | |||
578 | /* If we remove the transport an ASCONF was last sent to, set it to | ||
579 | * NULL. | ||
580 | */ | ||
581 | if (asoc->addip_last_asconf && | ||
582 | asoc->addip_last_asconf->transport == peer) | ||
583 | asoc->addip_last_asconf->transport = NULL; | ||
584 | |||
569 | asoc->peer.transport_count--; | 585 | asoc->peer.transport_count--; |
570 | 586 | ||
571 | sctp_transport_free(peer); | 587 | sctp_transport_free(peer); |
@@ -1268,49 +1284,21 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1268 | ntohs(t->ipaddr.v4.sin_port)); | 1284 | ntohs(t->ipaddr.v4.sin_port)); |
1269 | } | 1285 | } |
1270 | 1286 | ||
1271 | /* Choose the transport for sending a INIT packet. */ | 1287 | /* Choose the transport for sending retransmit packet. */ |
1272 | struct sctp_transport *sctp_assoc_choose_init_transport( | 1288 | struct sctp_transport *sctp_assoc_choose_alter_transport( |
1273 | struct sctp_association *asoc) | 1289 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) |
1274 | { | ||
1275 | struct sctp_transport *t; | ||
1276 | |||
1277 | /* Use the retran path. If the last INIT was sent over the | ||
1278 | * retran path, update the retran path and use it. | ||
1279 | */ | ||
1280 | if (!asoc->init_last_sent_to) { | ||
1281 | t = asoc->peer.active_path; | ||
1282 | } else { | ||
1283 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
1284 | sctp_assoc_update_retran_path(asoc); | ||
1285 | t = asoc->peer.retran_path; | ||
1286 | } | ||
1287 | |||
1288 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1289 | " %p addr: ", | ||
1290 | " port: %d\n", | ||
1291 | asoc, | ||
1292 | (&t->ipaddr), | ||
1293 | ntohs(t->ipaddr.v4.sin_port)); | ||
1294 | |||
1295 | return t; | ||
1296 | } | ||
1297 | |||
1298 | /* Choose the transport for sending a SHUTDOWN packet. */ | ||
1299 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | ||
1300 | struct sctp_association *asoc) | ||
1301 | { | 1290 | { |
1302 | /* If this is the first time SHUTDOWN is sent, use the active path, | 1291 | /* If this is the first time packet is sent, use the active path, |
1303 | * else use the retran path. If the last SHUTDOWN was sent over the | 1292 | * else use the retran path. If the last packet was sent over the |
1304 | * retran path, update the retran path and use it. | 1293 | * retran path, update the retran path and use it. |
1305 | */ | 1294 | */ |
1306 | if (!asoc->shutdown_last_sent_to) | 1295 | if (!last_sent_to) |
1307 | return asoc->peer.active_path; | 1296 | return asoc->peer.active_path; |
1308 | else { | 1297 | else { |
1309 | if (asoc->shutdown_last_sent_to == asoc->peer.retran_path) | 1298 | if (last_sent_to == asoc->peer.retran_path) |
1310 | sctp_assoc_update_retran_path(asoc); | 1299 | sctp_assoc_update_retran_path(asoc); |
1311 | return asoc->peer.retran_path; | 1300 | return asoc->peer.retran_path; |
1312 | } | 1301 | } |
1313 | |||
1314 | } | 1302 | } |
1315 | 1303 | ||
1316 | /* Update the association's pmtu and frag_point by going through all the | 1304 | /* Update the association's pmtu and frag_point by going through all the |
@@ -1482,6 +1470,10 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) | |||
1482 | { | 1470 | { |
1483 | int assoc_id; | 1471 | int assoc_id; |
1484 | int error = 0; | 1472 | int error = 0; |
1473 | |||
1474 | /* If the id is already assigned, keep it. */ | ||
1475 | if (asoc->assoc_id) | ||
1476 | return error; | ||
1485 | retry: | 1477 | retry: |
1486 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | 1478 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) |
1487 | return -ENOMEM; | 1479 | return -ENOMEM; |
diff --git a/net/sctp/input.c b/net/sctp/input.c index d2e98803ffe3..c0c973e67add 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -81,13 +81,13 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); | |||
81 | /* Calculate the SCTP checksum of an SCTP packet. */ | 81 | /* Calculate the SCTP checksum of an SCTP packet. */ |
82 | static inline int sctp_rcv_checksum(struct sk_buff *skb) | 82 | static inline int sctp_rcv_checksum(struct sk_buff *skb) |
83 | { | 83 | { |
84 | struct sk_buff *list = skb_shinfo(skb)->frag_list; | ||
85 | struct sctphdr *sh = sctp_hdr(skb); | 84 | struct sctphdr *sh = sctp_hdr(skb); |
86 | __le32 cmp = sh->checksum; | 85 | __le32 cmp = sh->checksum; |
86 | struct sk_buff *list; | ||
87 | __le32 val; | 87 | __le32 val; |
88 | __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); | 88 | __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); |
89 | 89 | ||
90 | for (; list; list = list->next) | 90 | skb_walk_frags(skb, list) |
91 | tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), | 91 | tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), |
92 | tmp); | 92 | tmp); |
93 | 93 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a63de3f7f185..6a4b19094143 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -133,7 +133,7 @@ static struct notifier_block sctp_inet6addr_notifier = { | |||
133 | 133 | ||
134 | /* ICMP error handler. */ | 134 | /* ICMP error handler. */ |
135 | SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 135 | SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
136 | int type, int code, int offset, __be32 info) | 136 | u8 type, u8 code, int offset, __be32 info) |
137 | { | 137 | { |
138 | struct inet6_dev *idev; | 138 | struct inet6_dev *idev; |
139 | struct sock *sk; | 139 | struct sock *sk; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 7d08f522ec84..b94c21190566 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -405,13 +405,14 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
405 | sctp_assoc_sync_pmtu(asoc); | 405 | sctp_assoc_sync_pmtu(asoc); |
406 | } | 406 | } |
407 | } | 407 | } |
408 | nskb->dst = dst_clone(tp->dst); | 408 | dst = dst_clone(tp->dst); |
409 | if (!nskb->dst) | 409 | skb_dst_set(nskb, dst); |
410 | if (!dst) | ||
410 | goto no_route; | 411 | goto no_route; |
411 | dst = nskb->dst; | ||
412 | 412 | ||
413 | /* Build the SCTP header. */ | 413 | /* Build the SCTP header. */ |
414 | sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); | 414 | sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); |
415 | skb_reset_transport_header(nskb); | ||
415 | sh->source = htons(packet->source_port); | 416 | sh->source = htons(packet->source_port); |
416 | sh->dest = htons(packet->destination_port); | 417 | sh->dest = htons(packet->destination_port); |
417 | 418 | ||
@@ -527,15 +528,25 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
527 | * Note: Adler-32 is no longer applicable, as has been replaced | 528 | * Note: Adler-32 is no longer applicable, as has been replaced |
528 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | 529 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. |
529 | */ | 530 | */ |
530 | if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) { | 531 | if (!sctp_checksum_disable && |
532 | !(dst->dev->features & (NETIF_F_NO_CSUM | NETIF_F_SCTP_CSUM))) { | ||
531 | __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 533 | __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
532 | 534 | ||
533 | /* 3) Put the resultant value into the checksum field in the | 535 | /* 3) Put the resultant value into the checksum field in the |
534 | * common header, and leave the rest of the bits unchanged. | 536 | * common header, and leave the rest of the bits unchanged. |
535 | */ | 537 | */ |
536 | sh->checksum = sctp_end_cksum(crc32); | 538 | sh->checksum = sctp_end_cksum(crc32); |
537 | } else | 539 | } else { |
538 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | 540 | if (dst->dev->features & NETIF_F_SCTP_CSUM) { |
541 | /* no need to seed psuedo checksum for SCTP */ | ||
542 | nskb->ip_summed = CHECKSUM_PARTIAL; | ||
543 | nskb->csum_start = (skb_transport_header(nskb) - | ||
544 | nskb->head); | ||
545 | nskb->csum_offset = offsetof(struct sctphdr, checksum); | ||
546 | } else { | ||
547 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | ||
548 | } | ||
549 | } | ||
539 | 550 | ||
540 | /* IP layer ECN support | 551 | /* IP layer ECN support |
541 | * From RFC 2481 | 552 | * From RFC 2481 |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 8eb3e61cb701..79cbd47f4df7 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -393,7 +393,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, | |||
393 | return 0; | 393 | return 0; |
394 | 394 | ||
395 | /* Is this a broadcast address? */ | 395 | /* Is this a broadcast address? */ |
396 | if (skb && skb->rtable->rt_flags & RTCF_BROADCAST) | 396 | if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST) |
397 | return 0; | 397 | return 0; |
398 | 398 | ||
399 | return 1; | 399 | return 1; |
@@ -572,7 +572,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk, | |||
572 | /* What interface did this skb arrive on? */ | 572 | /* What interface did this skb arrive on? */ |
573 | static int sctp_v4_skb_iif(const struct sk_buff *skb) | 573 | static int sctp_v4_skb_iif(const struct sk_buff *skb) |
574 | { | 574 | { |
575 | return skb->rtable->rt_iif; | 575 | return skb_rtable(skb)->rt_iif; |
576 | } | 576 | } |
577 | 577 | ||
578 | /* Was this packet marked by Explicit Congestion Notification? */ | 578 | /* Was this packet marked by Explicit Congestion Notification? */ |
@@ -848,8 +848,8 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
848 | 848 | ||
849 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", | 849 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", |
850 | __func__, skb, skb->len, | 850 | __func__, skb, skb->len, |
851 | &skb->rtable->rt_src, | 851 | &skb_rtable(skb)->rt_src, |
852 | &skb->rtable->rt_dst); | 852 | &skb_rtable(skb)->rt_dst); |
853 | 853 | ||
854 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? | 854 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? |
855 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | 855 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; |
@@ -1370,6 +1370,8 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1370 | sctp_proc_exit(); | 1370 | sctp_proc_exit(); |
1371 | cleanup_sctp_mibs(); | 1371 | cleanup_sctp_mibs(); |
1372 | 1372 | ||
1373 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | ||
1374 | |||
1373 | kmem_cache_destroy(sctp_chunk_cachep); | 1375 | kmem_cache_destroy(sctp_chunk_cachep); |
1374 | kmem_cache_destroy(sctp_bucket_cachep); | 1376 | kmem_cache_destroy(sctp_bucket_cachep); |
1375 | } | 1377 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 6851ee94e974..61cc6075b0df 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2864,19 +2864,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2864 | switch (addr_param->v4.param_hdr.type) { | 2864 | switch (addr_param->v4.param_hdr.type) { |
2865 | case SCTP_PARAM_IPV6_ADDRESS: | 2865 | case SCTP_PARAM_IPV6_ADDRESS: |
2866 | if (!asoc->peer.ipv6_address) | 2866 | if (!asoc->peer.ipv6_address) |
2867 | return SCTP_ERROR_INV_PARAM; | 2867 | return SCTP_ERROR_DNS_FAILED; |
2868 | break; | 2868 | break; |
2869 | case SCTP_PARAM_IPV4_ADDRESS: | 2869 | case SCTP_PARAM_IPV4_ADDRESS: |
2870 | if (!asoc->peer.ipv4_address) | 2870 | if (!asoc->peer.ipv4_address) |
2871 | return SCTP_ERROR_INV_PARAM; | 2871 | return SCTP_ERROR_DNS_FAILED; |
2872 | break; | 2872 | break; |
2873 | default: | 2873 | default: |
2874 | return SCTP_ERROR_INV_PARAM; | 2874 | return SCTP_ERROR_DNS_FAILED; |
2875 | } | 2875 | } |
2876 | 2876 | ||
2877 | af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); | 2877 | af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); |
2878 | if (unlikely(!af)) | 2878 | if (unlikely(!af)) |
2879 | return SCTP_ERROR_INV_PARAM; | 2879 | return SCTP_ERROR_DNS_FAILED; |
2880 | 2880 | ||
2881 | af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); | 2881 | af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); |
2882 | 2882 | ||
@@ -2886,7 +2886,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2886 | * make sure we check for that) | 2886 | * make sure we check for that) |
2887 | */ | 2887 | */ |
2888 | if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) | 2888 | if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) |
2889 | return SCTP_ERROR_INV_PARAM; | 2889 | return SCTP_ERROR_DNS_FAILED; |
2890 | 2890 | ||
2891 | switch (asconf_param->param_hdr.type) { | 2891 | switch (asconf_param->param_hdr.type) { |
2892 | case SCTP_PARAM_ADD_IP: | 2892 | case SCTP_PARAM_ADD_IP: |
@@ -2954,12 +2954,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2954 | 2954 | ||
2955 | peer = sctp_assoc_lookup_paddr(asoc, &addr); | 2955 | peer = sctp_assoc_lookup_paddr(asoc, &addr); |
2956 | if (!peer) | 2956 | if (!peer) |
2957 | return SCTP_ERROR_INV_PARAM; | 2957 | return SCTP_ERROR_DNS_FAILED; |
2958 | 2958 | ||
2959 | sctp_assoc_set_primary(asoc, peer); | 2959 | sctp_assoc_set_primary(asoc, peer); |
2960 | break; | 2960 | break; |
2961 | default: | 2961 | default: |
2962 | return SCTP_ERROR_INV_PARAM; | 2962 | return SCTP_ERROR_UNKNOWN_PARAM; |
2963 | break; | 2963 | break; |
2964 | } | 2964 | } |
2965 | 2965 | ||
@@ -3273,7 +3273,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
3273 | retval = 1; | 3273 | retval = 1; |
3274 | break; | 3274 | break; |
3275 | 3275 | ||
3276 | case SCTP_ERROR_INV_PARAM: | 3276 | case SCTP_ERROR_UNKNOWN_PARAM: |
3277 | /* Disable sending this type of asconf parameter in | 3277 | /* Disable sending this type of asconf parameter in |
3278 | * future. | 3278 | * future. |
3279 | */ | 3279 | */ |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e2020eb2c8ca..86426aac1600 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -686,7 +686,8 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, | |||
686 | { | 686 | { |
687 | struct sctp_transport *t; | 687 | struct sctp_transport *t; |
688 | 688 | ||
689 | t = sctp_assoc_choose_shutdown_transport(asoc); | 689 | t = sctp_assoc_choose_alter_transport(asoc, |
690 | asoc->shutdown_last_sent_to); | ||
690 | asoc->shutdown_last_sent_to = t; | 691 | asoc->shutdown_last_sent_to = t; |
691 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; | 692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; |
692 | chunk->transport = t; | 693 | chunk->transport = t; |
@@ -777,7 +778,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, | |||
777 | { | 778 | { |
778 | struct sctp_transport *t; | 779 | struct sctp_transport *t; |
779 | 780 | ||
780 | t = asoc->peer.active_path; | 781 | t = sctp_assoc_choose_alter_transport(asoc, chunk->transport); |
781 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; | 782 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; |
782 | chunk->transport = t; | 783 | chunk->transport = t; |
783 | } | 784 | } |
@@ -1379,7 +1380,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1379 | 1380 | ||
1380 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | 1381 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: |
1381 | chunk = cmd->obj.ptr; | 1382 | chunk = cmd->obj.ptr; |
1382 | t = sctp_assoc_choose_init_transport(asoc); | 1383 | t = sctp_assoc_choose_alter_transport(asoc, |
1384 | asoc->init_last_sent_to); | ||
1383 | asoc->init_last_sent_to = t; | 1385 | asoc->init_last_sent_to = t; |
1384 | chunk->transport = t; | 1386 | chunk->transport = t; |
1385 | t->init_sent_count++; | 1387 | t->init_sent_count++; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 55a61aa69662..7288192f7df5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -5432,9 +5432,13 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
5432 | if (!reply) | 5432 | if (!reply) |
5433 | goto nomem; | 5433 | goto nomem; |
5434 | 5434 | ||
5435 | /* Do some failure management (Section 8.2). */ | 5435 | /* Do some failure management (Section 8.2). |
5436 | sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, | 5436 | * If we remove the transport an SHUTDOWN was last sent to, don't |
5437 | SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); | 5437 | * do failure management. |
5438 | */ | ||
5439 | if (asoc->shutdown_last_sent_to) | ||
5440 | sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, | ||
5441 | SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); | ||
5438 | 5442 | ||
5439 | /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for | 5443 | /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for |
5440 | * the T2-shutdown timer. | 5444 | * the T2-shutdown timer. |
@@ -5471,7 +5475,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
5471 | * detection on the appropriate destination address as defined in | 5475 | * detection on the appropriate destination address as defined in |
5472 | * RFC2960 [5] section 8.1 and 8.2. | 5476 | * RFC2960 [5] section 8.1 and 8.2. |
5473 | */ | 5477 | */ |
5474 | sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); | 5478 | if (transport) |
5479 | sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, | ||
5480 | SCTP_TRANSPORT(transport)); | ||
5475 | 5481 | ||
5476 | /* Reconfig T4 timer and transport. */ | 5482 | /* Reconfig T4 timer and transport. */ |
5477 | sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); | 5483 | sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 5c8186d88c61..6d9b3aafcc5d 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -698,7 +698,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
698 | TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \ | 698 | TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \ |
699 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ | 699 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ |
700 | TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ | 700 | TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ |
701 | } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ | 701 | } /* TYPE_SCTP_PRIMITIVE_ASCONF */ |
702 | 702 | ||
703 | /* The primary index for this table is the primitive type. | 703 | /* The primary index for this table is the primitive type. |
704 | * The secondary index for this table is the state. | 704 | * The secondary index for this table is the state. |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5fb3a8c9792e..971890dbfea0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -130,7 +130,7 @@ static inline int sctp_wspace(struct sctp_association *asoc) | |||
130 | if (asoc->ep->sndbuf_policy) | 130 | if (asoc->ep->sndbuf_policy) |
131 | amt = asoc->sndbuf_used; | 131 | amt = asoc->sndbuf_used; |
132 | else | 132 | else |
133 | amt = atomic_read(&asoc->base.sk->sk_wmem_alloc); | 133 | amt = sk_wmem_alloc_get(asoc->base.sk); |
134 | 134 | ||
135 | if (amt >= asoc->base.sk->sk_sndbuf) { | 135 | if (amt >= asoc->base.sk->sk_sndbuf) { |
136 | if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK) | 136 | if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK) |
@@ -1100,6 +1100,15 @@ static int __sctp_connect(struct sock* sk, | |||
1100 | goto out_free; | 1100 | goto out_free; |
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | /* In case the user of sctp_connectx() wants an association | ||
1104 | * id back, assign one now. | ||
1105 | */ | ||
1106 | if (assoc_id) { | ||
1107 | err = sctp_assoc_set_id(asoc, GFP_KERNEL); | ||
1108 | if (err < 0) | ||
1109 | goto out_free; | ||
1110 | } | ||
1111 | |||
1103 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | 1112 | err = sctp_primitive_ASSOCIATE(asoc, NULL); |
1104 | if (err < 0) { | 1113 | if (err < 0) { |
1105 | goto out_free; | 1114 | goto out_free; |
@@ -1120,7 +1129,7 @@ static int __sctp_connect(struct sock* sk, | |||
1120 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); | 1129 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); |
1121 | 1130 | ||
1122 | err = sctp_wait_for_connect(asoc, &timeo); | 1131 | err = sctp_wait_for_connect(asoc, &timeo); |
1123 | if (!err && assoc_id) | 1132 | if ((err == 0 || err == -EINPROGRESS) && assoc_id) |
1124 | *assoc_id = asoc->assoc_id; | 1133 | *assoc_id = asoc->assoc_id; |
1125 | 1134 | ||
1126 | /* Don't free association on exit. */ | 1135 | /* Don't free association on exit. */ |
@@ -1264,6 +1273,34 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | |||
1264 | return assoc_id; | 1273 | return assoc_id; |
1265 | } | 1274 | } |
1266 | 1275 | ||
1276 | /* | ||
1277 | * New (hopefully final) interface for the API. The option buffer is used | ||
1278 | * both for the returned association id and the addresses. | ||
1279 | */ | ||
1280 | SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, | ||
1281 | char __user *optval, | ||
1282 | int __user *optlen) | ||
1283 | { | ||
1284 | sctp_assoc_t assoc_id = 0; | ||
1285 | int err = 0; | ||
1286 | |||
1287 | if (len < sizeof(assoc_id)) | ||
1288 | return -EINVAL; | ||
1289 | |||
1290 | err = __sctp_setsockopt_connectx(sk, | ||
1291 | (struct sockaddr __user *)(optval + sizeof(assoc_id)), | ||
1292 | len - sizeof(assoc_id), &assoc_id); | ||
1293 | |||
1294 | if (err == 0 || err == -EINPROGRESS) { | ||
1295 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) | ||
1296 | return -EFAULT; | ||
1297 | if (put_user(sizeof(assoc_id), optlen)) | ||
1298 | return -EFAULT; | ||
1299 | } | ||
1300 | |||
1301 | return err; | ||
1302 | } | ||
1303 | |||
1267 | /* API 3.1.4 close() - UDP Style Syntax | 1304 | /* API 3.1.4 close() - UDP Style Syntax |
1268 | * Applications use close() to perform graceful shutdown (as described in | 1305 | * Applications use close() to perform graceful shutdown (as described in |
1269 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1306 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
@@ -1844,7 +1881,7 @@ static int sctp_skb_pull(struct sk_buff *skb, int len) | |||
1844 | len -= skb_len; | 1881 | len -= skb_len; |
1845 | __skb_pull(skb, skb_len); | 1882 | __skb_pull(skb, skb_len); |
1846 | 1883 | ||
1847 | for (list = skb_shinfo(skb)->frag_list; list; list = list->next) { | 1884 | skb_walk_frags(skb, list) { |
1848 | rlen = sctp_skb_pull(list, len); | 1885 | rlen = sctp_skb_pull(list, len); |
1849 | skb->len -= (len-rlen); | 1886 | skb->len -= (len-rlen); |
1850 | skb->data_len -= (len-rlen); | 1887 | skb->data_len -= (len-rlen); |
@@ -5578,6 +5615,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5578 | retval = sctp_getsockopt_local_addrs(sk, len, optval, | 5615 | retval = sctp_getsockopt_local_addrs(sk, len, optval, |
5579 | optlen); | 5616 | optlen); |
5580 | break; | 5617 | break; |
5618 | case SCTP_SOCKOPT_CONNECTX3: | ||
5619 | retval = sctp_getsockopt_connectx3(sk, len, optval, optlen); | ||
5620 | break; | ||
5581 | case SCTP_DEFAULT_SEND_PARAM: | 5621 | case SCTP_DEFAULT_SEND_PARAM: |
5582 | retval = sctp_getsockopt_default_send_param(sk, len, | 5622 | retval = sctp_getsockopt_default_send_param(sk, len, |
5583 | optval, optlen); | 5623 | optval, optlen); |
@@ -6483,7 +6523,7 @@ static int sctp_writeable(struct sock *sk) | |||
6483 | { | 6523 | { |
6484 | int amt = 0; | 6524 | int amt = 0; |
6485 | 6525 | ||
6486 | amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 6526 | amt = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
6487 | if (amt < 0) | 6527 | if (amt < 0) |
6488 | amt = 0; | 6528 | amt = 0; |
6489 | return amt; | 6529 | return amt; |
@@ -6612,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
6612 | finish_wait(sk->sk_sleep, &wait); | 6652 | finish_wait(sk->sk_sleep, &wait); |
6613 | } | 6653 | } |
6614 | 6654 | ||
6615 | static void sctp_sock_rfree_frag(struct sk_buff *skb) | ||
6616 | { | ||
6617 | struct sk_buff *frag; | ||
6618 | |||
6619 | if (!skb->data_len) | ||
6620 | goto done; | ||
6621 | |||
6622 | /* Don't forget the fragments. */ | ||
6623 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | ||
6624 | sctp_sock_rfree_frag(frag); | ||
6625 | |||
6626 | done: | ||
6627 | sctp_sock_rfree(skb); | ||
6628 | } | ||
6629 | |||
6630 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | 6655 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) |
6631 | { | 6656 | { |
6632 | struct sk_buff *frag; | 6657 | struct sk_buff *frag; |
@@ -6635,7 +6660,7 @@ static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | |||
6635 | goto done; | 6660 | goto done; |
6636 | 6661 | ||
6637 | /* Don't forget the fragments. */ | 6662 | /* Don't forget the fragments. */ |
6638 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | 6663 | skb_walk_frags(skb, frag) |
6639 | sctp_skb_set_owner_r_frag(frag, sk); | 6664 | sctp_skb_set_owner_r_frag(frag, sk); |
6640 | 6665 | ||
6641 | done: | 6666 | done: |
@@ -6736,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6736 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { | 6761 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { |
6737 | event = sctp_skb2event(skb); | 6762 | event = sctp_skb2event(skb); |
6738 | if (event->asoc == assoc) { | 6763 | if (event->asoc == assoc) { |
6739 | sctp_sock_rfree_frag(skb); | ||
6740 | __skb_unlink(skb, &oldsk->sk_receive_queue); | 6764 | __skb_unlink(skb, &oldsk->sk_receive_queue); |
6741 | __skb_queue_tail(&newsk->sk_receive_queue, skb); | 6765 | __skb_queue_tail(&newsk->sk_receive_queue, skb); |
6742 | sctp_skb_set_owner_r_frag(skb, newsk); | 6766 | sctp_skb_set_owner_r_frag(skb, newsk); |
@@ -6767,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6767 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { | 6791 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { |
6768 | event = sctp_skb2event(skb); | 6792 | event = sctp_skb2event(skb); |
6769 | if (event->asoc == assoc) { | 6793 | if (event->asoc == assoc) { |
6770 | sctp_sock_rfree_frag(skb); | ||
6771 | __skb_unlink(skb, &oldsp->pd_lobby); | 6794 | __skb_unlink(skb, &oldsp->pd_lobby); |
6772 | __skb_queue_tail(queue, skb); | 6795 | __skb_queue_tail(queue, skb); |
6773 | sctp_skb_set_owner_r_frag(skb, newsk); | 6796 | sctp_skb_set_owner_r_frag(skb, newsk); |
@@ -6782,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6782 | 6805 | ||
6783 | } | 6806 | } |
6784 | 6807 | ||
6785 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { | 6808 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) |
6786 | sctp_sock_rfree_frag(skb); | ||
6787 | sctp_skb_set_owner_r_frag(skb, newsk); | 6809 | sctp_skb_set_owner_r_frag(skb, newsk); |
6788 | } | ||
6789 | 6810 | ||
6790 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { | 6811 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) |
6791 | sctp_sock_rfree_frag(skb); | ||
6792 | sctp_skb_set_owner_r_frag(skb, newsk); | 6812 | sctp_skb_set_owner_r_frag(skb, newsk); |
6793 | } | ||
6794 | 6813 | ||
6795 | /* Set the type of socket to indicate that it is peeled off from the | 6814 | /* Set the type of socket to indicate that it is peeled off from the |
6796 | * original UDP-style socket or created with the accept() call on a | 6815 | * original UDP-style socket or created with the accept() call on a |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index f58e994e6852..63eabbc71298 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -49,8 +49,8 @@ static int zero = 0; | |||
49 | static int one = 1; | 49 | static int one = 1; |
50 | static int timer_max = 86400000; /* ms in one day */ | 50 | static int timer_max = 86400000; /* ms in one day */ |
51 | static int int_max = INT_MAX; | 51 | static int int_max = INT_MAX; |
52 | static long sack_timer_min = 1; | 52 | static int sack_timer_min = 1; |
53 | static long sack_timer_max = 500; | 53 | static int sack_timer_max = 500; |
54 | 54 | ||
55 | extern int sysctl_sctp_mem[3]; | 55 | extern int sysctl_sctp_mem[3]; |
56 | extern int sysctl_sctp_rmem[3]; | 56 | extern int sysctl_sctp_rmem[3]; |
@@ -223,7 +223,7 @@ static ctl_table sctp_table[] = { | |||
223 | .ctl_name = NET_SCTP_SACK_TIMEOUT, | 223 | .ctl_name = NET_SCTP_SACK_TIMEOUT, |
224 | .procname = "sack_timeout", | 224 | .procname = "sack_timeout", |
225 | .data = &sctp_sack_timeout, | 225 | .data = &sctp_sack_timeout, |
226 | .maxlen = sizeof(long), | 226 | .maxlen = sizeof(int), |
227 | .mode = 0644, | 227 | .mode = 0644, |
228 | .proc_handler = proc_dointvec_minmax, | 228 | .proc_handler = proc_dointvec_minmax, |
229 | .strategy = sysctl_intvec, | 229 | .strategy = sysctl_intvec, |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 5f186ca550d7..8b3560fd876d 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -976,9 +976,8 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
976 | * In general, the skb passed from IP can have only 1 level of | 976 | * In general, the skb passed from IP can have only 1 level of |
977 | * fragments. But we allow multiple levels of fragments. | 977 | * fragments. But we allow multiple levels of fragments. |
978 | */ | 978 | */ |
979 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 979 | skb_walk_frags(skb, frag) |
980 | sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); | 980 | sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); |
981 | } | ||
982 | } | 981 | } |
983 | 982 | ||
984 | /* Do accounting for bytes just read by user and release the references to | 983 | /* Do accounting for bytes just read by user and release the references to |
@@ -1003,7 +1002,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
1003 | goto done; | 1002 | goto done; |
1004 | 1003 | ||
1005 | /* Don't forget the fragments. */ | 1004 | /* Don't forget the fragments. */ |
1006 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 1005 | skb_walk_frags(skb, frag) { |
1007 | /* NOTE: skb_shinfos are recursive. Although IP returns | 1006 | /* NOTE: skb_shinfos are recursive. Although IP returns |
1008 | * skb's with only 1 level of fragments, SCTP reassembly can | 1007 | * skb's with only 1 level of fragments, SCTP reassembly can |
1009 | * increase the levels. | 1008 | * increase the levels. |
@@ -1026,7 +1025,7 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | |||
1026 | goto done; | 1025 | goto done; |
1027 | 1026 | ||
1028 | /* Don't forget the fragments. */ | 1027 | /* Don't forget the fragments. */ |
1029 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 1028 | skb_walk_frags(skb, frag) { |
1030 | /* NOTE: skb_shinfos are recursive. Although IP returns | 1029 | /* NOTE: skb_shinfos are recursive. Although IP returns |
1031 | * skb's with only 1 level of fragments, SCTP reassembly can | 1030 | * skb's with only 1 level of fragments, SCTP reassembly can |
1032 | * increase the levels. | 1031 | * increase the levels. |