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 | |
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>
-rw-r--r-- | include/net/sctp/user.h | 13 | ||||
-rw-r--r-- | net/sctp/socket.c | 52 |
2 files changed, 65 insertions, 0 deletions
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index e73ebdae323d..793617ecbfdf 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -91,6 +91,7 @@ typedef __s32 sctp_assoc_t; | |||
91 | #define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */ | 91 | #define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */ |
92 | #define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */ | 92 | #define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */ |
93 | #define SCTP_GET_ASSOC_NUMBER 28 /* Read only */ | 93 | #define SCTP_GET_ASSOC_NUMBER 28 /* Read only */ |
94 | #define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */ | ||
94 | 95 | ||
95 | /* Internal Socket Options. Some of the sctp library functions are | 96 | /* Internal Socket Options. Some of the sctp library functions are |
96 | * implemented using these socket options. | 97 | * implemented using these socket options. |
@@ -669,6 +670,18 @@ struct sctp_authchunks { | |||
669 | }; | 670 | }; |
670 | 671 | ||
671 | /* | 672 | /* |
673 | * 8.2.6. Get the Current Identifiers of Associations | ||
674 | * (SCTP_GET_ASSOC_ID_LIST) | ||
675 | * | ||
676 | * This option gets the current list of SCTP association identifiers of | ||
677 | * the SCTP associations handled by a one-to-many style socket. | ||
678 | */ | ||
679 | struct sctp_assoc_ids { | ||
680 | __u32 gaids_number_of_ids; | ||
681 | sctp_assoc_t gaids_assoc_id[]; | ||
682 | }; | ||
683 | |||
684 | /* | ||
672 | * 8.3, 8.5 get all peer/local addresses in an association. | 685 | * 8.3, 8.5 get all peer/local addresses in an association. |
673 | * This parameter struct is used by SCTP_GET_PEER_ADDRS and | 686 | * This parameter struct is used by SCTP_GET_PEER_ADDRS and |
674 | * SCTP_GET_LOCAL_ADDRS socket options used internally to implement | 687 | * SCTP_GET_LOCAL_ADDRS socket options used internally to implement |
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; |