Fix the support of mapped IPv4 addresses.
Thanks to Mark Bonnekessel and Markus Boese for making me aware of the problems. MFC after: 1 week
This commit is contained in:
parent
f9307cced7
commit
d59107f700
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=275567
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_header.h>
|
||||
#include <netinet/sctp_var.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/sctp6_var.h>
|
||||
#endif
|
||||
#include <netinet/sctp_sysctl.h>
|
||||
#include <netinet/sctp_output.h>
|
||||
@ -1373,10 +1374,14 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
|
||||
switch (sctp_ifa->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
|
||||
cnt += sizeof(struct sockaddr_in6);
|
||||
else
|
||||
cnt += sizeof(struct sockaddr_in);
|
||||
#else
|
||||
cnt += sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
@ -1396,10 +1401,14 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
|
||||
switch (laddr->ifa->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
|
||||
cnt += sizeof(struct sockaddr_in6);
|
||||
else
|
||||
cnt += sizeof(struct sockaddr_in);
|
||||
#else
|
||||
cnt += sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
@ -2216,23 +2225,27 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
size = 0;
|
||||
/* Count the sizes */
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
size += sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
|
||||
switch (net->ro._l_addr.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
size += sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
size += sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
size += sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
size += sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
case AF_INET6:
|
||||
size += sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -2264,24 +2277,28 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
sas = (struct sockaddr_storage *)&saddr->addr[0];
|
||||
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
cpsz = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
|
||||
switch (net->ro._l_addr.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
cpsz = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
cpsz = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
cpsz = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
cpsz = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
case AF_INET6:
|
||||
cpsz = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
cpsz = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cpsz = 0;
|
||||
break;
|
||||
}
|
||||
if (cpsz == 0) {
|
||||
break;
|
||||
@ -2292,15 +2309,15 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
#if defined(INET) && defined(INET6)
|
||||
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
|
||||
(((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
|
||||
(net->ro._l_addr.sa.sa_family == AF_INET)) {
|
||||
/* Must map the address */
|
||||
in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
|
||||
in6_sin_2_v4mapsin6(&net->ro._l_addr.sin,
|
||||
(struct sockaddr_in6 *)sas);
|
||||
} else {
|
||||
#endif
|
||||
memcpy(sas, &net->ro._l_addr, cpsz);
|
||||
#if defined(INET) && defined(INET6)
|
||||
}
|
||||
#else
|
||||
memcpy(sas, &net->ro._l_addr, cpsz);
|
||||
#endif
|
||||
((struct sockaddr_in *)sas)->sin_port = stcb->rport;
|
||||
|
||||
@ -2337,13 +2354,35 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
{
|
||||
struct sctp_paddrparams *paddrp;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
|
||||
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (paddrp->spp_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -2352,22 +2391,20 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&paddrp->spp_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
@ -2376,10 +2413,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -2395,10 +2432,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb != NULL) {
|
||||
/* Applies to the specific association */
|
||||
paddrp->spp_flags = 0;
|
||||
if (net) {
|
||||
if (net != NULL) {
|
||||
int ovh;
|
||||
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
|
||||
@ -2514,13 +2551,35 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
{
|
||||
struct sctp_paddrinfo *paddri;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
|
||||
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (paddri->spinfo_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&paddri->spinfo_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddri->spinfo_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddri->spinfo_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&paddri->spinfo_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -2529,14 +2588,15 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((stcb) && (net)) {
|
||||
if ((stcb != NULL) && (net != NULL)) {
|
||||
if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
|
||||
/* It's unconfirmed */
|
||||
paddri->spinfo_state = SCTP_UNCONFIRMED;
|
||||
@ -2555,7 +2615,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
*optsize = sizeof(struct sctp_paddrinfo);
|
||||
} else {
|
||||
if (stcb) {
|
||||
if (stcb != NULL) {
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
|
||||
@ -2772,16 +2832,32 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
/* simply copy out the sockaddr_storage... */
|
||||
size_t len;
|
||||
union sctp_sockstore *addr;
|
||||
|
||||
len = *optsize;
|
||||
if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
|
||||
len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
|
||||
|
||||
memcpy(&ssp->ssp_addr,
|
||||
&stcb->asoc.primary_destination->ro._l_addr,
|
||||
len);
|
||||
addr = &stcb->asoc.primary_destination->ro._l_addr;
|
||||
switch (addr->sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
in6_sin_2_v4mapsin6(&addr->sin,
|
||||
(struct sockaddr_in6 *)&ssp->ssp_addr);
|
||||
} else {
|
||||
memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#else
|
||||
memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
memcpy(&ssp->ssp_addr, &addr->sin6, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
*optsize = sizeof(struct sctp_setprim);
|
||||
} else {
|
||||
@ -3121,13 +3197,35 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
{
|
||||
struct sctp_paddrthlds *thlds;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
|
||||
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (thlds->spt_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -3136,22 +3234,20 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&thlds->spt_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
@ -3160,10 +3256,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -3179,8 +3275,8 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (net) {
|
||||
if (stcb != NULL) {
|
||||
if (net != NULL) {
|
||||
thlds->spt_pathmaxrxt = net->failure_threshold;
|
||||
thlds->spt_pathpfthld = net->pf_threshold;
|
||||
} else {
|
||||
@ -3212,12 +3308,35 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
{
|
||||
struct sctp_udpencaps *encaps;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (encaps->sue_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
#endif
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -3228,21 +3347,18 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&encaps->sue_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
@ -3251,10 +3367,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -3270,7 +3386,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb != NULL) {
|
||||
if (net) {
|
||||
encaps->sue_port = net->port;
|
||||
} else {
|
||||
@ -4946,12 +5062,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
{
|
||||
struct sctp_paddrparams *paddrp;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (paddrp->spp_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&paddrp->spp_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -4960,25 +5099,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp,
|
||||
(struct sockaddr *)&paddrp->spp_address,
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr,
|
||||
&net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&paddrp->spp_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
error = EINVAL;
|
||||
@ -4987,10 +5123,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -5019,7 +5155,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb != NULL) {
|
||||
/************************TCB SPECIFIC SET ******************/
|
||||
/*
|
||||
* do we change the timer for HB, we run
|
||||
@ -5034,7 +5170,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
|
||||
/* network sets ? */
|
||||
if (net) {
|
||||
if (net != NULL) {
|
||||
/************************NET SPECIFIC SET ******************/
|
||||
if (paddrp->spp_flags & SPP_HB_DISABLE) {
|
||||
if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
|
||||
@ -5119,7 +5255,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
#endif
|
||||
} else {
|
||||
/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
|
||||
if (paddrp->spp_pathmaxrxt) {
|
||||
if (paddrp->spp_pathmaxrxt != 0) {
|
||||
stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
if (net->dest_state & SCTP_ADDR_PF) {
|
||||
@ -5150,14 +5286,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_HB_ENABLE) {
|
||||
if (paddrp->spp_hbinterval) {
|
||||
if (paddrp->spp_hbinterval != 0) {
|
||||
stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
|
||||
} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
|
||||
stcb->asoc.heart_beat_delay = 0;
|
||||
}
|
||||
/* Turn back on the timer */
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
if (paddrp->spp_hbinterval) {
|
||||
if (paddrp->spp_hbinterval != 0) {
|
||||
net->heart_beat_delay = paddrp->spp_hbinterval;
|
||||
} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
|
||||
net->heart_beat_delay = 0;
|
||||
@ -5238,12 +5374,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
* set it with the options on the
|
||||
* socket
|
||||
*/
|
||||
if (paddrp->spp_pathmaxrxt) {
|
||||
if (paddrp->spp_pathmaxrxt != 0) {
|
||||
inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
|
||||
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
|
||||
else if (paddrp->spp_hbinterval) {
|
||||
else if (paddrp->spp_hbinterval != 0) {
|
||||
if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
|
||||
paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
|
||||
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
|
||||
@ -5409,13 +5545,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
{
|
||||
struct sctp_setprim *spa;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
|
||||
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (spa->ssp_addr.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&spa->ssp_addr;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&spa->ssp_addr;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&spa->ssp_addr;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -5424,16 +5582,16 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp,
|
||||
(struct sockaddr *)&spa->ssp_addr,
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr,
|
||||
&net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((stcb) && (net)) {
|
||||
if ((stcb != NULL) && (net != NULL)) {
|
||||
if ((net != stcb->asoc.primary_destination) &&
|
||||
(!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
|
||||
/* Ok we need to set it */
|
||||
@ -5450,7 +5608,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
if (stcb) {
|
||||
if (stcb != NULL) {
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
break;
|
||||
@ -5472,14 +5630,36 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
case SCTP_SET_PEER_PRIMARY_ADDR:
|
||||
{
|
||||
struct sctp_setpeerprim *sspp;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
|
||||
if (stcb != NULL) {
|
||||
struct sctp_ifa *ifa;
|
||||
|
||||
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
|
||||
stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (sspp->sspp_addr.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&sspp->sspp_addr;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&sspp->sspp_addr;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&sspp->sspp_addr;
|
||||
#endif
|
||||
ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
|
||||
if (ifa == NULL) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
@ -5510,13 +5690,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
goto out_of_it;
|
||||
}
|
||||
} else {
|
||||
switch (sspp->sspp_addr.ss_family) {
|
||||
switch (addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)&sspp->sspp_addr;
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
@ -5531,7 +5711,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
@ -5547,8 +5727,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
goto out_of_it;
|
||||
}
|
||||
}
|
||||
if (sctp_set_primary_ip_address_sa(stcb,
|
||||
(struct sockaddr *)&sspp->sspp_addr) != 0) {
|
||||
if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
@ -5899,12 +6078,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
{
|
||||
struct sctp_paddrthlds *thlds;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
|
||||
net = NULL;
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (thlds->spt_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&thlds->spt_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -5913,25 +6115,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
* the locked tcb (last argument) is NOT a
|
||||
* TCB.. aka NULL.
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp,
|
||||
(struct sockaddr *)&thlds->spt_address,
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr,
|
||||
&net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&thlds->spt_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
error = EINVAL;
|
||||
@ -5940,10 +6139,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -5959,8 +6158,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (net) {
|
||||
if (stcb != NULL) {
|
||||
if (net != NULL) {
|
||||
if (net->dest_state & SCTP_ADDR_PF) {
|
||||
if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
|
||||
(net->failure_threshold <= thlds->spt_pathpfthld)) {
|
||||
@ -6040,11 +6239,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
{
|
||||
struct sctp_udpencaps *encaps;
|
||||
struct sctp_nets *net;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin_store;
|
||||
|
||||
#endif
|
||||
|
||||
SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
|
||||
if (stcb) {
|
||||
net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (encaps->sue_address.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin_store, sin6);
|
||||
addr = (struct sockaddr *)&sin_store;
|
||||
} else {
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
}
|
||||
} else {
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
}
|
||||
#else
|
||||
addr = (struct sockaddr *)&encaps->sue_address;
|
||||
#endif
|
||||
if (stcb != NULL) {
|
||||
net = sctp_findnet(stcb, addr);
|
||||
} else {
|
||||
/*
|
||||
* We increment here since
|
||||
@ -6055,22 +6278,19 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
*/
|
||||
net = NULL;
|
||||
SCTP_INP_INCR_REF(inp);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
|
||||
stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
}
|
||||
if (stcb && (net == NULL)) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = (struct sockaddr *)&encaps->sue_address;
|
||||
if ((stcb != NULL) && (net == NULL)) {
|
||||
#ifdef INET
|
||||
if (sa->sa_family == AF_INET) {
|
||||
if (addr->sa_family == AF_INET) {
|
||||
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if (sin->sin_addr.s_addr) {
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
error = EINVAL;
|
||||
@ -6079,10 +6299,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -6098,8 +6318,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stcb) {
|
||||
if (net) {
|
||||
if (stcb != NULL) {
|
||||
if (net != NULL) {
|
||||
net->port = encaps->sue_port;
|
||||
} else {
|
||||
stcb->asoc.port = encaps->sue_port;
|
||||
|
@ -2760,7 +2760,16 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
|
||||
switch (sa->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
in6_sin_2_v4mapsin6((struct sockaddr_in *)sa,
|
||||
(struct sockaddr_in6 *)&spc->spc_aaddr);
|
||||
} else {
|
||||
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#else
|
||||
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
@ -5653,43 +5662,43 @@ sctp_sorecvmsg(struct socket *so,
|
||||
entry->flgs = control->sinfo_flags;
|
||||
}
|
||||
#endif
|
||||
if (fromlen && from) {
|
||||
cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len);
|
||||
if ((fromlen > 0) && (from != NULL)) {
|
||||
union sctp_sockstore store;
|
||||
size_t len;
|
||||
|
||||
switch (control->whoFrom->ro._l_addr.sa.sa_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
store.sin6 = control->whoFrom->ro._l_addr.sin6;
|
||||
store.sin6.sin6_port = control->port_from;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)from)->sin_port = control->port_from;
|
||||
#ifdef INET6
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
in6_sin_2_v4mapsin6(&control->whoFrom->ro._l_addr.sin,
|
||||
&store.sin6);
|
||||
store.sin6.sin6_port = control->port_from;
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_in);
|
||||
store.sin = control->whoFrom->ro._l_addr.sin;
|
||||
store.sin.sin_port = control->port_from;
|
||||
}
|
||||
#else
|
||||
len = sizeof(struct sockaddr_in);
|
||||
store.sin = control->whoFrom->ro._l_addr.sin;
|
||||
store.sin.sin_port = control->port_from;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
|
||||
(from->sa_family == AF_INET) &&
|
||||
((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
sin = (struct sockaddr_in *)from;
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
|
||||
bcopy(&sin->sin_addr,
|
||||
&sin6.sin6_addr.s6_addr32[3],
|
||||
sizeof(sin6.sin6_addr.s6_addr32[3]));
|
||||
sin6.sin6_port = sin->sin_port;
|
||||
memcpy(from, &sin6, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
#endif
|
||||
memcpy(from, &store, min((size_t)fromlen, len));
|
||||
#ifdef INET6
|
||||
{
|
||||
struct sockaddr_in6 lsa6, *from6;
|
||||
@ -6450,7 +6459,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
|
||||
{
|
||||
struct sockaddr *addr_touse;
|
||||
|
||||
#ifdef INET6
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
@ -6464,8 +6473,10 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
|
||||
addr_touse = sa;
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
#ifdef INET
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
|
||||
*error = EINVAL;
|
||||
@ -6477,6 +6488,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
|
||||
*error = EINVAL;
|
||||
return;
|
||||
}
|
||||
#ifdef INET
|
||||
sin6 = (struct sockaddr_in6 *)addr_touse;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
@ -6489,6 +6501,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
addr_touse = (struct sockaddr *)&sin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef INET
|
||||
@ -6578,7 +6591,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
|
||||
{
|
||||
struct sockaddr *addr_touse;
|
||||
|
||||
#ifdef INET6
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
@ -6592,8 +6605,11 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
|
||||
addr_touse = sa;
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
#ifdef INET
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
|
||||
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
|
||||
*error = EINVAL;
|
||||
@ -6605,6 +6621,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
|
||||
*error = EINVAL;
|
||||
return;
|
||||
}
|
||||
#ifdef INET
|
||||
sin6 = (struct sockaddr_in6 *)addr_touse;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
@ -6617,6 +6634,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
addr_touse = (struct sockaddr *)&sin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef INET
|
||||
|
Loading…
Reference in New Issue
Block a user