Date: Fri, 29 May 2015 11:15:01 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r283699 - stable/10/sys/netinet Message-ID: <201505291115.t4TBF1Yh086492@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505291115.t4TBF1Yh086492>