Index: rtsock.c =================================================================== RCS file: /cvs/src/sys/net/rtsock.c,v retrieving revision 1.259 diff -u -p -r1.259 rtsock.c --- rtsock.c 18 Dec 2017 09:40:17 -0000 1.259 +++ rtsock.c 10 Feb 2018 02:00:53 -0000 @@ -138,6 +138,7 @@ struct routecb { unsigned int msgfilter; unsigned int flags; u_int rtableid; + int seq; }; #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb) @@ -348,28 +349,32 @@ route_ctloutput(int op, struct socket *s void route_senddesync(void *data) { - struct rawcb *rp; - struct routecb *rop; + struct routecb *rop = data; struct mbuf *desync_mbuf; - - rp = (struct rawcb *)data; - rop = (struct routecb *)rp; + int seq; /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */ if ((rop->flags & ROUTECB_FLAG_DESYNC) == 0) return; + /* * If we fail to alloc memory or if sbappendaddr() * fails, re-add timeout and try again. */ + seq = rop->seq++; desync_mbuf = rtm_msg1(RTM_DESYNC, NULL); if (desync_mbuf != NULL) { - struct socket *so = rp->rcb_socket; + struct socket *so = rop->rcb.rcb_socket; + struct rt_msghdr *rtm; + + rtm = mtod(desync_mbuf, struct rt_msghdr *); + rtm->rtm_seq = seq; + if (sbappendaddr(so, &so->so_rcv, &route_src, desync_mbuf, NULL) != 0) { rop->flags &= ~ROUTECB_FLAG_DESYNC; - sorwakeup(rp->rcb_socket); + sorwakeup(so); return; } m_freem(desync_mbuf); @@ -379,13 +384,61 @@ route_senddesync(void *data) } void +route_send(struct mbuf *m, struct socket *so, struct sockaddr *sosrc, int dup) +{ + struct routecb *rop = sotoroutecb(so); + struct rt_msghdr *rtm; + int seq; + + seq = rop->seq++; + + if (sbspace(so, &so->so_rcv) < m->m_pkthdr.len) + goto desync; + + if (dup) { + m = m_dup_pkt(m, 0, M_NOWAIT); + if (m == NULL) + goto desync; + } + + rtm = mtod(m, struct rt_msghdr *); + + switch (rtm->rtm_type) { /* XXX check rtm_hdrlen ? */ + case RTM_DELADDR: + case RTM_NEWADDR: + case RTM_IFINFO: + case RTM_IFANNOUNCE: +#ifdef BFD + case RTM_BFD: +#endif + break; + default: + rtm->rtm_seq = seq; + break; + } + + if (sbappendaddr(so, &so->so_rcv, sosrc, m, NULL) == 0) { + m_freem(m); + goto desync; + } + + sorwakeup(so); + + return; + +desync: + /* Flag socket as desync'ed and flush required */ + rop->flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH; + route_senddesync(rop); +} + +void route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family) { struct rawcb *rp; struct routecb *rop; struct rt_msghdr *rtm; struct mbuf *m = m0; - int sockets = 0; struct socket *last = NULL; struct sockaddr *sosrc, *sodst; @@ -455,43 +508,14 @@ route_input(struct mbuf *m0, struct sock if ((rop->flags & ROUTECB_FLAG_FLUSH) != 0) continue; - if (last) { - struct mbuf *n; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) { - if (sbspace(last, &last->so_rcv) < (2*MSIZE) || - sbappendaddr(last, &last->so_rcv, sosrc, - n, (struct mbuf *)NULL) == 0) { - /* - * Flag socket as desync'ed and - * flush required - */ - sotoroutecb(last)->flags |= - ROUTECB_FLAG_DESYNC | - ROUTECB_FLAG_FLUSH; - route_senddesync(sotorawcb(last)); - m_freem(n); - } else { - sorwakeup(last); - sockets++; - } - } - } + if (last) + route_send(m, last, sosrc, 1); + last = rp->rcb_socket; } - if (last) { - if (sbspace(last, &last->so_rcv) < (2 * MSIZE) || - sbappendaddr(last, &last->so_rcv, sosrc, - m, (struct mbuf *)NULL) == 0) { - /* Flag socket as desync'ed and flush required */ - sotoroutecb(last)->flags |= - ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH; - route_senddesync(sotorawcb(last)); - m_freem(m); - } else { - sorwakeup(last); - sockets++; - } - } else + if (last) + route_send(m, last, sosrc, 0); + else m_freem(m); }