diff options
-rw-r--r-- | include/net/sctp/structs.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/sctp.h | 12 | ||||
-rw-r--r-- | net/sctp/socket.c | 62 |
3 files changed, 77 insertions, 0 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 07115ca9de4d..d8e464aacb20 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -1853,6 +1853,9 @@ struct sctp_association { | |||
1853 | prsctp_enable:1; | 1853 | prsctp_enable:1; |
1854 | 1854 | ||
1855 | struct sctp_priv_assoc_stats stats; | 1855 | struct sctp_priv_assoc_stats stats; |
1856 | |||
1857 | __u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1]; | ||
1858 | __u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1]; | ||
1856 | }; | 1859 | }; |
1857 | 1860 | ||
1858 | 1861 | ||
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 984cf2e9a61d..d304f4c9792c 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h | |||
@@ -114,6 +114,7 @@ typedef __s32 sctp_assoc_t; | |||
114 | #define SCTP_GET_ASSOC_STATS 112 /* Read only */ | 114 | #define SCTP_GET_ASSOC_STATS 112 /* Read only */ |
115 | #define SCTP_PR_SUPPORTED 113 | 115 | #define SCTP_PR_SUPPORTED 113 |
116 | #define SCTP_DEFAULT_PRINFO 114 | 116 | #define SCTP_DEFAULT_PRINFO 114 |
117 | #define SCTP_PR_ASSOC_STATUS 115 | ||
117 | 118 | ||
118 | /* PR-SCTP policies */ | 119 | /* PR-SCTP policies */ |
119 | #define SCTP_PR_SCTP_NONE 0x0000 | 120 | #define SCTP_PR_SCTP_NONE 0x0000 |
@@ -926,6 +927,17 @@ struct sctp_paddrthlds { | |||
926 | __u16 spt_pathpfthld; | 927 | __u16 spt_pathpfthld; |
927 | }; | 928 | }; |
928 | 929 | ||
930 | /* | ||
931 | * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status | ||
932 | */ | ||
933 | struct sctp_prstatus { | ||
934 | sctp_assoc_t sprstat_assoc_id; | ||
935 | __u16 sprstat_sid; | ||
936 | __u16 sprstat_policy; | ||
937 | __u64 sprstat_abandoned_unsent; | ||
938 | __u64 sprstat_abandoned_sent; | ||
939 | }; | ||
940 | |||
929 | struct sctp_default_prinfo { | 941 | struct sctp_default_prinfo { |
930 | sctp_assoc_t pr_assoc_id; | 942 | sctp_assoc_t pr_assoc_id; |
931 | __u32 pr_value; | 943 | __u32 pr_value; |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c03fe1b76706..c3167c43a9c1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -6330,6 +6330,64 @@ out: | |||
6330 | return retval; | 6330 | return retval; |
6331 | } | 6331 | } |
6332 | 6332 | ||
6333 | static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len, | ||
6334 | char __user *optval, | ||
6335 | int __user *optlen) | ||
6336 | { | ||
6337 | struct sctp_prstatus params; | ||
6338 | struct sctp_association *asoc; | ||
6339 | int policy; | ||
6340 | int retval = -EINVAL; | ||
6341 | |||
6342 | if (len < sizeof(params)) | ||
6343 | goto out; | ||
6344 | |||
6345 | len = sizeof(params); | ||
6346 | if (copy_from_user(¶ms, optval, len)) { | ||
6347 | retval = -EFAULT; | ||
6348 | goto out; | ||
6349 | } | ||
6350 | |||
6351 | policy = params.sprstat_policy; | ||
6352 | if (policy & ~SCTP_PR_SCTP_MASK) | ||
6353 | goto out; | ||
6354 | |||
6355 | asoc = sctp_id2assoc(sk, params.sprstat_assoc_id); | ||
6356 | if (!asoc) | ||
6357 | goto out; | ||
6358 | |||
6359 | if (policy == SCTP_PR_SCTP_NONE) { | ||
6360 | params.sprstat_abandoned_unsent = 0; | ||
6361 | params.sprstat_abandoned_sent = 0; | ||
6362 | for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) { | ||
6363 | params.sprstat_abandoned_unsent += | ||
6364 | asoc->abandoned_unsent[policy]; | ||
6365 | params.sprstat_abandoned_sent += | ||
6366 | asoc->abandoned_sent[policy]; | ||
6367 | } | ||
6368 | } else { | ||
6369 | params.sprstat_abandoned_unsent = | ||
6370 | asoc->abandoned_unsent[__SCTP_PR_INDEX(policy)]; | ||
6371 | params.sprstat_abandoned_sent = | ||
6372 | asoc->abandoned_sent[__SCTP_PR_INDEX(policy)]; | ||
6373 | } | ||
6374 | |||
6375 | if (put_user(len, optlen)) { | ||
6376 | retval = -EFAULT; | ||
6377 | goto out; | ||
6378 | } | ||
6379 | |||
6380 | if (copy_to_user(optval, ¶ms, len)) { | ||
6381 | retval = -EFAULT; | ||
6382 | goto out; | ||
6383 | } | ||
6384 | |||
6385 | retval = 0; | ||
6386 | |||
6387 | out: | ||
6388 | return retval; | ||
6389 | } | ||
6390 | |||
6333 | static int sctp_getsockopt(struct sock *sk, int level, int optname, | 6391 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
6334 | char __user *optval, int __user *optlen) | 6392 | char __user *optval, int __user *optlen) |
6335 | { | 6393 | { |
@@ -6490,6 +6548,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
6490 | retval = sctp_getsockopt_default_prinfo(sk, len, optval, | 6548 | retval = sctp_getsockopt_default_prinfo(sk, len, optval, |
6491 | optlen); | 6549 | optlen); |
6492 | break; | 6550 | break; |
6551 | case SCTP_PR_ASSOC_STATUS: | ||
6552 | retval = sctp_getsockopt_pr_assocstatus(sk, len, optval, | ||
6553 | optlen); | ||
6554 | break; | ||
6493 | default: | 6555 | default: |
6494 | retval = -ENOPROTOOPT; | 6556 | retval = -ENOPROTOOPT; |
6495 | break; | 6557 | break; |