Allow SCTP to compile without INET6.

PR:		116816
Obtained from	tuexen@fh-muenster.de:
MFC after:	2 weeks
This commit is contained in:
Randall Stewart 2008-04-16 17:24:18 +00:00
parent c637bc9203
commit 5e2c2d872b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178251
13 changed files with 1529 additions and 957 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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 {
/*

View File

@ -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 *

View File

@ -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);

View File

@ -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) {

View File

@ -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 *,

View File

@ -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;
}
}
}

View File

@ -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 *);