diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2011-04-17 13:27:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-21 13:35:43 -0400 |
commit | 209ba424c2c6e5ff4dd0ff79bb23659aa6048eac (patch) | |
tree | df443b83a4d458cfb46ea2e08e176b2433fa5b66 /net/sctp/socket.c | |
parent | 4c6a6f42131dd750dcfe3c71e63bfc046e5a227e (diff) |
sctp: implement socket option SCTP_GET_ASSOC_ID_LIST
This patch Implement socket option SCTP_GET_ASSOC_ID_LIST.
SCTP Socket API Extension:
8.2.6. Get the Current Identifiers of Associations
(SCTP_GET_ASSOC_ID_LIST)
This option gets the current list of SCTP association identifiers of
the SCTP associations handled by a one-to-many style socket.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 431b8905c570..f694ee116746 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5277,6 +5277,55 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len, | |||
5277 | return 0; | 5277 | return 0; |
5278 | } | 5278 | } |
5279 | 5279 | ||
5280 | /* | ||
5281 | * 8.2.6. Get the Current Identifiers of Associations | ||
5282 | * (SCTP_GET_ASSOC_ID_LIST) | ||
5283 | * | ||
5284 | * This option gets the current list of SCTP association identifiers of | ||
5285 | * the SCTP associations handled by a one-to-many style socket. | ||
5286 | */ | ||
5287 | static int sctp_getsockopt_assoc_ids(struct sock *sk, int len, | ||
5288 | char __user *optval, int __user *optlen) | ||
5289 | { | ||
5290 | struct sctp_sock *sp = sctp_sk(sk); | ||
5291 | struct sctp_association *asoc; | ||
5292 | struct sctp_assoc_ids *ids; | ||
5293 | u32 num = 0; | ||
5294 | |||
5295 | if (sctp_style(sk, TCP)) | ||
5296 | return -EOPNOTSUPP; | ||
5297 | |||
5298 | if (len < sizeof(struct sctp_assoc_ids)) | ||
5299 | return -EINVAL; | ||
5300 | |||
5301 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5302 | num++; | ||
5303 | } | ||
5304 | |||
5305 | if (len < sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num) | ||
5306 | return -EINVAL; | ||
5307 | |||
5308 | len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num; | ||
5309 | |||
5310 | ids = kmalloc(len, GFP_KERNEL); | ||
5311 | if (unlikely(!ids)) | ||
5312 | return -ENOMEM; | ||
5313 | |||
5314 | ids->gaids_number_of_ids = num; | ||
5315 | num = 0; | ||
5316 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5317 | ids->gaids_assoc_id[num++] = asoc->assoc_id; | ||
5318 | } | ||
5319 | |||
5320 | if (put_user(len, optlen) || copy_to_user(optval, ids, len)) { | ||
5321 | kfree(ids); | ||
5322 | return -EFAULT; | ||
5323 | } | ||
5324 | |||
5325 | kfree(ids); | ||
5326 | return 0; | ||
5327 | } | ||
5328 | |||
5280 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5329 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5281 | char __user *optval, int __user *optlen) | 5330 | char __user *optval, int __user *optlen) |
5282 | { | 5331 | { |
@@ -5409,6 +5458,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5409 | case SCTP_GET_ASSOC_NUMBER: | 5458 | case SCTP_GET_ASSOC_NUMBER: |
5410 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); | 5459 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); |
5411 | break; | 5460 | break; |
5461 | case SCTP_GET_ASSOC_ID_LIST: | ||
5462 | retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen); | ||
5463 | break; | ||
5412 | default: | 5464 | default: |
5413 | retval = -ENOPROTOOPT; | 5465 | retval = -ENOPROTOOPT; |
5414 | break; | 5466 | break; |