SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf flag. With this feature, each endpoint will have its own flag for its future asoc's asconf_capable, instead of netns asconf flag. Note that when both ep's asconf_enable and auth_enable are enabled, SCTP_CID_ASCONF and SCTP_CID_ASCONF_ACK should be added into auth_chunk_list.
Unified · Split
| @@ -134,6 +134,7 @@ typedef __s32 sctp_assoc_t; · 133 unmodified lines | |||
| 134 | #define SCTP_INTERLEAVING_SUPPORTED 125 | 134 | #define SCTP_INTERLEAVING_SUPPORTED 125 |
| 135 | #define SCTP_SENDMSG_CONNECT 126 | 135 | #define SCTP_SENDMSG_CONNECT 126 |
| 136 | #define SCTP_EVENT 127 | 136 | #define SCTP_EVENT 127 |
| 137 | #define SCTP_ASCONF_SUPPORTED 128 | ||
| 137 | 138 | ||
| 138 | /* PR-SCTP policies */ | 139 | /* PR-SCTP policies */ |
| 139 | #define SCTP_PR_SCTP_NONE 0x0000 | 140 | #define SCTP_PR_SCTP_NONE 0x0000 |
| @@ -4496,6 +4496,42 @@ static int sctp_setsockopt_event(struct sock *sk, char __user *optval, · 4495 unmodified lines | |||
| 4496 | return retval; | 4496 | return retval; |
| 4497 | } | 4497 | } |
| 4498 | 4498 | ||
| 4499 | static int sctp_setsockopt_asconf_supported(struct sock *sk, | ||
| 4500 | char __user *optval, | ||
| 4501 | unsigned int optlen) | ||
| 4502 | { | ||
| 4503 | struct sctp_assoc_value params; | ||
| 4504 | struct sctp_association *asoc; | ||
| 4505 | struct sctp_endpoint *ep; | ||
| 4506 | int retval = -EINVAL; | ||
| 4507 | |||
| 4508 | if (optlen != sizeof(params)) | ||
| 4509 | goto out; | ||
| 4510 | |||
| 4511 | if (copy_from_user(¶ms, optval, optlen)) { | ||
| 4512 | retval = -EFAULT; | ||
| 4513 | goto out; | ||
| 4514 | } | ||
| 4515 | |||
| 4516 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
| 4517 | if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && | ||
| 4518 | sctp_style(sk, UDP)) | ||
| 4519 | goto out; | ||
| 4520 | |||
| 4521 | ep = sctp_sk(sk)->ep; | ||
| 4522 | ep->asconf_enable = !!params.assoc_value; | ||
| 4523 | |||
| 4524 | if (ep->asconf_enable && ep->auth_enable) { | ||
| 4525 | sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF); | ||
| 4526 | sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK); | ||
| 4527 | } | ||
| 4528 | |||
| 4529 | retval = 0; | ||
| 4530 | |||
| 4531 | out: | ||
| 4532 | return retval; | ||
| 4533 | } | ||
| 4534 | |||
| 4499 | /* API 6.2 setsockopt(), getsockopt() | 4535 | /* API 6.2 setsockopt(), getsockopt() |
| 4500 | * | 4536 | * |
| 4501 | * Applications use setsockopt() and getsockopt() to set or retrieve | 4537 | * Applications use setsockopt() and getsockopt() to set or retrieve |
| @@ -4696,6 +4732,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, · 194 unmodified lines | |||
| 4696 | case SCTP_EVENT: | 4732 | case SCTP_EVENT: |
| 4697 | retval = sctp_setsockopt_event(sk, optval, optlen); | 4733 | retval = sctp_setsockopt_event(sk, optval, optlen); |
| 4698 | break; | 4734 | break; |
| 4735 | case SCTP_ASCONF_SUPPORTED: | ||
| 4736 | retval = sctp_setsockopt_asconf_supported(sk, optval, optlen); | ||
| 4737 | break; | ||
| 4699 | default: | 4738 | default: |
| 4700 | retval = -ENOPROTOOPT; | 4739 | retval = -ENOPROTOOPT; |
| 4701 | break; | 4740 | break; |
| @@ -7675,6 +7714,45 @@ static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval, · 2973 unmodified lines | |||
| 7675 | return 0; | 7714 | return 0; |
| 7676 | } | 7715 | } |
| 7677 | 7716 | ||
| 7717 | static int sctp_getsockopt_asconf_supported(struct sock *sk, int len, | ||
| 7718 | char __user *optval, | ||
| 7719 | int __user *optlen) | ||
| 7720 | { | ||
| 7721 | struct sctp_assoc_value params; | ||
| 7722 | struct sctp_association *asoc; | ||
| 7723 | int retval = -EFAULT; | ||
| 7724 | |||
| 7725 | if (len < sizeof(params)) { | ||
| 7726 | retval = -EINVAL; | ||
| 7727 | goto out; | ||
| 7728 | } | ||
| 7729 | |||
| 7730 | len = sizeof(params); | ||
| 7731 | if (copy_from_user(¶ms, optval, len)) | ||
| 7732 | goto out; | ||
| 7733 | |||
| 7734 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
| 7735 | if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC && | ||
| 7736 | sctp_style(sk, UDP)) { | ||
| 7737 | retval = -EINVAL; | ||
| 7738 | goto out; | ||
| 7739 | } | ||
| 7740 | |||
| 7741 | params.assoc_value = asoc ? asoc->peer.asconf_capable | ||
| 7742 | : sctp_sk(sk)->ep->asconf_enable; | ||
| 7743 | |||
| 7744 | if (put_user(len, optlen)) | ||
| 7745 | goto out; | ||
| 7746 | |||
| 7747 | if (copy_to_user(optval, ¶ms, len)) | ||
| 7748 | goto out; | ||
| 7749 | |||
| 7750 | retval = 0; | ||
| 7751 | |||
| 7752 | out: | ||
| 7753 | return retval; | ||
| 7754 | } | ||
| 7755 | |||
| 7678 | static int sctp_getsockopt(struct sock *sk, int level, int optname, | 7756 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
| 7679 | char __user *optval, int __user *optlen) | 7757 | char __user *optval, int __user *optlen) |
| 7680 | { | 7758 | { |
| @@ -7876,6 +7954,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 195 unmodified lines | |||
| 7876 | case SCTP_EVENT: | 7954 | case SCTP_EVENT: |
| 7877 | retval = sctp_getsockopt_event(sk, len, optval, optlen); | 7955 | retval = sctp_getsockopt_event(sk, len, optval, optlen); |
| 7878 | break; | 7956 | break; |
| 7957 | case SCTP_ASCONF_SUPPORTED: | ||
| 7958 | retval = sctp_getsockopt_asconf_supported(sk, len, optval, | ||
| 7959 | optlen); | ||
| 7960 | break; | ||
| 7879 | default: | 7961 | default: |
| 7880 | retval = -ENOPROTOOPT; | 7962 | retval = -ENOPROTOOPT; |
| 7881 | break; | 7963 | break; |