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:
parent
79288c112c
commit
e6194c2ed4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=221249
File diff suppressed because it is too large
Load Diff
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user