summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2013-02-10 19:57:19 +0000
committertuexen <tuexen@FreeBSD.org>2013-02-10 19:57:19 +0000
commit6e3d604447905a0a85c64afe8b442f3a3590e930 (patch)
tree4b2b5266e898220d7867870ad5480051097a24d4
parent1d9f9f37f8fee7e4d32feb20fde8706619e29f93 (diff)
downloadFreeBSD-src-6e3d604447905a0a85c64afe8b442f3a3590e930.zip
FreeBSD-src-6e3d604447905a0a85c64afe8b442f3a3590e930.tar.gz
Make sure that received packets for removed addresses are handled
consistently. While there, make variable names consistent. MFC after: 3 days
-rw-r--r--sys/netinet/sctp_pcb.c372
1 files changed, 192 insertions, 180 deletions
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 4d01756..a2eb805 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -824,6 +824,160 @@ out_now:
}
+static int
+sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
+{
+ int loopback_scope, ipv4_local_scope, local_scope, site_scope;
+ int ipv4_addr_legal, ipv6_addr_legal;
+ struct sctp_vrf *vrf;
+ struct sctp_ifn *sctp_ifn;
+ struct sctp_ifa *sctp_ifa;
+
+ loopback_scope = stcb->asoc.scope.loopback_scope;
+ ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+ local_scope = stcb->asoc.scope.local_scope;
+ site_scope = stcb->asoc.scope.site_scope;
+ ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+ ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
+
+ SCTP_IPI_ADDR_RLOCK();
+ vrf = sctp_find_vrf(stcb->asoc.vrf_id);
+ if (vrf == NULL) {
+ /* no vrf, no addresses */
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (0);
+ }
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
+ if ((loopback_scope == 0) &&
+ SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
+ continue;
+ }
+ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+ if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
+ (!sctp_is_addr_pending(stcb, sctp_ifa))) {
+ /*
+ * We allow pending addresses, where
+ * we have sent an asconf-add to be
+ * considered valid.
+ */
+ continue;
+ }
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (ipv4_addr_legal) {
+ struct sockaddr_in *sin,
+ *rsin;
+
+ sin = &sctp_ifa->address.sin;
+ rsin = (struct sockaddr_in *)to;
+ if ((ipv4_local_scope == 0) &&
+ IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
+ continue;
+ }
+ if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (ipv6_addr_legal) {
+ struct sockaddr_in6 *sin6,
+ *rsin6;
+
+ sin6 = &sctp_ifa->address.sin6;
+ rsin6 = (struct sockaddr_in6 *)to;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ if (local_scope == 0)
+ continue;
+ if (sin6->sin6_scope_id == 0) {
+ if (sa6_recoverscope(sin6) != 0)
+ continue;
+ }
+ }
+ if ((site_scope == 0) &&
+ (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
+ continue;
+ }
+ if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ }
+ break;
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
+ }
+ }
+ } else {
+ struct sctp_laddr *laddr;
+
+ LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
+ if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
+ SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n");
+ continue;
+ }
+ if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
+ (!sctp_is_addr_pending(stcb, laddr->ifa))) {
+ /*
+ * We allow pending addresses, where we have
+ * sent an asconf-add to be considered
+ * valid.
+ */
+ continue;
+ }
+ if (laddr->ifa->address.sa.sa_family != to->sa_family) {
+ continue;
+ }
+ switch (to->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin, *rsin;
+
+ sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
+ rsin = (struct sockaddr_in *)to;
+ if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6, *rsin6;
+
+ sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
+ rsin6 = (struct sockaddr_in6 *)to;
+ if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ break;
+ }
+
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
+
+ }
+ }
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (0);
+}
+
+
static struct sctp_tcb *
sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id)
@@ -906,7 +1060,6 @@ 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 */
-
#ifdef INET
if (from->sa_family == AF_INET) {
struct sockaddr_in *intf_addr,
@@ -949,13 +1102,18 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
* Ok if we hit here the ep has the address, does it hold
* the tcb?
*/
-
+ /* XXX: Why don't we TAILQ_FOREACH through sctp_asoc_list? */
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
continue;
}
SCTP_TCB_LOCK(stcb);
+ if (!sctp_does_stcb_own_this_addr(stcb, to)) {
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ continue;
+ }
if (stcb->rport != rport) {
/* remote port does not match. */
SCTP_TCB_UNLOCK(stcb);
@@ -967,6 +1125,11 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
SCTP_INP_RUNLOCK(inp);
continue;
}
+ if (!sctp_does_stcb_own_this_addr(stcb, to)) {
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ continue;
+ }
/* Does this TCB have a matching address? */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -1035,156 +1198,6 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
}
-static int
-sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
-{
- int loopback_scope, ipv4_local_scope, local_scope, site_scope;
- int ipv4_addr_legal, ipv6_addr_legal;
- struct sctp_vrf *vrf;
- struct sctp_ifn *sctp_ifn;
- struct sctp_ifa *sctp_ifa;
-
- loopback_scope = stcb->asoc.scope.loopback_scope;
- ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
- local_scope = stcb->asoc.scope.local_scope;
- site_scope = stcb->asoc.scope.site_scope;
- ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
- ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
-
- SCTP_IPI_ADDR_RLOCK();
- vrf = sctp_find_vrf(stcb->asoc.vrf_id);
- if (vrf == NULL) {
- /* no vrf, no addresses */
- SCTP_IPI_ADDR_RUNLOCK();
- return (0);
- }
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
- LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
- if ((loopback_scope == 0) &&
- SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
- continue;
- }
- LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
- if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
- (!sctp_is_addr_pending(stcb, sctp_ifa))) {
- /*
- * We allow pending addresses, where
- * we have sent an asconf-add to be
- * considered valid.
- */
- continue;
- }
- switch (sctp_ifa->address.sa.sa_family) {
-#ifdef INET
- case AF_INET:
- if (ipv4_addr_legal) {
- struct sockaddr_in *sin,
- *rsin;
-
- sin = &sctp_ifa->address.sin;
- rsin = (struct sockaddr_in *)to;
- if ((ipv4_local_scope == 0) &&
- IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
- continue;
- }
- if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (ipv6_addr_legal) {
- struct sockaddr_in6 *sin6,
- *rsin6;
-
- sin6 = &sctp_ifa->address.sin6;
- rsin6 = (struct sockaddr_in6 *)to;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- if (local_scope == 0)
- continue;
- if (sin6->sin6_scope_id == 0) {
- if (sa6_recoverscope(sin6) != 0)
- continue;
- }
- }
- if ((site_scope == 0) &&
- (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
- continue;
- }
- if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- }
- break;
-#endif
- default:
- /* TSNH */
- break;
- }
- }
- }
- } else {
- struct sctp_laddr *laddr;
-
- LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
- if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
- (!sctp_is_addr_pending(stcb, laddr->ifa))) {
- /*
- * We allow pending addresses, where we have
- * sent an asconf-add to be considered
- * valid.
- */
- continue;
- }
- if (laddr->ifa->address.sa.sa_family != to->sa_family) {
- continue;
- }
- switch (to->sa_family) {
-#ifdef INET
- case AF_INET:
- {
- struct sockaddr_in *sin, *rsin;
-
- sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
- rsin = (struct sockaddr_in *)to;
- if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- break;
- }
-#endif
-#ifdef INET6
- case AF_INET6:
- {
- struct sockaddr_in6 *sin6, *rsin6;
-
- sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
- rsin6 = (struct sockaddr_in6 *)to;
- if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- break;
- }
-
-#endif
- default:
- /* TSNH */
- break;
- }
-
- }
- }
- SCTP_IPI_ADDR_RUNLOCK();
- return (0);
-}
-
-
/*
* rules for use
*
@@ -1906,20 +1919,20 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to,
uint32_t vrf_id)
{
struct sctp_inpcb *inp = NULL;
- struct sctp_tcb *retval;
+ struct sctp_tcb *stcb;
SCTP_INP_INFO_RLOCK();
if (find_tcp_pool) {
if (inp_p != NULL) {
- retval = sctp_tcb_special_locate(inp_p, from, to, netp,
+ stcb = sctp_tcb_special_locate(inp_p, from, to, netp,
vrf_id);
} else {
- retval = sctp_tcb_special_locate(&inp, from, to, netp,
+ stcb = sctp_tcb_special_locate(&inp, from, to, netp,
vrf_id);
}
- if (retval != NULL) {
+ if (stcb != NULL) {
SCTP_INP_INFO_RUNLOCK();
- return (retval);
+ return (stcb);
}
}
inp = sctp_pcb_findep(to, 0, 1, vrf_id);
@@ -1927,7 +1940,6 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to,
*inp_p = inp;
}
SCTP_INP_INFO_RUNLOCK();
-
if (inp == NULL) {
return (NULL);
}
@@ -1938,13 +1950,13 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to,
* inbound packet side.
*/
if (inp_p != NULL) {
- retval = sctp_findassociation_ep_addr(inp_p, from, netp, to,
+ stcb = sctp_findassociation_ep_addr(inp_p, from, netp, to,
NULL);
} else {
- retval = sctp_findassociation_ep_addr(&inp, from, netp, to,
+ stcb = sctp_findassociation_ep_addr(&inp, from, netp, to,
NULL);
}
- return retval;
+ return (stcb);
}
@@ -1959,7 +1971,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
struct sockaddr *dst)
{
struct sctp_paramhdr *phdr, parm_buf;
- struct sctp_tcb *retval;
+ struct sctp_tcb *stcb;
uint32_t ptype, plen;
#ifdef INET
@@ -1984,7 +1996,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
sin6.sin6_port = sh->src_port;
#endif
- retval = NULL;
+ stcb = NULL;
offset += sizeof(struct sctp_init_chunk);
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
@@ -2009,10 +2021,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
p4 = (struct sctp_ipv4addr_param *)phdr;
memcpy(&sin4.sin_addr, &p4->addr, sizeof(p4->addr));
/* look it up */
- retval = sctp_findassociation_ep_addr(inp_p,
+ stcb = sctp_findassociation_ep_addr(inp_p,
(struct sockaddr *)&sin4, netp, dst, NULL);
- if (retval != NULL) {
- return (retval);
+ if (stcb != NULL) {
+ return (stcb);
}
}
#endif
@@ -2030,10 +2042,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
p6 = (struct sctp_ipv6addr_param *)phdr;
memcpy(&sin6.sin6_addr, &p6->addr, sizeof(p6->addr));
/* look it up */
- retval = sctp_findassociation_ep_addr(inp_p,
+ stcb = sctp_findassociation_ep_addr(inp_p,
(struct sockaddr *)&sin6, netp, dst, NULL);
- if (retval != NULL) {
- return (retval);
+ if (stcb != NULL) {
+ return (stcb);
}
}
#endif
@@ -2158,15 +2170,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
int find_tcp_pool;
- struct sctp_tcb *retval;
+ struct sctp_tcb *stcb;
struct sctp_inpcb *inp;
if (sh->v_tag) {
/* we only go down this path if vtag is non-zero */
- retval = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag),
+ stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag),
inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0);
- if (retval) {
- return (retval);
+ if (stcb) {
+ return (stcb);
}
}
find_tcp_pool = 0;
@@ -2178,15 +2190,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
find_tcp_pool = 1;
}
if (inp_p) {
- retval = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
+ stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
find_tcp_pool, vrf_id);
inp = *inp_p;
} else {
- retval = sctp_findassociation_addr_sa(src, dst, &inp, netp,
+ stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp,
find_tcp_pool, vrf_id);
}
- SCTPDBG(SCTP_DEBUG_PCB1, "retval:%p inp:%p\n", (void *)retval, (void *)inp);
- if (retval == NULL && inp) {
+ SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp);
+ if (stcb == NULL && inp) {
/* Found a EP but not this address */
if ((ch->chunk_type == SCTP_INITIATION) ||
(ch->chunk_type == SCTP_INITIATION_ACK)) {
@@ -2204,15 +2216,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
}
return (NULL);
}
- retval = sctp_findassociation_special_addr(m,
+ stcb = sctp_findassociation_special_addr(m,
offset, sh, &inp, netp, dst);
if (inp_p != NULL) {
*inp_p = inp;
}
}
}
- SCTPDBG(SCTP_DEBUG_PCB1, "retval is %p\n", (void *)retval);
- return (retval);
+ SCTPDBG(SCTP_DEBUG_PCB1, "stcb is %p\n", (void *)stcb);
+ return (stcb);
}
/*
OpenPOWER on IntegriCloud