diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/if_atm.c | 2 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 85 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 17 | ||||
-rw-r--r-- | sys/netinet/in_rmx.c | 29 | ||||
-rw-r--r-- | sys/netinet/ip_flow.c | 2 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 2 |
7 files changed, 87 insertions, 54 deletions
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c index 82c95bf..5a9e53e 100644 --- a/sys/netinet/if_atm.c +++ b/sys/netinet/if_atm.c @@ -325,8 +325,10 @@ atmresolve(struct rtentry *rt, struct mbuf *m, struct sockaddr *dst, (rt->rt_flags & RTF_LLINFO) == 0 || /* XXX: are we using LLINFO? */ rt->rt_gateway->sa_family != AF_LINK) { + RT_UNLOCK(rt); goto bad; } + RT_UNLOCK(rt); } /* diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 239c616..4cc1d4e 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -105,11 +105,13 @@ struct llinfo_arp { static LIST_HEAD(, llinfo_arp) llinfo_arp; static struct ifqueue arpintrq; -static int arp_inuse, arp_allocated, arpinit_done; +static int arp_allocated; +static int arpinit_done; static int arp_maxtries = 5; static int useloopback = 1; /* use loopback interface for local traffic */ static int arp_proxyall = 0; +static struct callout arp_callout; SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, &arp_maxtries, 0, ""); @@ -140,7 +142,6 @@ arptimer(ignored_arg) void *ignored_arg; { struct llinfo_arp *la, *ola; - int s = splnet(); RADIX_NODE_HEAD_LOCK(rt_tables[AF_INET]); la = LIST_FIRST(&llinfo_arp); @@ -152,8 +153,8 @@ arptimer(ignored_arg) arptfree(ola); /* timer has expired, clear */ } RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET]); - splx(s); - timeout(arptimer, NULL, arpt_prune * hz); + + callout_reset(&arp_callout, arpt_prune * hz, arptimer, NULL); } /* @@ -165,16 +166,20 @@ arp_rtrequest(req, rt, info) register struct rtentry *rt; struct rt_addrinfo *info; { - register struct sockaddr *gate = rt->rt_gateway; - register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; + register struct sockaddr *gate; + register struct llinfo_arp *la; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; + RT_LOCK_ASSERT(rt); + if (!arpinit_done) { arpinit_done = 1; - timeout(arptimer, (caddr_t)0, hz); + callout_reset(&arp_callout, hz, arptimer, NULL); } if (rt->rt_flags & RTF_GATEWAY) return; + gate = rt->rt_gateway; + la = (struct llinfo_arp *)rt->rt_llinfo; switch (req) { case RTM_ADD: @@ -208,7 +213,7 @@ arp_rtrequest(req, rt, info) case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(null_sdl)) { - log(LOG_DEBUG, "arp_rtrequest: bad gateway %s%s\n", + log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__, inet_ntoa(SIN(rt_key(rt))->sin_addr), (gate->sa_family != AF_LINK) ? " (!AF_LINK)": ""); @@ -222,14 +227,13 @@ arp_rtrequest(req, rt, info) * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ - R_Malloc(la, struct llinfo_arp *, sizeof(*la)); + R_Zalloc(la, struct llinfo_arp *, sizeof(*la)); rt->rt_llinfo = (caddr_t)la; if (la == 0) { - log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); + log(LOG_DEBUG, "%s: malloc failed\n", __func__); break; } - arp_inuse++, arp_allocated++; - Bzero(la, sizeof(*la)); + arp_allocated++; la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; RADIX_NODE_HEAD_LOCK_ASSERT(rt_tables[AF_INET]); @@ -280,7 +284,6 @@ arp_rtrequest(req, rt, info) case RTM_DELETE: if (la == 0) break; - arp_inuse--; RADIX_NODE_HEAD_LOCK_ASSERT(rt_tables[AF_INET]); LIST_REMOVE(la, la_le); rt->rt_llinfo = 0; @@ -475,6 +478,7 @@ arpresolve(ifp, rt, m, dst, desten, rt0) m_freem(la->la_hold); la->la_hold = m; if (rt->rt_expire) { + RT_LOCK(rt); rt->rt_flags &= ~RTF_REJECT; if (la->la_asked == 0 || rt->rt_expire != time_second) { rt->rt_expire = time_second; @@ -491,6 +495,7 @@ arpresolve(ifp, rt, m, dst, desten, rt0) } } + RT_UNLOCK(rt); } return (0); } @@ -505,8 +510,9 @@ arpintr(struct mbuf *m) struct arphdr *ar; if (!arpinit_done) { + /* NB: this race should not matter */ arpinit_done = 1; - timeout(arptimer, (caddr_t)0, hz); + callout_reset(&arp_callout, hz, arptimer, NULL); } if (m->m_len < sizeof(struct arphdr) && ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { @@ -736,9 +742,11 @@ match: m->m_pkthdr.len += 8; th->rcf = trld->trld_rcf; } + RT_LOCK(rt); if (rt->rt_expire) rt->rt_expire = time_second + arpt_keep; rt->rt_flags &= ~RTF_REJECT; + RT_UNLOCK(rt); la->la_asked = 0; la->la_preempt = arp_maxtries; if (la->la_hold) { @@ -885,13 +893,16 @@ arptfree(la) { register struct rtentry *rt = la->la_rt; register struct sockaddr_dl *sdl; + if (rt == 0) panic("arptfree"); if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && sdl->sdl_family == AF_LINK) { sdl->sdl_alen = 0; la->la_preempt = la->la_asked = 0; + RT_LOCK(rt); /* XXX needed or move higher? */ rt->rt_flags &= ~RTF_REJECT; + RT_UNLOCK(rt); return; } rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), @@ -906,15 +917,18 @@ arplookup(addr, create, proxy) int create, proxy; { register struct rtentry *rt; - static struct sockaddr_inarp sin = {sizeof(sin), AF_INET }; + struct sockaddr_inarp sin; const char *why = 0; + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; - sin.sin_other = proxy ? SIN_PROXY : 0; + if (proxy) + sin.sin_other = SIN_PROXY; rt = rtalloc1((struct sockaddr *)&sin, create, 0UL); if (rt == 0) return (0); - rt->rt_refcnt--; if (rt->rt_flags & RTF_GATEWAY) why = "host is not on local network"; @@ -924,25 +938,32 @@ arplookup(addr, create, proxy) why = "gateway route is not ours"; if (why) { - if (create) { +#define ISDYNCLONE(_rt) \ + (((_rt)->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == RTF_WASCLONED) + if (create) log(LOG_DEBUG, "arplookup %s failed: %s\n", inet_ntoa(sin.sin_addr), why); - /* - * If there are no references to this Layer 2 route, - * and it is a cloned route, and not static, and - * arplookup() is creating the route, then purge - * it from the routing table as it is probably bogus. - */ - if (((rt->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == - RTF_WASCLONED) && (rt->rt_refcnt == 0)) - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), - rt->rt_flags, 0); + /* + * If there are no references to this Layer 2 route, + * and it is a cloned route, and not static, and + * arplookup() is creating the route, then purge + * it from the routing table as it is probably bogus. + */ + RT_UNLOCK(rt); + if (rt->rt_refcnt == 1 && ISDYNCLONE(rt)) { + rtrequest(RTM_DELETE, + (struct sockaddr *)rt_key(rt), + rt->rt_gateway, rt_mask(rt), + rt->rt_flags, 0); } + RTFREE(rt); return (0); +#undef ISDYNCLONE + } else { + rt->rt_refcnt--; + RT_UNLOCK(rt); + return ((struct llinfo_arp *)rt->rt_llinfo); } - return ((struct llinfo_arp *)rt->rt_llinfo); } void @@ -964,7 +985,7 @@ arp_init(void) arpintrq.ifq_maxlen = 50; mtx_init(&arpintrq.ifq_mtx, "arp_inq", NULL, MTX_DEF); LIST_INIT(&llinfo_arp); + callout_init(&arp_callout, CALLOUT_MPSAFE); netisr_register(NETISR_ARP, arpintr, &arpintrq); } - SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index dc52d89..e094c8c 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -165,11 +165,9 @@ in_pcballoc(so, pcbinfo, td) #ifdef IPSEC int error; #endif - - inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT); + inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO); if (inp == NULL) return (ENOBUFS); - bzero((caddr_t)inp, sizeof(*inp)); inp->inp_gencnt = ++pcbinfo->ipi_gencnt; inp->inp_pcbinfo = pcbinfo; inp->inp_socket = so; @@ -678,7 +676,7 @@ in_pcbdetach(inp) if (inp->inp_options) (void)m_free(inp->inp_options); if (inp->inp_route.ro_rt) - rtfree(inp->inp_route.ro_rt); + RTFREE(inp->inp_route.ro_rt); ip_freemoptions(inp->inp_moptions); inp->inp_vflag = 0; INP_LOCK_DESTROY(inp); @@ -865,16 +863,19 @@ in_losing(inp) struct rt_addrinfo info; if ((rt = inp->inp_route.ro_rt)) { + RT_LOCK(rt); + inp->inp_route.ro_rt = NULL; bzero((caddr_t)&info, sizeof(info)); info.rti_flags = rt->rt_flags; info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); - if (rt->rt_flags & RTF_DYNAMIC) + if (rt->rt_flags & RTF_DYNAMIC) { + RT_UNLOCK(rt); /* XXX refcnt? */ (void) rtrequest1(RTM_DELETE, &info, NULL); - inp->inp_route.ro_rt = NULL; - rtfree(rt); + } else + rtfree(rt); /* * A new route can be allocated * the next time output is attempted. @@ -892,7 +893,7 @@ in_rtchange(inp, errno) int errno; { if (inp->inp_route.ro_rt) { - rtfree(inp->inp_route.ro_rt); + RTFREE(inp->inp_route.ro_rt); inp->inp_route.ro_rt = 0; /* * A new route can be allocated the next time diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 0c743b5..5092bb9 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -49,6 +49,7 @@ #include <sys/socket.h> #include <sys/mbuf.h> #include <sys/syslog.h> +#include <sys/callout.h> #include <net/if.h> #include <net/route.h> @@ -124,14 +125,17 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, rt2->rt_flags & RTF_HOST && rt2->rt_gateway && rt2->rt_gateway->sa_family == AF_LINK) { + /* NB: must unlock to avoid recursion */ + RT_UNLOCK(rt2); rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt2), rt2->rt_gateway, rt_mask(rt2), rt2->rt_flags, 0); ret = rn_addroute(v_arg, n_arg, head, treenodes); + RT_LOCK(rt2); } - RTFREE(rt2); + RTFREE_LOCKED(rt2); } } @@ -159,6 +163,7 @@ in_matroute(void *v_arg, struct radix_node_head *head) struct radix_node *rn = rn_match(v_arg, head); struct rtentry *rt = (struct rtentry *)rn; + /*XXX locking? */ if (rt && rt->rt_refcnt == 0) { /* this is first reference */ if (rt->rt_flags & RTPRF_OURS) { rt->rt_flags &= ~RTPRF_OURS; @@ -190,6 +195,8 @@ in_clsroute(struct radix_node *rn, struct radix_node_head *head) { struct rtentry *rt = (struct rtentry *)rn; + RT_LOCK_ASSERT(rt); + if (!(rt->rt_flags & RTF_UP)) return; /* prophylactic measures */ @@ -207,10 +214,13 @@ in_clsroute(struct radix_node *rn, struct radix_node_head *head) rt->rt_flags |= RTPRF_OURS; rt->rt_rmx.rmx_expire = time_second + rtq_reallyold; } else { + /* NB: must unlock to avoid recursion */ + RT_UNLOCK(rt); rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); + RT_LOCK(rt); } } @@ -268,6 +278,7 @@ in_rtqkill(struct radix_node *rn, void *rock) #define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ static int rtq_timeout = RTQ_TIMEOUT; +static struct callout rtq_timer; static void in_rtqtimo(void *rock) @@ -276,17 +287,14 @@ in_rtqtimo(void *rock) struct rtqk_arg arg; struct timeval atv; static time_t last_adjusted_timeout = 0; - int s; arg.found = arg.killed = 0; arg.rnh = rnh; arg.nextstop = time_second + rtq_timeout; arg.draining = arg.updating = 0; - s = splnet(); RADIX_NODE_HEAD_LOCK(rnh); rnh->rnh_walktree(rnh, in_rtqkill, &arg); RADIX_NODE_HEAD_UNLOCK(rnh); - splx(s); /* * Attempt to be somewhat dynamic about this: @@ -311,16 +319,14 @@ in_rtqtimo(void *rock) #endif arg.found = arg.killed = 0; arg.updating = 1; - s = splnet(); RADIX_NODE_HEAD_LOCK(rnh); rnh->rnh_walktree(rnh, in_rtqkill, &arg); RADIX_NODE_HEAD_UNLOCK(rnh); - splx(s); } atv.tv_usec = 0; atv.tv_sec = arg.nextstop - time_second; - timeout(in_rtqtimo, rock, tvtohz(&atv)); + callout_reset(&rtq_timer, tvtohz(&atv), in_rtqtimo, rock); } void @@ -328,17 +334,15 @@ in_rtqdrain(void) { struct radix_node_head *rnh = rt_tables[AF_INET]; struct rtqk_arg arg; - int s; + arg.found = arg.killed = 0; arg.rnh = rnh; arg.nextstop = 0; arg.draining = 1; arg.updating = 0; - s = splnet(); RADIX_NODE_HEAD_LOCK(rnh); rnh->rnh_walktree(rnh, in_rtqkill, &arg); RADIX_NODE_HEAD_UNLOCK(rnh); - splx(s); } /* @@ -359,6 +363,7 @@ in_inithead(void **head, int off) rnh->rnh_addaddr = in_addroute; rnh->rnh_matchaddr = in_matroute; rnh->rnh_close = in_clsroute; + callout_init(&rtq_timer, CALLOUT_MPSAFE); in_rtqtimo(rnh); /* kick off timeout first time */ return 1; } @@ -395,7 +400,9 @@ in_ifadownkill(struct radix_node *rn, void *xap) * the routes that rtrequest() would have in any case, * so that behavior is not needed there. */ + RT_LOCK(rt); rt->rt_flags &= ~(RTF_CLONING | RTF_PRCLONING); + RT_UNLOCK(rt); err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if (err) { @@ -420,6 +427,6 @@ in_ifadown(struct ifaddr *ifa, int delete) RADIX_NODE_HEAD_LOCK(rnh); rnh->rnh_walktree(rnh, in_ifadownkill, &arg); RADIX_NODE_HEAD_UNLOCK(rnh); - ifa->ifa_flags &= ~IFA_ROUTE; + ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ return 0; } diff --git a/sys/netinet/ip_flow.c b/sys/netinet/ip_flow.c index f2e23ea..25b8fce 100644 --- a/sys/netinet/ip_flow.c +++ b/sys/netinet/ip_flow.c @@ -352,7 +352,9 @@ ipflow_create(const struct route *ro, struct mbuf *m) * Fill in the updated information. */ ipf->ipf_ro = *ro; + RT_LOCK(ro->ro_rt); ro->ro_rt->rt_refcnt++; + RT_UNLOCK(ro->ro_rt); ipf->ipf_timer = IPFLOW_TIMER; /* * Insert into the approriate bucket of the flow table. diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index f4df251..1e485e3 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -427,7 +427,7 @@ icmp_input(m, off) } } if (rt) - RTFREE(rt); + rtfree(rt); } #endif @@ -565,7 +565,7 @@ reflect: rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst, (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, - (struct sockaddr *)&icmpgw, (struct rtentry **)0); + (struct sockaddr *)&icmpgw); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); #ifdef IPSEC key_sa_routechange((struct sockaddr *)&icmpsrc); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 41e0cc0..dc71879 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1986,7 +1986,7 @@ ip_setmoptions(sopt, imop) break; } ifp = ro.ro_rt->rt_ifp; - rtfree(ro.ro_rt); + RTFREE(ro.ro_rt); } else { ifp = ip_multicast_if(&mreq.imr_interface, NULL); |