History

sctp: add SCTP_REMOTE_UDP_ENCAPS_PORT sockopt

This patch is to implement: rfc6951#section-6.1: Get or Set the Remote UDP Encapsulation Port Number with the param of the struct: struct sctp_udpencaps { sctp_assoc_t sue_assoc_id; struct sockaddr_storage sue_address; uint16_t sue_port; }; the encap_port of sock, assoc or transport can be changed by users, which also means it allows the different transports of the same asoc to have different encap_port value. v1->v2: - no change. v2->v3: - fix the endian warning when setting values between encap_port and sue_port.

Xin Long committed 6 years ago

Commit 8dba2961 parent e8a30012 files · +121 −0Browse files

Unified · Split

2 files
  1. include/uapi/linux/sctp.h +7 −0
  2. net/sctp/socket.c +114 −0
include/uapi/linux/sctp.h+7−0
@@ -140,6 +140,7 @@ typedef __s32 sctp_assoc_t; · 139 unmodified lines
140#define SCTP_ECN_SUPPORTED 130140#define SCTP_ECN_SUPPORTED 130
141#define SCTP_EXPOSE_POTENTIALLY_FAILED_STATE 131141#define SCTP_EXPOSE_POTENTIALLY_FAILED_STATE 131
142#define SCTP_EXPOSE_PF_STATE SCTP_EXPOSE_POTENTIALLY_FAILED_STATE142#define SCTP_EXPOSE_PF_STATE SCTP_EXPOSE_POTENTIALLY_FAILED_STATE
143#define SCTP_REMOTE_UDP_ENCAPS_PORT 132
143 144
144/* PR-SCTP policies */145/* PR-SCTP policies */
145#define SCTP_PR_SCTP_NONE 0x0000146#define SCTP_PR_SCTP_NONE 0x0000
@@ -1197,6 +1198,12 @@ struct sctp_event { · 1051 unmodified lines
1197 uint8_t se_on;1198 uint8_t se_on;
1198};1199};
1199 1200
1201struct sctp_udpencaps {
1202 sctp_assoc_t sue_assoc_id;
1203 struct sockaddr_storage sue_address;
1204 uint16_t sue_port;
1205};
1206
1200/* SCTP Stream schedulers */1207/* SCTP Stream schedulers */
1201enum sctp_sched_type {1208enum sctp_sched_type {
1202 SCTP_SS_FCFS,1209 SCTP_SS_FCFS,
net/sctp/socket.c+114−0
@@ -4417,6 +4417,55 @@ out: · 4416 unmodified lines
4417 return retval;4417 return retval;
4418}4418}
4419 4419
4420static int sctp_setsockopt_encap_port(struct sock *sk,
4421 struct sctp_udpencaps *encap,
4422 unsigned int optlen)
4423{
4424 struct sctp_association *asoc;
4425 struct sctp_transport *t;
4426 __be16 encap_port;
4427
4428 if (optlen != sizeof(*encap))
4429 return -EINVAL;
4430
4431 /* If an address other than INADDR_ANY is specified, and
4432 * no transport is found, then the request is invalid.
4433 */
4434 encap_port = (__force __be16)encap->sue_port;
4435 if (!sctp_is_any(sk, (union sctp_addr *)&encap->sue_address)) {
4436 t = sctp_addr_id2transport(sk, &encap->sue_address,
4437 encap->sue_assoc_id);
4438 if (!t)
4439 return -EINVAL;
4440
4441 t->encap_port = encap_port;
4442 return 0;
4443 }
4444
4445 /* Get association, if assoc_id != SCTP_FUTURE_ASSOC and the
4446 * socket is a one to many style socket, and an association
4447 * was not found, then the id was invalid.
4448 */
4449 asoc = sctp_id2assoc(sk, encap->sue_assoc_id);
4450 if (!asoc && encap->sue_assoc_id != SCTP_FUTURE_ASSOC &&
4451 sctp_style(sk, UDP))
4452 return -EINVAL;
4453
4454 /* If changes are for association, also apply encap_port to
4455 * each transport.
4456 */
4457 if (asoc) {
4458 list_for_each_entry(t, &asoc->peer.transport_addr_list,
4459 transports)
4460 t->encap_port = encap_port;
4461
4462 return 0;
4463 }
4464
4465 sctp_sk(sk)->encap_port = encap_port;
4466 return 0;
4467}
4468
4420/* API 6.2 setsockopt(), getsockopt()4469/* API 6.2 setsockopt(), getsockopt()
4421 *4470 *
4422 * Applications use setsockopt() and getsockopt() to set or retrieve4471 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4636,6 +4685,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, · 213 unmodified lines
4636 case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE:4685 case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE:
4637 retval = sctp_setsockopt_pf_expose(sk, kopt, optlen);4686 retval = sctp_setsockopt_pf_expose(sk, kopt, optlen);
4638 break;4687 break;
4688 case SCTP_REMOTE_UDP_ENCAPS_PORT:
4689 retval = sctp_setsockopt_encap_port(sk, kopt, optlen);
4690 break;
4639 default:4691 default:
4640 retval = -ENOPROTOOPT;4692 retval = -ENOPROTOOPT;
4641 break;4693 break;
@@ -7791,6 +7843,65 @@ out: · 3149 unmodified lines
7791 return retval;7843 return retval;
7792}7844}
7793 7845
7846static int sctp_getsockopt_encap_port(struct sock *sk, int len,
7847 char __user *optval, int __user *optlen)
7848{
7849 struct sctp_association *asoc;
7850 struct sctp_udpencaps encap;
7851 struct sctp_transport *t;
7852 __be16 encap_port;
7853
7854 if (len < sizeof(encap))
7855 return -EINVAL;
7856
7857 len = sizeof(encap);
7858 if (copy_from_user(&encap, optval, len))
7859 return -EFAULT;
7860
7861 /* If an address other than INADDR_ANY is specified, and
7862 * no transport is found, then the request is invalid.
7863 */
7864 if (!sctp_is_any(sk, (union sctp_addr *)&encap.sue_address)) {
7865 t = sctp_addr_id2transport(sk, &encap.sue_address,
7866 encap.sue_assoc_id);
7867 if (!t) {
7868 pr_debug("%s: failed no transport\n", __func__);
7869 return -EINVAL;
7870 }
7871
7872 encap_port = t->encap_port;
7873 goto out;
7874 }
7875
7876 /* Get association, if assoc_id != SCTP_FUTURE_ASSOC and the
7877 * socket is a one to many style socket, and an association
7878 * was not found, then the id was invalid.
7879 */
7880 asoc = sctp_id2assoc(sk, encap.sue_assoc_id);
7881 if (!asoc && encap.sue_assoc_id != SCTP_FUTURE_ASSOC &&
7882 sctp_style(sk, UDP)) {
7883 pr_debug("%s: failed no association\n", __func__);
7884 return -EINVAL;
7885 }
7886
7887 if (asoc) {
7888 encap_port = asoc->encap_port;
7889 goto out;
7890 }
7891
7892 encap_port = sctp_sk(sk)->encap_port;
7893
7894out:
7895 encap.sue_port = (__force uint16_t)encap_port;
7896 if (copy_to_user(optval, &encap, len))
7897 return -EFAULT;
7898
7899 if (put_user(len, optlen))
7900 return -EFAULT;
7901
7902 return 0;
7903}
7904
7794static int sctp_getsockopt(struct sock *sk, int level, int optname,7905static int sctp_getsockopt(struct sock *sk, int level, int optname,
7795 char __user *optval, int __user *optlen)7906 char __user *optval, int __user *optlen)
7796{7907{
@@ -8011,6 +8122,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 214 unmodified lines
8011 case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE:8122 case SCTP_EXPOSE_POTENTIALLY_FAILED_STATE:
8012 retval = sctp_getsockopt_pf_expose(sk, len, optval, optlen);8123 retval = sctp_getsockopt_pf_expose(sk, len, optval, optlen);
8013 break;8124 break;
8125 case SCTP_REMOTE_UDP_ENCAPS_PORT:
8126 retval = sctp_getsockopt_encap_port(sk, len, optval, optlen);
8127 break;
8014 default:8128 default:
8015 retval = -ENOPROTOOPT;8129 retval = -ENOPROTOOPT;
8016 break;8130 break;