diff options
author | Michio Honda <micchie@sfc.wide.ad.jp> | 2011-04-26 07:16:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-06-02 05:04:53 -0400 |
commit | 7dc04d712203eecdc1435a4cd135935c4a297be5 (patch) | |
tree | d50fa7599ca9ee393f7c50510e6ea742efcfbf81 /net/sctp/socket.c | |
parent | dd51be0f5484b450b8d48c9226ed86ce3dd5102e (diff) |
sctp: Add socket option operation for Auto-ASCONF.
This patch allows the application to operate Auto-ASCONF on/off
behavior via setsockopt() and getsockopt().
Signed-off-by: Michio Honda <micchie@sfc.wide.ad.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Acked-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 68 |
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 | */ | ||
3373 | static 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 | */ | ||
5358 | static 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; |