.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* SCTP kernel implementation |
---|
2 | 3 | * (C) Copyright IBM Corp. 2001, 2004 |
---|
3 | 4 | * Copyright (c) 1999-2000 Cisco, Inc. |
---|
.. | .. |
---|
14 | 15 | * Note that the descriptions from the specification are USER level |
---|
15 | 16 | * functions--this file is the functions which populate the struct proto |
---|
16 | 17 | * for SCTP which is the BOTTOM of the sockets interface. |
---|
17 | | - * |
---|
18 | | - * This SCTP implementation is free software; |
---|
19 | | - * you can redistribute it and/or modify it under the terms of |
---|
20 | | - * the GNU General Public License as published by |
---|
21 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
22 | | - * any later version. |
---|
23 | | - * |
---|
24 | | - * This SCTP implementation is distributed in the hope that it |
---|
25 | | - * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
---|
26 | | - * ************************ |
---|
27 | | - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
28 | | - * See the GNU General Public License for more details. |
---|
29 | | - * |
---|
30 | | - * You should have received a copy of the GNU General Public License |
---|
31 | | - * along with GNU CC; see the file COPYING. If not, see |
---|
32 | | - * <http://www.gnu.org/licenses/>. |
---|
33 | 18 | * |
---|
34 | 19 | * Please send any bug reports or fixes you make to the |
---|
35 | 20 | * email address(es): |
---|
.. | .. |
---|
83 | 68 | #include <net/sctp/stream_sched.h> |
---|
84 | 69 | |
---|
85 | 70 | /* Forward declarations for internal helper functions. */ |
---|
86 | | -static bool sctp_writeable(struct sock *sk); |
---|
| 71 | +static bool sctp_writeable(const struct sock *sk); |
---|
87 | 72 | static void sctp_wfree(struct sk_buff *skb); |
---|
88 | 73 | static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, |
---|
89 | 74 | size_t msg_len); |
---|
.. | .. |
---|
102 | 87 | struct sctp_chunk *chunk); |
---|
103 | 88 | static int sctp_do_bind(struct sock *, union sctp_addr *, int); |
---|
104 | 89 | static int sctp_autobind(struct sock *sk); |
---|
105 | | -static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, |
---|
106 | | - struct sctp_association *assoc, |
---|
107 | | - enum sctp_socket_type type); |
---|
| 90 | +static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, |
---|
| 91 | + struct sctp_association *assoc, |
---|
| 92 | + enum sctp_socket_type type); |
---|
108 | 93 | |
---|
109 | 94 | static unsigned long sctp_memory_pressure; |
---|
110 | 95 | static atomic_long_t sctp_memory_allocated; |
---|
.. | .. |
---|
112 | 97 | |
---|
113 | 98 | static void sctp_enter_memory_pressure(struct sock *sk) |
---|
114 | 99 | { |
---|
115 | | - sctp_memory_pressure = 1; |
---|
| 100 | + WRITE_ONCE(sctp_memory_pressure, 1); |
---|
116 | 101 | } |
---|
117 | 102 | |
---|
118 | 103 | |
---|
.. | .. |
---|
151 | 136 | /* Save the chunk pointer in skb for sctp_wfree to use later. */ |
---|
152 | 137 | skb_shinfo(chunk->skb)->destructor_arg = chunk; |
---|
153 | 138 | |
---|
154 | | - asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) + |
---|
155 | | - sizeof(struct sk_buff) + |
---|
156 | | - sizeof(struct sctp_chunk); |
---|
157 | | - |
---|
158 | 139 | refcount_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); |
---|
159 | | - sk->sk_wmem_queued += chunk->skb->truesize; |
---|
| 140 | + asoc->sndbuf_used += chunk->skb->truesize + sizeof(struct sctp_chunk); |
---|
| 141 | + sk_wmem_queued_add(sk, chunk->skb->truesize + sizeof(struct sctp_chunk)); |
---|
160 | 142 | sk_mem_charge(sk, chunk->skb->truesize); |
---|
161 | 143 | } |
---|
162 | 144 | |
---|
.. | .. |
---|
266 | 248 | } |
---|
267 | 249 | |
---|
268 | 250 | /* Otherwise this is a UDP-style socket. */ |
---|
269 | | - if (!id || (id == (sctp_assoc_t)-1)) |
---|
| 251 | + if (id <= SCTP_ALL_ASSOC) |
---|
270 | 252 | return NULL; |
---|
271 | 253 | |
---|
272 | 254 | spin_lock_bh(&sctp_assocs_id_lock); |
---|
.. | .. |
---|
342 | 324 | return retval; |
---|
343 | 325 | } |
---|
344 | 326 | |
---|
345 | | -static long sctp_get_port_local(struct sock *, union sctp_addr *); |
---|
| 327 | +static int sctp_get_port_local(struct sock *, union sctp_addr *); |
---|
346 | 328 | |
---|
347 | 329 | /* Verify this is a valid sockaddr. */ |
---|
348 | 330 | static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, |
---|
.. | .. |
---|
380 | 362 | struct net *net = sock_net(&sp->inet.sk); |
---|
381 | 363 | |
---|
382 | 364 | if (net->sctp.default_auto_asconf) { |
---|
383 | | - spin_lock(&net->sctp.addr_wq_lock); |
---|
| 365 | + spin_lock_bh(&net->sctp.addr_wq_lock); |
---|
384 | 366 | list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist); |
---|
385 | | - spin_unlock(&net->sctp.addr_wq_lock); |
---|
| 367 | + spin_unlock_bh(&net->sctp.addr_wq_lock); |
---|
386 | 368 | sp->do_auto_asconf = 1; |
---|
387 | 369 | } |
---|
388 | 370 | } |
---|
.. | .. |
---|
429 | 411 | } |
---|
430 | 412 | } |
---|
431 | 413 | |
---|
432 | | - if (snum && snum < inet_prot_sock(net) && |
---|
| 414 | + if (snum && inet_is_local_unbindable_port(net, snum)) |
---|
| 415 | + return -EPERM; |
---|
| 416 | + |
---|
| 417 | + if (snum && inet_port_requires_bind_service(net, snum) && |
---|
433 | 418 | !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) |
---|
434 | 419 | return -EACCES; |
---|
435 | 420 | |
---|
.. | .. |
---|
444 | 429 | * detection. |
---|
445 | 430 | */ |
---|
446 | 431 | addr->v4.sin_port = htons(snum); |
---|
447 | | - if ((ret = sctp_get_port_local(sk, addr))) { |
---|
| 432 | + if (sctp_get_port_local(sk, addr)) |
---|
448 | 433 | return -EADDRINUSE; |
---|
449 | | - } |
---|
450 | 434 | |
---|
451 | 435 | /* Refresh ephemeral port. */ |
---|
452 | 436 | if (!bp->port) { |
---|
.. | .. |
---|
460 | 444 | ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len, |
---|
461 | 445 | SCTP_ADDR_SRC, GFP_ATOMIC); |
---|
462 | 446 | |
---|
463 | | - /* Copy back into socket for getsockname() use. */ |
---|
464 | | - if (!ret) { |
---|
465 | | - inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); |
---|
466 | | - sp->pf->to_sk_saddr(addr, sk); |
---|
| 447 | + if (ret) { |
---|
| 448 | + sctp_put_port(sk); |
---|
| 449 | + return ret; |
---|
467 | 450 | } |
---|
| 451 | + /* Copy back into socket for getsockname() use. */ |
---|
| 452 | + inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); |
---|
| 453 | + sp->pf->to_sk_saddr(addr, sk); |
---|
468 | 454 | |
---|
469 | 455 | return ret; |
---|
470 | 456 | } |
---|
.. | .. |
---|
482 | 468 | static int sctp_send_asconf(struct sctp_association *asoc, |
---|
483 | 469 | struct sctp_chunk *chunk) |
---|
484 | 470 | { |
---|
485 | | - struct net *net = sock_net(asoc->base.sk); |
---|
486 | | - int retval = 0; |
---|
| 471 | + int retval = 0; |
---|
487 | 472 | |
---|
488 | 473 | /* If there is an outstanding ASCONF chunk, queue it for later |
---|
489 | 474 | * transmission. |
---|
.. | .. |
---|
495 | 480 | |
---|
496 | 481 | /* Hold the chunk until an ASCONF_ACK is received. */ |
---|
497 | 482 | sctp_chunk_hold(chunk); |
---|
498 | | - retval = sctp_primitive_ASCONF(net, asoc, chunk); |
---|
| 483 | + retval = sctp_primitive_ASCONF(asoc->base.net, asoc, chunk); |
---|
499 | 484 | if (retval) |
---|
500 | 485 | sctp_chunk_free(chunk); |
---|
501 | 486 | else |
---|
.. | .. |
---|
571 | 556 | struct sockaddr *addrs, |
---|
572 | 557 | int addrcnt) |
---|
573 | 558 | { |
---|
574 | | - struct net *net = sock_net(sk); |
---|
575 | 559 | struct sctp_sock *sp; |
---|
576 | 560 | struct sctp_endpoint *ep; |
---|
577 | 561 | struct sctp_association *asoc; |
---|
.. | .. |
---|
586 | 570 | int i; |
---|
587 | 571 | int retval = 0; |
---|
588 | 572 | |
---|
589 | | - if (!net->sctp.addip_enable) |
---|
590 | | - return retval; |
---|
591 | | - |
---|
592 | 573 | sp = sctp_sk(sk); |
---|
593 | 574 | ep = sp->ep; |
---|
| 575 | + |
---|
| 576 | + if (!ep->asconf_enable) |
---|
| 577 | + return retval; |
---|
594 | 578 | |
---|
595 | 579 | pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", |
---|
596 | 580 | __func__, sk, addrs, addrcnt); |
---|
.. | .. |
---|
774 | 758 | struct sockaddr *addrs, |
---|
775 | 759 | int addrcnt) |
---|
776 | 760 | { |
---|
777 | | - struct net *net = sock_net(sk); |
---|
778 | 761 | struct sctp_sock *sp; |
---|
779 | 762 | struct sctp_endpoint *ep; |
---|
780 | 763 | struct sctp_association *asoc; |
---|
.. | .. |
---|
790 | 773 | int stored = 0; |
---|
791 | 774 | |
---|
792 | 775 | chunk = NULL; |
---|
793 | | - if (!net->sctp.addip_enable) |
---|
794 | | - return retval; |
---|
795 | | - |
---|
796 | 776 | sp = sctp_sk(sk); |
---|
797 | 777 | ep = sp->ep; |
---|
| 778 | + |
---|
| 779 | + if (!ep->asconf_enable) |
---|
| 780 | + return retval; |
---|
798 | 781 | |
---|
799 | 782 | pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", |
---|
800 | 783 | __func__, sk, addrs, addrcnt); |
---|
.. | .. |
---|
1006 | 989 | * it. |
---|
1007 | 990 | * |
---|
1008 | 991 | * sk The sk of the socket |
---|
1009 | | - * addrs The pointer to the addresses in user land |
---|
| 992 | + * addrs The pointer to the addresses |
---|
1010 | 993 | * addrssize Size of the addrs buffer |
---|
1011 | 994 | * op Operation to perform (add or remove, see the flags of |
---|
1012 | 995 | * sctp_bindx) |
---|
1013 | 996 | * |
---|
1014 | 997 | * Returns 0 if ok, <0 errno code on error. |
---|
1015 | 998 | */ |
---|
1016 | | -static int sctp_setsockopt_bindx(struct sock *sk, |
---|
1017 | | - struct sockaddr __user *addrs, |
---|
| 999 | +static int sctp_setsockopt_bindx(struct sock *sk, struct sockaddr *addrs, |
---|
1018 | 1000 | int addrs_size, int op) |
---|
1019 | 1001 | { |
---|
1020 | | - struct sockaddr *kaddrs; |
---|
1021 | 1002 | int err; |
---|
1022 | 1003 | int addrcnt = 0; |
---|
1023 | 1004 | int walk_size = 0; |
---|
1024 | 1005 | struct sockaddr *sa_addr; |
---|
1025 | | - void *addr_buf; |
---|
| 1006 | + void *addr_buf = addrs; |
---|
1026 | 1007 | struct sctp_af *af; |
---|
1027 | 1008 | |
---|
1028 | 1009 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d opt:%d\n", |
---|
1029 | | - __func__, sk, addrs, addrs_size, op); |
---|
| 1010 | + __func__, sk, addr_buf, addrs_size, op); |
---|
1030 | 1011 | |
---|
1031 | 1012 | if (unlikely(addrs_size <= 0)) |
---|
1032 | 1013 | return -EINVAL; |
---|
1033 | 1014 | |
---|
1034 | | - kaddrs = memdup_user(addrs, addrs_size); |
---|
1035 | | - if (unlikely(IS_ERR(kaddrs))) |
---|
1036 | | - return PTR_ERR(kaddrs); |
---|
1037 | | - |
---|
1038 | 1015 | /* Walk through the addrs buffer and count the number of addresses. */ |
---|
1039 | | - addr_buf = kaddrs; |
---|
1040 | 1016 | while (walk_size < addrs_size) { |
---|
1041 | | - if (walk_size + sizeof(sa_family_t) > addrs_size) { |
---|
1042 | | - kfree(kaddrs); |
---|
| 1017 | + if (walk_size + sizeof(sa_family_t) > addrs_size) |
---|
1043 | 1018 | return -EINVAL; |
---|
1044 | | - } |
---|
1045 | 1019 | |
---|
1046 | 1020 | sa_addr = addr_buf; |
---|
1047 | 1021 | af = sctp_get_af_specific(sa_addr->sa_family); |
---|
.. | .. |
---|
1049 | 1023 | /* If the address family is not supported or if this address |
---|
1050 | 1024 | * causes the address buffer to overflow return EINVAL. |
---|
1051 | 1025 | */ |
---|
1052 | | - if (!af || (walk_size + af->sockaddr_len) > addrs_size) { |
---|
1053 | | - kfree(kaddrs); |
---|
| 1026 | + if (!af || (walk_size + af->sockaddr_len) > addrs_size) |
---|
1054 | 1027 | return -EINVAL; |
---|
1055 | | - } |
---|
1056 | 1028 | addrcnt++; |
---|
1057 | 1029 | addr_buf += af->sockaddr_len; |
---|
1058 | 1030 | walk_size += af->sockaddr_len; |
---|
.. | .. |
---|
1063 | 1035 | case SCTP_BINDX_ADD_ADDR: |
---|
1064 | 1036 | /* Allow security module to validate bindx addresses. */ |
---|
1065 | 1037 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD, |
---|
1066 | | - (struct sockaddr *)kaddrs, |
---|
1067 | | - addrs_size); |
---|
| 1038 | + addrs, addrs_size); |
---|
1068 | 1039 | if (err) |
---|
1069 | | - goto out; |
---|
1070 | | - err = sctp_bindx_add(sk, kaddrs, addrcnt); |
---|
| 1040 | + return err; |
---|
| 1041 | + err = sctp_bindx_add(sk, addrs, addrcnt); |
---|
1071 | 1042 | if (err) |
---|
1072 | | - goto out; |
---|
1073 | | - err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt); |
---|
1074 | | - break; |
---|
1075 | | - |
---|
| 1043 | + return err; |
---|
| 1044 | + return sctp_send_asconf_add_ip(sk, addrs, addrcnt); |
---|
1076 | 1045 | case SCTP_BINDX_REM_ADDR: |
---|
1077 | | - err = sctp_bindx_rem(sk, kaddrs, addrcnt); |
---|
| 1046 | + err = sctp_bindx_rem(sk, addrs, addrcnt); |
---|
1078 | 1047 | if (err) |
---|
1079 | | - goto out; |
---|
1080 | | - err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt); |
---|
1081 | | - break; |
---|
| 1048 | + return err; |
---|
| 1049 | + return sctp_send_asconf_del_ip(sk, addrs, addrcnt); |
---|
1082 | 1050 | |
---|
1083 | 1051 | default: |
---|
1084 | | - err = -EINVAL; |
---|
1085 | | - break; |
---|
| 1052 | + return -EINVAL; |
---|
| 1053 | + } |
---|
| 1054 | +} |
---|
| 1055 | + |
---|
| 1056 | +static int sctp_bind_add(struct sock *sk, struct sockaddr *addrs, |
---|
| 1057 | + int addrlen) |
---|
| 1058 | +{ |
---|
| 1059 | + int err; |
---|
| 1060 | + |
---|
| 1061 | + lock_sock(sk); |
---|
| 1062 | + err = sctp_setsockopt_bindx(sk, addrs, addrlen, SCTP_BINDX_ADD_ADDR); |
---|
| 1063 | + release_sock(sk); |
---|
| 1064 | + return err; |
---|
| 1065 | +} |
---|
| 1066 | + |
---|
| 1067 | +static int sctp_connect_new_asoc(struct sctp_endpoint *ep, |
---|
| 1068 | + const union sctp_addr *daddr, |
---|
| 1069 | + const struct sctp_initmsg *init, |
---|
| 1070 | + struct sctp_transport **tp) |
---|
| 1071 | +{ |
---|
| 1072 | + struct sctp_association *asoc; |
---|
| 1073 | + struct sock *sk = ep->base.sk; |
---|
| 1074 | + struct net *net = sock_net(sk); |
---|
| 1075 | + enum sctp_scope scope; |
---|
| 1076 | + int err; |
---|
| 1077 | + |
---|
| 1078 | + if (sctp_endpoint_is_peeled_off(ep, daddr)) |
---|
| 1079 | + return -EADDRNOTAVAIL; |
---|
| 1080 | + |
---|
| 1081 | + if (!ep->base.bind_addr.port) { |
---|
| 1082 | + if (sctp_autobind(sk)) |
---|
| 1083 | + return -EAGAIN; |
---|
| 1084 | + } else { |
---|
| 1085 | + if (inet_is_local_unbindable_port(net, ep->base.bind_addr.port)) |
---|
| 1086 | + return -EPERM; |
---|
| 1087 | + if (inet_port_requires_bind_service(net, ep->base.bind_addr.port) && |
---|
| 1088 | + !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) |
---|
| 1089 | + return -EACCES; |
---|
1086 | 1090 | } |
---|
1087 | 1091 | |
---|
1088 | | -out: |
---|
1089 | | - kfree(kaddrs); |
---|
| 1092 | + scope = sctp_scope(daddr); |
---|
| 1093 | + asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
---|
| 1094 | + if (!asoc) |
---|
| 1095 | + return -ENOMEM; |
---|
1090 | 1096 | |
---|
| 1097 | + err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); |
---|
| 1098 | + if (err < 0) |
---|
| 1099 | + goto free; |
---|
| 1100 | + |
---|
| 1101 | + *tp = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); |
---|
| 1102 | + if (!*tp) { |
---|
| 1103 | + err = -ENOMEM; |
---|
| 1104 | + goto free; |
---|
| 1105 | + } |
---|
| 1106 | + |
---|
| 1107 | + if (!init) |
---|
| 1108 | + return 0; |
---|
| 1109 | + |
---|
| 1110 | + if (init->sinit_num_ostreams) { |
---|
| 1111 | + __u16 outcnt = init->sinit_num_ostreams; |
---|
| 1112 | + |
---|
| 1113 | + asoc->c.sinit_num_ostreams = outcnt; |
---|
| 1114 | + /* outcnt has been changed, need to re-init stream */ |
---|
| 1115 | + err = sctp_stream_init(&asoc->stream, outcnt, 0, GFP_KERNEL); |
---|
| 1116 | + if (err) |
---|
| 1117 | + goto free; |
---|
| 1118 | + } |
---|
| 1119 | + |
---|
| 1120 | + if (init->sinit_max_instreams) |
---|
| 1121 | + asoc->c.sinit_max_instreams = init->sinit_max_instreams; |
---|
| 1122 | + |
---|
| 1123 | + if (init->sinit_max_attempts) |
---|
| 1124 | + asoc->max_init_attempts = init->sinit_max_attempts; |
---|
| 1125 | + |
---|
| 1126 | + if (init->sinit_max_init_timeo) |
---|
| 1127 | + asoc->max_init_timeo = |
---|
| 1128 | + msecs_to_jiffies(init->sinit_max_init_timeo); |
---|
| 1129 | + |
---|
| 1130 | + return 0; |
---|
| 1131 | +free: |
---|
| 1132 | + sctp_association_free(asoc); |
---|
1091 | 1133 | return err; |
---|
| 1134 | +} |
---|
| 1135 | + |
---|
| 1136 | +static int sctp_connect_add_peer(struct sctp_association *asoc, |
---|
| 1137 | + union sctp_addr *daddr, int addr_len) |
---|
| 1138 | +{ |
---|
| 1139 | + struct sctp_endpoint *ep = asoc->ep; |
---|
| 1140 | + struct sctp_association *old; |
---|
| 1141 | + struct sctp_transport *t; |
---|
| 1142 | + int err; |
---|
| 1143 | + |
---|
| 1144 | + err = sctp_verify_addr(ep->base.sk, daddr, addr_len); |
---|
| 1145 | + if (err) |
---|
| 1146 | + return err; |
---|
| 1147 | + |
---|
| 1148 | + old = sctp_endpoint_lookup_assoc(ep, daddr, &t); |
---|
| 1149 | + if (old && old != asoc) |
---|
| 1150 | + return old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN |
---|
| 1151 | + : -EALREADY; |
---|
| 1152 | + |
---|
| 1153 | + if (sctp_endpoint_is_peeled_off(ep, daddr)) |
---|
| 1154 | + return -EADDRNOTAVAIL; |
---|
| 1155 | + |
---|
| 1156 | + t = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); |
---|
| 1157 | + if (!t) |
---|
| 1158 | + return -ENOMEM; |
---|
| 1159 | + |
---|
| 1160 | + return 0; |
---|
1092 | 1161 | } |
---|
1093 | 1162 | |
---|
1094 | 1163 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) |
---|
.. | .. |
---|
1096 | 1165 | * Common routine for handling connect() and sctp_connectx(). |
---|
1097 | 1166 | * Connect will come in with just a single address. |
---|
1098 | 1167 | */ |
---|
1099 | | -static int __sctp_connect(struct sock *sk, |
---|
1100 | | - struct sockaddr *kaddrs, |
---|
1101 | | - int addrs_size, int flags, |
---|
1102 | | - sctp_assoc_t *assoc_id) |
---|
| 1168 | +static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, |
---|
| 1169 | + int addrs_size, int flags, sctp_assoc_t *assoc_id) |
---|
1103 | 1170 | { |
---|
1104 | | - struct net *net = sock_net(sk); |
---|
1105 | | - struct sctp_sock *sp; |
---|
1106 | | - struct sctp_endpoint *ep; |
---|
1107 | | - struct sctp_association *asoc = NULL; |
---|
1108 | | - struct sctp_association *asoc2; |
---|
| 1171 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 1172 | + struct sctp_endpoint *ep = sp->ep; |
---|
1109 | 1173 | struct sctp_transport *transport; |
---|
1110 | | - union sctp_addr to; |
---|
1111 | | - enum sctp_scope scope; |
---|
| 1174 | + struct sctp_association *asoc; |
---|
| 1175 | + void *addr_buf = kaddrs; |
---|
| 1176 | + union sctp_addr *daddr; |
---|
| 1177 | + struct sctp_af *af; |
---|
| 1178 | + int walk_size, err; |
---|
1112 | 1179 | long timeo; |
---|
1113 | | - int err = 0; |
---|
1114 | | - int addrcnt = 0; |
---|
1115 | | - int walk_size = 0; |
---|
1116 | | - union sctp_addr *sa_addr = NULL; |
---|
1117 | | - void *addr_buf; |
---|
1118 | | - unsigned short port; |
---|
1119 | 1180 | |
---|
1120 | | - sp = sctp_sk(sk); |
---|
1121 | | - ep = sp->ep; |
---|
1122 | | - |
---|
1123 | | - /* connect() cannot be done on a socket that is already in ESTABLISHED |
---|
1124 | | - * state - UDP-style peeled off socket or a TCP-style socket that |
---|
1125 | | - * is already connected. |
---|
1126 | | - * It cannot be done even on a TCP-style listening socket. |
---|
1127 | | - */ |
---|
1128 | 1181 | if (sctp_sstate(sk, ESTABLISHED) || sctp_sstate(sk, CLOSING) || |
---|
1129 | | - (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { |
---|
1130 | | - err = -EISCONN; |
---|
1131 | | - goto out_free; |
---|
1132 | | - } |
---|
| 1182 | + (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) |
---|
| 1183 | + return -EISCONN; |
---|
1133 | 1184 | |
---|
1134 | | - /* Walk through the addrs buffer and count the number of addresses. */ |
---|
1135 | | - addr_buf = kaddrs; |
---|
| 1185 | + daddr = addr_buf; |
---|
| 1186 | + af = sctp_get_af_specific(daddr->sa.sa_family); |
---|
| 1187 | + if (!af || af->sockaddr_len > addrs_size) |
---|
| 1188 | + return -EINVAL; |
---|
| 1189 | + |
---|
| 1190 | + err = sctp_verify_addr(sk, daddr, af->sockaddr_len); |
---|
| 1191 | + if (err) |
---|
| 1192 | + return err; |
---|
| 1193 | + |
---|
| 1194 | + asoc = sctp_endpoint_lookup_assoc(ep, daddr, &transport); |
---|
| 1195 | + if (asoc) |
---|
| 1196 | + return asoc->state >= SCTP_STATE_ESTABLISHED ? -EISCONN |
---|
| 1197 | + : -EALREADY; |
---|
| 1198 | + |
---|
| 1199 | + err = sctp_connect_new_asoc(ep, daddr, NULL, &transport); |
---|
| 1200 | + if (err) |
---|
| 1201 | + return err; |
---|
| 1202 | + asoc = transport->asoc; |
---|
| 1203 | + |
---|
| 1204 | + addr_buf += af->sockaddr_len; |
---|
| 1205 | + walk_size = af->sockaddr_len; |
---|
1136 | 1206 | while (walk_size < addrs_size) { |
---|
1137 | | - struct sctp_af *af; |
---|
1138 | | - |
---|
1139 | | - if (walk_size + sizeof(sa_family_t) > addrs_size) { |
---|
1140 | | - err = -EINVAL; |
---|
| 1207 | + err = -EINVAL; |
---|
| 1208 | + if (walk_size + sizeof(sa_family_t) > addrs_size) |
---|
1141 | 1209 | goto out_free; |
---|
1142 | | - } |
---|
1143 | 1210 | |
---|
1144 | | - sa_addr = addr_buf; |
---|
1145 | | - af = sctp_get_af_specific(sa_addr->sa.sa_family); |
---|
1146 | | - |
---|
1147 | | - /* If the address family is not supported or if this address |
---|
1148 | | - * causes the address buffer to overflow return EINVAL. |
---|
1149 | | - */ |
---|
1150 | | - if (!af || (walk_size + af->sockaddr_len) > addrs_size) { |
---|
1151 | | - err = -EINVAL; |
---|
| 1211 | + daddr = addr_buf; |
---|
| 1212 | + af = sctp_get_af_specific(daddr->sa.sa_family); |
---|
| 1213 | + if (!af || af->sockaddr_len + walk_size > addrs_size) |
---|
1152 | 1214 | goto out_free; |
---|
1153 | | - } |
---|
1154 | 1215 | |
---|
1155 | | - port = ntohs(sa_addr->v4.sin_port); |
---|
| 1216 | + if (asoc->peer.port != ntohs(daddr->v4.sin_port)) |
---|
| 1217 | + goto out_free; |
---|
1156 | 1218 | |
---|
1157 | | - /* Save current address so we can work with it */ |
---|
1158 | | - memcpy(&to, sa_addr, af->sockaddr_len); |
---|
1159 | | - |
---|
1160 | | - err = sctp_verify_addr(sk, &to, af->sockaddr_len); |
---|
| 1219 | + err = sctp_connect_add_peer(asoc, daddr, af->sockaddr_len); |
---|
1161 | 1220 | if (err) |
---|
1162 | 1221 | goto out_free; |
---|
1163 | 1222 | |
---|
1164 | | - /* Make sure the destination port is correctly set |
---|
1165 | | - * in all addresses. |
---|
1166 | | - */ |
---|
1167 | | - if (asoc && asoc->peer.port && asoc->peer.port != port) { |
---|
1168 | | - err = -EINVAL; |
---|
1169 | | - goto out_free; |
---|
1170 | | - } |
---|
1171 | | - |
---|
1172 | | - /* Check if there already is a matching association on the |
---|
1173 | | - * endpoint (other than the one created here). |
---|
1174 | | - */ |
---|
1175 | | - asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); |
---|
1176 | | - if (asoc2 && asoc2 != asoc) { |
---|
1177 | | - if (asoc2->state >= SCTP_STATE_ESTABLISHED) |
---|
1178 | | - err = -EISCONN; |
---|
1179 | | - else |
---|
1180 | | - err = -EALREADY; |
---|
1181 | | - goto out_free; |
---|
1182 | | - } |
---|
1183 | | - |
---|
1184 | | - /* If we could not find a matching association on the endpoint, |
---|
1185 | | - * make sure that there is no peeled-off association matching |
---|
1186 | | - * the peer address even on another socket. |
---|
1187 | | - */ |
---|
1188 | | - if (sctp_endpoint_is_peeled_off(ep, &to)) { |
---|
1189 | | - err = -EADDRNOTAVAIL; |
---|
1190 | | - goto out_free; |
---|
1191 | | - } |
---|
1192 | | - |
---|
1193 | | - if (!asoc) { |
---|
1194 | | - /* If a bind() or sctp_bindx() is not called prior to |
---|
1195 | | - * an sctp_connectx() call, the system picks an |
---|
1196 | | - * ephemeral port and will choose an address set |
---|
1197 | | - * equivalent to binding with a wildcard address. |
---|
1198 | | - */ |
---|
1199 | | - if (!ep->base.bind_addr.port) { |
---|
1200 | | - if (sctp_autobind(sk)) { |
---|
1201 | | - err = -EAGAIN; |
---|
1202 | | - goto out_free; |
---|
1203 | | - } |
---|
1204 | | - } else { |
---|
1205 | | - /* |
---|
1206 | | - * If an unprivileged user inherits a 1-many |
---|
1207 | | - * style socket with open associations on a |
---|
1208 | | - * privileged port, it MAY be permitted to |
---|
1209 | | - * accept new associations, but it SHOULD NOT |
---|
1210 | | - * be permitted to open new associations. |
---|
1211 | | - */ |
---|
1212 | | - if (ep->base.bind_addr.port < |
---|
1213 | | - inet_prot_sock(net) && |
---|
1214 | | - !ns_capable(net->user_ns, |
---|
1215 | | - CAP_NET_BIND_SERVICE)) { |
---|
1216 | | - err = -EACCES; |
---|
1217 | | - goto out_free; |
---|
1218 | | - } |
---|
1219 | | - } |
---|
1220 | | - |
---|
1221 | | - scope = sctp_scope(&to); |
---|
1222 | | - asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
---|
1223 | | - if (!asoc) { |
---|
1224 | | - err = -ENOMEM; |
---|
1225 | | - goto out_free; |
---|
1226 | | - } |
---|
1227 | | - |
---|
1228 | | - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, |
---|
1229 | | - GFP_KERNEL); |
---|
1230 | | - if (err < 0) { |
---|
1231 | | - goto out_free; |
---|
1232 | | - } |
---|
1233 | | - |
---|
1234 | | - } |
---|
1235 | | - |
---|
1236 | | - /* Prime the peer's transport structures. */ |
---|
1237 | | - transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, |
---|
1238 | | - SCTP_UNKNOWN); |
---|
1239 | | - if (!transport) { |
---|
1240 | | - err = -ENOMEM; |
---|
1241 | | - goto out_free; |
---|
1242 | | - } |
---|
1243 | | - |
---|
1244 | | - addrcnt++; |
---|
1245 | | - addr_buf += af->sockaddr_len; |
---|
| 1223 | + addr_buf += af->sockaddr_len; |
---|
1246 | 1224 | walk_size += af->sockaddr_len; |
---|
1247 | 1225 | } |
---|
1248 | 1226 | |
---|
.. | .. |
---|
1255 | 1233 | goto out_free; |
---|
1256 | 1234 | } |
---|
1257 | 1235 | |
---|
1258 | | - err = sctp_primitive_ASSOCIATE(net, asoc, NULL); |
---|
1259 | | - if (err < 0) { |
---|
| 1236 | + err = sctp_primitive_ASSOCIATE(sock_net(sk), asoc, NULL); |
---|
| 1237 | + if (err < 0) |
---|
1260 | 1238 | goto out_free; |
---|
1261 | | - } |
---|
1262 | 1239 | |
---|
1263 | 1240 | /* Initialize sk's dport and daddr for getpeername() */ |
---|
1264 | 1241 | inet_sk(sk)->inet_dport = htons(asoc->peer.port); |
---|
1265 | | - sp->pf->to_sk_daddr(sa_addr, sk); |
---|
| 1242 | + sp->pf->to_sk_daddr(daddr, sk); |
---|
1266 | 1243 | sk->sk_err = 0; |
---|
1267 | | - |
---|
1268 | | - timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); |
---|
1269 | 1244 | |
---|
1270 | 1245 | if (assoc_id) |
---|
1271 | 1246 | *assoc_id = asoc->assoc_id; |
---|
1272 | 1247 | |
---|
1273 | | - err = sctp_wait_for_connect(asoc, &timeo); |
---|
1274 | | - /* Note: the asoc may be freed after the return of |
---|
1275 | | - * sctp_wait_for_connect. |
---|
1276 | | - */ |
---|
1277 | | - |
---|
1278 | | - /* Don't free association on exit. */ |
---|
1279 | | - asoc = NULL; |
---|
| 1248 | + timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); |
---|
| 1249 | + return sctp_wait_for_connect(asoc, &timeo); |
---|
1280 | 1250 | |
---|
1281 | 1251 | out_free: |
---|
1282 | 1252 | pr_debug("%s: took out_free path with asoc:%p kaddrs:%p err:%d\n", |
---|
1283 | 1253 | __func__, asoc, kaddrs, err); |
---|
1284 | | - |
---|
1285 | | - if (asoc) { |
---|
1286 | | - /* sctp_primitive_ASSOCIATE may have added this association |
---|
1287 | | - * To the hash table, try to unhash it, just in case, its a noop |
---|
1288 | | - * if it wasn't hashed so we're safe |
---|
1289 | | - */ |
---|
1290 | | - sctp_association_free(asoc); |
---|
1291 | | - } |
---|
| 1254 | + sctp_association_free(asoc); |
---|
1292 | 1255 | return err; |
---|
1293 | 1256 | } |
---|
1294 | 1257 | |
---|
.. | .. |
---|
1342 | 1305 | * it. |
---|
1343 | 1306 | * |
---|
1344 | 1307 | * sk The sk of the socket |
---|
1345 | | - * addrs The pointer to the addresses in user land |
---|
| 1308 | + * addrs The pointer to the addresses |
---|
1346 | 1309 | * addrssize Size of the addrs buffer |
---|
1347 | 1310 | * |
---|
1348 | 1311 | * Returns >=0 if ok, <0 errno code on error. |
---|
1349 | 1312 | */ |
---|
1350 | | -static int __sctp_setsockopt_connectx(struct sock *sk, |
---|
1351 | | - struct sockaddr __user *addrs, |
---|
1352 | | - int addrs_size, |
---|
1353 | | - sctp_assoc_t *assoc_id) |
---|
| 1313 | +static int __sctp_setsockopt_connectx(struct sock *sk, struct sockaddr *kaddrs, |
---|
| 1314 | + int addrs_size, sctp_assoc_t *assoc_id) |
---|
1354 | 1315 | { |
---|
1355 | | - struct sockaddr *kaddrs; |
---|
1356 | 1316 | int err = 0, flags = 0; |
---|
1357 | 1317 | |
---|
1358 | 1318 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", |
---|
1359 | | - __func__, sk, addrs, addrs_size); |
---|
| 1319 | + __func__, sk, kaddrs, addrs_size); |
---|
1360 | 1320 | |
---|
1361 | | - if (unlikely(addrs_size <= 0)) |
---|
| 1321 | + /* make sure the 1st addr's sa_family is accessible later */ |
---|
| 1322 | + if (unlikely(addrs_size < sizeof(sa_family_t))) |
---|
1362 | 1323 | return -EINVAL; |
---|
1363 | | - |
---|
1364 | | - kaddrs = memdup_user(addrs, addrs_size); |
---|
1365 | | - if (unlikely(IS_ERR(kaddrs))) |
---|
1366 | | - return PTR_ERR(kaddrs); |
---|
1367 | 1324 | |
---|
1368 | 1325 | /* Allow security module to validate connectx addresses. */ |
---|
1369 | 1326 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX, |
---|
1370 | 1327 | (struct sockaddr *)kaddrs, |
---|
1371 | 1328 | addrs_size); |
---|
1372 | 1329 | if (err) |
---|
1373 | | - goto out_free; |
---|
| 1330 | + return err; |
---|
1374 | 1331 | |
---|
1375 | 1332 | /* in-kernel sockets don't generally have a file allocated to them |
---|
1376 | 1333 | * if all they do is call sock_create_kern(). |
---|
.. | .. |
---|
1378 | 1335 | if (sk->sk_socket->file) |
---|
1379 | 1336 | flags = sk->sk_socket->file->f_flags; |
---|
1380 | 1337 | |
---|
1381 | | - err = __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id); |
---|
1382 | | - |
---|
1383 | | -out_free: |
---|
1384 | | - kfree(kaddrs); |
---|
1385 | | - |
---|
1386 | | - return err; |
---|
| 1338 | + return __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id); |
---|
1387 | 1339 | } |
---|
1388 | 1340 | |
---|
1389 | 1341 | /* |
---|
.. | .. |
---|
1391 | 1343 | * to the option that doesn't provide association id. |
---|
1392 | 1344 | */ |
---|
1393 | 1345 | static int sctp_setsockopt_connectx_old(struct sock *sk, |
---|
1394 | | - struct sockaddr __user *addrs, |
---|
| 1346 | + struct sockaddr *kaddrs, |
---|
1395 | 1347 | int addrs_size) |
---|
1396 | 1348 | { |
---|
1397 | | - return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL); |
---|
| 1349 | + return __sctp_setsockopt_connectx(sk, kaddrs, addrs_size, NULL); |
---|
1398 | 1350 | } |
---|
1399 | 1351 | |
---|
1400 | 1352 | /* |
---|
.. | .. |
---|
1404 | 1356 | * always positive. |
---|
1405 | 1357 | */ |
---|
1406 | 1358 | static int sctp_setsockopt_connectx(struct sock *sk, |
---|
1407 | | - struct sockaddr __user *addrs, |
---|
| 1359 | + struct sockaddr *kaddrs, |
---|
1408 | 1360 | int addrs_size) |
---|
1409 | 1361 | { |
---|
1410 | 1362 | sctp_assoc_t assoc_id = 0; |
---|
1411 | 1363 | int err = 0; |
---|
1412 | 1364 | |
---|
1413 | | - err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id); |
---|
| 1365 | + err = __sctp_setsockopt_connectx(sk, kaddrs, addrs_size, &assoc_id); |
---|
1414 | 1366 | |
---|
1415 | 1367 | if (err) |
---|
1416 | 1368 | return err; |
---|
.. | .. |
---|
1440 | 1392 | { |
---|
1441 | 1393 | struct sctp_getaddrs_old param; |
---|
1442 | 1394 | sctp_assoc_t assoc_id = 0; |
---|
| 1395 | + struct sockaddr *kaddrs; |
---|
1443 | 1396 | int err = 0; |
---|
1444 | 1397 | |
---|
1445 | 1398 | #ifdef CONFIG_COMPAT |
---|
.. | .. |
---|
1463 | 1416 | return -EFAULT; |
---|
1464 | 1417 | } |
---|
1465 | 1418 | |
---|
1466 | | - err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *) |
---|
1467 | | - param.addrs, param.addr_num, |
---|
1468 | | - &assoc_id); |
---|
| 1419 | + kaddrs = memdup_user(param.addrs, param.addr_num); |
---|
| 1420 | + if (IS_ERR(kaddrs)) |
---|
| 1421 | + return PTR_ERR(kaddrs); |
---|
| 1422 | + |
---|
| 1423 | + err = __sctp_setsockopt_connectx(sk, kaddrs, param.addr_num, &assoc_id); |
---|
| 1424 | + kfree(kaddrs); |
---|
1469 | 1425 | if (err == 0 || err == -EINPROGRESS) { |
---|
1470 | 1426 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) |
---|
1471 | 1427 | return -EFAULT; |
---|
.. | .. |
---|
1706 | 1662 | struct sctp_transport **tp) |
---|
1707 | 1663 | { |
---|
1708 | 1664 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
1709 | | - struct net *net = sock_net(sk); |
---|
1710 | 1665 | struct sctp_association *asoc; |
---|
1711 | | - enum sctp_scope scope; |
---|
1712 | 1666 | struct cmsghdr *cmsg; |
---|
1713 | 1667 | __be32 flowinfo = 0; |
---|
1714 | 1668 | struct sctp_af *af; |
---|
.. | .. |
---|
1722 | 1676 | if (sctp_style(sk, TCP) && (sctp_sstate(sk, ESTABLISHED) || |
---|
1723 | 1677 | sctp_sstate(sk, CLOSING))) |
---|
1724 | 1678 | return -EADDRNOTAVAIL; |
---|
1725 | | - |
---|
1726 | | - if (sctp_endpoint_is_peeled_off(ep, daddr)) |
---|
1727 | | - return -EADDRNOTAVAIL; |
---|
1728 | | - |
---|
1729 | | - if (!ep->base.bind_addr.port) { |
---|
1730 | | - if (sctp_autobind(sk)) |
---|
1731 | | - return -EAGAIN; |
---|
1732 | | - } else { |
---|
1733 | | - if (ep->base.bind_addr.port < inet_prot_sock(net) && |
---|
1734 | | - !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) |
---|
1735 | | - return -EACCES; |
---|
1736 | | - } |
---|
1737 | | - |
---|
1738 | | - scope = sctp_scope(daddr); |
---|
1739 | 1679 | |
---|
1740 | 1680 | /* Label connection socket for first association 1-to-many |
---|
1741 | 1681 | * style for client sequence socket()->sendmsg(). This |
---|
.. | .. |
---|
1752 | 1692 | if (err < 0) |
---|
1753 | 1693 | return err; |
---|
1754 | 1694 | |
---|
1755 | | - asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
---|
1756 | | - if (!asoc) |
---|
1757 | | - return -ENOMEM; |
---|
1758 | | - |
---|
1759 | | - if (sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL) < 0) { |
---|
1760 | | - err = -ENOMEM; |
---|
1761 | | - goto free; |
---|
1762 | | - } |
---|
1763 | | - |
---|
1764 | | - if (cmsgs->init) { |
---|
1765 | | - struct sctp_initmsg *init = cmsgs->init; |
---|
1766 | | - |
---|
1767 | | - if (init->sinit_num_ostreams) { |
---|
1768 | | - __u16 outcnt = init->sinit_num_ostreams; |
---|
1769 | | - |
---|
1770 | | - asoc->c.sinit_num_ostreams = outcnt; |
---|
1771 | | - /* outcnt has been changed, need to re-init stream */ |
---|
1772 | | - err = sctp_stream_init(&asoc->stream, outcnt, 0, |
---|
1773 | | - GFP_KERNEL); |
---|
1774 | | - if (err) |
---|
1775 | | - goto free; |
---|
1776 | | - } |
---|
1777 | | - |
---|
1778 | | - if (init->sinit_max_instreams) |
---|
1779 | | - asoc->c.sinit_max_instreams = init->sinit_max_instreams; |
---|
1780 | | - |
---|
1781 | | - if (init->sinit_max_attempts) |
---|
1782 | | - asoc->max_init_attempts = init->sinit_max_attempts; |
---|
1783 | | - |
---|
1784 | | - if (init->sinit_max_init_timeo) |
---|
1785 | | - asoc->max_init_timeo = |
---|
1786 | | - msecs_to_jiffies(init->sinit_max_init_timeo); |
---|
1787 | | - } |
---|
1788 | | - |
---|
1789 | | - *tp = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); |
---|
1790 | | - if (!*tp) { |
---|
1791 | | - err = -ENOMEM; |
---|
1792 | | - goto free; |
---|
1793 | | - } |
---|
| 1695 | + err = sctp_connect_new_asoc(ep, daddr, cmsgs->init, tp); |
---|
| 1696 | + if (err) |
---|
| 1697 | + return err; |
---|
| 1698 | + asoc = (*tp)->asoc; |
---|
1794 | 1699 | |
---|
1795 | 1700 | if (!cmsgs->addrs_msg) |
---|
1796 | 1701 | return 0; |
---|
.. | .. |
---|
1800 | 1705 | |
---|
1801 | 1706 | /* sendv addr list parse */ |
---|
1802 | 1707 | for_each_cmsghdr(cmsg, cmsgs->addrs_msg) { |
---|
1803 | | - struct sctp_transport *transport; |
---|
1804 | | - struct sctp_association *old; |
---|
1805 | 1708 | union sctp_addr _daddr; |
---|
1806 | 1709 | int dlen; |
---|
1807 | 1710 | |
---|
.. | .. |
---|
1835 | 1738 | daddr->v6.sin6_port = htons(asoc->peer.port); |
---|
1836 | 1739 | memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen); |
---|
1837 | 1740 | } |
---|
1838 | | - err = sctp_verify_addr(sk, daddr, sizeof(*daddr)); |
---|
| 1741 | + |
---|
| 1742 | + err = sctp_connect_add_peer(asoc, daddr, sizeof(*daddr)); |
---|
1839 | 1743 | if (err) |
---|
1840 | 1744 | goto free; |
---|
1841 | | - |
---|
1842 | | - old = sctp_endpoint_lookup_assoc(ep, daddr, &transport); |
---|
1843 | | - if (old && old != asoc) { |
---|
1844 | | - if (old->state >= SCTP_STATE_ESTABLISHED) |
---|
1845 | | - err = -EISCONN; |
---|
1846 | | - else |
---|
1847 | | - err = -EALREADY; |
---|
1848 | | - goto free; |
---|
1849 | | - } |
---|
1850 | | - |
---|
1851 | | - if (sctp_endpoint_is_peeled_off(ep, daddr)) { |
---|
1852 | | - err = -EADDRNOTAVAIL; |
---|
1853 | | - goto free; |
---|
1854 | | - } |
---|
1855 | | - |
---|
1856 | | - transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, |
---|
1857 | | - SCTP_UNKNOWN); |
---|
1858 | | - if (!transport) { |
---|
1859 | | - err = -ENOMEM; |
---|
1860 | | - goto free; |
---|
1861 | | - } |
---|
1862 | 1745 | } |
---|
1863 | 1746 | |
---|
1864 | 1747 | return 0; |
---|
.. | .. |
---|
1953 | 1836 | err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); |
---|
1954 | 1837 | if (err) |
---|
1955 | 1838 | goto err; |
---|
| 1839 | + if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) { |
---|
| 1840 | + err = -EINVAL; |
---|
| 1841 | + goto err; |
---|
| 1842 | + } |
---|
1956 | 1843 | } |
---|
1957 | 1844 | |
---|
1958 | 1845 | if (sctp_state(asoc, CLOSED)) { |
---|
.. | .. |
---|
1960 | 1847 | if (err) |
---|
1961 | 1848 | goto err; |
---|
1962 | 1849 | |
---|
1963 | | - if (sp->strm_interleave) { |
---|
| 1850 | + if (asoc->ep->intl_enable) { |
---|
1964 | 1851 | timeo = sock_sndtimeo(sk, 0); |
---|
1965 | 1852 | err = sctp_wait_for_connect(asoc, &timeo); |
---|
1966 | 1853 | if (err) { |
---|
.. | .. |
---|
2266 | 2153 | if (sp->recvrcvinfo) |
---|
2267 | 2154 | sctp_ulpevent_read_rcvinfo(event, msg); |
---|
2268 | 2155 | /* Check if we allow SCTP_SNDRCVINFO. */ |
---|
2269 | | - if (sp->subscribe.sctp_data_io_event) |
---|
| 2156 | + if (sctp_ulpevent_type_enabled(sp->subscribe, SCTP_DATA_IO_EVENT)) |
---|
2270 | 2157 | sctp_ulpevent_read_sndrcvinfo(event, msg); |
---|
2271 | 2158 | |
---|
2272 | 2159 | err = copied; |
---|
.. | .. |
---|
2320 | 2207 | * exceeds the current PMTU size, the message will NOT be sent and |
---|
2321 | 2208 | * instead a error will be indicated to the user. |
---|
2322 | 2209 | */ |
---|
2323 | | -static int sctp_setsockopt_disable_fragments(struct sock *sk, |
---|
2324 | | - char __user *optval, |
---|
| 2210 | +static int sctp_setsockopt_disable_fragments(struct sock *sk, int *val, |
---|
2325 | 2211 | unsigned int optlen) |
---|
2326 | 2212 | { |
---|
2327 | | - int val; |
---|
2328 | | - |
---|
2329 | 2213 | if (optlen < sizeof(int)) |
---|
2330 | 2214 | return -EINVAL; |
---|
2331 | | - |
---|
2332 | | - if (get_user(val, (int __user *)optval)) |
---|
2333 | | - return -EFAULT; |
---|
2334 | | - |
---|
2335 | | - sctp_sk(sk)->disable_fragments = (val == 0) ? 0 : 1; |
---|
2336 | | - |
---|
| 2215 | + sctp_sk(sk)->disable_fragments = (*val == 0) ? 0 : 1; |
---|
2337 | 2216 | return 0; |
---|
2338 | 2217 | } |
---|
2339 | 2218 | |
---|
2340 | | -static int sctp_setsockopt_events(struct sock *sk, char __user *optval, |
---|
| 2219 | +static int sctp_setsockopt_events(struct sock *sk, __u8 *sn_type, |
---|
2341 | 2220 | unsigned int optlen) |
---|
2342 | 2221 | { |
---|
| 2222 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
2343 | 2223 | struct sctp_association *asoc; |
---|
2344 | | - struct sctp_ulpevent *event; |
---|
| 2224 | + int i; |
---|
2345 | 2225 | |
---|
2346 | 2226 | if (optlen > sizeof(struct sctp_event_subscribe)) |
---|
2347 | 2227 | return -EINVAL; |
---|
2348 | | - if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) |
---|
2349 | | - return -EFAULT; |
---|
| 2228 | + |
---|
| 2229 | + for (i = 0; i < optlen; i++) |
---|
| 2230 | + sctp_ulpevent_type_set(&sp->subscribe, SCTP_SN_TYPE_BASE + i, |
---|
| 2231 | + sn_type[i]); |
---|
| 2232 | + |
---|
| 2233 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) |
---|
| 2234 | + asoc->subscribe = sctp_sk(sk)->subscribe; |
---|
2350 | 2235 | |
---|
2351 | 2236 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, |
---|
2352 | 2237 | * if there is no data to be sent or retransmit, the stack will |
---|
2353 | 2238 | * immediately send up this notification. |
---|
2354 | 2239 | */ |
---|
2355 | | - if (sctp_ulpevent_type_enabled(SCTP_SENDER_DRY_EVENT, |
---|
2356 | | - &sctp_sk(sk)->subscribe)) { |
---|
2357 | | - asoc = sctp_id2assoc(sk, 0); |
---|
| 2240 | + if (sctp_ulpevent_type_enabled(sp->subscribe, SCTP_SENDER_DRY_EVENT)) { |
---|
| 2241 | + struct sctp_ulpevent *event; |
---|
2358 | 2242 | |
---|
| 2243 | + asoc = sctp_id2assoc(sk, 0); |
---|
2359 | 2244 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { |
---|
2360 | 2245 | event = sctp_ulpevent_make_sender_dry_event(asoc, |
---|
2361 | 2246 | GFP_USER | __GFP_NOWARN); |
---|
.. | .. |
---|
2380 | 2265 | * integer defining the number of seconds of idle time before an |
---|
2381 | 2266 | * association is closed. |
---|
2382 | 2267 | */ |
---|
2383 | | -static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, |
---|
| 2268 | +static int sctp_setsockopt_autoclose(struct sock *sk, u32 *optval, |
---|
2384 | 2269 | unsigned int optlen) |
---|
2385 | 2270 | { |
---|
2386 | 2271 | struct sctp_sock *sp = sctp_sk(sk); |
---|
.. | .. |
---|
2391 | 2276 | return -EOPNOTSUPP; |
---|
2392 | 2277 | if (optlen != sizeof(int)) |
---|
2393 | 2278 | return -EINVAL; |
---|
2394 | | - if (copy_from_user(&sp->autoclose, optval, optlen)) |
---|
2395 | | - return -EFAULT; |
---|
2396 | 2279 | |
---|
| 2280 | + sp->autoclose = *optval; |
---|
2397 | 2281 | if (sp->autoclose > net->sctp.max_autoclose) |
---|
2398 | 2282 | sp->autoclose = net->sctp.max_autoclose; |
---|
2399 | 2283 | |
---|
.. | .. |
---|
2549 | 2433 | int error; |
---|
2550 | 2434 | |
---|
2551 | 2435 | if (params->spp_flags & SPP_HB_DEMAND && trans) { |
---|
2552 | | - struct net *net = sock_net(trans->asoc->base.sk); |
---|
2553 | | - |
---|
2554 | | - error = sctp_primitive_REQUESTHEARTBEAT(net, trans->asoc, trans); |
---|
| 2436 | + error = sctp_primitive_REQUESTHEARTBEAT(trans->asoc->base.net, |
---|
| 2437 | + trans->asoc, trans); |
---|
2555 | 2438 | if (error) |
---|
2556 | 2439 | return error; |
---|
2557 | 2440 | } |
---|
.. | .. |
---|
2574 | 2457 | if (trans) { |
---|
2575 | 2458 | trans->hbinterval = |
---|
2576 | 2459 | msecs_to_jiffies(params->spp_hbinterval); |
---|
| 2460 | + sctp_transport_reset_hb_timer(trans); |
---|
2577 | 2461 | } else if (asoc) { |
---|
2578 | 2462 | asoc->hbinterval = |
---|
2579 | 2463 | msecs_to_jiffies(params->spp_hbinterval); |
---|
.. | .. |
---|
2729 | 2613 | } |
---|
2730 | 2614 | |
---|
2731 | 2615 | static int sctp_setsockopt_peer_addr_params(struct sock *sk, |
---|
2732 | | - char __user *optval, |
---|
| 2616 | + struct sctp_paddrparams *params, |
---|
2733 | 2617 | unsigned int optlen) |
---|
2734 | 2618 | { |
---|
2735 | | - struct sctp_paddrparams params; |
---|
2736 | 2619 | struct sctp_transport *trans = NULL; |
---|
2737 | 2620 | struct sctp_association *asoc = NULL; |
---|
2738 | 2621 | struct sctp_sock *sp = sctp_sk(sk); |
---|
2739 | 2622 | int error; |
---|
2740 | 2623 | int hb_change, pmtud_change, sackdelay_change; |
---|
2741 | 2624 | |
---|
2742 | | - if (optlen == sizeof(params)) { |
---|
2743 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
2744 | | - return -EFAULT; |
---|
2745 | | - } else if (optlen == ALIGN(offsetof(struct sctp_paddrparams, |
---|
| 2625 | + if (optlen == ALIGN(offsetof(struct sctp_paddrparams, |
---|
2746 | 2626 | spp_ipv6_flowlabel), 4)) { |
---|
2747 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
2748 | | - return -EFAULT; |
---|
2749 | | - if (params.spp_flags & (SPP_DSCP | SPP_IPV6_FLOWLABEL)) |
---|
| 2627 | + if (params->spp_flags & (SPP_DSCP | SPP_IPV6_FLOWLABEL)) |
---|
2750 | 2628 | return -EINVAL; |
---|
2751 | | - } else { |
---|
| 2629 | + } else if (optlen != sizeof(*params)) { |
---|
2752 | 2630 | return -EINVAL; |
---|
2753 | 2631 | } |
---|
2754 | 2632 | |
---|
2755 | 2633 | /* Validate flags and value parameters. */ |
---|
2756 | | - hb_change = params.spp_flags & SPP_HB; |
---|
2757 | | - pmtud_change = params.spp_flags & SPP_PMTUD; |
---|
2758 | | - sackdelay_change = params.spp_flags & SPP_SACKDELAY; |
---|
| 2634 | + hb_change = params->spp_flags & SPP_HB; |
---|
| 2635 | + pmtud_change = params->spp_flags & SPP_PMTUD; |
---|
| 2636 | + sackdelay_change = params->spp_flags & SPP_SACKDELAY; |
---|
2759 | 2637 | |
---|
2760 | 2638 | if (hb_change == SPP_HB || |
---|
2761 | 2639 | pmtud_change == SPP_PMTUD || |
---|
2762 | 2640 | sackdelay_change == SPP_SACKDELAY || |
---|
2763 | | - params.spp_sackdelay > 500 || |
---|
2764 | | - (params.spp_pathmtu && |
---|
2765 | | - params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT)) |
---|
| 2641 | + params->spp_sackdelay > 500 || |
---|
| 2642 | + (params->spp_pathmtu && |
---|
| 2643 | + params->spp_pathmtu < SCTP_DEFAULT_MINSEGMENT)) |
---|
2766 | 2644 | return -EINVAL; |
---|
2767 | 2645 | |
---|
2768 | 2646 | /* If an address other than INADDR_ANY is specified, and |
---|
2769 | 2647 | * no transport is found, then the request is invalid. |
---|
2770 | 2648 | */ |
---|
2771 | | - if (!sctp_is_any(sk, (union sctp_addr *)¶ms.spp_address)) { |
---|
2772 | | - trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
---|
2773 | | - params.spp_assoc_id); |
---|
| 2649 | + if (!sctp_is_any(sk, (union sctp_addr *)¶ms->spp_address)) { |
---|
| 2650 | + trans = sctp_addr_id2transport(sk, ¶ms->spp_address, |
---|
| 2651 | + params->spp_assoc_id); |
---|
2774 | 2652 | if (!trans) |
---|
2775 | 2653 | return -EINVAL; |
---|
2776 | 2654 | } |
---|
2777 | 2655 | |
---|
2778 | | - /* Get association, if assoc_id != 0 and the socket is a one |
---|
2779 | | - * to many style socket, and an association was not found, then |
---|
2780 | | - * the id was invalid. |
---|
| 2656 | + /* Get association, if assoc_id != SCTP_FUTURE_ASSOC and the |
---|
| 2657 | + * socket is a one to many style socket, and an association |
---|
| 2658 | + * was not found, then the id was invalid. |
---|
2781 | 2659 | */ |
---|
2782 | | - asoc = sctp_id2assoc(sk, params.spp_assoc_id); |
---|
2783 | | - if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) |
---|
| 2660 | + asoc = sctp_id2assoc(sk, params->spp_assoc_id); |
---|
| 2661 | + if (!asoc && params->spp_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 2662 | + sctp_style(sk, UDP)) |
---|
2784 | 2663 | return -EINVAL; |
---|
2785 | 2664 | |
---|
2786 | 2665 | /* Heartbeat demand can only be sent on a transport or |
---|
2787 | 2666 | * association, but not a socket. |
---|
2788 | 2667 | */ |
---|
2789 | | - if (params.spp_flags & SPP_HB_DEMAND && !trans && !asoc) |
---|
| 2668 | + if (params->spp_flags & SPP_HB_DEMAND && !trans && !asoc) |
---|
2790 | 2669 | return -EINVAL; |
---|
2791 | 2670 | |
---|
2792 | 2671 | /* Process parameters. */ |
---|
2793 | | - error = sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, |
---|
| 2672 | + error = sctp_apply_peer_addr_params(params, trans, asoc, sp, |
---|
2794 | 2673 | hb_change, pmtud_change, |
---|
2795 | 2674 | sackdelay_change); |
---|
2796 | 2675 | |
---|
.. | .. |
---|
2803 | 2682 | if (!trans && asoc) { |
---|
2804 | 2683 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
---|
2805 | 2684 | transports) { |
---|
2806 | | - sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, |
---|
| 2685 | + sctp_apply_peer_addr_params(params, trans, asoc, sp, |
---|
2807 | 2686 | hb_change, pmtud_change, |
---|
2808 | 2687 | sackdelay_change); |
---|
2809 | 2688 | } |
---|
.. | .. |
---|
2820 | 2699 | static inline __u32 sctp_spp_sackdelay_disable(__u32 param_flags) |
---|
2821 | 2700 | { |
---|
2822 | 2701 | return (param_flags & ~SPP_SACKDELAY) | SPP_SACKDELAY_DISABLE; |
---|
| 2702 | +} |
---|
| 2703 | + |
---|
| 2704 | +static void sctp_apply_asoc_delayed_ack(struct sctp_sack_info *params, |
---|
| 2705 | + struct sctp_association *asoc) |
---|
| 2706 | +{ |
---|
| 2707 | + struct sctp_transport *trans; |
---|
| 2708 | + |
---|
| 2709 | + if (params->sack_delay) { |
---|
| 2710 | + asoc->sackdelay = msecs_to_jiffies(params->sack_delay); |
---|
| 2711 | + asoc->param_flags = |
---|
| 2712 | + sctp_spp_sackdelay_enable(asoc->param_flags); |
---|
| 2713 | + } |
---|
| 2714 | + if (params->sack_freq == 1) { |
---|
| 2715 | + asoc->param_flags = |
---|
| 2716 | + sctp_spp_sackdelay_disable(asoc->param_flags); |
---|
| 2717 | + } else if (params->sack_freq > 1) { |
---|
| 2718 | + asoc->sackfreq = params->sack_freq; |
---|
| 2719 | + asoc->param_flags = |
---|
| 2720 | + sctp_spp_sackdelay_enable(asoc->param_flags); |
---|
| 2721 | + } |
---|
| 2722 | + |
---|
| 2723 | + list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
---|
| 2724 | + transports) { |
---|
| 2725 | + if (params->sack_delay) { |
---|
| 2726 | + trans->sackdelay = msecs_to_jiffies(params->sack_delay); |
---|
| 2727 | + trans->param_flags = |
---|
| 2728 | + sctp_spp_sackdelay_enable(trans->param_flags); |
---|
| 2729 | + } |
---|
| 2730 | + if (params->sack_freq == 1) { |
---|
| 2731 | + trans->param_flags = |
---|
| 2732 | + sctp_spp_sackdelay_disable(trans->param_flags); |
---|
| 2733 | + } else if (params->sack_freq > 1) { |
---|
| 2734 | + trans->sackfreq = params->sack_freq; |
---|
| 2735 | + trans->param_flags = |
---|
| 2736 | + sctp_spp_sackdelay_enable(trans->param_flags); |
---|
| 2737 | + } |
---|
| 2738 | + } |
---|
2823 | 2739 | } |
---|
2824 | 2740 | |
---|
2825 | 2741 | /* |
---|
.. | .. |
---|
2857 | 2773 | * timer to expire. The default value for this is 2, setting this |
---|
2858 | 2774 | * value to 1 will disable the delayed sack algorithm. |
---|
2859 | 2775 | */ |
---|
| 2776 | +static int __sctp_setsockopt_delayed_ack(struct sock *sk, |
---|
| 2777 | + struct sctp_sack_info *params) |
---|
| 2778 | +{ |
---|
| 2779 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 2780 | + struct sctp_association *asoc; |
---|
| 2781 | + |
---|
| 2782 | + /* Validate value parameter. */ |
---|
| 2783 | + if (params->sack_delay > 500) |
---|
| 2784 | + return -EINVAL; |
---|
| 2785 | + |
---|
| 2786 | + /* Get association, if sack_assoc_id != SCTP_FUTURE_ASSOC and the |
---|
| 2787 | + * socket is a one to many style socket, and an association |
---|
| 2788 | + * was not found, then the id was invalid. |
---|
| 2789 | + */ |
---|
| 2790 | + asoc = sctp_id2assoc(sk, params->sack_assoc_id); |
---|
| 2791 | + if (!asoc && params->sack_assoc_id > SCTP_ALL_ASSOC && |
---|
| 2792 | + sctp_style(sk, UDP)) |
---|
| 2793 | + return -EINVAL; |
---|
| 2794 | + |
---|
| 2795 | + if (asoc) { |
---|
| 2796 | + sctp_apply_asoc_delayed_ack(params, asoc); |
---|
| 2797 | + |
---|
| 2798 | + return 0; |
---|
| 2799 | + } |
---|
| 2800 | + |
---|
| 2801 | + if (sctp_style(sk, TCP)) |
---|
| 2802 | + params->sack_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 2803 | + |
---|
| 2804 | + if (params->sack_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 2805 | + params->sack_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 2806 | + if (params->sack_delay) { |
---|
| 2807 | + sp->sackdelay = params->sack_delay; |
---|
| 2808 | + sp->param_flags = |
---|
| 2809 | + sctp_spp_sackdelay_enable(sp->param_flags); |
---|
| 2810 | + } |
---|
| 2811 | + if (params->sack_freq == 1) { |
---|
| 2812 | + sp->param_flags = |
---|
| 2813 | + sctp_spp_sackdelay_disable(sp->param_flags); |
---|
| 2814 | + } else if (params->sack_freq > 1) { |
---|
| 2815 | + sp->sackfreq = params->sack_freq; |
---|
| 2816 | + sp->param_flags = |
---|
| 2817 | + sctp_spp_sackdelay_enable(sp->param_flags); |
---|
| 2818 | + } |
---|
| 2819 | + } |
---|
| 2820 | + |
---|
| 2821 | + if (params->sack_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 2822 | + params->sack_assoc_id == SCTP_ALL_ASSOC) |
---|
| 2823 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) |
---|
| 2824 | + sctp_apply_asoc_delayed_ack(params, asoc); |
---|
| 2825 | + |
---|
| 2826 | + return 0; |
---|
| 2827 | +} |
---|
2860 | 2828 | |
---|
2861 | 2829 | static int sctp_setsockopt_delayed_ack(struct sock *sk, |
---|
2862 | | - char __user *optval, unsigned int optlen) |
---|
| 2830 | + struct sctp_sack_info *params, |
---|
| 2831 | + unsigned int optlen) |
---|
2863 | 2832 | { |
---|
2864 | | - struct sctp_sack_info params; |
---|
2865 | | - struct sctp_transport *trans = NULL; |
---|
2866 | | - struct sctp_association *asoc = NULL; |
---|
2867 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
| 2833 | + if (optlen == sizeof(struct sctp_assoc_value)) { |
---|
| 2834 | + struct sctp_assoc_value *v = (struct sctp_assoc_value *)params; |
---|
| 2835 | + struct sctp_sack_info p; |
---|
2868 | 2836 | |
---|
2869 | | - if (optlen == sizeof(struct sctp_sack_info)) { |
---|
2870 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
2871 | | - return -EFAULT; |
---|
2872 | | - |
---|
2873 | | - if (params.sack_delay == 0 && params.sack_freq == 0) |
---|
2874 | | - return 0; |
---|
2875 | | - } else if (optlen == sizeof(struct sctp_assoc_value)) { |
---|
2876 | 2837 | pr_warn_ratelimited(DEPRECATED |
---|
2877 | 2838 | "%s (pid %d) " |
---|
2878 | 2839 | "Use of struct sctp_assoc_value in delayed_ack socket option.\n" |
---|
2879 | 2840 | "Use struct sctp_sack_info instead\n", |
---|
2880 | 2841 | current->comm, task_pid_nr(current)); |
---|
2881 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
2882 | | - return -EFAULT; |
---|
2883 | 2842 | |
---|
2884 | | - if (params.sack_delay == 0) |
---|
2885 | | - params.sack_freq = 1; |
---|
2886 | | - else |
---|
2887 | | - params.sack_freq = 0; |
---|
2888 | | - } else |
---|
2889 | | - return -EINVAL; |
---|
2890 | | - |
---|
2891 | | - /* Validate value parameter. */ |
---|
2892 | | - if (params.sack_delay > 500) |
---|
2893 | | - return -EINVAL; |
---|
2894 | | - |
---|
2895 | | - /* Get association, if sack_assoc_id != 0 and the socket is a one |
---|
2896 | | - * to many style socket, and an association was not found, then |
---|
2897 | | - * the id was invalid. |
---|
2898 | | - */ |
---|
2899 | | - asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
---|
2900 | | - if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
---|
2901 | | - return -EINVAL; |
---|
2902 | | - |
---|
2903 | | - if (params.sack_delay) { |
---|
2904 | | - if (asoc) { |
---|
2905 | | - asoc->sackdelay = |
---|
2906 | | - msecs_to_jiffies(params.sack_delay); |
---|
2907 | | - asoc->param_flags = |
---|
2908 | | - sctp_spp_sackdelay_enable(asoc->param_flags); |
---|
2909 | | - } else { |
---|
2910 | | - sp->sackdelay = params.sack_delay; |
---|
2911 | | - sp->param_flags = |
---|
2912 | | - sctp_spp_sackdelay_enable(sp->param_flags); |
---|
2913 | | - } |
---|
| 2843 | + p.sack_assoc_id = v->assoc_id; |
---|
| 2844 | + p.sack_delay = v->assoc_value; |
---|
| 2845 | + p.sack_freq = v->assoc_value ? 0 : 1; |
---|
| 2846 | + return __sctp_setsockopt_delayed_ack(sk, &p); |
---|
2914 | 2847 | } |
---|
2915 | 2848 | |
---|
2916 | | - if (params.sack_freq == 1) { |
---|
2917 | | - if (asoc) { |
---|
2918 | | - asoc->param_flags = |
---|
2919 | | - sctp_spp_sackdelay_disable(asoc->param_flags); |
---|
2920 | | - } else { |
---|
2921 | | - sp->param_flags = |
---|
2922 | | - sctp_spp_sackdelay_disable(sp->param_flags); |
---|
2923 | | - } |
---|
2924 | | - } else if (params.sack_freq > 1) { |
---|
2925 | | - if (asoc) { |
---|
2926 | | - asoc->sackfreq = params.sack_freq; |
---|
2927 | | - asoc->param_flags = |
---|
2928 | | - sctp_spp_sackdelay_enable(asoc->param_flags); |
---|
2929 | | - } else { |
---|
2930 | | - sp->sackfreq = params.sack_freq; |
---|
2931 | | - sp->param_flags = |
---|
2932 | | - sctp_spp_sackdelay_enable(sp->param_flags); |
---|
2933 | | - } |
---|
2934 | | - } |
---|
2935 | | - |
---|
2936 | | - /* If change is for association, also apply to each transport. */ |
---|
2937 | | - if (asoc) { |
---|
2938 | | - list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
---|
2939 | | - transports) { |
---|
2940 | | - if (params.sack_delay) { |
---|
2941 | | - trans->sackdelay = |
---|
2942 | | - msecs_to_jiffies(params.sack_delay); |
---|
2943 | | - trans->param_flags = |
---|
2944 | | - sctp_spp_sackdelay_enable(trans->param_flags); |
---|
2945 | | - } |
---|
2946 | | - if (params.sack_freq == 1) { |
---|
2947 | | - trans->param_flags = |
---|
2948 | | - sctp_spp_sackdelay_disable(trans->param_flags); |
---|
2949 | | - } else if (params.sack_freq > 1) { |
---|
2950 | | - trans->sackfreq = params.sack_freq; |
---|
2951 | | - trans->param_flags = |
---|
2952 | | - sctp_spp_sackdelay_enable(trans->param_flags); |
---|
2953 | | - } |
---|
2954 | | - } |
---|
2955 | | - } |
---|
2956 | | - |
---|
2957 | | - return 0; |
---|
| 2849 | + if (optlen != sizeof(struct sctp_sack_info)) |
---|
| 2850 | + return -EINVAL; |
---|
| 2851 | + if (params->sack_delay == 0 && params->sack_freq == 0) |
---|
| 2852 | + return 0; |
---|
| 2853 | + return __sctp_setsockopt_delayed_ack(sk, params); |
---|
2958 | 2854 | } |
---|
2959 | 2855 | |
---|
2960 | 2856 | /* 7.1.3 Initialization Parameters (SCTP_INITMSG) |
---|
.. | .. |
---|
2968 | 2864 | * by the change). With TCP-style sockets, this option is inherited by |
---|
2969 | 2865 | * sockets derived from a listener socket. |
---|
2970 | 2866 | */ |
---|
2971 | | -static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, unsigned int optlen) |
---|
| 2867 | +static int sctp_setsockopt_initmsg(struct sock *sk, struct sctp_initmsg *sinit, |
---|
| 2868 | + unsigned int optlen) |
---|
2972 | 2869 | { |
---|
2973 | | - struct sctp_initmsg sinit; |
---|
2974 | 2870 | struct sctp_sock *sp = sctp_sk(sk); |
---|
2975 | 2871 | |
---|
2976 | 2872 | if (optlen != sizeof(struct sctp_initmsg)) |
---|
2977 | 2873 | return -EINVAL; |
---|
2978 | | - if (copy_from_user(&sinit, optval, optlen)) |
---|
2979 | | - return -EFAULT; |
---|
2980 | 2874 | |
---|
2981 | | - if (sinit.sinit_num_ostreams) |
---|
2982 | | - sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams; |
---|
2983 | | - if (sinit.sinit_max_instreams) |
---|
2984 | | - sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams; |
---|
2985 | | - if (sinit.sinit_max_attempts) |
---|
2986 | | - sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts; |
---|
2987 | | - if (sinit.sinit_max_init_timeo) |
---|
2988 | | - sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo; |
---|
| 2875 | + if (sinit->sinit_num_ostreams) |
---|
| 2876 | + sp->initmsg.sinit_num_ostreams = sinit->sinit_num_ostreams; |
---|
| 2877 | + if (sinit->sinit_max_instreams) |
---|
| 2878 | + sp->initmsg.sinit_max_instreams = sinit->sinit_max_instreams; |
---|
| 2879 | + if (sinit->sinit_max_attempts) |
---|
| 2880 | + sp->initmsg.sinit_max_attempts = sinit->sinit_max_attempts; |
---|
| 2881 | + if (sinit->sinit_max_init_timeo) |
---|
| 2882 | + sp->initmsg.sinit_max_init_timeo = sinit->sinit_max_init_timeo; |
---|
2989 | 2883 | |
---|
2990 | 2884 | return 0; |
---|
2991 | 2885 | } |
---|
.. | .. |
---|
3005 | 2899 | * to this call if the caller is using the UDP model. |
---|
3006 | 2900 | */ |
---|
3007 | 2901 | static int sctp_setsockopt_default_send_param(struct sock *sk, |
---|
3008 | | - char __user *optval, |
---|
| 2902 | + struct sctp_sndrcvinfo *info, |
---|
3009 | 2903 | unsigned int optlen) |
---|
3010 | 2904 | { |
---|
3011 | 2905 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3012 | 2906 | struct sctp_association *asoc; |
---|
3013 | | - struct sctp_sndrcvinfo info; |
---|
3014 | 2907 | |
---|
3015 | | - if (optlen != sizeof(info)) |
---|
| 2908 | + if (optlen != sizeof(*info)) |
---|
3016 | 2909 | return -EINVAL; |
---|
3017 | | - if (copy_from_user(&info, optval, optlen)) |
---|
3018 | | - return -EFAULT; |
---|
3019 | | - if (info.sinfo_flags & |
---|
| 2910 | + if (info->sinfo_flags & |
---|
3020 | 2911 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
---|
3021 | 2912 | SCTP_ABORT | SCTP_EOF)) |
---|
3022 | 2913 | return -EINVAL; |
---|
3023 | 2914 | |
---|
3024 | | - asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); |
---|
3025 | | - if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) |
---|
| 2915 | + asoc = sctp_id2assoc(sk, info->sinfo_assoc_id); |
---|
| 2916 | + if (!asoc && info->sinfo_assoc_id > SCTP_ALL_ASSOC && |
---|
| 2917 | + sctp_style(sk, UDP)) |
---|
3026 | 2918 | return -EINVAL; |
---|
| 2919 | + |
---|
3027 | 2920 | if (asoc) { |
---|
3028 | | - asoc->default_stream = info.sinfo_stream; |
---|
3029 | | - asoc->default_flags = info.sinfo_flags; |
---|
3030 | | - asoc->default_ppid = info.sinfo_ppid; |
---|
3031 | | - asoc->default_context = info.sinfo_context; |
---|
3032 | | - asoc->default_timetolive = info.sinfo_timetolive; |
---|
3033 | | - } else { |
---|
3034 | | - sp->default_stream = info.sinfo_stream; |
---|
3035 | | - sp->default_flags = info.sinfo_flags; |
---|
3036 | | - sp->default_ppid = info.sinfo_ppid; |
---|
3037 | | - sp->default_context = info.sinfo_context; |
---|
3038 | | - sp->default_timetolive = info.sinfo_timetolive; |
---|
| 2921 | + asoc->default_stream = info->sinfo_stream; |
---|
| 2922 | + asoc->default_flags = info->sinfo_flags; |
---|
| 2923 | + asoc->default_ppid = info->sinfo_ppid; |
---|
| 2924 | + asoc->default_context = info->sinfo_context; |
---|
| 2925 | + asoc->default_timetolive = info->sinfo_timetolive; |
---|
| 2926 | + |
---|
| 2927 | + return 0; |
---|
| 2928 | + } |
---|
| 2929 | + |
---|
| 2930 | + if (sctp_style(sk, TCP)) |
---|
| 2931 | + info->sinfo_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 2932 | + |
---|
| 2933 | + if (info->sinfo_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 2934 | + info->sinfo_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 2935 | + sp->default_stream = info->sinfo_stream; |
---|
| 2936 | + sp->default_flags = info->sinfo_flags; |
---|
| 2937 | + sp->default_ppid = info->sinfo_ppid; |
---|
| 2938 | + sp->default_context = info->sinfo_context; |
---|
| 2939 | + sp->default_timetolive = info->sinfo_timetolive; |
---|
| 2940 | + } |
---|
| 2941 | + |
---|
| 2942 | + if (info->sinfo_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 2943 | + info->sinfo_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 2944 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) { |
---|
| 2945 | + asoc->default_stream = info->sinfo_stream; |
---|
| 2946 | + asoc->default_flags = info->sinfo_flags; |
---|
| 2947 | + asoc->default_ppid = info->sinfo_ppid; |
---|
| 2948 | + asoc->default_context = info->sinfo_context; |
---|
| 2949 | + asoc->default_timetolive = info->sinfo_timetolive; |
---|
| 2950 | + } |
---|
3039 | 2951 | } |
---|
3040 | 2952 | |
---|
3041 | 2953 | return 0; |
---|
.. | .. |
---|
3045 | 2957 | * (SCTP_DEFAULT_SNDINFO) |
---|
3046 | 2958 | */ |
---|
3047 | 2959 | static int sctp_setsockopt_default_sndinfo(struct sock *sk, |
---|
3048 | | - char __user *optval, |
---|
| 2960 | + struct sctp_sndinfo *info, |
---|
3049 | 2961 | unsigned int optlen) |
---|
3050 | 2962 | { |
---|
3051 | 2963 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3052 | 2964 | struct sctp_association *asoc; |
---|
3053 | | - struct sctp_sndinfo info; |
---|
3054 | 2965 | |
---|
3055 | | - if (optlen != sizeof(info)) |
---|
| 2966 | + if (optlen != sizeof(*info)) |
---|
3056 | 2967 | return -EINVAL; |
---|
3057 | | - if (copy_from_user(&info, optval, optlen)) |
---|
3058 | | - return -EFAULT; |
---|
3059 | | - if (info.snd_flags & |
---|
| 2968 | + if (info->snd_flags & |
---|
3060 | 2969 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
---|
3061 | 2970 | SCTP_ABORT | SCTP_EOF)) |
---|
3062 | 2971 | return -EINVAL; |
---|
3063 | 2972 | |
---|
3064 | | - asoc = sctp_id2assoc(sk, info.snd_assoc_id); |
---|
3065 | | - if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP)) |
---|
| 2973 | + asoc = sctp_id2assoc(sk, info->snd_assoc_id); |
---|
| 2974 | + if (!asoc && info->snd_assoc_id > SCTP_ALL_ASSOC && |
---|
| 2975 | + sctp_style(sk, UDP)) |
---|
3066 | 2976 | return -EINVAL; |
---|
| 2977 | + |
---|
3067 | 2978 | if (asoc) { |
---|
3068 | | - asoc->default_stream = info.snd_sid; |
---|
3069 | | - asoc->default_flags = info.snd_flags; |
---|
3070 | | - asoc->default_ppid = info.snd_ppid; |
---|
3071 | | - asoc->default_context = info.snd_context; |
---|
3072 | | - } else { |
---|
3073 | | - sp->default_stream = info.snd_sid; |
---|
3074 | | - sp->default_flags = info.snd_flags; |
---|
3075 | | - sp->default_ppid = info.snd_ppid; |
---|
3076 | | - sp->default_context = info.snd_context; |
---|
| 2979 | + asoc->default_stream = info->snd_sid; |
---|
| 2980 | + asoc->default_flags = info->snd_flags; |
---|
| 2981 | + asoc->default_ppid = info->snd_ppid; |
---|
| 2982 | + asoc->default_context = info->snd_context; |
---|
| 2983 | + |
---|
| 2984 | + return 0; |
---|
| 2985 | + } |
---|
| 2986 | + |
---|
| 2987 | + if (sctp_style(sk, TCP)) |
---|
| 2988 | + info->snd_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 2989 | + |
---|
| 2990 | + if (info->snd_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 2991 | + info->snd_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 2992 | + sp->default_stream = info->snd_sid; |
---|
| 2993 | + sp->default_flags = info->snd_flags; |
---|
| 2994 | + sp->default_ppid = info->snd_ppid; |
---|
| 2995 | + sp->default_context = info->snd_context; |
---|
| 2996 | + } |
---|
| 2997 | + |
---|
| 2998 | + if (info->snd_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 2999 | + info->snd_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3000 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) { |
---|
| 3001 | + asoc->default_stream = info->snd_sid; |
---|
| 3002 | + asoc->default_flags = info->snd_flags; |
---|
| 3003 | + asoc->default_ppid = info->snd_ppid; |
---|
| 3004 | + asoc->default_context = info->snd_context; |
---|
| 3005 | + } |
---|
3077 | 3006 | } |
---|
3078 | 3007 | |
---|
3079 | 3008 | return 0; |
---|
.. | .. |
---|
3085 | 3014 | * the association primary. The enclosed address must be one of the |
---|
3086 | 3015 | * association peer's addresses. |
---|
3087 | 3016 | */ |
---|
3088 | | -static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, |
---|
| 3017 | +static int sctp_setsockopt_primary_addr(struct sock *sk, struct sctp_prim *prim, |
---|
3089 | 3018 | unsigned int optlen) |
---|
3090 | 3019 | { |
---|
3091 | | - struct sctp_prim prim; |
---|
3092 | 3020 | struct sctp_transport *trans; |
---|
3093 | 3021 | struct sctp_af *af; |
---|
3094 | 3022 | int err; |
---|
.. | .. |
---|
3096 | 3024 | if (optlen != sizeof(struct sctp_prim)) |
---|
3097 | 3025 | return -EINVAL; |
---|
3098 | 3026 | |
---|
3099 | | - if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) |
---|
3100 | | - return -EFAULT; |
---|
3101 | | - |
---|
3102 | 3027 | /* Allow security module to validate address but need address len. */ |
---|
3103 | | - af = sctp_get_af_specific(prim.ssp_addr.ss_family); |
---|
| 3028 | + af = sctp_get_af_specific(prim->ssp_addr.ss_family); |
---|
3104 | 3029 | if (!af) |
---|
3105 | 3030 | return -EINVAL; |
---|
3106 | 3031 | |
---|
3107 | 3032 | err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR, |
---|
3108 | | - (struct sockaddr *)&prim.ssp_addr, |
---|
| 3033 | + (struct sockaddr *)&prim->ssp_addr, |
---|
3109 | 3034 | af->sockaddr_len); |
---|
3110 | 3035 | if (err) |
---|
3111 | 3036 | return err; |
---|
3112 | 3037 | |
---|
3113 | | - trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); |
---|
| 3038 | + trans = sctp_addr_id2transport(sk, &prim->ssp_addr, prim->ssp_assoc_id); |
---|
3114 | 3039 | if (!trans) |
---|
3115 | 3040 | return -EINVAL; |
---|
3116 | 3041 | |
---|
.. | .. |
---|
3127 | 3052 | * introduced, at the cost of more packets in the network. Expects an |
---|
3128 | 3053 | * integer boolean flag. |
---|
3129 | 3054 | */ |
---|
3130 | | -static int sctp_setsockopt_nodelay(struct sock *sk, char __user *optval, |
---|
| 3055 | +static int sctp_setsockopt_nodelay(struct sock *sk, int *val, |
---|
3131 | 3056 | unsigned int optlen) |
---|
3132 | 3057 | { |
---|
3133 | | - int val; |
---|
3134 | | - |
---|
3135 | 3058 | if (optlen < sizeof(int)) |
---|
3136 | 3059 | return -EINVAL; |
---|
3137 | | - if (get_user(val, (int __user *)optval)) |
---|
3138 | | - return -EFAULT; |
---|
3139 | | - |
---|
3140 | | - sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1; |
---|
| 3060 | + sctp_sk(sk)->nodelay = (*val == 0) ? 0 : 1; |
---|
3141 | 3061 | return 0; |
---|
3142 | 3062 | } |
---|
3143 | 3063 | |
---|
.. | .. |
---|
3153 | 3073 | * be changed. |
---|
3154 | 3074 | * |
---|
3155 | 3075 | */ |
---|
3156 | | -static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigned int optlen) |
---|
| 3076 | +static int sctp_setsockopt_rtoinfo(struct sock *sk, |
---|
| 3077 | + struct sctp_rtoinfo *rtoinfo, |
---|
| 3078 | + unsigned int optlen) |
---|
3157 | 3079 | { |
---|
3158 | | - struct sctp_rtoinfo rtoinfo; |
---|
3159 | 3080 | struct sctp_association *asoc; |
---|
3160 | 3081 | unsigned long rto_min, rto_max; |
---|
3161 | 3082 | struct sctp_sock *sp = sctp_sk(sk); |
---|
.. | .. |
---|
3163 | 3084 | if (optlen != sizeof (struct sctp_rtoinfo)) |
---|
3164 | 3085 | return -EINVAL; |
---|
3165 | 3086 | |
---|
3166 | | - if (copy_from_user(&rtoinfo, optval, optlen)) |
---|
3167 | | - return -EFAULT; |
---|
3168 | | - |
---|
3169 | | - asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); |
---|
| 3087 | + asoc = sctp_id2assoc(sk, rtoinfo->srto_assoc_id); |
---|
3170 | 3088 | |
---|
3171 | 3089 | /* Set the values to the specific association */ |
---|
3172 | | - if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) |
---|
| 3090 | + if (!asoc && rtoinfo->srto_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 3091 | + sctp_style(sk, UDP)) |
---|
3173 | 3092 | return -EINVAL; |
---|
3174 | 3093 | |
---|
3175 | | - rto_max = rtoinfo.srto_max; |
---|
3176 | | - rto_min = rtoinfo.srto_min; |
---|
| 3094 | + rto_max = rtoinfo->srto_max; |
---|
| 3095 | + rto_min = rtoinfo->srto_min; |
---|
3177 | 3096 | |
---|
3178 | 3097 | if (rto_max) |
---|
3179 | 3098 | rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max; |
---|
.. | .. |
---|
3189 | 3108 | return -EINVAL; |
---|
3190 | 3109 | |
---|
3191 | 3110 | if (asoc) { |
---|
3192 | | - if (rtoinfo.srto_initial != 0) |
---|
| 3111 | + if (rtoinfo->srto_initial != 0) |
---|
3193 | 3112 | asoc->rto_initial = |
---|
3194 | | - msecs_to_jiffies(rtoinfo.srto_initial); |
---|
| 3113 | + msecs_to_jiffies(rtoinfo->srto_initial); |
---|
3195 | 3114 | asoc->rto_max = rto_max; |
---|
3196 | 3115 | asoc->rto_min = rto_min; |
---|
3197 | 3116 | } else { |
---|
3198 | 3117 | /* If there is no association or the association-id = 0 |
---|
3199 | 3118 | * set the values to the endpoint. |
---|
3200 | 3119 | */ |
---|
3201 | | - if (rtoinfo.srto_initial != 0) |
---|
3202 | | - sp->rtoinfo.srto_initial = rtoinfo.srto_initial; |
---|
| 3120 | + if (rtoinfo->srto_initial != 0) |
---|
| 3121 | + sp->rtoinfo.srto_initial = rtoinfo->srto_initial; |
---|
3203 | 3122 | sp->rtoinfo.srto_max = rto_max; |
---|
3204 | 3123 | sp->rtoinfo.srto_min = rto_min; |
---|
3205 | 3124 | } |
---|
.. | .. |
---|
3218 | 3137 | * See [SCTP] for more information. |
---|
3219 | 3138 | * |
---|
3220 | 3139 | */ |
---|
3221 | | -static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, unsigned int optlen) |
---|
| 3140 | +static int sctp_setsockopt_associnfo(struct sock *sk, |
---|
| 3141 | + struct sctp_assocparams *assocparams, |
---|
| 3142 | + unsigned int optlen) |
---|
3222 | 3143 | { |
---|
3223 | 3144 | |
---|
3224 | | - struct sctp_assocparams assocparams; |
---|
3225 | 3145 | struct sctp_association *asoc; |
---|
3226 | 3146 | |
---|
3227 | 3147 | if (optlen != sizeof(struct sctp_assocparams)) |
---|
3228 | 3148 | return -EINVAL; |
---|
3229 | | - if (copy_from_user(&assocparams, optval, optlen)) |
---|
3230 | | - return -EFAULT; |
---|
3231 | 3149 | |
---|
3232 | | - asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); |
---|
| 3150 | + asoc = sctp_id2assoc(sk, assocparams->sasoc_assoc_id); |
---|
3233 | 3151 | |
---|
3234 | | - if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP)) |
---|
| 3152 | + if (!asoc && assocparams->sasoc_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 3153 | + sctp_style(sk, UDP)) |
---|
3235 | 3154 | return -EINVAL; |
---|
3236 | 3155 | |
---|
3237 | 3156 | /* Set the values to the specific association */ |
---|
3238 | 3157 | if (asoc) { |
---|
3239 | | - if (assocparams.sasoc_asocmaxrxt != 0) { |
---|
| 3158 | + if (assocparams->sasoc_asocmaxrxt != 0) { |
---|
3240 | 3159 | __u32 path_sum = 0; |
---|
3241 | 3160 | int paths = 0; |
---|
3242 | 3161 | struct sctp_transport *peer_addr; |
---|
.. | .. |
---|
3253 | 3172 | * then one path. |
---|
3254 | 3173 | */ |
---|
3255 | 3174 | if (paths > 1 && |
---|
3256 | | - assocparams.sasoc_asocmaxrxt > path_sum) |
---|
| 3175 | + assocparams->sasoc_asocmaxrxt > path_sum) |
---|
3257 | 3176 | return -EINVAL; |
---|
3258 | 3177 | |
---|
3259 | | - asoc->max_retrans = assocparams.sasoc_asocmaxrxt; |
---|
| 3178 | + asoc->max_retrans = assocparams->sasoc_asocmaxrxt; |
---|
3260 | 3179 | } |
---|
3261 | 3180 | |
---|
3262 | | - if (assocparams.sasoc_cookie_life != 0) |
---|
3263 | | - asoc->cookie_life = ms_to_ktime(assocparams.sasoc_cookie_life); |
---|
| 3181 | + if (assocparams->sasoc_cookie_life != 0) |
---|
| 3182 | + asoc->cookie_life = |
---|
| 3183 | + ms_to_ktime(assocparams->sasoc_cookie_life); |
---|
3264 | 3184 | } else { |
---|
3265 | 3185 | /* Set the values to the endpoint */ |
---|
3266 | 3186 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3267 | 3187 | |
---|
3268 | | - if (assocparams.sasoc_asocmaxrxt != 0) |
---|
| 3188 | + if (assocparams->sasoc_asocmaxrxt != 0) |
---|
3269 | 3189 | sp->assocparams.sasoc_asocmaxrxt = |
---|
3270 | | - assocparams.sasoc_asocmaxrxt; |
---|
3271 | | - if (assocparams.sasoc_cookie_life != 0) |
---|
| 3190 | + assocparams->sasoc_asocmaxrxt; |
---|
| 3191 | + if (assocparams->sasoc_cookie_life != 0) |
---|
3272 | 3192 | sp->assocparams.sasoc_cookie_life = |
---|
3273 | | - assocparams.sasoc_cookie_life; |
---|
| 3193 | + assocparams->sasoc_cookie_life; |
---|
3274 | 3194 | } |
---|
3275 | 3195 | return 0; |
---|
3276 | 3196 | } |
---|
.. | .. |
---|
3285 | 3205 | * addresses and a user will receive both PF_INET6 and PF_INET type |
---|
3286 | 3206 | * addresses on the socket. |
---|
3287 | 3207 | */ |
---|
3288 | | -static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsigned int optlen) |
---|
| 3208 | +static int sctp_setsockopt_mappedv4(struct sock *sk, int *val, |
---|
| 3209 | + unsigned int optlen) |
---|
3289 | 3210 | { |
---|
3290 | | - int val; |
---|
3291 | 3211 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3292 | 3212 | |
---|
3293 | 3213 | if (optlen < sizeof(int)) |
---|
3294 | 3214 | return -EINVAL; |
---|
3295 | | - if (get_user(val, (int __user *)optval)) |
---|
3296 | | - return -EFAULT; |
---|
3297 | | - if (val) |
---|
| 3215 | + if (*val) |
---|
3298 | 3216 | sp->v4mapped = 1; |
---|
3299 | 3217 | else |
---|
3300 | 3218 | sp->v4mapped = 0; |
---|
.. | .. |
---|
3329 | 3247 | * changed (effecting future associations only). |
---|
3330 | 3248 | * assoc_value: This parameter specifies the maximum size in bytes. |
---|
3331 | 3249 | */ |
---|
3332 | | -static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) |
---|
| 3250 | +static int sctp_setsockopt_maxseg(struct sock *sk, |
---|
| 3251 | + struct sctp_assoc_value *params, |
---|
| 3252 | + unsigned int optlen) |
---|
3333 | 3253 | { |
---|
3334 | 3254 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3335 | | - struct sctp_assoc_value params; |
---|
3336 | 3255 | struct sctp_association *asoc; |
---|
| 3256 | + sctp_assoc_t assoc_id; |
---|
3337 | 3257 | int val; |
---|
3338 | 3258 | |
---|
3339 | 3259 | if (optlen == sizeof(int)) { |
---|
.. | .. |
---|
3342 | 3262 | "Use of int in maxseg socket option.\n" |
---|
3343 | 3263 | "Use struct sctp_assoc_value instead\n", |
---|
3344 | 3264 | current->comm, task_pid_nr(current)); |
---|
3345 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3346 | | - return -EFAULT; |
---|
3347 | | - params.assoc_id = 0; |
---|
| 3265 | + assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3266 | + val = *(int *)params; |
---|
3348 | 3267 | } else if (optlen == sizeof(struct sctp_assoc_value)) { |
---|
3349 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
3350 | | - return -EFAULT; |
---|
3351 | | - val = params.assoc_value; |
---|
| 3268 | + assoc_id = params->assoc_id; |
---|
| 3269 | + val = params->assoc_value; |
---|
3352 | 3270 | } else { |
---|
3353 | 3271 | return -EINVAL; |
---|
3354 | 3272 | } |
---|
3355 | 3273 | |
---|
3356 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 3274 | + asoc = sctp_id2assoc(sk, assoc_id); |
---|
| 3275 | + if (!asoc && assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 3276 | + sctp_style(sk, UDP)) |
---|
| 3277 | + return -EINVAL; |
---|
3357 | 3278 | |
---|
3358 | 3279 | if (val) { |
---|
3359 | 3280 | int min_len, max_len; |
---|
.. | .. |
---|
3371 | 3292 | asoc->user_frag = val; |
---|
3372 | 3293 | sctp_assoc_update_frag_point(asoc); |
---|
3373 | 3294 | } else { |
---|
3374 | | - if (params.assoc_id && sctp_style(sk, UDP)) |
---|
3375 | | - return -EINVAL; |
---|
3376 | 3295 | sp->user_frag = val; |
---|
3377 | 3296 | } |
---|
3378 | 3297 | |
---|
.. | .. |
---|
3388 | 3307 | * locally bound addresses. The following structure is used to make a |
---|
3389 | 3308 | * set primary request: |
---|
3390 | 3309 | */ |
---|
3391 | | -static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval, |
---|
| 3310 | +static int sctp_setsockopt_peer_primary_addr(struct sock *sk, |
---|
| 3311 | + struct sctp_setpeerprim *prim, |
---|
3392 | 3312 | unsigned int optlen) |
---|
3393 | 3313 | { |
---|
3394 | | - struct net *net = sock_net(sk); |
---|
3395 | 3314 | struct sctp_sock *sp; |
---|
3396 | 3315 | struct sctp_association *asoc = NULL; |
---|
3397 | | - struct sctp_setpeerprim prim; |
---|
3398 | 3316 | struct sctp_chunk *chunk; |
---|
3399 | 3317 | struct sctp_af *af; |
---|
3400 | 3318 | int err; |
---|
3401 | 3319 | |
---|
3402 | 3320 | sp = sctp_sk(sk); |
---|
3403 | 3321 | |
---|
3404 | | - if (!net->sctp.addip_enable) |
---|
| 3322 | + if (!sp->ep->asconf_enable) |
---|
3405 | 3323 | return -EPERM; |
---|
3406 | 3324 | |
---|
3407 | 3325 | if (optlen != sizeof(struct sctp_setpeerprim)) |
---|
3408 | 3326 | return -EINVAL; |
---|
3409 | 3327 | |
---|
3410 | | - if (copy_from_user(&prim, optval, optlen)) |
---|
3411 | | - return -EFAULT; |
---|
3412 | | - |
---|
3413 | | - asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); |
---|
| 3328 | + asoc = sctp_id2assoc(sk, prim->sspp_assoc_id); |
---|
3414 | 3329 | if (!asoc) |
---|
3415 | 3330 | return -EINVAL; |
---|
3416 | 3331 | |
---|
.. | .. |
---|
3423 | 3338 | if (!sctp_state(asoc, ESTABLISHED)) |
---|
3424 | 3339 | return -ENOTCONN; |
---|
3425 | 3340 | |
---|
3426 | | - af = sctp_get_af_specific(prim.sspp_addr.ss_family); |
---|
| 3341 | + af = sctp_get_af_specific(prim->sspp_addr.ss_family); |
---|
3427 | 3342 | if (!af) |
---|
3428 | 3343 | return -EINVAL; |
---|
3429 | 3344 | |
---|
3430 | | - if (!af->addr_valid((union sctp_addr *)&prim.sspp_addr, sp, NULL)) |
---|
| 3345 | + if (!af->addr_valid((union sctp_addr *)&prim->sspp_addr, sp, NULL)) |
---|
3431 | 3346 | return -EADDRNOTAVAIL; |
---|
3432 | 3347 | |
---|
3433 | | - if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) |
---|
| 3348 | + if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim->sspp_addr)) |
---|
3434 | 3349 | return -EADDRNOTAVAIL; |
---|
3435 | 3350 | |
---|
3436 | 3351 | /* Allow security module to validate address. */ |
---|
3437 | 3352 | err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR, |
---|
3438 | | - (struct sockaddr *)&prim.sspp_addr, |
---|
| 3353 | + (struct sockaddr *)&prim->sspp_addr, |
---|
3439 | 3354 | af->sockaddr_len); |
---|
3440 | 3355 | if (err) |
---|
3441 | 3356 | return err; |
---|
3442 | 3357 | |
---|
3443 | 3358 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ |
---|
3444 | 3359 | chunk = sctp_make_asconf_set_prim(asoc, |
---|
3445 | | - (union sctp_addr *)&prim.sspp_addr); |
---|
| 3360 | + (union sctp_addr *)&prim->sspp_addr); |
---|
3446 | 3361 | if (!chunk) |
---|
3447 | 3362 | return -ENOMEM; |
---|
3448 | 3363 | |
---|
.. | .. |
---|
3453 | 3368 | return err; |
---|
3454 | 3369 | } |
---|
3455 | 3370 | |
---|
3456 | | -static int sctp_setsockopt_adaptation_layer(struct sock *sk, char __user *optval, |
---|
| 3371 | +static int sctp_setsockopt_adaptation_layer(struct sock *sk, |
---|
| 3372 | + struct sctp_setadaptation *adapt, |
---|
3457 | 3373 | unsigned int optlen) |
---|
3458 | 3374 | { |
---|
3459 | | - struct sctp_setadaptation adaptation; |
---|
3460 | | - |
---|
3461 | 3375 | if (optlen != sizeof(struct sctp_setadaptation)) |
---|
3462 | 3376 | return -EINVAL; |
---|
3463 | | - if (copy_from_user(&adaptation, optval, optlen)) |
---|
3464 | | - return -EFAULT; |
---|
3465 | 3377 | |
---|
3466 | | - sctp_sk(sk)->adaptation_ind = adaptation.ssb_adaptation_ind; |
---|
| 3378 | + sctp_sk(sk)->adaptation_ind = adapt->ssb_adaptation_ind; |
---|
3467 | 3379 | |
---|
3468 | 3380 | return 0; |
---|
3469 | 3381 | } |
---|
.. | .. |
---|
3482 | 3394 | * received messages from the peer and does not effect the value that is |
---|
3483 | 3395 | * saved with outbound messages. |
---|
3484 | 3396 | */ |
---|
3485 | | -static int sctp_setsockopt_context(struct sock *sk, char __user *optval, |
---|
| 3397 | +static int sctp_setsockopt_context(struct sock *sk, |
---|
| 3398 | + struct sctp_assoc_value *params, |
---|
3486 | 3399 | unsigned int optlen) |
---|
3487 | 3400 | { |
---|
3488 | | - struct sctp_assoc_value params; |
---|
3489 | | - struct sctp_sock *sp; |
---|
| 3401 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
3490 | 3402 | struct sctp_association *asoc; |
---|
3491 | 3403 | |
---|
3492 | 3404 | if (optlen != sizeof(struct sctp_assoc_value)) |
---|
3493 | 3405 | return -EINVAL; |
---|
3494 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
3495 | | - return -EFAULT; |
---|
3496 | 3406 | |
---|
3497 | | - sp = sctp_sk(sk); |
---|
| 3407 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 3408 | + if (!asoc && params->assoc_id > SCTP_ALL_ASSOC && |
---|
| 3409 | + sctp_style(sk, UDP)) |
---|
| 3410 | + return -EINVAL; |
---|
3498 | 3411 | |
---|
3499 | | - if (params.assoc_id != 0) { |
---|
3500 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
3501 | | - if (!asoc) |
---|
3502 | | - return -EINVAL; |
---|
3503 | | - asoc->default_rcv_context = params.assoc_value; |
---|
3504 | | - } else { |
---|
3505 | | - sp->default_rcv_context = params.assoc_value; |
---|
| 3412 | + if (asoc) { |
---|
| 3413 | + asoc->default_rcv_context = params->assoc_value; |
---|
| 3414 | + |
---|
| 3415 | + return 0; |
---|
3506 | 3416 | } |
---|
| 3417 | + |
---|
| 3418 | + if (sctp_style(sk, TCP)) |
---|
| 3419 | + params->assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3420 | + |
---|
| 3421 | + if (params->assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 3422 | + params->assoc_id == SCTP_ALL_ASSOC) |
---|
| 3423 | + sp->default_rcv_context = params->assoc_value; |
---|
| 3424 | + |
---|
| 3425 | + if (params->assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 3426 | + params->assoc_id == SCTP_ALL_ASSOC) |
---|
| 3427 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) |
---|
| 3428 | + asoc->default_rcv_context = params->assoc_value; |
---|
3507 | 3429 | |
---|
3508 | 3430 | return 0; |
---|
3509 | 3431 | } |
---|
.. | .. |
---|
3532 | 3454 | * application using the one to many model may become confused and act |
---|
3533 | 3455 | * incorrectly. |
---|
3534 | 3456 | */ |
---|
3535 | | -static int sctp_setsockopt_fragment_interleave(struct sock *sk, |
---|
3536 | | - char __user *optval, |
---|
| 3457 | +static int sctp_setsockopt_fragment_interleave(struct sock *sk, int *val, |
---|
3537 | 3458 | unsigned int optlen) |
---|
3538 | 3459 | { |
---|
3539 | | - int val; |
---|
3540 | | - |
---|
3541 | 3460 | if (optlen != sizeof(int)) |
---|
3542 | 3461 | return -EINVAL; |
---|
3543 | | - if (get_user(val, (int __user *)optval)) |
---|
3544 | | - return -EFAULT; |
---|
3545 | 3462 | |
---|
3546 | | - sctp_sk(sk)->frag_interleave = !!val; |
---|
| 3463 | + sctp_sk(sk)->frag_interleave = !!*val; |
---|
3547 | 3464 | |
---|
3548 | 3465 | if (!sctp_sk(sk)->frag_interleave) |
---|
3549 | | - sctp_sk(sk)->strm_interleave = 0; |
---|
| 3466 | + sctp_sk(sk)->ep->intl_enable = 0; |
---|
3550 | 3467 | |
---|
3551 | 3468 | return 0; |
---|
3552 | 3469 | } |
---|
.. | .. |
---|
3568 | 3485 | * call as long as the user provided buffer is large enough to hold the |
---|
3569 | 3486 | * message. |
---|
3570 | 3487 | */ |
---|
3571 | | -static int sctp_setsockopt_partial_delivery_point(struct sock *sk, |
---|
3572 | | - char __user *optval, |
---|
| 3488 | +static int sctp_setsockopt_partial_delivery_point(struct sock *sk, u32 *val, |
---|
3573 | 3489 | unsigned int optlen) |
---|
3574 | 3490 | { |
---|
3575 | | - u32 val; |
---|
3576 | | - |
---|
3577 | 3491 | if (optlen != sizeof(u32)) |
---|
3578 | 3492 | return -EINVAL; |
---|
3579 | | - if (get_user(val, (int __user *)optval)) |
---|
3580 | | - return -EFAULT; |
---|
3581 | 3493 | |
---|
3582 | 3494 | /* Note: We double the receive buffer from what the user sets |
---|
3583 | 3495 | * it to be, also initial rwnd is based on rcvbuf/2. |
---|
3584 | 3496 | */ |
---|
3585 | | - if (val > (sk->sk_rcvbuf >> 1)) |
---|
| 3497 | + if (*val > (sk->sk_rcvbuf >> 1)) |
---|
3586 | 3498 | return -EINVAL; |
---|
3587 | 3499 | |
---|
3588 | | - sctp_sk(sk)->pd_point = val; |
---|
| 3500 | + sctp_sk(sk)->pd_point = *val; |
---|
3589 | 3501 | |
---|
3590 | 3502 | return 0; /* is this the right error code? */ |
---|
3591 | 3503 | } |
---|
.. | .. |
---|
3602 | 3514 | * future associations inheriting the socket value. |
---|
3603 | 3515 | */ |
---|
3604 | 3516 | static int sctp_setsockopt_maxburst(struct sock *sk, |
---|
3605 | | - char __user *optval, |
---|
| 3517 | + struct sctp_assoc_value *params, |
---|
3606 | 3518 | unsigned int optlen) |
---|
3607 | 3519 | { |
---|
3608 | | - struct sctp_assoc_value params; |
---|
3609 | | - struct sctp_sock *sp; |
---|
| 3520 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
3610 | 3521 | struct sctp_association *asoc; |
---|
3611 | | - int val; |
---|
3612 | | - int assoc_id = 0; |
---|
| 3522 | + sctp_assoc_t assoc_id; |
---|
| 3523 | + u32 assoc_value; |
---|
3613 | 3524 | |
---|
3614 | 3525 | if (optlen == sizeof(int)) { |
---|
3615 | 3526 | pr_warn_ratelimited(DEPRECATED |
---|
.. | .. |
---|
3617 | 3528 | "Use of int in max_burst socket option deprecated.\n" |
---|
3618 | 3529 | "Use struct sctp_assoc_value instead\n", |
---|
3619 | 3530 | current->comm, task_pid_nr(current)); |
---|
3620 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3621 | | - return -EFAULT; |
---|
| 3531 | + assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3532 | + assoc_value = *((int *)params); |
---|
3622 | 3533 | } else if (optlen == sizeof(struct sctp_assoc_value)) { |
---|
3623 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
3624 | | - return -EFAULT; |
---|
3625 | | - val = params.assoc_value; |
---|
3626 | | - assoc_id = params.assoc_id; |
---|
| 3534 | + assoc_id = params->assoc_id; |
---|
| 3535 | + assoc_value = params->assoc_value; |
---|
3627 | 3536 | } else |
---|
3628 | 3537 | return -EINVAL; |
---|
3629 | 3538 | |
---|
3630 | | - sp = sctp_sk(sk); |
---|
| 3539 | + asoc = sctp_id2assoc(sk, assoc_id); |
---|
| 3540 | + if (!asoc && assoc_id > SCTP_ALL_ASSOC && sctp_style(sk, UDP)) |
---|
| 3541 | + return -EINVAL; |
---|
3631 | 3542 | |
---|
3632 | | - if (assoc_id != 0) { |
---|
3633 | | - asoc = sctp_id2assoc(sk, assoc_id); |
---|
3634 | | - if (!asoc) |
---|
3635 | | - return -EINVAL; |
---|
3636 | | - asoc->max_burst = val; |
---|
3637 | | - } else |
---|
3638 | | - sp->max_burst = val; |
---|
| 3543 | + if (asoc) { |
---|
| 3544 | + asoc->max_burst = assoc_value; |
---|
| 3545 | + |
---|
| 3546 | + return 0; |
---|
| 3547 | + } |
---|
| 3548 | + |
---|
| 3549 | + if (sctp_style(sk, TCP)) |
---|
| 3550 | + assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3551 | + |
---|
| 3552 | + if (assoc_id == SCTP_FUTURE_ASSOC || assoc_id == SCTP_ALL_ASSOC) |
---|
| 3553 | + sp->max_burst = assoc_value; |
---|
| 3554 | + |
---|
| 3555 | + if (assoc_id == SCTP_CURRENT_ASSOC || assoc_id == SCTP_ALL_ASSOC) |
---|
| 3556 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) |
---|
| 3557 | + asoc->max_burst = assoc_value; |
---|
3639 | 3558 | |
---|
3640 | 3559 | return 0; |
---|
3641 | 3560 | } |
---|
.. | .. |
---|
3648 | 3567 | * will only effect future associations on the socket. |
---|
3649 | 3568 | */ |
---|
3650 | 3569 | static int sctp_setsockopt_auth_chunk(struct sock *sk, |
---|
3651 | | - char __user *optval, |
---|
| 3570 | + struct sctp_authchunk *val, |
---|
3652 | 3571 | unsigned int optlen) |
---|
3653 | 3572 | { |
---|
3654 | 3573 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3655 | | - struct sctp_authchunk val; |
---|
3656 | 3574 | |
---|
3657 | 3575 | if (!ep->auth_enable) |
---|
3658 | 3576 | return -EACCES; |
---|
3659 | 3577 | |
---|
3660 | 3578 | if (optlen != sizeof(struct sctp_authchunk)) |
---|
3661 | 3579 | return -EINVAL; |
---|
3662 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3663 | | - return -EFAULT; |
---|
3664 | 3580 | |
---|
3665 | | - switch (val.sauth_chunk) { |
---|
| 3581 | + switch (val->sauth_chunk) { |
---|
3666 | 3582 | case SCTP_CID_INIT: |
---|
3667 | 3583 | case SCTP_CID_INIT_ACK: |
---|
3668 | 3584 | case SCTP_CID_SHUTDOWN_COMPLETE: |
---|
.. | .. |
---|
3671 | 3587 | } |
---|
3672 | 3588 | |
---|
3673 | 3589 | /* add this chunk id to the endpoint */ |
---|
3674 | | - return sctp_auth_ep_add_chunkid(ep, val.sauth_chunk); |
---|
| 3590 | + return sctp_auth_ep_add_chunkid(ep, val->sauth_chunk); |
---|
3675 | 3591 | } |
---|
3676 | 3592 | |
---|
3677 | 3593 | /* |
---|
.. | .. |
---|
3681 | 3597 | * endpoint requires the peer to use. |
---|
3682 | 3598 | */ |
---|
3683 | 3599 | static int sctp_setsockopt_hmac_ident(struct sock *sk, |
---|
3684 | | - char __user *optval, |
---|
| 3600 | + struct sctp_hmacalgo *hmacs, |
---|
3685 | 3601 | unsigned int optlen) |
---|
3686 | 3602 | { |
---|
3687 | 3603 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3688 | | - struct sctp_hmacalgo *hmacs; |
---|
3689 | 3604 | u32 idents; |
---|
3690 | | - int err; |
---|
3691 | 3605 | |
---|
3692 | 3606 | if (!ep->auth_enable) |
---|
3693 | 3607 | return -EACCES; |
---|
.. | .. |
---|
3697 | 3611 | optlen = min_t(unsigned int, optlen, sizeof(struct sctp_hmacalgo) + |
---|
3698 | 3612 | SCTP_AUTH_NUM_HMACS * sizeof(u16)); |
---|
3699 | 3613 | |
---|
3700 | | - hmacs = memdup_user(optval, optlen); |
---|
3701 | | - if (IS_ERR(hmacs)) |
---|
3702 | | - return PTR_ERR(hmacs); |
---|
3703 | | - |
---|
3704 | 3614 | idents = hmacs->shmac_num_idents; |
---|
3705 | 3615 | if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS || |
---|
3706 | | - (idents * sizeof(u16)) > (optlen - sizeof(struct sctp_hmacalgo))) { |
---|
3707 | | - err = -EINVAL; |
---|
3708 | | - goto out; |
---|
3709 | | - } |
---|
| 3616 | + (idents * sizeof(u16)) > (optlen - sizeof(struct sctp_hmacalgo))) |
---|
| 3617 | + return -EINVAL; |
---|
3710 | 3618 | |
---|
3711 | | - err = sctp_auth_ep_set_hmacs(ep, hmacs); |
---|
3712 | | -out: |
---|
3713 | | - kfree(hmacs); |
---|
3714 | | - return err; |
---|
| 3619 | + return sctp_auth_ep_set_hmacs(ep, hmacs); |
---|
3715 | 3620 | } |
---|
3716 | 3621 | |
---|
3717 | 3622 | /* |
---|
.. | .. |
---|
3721 | 3626 | * association shared key. |
---|
3722 | 3627 | */ |
---|
3723 | 3628 | static int sctp_setsockopt_auth_key(struct sock *sk, |
---|
3724 | | - char __user *optval, |
---|
| 3629 | + struct sctp_authkey *authkey, |
---|
3725 | 3630 | unsigned int optlen) |
---|
3726 | 3631 | { |
---|
3727 | 3632 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3728 | | - struct sctp_authkey *authkey; |
---|
3729 | 3633 | struct sctp_association *asoc; |
---|
3730 | | - int ret; |
---|
3731 | | - |
---|
3732 | | - if (!ep->auth_enable) |
---|
3733 | | - return -EACCES; |
---|
| 3634 | + int ret = -EINVAL; |
---|
3734 | 3635 | |
---|
3735 | 3636 | if (optlen <= sizeof(struct sctp_authkey)) |
---|
3736 | 3637 | return -EINVAL; |
---|
3737 | 3638 | /* authkey->sca_keylength is u16, so optlen can't be bigger than |
---|
3738 | 3639 | * this. |
---|
3739 | 3640 | */ |
---|
3740 | | - optlen = min_t(unsigned int, optlen, USHRT_MAX + |
---|
3741 | | - sizeof(struct sctp_authkey)); |
---|
| 3641 | + optlen = min_t(unsigned int, optlen, USHRT_MAX + sizeof(*authkey)); |
---|
3742 | 3642 | |
---|
3743 | | - authkey = memdup_user(optval, optlen); |
---|
3744 | | - if (IS_ERR(authkey)) |
---|
3745 | | - return PTR_ERR(authkey); |
---|
3746 | | - |
---|
3747 | | - if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) { |
---|
3748 | | - ret = -EINVAL; |
---|
| 3643 | + if (authkey->sca_keylength > optlen - sizeof(*authkey)) |
---|
3749 | 3644 | goto out; |
---|
3750 | | - } |
---|
3751 | 3645 | |
---|
3752 | 3646 | asoc = sctp_id2assoc(sk, authkey->sca_assoc_id); |
---|
3753 | | - if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) { |
---|
3754 | | - ret = -EINVAL; |
---|
| 3647 | + if (!asoc && authkey->sca_assoc_id > SCTP_ALL_ASSOC && |
---|
| 3648 | + sctp_style(sk, UDP)) |
---|
| 3649 | + goto out; |
---|
| 3650 | + |
---|
| 3651 | + if (asoc) { |
---|
| 3652 | + ret = sctp_auth_set_key(ep, asoc, authkey); |
---|
3755 | 3653 | goto out; |
---|
3756 | 3654 | } |
---|
3757 | 3655 | |
---|
3758 | | - ret = sctp_auth_set_key(ep, asoc, authkey); |
---|
| 3656 | + if (sctp_style(sk, TCP)) |
---|
| 3657 | + authkey->sca_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3658 | + |
---|
| 3659 | + if (authkey->sca_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 3660 | + authkey->sca_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3661 | + ret = sctp_auth_set_key(ep, asoc, authkey); |
---|
| 3662 | + if (ret) |
---|
| 3663 | + goto out; |
---|
| 3664 | + } |
---|
| 3665 | + |
---|
| 3666 | + ret = 0; |
---|
| 3667 | + |
---|
| 3668 | + if (authkey->sca_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 3669 | + authkey->sca_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3670 | + list_for_each_entry(asoc, &ep->asocs, asocs) { |
---|
| 3671 | + int res = sctp_auth_set_key(ep, asoc, authkey); |
---|
| 3672 | + |
---|
| 3673 | + if (res && !ret) |
---|
| 3674 | + ret = res; |
---|
| 3675 | + } |
---|
| 3676 | + } |
---|
| 3677 | + |
---|
3759 | 3678 | out: |
---|
3760 | | - kzfree(authkey); |
---|
| 3679 | + memzero_explicit(authkey, optlen); |
---|
3761 | 3680 | return ret; |
---|
3762 | 3681 | } |
---|
3763 | 3682 | |
---|
.. | .. |
---|
3768 | 3687 | * the association shared key. |
---|
3769 | 3688 | */ |
---|
3770 | 3689 | static int sctp_setsockopt_active_key(struct sock *sk, |
---|
3771 | | - char __user *optval, |
---|
| 3690 | + struct sctp_authkeyid *val, |
---|
3772 | 3691 | unsigned int optlen) |
---|
3773 | 3692 | { |
---|
3774 | 3693 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3775 | | - struct sctp_authkeyid val; |
---|
3776 | 3694 | struct sctp_association *asoc; |
---|
3777 | | - |
---|
3778 | | - if (!ep->auth_enable) |
---|
3779 | | - return -EACCES; |
---|
| 3695 | + int ret = 0; |
---|
3780 | 3696 | |
---|
3781 | 3697 | if (optlen != sizeof(struct sctp_authkeyid)) |
---|
3782 | 3698 | return -EINVAL; |
---|
3783 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3784 | | - return -EFAULT; |
---|
3785 | 3699 | |
---|
3786 | | - asoc = sctp_id2assoc(sk, val.scact_assoc_id); |
---|
3787 | | - if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
---|
| 3700 | + asoc = sctp_id2assoc(sk, val->scact_assoc_id); |
---|
| 3701 | + if (!asoc && val->scact_assoc_id > SCTP_ALL_ASSOC && |
---|
| 3702 | + sctp_style(sk, UDP)) |
---|
3788 | 3703 | return -EINVAL; |
---|
3789 | 3704 | |
---|
3790 | | - return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); |
---|
| 3705 | + if (asoc) |
---|
| 3706 | + return sctp_auth_set_active_key(ep, asoc, val->scact_keynumber); |
---|
| 3707 | + |
---|
| 3708 | + if (sctp_style(sk, TCP)) |
---|
| 3709 | + val->scact_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3710 | + |
---|
| 3711 | + if (val->scact_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 3712 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3713 | + ret = sctp_auth_set_active_key(ep, asoc, val->scact_keynumber); |
---|
| 3714 | + if (ret) |
---|
| 3715 | + return ret; |
---|
| 3716 | + } |
---|
| 3717 | + |
---|
| 3718 | + if (val->scact_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 3719 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3720 | + list_for_each_entry(asoc, &ep->asocs, asocs) { |
---|
| 3721 | + int res = sctp_auth_set_active_key(ep, asoc, |
---|
| 3722 | + val->scact_keynumber); |
---|
| 3723 | + |
---|
| 3724 | + if (res && !ret) |
---|
| 3725 | + ret = res; |
---|
| 3726 | + } |
---|
| 3727 | + } |
---|
| 3728 | + |
---|
| 3729 | + return ret; |
---|
3791 | 3730 | } |
---|
3792 | 3731 | |
---|
3793 | 3732 | /* |
---|
.. | .. |
---|
3796 | 3735 | * This set option will delete a shared secret key from use. |
---|
3797 | 3736 | */ |
---|
3798 | 3737 | static int sctp_setsockopt_del_key(struct sock *sk, |
---|
3799 | | - char __user *optval, |
---|
| 3738 | + struct sctp_authkeyid *val, |
---|
3800 | 3739 | unsigned int optlen) |
---|
3801 | 3740 | { |
---|
3802 | 3741 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3803 | | - struct sctp_authkeyid val; |
---|
3804 | 3742 | struct sctp_association *asoc; |
---|
3805 | | - |
---|
3806 | | - if (!ep->auth_enable) |
---|
3807 | | - return -EACCES; |
---|
| 3743 | + int ret = 0; |
---|
3808 | 3744 | |
---|
3809 | 3745 | if (optlen != sizeof(struct sctp_authkeyid)) |
---|
3810 | 3746 | return -EINVAL; |
---|
3811 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3812 | | - return -EFAULT; |
---|
3813 | 3747 | |
---|
3814 | | - asoc = sctp_id2assoc(sk, val.scact_assoc_id); |
---|
3815 | | - if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
---|
| 3748 | + asoc = sctp_id2assoc(sk, val->scact_assoc_id); |
---|
| 3749 | + if (!asoc && val->scact_assoc_id > SCTP_ALL_ASSOC && |
---|
| 3750 | + sctp_style(sk, UDP)) |
---|
3816 | 3751 | return -EINVAL; |
---|
3817 | 3752 | |
---|
3818 | | - return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); |
---|
| 3753 | + if (asoc) |
---|
| 3754 | + return sctp_auth_del_key_id(ep, asoc, val->scact_keynumber); |
---|
3819 | 3755 | |
---|
| 3756 | + if (sctp_style(sk, TCP)) |
---|
| 3757 | + val->scact_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3758 | + |
---|
| 3759 | + if (val->scact_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 3760 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3761 | + ret = sctp_auth_del_key_id(ep, asoc, val->scact_keynumber); |
---|
| 3762 | + if (ret) |
---|
| 3763 | + return ret; |
---|
| 3764 | + } |
---|
| 3765 | + |
---|
| 3766 | + if (val->scact_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 3767 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3768 | + list_for_each_entry(asoc, &ep->asocs, asocs) { |
---|
| 3769 | + int res = sctp_auth_del_key_id(ep, asoc, |
---|
| 3770 | + val->scact_keynumber); |
---|
| 3771 | + |
---|
| 3772 | + if (res && !ret) |
---|
| 3773 | + ret = res; |
---|
| 3774 | + } |
---|
| 3775 | + } |
---|
| 3776 | + |
---|
| 3777 | + return ret; |
---|
3820 | 3778 | } |
---|
3821 | 3779 | |
---|
3822 | 3780 | /* |
---|
.. | .. |
---|
3824 | 3782 | * |
---|
3825 | 3783 | * This set option will deactivate a shared secret key. |
---|
3826 | 3784 | */ |
---|
3827 | | -static int sctp_setsockopt_deactivate_key(struct sock *sk, char __user *optval, |
---|
| 3785 | +static int sctp_setsockopt_deactivate_key(struct sock *sk, |
---|
| 3786 | + struct sctp_authkeyid *val, |
---|
3828 | 3787 | unsigned int optlen) |
---|
3829 | 3788 | { |
---|
3830 | 3789 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
3831 | | - struct sctp_authkeyid val; |
---|
3832 | 3790 | struct sctp_association *asoc; |
---|
3833 | | - |
---|
3834 | | - if (!ep->auth_enable) |
---|
3835 | | - return -EACCES; |
---|
| 3791 | + int ret = 0; |
---|
3836 | 3792 | |
---|
3837 | 3793 | if (optlen != sizeof(struct sctp_authkeyid)) |
---|
3838 | 3794 | return -EINVAL; |
---|
3839 | | - if (copy_from_user(&val, optval, optlen)) |
---|
3840 | | - return -EFAULT; |
---|
3841 | 3795 | |
---|
3842 | | - asoc = sctp_id2assoc(sk, val.scact_assoc_id); |
---|
3843 | | - if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
---|
| 3796 | + asoc = sctp_id2assoc(sk, val->scact_assoc_id); |
---|
| 3797 | + if (!asoc && val->scact_assoc_id > SCTP_ALL_ASSOC && |
---|
| 3798 | + sctp_style(sk, UDP)) |
---|
3844 | 3799 | return -EINVAL; |
---|
3845 | 3800 | |
---|
3846 | | - return sctp_auth_deact_key_id(ep, asoc, val.scact_keynumber); |
---|
| 3801 | + if (asoc) |
---|
| 3802 | + return sctp_auth_deact_key_id(ep, asoc, val->scact_keynumber); |
---|
| 3803 | + |
---|
| 3804 | + if (sctp_style(sk, TCP)) |
---|
| 3805 | + val->scact_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 3806 | + |
---|
| 3807 | + if (val->scact_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 3808 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3809 | + ret = sctp_auth_deact_key_id(ep, asoc, val->scact_keynumber); |
---|
| 3810 | + if (ret) |
---|
| 3811 | + return ret; |
---|
| 3812 | + } |
---|
| 3813 | + |
---|
| 3814 | + if (val->scact_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 3815 | + val->scact_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 3816 | + list_for_each_entry(asoc, &ep->asocs, asocs) { |
---|
| 3817 | + int res = sctp_auth_deact_key_id(ep, asoc, |
---|
| 3818 | + val->scact_keynumber); |
---|
| 3819 | + |
---|
| 3820 | + if (res && !ret) |
---|
| 3821 | + ret = res; |
---|
| 3822 | + } |
---|
| 3823 | + } |
---|
| 3824 | + |
---|
| 3825 | + return ret; |
---|
3847 | 3826 | } |
---|
3848 | 3827 | |
---|
3849 | 3828 | /* |
---|
.. | .. |
---|
3860 | 3839 | * Note. In this implementation, socket operation overrides default parameter |
---|
3861 | 3840 | * being set by sysctl as well as FreeBSD implementation |
---|
3862 | 3841 | */ |
---|
3863 | | -static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, |
---|
| 3842 | +static int sctp_setsockopt_auto_asconf(struct sock *sk, int *val, |
---|
3864 | 3843 | unsigned int optlen) |
---|
3865 | 3844 | { |
---|
3866 | | - int val; |
---|
3867 | 3845 | struct sctp_sock *sp = sctp_sk(sk); |
---|
3868 | 3846 | |
---|
3869 | 3847 | if (optlen < sizeof(int)) |
---|
3870 | 3848 | return -EINVAL; |
---|
3871 | | - if (get_user(val, (int __user *)optval)) |
---|
3872 | | - return -EFAULT; |
---|
3873 | | - if (!sctp_is_ep_boundall(sk) && val) |
---|
| 3849 | + if (!sctp_is_ep_boundall(sk) && *val) |
---|
3874 | 3850 | return -EINVAL; |
---|
3875 | | - if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf)) |
---|
| 3851 | + if ((*val && sp->do_auto_asconf) || (!*val && !sp->do_auto_asconf)) |
---|
3876 | 3852 | return 0; |
---|
3877 | 3853 | |
---|
3878 | 3854 | spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock); |
---|
3879 | | - if (val == 0 && sp->do_auto_asconf) { |
---|
| 3855 | + if (*val == 0 && sp->do_auto_asconf) { |
---|
3880 | 3856 | list_del(&sp->auto_asconf_list); |
---|
3881 | 3857 | sp->do_auto_asconf = 0; |
---|
3882 | | - } else if (val && !sp->do_auto_asconf) { |
---|
| 3858 | + } else if (*val && !sp->do_auto_asconf) { |
---|
3883 | 3859 | list_add_tail(&sp->auto_asconf_list, |
---|
3884 | 3860 | &sock_net(sk)->sctp.auto_asconf_splist); |
---|
3885 | 3861 | sp->do_auto_asconf = 1; |
---|
.. | .. |
---|
3896 | 3872 | * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt |
---|
3897 | 3873 | */ |
---|
3898 | 3874 | static int sctp_setsockopt_paddr_thresholds(struct sock *sk, |
---|
3899 | | - char __user *optval, |
---|
3900 | | - unsigned int optlen) |
---|
| 3875 | + struct sctp_paddrthlds_v2 *val, |
---|
| 3876 | + unsigned int optlen, bool v2) |
---|
3901 | 3877 | { |
---|
3902 | | - struct sctp_paddrthlds val; |
---|
3903 | 3878 | struct sctp_transport *trans; |
---|
3904 | 3879 | struct sctp_association *asoc; |
---|
| 3880 | + int len; |
---|
3905 | 3881 | |
---|
3906 | | - if (optlen < sizeof(struct sctp_paddrthlds)) |
---|
| 3882 | + len = v2 ? sizeof(*val) : sizeof(struct sctp_paddrthlds); |
---|
| 3883 | + if (optlen < len) |
---|
3907 | 3884 | return -EINVAL; |
---|
3908 | | - if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, |
---|
3909 | | - sizeof(struct sctp_paddrthlds))) |
---|
3910 | | - return -EFAULT; |
---|
3911 | 3885 | |
---|
| 3886 | + if (v2 && val->spt_pathpfthld > val->spt_pathcpthld) |
---|
| 3887 | + return -EINVAL; |
---|
3912 | 3888 | |
---|
3913 | | - if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) { |
---|
3914 | | - asoc = sctp_id2assoc(sk, val.spt_assoc_id); |
---|
3915 | | - if (!asoc) |
---|
3916 | | - return -ENOENT; |
---|
3917 | | - list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
---|
3918 | | - transports) { |
---|
3919 | | - if (val.spt_pathmaxrxt) |
---|
3920 | | - trans->pathmaxrxt = val.spt_pathmaxrxt; |
---|
3921 | | - trans->pf_retrans = val.spt_pathpfthld; |
---|
3922 | | - } |
---|
3923 | | - |
---|
3924 | | - if (val.spt_pathmaxrxt) |
---|
3925 | | - asoc->pathmaxrxt = val.spt_pathmaxrxt; |
---|
3926 | | - asoc->pf_retrans = val.spt_pathpfthld; |
---|
3927 | | - } else { |
---|
3928 | | - trans = sctp_addr_id2transport(sk, &val.spt_address, |
---|
3929 | | - val.spt_assoc_id); |
---|
| 3889 | + if (!sctp_is_any(sk, (const union sctp_addr *)&val->spt_address)) { |
---|
| 3890 | + trans = sctp_addr_id2transport(sk, &val->spt_address, |
---|
| 3891 | + val->spt_assoc_id); |
---|
3930 | 3892 | if (!trans) |
---|
3931 | 3893 | return -ENOENT; |
---|
3932 | 3894 | |
---|
3933 | | - if (val.spt_pathmaxrxt) |
---|
3934 | | - trans->pathmaxrxt = val.spt_pathmaxrxt; |
---|
3935 | | - trans->pf_retrans = val.spt_pathpfthld; |
---|
| 3895 | + if (val->spt_pathmaxrxt) |
---|
| 3896 | + trans->pathmaxrxt = val->spt_pathmaxrxt; |
---|
| 3897 | + if (v2) |
---|
| 3898 | + trans->ps_retrans = val->spt_pathcpthld; |
---|
| 3899 | + trans->pf_retrans = val->spt_pathpfthld; |
---|
| 3900 | + |
---|
| 3901 | + return 0; |
---|
| 3902 | + } |
---|
| 3903 | + |
---|
| 3904 | + asoc = sctp_id2assoc(sk, val->spt_assoc_id); |
---|
| 3905 | + if (!asoc && val->spt_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 3906 | + sctp_style(sk, UDP)) |
---|
| 3907 | + return -EINVAL; |
---|
| 3908 | + |
---|
| 3909 | + if (asoc) { |
---|
| 3910 | + list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
---|
| 3911 | + transports) { |
---|
| 3912 | + if (val->spt_pathmaxrxt) |
---|
| 3913 | + trans->pathmaxrxt = val->spt_pathmaxrxt; |
---|
| 3914 | + if (v2) |
---|
| 3915 | + trans->ps_retrans = val->spt_pathcpthld; |
---|
| 3916 | + trans->pf_retrans = val->spt_pathpfthld; |
---|
| 3917 | + } |
---|
| 3918 | + |
---|
| 3919 | + if (val->spt_pathmaxrxt) |
---|
| 3920 | + asoc->pathmaxrxt = val->spt_pathmaxrxt; |
---|
| 3921 | + if (v2) |
---|
| 3922 | + asoc->ps_retrans = val->spt_pathcpthld; |
---|
| 3923 | + asoc->pf_retrans = val->spt_pathpfthld; |
---|
| 3924 | + } else { |
---|
| 3925 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 3926 | + |
---|
| 3927 | + if (val->spt_pathmaxrxt) |
---|
| 3928 | + sp->pathmaxrxt = val->spt_pathmaxrxt; |
---|
| 3929 | + if (v2) |
---|
| 3930 | + sp->ps_retrans = val->spt_pathcpthld; |
---|
| 3931 | + sp->pf_retrans = val->spt_pathpfthld; |
---|
3936 | 3932 | } |
---|
3937 | 3933 | |
---|
3938 | 3934 | return 0; |
---|
3939 | 3935 | } |
---|
3940 | 3936 | |
---|
3941 | | -static int sctp_setsockopt_recvrcvinfo(struct sock *sk, |
---|
3942 | | - char __user *optval, |
---|
| 3937 | +static int sctp_setsockopt_recvrcvinfo(struct sock *sk, int *val, |
---|
3943 | 3938 | unsigned int optlen) |
---|
3944 | 3939 | { |
---|
3945 | | - int val; |
---|
3946 | | - |
---|
3947 | 3940 | if (optlen < sizeof(int)) |
---|
3948 | 3941 | return -EINVAL; |
---|
3949 | | - if (get_user(val, (int __user *) optval)) |
---|
3950 | | - return -EFAULT; |
---|
3951 | 3942 | |
---|
3952 | | - sctp_sk(sk)->recvrcvinfo = (val == 0) ? 0 : 1; |
---|
| 3943 | + sctp_sk(sk)->recvrcvinfo = (*val == 0) ? 0 : 1; |
---|
3953 | 3944 | |
---|
3954 | 3945 | return 0; |
---|
3955 | 3946 | } |
---|
3956 | 3947 | |
---|
3957 | | -static int sctp_setsockopt_recvnxtinfo(struct sock *sk, |
---|
3958 | | - char __user *optval, |
---|
| 3948 | +static int sctp_setsockopt_recvnxtinfo(struct sock *sk, int *val, |
---|
3959 | 3949 | unsigned int optlen) |
---|
3960 | 3950 | { |
---|
3961 | | - int val; |
---|
3962 | | - |
---|
3963 | 3951 | if (optlen < sizeof(int)) |
---|
3964 | 3952 | return -EINVAL; |
---|
3965 | | - if (get_user(val, (int __user *) optval)) |
---|
3966 | | - return -EFAULT; |
---|
3967 | 3953 | |
---|
3968 | | - sctp_sk(sk)->recvnxtinfo = (val == 0) ? 0 : 1; |
---|
| 3954 | + sctp_sk(sk)->recvnxtinfo = (*val == 0) ? 0 : 1; |
---|
3969 | 3955 | |
---|
3970 | 3956 | return 0; |
---|
3971 | 3957 | } |
---|
3972 | 3958 | |
---|
3973 | 3959 | static int sctp_setsockopt_pr_supported(struct sock *sk, |
---|
3974 | | - char __user *optval, |
---|
| 3960 | + struct sctp_assoc_value *params, |
---|
3975 | 3961 | unsigned int optlen) |
---|
3976 | 3962 | { |
---|
3977 | | - struct sctp_assoc_value params; |
---|
| 3963 | + struct sctp_association *asoc; |
---|
3978 | 3964 | |
---|
3979 | | - if (optlen != sizeof(params)) |
---|
| 3965 | + if (optlen != sizeof(*params)) |
---|
3980 | 3966 | return -EINVAL; |
---|
3981 | 3967 | |
---|
3982 | | - if (copy_from_user(¶ms, optval, optlen)) |
---|
3983 | | - return -EFAULT; |
---|
| 3968 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 3969 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 3970 | + sctp_style(sk, UDP)) |
---|
| 3971 | + return -EINVAL; |
---|
3984 | 3972 | |
---|
3985 | | - sctp_sk(sk)->ep->prsctp_enable = !!params.assoc_value; |
---|
| 3973 | + sctp_sk(sk)->ep->prsctp_enable = !!params->assoc_value; |
---|
3986 | 3974 | |
---|
3987 | 3975 | return 0; |
---|
3988 | 3976 | } |
---|
3989 | 3977 | |
---|
3990 | 3978 | static int sctp_setsockopt_default_prinfo(struct sock *sk, |
---|
3991 | | - char __user *optval, |
---|
| 3979 | + struct sctp_default_prinfo *info, |
---|
3992 | 3980 | unsigned int optlen) |
---|
3993 | 3981 | { |
---|
3994 | | - struct sctp_default_prinfo info; |
---|
| 3982 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
3995 | 3983 | struct sctp_association *asoc; |
---|
3996 | 3984 | int retval = -EINVAL; |
---|
3997 | 3985 | |
---|
3998 | | - if (optlen != sizeof(info)) |
---|
| 3986 | + if (optlen != sizeof(*info)) |
---|
3999 | 3987 | goto out; |
---|
4000 | 3988 | |
---|
4001 | | - if (copy_from_user(&info, optval, sizeof(info))) { |
---|
4002 | | - retval = -EFAULT; |
---|
4003 | | - goto out; |
---|
4004 | | - } |
---|
4005 | | - |
---|
4006 | | - if (info.pr_policy & ~SCTP_PR_SCTP_MASK) |
---|
| 3989 | + if (info->pr_policy & ~SCTP_PR_SCTP_MASK) |
---|
4007 | 3990 | goto out; |
---|
4008 | 3991 | |
---|
4009 | | - if (info.pr_policy == SCTP_PR_SCTP_NONE) |
---|
4010 | | - info.pr_value = 0; |
---|
| 3992 | + if (info->pr_policy == SCTP_PR_SCTP_NONE) |
---|
| 3993 | + info->pr_value = 0; |
---|
4011 | 3994 | |
---|
4012 | | - asoc = sctp_id2assoc(sk, info.pr_assoc_id); |
---|
4013 | | - if (asoc) { |
---|
4014 | | - SCTP_PR_SET_POLICY(asoc->default_flags, info.pr_policy); |
---|
4015 | | - asoc->default_timetolive = info.pr_value; |
---|
4016 | | - } else if (!info.pr_assoc_id) { |
---|
4017 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
4018 | | - |
---|
4019 | | - SCTP_PR_SET_POLICY(sp->default_flags, info.pr_policy); |
---|
4020 | | - sp->default_timetolive = info.pr_value; |
---|
4021 | | - } else { |
---|
| 3995 | + asoc = sctp_id2assoc(sk, info->pr_assoc_id); |
---|
| 3996 | + if (!asoc && info->pr_assoc_id > SCTP_ALL_ASSOC && |
---|
| 3997 | + sctp_style(sk, UDP)) |
---|
4022 | 3998 | goto out; |
---|
4023 | | - } |
---|
4024 | 3999 | |
---|
4025 | 4000 | retval = 0; |
---|
| 4001 | + |
---|
| 4002 | + if (asoc) { |
---|
| 4003 | + SCTP_PR_SET_POLICY(asoc->default_flags, info->pr_policy); |
---|
| 4004 | + asoc->default_timetolive = info->pr_value; |
---|
| 4005 | + goto out; |
---|
| 4006 | + } |
---|
| 4007 | + |
---|
| 4008 | + if (sctp_style(sk, TCP)) |
---|
| 4009 | + info->pr_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 4010 | + |
---|
| 4011 | + if (info->pr_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 4012 | + info->pr_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 4013 | + SCTP_PR_SET_POLICY(sp->default_flags, info->pr_policy); |
---|
| 4014 | + sp->default_timetolive = info->pr_value; |
---|
| 4015 | + } |
---|
| 4016 | + |
---|
| 4017 | + if (info->pr_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 4018 | + info->pr_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 4019 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) { |
---|
| 4020 | + SCTP_PR_SET_POLICY(asoc->default_flags, |
---|
| 4021 | + info->pr_policy); |
---|
| 4022 | + asoc->default_timetolive = info->pr_value; |
---|
| 4023 | + } |
---|
| 4024 | + } |
---|
4026 | 4025 | |
---|
4027 | 4026 | out: |
---|
4028 | 4027 | return retval; |
---|
4029 | 4028 | } |
---|
4030 | 4029 | |
---|
4031 | 4030 | static int sctp_setsockopt_reconfig_supported(struct sock *sk, |
---|
4032 | | - char __user *optval, |
---|
| 4031 | + struct sctp_assoc_value *params, |
---|
4033 | 4032 | unsigned int optlen) |
---|
4034 | 4033 | { |
---|
4035 | | - struct sctp_assoc_value params; |
---|
4036 | 4034 | struct sctp_association *asoc; |
---|
4037 | 4035 | int retval = -EINVAL; |
---|
4038 | 4036 | |
---|
4039 | | - if (optlen != sizeof(params)) |
---|
| 4037 | + if (optlen != sizeof(*params)) |
---|
4040 | 4038 | goto out; |
---|
4041 | 4039 | |
---|
4042 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4043 | | - retval = -EFAULT; |
---|
| 4040 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4041 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 4042 | + sctp_style(sk, UDP)) |
---|
4044 | 4043 | goto out; |
---|
4045 | | - } |
---|
4046 | 4044 | |
---|
4047 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
4048 | | - if (asoc) { |
---|
4049 | | - asoc->reconf_enable = !!params.assoc_value; |
---|
4050 | | - } else if (!params.assoc_id) { |
---|
4051 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
4052 | | - |
---|
4053 | | - sp->ep->reconf_enable = !!params.assoc_value; |
---|
4054 | | - } else { |
---|
4055 | | - goto out; |
---|
4056 | | - } |
---|
| 4045 | + sctp_sk(sk)->ep->reconf_enable = !!params->assoc_value; |
---|
4057 | 4046 | |
---|
4058 | 4047 | retval = 0; |
---|
4059 | 4048 | |
---|
.. | .. |
---|
4062 | 4051 | } |
---|
4063 | 4052 | |
---|
4064 | 4053 | static int sctp_setsockopt_enable_strreset(struct sock *sk, |
---|
4065 | | - char __user *optval, |
---|
| 4054 | + struct sctp_assoc_value *params, |
---|
4066 | 4055 | unsigned int optlen) |
---|
4067 | 4056 | { |
---|
4068 | | - struct sctp_assoc_value params; |
---|
| 4057 | + struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
4069 | 4058 | struct sctp_association *asoc; |
---|
4070 | 4059 | int retval = -EINVAL; |
---|
4071 | 4060 | |
---|
4072 | | - if (optlen != sizeof(params)) |
---|
| 4061 | + if (optlen != sizeof(*params)) |
---|
4073 | 4062 | goto out; |
---|
4074 | 4063 | |
---|
4075 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4076 | | - retval = -EFAULT; |
---|
4077 | | - goto out; |
---|
4078 | | - } |
---|
4079 | | - |
---|
4080 | | - if (params.assoc_value & (~SCTP_ENABLE_STRRESET_MASK)) |
---|
| 4064 | + if (params->assoc_value & (~SCTP_ENABLE_STRRESET_MASK)) |
---|
4081 | 4065 | goto out; |
---|
4082 | 4066 | |
---|
4083 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
4084 | | - if (asoc) { |
---|
4085 | | - asoc->strreset_enable = params.assoc_value; |
---|
4086 | | - } else if (!params.assoc_id) { |
---|
4087 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
4088 | | - |
---|
4089 | | - sp->ep->strreset_enable = params.assoc_value; |
---|
4090 | | - } else { |
---|
| 4067 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4068 | + if (!asoc && params->assoc_id > SCTP_ALL_ASSOC && |
---|
| 4069 | + sctp_style(sk, UDP)) |
---|
4091 | 4070 | goto out; |
---|
4092 | | - } |
---|
4093 | 4071 | |
---|
4094 | 4072 | retval = 0; |
---|
| 4073 | + |
---|
| 4074 | + if (asoc) { |
---|
| 4075 | + asoc->strreset_enable = params->assoc_value; |
---|
| 4076 | + goto out; |
---|
| 4077 | + } |
---|
| 4078 | + |
---|
| 4079 | + if (sctp_style(sk, TCP)) |
---|
| 4080 | + params->assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 4081 | + |
---|
| 4082 | + if (params->assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 4083 | + params->assoc_id == SCTP_ALL_ASSOC) |
---|
| 4084 | + ep->strreset_enable = params->assoc_value; |
---|
| 4085 | + |
---|
| 4086 | + if (params->assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 4087 | + params->assoc_id == SCTP_ALL_ASSOC) |
---|
| 4088 | + list_for_each_entry(asoc, &ep->asocs, asocs) |
---|
| 4089 | + asoc->strreset_enable = params->assoc_value; |
---|
4095 | 4090 | |
---|
4096 | 4091 | out: |
---|
4097 | 4092 | return retval; |
---|
4098 | 4093 | } |
---|
4099 | 4094 | |
---|
4100 | 4095 | static int sctp_setsockopt_reset_streams(struct sock *sk, |
---|
4101 | | - char __user *optval, |
---|
| 4096 | + struct sctp_reset_streams *params, |
---|
4102 | 4097 | unsigned int optlen) |
---|
4103 | 4098 | { |
---|
4104 | | - struct sctp_reset_streams *params; |
---|
4105 | 4099 | struct sctp_association *asoc; |
---|
4106 | | - int retval = -EINVAL; |
---|
4107 | 4100 | |
---|
4108 | 4101 | if (optlen < sizeof(*params)) |
---|
4109 | 4102 | return -EINVAL; |
---|
.. | .. |
---|
4111 | 4104 | optlen = min_t(unsigned int, optlen, USHRT_MAX + |
---|
4112 | 4105 | sizeof(__u16) * sizeof(*params)); |
---|
4113 | 4106 | |
---|
4114 | | - params = memdup_user(optval, optlen); |
---|
4115 | | - if (IS_ERR(params)) |
---|
4116 | | - return PTR_ERR(params); |
---|
4117 | | - |
---|
4118 | 4107 | if (params->srs_number_streams * sizeof(__u16) > |
---|
4119 | 4108 | optlen - sizeof(*params)) |
---|
4120 | | - goto out; |
---|
| 4109 | + return -EINVAL; |
---|
4121 | 4110 | |
---|
4122 | 4111 | asoc = sctp_id2assoc(sk, params->srs_assoc_id); |
---|
4123 | 4112 | if (!asoc) |
---|
4124 | | - goto out; |
---|
| 4113 | + return -EINVAL; |
---|
4125 | 4114 | |
---|
4126 | | - retval = sctp_send_reset_streams(asoc, params); |
---|
4127 | | - |
---|
4128 | | -out: |
---|
4129 | | - kfree(params); |
---|
4130 | | - return retval; |
---|
| 4115 | + return sctp_send_reset_streams(asoc, params); |
---|
4131 | 4116 | } |
---|
4132 | 4117 | |
---|
4133 | | -static int sctp_setsockopt_reset_assoc(struct sock *sk, |
---|
4134 | | - char __user *optval, |
---|
| 4118 | +static int sctp_setsockopt_reset_assoc(struct sock *sk, sctp_assoc_t *associd, |
---|
4135 | 4119 | unsigned int optlen) |
---|
4136 | 4120 | { |
---|
4137 | 4121 | struct sctp_association *asoc; |
---|
4138 | | - sctp_assoc_t associd; |
---|
4139 | | - int retval = -EINVAL; |
---|
4140 | 4122 | |
---|
4141 | | - if (optlen != sizeof(associd)) |
---|
4142 | | - goto out; |
---|
| 4123 | + if (optlen != sizeof(*associd)) |
---|
| 4124 | + return -EINVAL; |
---|
4143 | 4125 | |
---|
4144 | | - if (copy_from_user(&associd, optval, optlen)) { |
---|
4145 | | - retval = -EFAULT; |
---|
4146 | | - goto out; |
---|
4147 | | - } |
---|
4148 | | - |
---|
4149 | | - asoc = sctp_id2assoc(sk, associd); |
---|
| 4126 | + asoc = sctp_id2assoc(sk, *associd); |
---|
4150 | 4127 | if (!asoc) |
---|
4151 | | - goto out; |
---|
| 4128 | + return -EINVAL; |
---|
4152 | 4129 | |
---|
4153 | | - retval = sctp_send_reset_assoc(asoc); |
---|
4154 | | - |
---|
4155 | | -out: |
---|
4156 | | - return retval; |
---|
| 4130 | + return sctp_send_reset_assoc(asoc); |
---|
4157 | 4131 | } |
---|
4158 | 4132 | |
---|
4159 | 4133 | static int sctp_setsockopt_add_streams(struct sock *sk, |
---|
4160 | | - char __user *optval, |
---|
| 4134 | + struct sctp_add_streams *params, |
---|
4161 | 4135 | unsigned int optlen) |
---|
4162 | 4136 | { |
---|
4163 | 4137 | struct sctp_association *asoc; |
---|
4164 | | - struct sctp_add_streams params; |
---|
4165 | | - int retval = -EINVAL; |
---|
4166 | 4138 | |
---|
4167 | | - if (optlen != sizeof(params)) |
---|
4168 | | - goto out; |
---|
| 4139 | + if (optlen != sizeof(*params)) |
---|
| 4140 | + return -EINVAL; |
---|
4169 | 4141 | |
---|
4170 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4171 | | - retval = -EFAULT; |
---|
4172 | | - goto out; |
---|
4173 | | - } |
---|
4174 | | - |
---|
4175 | | - asoc = sctp_id2assoc(sk, params.sas_assoc_id); |
---|
| 4142 | + asoc = sctp_id2assoc(sk, params->sas_assoc_id); |
---|
4176 | 4143 | if (!asoc) |
---|
4177 | | - goto out; |
---|
| 4144 | + return -EINVAL; |
---|
4178 | 4145 | |
---|
4179 | | - retval = sctp_send_add_streams(asoc, ¶ms); |
---|
4180 | | - |
---|
4181 | | -out: |
---|
4182 | | - return retval; |
---|
| 4146 | + return sctp_send_add_streams(asoc, params); |
---|
4183 | 4147 | } |
---|
4184 | 4148 | |
---|
4185 | 4149 | static int sctp_setsockopt_scheduler(struct sock *sk, |
---|
4186 | | - char __user *optval, |
---|
| 4150 | + struct sctp_assoc_value *params, |
---|
4187 | 4151 | unsigned int optlen) |
---|
4188 | 4152 | { |
---|
| 4153 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
4189 | 4154 | struct sctp_association *asoc; |
---|
4190 | | - struct sctp_assoc_value params; |
---|
4191 | | - int retval = -EINVAL; |
---|
| 4155 | + int retval = 0; |
---|
4192 | 4156 | |
---|
4193 | | - if (optlen < sizeof(params)) |
---|
4194 | | - goto out; |
---|
| 4157 | + if (optlen < sizeof(*params)) |
---|
| 4158 | + return -EINVAL; |
---|
4195 | 4159 | |
---|
4196 | | - optlen = sizeof(params); |
---|
4197 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4198 | | - retval = -EFAULT; |
---|
4199 | | - goto out; |
---|
| 4160 | + if (params->assoc_value > SCTP_SS_MAX) |
---|
| 4161 | + return -EINVAL; |
---|
| 4162 | + |
---|
| 4163 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4164 | + if (!asoc && params->assoc_id > SCTP_ALL_ASSOC && |
---|
| 4165 | + sctp_style(sk, UDP)) |
---|
| 4166 | + return -EINVAL; |
---|
| 4167 | + |
---|
| 4168 | + if (asoc) |
---|
| 4169 | + return sctp_sched_set_sched(asoc, params->assoc_value); |
---|
| 4170 | + |
---|
| 4171 | + if (sctp_style(sk, TCP)) |
---|
| 4172 | + params->assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 4173 | + |
---|
| 4174 | + if (params->assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 4175 | + params->assoc_id == SCTP_ALL_ASSOC) |
---|
| 4176 | + sp->default_ss = params->assoc_value; |
---|
| 4177 | + |
---|
| 4178 | + if (params->assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 4179 | + params->assoc_id == SCTP_ALL_ASSOC) { |
---|
| 4180 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) { |
---|
| 4181 | + int ret = sctp_sched_set_sched(asoc, |
---|
| 4182 | + params->assoc_value); |
---|
| 4183 | + |
---|
| 4184 | + if (ret && !retval) |
---|
| 4185 | + retval = ret; |
---|
| 4186 | + } |
---|
4200 | 4187 | } |
---|
4201 | 4188 | |
---|
4202 | | - if (params.assoc_value > SCTP_SS_MAX) |
---|
4203 | | - goto out; |
---|
4204 | | - |
---|
4205 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
4206 | | - if (!asoc) |
---|
4207 | | - goto out; |
---|
4208 | | - |
---|
4209 | | - retval = sctp_sched_set_sched(asoc, params.assoc_value); |
---|
4210 | | - |
---|
4211 | | -out: |
---|
4212 | 4189 | return retval; |
---|
4213 | 4190 | } |
---|
4214 | 4191 | |
---|
4215 | 4192 | static int sctp_setsockopt_scheduler_value(struct sock *sk, |
---|
4216 | | - char __user *optval, |
---|
| 4193 | + struct sctp_stream_value *params, |
---|
4217 | 4194 | unsigned int optlen) |
---|
4218 | 4195 | { |
---|
4219 | 4196 | struct sctp_association *asoc; |
---|
4220 | | - struct sctp_stream_value params; |
---|
4221 | 4197 | int retval = -EINVAL; |
---|
4222 | 4198 | |
---|
4223 | | - if (optlen < sizeof(params)) |
---|
| 4199 | + if (optlen < sizeof(*params)) |
---|
4224 | 4200 | goto out; |
---|
4225 | 4201 | |
---|
4226 | | - optlen = sizeof(params); |
---|
4227 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4228 | | - retval = -EFAULT; |
---|
| 4202 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4203 | + if (!asoc && params->assoc_id != SCTP_CURRENT_ASSOC && |
---|
| 4204 | + sctp_style(sk, UDP)) |
---|
| 4205 | + goto out; |
---|
| 4206 | + |
---|
| 4207 | + if (asoc) { |
---|
| 4208 | + retval = sctp_sched_set_value(asoc, params->stream_id, |
---|
| 4209 | + params->stream_value, GFP_KERNEL); |
---|
4229 | 4210 | goto out; |
---|
4230 | 4211 | } |
---|
4231 | 4212 | |
---|
4232 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
4233 | | - if (!asoc) |
---|
4234 | | - goto out; |
---|
| 4213 | + retval = 0; |
---|
4235 | 4214 | |
---|
4236 | | - retval = sctp_sched_set_value(asoc, params.stream_id, |
---|
4237 | | - params.stream_value, GFP_KERNEL); |
---|
| 4215 | + list_for_each_entry(asoc, &sctp_sk(sk)->ep->asocs, asocs) { |
---|
| 4216 | + int ret = sctp_sched_set_value(asoc, params->stream_id, |
---|
| 4217 | + params->stream_value, |
---|
| 4218 | + GFP_KERNEL); |
---|
| 4219 | + if (ret && !retval) /* try to return the 1st error. */ |
---|
| 4220 | + retval = ret; |
---|
| 4221 | + } |
---|
4238 | 4222 | |
---|
4239 | 4223 | out: |
---|
4240 | 4224 | return retval; |
---|
4241 | 4225 | } |
---|
4242 | 4226 | |
---|
4243 | 4227 | static int sctp_setsockopt_interleaving_supported(struct sock *sk, |
---|
4244 | | - char __user *optval, |
---|
| 4228 | + struct sctp_assoc_value *p, |
---|
4245 | 4229 | unsigned int optlen) |
---|
4246 | 4230 | { |
---|
4247 | 4231 | struct sctp_sock *sp = sctp_sk(sk); |
---|
4248 | | - struct net *net = sock_net(sk); |
---|
4249 | | - struct sctp_assoc_value params; |
---|
4250 | | - int retval = -EINVAL; |
---|
| 4232 | + struct sctp_association *asoc; |
---|
4251 | 4233 | |
---|
4252 | | - if (optlen < sizeof(params)) |
---|
4253 | | - goto out; |
---|
| 4234 | + if (optlen < sizeof(*p)) |
---|
| 4235 | + return -EINVAL; |
---|
4254 | 4236 | |
---|
4255 | | - optlen = sizeof(params); |
---|
4256 | | - if (copy_from_user(¶ms, optval, optlen)) { |
---|
4257 | | - retval = -EFAULT; |
---|
4258 | | - goto out; |
---|
| 4237 | + asoc = sctp_id2assoc(sk, p->assoc_id); |
---|
| 4238 | + if (!asoc && p->assoc_id != SCTP_FUTURE_ASSOC && sctp_style(sk, UDP)) |
---|
| 4239 | + return -EINVAL; |
---|
| 4240 | + |
---|
| 4241 | + if (!sock_net(sk)->sctp.intl_enable || !sp->frag_interleave) { |
---|
| 4242 | + return -EPERM; |
---|
4259 | 4243 | } |
---|
4260 | 4244 | |
---|
4261 | | - if (params.assoc_id) |
---|
4262 | | - goto out; |
---|
4263 | | - |
---|
4264 | | - if (!net->sctp.intl_enable || !sp->frag_interleave) { |
---|
4265 | | - retval = -EPERM; |
---|
4266 | | - goto out; |
---|
4267 | | - } |
---|
4268 | | - |
---|
4269 | | - sp->strm_interleave = !!params.assoc_value; |
---|
4270 | | - |
---|
4271 | | - retval = 0; |
---|
4272 | | - |
---|
4273 | | -out: |
---|
4274 | | - return retval; |
---|
| 4245 | + sp->ep->intl_enable = !!p->assoc_value; |
---|
| 4246 | + return 0; |
---|
4275 | 4247 | } |
---|
4276 | 4248 | |
---|
4277 | | -static int sctp_setsockopt_reuse_port(struct sock *sk, char __user *optval, |
---|
| 4249 | +static int sctp_setsockopt_reuse_port(struct sock *sk, int *val, |
---|
4278 | 4250 | unsigned int optlen) |
---|
4279 | 4251 | { |
---|
4280 | | - int val; |
---|
4281 | | - |
---|
4282 | 4252 | if (!sctp_style(sk, TCP)) |
---|
4283 | 4253 | return -EOPNOTSUPP; |
---|
4284 | 4254 | |
---|
.. | .. |
---|
4288 | 4258 | if (optlen < sizeof(int)) |
---|
4289 | 4259 | return -EINVAL; |
---|
4290 | 4260 | |
---|
4291 | | - if (get_user(val, (int __user *)optval)) |
---|
4292 | | - return -EFAULT; |
---|
4293 | | - |
---|
4294 | | - sctp_sk(sk)->reuse = !!val; |
---|
| 4261 | + sctp_sk(sk)->reuse = !!*val; |
---|
4295 | 4262 | |
---|
4296 | 4263 | return 0; |
---|
| 4264 | +} |
---|
| 4265 | + |
---|
| 4266 | +static int sctp_assoc_ulpevent_type_set(struct sctp_event *param, |
---|
| 4267 | + struct sctp_association *asoc) |
---|
| 4268 | +{ |
---|
| 4269 | + struct sctp_ulpevent *event; |
---|
| 4270 | + |
---|
| 4271 | + sctp_ulpevent_type_set(&asoc->subscribe, param->se_type, param->se_on); |
---|
| 4272 | + |
---|
| 4273 | + if (param->se_type == SCTP_SENDER_DRY_EVENT && param->se_on) { |
---|
| 4274 | + if (sctp_outq_is_empty(&asoc->outqueue)) { |
---|
| 4275 | + event = sctp_ulpevent_make_sender_dry_event(asoc, |
---|
| 4276 | + GFP_USER | __GFP_NOWARN); |
---|
| 4277 | + if (!event) |
---|
| 4278 | + return -ENOMEM; |
---|
| 4279 | + |
---|
| 4280 | + asoc->stream.si->enqueue_event(&asoc->ulpq, event); |
---|
| 4281 | + } |
---|
| 4282 | + } |
---|
| 4283 | + |
---|
| 4284 | + return 0; |
---|
| 4285 | +} |
---|
| 4286 | + |
---|
| 4287 | +static int sctp_setsockopt_event(struct sock *sk, struct sctp_event *param, |
---|
| 4288 | + unsigned int optlen) |
---|
| 4289 | +{ |
---|
| 4290 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 4291 | + struct sctp_association *asoc; |
---|
| 4292 | + int retval = 0; |
---|
| 4293 | + |
---|
| 4294 | + if (optlen < sizeof(*param)) |
---|
| 4295 | + return -EINVAL; |
---|
| 4296 | + |
---|
| 4297 | + if (param->se_type < SCTP_SN_TYPE_BASE || |
---|
| 4298 | + param->se_type > SCTP_SN_TYPE_MAX) |
---|
| 4299 | + return -EINVAL; |
---|
| 4300 | + |
---|
| 4301 | + asoc = sctp_id2assoc(sk, param->se_assoc_id); |
---|
| 4302 | + if (!asoc && param->se_assoc_id > SCTP_ALL_ASSOC && |
---|
| 4303 | + sctp_style(sk, UDP)) |
---|
| 4304 | + return -EINVAL; |
---|
| 4305 | + |
---|
| 4306 | + if (asoc) |
---|
| 4307 | + return sctp_assoc_ulpevent_type_set(param, asoc); |
---|
| 4308 | + |
---|
| 4309 | + if (sctp_style(sk, TCP)) |
---|
| 4310 | + param->se_assoc_id = SCTP_FUTURE_ASSOC; |
---|
| 4311 | + |
---|
| 4312 | + if (param->se_assoc_id == SCTP_FUTURE_ASSOC || |
---|
| 4313 | + param->se_assoc_id == SCTP_ALL_ASSOC) |
---|
| 4314 | + sctp_ulpevent_type_set(&sp->subscribe, |
---|
| 4315 | + param->se_type, param->se_on); |
---|
| 4316 | + |
---|
| 4317 | + if (param->se_assoc_id == SCTP_CURRENT_ASSOC || |
---|
| 4318 | + param->se_assoc_id == SCTP_ALL_ASSOC) { |
---|
| 4319 | + list_for_each_entry(asoc, &sp->ep->asocs, asocs) { |
---|
| 4320 | + int ret = sctp_assoc_ulpevent_type_set(param, asoc); |
---|
| 4321 | + |
---|
| 4322 | + if (ret && !retval) |
---|
| 4323 | + retval = ret; |
---|
| 4324 | + } |
---|
| 4325 | + } |
---|
| 4326 | + |
---|
| 4327 | + return retval; |
---|
| 4328 | +} |
---|
| 4329 | + |
---|
| 4330 | +static int sctp_setsockopt_asconf_supported(struct sock *sk, |
---|
| 4331 | + struct sctp_assoc_value *params, |
---|
| 4332 | + unsigned int optlen) |
---|
| 4333 | +{ |
---|
| 4334 | + struct sctp_association *asoc; |
---|
| 4335 | + struct sctp_endpoint *ep; |
---|
| 4336 | + int retval = -EINVAL; |
---|
| 4337 | + |
---|
| 4338 | + if (optlen != sizeof(*params)) |
---|
| 4339 | + goto out; |
---|
| 4340 | + |
---|
| 4341 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4342 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 4343 | + sctp_style(sk, UDP)) |
---|
| 4344 | + goto out; |
---|
| 4345 | + |
---|
| 4346 | + ep = sctp_sk(sk)->ep; |
---|
| 4347 | + ep->asconf_enable = !!params->assoc_value; |
---|
| 4348 | + |
---|
| 4349 | + if (ep->asconf_enable && ep->auth_enable) { |
---|
| 4350 | + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF); |
---|
| 4351 | + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK); |
---|
| 4352 | + } |
---|
| 4353 | + |
---|
| 4354 | + retval = 0; |
---|
| 4355 | + |
---|
| 4356 | +out: |
---|
| 4357 | + return retval; |
---|
| 4358 | +} |
---|
| 4359 | + |
---|
| 4360 | +static int sctp_setsockopt_auth_supported(struct sock *sk, |
---|
| 4361 | + struct sctp_assoc_value *params, |
---|
| 4362 | + unsigned int optlen) |
---|
| 4363 | +{ |
---|
| 4364 | + struct sctp_association *asoc; |
---|
| 4365 | + struct sctp_endpoint *ep; |
---|
| 4366 | + int retval = -EINVAL; |
---|
| 4367 | + |
---|
| 4368 | + if (optlen != sizeof(*params)) |
---|
| 4369 | + goto out; |
---|
| 4370 | + |
---|
| 4371 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4372 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 4373 | + sctp_style(sk, UDP)) |
---|
| 4374 | + goto out; |
---|
| 4375 | + |
---|
| 4376 | + ep = sctp_sk(sk)->ep; |
---|
| 4377 | + if (params->assoc_value) { |
---|
| 4378 | + retval = sctp_auth_init(ep, GFP_KERNEL); |
---|
| 4379 | + if (retval) |
---|
| 4380 | + goto out; |
---|
| 4381 | + if (ep->asconf_enable) { |
---|
| 4382 | + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF); |
---|
| 4383 | + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK); |
---|
| 4384 | + } |
---|
| 4385 | + } |
---|
| 4386 | + |
---|
| 4387 | + ep->auth_enable = !!params->assoc_value; |
---|
| 4388 | + retval = 0; |
---|
| 4389 | + |
---|
| 4390 | +out: |
---|
| 4391 | + return retval; |
---|
| 4392 | +} |
---|
| 4393 | + |
---|
| 4394 | +static int sctp_setsockopt_ecn_supported(struct sock *sk, |
---|
| 4395 | + struct sctp_assoc_value *params, |
---|
| 4396 | + unsigned int optlen) |
---|
| 4397 | +{ |
---|
| 4398 | + struct sctp_association *asoc; |
---|
| 4399 | + int retval = -EINVAL; |
---|
| 4400 | + |
---|
| 4401 | + if (optlen != sizeof(*params)) |
---|
| 4402 | + goto out; |
---|
| 4403 | + |
---|
| 4404 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4405 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 4406 | + sctp_style(sk, UDP)) |
---|
| 4407 | + goto out; |
---|
| 4408 | + |
---|
| 4409 | + sctp_sk(sk)->ep->ecn_enable = !!params->assoc_value; |
---|
| 4410 | + retval = 0; |
---|
| 4411 | + |
---|
| 4412 | +out: |
---|
| 4413 | + return retval; |
---|
| 4414 | +} |
---|
| 4415 | + |
---|
| 4416 | +static int sctp_setsockopt_pf_expose(struct sock *sk, |
---|
| 4417 | + struct sctp_assoc_value *params, |
---|
| 4418 | + unsigned int optlen) |
---|
| 4419 | +{ |
---|
| 4420 | + struct sctp_association *asoc; |
---|
| 4421 | + int retval = -EINVAL; |
---|
| 4422 | + |
---|
| 4423 | + if (optlen != sizeof(*params)) |
---|
| 4424 | + goto out; |
---|
| 4425 | + |
---|
| 4426 | + if (params->assoc_value > SCTP_PF_EXPOSE_MAX) |
---|
| 4427 | + goto out; |
---|
| 4428 | + |
---|
| 4429 | + asoc = sctp_id2assoc(sk, params->assoc_id); |
---|
| 4430 | + if (!asoc && params->assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 4431 | + sctp_style(sk, UDP)) |
---|
| 4432 | + goto out; |
---|
| 4433 | + |
---|
| 4434 | + if (asoc) |
---|
| 4435 | + asoc->pf_expose = params->assoc_value; |
---|
| 4436 | + else |
---|
| 4437 | + sctp_sk(sk)->pf_expose = params->assoc_value; |
---|
| 4438 | + retval = 0; |
---|
| 4439 | + |
---|
| 4440 | +out: |
---|
| 4441 | + return retval; |
---|
4297 | 4442 | } |
---|
4298 | 4443 | |
---|
4299 | 4444 | /* API 6.2 setsockopt(), getsockopt() |
---|
.. | .. |
---|
4316 | 4461 | * optlen - the size of the buffer. |
---|
4317 | 4462 | */ |
---|
4318 | 4463 | static int sctp_setsockopt(struct sock *sk, int level, int optname, |
---|
4319 | | - char __user *optval, unsigned int optlen) |
---|
| 4464 | + sockptr_t optval, unsigned int optlen) |
---|
4320 | 4465 | { |
---|
| 4466 | + void *kopt = NULL; |
---|
4321 | 4467 | int retval = 0; |
---|
4322 | 4468 | |
---|
4323 | 4469 | pr_debug("%s: sk:%p, optname:%d\n", __func__, sk, optname); |
---|
.. | .. |
---|
4330 | 4476 | */ |
---|
4331 | 4477 | if (level != SOL_SCTP) { |
---|
4332 | 4478 | struct sctp_af *af = sctp_sk(sk)->pf->af; |
---|
4333 | | - retval = af->setsockopt(sk, level, optname, optval, optlen); |
---|
4334 | | - goto out_nounlock; |
---|
| 4479 | + |
---|
| 4480 | + return af->setsockopt(sk, level, optname, optval, optlen); |
---|
| 4481 | + } |
---|
| 4482 | + |
---|
| 4483 | + if (optlen > 0) { |
---|
| 4484 | + /* Trim it to the biggest size sctp sockopt may need if necessary */ |
---|
| 4485 | + optlen = min_t(unsigned int, optlen, |
---|
| 4486 | + PAGE_ALIGN(USHRT_MAX + |
---|
| 4487 | + sizeof(__u16) * sizeof(struct sctp_reset_streams))); |
---|
| 4488 | + kopt = memdup_sockptr(optval, optlen); |
---|
| 4489 | + if (IS_ERR(kopt)) |
---|
| 4490 | + return PTR_ERR(kopt); |
---|
4335 | 4491 | } |
---|
4336 | 4492 | |
---|
4337 | 4493 | lock_sock(sk); |
---|
.. | .. |
---|
4339 | 4495 | switch (optname) { |
---|
4340 | 4496 | case SCTP_SOCKOPT_BINDX_ADD: |
---|
4341 | 4497 | /* 'optlen' is the size of the addresses buffer. */ |
---|
4342 | | - retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval, |
---|
4343 | | - optlen, SCTP_BINDX_ADD_ADDR); |
---|
| 4498 | + retval = sctp_setsockopt_bindx(sk, kopt, optlen, |
---|
| 4499 | + SCTP_BINDX_ADD_ADDR); |
---|
4344 | 4500 | break; |
---|
4345 | 4501 | |
---|
4346 | 4502 | case SCTP_SOCKOPT_BINDX_REM: |
---|
4347 | 4503 | /* 'optlen' is the size of the addresses buffer. */ |
---|
4348 | | - retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval, |
---|
4349 | | - optlen, SCTP_BINDX_REM_ADDR); |
---|
| 4504 | + retval = sctp_setsockopt_bindx(sk, kopt, optlen, |
---|
| 4505 | + SCTP_BINDX_REM_ADDR); |
---|
4350 | 4506 | break; |
---|
4351 | 4507 | |
---|
4352 | 4508 | case SCTP_SOCKOPT_CONNECTX_OLD: |
---|
4353 | 4509 | /* 'optlen' is the size of the addresses buffer. */ |
---|
4354 | | - retval = sctp_setsockopt_connectx_old(sk, |
---|
4355 | | - (struct sockaddr __user *)optval, |
---|
4356 | | - optlen); |
---|
| 4510 | + retval = sctp_setsockopt_connectx_old(sk, kopt, optlen); |
---|
4357 | 4511 | break; |
---|
4358 | 4512 | |
---|
4359 | 4513 | case SCTP_SOCKOPT_CONNECTX: |
---|
4360 | 4514 | /* 'optlen' is the size of the addresses buffer. */ |
---|
4361 | | - retval = sctp_setsockopt_connectx(sk, |
---|
4362 | | - (struct sockaddr __user *)optval, |
---|
4363 | | - optlen); |
---|
| 4515 | + retval = sctp_setsockopt_connectx(sk, kopt, optlen); |
---|
4364 | 4516 | break; |
---|
4365 | 4517 | |
---|
4366 | 4518 | case SCTP_DISABLE_FRAGMENTS: |
---|
4367 | | - retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
---|
| 4519 | + retval = sctp_setsockopt_disable_fragments(sk, kopt, optlen); |
---|
4368 | 4520 | break; |
---|
4369 | 4521 | |
---|
4370 | 4522 | case SCTP_EVENTS: |
---|
4371 | | - retval = sctp_setsockopt_events(sk, optval, optlen); |
---|
| 4523 | + retval = sctp_setsockopt_events(sk, kopt, optlen); |
---|
4372 | 4524 | break; |
---|
4373 | 4525 | |
---|
4374 | 4526 | case SCTP_AUTOCLOSE: |
---|
4375 | | - retval = sctp_setsockopt_autoclose(sk, optval, optlen); |
---|
| 4527 | + retval = sctp_setsockopt_autoclose(sk, kopt, optlen); |
---|
4376 | 4528 | break; |
---|
4377 | 4529 | |
---|
4378 | 4530 | case SCTP_PEER_ADDR_PARAMS: |
---|
4379 | | - retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); |
---|
| 4531 | + retval = sctp_setsockopt_peer_addr_params(sk, kopt, optlen); |
---|
4380 | 4532 | break; |
---|
4381 | 4533 | |
---|
4382 | 4534 | case SCTP_DELAYED_SACK: |
---|
4383 | | - retval = sctp_setsockopt_delayed_ack(sk, optval, optlen); |
---|
| 4535 | + retval = sctp_setsockopt_delayed_ack(sk, kopt, optlen); |
---|
4384 | 4536 | break; |
---|
4385 | 4537 | case SCTP_PARTIAL_DELIVERY_POINT: |
---|
4386 | | - retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); |
---|
| 4538 | + retval = sctp_setsockopt_partial_delivery_point(sk, kopt, optlen); |
---|
4387 | 4539 | break; |
---|
4388 | 4540 | |
---|
4389 | 4541 | case SCTP_INITMSG: |
---|
4390 | | - retval = sctp_setsockopt_initmsg(sk, optval, optlen); |
---|
| 4542 | + retval = sctp_setsockopt_initmsg(sk, kopt, optlen); |
---|
4391 | 4543 | break; |
---|
4392 | 4544 | case SCTP_DEFAULT_SEND_PARAM: |
---|
4393 | | - retval = sctp_setsockopt_default_send_param(sk, optval, |
---|
4394 | | - optlen); |
---|
| 4545 | + retval = sctp_setsockopt_default_send_param(sk, kopt, optlen); |
---|
4395 | 4546 | break; |
---|
4396 | 4547 | case SCTP_DEFAULT_SNDINFO: |
---|
4397 | | - retval = sctp_setsockopt_default_sndinfo(sk, optval, optlen); |
---|
| 4548 | + retval = sctp_setsockopt_default_sndinfo(sk, kopt, optlen); |
---|
4398 | 4549 | break; |
---|
4399 | 4550 | case SCTP_PRIMARY_ADDR: |
---|
4400 | | - retval = sctp_setsockopt_primary_addr(sk, optval, optlen); |
---|
| 4551 | + retval = sctp_setsockopt_primary_addr(sk, kopt, optlen); |
---|
4401 | 4552 | break; |
---|
4402 | 4553 | case SCTP_SET_PEER_PRIMARY_ADDR: |
---|
4403 | | - retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen); |
---|
| 4554 | + retval = sctp_setsockopt_peer_primary_addr(sk, kopt, optlen); |
---|
4404 | 4555 | break; |
---|
4405 | 4556 | case SCTP_NODELAY: |
---|
4406 | | - retval = sctp_setsockopt_nodelay(sk, optval, optlen); |
---|
| 4557 | + retval = sctp_setsockopt_nodelay(sk, kopt, optlen); |
---|
4407 | 4558 | break; |
---|
4408 | 4559 | case SCTP_RTOINFO: |
---|
4409 | | - retval = sctp_setsockopt_rtoinfo(sk, optval, optlen); |
---|
| 4560 | + retval = sctp_setsockopt_rtoinfo(sk, kopt, optlen); |
---|
4410 | 4561 | break; |
---|
4411 | 4562 | case SCTP_ASSOCINFO: |
---|
4412 | | - retval = sctp_setsockopt_associnfo(sk, optval, optlen); |
---|
| 4563 | + retval = sctp_setsockopt_associnfo(sk, kopt, optlen); |
---|
4413 | 4564 | break; |
---|
4414 | 4565 | case SCTP_I_WANT_MAPPED_V4_ADDR: |
---|
4415 | | - retval = sctp_setsockopt_mappedv4(sk, optval, optlen); |
---|
| 4566 | + retval = sctp_setsockopt_mappedv4(sk, kopt, optlen); |
---|
4416 | 4567 | break; |
---|
4417 | 4568 | case SCTP_MAXSEG: |
---|
4418 | | - retval = sctp_setsockopt_maxseg(sk, optval, optlen); |
---|
| 4569 | + retval = sctp_setsockopt_maxseg(sk, kopt, optlen); |
---|
4419 | 4570 | break; |
---|
4420 | 4571 | case SCTP_ADAPTATION_LAYER: |
---|
4421 | | - retval = sctp_setsockopt_adaptation_layer(sk, optval, optlen); |
---|
| 4572 | + retval = sctp_setsockopt_adaptation_layer(sk, kopt, optlen); |
---|
4422 | 4573 | break; |
---|
4423 | 4574 | case SCTP_CONTEXT: |
---|
4424 | | - retval = sctp_setsockopt_context(sk, optval, optlen); |
---|
| 4575 | + retval = sctp_setsockopt_context(sk, kopt, optlen); |
---|
4425 | 4576 | break; |
---|
4426 | 4577 | case SCTP_FRAGMENT_INTERLEAVE: |
---|
4427 | | - retval = sctp_setsockopt_fragment_interleave(sk, optval, optlen); |
---|
| 4578 | + retval = sctp_setsockopt_fragment_interleave(sk, kopt, optlen); |
---|
4428 | 4579 | break; |
---|
4429 | 4580 | case SCTP_MAX_BURST: |
---|
4430 | | - retval = sctp_setsockopt_maxburst(sk, optval, optlen); |
---|
| 4581 | + retval = sctp_setsockopt_maxburst(sk, kopt, optlen); |
---|
4431 | 4582 | break; |
---|
4432 | 4583 | case SCTP_AUTH_CHUNK: |
---|
4433 | | - retval = sctp_setsockopt_auth_chunk(sk, optval, optlen); |
---|
| 4584 | + retval = sctp_setsockopt_auth_chunk(sk, kopt, optlen); |
---|
4434 | 4585 | break; |
---|
4435 | 4586 | case SCTP_HMAC_IDENT: |
---|
4436 | | - retval = sctp_setsockopt_hmac_ident(sk, optval, optlen); |
---|
| 4587 | + retval = sctp_setsockopt_hmac_ident(sk, kopt, optlen); |
---|
4437 | 4588 | break; |
---|
4438 | 4589 | case SCTP_AUTH_KEY: |
---|
4439 | | - retval = sctp_setsockopt_auth_key(sk, optval, optlen); |
---|
| 4590 | + retval = sctp_setsockopt_auth_key(sk, kopt, optlen); |
---|
4440 | 4591 | break; |
---|
4441 | 4592 | case SCTP_AUTH_ACTIVE_KEY: |
---|
4442 | | - retval = sctp_setsockopt_active_key(sk, optval, optlen); |
---|
| 4593 | + retval = sctp_setsockopt_active_key(sk, kopt, optlen); |
---|
4443 | 4594 | break; |
---|
4444 | 4595 | case SCTP_AUTH_DELETE_KEY: |
---|
4445 | | - retval = sctp_setsockopt_del_key(sk, optval, optlen); |
---|
| 4596 | + retval = sctp_setsockopt_del_key(sk, kopt, optlen); |
---|
4446 | 4597 | break; |
---|
4447 | 4598 | case SCTP_AUTH_DEACTIVATE_KEY: |
---|
4448 | | - retval = sctp_setsockopt_deactivate_key(sk, optval, optlen); |
---|
| 4599 | + retval = sctp_setsockopt_deactivate_key(sk, kopt, optlen); |
---|
4449 | 4600 | break; |
---|
4450 | 4601 | case SCTP_AUTO_ASCONF: |
---|
4451 | | - retval = sctp_setsockopt_auto_asconf(sk, optval, optlen); |
---|
| 4602 | + retval = sctp_setsockopt_auto_asconf(sk, kopt, optlen); |
---|
4452 | 4603 | break; |
---|
4453 | 4604 | case SCTP_PEER_ADDR_THLDS: |
---|
4454 | | - retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen); |
---|
| 4605 | + retval = sctp_setsockopt_paddr_thresholds(sk, kopt, optlen, |
---|
| 4606 | + false); |
---|
| 4607 | + break; |
---|
| 4608 | + case SCTP_PEER_ADDR_THLDS_V2: |
---|
| 4609 | + retval = sctp_setsockopt_paddr_thresholds(sk, kopt, optlen, |
---|
| 4610 | + true); |
---|
4455 | 4611 | break; |
---|
4456 | 4612 | case SCTP_RECVRCVINFO: |
---|
4457 | | - retval = sctp_setsockopt_recvrcvinfo(sk, optval, optlen); |
---|
| 4613 | + retval = sctp_setsockopt_recvrcvinfo(sk, kopt, optlen); |
---|
4458 | 4614 | break; |
---|
4459 | 4615 | case SCTP_RECVNXTINFO: |
---|
4460 | | - retval = sctp_setsockopt_recvnxtinfo(sk, optval, optlen); |
---|
| 4616 | + retval = sctp_setsockopt_recvnxtinfo(sk, kopt, optlen); |
---|
4461 | 4617 | break; |
---|
4462 | 4618 | case SCTP_PR_SUPPORTED: |
---|
4463 | | - retval = sctp_setsockopt_pr_supported(sk, optval, optlen); |
---|
| 4619 | + retval = sctp_setsockopt_pr_supported(sk, kopt, optlen); |
---|
4464 | 4620 | break; |
---|
4465 | 4621 | case SCTP_DEFAULT_PRINFO: |
---|
4466 | | - retval = sctp_setsockopt_default_prinfo(sk, optval, optlen); |
---|
| 4622 | + retval = sctp_setsockopt_default_prinfo(sk, kopt, optlen); |
---|
4467 | 4623 | break; |
---|
4468 | 4624 | case SCTP_RECONFIG_SUPPORTED: |
---|
4469 | | - retval = sctp_setsockopt_reconfig_supported(sk, optval, optlen); |
---|
| 4625 | + retval = sctp_setsockopt_reconfig_supported(sk, kopt, optlen); |
---|
4470 | 4626 | break; |
---|
4471 | 4627 | case SCTP_ENABLE_STREAM_RESET: |
---|
4472 | | - retval = sctp_setsockopt_enable_strreset(sk, optval, optlen); |
---|
| 4628 | + retval = sctp_setsockopt_enable_strreset(sk, kopt, optlen); |
---|
4473 | 4629 | break; |
---|
4474 | 4630 | case SCTP_RESET_STREAMS: |
---|
4475 | | - retval = sctp_setsockopt_reset_streams(sk, optval, optlen); |
---|
| 4631 | + retval = sctp_setsockopt_reset_streams(sk, kopt, optlen); |
---|
4476 | 4632 | break; |
---|
4477 | 4633 | case SCTP_RESET_ASSOC: |
---|
4478 | | - retval = sctp_setsockopt_reset_assoc(sk, optval, optlen); |
---|
| 4634 | + retval = sctp_setsockopt_reset_assoc(sk, kopt, optlen); |
---|
4479 | 4635 | break; |
---|
4480 | 4636 | case SCTP_ADD_STREAMS: |
---|
4481 | | - retval = sctp_setsockopt_add_streams(sk, optval, optlen); |
---|
| 4637 | + retval = sctp_setsockopt_add_streams(sk, kopt, optlen); |
---|
4482 | 4638 | break; |
---|
4483 | 4639 | case SCTP_STREAM_SCHEDULER: |
---|
4484 | | - retval = sctp_setsockopt_scheduler(sk, optval, optlen); |
---|
| 4640 | + retval = sctp_setsockopt_scheduler(sk, kopt, optlen); |
---|
4485 | 4641 | break; |
---|
4486 | 4642 | case SCTP_STREAM_SCHEDULER_VALUE: |
---|
4487 | | - retval = sctp_setsockopt_scheduler_value(sk, optval, optlen); |
---|
| 4643 | + retval = sctp_setsockopt_scheduler_value(sk, kopt, optlen); |
---|
4488 | 4644 | break; |
---|
4489 | 4645 | case SCTP_INTERLEAVING_SUPPORTED: |
---|
4490 | | - retval = sctp_setsockopt_interleaving_supported(sk, optval, |
---|
| 4646 | + retval = sctp_setsockopt_interleaving_supported(sk, kopt, |
---|
4491 | 4647 | optlen); |
---|
4492 | 4648 | break; |
---|
4493 | 4649 | case SCTP_REUSE_PORT: |
---|
4494 | | - retval = sctp_setsockopt_reuse_port(sk, optval, optlen); |
---|
| 4650 | + retval = sctp_setsockopt_reuse_port(sk, kopt, optlen); |
---|
| 4651 | + break; |
---|
| 4652 | + case SCTP_EVENT: |
---|
| 4653 | + retval = sctp_setsockopt_event(sk, kopt, optlen); |
---|
| 4654 | + break; |
---|
| 4655 | + case SCTP_ASCONF_SUPPORTED: |
---|
| 4656 | + retval = sctp_setsockopt_asconf_supported(sk, kopt, optlen); |
---|
| 4657 | + break; |
---|
| 4658 | + case SCTP_AUTH_SUPPORTED: |
---|
| 4659 | + retval = sctp_setsockopt_auth_supported(sk, kopt, optlen); |
---|
| 4660 | + break; |
---|
| 4661 | + case SCTP_ECN_SUPPORTED: |
---|
| 4662 | + retval = sctp_setsockopt_ecn_supported(sk, kopt, optlen); |
---|
| 4663 | + break; |
---|
| 4664 | + case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE: |
---|
| 4665 | + retval = sctp_setsockopt_pf_expose(sk, kopt, optlen); |
---|
4495 | 4666 | break; |
---|
4496 | 4667 | default: |
---|
4497 | 4668 | retval = -ENOPROTOOPT; |
---|
.. | .. |
---|
4499 | 4670 | } |
---|
4500 | 4671 | |
---|
4501 | 4672 | release_sock(sk); |
---|
4502 | | - |
---|
4503 | | -out_nounlock: |
---|
| 4673 | + kfree(kopt); |
---|
4504 | 4674 | return retval; |
---|
4505 | 4675 | } |
---|
4506 | 4676 | |
---|
.. | .. |
---|
4527 | 4697 | int err = -EINVAL; |
---|
4528 | 4698 | |
---|
4529 | 4699 | lock_sock(sk); |
---|
4530 | | - |
---|
4531 | 4700 | pr_debug("%s: sk:%p, sockaddr:%p, addr_len:%d\n", __func__, sk, |
---|
4532 | 4701 | addr, addr_len); |
---|
4533 | 4702 | |
---|
.. | .. |
---|
4609 | 4778 | /* Populate the fields of the newsk from the oldsk and migrate the |
---|
4610 | 4779 | * asoc to the newsk. |
---|
4611 | 4780 | */ |
---|
4612 | | - sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP); |
---|
| 4781 | + error = sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP); |
---|
| 4782 | + if (error) { |
---|
| 4783 | + sk_common_release(newsk); |
---|
| 4784 | + newsk = NULL; |
---|
| 4785 | + } |
---|
4613 | 4786 | |
---|
4614 | 4787 | out: |
---|
4615 | 4788 | release_sock(sk); |
---|
.. | .. |
---|
4725 | 4898 | /* Initialize default event subscriptions. By default, all the |
---|
4726 | 4899 | * options are off. |
---|
4727 | 4900 | */ |
---|
4728 | | - memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); |
---|
| 4901 | + sp->subscribe = 0; |
---|
4729 | 4902 | |
---|
4730 | 4903 | /* Default Peer Address Parameters. These defaults can |
---|
4731 | 4904 | * be modified via SCTP_PEER_ADDR_PARAMS |
---|
4732 | 4905 | */ |
---|
4733 | 4906 | sp->hbinterval = net->sctp.hb_interval; |
---|
4734 | 4907 | sp->pathmaxrxt = net->sctp.max_retrans_path; |
---|
| 4908 | + sp->pf_retrans = net->sctp.pf_retrans; |
---|
| 4909 | + sp->ps_retrans = net->sctp.ps_retrans; |
---|
| 4910 | + sp->pf_expose = net->sctp.pf_expose; |
---|
4735 | 4911 | sp->pathmtu = 0; /* allow default discovery */ |
---|
4736 | 4912 | sp->sackdelay = net->sctp.sack_timeout; |
---|
4737 | 4913 | sp->sackfreq = 2; |
---|
4738 | 4914 | sp->param_flags = SPP_HB_ENABLE | |
---|
4739 | 4915 | SPP_PMTUD_ENABLE | |
---|
4740 | 4916 | SPP_SACKDELAY_ENABLE; |
---|
| 4917 | + sp->default_ss = SCTP_SS_DEFAULT; |
---|
4741 | 4918 | |
---|
4742 | 4919 | /* If enabled no SCTP message fragmentation will be performed. |
---|
4743 | 4920 | * Configure through SCTP_DISABLE_FRAGMENTS socket option. |
---|
.. | .. |
---|
4824 | 5001 | } |
---|
4825 | 5002 | |
---|
4826 | 5003 | /* Triggered when there are no references on the socket anymore */ |
---|
4827 | | -static void sctp_destruct_sock(struct sock *sk) |
---|
| 5004 | +static void sctp_destruct_common(struct sock *sk) |
---|
4828 | 5005 | { |
---|
4829 | 5006 | struct sctp_sock *sp = sctp_sk(sk); |
---|
4830 | 5007 | |
---|
4831 | 5008 | /* Free up the HMAC transform. */ |
---|
4832 | 5009 | crypto_free_shash(sp->hmac); |
---|
| 5010 | +} |
---|
4833 | 5011 | |
---|
| 5012 | +static void sctp_destruct_sock(struct sock *sk) |
---|
| 5013 | +{ |
---|
| 5014 | + sctp_destruct_common(sk); |
---|
4834 | 5015 | inet_sock_destruct(sk); |
---|
4835 | 5016 | } |
---|
4836 | 5017 | |
---|
.. | .. |
---|
4956 | 5137 | EXPORT_SYMBOL_GPL(sctp_get_sctp_info); |
---|
4957 | 5138 | |
---|
4958 | 5139 | /* use callback to avoid exporting the core structure */ |
---|
4959 | | -void sctp_transport_walk_start(struct rhashtable_iter *iter) |
---|
| 5140 | +void sctp_transport_walk_start(struct rhashtable_iter *iter) __acquires(RCU) |
---|
4960 | 5141 | { |
---|
4961 | 5142 | rhltable_walk_enter(&sctp_transport_hashtable, iter); |
---|
4962 | 5143 | |
---|
4963 | 5144 | rhashtable_walk_start(iter); |
---|
4964 | 5145 | } |
---|
4965 | 5146 | |
---|
4966 | | -void sctp_transport_walk_stop(struct rhashtable_iter *iter) |
---|
| 5147 | +void sctp_transport_walk_stop(struct rhashtable_iter *iter) __releases(RCU) |
---|
4967 | 5148 | { |
---|
4968 | 5149 | rhashtable_walk_stop(iter); |
---|
4969 | 5150 | rhashtable_walk_exit(iter); |
---|
.. | .. |
---|
4985 | 5166 | if (!sctp_transport_hold(t)) |
---|
4986 | 5167 | continue; |
---|
4987 | 5168 | |
---|
4988 | | - if (net_eq(sock_net(t->asoc->base.sk), net) && |
---|
| 5169 | + if (net_eq(t->asoc->base.net, net) && |
---|
4989 | 5170 | t->asoc->peer.primary_path == t) |
---|
4990 | 5171 | break; |
---|
4991 | 5172 | |
---|
.. | .. |
---|
5205 | 5386 | |
---|
5206 | 5387 | transport = sctp_addr_id2transport(sk, &pinfo.spinfo_address, |
---|
5207 | 5388 | pinfo.spinfo_assoc_id); |
---|
5208 | | - if (!transport) |
---|
5209 | | - return -EINVAL; |
---|
| 5389 | + if (!transport) { |
---|
| 5390 | + retval = -EINVAL; |
---|
| 5391 | + goto out; |
---|
| 5392 | + } |
---|
| 5393 | + |
---|
| 5394 | + if (transport->state == SCTP_PF && |
---|
| 5395 | + transport->asoc->pf_expose == SCTP_PF_EXPOSE_DISABLE) { |
---|
| 5396 | + retval = -EACCES; |
---|
| 5397 | + goto out; |
---|
| 5398 | + } |
---|
5210 | 5399 | |
---|
5211 | 5400 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
---|
5212 | 5401 | pinfo.spinfo_state = transport->state; |
---|
.. | .. |
---|
5264 | 5453 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, |
---|
5265 | 5454 | int __user *optlen) |
---|
5266 | 5455 | { |
---|
| 5456 | + struct sctp_event_subscribe subscribe; |
---|
| 5457 | + __u8 *sn_type = (__u8 *)&subscribe; |
---|
| 5458 | + int i; |
---|
| 5459 | + |
---|
5267 | 5460 | if (len == 0) |
---|
5268 | 5461 | return -EINVAL; |
---|
5269 | 5462 | if (len > sizeof(struct sctp_event_subscribe)) |
---|
5270 | 5463 | len = sizeof(struct sctp_event_subscribe); |
---|
5271 | 5464 | if (put_user(len, optlen)) |
---|
5272 | 5465 | return -EFAULT; |
---|
5273 | | - if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) |
---|
| 5466 | + |
---|
| 5467 | + for (i = 0; i < len; i++) |
---|
| 5468 | + sn_type[i] = sctp_ulpevent_type_enabled(sctp_sk(sk)->subscribe, |
---|
| 5469 | + SCTP_SN_TYPE_BASE + i); |
---|
| 5470 | + |
---|
| 5471 | + if (copy_to_user(optval, &subscribe, len)) |
---|
5274 | 5472 | return -EFAULT; |
---|
| 5473 | + |
---|
5275 | 5474 | return 0; |
---|
5276 | 5475 | } |
---|
5277 | 5476 | |
---|
.. | .. |
---|
5333 | 5532 | * Set the daddr and initialize id to something more random and also |
---|
5334 | 5533 | * copy over any ip options. |
---|
5335 | 5534 | */ |
---|
5336 | | - sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); |
---|
| 5535 | + sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sock->sk); |
---|
5337 | 5536 | sp->pf->copy_ip_options(sk, sock->sk); |
---|
5338 | 5537 | |
---|
5339 | 5538 | /* Populate the fields of the newsk from the oldsk and migrate the |
---|
5340 | 5539 | * asoc to the newsk. |
---|
5341 | 5540 | */ |
---|
5342 | | - sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); |
---|
| 5541 | + err = sctp_sock_migrate(sk, sock->sk, asoc, |
---|
| 5542 | + SCTP_SOCKET_UDP_HIGH_BANDWIDTH); |
---|
| 5543 | + if (err) { |
---|
| 5544 | + sock_release(sock); |
---|
| 5545 | + sock = NULL; |
---|
| 5546 | + } |
---|
5343 | 5547 | |
---|
5344 | 5548 | *sockp = sock; |
---|
5345 | 5549 | |
---|
.. | .. |
---|
5615 | 5819 | } |
---|
5616 | 5820 | } |
---|
5617 | 5821 | |
---|
5618 | | - /* Get association, if assoc_id != 0 and the socket is a one |
---|
5619 | | - * to many style socket, and an association was not found, then |
---|
5620 | | - * the id was invalid. |
---|
| 5822 | + /* Get association, if assoc_id != SCTP_FUTURE_ASSOC and the |
---|
| 5823 | + * socket is a one to many style socket, and an association |
---|
| 5824 | + * was not found, then the id was invalid. |
---|
5621 | 5825 | */ |
---|
5622 | 5826 | asoc = sctp_id2assoc(sk, params.spp_assoc_id); |
---|
5623 | | - if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) { |
---|
| 5827 | + if (!asoc && params.spp_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 5828 | + sctp_style(sk, UDP)) { |
---|
5624 | 5829 | pr_debug("%s: failed no association\n", __func__); |
---|
5625 | 5830 | return -EINVAL; |
---|
5626 | 5831 | } |
---|
.. | .. |
---|
5749 | 5954 | } else |
---|
5750 | 5955 | return -EINVAL; |
---|
5751 | 5956 | |
---|
5752 | | - /* Get association, if sack_assoc_id != 0 and the socket is a one |
---|
5753 | | - * to many style socket, and an association was not found, then |
---|
5754 | | - * the id was invalid. |
---|
| 5957 | + /* Get association, if sack_assoc_id != SCTP_FUTURE_ASSOC and the |
---|
| 5958 | + * socket is a one to many style socket, and an association |
---|
| 5959 | + * was not found, then the id was invalid. |
---|
5755 | 5960 | */ |
---|
5756 | 5961 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
---|
5757 | | - if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
---|
| 5962 | + if (!asoc && params.sack_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 5963 | + sctp_style(sk, UDP)) |
---|
5758 | 5964 | return -EINVAL; |
---|
5759 | 5965 | |
---|
5760 | 5966 | if (asoc) { |
---|
5761 | 5967 | /* Fetch association values. */ |
---|
5762 | 5968 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) { |
---|
5763 | | - params.sack_delay = jiffies_to_msecs( |
---|
5764 | | - asoc->sackdelay); |
---|
| 5969 | + params.sack_delay = jiffies_to_msecs(asoc->sackdelay); |
---|
5765 | 5970 | params.sack_freq = asoc->sackfreq; |
---|
5766 | 5971 | |
---|
5767 | 5972 | } else { |
---|
.. | .. |
---|
6114 | 6319 | return -EFAULT; |
---|
6115 | 6320 | |
---|
6116 | 6321 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); |
---|
6117 | | - if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) |
---|
| 6322 | + if (!asoc && info.sinfo_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6323 | + sctp_style(sk, UDP)) |
---|
6118 | 6324 | return -EINVAL; |
---|
| 6325 | + |
---|
6119 | 6326 | if (asoc) { |
---|
6120 | 6327 | info.sinfo_stream = asoc->default_stream; |
---|
6121 | 6328 | info.sinfo_flags = asoc->default_flags; |
---|
.. | .. |
---|
6158 | 6365 | return -EFAULT; |
---|
6159 | 6366 | |
---|
6160 | 6367 | asoc = sctp_id2assoc(sk, info.snd_assoc_id); |
---|
6161 | | - if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP)) |
---|
| 6368 | + if (!asoc && info.snd_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6369 | + sctp_style(sk, UDP)) |
---|
6162 | 6370 | return -EINVAL; |
---|
| 6371 | + |
---|
6163 | 6372 | if (asoc) { |
---|
6164 | 6373 | info.snd_sid = asoc->default_stream; |
---|
6165 | 6374 | info.snd_flags = asoc->default_flags; |
---|
.. | .. |
---|
6235 | 6444 | |
---|
6236 | 6445 | asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); |
---|
6237 | 6446 | |
---|
6238 | | - if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) |
---|
| 6447 | + if (!asoc && rtoinfo.srto_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6448 | + sctp_style(sk, UDP)) |
---|
6239 | 6449 | return -EINVAL; |
---|
6240 | 6450 | |
---|
6241 | 6451 | /* Values corresponding to the specific association. */ |
---|
.. | .. |
---|
6292 | 6502 | |
---|
6293 | 6503 | asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); |
---|
6294 | 6504 | |
---|
6295 | | - if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP)) |
---|
| 6505 | + if (!asoc && assocparams.sasoc_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6506 | + sctp_style(sk, UDP)) |
---|
6296 | 6507 | return -EINVAL; |
---|
6297 | 6508 | |
---|
6298 | 6509 | /* Values correspoinding to the specific association */ |
---|
.. | .. |
---|
6367 | 6578 | char __user *optval, int __user *optlen) |
---|
6368 | 6579 | { |
---|
6369 | 6580 | struct sctp_assoc_value params; |
---|
6370 | | - struct sctp_sock *sp; |
---|
6371 | 6581 | struct sctp_association *asoc; |
---|
6372 | 6582 | |
---|
6373 | 6583 | if (len < sizeof(struct sctp_assoc_value)) |
---|
.. | .. |
---|
6378 | 6588 | if (copy_from_user(¶ms, optval, len)) |
---|
6379 | 6589 | return -EFAULT; |
---|
6380 | 6590 | |
---|
6381 | | - sp = sctp_sk(sk); |
---|
| 6591 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 6592 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6593 | + sctp_style(sk, UDP)) |
---|
| 6594 | + return -EINVAL; |
---|
6382 | 6595 | |
---|
6383 | | - if (params.assoc_id != 0) { |
---|
6384 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
6385 | | - if (!asoc) |
---|
6386 | | - return -EINVAL; |
---|
6387 | | - params.assoc_value = asoc->default_rcv_context; |
---|
6388 | | - } else { |
---|
6389 | | - params.assoc_value = sp->default_rcv_context; |
---|
6390 | | - } |
---|
| 6596 | + params.assoc_value = asoc ? asoc->default_rcv_context |
---|
| 6597 | + : sctp_sk(sk)->default_rcv_context; |
---|
6391 | 6598 | |
---|
6392 | 6599 | if (put_user(len, optlen)) |
---|
6393 | 6600 | return -EFAULT; |
---|
.. | .. |
---|
6436 | 6643 | "Use of int in maxseg socket option.\n" |
---|
6437 | 6644 | "Use struct sctp_assoc_value instead\n", |
---|
6438 | 6645 | current->comm, task_pid_nr(current)); |
---|
6439 | | - params.assoc_id = 0; |
---|
| 6646 | + params.assoc_id = SCTP_FUTURE_ASSOC; |
---|
6440 | 6647 | } else if (len >= sizeof(struct sctp_assoc_value)) { |
---|
6441 | 6648 | len = sizeof(struct sctp_assoc_value); |
---|
6442 | 6649 | if (copy_from_user(¶ms, optval, len)) |
---|
.. | .. |
---|
6445 | 6652 | return -EINVAL; |
---|
6446 | 6653 | |
---|
6447 | 6654 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
6448 | | - if (!asoc && params.assoc_id && sctp_style(sk, UDP)) |
---|
| 6655 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6656 | + sctp_style(sk, UDP)) |
---|
6449 | 6657 | return -EINVAL; |
---|
6450 | 6658 | |
---|
6451 | 6659 | if (asoc) |
---|
.. | .. |
---|
6522 | 6730 | int __user *optlen) |
---|
6523 | 6731 | { |
---|
6524 | 6732 | struct sctp_assoc_value params; |
---|
6525 | | - struct sctp_sock *sp; |
---|
6526 | 6733 | struct sctp_association *asoc; |
---|
6527 | 6734 | |
---|
6528 | 6735 | if (len == sizeof(int)) { |
---|
.. | .. |
---|
6531 | 6738 | "Use of int in max_burst socket option.\n" |
---|
6532 | 6739 | "Use struct sctp_assoc_value instead\n", |
---|
6533 | 6740 | current->comm, task_pid_nr(current)); |
---|
6534 | | - params.assoc_id = 0; |
---|
| 6741 | + params.assoc_id = SCTP_FUTURE_ASSOC; |
---|
6535 | 6742 | } else if (len >= sizeof(struct sctp_assoc_value)) { |
---|
6536 | 6743 | len = sizeof(struct sctp_assoc_value); |
---|
6537 | 6744 | if (copy_from_user(¶ms, optval, len)) |
---|
.. | .. |
---|
6539 | 6746 | } else |
---|
6540 | 6747 | return -EINVAL; |
---|
6541 | 6748 | |
---|
6542 | | - sp = sctp_sk(sk); |
---|
| 6749 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 6750 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6751 | + sctp_style(sk, UDP)) |
---|
| 6752 | + return -EINVAL; |
---|
6543 | 6753 | |
---|
6544 | | - if (params.assoc_id != 0) { |
---|
6545 | | - asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
6546 | | - if (!asoc) |
---|
6547 | | - return -EINVAL; |
---|
6548 | | - params.assoc_value = asoc->max_burst; |
---|
6549 | | - } else |
---|
6550 | | - params.assoc_value = sp->max_burst; |
---|
| 6754 | + params.assoc_value = asoc ? asoc->max_burst : sctp_sk(sk)->max_burst; |
---|
6551 | 6755 | |
---|
6552 | 6756 | if (len == sizeof(int)) { |
---|
6553 | 6757 | if (copy_to_user(optval, ¶ms.assoc_value, len)) |
---|
.. | .. |
---|
6604 | 6808 | struct sctp_authkeyid val; |
---|
6605 | 6809 | struct sctp_association *asoc; |
---|
6606 | 6810 | |
---|
6607 | | - if (!ep->auth_enable) |
---|
6608 | | - return -EACCES; |
---|
6609 | | - |
---|
6610 | 6811 | if (len < sizeof(struct sctp_authkeyid)) |
---|
6611 | 6812 | return -EINVAL; |
---|
6612 | 6813 | |
---|
.. | .. |
---|
6618 | 6819 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
---|
6619 | 6820 | return -EINVAL; |
---|
6620 | 6821 | |
---|
6621 | | - if (asoc) |
---|
| 6822 | + if (asoc) { |
---|
| 6823 | + if (!asoc->peer.auth_capable) |
---|
| 6824 | + return -EACCES; |
---|
6622 | 6825 | val.scact_keynumber = asoc->active_key_id; |
---|
6623 | | - else |
---|
| 6826 | + } else { |
---|
| 6827 | + if (!ep->auth_enable) |
---|
| 6828 | + return -EACCES; |
---|
6624 | 6829 | val.scact_keynumber = ep->active_key_id; |
---|
| 6830 | + } |
---|
6625 | 6831 | |
---|
6626 | 6832 | if (put_user(len, optlen)) |
---|
6627 | 6833 | return -EFAULT; |
---|
.. | .. |
---|
6634 | 6840 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
---|
6635 | 6841 | char __user *optval, int __user *optlen) |
---|
6636 | 6842 | { |
---|
6637 | | - struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
---|
6638 | 6843 | struct sctp_authchunks __user *p = (void __user *)optval; |
---|
6639 | 6844 | struct sctp_authchunks val; |
---|
6640 | 6845 | struct sctp_association *asoc; |
---|
6641 | 6846 | struct sctp_chunks_param *ch; |
---|
6642 | 6847 | u32 num_chunks = 0; |
---|
6643 | 6848 | char __user *to; |
---|
6644 | | - |
---|
6645 | | - if (!ep->auth_enable) |
---|
6646 | | - return -EACCES; |
---|
6647 | 6849 | |
---|
6648 | 6850 | if (len < sizeof(struct sctp_authchunks)) |
---|
6649 | 6851 | return -EINVAL; |
---|
.. | .. |
---|
6655 | 6857 | asoc = sctp_id2assoc(sk, val.gauth_assoc_id); |
---|
6656 | 6858 | if (!asoc) |
---|
6657 | 6859 | return -EINVAL; |
---|
| 6860 | + |
---|
| 6861 | + if (!asoc->peer.auth_capable) |
---|
| 6862 | + return -EACCES; |
---|
6658 | 6863 | |
---|
6659 | 6864 | ch = asoc->peer.peer_chunks; |
---|
6660 | 6865 | if (!ch) |
---|
.. | .. |
---|
6687 | 6892 | u32 num_chunks = 0; |
---|
6688 | 6893 | char __user *to; |
---|
6689 | 6894 | |
---|
6690 | | - if (!ep->auth_enable) |
---|
6691 | | - return -EACCES; |
---|
6692 | | - |
---|
6693 | 6895 | if (len < sizeof(struct sctp_authchunks)) |
---|
6694 | 6896 | return -EINVAL; |
---|
6695 | 6897 | |
---|
.. | .. |
---|
6698 | 6900 | |
---|
6699 | 6901 | to = p->gauth_chunks; |
---|
6700 | 6902 | asoc = sctp_id2assoc(sk, val.gauth_assoc_id); |
---|
6701 | | - if (!asoc && val.gauth_assoc_id && sctp_style(sk, UDP)) |
---|
| 6903 | + if (!asoc && val.gauth_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 6904 | + sctp_style(sk, UDP)) |
---|
6702 | 6905 | return -EINVAL; |
---|
6703 | 6906 | |
---|
6704 | | - if (asoc) |
---|
| 6907 | + if (asoc) { |
---|
| 6908 | + if (!asoc->peer.auth_capable) |
---|
| 6909 | + return -EACCES; |
---|
6705 | 6910 | ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; |
---|
6706 | | - else |
---|
| 6911 | + } else { |
---|
| 6912 | + if (!ep->auth_enable) |
---|
| 6913 | + return -EACCES; |
---|
6707 | 6914 | ch = ep->auth_chunk_list; |
---|
6708 | | - |
---|
| 6915 | + } |
---|
6709 | 6916 | if (!ch) |
---|
6710 | 6917 | goto num; |
---|
6711 | 6918 | |
---|
.. | .. |
---|
6836 | 7043 | * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt |
---|
6837 | 7044 | */ |
---|
6838 | 7045 | static int sctp_getsockopt_paddr_thresholds(struct sock *sk, |
---|
6839 | | - char __user *optval, |
---|
6840 | | - int len, |
---|
6841 | | - int __user *optlen) |
---|
| 7046 | + char __user *optval, int len, |
---|
| 7047 | + int __user *optlen, bool v2) |
---|
6842 | 7048 | { |
---|
6843 | | - struct sctp_paddrthlds val; |
---|
| 7049 | + struct sctp_paddrthlds_v2 val; |
---|
6844 | 7050 | struct sctp_transport *trans; |
---|
6845 | 7051 | struct sctp_association *asoc; |
---|
| 7052 | + int min; |
---|
6846 | 7053 | |
---|
6847 | | - if (len < sizeof(struct sctp_paddrthlds)) |
---|
| 7054 | + min = v2 ? sizeof(val) : sizeof(struct sctp_paddrthlds); |
---|
| 7055 | + if (len < min) |
---|
6848 | 7056 | return -EINVAL; |
---|
6849 | | - len = sizeof(struct sctp_paddrthlds); |
---|
6850 | | - if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, len)) |
---|
| 7057 | + len = min; |
---|
| 7058 | + if (copy_from_user(&val, optval, len)) |
---|
6851 | 7059 | return -EFAULT; |
---|
6852 | 7060 | |
---|
6853 | | - if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) { |
---|
6854 | | - asoc = sctp_id2assoc(sk, val.spt_assoc_id); |
---|
6855 | | - if (!asoc) |
---|
6856 | | - return -ENOENT; |
---|
6857 | | - |
---|
6858 | | - val.spt_pathpfthld = asoc->pf_retrans; |
---|
6859 | | - val.spt_pathmaxrxt = asoc->pathmaxrxt; |
---|
6860 | | - } else { |
---|
| 7061 | + if (!sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) { |
---|
6861 | 7062 | trans = sctp_addr_id2transport(sk, &val.spt_address, |
---|
6862 | 7063 | val.spt_assoc_id); |
---|
6863 | 7064 | if (!trans) |
---|
.. | .. |
---|
6865 | 7066 | |
---|
6866 | 7067 | val.spt_pathmaxrxt = trans->pathmaxrxt; |
---|
6867 | 7068 | val.spt_pathpfthld = trans->pf_retrans; |
---|
| 7069 | + val.spt_pathcpthld = trans->ps_retrans; |
---|
| 7070 | + |
---|
| 7071 | + goto out; |
---|
6868 | 7072 | } |
---|
6869 | 7073 | |
---|
| 7074 | + asoc = sctp_id2assoc(sk, val.spt_assoc_id); |
---|
| 7075 | + if (!asoc && val.spt_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7076 | + sctp_style(sk, UDP)) |
---|
| 7077 | + return -EINVAL; |
---|
| 7078 | + |
---|
| 7079 | + if (asoc) { |
---|
| 7080 | + val.spt_pathpfthld = asoc->pf_retrans; |
---|
| 7081 | + val.spt_pathmaxrxt = asoc->pathmaxrxt; |
---|
| 7082 | + val.spt_pathcpthld = asoc->ps_retrans; |
---|
| 7083 | + } else { |
---|
| 7084 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 7085 | + |
---|
| 7086 | + val.spt_pathpfthld = sp->pf_retrans; |
---|
| 7087 | + val.spt_pathmaxrxt = sp->pathmaxrxt; |
---|
| 7088 | + val.spt_pathcpthld = sp->ps_retrans; |
---|
| 7089 | + } |
---|
| 7090 | + |
---|
| 7091 | +out: |
---|
6870 | 7092 | if (put_user(len, optlen) || copy_to_user(optval, &val, len)) |
---|
6871 | 7093 | return -EFAULT; |
---|
6872 | 7094 | |
---|
.. | .. |
---|
6995 | 7217 | goto out; |
---|
6996 | 7218 | |
---|
6997 | 7219 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
6998 | | - if (asoc) { |
---|
6999 | | - params.assoc_value = asoc->prsctp_enable; |
---|
7000 | | - } else if (!params.assoc_id) { |
---|
7001 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
7002 | | - |
---|
7003 | | - params.assoc_value = sp->ep->prsctp_enable; |
---|
7004 | | - } else { |
---|
| 7220 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7221 | + sctp_style(sk, UDP)) { |
---|
7005 | 7222 | retval = -EINVAL; |
---|
7006 | 7223 | goto out; |
---|
7007 | 7224 | } |
---|
| 7225 | + |
---|
| 7226 | + params.assoc_value = asoc ? asoc->peer.prsctp_capable |
---|
| 7227 | + : sctp_sk(sk)->ep->prsctp_enable; |
---|
7008 | 7228 | |
---|
7009 | 7229 | if (put_user(len, optlen)) |
---|
7010 | 7230 | goto out; |
---|
.. | .. |
---|
7036 | 7256 | goto out; |
---|
7037 | 7257 | |
---|
7038 | 7258 | asoc = sctp_id2assoc(sk, info.pr_assoc_id); |
---|
| 7259 | + if (!asoc && info.pr_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7260 | + sctp_style(sk, UDP)) { |
---|
| 7261 | + retval = -EINVAL; |
---|
| 7262 | + goto out; |
---|
| 7263 | + } |
---|
| 7264 | + |
---|
7039 | 7265 | if (asoc) { |
---|
7040 | 7266 | info.pr_policy = SCTP_PR_POLICY(asoc->default_flags); |
---|
7041 | 7267 | info.pr_value = asoc->default_timetolive; |
---|
7042 | | - } else if (!info.pr_assoc_id) { |
---|
| 7268 | + } else { |
---|
7043 | 7269 | struct sctp_sock *sp = sctp_sk(sk); |
---|
7044 | 7270 | |
---|
7045 | 7271 | info.pr_policy = SCTP_PR_POLICY(sp->default_flags); |
---|
7046 | 7272 | info.pr_value = sp->default_timetolive; |
---|
7047 | | - } else { |
---|
7048 | | - retval = -EINVAL; |
---|
7049 | | - goto out; |
---|
7050 | 7273 | } |
---|
7051 | 7274 | |
---|
7052 | 7275 | if (put_user(len, optlen)) |
---|
.. | .. |
---|
7202 | 7425 | goto out; |
---|
7203 | 7426 | |
---|
7204 | 7427 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
7205 | | - if (asoc) { |
---|
7206 | | - params.assoc_value = asoc->reconf_enable; |
---|
7207 | | - } else if (!params.assoc_id) { |
---|
7208 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
7209 | | - |
---|
7210 | | - params.assoc_value = sp->ep->reconf_enable; |
---|
7211 | | - } else { |
---|
| 7428 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7429 | + sctp_style(sk, UDP)) { |
---|
7212 | 7430 | retval = -EINVAL; |
---|
7213 | 7431 | goto out; |
---|
7214 | 7432 | } |
---|
| 7433 | + |
---|
| 7434 | + params.assoc_value = asoc ? asoc->peer.reconf_capable |
---|
| 7435 | + : sctp_sk(sk)->ep->reconf_enable; |
---|
7215 | 7436 | |
---|
7216 | 7437 | if (put_user(len, optlen)) |
---|
7217 | 7438 | goto out; |
---|
.. | .. |
---|
7243 | 7464 | goto out; |
---|
7244 | 7465 | |
---|
7245 | 7466 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
7246 | | - if (asoc) { |
---|
7247 | | - params.assoc_value = asoc->strreset_enable; |
---|
7248 | | - } else if (!params.assoc_id) { |
---|
7249 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
7250 | | - |
---|
7251 | | - params.assoc_value = sp->ep->strreset_enable; |
---|
7252 | | - } else { |
---|
| 7467 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7468 | + sctp_style(sk, UDP)) { |
---|
7253 | 7469 | retval = -EINVAL; |
---|
7254 | 7470 | goto out; |
---|
7255 | 7471 | } |
---|
| 7472 | + |
---|
| 7473 | + params.assoc_value = asoc ? asoc->strreset_enable |
---|
| 7474 | + : sctp_sk(sk)->ep->strreset_enable; |
---|
7256 | 7475 | |
---|
7257 | 7476 | if (put_user(len, optlen)) |
---|
7258 | 7477 | goto out; |
---|
.. | .. |
---|
7284 | 7503 | goto out; |
---|
7285 | 7504 | |
---|
7286 | 7505 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
7287 | | - if (!asoc) { |
---|
| 7506 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7507 | + sctp_style(sk, UDP)) { |
---|
7288 | 7508 | retval = -EINVAL; |
---|
7289 | 7509 | goto out; |
---|
7290 | 7510 | } |
---|
7291 | 7511 | |
---|
7292 | | - params.assoc_value = sctp_sched_get_sched(asoc); |
---|
| 7512 | + params.assoc_value = asoc ? sctp_sched_get_sched(asoc) |
---|
| 7513 | + : sctp_sk(sk)->default_ss; |
---|
7293 | 7514 | |
---|
7294 | 7515 | if (put_user(len, optlen)) |
---|
7295 | 7516 | goto out; |
---|
.. | .. |
---|
7363 | 7584 | goto out; |
---|
7364 | 7585 | |
---|
7365 | 7586 | asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
7366 | | - if (asoc) { |
---|
7367 | | - params.assoc_value = asoc->intl_enable; |
---|
7368 | | - } else if (!params.assoc_id) { |
---|
7369 | | - struct sctp_sock *sp = sctp_sk(sk); |
---|
7370 | | - |
---|
7371 | | - params.assoc_value = sp->strm_interleave; |
---|
7372 | | - } else { |
---|
| 7587 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7588 | + sctp_style(sk, UDP)) { |
---|
7373 | 7589 | retval = -EINVAL; |
---|
7374 | 7590 | goto out; |
---|
7375 | 7591 | } |
---|
| 7592 | + |
---|
| 7593 | + params.assoc_value = asoc ? asoc->peer.intl_capable |
---|
| 7594 | + : sctp_sk(sk)->ep->intl_enable; |
---|
7376 | 7595 | |
---|
7377 | 7596 | if (put_user(len, optlen)) |
---|
7378 | 7597 | goto out; |
---|
.. | .. |
---|
7404 | 7623 | return -EFAULT; |
---|
7405 | 7624 | |
---|
7406 | 7625 | return 0; |
---|
| 7626 | +} |
---|
| 7627 | + |
---|
| 7628 | +static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval, |
---|
| 7629 | + int __user *optlen) |
---|
| 7630 | +{ |
---|
| 7631 | + struct sctp_association *asoc; |
---|
| 7632 | + struct sctp_event param; |
---|
| 7633 | + __u16 subscribe; |
---|
| 7634 | + |
---|
| 7635 | + if (len < sizeof(param)) |
---|
| 7636 | + return -EINVAL; |
---|
| 7637 | + |
---|
| 7638 | + len = sizeof(param); |
---|
| 7639 | + if (copy_from_user(¶m, optval, len)) |
---|
| 7640 | + return -EFAULT; |
---|
| 7641 | + |
---|
| 7642 | + if (param.se_type < SCTP_SN_TYPE_BASE || |
---|
| 7643 | + param.se_type > SCTP_SN_TYPE_MAX) |
---|
| 7644 | + return -EINVAL; |
---|
| 7645 | + |
---|
| 7646 | + asoc = sctp_id2assoc(sk, param.se_assoc_id); |
---|
| 7647 | + if (!asoc && param.se_assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7648 | + sctp_style(sk, UDP)) |
---|
| 7649 | + return -EINVAL; |
---|
| 7650 | + |
---|
| 7651 | + subscribe = asoc ? asoc->subscribe : sctp_sk(sk)->subscribe; |
---|
| 7652 | + param.se_on = sctp_ulpevent_type_enabled(subscribe, param.se_type); |
---|
| 7653 | + |
---|
| 7654 | + if (put_user(len, optlen)) |
---|
| 7655 | + return -EFAULT; |
---|
| 7656 | + |
---|
| 7657 | + if (copy_to_user(optval, ¶m, len)) |
---|
| 7658 | + return -EFAULT; |
---|
| 7659 | + |
---|
| 7660 | + return 0; |
---|
| 7661 | +} |
---|
| 7662 | + |
---|
| 7663 | +static int sctp_getsockopt_asconf_supported(struct sock *sk, int len, |
---|
| 7664 | + char __user *optval, |
---|
| 7665 | + int __user *optlen) |
---|
| 7666 | +{ |
---|
| 7667 | + struct sctp_assoc_value params; |
---|
| 7668 | + struct sctp_association *asoc; |
---|
| 7669 | + int retval = -EFAULT; |
---|
| 7670 | + |
---|
| 7671 | + if (len < sizeof(params)) { |
---|
| 7672 | + retval = -EINVAL; |
---|
| 7673 | + goto out; |
---|
| 7674 | + } |
---|
| 7675 | + |
---|
| 7676 | + len = sizeof(params); |
---|
| 7677 | + if (copy_from_user(¶ms, optval, len)) |
---|
| 7678 | + goto out; |
---|
| 7679 | + |
---|
| 7680 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 7681 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7682 | + sctp_style(sk, UDP)) { |
---|
| 7683 | + retval = -EINVAL; |
---|
| 7684 | + goto out; |
---|
| 7685 | + } |
---|
| 7686 | + |
---|
| 7687 | + params.assoc_value = asoc ? asoc->peer.asconf_capable |
---|
| 7688 | + : sctp_sk(sk)->ep->asconf_enable; |
---|
| 7689 | + |
---|
| 7690 | + if (put_user(len, optlen)) |
---|
| 7691 | + goto out; |
---|
| 7692 | + |
---|
| 7693 | + if (copy_to_user(optval, ¶ms, len)) |
---|
| 7694 | + goto out; |
---|
| 7695 | + |
---|
| 7696 | + retval = 0; |
---|
| 7697 | + |
---|
| 7698 | +out: |
---|
| 7699 | + return retval; |
---|
| 7700 | +} |
---|
| 7701 | + |
---|
| 7702 | +static int sctp_getsockopt_auth_supported(struct sock *sk, int len, |
---|
| 7703 | + char __user *optval, |
---|
| 7704 | + int __user *optlen) |
---|
| 7705 | +{ |
---|
| 7706 | + struct sctp_assoc_value params; |
---|
| 7707 | + struct sctp_association *asoc; |
---|
| 7708 | + int retval = -EFAULT; |
---|
| 7709 | + |
---|
| 7710 | + if (len < sizeof(params)) { |
---|
| 7711 | + retval = -EINVAL; |
---|
| 7712 | + goto out; |
---|
| 7713 | + } |
---|
| 7714 | + |
---|
| 7715 | + len = sizeof(params); |
---|
| 7716 | + if (copy_from_user(¶ms, optval, len)) |
---|
| 7717 | + goto out; |
---|
| 7718 | + |
---|
| 7719 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 7720 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7721 | + sctp_style(sk, UDP)) { |
---|
| 7722 | + retval = -EINVAL; |
---|
| 7723 | + goto out; |
---|
| 7724 | + } |
---|
| 7725 | + |
---|
| 7726 | + params.assoc_value = asoc ? asoc->peer.auth_capable |
---|
| 7727 | + : sctp_sk(sk)->ep->auth_enable; |
---|
| 7728 | + |
---|
| 7729 | + if (put_user(len, optlen)) |
---|
| 7730 | + goto out; |
---|
| 7731 | + |
---|
| 7732 | + if (copy_to_user(optval, ¶ms, len)) |
---|
| 7733 | + goto out; |
---|
| 7734 | + |
---|
| 7735 | + retval = 0; |
---|
| 7736 | + |
---|
| 7737 | +out: |
---|
| 7738 | + return retval; |
---|
| 7739 | +} |
---|
| 7740 | + |
---|
| 7741 | +static int sctp_getsockopt_ecn_supported(struct sock *sk, int len, |
---|
| 7742 | + char __user *optval, |
---|
| 7743 | + int __user *optlen) |
---|
| 7744 | +{ |
---|
| 7745 | + struct sctp_assoc_value params; |
---|
| 7746 | + struct sctp_association *asoc; |
---|
| 7747 | + int retval = -EFAULT; |
---|
| 7748 | + |
---|
| 7749 | + if (len < sizeof(params)) { |
---|
| 7750 | + retval = -EINVAL; |
---|
| 7751 | + goto out; |
---|
| 7752 | + } |
---|
| 7753 | + |
---|
| 7754 | + len = sizeof(params); |
---|
| 7755 | + if (copy_from_user(¶ms, optval, len)) |
---|
| 7756 | + goto out; |
---|
| 7757 | + |
---|
| 7758 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 7759 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7760 | + sctp_style(sk, UDP)) { |
---|
| 7761 | + retval = -EINVAL; |
---|
| 7762 | + goto out; |
---|
| 7763 | + } |
---|
| 7764 | + |
---|
| 7765 | + params.assoc_value = asoc ? asoc->peer.ecn_capable |
---|
| 7766 | + : sctp_sk(sk)->ep->ecn_enable; |
---|
| 7767 | + |
---|
| 7768 | + if (put_user(len, optlen)) |
---|
| 7769 | + goto out; |
---|
| 7770 | + |
---|
| 7771 | + if (copy_to_user(optval, ¶ms, len)) |
---|
| 7772 | + goto out; |
---|
| 7773 | + |
---|
| 7774 | + retval = 0; |
---|
| 7775 | + |
---|
| 7776 | +out: |
---|
| 7777 | + return retval; |
---|
| 7778 | +} |
---|
| 7779 | + |
---|
| 7780 | +static int sctp_getsockopt_pf_expose(struct sock *sk, int len, |
---|
| 7781 | + char __user *optval, |
---|
| 7782 | + int __user *optlen) |
---|
| 7783 | +{ |
---|
| 7784 | + struct sctp_assoc_value params; |
---|
| 7785 | + struct sctp_association *asoc; |
---|
| 7786 | + int retval = -EFAULT; |
---|
| 7787 | + |
---|
| 7788 | + if (len < sizeof(params)) { |
---|
| 7789 | + retval = -EINVAL; |
---|
| 7790 | + goto out; |
---|
| 7791 | + } |
---|
| 7792 | + |
---|
| 7793 | + len = sizeof(params); |
---|
| 7794 | + if (copy_from_user(¶ms, optval, len)) |
---|
| 7795 | + goto out; |
---|
| 7796 | + |
---|
| 7797 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
---|
| 7798 | + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && |
---|
| 7799 | + sctp_style(sk, UDP)) { |
---|
| 7800 | + retval = -EINVAL; |
---|
| 7801 | + goto out; |
---|
| 7802 | + } |
---|
| 7803 | + |
---|
| 7804 | + params.assoc_value = asoc ? asoc->pf_expose |
---|
| 7805 | + : sctp_sk(sk)->pf_expose; |
---|
| 7806 | + |
---|
| 7807 | + if (put_user(len, optlen)) |
---|
| 7808 | + goto out; |
---|
| 7809 | + |
---|
| 7810 | + if (copy_to_user(optval, ¶ms, len)) |
---|
| 7811 | + goto out; |
---|
| 7812 | + |
---|
| 7813 | + retval = 0; |
---|
| 7814 | + |
---|
| 7815 | +out: |
---|
| 7816 | + return retval; |
---|
7407 | 7817 | } |
---|
7408 | 7818 | |
---|
7409 | 7819 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
---|
.. | .. |
---|
7555 | 7965 | retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen); |
---|
7556 | 7966 | break; |
---|
7557 | 7967 | case SCTP_PEER_ADDR_THLDS: |
---|
7558 | | - retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen); |
---|
| 7968 | + retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, |
---|
| 7969 | + optlen, false); |
---|
| 7970 | + break; |
---|
| 7971 | + case SCTP_PEER_ADDR_THLDS_V2: |
---|
| 7972 | + retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, |
---|
| 7973 | + optlen, true); |
---|
7559 | 7974 | break; |
---|
7560 | 7975 | case SCTP_GET_ASSOC_STATS: |
---|
7561 | 7976 | retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen); |
---|
.. | .. |
---|
7604 | 8019 | case SCTP_REUSE_PORT: |
---|
7605 | 8020 | retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen); |
---|
7606 | 8021 | break; |
---|
| 8022 | + case SCTP_EVENT: |
---|
| 8023 | + retval = sctp_getsockopt_event(sk, len, optval, optlen); |
---|
| 8024 | + break; |
---|
| 8025 | + case SCTP_ASCONF_SUPPORTED: |
---|
| 8026 | + retval = sctp_getsockopt_asconf_supported(sk, len, optval, |
---|
| 8027 | + optlen); |
---|
| 8028 | + break; |
---|
| 8029 | + case SCTP_AUTH_SUPPORTED: |
---|
| 8030 | + retval = sctp_getsockopt_auth_supported(sk, len, optval, |
---|
| 8031 | + optlen); |
---|
| 8032 | + break; |
---|
| 8033 | + case SCTP_ECN_SUPPORTED: |
---|
| 8034 | + retval = sctp_getsockopt_ecn_supported(sk, len, optval, optlen); |
---|
| 8035 | + break; |
---|
| 8036 | + case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE: |
---|
| 8037 | + retval = sctp_getsockopt_pf_expose(sk, len, optval, optlen); |
---|
| 8038 | + break; |
---|
7607 | 8039 | default: |
---|
7608 | 8040 | retval = -ENOPROTOOPT; |
---|
7609 | 8041 | break; |
---|
.. | .. |
---|
7639 | 8071 | static struct sctp_bind_bucket *sctp_bucket_create( |
---|
7640 | 8072 | struct sctp_bind_hashbucket *head, struct net *, unsigned short snum); |
---|
7641 | 8073 | |
---|
7642 | | -static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) |
---|
| 8074 | +static int sctp_get_port_local(struct sock *sk, union sctp_addr *addr) |
---|
7643 | 8075 | { |
---|
7644 | | - bool reuse = (sk->sk_reuse || sctp_sk(sk)->reuse); |
---|
| 8076 | + struct sctp_sock *sp = sctp_sk(sk); |
---|
| 8077 | + bool reuse = (sk->sk_reuse || sp->reuse); |
---|
7645 | 8078 | struct sctp_bind_hashbucket *head; /* hash list */ |
---|
| 8079 | + struct net *net = sock_net(sk); |
---|
| 8080 | + kuid_t uid = sock_i_uid(sk); |
---|
7646 | 8081 | struct sctp_bind_bucket *pp; |
---|
7647 | 8082 | unsigned short snum; |
---|
7648 | 8083 | int ret; |
---|
.. | .. |
---|
7655 | 8090 | /* Search for an available port. */ |
---|
7656 | 8091 | int low, high, remaining, index; |
---|
7657 | 8092 | unsigned int rover; |
---|
7658 | | - struct net *net = sock_net(sk); |
---|
7659 | 8093 | |
---|
7660 | 8094 | inet_get_local_port_range(net, &low, &high); |
---|
7661 | 8095 | remaining = (high - low) + 1; |
---|
.. | .. |
---|
7667 | 8101 | rover = low; |
---|
7668 | 8102 | if (inet_is_local_reserved_port(net, rover)) |
---|
7669 | 8103 | continue; |
---|
7670 | | - index = sctp_phashfn(sock_net(sk), rover); |
---|
| 8104 | + index = sctp_phashfn(net, rover); |
---|
7671 | 8105 | head = &sctp_port_hashtable[index]; |
---|
7672 | 8106 | spin_lock_bh(&head->lock); |
---|
7673 | 8107 | sctp_for_each_hentry(pp, &head->chain) |
---|
7674 | 8108 | if ((pp->port == rover) && |
---|
7675 | | - net_eq(sock_net(sk), pp->net)) |
---|
| 8109 | + net_eq(net, pp->net)) |
---|
7676 | 8110 | goto next; |
---|
7677 | 8111 | break; |
---|
7678 | 8112 | next: |
---|
.. | .. |
---|
7697 | 8131 | * to the port number (snum) - we detect that with the |
---|
7698 | 8132 | * port iterator, pp being NULL. |
---|
7699 | 8133 | */ |
---|
7700 | | - head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)]; |
---|
| 8134 | + head = &sctp_port_hashtable[sctp_phashfn(net, snum)]; |
---|
7701 | 8135 | spin_lock_bh(&head->lock); |
---|
7702 | 8136 | sctp_for_each_hentry(pp, &head->chain) { |
---|
7703 | | - if ((pp->port == snum) && net_eq(pp->net, sock_net(sk))) |
---|
| 8137 | + if ((pp->port == snum) && net_eq(pp->net, net)) |
---|
7704 | 8138 | goto pp_found; |
---|
7705 | 8139 | } |
---|
7706 | 8140 | } |
---|
.. | .. |
---|
7717 | 8151 | |
---|
7718 | 8152 | pr_debug("%s: found a possible match\n", __func__); |
---|
7719 | 8153 | |
---|
7720 | | - if (pp->fastreuse && reuse && sk->sk_state != SCTP_SS_LISTENING) |
---|
| 8154 | + if ((pp->fastreuse && reuse && |
---|
| 8155 | + sk->sk_state != SCTP_SS_LISTENING) || |
---|
| 8156 | + (pp->fastreuseport && sk->sk_reuseport && |
---|
| 8157 | + uid_eq(pp->fastuid, uid))) |
---|
7721 | 8158 | goto success; |
---|
7722 | 8159 | |
---|
7723 | 8160 | /* Run through the list of sockets bound to the port |
---|
.. | .. |
---|
7731 | 8168 | * in an endpoint. |
---|
7732 | 8169 | */ |
---|
7733 | 8170 | sk_for_each_bound(sk2, &pp->owner) { |
---|
7734 | | - struct sctp_endpoint *ep2; |
---|
7735 | | - ep2 = sctp_sk(sk2)->ep; |
---|
| 8171 | + struct sctp_sock *sp2 = sctp_sk(sk2); |
---|
| 8172 | + struct sctp_endpoint *ep2 = sp2->ep; |
---|
7736 | 8173 | |
---|
7737 | 8174 | if (sk == sk2 || |
---|
7738 | | - (reuse && (sk2->sk_reuse || sctp_sk(sk2)->reuse) && |
---|
7739 | | - sk2->sk_state != SCTP_SS_LISTENING)) |
---|
| 8175 | + (reuse && (sk2->sk_reuse || sp2->reuse) && |
---|
| 8176 | + sk2->sk_state != SCTP_SS_LISTENING) || |
---|
| 8177 | + (sk->sk_reuseport && sk2->sk_reuseport && |
---|
| 8178 | + uid_eq(uid, sock_i_uid(sk2)))) |
---|
7740 | 8179 | continue; |
---|
7741 | 8180 | |
---|
7742 | | - if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr, |
---|
7743 | | - sctp_sk(sk2), sctp_sk(sk))) { |
---|
7744 | | - ret = (long)sk2; |
---|
| 8181 | + if (sctp_bind_addr_conflict(&ep2->base.bind_addr, |
---|
| 8182 | + addr, sp2, sp)) { |
---|
| 8183 | + ret = 1; |
---|
7745 | 8184 | goto fail_unlock; |
---|
7746 | 8185 | } |
---|
7747 | 8186 | } |
---|
.. | .. |
---|
7751 | 8190 | pp_not_found: |
---|
7752 | 8191 | /* If there was a hash table miss, create a new port. */ |
---|
7753 | 8192 | ret = 1; |
---|
7754 | | - if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum))) |
---|
| 8193 | + if (!pp && !(pp = sctp_bucket_create(head, net, snum))) |
---|
7755 | 8194 | goto fail_unlock; |
---|
7756 | 8195 | |
---|
7757 | 8196 | /* In either case (hit or miss), make sure fastreuse is 1 only |
---|
.. | .. |
---|
7763 | 8202 | pp->fastreuse = 1; |
---|
7764 | 8203 | else |
---|
7765 | 8204 | pp->fastreuse = 0; |
---|
7766 | | - } else if (pp->fastreuse && |
---|
7767 | | - (!reuse || sk->sk_state == SCTP_SS_LISTENING)) |
---|
7768 | | - pp->fastreuse = 0; |
---|
| 8205 | + |
---|
| 8206 | + if (sk->sk_reuseport) { |
---|
| 8207 | + pp->fastreuseport = 1; |
---|
| 8208 | + pp->fastuid = uid; |
---|
| 8209 | + } else { |
---|
| 8210 | + pp->fastreuseport = 0; |
---|
| 8211 | + } |
---|
| 8212 | + } else { |
---|
| 8213 | + if (pp->fastreuse && |
---|
| 8214 | + (!reuse || sk->sk_state == SCTP_SS_LISTENING)) |
---|
| 8215 | + pp->fastreuse = 0; |
---|
| 8216 | + |
---|
| 8217 | + if (pp->fastreuseport && |
---|
| 8218 | + (!sk->sk_reuseport || !uid_eq(pp->fastuid, uid))) |
---|
| 8219 | + pp->fastreuseport = 0; |
---|
| 8220 | + } |
---|
7769 | 8221 | |
---|
7770 | 8222 | /* We are set, so fill up all the data in the hash table |
---|
7771 | 8223 | * entry, tie the socket list information with the rest of the |
---|
7772 | 8224 | * sockets FIXME: Blurry, NPI (ipg). |
---|
7773 | 8225 | */ |
---|
7774 | 8226 | success: |
---|
7775 | | - if (!sctp_sk(sk)->bind_hash) { |
---|
| 8227 | + if (!sp->bind_hash) { |
---|
7776 | 8228 | inet_sk(sk)->inet_num = snum; |
---|
7777 | 8229 | sk_add_bind_node(sk, &pp->owner); |
---|
7778 | | - sctp_sk(sk)->bind_hash = pp; |
---|
| 8230 | + sp->bind_hash = pp; |
---|
7779 | 8231 | } |
---|
7780 | 8232 | ret = 0; |
---|
7781 | 8233 | |
---|
.. | .. |
---|
7797 | 8249 | addr.v4.sin_port = htons(snum); |
---|
7798 | 8250 | |
---|
7799 | 8251 | /* Note: sk->sk_num gets filled in if ephemeral port request. */ |
---|
7800 | | - return !!sctp_get_port_local(sk, &addr); |
---|
| 8252 | + return sctp_get_port_local(sk, &addr); |
---|
7801 | 8253 | } |
---|
7802 | 8254 | |
---|
7803 | 8255 | /* |
---|
.. | .. |
---|
7844 | 8296 | } |
---|
7845 | 8297 | } |
---|
7846 | 8298 | |
---|
7847 | | - sk->sk_max_ack_backlog = backlog; |
---|
7848 | | - sctp_hash_endpoint(ep); |
---|
7849 | | - return 0; |
---|
| 8299 | + WRITE_ONCE(sk->sk_max_ack_backlog, backlog); |
---|
| 8300 | + return sctp_hash_endpoint(ep); |
---|
7850 | 8301 | } |
---|
7851 | 8302 | |
---|
7852 | 8303 | /* |
---|
.. | .. |
---|
7899 | 8350 | |
---|
7900 | 8351 | /* If we are already listening, just update the backlog */ |
---|
7901 | 8352 | if (sctp_sstate(sk, LISTENING)) |
---|
7902 | | - sk->sk_max_ack_backlog = backlog; |
---|
| 8353 | + WRITE_ONCE(sk->sk_max_ack_backlog, backlog); |
---|
7903 | 8354 | else { |
---|
7904 | 8355 | err = sctp_listen_start(sk, backlog); |
---|
7905 | 8356 | if (err) |
---|
.. | .. |
---|
8438 | 8889 | struct sctp_association *asoc = chunk->asoc; |
---|
8439 | 8890 | struct sock *sk = asoc->base.sk; |
---|
8440 | 8891 | |
---|
8441 | | - asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) + |
---|
8442 | | - sizeof(struct sk_buff) + |
---|
8443 | | - sizeof(struct sctp_chunk); |
---|
8444 | | - |
---|
8445 | | - WARN_ON(refcount_sub_and_test(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc)); |
---|
8446 | | - |
---|
8447 | | - /* |
---|
8448 | | - * This undoes what is done via sctp_set_owner_w and sk_mem_charge |
---|
8449 | | - */ |
---|
8450 | | - sk->sk_wmem_queued -= skb->truesize; |
---|
8451 | 8892 | sk_mem_uncharge(sk, skb->truesize); |
---|
| 8893 | + sk_wmem_queued_add(sk, -(skb->truesize + sizeof(struct sctp_chunk))); |
---|
| 8894 | + asoc->sndbuf_used -= skb->truesize + sizeof(struct sctp_chunk); |
---|
| 8895 | + WARN_ON(refcount_sub_and_test(sizeof(struct sctp_chunk), |
---|
| 8896 | + &sk->sk_wmem_alloc)); |
---|
8452 | 8897 | |
---|
8453 | 8898 | if (chunk->shkey) { |
---|
8454 | 8899 | struct sctp_shared_key *shkey = chunk->shkey; |
---|
.. | .. |
---|
8600 | 9045 | * UDP-style sockets or TCP-style sockets, this code should work. |
---|
8601 | 9046 | * - Daisy |
---|
8602 | 9047 | */ |
---|
8603 | | -static bool sctp_writeable(struct sock *sk) |
---|
| 9048 | +static bool sctp_writeable(const struct sock *sk) |
---|
8604 | 9049 | { |
---|
8605 | | - return sk->sk_sndbuf > sk->sk_wmem_queued; |
---|
| 9050 | + return READ_ONCE(sk->sk_sndbuf) > READ_ONCE(sk->sk_wmem_queued); |
---|
8606 | 9051 | } |
---|
8607 | 9052 | |
---|
8608 | 9053 | /* Wait for an association to go into ESTABLISHED state. If timeout is 0, |
---|
.. | .. |
---|
8760 | 9205 | sctp_sk(newsk)->reuse = sp->reuse; |
---|
8761 | 9206 | |
---|
8762 | 9207 | newsk->sk_shutdown = sk->sk_shutdown; |
---|
8763 | | - newsk->sk_destruct = sctp_destruct_sock; |
---|
| 9208 | + newsk->sk_destruct = sk->sk_destruct; |
---|
8764 | 9209 | newsk->sk_family = sk->sk_family; |
---|
8765 | 9210 | newsk->sk_protocol = IPPROTO_SCTP; |
---|
8766 | 9211 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; |
---|
.. | .. |
---|
8801 | 9246 | static inline void sctp_copy_descendant(struct sock *sk_to, |
---|
8802 | 9247 | const struct sock *sk_from) |
---|
8803 | 9248 | { |
---|
8804 | | - int ancestor_size = sizeof(struct inet_sock) + |
---|
8805 | | - sizeof(struct sctp_sock) - |
---|
8806 | | - offsetof(struct sctp_sock, auto_asconf_list); |
---|
| 9249 | + size_t ancestor_size = sizeof(struct inet_sock); |
---|
8807 | 9250 | |
---|
8808 | | - if (sk_from->sk_family == PF_INET6) |
---|
8809 | | - ancestor_size += sizeof(struct ipv6_pinfo); |
---|
8810 | | - |
---|
| 9251 | + ancestor_size += sk_from->sk_prot->obj_size; |
---|
| 9252 | + ancestor_size -= offsetof(struct sctp_sock, pd_lobby); |
---|
8811 | 9253 | __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size); |
---|
8812 | 9254 | } |
---|
8813 | 9255 | |
---|
8814 | 9256 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
---|
8815 | 9257 | * and its messages to the newsk. |
---|
8816 | 9258 | */ |
---|
8817 | | -static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, |
---|
8818 | | - struct sctp_association *assoc, |
---|
8819 | | - enum sctp_socket_type type) |
---|
| 9259 | +static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, |
---|
| 9260 | + struct sctp_association *assoc, |
---|
| 9261 | + enum sctp_socket_type type) |
---|
8820 | 9262 | { |
---|
8821 | 9263 | struct sctp_sock *oldsp = sctp_sk(oldsk); |
---|
8822 | 9264 | struct sctp_sock *newsp = sctp_sk(newsk); |
---|
.. | .. |
---|
8825 | 9267 | struct sk_buff *skb, *tmp; |
---|
8826 | 9268 | struct sctp_ulpevent *event; |
---|
8827 | 9269 | struct sctp_bind_hashbucket *head; |
---|
| 9270 | + int err; |
---|
8828 | 9271 | |
---|
8829 | 9272 | /* Migrate socket buffer sizes and all the socket level options to the |
---|
8830 | 9273 | * new socket. |
---|
.. | .. |
---|
8853 | 9296 | /* Copy the bind_addr list from the original endpoint to the new |
---|
8854 | 9297 | * endpoint so that we can handle restarts properly |
---|
8855 | 9298 | */ |
---|
8856 | | - sctp_bind_addr_dup(&newsp->ep->base.bind_addr, |
---|
8857 | | - &oldsp->ep->base.bind_addr, GFP_KERNEL); |
---|
| 9299 | + err = sctp_bind_addr_dup(&newsp->ep->base.bind_addr, |
---|
| 9300 | + &oldsp->ep->base.bind_addr, GFP_KERNEL); |
---|
| 9301 | + if (err) |
---|
| 9302 | + return err; |
---|
| 9303 | + |
---|
| 9304 | + /* New ep's auth_hmacs should be set if old ep's is set, in case |
---|
| 9305 | + * that net->sctp.auth_enable has been changed to 0 by users and |
---|
| 9306 | + * new ep's auth_hmacs couldn't be set in sctp_endpoint_init(). |
---|
| 9307 | + */ |
---|
| 9308 | + if (oldsp->ep->auth_hmacs) { |
---|
| 9309 | + err = sctp_auth_init_hmacs(newsp->ep, GFP_KERNEL); |
---|
| 9310 | + if (err) |
---|
| 9311 | + return err; |
---|
| 9312 | + } |
---|
8858 | 9313 | |
---|
8859 | 9314 | sctp_auto_asconf_init(newsp); |
---|
8860 | 9315 | |
---|
.. | .. |
---|
8876 | 9331 | * 2) Peeling off partial delivery; keep pd_lobby in new pd_lobby. |
---|
8877 | 9332 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. |
---|
8878 | 9333 | */ |
---|
8879 | | - skb_queue_head_init(&newsp->pd_lobby); |
---|
8880 | 9334 | atomic_set(&sctp_sk(newsk)->pd_mode, assoc->ulpq.pd_mode); |
---|
8881 | 9335 | |
---|
8882 | 9336 | if (atomic_read(&sctp_sk(oldsk)->pd_mode)) { |
---|
.. | .. |
---|
8941 | 9395 | } |
---|
8942 | 9396 | |
---|
8943 | 9397 | release_sock(newsk); |
---|
| 9398 | + |
---|
| 9399 | + return 0; |
---|
8944 | 9400 | } |
---|
8945 | 9401 | |
---|
8946 | 9402 | |
---|
.. | .. |
---|
8960 | 9416 | .sendmsg = sctp_sendmsg, |
---|
8961 | 9417 | .recvmsg = sctp_recvmsg, |
---|
8962 | 9418 | .bind = sctp_bind, |
---|
| 9419 | + .bind_add = sctp_bind_add, |
---|
8963 | 9420 | .backlog_rcv = sctp_backlog_rcv, |
---|
8964 | 9421 | .hash = sctp_hash, |
---|
8965 | 9422 | .unhash = sctp_unhash, |
---|
.. | .. |
---|
8980 | 9437 | |
---|
8981 | 9438 | #if IS_ENABLED(CONFIG_IPV6) |
---|
8982 | 9439 | |
---|
8983 | | -#include <net/transp_v6.h> |
---|
8984 | | -static void sctp_v6_destroy_sock(struct sock *sk) |
---|
| 9440 | +static void sctp_v6_destruct_sock(struct sock *sk) |
---|
8985 | 9441 | { |
---|
8986 | | - sctp_destroy_sock(sk); |
---|
8987 | | - inet6_destroy_sock(sk); |
---|
| 9442 | + sctp_destruct_common(sk); |
---|
| 9443 | + inet6_sock_destruct(sk); |
---|
| 9444 | +} |
---|
| 9445 | + |
---|
| 9446 | +static int sctp_v6_init_sock(struct sock *sk) |
---|
| 9447 | +{ |
---|
| 9448 | + int ret = sctp_init_sock(sk); |
---|
| 9449 | + |
---|
| 9450 | + if (!ret) |
---|
| 9451 | + sk->sk_destruct = sctp_v6_destruct_sock; |
---|
| 9452 | + |
---|
| 9453 | + return ret; |
---|
8988 | 9454 | } |
---|
8989 | 9455 | |
---|
8990 | 9456 | struct proto sctpv6_prot = { |
---|
.. | .. |
---|
8994 | 9460 | .disconnect = sctp_disconnect, |
---|
8995 | 9461 | .accept = sctp_accept, |
---|
8996 | 9462 | .ioctl = sctp_ioctl, |
---|
8997 | | - .init = sctp_init_sock, |
---|
8998 | | - .destroy = sctp_v6_destroy_sock, |
---|
| 9463 | + .init = sctp_v6_init_sock, |
---|
| 9464 | + .destroy = sctp_destroy_sock, |
---|
8999 | 9465 | .shutdown = sctp_shutdown, |
---|
9000 | 9466 | .setsockopt = sctp_setsockopt, |
---|
9001 | 9467 | .getsockopt = sctp_getsockopt, |
---|
9002 | 9468 | .sendmsg = sctp_sendmsg, |
---|
9003 | 9469 | .recvmsg = sctp_recvmsg, |
---|
9004 | 9470 | .bind = sctp_bind, |
---|
| 9471 | + .bind_add = sctp_bind_add, |
---|
9005 | 9472 | .backlog_rcv = sctp_backlog_rcv, |
---|
9006 | 9473 | .hash = sctp_hash, |
---|
9007 | 9474 | .unhash = sctp_unhash, |
---|