summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/if_atm.c2
-rw-r--r--sys/netinet/if_ether.c85
-rw-r--r--sys/netinet/in_pcb.c17
-rw-r--r--sys/netinet/in_rmx.c29
-rw-r--r--sys/netinet/ip_flow.c2
-rw-r--r--sys/netinet/ip_icmp.c4
-rw-r--r--sys/netinet/ip_output.c2
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);
OpenPOWER on IntegriCloud