diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 62 |
1 files changed, 62 insertions, 0 deletions
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; |