Honor jails for unbound SCTP sockets when selecting source addresses,
reporting IP-addresses to the peer during the handshake, adding addresses to the host, reporting the addresses via the sysctl interface (used by netstat, for example) and reporting the addresses to the application via socket options. This issue was reported by Bernd Walter. MFC after: 3 days
This commit is contained in:
parent
cef789cd61
commit
6ba22f19ca
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267674
@ -1889,14 +1889,22 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
* this is boundall or subset bound w/ASCONF allowed
|
||||
*/
|
||||
|
||||
/* first, make sure it's a good address family */
|
||||
/* first, make sure that the address is IPv4 or IPv6 and not jailed */
|
||||
switch (ifa->address.sa.sa_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin6.sin6_addr) != 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin.sin_addr) != 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@ -2122,6 +2130,10 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
/* we skip unspecifed addresses */
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
if (stcb->asoc.scope.local_scope == 0) {
|
||||
continue;
|
||||
@ -2152,6 +2164,10 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
/* we skip unspecifed addresses */
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (stcb->asoc.scope.ipv4_local_scope == 0 &&
|
||||
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
|
||||
continue;
|
||||
@ -2465,6 +2481,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
|
||||
/* skip unspecifed addresses */
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (stcb->asoc.scope.ipv4_local_scope == 0 &&
|
||||
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
|
||||
continue;
|
||||
@ -2498,6 +2518,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (stcb->asoc.scope.local_scope == 0 &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
|
||||
continue;
|
||||
@ -3112,6 +3136,10 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
|
||||
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if ((ipv4_scope == 0) &&
|
||||
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
|
||||
/* private address not in scope */
|
||||
@ -3122,6 +3150,10 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
|
||||
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if ((local_scope == 0) &&
|
||||
(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
|
||||
continue;
|
||||
@ -3407,6 +3439,10 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
to = &sctp_ifap->address.sin;
|
||||
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&to->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
|
||||
continue;
|
||||
}
|
||||
@ -3418,6 +3454,10 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
to6 = &sctp_ifap->address.sin6;
|
||||
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&to6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -2060,6 +2060,20 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
continue;
|
||||
}
|
||||
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifap->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifap->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifap->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifap->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
|
||||
continue;
|
||||
}
|
||||
@ -2089,6 +2103,20 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
continue;
|
||||
}
|
||||
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifap->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifap->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifap->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifap->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
|
||||
continue;
|
||||
}
|
||||
@ -2453,6 +2481,20 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
|
||||
if (sctp_ifn) {
|
||||
/* is a preferred one on the interface we route out? */
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
@ -2576,6 +2618,20 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
if (sctp_ifn) {
|
||||
/* first try for a preferred address on the ep */
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
|
||||
@ -2596,6 +2652,20 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
}
|
||||
/* next try for an acceptable address on the ep */
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
|
||||
@ -2700,6 +2770,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
|
||||
static struct sctp_ifa *
|
||||
sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
struct sctp_inpcb *inp,
|
||||
struct sctp_tcb *stcb,
|
||||
int non_asoc_addr_ok,
|
||||
uint8_t dest_is_loop,
|
||||
@ -2721,6 +2792,20 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
}
|
||||
#endif /* INET6 */
|
||||
LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
@ -2806,6 +2891,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
|
||||
static int
|
||||
sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
|
||||
struct sctp_inpcb *inp,
|
||||
struct sctp_tcb *stcb,
|
||||
int non_asoc_addr_ok,
|
||||
uint8_t dest_is_loop,
|
||||
@ -2816,6 +2902,21 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
|
||||
int num_eligible_addr = 0;
|
||||
|
||||
LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(stcb != NULL) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0)) {
|
||||
continue;
|
||||
@ -2847,7 +2948,8 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
|
||||
}
|
||||
|
||||
static struct sctp_ifa *
|
||||
sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net,
|
||||
sctp_route_t * ro,
|
||||
uint32_t vrf_id,
|
||||
@ -2902,7 +3004,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
cur_addr_num = net->indx_of_eligible_next_to_use;
|
||||
}
|
||||
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn,
|
||||
stcb,
|
||||
inp, stcb,
|
||||
non_asoc_addr_ok,
|
||||
dest_is_loop,
|
||||
dest_is_priv, fam);
|
||||
@ -2929,7 +3031,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
*/
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "cur_addr_num:%d\n", cur_addr_num);
|
||||
|
||||
sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
dest_is_priv, cur_addr_num, fam, ro);
|
||||
|
||||
/* if sctp_ifa is NULL something changed??, fall to plan b. */
|
||||
@ -2960,7 +3062,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "already seen\n");
|
||||
continue;
|
||||
}
|
||||
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok,
|
||||
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok,
|
||||
dest_is_loop, dest_is_priv, fam);
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2,
|
||||
"Found ifn:%p %d preferred source addresses\n",
|
||||
@ -2982,7 +3084,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
if (cur_addr_num >= num_preferred) {
|
||||
cur_addr_num = 0;
|
||||
}
|
||||
sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
dest_is_priv, cur_addr_num, fam, ro);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
@ -3010,6 +3112,22 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
}
|
||||
LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifa:%p\n", (void *)sctp_ifa);
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Defer\n");
|
||||
@ -3060,6 +3178,20 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
continue;
|
||||
}
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
@ -3110,6 +3242,20 @@ sctp_choose_boundall(struct sctp_tcb *stcb,
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
struct sctp_ifa *tmp_sifa;
|
||||
|
||||
#ifdef INET
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
|
||||
(prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin.sin_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
|
||||
(prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sctp_ifa->address.sin6.sin6_addr) != 0)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
@ -3295,7 +3441,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
|
||||
/*
|
||||
* Bound all case
|
||||
*/
|
||||
answer = sctp_choose_boundall(stcb, net, ro, vrf_id,
|
||||
answer = sctp_choose_boundall(inp, stcb, net, ro, vrf_id,
|
||||
dest_is_priv, dest_is_loop,
|
||||
non_asoc_addr_ok, fam);
|
||||
SCTP_IPI_ADDR_RUNLOCK();
|
||||
|
@ -898,6 +898,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
|
||||
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
|
||||
SCTP_IPI_ADDR_RUNLOCK();
|
||||
return (1);
|
||||
@ -913,6 +917,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
|
||||
|
||||
sin6 = &sctp_ifa->address.sin6;
|
||||
rsin6 = (struct sockaddr_in6 *)to;
|
||||
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
if (local_scope == 0)
|
||||
continue;
|
||||
@ -1060,6 +1068,39 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
switch (to->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)to;
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)to;
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
if (inp->def_vrf_id != vrf_id) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
@ -1628,23 +1669,45 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) &&
|
||||
(inp->sctp_lport == lport)) {
|
||||
/* got it */
|
||||
switch (nam->sa_family) {
|
||||
#ifdef INET
|
||||
if ((nam->sa_family == AF_INET) &&
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
SCTP_IPV6_V6ONLY(inp)) {
|
||||
/* IPv4 on a IPv6 socket with ONLY IPv6 set */
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
case AF_INET:
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
SCTP_IPV6_V6ONLY(inp)) {
|
||||
/*
|
||||
* IPv4 on a IPv6 socket with ONLY
|
||||
* IPv6 set
|
||||
*/
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#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;
|
||||
}
|
||||
case AF_INET6:
|
||||
/*
|
||||
* A V6 address and the endpoint is NOT
|
||||
* bound V6
|
||||
*/
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* does a VRF id match? */
|
||||
fnd = 0;
|
||||
if (inp->def_vrf_id == vrf_id)
|
||||
@ -2403,6 +2466,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
/* setup socket pointers */
|
||||
inp->sctp_socket = so;
|
||||
inp->ip_inp.inp.inp_socket = so;
|
||||
inp->ip_inp.inp.inp_cred = crhold(so->so_cred);
|
||||
#ifdef INET6
|
||||
if (INP_SOCKAF(so) == AF_INET6) {
|
||||
if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
|
||||
@ -2421,6 +2485,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
/* init the small hash table we use to track asocid <-> tcb */
|
||||
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
|
||||
if (inp->sctp_asocidhash == NULL) {
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
return (ENOBUFS);
|
||||
@ -2435,6 +2500,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp;
|
||||
}
|
||||
if (error != 0) {
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
return error;
|
||||
@ -2465,6 +2531,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
*/
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
|
||||
so->so_pcb = NULL;
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
@ -2484,6 +2551,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n");
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
|
||||
so->so_pcb = NULL;
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
@ -3630,6 +3698,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
|
||||
inp->sctp_tcbhash = NULL;
|
||||
}
|
||||
/* Now we must put the ep memory back into the zone pool */
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
INP_LOCK_DESTROY(&inp->ip_inp.inp);
|
||||
SCTP_INP_LOCK_DESTROY(inp);
|
||||
SCTP_INP_READ_DESTROY(inp);
|
||||
|
@ -252,6 +252,10 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
|
||||
sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
|
||||
if (sin->sin_addr.s_addr == 0)
|
||||
continue;
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)))
|
||||
continue;
|
||||
} else {
|
||||
@ -267,6 +271,10 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
|
||||
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
|
||||
continue;
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
if (local_scope == 0)
|
||||
continue;
|
||||
|
@ -1197,6 +1197,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if ((ipv4_local_scope == 0) &&
|
||||
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
|
||||
continue;
|
||||
@ -1238,6 +1242,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
if (local_scope == 0)
|
||||
continue;
|
||||
@ -5239,6 +5247,43 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
error = EINVAL;
|
||||
goto out_of_it;
|
||||
}
|
||||
} else {
|
||||
switch (sspp->sspp_addr.ss_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)&sspp->sspp_addr;
|
||||
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
goto out_of_it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
|
||||
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
goto out_of_it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
goto out_of_it;
|
||||
}
|
||||
}
|
||||
if (sctp_set_primary_ip_address_sa(stcb,
|
||||
(struct sockaddr *)&sspp->sspp_addr) != 0) {
|
||||
|
@ -6693,6 +6693,10 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin->sin_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if ((ipv4_local_scope == 0) &&
|
||||
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
|
||||
continue;
|
||||
@ -6713,6 +6717,10 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
continue;
|
||||
}
|
||||
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
|
||||
&sin6->sin6_addr) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
if (local_scope == 0)
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user