diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 35 | ||||
-rw-r--r-- | net/sctp/protocol.c | 29 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 78 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 4 | ||||
-rw-r--r-- | net/sctp/socket.c | 206 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 82 |
7 files changed, 319 insertions, 117 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index a49fa80b57b9..bf612d954d41 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -369,7 +369,7 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) | |||
369 | void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | 369 | void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, |
370 | struct sctp_transport *t, __u32 pmtu) | 370 | struct sctp_transport *t, __u32 pmtu) |
371 | { | 371 | { |
372 | if (!t || (t->pathmtu == pmtu)) | 372 | if (!t || (t->pathmtu <= pmtu)) |
373 | return; | 373 | return; |
374 | 374 | ||
375 | if (sock_owned_by_user(sk)) { | 375 | if (sock_owned_by_user(sk)) { |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 4124bbb99947..ceaa4aa066ea 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -223,10 +223,9 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
223 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 223 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
224 | } | 224 | } |
225 | 225 | ||
226 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " | 226 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", |
227 | "src:" NIP6_FMT " dst:" NIP6_FMT "\n", | ||
228 | __func__, skb, skb->len, | 227 | __func__, skb, skb->len, |
229 | NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); | 228 | &fl.fl6_src, &fl.fl6_dst); |
230 | 229 | ||
231 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); | 230 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); |
232 | 231 | ||
@@ -252,23 +251,19 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
252 | fl.oif = daddr->v6.sin6_scope_id; | 251 | fl.oif = daddr->v6.sin6_scope_id; |
253 | 252 | ||
254 | 253 | ||
255 | SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ", | 254 | SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl.fl6_dst); |
256 | __func__, NIP6(fl.fl6_dst)); | ||
257 | 255 | ||
258 | if (saddr) { | 256 | if (saddr) { |
259 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); | 257 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); |
260 | SCTP_DEBUG_PRINTK( | 258 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl.fl6_src); |
261 | "SRC=" NIP6_FMT " - ", | ||
262 | NIP6(fl.fl6_src)); | ||
263 | } | 259 | } |
264 | 260 | ||
265 | dst = ip6_route_output(&init_net, NULL, &fl); | 261 | dst = ip6_route_output(&init_net, NULL, &fl); |
266 | if (!dst->error) { | 262 | if (!dst->error) { |
267 | struct rt6_info *rt; | 263 | struct rt6_info *rt; |
268 | rt = (struct rt6_info *)dst; | 264 | rt = (struct rt6_info *)dst; |
269 | SCTP_DEBUG_PRINTK( | 265 | SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", |
270 | "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", | 266 | &rt->rt6i_dst.addr, &rt->rt6i_src.addr); |
271 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); | ||
272 | return dst; | 267 | return dst; |
273 | } | 268 | } |
274 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 269 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
@@ -314,9 +309,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, | |||
314 | __u8 matchlen = 0; | 309 | __u8 matchlen = 0; |
315 | __u8 bmatchlen; | 310 | __u8 bmatchlen; |
316 | 311 | ||
317 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " | 312 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", |
318 | "daddr:" NIP6_FMT " ", | 313 | __func__, asoc, dst, &daddr->v6.sin6_addr); |
319 | __func__, asoc, dst, NIP6(daddr->v6.sin6_addr)); | ||
320 | 314 | ||
321 | if (!asoc) { | 315 | if (!asoc) { |
322 | ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), | 316 | ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), |
@@ -324,8 +318,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, | |||
324 | &daddr->v6.sin6_addr, | 318 | &daddr->v6.sin6_addr, |
325 | inet6_sk(&sk->inet.sk)->srcprefs, | 319 | inet6_sk(&sk->inet.sk)->srcprefs, |
326 | &saddr->v6.sin6_addr); | 320 | &saddr->v6.sin6_addr); |
327 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", | 321 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n", |
328 | NIP6(saddr->v6.sin6_addr)); | 322 | &saddr->v6.sin6_addr); |
329 | return; | 323 | return; |
330 | } | 324 | } |
331 | 325 | ||
@@ -353,12 +347,11 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, | |||
353 | 347 | ||
354 | if (baddr) { | 348 | if (baddr) { |
355 | memcpy(saddr, baddr, sizeof(union sctp_addr)); | 349 | memcpy(saddr, baddr, sizeof(union sctp_addr)); |
356 | SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n", | 350 | SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr); |
357 | NIP6(saddr->v6.sin6_addr)); | ||
358 | } else { | 351 | } else { |
359 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " | 352 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " |
360 | "address for the dest:" NIP6_FMT "\n", | 353 | "address for the dest:%pI6\n", |
361 | __func__, asoc, NIP6(daddr->v6.sin6_addr)); | 354 | __func__, asoc, &daddr->v6.sin6_addr); |
362 | } | 355 | } |
363 | 356 | ||
364 | rcu_read_unlock(); | 357 | rcu_read_unlock(); |
@@ -727,7 +720,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb) | |||
727 | /* Dump the v6 addr to the seq file. */ | 720 | /* Dump the v6 addr to the seq file. */ |
728 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) | 721 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) |
729 | { | 722 | { |
730 | seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr)); | 723 | seq_printf(seq, "%pI6 ", &addr->v6.sin6_addr); |
731 | } | 724 | } |
732 | 725 | ||
733 | static void sctp_v6_ecn_capable(struct sock *sk) | 726 | static void sctp_v6_ecn_capable(struct sock *sk) |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 0b65354aaf64..b78e3be69013 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -102,6 +102,8 @@ struct sock *sctp_get_ctl_sock(void) | |||
102 | /* Set up the proc fs entry for the SCTP protocol. */ | 102 | /* Set up the proc fs entry for the SCTP protocol. */ |
103 | static __init int sctp_proc_init(void) | 103 | static __init int sctp_proc_init(void) |
104 | { | 104 | { |
105 | if (percpu_counter_init(&sctp_sockets_allocated, 0)) | ||
106 | goto out_nomem; | ||
105 | #ifdef CONFIG_PROC_FS | 107 | #ifdef CONFIG_PROC_FS |
106 | if (!proc_net_sctp) { | 108 | if (!proc_net_sctp) { |
107 | struct proc_dir_entry *ent; | 109 | struct proc_dir_entry *ent; |
@@ -110,7 +112,7 @@ static __init int sctp_proc_init(void) | |||
110 | ent->owner = THIS_MODULE; | 112 | ent->owner = THIS_MODULE; |
111 | proc_net_sctp = ent; | 113 | proc_net_sctp = ent; |
112 | } else | 114 | } else |
113 | goto out_nomem; | 115 | goto out_free_percpu; |
114 | } | 116 | } |
115 | 117 | ||
116 | if (sctp_snmp_proc_init()) | 118 | if (sctp_snmp_proc_init()) |
@@ -135,11 +137,14 @@ out_snmp_proc_init: | |||
135 | proc_net_sctp = NULL; | 137 | proc_net_sctp = NULL; |
136 | remove_proc_entry("sctp", init_net.proc_net); | 138 | remove_proc_entry("sctp", init_net.proc_net); |
137 | } | 139 | } |
138 | out_nomem: | 140 | out_free_percpu: |
139 | return -ENOMEM; | 141 | percpu_counter_destroy(&sctp_sockets_allocated); |
140 | #else | 142 | #else |
141 | return 0; | 143 | return 0; |
142 | #endif /* CONFIG_PROC_FS */ | 144 | #endif /* CONFIG_PROC_FS */ |
145 | |||
146 | out_nomem: | ||
147 | return -ENOMEM; | ||
143 | } | 148 | } |
144 | 149 | ||
145 | /* Clean up the proc fs entry for the SCTP protocol. | 150 | /* Clean up the proc fs entry for the SCTP protocol. |
@@ -482,9 +487,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
482 | if (saddr) | 487 | if (saddr) |
483 | fl.fl4_src = saddr->v4.sin_addr.s_addr; | 488 | fl.fl4_src = saddr->v4.sin_addr.s_addr; |
484 | 489 | ||
485 | SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ", | 490 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
486 | __func__, NIPQUAD(fl.fl4_dst), | 491 | __func__, &fl.fl4_dst, &fl.fl4_src); |
487 | NIPQUAD(fl.fl4_src)); | ||
488 | 492 | ||
489 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 493 | if (!ip_route_output_key(&init_net, &rt, &fl)) { |
490 | dst = &rt->u.dst; | 494 | dst = &rt->u.dst; |
@@ -540,8 +544,8 @@ out_unlock: | |||
540 | rcu_read_unlock(); | 544 | rcu_read_unlock(); |
541 | out: | 545 | out: |
542 | if (dst) | 546 | if (dst) |
543 | SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n", | 547 | SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", |
544 | NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_src)); | 548 | &rt->rt_dst, &rt->rt_src); |
545 | else | 549 | else |
546 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 550 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
547 | 551 | ||
@@ -646,7 +650,7 @@ static void sctp_v4_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr) | |||
646 | /* Dump the v4 addr to the seq file. */ | 650 | /* Dump the v4 addr to the seq file. */ |
647 | static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) | 651 | static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) |
648 | { | 652 | { |
649 | seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr)); | 653 | seq_printf(seq, "%pI4 ", &addr->v4.sin_addr); |
650 | } | 654 | } |
651 | 655 | ||
652 | static void sctp_v4_ecn_capable(struct sock *sk) | 656 | static void sctp_v4_ecn_capable(struct sock *sk) |
@@ -866,11 +870,10 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
866 | { | 870 | { |
867 | struct inet_sock *inet = inet_sk(skb->sk); | 871 | struct inet_sock *inet = inet_sk(skb->sk); |
868 | 872 | ||
869 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " | 873 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", |
870 | "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n", | ||
871 | __func__, skb, skb->len, | 874 | __func__, skb, skb->len, |
872 | NIPQUAD(skb->rtable->rt_src), | 875 | &skb->rtable->rt_src, |
873 | NIPQUAD(skb->rtable->rt_dst)); | 876 | &skb->rtable->rt_dst); |
874 | 877 | ||
875 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? | 878 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? |
876 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | 879 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index d4c3fbc4671e..1c4e5d6c29c0 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -1123,19 +1123,17 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1123 | if (from_addr.sa.sa_family == AF_INET6) { | 1123 | if (from_addr.sa.sa_family == AF_INET6) { |
1124 | if (net_ratelimit()) | 1124 | if (net_ratelimit()) |
1125 | printk(KERN_WARNING | 1125 | printk(KERN_WARNING |
1126 | "%s association %p could not find address " | 1126 | "%s association %p could not find address %pI6\n", |
1127 | NIP6_FMT "\n", | ||
1128 | __func__, | 1127 | __func__, |
1129 | asoc, | 1128 | asoc, |
1130 | NIP6(from_addr.v6.sin6_addr)); | 1129 | &from_addr.v6.sin6_addr); |
1131 | } else { | 1130 | } else { |
1132 | if (net_ratelimit()) | 1131 | if (net_ratelimit()) |
1133 | printk(KERN_WARNING | 1132 | printk(KERN_WARNING |
1134 | "%s association %p could not find address " | 1133 | "%s association %p could not find address %pI4\n", |
1135 | NIPQUAD_FMT "\n", | ||
1136 | __func__, | 1134 | __func__, |
1137 | asoc, | 1135 | asoc, |
1138 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | 1136 | &from_addr.v4.sin_addr.s_addr); |
1139 | } | 1137 | } |
1140 | return SCTP_DISPOSITION_DISCARD; | 1138 | return SCTP_DISPOSITION_DISCARD; |
1141 | } | 1139 | } |
@@ -2544,6 +2542,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
2544 | sctp_shutdownhdr_t *sdh; | 2542 | sctp_shutdownhdr_t *sdh; |
2545 | sctp_disposition_t disposition; | 2543 | sctp_disposition_t disposition; |
2546 | struct sctp_ulpevent *ev; | 2544 | struct sctp_ulpevent *ev; |
2545 | __u32 ctsn; | ||
2547 | 2546 | ||
2548 | if (!sctp_vtag_verify(chunk, asoc)) | 2547 | if (!sctp_vtag_verify(chunk, asoc)) |
2549 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2548 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
@@ -2558,6 +2557,14 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
2558 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; | 2557 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; |
2559 | skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); | 2558 | skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); |
2560 | chunk->subh.shutdown_hdr = sdh; | 2559 | chunk->subh.shutdown_hdr = sdh; |
2560 | ctsn = ntohl(sdh->cum_tsn_ack); | ||
2561 | |||
2562 | /* If Cumulative TSN Ack beyond the max tsn currently | ||
2563 | * send, terminating the association and respond to the | ||
2564 | * sender with an ABORT. | ||
2565 | */ | ||
2566 | if (!TSN_lt(ctsn, asoc->next_tsn)) | ||
2567 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | ||
2561 | 2568 | ||
2562 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT | 2569 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT |
2563 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to | 2570 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to |
@@ -2599,6 +2606,51 @@ out: | |||
2599 | return disposition; | 2606 | return disposition; |
2600 | } | 2607 | } |
2601 | 2608 | ||
2609 | /* | ||
2610 | * sctp_sf_do_9_2_shut_ctsn | ||
2611 | * | ||
2612 | * Once an endpoint has reached the SHUTDOWN-RECEIVED state, | ||
2613 | * it MUST NOT send a SHUTDOWN in response to a ULP request. | ||
2614 | * The Cumulative TSN Ack of the received SHUTDOWN chunk | ||
2615 | * MUST be processed. | ||
2616 | */ | ||
2617 | sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | ||
2618 | const struct sctp_association *asoc, | ||
2619 | const sctp_subtype_t type, | ||
2620 | void *arg, | ||
2621 | sctp_cmd_seq_t *commands) | ||
2622 | { | ||
2623 | struct sctp_chunk *chunk = arg; | ||
2624 | sctp_shutdownhdr_t *sdh; | ||
2625 | |||
2626 | if (!sctp_vtag_verify(chunk, asoc)) | ||
2627 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
2628 | |||
2629 | /* Make sure that the SHUTDOWN chunk has a valid length. */ | ||
2630 | if (!sctp_chunk_length_valid(chunk, | ||
2631 | sizeof(struct sctp_shutdown_chunk_t))) | ||
2632 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | ||
2633 | commands); | ||
2634 | |||
2635 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; | ||
2636 | |||
2637 | /* If Cumulative TSN Ack beyond the max tsn currently | ||
2638 | * send, terminating the association and respond to the | ||
2639 | * sender with an ABORT. | ||
2640 | */ | ||
2641 | if (!TSN_lt(ntohl(sdh->cum_tsn_ack), asoc->next_tsn)) | ||
2642 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | ||
2643 | |||
2644 | /* verify, by checking the Cumulative TSN Ack field of the | ||
2645 | * chunk, that all its outstanding DATA chunks have been | ||
2646 | * received by the SHUTDOWN sender. | ||
2647 | */ | ||
2648 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, | ||
2649 | SCTP_BE32(sdh->cum_tsn_ack)); | ||
2650 | |||
2651 | return SCTP_DISPOSITION_CONSUME; | ||
2652 | } | ||
2653 | |||
2602 | /* RFC 2960 9.2 | 2654 | /* RFC 2960 9.2 |
2603 | * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk | 2655 | * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk |
2604 | * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination | 2656 | * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination |
@@ -3637,6 +3689,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep, | |||
3637 | { | 3689 | { |
3638 | struct sctp_chunk *chunk = arg; | 3690 | struct sctp_chunk *chunk = arg; |
3639 | struct sctp_fwdtsn_hdr *fwdtsn_hdr; | 3691 | struct sctp_fwdtsn_hdr *fwdtsn_hdr; |
3692 | struct sctp_fwdtsn_skip *skip; | ||
3640 | __u16 len; | 3693 | __u16 len; |
3641 | __u32 tsn; | 3694 | __u32 tsn; |
3642 | 3695 | ||
@@ -3666,6 +3719,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep, | |||
3666 | if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) | 3719 | if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) |
3667 | goto discard_noforce; | 3720 | goto discard_noforce; |
3668 | 3721 | ||
3722 | /* Silently discard the chunk if stream-id is not valid */ | ||
3723 | sctp_walk_fwdtsn(skip, chunk) { | ||
3724 | if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams) | ||
3725 | goto discard_noforce; | ||
3726 | } | ||
3727 | |||
3669 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); | 3728 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); |
3670 | if (len > sizeof(struct sctp_fwdtsn_hdr)) | 3729 | if (len > sizeof(struct sctp_fwdtsn_hdr)) |
3671 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, | 3730 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, |
@@ -3697,6 +3756,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( | |||
3697 | { | 3756 | { |
3698 | struct sctp_chunk *chunk = arg; | 3757 | struct sctp_chunk *chunk = arg; |
3699 | struct sctp_fwdtsn_hdr *fwdtsn_hdr; | 3758 | struct sctp_fwdtsn_hdr *fwdtsn_hdr; |
3759 | struct sctp_fwdtsn_skip *skip; | ||
3700 | __u16 len; | 3760 | __u16 len; |
3701 | __u32 tsn; | 3761 | __u32 tsn; |
3702 | 3762 | ||
@@ -3726,6 +3786,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( | |||
3726 | if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) | 3786 | if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) |
3727 | goto gen_shutdown; | 3787 | goto gen_shutdown; |
3728 | 3788 | ||
3789 | /* Silently discard the chunk if stream-id is not valid */ | ||
3790 | sctp_walk_fwdtsn(skip, chunk) { | ||
3791 | if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams) | ||
3792 | goto gen_shutdown; | ||
3793 | } | ||
3794 | |||
3729 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); | 3795 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); |
3730 | if (len > sizeof(struct sctp_fwdtsn_hdr)) | 3796 | if (len > sizeof(struct sctp_fwdtsn_hdr)) |
3731 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, | 3797 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index dd4ddc40c0ad..5c8186d88c61 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -266,11 +266,11 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
266 | /* SCTP_STATE_ESTABLISHED */ \ | 266 | /* SCTP_STATE_ESTABLISHED */ \ |
267 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ | 267 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ |
268 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 268 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
269 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 269 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ |
270 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 270 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
271 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ | 271 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ |
272 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 272 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
273 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 273 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shut_ctsn), \ |
274 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ | 274 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ |
275 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 275 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
276 | } /* TYPE_SCTP_SHUTDOWN */ | 276 | } /* TYPE_SCTP_SHUTDOWN */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a1b904529d5e..b14a8f33e42d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -114,7 +114,7 @@ extern int sysctl_sctp_wmem[3]; | |||
114 | 114 | ||
115 | static int sctp_memory_pressure; | 115 | static int sctp_memory_pressure; |
116 | static atomic_t sctp_memory_allocated; | 116 | static atomic_t sctp_memory_allocated; |
117 | static atomic_t sctp_sockets_allocated; | 117 | struct percpu_counter sctp_sockets_allocated; |
118 | 118 | ||
119 | static void sctp_enter_memory_pressure(struct sock *sk) | 119 | static void sctp_enter_memory_pressure(struct sock *sk) |
120 | { | 120 | { |
@@ -2404,9 +2404,9 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk, | |||
2404 | if (params.sack_delay == 0 && params.sack_freq == 0) | 2404 | if (params.sack_delay == 0 && params.sack_freq == 0) |
2405 | return 0; | 2405 | return 0; |
2406 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | 2406 | } else if (optlen == sizeof(struct sctp_assoc_value)) { |
2407 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | 2407 | printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " |
2408 | "in delayed_ack socket option deprecated\n"); | 2408 | "in delayed_ack socket option deprecated\n"); |
2409 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | 2409 | printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); |
2410 | if (copy_from_user(¶ms, optval, optlen)) | 2410 | if (copy_from_user(¶ms, optval, optlen)) |
2411 | return -EFAULT; | 2411 | return -EFAULT; |
2412 | 2412 | ||
@@ -2778,32 +2778,77 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op | |||
2778 | } | 2778 | } |
2779 | 2779 | ||
2780 | /* | 2780 | /* |
2781 | * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) | 2781 | * 8.1.16. Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) |
2782 | * | 2782 | * This option will get or set the maximum size to put in any outgoing |
2783 | * This socket option specifies the maximum size to put in any outgoing | 2783 | * SCTP DATA chunk. If a message is larger than this size it will be |
2784 | * SCTP chunk. If a message is larger than this size it will be | ||
2785 | * fragmented by SCTP into the specified size. Note that the underlying | 2784 | * fragmented by SCTP into the specified size. Note that the underlying |
2786 | * SCTP implementation may fragment into smaller sized chunks when the | 2785 | * SCTP implementation may fragment into smaller sized chunks when the |
2787 | * PMTU of the underlying association is smaller than the value set by | 2786 | * PMTU of the underlying association is smaller than the value set by |
2788 | * the user. | 2787 | * the user. The default value for this option is '0' which indicates |
2788 | * the user is NOT limiting fragmentation and only the PMTU will effect | ||
2789 | * SCTP's choice of DATA chunk size. Note also that values set larger | ||
2790 | * than the maximum size of an IP datagram will effectively let SCTP | ||
2791 | * control fragmentation (i.e. the same as setting this option to 0). | ||
2792 | * | ||
2793 | * The following structure is used to access and modify this parameter: | ||
2794 | * | ||
2795 | * struct sctp_assoc_value { | ||
2796 | * sctp_assoc_t assoc_id; | ||
2797 | * uint32_t assoc_value; | ||
2798 | * }; | ||
2799 | * | ||
2800 | * assoc_id: This parameter is ignored for one-to-one style sockets. | ||
2801 | * For one-to-many style sockets this parameter indicates which | ||
2802 | * association the user is performing an action upon. Note that if | ||
2803 | * this field's value is zero then the endpoints default value is | ||
2804 | * changed (effecting future associations only). | ||
2805 | * assoc_value: This parameter specifies the maximum size in bytes. | ||
2789 | */ | 2806 | */ |
2790 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) | 2807 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) |
2791 | { | 2808 | { |
2809 | struct sctp_assoc_value params; | ||
2792 | struct sctp_association *asoc; | 2810 | struct sctp_association *asoc; |
2793 | struct sctp_sock *sp = sctp_sk(sk); | 2811 | struct sctp_sock *sp = sctp_sk(sk); |
2794 | int val; | 2812 | int val; |
2795 | 2813 | ||
2796 | if (optlen < sizeof(int)) | 2814 | if (optlen == sizeof(int)) { |
2815 | printk(KERN_WARNING | ||
2816 | "SCTP: Use of int in maxseg socket option deprecated\n"); | ||
2817 | printk(KERN_WARNING | ||
2818 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
2819 | if (copy_from_user(&val, optval, optlen)) | ||
2820 | return -EFAULT; | ||
2821 | params.assoc_id = 0; | ||
2822 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2823 | if (copy_from_user(¶ms, optval, optlen)) | ||
2824 | return -EFAULT; | ||
2825 | val = params.assoc_value; | ||
2826 | } else | ||
2797 | return -EINVAL; | 2827 | return -EINVAL; |
2798 | if (get_user(val, (int __user *)optval)) | 2828 | |
2799 | return -EFAULT; | ||
2800 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) | 2829 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) |
2801 | return -EINVAL; | 2830 | return -EINVAL; |
2802 | sp->user_frag = val; | ||
2803 | 2831 | ||
2804 | /* Update the frag_point of the existing associations. */ | 2832 | asoc = sctp_id2assoc(sk, params.assoc_id); |
2805 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | 2833 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) |
2806 | asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | 2834 | return -EINVAL; |
2835 | |||
2836 | if (asoc) { | ||
2837 | if (val == 0) { | ||
2838 | val = asoc->pathmtu; | ||
2839 | val -= sp->pf->af->net_header_len; | ||
2840 | val -= sizeof(struct sctphdr) + | ||
2841 | sizeof(struct sctp_data_chunk); | ||
2842 | } | ||
2843 | |||
2844 | asoc->frag_point = val; | ||
2845 | } else { | ||
2846 | sp->user_frag = val; | ||
2847 | |||
2848 | /* Update the frag_point of the existing associations. */ | ||
2849 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
2850 | asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | ||
2851 | } | ||
2807 | } | 2852 | } |
2808 | 2853 | ||
2809 | return 0; | 2854 | return 0; |
@@ -2965,14 +3010,21 @@ static int sctp_setsockopt_fragment_interleave(struct sock *sk, | |||
2965 | } | 3010 | } |
2966 | 3011 | ||
2967 | /* | 3012 | /* |
2968 | * 7.1.25. Set or Get the sctp partial delivery point | 3013 | * 8.1.21. Set or Get the SCTP Partial Delivery Point |
2969 | * (SCTP_PARTIAL_DELIVERY_POINT) | 3014 | * (SCTP_PARTIAL_DELIVERY_POINT) |
3015 | * | ||
2970 | * This option will set or get the SCTP partial delivery point. This | 3016 | * This option will set or get the SCTP partial delivery point. This |
2971 | * point is the size of a message where the partial delivery API will be | 3017 | * point is the size of a message where the partial delivery API will be |
2972 | * invoked to help free up rwnd space for the peer. Setting this to a | 3018 | * invoked to help free up rwnd space for the peer. Setting this to a |
2973 | * lower value will cause partial delivery's to happen more often. The | 3019 | * lower value will cause partial deliveries to happen more often. The |
2974 | * calls argument is an integer that sets or gets the partial delivery | 3020 | * calls argument is an integer that sets or gets the partial delivery |
2975 | * point. | 3021 | * point. Note also that the call will fail if the user attempts to set |
3022 | * this value larger than the socket receive buffer size. | ||
3023 | * | ||
3024 | * Note that any single message having a length smaller than or equal to | ||
3025 | * the SCTP partial delivery point will be delivered in one single read | ||
3026 | * call as long as the user provided buffer is large enough to hold the | ||
3027 | * message. | ||
2976 | */ | 3028 | */ |
2977 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | 3029 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, |
2978 | char __user *optval, | 3030 | char __user *optval, |
@@ -2985,6 +3037,12 @@ static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | |||
2985 | if (get_user(val, (int __user *)optval)) | 3037 | if (get_user(val, (int __user *)optval)) |
2986 | return -EFAULT; | 3038 | return -EFAULT; |
2987 | 3039 | ||
3040 | /* Note: We double the receive buffer from what the user sets | ||
3041 | * it to be, also initial rwnd is based on rcvbuf/2. | ||
3042 | */ | ||
3043 | if (val > (sk->sk_rcvbuf >> 1)) | ||
3044 | return -EINVAL; | ||
3045 | |||
2988 | sctp_sk(sk)->pd_point = val; | 3046 | sctp_sk(sk)->pd_point = val; |
2989 | 3047 | ||
2990 | return 0; /* is this the right error code? */ | 3048 | return 0; /* is this the right error code? */ |
@@ -3613,7 +3671,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3613 | sp->hmac = NULL; | 3671 | sp->hmac = NULL; |
3614 | 3672 | ||
3615 | SCTP_DBG_OBJCNT_INC(sock); | 3673 | SCTP_DBG_OBJCNT_INC(sock); |
3616 | atomic_inc(&sctp_sockets_allocated); | 3674 | percpu_counter_inc(&sctp_sockets_allocated); |
3675 | |||
3676 | local_bh_disable(); | ||
3677 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | ||
3678 | local_bh_enable(); | ||
3679 | |||
3617 | return 0; | 3680 | return 0; |
3618 | } | 3681 | } |
3619 | 3682 | ||
@@ -3627,7 +3690,10 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
3627 | /* Release our hold on the endpoint. */ | 3690 | /* Release our hold on the endpoint. */ |
3628 | ep = sctp_sk(sk)->ep; | 3691 | ep = sctp_sk(sk)->ep; |
3629 | sctp_endpoint_free(ep); | 3692 | sctp_endpoint_free(ep); |
3630 | atomic_dec(&sctp_sockets_allocated); | 3693 | percpu_counter_dec(&sctp_sockets_allocated); |
3694 | local_bh_disable(); | ||
3695 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | ||
3696 | local_bh_enable(); | ||
3631 | } | 3697 | } |
3632 | 3698 | ||
3633 | /* API 4.1.7 shutdown() - TCP Style Syntax | 3699 | /* API 4.1.7 shutdown() - TCP Style Syntax |
@@ -4168,9 +4234,9 @@ static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, | |||
4168 | if (copy_from_user(¶ms, optval, len)) | 4234 | if (copy_from_user(¶ms, optval, len)) |
4169 | return -EFAULT; | 4235 | return -EFAULT; |
4170 | } else if (len == sizeof(struct sctp_assoc_value)) { | 4236 | } else if (len == sizeof(struct sctp_assoc_value)) { |
4171 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | 4237 | printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " |
4172 | "in delayed_ack socket option deprecated\n"); | 4238 | "in delayed_ack socket option deprecated\n"); |
4173 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | 4239 | printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); |
4174 | if (copy_from_user(¶ms, optval, len)) | 4240 | if (copy_from_user(¶ms, optval, len)) |
4175 | return -EFAULT; | 4241 | return -EFAULT; |
4176 | } else | 4242 | } else |
@@ -5092,30 +5158,69 @@ static int sctp_getsockopt_context(struct sock *sk, int len, | |||
5092 | } | 5158 | } |
5093 | 5159 | ||
5094 | /* | 5160 | /* |
5095 | * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) | 5161 | * 8.1.16. Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) |
5096 | * | 5162 | * This option will get or set the maximum size to put in any outgoing |
5097 | * This socket option specifies the maximum size to put in any outgoing | 5163 | * SCTP DATA chunk. If a message is larger than this size it will be |
5098 | * SCTP chunk. If a message is larger than this size it will be | ||
5099 | * fragmented by SCTP into the specified size. Note that the underlying | 5164 | * fragmented by SCTP into the specified size. Note that the underlying |
5100 | * SCTP implementation may fragment into smaller sized chunks when the | 5165 | * SCTP implementation may fragment into smaller sized chunks when the |
5101 | * PMTU of the underlying association is smaller than the value set by | 5166 | * PMTU of the underlying association is smaller than the value set by |
5102 | * the user. | 5167 | * the user. The default value for this option is '0' which indicates |
5168 | * the user is NOT limiting fragmentation and only the PMTU will effect | ||
5169 | * SCTP's choice of DATA chunk size. Note also that values set larger | ||
5170 | * than the maximum size of an IP datagram will effectively let SCTP | ||
5171 | * control fragmentation (i.e. the same as setting this option to 0). | ||
5172 | * | ||
5173 | * The following structure is used to access and modify this parameter: | ||
5174 | * | ||
5175 | * struct sctp_assoc_value { | ||
5176 | * sctp_assoc_t assoc_id; | ||
5177 | * uint32_t assoc_value; | ||
5178 | * }; | ||
5179 | * | ||
5180 | * assoc_id: This parameter is ignored for one-to-one style sockets. | ||
5181 | * For one-to-many style sockets this parameter indicates which | ||
5182 | * association the user is performing an action upon. Note that if | ||
5183 | * this field's value is zero then the endpoints default value is | ||
5184 | * changed (effecting future associations only). | ||
5185 | * assoc_value: This parameter specifies the maximum size in bytes. | ||
5103 | */ | 5186 | */ |
5104 | static int sctp_getsockopt_maxseg(struct sock *sk, int len, | 5187 | static int sctp_getsockopt_maxseg(struct sock *sk, int len, |
5105 | char __user *optval, int __user *optlen) | 5188 | char __user *optval, int __user *optlen) |
5106 | { | 5189 | { |
5107 | int val; | 5190 | struct sctp_assoc_value params; |
5191 | struct sctp_association *asoc; | ||
5108 | 5192 | ||
5109 | if (len < sizeof(int)) | 5193 | if (len == sizeof(int)) { |
5194 | printk(KERN_WARNING | ||
5195 | "SCTP: Use of int in maxseg socket option deprecated\n"); | ||
5196 | printk(KERN_WARNING | ||
5197 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
5198 | params.assoc_id = 0; | ||
5199 | } else if (len >= sizeof(struct sctp_assoc_value)) { | ||
5200 | len = sizeof(struct sctp_assoc_value); | ||
5201 | if (copy_from_user(¶ms, optval, sizeof(params))) | ||
5202 | return -EFAULT; | ||
5203 | } else | ||
5110 | return -EINVAL; | 5204 | return -EINVAL; |
5111 | 5205 | ||
5112 | len = sizeof(int); | 5206 | asoc = sctp_id2assoc(sk, params.assoc_id); |
5207 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||
5208 | return -EINVAL; | ||
5209 | |||
5210 | if (asoc) | ||
5211 | params.assoc_value = asoc->frag_point; | ||
5212 | else | ||
5213 | params.assoc_value = sctp_sk(sk)->user_frag; | ||
5113 | 5214 | ||
5114 | val = sctp_sk(sk)->user_frag; | ||
5115 | if (put_user(len, optlen)) | 5215 | if (put_user(len, optlen)) |
5116 | return -EFAULT; | 5216 | return -EFAULT; |
5117 | if (copy_to_user(optval, &val, len)) | 5217 | if (len == sizeof(int)) { |
5118 | return -EFAULT; | 5218 | if (copy_to_user(optval, ¶ms.assoc_value, len)) |
5219 | return -EFAULT; | ||
5220 | } else { | ||
5221 | if (copy_to_user(optval, ¶ms, len)) | ||
5222 | return -EFAULT; | ||
5223 | } | ||
5119 | 5224 | ||
5120 | return 0; | 5225 | return 0; |
5121 | } | 5226 | } |
@@ -5368,6 +5473,38 @@ num: | |||
5368 | return 0; | 5473 | return 0; |
5369 | } | 5474 | } |
5370 | 5475 | ||
5476 | /* | ||
5477 | * 8.2.5. Get the Current Number of Associations (SCTP_GET_ASSOC_NUMBER) | ||
5478 | * This option gets the current number of associations that are attached | ||
5479 | * to a one-to-many style socket. The option value is an uint32_t. | ||
5480 | */ | ||
5481 | static int sctp_getsockopt_assoc_number(struct sock *sk, int len, | ||
5482 | char __user *optval, int __user *optlen) | ||
5483 | { | ||
5484 | struct sctp_sock *sp = sctp_sk(sk); | ||
5485 | struct sctp_association *asoc; | ||
5486 | u32 val = 0; | ||
5487 | |||
5488 | if (sctp_style(sk, TCP)) | ||
5489 | return -EOPNOTSUPP; | ||
5490 | |||
5491 | if (len < sizeof(u32)) | ||
5492 | return -EINVAL; | ||
5493 | |||
5494 | len = sizeof(u32); | ||
5495 | |||
5496 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5497 | val++; | ||
5498 | } | ||
5499 | |||
5500 | if (put_user(len, optlen)) | ||
5501 | return -EFAULT; | ||
5502 | if (copy_to_user(optval, &val, len)) | ||
5503 | return -EFAULT; | ||
5504 | |||
5505 | return 0; | ||
5506 | } | ||
5507 | |||
5371 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5508 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5372 | char __user *optval, int __user *optlen) | 5509 | char __user *optval, int __user *optlen) |
5373 | { | 5510 | { |
@@ -5510,6 +5647,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5510 | retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, | 5647 | retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, |
5511 | optlen); | 5648 | optlen); |
5512 | break; | 5649 | break; |
5650 | case SCTP_GET_ASSOC_NUMBER: | ||
5651 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); | ||
5652 | break; | ||
5513 | default: | 5653 | default: |
5514 | retval = -ENOPROTOOPT; | 5654 | retval = -ENOPROTOOPT; |
5515 | break; | 5655 | break; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 52910697e104..f58e994e6852 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -63,8 +63,8 @@ static ctl_table sctp_table[] = { | |||
63 | .data = &sctp_rto_initial, | 63 | .data = &sctp_rto_initial, |
64 | .maxlen = sizeof(unsigned int), | 64 | .maxlen = sizeof(unsigned int), |
65 | .mode = 0644, | 65 | .mode = 0644, |
66 | .proc_handler = &proc_dointvec_minmax, | 66 | .proc_handler = proc_dointvec_minmax, |
67 | .strategy = &sysctl_intvec, | 67 | .strategy = sysctl_intvec, |
68 | .extra1 = &one, | 68 | .extra1 = &one, |
69 | .extra2 = &timer_max | 69 | .extra2 = &timer_max |
70 | }, | 70 | }, |
@@ -74,8 +74,8 @@ static ctl_table sctp_table[] = { | |||
74 | .data = &sctp_rto_min, | 74 | .data = &sctp_rto_min, |
75 | .maxlen = sizeof(unsigned int), | 75 | .maxlen = sizeof(unsigned int), |
76 | .mode = 0644, | 76 | .mode = 0644, |
77 | .proc_handler = &proc_dointvec_minmax, | 77 | .proc_handler = proc_dointvec_minmax, |
78 | .strategy = &sysctl_intvec, | 78 | .strategy = sysctl_intvec, |
79 | .extra1 = &one, | 79 | .extra1 = &one, |
80 | .extra2 = &timer_max | 80 | .extra2 = &timer_max |
81 | }, | 81 | }, |
@@ -85,8 +85,8 @@ static ctl_table sctp_table[] = { | |||
85 | .data = &sctp_rto_max, | 85 | .data = &sctp_rto_max, |
86 | .maxlen = sizeof(unsigned int), | 86 | .maxlen = sizeof(unsigned int), |
87 | .mode = 0644, | 87 | .mode = 0644, |
88 | .proc_handler = &proc_dointvec_minmax, | 88 | .proc_handler = proc_dointvec_minmax, |
89 | .strategy = &sysctl_intvec, | 89 | .strategy = sysctl_intvec, |
90 | .extra1 = &one, | 90 | .extra1 = &one, |
91 | .extra2 = &timer_max | 91 | .extra2 = &timer_max |
92 | }, | 92 | }, |
@@ -96,8 +96,8 @@ static ctl_table sctp_table[] = { | |||
96 | .data = &sctp_valid_cookie_life, | 96 | .data = &sctp_valid_cookie_life, |
97 | .maxlen = sizeof(unsigned int), | 97 | .maxlen = sizeof(unsigned int), |
98 | .mode = 0644, | 98 | .mode = 0644, |
99 | .proc_handler = &proc_dointvec_minmax, | 99 | .proc_handler = proc_dointvec_minmax, |
100 | .strategy = &sysctl_intvec, | 100 | .strategy = sysctl_intvec, |
101 | .extra1 = &one, | 101 | .extra1 = &one, |
102 | .extra2 = &timer_max | 102 | .extra2 = &timer_max |
103 | }, | 103 | }, |
@@ -107,8 +107,8 @@ static ctl_table sctp_table[] = { | |||
107 | .data = &sctp_max_burst, | 107 | .data = &sctp_max_burst, |
108 | .maxlen = sizeof(int), | 108 | .maxlen = sizeof(int), |
109 | .mode = 0644, | 109 | .mode = 0644, |
110 | .proc_handler = &proc_dointvec_minmax, | 110 | .proc_handler = proc_dointvec_minmax, |
111 | .strategy = &sysctl_intvec, | 111 | .strategy = sysctl_intvec, |
112 | .extra1 = &zero, | 112 | .extra1 = &zero, |
113 | .extra2 = &int_max | 113 | .extra2 = &int_max |
114 | }, | 114 | }, |
@@ -118,8 +118,8 @@ static ctl_table sctp_table[] = { | |||
118 | .data = &sctp_max_retrans_association, | 118 | .data = &sctp_max_retrans_association, |
119 | .maxlen = sizeof(int), | 119 | .maxlen = sizeof(int), |
120 | .mode = 0644, | 120 | .mode = 0644, |
121 | .proc_handler = &proc_dointvec_minmax, | 121 | .proc_handler = proc_dointvec_minmax, |
122 | .strategy = &sysctl_intvec, | 122 | .strategy = sysctl_intvec, |
123 | .extra1 = &one, | 123 | .extra1 = &one, |
124 | .extra2 = &int_max | 124 | .extra2 = &int_max |
125 | }, | 125 | }, |
@@ -129,8 +129,8 @@ static ctl_table sctp_table[] = { | |||
129 | .data = &sctp_sndbuf_policy, | 129 | .data = &sctp_sndbuf_policy, |
130 | .maxlen = sizeof(int), | 130 | .maxlen = sizeof(int), |
131 | .mode = 0644, | 131 | .mode = 0644, |
132 | .proc_handler = &proc_dointvec, | 132 | .proc_handler = proc_dointvec, |
133 | .strategy = &sysctl_intvec | 133 | .strategy = sysctl_intvec |
134 | }, | 134 | }, |
135 | { | 135 | { |
136 | .ctl_name = NET_SCTP_RCVBUF_POLICY, | 136 | .ctl_name = NET_SCTP_RCVBUF_POLICY, |
@@ -138,8 +138,8 @@ static ctl_table sctp_table[] = { | |||
138 | .data = &sctp_rcvbuf_policy, | 138 | .data = &sctp_rcvbuf_policy, |
139 | .maxlen = sizeof(int), | 139 | .maxlen = sizeof(int), |
140 | .mode = 0644, | 140 | .mode = 0644, |
141 | .proc_handler = &proc_dointvec, | 141 | .proc_handler = proc_dointvec, |
142 | .strategy = &sysctl_intvec | 142 | .strategy = sysctl_intvec |
143 | }, | 143 | }, |
144 | { | 144 | { |
145 | .ctl_name = NET_SCTP_PATH_MAX_RETRANS, | 145 | .ctl_name = NET_SCTP_PATH_MAX_RETRANS, |
@@ -147,8 +147,8 @@ static ctl_table sctp_table[] = { | |||
147 | .data = &sctp_max_retrans_path, | 147 | .data = &sctp_max_retrans_path, |
148 | .maxlen = sizeof(int), | 148 | .maxlen = sizeof(int), |
149 | .mode = 0644, | 149 | .mode = 0644, |
150 | .proc_handler = &proc_dointvec_minmax, | 150 | .proc_handler = proc_dointvec_minmax, |
151 | .strategy = &sysctl_intvec, | 151 | .strategy = sysctl_intvec, |
152 | .extra1 = &one, | 152 | .extra1 = &one, |
153 | .extra2 = &int_max | 153 | .extra2 = &int_max |
154 | }, | 154 | }, |
@@ -158,8 +158,8 @@ static ctl_table sctp_table[] = { | |||
158 | .data = &sctp_max_retrans_init, | 158 | .data = &sctp_max_retrans_init, |
159 | .maxlen = sizeof(int), | 159 | .maxlen = sizeof(int), |
160 | .mode = 0644, | 160 | .mode = 0644, |
161 | .proc_handler = &proc_dointvec_minmax, | 161 | .proc_handler = proc_dointvec_minmax, |
162 | .strategy = &sysctl_intvec, | 162 | .strategy = sysctl_intvec, |
163 | .extra1 = &one, | 163 | .extra1 = &one, |
164 | .extra2 = &int_max | 164 | .extra2 = &int_max |
165 | }, | 165 | }, |
@@ -169,8 +169,8 @@ static ctl_table sctp_table[] = { | |||
169 | .data = &sctp_hb_interval, | 169 | .data = &sctp_hb_interval, |
170 | .maxlen = sizeof(unsigned int), | 170 | .maxlen = sizeof(unsigned int), |
171 | .mode = 0644, | 171 | .mode = 0644, |
172 | .proc_handler = &proc_dointvec_minmax, | 172 | .proc_handler = proc_dointvec_minmax, |
173 | .strategy = &sysctl_intvec, | 173 | .strategy = sysctl_intvec, |
174 | .extra1 = &one, | 174 | .extra1 = &one, |
175 | .extra2 = &timer_max | 175 | .extra2 = &timer_max |
176 | }, | 176 | }, |
@@ -180,8 +180,8 @@ static ctl_table sctp_table[] = { | |||
180 | .data = &sctp_cookie_preserve_enable, | 180 | .data = &sctp_cookie_preserve_enable, |
181 | .maxlen = sizeof(int), | 181 | .maxlen = sizeof(int), |
182 | .mode = 0644, | 182 | .mode = 0644, |
183 | .proc_handler = &proc_dointvec, | 183 | .proc_handler = proc_dointvec, |
184 | .strategy = &sysctl_intvec | 184 | .strategy = sysctl_intvec |
185 | }, | 185 | }, |
186 | { | 186 | { |
187 | .ctl_name = NET_SCTP_RTO_ALPHA, | 187 | .ctl_name = NET_SCTP_RTO_ALPHA, |
@@ -189,8 +189,8 @@ static ctl_table sctp_table[] = { | |||
189 | .data = &sctp_rto_alpha, | 189 | .data = &sctp_rto_alpha, |
190 | .maxlen = sizeof(int), | 190 | .maxlen = sizeof(int), |
191 | .mode = 0444, | 191 | .mode = 0444, |
192 | .proc_handler = &proc_dointvec, | 192 | .proc_handler = proc_dointvec, |
193 | .strategy = &sysctl_intvec | 193 | .strategy = sysctl_intvec |
194 | }, | 194 | }, |
195 | { | 195 | { |
196 | .ctl_name = NET_SCTP_RTO_BETA, | 196 | .ctl_name = NET_SCTP_RTO_BETA, |
@@ -198,8 +198,8 @@ static ctl_table sctp_table[] = { | |||
198 | .data = &sctp_rto_beta, | 198 | .data = &sctp_rto_beta, |
199 | .maxlen = sizeof(int), | 199 | .maxlen = sizeof(int), |
200 | .mode = 0444, | 200 | .mode = 0444, |
201 | .proc_handler = &proc_dointvec, | 201 | .proc_handler = proc_dointvec, |
202 | .strategy = &sysctl_intvec | 202 | .strategy = sysctl_intvec |
203 | }, | 203 | }, |
204 | { | 204 | { |
205 | .ctl_name = NET_SCTP_ADDIP_ENABLE, | 205 | .ctl_name = NET_SCTP_ADDIP_ENABLE, |
@@ -207,8 +207,8 @@ static ctl_table sctp_table[] = { | |||
207 | .data = &sctp_addip_enable, | 207 | .data = &sctp_addip_enable, |
208 | .maxlen = sizeof(int), | 208 | .maxlen = sizeof(int), |
209 | .mode = 0644, | 209 | .mode = 0644, |
210 | .proc_handler = &proc_dointvec, | 210 | .proc_handler = proc_dointvec, |
211 | .strategy = &sysctl_intvec | 211 | .strategy = sysctl_intvec |
212 | }, | 212 | }, |
213 | { | 213 | { |
214 | .ctl_name = NET_SCTP_PRSCTP_ENABLE, | 214 | .ctl_name = NET_SCTP_PRSCTP_ENABLE, |
@@ -216,8 +216,8 @@ static ctl_table sctp_table[] = { | |||
216 | .data = &sctp_prsctp_enable, | 216 | .data = &sctp_prsctp_enable, |
217 | .maxlen = sizeof(int), | 217 | .maxlen = sizeof(int), |
218 | .mode = 0644, | 218 | .mode = 0644, |
219 | .proc_handler = &proc_dointvec, | 219 | .proc_handler = proc_dointvec, |
220 | .strategy = &sysctl_intvec | 220 | .strategy = sysctl_intvec |
221 | }, | 221 | }, |
222 | { | 222 | { |
223 | .ctl_name = NET_SCTP_SACK_TIMEOUT, | 223 | .ctl_name = NET_SCTP_SACK_TIMEOUT, |
@@ -225,8 +225,8 @@ static ctl_table sctp_table[] = { | |||
225 | .data = &sctp_sack_timeout, | 225 | .data = &sctp_sack_timeout, |
226 | .maxlen = sizeof(long), | 226 | .maxlen = sizeof(long), |
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, |
230 | .extra1 = &sack_timer_min, | 230 | .extra1 = &sack_timer_min, |
231 | .extra2 = &sack_timer_max, | 231 | .extra2 = &sack_timer_max, |
232 | }, | 232 | }, |
@@ -236,7 +236,7 @@ static ctl_table sctp_table[] = { | |||
236 | .data = &sysctl_sctp_mem, | 236 | .data = &sysctl_sctp_mem, |
237 | .maxlen = sizeof(sysctl_sctp_mem), | 237 | .maxlen = sizeof(sysctl_sctp_mem), |
238 | .mode = 0644, | 238 | .mode = 0644, |
239 | .proc_handler = &proc_dointvec, | 239 | .proc_handler = proc_dointvec, |
240 | }, | 240 | }, |
241 | { | 241 | { |
242 | .ctl_name = CTL_UNNUMBERED, | 242 | .ctl_name = CTL_UNNUMBERED, |
@@ -244,7 +244,7 @@ static ctl_table sctp_table[] = { | |||
244 | .data = &sysctl_sctp_rmem, | 244 | .data = &sysctl_sctp_rmem, |
245 | .maxlen = sizeof(sysctl_sctp_rmem), | 245 | .maxlen = sizeof(sysctl_sctp_rmem), |
246 | .mode = 0644, | 246 | .mode = 0644, |
247 | .proc_handler = &proc_dointvec, | 247 | .proc_handler = proc_dointvec, |
248 | }, | 248 | }, |
249 | { | 249 | { |
250 | .ctl_name = CTL_UNNUMBERED, | 250 | .ctl_name = CTL_UNNUMBERED, |
@@ -252,7 +252,7 @@ static ctl_table sctp_table[] = { | |||
252 | .data = &sysctl_sctp_wmem, | 252 | .data = &sysctl_sctp_wmem, |
253 | .maxlen = sizeof(sysctl_sctp_wmem), | 253 | .maxlen = sizeof(sysctl_sctp_wmem), |
254 | .mode = 0644, | 254 | .mode = 0644, |
255 | .proc_handler = &proc_dointvec, | 255 | .proc_handler = proc_dointvec, |
256 | }, | 256 | }, |
257 | { | 257 | { |
258 | .ctl_name = CTL_UNNUMBERED, | 258 | .ctl_name = CTL_UNNUMBERED, |
@@ -260,8 +260,8 @@ static ctl_table sctp_table[] = { | |||
260 | .data = &sctp_auth_enable, | 260 | .data = &sctp_auth_enable, |
261 | .maxlen = sizeof(int), | 261 | .maxlen = sizeof(int), |
262 | .mode = 0644, | 262 | .mode = 0644, |
263 | .proc_handler = &proc_dointvec, | 263 | .proc_handler = proc_dointvec, |
264 | .strategy = &sysctl_intvec | 264 | .strategy = sysctl_intvec |
265 | }, | 265 | }, |
266 | { | 266 | { |
267 | .ctl_name = CTL_UNNUMBERED, | 267 | .ctl_name = CTL_UNNUMBERED, |
@@ -269,8 +269,8 @@ static ctl_table sctp_table[] = { | |||
269 | .data = &sctp_addip_noauth, | 269 | .data = &sctp_addip_noauth, |
270 | .maxlen = sizeof(int), | 270 | .maxlen = sizeof(int), |
271 | .mode = 0644, | 271 | .mode = 0644, |
272 | .proc_handler = &proc_dointvec, | 272 | .proc_handler = proc_dointvec, |
273 | .strategy = &sysctl_intvec | 273 | .strategy = sysctl_intvec |
274 | }, | 274 | }, |
275 | { .ctl_name = 0 } | 275 | { .ctl_name = 0 } |
276 | }; | 276 | }; |