Allow SCTP to compile without INET6.
PR: 116816 Obtained from tuexen@fh-muenster.de: MFC after: 2 weeks
This commit is contained in:
parent
c637bc9203
commit
5e2c2d872b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178251
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
/*
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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 *,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user