Improve compilation of SCTP code without INET support.

Some bugs where fixed while doing this:
* ASCONF-ACK messages might use wrong port number when using
  IPv6.
* Checking for additional addresses takes the correct address
  into account and also does not do more comparisons than
  necessary.

This patch is based on one received from bz@ who was
sponsored by The FreeBSD Foundation and iXsystems.

MFC after: 1 week
This commit is contained in:
Michael Tuexen 2011-04-30 11:18:16 +00:00
parent 79288c112c
commit e6194c2ed4
11 changed files with 2183 additions and 1370 deletions

File diff suppressed because it is too large Load Diff

View File

@ -228,10 +228,14 @@ sctp_init_ifns_for_vrf(int vrfid)
*/
struct ifnet *ifn;
struct ifaddr *ifa;
struct in6_ifaddr *ifa6;
struct sctp_ifa *sctp_ifa;
uint32_t ifa_flags;
#ifdef INET6
struct in6_ifaddr *ifa6;
#endif
IFNET_RLOCK();
TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
IF_ADDR_LOCK(ifn);
@ -239,29 +243,44 @@ sctp_init_ifns_for_vrf(int vrfid)
if (ifa->ifa_addr == NULL) {
continue;
}
if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
/* non inet/inet6 skip */
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET6) {
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
continue;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
/* skip unspecifed addresses */
continue;
}
} else {
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
continue;
}
break;
#endif
default:
continue;
}
if (sctp_is_desired_interface_type(ifa) == 0) {
/* non desired type */
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET6) {
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
ifa_flags = 0;
break;
#endif
#ifdef INET6
case AF_INET6:
ifa6 = (struct in6_ifaddr *)ifa;
ifa_flags = ifa6->ia6_flags;
} else {
break;
#endif
default:
ifa_flags = 0;
break;
}
sctp_ifa = sctp_add_addr_to_vrf(vrfid,
(void *)ifn,
@ -320,20 +339,26 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
if (ifa->ifa_addr == NULL) {
return;
}
if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
/* non inet/inet6 skip */
return;
}
if (ifa->ifa_addr->sa_family == AF_INET6) {
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
return;
}
break;
#endif
#ifdef INET6
case AF_INET6:
ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags;
if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
/* skip unspecifed addresses */
return;
}
} else {
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
return;
}
break;
#endif
default:
/* non inet/inet6 skip */
return;
}
if (sctp_is_desired_interface_type(ifa) == 0) {

View File

@ -530,38 +530,57 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sockaddr_storage store;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct sctp_nets *r_net, *f_net;
struct timeval tv;
int req_prim = 0;
#ifdef INET
struct sockaddr_in *sin;
#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
/* Invalid length */
return;
}
sin = (struct sockaddr_in *)&store;
sin6 = (struct sockaddr_in6 *)&store;
memset(&store, 0, sizeof(store));
if (cp->heartbeat.hb_info.addr_family == AF_INET &&
cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
sin->sin_family = cp->heartbeat.hb_info.addr_family;
sin->sin_len = cp->heartbeat.hb_info.addr_len;
sin->sin_port = stcb->rport;
memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
sizeof(sin->sin_addr));
} else if (cp->heartbeat.hb_info.addr_family == AF_INET6 &&
cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
sin6->sin6_port = stcb->rport;
memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
sizeof(sin6->sin6_addr));
} else {
switch (cp->heartbeat.hb_info.addr_family) {
#ifdef INET
case AF_INET:
if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
sin = (struct sockaddr_in *)&store;
sin->sin_family = cp->heartbeat.hb_info.addr_family;
sin->sin_len = cp->heartbeat.hb_info.addr_len;
sin->sin_port = stcb->rport;
memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
sizeof(sin->sin_addr));
} else {
return;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
sin6 = (struct sockaddr_in6 *)&store;
sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
sin6->sin6_port = stcb->rport;
memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
sizeof(sin6->sin6_addr));
} else {
return;
}
break;
#endif
default:
return;
}
r_net = sctp_findnet(stcb, (struct sockaddr *)sin);
r_net = sctp_findnet(stcb, (struct sockaddr *)&store);
if (r_net == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n");
return;
@ -1940,8 +1959,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
struct sctp_init_ack_chunk *initack_cp, initack_buf;
struct sockaddr_storage sa_store;
struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct sctp_association *asoc;
int chk_length;
int init_offset, initack_offset, initack_limit;
@ -1950,6 +1967,14 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
uint32_t old_tag;
uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
#ifdef INET
struct sockaddr_in *sin;
#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
@ -2169,14 +2194,19 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* warning, we re-use sin, sin6, sa_store here! */
/* pull in local_address (our "from" address) */
if (cookie->laddr_type == SCTP_IPV4_ADDRESS) {
switch (cookie->laddr_type) {
#ifdef INET
case SCTP_IPV4_ADDRESS:
/* source addr is IPv4 */
sin = (struct sockaddr_in *)initack_src;
memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_addr.s_addr = cookie->laddress[0];
} else if (cookie->laddr_type == SCTP_IPV6_ADDRESS) {
break;
#endif
#ifdef INET6
case SCTP_IPV6_ADDRESS:
/* source addr is IPv6 */
sin6 = (struct sockaddr_in6 *)initack_src;
memset(sin6, 0, sizeof(*sin6));
@ -2185,7 +2215,9 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sin6->sin6_scope_id = cookie->scope_id;
memcpy(&sin6->sin6_addr, cookie->laddress,
sizeof(sin6->sin6_addr));
} else {
break;
#endif
default:
atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
@ -2295,8 +2327,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
struct sctp_tcb **locked_tcb, uint32_t vrf_id, uint16_t port)
{
struct sctp_state_cookie *cookie;
struct sockaddr_in6 sin6;
struct sockaddr_in sin;
struct sctp_tcb *l_stcb = *stcb;
struct sctp_inpcb *l_inp;
struct sockaddr *to;
@ -2318,6 +2348,15 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
int had_a_existing_tcb = 0;
int send_int_conf = 0;
#ifdef INET
struct sockaddr_in sin;
#endif
#ifdef INET6
struct sockaddr_in6 sin6;
#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_cookie: handling COOKIE-ECHO\n");
@ -2327,6 +2366,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* First get the destination address setup too. */
iph = mtod(m, struct ip *);
switch (iph->ip_v) {
#ifdef INET
case IPVERSION:
{
/* its IPv4 */
@ -2341,6 +2381,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
size_of_pkt = SCTP_GET_IPV4_LENGTH(iph);
break;
}
#endif
#ifdef INET6
case IPV6_VERSION >> 4:
{
@ -2535,7 +2576,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* up.
*/
to = NULL;
if (cookie->addr_type == SCTP_IPV6_ADDRESS) {
switch (cookie->addr_type) {
#ifdef INET6
case SCTP_IPV6_ADDRESS:
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
@ -2544,14 +2587,19 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
sizeof(sin6.sin6_addr.s6_addr));
to = (struct sockaddr *)&sin6;
} else if (cookie->addr_type == SCTP_IPV4_ADDRESS) {
break;
#endif
#ifdef INET
case SCTP_IPV4_ADDRESS:
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_port = sh->src_port;
sin.sin_addr.s_addr = cookie->address[0];
to = (struct sockaddr *)&sin;
} else {
break;
#endif
default:
/* This should not happen */
return (NULL);
}
@ -5705,6 +5753,7 @@ sctp_print_mbuf_chain(struct mbuf *m)
#endif
#ifdef INET
void
sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
{
@ -6003,3 +6052,5 @@ sctp_input(struct mbuf *m, int off)
#endif
sctp_input_with_port(m, off, 0);
}
#endif

View File

@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$");
#include "opt_ipsec.h"
#include "opt_compat.h"
#include "opt_inet6.h"
#if 1
#include "opt_inet.h"
#endif
#include "opt_sctp.h"
#include <sys/param.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -155,17 +155,33 @@ number_of_addresses(struct sctp_inpcb *inp)
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->address.sa.sa_family == AF_INET) ||
(sctp_ifa->address.sa.sa_family == AF_INET6)) {
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
#endif
#ifdef INET6
case AF_INET6:
#endif
cnt++;
break;
default:
break;
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if ((laddr->ifa->address.sa.sa_family == AF_INET) ||
(laddr->ifa->address.sa.sa_family == AF_INET6)) {
switch (laddr->ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
#endif
#ifdef INET6
case AF_INET6:
#endif
cnt++;
break;
default:
break;
}
}
}
@ -233,6 +249,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
continue;
}
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
@ -246,6 +263,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
continue;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
@ -535,6 +553,8 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
#if !defined(__FreeBSD__) || defined(INET)
static int
sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
{
@ -566,6 +586,8 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
return (error);
}
#endif
static int
sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
@ -646,7 +668,10 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX);
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
#if !defined(__FreeBSD__) || defined(INET)
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX);
#endif
RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX);
@ -1083,6 +1108,8 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_R
"Clear SCTP Logging buffer");
#endif
/* XXX: Remove the #if after tunneling over IPv6 works also on FreeBSD. */
#if !defined(__FreeBSD__) || defined(INET)
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC);
@ -1090,6 +1117,7 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLT
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU",
SCTPCTL_UDP_TUNNELING_PORT_DESC);
#endif
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU",

