From d16fa20132ea6d21b9bd26cc09246c12134ba6ee Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 31 Jan 2009 12:07:32 +0800 Subject: [PATCH] rtsock: Fix !SO_USELOOPBACK support in route_output() Old BSD code assumes that rts_input() is synchronous, so clear/set sp_family could be used to skip the current rawcb. However, our rts_input() is asynchronous, thus the clear/set sp_family trick no longer takes any effect. Reimplement the rawcb skipping in the following way: - Record the address of rawcb to be skipped in netmsg. - Extend raw_input() interface to accept a 'skip' argument. At the beginning of the rawcb list iteration, check the address of the current rawcb against the 'skip'. --- sys/net/raw_cb.h | 5 +++-- sys/net/raw_usrreq.c | 7 +++++-- sys/net/rtsock.c | 27 +++++++++++++++++++-------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/sys/net/raw_cb.h b/sys/net/raw_cb.h index 2e67590295..50fc11305f 100644 --- a/sys/net/raw_cb.h +++ b/sys/net/raw_cb.h @@ -79,8 +79,9 @@ void raw_ctlinput (int, struct sockaddr *, void *); void raw_detach (struct rawcb *); void raw_disconnect (struct rawcb *); void raw_init (void); -void raw_input (struct mbuf *, struct sockproto *, - const struct sockaddr *, const struct sockaddr *); +void raw_input (struct mbuf *, const struct sockproto *, + const struct sockaddr *, const struct sockaddr *, + const struct rawcb *); extern struct pr_usrreqs raw_usrreqs; #endif diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index fb38a7654f..3e98646d44 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -68,8 +68,9 @@ raw_init(void) * Most other raw protocol interface functions are also serialized XXX. */ void -raw_input(struct mbuf *m0, struct sockproto *proto, const struct sockaddr *src, - const struct sockaddr *dst) +raw_input(struct mbuf *m0, const struct sockproto *proto, + const struct sockaddr *src, const struct sockaddr *dst, + const struct rawcb *skip) { struct rawcb *rp; struct mbuf *m = m0; @@ -77,6 +78,8 @@ raw_input(struct mbuf *m0, struct sockproto *proto, const struct sockaddr *src, last = NULL; LIST_FOREACH(rp, &rawcb_list, list) { + if (rp == skip) + continue; if (rp->rcb_proto.sp_family != proto->sp_family) continue; if (rp->rcb_proto.sp_protocol && diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 3b95ed0f31..e2f2160113 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -350,31 +350,46 @@ rts_input_handler(struct netmsg *msg) struct netmsg_packet *pmsg; struct mbuf *m; sa_family_t family; + struct rawcb *skip; pmsg = (void *)msg; - m = pmsg->nm_packet; family = pmsg->nm_netmsg.nm_lmsg.u.ms_result; route_proto.sp_family = PF_ROUTE; route_proto.sp_protocol = family; - raw_input(m, &route_proto, &route_src, &route_dst); + m = pmsg->nm_packet; + M_ASSERTPKTHDR(m); + + skip = m->m_pkthdr.header; + m->m_pkthdr.header = NULL; + + raw_input(m, &route_proto, &route_src, &route_dst, skip); } static void -rts_input(struct mbuf *m, sa_family_t family) +rts_input_skip(struct mbuf *m, sa_family_t family, struct rawcb *skip) { struct netmsg_packet *pmsg; lwkt_port_t port; + M_ASSERTPKTHDR(m); + port = cpu0_soport(NULL, NULL, NULL, 0); pmsg = &m->m_hdr.mh_netmsg; netmsg_init(&pmsg->nm_netmsg, &netisr_apanic_rport, 0, rts_input_handler); pmsg->nm_packet = m; pmsg->nm_netmsg.nm_lmsg.u.ms_result = family; + m->m_pkthdr.header = skip; /* XXX steal field in pkthdr */ lwkt_sendmsg(port, &pmsg->nm_netmsg.nm_lmsg); } +static __inline void +rts_input(struct mbuf *m, sa_family_t family) +{ + rts_input_skip(m, family, NULL); +} + static void * reallocbuf(void *ptr, size_t len, size_t olen) { @@ -594,12 +609,8 @@ flush: m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); kfree(rtm, M_RTABLE); } - if (rp != NULL) - rp->rcb_proto.sp_family = 0; /* Avoid us */ if (m != NULL) - rts_input(m, familyof(rtinfo.rti_dst)); - if (rp != NULL) - rp->rcb_proto.sp_family = PF_ROUTE; + rts_input_skip(m, familyof(rtinfo.rti_dst), rp); return (error); } -- 2.41.0