svn commit: r283699 - stable/10/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Fri May 29 11:15:02 UTC 2015
Author: tuexen
Date: Fri May 29 11:15:00 2015
New Revision: 283699
URL: https://svnweb.freebsd.org/changeset/base/283699
Log:
MFC r275567:
Fix the support of mapped IPv4 addresses.
Thanks to Mark Bonnekessel and Markus Boese for making me aware of the
problems.
Modified:
stable/10/sys/netinet/sctp_usrreq.c
stable/10/sys/netinet/sctputil.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c Fri May 29 11:04:55 2015 (r283698)
+++ stable/10/sys/netinet/sctp_usrreq.c Fri May 29 11:15:00 2015 (r283699)
@@ -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
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
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
@@ -2217,23 +2226,27 @@ flags_out:
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);
@@ -2265,24 +2278,28 @@ flags_out:
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;
@@ -2293,15 +2310,15 @@ flags_out:
}
#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;
@@ -2338,13 +2355,35 @@ flags_out:
{
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
@@ -2353,22 +2392,20 @@ flags_out:
* 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);
@@ -2377,10 +2414,10 @@ flags_out:
} 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);
@@ -2396,10 +2433,10 @@ flags_out:
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) {
@@ -2515,13 +2552,35 @@ flags_out:
{
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
@@ -2530,14 +2589,15 @@ flags_out:
* 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;
@@ -2556,7 +2616,7 @@ flags_out:
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);
@@ -2773,16 +2833,32 @@ flags_out:
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 {
@@ -3122,13 +3198,35 @@ flags_out:
{
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
@@ -3137,22 +3235,20 @@ flags_out:
* 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);
@@ -3161,10 +3257,10 @@ flags_out:
} 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);
@@ -3180,8 +3276,8 @@ flags_out:
break;
}
}
- if (stcb) {
- if (net) {
+ if (stcb != NULL) {
+ if (net != NULL) {
thlds->spt_pathmaxrxt = net->failure_threshold;
thlds->spt_pathpfthld = net->pf_threshold;
} else {
@@ -3213,12 +3309,35 @@ flags_out:
{
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
@@ -3229,21 +3348,18 @@ flags_out:
*/
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);
@@ -3252,10 +3368,10 @@ flags_out:
} 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);
@@ -3271,7 +3387,7 @@ flags_out:
break;
}
}
- if (stcb) {
+ if (stcb != NULL) {
if (net) {
encaps->sue_port = net->port;
} else {
@@ -4950,12 +5066,35 @@ sctp_setopt(struct socket *so, int optna
{
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
@@ -4964,25 +5103,22 @@ sctp_setopt(struct socket *so, int optna
* 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;
@@ -4991,10 +5127,10 @@ sctp_setopt(struct socket *so, int optna
} 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);
@@ -5023,7 +5159,7 @@ sctp_setopt(struct socket *so, int optna
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
@@ -5038,7 +5174,7 @@ sctp_setopt(struct socket *so, int optna
}
/* network sets ? */
- if (net) {
+ if (net != NULL) {
/************************NET SPECIFIC SET ******************/
if (paddrp->spp_flags & SPP_HB_DISABLE) {
if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
@@ -5123,7 +5259,7 @@ sctp_setopt(struct socket *so, int optna
#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) {
@@ -5154,14 +5290,14 @@ sctp_setopt(struct socket *so, int optna
}
}
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;
@@ -5242,12 +5378,12 @@ sctp_setopt(struct socket *so, int optna
* 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);
@@ -5413,13 +5549,35 @@ sctp_setopt(struct socket *so, int optna
{
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
@@ -5428,16 +5586,16 @@ sctp_setopt(struct socket *so, int optna
* 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 */
@@ -5454,7 +5612,7 @@ sctp_setopt(struct socket *so, int optna
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- if (stcb) {
+ if (stcb != NULL) {
SCTP_TCB_UNLOCK(stcb);
}
break;
@@ -5476,14 +5634,36 @@ sctp_setopt(struct socket *so, int optna
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;
@@ -5514,13 +5694,13 @@ sctp_setopt(struct socket *so, int optna
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);
@@ -5535,7 +5715,7 @@ sctp_setopt(struct socket *so, int optna
{
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);
@@ -5551,8 +5731,7 @@ sctp_setopt(struct socket *so, int optna
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;
}
@@ -5903,12 +6082,35 @@ sctp_setopt(struct socket *so, int optna
{
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
@@ -5917,25 +6119,22 @@ sctp_setopt(struct socket *so, int optna
* 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;
@@ -5944,10 +6143,10 @@ sctp_setopt(struct socket *so, int optna
} 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);
@@ -5963,8 +6162,8 @@ sctp_setopt(struct socket *so, int optna
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)) {
@@ -6044,11 +6243,35 @@ sctp_setopt(struct socket *so, int optna
{
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
@@ -6059,22 +6282,19 @@ sctp_setopt(struct socket *so, int optna
*/
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;
@@ -6083,10 +6303,10 @@ sctp_setopt(struct socket *so, int optna
} 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);
@@ -6102,8 +6322,8 @@ sctp_setopt(struct socket *so, int optna
break;
}
}
- if (stcb) {
- if (net) {
+ if (stcb != NULL) {
+ if (net != NULL) {
net->port = encaps->sue_port;
} else {
stcb->asoc.port = encaps->sue_port;
Modified: stable/10/sys/netinet/sctputil.c
==============================================================================
--- stable/10/sys/netinet/sctputil.c Fri May 29 11:04:55 2015 (r283698)
+++ stable/10/sys/netinet/sctputil.c Fri May 29 11:15:00 2015 (r283699)
@@ -2760,7 +2760,16 @@ sctp_notify_peer_addr_change(struct sctp
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)) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list