From e6194c2ed4c3fe69ba25a005d1b8b387d1ce982f Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sat, 30 Apr 2011 11:18:16 +0000 Subject: [PATCH] Improve compilation of SCTP code without INET support. Some bugs where fixed while doing this: * ASCONF-ACK messages might use wrong port number when using IPv6. * Checking for additional addresses takes the correct address into account and also does not do more comparisons than necessary. This patch is based on one received from bz@ who was sponsored by The FreeBSD Foundation and iXsystems. MFC after: 1 week --- sys/netinet/sctp_asconf.c | 845 ++++++++++++-------- sys/netinet/sctp_bsd_addr.c | 67 +- sys/netinet/sctp_input.c | 113 ++- sys/netinet/sctp_os_bsd.h | 2 + sys/netinet/sctp_output.c | 1501 +++++++++++++++++++---------------- sys/netinet/sctp_pcb.c | 605 +++++++++----- sys/netinet/sctp_sysctl.c | 36 +- sys/netinet/sctp_usrreq.c | 239 ++++-- sys/netinet/sctp_var.h | 7 + sys/netinet/sctputil.c | 10 +- sys/netinet6/sctp6_usrreq.c | 128 ++- 11 files changed, 2183 insertions(+), 1370 deletions(-) diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index ed8c118b2f45..1c0a454bea12 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -57,41 +57,51 @@ static void sctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa) { struct ip *iph; + +#ifdef INET struct sockaddr_in *sin; +#endif #ifdef INET6 struct sockaddr_in6 *sin6; #endif iph = mtod(m, struct ip *); - if (iph->ip_v == IPVERSION) { - /* IPv4 source */ - sin = (struct sockaddr_in *)sa; - bzero(sin, sizeof(*sin)); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - sin->sin_port = 0; - sin->sin_addr.s_addr = iph->ip_src.s_addr; - return; - } + switch (iph->ip_v) { +#ifdef INET + case IPVERSION: + { + /* IPv4 source */ + sin = (struct sockaddr_in *)sa; + bzero(sin, sizeof(*sin)); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_port = 0; + sin->sin_addr.s_addr = iph->ip_src.s_addr; + break; + } +#endif #ifdef INET6 - else if (iph->ip_v == (IPV6_VERSION >> 4)) { - /* IPv6 source */ - struct ip6_hdr *ip6; + case (IPV6_VERSION >> 4): + { + /* IPv6 source */ + struct ip6_hdr *ip6; - sin6 = (struct sockaddr_in6 *)sa; - bzero(sin6, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - sin6->sin6_port = 0; - ip6 = mtod(m, struct ip6_hdr *); - sin6->sin6_addr = ip6->ip6_src; - return; - } + sin6 = (struct sockaddr_in6 *)sa; + bzero(sin6, sizeof(*sin6)); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_port = 0; + ip6 = mtod(m, struct ip6_hdr *); + sin6->sin6_addr = ip6->ip6_src; + break; + } #endif /* INET6 */ - else - return; + default: + break; + } + return; } /* @@ -192,33 +202,36 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_source, sa_store; - struct sctp_ipv4addr_param *v4addr; + struct sctp_paramhdr *ph; uint16_t param_type, param_length, aparam_length; struct sockaddr *sa; - struct sockaddr_in *sin; int zero_address = 0; +#ifdef INET + struct sockaddr_in *sin; + struct sctp_ipv4addr_param *v4addr; + +#endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; -#endif /* INET6 */ +#endif aparam_length = ntohs(aph->ph.param_length); - v4addr = (struct sctp_ipv4addr_param *)(aph + 1); -#ifdef INET6 - v6addr = (struct sctp_ipv6addr_param *)(aph + 1); -#endif /* INET6 */ - param_type = ntohs(v4addr->ph.param_type); - param_length = ntohs(v4addr->ph.param_length); + ph = (struct sctp_paramhdr *)(aph + 1); + param_type = ntohs(ph->param_type); + param_length = ntohs(ph->param_length); sa = (struct sockaddr *)&sa_store; switch (param_type) { +#ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return NULL; } + v4addr = (struct sctp_ipv4addr_param *)ph; sin = (struct sockaddr_in *)&sa_store; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; @@ -230,12 +243,14 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); break; - case SCTP_IPV6_ADDRESS: +#endif #ifdef INET6 + case SCTP_IPV6_ADDRESS: if (param_length != sizeof(struct sctp_ipv6addr_param)) { /* invalid param size */ return NULL; } + v6addr = (struct sctp_ipv6addr_param *)ph; sin6 = (struct sockaddr_in6 *)&sa_store; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; @@ -247,18 +262,13 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, zero_address = 1; SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); -#else - /* IPv6 not enabled! */ - /* FIX ME: currently sends back an invalid param error */ - m_reply = sctp_asconf_error_response(aph->correlation_id, - SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, aparam_length); - SCTPDBG(SCTP_DEBUG_ASCONF1, - "process_asconf_add_ip: v6 disabled- skipping "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); - return m_reply; -#endif break; +#endif default: + /* + * XXX: Is this the correct error cause? Maybe + * SCTP_CAUSE_INVALID_PARAM is a better choice. + */ m_reply = sctp_asconf_error_response(aph->correlation_id, SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, aparam_length); @@ -293,7 +303,6 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL); } - return m_reply; } @@ -331,37 +340,40 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_source, sa_store; - struct sctp_ipv4addr_param *v4addr; + struct sctp_paramhdr *ph; uint16_t param_type, param_length, aparam_length; struct sockaddr *sa; - struct sockaddr_in *sin; int zero_address = 0; int result; +#ifdef INET + struct sockaddr_in *sin; + struct sctp_ipv4addr_param *v4addr; + +#endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; -#endif /* INET6 */ +#endif /* get the source IP address for src and 0.0.0.0/::0 delete checks */ sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source); aparam_length = ntohs(aph->ph.param_length); - v4addr = (struct sctp_ipv4addr_param *)(aph + 1); -#ifdef INET6 - v6addr = (struct sctp_ipv6addr_param *)(aph + 1); -#endif /* INET6 */ - param_type = ntohs(v4addr->ph.param_type); - param_length = ntohs(v4addr->ph.param_length); + ph = (struct sctp_paramhdr *)(aph + 1); + param_type = ntohs(ph->param_type); + param_length = ntohs(ph->param_length); sa = (struct sockaddr *)&sa_store; switch (param_type) { +#ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return NULL; } + v4addr = (struct sctp_ipv4addr_param *)ph; sin = (struct sockaddr_in *)&sa_store; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; @@ -374,12 +386,14 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, "process_asconf_delete_ip: deleting "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); break; +#endif +#ifdef INET6 case SCTP_IPV6_ADDRESS: if (param_length != sizeof(struct sctp_ipv6addr_param)) { /* invalid param size */ return NULL; } -#ifdef INET6 + v6addr = (struct sctp_ipv6addr_param *)ph; sin6 = (struct sockaddr_in6 *)&sa_store; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; @@ -392,15 +406,8 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: deleting "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); -#else - /* IPv6 not enabled! No "action" needed; just ack it */ - SCTPDBG(SCTP_DEBUG_ASCONF1, - "process_asconf_delete_ip: v6 disabled- ignoring: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); - /* just respond with a "success" ASCONF-ACK */ - return NULL; -#endif break; +#endif default: m_reply = sctp_asconf_error_response(aph->correlation_id, SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, @@ -466,33 +473,36 @@ sctp_process_asconf_set_primary(struct mbuf *m, { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_source, sa_store; - struct sctp_ipv4addr_param *v4addr; + struct sctp_paramhdr *ph; uint16_t param_type, param_length, aparam_length; struct sockaddr *sa; - struct sockaddr_in *sin; int zero_address = 0; +#ifdef INET + struct sockaddr_in *sin; + struct sctp_ipv4addr_param *v4addr; + +#endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; -#endif /* INET6 */ +#endif aparam_length = ntohs(aph->ph.param_length); - v4addr = (struct sctp_ipv4addr_param *)(aph + 1); -#ifdef INET6 - v6addr = (struct sctp_ipv6addr_param *)(aph + 1); -#endif /* INET6 */ - param_type = ntohs(v4addr->ph.param_type); - param_length = ntohs(v4addr->ph.param_length); + ph = (struct sctp_paramhdr *)(aph + 1); + param_type = ntohs(ph->param_type); + param_length = ntohs(ph->param_length); sa = (struct sockaddr *)&sa_store; switch (param_type) { +#ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return NULL; } + v4addr = (struct sctp_ipv4addr_param *)ph; sin = (struct sockaddr_in *)&sa_store; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; @@ -503,12 +513,14 @@ sctp_process_asconf_set_primary(struct mbuf *m, SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); break; +#endif +#ifdef INET6 case SCTP_IPV6_ADDRESS: if (param_length != sizeof(struct sctp_ipv6addr_param)) { /* invalid param size */ return NULL; } -#ifdef INET6 + v6addr = (struct sctp_ipv6addr_param *)ph; sin6 = (struct sockaddr_in6 *)&sa_store; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; @@ -519,15 +531,8 @@ sctp_process_asconf_set_primary(struct mbuf *m, zero_address = 1; SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); -#else - /* IPv6 not enabled! No "action" needed; just ack it */ - SCTPDBG(SCTP_DEBUG_ASCONF1, - "process_asconf_set_primary: v6 disabled- ignoring: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); - /* just respond with a "success" ASCONF-ACK */ - return NULL; -#endif break; +#endif default: m_reply = sctp_asconf_error_response(aph->correlation_id, SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, @@ -655,7 +660,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, if (first) { /* delete old cache */ - SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing firstASCONF. Try to delte old cache\n"); + SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing first ASCONF. Try to delete old cache\n"); TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) { if (ack->serial_number == serial_num) @@ -825,10 +830,8 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, ack->last_sent_to = NULL; ack->data = m_ack; ack->len = 0; - n = m_ack; - while (n) { + for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) { ack->len += SCTP_BUF_LEN(n); - n = SCTP_BUF_NEXT(n); } TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next); @@ -846,12 +849,13 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n"); /* pullup already done, IP options already stripped */ iph = mtod(m, struct ip *); - sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph)); switch (iph->ip_v) { +#ifdef INET case IPVERSION: { struct sockaddr_in *from4; + sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph)); from4 = (struct sockaddr_in *)&from_store; bzero(from4, sizeof(*from4)); from4->sin_family = AF_INET; @@ -860,6 +864,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, from4->sin_port = sh->src_port; break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -867,6 +872,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, struct sockaddr_in6 *from6; ip6 = mtod(m, struct ip6_hdr *); + sh = (struct sctphdr *)((caddr_t)ip6 + sizeof(*ip6)); from6 = (struct sockaddr_in6 *)&from_store; bzero(from6, sizeof(*from6)); from6->sin6_family = AF_INET6; @@ -908,28 +914,36 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, static uint32_t sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) { + switch (sa->sa_family) { #ifdef INET6 - if (sa->sa_family == AF_INET6) { - /* IPv6 sa address */ - /* XXX scopeid */ - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + case AF_INET6: + { + /* XXX scopeid */ + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; - if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && - (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, - sizeof(struct in6_addr)) == 0)) { - return (1); + if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && + (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, + sizeof(struct in6_addr)) == 0)) { + return (1); + } + break; } - } else -#endif /* INET6 */ - if (sa->sa_family == AF_INET) { - /* IPv4 sa address */ - struct sockaddr_in *sin = (struct sockaddr_in *)sa; +#endif +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; - if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && - (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, - sizeof(struct in_addr)) == 0)) { - return (1); + if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && + (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, + sizeof(struct in_addr)) == 0)) { + return (1); + } + break; } +#endif + default: + break; } return (0); } @@ -938,43 +952,48 @@ sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) * does the address match? returns 0 if not, 1 if so */ static uint32_t -sctp_addr_match( - struct sctp_ipv6addr_param *v6addr, - struct sockaddr *sa) +sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) { uint16_t param_type, param_length; - struct sctp_ipv4addr_param *v4addr = (struct sctp_ipv4addr_param *)v6addr; + param_type = ntohs(ph->param_type); + param_length = ntohs(ph->param_length); + switch (sa->sa_family) { #ifdef INET6 - if (sa->sa_family == AF_INET6) { - /* IPv6 sa address */ - /* XXX scopeid */ - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + case AF_INET6: + { + /* XXX scopeid */ + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + struct sctp_ipv6addr_param *v6addr; - param_type = ntohs(v6addr->ph.param_type); - param_length = ntohs(v6addr->ph.param_length); - - if ((param_type == SCTP_IPV6_ADDRESS) && - param_length == sizeof(struct sctp_ipv6addr_param) && - (memcmp(&v6addr->addr, &sin6->sin6_addr, - sizeof(struct in6_addr)) == 0)) { - return (1); + v6addr = (struct sctp_ipv6addr_param *)ph; + if ((param_type == SCTP_IPV6_ADDRESS) && + param_length == sizeof(struct sctp_ipv6addr_param) && + (memcmp(&v6addr->addr, &sin6->sin6_addr, + sizeof(struct in6_addr)) == 0)) { + return (1); + } + break; } - } #endif - if (sa->sa_family == AF_INET) { - /* IPv4 sa address */ - struct sockaddr_in *sin = (struct sockaddr_in *)sa; +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sctp_ipv4addr_param *v4addr; - param_type = ntohs(v4addr->ph.param_type); - param_length = ntohs(v4addr->ph.param_length); - - if ((param_type == SCTP_IPV4_ADDRESS) && - param_length == sizeof(struct sctp_ipv4addr_param) && - (memcmp(&v4addr->addr, &sin->sin_addr, - sizeof(struct in_addr)) == 0)) { - return (1); + v4addr = (struct sctp_ipv4addr_param *)ph; + if ((param_type == SCTP_IPV4_ADDRESS) && + param_length == sizeof(struct sctp_ipv4addr_param) && + (memcmp(&v4addr->addr, &sin->sin_addr, + sizeof(struct in_addr)) == 0)) { + return (1); + } + break; } +#endif + default: + break; } return (0); } @@ -1179,17 +1198,25 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) continue; changed = 0; - if (net->ro._l_addr.sa.sa_family == AF_INET) { - if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) { changed = 1; - } -#ifdef INET6 - if (net->ro._l_addr.sa.sa_family == AF_INET6) { - if (sctp_v6src_match_nexthop( - &newifa->address.sin6, (sctp_route_t *) & net->ro)) - changed = 1; - } + } + break; #endif +#ifdef INET6 + case AF_INET6: + if (sctp_v6src_match_nexthop( + &newifa->address.sin6, (sctp_route_t *) & net->ro)) { + changed = 1; + } + break; +#endif + default: + break; + } /* * if the newly added address does not relate routing * information, we skip. @@ -1316,31 +1343,40 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, aa->ifa = ifa; atomic_add_int(&ifa->refcount, 1); /* correlation_id filled in during send routine later... */ - if (ifa->address.sa.sa_family == AF_INET6) { - /* IPv6 address */ - struct sockaddr_in6 *sin6; + switch (ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&ifa->address.sa; - sa = (struct sockaddr *)sin6; - aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; - aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); - aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + - sizeof(struct sctp_ipv6addr_param); - memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, - sizeof(struct in6_addr)); - } else if (ifa->address.sa.sa_family == AF_INET) { - /* IPv4 address */ - struct sockaddr_in *sin; + sin6 = (struct sockaddr_in6 *)&ifa->address.sa; + sa = (struct sockaddr *)sin6; + aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; + aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + + sizeof(struct sctp_ipv6addr_param); + memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, + sizeof(struct in6_addr)); + break; + } +#endif +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sa; - sa = (struct sockaddr *)sin; - aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; - aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); - aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + - sizeof(struct sctp_ipv4addr_param); - memcpy(&aa->ap.addrp.addr, &sin->sin_addr, - sizeof(struct in_addr)); - } else { + sin = (struct sockaddr_in *)&ifa->address.sa; + sa = (struct sockaddr *)sin; + aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; + aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + + sizeof(struct sctp_ipv4addr_param); + memcpy(&aa->ap.addrp.addr, &sin->sin_addr, + sizeof(struct in_addr)); + break; + } +#endif + default: /* invalid family! */ SCTP_FREE(aa, SCTP_M_ASC_ADDR); sctp_free_ifa(ifa); @@ -1522,26 +1558,37 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) if (ifa) atomic_add_int(&ifa->refcount, 1); /* correlation_id filled in during send routine later... */ - if (sa->sa_family == AF_INET6) { - /* IPv6 address */ - struct sockaddr_in6 *sin6; + switch (sa->sa_family) { +#ifdef INET6 + case AF_INET6: + { + /* IPv6 address */ + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)sa; - aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; - aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); - aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); - memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, - sizeof(struct in6_addr)); - } else if (sa->sa_family == AF_INET) { - /* IPv4 address */ - struct sockaddr_in *sin = (struct sockaddr_in *)sa; + sin6 = (struct sockaddr_in6 *)sa; + aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; + aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); + memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, + sizeof(struct in6_addr)); + break; + } +#endif +#ifdef INET + case AF_INET: + { + /* IPv4 address */ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; - aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; - aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); - aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); - memcpy(&aa->ap.addrp.addr, &sin->sin_addr, - sizeof(struct in_addr)); - } else { + aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; + aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); + memcpy(&aa->ap.addrp.addr, &sin->sin_addr, + sizeof(struct in_addr)); + break; + } +#endif + default: /* invalid family! */ SCTP_FREE(aa, SCTP_M_ASC_ADDR); if (ifa) @@ -1923,10 +1970,19 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, */ /* first, make sure it's a good address family */ - if (ifa->address.sa.sa_family != AF_INET6 && - ifa->address.sa.sa_family != AF_INET) { + switch (ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: + break; +#endif +#ifdef INET + case AF_INET: + break; +#endif + default: return; } +#ifdef INET6 /* make sure we're "allowed" to add this type of addr */ if (ifa->address.sa.sa_family == AF_INET6) { /* invalid if we're not a v6 endpoint */ @@ -1937,6 +1993,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return; } } +#endif /* put this address on the "pending/do not use yet" list */ sctp_add_local_addr_restricted(stcb, ifa); /* @@ -1971,6 +2028,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; } #endif +#ifdef INET case AF_INET: { struct sockaddr_in *sin; @@ -1993,6 +2051,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } break; } +#endif default: /* else, not AF_INET or AF_INET6, so skip */ return; @@ -2036,35 +2095,38 @@ sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val) asc = (struct sctp_asconf_iterator *)ptr; LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { ifa = l->ifa; - if (ifa->address.sa.sa_family == AF_INET6) { + switch (ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: /* invalid if we're not a v6 endpoint */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { cnt_invalid++; if (asc->cnt == cnt_invalid) return (1); - else - continue; } - } else if (ifa->address.sa.sa_family == AF_INET) { - /* invalid if we are a v6 only endpoint */ - struct in6pcb *inp6; + break; +#endif +#ifdef INET + case AF_INET: + { + /* invalid if we are a v6 only endpoint */ + struct in6pcb *inp6; - inp6 = (struct in6pcb *)&inp->ip_inp.inp; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp6)) { - cnt_invalid++; - if (asc->cnt == cnt_invalid) - return (1); - else - continue; + inp6 = (struct in6pcb *)&inp->ip_inp.inp; + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp6)) { + cnt_invalid++; + if (asc->cnt == cnt_invalid) + return (1); + } + break; } - } else { +#endif + default: /* invalid address family */ cnt_invalid++; if (asc->cnt == cnt_invalid) return (1); - else - continue; } } return (0); @@ -2153,6 +2215,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; } #endif +#ifdef INET case AF_INET: { /* invalid if we are a v6 only endpoint */ @@ -2184,6 +2247,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } break; } +#endif default: /* invalid address family */ cnt_invalid++; @@ -2374,7 +2438,7 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) struct sctp_asconf_chunk *acp; struct sctp_asconf_paramhdr *aph; uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; - struct sctp_ipv6addr_param *p_addr; + struct sctp_paramhdr *ph; int add_cnt, del_cnt; uint16_t last_param_type; @@ -2389,12 +2453,12 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) acp = mtod(chk->data, struct sctp_asconf_chunk *); offset += sizeof(struct sctp_asconf_chunk); asconf_limit = ntohs(acp->ch.chunk_length); - p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf); - if (p_addr == NULL) { + ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf); + if (ph == NULL) { SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n"); continue; } - offset += ntohs(p_addr->ph.param_length); + offset += ntohs(ph->param_length); aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); if (aph == NULL) { @@ -2423,8 +2487,8 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n"); break; } - p_addr = (struct sctp_ipv6addr_param *)(aph + 1); - if (sctp_addr_match(p_addr, &sctp_ifa->address.sa) != 0) { + ph = (struct sctp_paramhdr *)(aph + 1); + if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) { switch (param_type) { case SCTP_ADD_IP_ADDRESS: add_cnt++; @@ -2480,52 +2544,72 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) continue; } LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { - if (sctp_ifa->address.sa.sa_family == AF_INET && - stcb->asoc.ipv4_addr_legal) { - struct sockaddr_in *sin; + switch (sctp_ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: + if (stcb->asoc.ipv4_addr_legal) { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; - if (sin->sin_addr.s_addr == 0) { - /* skip unspecifed addresses */ - continue; + sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + if (sin->sin_addr.s_addr == 0) { + /* skip unspecifed addresses */ + continue; + } + if (stcb->asoc.ipv4_local_scope == 0 && + IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) + continue; + + if (sctp_is_addr_restricted(stcb, sctp_ifa) && + (!sctp_is_addr_pending(stcb, sctp_ifa))) + continue; + /* + * found a valid local v4 address to + * use + */ + if (addr_locked == SCTP_ADDR_NOT_LOCKED) + SCTP_IPI_ADDR_RUNLOCK(); + return (&sctp_ifa->address.sa); } - if (stcb->asoc.ipv4_local_scope == 0 && - IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) - continue; + break; +#endif +#ifdef INET6 + case AF_INET6: + if (stcb->asoc.ipv6_addr_legal) { + struct sockaddr_in6 *sin6; - if (sctp_is_addr_restricted(stcb, sctp_ifa) && - (!sctp_is_addr_pending(stcb, sctp_ifa))) - continue; - /* found a valid local v4 address to use */ - if (addr_locked == SCTP_ADDR_NOT_LOCKED) - SCTP_IPI_ADDR_RUNLOCK(); - return (&sctp_ifa->address.sa); - } else if (sctp_ifa->address.sa.sa_family == AF_INET6 && - stcb->asoc.ipv6_addr_legal) { - struct sockaddr_in6 *sin6; + if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { + continue; + } + sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * we skip unspecifed + * addresses + */ + continue; + } + if (stcb->asoc.local_scope == 0 && + IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + continue; + if (stcb->asoc.site_scope == 0 && + IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) + continue; - if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { - continue; + if (sctp_is_addr_restricted(stcb, sctp_ifa) && + (!sctp_is_addr_pending(stcb, sctp_ifa))) + continue; + /* + * found a valid local v6 address to + * use + */ + if (addr_locked == SCTP_ADDR_NOT_LOCKED) + SCTP_IPI_ADDR_RUNLOCK(); + return (&sctp_ifa->address.sa); } - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* we skip unspecifed addresses */ - continue; - } - if (stcb->asoc.local_scope == 0 && - IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) - continue; - if (stcb->asoc.site_scope == 0 && - IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) - continue; - - if (sctp_is_addr_restricted(stcb, sctp_ifa) && - (!sctp_is_addr_pending(stcb, sctp_ifa))) - continue; - /* found a valid local v6 address to use */ - if (addr_locked == SCTP_ADDR_NOT_LOCKED) - SCTP_IPI_ADDR_RUNLOCK(); - return (&sctp_ifa->address.sa); + break; +#endif + default: + break; } } } @@ -2697,7 +2781,9 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) lookup = (struct sctp_ipv6addr_param *)lookup_ptr; if (found_addr != NULL) { - if (found_addr->sa_family == AF_INET6) { + switch (found_addr->sa_family) { +#ifdef INET6 + case AF_INET6: /* copy IPv6 address */ lookup->ph.param_type = htons(SCTP_IPV6_ADDRESS); @@ -2705,7 +2791,10 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) addr_size = sizeof(struct in6_addr); addr_ptr = (caddr_t)&((struct sockaddr_in6 *) found_addr)->sin6_addr; - } else { + break; +#endif +#ifdef INET + case AF_INET: /* copy IPv4 address */ lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); @@ -2713,6 +2802,13 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) addr_size = sizeof(struct in_addr); addr_ptr = (caddr_t)&((struct sockaddr_in *) found_addr)->sin_addr; + break; +#endif + default: + p_size = 0; + addr_size = 0; + addr_ptr = NULL; + break; } lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); memcpy(lookup->addr, addr_ptr, addr_size); @@ -2722,7 +2818,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) /* uh oh... don't have any address?? */ SCTPDBG(SCTP_DEBUG_ASCONF1, "compose_asconf: no lookup addr!\n"); - /* for now, we send a IPv4 address of 0.0.0.0 */ + /* XXX for now, we send a IPv4 address of 0.0.0.0 */ lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); bzero(lookup->addr, sizeof(struct in_addr)); @@ -2754,8 +2850,15 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, uint16_t plen, ptype; struct sctp_ifa *sctp_ifa; struct sctp_ipv6addr_param addr_store; + +#ifdef INET6 struct sockaddr_in6 sin6; + +#endif +#ifdef INET struct sockaddr_in sin; + +#endif struct sockaddr *sa; uint32_t vrf_id; @@ -2770,51 +2873,66 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, return; } /* init the addresses */ +#ifdef INET6 bzero(&sin6, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); sin6.sin6_port = stcb->rport; +#endif +#ifdef INET bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); sin.sin_port = stcb->rport; +#endif /* go through the addresses in the init-ack */ - ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, - sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); + ph = (struct sctp_paramhdr *) + sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), + (uint8_t *) & tmp_param); while (ph != NULL) { ptype = ntohs(ph->param_type); plen = ntohs(ph->param_length); - if (ptype == SCTP_IPV6_ADDRESS) { - struct sctp_ipv6addr_param *a6p; + switch (ptype) { +#ifdef INET6 + case SCTP_IPV6_ADDRESS: + { + struct sctp_ipv6addr_param *a6p; - /* get the entire IPv6 address param */ - a6p = (struct sctp_ipv6addr_param *) - sctp_m_getptr(m, offset, - sizeof(struct sctp_ipv6addr_param), - (uint8_t *) & addr_store); - if (plen != sizeof(struct sctp_ipv6addr_param) || - a6p == NULL) { - return; + /* get the entire IPv6 address param */ + a6p = (struct sctp_ipv6addr_param *) + sctp_m_getptr(m, offset, + sizeof(struct sctp_ipv6addr_param), + (uint8_t *) & addr_store); + if (plen != sizeof(struct sctp_ipv6addr_param) || + a6p == NULL) { + return; + } + memcpy(&sin6.sin6_addr, a6p->addr, + sizeof(struct in6_addr)); + sa = (struct sockaddr *)&sin6; + break; } - memcpy(&sin6.sin6_addr, a6p->addr, - sizeof(struct in6_addr)); - sa = (struct sockaddr *)&sin6; - } else if (ptype == SCTP_IPV4_ADDRESS) { - struct sctp_ipv4addr_param *a4p; +#endif +#ifdef INET + case SCTP_IPV4_ADDRESS: + { + struct sctp_ipv4addr_param *a4p; - /* get the entire IPv4 address param */ - a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, - sizeof(struct sctp_ipv4addr_param), - (uint8_t *) & addr_store); - if (plen != sizeof(struct sctp_ipv4addr_param) || - a4p == NULL) { - return; + /* get the entire IPv4 address param */ + a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, + sizeof(struct sctp_ipv4addr_param), + (uint8_t *) & addr_store); + if (plen != sizeof(struct sctp_ipv4addr_param) || + a4p == NULL) { + return; + } + sin.sin_addr.s_addr = a4p->addr; + sa = (struct sockaddr *)&sin; } - sin.sin_addr.s_addr = a4p->addr; - sa = (struct sockaddr *)&sin; - } else { +#endif + default: goto next_addr; } @@ -2885,22 +3003,31 @@ sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset, struct sctp_paramhdr tmp_param, *ph; uint16_t plen, ptype; struct sctp_ipv6addr_param addr_store; + +#ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *a4p; +#endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *a6p; struct sockaddr_in6 sin6_tmp; -#endif /* INET6 */ +#endif - if ( + switch (sa->sa_family) { +#ifdef INET + case AF_INET: + break; +#endif #ifdef INET6 - (sa->sa_family != AF_INET6) && -#endif /* INET6 */ - (sa->sa_family != AF_INET)) + case AF_INET6: + break; +#endif + default: return (0); + } SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); @@ -2918,55 +3045,68 @@ sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset, while (ph != NULL) { ptype = ntohs(ph->param_type); plen = ntohs(ph->param_length); + switch (ptype) { #ifdef INET6 - if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) { - /* get the entire IPv6 address param */ - a6p = (struct sctp_ipv6addr_param *) - sctp_m_getptr(m, offset, - sizeof(struct sctp_ipv6addr_param), - (uint8_t *) & addr_store); - if (plen != sizeof(struct sctp_ipv6addr_param) || - (ph == NULL) || - (a6p == NULL)) { - return (0); + case SCTP_IPV6_ADDRESS: + if (sa->sa_family == AF_INET6) { + /* get the entire IPv6 address param */ + if (plen != sizeof(struct sctp_ipv6addr_param)) { + break; + } + /* get the entire IPv6 address param */ + a6p = (struct sctp_ipv6addr_param *) + sctp_m_getptr(m, offset, + sizeof(struct sctp_ipv6addr_param), + (uint8_t *) & addr_store); + if (a6p == NULL) { + return (0); + } + sin6 = (struct sockaddr_in6 *)sa; + if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { + /* create a copy and clear scope */ + memcpy(&sin6_tmp, sin6, + sizeof(struct sockaddr_in6)); + sin6 = &sin6_tmp; + in6_clearscope(&sin6->sin6_addr); + } + if (memcmp(&sin6->sin6_addr, a6p->addr, + sizeof(struct in6_addr)) == 0) { + /* found it */ + return (1); + } } - sin6 = (struct sockaddr_in6 *)sa; - if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { - /* create a copy and clear scope */ - memcpy(&sin6_tmp, sin6, - sizeof(struct sockaddr_in6)); - sin6 = &sin6_tmp; - in6_clearscope(&sin6->sin6_addr); - } - if (memcmp(&sin6->sin6_addr, a6p->addr, - sizeof(struct in6_addr)) == 0) { - /* found it */ - return (1); - } - } else + break; #endif /* INET6 */ - - if (ptype == SCTP_IPV4_ADDRESS && - sa->sa_family == AF_INET) { - /* get the entire IPv4 address param */ - a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, - offset, sizeof(struct sctp_ipv4addr_param), - (uint8_t *) & addr_store); - if (plen != sizeof(struct sctp_ipv4addr_param) || - (ph == NULL) || - (a4p == NULL)) { - return (0); - } - sin = (struct sockaddr_in *)sa; - if (sin->sin_addr.s_addr == a4p->addr) { - /* found it */ - return (1); +#ifdef INET + case SCTP_IPV4_ADDRESS: + if (sa->sa_family == AF_INET) { + if (plen != sizeof(struct sctp_ipv4addr_param)) { + break; + } + /* get the entire IPv4 address param */ + a4p = (struct sctp_ipv4addr_param *) + sctp_m_getptr(m, offset, + sizeof(struct sctp_ipv4addr_param), + (uint8_t *) & addr_store); + if (a4p == NULL) { + return (0); + } + sin = (struct sockaddr_in *)sa; + if (sin->sin_addr.s_addr == a4p->addr) { + /* found it */ + return (1); + } } + break; +#endif + default: + break; } /* get next parameter */ offset += SCTP_SIZE32(plen); - if (offset + sizeof(struct sctp_paramhdr) > length) + if (offset + sizeof(struct sctp_paramhdr) > length) { return (0); + } ph = (struct sctp_paramhdr *) sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); @@ -3198,8 +3338,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, struct sctp_asconf_addr *aa; struct sctp_ifa *sctp_ifap; struct sctp_asconf_tag_param *vtag; + +#ifdef INET struct sockaddr_in *to; +#endif #ifdef INET6 struct sockaddr_in6 *to6; @@ -3247,24 +3390,28 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, memset(aa, 0, sizeof(struct sctp_asconf_addr)); /* fill in asconf address parameter fields */ /* ADD(0.0.0.0) */ - if (net->ro._l_addr.sa.sa_family == AF_INET) { + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); /* No need to add an address, we are using 0.0.0.0 */ TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); - } + break; +#endif #ifdef INET6 - else if (net->ro._l_addr.sa.sa_family == AF_INET6) { + case AF_INET6: aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); /* No need to add an address, we are using 0.0.0.0 */ TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + break; +#endif } -#endif /* INET6 */ SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), SCTP_M_ASC_ADDR); if (aa == NULL) { @@ -3276,24 +3423,28 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, memset(aa, 0, sizeof(struct sctp_asconf_addr)); /* fill in asconf address parameter fields */ /* ADD(0.0.0.0) */ - if (net->ro._l_addr.sa.sa_family == AF_INET) { + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); /* No need to add an address, we are using 0.0.0.0 */ TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); - } + break; +#endif #ifdef INET6 - else if (net->ro._l_addr.sa.sa_family == AF_INET6) { + case AF_INET6: aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); /* No need to add an address, we are using 0.0.0.0 */ TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + break; +#endif } -#endif /* INET6 */ /* Now we must hunt the addresses and add all global addresses */ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { struct sctp_vrf *vrf = NULL; @@ -3308,18 +3459,20 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, SCTP_IPI_ADDR_RLOCK(); LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { - if (sctp_ifap->address.sa.sa_family == AF_INET) { + switch (sctp_ifap->address.sa.sa_family) { +#ifdef INET + case AF_INET: to = &sctp_ifap->address.sin; - if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { continue; } if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { continue; } - } + break; +#endif #ifdef INET6 - else if (sctp_ifap->address.sa.sa_family == AF_INET6) { + case AF_INET6: to6 = &sctp_ifap->address.sin6; if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { continue; @@ -3327,8 +3480,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { continue; } - } + break; #endif + default: + continue; + } sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); } } @@ -3354,18 +3510,20 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, continue; } sctp_ifap = laddr->ifa; - if (sctp_ifap->address.sa.sa_family == AF_INET) { + switch (sctp_ifap->address.sa.sa_family) { +#ifdef INET + case AF_INET: to = &sctp_ifap->address.sin; - if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { continue; } if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { continue; } - } + break; +#endif #ifdef INET6 - else if (sctp_ifap->address.sa.sa_family == AF_INET6) { + case AF_INET6: to6 = &sctp_ifap->address.sin6; if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { continue; @@ -3373,8 +3531,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { continue; } - } + break; #endif + default: + continue; + } sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); } } diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index 0a35df07f961..3d004b6b108c 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -228,10 +228,14 @@ sctp_init_ifns_for_vrf(int vrfid) */ struct ifnet *ifn; struct ifaddr *ifa; - struct in6_ifaddr *ifa6; struct sctp_ifa *sctp_ifa; uint32_t ifa_flags; +#ifdef INET6 + struct in6_ifaddr *ifa6; + +#endif + IFNET_RLOCK(); TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { IF_ADDR_LOCK(ifn); @@ -239,29 +243,44 @@ sctp_init_ifns_for_vrf(int vrfid) if (ifa->ifa_addr == NULL) { continue; } - if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { - /* non inet/inet6 skip */ - continue; - } - if (ifa->ifa_addr->sa_family == AF_INET6) { + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { + continue; + } + break; +#endif +#ifdef INET6 + case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { /* skip unspecifed addresses */ continue; } - } else { - if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { - continue; - } + break; +#endif + default: + continue; } if (sctp_is_desired_interface_type(ifa) == 0) { /* non desired type */ continue; } - if (ifa->ifa_addr->sa_family == AF_INET6) { + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + ifa_flags = 0; + break; +#endif +#ifdef INET6 + case AF_INET6: ifa6 = (struct in6_ifaddr *)ifa; ifa_flags = ifa6->ia6_flags; - } else { + break; +#endif + default: ifa_flags = 0; + break; } sctp_ifa = sctp_add_addr_to_vrf(vrfid, (void *)ifn, @@ -320,20 +339,26 @@ sctp_addr_change(struct ifaddr *ifa, int cmd) if (ifa->ifa_addr == NULL) { return; } - if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { - /* non inet/inet6 skip */ - return; - } - if (ifa->ifa_addr->sa_family == AF_INET6) { + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { + return; + } + break; +#endif +#ifdef INET6 + case AF_INET6: ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags; if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { /* skip unspecifed addresses */ return; } - } else { - if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { - return; - } + break; +#endif + default: + /* non inet/inet6 skip */ + return; } if (sctp_is_desired_interface_type(ifa) == 0) { diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 3c25eaabf291..63771d7e8932 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -530,38 +530,57 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) { struct sockaddr_storage store; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; struct sctp_nets *r_net, *f_net; struct timeval tv; int req_prim = 0; +#ifdef INET + struct sockaddr_in *sin; + +#endif +#ifdef INET6 + struct sockaddr_in6 *sin6; + +#endif + if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { /* Invalid length */ return; } - sin = (struct sockaddr_in *)&store; - sin6 = (struct sockaddr_in6 *)&store; - memset(&store, 0, sizeof(store)); - if (cp->heartbeat.hb_info.addr_family == AF_INET && - cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { - sin->sin_family = cp->heartbeat.hb_info.addr_family; - sin->sin_len = cp->heartbeat.hb_info.addr_len; - sin->sin_port = stcb->rport; - memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, - sizeof(sin->sin_addr)); - } else if (cp->heartbeat.hb_info.addr_family == AF_INET6 && - cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { - sin6->sin6_family = cp->heartbeat.hb_info.addr_family; - sin6->sin6_len = cp->heartbeat.hb_info.addr_len; - sin6->sin6_port = stcb->rport; - memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, - sizeof(sin6->sin6_addr)); - } else { + switch (cp->heartbeat.hb_info.addr_family) { +#ifdef INET + case AF_INET: + if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { + sin = (struct sockaddr_in *)&store; + sin->sin_family = cp->heartbeat.hb_info.addr_family; + sin->sin_len = cp->heartbeat.hb_info.addr_len; + sin->sin_port = stcb->rport; + memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, + sizeof(sin->sin_addr)); + } else { + return; + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { + sin6 = (struct sockaddr_in6 *)&store; + sin6->sin6_family = cp->heartbeat.hb_info.addr_family; + sin6->sin6_len = cp->heartbeat.hb_info.addr_len; + sin6->sin6_port = stcb->rport; + memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, + sizeof(sin6->sin6_addr)); + } else { + return; + } + break; +#endif + default: return; } - r_net = sctp_findnet(stcb, (struct sockaddr *)sin); + r_net = sctp_findnet(stcb, (struct sockaddr *)&store); if (r_net == NULL) { SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); return; @@ -1940,8 +1959,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, struct sctp_init_ack_chunk *initack_cp, initack_buf; struct sockaddr_storage sa_store; struct sockaddr *initack_src = (struct sockaddr *)&sa_store; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; struct sctp_association *asoc; int chk_length; int init_offset, initack_offset, initack_limit; @@ -1950,6 +1967,14 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, uint32_t old_tag; uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; +#ifdef INET + struct sockaddr_in *sin; + +#endif +#ifdef INET6 + struct sockaddr_in6 *sin6; + +#endif #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -2169,14 +2194,19 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, /* warning, we re-use sin, sin6, sa_store here! */ /* pull in local_address (our "from" address) */ - if (cookie->laddr_type == SCTP_IPV4_ADDRESS) { + switch (cookie->laddr_type) { +#ifdef INET + case SCTP_IPV4_ADDRESS: /* source addr is IPv4 */ sin = (struct sockaddr_in *)initack_src; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(struct sockaddr_in); sin->sin_addr.s_addr = cookie->laddress[0]; - } else if (cookie->laddr_type == SCTP_IPV6_ADDRESS) { + break; +#endif +#ifdef INET6 + case SCTP_IPV6_ADDRESS: /* source addr is IPv6 */ sin6 = (struct sockaddr_in6 *)initack_src; memset(sin6, 0, sizeof(*sin6)); @@ -2185,7 +2215,9 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, sin6->sin6_scope_id = cookie->scope_id; memcpy(&sin6->sin6_addr, cookie->laddress, sizeof(sin6->sin6_addr)); - } else { + break; +#endif + default: atomic_add_int(&stcb->asoc.refcnt, 1); #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_TCB_UNLOCK(stcb); @@ -2295,8 +2327,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, struct sctp_tcb **locked_tcb, uint32_t vrf_id, uint16_t port) { struct sctp_state_cookie *cookie; - struct sockaddr_in6 sin6; - struct sockaddr_in sin; struct sctp_tcb *l_stcb = *stcb; struct sctp_inpcb *l_inp; struct sockaddr *to; @@ -2318,6 +2348,15 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, int had_a_existing_tcb = 0; int send_int_conf = 0; +#ifdef INET + struct sockaddr_in sin; + +#endif +#ifdef INET6 + struct sockaddr_in6 sin6; + +#endif + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_cookie: handling COOKIE-ECHO\n"); @@ -2327,6 +2366,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, /* First get the destination address setup too. */ iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: { /* its IPv4 */ @@ -2341,6 +2381,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, size_of_pkt = SCTP_GET_IPV4_LENGTH(iph); break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -2535,7 +2576,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, * up. */ to = NULL; - if (cookie->addr_type == SCTP_IPV6_ADDRESS) { + switch (cookie->addr_type) { +#ifdef INET6 + case SCTP_IPV6_ADDRESS: memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); @@ -2544,14 +2587,19 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, memcpy(&sin6.sin6_addr.s6_addr, cookie->address, sizeof(sin6.sin6_addr.s6_addr)); to = (struct sockaddr *)&sin6; - } else if (cookie->addr_type == SCTP_IPV4_ADDRESS) { + break; +#endif +#ifdef INET + case SCTP_IPV4_ADDRESS: memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); sin.sin_port = sh->src_port; sin.sin_addr.s_addr = cookie->address[0]; to = (struct sockaddr *)&sin; - } else { + break; +#endif + default: /* This should not happen */ return (NULL); } @@ -5705,6 +5753,7 @@ sctp_print_mbuf_chain(struct mbuf *m) #endif +#ifdef INET void sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) { @@ -6003,3 +6052,5 @@ sctp_input(struct mbuf *m, int off) #endif sctp_input_with_port(m, off, 0); } + +#endif diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 4e0dcab53520..4ab0add869de 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$"); #include "opt_ipsec.h" #include "opt_compat.h" #include "opt_inet6.h" +#if 1 #include "opt_inet.h" +#endif #include "opt_sctp.h" #include diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 23361baf57aa..1e16b99e6315 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -1880,6 +1880,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, return (0); } switch (ifa->address.sa.sa_family) { +#ifdef INET case AF_INET: if (ipv4_addr_legal) { struct sockaddr_in *sin; @@ -1898,6 +1899,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, return (0); } break; +#endif #ifdef INET6 case AF_INET6: if (ipv6_addr_legal) { @@ -1945,12 +1947,18 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa) struct mbuf *mret; int len; - if (ifa->address.sa.sa_family == AF_INET) { + switch (ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: len = sizeof(struct sctp_ipv4addr_param); - } else if (ifa->address.sa.sa_family == AF_INET6) { + break; +#endif +#ifdef INET6 + case AF_INET6: len = sizeof(struct sctp_ipv6addr_param); - } else { - /* unknown type */ + break; +#endif + default: return (m); } if (M_TRAILINGSPACE(m) >= len) { @@ -1973,6 +1981,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa) } /* now add the parameter */ switch (ifa->address.sa.sa_family) { +#ifdef INET case AF_INET: { struct sctp_ipv4addr_param *ipv4p; @@ -1986,6 +1995,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa) SCTP_BUF_LEN(mret) += len; break; } +#endif #ifdef INET6 case AF_INET6: { @@ -2225,6 +2235,7 @@ sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa, SCTPDBG(SCTP_DEBUG_OUTPUT2, "Is destination preferred:"); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &ifa->address.sa); /* Ok the address may be ok */ +#ifdef INET6 if (fam == AF_INET6) { /* ok to use deprecated addresses? no lets not! */ if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { @@ -2244,6 +2255,7 @@ sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa, } } } +#endif /* * Now that we know what is what, implement or table this could in * theory be done slicker (it used to be), but this is @@ -2312,6 +2324,7 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa, if ((dest_is_loop == 0) && (dest_is_priv == 0)) { dest_is_global = 1; } +#ifdef INET6 if (fam == AF_INET6) { /* ok to use deprecated addresses? */ if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { @@ -2323,6 +2336,7 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa, return (NULL); } } +#endif /* * Now that we know what is what, implement our table. This could in * theory be done slicker (it used to be), but this is @@ -2734,6 +2748,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, } } #endif +#ifdef INET /* Avoid topologically incorrect IPv4 address */ if (stcb && fam == AF_INET && sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) { @@ -2741,6 +2756,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, continue; } } +#endif if (stcb) { if (sctp_is_address_in_scope(ifa, stcb->asoc.ipv4_addr_legal, @@ -3077,15 +3093,18 @@ sctp_source_address_selection(struct sctp_inpcb *inp, struct sctp_nets *net, int non_asoc_addr_ok, uint32_t vrf_id) { + struct sctp_ifa *answer; + uint8_t dest_is_priv, dest_is_loop; + sa_family_t fam; + +#ifdef INET struct sockaddr_in *to = (struct sockaddr_in *)&ro->ro_dst; +#endif #ifdef INET6 struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ro->ro_dst; #endif - struct sctp_ifa *answer; - uint8_t dest_is_priv, dest_is_loop; - sa_family_t fam; /*- * Rules: - Find the route if needed, cache if I can. - Look at @@ -3158,10 +3177,11 @@ sctp_source_address_selection(struct sctp_inpcb *inp, if (ro->ro_rt == NULL) { return (NULL); } - fam = to->sin_family; + fam = ro->ro_dst.sa_family; dest_is_priv = dest_is_loop = 0; /* Setup our scopes for the destination */ switch (fam) { +#ifdef INET case AF_INET: /* Scope based on outbound address */ if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { @@ -3174,6 +3194,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp, dest_is_priv = 1; } break; +#endif #ifdef INET6 case AF_INET6: /* Scope based on outbound address */ @@ -3197,7 +3218,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp, #endif } SCTPDBG(SCTP_DEBUG_OUTPUT2, "Select source addr for:"); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)to); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&ro->ro_dst); SCTP_IPI_ADDR_RLOCK(); if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { /* @@ -3398,6 +3419,70 @@ sctp_get_ect(struct sctp_tcb *stcb, } } +static void +sctp_handle_no_route(struct sctp_tcb *stcb, + struct sctp_nets *net, + int so_locked) +{ + SCTPDBG(SCTP_DEBUG_OUTPUT1, "dropped packet - no valid source addr\n"); + + if (net) { + SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination was "); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT1, &net->ro._l_addr.sa); + if (net->dest_state & SCTP_ADDR_CONFIRMED) { + if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb) { + SCTPDBG(SCTP_DEBUG_OUTPUT1, "no route takes interface %p down\n", net); + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, + stcb, + SCTP_FAILED_THRESHOLD, + (void *)net, + so_locked); + net->dest_state &= ~SCTP_ADDR_REACHABLE; + net->dest_state |= SCTP_ADDR_NOT_REACHABLE; + /* + * JRS 5/14/07 - If a destination is + * unreachable, the PF bit is turned off. + * This allows an unambiguous use of the PF + * bit for destinations that are reachable + * but potentially failed. If the + * destination is set to the unreachable + * state, also set the destination to the PF + * state. + */ + /* + * Add debug message here if destination is + * not in PF state. + */ + /* Stop any running T3 timers here? */ + if ((stcb->asoc.sctp_cmt_on_off > 0) && + (stcb->asoc.sctp_cmt_pf > 0)) { + net->dest_state &= ~SCTP_ADDR_PF; + SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n", + net); + } + } + } + if (stcb) { + if (net == stcb->asoc.primary_destination) { + /* need a new primary */ + struct sctp_nets *alt; + + alt = sctp_find_alternate_net(stcb, net, 0); + if (alt != net) { + if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, alt) == 0) { + net->dest_state |= SCTP_ADDR_WAS_PRIMARY; + if (net->ro._s_addr) { + sctp_free_ifa(net->ro._s_addr); + net->ro._s_addr = NULL; + } + net->src_addr_selected = 0; + } + } + } + } + } +} + static int sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* may be NULL */ @@ -3464,658 +3549,617 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if ((auth != NULL) && (stcb != NULL)) { sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid); } - if (to->sa_family == AF_INET) { - struct ip *ip = NULL; - sctp_route_t iproute; - uint8_t tos_value; - int len; + switch (to->sa_family) { +#ifdef INET + case AF_INET: + { + struct ip *ip = NULL; + sctp_route_t iproute; + uint8_t tos_value; + int len; - len = sizeof(struct ip) + sizeof(struct sctphdr); - if (port) { - len += sizeof(struct udphdr); - } - newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); - if (newm == NULL) { - sctp_m_freem(m); - SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); - return (ENOMEM); - } - SCTP_ALIGN_TO_END(newm, len); - SCTP_BUF_LEN(newm) = len; - SCTP_BUF_NEXT(newm) = m; - m = newm; - if (net != NULL) { + len = sizeof(struct ip) + sizeof(struct sctphdr); + if (port) { + len += sizeof(struct udphdr); + } + newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); + if (newm == NULL) { + sctp_m_freem(m); + SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + SCTP_ALIGN_TO_END(newm, len); + SCTP_BUF_LEN(newm) = len; + SCTP_BUF_NEXT(newm) = m; + m = newm; + if (net != NULL) { #ifdef INVARIANTS - if (net->flowidset == 0) { - panic("Flow ID not set"); - } + if (net->flowidset == 0) { + panic("Flow ID not set"); + } #endif - m->m_pkthdr.flowid = net->flowid; - m->m_flags |= M_FLOWID; - } else { - if ((init != NULL) && (init->m_flags & M_FLOWID)) { - m->m_pkthdr.flowid = init->m_pkthdr.flowid; + m->m_pkthdr.flowid = net->flowid; m->m_flags |= M_FLOWID; - } - } - packet_length = sctp_calculate_len(m); - ip = mtod(m, struct ip *); - ip->ip_v = IPVERSION; - ip->ip_hl = (sizeof(struct ip) >> 2); - if (net) { - tos_value = net->tos_flowlabel & 0x000000ff; - } else { - tos_value = inp->ip_inp.inp.inp_ip_tos; - } - if ((nofragment_flag) && (port == 0)) { - ip->ip_off = IP_DF; - } else - ip->ip_off = 0; - - /* FreeBSD has a function for ip_id's */ - ip->ip_id = ip_newid(); - - ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl; - ip->ip_len = packet_length; - ip->ip_tos = tos_value & 0xfc; - if (ecn_ok) { - ip->ip_tos |= sctp_get_ect(stcb, chk); - } - if (port) { - ip->ip_p = IPPROTO_UDP; - } else { - ip->ip_p = IPPROTO_SCTP; - } - ip->ip_sum = 0; - if (net == NULL) { - ro = &iproute; - memset(&iproute, 0, sizeof(iproute)); - memcpy(&ro->ro_dst, to, to->sa_len); - } else { - ro = (sctp_route_t *) & net->ro; - } - /* Now the address selection part */ - ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; - - /* call the routine to select the src address */ - if (net && out_of_asoc_ok == 0) { - if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) { - sctp_free_ifa(net->ro._s_addr); - net->ro._s_addr = NULL; - net->src_addr_selected = 0; - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } - } - if (net->src_addr_selected == 0) { - /* Cache the source address */ - net->ro._s_addr = sctp_source_address_selection(inp, stcb, - ro, net, 0, - vrf_id); - net->src_addr_selected = 1; - } - if (net->ro._s_addr == NULL) { - /* No route to host */ - net->src_addr_selected = 0; - goto no_route; - } - ip->ip_src = net->ro._s_addr->address.sin.sin_addr; - } else { - if (over_addr == NULL) { - struct sctp_ifa *_lsrc; - - _lsrc = sctp_source_address_selection(inp, stcb, ro, - net, - out_of_asoc_ok, - vrf_id); - if (_lsrc == NULL) { - goto no_route; - } - ip->ip_src = _lsrc->address.sin.sin_addr; - sctp_free_ifa(_lsrc); } else { - ip->ip_src = over_addr->sin.sin_addr; - SCTP_RTALLOC(ro, vrf_id); + if ((init != NULL) && (init->m_flags & M_FLOWID)) { + m->m_pkthdr.flowid = init->m_pkthdr.flowid; + m->m_flags |= M_FLOWID; + } } - } - if (port) { - udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip)); - udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); - udp->uh_dport = port; - udp->uh_ulen = htons(packet_length - sizeof(struct ip)); - udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP)); - sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); - } else { - sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip)); - } - - sctphdr->src_port = src_port; - sctphdr->dest_port = dest_port; - sctphdr->v_tag = v_tag; - sctphdr->checksum = 0; - - /* - * If source address selection fails and we find no route - * then the ip_output should fail as well with a - * NO_ROUTE_TO_HOST type error. We probably should catch - * that somewhere and abort the association right away - * (assuming this is an INIT being sent). - */ - if ((ro->ro_rt == NULL)) { - /* - * src addr selection failed to find a route (or - * valid source addr), so we can't get there from - * here (yet)! - */ - no_route: - SCTPDBG(SCTP_DEBUG_OUTPUT1, - "%s: dropped packet - no valid source addr\n", - __FUNCTION__); + packet_length = sctp_calculate_len(m); + ip = mtod(m, struct ip *); + ip->ip_v = IPVERSION; + ip->ip_hl = (sizeof(struct ip) >> 2); if (net) { - SCTPDBG(SCTP_DEBUG_OUTPUT1, - "Destination was "); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT1, - &net->ro._l_addr.sa); - if (net->dest_state & SCTP_ADDR_CONFIRMED) { - if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb) { - SCTPDBG(SCTP_DEBUG_OUTPUT1, "no route takes interface %p down\n", net); - sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, - stcb, - SCTP_FAILED_THRESHOLD, - (void *)net, - so_locked); - net->dest_state &= ~SCTP_ADDR_REACHABLE; - net->dest_state |= SCTP_ADDR_NOT_REACHABLE; - /* - * JRS 5/14/07 - If a - * destination is - * unreachable, the PF bit - * is turned off. This - * allows an unambiguous use - * of the PF bit for - * destinations that are - * reachable but potentially - * failed. If the - * destination is set to the - * unreachable state, also - * set the destination to - * the PF state. - */ - /* - * Add debug message here if - * destination is not in PF - * state. - */ - /* - * Stop any running T3 - * timers here? - */ - if ((stcb->asoc.sctp_cmt_on_off > 0) && - (stcb->asoc.sctp_cmt_pf > 0)) { - net->dest_state &= ~SCTP_ADDR_PF; - SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n", - net); - } - } - } - if (stcb) { - if (net == stcb->asoc.primary_destination) { - /* need a new primary */ - struct sctp_nets *alt; - - alt = sctp_find_alternate_net(stcb, net, 0); - if (alt != net) { - if (sctp_set_primary_addr(stcb, - (struct sockaddr *)NULL, - alt) == 0) { - net->dest_state |= SCTP_ADDR_WAS_PRIMARY; - if (net->ro._s_addr) { - sctp_free_ifa(net->ro._s_addr); - net->ro._s_addr = NULL; - } - net->src_addr_selected = 0; - } - } - } - } - } - SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); - sctp_m_freem(m); - return (EHOSTUNREACH); - } - if (ro != &iproute) { - memcpy(&iproute, ro, sizeof(*ro)); - } - SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv4 output routine from low level src addr:%x\n", - (uint32_t) (ntohl(ip->ip_src.s_addr))); - SCTPDBG(SCTP_DEBUG_OUTPUT3, "Destination is %x\n", - (uint32_t) (ntohl(ip->ip_dst.s_addr))); - SCTPDBG(SCTP_DEBUG_OUTPUT3, "RTP route is %p through\n", - ro->ro_rt); - - if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) { - /* failed to prepend data, give up */ - SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); - sctp_m_freem(m); - return (ENOMEM); - } -#ifdef SCTP_PACKET_LOGGING - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) - sctp_packet_log(m, packet_length); -#endif - SCTP_ATTACH_CHAIN(o_pak, m, packet_length); - if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else - if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && - (stcb) && - (stcb->asoc.loopback_scope))) { - sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr)); - SCTP_STAT_INCR(sctps_sendswcrc); + tos_value = net->tos_flowlabel & 0x000000ff; } else { - SCTP_STAT_INCR(sctps_sendnocrc); + tos_value = inp->ip_inp.inp.inp_ip_tos; } -#endif - SCTP_ENABLE_UDP_CSUM(o_pak); - } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else - m->m_pkthdr.csum_flags = CSUM_SCTP; - m->m_pkthdr.csum_data = 0; - SCTP_STAT_INCR(sctps_sendhwcrc); -#endif - } - /* send it out. table id is taken from stcb */ -#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { - so = SCTP_INP_SO(inp); - SCTP_SOCKET_UNLOCK(so, 0); - } -#endif - SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id); -#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { - atomic_add_int(&stcb->asoc.refcnt, 1); - SCTP_TCB_UNLOCK(stcb); - SCTP_SOCKET_LOCK(so, 0); - SCTP_TCB_LOCK(stcb); - atomic_subtract_int(&stcb->asoc.refcnt, 1); - } -#endif - SCTP_STAT_INCR(sctps_sendpackets); - SCTP_STAT_INCR_COUNTER64(sctps_outpackets); - if (ret) - SCTP_STAT_INCR(sctps_senderrors); + if ((nofragment_flag) && (port == 0)) { + ip->ip_off = IP_DF; + } else + ip->ip_off = 0; - SCTPDBG(SCTP_DEBUG_OUTPUT3, "IP output returns %d\n", ret); - if (net == NULL) { - /* free tempy routes */ - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; + /* FreeBSD has a function for ip_id's */ + ip->ip_id = ip_newid(); + + ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl; + ip->ip_len = packet_length; + ip->ip_tos = tos_value & 0xfc; + if (ecn_ok) { + ip->ip_tos |= sctp_get_ect(stcb, chk); } - } else { - /* PMTU check versus smallest asoc MTU goes here */ - if ((ro->ro_rt != NULL) && - (net->ro._s_addr)) { - uint32_t mtu; + if (port) { + ip->ip_p = IPPROTO_UDP; + } else { + ip->ip_p = IPPROTO_SCTP; + } + ip->ip_sum = 0; + if (net == NULL) { + ro = &iproute; + memset(&iproute, 0, sizeof(iproute)); + memcpy(&ro->ro_dst, to, to->sa_len); + } else { + ro = (sctp_route_t *) & net->ro; + } + /* Now the address selection part */ + ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; - mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); - if (net->port) { - mtu -= sizeof(struct udphdr); - } - if (mtu && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); - net->mtu = mtu; - } - } else if (ro->ro_rt == NULL) { - /* route was freed */ - if (net->ro._s_addr && - net->src_addr_selected) { + /* call the routine to select the src address */ + if (net && out_of_asoc_ok == 0) { + if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) { sctp_free_ifa(net->ro._s_addr); net->ro._s_addr = NULL; + net->src_addr_selected = 0; + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; + } + } + if (net->src_addr_selected == 0) { + /* Cache the source address */ + net->ro._s_addr = sctp_source_address_selection(inp, stcb, + ro, net, 0, + vrf_id); + net->src_addr_selected = 1; + } + if (net->ro._s_addr == NULL) { + /* No route to host */ + net->src_addr_selected = 0; + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + ip->ip_src = net->ro._s_addr->address.sin.sin_addr; + } else { + if (over_addr == NULL) { + struct sctp_ifa *_lsrc; + + _lsrc = sctp_source_address_selection(inp, stcb, ro, + net, + out_of_asoc_ok, + vrf_id); + if (_lsrc == NULL) { + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + ip->ip_src = _lsrc->address.sin.sin_addr; + sctp_free_ifa(_lsrc); + } else { + ip->ip_src = over_addr->sin.sin_addr; + SCTP_RTALLOC(ro, vrf_id); } - net->src_addr_selected = 0; } - } - return (ret); - } -#ifdef INET6 - else if (to->sa_family == AF_INET6) { - uint32_t flowlabel; - struct ip6_hdr *ip6h; - struct route_in6 ip6route; - struct ifnet *ifp; - u_char flowTop; - uint16_t flowBottom; - u_char tosBottom, tosTop; - struct sockaddr_in6 *sin6, tmp, *lsa6, lsa6_tmp; - int prev_scope = 0; - struct sockaddr_in6 lsa6_storage; - int error; - u_short prev_port = 0; - int len; + if (port) { + udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip)); + udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); + udp->uh_dport = port; + udp->uh_ulen = htons(packet_length - sizeof(struct ip)); + udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP)); + sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); + } else { + sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip)); + } - if (net != NULL) { - flowlabel = net->tos_flowlabel; - } else { - flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo; - } + sctphdr->src_port = src_port; + sctphdr->dest_port = dest_port; + sctphdr->v_tag = v_tag; + sctphdr->checksum = 0; - len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); - if (port) { - len += sizeof(struct udphdr); - } - newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); - if (newm == NULL) { - sctp_m_freem(m); - SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); - return (ENOMEM); - } - SCTP_ALIGN_TO_END(newm, len); - SCTP_BUF_LEN(newm) = len; - SCTP_BUF_NEXT(newm) = m; - m = newm; - if (net != NULL) { -#ifdef INVARIANTS - if (net->flowidset == 0) { - panic("Flow ID not set"); + /* + * If source address selection fails and we find no + * route then the ip_output should fail as well with + * a NO_ROUTE_TO_HOST type error. We probably should + * catch that somewhere and abort the association + * right away (assuming this is an INIT being sent). + */ + if (ro->ro_rt == NULL) { + /* + * src addr selection failed to find a route + * (or valid source addr), so we can't get + * there from here (yet)! + */ + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + if (ro != &iproute) { + memcpy(&iproute, ro, sizeof(*ro)); + } + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv4 output routine from low level src addr:%x\n", + (uint32_t) (ntohl(ip->ip_src.s_addr))); + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Destination is %x\n", + (uint32_t) (ntohl(ip->ip_dst.s_addr))); + SCTPDBG(SCTP_DEBUG_OUTPUT3, "RTP route is %p through\n", + ro->ro_rt); + + if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) { + /* failed to prepend data, give up */ + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + sctp_m_freem(m); + return (ENOMEM); + } +#ifdef SCTP_PACKET_LOGGING + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) + sctp_packet_log(m, packet_length); +#endif + SCTP_ATTACH_CHAIN(o_pak, m, packet_length); + if (port) { +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr)); + SCTP_STAT_INCR(sctps_sendswcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } +#endif + SCTP_ENABLE_UDP_CSUM(o_pak); + } else { +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else + m->m_pkthdr.csum_flags = CSUM_SCTP; + m->m_pkthdr.csum_data = 0; + SCTP_STAT_INCR(sctps_sendhwcrc); +#endif + } + /* send it out. table id is taken from stcb */ +#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { + so = SCTP_INP_SO(inp); + SCTP_SOCKET_UNLOCK(so, 0); } #endif - m->m_pkthdr.flowid = net->flowid; - m->m_flags |= M_FLOWID; - } else { - if ((init != NULL) && (init->m_flags & M_FLOWID)) { - m->m_pkthdr.flowid = init->m_pkthdr.flowid; - m->m_flags |= M_FLOWID; + SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id); +#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_SOCKET_LOCK(so, 0); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); } - } - packet_length = sctp_calculate_len(m); +#endif + SCTP_STAT_INCR(sctps_sendpackets); + SCTP_STAT_INCR_COUNTER64(sctps_outpackets); + if (ret) + SCTP_STAT_INCR(sctps_senderrors); - ip6h = mtod(m, struct ip6_hdr *); - /* - * We assume here that inp_flow is in host byte order within - * the TCB! - */ - flowBottom = flowlabel & 0x0000ffff; - flowTop = ((flowlabel & 0x000f0000) >> 16); - tosTop = (((flowlabel & 0xf0) >> 4) | IPV6_VERSION); - /* protect *sin6 from overwrite */ - sin6 = (struct sockaddr_in6 *)to; - tmp = *sin6; - sin6 = &tmp; - - /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { - SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - return (EINVAL); - } - if (net == NULL) { - memset(&ip6route, 0, sizeof(ip6route)); - ro = (sctp_route_t *) & ip6route; - memcpy(&ro->ro_dst, sin6, sin6->sin6_len); - } else { - ro = (sctp_route_t *) & net->ro; - } - tosBottom = (((struct in6pcb *)inp)->in6p_flowinfo & 0x0c); - if (ecn_ok) { - tosBottom |= sctp_get_ect(stcb, chk); - } - tosBottom <<= 4; - ip6h->ip6_flow = htonl(((tosTop << 24) | ((tosBottom | flowTop) << 16) | flowBottom)); - if (port) { - ip6h->ip6_nxt = IPPROTO_UDP; - } else { - ip6h->ip6_nxt = IPPROTO_SCTP; - } - ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr)); - ip6h->ip6_dst = sin6->sin6_addr; - - /* - * Add SRC address selection here: we can only reuse to a - * limited degree the kame src-addr-sel, since we can try - * their selection but it may not be bound. - */ - bzero(&lsa6_tmp, sizeof(lsa6_tmp)); - lsa6_tmp.sin6_family = AF_INET6; - lsa6_tmp.sin6_len = sizeof(lsa6_tmp); - lsa6 = &lsa6_tmp; - if (net && out_of_asoc_ok == 0) { - if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) { - sctp_free_ifa(net->ro._s_addr); - net->ro._s_addr = NULL; - net->src_addr_selected = 0; + SCTPDBG(SCTP_DEBUG_OUTPUT3, "IP output returns %d\n", ret); + if (net == NULL) { + /* free tempy routes */ if (ro->ro_rt) { RTFREE(ro->ro_rt); ro->ro_rt = NULL; } - } - if (net->src_addr_selected == 0) { - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { - SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - return (EINVAL); + } else { + /* + * PMTU check versus smallest asoc MTU goes + * here + */ + if ((ro->ro_rt != NULL) && + (net->ro._s_addr)) { + uint32_t mtu; + + mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); + if (net->port) { + mtu -= sizeof(struct udphdr); + } + if (mtu && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + net->mtu = mtu; + } + } else if (ro->ro_rt == NULL) { + /* route was freed */ + if (net->ro._s_addr && + net->src_addr_selected) { + sctp_free_ifa(net->ro._s_addr); + net->ro._s_addr = NULL; + } + net->src_addr_selected = 0; } - /* Cache the source address */ - net->ro._s_addr = sctp_source_address_selection(inp, - stcb, - ro, - net, - 0, - vrf_id); - (void)sa6_recoverscope(sin6); - net->src_addr_selected = 1; } - if (net->ro._s_addr == NULL) { - SCTPDBG(SCTP_DEBUG_OUTPUT3, "V6:No route to host\n"); - net->src_addr_selected = 0; - goto no_route; + return (ret); + } +#endif +#ifdef INET6 + case AF_INET6: + { + uint32_t flowlabel; + struct ip6_hdr *ip6h; + struct route_in6 ip6route; + struct ifnet *ifp; + u_char flowTop; + uint16_t flowBottom; + u_char tosBottom, tosTop; + struct sockaddr_in6 *sin6, tmp, *lsa6, lsa6_tmp; + int prev_scope = 0; + struct sockaddr_in6 lsa6_storage; + int error; + u_short prev_port = 0; + int len; + + if (net != NULL) { + flowlabel = net->tos_flowlabel; + } else { + flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo; } - lsa6->sin6_addr = net->ro._s_addr->address.sin6.sin6_addr; - } else { - sin6 = (struct sockaddr_in6 *)&ro->ro_dst; + + len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); + if (port) { + len += sizeof(struct udphdr); + } + newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); + if (newm == NULL) { + sctp_m_freem(m); + SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + SCTP_ALIGN_TO_END(newm, len); + SCTP_BUF_LEN(newm) = len; + SCTP_BUF_NEXT(newm) = m; + m = newm; + if (net != NULL) { +#ifdef INVARIANTS + if (net->flowidset == 0) { + panic("Flow ID not set"); + } +#endif + m->m_pkthdr.flowid = net->flowid; + m->m_flags |= M_FLOWID; + } else { + if ((init != NULL) && (init->m_flags & M_FLOWID)) { + m->m_pkthdr.flowid = init->m_pkthdr.flowid; + m->m_flags |= M_FLOWID; + } + } + packet_length = sctp_calculate_len(m); + + ip6h = mtod(m, struct ip6_hdr *); + /* + * We assume here that inp_flow is in host byte + * order within the TCB! + */ + flowBottom = flowlabel & 0x0000ffff; + flowTop = ((flowlabel & 0x000f0000) >> 16); + tosTop = (((flowlabel & 0xf0) >> 4) | IPV6_VERSION); + /* protect *sin6 from overwrite */ + sin6 = (struct sockaddr_in6 *)to; + tmp = *sin6; + sin6 = &tmp; + /* KAME hack: embed scopeid */ if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } - if (over_addr == NULL) { - struct sctp_ifa *_lsrc; - - _lsrc = sctp_source_address_selection(inp, stcb, ro, - net, - out_of_asoc_ok, - vrf_id); - if (_lsrc == NULL) { - goto no_route; - } - lsa6->sin6_addr = _lsrc->address.sin6.sin6_addr; - sctp_free_ifa(_lsrc); + if (net == NULL) { + memset(&ip6route, 0, sizeof(ip6route)); + ro = (sctp_route_t *) & ip6route; + memcpy(&ro->ro_dst, sin6, sin6->sin6_len); } else { - lsa6->sin6_addr = over_addr->sin6.sin6_addr; - SCTP_RTALLOC(ro, vrf_id); + ro = (sctp_route_t *) & net->ro; } - (void)sa6_recoverscope(sin6); - } - lsa6->sin6_port = inp->sctp_lport; + tosBottom = (((struct in6pcb *)inp)->in6p_flowinfo & 0x0c); + if (ecn_ok) { + tosBottom |= sctp_get_ect(stcb, chk); + } + tosBottom <<= 4; + ip6h->ip6_flow = htonl(((tosTop << 24) | ((tosBottom | flowTop) << 16) | flowBottom)); + if (port) { + ip6h->ip6_nxt = IPPROTO_UDP; + } else { + ip6h->ip6_nxt = IPPROTO_SCTP; + } + ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr)); + ip6h->ip6_dst = sin6->sin6_addr; - if (ro->ro_rt == NULL) { /* - * src addr selection failed to find a route (or - * valid source addr), so we can't get there from - * here! + * Add SRC address selection here: we can only reuse + * to a limited degree the kame src-addr-sel, since + * we can try their selection but it may not be + * bound. */ - goto no_route; - } - /* - * XXX: sa6 may not have a valid sin6_scope_id in the - * non-SCOPEDROUTING case. - */ - bzero(&lsa6_storage, sizeof(lsa6_storage)); - lsa6_storage.sin6_family = AF_INET6; - lsa6_storage.sin6_len = sizeof(lsa6_storage); - lsa6_storage.sin6_addr = lsa6->sin6_addr; - if ((error = sa6_recoverscope(&lsa6_storage)) != 0) { - SCTPDBG(SCTP_DEBUG_OUTPUT3, "recover scope fails error %d\n", error); - sctp_m_freem(m); - return (error); - } - /* XXX */ - lsa6_storage.sin6_addr = lsa6->sin6_addr; - lsa6_storage.sin6_port = inp->sctp_lport; - lsa6 = &lsa6_storage; - ip6h->ip6_src = lsa6->sin6_addr; - - if (port) { - udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); - udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); - udp->uh_dport = port; - udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr)); - udp->uh_sum = 0; - sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); - } else { - sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); - } - - sctphdr->src_port = src_port; - sctphdr->dest_port = dest_port; - sctphdr->v_tag = v_tag; - sctphdr->checksum = 0; - - /* - * We set the hop limit now since there is a good chance - * that our ro pointer is now filled - */ - ip6h->ip6_hlim = SCTP_GET_HLIM(inp, ro); - ifp = SCTP_GET_IFN_VOID_FROM_ROUTE(ro); - -#ifdef SCTP_DEBUG - /* Copy to be sure something bad is not happening */ - sin6->sin6_addr = ip6h->ip6_dst; - lsa6->sin6_addr = ip6h->ip6_src; -#endif - - SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv6 output routine from low level\n"); - SCTPDBG(SCTP_DEBUG_OUTPUT3, "src: "); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)lsa6); - SCTPDBG(SCTP_DEBUG_OUTPUT3, "dst: "); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)sin6); - if (net) { - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - /* preserve the port and scope for link local send */ - prev_scope = sin6->sin6_scope_id; - prev_port = sin6->sin6_port; - } - if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) { - /* failed to prepend data, give up */ - sctp_m_freem(m); - SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); - return (ENOMEM); - } -#ifdef SCTP_PACKET_LOGGING - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) - sctp_packet_log(m, packet_length); -#endif - SCTP_ATTACH_CHAIN(o_pak, m, packet_length); - if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else - if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && - (stcb) && - (stcb->asoc.loopback_scope))) { - sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); - SCTP_STAT_INCR(sctps_sendswcrc); - } else { - SCTP_STAT_INCR(sctps_sendnocrc); - } -#endif - if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) { - udp->uh_sum = 0xffff; - } - } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else - m->m_pkthdr.csum_flags = CSUM_SCTP; - m->m_pkthdr.csum_data = 0; - SCTP_STAT_INCR(sctps_sendhwcrc); -#endif - } - /* send it out. table id is taken from stcb */ -#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { - so = SCTP_INP_SO(inp); - SCTP_SOCKET_UNLOCK(so, 0); - } -#endif - SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id); -#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { - atomic_add_int(&stcb->asoc.refcnt, 1); - SCTP_TCB_UNLOCK(stcb); - SCTP_SOCKET_LOCK(so, 0); - SCTP_TCB_LOCK(stcb); - atomic_subtract_int(&stcb->asoc.refcnt, 1); - } -#endif - if (net) { - /* for link local this must be done */ - sin6->sin6_scope_id = prev_scope; - sin6->sin6_port = prev_port; - } - SCTPDBG(SCTP_DEBUG_OUTPUT3, "return from send is %d\n", ret); - SCTP_STAT_INCR(sctps_sendpackets); - SCTP_STAT_INCR_COUNTER64(sctps_outpackets); - if (ret) { - SCTP_STAT_INCR(sctps_senderrors); - } - if (net == NULL) { - /* Now if we had a temp route free it */ - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - } - } else { - /* PMTU check versus smallest asoc MTU goes here */ - if (ro->ro_rt == NULL) { - /* Route was freed */ - if (net->ro._s_addr && - net->src_addr_selected) { + bzero(&lsa6_tmp, sizeof(lsa6_tmp)); + lsa6_tmp.sin6_family = AF_INET6; + lsa6_tmp.sin6_len = sizeof(lsa6_tmp); + lsa6 = &lsa6_tmp; + if (net && out_of_asoc_ok == 0) { + if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) { sctp_free_ifa(net->ro._s_addr); net->ro._s_addr = NULL; - } - net->src_addr_selected = 0; - } - if ((ro->ro_rt != NULL) && - (net->ro._s_addr)) { - uint32_t mtu; - - mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); - if (mtu && - (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); - net->mtu = mtu; - if (net->port) { - net->mtu -= sizeof(struct udphdr); + net->src_addr_selected = 0; + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; } } - } else if (ifp) { - if (ND_IFINFO(ifp)->linkmtu && - (stcb->asoc.smallest_mtu > ND_IFINFO(ifp)->linkmtu)) { - sctp_mtu_size_reset(inp, - &stcb->asoc, - ND_IFINFO(ifp)->linkmtu); + if (net->src_addr_selected == 0) { + sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; + /* KAME hack: embed scopeid */ + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + return (EINVAL); + } + /* Cache the source address */ + net->ro._s_addr = sctp_source_address_selection(inp, + stcb, + ro, + net, + 0, + vrf_id); + (void)sa6_recoverscope(sin6); + net->src_addr_selected = 1; + } + if (net->ro._s_addr == NULL) { + SCTPDBG(SCTP_DEBUG_OUTPUT3, "V6:No route to host\n"); + net->src_addr_selected = 0; + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + lsa6->sin6_addr = net->ro._s_addr->address.sin6.sin6_addr; + } else { + sin6 = (struct sockaddr_in6 *)&ro->ro_dst; + /* KAME hack: embed scopeid */ + if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + return (EINVAL); + } + if (over_addr == NULL) { + struct sctp_ifa *_lsrc; + + _lsrc = sctp_source_address_selection(inp, stcb, ro, + net, + out_of_asoc_ok, + vrf_id); + if (_lsrc == NULL) { + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + lsa6->sin6_addr = _lsrc->address.sin6.sin6_addr; + sctp_free_ifa(_lsrc); + } else { + lsa6->sin6_addr = over_addr->sin6.sin6_addr; + SCTP_RTALLOC(ro, vrf_id); + } + (void)sa6_recoverscope(sin6); + } + lsa6->sin6_port = inp->sctp_lport; + + if (ro->ro_rt == NULL) { + /* + * src addr selection failed to find a route + * (or valid source addr), so we can't get + * there from here! + */ + sctp_handle_no_route(stcb, net, so_locked); + SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH); + sctp_m_freem(m); + return (EHOSTUNREACH); + } + /* + * XXX: sa6 may not have a valid sin6_scope_id in + * the non-SCOPEDROUTING case. + */ + bzero(&lsa6_storage, sizeof(lsa6_storage)); + lsa6_storage.sin6_family = AF_INET6; + lsa6_storage.sin6_len = sizeof(lsa6_storage); + lsa6_storage.sin6_addr = lsa6->sin6_addr; + if ((error = sa6_recoverscope(&lsa6_storage)) != 0) { + SCTPDBG(SCTP_DEBUG_OUTPUT3, "recover scope fails error %d\n", error); + sctp_m_freem(m); + return (error); + } + /* XXX */ + lsa6_storage.sin6_addr = lsa6->sin6_addr; + lsa6_storage.sin6_port = inp->sctp_lport; + lsa6 = &lsa6_storage; + ip6h->ip6_src = lsa6->sin6_addr; + + if (port) { + udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); + udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); + udp->uh_dport = port; + udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr)); + udp->uh_sum = 0; + sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); + } else { + sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); + } + + sctphdr->src_port = src_port; + sctphdr->dest_port = dest_port; + sctphdr->v_tag = v_tag; + sctphdr->checksum = 0; + + /* + * We set the hop limit now since there is a good + * chance that our ro pointer is now filled + */ + ip6h->ip6_hlim = SCTP_GET_HLIM(inp, ro); + ifp = SCTP_GET_IFN_VOID_FROM_ROUTE(ro); + +#ifdef SCTP_DEBUG + /* Copy to be sure something bad is not happening */ + sin6->sin6_addr = ip6h->ip6_dst; + lsa6->sin6_addr = ip6h->ip6_src; +#endif + + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv6 output routine from low level\n"); + SCTPDBG(SCTP_DEBUG_OUTPUT3, "src: "); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)lsa6); + SCTPDBG(SCTP_DEBUG_OUTPUT3, "dst: "); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)sin6); + if (net) { + sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; + /* + * preserve the port and scope for link + * local send + */ + prev_scope = sin6->sin6_scope_id; + prev_port = sin6->sin6_port; + } + if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) { + /* failed to prepend data, give up */ + sctp_m_freem(m); + SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } +#ifdef SCTP_PACKET_LOGGING + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) + sctp_packet_log(m, packet_length); +#endif + SCTP_ATTACH_CHAIN(o_pak, m, packet_length); + if (port) { +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); + SCTP_STAT_INCR(sctps_sendswcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } +#endif + if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) { + udp->uh_sum = 0xffff; + } + } else { +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else + m->m_pkthdr.csum_flags = CSUM_SCTP; + m->m_pkthdr.csum_data = 0; + SCTP_STAT_INCR(sctps_sendhwcrc); +#endif + } + /* send it out. table id is taken from stcb */ +#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { + so = SCTP_INP_SO(inp); + SCTP_SOCKET_UNLOCK(so, 0); + } +#endif + SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id); +#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_SOCKET_LOCK(so, 0); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + } +#endif + if (net) { + /* for link local this must be done */ + sin6->sin6_scope_id = prev_scope; + sin6->sin6_port = prev_port; + } + SCTPDBG(SCTP_DEBUG_OUTPUT3, "return from send is %d\n", ret); + SCTP_STAT_INCR(sctps_sendpackets); + SCTP_STAT_INCR_COUNTER64(sctps_outpackets); + if (ret) { + SCTP_STAT_INCR(sctps_senderrors); + } + if (net == NULL) { + /* Now if we had a temp route free it */ + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + } + } else { + /* + * PMTU check versus smallest asoc MTU goes + * here + */ + if (ro->ro_rt == NULL) { + /* Route was freed */ + if (net->ro._s_addr && + net->src_addr_selected) { + sctp_free_ifa(net->ro._s_addr); + net->ro._s_addr = NULL; + } + net->src_addr_selected = 0; + } + if ((ro->ro_rt != NULL) && + (net->ro._s_addr)) { + uint32_t mtu; + + mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); + if (mtu && + (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + net->mtu = mtu; + if (net->port) { + net->mtu -= sizeof(struct udphdr); + } + } + } else if (ifp) { + if (ND_IFINFO(ifp)->linkmtu && + (stcb->asoc.smallest_mtu > ND_IFINFO(ifp)->linkmtu)) { + sctp_mtu_size_reset(inp, + &stcb->asoc, + ND_IFINFO(ifp)->linkmtu); + } } } + return (ret); } - return (ret); - } #endif - else { + default: SCTPDBG(SCTP_DEBUG_OUTPUT1, "Unknown protocol (TSNH) type %d\n", ((struct sockaddr *)to)->sa_family); sctp_m_freem(m); @@ -4213,14 +4257,22 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams); init->init.initial_tsn = htonl(stcb->asoc.init_seq_number); /* now the address restriction */ + /* XXX Should we take the address family of the socket into account? */ sup_addr = (struct sctp_supported_addr_param *)((caddr_t)init + sizeof(*init)); sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); #ifdef INET6 - /* we support 2 types: IPv6/IPv4 */ +#ifdef INET + /* we support 2 types: IPv4/IPv6 */ sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint16_t)); sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS); sup_addr->addr_type[1] = htons(SCTP_IPV6_ADDRESS); +#else + /* we support 1 type: IPv6 */ + sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint8_t)); + sup_addr->addr_type[0] = htons(SCTP_IPV6_ADDRESS); + sup_addr->addr_type[1] = htons(0); /* this is the padding */ +#endif #else /* we support 1 type: IPv4 */ sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint8_t)); @@ -4750,34 +4802,31 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, * must return (1) to drop the packet if we see a un-understood * parameter that tells us to drop the chunk. */ - struct sockaddr_in sin4, *sa4; - -#ifdef INET6 - struct sockaddr_in6 sin6, *sa6; - -#endif struct sockaddr *sa_touse; struct sockaddr *sa; struct sctp_paramhdr *phdr, params; + uint16_t ptype, plen; + uint8_t fnd; + struct sctp_nets *net; struct ip *iph; +#ifdef INET + struct sockaddr_in sin4, *sa4; + +#endif #ifdef INET6 + struct sockaddr_in6 sin6, *sa6; struct ip6_hdr *ip6h; #endif - struct mbuf *mat; - uint16_t ptype, plen; - int err_at; - uint8_t fnd; - struct sctp_nets *net; +#ifdef INET memset(&sin4, 0, sizeof(sin4)); -#ifdef INET6 - memset(&sin6, 0, sizeof(sin6)); -#endif sin4.sin_family = AF_INET; sin4.sin_len = sizeof(sin4); +#endif #ifdef INET6 + memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); #endif @@ -4785,11 +4834,13 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, /* First what about the src address of the pkt ? */ iph = mtod(in_initpkt, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: /* source addr is IPv4 */ sin4.sin_addr = iph->ip_src; sa_touse = (struct sockaddr *)&sin4; break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: /* source addr is IPv6 */ @@ -4806,19 +4857,19 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, TAILQ_FOREACH(net, &asoc->nets, sctp_next) { sa = (struct sockaddr *)&net->ro._l_addr; if (sa->sa_family == sa_touse->sa_family) { +#ifdef INET if (sa->sa_family == AF_INET) { sa4 = (struct sockaddr_in *)sa; - if (sa4->sin_addr.s_addr == - sin4.sin_addr.s_addr) { + if (sa4->sin_addr.s_addr == sin4.sin_addr.s_addr) { fnd = 1; break; } } +#endif #ifdef INET6 if (sa->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)sa; - if (SCTP6_ARE_ADDR_EQUAL(sa6, - &sin6)) { + if (SCTP6_ARE_ADDR_EQUAL(sa6, &sin6)) { fnd = 1; break; } @@ -4831,41 +4882,48 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, return (1); } /* Ok so far lets munge through the rest of the packet */ - mat = in_initpkt; - err_at = 0; - sa_touse = NULL; offset += sizeof(struct sctp_init_chunk); - phdr = sctp_get_next_param(mat, offset, ¶ms, sizeof(params)); + phdr = sctp_get_next_param(in_initpkt, offset, ¶ms, sizeof(params)); while (phdr) { + sa_touse = NULL; ptype = ntohs(phdr->param_type); plen = ntohs(phdr->param_length); - if (ptype == SCTP_IPV4_ADDRESS) { - struct sctp_ipv4addr_param *p4, p4_buf; + switch (ptype) { +#ifdef INET + case SCTP_IPV4_ADDRESS: + { + struct sctp_ipv4addr_param *p4, p4_buf; - phdr = sctp_get_next_param(mat, offset, - (struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf)); - if (plen != sizeof(struct sctp_ipv4addr_param) || - phdr == NULL) { - return (1); + phdr = sctp_get_next_param(in_initpkt, offset, + (struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf)); + if (plen != sizeof(struct sctp_ipv4addr_param) || + phdr == NULL) { + return (1); + } + p4 = (struct sctp_ipv4addr_param *)phdr; + sin4.sin_addr.s_addr = p4->addr; + sa_touse = (struct sockaddr *)&sin4; } - p4 = (struct sctp_ipv4addr_param *)phdr; - sin4.sin_addr.s_addr = p4->addr; - sa_touse = (struct sockaddr *)&sin4; - } else if (ptype == SCTP_IPV6_ADDRESS) { - struct sctp_ipv6addr_param *p6, p6_buf; - - phdr = sctp_get_next_param(mat, offset, - (struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf)); - if (plen != sizeof(struct sctp_ipv6addr_param) || - phdr == NULL) { - return (1); - } - p6 = (struct sctp_ipv6addr_param *)phdr; -#ifdef INET6 - memcpy((caddr_t)&sin6.sin6_addr, p6->addr, - sizeof(p6->addr)); #endif - sa_touse = (struct sockaddr *)&sin4; +#ifdef INET6 + case SCTP_IPV6_ADDRESS: + { + struct sctp_ipv6addr_param *p6, p6_buf; + + phdr = sctp_get_next_param(in_initpkt, offset, + (struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf)); + if (plen != sizeof(struct sctp_ipv6addr_param) || + phdr == NULL) { + return (1); + } + p6 = (struct sctp_ipv6addr_param *)phdr; + memcpy((caddr_t)&sin6.sin6_addr, p6->addr, + sizeof(p6->addr)); + sa_touse = (struct sockaddr *)&sin6; + } +#endif + default: + sa_touse = NULL; } if (sa_touse) { /* ok, sa_touse points to one to check */ @@ -4875,6 +4933,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, if (sa->sa_family != sa_touse->sa_family) { continue; } +#ifdef INET if (sa->sa_family == AF_INET) { sa4 = (struct sockaddr_in *)sa; if (sa4->sin_addr.s_addr == @@ -4883,6 +4942,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, break; } } +#endif #ifdef INET6 if (sa->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)sa; @@ -4900,7 +4960,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, } } offset += SCTP_SIZE32(plen); - phdr = sctp_get_next_param(mat, offset, ¶ms, sizeof(params)); + phdr = sctp_get_next_param(in_initpkt, offset, ¶ms, sizeof(params)); } return (0); } @@ -4924,8 +4984,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_prsctp_supported_param *prsctp; struct sctp_supported_chunk_types_param *pr_supported; union sctp_sockstore store, store1, *over_addr; + +#ifdef INET struct sockaddr_in *sin, *to_sin; +#endif #ifdef INET6 struct sockaddr_in6 *sin6, *to_sin6; @@ -5037,8 +5100,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* now for scope setup */ memset((caddr_t)&store, 0, sizeof(store)); memset((caddr_t)&store1, 0, sizeof(store1)); +#ifdef INET sin = &store.sin; to_sin = &store1.sin; +#endif #ifdef INET6 sin6 = &store.sin6; to_sin6 = &store1.sin6; @@ -5046,12 +5111,14 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, iph = mtod(init_pkt, struct ip *); /* establish the to_addr's */ switch (iph->ip_v) { +#ifdef INET case IPVERSION: to_sin->sin_port = sh->dest_port; to_sin->sin_family = AF_INET; to_sin->sin_len = sizeof(struct sockaddr_in); to_sin->sin_addr = iph->ip_dst; break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: ip6 = mtod(init_pkt, struct ip6_hdr *); @@ -5070,6 +5137,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (net == NULL) { to = (struct sockaddr *)&store; switch (iph->ip_v) { +#ifdef INET case IPVERSION: { sin->sin_family = AF_INET; @@ -5106,6 +5174,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -5211,6 +5280,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* use the net pointer */ to = (struct sockaddr *)&net->ro._l_addr; switch (to->sa_family) { +#ifdef INET case AF_INET: sin = (struct sockaddr_in *)to; stc.address[0] = sin->sin_addr.s_addr; @@ -5238,6 +5308,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stc.laddress[3] = 0; stc.laddr_type = SCTP_IPV4_ADDRESS; break; +#endif #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)to; @@ -7455,9 +7526,11 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, } } switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { +#ifdef INET case AF_INET: mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); break; +#endif #ifdef INET6 case AF_INET6: mtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); @@ -10320,21 +10393,27 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, /* formulate and SEND a SHUTDOWN-COMPLETE */ struct mbuf *o_pak; struct mbuf *mout; - struct ip *iph, *iph_out; + struct ip *iph; struct udphdr *udp = NULL; + int offset_out, len, mlen; + struct sctp_shutdown_complete_msg *comp_cp; +#ifdef INET + struct ip *iph_out; + +#endif #ifdef INET6 struct ip6_hdr *ip6, *ip6_out; #endif - int offset_out, len, mlen; - struct sctp_shutdown_complete_msg *comp_cp; iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: len = (sizeof(struct ip) + sizeof(struct sctp_shutdown_complete_msg)); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg)); @@ -10357,13 +10436,16 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, mout->m_pkthdr.flowid = m->m_pkthdr.flowid; mout->m_flags |= M_FLOWID; } +#ifdef INET iph_out = NULL; +#endif #ifdef INET6 ip6_out = NULL; #endif offset_out = 0; switch (iph->ip_v) { +#ifdef INET case IPVERSION: iph_out = mtod(mout, struct ip *); @@ -10388,6 +10470,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, comp_cp = (struct sctp_shutdown_complete_msg *)( (caddr_t)iph_out + offset_out); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: ip6 = (struct ip6_hdr *)iph; @@ -10423,8 +10506,10 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); udp->uh_dport = port; udp->uh_ulen = htons(sizeof(struct sctp_shutdown_complete_msg) + sizeof(struct udphdr)); +#ifdef INET if (iph_out) udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP)); +#endif offset_out += sizeof(struct udphdr); comp_cp = (struct sctp_shutdown_complete_msg *)((caddr_t)comp_cp + sizeof(struct udphdr)); } @@ -10442,6 +10527,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE; comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk)); +#ifdef INET if (iph_out != NULL) { sctp_route_t ro; int ret; @@ -10479,6 +10565,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, if (ro.ro_rt) RTFREE(ro.ro_rt); } +#endif #ifdef INET6 if (ip6_out != NULL) { struct route_in6 ro; @@ -10610,8 +10697,6 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) struct sctp_nets *net; struct sctp_heartbeat_chunk *hb; struct timeval now; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; SCTP_TCB_LOCK_ASSERT(stcb); if (user_req == 0) { @@ -10637,12 +10722,17 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) } (void)SCTP_GETTIME_TIMEVAL(&now); } - sin = (struct sockaddr_in *)&net->ro._l_addr; - if (sin->sin_family != AF_INET) { - if (sin->sin_family != AF_INET6) { - /* huh */ - return (0); - } + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + break; +#endif +#ifdef INET6 + case AF_INET6: + break; +#endif + default: + return (0); } sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -10680,8 +10770,8 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) hb->heartbeat.hb_info.time_value_2 = now.tv_usec; /* Did our user request this one, put it in */ hb->heartbeat.hb_info.user_req = user_req; - hb->heartbeat.hb_info.addr_family = sin->sin_family; - hb->heartbeat.hb_info.addr_len = sin->sin_len; + hb->heartbeat.hb_info.addr_family = net->ro._l_addr.sa.sa_family; + hb->heartbeat.hb_info.addr_len = net->ro._l_addr.sa.sa_len; if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { /* * we only take from the entropy pool if the address is not @@ -10693,15 +10783,24 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) net->heartbeat_random1 = hb->heartbeat.hb_info.random_value1 = 0; net->heartbeat_random2 = hb->heartbeat.hb_info.random_value2 = 0; } - if (sin->sin_family == AF_INET) { - memcpy(hb->heartbeat.hb_info.address, &sin->sin_addr, sizeof(sin->sin_addr)); - } else if (sin->sin_family == AF_INET6) { - /* We leave the scope the way it is in our lookup table. */ - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - memcpy(hb->heartbeat.hb_info.address, &sin6->sin6_addr, sizeof(sin6->sin6_addr)); - } else { - /* huh compiler bug */ + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + memcpy(hb->heartbeat.hb_info.address, + &net->ro._l_addr.sin.sin_addr, + sizeof(net->ro._l_addr.sin.sin_addr)); + break; +#endif +#ifdef INET6 + case AF_INET6: + memcpy(hb->heartbeat.hb_info.address, + &net->ro._l_addr.sin6.sin6_addr, + sizeof(net->ro._l_addr.sin6.sin6_addr)); + break; +#endif + default: return (0); + break; } /* @@ -10860,10 +10959,12 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net, return; } switch (iph->ip_v) { +#ifdef INET case IPVERSION: /* IPv4 */ len = chk->send_size = iph->ip_len; break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: /* IPv6 */ @@ -11377,14 +11478,18 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, struct mbuf *o_pak; struct mbuf *mout; struct sctp_abort_msg *abm; - struct ip *iph, *iph_out; + struct ip *iph; struct udphdr *udp; + int iphlen_out, len; +#ifdef INET + struct ip *iph_out; + +#endif #ifdef INET6 struct ip6_hdr *ip6, *ip6_out; #endif - int iphlen_out, len; /* don't respond to ABORT with ABORT */ if (sctp_is_there_an_abort_here(m, iphlen, &vtag)) { @@ -11394,9 +11499,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, } iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: len = (sizeof(struct ip) + sizeof(struct sctp_abort_msg)); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg)); @@ -11425,11 +11532,14 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, mout->m_pkthdr.flowid = m->m_pkthdr.flowid; mout->m_flags |= M_FLOWID; } +#ifdef INET iph_out = NULL; +#endif #ifdef INET6 ip6_out = NULL; #endif switch (iph->ip_v) { +#ifdef INET case IPVERSION: iph_out = mtod(mout, struct ip *); @@ -11453,6 +11563,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, iphlen_out = sizeof(*iph_out); abm = (struct sctp_abort_msg *)((caddr_t)iph_out + iphlen_out); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: ip6 = (struct ip6_hdr *)iph; @@ -11530,6 +11641,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, sctp_m_freem(mout); return; } +#ifdef INET if (iph_out != NULL) { sctp_route_t ro; int ret; @@ -11573,6 +11685,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, if (ro.ro_rt) RTFREE(ro.ro_rt); } +#endif #ifdef INET6 if (ip6_out != NULL) { struct route_in6 ro; @@ -11630,22 +11743,28 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, struct mbuf *o_pak; struct sctphdr *sh, *sh_out; struct sctp_chunkhdr *ch; - struct ip *iph, *iph_out; + struct ip *iph; struct udphdr *udp = NULL; struct mbuf *mout; + int iphlen_out, len; +#ifdef INET + struct ip *iph_out; + +#endif #ifdef INET6 struct ip6_hdr *ip6, *ip6_out; #endif - int iphlen_out, len; iph = mtod(m, struct ip *); sh = (struct sctphdr *)((caddr_t)iph + iphlen); switch (iph->ip_v) { +#ifdef INET case IPVERSION: len = (sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: len = (sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)); @@ -11674,11 +11793,14 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, mout->m_pkthdr.flowid = m->m_pkthdr.flowid; mout->m_flags |= M_FLOWID; } +#ifdef INET iph_out = NULL; +#endif #ifdef INET6 ip6_out = NULL; #endif switch (iph->ip_v) { +#ifdef INET case IPVERSION: iph_out = mtod(mout, struct ip *); @@ -11702,6 +11824,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, iphlen_out = sizeof(struct ip); sh_out = (struct sctphdr *)((caddr_t)iph_out + iphlen_out); break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: ip6 = (struct ip6_hdr *)iph; @@ -11776,6 +11899,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, sctp_m_freem(mout); return; } +#ifdef INET if (iph_out != NULL) { sctp_route_t ro; int ret; @@ -11817,6 +11941,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, if (ro.ro_rt) RTFREE(ro.ro_rt); } +#endif #ifdef INET6 if (ip6_out != NULL) { struct route_in6 ro; @@ -13428,6 +13553,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) int sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro) { +#ifdef INET struct sockaddr_in *sin, *mask; struct ifaddr *ifa; struct in_addr srcnetaddr, gwnetaddr; @@ -13452,5 +13578,6 @@ sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro) if (srcnetaddr.s_addr == gwnetaddr.s_addr) { return (1); } +#endif return (0); } diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 797816147195..b7c8dc6113ab 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -426,10 +426,20 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap) /* update address counts */ sctp_ifnp->ifa_count++; ifa_af = sctp_ifap->address.sa.sa_family; - if (ifa_af == AF_INET) + switch (ifa_af) { +#ifdef INET + case AF_INET: sctp_ifnp->num_v4++; - else + break; +#endif +#ifdef INET6 + case AF_INET6: sctp_ifnp->num_v6++; + break; +#endif + default: + break; + } if (sctp_ifnp->ifa_count == 1) { /* register the new interface */ SCTP_REGISTER_INTERFACE(sctp_ifnp->ifn_index, ifa_af); @@ -452,10 +462,20 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap) if (sctp_ifap->ifn_p) { /* update address counts */ sctp_ifap->ifn_p->ifa_count--; - if (sctp_ifap->address.sa.sa_family == AF_INET6) - sctp_ifap->ifn_p->num_v6--; - else if (sctp_ifap->address.sa.sa_family == AF_INET) + switch (sctp_ifap->address.sa.sa_family) { +#ifdef INET + case AF_INET: sctp_ifap->ifn_p->num_v4--; + break; +#endif +#ifdef INET6 + case AF_INET6: + sctp_ifap->ifn_p->num_v6--; + break; +#endif + default: + break; + } ifn_index = sctp_ifap->ifn_p->ifn_index; if (LIST_EMPTY(&sctp_ifap->ifn_p->ifalist)) { @@ -613,6 +633,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, sctp_ifap->flags = ifa_flags; /* Set scope */ switch (sctp_ifap->address.sa.sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin; @@ -630,6 +651,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, new_ifn_af = AF_INET; break; } +#endif #ifdef INET6 case AF_INET6: { @@ -846,14 +868,29 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, if ((to == NULL) || (from == NULL)) { return (NULL); } - if (to->sa_family == AF_INET && from->sa_family == AF_INET) { - lport = ((struct sockaddr_in *)to)->sin_port; - rport = ((struct sockaddr_in *)from)->sin_port; - } else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { - lport = ((struct sockaddr_in6 *)to)->sin6_port; - rport = ((struct sockaddr_in6 *)from)->sin6_port; - } else { - return NULL; + switch (to->sa_family) { +#ifdef INET + case AF_INET: + if (from->sa_family == AF_INET) { + lport = ((struct sockaddr_in *)to)->sin_port; + rport = ((struct sockaddr_in *)from)->sin_port; + } else { + return (NULL); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (from->sa_family == AF_INET6) { + lport = ((struct sockaddr_in6 *)to)->sin6_port; + rport = ((struct sockaddr_in6 *)from)->sin6_port; + } else { + return (NULL); + } + break; +#endif + default: + return (NULL); } ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; /* @@ -894,17 +931,21 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, if (laddr->ifa->address.sa.sa_family == to->sa_family) { /* see if it matches */ - struct sockaddr_in *intf_addr, *sin; - intf_addr = &laddr->ifa->address.sin; - sin = (struct sockaddr_in *)to; +#ifdef INET if (from->sa_family == AF_INET) { + struct sockaddr_in *intf_addr, + *sin; + + intf_addr = &laddr->ifa->address.sin; + sin = (struct sockaddr_in *)to; if (sin->sin_addr.s_addr == intf_addr->sin_addr.s_addr) { match = 1; break; } } +#endif #ifdef INET6 if (from->sa_family == AF_INET6) { struct sockaddr_in6 *intf_addr6; @@ -959,6 +1000,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, continue; } switch (from->sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin, *rsin; @@ -981,6 +1023,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, } break; } +#endif #ifdef INET6 case AF_INET6: { @@ -1256,6 +1299,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, continue; } switch (remote->sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin, @@ -1284,6 +1328,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, } break; } +#endif #ifdef INET6 case AF_INET6: { @@ -1357,6 +1402,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, continue; } switch (remote->sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin, @@ -1385,6 +1431,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, } break; } +#endif #ifdef INET6 case AF_INET6: { @@ -1505,15 +1552,14 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, uint16_t lport, uint32_t vrf_id) { struct sctp_inpcb *inp; - struct sockaddr_in *sin; - -#ifdef INET6 - struct sockaddr_in6 *sin6; - -#endif struct sctp_laddr *laddr; +#ifdef INET + struct sockaddr_in *sin; + +#endif #ifdef INET6 + struct sockaddr_in6 *sin6; struct sockaddr_in6 *intf_addr6; #endif @@ -1523,14 +1569,18 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, /* * Endpoint probe expects that the INP_INFO is locked. */ +#ifdef INET sin = NULL; +#endif #ifdef INET6 sin6 = NULL; #endif switch (nam->sa_family) { +#ifdef INET case AF_INET: sin = (struct sockaddr_in *)nam; break; +#endif #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)nam; @@ -1553,6 +1603,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) && (inp->sctp_lport == lport)) { /* got it */ +#ifdef INET if ((nam->sa_family == AF_INET) && (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && SCTP_IPV6_V6ONLY(inp)) { @@ -1560,12 +1611,15 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, SCTP_INP_RUNLOCK(inp); continue; } +#endif +#ifdef INET6 /* A V6 address and the endpoint is NOT bound V6 */ if (nam->sa_family == AF_INET6 && (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { SCTP_INP_RUNLOCK(inp); continue; } +#endif /* does a VRF id match? */ fnd = 0; if (inp->def_vrf_id == vrf_id) @@ -1578,18 +1632,26 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, } SCTP_INP_RUNLOCK(inp); } - if ((nam->sa_family == AF_INET) && - (sin->sin_addr.s_addr == INADDR_ANY)) { - /* Can't hunt for one that has no address specified */ - return (NULL); - } -#ifdef INET6 - if ((nam->sa_family == AF_INET6) && - (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) { - /* Can't hunt for one that has no address specified */ - return (NULL); - } + switch (nam->sa_family) { +#ifdef INET + case AF_INET: + if (sin->sin_addr.s_addr == INADDR_ANY) { + /* Can't hunt for one that has no address specified */ + return (NULL); + } + break; #endif +#ifdef INET6 + case AF_INET6: + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* Can't hunt for one that has no address specified */ + return (NULL); + } + break; +#endif + default: + break; + } /* * ok, not bound to all so see if we can find a EP bound to this * address. @@ -1635,17 +1697,16 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, } if (laddr->ifa->address.sa.sa_family == nam->sa_family) { /* possible, see if it matches */ - struct sockaddr_in *intf_addr; - - intf_addr = &laddr->ifa->address.sin; switch (nam->sa_family) { +#ifdef INET case AF_INET: if (sin->sin_addr.s_addr == - intf_addr->sin_addr.s_addr) { + laddr->ifa->address.sin.sin_addr.s_addr) { SCTP_INP_RUNLOCK(inp); return (inp); } break; +#endif #ifdef INET6 case AF_INET6: intf_addr6 = &laddr->ifa->address.sin6; @@ -1774,19 +1835,32 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, */ struct sctp_inpcb *inp; struct sctppcbhead *head; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; int lport; unsigned int i; - if (nam->sa_family == AF_INET) { +#ifdef INET + struct sockaddr_in *sin; + +#endif +#ifdef INET6 + struct sockaddr_in6 *sin6; + +#endif + + switch (nam->sa_family) { +#ifdef INET + case AF_INET: sin = (struct sockaddr_in *)nam; lport = ((struct sockaddr_in *)nam)->sin_port; - } else if (nam->sa_family == AF_INET6) { + break; +#endif +#ifdef INET6 + case AF_INET6: sin6 = (struct sockaddr_in6 *)nam; lport = ((struct sockaddr_in6 *)nam)->sin6_port; - } else { - /* unsupported family */ + break; +#endif + default: return (NULL); } /* @@ -1893,20 +1967,31 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, struct sockaddr *dest) { - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; struct sctp_paramhdr *phdr, parm_buf; struct sctp_tcb *retval; uint32_t ptype, plen; +#ifdef INET + struct sockaddr_in sin4; + +#endif +#ifdef INET6 + struct sockaddr_in6 sin6; + +#endif + +#ifdef INET memset(&sin4, 0, sizeof(sin4)); - memset(&sin6, 0, sizeof(sin6)); sin4.sin_len = sizeof(sin4); sin4.sin_family = AF_INET; sin4.sin_port = sh->src_port; +#endif +#ifdef INET6 + memset(&sin6, 0, sizeof(sin6)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_port = sh->src_port; +#endif retval = NULL; offset += sizeof(struct sctp_init_chunk); @@ -1919,6 +2004,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset, if (plen == 0) { break; } +#ifdef INET if (ptype == SCTP_IPV4_ADDRESS && plen == sizeof(struct sctp_ipv4addr_param)) { /* Get the rest of the address */ @@ -1937,7 +2023,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset, if (retval != NULL) { return (retval); } - } else if (ptype == SCTP_IPV6_ADDRESS && + } +#endif +#ifdef INET6 + if (ptype == SCTP_IPV6_ADDRESS && plen == sizeof(struct sctp_ipv6addr_param)) { /* Get the rest of the address */ struct sctp_ipv6addr_param ip6_parm, *p6; @@ -1956,6 +2045,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset, return (retval); } } +#endif offset += SCTP_SIZE32(plen); phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); @@ -2082,6 +2172,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: { /* its IPv4 */ @@ -2095,6 +2186,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, from4->sin_port = sh->src_port; break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -2123,6 +2215,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, switch (iph->ip_v) { +#ifdef INET case IPVERSION: { /* its IPv4 */ @@ -2136,6 +2229,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, to4->sin_port = sh->dest_port; break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -2224,24 +2318,22 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) { struct sctp_tcb *stcb; - struct sockaddr_in *sin; - -#ifdef INET6 - struct sockaddr_in6 *sin6; - -#endif struct sockaddr_storage local_store, remote_store; struct sockaddr *to; struct ip *iph; - -#ifdef INET6 - struct ip6_hdr *ip6; - -#endif struct sctp_paramhdr parm_buf, *phdr; int ptype; int zero_address = 0; +#ifdef INET + struct sockaddr_in *sin; + +#endif +#ifdef INET6 + struct ip6_hdr *ip6; + struct sockaddr_in6 *sin6; + +#endif memset(&local_store, 0, sizeof(local_store)); memset(&remote_store, 0, sizeof(remote_store)); @@ -2249,6 +2341,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, /* First get the destination address setup too. */ iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: /* its IPv4 */ sin = (struct sockaddr_in *)&local_store; @@ -2257,6 +2350,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, sin->sin_port = sh->dest_port; sin->sin_addr.s_addr = iph->ip_dst.s_addr; break; +#endif #ifdef INET6 case IPV6_VERSION >> 4: /* its IPv6 */ @@ -2309,6 +2403,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, break; } #endif +#ifdef INET case SCTP_IPV4_ADDRESS: { /* ipv4 address param */ @@ -2334,6 +2429,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, zero_address = 1; break; } +#endif default: /* invalid address param type */ return NULL; @@ -2733,6 +2829,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, #endif if (addr != NULL) { switch (addr->sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin; @@ -2762,6 +2859,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, } break; } +#endif #ifdef INET6 case AF_INET6: { @@ -3033,18 +3131,27 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct sockaddr_storage store_sa; memset(&store_sa, 0, sizeof(store_sa)); - if (addr->sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&store_sa; - memcpy(sin, addr, sizeof(struct sockaddr_in)); - sin->sin_port = 0; - } else if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6; + sin = (struct sockaddr_in *)&store_sa; + memcpy(sin, addr, sizeof(struct sockaddr_in)); + sin->sin_port = 0; + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&store_sa; - memcpy(sin6, addr, sizeof(struct sockaddr_in6)); - sin6->sin6_port = 0; + sin6 = (struct sockaddr_in6 *)&store_sa; + memcpy(sin6, addr, sizeof(struct sockaddr_in6)); + sin6->sin6_port = 0; + break; + } + default: + break; } /* * first find the interface with the bound address need to @@ -3069,6 +3176,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL); return (EADDRNOTAVAIL); } +#ifdef INET6 if (addr->sa_family == AF_INET6) { /* GAK, more FIXME IFA lock? */ if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { @@ -3079,6 +3187,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, return (EINVAL); } } +#endif /* we're not bound all */ inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL; /* allow bindx() to send ASCONF's for binding changes */ @@ -3612,10 +3721,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) (void)sctp_m_free(ip_pcb->inp_options); ip_pcb->inp_options = 0; } +#ifdef INET if (ip_pcb->inp_moptions) { inp_freemoptions(ip_pcb->inp_moptions); ip_pcb->inp_moptions = 0; } +#endif + #ifdef INET6 if (ip_pcb->inp_vflag & INP_IPV6) { struct in6pcb *in6p; @@ -3740,84 +3852,96 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, return (0); } addr_inscope = 1; - if (newaddr->sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (newaddr->sa_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)newaddr; - if (sin->sin_addr.s_addr == 0) { - /* Invalid address */ - return (-1); - } - /* zero out the bzero area */ - memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); + sin = (struct sockaddr_in *)newaddr; + if (sin->sin_addr.s_addr == 0) { + /* Invalid address */ + return (-1); + } + /* zero out the bzero area */ + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); - /* assure len is set */ - sin->sin_len = sizeof(struct sockaddr_in); - if (set_scope) { + /* assure len is set */ + sin->sin_len = sizeof(struct sockaddr_in); + if (set_scope) { #ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stcb->ipv4_local_scope = 1; + stcb->ipv4_local_scope = 1; #else - if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { - stcb->asoc.ipv4_local_scope = 1; - } + if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { + stcb->asoc.ipv4_local_scope = 1; + } #endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ - } else { - /* Validate the address is in scope */ - if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && - (stcb->asoc.ipv4_local_scope == 0)) { - addr_inscope = 0; - } - } -#ifdef INET6 - } else if (newaddr->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)newaddr; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* Invalid address */ - return (-1); - } - /* assure len is set */ - sin6->sin6_len = sizeof(struct sockaddr_in6); - if (set_scope) { - if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { - stcb->asoc.loopback_scope = 1; - stcb->asoc.local_scope = 0; - stcb->asoc.ipv4_local_scope = 1; - stcb->asoc.site_scope = 1; - } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - /* - * If the new destination is a LINK_LOCAL we - * must have common site scope. Don't set - * the local scope since we may not share - * all links, only loopback can do this. - * Links on the local network would also be - * on our private network for v4 too. - */ - stcb->asoc.ipv4_local_scope = 1; - stcb->asoc.site_scope = 1; - } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { - /* - * If the new destination is SITE_LOCAL then - * we must have site scope in common. - */ - stcb->asoc.site_scope = 1; - } - } else { - /* Validate the address is in scope */ - if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && - (stcb->asoc.loopback_scope == 0)) { - addr_inscope = 0; - } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && - (stcb->asoc.local_scope == 0)) { - addr_inscope = 0; - } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && - (stcb->asoc.site_scope == 0)) { - addr_inscope = 0; + } else { + /* Validate the address is in scope */ + if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && + (stcb->asoc.ipv4_local_scope == 0)) { + addr_inscope = 0; + } } + break; } #endif - } else { +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)newaddr; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* Invalid address */ + return (-1); + } + /* assure len is set */ + sin6->sin6_len = sizeof(struct sockaddr_in6); + if (set_scope) { + if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { + stcb->asoc.loopback_scope = 1; + stcb->asoc.local_scope = 0; + stcb->asoc.ipv4_local_scope = 1; + stcb->asoc.site_scope = 1; + } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + /* + * If the new destination is a + * LINK_LOCAL we must have common + * site scope. Don't set the local + * scope since we may not share all + * links, only loopback can do this. + * Links on the local network would + * also be on our private network + * for v4 too. + */ + stcb->asoc.ipv4_local_scope = 1; + stcb->asoc.site_scope = 1; + } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { + /* + * If the new destination is + * SITE_LOCAL then we must have site + * scope in common. + */ + stcb->asoc.site_scope = 1; + } + } else { + /* Validate the address is in scope */ + if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && + (stcb->asoc.loopback_scope == 0)) { + addr_inscope = 0; + } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && + (stcb->asoc.local_scope == 0)) { + addr_inscope = 0; + } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && + (stcb->asoc.site_scope == 0)) { + addr_inscope = 0; + } + } + break; + } +#endif + default: /* not supported family type */ return (-1); } @@ -3829,10 +3953,19 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, bzero(net, sizeof(*net)); (void)SCTP_GETTIME_TIMEVAL(&net->start_time); memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len); - if (newaddr->sa_family == AF_INET) { + switch (newaddr->sa_family) { +#ifdef INET + case AF_INET: ((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport; - } else if (newaddr->sa_family == AF_INET6) { + break; +#endif +#ifdef INET6 + case AF_INET6: ((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport; + break; +#endif + default: + break; } net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id); if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) { @@ -4136,38 +4269,63 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, #ifdef SCTP_DEBUG if (firstaddr) { SCTPDBG_ADDR(SCTP_DEBUG_PCB3, firstaddr); - SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", - ntohs(((struct sockaddr_in *)firstaddr)->sin_port)); + switch (firstaddr->sa_family) { +#ifdef INET + case AF_INET: + SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", + ntohs(((struct sockaddr_in *)firstaddr)->sin_port)); + break; +#endif +#ifdef INET6 + case AF_INET6: + SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", + ntohs(((struct sockaddr_in6 *)firstaddr)->sin6_port)); + break; +#endif + default: + break; + } } else { SCTPDBG(SCTP_DEBUG_PCB3, "None\n"); } #endif /* SCTP_DEBUG */ - if (firstaddr->sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (firstaddr->sa_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)firstaddr; - if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) { - /* Invalid address */ - SCTP_INP_RUNLOCK(inp); - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - *error = EINVAL; - return (NULL); + sin = (struct sockaddr_in *)firstaddr; + if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) { + /* Invalid address */ + SCTP_INP_RUNLOCK(inp); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + *error = EINVAL; + return (NULL); + } + rport = sin->sin_port; + break; } - rport = sin->sin_port; - } else if (firstaddr->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6; +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)firstaddr; - if ((sin6->sin6_port == 0) || - (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) { - /* Invalid address */ - SCTP_INP_RUNLOCK(inp); - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - *error = EINVAL; - return (NULL); + sin6 = (struct sockaddr_in6 *)firstaddr; + if ((sin6->sin6_port == 0) || + (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) { + /* Invalid address */ + SCTP_INP_RUNLOCK(inp); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + *error = EINVAL; + return (NULL); + } + rport = sin6->sin6_port; + break; } - rport = sin6->sin6_port; - } else { +#endif + default: /* not supported family type */ SCTP_INP_RUNLOCK(inp); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); @@ -5135,13 +5293,17 @@ sctp_destination_is_reachable(struct sctp_tcb *stcb, struct sockaddr *destaddr) return (1); } /* NOTE: all "scope" checks are done when local addresses are added */ - if (destaddr->sa_family == AF_INET6) { + switch (destaddr->sa_family) { + case AF_INET6: answer = inp->ip_inp.inp.inp_vflag & INP_IPV6; - } else if (destaddr->sa_family == AF_INET) { + break; + case AF_INET: answer = inp->ip_inp.inp.inp_vflag & INP_IPV4; - } else { + break; + default: /* invalid family, so it's unreachable */ answer = 0; + break; } return (answer); } @@ -5166,10 +5328,19 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp) if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { continue; } - if (laddr->ifa->address.sa.sa_family == AF_INET6) { + switch (laddr->ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: inp->ip_inp.inp.inp_vflag |= INP_IPV6; - } else if (laddr->ifa->address.sa.sa_family == AF_INET) { + break; +#endif +#ifdef INET + case AF_INET: inp->ip_inp.inp.inp_vflag |= INP_IPV4; + break; +#endif + default: + break; } } } @@ -5190,12 +5361,14 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac /* You are already bound to all. You have it already */ return; } +#ifdef INET6 if (ifa->address.sa.sa_family == AF_INET6) { if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { /* Can't bind a non-useable addr. */ return; } } +#endif /* first, is it already present? */ LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == ifa) { @@ -5211,10 +5384,19 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac return; inp->laddr_count++; /* update inp_vflag flags */ - if (ifa->address.sa.sa_family == AF_INET6) { + switch (ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: inp->ip_inp.inp.inp_vflag |= INP_IPV6; - } else if (ifa->address.sa.sa_family == AF_INET) { + break; +#endif +#ifdef INET6 + case AF_INET: inp->ip_inp.inp.inp_vflag |= INP_IPV4; + break; +#endif + default: + break; } } return; @@ -5343,12 +5525,14 @@ sctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) list = &stcb->asoc.sctp_restricted_addrs; inp = stcb->sctp_ep; +#ifdef INET6 if (ifa->address.sa.sa_family == AF_INET6) { if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { /* Can't bind a non-existent addr. */ return; } } +#endif /* does the address already exist? */ LIST_FOREACH(laddr, list, sctp_nxt_addr) { if (laddr->ifa == ifa) { @@ -5906,8 +6090,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, struct sockaddr *sa; struct sockaddr_storage dest_store; struct sockaddr *local_sa = (struct sockaddr *)&dest_store; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; uint8_t random_store[SCTP_PARAM_BUFFER_SIZE]; struct sctp_auth_random *p_random = NULL; uint16_t random_len = 0; @@ -5924,20 +6106,32 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, int got_random = 0, got_hmacs = 0, got_chklist = 0; uint8_t ecn_allowed; - /* First get the destination address setup too. */ - memset(&sin, 0, sizeof(sin)); - memset(&sin6, 0, sizeof(sin6)); +#ifdef INET + struct sockaddr_in sin; +#endif +#ifdef INET6 + struct sockaddr_in6 sin6; + +#endif + + /* First get the destination address setup too. */ +#ifdef INET + memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); sin.sin_port = stcb->rport; - +#endif +#ifdef INET6 + memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_port = stcb->rport; +#endif if (altsa == NULL) { iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: { /* its IPv4 */ @@ -5953,6 +6147,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, sa = (struct sockaddr *)&sin; break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { @@ -5998,16 +6193,27 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || inp == NULL) { /* we must add the source address */ /* no scope set here since we have a tcb already. */ - if ((sa->sa_family == AF_INET) && - (stcb->asoc.ipv4_addr_legal)) { - if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) { - return (-1); + switch (sa->sa_family) { +#ifdef INET + case AF_INET: + if (stcb->asoc.ipv4_addr_legal) { + if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) { + return (-1); + } } - } else if ((sa->sa_family == AF_INET6) && - (stcb->asoc.ipv6_addr_legal)) { - if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { - return (-2); + break; +#endif +#ifdef INET6 + case AF_INET6: + if (stcb->asoc.ipv6_addr_legal) { + if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { + return (-2); + } } + break; +#endif + default: + break; } } else { if (net_tmp != NULL && stcb_tmp == stcb) { @@ -6044,6 +6250,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, if (plen == 0) { break; } +#ifdef INET if (ptype == SCTP_IPV4_ADDRESS) { if (stcb->asoc.ipv4_addr_legal) { struct sctp_ipv4addr_param *p4, p4_buf; @@ -6127,7 +6334,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, return (-13); } } - } else if (ptype == SCTP_IPV6_ADDRESS) { + } else +#endif +#ifdef INET6 + if (ptype == SCTP_IPV6_ADDRESS) { if (stcb->asoc.ipv6_addr_legal) { /* ok get the v6 address and check/add */ struct sctp_ipv6addr_param *p6, p6_buf; @@ -6215,7 +6425,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, return (-22); } } - } else if (ptype == SCTP_ECN_CAPABLE) { + } else +#endif + if (ptype == SCTP_ECN_CAPABLE) { ecn_allowed = 1; } else if (ptype == SCTP_ULP_ADAPTATION) { if (stcb->asoc.state != SCTP_STATE_OPEN) { @@ -6232,10 +6444,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } } else if (ptype == SCTP_SET_PRIM_ADDR) { struct sctp_asconf_addr_param lstore, *fee; - struct sctp_asconf_addrv4_param *fii; int lptype; struct sockaddr *lsa = NULL; +#ifdef INET + struct sctp_asconf_addrv4_param *fii; + +#endif + stcb->asoc.peer_supports_asconf = 1; if (plen > sizeof(lstore)) { return (-23); @@ -6248,7 +6464,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } fee = (struct sctp_asconf_addr_param *)phdr; lptype = ntohs(fee->addrp.ph.param_type); - if (lptype == SCTP_IPV4_ADDRESS) { + switch (lptype) { +#ifdef INET + case SCTP_IPV4_ADDRESS: if (plen != sizeof(struct sctp_asconf_addrv4_param)) { SCTP_PRINTF("Sizeof setprim in init/init ack not %d but %d - ignored\n", @@ -6259,7 +6477,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, sin.sin_addr.s_addr = fii->addrp.addr; lsa = (struct sockaddr *)&sin; } - } else if (lptype == SCTP_IPV6_ADDRESS) { + break; +#endif +#ifdef INET6 + case SCTP_IPV6_ADDRESS: if (plen != sizeof(struct sctp_asconf_addr_param)) { SCTP_PRINTF("Sizeof setprim (v6) in init/init ack not %d but %d - ignored\n", @@ -6271,6 +6492,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, sizeof(fee->addrp.addr)); lsa = (struct sockaddr *)&sin6; } + break; +#endif + default: + break; } if (lsa) { (void)sctp_set_primary_addr(stcb, sa, NULL); diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index a8d080aaaafd..bb7b6e265d22 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -155,17 +155,33 @@ number_of_addresses(struct sctp_inpcb *inp) if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { - if ((sctp_ifa->address.sa.sa_family == AF_INET) || - (sctp_ifa->address.sa.sa_family == AF_INET6)) { + switch (sctp_ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: +#endif +#ifdef INET6 + case AF_INET6: +#endif cnt++; + break; + default: + break; } } } } else { LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { - if ((laddr->ifa->address.sa.sa_family == AF_INET) || - (laddr->ifa->address.sa.sa_family == AF_INET6)) { + switch (laddr->ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: +#endif +#ifdef INET6 + case AF_INET6: +#endif cnt++; + break; + default: + break; } } } @@ -233,6 +249,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s continue; } switch (sctp_ifa->address.sa.sa_family) { +#ifdef INET case AF_INET: if (ipv4_addr_legal) { struct sockaddr_in *sin; @@ -246,6 +263,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s continue; } break; +#endif #ifdef INET6 case AF_INET6: if (ipv6_addr_legal) { @@ -535,6 +553,8 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) if ((var) < (min)) { (var) = (min); } \ else if ((var) > (max)) { (var) = (max); } +/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */ +#if !defined(__FreeBSD__) || defined(INET) static int sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS) { @@ -566,6 +586,8 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS) return (error); } +#endif + static int sysctl_sctp_check(SYSCTL_HANDLER_ARGS) @@ -646,7 +668,10 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS) RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX); +/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */ +#if !defined(__FreeBSD__) || defined(INET) RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX); +#endif RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX); @@ -1083,6 +1108,8 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_R "Clear SCTP Logging buffer"); #endif +/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */ +#if !defined(__FreeBSD__) || defined(INET) SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), 0, sysctl_sctp_check, "IU", SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC); @@ -1090,6 +1117,7 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLT SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU", SCTPCTL_UDP_TUNNELING_PORT_DESC); +#endif SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU", diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index b4e9fd5e3278..cecfde741e73 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -150,6 +150,7 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp, } } +#ifdef INET static void sctp_notify_mbuf(struct sctp_inpcb *inp, struct sctp_tcb *stcb, @@ -220,6 +221,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, SCTP_TCB_UNLOCK(stcb); } +#endif void sctp_notify(struct sctp_inpcb *inp, @@ -335,6 +337,7 @@ sctp_notify(struct sctp_inpcb *inp, } } +#ifdef INET void sctp_ctlinput(cmd, sa, vip) int cmd; @@ -404,6 +407,8 @@ sctp_ctlinput(cmd, sa, vip) return; } +#endif + static int sctp_getcred(SYSCTL_HANDLER_ARGS) { @@ -466,6 +471,7 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW, 0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection"); +#ifdef INET static void sctp_abort(struct socket *so) { @@ -599,6 +605,7 @@ sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p) return error; } +#endif void sctp_close(struct socket *so) { @@ -1209,6 +1216,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } } switch (sctp_ifa->address.sa.sa_family) { +#ifdef INET case AF_INET: if (ipv4_addr_legal) { struct sockaddr_in *sin; @@ -1248,6 +1256,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, continue; } break; +#endif #ifdef INET6 case AF_INET6: if (ipv6_addr_legal) { @@ -1373,28 +1382,46 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id) LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { /* Count them if they are the right type */ - if (sctp_ifa->address.sa.sa_family == AF_INET) { + switch (sctp_ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) cnt += sizeof(struct sockaddr_in6); else cnt += sizeof(struct sockaddr_in); - - } else if (sctp_ifa->address.sa.sa_family == AF_INET6) + break; +#endif +#ifdef INET6 + case AF_INET6: cnt += sizeof(struct sockaddr_in6); + break; +#endif + default: + break; + } } } } else { struct sctp_laddr *laddr; LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { - if (laddr->ifa->address.sa.sa_family == AF_INET) { + switch (laddr->ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) cnt += sizeof(struct sockaddr_in6); else cnt += sizeof(struct sockaddr_in); - - } else if (laddr->ifa->address.sa.sa_family == AF_INET6) + break; +#endif +#ifdef INET6 + case AF_INET6: cnt += sizeof(struct sockaddr_in6); + break; +#endif + default: + break; + } } } return (cnt); @@ -1517,10 +1544,20 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, } SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT); /* move to second address */ - if (sa->sa_family == AF_INET) + switch (sa->sa_family) { +#ifdef INET + case AF_INET: sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); - else + break; +#endif +#ifdef INET6 + case AF_INET6: sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); + break; +#endif + default: + break; + } error = 0; added = sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error); @@ -2126,14 +2163,23 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, size = 0; /* Count the sizes */ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { - if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) || - (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) { + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { size += sizeof(struct sockaddr_in6); - } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { - size += sizeof(struct sockaddr_in); } else { - /* huh */ - break; + switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { +#ifdef INET + case AF_INET: + size += sizeof(struct sockaddr_in); + break; +#endif +#ifdef INET6 + case AF_INET6: + size += sizeof(struct sockaddr_in6); + break; +#endif + default: + break; + } } } SCTP_TCB_UNLOCK(stcb); @@ -2165,20 +2211,33 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, sas = (struct sockaddr_storage *)&saddr->addr[0]; TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { - if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) || - (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) { + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { cpsz = sizeof(struct sockaddr_in6); - } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { - cpsz = sizeof(struct sockaddr_in); } else { - /* huh */ + switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { +#ifdef INET + case AF_INET: + cpsz = sizeof(struct sockaddr_in); + break; +#endif +#ifdef INET6 + case AF_INET6: + cpsz = sizeof(struct sockaddr_in6); + break; +#endif + default: + cpsz = 0; + break; + } + } + if (cpsz == 0) { break; } if (left < cpsz) { /* not enough room. */ break; } -#ifdef INET6 +#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)) { /* Must map the address */ @@ -2187,7 +2246,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, } else { #endif memcpy(sas, &net->ro._l_addr, cpsz); -#ifdef INET6 +#if defined(INET) && defined(INET6) } #endif ((struct sockaddr_in *)sas)->sin_port = stcb->rport; @@ -2250,6 +2309,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, struct sockaddr *sa; sa = (struct sockaddr *)&paddrp->spp_address; +#ifdef INET if (sa->sa_family == AF_INET) { struct sockaddr_in *sin; @@ -2260,7 +2320,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } - } else if (sa->sa_family == AF_INET6) { + } else +#endif +#ifdef INET6 + if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)sa; @@ -2270,7 +2333,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } - } else { + } else +#endif + { error = EAFNOSUPPORT; SCTP_TCB_UNLOCK(stcb); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); @@ -3857,7 +3922,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, struct sockaddr *sa; sa = (struct sockaddr *)&paddrp->spp_address; +#ifdef INET if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin; sin = (struct sockaddr_in *)sa; @@ -3867,7 +3934,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = EINVAL; break; } - } else if (sa->sa_family == AF_INET6) { + } else +#endif +#ifdef INET6 + if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)sa; @@ -3877,7 +3947,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = EINVAL; break; } - } else { + } else +#endif + { error = EAFNOSUPPORT; SCTP_TCB_UNLOCK(stcb); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); @@ -4305,6 +4377,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, td = (struct thread *)p; SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize); +#ifdef INET if (addrs->addr->sa_family == AF_INET) { sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in); if (optsize < sz) { @@ -4316,8 +4389,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } + } else +#endif #ifdef INET6 - } else if (addrs->addr->sa_family == AF_INET6) { + if (addrs->addr->sa_family == AF_INET6) { sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6); if (optsize < sz) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); @@ -4329,8 +4404,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } + } else #endif - } else { + { error = EAFNOSUPPORT; break; } @@ -4348,6 +4424,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, td = (struct thread *)p; SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize); +#ifdef INET if (addrs->addr->sa_family == AF_INET) { sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in); if (optsize < sz) { @@ -4359,8 +4436,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } + } else +#endif #ifdef INET6 - } else if (addrs->addr->sa_family == AF_INET6) { + if (addrs->addr->sa_family == AF_INET6) { sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6); if (optsize < sz) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); @@ -4372,8 +4451,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); break; } + } else #endif - } else { + { error = EAFNOSUPPORT; break; } @@ -4410,9 +4490,13 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) #ifdef INET6 if (INP_CHECK_SOCKAF(so, AF_INET6)) error = ip6_ctloutput(so, sopt); - else #endif /* INET6 */ +#if defined(INET) && defined (INET6) + else +#endif +#ifdef INET error = ip_ctloutput(so, sopt); +#endif return (error); } optsize = sopt->sopt_valsize; @@ -4447,7 +4531,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) return (error); } - +#ifdef INET static int sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) { @@ -4467,34 +4551,42 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return EINVAL; } + switch (addr->sa_family) { #ifdef INET6 - if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6p; + case AF_INET6: + { + struct sockaddr_in6 *sin6p; - if (addr->sa_len != sizeof(struct sockaddr_in6)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); - return (EINVAL); + if (addr->sa_len != sizeof(struct sockaddr_in6)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + return (EINVAL); + } + sin6p = (struct sockaddr_in6 *)addr; + if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); + return (error); + } + break; } - sin6p = (struct sockaddr_in6 *)addr; - if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); - return (error); - } - } else #endif - if (addr->sa_family == AF_INET) { - struct sockaddr_in *sinp; +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sinp; - if (addr->sa_len != sizeof(struct sockaddr_in)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); - return (EINVAL); + if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + return (EINVAL); + } + sinp = (struct sockaddr_in *)addr; + if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); + return (error); + } + break; } - sinp = (struct sockaddr_in *)addr; - if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); - return (error); - } - } else { +#endif + default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT); return (EAFNOSUPPORT); } @@ -4601,6 +4693,8 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) return error; } +#endif + int sctp_listen(struct socket *so, int backlog, struct thread *p) { @@ -4634,7 +4728,20 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { memcpy(&store, &laddr->ifa->address, sizeof(store)); - sp->sin.sin_port = inp->sctp_lport; + switch (sp->sa.sa_family) { +#ifdef INET + case AF_INET: + sp->sin.sin_port = inp->sctp_lport; + break; +#endif +#ifdef INET6 + case AF_INET6: + sp->sin6.sin6_port = inp->sctp_lport; + break; +#endif + default: + break; + } tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id); if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && @@ -4653,17 +4760,32 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) } else { /* Setup a local addr bound all */ memset(&store, 0, sizeof(store)); - store.sin.sin_port = inp->sctp_lport; + switch (sp->sa.sa_family) { +#ifdef INET + case AF_INET: + store.sin.sin_port = inp->sctp_lport; + break; +#endif +#ifdef INET6 + case AF_INET6: + sp->sin6.sin6_port = inp->sctp_lport; + break; +#endif + default: + break; + } #ifdef INET6 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { store.sa.sa_family = AF_INET6; store.sa.sa_len = sizeof(struct sockaddr_in6); } #endif +#ifdef INET if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { store.sa.sa_family = AF_INET; store.sa.sa_len = sizeof(struct sockaddr_in); } +#endif tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id); if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && @@ -4780,6 +4902,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr) stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; SCTP_TCB_UNLOCK(stcb); switch (store.sa.sa_family) { +#ifdef INET case AF_INET: { struct sockaddr_in *sin; @@ -4794,6 +4917,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr) *addr = (struct sockaddr *)sin; break; } +#endif #ifdef INET6 case AF_INET6: { @@ -4855,6 +4979,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr) return (0); } +#ifdef INET int sctp_ingetaddr(struct socket *so, struct sockaddr **addr) { @@ -5015,6 +5140,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr) return (0); } +#ifdef INET struct pr_usrreqs sctp_usrreqs = { .pru_abort = sctp_abort, .pru_accept = sctp_accept, @@ -5035,3 +5161,6 @@ struct pr_usrreqs sctp_usrreqs = { .pru_sosend = sctp_sosend, .pru_soreceive = sctp_soreceive }; + +#endif +#endif diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 3ab04c0348ab..c972a166e07a 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -300,8 +300,15 @@ int sctp_disconnect(struct socket *so); void sctp_ctlinput __P((int, struct sockaddr *, void *)); int sctp_ctloutput __P((struct socket *, struct sockopt *)); + +#ifdef INET void sctp_input_with_port __P((struct mbuf *, int, uint16_t)); + +#endif +#ifdef INET void sctp_input __P((struct mbuf *, int)); + +#endif void sctp_pathmtu_adjustment __P((struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, uint16_t)); void sctp_drain __P((void)); void sctp_init __P((void)); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index ffd131ffc6c5..22e5c5b836bb 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -4826,6 +4826,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, continue; if (addr->sa_family != laddr->ifa->address.sa.sa_family) continue; +#ifdef INET if (addr->sa_family == AF_INET) { if (((struct sockaddr_in *)addr)->sin_addr.s_addr == laddr->ifa->address.sin.sin_addr.s_addr) { @@ -4837,6 +4838,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, break; } } +#endif #ifdef INET6 if (addr->sa_family == AF_INET6) { if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, @@ -4924,6 +4926,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) } if (addr->sa_family != sctp_ifap->address.sa.sa_family) continue; +#ifdef INET if (addr->sa_family == AF_INET) { if (((struct sockaddr_in *)addr)->sin_addr.s_addr == sctp_ifap->address.sin.sin_addr.s_addr) { @@ -4934,6 +4937,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) break; } } +#endif #ifdef INET6 if (addr->sa_family == AF_INET6) { if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, @@ -6729,7 +6733,7 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored) struct ip *iph; struct mbuf *sp, *last; struct udphdr *uhdr; - uint16_t port = 0, len; + uint16_t port = 0; int header_size = sizeof(struct udphdr) + sizeof(struct sctphdr); /* @@ -6779,8 +6783,11 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored) /* Now its ready for sctp_input or sctp6_input */ iph = mtod(m, struct ip *); switch (iph->ip_v) { +#ifdef INET case IPVERSION: { + uint16_t len; + /* its IPv4 */ len = SCTP_GET_IPV4_LENGTH(iph); len -= sizeof(struct udphdr); @@ -6788,6 +6795,7 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored) sctp_input_with_port(m, off, port); break; } +#endif #ifdef INET6 case IPV6_VERSION >> 4: { diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index fd71dec0c750..10eed08ee5c3 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -745,13 +745,24 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p) return EINVAL; } if (addr) { - if ((addr->sa_family == AF_INET6) && - (addr->sa_len != sizeof(struct sockaddr_in6))) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); - return EINVAL; - } - if ((addr->sa_family == AF_INET) && - (addr->sa_len != sizeof(struct sockaddr_in))) { + switch (addr->sa_family) { +#ifdef INET + case AF_INET: + if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return EINVAL; + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (addr->sa_len != sizeof(struct sockaddr_in6)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return EINVAL; + } + break; +#endif + default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return EINVAL; } @@ -760,44 +771,59 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p) inp6->inp_vflag &= ~INP_IPV4; inp6->inp_vflag |= INP_IPV6; if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) { - if (addr->sa_family == AF_INET) { + switch (addr->sa_family) { +#ifdef INET + case AF_INET: /* binding v4 addr to v6 socket, so reset flags */ inp6->inp_vflag |= INP_IPV4; inp6->inp_vflag &= ~INP_IPV6; - } else { - struct sockaddr_in6 *sin6_p; + break; +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6_p; - sin6_p = (struct sockaddr_in6 *)addr; + sin6_p = (struct sockaddr_in6 *)addr; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) { - inp6->inp_vflag |= INP_IPV4; - } else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { - struct sockaddr_in sin; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) { + inp6->inp_vflag |= INP_IPV4; + } +#ifdef INET + if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { + struct sockaddr_in sin; - in6_sin6_2_sin(&sin, sin6_p); - inp6->inp_vflag |= INP_IPV4; - inp6->inp_vflag &= ~INP_IPV6; - error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p); - return error; + in6_sin6_2_sin(&sin, sin6_p); + inp6->inp_vflag |= INP_IPV4; + inp6->inp_vflag &= ~INP_IPV6; + error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p); + return error; + } +#endif + break; } +#endif + default: + break; } } else if (addr != NULL) { + struct sockaddr_in6 *sin6_p; + /* IPV6_V6ONLY socket */ +#ifdef INET if (addr->sa_family == AF_INET) { /* can't bind v4 addr to v6 only socket! */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return EINVAL; - } else { - struct sockaddr_in6 *sin6_p; + } +#endif + sin6_p = (struct sockaddr_in6 *)addr; - sin6_p = (struct sockaddr_in6 *)addr; - - if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { - /* can't bind v4-mapped addrs either! */ - /* NOTE: we don't support SIIT */ - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); - return EINVAL; - } + if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { + /* can't bind v4-mapped addrs either! */ + /* NOTE: we don't support SIIT */ + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return EINVAL; } } error = sctp_inpcb_bind(so, addr, NULL, p); @@ -950,7 +976,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p) struct sockaddr_in6 *sin6; struct sockaddr_storage ss; -#endif /* INET */ +#endif inp6 = (struct in6pcb *)so->so_pcb; inp = (struct sctp_inpcb *)so->so_pcb; @@ -963,14 +989,28 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } - if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); - return (EINVAL); - } - if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) { + switch (addr->sa_family) { +#ifdef INET + case AF_INET: + if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return (EINVAL); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (addr->sa_len != sizeof(struct sockaddr_in6)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return (EINVAL); + } + break; +#endif + default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } + vrf_id = inp->def_vrf_id; SCTP_ASOC_CREATE_LOCK(inp); SCTP_INP_RLOCK(inp); @@ -1093,7 +1133,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr) /* * Do the malloc first in case it blocks. */ - SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); + SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6)); if (sin6 == NULL) return ENOMEM; sin6->sin6_family = AF_INET6; @@ -1249,7 +1289,10 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr) static int sctp6_in6getaddr(struct socket *so, struct sockaddr **nam) { +#ifdef INET struct sockaddr *addr; + +#endif struct in6pcb *inp6 = sotoin6pcb(so); int error; @@ -1259,6 +1302,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam) } /* allow v6 addresses precedence */ error = sctp6_getaddr(so, nam); +#ifdef INET if (error) { /* try v4 next if v6 failed */ error = sctp_ingetaddr(so, nam); @@ -1272,9 +1316,9 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam) in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6); memcpy(addr, &sin6, sizeof(struct sockaddr_in6)); - } } +#endif return (error); } @@ -1282,7 +1326,10 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam) static int sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam) { - struct sockaddr *addr = *nam; +#ifdef INET + struct sockaddr *addr; + +#endif struct in6pcb *inp6 = sotoin6pcb(so); int error; @@ -1292,12 +1339,14 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam) } /* allow v6 addresses precedence */ error = sctp6_peeraddr(so, nam); +#ifdef INET if (error) { /* try v4 next if v6 failed */ error = sctp_peeraddr(so, nam); if (error) { return (error); } + addr = *nam; /* if I'm V6ONLY, convert it to v4-mapped */ if (SCTP_IPV6_V6ONLY(inp6)) { struct sockaddr_in6 sin6; @@ -1306,6 +1355,7 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam) memcpy(addr, &sin6, sizeof(struct sockaddr_in6)); } } +#endif return error; }