diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/sctp/associola.c | 4 | ||||
| -rw-r--r-- | net/sctp/socket.c | 42 |
2 files changed, 45 insertions, 1 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 39f5166ae7af..525864bf4f07 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1470,6 +1470,10 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) | |||
| 1470 | { | 1470 | { |
| 1471 | int assoc_id; | 1471 | int assoc_id; |
| 1472 | int error = 0; | 1472 | int error = 0; |
| 1473 | |||
| 1474 | /* If the id is already assigned, keep it. */ | ||
| 1475 | if (asoc->assoc_id) | ||
| 1476 | return error; | ||
| 1473 | retry: | 1477 | retry: |
| 1474 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | 1478 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) |
| 1475 | return -ENOMEM; | 1479 | return -ENOMEM; |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5fb3a8c9792e..7c3dfd2d9489 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -1100,6 +1100,15 @@ static int __sctp_connect(struct sock* sk, | |||
| 1100 | goto out_free; | 1100 | goto out_free; |
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| 1103 | /* In case the user of sctp_connectx() wants an association | ||
| 1104 | * id back, assign one now. | ||
| 1105 | */ | ||
| 1106 | if (assoc_id) { | ||
| 1107 | err = sctp_assoc_set_id(asoc, GFP_KERNEL); | ||
| 1108 | if (err < 0) | ||
| 1109 | goto out_free; | ||
| 1110 | } | ||
| 1111 | |||
| 1103 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | 1112 | err = sctp_primitive_ASSOCIATE(asoc, NULL); |
| 1104 | if (err < 0) { | 1113 | if (err < 0) { |
| 1105 | goto out_free; | 1114 | goto out_free; |
| @@ -1120,7 +1129,7 @@ static int __sctp_connect(struct sock* sk, | |||
| 1120 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); | 1129 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); |
| 1121 | 1130 | ||
| 1122 | err = sctp_wait_for_connect(asoc, &timeo); | 1131 | err = sctp_wait_for_connect(asoc, &timeo); |
| 1123 | if (!err && assoc_id) | 1132 | if ((err == 0 || err == -EINPROGRESS) && assoc_id) |
| 1124 | *assoc_id = asoc->assoc_id; | 1133 | *assoc_id = asoc->assoc_id; |
| 1125 | 1134 | ||
| 1126 | /* Don't free association on exit. */ | 1135 | /* Don't free association on exit. */ |
| @@ -1264,6 +1273,34 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | |||
| 1264 | return assoc_id; | 1273 | return assoc_id; |
| 1265 | } | 1274 | } |
| 1266 | 1275 | ||
| 1276 | /* | ||
| 1277 | * New (hopefully final) interface for the API. The option buffer is used | ||
| 1278 | * both for the returned association id and the addresses. | ||
| 1279 | */ | ||
| 1280 | SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, | ||
| 1281 | char __user *optval, | ||
| 1282 | int __user *optlen) | ||
| 1283 | { | ||
| 1284 | sctp_assoc_t assoc_id = 0; | ||
| 1285 | int err = 0; | ||
| 1286 | |||
| 1287 | if (len < sizeof(assoc_id)) | ||
| 1288 | return -EINVAL; | ||
| 1289 | |||
| 1290 | err = __sctp_setsockopt_connectx(sk, | ||
| 1291 | (struct sockaddr __user *)(optval + sizeof(assoc_id)), | ||
| 1292 | len - sizeof(assoc_id), &assoc_id); | ||
| 1293 | |||
| 1294 | if (err == 0 || err == -EINPROGRESS) { | ||
| 1295 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) | ||
| 1296 | return -EFAULT; | ||
| 1297 | if (put_user(sizeof(assoc_id), optlen)) | ||
| 1298 | return -EFAULT; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | return err; | ||
| 1302 | } | ||
| 1303 | |||
| 1267 | /* API 3.1.4 close() - UDP Style Syntax | 1304 | /* API 3.1.4 close() - UDP Style Syntax |
| 1268 | * Applications use close() to perform graceful shutdown (as described in | 1305 | * Applications use close() to perform graceful shutdown (as described in |
| 1269 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1306 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
| @@ -5578,6 +5615,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
| 5578 | retval = sctp_getsockopt_local_addrs(sk, len, optval, | 5615 | retval = sctp_getsockopt_local_addrs(sk, len, optval, |
| 5579 | optlen); | 5616 | optlen); |
| 5580 | break; | 5617 | break; |
| 5618 | case SCTP_SOCKOPT_CONNECTX3: | ||
| 5619 | retval = sctp_getsockopt_connectx3(sk, len, optval, optlen); | ||
| 5620 | break; | ||
| 5581 | case SCTP_DEFAULT_SEND_PARAM: | 5621 | case SCTP_DEFAULT_SEND_PARAM: |
| 5582 | retval = sctp_getsockopt_default_send_param(sk, len, | 5622 | retval = sctp_getsockopt_default_send_param(sk, len, |
| 5583 | optval, optlen); | 5623 | optval, optlen); |
