From 04ee4c21641124d83460020c6fe707fc41ffd21e Mon Sep 17 00:00:00 2001 From: rrs Date: Wed, 16 Apr 2008 17:24:18 +0000 Subject: [PATCH] Allow SCTP to compile without INET6. PR: 116816 Obtained from tuexen@fh-muenster.de: MFC after: 2 weeks --- sys/conf/files | 28 +- sys/netinet/sctp_asconf.c | 242 ++++++----- sys/netinet/sctp_bsd_addr.c | 3 +- sys/netinet/sctp_bsd_addr.h | 3 + sys/netinet/sctp_input.c | 63 +-- sys/netinet/sctp_output.c | 751 +++++++++++++++++++++------------- sys/netinet/sctp_pcb.c | 779 +++++++++++++++++++++--------------- sys/netinet/sctp_pcb.h | 3 + sys/netinet/sctp_sysctl.c | 67 ++-- sys/netinet/sctp_usrreq.c | 221 ++++++---- sys/netinet/sctp_var.h | 2 - sys/netinet/sctputil.c | 320 +++++++++------ sys/netinet/sctputil.h | 4 +- 13 files changed, 1529 insertions(+), 957 deletions(-) diff --git a/sys/conf/files b/sys/conf/files index e38632739314..c1ca81e329a3 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1901,20 +1901,20 @@ netinet/ip_mroute.c optional mrouting inet | mrouting inet6 netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet -netinet/sctp_asconf.c optional inet inet6 sctp -netinet/sctp_auth.c optional inet inet6 sctp -netinet/sctp_bsd_addr.c optional inet inet6 sctp -netinet/sctp_cc_functions.c optional inet inet6 sctp -netinet/sctp_crc32.c optional inet inet6 sctp -netinet/sctp_indata.c optional inet inet6 sctp -netinet/sctp_input.c optional inet inet6 sctp -netinet/sctp_output.c optional inet inet6 sctp -netinet/sctp_pcb.c optional inet inet6 sctp -netinet/sctp_peeloff.c optional inet inet6 sctp -netinet/sctp_sysctl.c optional inet inet6 sctp -netinet/sctp_timer.c optional inet inet6 sctp -netinet/sctp_usrreq.c optional inet inet6 sctp -netinet/sctputil.c optional inet inet6 sctp +netinet/sctp_asconf.c optional inet sctp +netinet/sctp_auth.c optional inet sctp +netinet/sctp_bsd_addr.c optional inet sctp +netinet/sctp_cc_functions.c optional inet sctp +netinet/sctp_crc32.c optional inet sctp +netinet/sctp_indata.c optional inet sctp +netinet/sctp_input.c optional inet sctp +netinet/sctp_output.c optional inet sctp +netinet/sctp_pcb.c optional inet sctp +netinet/sctp_peeloff.c optional inet sctp +netinet/sctp_sysctl.c optional inet sctp +netinet/sctp_timer.c optional inet sctp +netinet/sctp_usrreq.c optional inet sctp +netinet/sctputil.c optional inet sctp netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet netinet/tcp_input.c optional inet diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index f9f3660f52fa..e3bb19f1fd85 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -845,31 +845,43 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, /* pullup already done, IP options already stripped */ iph = mtod(m, struct ip *); sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph)); - if (iph->ip_v == IPVERSION) { - struct sockaddr_in *from4; + switch (iph->ip_v) { + case IPVERSION: + { + struct sockaddr_in *from4; - from4 = (struct sockaddr_in *)&from_store; - bzero(from4, sizeof(*from4)); - from4->sin_family = AF_INET; - from4->sin_len = sizeof(struct sockaddr_in); - from4->sin_addr.s_addr = iph->ip_src.s_addr; - from4->sin_port = sh->src_port; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - struct ip6_hdr *ip6; - struct sockaddr_in6 *from6; + from4 = (struct sockaddr_in *)&from_store; + bzero(from4, sizeof(*from4)); + from4->sin_family = AF_INET; + from4->sin_len = sizeof(struct sockaddr_in); + from4->sin_addr.s_addr = iph->ip_src.s_addr; + from4->sin_port = sh->src_port; + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + struct ip6_hdr *ip6; + struct sockaddr_in6 *from6; - ip6 = mtod(m, struct ip6_hdr *); - from6 = (struct sockaddr_in6 *)&from_store; - bzero(from6, sizeof(*from6)); - from6->sin6_family = AF_INET6; - from6->sin6_len = sizeof(struct sockaddr_in6); - from6->sin6_addr = ip6->ip6_src; - from6->sin6_port = sh->src_port; - /* Get the scopes in properly to the sin6 addr's */ - /* we probably don't need these operations */ - (void)sa6_recoverscope(from6); - sa6_embedscope(from6, ip6_use_defzone); - } else { + ip6 = mtod(m, struct ip6_hdr *); + from6 = (struct sockaddr_in6 *)&from_store; + bzero(from6, sizeof(*from6)); + from6->sin6_family = AF_INET6; + from6->sin6_len = sizeof(struct sockaddr_in6); + from6->sin6_addr = ip6->ip6_src; + from6->sin6_port = sh->src_port; + /* + * Get the scopes in properly to the sin6 + * addr's + */ + /* we probably don't need these operations */ + (void)sa6_recoverscope(from6); + sa6_embedscope(from6, ip6_use_defzone); + break; + } +#endif + default: /* unknown address type */ from = NULL; } @@ -1162,11 +1174,13 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) 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; } +#endif /* * if the newly added address does not relate routing * information, we skip. @@ -1858,6 +1872,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, } } +#ifdef INET6 static uint32_t sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) { @@ -1890,6 +1905,8 @@ sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) return (0); } +#endif + /* * address management functions */ @@ -1932,47 +1949,56 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * anything... note: this would leave the address on both inp and * asoc lists */ - if (ifa->address.sa.sa_family == AF_INET6) { - 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.sin6; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* we skip unspecifed addresses */ - return; - } - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (stcb->asoc.local_scope == 0) { + sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* we skip unspecifed addresses */ return; } - /* is it the right link local scope? */ - if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (stcb->asoc.local_scope == 0) { + return; + } + /* is it the right link local scope? */ + if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { + return; + } + } + if (stcb->asoc.site_scope == 0 && + IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { return; } + break; } - if (stcb->asoc.site_scope == 0 && - IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { - return; - } - } else if (ifa->address.sa.sa_family == AF_INET) { - struct sockaddr_in *sin; - struct in6pcb *inp6; +#endif + case AF_INET: + { + struct sockaddr_in *sin; + struct in6pcb *inp6; - inp6 = (struct in6pcb *)&inp->ip_inp.inp; - /* invalid if we are a v6 only endpoint */ - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp6)) - return; + inp6 = (struct in6pcb *)&inp->ip_inp.inp; + /* invalid if we are a v6 only endpoint */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp6)) + return; - sin = (struct sockaddr_in *)&ifa->address.sa; - if (sin->sin_addr.s_addr == 0) { - /* we skip unspecifed addresses */ - return; + sin = (struct sockaddr_in *)&ifa->address.sa; + if (sin->sin_addr.s_addr == 0) { + /* we skip unspecifed addresses */ + return; + } + if (stcb->asoc.ipv4_local_scope == 0 && + IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { + return; + } + break; } - if (stcb->asoc.ipv4_local_scope == 0 && - IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { - return; - } - } else { + default: /* else, not AF_INET or AF_INET6, so skip */ return; } @@ -2106,66 +2132,76 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, continue; } /* Same checks again for assoc */ - if (ifa->address.sa.sa_family == AF_INET6) { - /* invalid if we're not a v6 endpoint */ - struct sockaddr_in6 *sin6; + switch (ifa->address.sa.sa_family) { +#ifdef INET6 + case AF_INET6: + { + /* invalid if we're not a v6 endpoint */ + struct sockaddr_in6 *sin6; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { - cnt_invalid++; - if (asc->cnt == cnt_invalid) - return; - else - continue; - } - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* we skip unspecifed addresses */ - continue; - } - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (stcb->asoc.local_scope == 0) { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { + cnt_invalid++; + if (asc->cnt == cnt_invalid) + return; + else + continue; + } + sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* we skip unspecifed addresses */ continue; } - /* is it the right link local scope? */ - if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (stcb->asoc.local_scope == 0) { + continue; + } + /* is it the right link local scope? */ + if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { + continue; + } + } + break; + } +#endif + case AF_INET: + { + /* invalid if we are a v6 only endpoint */ + struct in6pcb *inp6; + struct sockaddr_in *sin; + + inp6 = (struct in6pcb *)&inp->ip_inp.inp; + /* invalid if we are a v6 only endpoint */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp6)) + continue; + + sin = (struct sockaddr_in *)&ifa->address.sa; + if (sin->sin_addr.s_addr == 0) { + /* we skip unspecifed addresses */ continue; } + if (stcb->asoc.ipv4_local_scope == 0 && + IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { + continue;; + } + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp6)) { + cnt_invalid++; + if (asc->cnt == cnt_invalid) + return; + else + continue; + } + break; } - } else if (ifa->address.sa.sa_family == AF_INET) { - /* invalid if we are a v6 only endpoint */ - struct in6pcb *inp6; - struct sockaddr_in *sin; - - inp6 = (struct in6pcb *)&inp->ip_inp.inp; - /* invalid if we are a v6 only endpoint */ - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp6)) - continue; - - sin = (struct sockaddr_in *)&ifa->address.sa; - if (sin->sin_addr.s_addr == 0) { - /* we skip unspecifed addresses */ - continue; - } - if (stcb->asoc.ipv4_local_scope == 0 && - IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { - continue;; - } - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp6)) { - cnt_invalid++; - if (asc->cnt == cnt_invalid) - return; - else - continue; - } - } else { + default: /* invalid address family */ cnt_invalid++; if (asc->cnt == cnt_invalid) return; else continue; + break; } if (type == SCTP_ADD_IP_ADDRESS) { diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index fcb607cc4f93..993f6417220f 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -116,7 +116,7 @@ sctp_startup_iterator(void) #endif - +#ifdef INET6 void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) { @@ -144,6 +144,7 @@ sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) } } +#endif static uint32_t diff --git a/sys/netinet/sctp_bsd_addr.h b/sys/netinet/sctp_bsd_addr.h index 45a05b643e87..63d39b2bb4ba 100644 --- a/sys/netinet/sctp_bsd_addr.h +++ b/sys/netinet/sctp_bsd_addr.h @@ -44,8 +44,11 @@ void sctp_startup_iterator(void); #endif +#ifdef INET6 void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa); +#endif + #ifdef SCTP_PACKET_LOGGING void sctp_packet_log(struct mbuf *m, int length); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 4e57cb1760d5..160245980004 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -1248,7 +1248,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, return (NULL); } /* pre-reserve some space */ +#ifdef INET6 SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); +#else + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* Set the len */ @@ -2116,31 +2120,40 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, } /* First get the destination address setup too. */ iph = mtod(m, struct ip *); - if (iph->ip_v == IPVERSION) { - /* its IPv4 */ - struct sockaddr_in *lsin; + switch (iph->ip_v) { + case IPVERSION: + { + /* its IPv4 */ + struct sockaddr_in *lsin; - lsin = (struct sockaddr_in *)(localep_sa); - memset(lsin, 0, sizeof(*lsin)); - lsin->sin_family = AF_INET; - lsin->sin_len = sizeof(*lsin); - lsin->sin_port = sh->dest_port; - lsin->sin_addr.s_addr = iph->ip_dst.s_addr; - size_of_pkt = SCTP_GET_IPV4_LENGTH(iph); - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - /* its IPv6 */ - struct ip6_hdr *ip6; - struct sockaddr_in6 *lsin6; + lsin = (struct sockaddr_in *)(localep_sa); + memset(lsin, 0, sizeof(*lsin)); + lsin->sin_family = AF_INET; + lsin->sin_len = sizeof(*lsin); + lsin->sin_port = sh->dest_port; + lsin->sin_addr.s_addr = iph->ip_dst.s_addr; + size_of_pkt = SCTP_GET_IPV4_LENGTH(iph); + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + /* its IPv6 */ + struct ip6_hdr *ip6; + struct sockaddr_in6 *lsin6; - lsin6 = (struct sockaddr_in6 *)(localep_sa); - memset(lsin6, 0, sizeof(*lsin6)); - lsin6->sin6_family = AF_INET6; - lsin6->sin6_len = sizeof(struct sockaddr_in6); - ip6 = mtod(m, struct ip6_hdr *); - lsin6->sin6_port = sh->dest_port; - lsin6->sin6_addr = ip6->ip6_dst; - size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6) + iphlen; - } else { + lsin6 = (struct sockaddr_in6 *)(localep_sa); + memset(lsin6, 0, sizeof(*lsin6)); + lsin6->sin6_family = AF_INET6; + lsin6->sin6_len = sizeof(struct sockaddr_in6); + ip6 = mtod(m, struct ip6_hdr *); + lsin6->sin6_port = sh->dest_port; + lsin6->sin6_addr = ip6->ip6_dst; + size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6) + iphlen; + break; + } +#endif + default: return (NULL); } @@ -2287,7 +2300,11 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, return (NULL); } /* pre-reserve some space */ +#ifdef INET6 SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); +#else + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 7cfe60fd7cf1..8fa1846ce61d 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -1874,47 +1874,60 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, */ return (0); } - if ((ifa->address.sa.sa_family == AF_INET) && ipv4_addr_legal) { - struct sockaddr_in *sin; + switch (ifa->address.sa.sa_family) { + case AF_INET: + if (ipv4_addr_legal) { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sin; - if (sin->sin_addr.s_addr == 0) { - /* not in scope , unspecified */ + sin = (struct sockaddr_in *)&ifa->address.sin; + if (sin->sin_addr.s_addr == 0) { + /* not in scope , unspecified */ + return (0); + } + if ((ipv4_local_scope == 0) && + (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { + /* private address not in scope */ + return (0); + } + } else { return (0); } - if ((ipv4_local_scope == 0) && - (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { - /* private address not in scope */ - return (0); - } - } else if ((ifa->address.sa.sa_family == AF_INET6) && ipv6_addr_legal) { - struct sockaddr_in6 *sin6; + break; +#ifdef INET6 + case AF_INET6: + if (ipv6_addr_legal) { + struct sockaddr_in6 *sin6; - /* - * Must update the flags, bummer, which means any IFA locks - * must now be applied HERE <-> - */ - if (do_update) { - sctp_gather_internal_ifa_flags(ifa); - } - if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { + /* + * Must update the flags, bummer, which means any + * IFA locks must now be applied HERE <-> + */ + if (do_update) { + sctp_gather_internal_ifa_flags(ifa); + } + if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { + return (0); + } + /* ok to use deprecated addresses? */ + sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* skip unspecifed addresses */ + return (0); + } + if ( /* (local_scope == 0) && */ + (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { + return (0); + } + if ((site_scope == 0) && + (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { + return (0); + } + } else { return (0); } - /* ok to use deprecated addresses? */ - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* skip unspecifed addresses */ - return (0); - } - if ( /* (local_scope == 0) && */ - (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { - return (0); - } - if ((site_scope == 0) && - (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { - return (0); - } - } else { + break; +#endif + default: return (0); } return (1); @@ -1954,30 +1967,39 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa) parmh = mtod(mret, struct sctp_paramhdr *); } /* now add the parameter */ - if (ifa->address.sa.sa_family == AF_INET) { - struct sctp_ipv4addr_param *ipv4p; - struct sockaddr_in *sin; + switch (ifa->address.sa.sa_family) { + case AF_INET: + { + struct sctp_ipv4addr_param *ipv4p; + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sin; - ipv4p = (struct sctp_ipv4addr_param *)parmh; - parmh->param_type = htons(SCTP_IPV4_ADDRESS); - parmh->param_length = htons(len); - ipv4p->addr = sin->sin_addr.s_addr; - SCTP_BUF_LEN(mret) += len; - } else if (ifa->address.sa.sa_family == AF_INET6) { - struct sctp_ipv6addr_param *ipv6p; - struct sockaddr_in6 *sin6; + sin = (struct sockaddr_in *)&ifa->address.sin; + ipv4p = (struct sctp_ipv4addr_param *)parmh; + parmh->param_type = htons(SCTP_IPV4_ADDRESS); + parmh->param_length = htons(len); + ipv4p->addr = sin->sin_addr.s_addr; + SCTP_BUF_LEN(mret) += len; + break; + } +#ifdef INET6 + case AF_INET6: + { + struct sctp_ipv6addr_param *ipv6p; + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; - ipv6p = (struct sctp_ipv6addr_param *)parmh; - parmh->param_type = htons(SCTP_IPV6_ADDRESS); - parmh->param_length = htons(len); - memcpy(ipv6p->addr, &sin6->sin6_addr, - sizeof(ipv6p->addr)); - /* clear embedded scope in the address */ - in6_clearscope((struct in6_addr *)ipv6p->addr); - SCTP_BUF_LEN(mret) += len; - } else { + sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + ipv6p = (struct sctp_ipv6addr_param *)parmh; + parmh->param_type = htons(SCTP_IPV6_ADDRESS); + parmh->param_length = htons(len); + memcpy(ipv6p->addr, &sin6->sin6_addr, + sizeof(ipv6p->addr)); + /* clear embedded scope in the address */ + in6_clearscope((struct in6_addr *)ipv6p->addr); + SCTP_BUF_LEN(mret) += len; + break; + } +#endif + default: return (m); } return (mret); @@ -2643,6 +2665,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, * addresses. We should use one corresponding to the * next-hop. (by micchie) */ +#ifdef INET6 if (stcb && fam == AF_INET6 && sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) { if (sctp_v6src_match_nexthop(&sifa->address.sin6, ro) @@ -2650,6 +2673,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, continue; } } +#endif /* Avoid topologically incorrect IPv4 address */ if (stcb && fam == AF_INET && sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) { @@ -2946,7 +2970,11 @@ sctp_source_address_selection(struct sctp_inpcb *inp, int non_asoc_addr_ok, uint32_t vrf_id) { struct sockaddr_in *to = (struct sockaddr_in *)&ro->ro_dst; + +#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; @@ -3025,7 +3053,8 @@ sctp_source_address_selection(struct sctp_inpcb *inp, fam = to->sin_family; dest_is_priv = dest_is_loop = 0; /* Setup our scopes for the destination */ - if (fam == AF_INET) { + switch (fam) { + case AF_INET: /* Scope based on outbound address */ if ((IN4_ISPRIVATE_ADDRESS(&to->sin_addr))) { dest_is_priv = 1; @@ -3036,7 +3065,9 @@ sctp_source_address_selection(struct sctp_inpcb *inp, net->addr_is_local = 1; } } - } else if (fam == AF_INET6) { + break; +#ifdef INET6 + case AF_INET6: /* Scope based on outbound address */ if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { /* @@ -3053,6 +3084,8 @@ sctp_source_address_selection(struct sctp_inpcb *inp, } else if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { dest_is_priv = 1; } + break; +#endif } SCTPDBG(SCTP_DEBUG_OUTPUT2, "Select source addr for:"); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)to); @@ -3931,6 +3964,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; } SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT\n"); +#ifdef INET6 if (((struct sockaddr *)&(net->ro._l_addr))->sa_family == AF_INET6) { /* * special hook, if we are sending to link local it will not @@ -3942,6 +3976,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked if (IN6_IS_ADDR_LINKLOCAL(&sin6l->sin6_addr)) cnt_inits_to = 1; } +#endif if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { /* This case should not happen */ SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - failed timer?\n"); @@ -3987,11 +4022,17 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked sup_addr = (struct sctp_supported_addr_param *)((caddr_t)initm + sizeof(*initm)); sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); - /* we support 2 types IPv6/IPv4 */ - sup_addr->ph.param_length = htons(sizeof(*sup_addr) + - sizeof(uint16_t)); +#ifdef INET6 + /* we support 2 types: IPv6/IPv4 */ + 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: IPv4 */ + sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint8_t)); + sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS); + sup_addr->addr_type[1] = htons(0); /* this is the padding */ +#endif SCTP_BUF_LEN(m) += sizeof(*sup_addr) + sizeof(uint16_t); if (inp->sctp_ep.adaptation_layer_indicator) { @@ -4327,7 +4368,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, *abort_processing = 1; if (op_err == NULL) { /* Ok need to try to get a mbuf */ +#ifdef INET6 l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#else + l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#endif l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA); @@ -4338,7 +4383,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, * and sctp header and * chunk hdr */ +#ifdef INET6 SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); +#else + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); } @@ -4389,13 +4438,21 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, int l_len; /* Ok need to try to get an mbuf */ +#ifdef INET6 l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#else + l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#endif l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA); if (op_err) { SCTP_BUF_LEN(op_err) = 0; +#ifdef INET6 SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); +#else + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); } @@ -4456,12 +4513,20 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, if ((op_err == NULL) && phdr) { int l_len; +#ifdef INET6 l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#else + l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); +#endif l_len += (2 * sizeof(struct sctp_paramhdr)); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA); if (op_err) { SCTP_BUF_LEN(op_err) = 0; +#ifdef INET6 SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); +#else + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); +#endif SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); } @@ -4498,11 +4563,20 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, * 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; struct ip *iph; + +#ifdef INET6 + struct ip6_hdr *ip6h; + +#endif struct mbuf *mat; uint16_t ptype, plen; int err_at; @@ -4510,27 +4584,33 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, struct sctp_nets *net; memset(&sin4, 0, sizeof(sin4)); +#ifdef INET6 memset(&sin6, 0, sizeof(sin6)); +#endif sin4.sin_family = AF_INET; sin4.sin_len = sizeof(sin4); +#ifdef INET6 sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); - +#endif sa_touse = NULL; /* First what about the src address of the pkt ? */ iph = mtod(in_initpkt, struct ip *); - if (iph->ip_v == IPVERSION) { + switch (iph->ip_v) { + case IPVERSION: /* source addr is IPv4 */ sin4.sin_addr = iph->ip_src; sa_touse = (struct sockaddr *)&sin4; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { + break; +#ifdef INET6 + case IPV6_VERSION >> 4: /* source addr is IPv6 */ - struct ip6_hdr *ip6h; - ip6h = mtod(in_initpkt, struct ip6_hdr *); sin6.sin6_addr = ip6h->ip6_src; sa_touse = (struct sockaddr *)&sin6; - } else { + break; +#endif + default: return (1); } @@ -4545,7 +4625,9 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, fnd = 1; break; } - } else if (sa->sa_family == AF_INET6) { + } +#ifdef INET6 + if (sa->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)sa; if (SCTP6_ARE_ADDR_EQUAL(&sa6->sin6_addr, &sin6.sin6_addr)) { @@ -4553,6 +4635,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, break; } } +#endif } } if (fnd == 0) { @@ -4590,8 +4673,10 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, 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; } if (sa_touse) { @@ -4609,7 +4694,9 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, fnd = 1; break; } - } else if (sa->sa_family == AF_INET6) { + } +#ifdef INET6 + if (sa->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)sa; if (SCTP6_ARE_ADDR_EQUAL( &sa6->sin6_addr, &sin6.sin6_addr)) { @@ -4617,6 +4704,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, break; } } +#endif } if (!fnd) { /* New addr added! no need to look further */ @@ -4649,10 +4737,18 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_supported_chunk_types_param *pr_supported; struct sockaddr_storage store; struct sockaddr_in *sin; + +#ifdef INET6 struct sockaddr_in6 *sin6; + +#endif sctp_route_t *ro; struct ip *iph; + +#ifdef INET6 struct ip6_hdr *ip6; + +#endif struct sockaddr *to; struct sctp_state_cookie stc; struct sctp_nets *net = NULL; @@ -4752,138 +4848,166 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* now for scope setup */ memset((caddr_t)&store, 0, sizeof(store)); sin = (struct sockaddr_in *)&store; +#ifdef INET6 sin6 = (struct sockaddr_in6 *)&store; +#endif if (net == NULL) { to = (struct sockaddr *)&store; iph = mtod(init_pkt, struct ip *); - if (iph->ip_v == IPVERSION) { - struct sctp_ifa *addr; - sctp_route_t iproute; + switch (iph->ip_v) { + case IPVERSION: + { + struct sctp_ifa *addr; + sctp_route_t iproute; - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - sin->sin_port = sh->src_port; - sin->sin_addr = iph->ip_src; - /* lookup address */ - stc.address[0] = sin->sin_addr.s_addr; - stc.address[1] = 0; - stc.address[2] = 0; - stc.address[3] = 0; - stc.addr_type = SCTP_IPV4_ADDRESS; - /* local from address */ - memset(&iproute, 0, sizeof(iproute)); - ro = &iproute; - memcpy(&ro->ro_dst, sin, sizeof(*sin)); - addr = sctp_source_address_selection(inp, NULL, - ro, NULL, 0, - vrf_id); - if (addr == NULL) - return; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_port = sh->src_port; + sin->sin_addr = iph->ip_src; + /* lookup address */ + stc.address[0] = sin->sin_addr.s_addr; + stc.address[1] = 0; + stc.address[2] = 0; + stc.address[3] = 0; + stc.addr_type = SCTP_IPV4_ADDRESS; + /* local from address */ + memset(&iproute, 0, sizeof(iproute)); + ro = &iproute; + memcpy(&ro->ro_dst, sin, sizeof(*sin)); + addr = sctp_source_address_selection(inp, NULL, + ro, NULL, 0, + vrf_id); + if (addr == NULL) + return; - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } - stc.laddress[0] = addr->address.sin.sin_addr.s_addr; - stc.laddress[1] = 0; - stc.laddress[2] = 0; - stc.laddress[3] = 0; - stc.laddr_type = SCTP_IPV4_ADDRESS; - /* scope_id is only for v6 */ - stc.scope_id = 0; + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; + } + stc.laddress[0] = addr->address.sin.sin_addr.s_addr; + stc.laddress[1] = 0; + stc.laddress[2] = 0; + stc.laddress[3] = 0; + stc.laddr_type = SCTP_IPV4_ADDRESS; + /* scope_id is only for v6 */ + stc.scope_id = 0; #ifndef SCTP_DONT_DO_PRIVADDR_SCOPE - if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { - stc.ipv4_scope = 1; - } + if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { + stc.ipv4_scope = 1; + } #else - stc.ipv4_scope = 1; + stc.ipv4_scope = 1; #endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ - /* Must use the address in this case */ - if (sctp_is_address_on_local_host((struct sockaddr *)sin, vrf_id)) { - stc.loopback_scope = 1; - stc.ipv4_scope = 1; - stc.site_scope = 1; - stc.local_scope = 0; + /* Must use the address in this case */ + if (sctp_is_address_on_local_host((struct sockaddr *)sin, vrf_id)) { + stc.loopback_scope = 1; + stc.ipv4_scope = 1; + stc.site_scope = 1; + stc.local_scope = 0; + } + sctp_free_ifa(addr); + break; } - sctp_free_ifa(addr); - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - struct sctp_ifa *addr; - struct route_in6 iproute6; +#ifdef INET6 + case IPV6_VERSION >> 4: + { + struct sctp_ifa *addr; + struct route_in6 iproute6; - ip6 = mtod(init_pkt, struct ip6_hdr *); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - sin6->sin6_port = sh->src_port; - sin6->sin6_addr = ip6->ip6_src; - /* lookup address */ - memcpy(&stc.address, &sin6->sin6_addr, - sizeof(struct in6_addr)); - sin6->sin6_scope_id = 0; - stc.addr_type = SCTP_IPV6_ADDRESS; - stc.scope_id = 0; - if (sctp_is_address_on_local_host((struct sockaddr *)sin6, vrf_id)) { - stc.loopback_scope = 1; - stc.local_scope = 0; - stc.site_scope = 1; - stc.ipv4_scope = 1; - } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - /* - * If the new destination is a LINK_LOCAL we - * must have common both site and local - * scope. Don't set local scope though since - * we must depend on the source to be added - * implicitly. We cannot assure just because - * we share one link that all links are - * common. - */ - stc.local_scope = 0; - stc.site_scope = 1; - stc.ipv4_scope = 1; - /* - * we start counting for the private address - * stuff at 1. since the link local we - * source from won't show up in our scoped - * count. - */ - cnt_inits_to = 1; - /* pull out the scope_id from incoming pkt */ - /* FIX ME: does this have scope from rcvif? */ - (void)sa6_recoverscope(sin6); + ip6 = mtod(init_pkt, struct ip6_hdr *); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_port = sh->src_port; + sin6->sin6_addr = ip6->ip6_src; + /* lookup address */ + memcpy(&stc.address, &sin6->sin6_addr, + sizeof(struct in6_addr)); + sin6->sin6_scope_id = 0; + stc.addr_type = SCTP_IPV6_ADDRESS; + stc.scope_id = 0; + if (sctp_is_address_on_local_host((struct sockaddr *)sin6, vrf_id)) { + stc.loopback_scope = 1; + stc.local_scope = 0; + stc.site_scope = 1; + stc.ipv4_scope = 1; + } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + /* + * If the new destination is a + * LINK_LOCAL we must have common + * both site and local scope. Don't + * set local scope though since we + * must depend on the source to be + * added implicitly. We cannot + * assure just because we share one + * link that all links are common. + */ + stc.local_scope = 0; + stc.site_scope = 1; + stc.ipv4_scope = 1; + /* + * we start counting for the private + * address stuff at 1. since the + * link local we source from won't + * show up in our scoped count. + */ + cnt_inits_to = 1; + /* + * pull out the scope_id from + * incoming pkt + */ + /* + * FIX ME: does this have scope from + * rcvif? + */ + (void)sa6_recoverscope(sin6); - sa6_embedscope(sin6, ip6_use_defzone); - stc.scope_id = sin6->sin6_scope_id; - } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { - /* - * If the new destination is SITE_LOCAL then - * we must have site scope in common. - */ - stc.site_scope = 1; + sa6_embedscope(sin6, ip6_use_defzone); + stc.scope_id = sin6->sin6_scope_id; + } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { + /* + * If the new destination is + * SITE_LOCAL then we must have site + * scope in common. + */ + stc.site_scope = 1; + } + /* local from address */ + memset(&iproute6, 0, sizeof(iproute6)); + ro = (sctp_route_t *) & iproute6; + memcpy(&ro->ro_dst, sin6, sizeof(*sin6)); + addr = sctp_source_address_selection(inp, NULL, + ro, NULL, 0, vrf_id); + if (addr == NULL) + return; + + if (ro->ro_rt) { + RTFREE(ro->ro_rt); + ro->ro_rt = NULL; + } + memcpy(&stc.laddress, &addr->address.sin6.sin6_addr, sizeof(struct in6_addr)); + stc.laddr_type = SCTP_IPV6_ADDRESS; + sctp_free_ifa(addr); + break; } - /* local from address */ - memset(&iproute6, 0, sizeof(iproute6)); - ro = (sctp_route_t *) & iproute6; - memcpy(&ro->ro_dst, sin6, sizeof(*sin6)); - addr = sctp_source_address_selection(inp, NULL, - ro, NULL, 0, vrf_id); - if (addr == NULL) - return; - - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } - memcpy(&stc.laddress, &addr->address.sin6.sin6_addr, sizeof(struct in6_addr)); - stc.laddr_type = SCTP_IPV6_ADDRESS; - sctp_free_ifa(addr); +#endif + default: + /* TSNH */ + break; } } else { /* set the scope per the existing tcb */ + +#ifdef INET6 struct sctp_nets *lnet; +#endif + stc.loopback_scope = asoc->loopback_scope; stc.ipv4_scope = asoc->ipv4_local_scope; stc.site_scope = asoc->site_scope; stc.local_scope = asoc->local_scope; +#ifdef INET6 + /* Why do we not consider IPv4 LL addresses? */ TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { if (lnet->ro._l_addr.sin6.sin6_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL(&lnet->ro._l_addr.sin6.sin6_addr)) { @@ -4895,10 +5019,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } } } - +#endif /* use the net pointer */ to = (struct sockaddr *)&net->ro._l_addr; - if (to->sa_family == AF_INET) { + switch (to->sa_family) { + case AF_INET: sin = (struct sockaddr_in *)to; stc.address[0] = sin->sin_addr.s_addr; stc.address[1] = 0; @@ -4924,7 +5049,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stc.laddress[2] = 0; stc.laddress[3] = 0; stc.laddr_type = SCTP_IPV4_ADDRESS; - } else if (to->sa_family == AF_INET6) { + break; +#ifdef INET6 + case AF_INET6: sin6 = (struct sockaddr_in6 *)to; memcpy(&stc.address, &sin6->sin6_addr, sizeof(struct in6_addr)); @@ -4945,6 +5072,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, memcpy(&stc.laddress, &net->ro._s_addr->address.sin6.sin6_addr, sizeof(struct in6_addr)); stc.laddr_type = SCTP_IPV6_ADDRESS; + break; +#endif } } /* Now lets put the SCTP header in place */ @@ -6839,7 +6968,6 @@ sctp_fill_outqueue(struct sctp_tcb *stcb, } #else goal_mtu = net->mtu - SCTP_MIN_OVERHEAD; - mtu_fromwheel = 0; #endif /* Need an allowance for the data chunk header too */ goal_mtu -= sizeof(struct sctp_data_chunk); @@ -7233,10 +7361,19 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, continue; } } - if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { + switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { + case AF_INET: mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); - } else { + break; +#ifdef INET6 + case AF_INET6: mtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); + break; +#endif + default: + /* TSNH */ + mtu = net->mtu; + break; } mx_mtu = mtu; to_out = 0; @@ -7513,16 +7650,25 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, mtu -= sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id); } /* now lets add any data within the MTU constraints */ - if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { + switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { + case AF_INET: if (net->mtu > (sizeof(struct ip) + sizeof(struct sctphdr))) omtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); else omtu = 0; - } else { + break; +#ifdef INET6 + case AF_INET6: if (net->mtu > (sizeof(struct ip6_hdr) + sizeof(struct sctphdr))) omtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); else omtu = 0; + break; +#endif + default: + /* TSNH */ + omtu = 0; + break; } if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) && (skip_data_for_this_net == 0)) || (cookie)) { @@ -9691,12 +9837,20 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *o_pak; struct mbuf *mout; struct ip *iph, *iph_out; + +#ifdef INET6 struct ip6_hdr *ip6, *ip6_out; + +#endif int offset_out, len, mlen; struct sctp_shutdown_complete_msg *comp_cp; /* Get room for the largest message */ +#ifdef INET6 len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg)); +#else + len = (sizeof(struct ip) + sizeof(struct sctp_shutdown_complete_msg)); +#endif mout = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); if (mout == NULL) { return; @@ -9704,9 +9858,12 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, SCTP_BUF_LEN(mout) = len; iph = mtod(m, struct ip *); iph_out = NULL; +#ifdef INET6 ip6_out = NULL; +#endif offset_out = 0; - if (iph->ip_v == IPVERSION) { + switch (iph->ip_v) { + case IPVERSION: SCTP_BUF_LEN(mout) = sizeof(struct ip) + sizeof(struct sctp_shutdown_complete_msg); SCTP_BUF_NEXT(mout) = NULL; @@ -9728,7 +9885,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, offset_out += sizeof(*iph_out); comp_cp = (struct sctp_shutdown_complete_msg *)( (caddr_t)iph_out + offset_out); - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { + break; +#ifdef INET6 + case IPV6_VERSION >> 4: ip6 = (struct ip6_hdr *)iph; SCTP_BUF_LEN(mout) = sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg); @@ -9749,7 +9908,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, offset_out += sizeof(*ip6_out); comp_cp = (struct sctp_shutdown_complete_msg *)( (caddr_t)ip6_out + offset_out); - } else { + break; +#endif + default: /* Currently not supported. */ return; } @@ -9790,7 +9951,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, /* Free the route if we got one back */ if (ro.ro_rt) RTFREE(ro.ro_rt); - } else if (ip6_out != NULL) { + } +#ifdef INET6 + if (ip6_out != NULL) { struct route_in6 ro; int ret; struct sctp_tcb *stcb = NULL; @@ -9809,6 +9972,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh, if (ro.ro_rt) RTFREE(ro.ro_rt); } +#endif SCTP_STAT_INCR(sctps_sendpackets); SCTP_STAT_INCR_COUNTER64(sctps_outpackets); SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); @@ -10104,6 +10268,11 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net, int len; int was_trunc = 0; struct ip *iph; + +#ifdef INET6 + struct ip6_hdr *ip6h; + +#endif int fullsz = 0, extra = 0; long spc; int offset; @@ -10134,15 +10303,20 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net, sctp_free_a_chunk(stcb, chk); return; } - if (iph->ip_v == IPVERSION) { + switch (iph->ip_v) { + case IPVERSION: /* IPv4 */ len = chk->send_size = iph->ip_len; - } else { - struct ip6_hdr *ip6h; - + break; +#ifdef INET6 + case IPV6_VERSION >> 4: /* IPv6 */ ip6h = mtod(m, struct ip6_hdr *); len = chk->send_size = htons(ip6h->ip6_plen); + break; +#endif + default: + return; } /* Validate that we do not have an ABORT in here. */ offset = iphlen + sizeof(struct sctphdr); @@ -10593,7 +10767,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, struct mbuf *mout; struct sctp_abort_msg *abm; struct ip *iph, *iph_out; + +#ifdef INET6 struct ip6_hdr *ip6, *ip6_out; + +#endif int iphlen_out, len; /* don't respond to ABORT with ABORT */ @@ -10602,8 +10780,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, sctp_m_freem(err_cause); return; } +#ifdef INET6 len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg)); - +#else + len = (sizeof(struct ip) + sizeof(struct sctp_abort_msg)); +#endif mout = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); if (mout == NULL) { if (err_cause) @@ -10612,8 +10793,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, } iph = mtod(m, struct ip *); iph_out = NULL; +#ifdef INET6 ip6_out = NULL; - if (iph->ip_v == IPVERSION) { +#endif + switch (iph->ip_v) { + case IPVERSION: iph_out = mtod(mout, struct ip *); SCTP_BUF_LEN(mout) = sizeof(*iph_out) + sizeof(*abm); SCTP_BUF_NEXT(mout) = err_cause; @@ -10633,7 +10817,9 @@ 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); - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { + break; +#ifdef INET6 + case IPV6_VERSION >> 4: ip6 = (struct ip6_hdr *)iph; ip6_out = mtod(mout, struct ip6_hdr *); SCTP_BUF_LEN(mout) = sizeof(*ip6_out) + sizeof(*abm); @@ -10648,7 +10834,9 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, iphlen_out = sizeof(*ip6_out); abm = (struct sctp_abort_msg *)((caddr_t)ip6_out + iphlen_out); - } else { + break; +#endif + default: /* Currently not supported */ if (err_cause) sctp_m_freem(err_cause); @@ -10722,7 +10910,9 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, /* Free the route if we got one back */ if (ro.ro_rt) RTFREE(ro.ro_rt); - } else if (ip6_out != NULL) { + } +#ifdef INET6 + if (ip6_out != NULL) { struct route_in6 ro; int ret; struct sctp_tcb *stcb = NULL; @@ -10744,6 +10934,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, if (ro.ro_rt) RTFREE(ro.ro_rt); } +#endif SCTP_STAT_INCR(sctps_sendpackets); SCTP_STAT_INCR_COUNTER64(sctps_outpackets); } @@ -10801,7 +10992,11 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, len += padlen; } val = sctp_calculate_sum(scm, NULL, 0); +#ifdef INET6 mout = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr), 1, M_DONTWAIT, 1, MT_DATA); +#else + mout = sctp_get_mbuf_for_msg(sizeof(struct ip), 1, M_DONTWAIT, 1, MT_DATA); +#endif if (mout == NULL) { sctp_m_freem(scm); return; @@ -10812,89 +11007,101 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, return; } ohdr->checksum = val; - if (iph->ip_v == IPVERSION) { - /* V4 */ - struct ip *out; - sctp_route_t ro; - struct sctp_tcb *stcb = NULL; + switch (iph->ip_v) { + case IPVERSION: + { + /* V4 */ + struct ip *out; + sctp_route_t ro; + struct sctp_tcb *stcb = NULL; - SCTP_BUF_LEN(mout) = sizeof(struct ip); - len += sizeof(struct ip); + SCTP_BUF_LEN(mout) = sizeof(struct ip); + len += sizeof(struct ip); - bzero(&ro, sizeof ro); - out = mtod(mout, struct ip *); - out->ip_v = iph->ip_v; - out->ip_hl = (sizeof(struct ip) / 4); - out->ip_tos = iph->ip_tos; - out->ip_id = iph->ip_id; - out->ip_off = 0; - out->ip_ttl = MAXTTL; - out->ip_p = IPPROTO_SCTP; - out->ip_sum = 0; - out->ip_src = iph->ip_dst; - out->ip_dst = iph->ip_src; - out->ip_len = len; + bzero(&ro, sizeof ro); + out = mtod(mout, struct ip *); + out->ip_v = iph->ip_v; + out->ip_hl = (sizeof(struct ip) / 4); + out->ip_tos = iph->ip_tos; + out->ip_id = iph->ip_id; + out->ip_off = 0; + out->ip_ttl = MAXTTL; + out->ip_p = IPPROTO_SCTP; + out->ip_sum = 0; + out->ip_src = iph->ip_dst; + out->ip_dst = iph->ip_src; + out->ip_len = len; #ifdef SCTP_PACKET_LOGGING - if (sctp_logging_level & SCTP_LAST_PACKET_TRACING) - sctp_packet_log(mout, len); + if (sctp_logging_level & SCTP_LAST_PACKET_TRACING) + sctp_packet_log(mout, len); #endif - SCTP_ATTACH_CHAIN(o_pak, mout, len); + SCTP_ATTACH_CHAIN(o_pak, mout, len); - SCTP_IP_OUTPUT(retcode, o_pak, &ro, stcb, vrf_id); + SCTP_IP_OUTPUT(retcode, o_pak, &ro, stcb, vrf_id); - SCTP_STAT_INCR(sctps_sendpackets); - SCTP_STAT_INCR_COUNTER64(sctps_outpackets); - /* Free the route if we got one back */ - if (ro.ro_rt) - RTFREE(ro.ro_rt); - } else { - /* V6 */ - struct route_in6 ro; - int ret; - struct sctp_tcb *stcb = NULL; - struct ifnet *ifp = NULL; - struct ip6_hdr *out6, *in6; + SCTP_STAT_INCR(sctps_sendpackets); + SCTP_STAT_INCR_COUNTER64(sctps_outpackets); + /* Free the route if we got one back */ + if (ro.ro_rt) + RTFREE(ro.ro_rt); + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + /* V6 */ + struct route_in6 ro; + int ret; + struct sctp_tcb *stcb = NULL; + struct ifnet *ifp = NULL; + struct ip6_hdr *out6, *in6; - SCTP_BUF_LEN(mout) = sizeof(struct ip6_hdr); - len += sizeof(struct ip6_hdr); - bzero(&ro, sizeof ro); - in6 = mtod(m, struct ip6_hdr *); - out6 = mtod(mout, struct ip6_hdr *); - out6->ip6_flow = in6->ip6_flow; - out6->ip6_hlim = ip6_defhlim; - out6->ip6_nxt = IPPROTO_SCTP; - out6->ip6_src = in6->ip6_dst; - out6->ip6_dst = in6->ip6_src; - out6->ip6_plen = len - sizeof(struct ip6_hdr); + SCTP_BUF_LEN(mout) = sizeof(struct ip6_hdr); + len += sizeof(struct ip6_hdr); + bzero(&ro, sizeof ro); + in6 = mtod(m, struct ip6_hdr *); + out6 = mtod(mout, struct ip6_hdr *); + out6->ip6_flow = in6->ip6_flow; + out6->ip6_hlim = ip6_defhlim; + out6->ip6_nxt = IPPROTO_SCTP; + out6->ip6_src = in6->ip6_dst; + out6->ip6_dst = in6->ip6_src; + out6->ip6_plen = len - sizeof(struct ip6_hdr); #ifdef SCTP_DEBUG - bzero(&lsa6, sizeof(lsa6)); - lsa6.sin6_len = sizeof(lsa6); - lsa6.sin6_family = AF_INET6; - lsa6.sin6_addr = out6->ip6_src; - bzero(&fsa6, sizeof(fsa6)); - fsa6.sin6_len = sizeof(fsa6); - fsa6.sin6_family = AF_INET6; - fsa6.sin6_addr = out6->ip6_dst; + bzero(&lsa6, sizeof(lsa6)); + lsa6.sin6_len = sizeof(lsa6); + lsa6.sin6_family = AF_INET6; + lsa6.sin6_addr = out6->ip6_src; + bzero(&fsa6, sizeof(fsa6)); + fsa6.sin6_len = sizeof(fsa6); + fsa6.sin6_family = AF_INET6; + fsa6.sin6_addr = out6->ip6_dst; #endif - SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_operr_to calling ipv6 output:\n"); - SCTPDBG(SCTP_DEBUG_OUTPUT2, "src: "); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&lsa6); - SCTPDBG(SCTP_DEBUG_OUTPUT2, "dst "); - SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&fsa6); + SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_operr_to calling ipv6 output:\n"); + SCTPDBG(SCTP_DEBUG_OUTPUT2, "src: "); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&lsa6); + SCTPDBG(SCTP_DEBUG_OUTPUT2, "dst "); + SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&fsa6); #ifdef SCTP_PACKET_LOGGING - if (sctp_logging_level & SCTP_LAST_PACKET_TRACING) - sctp_packet_log(mout, len); + if (sctp_logging_level & SCTP_LAST_PACKET_TRACING) + sctp_packet_log(mout, len); #endif - SCTP_ATTACH_CHAIN(o_pak, mout, len); - SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id); + SCTP_ATTACH_CHAIN(o_pak, mout, len); + SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id); - SCTP_STAT_INCR(sctps_sendpackets); - SCTP_STAT_INCR_COUNTER64(sctps_outpackets); - /* Free the route if we got one back */ - if (ro.ro_rt) - RTFREE(ro.ro_rt); + SCTP_STAT_INCR(sctps_sendpackets); + SCTP_STAT_INCR_COUNTER64(sctps_outpackets); + /* Free the route if we got one back */ + if (ro.ro_rt) + RTFREE(ro.ro_rt); + break; + } +#endif + default: + /* TSNH */ + break; } } @@ -12479,6 +12686,7 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end, return (m); } +#ifdef INET6 int sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) { @@ -12527,6 +12735,9 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) SCTPDBG(SCTP_DEBUG_OUTPUT2, "pfxrouter is not installed\n"); return (0); } + +#endif + int sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro) { diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 25e5c7983932..7ad3f7f95aac 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -51,6 +51,7 @@ struct sctp_epinfo sctppcbinfo; /* FIX: we don't handle multiple link local scopes */ /* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ +#ifdef INET6 int SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b) { @@ -64,6 +65,8 @@ SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b) return (IN6_ARE_ADDR_EQUAL(&tmp_a, &tmp_b)); } +#endif + void sctp_fill_pcbinfo(struct sctp_pcbinfo *spcb) { @@ -608,37 +611,47 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, sctp_ifap->localifa_flags = SCTP_ADDR_VALID | SCTP_ADDR_DEFER_USE; sctp_ifap->flags = ifa_flags; /* Set scope */ - if (sctp_ifap->address.sa.sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (sctp_ifap->address.sa.sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifap->address.sin; - if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || - (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { - sctp_ifap->src_is_loop = 1; + sin = (struct sockaddr_in *)&sctp_ifap->address.sin; + if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || + (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { + sctp_ifap->src_is_loop = 1; + } + if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { + sctp_ifap->src_is_priv = 1; + } + sctp_ifnp->num_v4++; + if (new_ifn_af) + new_ifn_af = AF_INET; + break; } - if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { - sctp_ifap->src_is_priv = 1; - } - sctp_ifnp->num_v4++; - if (new_ifn_af) - new_ifn_af = AF_INET; - } else if (sctp_ifap->address.sa.sa_family == AF_INET6) { - /* ok to use deprecated addresses? */ - struct sockaddr_in6 *sin6; +#ifdef INET6 + case AF_INET6: + { + /* ok to use deprecated addresses? */ + struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6; - if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || - (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { - sctp_ifap->src_is_loop = 1; + sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6; + if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || + (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { + sctp_ifap->src_is_loop = 1; + } + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + sctp_ifap->src_is_priv = 1; + } + sctp_ifnp->num_v6++; + if (new_ifn_af) + new_ifn_af = AF_INET6; + break; } - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - sctp_ifap->src_is_priv = 1; - } - sctp_ifnp->num_v6++; - if (new_ifn_af) - new_ifn_af = AF_INET6; - } else { +#endif + default: new_ifn_af = 0; + break; } hash_of_addr = sctp_get_ifa_hash_val(&sctp_ifap->address.sa); @@ -893,7 +906,9 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, match = 1; break; } - } else { + } +#ifdef INET6 + if (from->sa_family == AF_INET6) { struct sockaddr_in6 *intf_addr6; struct sockaddr_in6 *sin6; @@ -907,6 +922,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, break; } } +#endif } } if (match == 0) { @@ -944,38 +960,56 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, /* not the same family, can't be a match */ continue; } - if (from->sa_family == AF_INET) { - struct sockaddr_in *sin, *rsin; + switch (from->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin, *rsin; - sin = (struct sockaddr_in *)&net->ro._l_addr; - rsin = (struct sockaddr_in *)from; - if (sin->sin_addr.s_addr == - rsin->sin_addr.s_addr) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin = (struct sockaddr_in *)&net->ro._l_addr; + rsin = (struct sockaddr_in *)from; + if (sin->sin_addr.s_addr == + rsin->sin_addr.s_addr) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + /* + * Update the endpoint + * pointer + */ + *inp_p = inp; + SCTP_INP_RUNLOCK(inp); + return (stcb); } - /* Update the endpoint pointer */ - *inp_p = inp; - SCTP_INP_RUNLOCK(inp); - return (stcb); + break; } - } else { - struct sockaddr_in6 *sin6, *rsin6; +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6, *rsin6; - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - rsin6 = (struct sockaddr_in6 *)from; - if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, - &rsin6->sin6_addr)) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; + rsin6 = (struct sockaddr_in6 *)from; + if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, + &rsin6->sin6_addr)) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + /* + * Update the endpoint + * pointer + */ + *inp_p = inp; + SCTP_INP_RUNLOCK(inp); + return (stcb); } - /* Update the endpoint pointer */ - *inp_p = inp; - SCTP_INP_RUNLOCK(inp); - return (stcb); + break; } +#endif + default: + /* TSNH */ + break; } } SCTP_TCB_UNLOCK(stcb); @@ -1076,53 +1110,67 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, /* not the same family */ continue; } - if (remote->sa_family == AF_INET) { - struct sockaddr_in *sin, *rsin; + switch (remote->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin, + *rsin; - sin = (struct sockaddr_in *) - &net->ro._l_addr; - rsin = (struct sockaddr_in *)remote; - if (sin->sin_addr.s_addr == - rsin->sin_addr.s_addr) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin = (struct sockaddr_in *) + &net->ro._l_addr; + rsin = (struct sockaddr_in *)remote; + if (sin->sin_addr.s_addr == + rsin->sin_addr.s_addr) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + if (locked_tcb == NULL) { + SCTP_INP_DECR_REF(inp); + } else if (locked_tcb != stcb) { + SCTP_TCB_LOCK(locked_tcb); + } + if (locked_tcb) { + atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); + } + SCTP_INP_WUNLOCK(inp); + SCTP_INP_INFO_RUNLOCK(); + return (stcb); } - if (locked_tcb == NULL) { - SCTP_INP_DECR_REF(inp); - } else if (locked_tcb != stcb) { - SCTP_TCB_LOCK(locked_tcb); - } - if (locked_tcb) { - atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); - } - SCTP_INP_WUNLOCK(inp); - SCTP_INP_INFO_RUNLOCK(); - return (stcb); + break; } - } else if (remote->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6, *rsin6; +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6, + *rsin6; - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - rsin6 = (struct sockaddr_in6 *)remote; - if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, - &rsin6->sin6_addr)) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; + rsin6 = (struct sockaddr_in6 *)remote; + if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, + &rsin6->sin6_addr)) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + if (locked_tcb == NULL) { + SCTP_INP_DECR_REF(inp); + } else if (locked_tcb != stcb) { + SCTP_TCB_LOCK(locked_tcb); + } + if (locked_tcb) { + atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); + } + SCTP_INP_WUNLOCK(inp); + SCTP_INP_INFO_RUNLOCK(); + return (stcb); } - if (locked_tcb == NULL) { - SCTP_INP_DECR_REF(inp); - } else if (locked_tcb != stcb) { - SCTP_TCB_LOCK(locked_tcb); - } - if (locked_tcb) { - atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); - } - SCTP_INP_WUNLOCK(inp); - SCTP_INP_INFO_RUNLOCK(); - return (stcb); + break; } +#endif + default: + /* TSNH */ + break; } } SCTP_TCB_UNLOCK(stcb); @@ -1159,54 +1207,68 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, /* not the same family */ continue; } - if (remote->sa_family == AF_INET) { - struct sockaddr_in *sin, *rsin; + switch (remote->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin, + *rsin; - sin = (struct sockaddr_in *) - &net->ro._l_addr; - rsin = (struct sockaddr_in *)remote; - if (sin->sin_addr.s_addr == - rsin->sin_addr.s_addr) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin = (struct sockaddr_in *) + &net->ro._l_addr; + rsin = (struct sockaddr_in *)remote; + if (sin->sin_addr.s_addr == + rsin->sin_addr.s_addr) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + if (locked_tcb == NULL) { + SCTP_INP_DECR_REF(inp); + } else if (locked_tcb != stcb) { + SCTP_TCB_LOCK(locked_tcb); + } + if (locked_tcb) { + atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); + } + SCTP_INP_WUNLOCK(inp); + SCTP_INP_INFO_RUNLOCK(); + return (stcb); } - if (locked_tcb == NULL) { - SCTP_INP_DECR_REF(inp); - } else if (locked_tcb != stcb) { - SCTP_TCB_LOCK(locked_tcb); - } - if (locked_tcb) { - atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); - } - SCTP_INP_WUNLOCK(inp); - SCTP_INP_INFO_RUNLOCK(); - return (stcb); + break; } - } else if (remote->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6, *rsin6; +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6, + *rsin6; - sin6 = (struct sockaddr_in6 *) - &net->ro._l_addr; - rsin6 = (struct sockaddr_in6 *)remote; - if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, - &rsin6->sin6_addr)) { - /* found it */ - if (netp != NULL) { - *netp = net; + sin6 = (struct sockaddr_in6 *) + &net->ro._l_addr; + rsin6 = (struct sockaddr_in6 *)remote; + if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, + &rsin6->sin6_addr)) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + if (locked_tcb == NULL) { + SCTP_INP_DECR_REF(inp); + } else if (locked_tcb != stcb) { + SCTP_TCB_LOCK(locked_tcb); + } + if (locked_tcb) { + atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); + } + SCTP_INP_WUNLOCK(inp); + SCTP_INP_INFO_RUNLOCK(); + return (stcb); } - if (locked_tcb == NULL) { - SCTP_INP_DECR_REF(inp); - } else if (locked_tcb != stcb) { - SCTP_TCB_LOCK(locked_tcb); - } - if (locked_tcb) { - atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); - } - SCTP_INP_WUNLOCK(inp); - SCTP_INP_INFO_RUNLOCK(); - return (stcb); + break; } +#endif + default: + /* TSNH */ + break; } } SCTP_TCB_UNLOCK(stcb); @@ -1332,20 +1394,37 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, { struct sctp_inpcb *inp; struct sockaddr_in *sin; + +#ifdef INET6 struct sockaddr_in6 *sin6; + +#endif struct sctp_laddr *laddr; + +#ifdef INET6 + struct sockaddr_in6 *intf_addr6; + +#endif + int fnd; /* * Endpoing probe expects that the INP_INFO is locked. */ - if (nam->sa_family == AF_INET) { + sin = NULL; +#ifdef INET6 + sin6 = NULL; +#endif + switch (nam->sa_family) { + case AF_INET: sin = (struct sockaddr_in *)nam; - sin6 = NULL; - } else if (nam->sa_family == AF_INET6) { + break; +#ifdef INET6 + case AF_INET6: sin6 = (struct sockaddr_in6 *)nam; - sin = NULL; - } else { + break; +#endif + default: /* unsupported family */ return (NULL); } @@ -1390,11 +1469,14 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, (sin->sin_addr.s_addr == INADDR_ANY)) { /* Can't hunt for one that has no address specified */ return (NULL); - } else if ((nam->sa_family == AF_INET6) && + } +#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); } +#endif /* * ok, not bound to all so see if we can find a EP bound to this * address. @@ -1443,21 +1525,24 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, struct sockaddr_in *intf_addr; intf_addr = &laddr->ifa->address.sin; - if (nam->sa_family == AF_INET) { + switch (nam->sa_family) { + case AF_INET: if (sin->sin_addr.s_addr == intf_addr->sin_addr.s_addr) { SCTP_INP_RUNLOCK(inp); return (inp); } - } else if (nam->sa_family == AF_INET6) { - struct sockaddr_in6 *intf_addr6; - + break; +#ifdef INET6 + case AF_INET6: intf_addr6 = &laddr->ifa->address.sin6; if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &intf_addr6->sin6_addr)) { SCTP_INP_RUNLOCK(inp); return (inp); } + break; +#endif } } } @@ -1774,33 +1859,42 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, struct sctp_inpcb *inp; iph = mtod(m, struct ip *); - if (iph->ip_v == IPVERSION) { - /* its IPv4 */ - struct sockaddr_in *from4; + switch (iph->ip_v) { + case IPVERSION: + { + /* its IPv4 */ + struct sockaddr_in *from4; - from4 = (struct sockaddr_in *)&from_store; - bzero(from4, sizeof(*from4)); - from4->sin_family = AF_INET; - from4->sin_len = sizeof(struct sockaddr_in); - from4->sin_addr.s_addr = iph->ip_src.s_addr; - from4->sin_port = sh->src_port; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - /* its IPv6 */ - struct ip6_hdr *ip6; - struct sockaddr_in6 *from6; + from4 = (struct sockaddr_in *)&from_store; + bzero(from4, sizeof(*from4)); + from4->sin_family = AF_INET; + from4->sin_len = sizeof(struct sockaddr_in); + from4->sin_addr.s_addr = iph->ip_src.s_addr; + from4->sin_port = sh->src_port; + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + /* its IPv6 */ + struct ip6_hdr *ip6; + struct sockaddr_in6 *from6; - ip6 = mtod(m, struct ip6_hdr *); - from6 = (struct sockaddr_in6 *)&from_store; - bzero(from6, sizeof(*from6)); - from6->sin6_family = AF_INET6; - from6->sin6_len = sizeof(struct sockaddr_in6); - from6->sin6_addr = ip6->ip6_src; - from6->sin6_port = sh->src_port; - /* Get the scopes in properly to the sin6 addr's */ - /* we probably don't need these operations */ - (void)sa6_recoverscope(from6); - sa6_embedscope(from6, ip6_use_defzone); - } else { + ip6 = mtod(m, struct ip6_hdr *); + from6 = (struct sockaddr_in6 *)&from_store; + bzero(from6, sizeof(*from6)); + from6->sin6_family = AF_INET6; + from6->sin6_len = sizeof(struct sockaddr_in6); + from6->sin6_addr = ip6->ip6_src; + from6->sin6_port = sh->src_port; + /* Get the scopes in properly to the sin6 addr's */ + /* we probably don't need these operations */ + (void)sa6_recoverscope(from6); + sa6_embedscope(from6, ip6_use_defzone); + break; + } +#endif + default: /* Currently not supported. */ return (NULL); } @@ -1812,32 +1906,44 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset, return (retval); } } - if (iph->ip_v == IPVERSION) { - /* its IPv4 */ - struct sockaddr_in *to4; + switch (iph->ip_v) { + case IPVERSION: + { + /* its IPv4 */ + struct sockaddr_in *to4; - to4 = (struct sockaddr_in *)&to_store; - bzero(to4, sizeof(*to4)); - to4->sin_family = AF_INET; - to4->sin_len = sizeof(struct sockaddr_in); - to4->sin_addr.s_addr = iph->ip_dst.s_addr; - to4->sin_port = sh->dest_port; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - /* its IPv6 */ - struct ip6_hdr *ip6; - struct sockaddr_in6 *to6; + to4 = (struct sockaddr_in *)&to_store; + bzero(to4, sizeof(*to4)); + to4->sin_family = AF_INET; + to4->sin_len = sizeof(struct sockaddr_in); + to4->sin_addr.s_addr = iph->ip_dst.s_addr; + to4->sin_port = sh->dest_port; + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + /* its IPv6 */ + struct ip6_hdr *ip6; + struct sockaddr_in6 *to6; - ip6 = mtod(m, struct ip6_hdr *); - to6 = (struct sockaddr_in6 *)&to_store; - bzero(to6, sizeof(*to6)); - to6->sin6_family = AF_INET6; - to6->sin6_len = sizeof(struct sockaddr_in6); - to6->sin6_addr = ip6->ip6_dst; - to6->sin6_port = sh->dest_port; - /* Get the scopes in properly to the sin6 addr's */ - /* we probably don't need these operations */ - (void)sa6_recoverscope(to6); - sa6_embedscope(to6, ip6_use_defzone); + ip6 = mtod(m, struct ip6_hdr *); + to6 = (struct sockaddr_in6 *)&to_store; + bzero(to6, sizeof(*to6)); + to6->sin6_family = AF_INET6; + to6->sin6_len = sizeof(struct sockaddr_in6); + to6->sin6_addr = ip6->ip6_dst; + to6->sin6_port = sh->dest_port; + /* Get the scopes in properly to the sin6 addr's */ + /* we probably don't need these operations */ + (void)sa6_recoverscope(to6); + sa6_embedscope(to6, ip6_use_defzone); + break; + } +#endif + default: + /* TSNH */ + break; } find_tcp_pool = 0; if ((ch->chunk_type != SCTP_INITIATION) && @@ -1895,9 +2001,18 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, { struct sctp_tcb *stcb; struct sockaddr_in *sin; + +#ifdef INET6 struct sockaddr_in6 *sin6; + +#endif struct sockaddr_storage local_store, remote_store; struct ip *iph; + +#ifdef INET6 + struct ip6_hdr *ip6; + +#endif struct sctp_paramhdr parm_buf, *phdr; int ptype; int zero_address = 0; @@ -1908,24 +2023,27 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, /* First get the destination address setup too. */ iph = mtod(m, struct ip *); - if (iph->ip_v == IPVERSION) { + switch (iph->ip_v) { + case IPVERSION: /* its IPv4 */ sin = (struct sockaddr_in *)&local_store; sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_port = sh->dest_port; sin->sin_addr.s_addr = iph->ip_dst.s_addr; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { + break; +#ifdef INET6 + case IPV6_VERSION >> 4: /* its IPv6 */ - struct ip6_hdr *ip6; - ip6 = mtod(m, struct ip6_hdr *); sin6 = (struct sockaddr_in6 *)&local_store; sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); sin6->sin6_port = sh->dest_port; sin6->sin6_addr = ip6->ip6_dst; - } else { + break; +#endif + default: return NULL; } @@ -1938,51 +2056,60 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset, } ptype = (int)((uint32_t) ntohs(phdr->param_type)); /* get the correlation address */ - if (ptype == SCTP_IPV6_ADDRESS) { - /* ipv6 address param */ - struct sctp_ipv6addr_param *p6, p6_buf; + switch (ptype) { +#ifdef INET6 + case SCTP_IPV6_ADDRESS: + { + /* ipv6 address param */ + struct sctp_ipv6addr_param *p6, p6_buf; - if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv6addr_param)) { - return NULL; + if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv6addr_param)) { + return NULL; + } + p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m, + offset + sizeof(struct sctp_asconf_chunk), + &p6_buf.ph, sizeof(*p6)); + if (p6 == NULL) { + SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", + __FUNCTION__); + return (NULL); + } + sin6 = (struct sockaddr_in6 *)&remote_store; + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_port = sh->src_port; + memcpy(&sin6->sin6_addr, &p6->addr, sizeof(struct in6_addr)); + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) + zero_address = 1; + break; } - p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m, - offset + sizeof(struct sctp_asconf_chunk), - &p6_buf.ph, sizeof(*p6)); - if (p6 == NULL) { - SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", - __FUNCTION__); - return (NULL); - } - sin6 = (struct sockaddr_in6 *)&remote_store; - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_port = sh->src_port; - memcpy(&sin6->sin6_addr, &p6->addr, sizeof(struct in6_addr)); - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) - zero_address = 1; - } else if (ptype == SCTP_IPV4_ADDRESS) { - /* ipv4 address param */ - struct sctp_ipv4addr_param *p4, p4_buf; +#endif + case SCTP_IPV4_ADDRESS: + { + /* ipv4 address param */ + struct sctp_ipv4addr_param *p4, p4_buf; - if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv4addr_param)) { - return NULL; + if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv4addr_param)) { + return NULL; + } + p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m, + offset + sizeof(struct sctp_asconf_chunk), + &p4_buf.ph, sizeof(*p4)); + if (p4 == NULL) { + SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", + __FUNCTION__); + return (NULL); + } + sin = (struct sockaddr_in *)&remote_store; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_port = sh->src_port; + memcpy(&sin->sin_addr, &p4->addr, sizeof(struct in_addr)); + if (sin->sin_addr.s_addr == INADDR_ANY) + zero_address = 1; + break; } - p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m, - offset + sizeof(struct sctp_asconf_chunk), - &p4_buf.ph, sizeof(*p4)); - if (p4 == NULL) { - SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", - __FUNCTION__); - return (NULL); - } - sin = (struct sockaddr_in *)&remote_store; - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_port = sh->src_port; - memcpy(&sin->sin_addr, &p4->addr, sizeof(struct in_addr)); - if (sin->sin_addr.s_addr == INADDR_ANY) - zero_address = 1; - } else { + default: /* invalid address param type */ return NULL; } @@ -2416,62 +2543,76 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, prison = 1; } if (addr != NULL) { - if (addr->sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; - /* IPV6_V6ONLY socket? */ - if (SCTP_IPV6_V6ONLY(ip_inp)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - return (EINVAL); + /* IPV6_V6ONLY socket? */ + if (SCTP_IPV6_V6ONLY(ip_inp)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + return (EINVAL); + } + if (addr->sa_len != sizeof(*sin)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + return (EINVAL); + } + sin = (struct sockaddr_in *)addr; + lport = sin->sin_port; + if (prison) { + /* + * For INADDR_ANY and LOOPBACK the + * prison_ip() call will transmute + * the ip address to the proper + * value (i.e. the IP address owned + * by the jail). + */ + if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + return (EINVAL); + } + } + if (sin->sin_addr.s_addr != INADDR_ANY) { + bindall = 0; + } + break; } - if (addr->sa_len != sizeof(*sin)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - return (EINVAL); - } - sin = (struct sockaddr_in *)addr; - lport = sin->sin_port; - if (prison) { +#ifdef INET6 + case AF_INET6: + { /* - * For INADDR_ANY and LOOPBACK the - * prison_ip() call will transmute the ip - * address to the proper value (i.e. the IP - * address owned by the jail). + * Only for pure IPv6 Address. (No IPv4 + * Mapped!) */ - if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr)) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)addr; + + if (addr->sa_len != sizeof(*sin6)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); return (EINVAL); } - } - if (sin->sin_addr.s_addr != INADDR_ANY) { - bindall = 0; - } - } else if (addr->sa_family == AF_INET6) { - /* Only for pure IPv6 Address. (No IPv4 Mapped!) */ - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)addr; - - if (addr->sa_len != sizeof(*sin6)) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - return (EINVAL); - } - lport = sin6->sin6_port; - /* - * Jail checks for IPv6 should go HERE! i.e. add the - * prison_ip() equivilant in this postion to - * transmute the addresses to the proper one jailed. - */ - if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - bindall = 0; - /* KAME hack: embed scopeid */ - if (sa6_embedscope(sin6, ip6_use_defzone) != 0) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); - return (EINVAL); + lport = sin6->sin6_port; + /* + * Jail checks for IPv6 should go HERE! i.e. + * add the prison_ip() equivilant in this + * postion to transmute the addresses to the + * proper one jailed. + */ + if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + bindall = 0; + /* KAME hack: embed scopeid */ + if (sa6_embedscope(sin6, ip6_use_defzone) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); + return (EINVAL); + } } + /* this must be cleared for ifa_ifwithaddr() */ + sin6->sin6_scope_id = 0; + break; } - /* this must be cleared for ifa_ifwithaddr() */ - sin6->sin6_scope_id = 0; - } else { +#endif + default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT); return (EAFNOSUPPORT); } @@ -3472,6 +3613,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer); /* Now generate a route for this guy */ +#ifdef INET6 /* KAME hack: embed scopeid */ if (newaddr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; @@ -3480,14 +3622,17 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, (void)sa6_embedscope(sin6, ip6_use_defzone); sin6->sin6_scope_id = 0; } +#endif SCTP_RTALLOC((sctp_route_t *) & net->ro, stcb->asoc.vrf_id); +#ifdef INET6 if (newaddr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; (void)sa6_recoverscope(sin6); } +#endif if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { /* Get source address */ net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep, @@ -5205,33 +5350,43 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, sin6.sin6_port = stcb->rport; if (altsa == NULL) { iph = mtod(m, struct ip *); - if (iph->ip_v == IPVERSION) { - /* its IPv4 */ - struct sockaddr_in *sin_2; + switch (iph->ip_v) { + case IPVERSION: + { + /* its IPv4 */ + struct sockaddr_in *sin_2; - sin_2 = (struct sockaddr_in *)(local_sa); - memset(sin_2, 0, sizeof(sin)); - sin_2->sin_family = AF_INET; - sin_2->sin_len = sizeof(sin); - sin_2->sin_port = sh->dest_port; - sin_2->sin_addr.s_addr = iph->ip_dst.s_addr; - sin.sin_addr = iph->ip_src; - sa = (struct sockaddr *)&sin; - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - /* its IPv6 */ - struct ip6_hdr *ip6; - struct sockaddr_in6 *sin6_2; + sin_2 = (struct sockaddr_in *)(local_sa); + memset(sin_2, 0, sizeof(sin)); + sin_2->sin_family = AF_INET; + sin_2->sin_len = sizeof(sin); + sin_2->sin_port = sh->dest_port; + sin_2->sin_addr.s_addr = iph->ip_dst.s_addr; + sin.sin_addr = iph->ip_src; + sa = (struct sockaddr *)&sin; + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + /* its IPv6 */ + struct ip6_hdr *ip6; + struct sockaddr_in6 *sin6_2; - ip6 = mtod(m, struct ip6_hdr *); - sin6_2 = (struct sockaddr_in6 *)(local_sa); - memset(sin6_2, 0, sizeof(sin6)); - sin6_2->sin6_family = AF_INET6; - sin6_2->sin6_len = sizeof(struct sockaddr_in6); - sin6_2->sin6_port = sh->dest_port; - sin6.sin6_addr = ip6->ip6_src; - sa = (struct sockaddr *)&sin6; - } else { + ip6 = mtod(m, struct ip6_hdr *); + sin6_2 = (struct sockaddr_in6 *)(local_sa); + memset(sin6_2, 0, sizeof(sin6)); + sin6_2->sin6_family = AF_INET6; + sin6_2->sin6_len = sizeof(struct sockaddr_in6); + sin6_2->sin6_port = sh->dest_port; + sin6.sin6_addr = ip6->ip6_src; + sa = (struct sockaddr *)&sin6; + break; + } +#endif + default: sa = NULL; + break; } } else { /* diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 65e4b505c0c8..44ac300a4fc4 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -434,8 +434,11 @@ struct sctp_tcb { extern struct sctp_epinfo sctppcbinfo; +#ifdef INET6 int SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b); +#endif + void sctp_fill_pcbinfo(struct sctp_pcbinfo *); struct sctp_ifn * diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index fd232d94c559..b42802938153 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -206,36 +206,51 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s if (sctp_is_addr_restricted(stcb, sctp_ifa)) continue; } - if ((sctp_ifa->address.sa.sa_family == AF_INET) && (ipv4_addr_legal)) { - struct sockaddr_in *sin; + switch (sctp_ifa->address.sa.sa_family) { + case AF_INET: + if (ipv4_addr_legal) { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; - if (sin->sin_addr.s_addr == 0) - continue; - if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) - continue; - } else if ((sctp_ifa->address.sa.sa_family == AF_INET6) && (ipv6_addr_legal)) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) - continue; - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (local_scope == 0) + sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + if (sin->sin_addr.s_addr == 0) continue; - if (sin6->sin6_scope_id == 0) { - /* - * bad link local - * address - */ - if (sa6_recoverscope(sin6) != 0) - continue; - } - } - if ((site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) + if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) + continue; + } else { continue; - } else + } + break; +#ifdef INET6 + case AF_INET6: + if (ipv6_addr_legal) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) + continue; + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (local_scope == 0) + continue; + if (sin6->sin6_scope_id == 0) { + /* + * bad link + * local + * address + */ + if (sa6_recoverscope(sin6) != 0) + continue; + } + } + if ((site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) + continue; + } else { + continue; + } + break; +#endif + default: continue; + } memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr)); memcpy((void *)&xladdr.address, (const void *)&sctp_ifa->address, sizeof(union sctp_sockstore)); SCTP_INP_RUNLOCK(inp); diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 62cdeabbebcd..1be19f9b7c52 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -1089,10 +1089,12 @@ sctp_shutdown(struct socket *so) static uint32_t sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa) { +#ifdef INET6 struct sockaddr_in6 lsa6; sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa, &lsa6); +#endif memcpy(ss, sa, sa->sa_len); return (0); } @@ -1166,72 +1168,101 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, continue; } } - if ((sctp_ifa->address.sa.sa_family == AF_INET) && - (ipv4_addr_legal)) { - struct sockaddr_in *sin; + switch (sctp_ifa->address.sa.sa_family) { + case AF_INET: + if (ipv4_addr_legal) { + struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; - if (sin->sin_addr.s_addr == 0) { - /* - * we skip unspecifed - * addresses - */ - continue; - } - if ((ipv4_local_scope == 0) && - (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { - continue; - } - if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) { - in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas); - ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; - sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); - actual += sizeof(struct sockaddr_in6); - } else { - memcpy(sas, sin, sizeof(*sin)); - ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport; - sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin)); - actual += sizeof(*sin); - } - if (actual >= limit) { - return (actual); - } - } else if ((sctp_ifa->address.sa.sa_family == AF_INET6) && - (ipv6_addr_legal)) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* - * we skip unspecifed - * addresses - */ - continue; - } - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (local_scope == 0) + sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + if (sin->sin_addr.s_addr == 0) { + /* + * we skip + * unspecifed + * addresses + */ continue; - if (sin6->sin6_scope_id == 0) { - if (sa6_recoverscope(sin6) != 0) - /* - * bad link - * local - * address - */ - continue; } - } - if ((site_scope == 0) && - (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { + if ((ipv4_local_scope == 0) && + (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { + continue; + } +#ifdef INET6 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { + in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas); + ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; + sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); + actual += sizeof(struct sockaddr_in6); + } else { +#endif + memcpy(sas, sin, sizeof(*sin)); + ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport; + sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin)); + actual += sizeof(*sin); +#ifdef INET6 + } +#endif + if (actual >= limit) { + return (actual); + } + } else { continue; } - memcpy(sas, sin6, sizeof(*sin6)); - ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; - sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6)); - actual += sizeof(*sin6); - if (actual >= limit) { - return (actual); + break; +#ifdef INET6 + case AF_INET6: + if (ipv6_addr_legal) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * we skip + * unspecifed + * addresses + */ + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (local_scope == 0) + continue; + if (sin6->sin6_scope_id == 0) { + if (sa6_recoverscope(sin6) != 0) + /* + * + * bad + * + * li + * nk + * + * loc + * al + * + * add + * re + * ss + * */ + continue; + } + } + if ((site_scope == 0) && + (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { + continue; + } + memcpy(sas, sin6, sizeof(*sin6)); + ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; + sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6)); + actual += sizeof(*sin6); + if (actual >= limit) { + return (actual); + } + } else { + continue; } + break; +#endif + default: + /* TSNH */ + break; } } } @@ -1303,7 +1334,7 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id) 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) { - if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) cnt += sizeof(struct sockaddr_in6); else cnt += sizeof(struct sockaddr_in); @@ -1317,7 +1348,7 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa->address.sa.sa_family == AF_INET) { - if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) cnt += sizeof(struct sockaddr_in6); else cnt += sizeof(struct sockaddr_in); @@ -1972,7 +2003,7 @@ 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 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) || + if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) || (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) { size += sizeof(struct sockaddr_in6); } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { @@ -2011,7 +2042,7 @@ 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 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) || + if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) || (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) { cpsz = sizeof(struct sockaddr_in6); } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) { @@ -2024,14 +2055,18 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, /* not enough room. */ break; } - if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) && +#ifdef 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 */ in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr, (struct sockaddr_in6 *)sas); } else { +#endif memcpy(sas, &net->ro._l_addr, cpsz); +#ifdef INET6 } +#endif ((struct sockaddr_in *)sas)->sin_port = stcb->rport; sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz); @@ -4214,8 +4249,10 @@ sctp_accept(struct socket *so, struct sockaddr **addr) struct sctp_inpcb *inp; union sctp_sockstore store; +#ifdef INET6 int error; +#endif inp = (struct sctp_inpcb *)so->so_pcb; if (inp == 0) { @@ -4243,29 +4280,41 @@ sctp_accept(struct socket *so, struct sockaddr **addr) SCTP_INP_RUNLOCK(inp); store = stcb->asoc.primary_destination->ro._l_addr; SCTP_TCB_UNLOCK(stcb); - if (store.sa.sa_family == AF_INET) { - struct sockaddr_in *sin; + switch (store.sa.sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; - SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_port = ((struct sockaddr_in *)&store)->sin_port; - sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr; - *addr = (struct sockaddr *)sin; - } else { - struct sockaddr_in6 *sin6; - - SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port; - - sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr; - if ((error = sa6_recoverscope(sin6)) != 0) { - SCTP_FREE_SONAME(sin6); - return (error); + SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_port = ((struct sockaddr_in *)&store)->sin_port; + sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr; + *addr = (struct sockaddr *)sin; + break; } - *addr = (struct sockaddr *)sin6; +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port; + + sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr; + if ((error = sa6_recoverscope(sin6)) != 0) { + SCTP_FREE_SONAME(sin6); + return (error); + } + *addr = (struct sockaddr *)sin6; + break; + } +#endif + default: + /* TSNH */ + break; } /* Wake any delayed sleep action */ if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) { diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index e9776900226c..cae00b0ad077 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -306,9 +306,7 @@ void sctp_init __P((void)); void sctp_pcbinfo_cleanup(void); - int sctp_flush(struct socket *, int); - int sctp_shutdown __P((struct socket *)); void sctp_notify __P((struct sctp_inpcb *, struct ip *ip, struct sctphdr *, diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 25b2f9215ac5..ac7c51aaeeb4 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -3029,23 +3029,33 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, spc->spc_type = SCTP_PEER_ADDR_CHANGE; spc->spc_flags = 0; spc->spc_length = sizeof(struct sctp_paddr_change); - if (sa->sa_family == AF_INET) { + switch (sa->sa_family) { + case AF_INET: memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); - } else { - struct sockaddr_in6 *sin6; + break; +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; - memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); + memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); - sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; - if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { - if (sin6->sin6_scope_id == 0) { - /* recover scope_id for user */ - (void)sa6_recoverscope(sin6); - } else { - /* clear embedded scope_id for user */ - in6_clearscope(&sin6->sin6_addr); + sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; + if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { + if (sin6->sin6_scope_id == 0) { + /* recover scope_id for user */ + (void)sa6_recoverscope(sin6); + } else { + /* clear embedded scope_id for user */ + in6_clearscope(&sin6->sin6_addr); + } } + break; } +#endif + default: + /* TSNH */ + break; } spc->spc_state = state; spc->spc_error = error; @@ -4048,6 +4058,7 @@ sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill) * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id * set (i.e. it's 0) so, create this function to compare link local scopes */ +#ifdef INET6 uint32_t sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2) { @@ -4097,6 +4108,8 @@ sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store) return (addr); } +#endif + /* * are the two addresses the same? currently a "scopeless" check returns: 1 * if same, 0 if not @@ -4113,22 +4126,29 @@ sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2) if (sa1->sa_family != sa2->sa_family) return (0); - if (sa1->sa_family == AF_INET6) { - /* IPv6 addresses */ - struct sockaddr_in6 *sin6_1, *sin6_2; + switch (sa1->sa_family) { +#ifdef INET6 + case AF_INET6: + { + /* IPv6 addresses */ + struct sockaddr_in6 *sin6_1, *sin6_2; - sin6_1 = (struct sockaddr_in6 *)sa1; - sin6_2 = (struct sockaddr_in6 *)sa2; - return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr, - &sin6_2->sin6_addr)); - } else if (sa1->sa_family == AF_INET) { - /* IPv4 addresses */ - struct sockaddr_in *sin_1, *sin_2; + sin6_1 = (struct sockaddr_in6 *)sa1; + sin6_2 = (struct sockaddr_in6 *)sa2; + return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr, + &sin6_2->sin6_addr)); + } +#endif + case AF_INET: + { + /* IPv4 addresses */ + struct sockaddr_in *sin_1, *sin_2; - sin_1 = (struct sockaddr_in *)sa1; - sin_2 = (struct sockaddr_in *)sa2; - return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr); - } else { + sin_1 = (struct sockaddr_in *)sa1; + sin_2 = (struct sockaddr_in *)sa2; + return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr); + } + default: /* we don't do these... */ return (0); } @@ -4137,69 +4157,94 @@ sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2) void sctp_print_address(struct sockaddr *sa) { +#ifdef INET6 char ip6buf[INET6_ADDRSTRLEN]; ip6buf[0] = 0; - if (sa->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6; +#endif - sin6 = (struct sockaddr_in6 *)sa; - SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", - ip6_sprintf(ip6buf, &sin6->sin6_addr), - ntohs(sin6->sin6_port), - sin6->sin6_scope_id); - } else if (sa->sa_family == AF_INET) { - struct sockaddr_in *sin; - unsigned char *p; + switch (sa->sa_family) { +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; - sin = (struct sockaddr_in *)sa; - p = (unsigned char *)&sin->sin_addr; - SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n", - p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); - } else { + sin6 = (struct sockaddr_in6 *)sa; + SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", + ip6_sprintf(ip6buf, &sin6->sin6_addr), + ntohs(sin6->sin6_port), + sin6->sin6_scope_id); + break; + } +#endif + case AF_INET: + { + struct sockaddr_in *sin; + unsigned char *p; + + sin = (struct sockaddr_in *)sa; + p = (unsigned char *)&sin->sin_addr; + SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n", + p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); + break; + } + default: SCTP_PRINTF("?\n"); + break; } } void sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh) { - if (iph->ip_v == IPVERSION) { - struct sockaddr_in lsa, fsa; + switch (iph->ip_v) { + case IPVERSION: + { + struct sockaddr_in lsa, fsa; - bzero(&lsa, sizeof(lsa)); - lsa.sin_len = sizeof(lsa); - lsa.sin_family = AF_INET; - lsa.sin_addr = iph->ip_src; - lsa.sin_port = sh->src_port; - bzero(&fsa, sizeof(fsa)); - fsa.sin_len = sizeof(fsa); - fsa.sin_family = AF_INET; - fsa.sin_addr = iph->ip_dst; - fsa.sin_port = sh->dest_port; - SCTP_PRINTF("src: "); - sctp_print_address((struct sockaddr *)&lsa); - SCTP_PRINTF("dest: "); - sctp_print_address((struct sockaddr *)&fsa); - } else if (iph->ip_v == (IPV6_VERSION >> 4)) { - struct ip6_hdr *ip6; - struct sockaddr_in6 lsa6, fsa6; + bzero(&lsa, sizeof(lsa)); + lsa.sin_len = sizeof(lsa); + lsa.sin_family = AF_INET; + lsa.sin_addr = iph->ip_src; + lsa.sin_port = sh->src_port; + bzero(&fsa, sizeof(fsa)); + fsa.sin_len = sizeof(fsa); + fsa.sin_family = AF_INET; + fsa.sin_addr = iph->ip_dst; + fsa.sin_port = sh->dest_port; + SCTP_PRINTF("src: "); + sctp_print_address((struct sockaddr *)&lsa); + SCTP_PRINTF("dest: "); + sctp_print_address((struct sockaddr *)&fsa); + break; + } +#ifdef INET6 + case IPV6_VERSION >> 4: + { + struct ip6_hdr *ip6; + struct sockaddr_in6 lsa6, fsa6; - ip6 = (struct ip6_hdr *)iph; - bzero(&lsa6, sizeof(lsa6)); - lsa6.sin6_len = sizeof(lsa6); - lsa6.sin6_family = AF_INET6; - lsa6.sin6_addr = ip6->ip6_src; - lsa6.sin6_port = sh->src_port; - bzero(&fsa6, sizeof(fsa6)); - fsa6.sin6_len = sizeof(fsa6); - fsa6.sin6_family = AF_INET6; - fsa6.sin6_addr = ip6->ip6_dst; - fsa6.sin6_port = sh->dest_port; - SCTP_PRINTF("src: "); - sctp_print_address((struct sockaddr *)&lsa6); - SCTP_PRINTF("dest: "); - sctp_print_address((struct sockaddr *)&fsa6); + ip6 = (struct ip6_hdr *)iph; + bzero(&lsa6, sizeof(lsa6)); + lsa6.sin6_len = sizeof(lsa6); + lsa6.sin6_family = AF_INET6; + lsa6.sin6_addr = ip6->ip6_src; + lsa6.sin6_port = sh->src_port; + bzero(&fsa6, sizeof(fsa6)); + fsa6.sin6_len = sizeof(fsa6); + fsa6.sin6_family = AF_INET6; + fsa6.sin6_addr = ip6->ip6_dst; + fsa6.sin6_port = sh->dest_port; + SCTP_PRINTF("src: "); + sctp_print_address((struct sockaddr *)&lsa6); + SCTP_PRINTF("dest: "); + sctp_print_address((struct sockaddr *)&fsa6); + break; + } +#endif + default: + /* TSNH */ + break; } } @@ -4723,7 +4768,9 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, return (laddr->ifa); break; } - } else if (addr->sa_family == AF_INET6) { + } +#ifdef INET6 + if (addr->sa_family == AF_INET6) { if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr, &laddr->ifa->address.sin6.sin6_addr)) { /* found him. */ @@ -4734,6 +4781,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, break; } } +#endif } if (holds_lock == 0) { SCTP_INP_RUNLOCK(inp); @@ -4810,7 +4858,9 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) return (sctp_ifap); break; } - } else if (addr->sa_family == AF_INET6) { + } +#ifdef INET6 + if (addr->sa_family == AF_INET6) { if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr, &sctp_ifap->address.sin6.sin6_addr)) { /* found him. */ @@ -4820,6 +4870,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) break; } } +#endif } if (holds_lock == 0) SCTP_IPI_ADDR_RUNLOCK(); @@ -5399,7 +5450,7 @@ sctp_sorecvmsg(struct socket *so, to = from; #if defined(INET) && defined(INET6) - if ((inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) && + if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) && (to->sa_family == AF_INET) && ((size_t)fromlen >= sizeof(struct sockaddr_in6))) { struct sockaddr_in *sin; @@ -5409,10 +5460,10 @@ sctp_sorecvmsg(struct socket *so, bzero(&sin6, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_addr.s6_addr16[2] = 0xffff; + sin6.sin6_addr.s6_addr32[2] = ntohl(0x0000ffff); bcopy(&sin->sin_addr, - &sin6.sin6_addr.s6_addr16[3], - sizeof(sin6.sin6_addr.s6_addr16[3])); + &sin6.sin6_addr.s6_addr32[3], + sizeof(sin6.sin6_addr.s6_addr32[3])); sin6.sin6_port = sin->sin_port; memcpy(from, (caddr_t)&sin6, sizeof(sin6)); } @@ -6185,8 +6236,12 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, uint32_t vrf_id, int *error, void *p) { struct sockaddr *addr_touse; + +#ifdef INET6 struct sockaddr_in sin; +#endif + /* see if we're bound all already! */ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); @@ -6307,8 +6362,12 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp, uint32_t vrf_id, int *error) { struct sockaddr *addr_touse; + +#ifdef INET6 struct sockaddr_in sin; +#endif + /* see if we're bound all already! */ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); @@ -6424,49 +6483,72 @@ sctp_local_addr_count(struct sctp_tcb *stcb) LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { if (sctp_is_addr_restricted(stcb, sctp_ifa)) continue; + switch (sctp_ifa->address.sa.sa_family) { + case AF_INET: + if (ipv4_addr_legal) { + struct sockaddr_in *sin; - if ((sctp_ifa->address.sa.sa_family == AF_INET) && - (ipv4_addr_legal)) { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; - if (sin->sin_addr.s_addr == 0) { - /* skip unspecified addrs */ - continue; - } - if ((ipv4_local_scope == 0) && - (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { - continue; - } - /* count this one */ - count++; - } else if ((sctp_ifa->address.sa.sa_family == AF_INET6) && - (ipv6_addr_legal)) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - continue; - } - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (local_scope == 0) + sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + if (sin->sin_addr.s_addr == 0) { + /* + * skip unspecified + * addrs + */ continue; - if (sin6->sin6_scope_id == 0) { - if (sa6_recoverscope(sin6) != 0) - /* - * bad link - * local - * address - */ - continue; } - } - if ((site_scope == 0) && - (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { + if ((ipv4_local_scope == 0) && + (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { + continue; + } + /* count this one */ + count++; + } else { continue; } - /* count this one */ - count++; + break; +#ifdef INET6 + case AF_INET6: + if (ipv6_addr_legal) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (local_scope == 0) + continue; + if (sin6->sin6_scope_id == 0) { + if (sa6_recoverscope(sin6) != 0) + /* + * + * bad + * + * li + * nk + * + * loc + * al + * + * add + * re + * ss + * */ + continue; + } + } + if ((site_scope == 0) && + (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { + continue; + } + /* count this one */ + count++; + } + break; +#endif + default: + /* TSNH */ + break; } } } diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index 24157e33e310..ec4631c7a67f 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -203,6 +203,8 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, int *totaddr, int *num_v4, int *num_v6, int *error, int limit, int *bad_addr); int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *); + +#ifdef INET6 uint32_t sctp_is_same_scope(struct sockaddr_in6 *, struct sockaddr_in6 *); struct sockaddr_in6 * @@ -222,7 +224,7 @@ struct sockaddr_in6 * } \ } \ } while (0) - +#endif int sctp_cmpaddr(struct sockaddr *, struct sockaddr *);