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
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 */
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
|
||||
continue;
|
||||
}
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
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) {
|
||||
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,21 +339,27 @@ 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 */
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
|
||||
return;
|
||||
}
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
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) {
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* non inet/inet6 skip */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sctp_is_desired_interface_type(ifa) == 0) {
|
||||
/* non desired type */
|
||||
|
@ -530,29 +530,43 @@ 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)) {
|
||||
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 if (cp->heartbeat.hb_info.addr_family == AF_INET6 &&
|
||||
cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
|
||||
} 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;
|
||||
@ -561,7 +575,12 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
r_net = sctp_findnet(stcb, (struct sockaddr *)sin);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
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
@ -426,10 +426,20 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap)
|
||||
/* update address counts */
|
||||
sctp_ifnp->ifa_count++;
|
||||
ifa_af = sctp_ifap->address.sa.sa_family;
|
||||
if (ifa_af == AF_INET)
|
||||
switch (ifa_af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sctp_ifnp->num_v4++;
|
||||
else
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sctp_ifnp->num_v6++;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (sctp_ifnp->ifa_count == 1) {
|
||||
/* register the new interface */
|
||||
SCTP_REGISTER_INTERFACE(sctp_ifnp->ifn_index, ifa_af);
|
||||
@ -452,10 +462,20 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap)
|
||||
if (sctp_ifap->ifn_p) {
|
||||
/* update address counts */
|
||||
sctp_ifap->ifn_p->ifa_count--;
|
||||
if (sctp_ifap->address.sa.sa_family == AF_INET6)
|
||||
sctp_ifap->ifn_p->num_v6--;
|
||||
else if (sctp_ifap->address.sa.sa_family == AF_INET)
|
||||
switch (sctp_ifap->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sctp_ifap->ifn_p->num_v4--;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sctp_ifap->ifn_p->num_v6--;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ifn_index = sctp_ifap->ifn_p->ifn_index;
|
||||
if (LIST_EMPTY(&sctp_ifap->ifn_p->ifalist)) {
|
||||
@ -613,6 +633,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
|
||||
sctp_ifap->flags = ifa_flags;
|
||||
/* Set scope */
|
||||
switch (sctp_ifap->address.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
@ -630,6 +651,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
|
||||
new_ifn_af = AF_INET;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
@ -846,14 +868,29 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
if ((to == NULL) || (from == NULL)) {
|
||||
return (NULL);
|
||||
}
|
||||
if (to->sa_family == AF_INET && from->sa_family == AF_INET) {
|
||||
switch (to->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (from->sa_family == AF_INET) {
|
||||
lport = ((struct sockaddr_in *)to)->sin_port;
|
||||
rport = ((struct sockaddr_in *)from)->sin_port;
|
||||
} else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
|
||||
} else {
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (from->sa_family == AF_INET6) {
|
||||
lport = ((struct sockaddr_in6 *)to)->sin6_port;
|
||||
rport = ((struct sockaddr_in6 *)from)->sin6_port;
|
||||
} else {
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))];
|
||||
/*
|
||||
@ -894,17 +931,21 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
if (laddr->ifa->address.sa.sa_family ==
|
||||
to->sa_family) {
|
||||
/* see if it matches */
|
||||
struct sockaddr_in *intf_addr, *sin;
|
||||
|
||||
#ifdef INET
|
||||
if (from->sa_family == AF_INET) {
|
||||
struct sockaddr_in *intf_addr,
|
||||
*sin;
|
||||
|
||||
intf_addr = &laddr->ifa->address.sin;
|
||||
sin = (struct sockaddr_in *)to;
|
||||
if (from->sa_family == AF_INET) {
|
||||
if (sin->sin_addr.s_addr ==
|
||||
intf_addr->sin_addr.s_addr) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (from->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *intf_addr6;
|
||||
@ -959,6 +1000,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
continue;
|
||||
}
|
||||
switch (from->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin, *rsin;
|
||||
@ -981,6 +1023,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
@ -1256,6 +1299,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
|
||||
continue;
|
||||
}
|
||||
switch (remote->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin,
|
||||
@ -1284,6 +1328,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
@ -1357,6 +1402,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
|
||||
continue;
|
||||
}
|
||||
switch (remote->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin,
|
||||
@ -1385,6 +1431,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
@ -1505,15 +1552,14 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
uint16_t lport, uint32_t vrf_id)
|
||||
{
|
||||
struct sctp_inpcb *inp;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
struct sctp_laddr *laddr;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_in6 *intf_addr6;
|
||||
|
||||
#endif
|
||||
@ -1523,14 +1569,18 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
/*
|
||||
* Endpoint probe expects that the INP_INFO is locked.
|
||||
*/
|
||||
#ifdef INET
|
||||
sin = NULL;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
sin6 = NULL;
|
||||
#endif
|
||||
switch (nam->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)nam;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)nam;
|
||||
@ -1553,6 +1603,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) &&
|
||||
(inp->sctp_lport == lport)) {
|
||||
/* got it */
|
||||
#ifdef INET
|
||||
if ((nam->sa_family == AF_INET) &&
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
SCTP_IPV6_V6ONLY(inp)) {
|
||||
@ -1560,12 +1611,15 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
/* A V6 address and the endpoint is NOT bound V6 */
|
||||
if (nam->sa_family == AF_INET6 &&
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* does a VRF id match? */
|
||||
fnd = 0;
|
||||
if (inp->def_vrf_id == vrf_id)
|
||||
@ -1578,18 +1632,26 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
}
|
||||
if ((nam->sa_family == AF_INET) &&
|
||||
(sin->sin_addr.s_addr == INADDR_ANY)) {
|
||||
/* Can't hunt for one that has no address specified */
|
||||
return (NULL);
|
||||
}
|
||||
#ifdef INET6
|
||||
if ((nam->sa_family == AF_INET6) &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
|
||||
switch (nam->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (sin->sin_addr.s_addr == INADDR_ANY) {
|
||||
/* Can't hunt for one that has no address specified */
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
/* Can't hunt for one that has no address specified */
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* ok, not bound to all so see if we can find a EP bound to this
|
||||
* address.
|
||||
@ -1635,17 +1697,16 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
}
|
||||
if (laddr->ifa->address.sa.sa_family == nam->sa_family) {
|
||||
/* possible, see if it matches */
|
||||
struct sockaddr_in *intf_addr;
|
||||
|
||||
intf_addr = &laddr->ifa->address.sin;
|
||||
switch (nam->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (sin->sin_addr.s_addr ==
|
||||
intf_addr->sin_addr.s_addr) {
|
||||
laddr->ifa->address.sin.sin_addr.s_addr) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
return (inp);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
intf_addr6 = &laddr->ifa->address.sin6;
|
||||
@ -1774,19 +1835,32 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock,
|
||||
*/
|
||||
struct sctp_inpcb *inp;
|
||||
struct sctppcbhead *head;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
int lport;
|
||||
unsigned int i;
|
||||
|
||||
if (nam->sa_family == AF_INET) {
|
||||
#ifdef INET
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
|
||||
switch (nam->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)nam;
|
||||
lport = ((struct sockaddr_in *)nam)->sin_port;
|
||||
} else if (nam->sa_family == AF_INET6) {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)nam;
|
||||
lport = ((struct sockaddr_in6 *)nam)->sin6_port;
|
||||
} else {
|
||||
/* unsupported family */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
@ -1893,20 +1967,31 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
|
||||
struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp,
|
||||
struct sockaddr *dest)
|
||||
{
|
||||
struct sockaddr_in sin4;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sctp_paramhdr *phdr, parm_buf;
|
||||
struct sctp_tcb *retval;
|
||||
uint32_t ptype, plen;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin4;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
memset(&sin4, 0, sizeof(sin4));
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin4.sin_len = sizeof(sin4);
|
||||
sin4.sin_family = AF_INET;
|
||||
sin4.sin_port = sh->src_port;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = sh->src_port;
|
||||
#endif
|
||||
|
||||
retval = NULL;
|
||||
offset += sizeof(struct sctp_init_chunk);
|
||||
@ -1919,6 +2004,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
|
||||
if (plen == 0) {
|
||||
break;
|
||||
}
|
||||
#ifdef INET
|
||||
if (ptype == SCTP_IPV4_ADDRESS &&
|
||||
plen == sizeof(struct sctp_ipv4addr_param)) {
|
||||
/* Get the rest of the address */
|
||||
@ -1937,7 +2023,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
|
||||
if (retval != NULL) {
|
||||
return (retval);
|
||||
}
|
||||
} else if (ptype == SCTP_IPV6_ADDRESS &&
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (ptype == SCTP_IPV6_ADDRESS &&
|
||||
plen == sizeof(struct sctp_ipv6addr_param)) {
|
||||
/* Get the rest of the address */
|
||||
struct sctp_ipv6addr_param ip6_parm, *p6;
|
||||
@ -1956,6 +2045,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
|
||||
return (retval);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
offset += SCTP_SIZE32(plen);
|
||||
phdr = sctp_get_next_param(m, offset, &parm_buf,
|
||||
sizeof(parm_buf));
|
||||
@ -2082,6 +2172,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
|
||||
|
||||
iph = mtod(m, struct ip *);
|
||||
switch (iph->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
{
|
||||
/* its IPv4 */
|
||||
@ -2095,6 +2186,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
|
||||
from4->sin_port = sh->src_port;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
{
|
||||
@ -2123,6 +2215,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
|
||||
|
||||
|
||||
switch (iph->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
{
|
||||
/* its IPv4 */
|
||||
@ -2136,6 +2229,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
|
||||
to4->sin_port = sh->dest_port;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
{
|
||||
@ -2224,24 +2318,22 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
|
||||
struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
|
||||
{
|
||||
struct sctp_tcb *stcb;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
struct sockaddr_storage local_store, remote_store;
|
||||
struct sockaddr *to;
|
||||
struct ip *iph;
|
||||
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
|
||||
#endif
|
||||
struct sctp_paramhdr parm_buf, *phdr;
|
||||
int ptype;
|
||||
int zero_address = 0;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
|
||||
memset(&local_store, 0, sizeof(local_store));
|
||||
memset(&remote_store, 0, sizeof(remote_store));
|
||||
@ -2249,6 +2341,7 @@ sctp_findassociation_ep_asconf(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 */
|
||||
sin = (struct sockaddr_in *)&local_store;
|
||||
@ -2257,6 +2350,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
|
||||
sin->sin_port = sh->dest_port;
|
||||
sin->sin_addr.s_addr = iph->ip_dst.s_addr;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
/* its IPv6 */
|
||||
@ -2309,6 +2403,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET
|
||||
case SCTP_IPV4_ADDRESS:
|
||||
{
|
||||
/* ipv4 address param */
|
||||
@ -2334,6 +2429,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
|
||||
zero_address = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* invalid address param type */
|
||||
return NULL;
|
||||
@ -2733,6 +2829,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
#endif
|
||||
if (addr != NULL) {
|
||||
switch (addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
@ -2762,6 +2859,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
@ -3033,18 +3131,27 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
struct sockaddr_storage store_sa;
|
||||
|
||||
memset(&store_sa, 0, sizeof(store_sa));
|
||||
if (addr->sa_family == AF_INET) {
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)&store_sa;
|
||||
memcpy(sin, addr, sizeof(struct sockaddr_in));
|
||||
sin->sin_port = 0;
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
break;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&store_sa;
|
||||
memcpy(sin6, addr, sizeof(struct sockaddr_in6));
|
||||
sin6->sin6_port = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* first find the interface with the bound address need to
|
||||
@ -3069,6 +3176,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL);
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
#ifdef INET6
|
||||
if (addr->sa_family == AF_INET6) {
|
||||
/* GAK, more FIXME IFA lock? */
|
||||
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
|
||||
@ -3079,6 +3187,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* we're not bound all */
|
||||
inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL;
|
||||
/* allow bindx() to send ASCONF's for binding changes */
|
||||
@ -3612,10 +3721,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
|
||||
(void)sctp_m_free(ip_pcb->inp_options);
|
||||
ip_pcb->inp_options = 0;
|
||||
}
|
||||
#ifdef INET
|
||||
if (ip_pcb->inp_moptions) {
|
||||
inp_freemoptions(ip_pcb->inp_moptions);
|
||||
ip_pcb->inp_moptions = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
if (ip_pcb->inp_vflag & INP_IPV6) {
|
||||
struct in6pcb *in6p;
|
||||
@ -3740,7 +3852,10 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
return (0);
|
||||
}
|
||||
addr_inscope = 1;
|
||||
if (newaddr->sa_family == AF_INET) {
|
||||
switch (newaddr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)newaddr;
|
||||
@ -3768,8 +3883,12 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
addr_inscope = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
} else if (newaddr->sa_family == AF_INET6) {
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)newaddr;
|
||||
@ -3787,19 +3906,22 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
stcb->asoc.site_scope = 1;
|
||||
} else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
/*
|
||||
* If the new destination is a LINK_LOCAL we
|
||||
* must have common site scope. Don't set
|
||||
* the local scope since we may not share
|
||||
* all links, only loopback can do this.
|
||||
* Links on the local network would also be
|
||||
* on our private network for v4 too.
|
||||
* If the new destination is a
|
||||
* LINK_LOCAL we must have common
|
||||
* site scope. Don't set the local
|
||||
* scope since we may not share all
|
||||
* links, only loopback can do this.
|
||||
* Links on the local network would
|
||||
* also be on our private network
|
||||
* for v4 too.
|
||||
*/
|
||||
stcb->asoc.ipv4_local_scope = 1;
|
||||
stcb->asoc.site_scope = 1;
|
||||
} else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
|
||||
/*
|
||||
* If the new destination is SITE_LOCAL then
|
||||
* we must have site scope in common.
|
||||
* If the new destination is
|
||||
* SITE_LOCAL then we must have site
|
||||
* scope in common.
|
||||
*/
|
||||
stcb->asoc.site_scope = 1;
|
||||
}
|
||||
@ -3816,8 +3938,10 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
addr_inscope = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
default:
|
||||
/* not supported family type */
|
||||
return (-1);
|
||||
}
|
||||
@ -3829,10 +3953,19 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
bzero(net, sizeof(*net));
|
||||
(void)SCTP_GETTIME_TIMEVAL(&net->start_time);
|
||||
memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
|
||||
if (newaddr->sa_family == AF_INET) {
|
||||
switch (newaddr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport;
|
||||
} else if (newaddr->sa_family == AF_INET6) {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id);
|
||||
if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) {
|
||||
@ -4136,13 +4269,30 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
#ifdef SCTP_DEBUG
|
||||
if (firstaddr) {
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_PCB3, firstaddr);
|
||||
switch (firstaddr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n",
|
||||
ntohs(((struct sockaddr_in *)firstaddr)->sin_port));
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n",
|
||||
ntohs(((struct sockaddr_in6 *)firstaddr)->sin6_port));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SCTPDBG(SCTP_DEBUG_PCB3, "None\n");
|
||||
}
|
||||
#endif /* SCTP_DEBUG */
|
||||
if (firstaddr->sa_family == AF_INET) {
|
||||
switch (firstaddr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)firstaddr;
|
||||
@ -4154,7 +4304,12 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
return (NULL);
|
||||
}
|
||||
rport = sin->sin_port;
|
||||
} else if (firstaddr->sa_family == AF_INET6) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)firstaddr;
|
||||
@ -4167,7 +4322,10 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
return (NULL);
|
||||
}
|
||||
rport = sin6->sin6_port;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* not supported family type */
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
|
||||
@ -5135,13 +5293,17 @@ sctp_destination_is_reachable(struct sctp_tcb *stcb, struct sockaddr *destaddr)
|
||||
return (1);
|
||||
}
|
||||
/* NOTE: all "scope" checks are done when local addresses are added */
|
||||
if (destaddr->sa_family == AF_INET6) {
|
||||
switch (destaddr->sa_family) {
|
||||
case AF_INET6:
|
||||
answer = inp->ip_inp.inp.inp_vflag & INP_IPV6;
|
||||
} else if (destaddr->sa_family == AF_INET) {
|
||||
break;
|
||||
case AF_INET:
|
||||
answer = inp->ip_inp.inp.inp_vflag & INP_IPV4;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
/* invalid family, so it's unreachable */
|
||||
answer = 0;
|
||||
break;
|
||||
}
|
||||
return (answer);
|
||||
}
|
||||
@ -5166,10 +5328,19 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp)
|
||||
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
|
||||
continue;
|
||||
}
|
||||
if (laddr->ifa->address.sa.sa_family == AF_INET6) {
|
||||
switch (laddr->ifa->address.sa.sa_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
inp->ip_inp.inp.inp_vflag |= INP_IPV6;
|
||||
} else if (laddr->ifa->address.sa.sa_family == AF_INET) {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
inp->ip_inp.inp.inp_vflag |= INP_IPV4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5190,12 +5361,14 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
|
||||
/* You are already bound to all. You have it already */
|
||||
return;
|
||||
}
|
||||
#ifdef INET6
|
||||
if (ifa->address.sa.sa_family == AF_INET6) {
|
||||
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
|
||||
/* Can't bind a non-useable addr. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* first, is it already present? */
|
||||
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
|
||||
if (laddr->ifa == ifa) {
|
||||
@ -5211,10 +5384,19 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
|
||||
return;
|
||||
inp->laddr_count++;
|
||||
/* update inp_vflag flags */
|
||||
if (ifa->address.sa.sa_family == AF_INET6) {
|
||||
switch (ifa->address.sa.sa_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
inp->ip_inp.inp.inp_vflag |= INP_IPV6;
|
||||
} else if (ifa->address.sa.sa_family == AF_INET) {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET:
|
||||
inp->ip_inp.inp.inp_vflag |= INP_IPV4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -5343,12 +5525,14 @@ sctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
|
||||
list = &stcb->asoc.sctp_restricted_addrs;
|
||||
|
||||
inp = stcb->sctp_ep;
|
||||
#ifdef INET6
|
||||
if (ifa->address.sa.sa_family == AF_INET6) {
|
||||
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
|
||||
/* Can't bind a non-existent addr. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* does the address already exist? */
|
||||
LIST_FOREACH(laddr, list, sctp_nxt_addr) {
|
||||
if (laddr->ifa == ifa) {
|
||||
@ -5906,8 +6090,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr_storage dest_store;
|
||||
struct sockaddr *local_sa = (struct sockaddr *)&dest_store;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
|
||||
struct sctp_auth_random *p_random = NULL;
|
||||
uint16_t random_len = 0;
|
||||
@ -5924,20 +6106,32 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
int got_random = 0, got_hmacs = 0, got_chklist = 0;
|
||||
uint8_t ecn_allowed;
|
||||
|
||||
/* First get the destination address setup too. */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
#endif
|
||||
|
||||
/* First get the destination address setup too. */
|
||||
#ifdef INET
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_port = stcb->rport;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_port = stcb->rport;
|
||||
#endif
|
||||
if (altsa == NULL) {
|
||||
iph = mtod(m, struct ip *);
|
||||
switch (iph->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
{
|
||||
/* its IPv4 */
|
||||
@ -5953,6 +6147,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sa = (struct sockaddr *)&sin;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case IPV6_VERSION >> 4:
|
||||
{
|
||||
@ -5998,17 +6193,28 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || inp == NULL) {
|
||||
/* we must add the source address */
|
||||
/* no scope set here since we have a tcb already. */
|
||||
if ((sa->sa_family == AF_INET) &&
|
||||
(stcb->asoc.ipv4_addr_legal)) {
|
||||
switch (sa->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (stcb->asoc.ipv4_addr_legal) {
|
||||
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
|
||||
return (-1);
|
||||
}
|
||||
} else if ((sa->sa_family == AF_INET6) &&
|
||||
(stcb->asoc.ipv6_addr_legal)) {
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (stcb->asoc.ipv6_addr_legal) {
|
||||
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
|
||||
return (-2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (net_tmp != NULL && stcb_tmp == stcb) {
|
||||
net_tmp->dest_state &= ~SCTP_ADDR_NOT_IN_ASSOC;
|
||||
@ -6044,6 +6250,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
if (plen == 0) {
|
||||
break;
|
||||
}
|
||||
#ifdef INET
|
||||
if (ptype == SCTP_IPV4_ADDRESS) {
|
||||
if (stcb->asoc.ipv4_addr_legal) {
|
||||
struct sctp_ipv4addr_param *p4, p4_buf;
|
||||
@ -6127,7 +6334,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
return (-13);
|
||||
}
|
||||
}
|
||||
} else if (ptype == SCTP_IPV6_ADDRESS) {
|
||||
} else
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (ptype == SCTP_IPV6_ADDRESS) {
|
||||
if (stcb->asoc.ipv6_addr_legal) {
|
||||
/* ok get the v6 address and check/add */
|
||||
struct sctp_ipv6addr_param *p6, p6_buf;
|
||||
@ -6215,7 +6425,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
return (-22);
|
||||
}
|
||||
}
|
||||
} else if (ptype == SCTP_ECN_CAPABLE) {
|
||||
} else
|
||||
#endif
|
||||
if (ptype == SCTP_ECN_CAPABLE) {
|
||||
ecn_allowed = 1;
|
||||
} else if (ptype == SCTP_ULP_ADAPTATION) {
|
||||
if (stcb->asoc.state != SCTP_STATE_OPEN) {
|
||||
@ -6232,10 +6444,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
}
|
||||
} else if (ptype == SCTP_SET_PRIM_ADDR) {
|
||||
struct sctp_asconf_addr_param lstore, *fee;
|
||||
struct sctp_asconf_addrv4_param *fii;
|
||||
int lptype;
|
||||
struct sockaddr *lsa = NULL;
|
||||
|
||||
#ifdef INET
|
||||
struct sctp_asconf_addrv4_param *fii;
|
||||
|
||||
#endif
|
||||
|
||||
stcb->asoc.peer_supports_asconf = 1;
|
||||
if (plen > sizeof(lstore)) {
|
||||
return (-23);
|
||||
@ -6248,7 +6464,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
}
|
||||
fee = (struct sctp_asconf_addr_param *)phdr;
|
||||
lptype = ntohs(fee->addrp.ph.param_type);
|
||||
if (lptype == SCTP_IPV4_ADDRESS) {
|
||||
switch (lptype) {
|
||||
#ifdef INET
|
||||
case SCTP_IPV4_ADDRESS:
|
||||
if (plen !=
|
||||
sizeof(struct sctp_asconf_addrv4_param)) {
|
||||
SCTP_PRINTF("Sizeof setprim in init/init ack not %d but %d - ignored\n",
|
||||
@ -6259,7 +6477,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sin.sin_addr.s_addr = fii->addrp.addr;
|
||||
lsa = (struct sockaddr *)&sin;
|
||||
}
|
||||
} else if (lptype == SCTP_IPV6_ADDRESS) {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case SCTP_IPV6_ADDRESS:
|
||||
if (plen !=
|
||||
sizeof(struct sctp_asconf_addr_param)) {
|
||||
SCTP_PRINTF("Sizeof setprim (v6) in init/init ack not %d but %d - ignored\n",
|
||||
@ -6271,6 +6492,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sizeof(fee->addrp.addr));
|
||||
lsa = (struct sockaddr *)&sin6;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (lsa) {
|
||||
(void)sctp_set_primary_addr(stcb, sa, NULL);
|
||||
|
@ -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 */
|
||||
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,8 +4551,10 @@ 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) {
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6p;
|
||||
|
||||
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
|
||||
@ -4480,9 +4566,12 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
return (error);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (addr->sa_family == AF_INET) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sinp;
|
||||
|
||||
if (addr->sa_len != sizeof(struct sockaddr_in)) {
|
||||
@ -4494,7 +4583,10 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
|
||||
return (error);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
#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));
|
||||
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));
|
||||
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))) {
|
||||
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;
|
||||
}
|
||||
if ((addr->sa_family == AF_INET) &&
|
||||
(addr->sa_len != sizeof(struct sockaddr_in))) {
|
||||
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,18 +771,26 @@ 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 {
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6_p;
|
||||
|
||||
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)) {
|
||||
}
|
||||
#ifdef INET
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
in6_sin6_2_sin(&sin, sin6_p);
|
||||
@ -780,16 +799,24 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
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;
|
||||
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
|
||||
@ -799,7 +826,6 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
error = sctp_inpcb_bind(so, addr, NULL, p);
|
||||
return error;
|
||||
}
|
||||
@ -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))) {
|
||||
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);
|
||||
}
|
||||
if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
|
||||
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