diff options
author | Frank Filz <ffilzlnx@us.ibm.com> | 2005-06-20 16:14:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-20 16:14:57 -0400 |
commit | 3f7a87d2fa9b42f7aade43914f060df68cc89cc7 (patch) | |
tree | 15162d2dd770428f98a0d39f8dc6063aba0ad1e6 /net/sctp/socket.c | |
parent | 8b22c249e7de453961e4d253b19fc2a0bdd65d53 (diff) |
[SCTP] sctp_connectx() API support
Implements sctp_connectx() as defined in the SCTP sockets API draft by
tunneling the request through a setsockopt().
Signed-off-by: Frank Filz <ffilzlnx@us.ibm.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 405 |
1 files changed, 288 insertions, 117 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e6926cb19420..aad55dc3792b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
262 | * sockaddr_in6 [RFC 2553]), | 262 | * sockaddr_in6 [RFC 2553]), |
263 | * addr_len - the size of the address structure. | 263 | * addr_len - the size of the address structure. |
264 | */ | 264 | */ |
265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) |
266 | { | 266 | { |
267 | int retval = 0; | 267 | int retval = 0; |
268 | 268 | ||
269 | sctp_lock_sock(sk); | 269 | sctp_lock_sock(sk); |
270 | 270 | ||
271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n", | 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", |
272 | sk, uaddr, addr_len); | 272 | sk, addr, addr_len); |
273 | 273 | ||
274 | /* Disallow binding twice. */ | 274 | /* Disallow binding twice. */ |
275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) | 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) |
276 | retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, | 276 | retval = sctp_do_bind(sk, (union sctp_addr *)addr, |
277 | addr_len); | 277 | addr_len); |
278 | else | 278 | else |
279 | retval = -EINVAL; | 279 | retval = -EINVAL; |
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
318 | unsigned short snum; | 318 | unsigned short snum; |
319 | int ret = 0; | 319 | int ret = 0; |
320 | 320 | ||
321 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n", | ||
322 | sk, addr, len); | ||
323 | |||
324 | /* Common sockaddr verification. */ | 321 | /* Common sockaddr verification. */ |
325 | af = sctp_sockaddr_af(sp, addr, len); | 322 | af = sctp_sockaddr_af(sp, addr, len); |
326 | if (!af) | 323 | if (!af) { |
324 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", | ||
325 | sk, addr, len); | ||
327 | return -EINVAL; | 326 | return -EINVAL; |
327 | } | ||
328 | |||
329 | snum = ntohs(addr->v4.sin_port); | ||
330 | |||
331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", | ||
332 | ", port: %d, new port: %d, len: %d)\n", | ||
333 | sk, | ||
334 | addr, | ||
335 | bp->port, snum, | ||
336 | len); | ||
328 | 337 | ||
329 | /* PF specific bind() address verification. */ | 338 | /* PF specific bind() address verification. */ |
330 | if (!sp->pf->bind_verify(sp, addr)) | 339 | if (!sp->pf->bind_verify(sp, addr)) |
331 | return -EADDRNOTAVAIL; | 340 | return -EADDRNOTAVAIL; |
332 | 341 | ||
333 | snum= ntohs(addr->v4.sin_port); | ||
334 | |||
335 | SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n", | ||
336 | bp->port, snum); | ||
337 | |||
338 | /* We must either be unbound, or bind to the same port. */ | 342 | /* We must either be unbound, or bind to the same port. */ |
339 | if (bp->port && (snum != bp->port)) { | 343 | if (bp->port && (snum != bp->port)) { |
340 | SCTP_DEBUG_PRINTK("sctp_do_bind:" | 344 | SCTP_DEBUG_PRINTK("sctp_do_bind:" |
@@ -816,7 +820,8 @@ out: | |||
816 | * | 820 | * |
817 | * Basically do nothing but copying the addresses from user to kernel | 821 | * Basically do nothing but copying the addresses from user to kernel |
818 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. | 822 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. |
819 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. | 823 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
824 | * from userspace. | ||
820 | * | 825 | * |
821 | * We don't use copy_from_user() for optimization: we first do the | 826 | * We don't use copy_from_user() for optimization: we first do the |
822 | * sanity checks (buffer size -fast- and access check-healthy | 827 | * sanity checks (buffer size -fast- and access check-healthy |
@@ -913,6 +918,243 @@ out: | |||
913 | return err; | 918 | return err; |
914 | } | 919 | } |
915 | 920 | ||
921 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) | ||
922 | * | ||
923 | * Common routine for handling connect() and sctp_connectx(). | ||
924 | * Connect will come in with just a single address. | ||
925 | */ | ||
926 | static int __sctp_connect(struct sock* sk, | ||
927 | struct sockaddr *kaddrs, | ||
928 | int addrs_size) | ||
929 | { | ||
930 | struct sctp_sock *sp; | ||
931 | struct sctp_endpoint *ep; | ||
932 | struct sctp_association *asoc = NULL; | ||
933 | struct sctp_association *asoc2; | ||
934 | struct sctp_transport *transport; | ||
935 | union sctp_addr to; | ||
936 | struct sctp_af *af; | ||
937 | sctp_scope_t scope; | ||
938 | long timeo; | ||
939 | int err = 0; | ||
940 | int addrcnt = 0; | ||
941 | int walk_size = 0; | ||
942 | struct sockaddr *sa_addr; | ||
943 | void *addr_buf; | ||
944 | |||
945 | sp = sctp_sk(sk); | ||
946 | ep = sp->ep; | ||
947 | |||
948 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
949 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
950 | * is already connected. | ||
951 | * It cannot be done even on a TCP-style listening socket. | ||
952 | */ | ||
953 | if (sctp_sstate(sk, ESTABLISHED) || | ||
954 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
955 | err = -EISCONN; | ||
956 | goto out_free; | ||
957 | } | ||
958 | |||
959 | /* Walk through the addrs buffer and count the number of addresses. */ | ||
960 | addr_buf = kaddrs; | ||
961 | while (walk_size < addrs_size) { | ||
962 | sa_addr = (struct sockaddr *)addr_buf; | ||
963 | af = sctp_get_af_specific(sa_addr->sa_family); | ||
964 | |||
965 | /* If the address family is not supported or if this address | ||
966 | * causes the address buffer to overflow return EINVAL. | ||
967 | */ | ||
968 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | ||
969 | err = -EINVAL; | ||
970 | goto out_free; | ||
971 | } | ||
972 | |||
973 | err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, | ||
974 | af->sockaddr_len); | ||
975 | if (err) | ||
976 | goto out_free; | ||
977 | |||
978 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
979 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
980 | |||
981 | /* Check if there already is a matching association on the | ||
982 | * endpoint (other than the one created here). | ||
983 | */ | ||
984 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
985 | if (asoc2 && asoc2 != asoc) { | ||
986 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | ||
987 | err = -EISCONN; | ||
988 | else | ||
989 | err = -EALREADY; | ||
990 | goto out_free; | ||
991 | } | ||
992 | |||
993 | /* If we could not find a matching association on the endpoint, | ||
994 | * make sure that there is no peeled-off association matching | ||
995 | * the peer address even on another socket. | ||
996 | */ | ||
997 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
998 | err = -EADDRNOTAVAIL; | ||
999 | goto out_free; | ||
1000 | } | ||
1001 | |||
1002 | if (!asoc) { | ||
1003 | /* If a bind() or sctp_bindx() is not called prior to | ||
1004 | * an sctp_connectx() call, the system picks an | ||
1005 | * ephemeral port and will choose an address set | ||
1006 | * equivalent to binding with a wildcard address. | ||
1007 | */ | ||
1008 | if (!ep->base.bind_addr.port) { | ||
1009 | if (sctp_autobind(sk)) { | ||
1010 | err = -EAGAIN; | ||
1011 | goto out_free; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | scope = sctp_scope(&to); | ||
1016 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
1017 | if (!asoc) { | ||
1018 | err = -ENOMEM; | ||
1019 | goto out_free; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | /* Prime the peer's transport structures. */ | ||
1024 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, | ||
1025 | SCTP_UNKNOWN); | ||
1026 | if (!transport) { | ||
1027 | err = -ENOMEM; | ||
1028 | goto out_free; | ||
1029 | } | ||
1030 | |||
1031 | addrcnt++; | ||
1032 | addr_buf += af->sockaddr_len; | ||
1033 | walk_size += af->sockaddr_len; | ||
1034 | } | ||
1035 | |||
1036 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | ||
1037 | if (err < 0) { | ||
1038 | goto out_free; | ||
1039 | } | ||
1040 | |||
1041 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
1042 | if (err < 0) { | ||
1043 | goto out_free; | ||
1044 | } | ||
1045 | |||
1046 | /* Initialize sk's dport and daddr for getpeername() */ | ||
1047 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
1048 | af = sctp_get_af_specific(to.sa.sa_family); | ||
1049 | af->to_sk_daddr(&to, sk); | ||
1050 | |||
1051 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
1052 | err = sctp_wait_for_connect(asoc, &timeo); | ||
1053 | |||
1054 | /* Don't free association on exit. */ | ||
1055 | asoc = NULL; | ||
1056 | |||
1057 | out_free: | ||
1058 | |||
1059 | SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" | ||
1060 | " kaddrs: %p err: %d\n", | ||
1061 | asoc, kaddrs, err); | ||
1062 | if (asoc) | ||
1063 | sctp_association_free(asoc); | ||
1064 | return err; | ||
1065 | } | ||
1066 | |||
1067 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | ||
1068 | * | ||
1069 | * API 8.9 | ||
1070 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | ||
1071 | * | ||
1072 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | ||
1073 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | ||
1074 | * or IPv6 addresses. | ||
1075 | * | ||
1076 | * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see | ||
1077 | * Section 3.1.2 for this usage. | ||
1078 | * | ||
1079 | * addrs is a pointer to an array of one or more socket addresses. Each | ||
1080 | * address is contained in its appropriate structure (i.e. struct | ||
1081 | * sockaddr_in or struct sockaddr_in6) the family of the address type | ||
1082 | * must be used to distengish the address length (note that this | ||
1083 | * representation is termed a "packed array" of addresses). The caller | ||
1084 | * specifies the number of addresses in the array with addrcnt. | ||
1085 | * | ||
1086 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | ||
1087 | * -1, and sets errno to the appropriate error code. | ||
1088 | * | ||
1089 | * For SCTP, the port given in each socket address must be the same, or | ||
1090 | * sctp_connectx() will fail, setting errno to EINVAL. | ||
1091 | * | ||
1092 | * An application can use sctp_connectx to initiate an association with | ||
1093 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | ||
1094 | * allows a caller to specify multiple addresses at which a peer can be | ||
1095 | * reached. The way the SCTP stack uses the list of addresses to set up | ||
1096 | * the association is implementation dependant. This function only | ||
1097 | * specifies that the stack will try to make use of all the addresses in | ||
1098 | * the list when needed. | ||
1099 | * | ||
1100 | * Note that the list of addresses passed in is only used for setting up | ||
1101 | * the association. It does not necessarily equal the set of addresses | ||
1102 | * the peer uses for the resulting association. If the caller wants to | ||
1103 | * find out the set of peer addresses, it must use sctp_getpaddrs() to | ||
1104 | * retrieve them after the association has been set up. | ||
1105 | * | ||
1106 | * Basically do nothing but copying the addresses from user to kernel | ||
1107 | * land and invoking either sctp_connectx(). This is used for tunneling | ||
1108 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | ||
1109 | * | ||
1110 | * We don't use copy_from_user() for optimization: we first do the | ||
1111 | * sanity checks (buffer size -fast- and access check-healthy | ||
1112 | * pointer); if all of those succeed, then we can alloc the memory | ||
1113 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
1114 | * the copying without checking the user space area | ||
1115 | * (__copy_from_user()). | ||
1116 | * | ||
1117 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | ||
1118 | * it. | ||
1119 | * | ||
1120 | * sk The sk of the socket | ||
1121 | * addrs The pointer to the addresses in user land | ||
1122 | * addrssize Size of the addrs buffer | ||
1123 | * | ||
1124 | * Returns 0 if ok, <0 errno code on error. | ||
1125 | */ | ||
1126 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
1127 | struct sockaddr __user *addrs, | ||
1128 | int addrs_size) | ||
1129 | { | ||
1130 | int err = 0; | ||
1131 | struct sockaddr *kaddrs; | ||
1132 | |||
1133 | SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", | ||
1134 | __FUNCTION__, sk, addrs, addrs_size); | ||
1135 | |||
1136 | if (unlikely(addrs_size <= 0)) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | /* Check the user passed a healthy pointer. */ | ||
1140 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | ||
1141 | return -EFAULT; | ||
1142 | |||
1143 | /* Alloc space for the address array in kernel memory. */ | ||
1144 | kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); | ||
1145 | if (unlikely(!kaddrs)) | ||
1146 | return -ENOMEM; | ||
1147 | |||
1148 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
1149 | err = -EFAULT; | ||
1150 | } else { | ||
1151 | err = __sctp_connect(sk, kaddrs, addrs_size); | ||
1152 | } | ||
1153 | |||
1154 | kfree(kaddrs); | ||
1155 | return err; | ||
1156 | } | ||
1157 | |||
916 | /* API 3.1.4 close() - UDP Style Syntax | 1158 | /* API 3.1.4 close() - UDP Style Syntax |
917 | * Applications use close() to perform graceful shutdown (as described in | 1159 | * Applications use close() to perform graceful shutdown (as described in |
918 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1160 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
@@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1095 | sp = sctp_sk(sk); | 1337 | sp = sctp_sk(sk); |
1096 | ep = sp->ep; | 1338 | ep = sp->ep; |
1097 | 1339 | ||
1098 | SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); | 1340 | SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); |
1099 | 1341 | ||
1100 | /* We cannot send a message over a TCP-style listening socket. */ | 1342 | /* We cannot send a message over a TCP-style listening socket. */ |
1101 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { | 1343 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { |
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1306 | } | 1548 | } |
1307 | 1549 | ||
1308 | /* Prime the peer's transport structures. */ | 1550 | /* Prime the peer's transport structures. */ |
1309 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 1551 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); |
1310 | if (!transport) { | 1552 | if (!transport) { |
1311 | err = -ENOMEM; | 1553 | err = -ENOMEM; |
1312 | goto out_free; | 1554 | goto out_free; |
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2208 | optlen, SCTP_BINDX_REM_ADDR); | 2450 | optlen, SCTP_BINDX_REM_ADDR); |
2209 | break; | 2451 | break; |
2210 | 2452 | ||
2453 | case SCTP_SOCKOPT_CONNECTX: | ||
2454 | /* 'optlen' is the size of the addresses buffer. */ | ||
2455 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | ||
2456 | optlen); | ||
2457 | break; | ||
2458 | |||
2211 | case SCTP_DISABLE_FRAGMENTS: | 2459 | case SCTP_DISABLE_FRAGMENTS: |
2212 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); | 2460 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
2213 | break; | 2461 | break; |
@@ -2283,112 +2531,29 @@ out_nounlock: | |||
2283 | * | 2531 | * |
2284 | * len: the size of the address. | 2532 | * len: the size of the address. |
2285 | */ | 2533 | */ |
2286 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, | 2534 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, |
2287 | int addr_len) | 2535 | int addr_len) |
2288 | { | 2536 | { |
2289 | struct sctp_sock *sp; | ||
2290 | struct sctp_endpoint *ep; | ||
2291 | struct sctp_association *asoc; | ||
2292 | struct sctp_transport *transport; | ||
2293 | union sctp_addr to; | ||
2294 | struct sctp_af *af; | ||
2295 | sctp_scope_t scope; | ||
2296 | long timeo; | ||
2297 | int err = 0; | 2537 | int err = 0; |
2538 | struct sctp_af *af; | ||
2298 | 2539 | ||
2299 | sctp_lock_sock(sk); | 2540 | sctp_lock_sock(sk); |
2300 | 2541 | ||
2301 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", | 2542 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", |
2302 | __FUNCTION__, sk, uaddr, addr_len); | 2543 | __FUNCTION__, sk, addr, addr_len); |
2303 | |||
2304 | sp = sctp_sk(sk); | ||
2305 | ep = sp->ep; | ||
2306 | |||
2307 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
2308 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
2309 | * is already connected. | ||
2310 | * It cannot be done even on a TCP-style listening socket. | ||
2311 | */ | ||
2312 | if (sctp_sstate(sk, ESTABLISHED) || | ||
2313 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
2314 | err = -EISCONN; | ||
2315 | goto out_unlock; | ||
2316 | } | ||
2317 | |||
2318 | err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len); | ||
2319 | if (err) | ||
2320 | goto out_unlock; | ||
2321 | |||
2322 | if (addr_len > sizeof(to)) | ||
2323 | addr_len = sizeof(to); | ||
2324 | memcpy(&to, uaddr, addr_len); | ||
2325 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
2326 | |||
2327 | asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
2328 | if (asoc) { | ||
2329 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
2330 | err = -EISCONN; | ||
2331 | else | ||
2332 | err = -EALREADY; | ||
2333 | goto out_unlock; | ||
2334 | } | ||
2335 | |||
2336 | /* If we could not find a matching association on the endpoint, | ||
2337 | * make sure that there is no peeled-off association matching the | ||
2338 | * peer address even on another socket. | ||
2339 | */ | ||
2340 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
2341 | err = -EADDRNOTAVAIL; | ||
2342 | goto out_unlock; | ||
2343 | } | ||
2344 | |||
2345 | /* If a bind() or sctp_bindx() is not called prior to a connect() | ||
2346 | * call, the system picks an ephemeral port and will choose an address | ||
2347 | * set equivalent to binding with a wildcard address. | ||
2348 | */ | ||
2349 | if (!ep->base.bind_addr.port) { | ||
2350 | if (sctp_autobind(sk)) { | ||
2351 | err = -EAGAIN; | ||
2352 | goto out_unlock; | ||
2353 | } | ||
2354 | } | ||
2355 | |||
2356 | scope = sctp_scope(&to); | ||
2357 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
2358 | if (!asoc) { | ||
2359 | err = -ENOMEM; | ||
2360 | goto out_unlock; | ||
2361 | } | ||
2362 | 2544 | ||
2363 | /* Prime the peer's transport structures. */ | 2545 | /* Validate addr_len before calling common connect/connectx routine. */ |
2364 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 2546 | af = sctp_get_af_specific(addr->sa_family); |
2365 | if (!transport) { | 2547 | if (!af || addr_len < af->sockaddr_len) { |
2366 | sctp_association_free(asoc); | 2548 | err = -EINVAL; |
2367 | goto out_unlock; | 2549 | } else { |
2368 | } | 2550 | /* Pass correct addr len to common routine (so it knows there |
2369 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | 2551 | * is only one address being passed. |
2370 | if (err < 0) { | 2552 | */ |
2371 | sctp_association_free(asoc); | 2553 | err = __sctp_connect(sk, addr, af->sockaddr_len); |
2372 | goto out_unlock; | ||
2373 | } | ||
2374 | |||
2375 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
2376 | if (err < 0) { | ||
2377 | sctp_association_free(asoc); | ||
2378 | goto out_unlock; | ||
2379 | } | 2554 | } |
2380 | 2555 | ||
2381 | /* Initialize sk's dport and daddr for getpeername() */ | ||
2382 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
2383 | af = sctp_get_af_specific(to.sa.sa_family); | ||
2384 | af->to_sk_daddr(&to, sk); | ||
2385 | |||
2386 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
2387 | err = sctp_wait_for_connect(asoc, &timeo); | ||
2388 | |||
2389 | out_unlock: | ||
2390 | sctp_release_sock(sk); | 2556 | sctp_release_sock(sk); |
2391 | |||
2392 | return err; | 2557 | return err; |
2393 | } | 2558 | } |
2394 | 2559 | ||
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
2677 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 2842 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
2678 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 2843 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), |
2679 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 2844 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
2680 | status.sstat_primary.spinfo_state = transport->active; | 2845 | status.sstat_primary.spinfo_state = transport->state; |
2681 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 2846 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
2682 | status.sstat_primary.spinfo_srtt = transport->srtt; | 2847 | status.sstat_primary.spinfo_srtt = transport->srtt; |
2683 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 2848 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
2684 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 2849 | status.sstat_primary.spinfo_mtu = transport->pmtu; |
2685 | 2850 | ||
2851 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | ||
2852 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | ||
2853 | |||
2686 | if (put_user(len, optlen)) { | 2854 | if (put_user(len, optlen)) { |
2687 | retval = -EFAULT; | 2855 | retval = -EFAULT; |
2688 | goto out; | 2856 | goto out; |
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
2733 | return -EINVAL; | 2901 | return -EINVAL; |
2734 | 2902 | ||
2735 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); | 2903 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
2736 | pinfo.spinfo_state = transport->active; | 2904 | pinfo.spinfo_state = transport->state; |
2737 | pinfo.spinfo_cwnd = transport->cwnd; | 2905 | pinfo.spinfo_cwnd = transport->cwnd; |
2738 | pinfo.spinfo_srtt = transport->srtt; | 2906 | pinfo.spinfo_srtt = transport->srtt; |
2739 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 2907 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
2740 | pinfo.spinfo_mtu = transport->pmtu; | 2908 | pinfo.spinfo_mtu = transport->pmtu; |
2741 | 2909 | ||
2910 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | ||
2911 | pinfo.spinfo_state = SCTP_ACTIVE; | ||
2912 | |||
2742 | if (put_user(len, optlen)) { | 2913 | if (put_user(len, optlen)) { |
2743 | retval = -EFAULT; | 2914 | retval = -EFAULT; |
2744 | goto out; | 2915 | goto out; |
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
3591 | int retval = 0; | 3762 | int retval = 0; |
3592 | int len; | 3763 | int len; |
3593 | 3764 | ||
3594 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk); | 3765 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", |
3766 | sk, optname); | ||
3595 | 3767 | ||
3596 | /* I can hardly begin to describe how wrong this is. This is | 3768 | /* I can hardly begin to describe how wrong this is. This is |
3597 | * so broken as to be worse than useless. The API draft | 3769 | * so broken as to be worse than useless. The API draft |
@@ -4596,8 +4768,7 @@ out: | |||
4596 | return err; | 4768 | return err; |
4597 | 4769 | ||
4598 | do_error: | 4770 | do_error: |
4599 | if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >= | 4771 | if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) |
4600 | asoc->max_init_attempts) | ||
4601 | err = -ETIMEDOUT; | 4772 | err = -ETIMEDOUT; |
4602 | else | 4773 | else |
4603 | err = -ECONNREFUSED; | 4774 | err = -ECONNREFUSED; |