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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to