summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/sctp_asconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/sctp_asconf.c')
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c92
1 files changed, 75 insertions, 17 deletions
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index 71fa307c..551f0690 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -152,7 +152,12 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
struct sctp_paramhdr *ph;
- uint16_t param_type, param_length, aparam_length;
+ uint16_t param_type, aparam_length;
+
+#if defined(INET) || defined(INET6)
+ uint16_t param_length;
+
+#endif
struct sockaddr *sa;
int zero_address = 0;
int bad_address = 0;
@@ -171,8 +176,9 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
aparam_length = ntohs(aph->ph.param_length);
ph = (struct sctp_paramhdr *)(aph + 1);
param_type = ntohs(ph->param_type);
+#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
-
+#endif
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
#ifdef INET
@@ -300,7 +306,12 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
struct sctp_paramhdr *ph;
- uint16_t param_type, param_length, aparam_length;
+ uint16_t param_type, aparam_length;
+
+#if defined(INET) || defined(INET6)
+ uint16_t param_length;
+
+#endif
struct sockaddr *sa;
int zero_address = 0;
int result;
@@ -319,8 +330,9 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
aparam_length = ntohs(aph->ph.param_length);
ph = (struct sctp_paramhdr *)(aph + 1);
param_type = ntohs(ph->param_type);
+#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
-
+#endif
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
#ifdef INET
@@ -429,7 +441,12 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
struct sctp_paramhdr *ph;
- uint16_t param_type, param_length, aparam_length;
+ uint16_t param_type, aparam_length;
+
+#if defined(INET) || defined(INET6)
+ uint16_t param_length;
+
+#endif
struct sockaddr *sa;
int zero_address = 0;
@@ -447,8 +464,9 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
aparam_length = ntohs(aph->ph.param_length);
ph = (struct sctp_paramhdr *)(aph + 1);
param_type = ntohs(ph->param_type);
+#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
-
+#endif
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
#ifdef INET
@@ -862,10 +880,12 @@ sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
static uint32_t
sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
{
+#if defined(INET) || defined(INET6)
uint16_t param_type, param_length;
param_type = ntohs(ph->param_type);
param_length = ntohs(ph->param_length);
+#endif
switch (sa->sa_family) {
#ifdef INET6
case AF_INET6:
@@ -876,7 +896,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
v6addr = (struct sctp_ipv6addr_param *)ph;
if ((param_type == SCTP_IPV6_ADDRESS) &&
- param_length == sizeof(struct sctp_ipv6addr_param) &&
+ (param_length == sizeof(struct sctp_ipv6addr_param)) &&
(memcmp(&v6addr->addr, &sin6->sin6_addr,
sizeof(struct in6_addr)) == 0)) {
return (1);
@@ -892,7 +912,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
v4addr = (struct sctp_ipv4addr_param *)ph;
if ((param_type == SCTP_IPV4_ADDRESS) &&
- param_length == sizeof(struct sctp_ipv4addr_param) &&
+ (param_length == sizeof(struct sctp_ipv4addr_param)) &&
(memcmp(&v4addr->addr, &sin->sin_addr,
sizeof(struct in_addr)) == 0)) {
return (1);
@@ -1193,7 +1213,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
uint16_t type)
{
struct sctp_asconf_addr *aa, *aa_next;
- struct sockaddr *sa;
/* make sure the request isn't already in the queue */
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
@@ -1257,7 +1276,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
- sa = (struct sockaddr *)sin6;
aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
@@ -1273,7 +1291,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&ifa->address.sa;
- sa = (struct sockaddr *)sin;
aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
@@ -1296,13 +1313,13 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
if (type == SCTP_ADD_IP_ADDRESS) {
SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
} else if (type == SCTP_DEL_IP_ADDRESS) {
SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
} else {
SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
}
}
#endif
@@ -1874,14 +1891,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:
@@ -2107,6 +2132,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;
@@ -2137,6 +2166,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;
@@ -2450,6 +2483,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;
@@ -2483,6 +2520,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;
@@ -2601,7 +2642,8 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
/* get the parameter length */
p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
/* will it fit in current chunk? */
- if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
+ if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) ||
+ (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) {
/* won't fit, so we're done with this chunk */
break;
}
@@ -2722,7 +2764,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
/* chain it all together */
SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
- acp->ch.chunk_length = ntohs(*retlen);
+ acp->ch.chunk_length = htons(*retlen);
return (m_asconf_chk);
}
@@ -3096,6 +3138,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 */
@@ -3106,6 +3152,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;
@@ -3391,6 +3441,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;
}
@@ -3402,6 +3456,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;
}