summaryrefslogtreecommitdiff
path: root/sys/net/rtsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r--sys/net/rtsock.c113
1 files changed, 58 insertions, 55 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index fff48f069ab..7fdc5291892 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.239 2017/06/26 09:32:32 mpi Exp $ */
+/* $OpenBSD: rtsock.c,v 1.240 2017/07/03 19:23:47 claudio Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -98,6 +98,7 @@ struct walkarg {
caddr_t w_where, w_tmem;
};
+void route_prinit(void);
int route_output(struct mbuf *, struct socket *, struct sockaddr *,
struct mbuf *);
int route_ctloutput(int, struct socket *, int, int, struct mbuf *);
@@ -126,19 +127,21 @@ int sysctl_ifnames(struct walkarg *);
int sysctl_rtable_rtstat(void *, size_t *, void *);
struct routecb {
- struct rawcb rcb;
- struct timeout timeout;
- unsigned int msgfilter;
- unsigned int flags;
- u_int rtableid;
+ struct rawcb rcb;
+ LIST_ENTRY(routecb) rcb_list;
+ struct timeout timeout;
+ unsigned int msgfilter;
+ unsigned int flags;
+ u_int rtableid;
};
#define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
struct route_cb {
- int ip_count;
- int ip6_count;
- int mpls_count;
- int any_count;
+ LIST_HEAD(, routecb) rcb;
+ int ip_count;
+ int ip6_count;
+ int mpls_count;
+ int any_count;
};
struct route_cb route_cb;
@@ -154,45 +157,53 @@ struct route_cb route_cb;
#define ROUTE_DESYNC_RESEND_TIMEOUT (hz / 5) /* In hz */
+void
+route_prinit(void)
+{
+ LIST_INIT(&route_cb.rcb);
+}
+
+
int
route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
struct mbuf *control, struct proc *p)
{
- struct rawcb *rp;
struct routecb *rop;
int af;
int error = 0;
- rp = sotorawcb(so);
+ rop = sotoroutecb(so);
+ if (rop == NULL) {
+ m_freem(m);
+ return (EINVAL);
+ }
switch (req) {
case PRU_RCVD:
- rop = (struct routecb *)rp;
-
/*
* If we are in a FLUSH state, check if the buffer is
* empty so that we can clear the flag.
*/
if (((rop->flags & ROUTECB_FLAG_FLUSH) != 0) &&
- ((sbspace(rp->rcb_socket, &rp->rcb_socket->so_rcv) ==
- rp->rcb_socket->so_rcv.sb_hiwat)))
+ ((sbspace(rop->rcb.rcb_socket,
+ &rop->rcb.rcb_socket->so_rcv) ==
+ rop->rcb.rcb_socket->so_rcv.sb_hiwat)))
rop->flags &= ~ROUTECB_FLAG_FLUSH;
break;
case PRU_DETACH:
- if (rp) {
- timeout_del(&((struct routecb *)rp)->timeout);
- af = rp->rcb_proto.sp_protocol;
- if (af == AF_INET)
- route_cb.ip_count--;
- else if (af == AF_INET6)
- route_cb.ip6_count--;
+ timeout_del(&rop->timeout);
+ af = rop->rcb.rcb_proto.sp_protocol;
+ if (af == AF_INET)
+ route_cb.ip_count--;
+ else if (af == AF_INET6)
+ route_cb.ip6_count--;
#ifdef MPLS
- else if (af == AF_MPLS)
- route_cb.mpls_count--;
+ else if (af == AF_MPLS)
+ route_cb.mpls_count--;
#endif
- route_cb.any_count--;
- }
+ route_cb.any_count--;
+ LIST_REMOVE(rop, rcb_list);
/* FALLTHROUGH */
default:
error = raw_usrreq(so, req, m, nam, control, p);
@@ -206,8 +217,7 @@ route_attach(struct socket *so, int proto)
{
struct rawcb *rp;
struct routecb *rop;
- int af;
- int error = 0;
+ int error;
/*
* use the rawcb but allocate a routecb, this
@@ -229,21 +239,28 @@ route_attach(struct socket *so, int proto)
return (error);
}
rop->rtableid = curproc->p_p->ps_rtableid;
- af = rp->rcb_proto.sp_protocol;
- if (af == AF_INET)
+ switch (rp->rcb_proto.sp_protocol) {
+ case AF_INET:
route_cb.ip_count++;
- else if (af == AF_INET6)
+ break;
+ case AF_INET6:
route_cb.ip6_count++;
+ break;
#ifdef MPLS
- else if (af == AF_MPLS)
+ case AF_MPLS:
route_cb.mpls_count++;
+ break;
#endif
- rp->rcb_faddr = &route_src;
- route_cb.any_count++;
+ }
+
soisconnected(so);
so->so_options |= SO_USELOOPBACK;
- return (error);
+ rp->rcb_faddr = &route_src;
+ route_cb.any_count++;
+ LIST_INSERT_HEAD(&route_cb.rcb, rop, rcb_list);
+
+ return (0);
}
int
@@ -360,10 +377,11 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
return;
}
- LIST_FOREACH(rp, &rawcb, rcb_list) {
- if (rp->rcb_socket->so_state & SS_CANTRCVMORE)
+ LIST_FOREACH(rop, &route_cb.rcb, rcb_list) {
+ rp = &rop->rcb;
+ if (!(rp->rcb_socket->so_state & SS_ISCONNECTED))
continue;
- if (rp->rcb_proto.sp_family != PF_ROUTE)
+ if (rp->rcb_socket->so_state & SS_CANTRCVMORE)
continue;
/* Check to see if we don't want our own messages. */
if (so == rp->rcb_socket && !(so->so_options & SO_USELOOPBACK))
@@ -378,23 +396,8 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
sa_family != AF_UNSPEC &&
rp->rcb_proto.sp_protocol != sa_family)
continue;
- /*
- * We assume the lower level routines have
- * placed the address in a canonical format
- * suitable for a structure comparison.
- *
- * Note that if the lengths are not the same
- * the comparison will fail at the first byte.
- */
-#define equal(a1, a2) \
- (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
- if (rp->rcb_laddr && !equal(rp->rcb_laddr, sodst))
- continue;
- if (rp->rcb_faddr && !equal(rp->rcb_faddr, sosrc))
- continue;
/* filter messages that the process does not want */
- rop = (struct routecb *)rp;
rtm = mtod(m, struct rt_msghdr *);
/* but RTM_DESYNC can't be filtered */
if (rtm->rtm_type != RTM_DESYNC && rop->msgfilter != 0 &&
@@ -1787,7 +1790,7 @@ struct protosw routesw[] = {
.pr_ctloutput = route_ctloutput,
.pr_usrreq = route_usrreq,
.pr_attach = route_attach,
- .pr_init = raw_init,
+ .pr_init = route_prinit,
.pr_sysctl = sysctl_rtable
}
};