aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 7eb1f1a736fb..cc06198dc444 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3356,6 +3356,46 @@ static int sctp_setsockopt_del_key(struct sock *sk,
3356 3356
3357} 3357}
3358 3358
3359/*
3360 * 8.1.23 SCTP_AUTO_ASCONF
3361 *
3362 * This option will enable or disable the use of the automatic generation of
3363 * ASCONF chunks to add and delete addresses to an existing association. Note
3364 * that this option has two caveats namely: a) it only affects sockets that
3365 * are bound to all addresses available to the SCTP stack, and b) the system
3366 * administrator may have an overriding control that turns the ASCONF feature
3367 * off no matter what setting the socket option may have.
3368 * This option expects an integer boolean flag, where a non-zero value turns on
3369 * the option, and a zero value turns off the option.
3370 * Note. In this implementation, socket operation overrides default parameter
3371 * being set by sysctl as well as FreeBSD implementation
3372 */
3373static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
3374 unsigned int optlen)
3375{
3376 int val;
3377 struct sctp_sock *sp = sctp_sk(sk);
3378
3379 if (optlen < sizeof(int))
3380 return -EINVAL;
3381 if (get_user(val, (int __user *)optval))
3382 return -EFAULT;
3383 if (!sctp_is_ep_boundall(sk) && val)
3384 return -EINVAL;
3385 if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
3386 return 0;
3387
3388 if (val == 0 && sp->do_auto_asconf) {
3389 list_del(&sp->auto_asconf_list);
3390 sp->do_auto_asconf = 0;
3391 } else if (val && !sp->do_auto_asconf) {
3392 list_add_tail(&sp->auto_asconf_list,
3393 &sctp_auto_asconf_splist);
3394 sp->do_auto_asconf = 1;
3395 }
3396 return 0;
3397}
3398
3359 3399
3360/* API 6.2 setsockopt(), getsockopt() 3400/* API 6.2 setsockopt(), getsockopt()
3361 * 3401 *
@@ -3503,6 +3543,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
3503 case SCTP_AUTH_DELETE_KEY: 3543 case SCTP_AUTH_DELETE_KEY:
3504 retval = sctp_setsockopt_del_key(sk, optval, optlen); 3544 retval = sctp_setsockopt_del_key(sk, optval, optlen);
3505 break; 3545 break;
3546 case SCTP_AUTO_ASCONF:
3547 retval = sctp_setsockopt_auto_asconf(sk, optval, optlen);
3548 break;
3506 default: 3549 default:
3507 retval = -ENOPROTOOPT; 3550 retval = -ENOPROTOOPT;
3508 break; 3551 break;
@@ -5309,6 +5352,28 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len,
5309} 5352}
5310 5353
5311/* 5354/*
5355 * 8.1.23 SCTP_AUTO_ASCONF
5356 * See the corresponding setsockopt entry as description
5357 */
5358static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
5359 char __user *optval, int __user *optlen)
5360{
5361 int val = 0;
5362
5363 if (len < sizeof(int))
5364 return -EINVAL;
5365
5366 len = sizeof(int);
5367 if (sctp_sk(sk)->do_auto_asconf && sctp_is_ep_boundall(sk))
5368 val = 1;
5369 if (put_user(len, optlen))
5370 return -EFAULT;
5371 if (copy_to_user(optval, &val, len))
5372 return -EFAULT;
5373 return 0;
5374}
5375
5376/*
5312 * 8.2.6. Get the Current Identifiers of Associations 5377 * 8.2.6. Get the Current Identifiers of Associations
5313 * (SCTP_GET_ASSOC_ID_LIST) 5378 * (SCTP_GET_ASSOC_ID_LIST)
5314 * 5379 *
@@ -5492,6 +5557,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5492 case SCTP_GET_ASSOC_ID_LIST: 5557 case SCTP_GET_ASSOC_ID_LIST:
5493 retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen); 5558 retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen);
5494 break; 5559 break;
5560 case SCTP_AUTO_ASCONF:
5561 retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen);
5562 break;
5495 default: 5563 default:
5496 retval = -ENOPROTOOPT; 5564 retval = -ENOPROTOOPT;
5497 break; 5565 break;