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 | 134 | #define SCTP_INTERLEAVING_SUPPORTED 125 |
| 135 | 135 | #define SCTP_SENDMSG_CONNECT 126 |
| 136 | 136 | #define SCTP_EVENT 127 |
| 137 | +#define SCTP_ASCONF_SUPPORTED 128 | |
| 137 | 138 | |
| 138 | 139 | /* PR-SCTP policies */ |
| 139 | 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 | 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 | 4535 | /* API 6.2 setsockopt(), getsockopt() |
| 4500 | 4536 | * |
| 4501 | 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 | 4732 | case SCTP_EVENT: |
| 4697 | 4733 | retval = sctp_setsockopt_event(sk, optval, optlen); |
| 4698 | 4734 | break; |
| 4735 | + case SCTP_ASCONF_SUPPORTED: | |
| 4736 | + retval = sctp_setsockopt_asconf_supported(sk, optval, optlen); | |
| 4737 | + break; | |
| 4699 | 4738 | default: |
| 4700 | 4739 | retval = -ENOPROTOOPT; |
| 4701 | 4740 | break; |
| @@ -7675,6 +7714,45 @@ static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval, · 2973 unmodified lines | ||
| 7675 | 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 | 7756 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
| 7679 | 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 | 7954 | case SCTP_EVENT: |
| 7877 | 7955 | retval = sctp_getsockopt_event(sk, len, optval, optlen); |
| 7878 | 7956 | break; |
| 7957 | + case SCTP_ASCONF_SUPPORTED: | |
| 7958 | + retval = sctp_getsockopt_asconf_supported(sk, len, optval, | |
| 7959 | + optlen); | |
| 7960 | + break; | |
| 7879 | 7961 | default: |
| 7880 | 7962 | retval = -ENOPROTOOPT; |
| 7881 | 7963 | break; |