View File

@ -150,6 +150,7 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
}
}
#ifdef INET
static void
sctp_notify_mbuf(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
@ -220,6 +221,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
SCTP_TCB_UNLOCK(stcb);
}
#endif
void
sctp_notify(struct sctp_inpcb *inp,
@ -335,6 +337,7 @@ sctp_notify(struct sctp_inpcb *inp,
}
}
#ifdef INET
void
sctp_ctlinput(cmd, sa, vip)
int cmd;
@ -404,6 +407,8 @@ sctp_ctlinput(cmd, sa, vip)
return;
}
#endif
static int
sctp_getcred(SYSCTL_HANDLER_ARGS)
{
@ -466,6 +471,7 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
#ifdef INET
static void
sctp_abort(struct socket *so)
{
@ -599,6 +605,7 @@ sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
return error;
}
#endif
void
sctp_close(struct socket *so)
{
@ -1209,6 +1216,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
}
}
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
@ -1248,6 +1256,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
continue;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
@ -1373,28 +1382,46 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
/* Count them if they are the right type */
if (sctp_ifa->address.sa.sa_family == AF_INET) {
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
} else if (sctp_ifa->address.sa.sa_family == AF_INET6)
break;
#endif
#ifdef INET6
case AF_INET6:
cnt += sizeof(struct sockaddr_in6);
break;
#endif
default:
break;
}
}
}
} else {
struct sctp_laddr *laddr;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa->address.sa.sa_family == AF_INET) {
switch (laddr->ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
} else if (laddr->ifa->address.sa.sa_family == AF_INET6)
break;
#endif
#ifdef INET6
case AF_INET6:
cnt += sizeof(struct sockaddr_in6);
break;
#endif
default:
break;
}
}
}
return (cnt);
@ -1517,10 +1544,20 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
}
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
if (sa->sa_family == AF_INET)
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
else
break;
#endif
#ifdef INET6
case AF_INET6:
sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
break;
#endif
default:
break;
}
error = 0;
added = sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
@ -2126,14 +2163,23 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
size = 0;
/* Count the sizes */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) ||
(((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
size += sizeof(struct sockaddr_in6);
} else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
size += sizeof(struct sockaddr_in);
} else {
/* huh */
break;
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
#ifdef INET
case AF_INET:
size += sizeof(struct sockaddr_in);
break;
#endif
#ifdef INET6
case AF_INET6:
size += sizeof(struct sockaddr_in6);
break;
#endif
default:
break;
}
}
}
SCTP_TCB_UNLOCK(stcb);
@ -2165,20 +2211,33 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sas = (struct sockaddr_storage *)&saddr->addr[0];
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) ||
(((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
cpsz = sizeof(struct sockaddr_in6);
} else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
cpsz = sizeof(struct sockaddr_in);
} else {
/* huh */
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
#ifdef INET
case AF_INET:
cpsz = sizeof(struct sockaddr_in);
break;
#endif
#ifdef INET6
case AF_INET6:
cpsz = sizeof(struct sockaddr_in6);
break;
#endif
default:
cpsz = 0;
break;
}
}
if (cpsz == 0) {
break;
}
if (left < cpsz) {
/* not enough room. */
break;
}
#ifdef INET6
#if defined(INET) && defined(INET6)
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
(((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
/* Must map the address */
@ -2187,7 +2246,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
} else {
#endif
memcpy(sas, &net->ro._l_addr, cpsz);
#ifdef INET6
#if defined(INET) && defined(INET6)
}
#endif
((struct sockaddr_in *)sas)->sin_port = stcb->rport;
@ -2250,6 +2309,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
struct sockaddr *sa;
sa = (struct sockaddr *)&paddrp->spp_address;
#ifdef INET
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin;
@ -2260,7 +2320,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else if (sa->sa_family == AF_INET6) {
} else
#endif
#ifdef INET6
if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
@ -2270,7 +2333,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else {
} else
#endif
{
error = EAFNOSUPPORT;
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@ -3857,7 +3922,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
struct sockaddr *sa;
sa = (struct sockaddr *)&paddrp->spp_address;
#ifdef INET
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)sa;
@ -3867,7 +3934,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
} else if (sa->sa_family == AF_INET6) {
} else
#endif
#ifdef INET6
if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
@ -3877,7 +3947,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
} else {
} else
#endif
{
error = EAFNOSUPPORT;
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@ -4305,6 +4377,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
td = (struct thread *)p;
SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
optsize);
#ifdef INET
if (addrs->addr->sa_family == AF_INET) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
if (optsize < sz) {
@ -4316,8 +4389,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else
#endif
#ifdef INET6
} else if (addrs->addr->sa_family == AF_INET6) {
if (addrs->addr->sa_family == AF_INET6) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
if (optsize < sz) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@ -4329,8 +4404,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else
#endif
} else {
{
error = EAFNOSUPPORT;
break;
}
@ -4348,6 +4424,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
td = (struct thread *)p;
SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
#ifdef INET
if (addrs->addr->sa_family == AF_INET) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
if (optsize < sz) {
@ -4359,8 +4436,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else
#endif
#ifdef INET6
} else if (addrs->addr->sa_family == AF_INET6) {
if (addrs->addr->sa_family == AF_INET6) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
if (optsize < sz) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@ -4372,8 +4451,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
} else
#endif
} else {
{
error = EAFNOSUPPORT;
break;
}
@ -4410,9 +4490,13 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
#ifdef INET6
if (INP_CHECK_SOCKAF(so, AF_INET6))
error = ip6_ctloutput(so, sopt);
else
#endif /* INET6 */
#if defined(INET) && defined (INET6)
else
#endif
#ifdef INET
error = ip_ctloutput(so, sopt);
#endif
return (error);
}
optsize = sopt->sopt_valsize;
@ -4447,7 +4531,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
return (error);
}
#ifdef INET
static int
sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
{
@ -4467,34 +4551,42 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
switch (addr->sa_family) {
#ifdef INET6
if (addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6p;
case AF_INET6:
{
struct sockaddr_in6 *sin6p;
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
sin6p = (struct sockaddr_in6 *)addr;
if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
return (error);
}
break;
}
sin6p = (struct sockaddr_in6 *)addr;
if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
return (error);
}
} else
#endif
if (addr->sa_family == AF_INET) {
struct sockaddr_in *sinp;
#ifdef INET
case AF_INET:
{
struct sockaddr_in *sinp;
if (addr->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
if (addr->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
sinp = (struct sockaddr_in *)addr;
if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
return (error);
}
break;
}
sinp = (struct sockaddr_in *)addr;
if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
return (error);
}
} else {
#endif
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
return (EAFNOSUPPORT);
}
@ -4601,6 +4693,8 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
return error;
}
#endif
int
sctp_listen(struct socket *so, int backlog, struct thread *p)
{
@ -4634,7 +4728,20 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
memcpy(&store, &laddr->ifa->address, sizeof(store));
sp->sin.sin_port = inp->sctp_lport;
switch (sp->sa.sa_family) {
#ifdef INET
case AF_INET:
sp->sin.sin_port = inp->sctp_lport;
break;
#endif
#ifdef INET6
case AF_INET6:
sp->sin6.sin6_port = inp->sctp_lport;
break;
#endif
default:
break;
}
tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
if (tinp && (tinp != inp) &&
((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
@ -4653,17 +4760,32 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
} else {
/* Setup a local addr bound all */
memset(&store, 0, sizeof(store));
store.sin.sin_port = inp->sctp_lport;
switch (sp->sa.sa_family) {
#ifdef INET
case AF_INET:
store.sin.sin_port = inp->sctp_lport;
break;
#endif
#ifdef INET6
case AF_INET6:
sp->sin6.sin6_port = inp->sctp_lport;
break;
#endif
default:
break;
}
#ifdef INET6
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
store.sa.sa_family = AF_INET6;
store.sa.sa_len = sizeof(struct sockaddr_in6);
}
#endif
#ifdef INET
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
store.sa.sa_family = AF_INET;
store.sa.sa_len = sizeof(struct sockaddr_in);
}
#endif
tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
if (tinp && (tinp != inp) &&
((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
@ -4780,6 +4902,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
SCTP_TCB_UNLOCK(stcb);
switch (store.sa.sa_family) {
#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@ -4794,6 +4917,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
*addr = (struct sockaddr *)sin;
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
@ -4855,6 +4979,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
return (0);
}
#ifdef INET
int
sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
{
@ -5015,6 +5140,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
return (0);
}
#ifdef INET
struct pr_usrreqs sctp_usrreqs = {
.pru_abort = sctp_abort,
.pru_accept = sctp_accept,
@ -5035,3 +5161,6 @@ struct pr_usrreqs sctp_usrreqs = {
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
};
#endif
#endif

View File

@ -300,8 +300,15 @@ int sctp_disconnect(struct socket *so);
void sctp_ctlinput __P((int, struct sockaddr *, void *));
int sctp_ctloutput __P((struct socket *, struct sockopt *));
#ifdef INET
void sctp_input_with_port __P((struct mbuf *, int, uint16_t));
#endif
#ifdef INET
void sctp_input __P((struct mbuf *, int));
#endif
void sctp_pathmtu_adjustment __P((struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, uint16_t));
void sctp_drain __P((void));
void sctp_init __P((void));

View File

@ -4826,6 +4826,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
continue;
if (addr->sa_family != laddr->ifa->address.sa.sa_family)
continue;
#ifdef INET
if (addr->sa_family == AF_INET) {
if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
laddr->ifa->address.sin.sin_addr.s_addr) {
@ -4837,6 +4838,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
break;
}
}
#endif
#ifdef INET6
if (addr->sa_family == AF_INET6) {
if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
@ -4924,6 +4926,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
}
if (addr->sa_family != sctp_ifap->address.sa.sa_family)
continue;
#ifdef INET
if (addr->sa_family == AF_INET) {
if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
sctp_ifap->address.sin.sin_addr.s_addr) {
@ -4934,6 +4937,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
break;
}
}
#endif
#ifdef INET6
if (addr->sa_family == AF_INET6) {
if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
@ -6729,7 +6733,7 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
struct ip *iph;
struct mbuf *sp, *last;
struct udphdr *uhdr;
uint16_t port = 0, len;
uint16_t port = 0;
int header_size = sizeof(struct udphdr) + sizeof(struct sctphdr);
/*
@ -6779,8 +6783,11 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
/* Now its ready for sctp_input or sctp6_input */
iph = mtod(m, struct ip *);
switch (iph->ip_v) {
#ifdef INET
case IPVERSION:
{
uint16_t len;
/* its IPv4 */
len = SCTP_GET_IPV4_LENGTH(iph);
len -= sizeof(struct udphdr);
@ -6788,6 +6795,7 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
sctp_input_with_port(m, off, port);
break;
}
#endif
#ifdef INET6
case IPV6_VERSION >> 4:
{

View File

@ -745,13 +745,24 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
return EINVAL;
}
if (addr) {
if ((addr->sa_family == AF_INET6) &&
(addr->sa_len != sizeof(struct sockaddr_in6))) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
if ((addr->sa_family == AF_INET) &&
(addr->sa_len != sizeof(struct sockaddr_in))) {
switch (addr->sa_family) {
#ifdef INET
case AF_INET:
if (addr->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
break;
#endif
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
@ -760,44 +771,59 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
inp6->inp_vflag &= ~INP_IPV4;
inp6->inp_vflag |= INP_IPV6;
if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
if (addr->sa_family == AF_INET) {
switch (addr->sa_family) {
#ifdef INET
case AF_INET:
/* binding v4 addr to v6 socket, so reset flags */
inp6->inp_vflag |= INP_IPV4;
inp6->inp_vflag &= ~INP_IPV6;
} else {
struct sockaddr_in6 *sin6_p;
break;
#endif
#ifdef INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6_p;
sin6_p = (struct sockaddr_in6 *)addr;
sin6_p = (struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
inp6->inp_vflag |= INP_IPV4;
} else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
struct sockaddr_in sin;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
inp6->inp_vflag |= INP_IPV4;
}
#ifdef INET
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
struct sockaddr_in sin;
in6_sin6_2_sin(&sin, sin6_p);
inp6->inp_vflag |= INP_IPV4;
inp6->inp_vflag &= ~INP_IPV6;
error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
return error;
in6_sin6_2_sin(&sin, sin6_p);
inp6->inp_vflag |= INP_IPV4;
inp6->inp_vflag &= ~INP_IPV6;
error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
return error;
}
#endif
break;
}
#endif
default:
break;
}
} else if (addr != NULL) {
struct sockaddr_in6 *sin6_p;
/* IPV6_V6ONLY socket */
#ifdef INET
if (addr->sa_family == AF_INET) {
/* can't bind v4 addr to v6 only socket! */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
} else {
struct sockaddr_in6 *sin6_p;
}
#endif
sin6_p = (struct sockaddr_in6 *)addr;
sin6_p = (struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
/* can't bind v4-mapped addrs either! */
/* NOTE: we don't support SIIT */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
/* can't bind v4-mapped addrs either! */
/* NOTE: we don't support SIIT */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
}
error = sctp_inpcb_bind(so, addr, NULL, p);
@ -950,7 +976,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sockaddr_in6 *sin6;
struct sockaddr_storage ss;
#endif /* INET */
#endif
inp6 = (struct in6pcb *)so->so_pcb;
inp = (struct sctp_inpcb *)so->so_pcb;
@ -963,14 +989,28 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
switch (addr->sa_family) {
#ifdef INET
case AF_INET:
if (addr->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
break;
#endif
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
vrf_id = inp->def_vrf_id;
SCTP_ASOC_CREATE_LOCK(inp);
SCTP_INP_RLOCK(inp);
@ -1093,7 +1133,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
/*
* Do the malloc first in case it blocks.
*/
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
if (sin6 == NULL)
return ENOMEM;
sin6->sin6_family = AF_INET6;
@ -1249,7 +1289,10 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
{
#ifdef INET
struct sockaddr *addr;
#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
@ -1259,6 +1302,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
}
/* allow v6 addresses precedence */
error = sctp6_getaddr(so, nam);
#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_ingetaddr(so, nam);
@ -1272,9 +1316,9 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
}
}
#endif
return (error);
}
@ -1282,7 +1326,10 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
static int
sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
struct sockaddr *addr = *nam;
#ifdef INET
struct sockaddr *addr;
#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
@ -1292,12 +1339,14 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
}
/* allow v6 addresses precedence */
error = sctp6_peeraddr(so, nam);
#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_peeraddr(so, nam);
if (error) {
return (error);
}
addr = *nam;
/* if I'm V6ONLY, convert it to v4-mapped */
if (SCTP_IPV6_V6ONLY(inp6)) {
struct sockaddr_in6 sin6;
@ -1306,6 +1355,7 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
}
}
#endif
return error;
}