diff options
author | Jolan Luff <jolan@cvs.openbsd.org> | 2005-11-29 02:59:43 +0000 |
---|---|---|
committer | Jolan Luff <jolan@cvs.openbsd.org> | 2005-11-29 02:59:43 +0000 |
commit | adb4778804adba0245306281be53c4c3659bcb68 (patch) | |
tree | d19d9d4f1abd87230c6e6dfacb8381d75ec903f0 /sys/net | |
parent | 1095458dcf6143c8e7dd908e945fc791eee652d8 (diff) |
something in the eurobsdcon route-a-thon broke my simple home network
router so back out the routing stuff to pre-eurobsdcon where my machine
doesn't crash immediately.
i am happy to test diffs and report success/failures but i am not happy
to have instantaneous crashes when i reboot with a new kernel that was
compiled from pristine sources.
if you are going to be an elitist asshole then you could at least make
sure your code works.
ok and "be crass towards them" deraadt@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 76 | ||||
-rw-r--r-- | sys/net/if_tun.c | 18 | ||||
-rw-r--r-- | sys/net/route.c | 400 | ||||
-rw-r--r-- | sys/net/route.h | 7 | ||||
-rw-r--r-- | sys/net/rtsock.c | 10 |
5 files changed, 250 insertions, 261 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 3aa81a74595..cf75acdaef6 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.139 2005/11/27 16:22:45 henning Exp $ */ +/* $OpenBSD: if.c,v 1.140 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -126,6 +126,7 @@ void if_attachsetup(struct ifnet *); void if_attachdomain1(struct ifnet *); +int if_detach_rtdelete(struct radix_node *, void *); int ifqmaxlen = IFQ_MAXLEN; @@ -448,6 +449,37 @@ if_attach(struct ifnet *ifp) } /* + * Delete a route if it has a specific interface for output. + * This function complies to the rn_walktree callback API. + * + * Note that deleting a RTF_CLONING route can trigger the + * deletion of more entries, so we need to cancel the walk + * and return EAGAIN. The caller should restart the walk + * as long as EAGAIN is returned. + */ +int +if_detach_rtdelete(struct radix_node *rn, void *vifp) +{ + struct ifnet *ifp = vifp; + struct rtentry *rt = (struct rtentry *)rn; + + if (rt->rt_ifp == ifp) { + int cloning = (rt->rt_flags & RTF_CLONING); + + if (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, + rt_mask(rt), 0, NULL) == 0 && cloning) + return (EAGAIN); + } + + /* + * XXX There should be no need to check for rt_ifa belonging to this + * interface, because then rt_ifp is set, right? + */ + + return (0); +} + +/* * Detach an interface from everything in the kernel. Also deallocate * private resources. * XXX So far only the INET protocol family has been looked over @@ -458,11 +490,10 @@ if_detach(struct ifnet *ifp) { struct ifaddr *ifa; struct ifg_list *ifg; - int s; + int i, s = splimp(); + struct radix_node_head *rnh; struct domain *dp; - s = splimp(); - ifp->if_flags &= ~IFF_OACTIVE; ifp->if_start = if_detached_start; ifp->if_ioctl = if_detached_ioctl; @@ -498,7 +529,17 @@ if_detach(struct ifnet *ifp) altq_detach(&ifp->if_snd); #endif - rt_if_remove(ifp); + /* + * Find and remove all routes which is using this interface. + * XXX Factor out into a route.c function? + */ + for (i = 1; i <= AF_MAX; i++) { + rnh = rt_tables[i]; + if (rnh) + while ((*rnh->rnh_walktree)(rnh, + if_detach_rtdelete, ifp) == EAGAIN) + ; + } #ifdef INET rti_delete(ifp); @@ -1750,6 +1791,7 @@ if_group_egress_build(void) #ifdef INET6 struct sockaddr_in6 sa_in6; #endif + struct radix_node_head *rnh; struct radix_node *rn; struct rtentry *rt; @@ -1763,34 +1805,42 @@ if_group_egress_build(void) if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS); } + if ((rnh = rt_tables[AF_INET]) == NULL) + return (-1); + bzero(&sa_in, sizeof(sa_in)); sa_in.sin_len = sizeof(sa_in); sa_in.sin_family = AF_INET; - if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) { + if ((rn = rnh->rnh_lookup(&sa_in, &sa_in, rnh))) { do { rt = (struct rtentry *)rn; if (rt->rt_ifp) if_addgroup(rt->rt_ifp, IFG_EGRESS); #ifndef SMALL_KERNEL - rn = rn_mpath_next(rn); -#else - rn = NULL; + if (rn_mpath_capable(rnh)) + rn = rn_mpath_next(rn); + else #endif + rn = NULL; } while (rn != NULL); } #ifdef INET6 + if ((rnh = rt_tables[AF_INET6]) == NULL) + return (-1); + bcopy(&sa6_any, &sa_in6, sizeof(sa_in6)); - if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) { + if ((rn = rnh->rnh_lookup(&sa_in6, &sa_in6, rnh))) { do { rt = (struct rtentry *)rn; if (rt->rt_ifp) if_addgroup(rt->rt_ifp, IFG_EGRESS); #ifndef SMALL_KERNEL - rn = rn_mpath_next(rn); -#else - rn = NULL; + if (rn_mpath_capable(rnh)) + rn = rn_mpath_next(rn); + else #endif + rn = NULL; } while (rn != NULL); } #endif diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 8e89ff70d1e..d308eff5038 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tun.c,v 1.72 2005/11/25 13:45:02 henning Exp $ */ +/* $OpenBSD: if_tun.c,v 1.73 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */ /* @@ -346,9 +346,11 @@ tunopen(dev_t dev, int flag, int mode, struct proc *p) int tunclose(dev_t dev, int flag, int mode, struct proc *p) { - int s; + extern int if_detach_rtdelete(struct radix_node *, void *); + int s, i; struct tun_softc *tp; struct ifnet *ifp; + struct radix_node_head *rnh; if ((tp = tun_lookup(minor(dev))) == NULL) return (ENXIO); @@ -380,7 +382,17 @@ tunclose(dev_t dev, int flag, int mode, struct proc *p) /* XXX INET6 */ #endif } - rt_if_remove(ifp); + /* + * Find and remove all routes which is using this + * interface. Stolen from if.c if_detach(). + */ + for (i = 1; i <= AF_MAX; i++) { + rnh = rt_tables[i]; + if (rnh) + while ((*rnh->rnh_walktree)(rnh, + if_detach_rtdelete, ifp) == EAGAIN) + ; + } ifp->if_flags &= ~IFF_RUNNING; } splx(s); diff --git a/sys/net/route.c b/sys/net/route.c index 1483205ba9a..4214d8ae52d 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.61 2005/11/28 15:27:19 markus Exp $ */ +/* $OpenBSD: route.c,v 1.62 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -124,27 +124,26 @@ #ifdef IPSEC #include <netinet/ip_ipsp.h> -extern struct ifnet encif; -struct ifaddr *encap_findgwifa(struct sockaddr *); +extern struct ifnet encif; +struct ifaddr * encap_findgwifa(struct sockaddr *); #endif #define SA(p) ((struct sockaddr *)(p)) -struct route_cb route_cb; -struct rtstat rtstat; -struct radix_node_head *rt_tables[AF_MAX+1]; +struct route_cb route_cb; +struct rtstat rtstat; +struct radix_node_head *rt_tables[AF_MAX+1]; -int rttrash; /* routes not in table but not freed */ -struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ +int rttrash; /* routes not in table but not freed */ +struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ -struct pool rtentry_pool; /* pool for rtentry structures */ -struct pool rttimer_pool; /* pool for rttimer structures */ +struct pool rtentry_pool; /* pool for rtentry structures */ +struct pool rttimer_pool; /* pool for rttimer structures */ -int okaytoclone(u_int, int); -int rtdeletemsg(struct rtentry *); -int rtflushclone1(struct radix_node *, void *); -void rtflushclone(struct radix_node_head *, struct rtentry *); -int rt_if_remove_rtdelete(struct radix_node *, void *); +int okaytoclone(u_int, int); +int rtdeletemsg(struct rtentry *); +int rtflushclone1(struct radix_node *, void *); +void rtflushclone(struct radix_node_head *, struct rtentry *); #define LABELID_MAX 50000 @@ -158,18 +157,19 @@ struct rt_label { TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); #ifdef IPSEC + struct ifaddr * encap_findgwifa(struct sockaddr *gw) { return (TAILQ_FIRST(&encif.if_addrlist)); } + #endif void rtable_init(void **table) { - struct domain *dom; - + struct domain *dom; for (dom = domains; dom != NULL; dom = dom->dom_next) if (dom->dom_rtattach) dom->dom_rtattach(&table[dom->dom_family], @@ -206,14 +206,13 @@ okaytoclone(u_int flags, int howstrict) struct rtentry * rtalloc2(struct sockaddr *dst, int report, int howstrict) { - struct radix_node_head *rnh = rt_tables[dst->sa_family]; - struct rtentry *rt; - struct radix_node *rn; - struct rtentry *newrt = 0; - struct rt_addrinfo info; - int s, err = 0, msgtype = RTM_MISS; - - s = splnet(); + struct radix_node_head *rnh = rt_tables[dst->sa_family]; + struct rtentry *rt; + struct radix_node *rn; + struct rtentry *newrt = 0; + struct rt_addrinfo info; + int s = splnet(), err = 0, msgtype = RTM_MISS; + if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; @@ -234,7 +233,6 @@ rtalloc2(struct sockaddr *dst, int report, int howstrict) rt->rt_refcnt++; } else { rtstat.rts_unreach++; - miss: if (report) { bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; @@ -259,14 +257,13 @@ rtalloc(struct route *ro) struct rtentry * rtalloc1(struct sockaddr *dst, int report) { - struct radix_node_head *rnh = rt_tables[dst->sa_family]; - struct rtentry *rt; - struct radix_node *rn; - struct rtentry *newrt = 0; - struct rt_addrinfo info; - int s, err = 0, msgtype = RTM_MISS; + struct radix_node_head *rnh = rt_tables[dst->sa_family]; + struct rtentry *rt; + struct radix_node *rn; + struct rtentry *newrt = 0; + struct rt_addrinfo info; + int s = splsoftnet(), err = 0, msgtype = RTM_MISS; - s = splsoftnet(); if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; @@ -288,8 +285,8 @@ rtalloc1(struct sockaddr *dst, int report) info.rti_info[RTAX_NETMASK] = rt_mask(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; if (rt->rt_ifp != NULL) { - info.rti_info[RTAX_IFP] = TAILQ_FIRST - (&rt->rt_ifp->if_addrlist)->ifa_addr; + info.rti_info[RTAX_IFP] = + TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr; info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0); @@ -297,13 +294,13 @@ rtalloc1(struct sockaddr *dst, int report) rt->rt_refcnt++; } else { if (dst->sa_family != PF_KEY) - rtstat.rts_unreach++; + rtstat.rts_unreach++; /* * IP encapsulation does lots of lookups where we don't need nor want * the RTM_MISSes that would be generated. It causes RTM_MISS storms * sent upward breaking user-level routing queries. */ -miss: if (report && dst->sa_family != PF_KEY) { + miss: if (report && dst->sa_family != PF_KEY) { bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; rt_missmsg(msgtype, &info, 0, err); @@ -316,16 +313,14 @@ miss: if (report && dst->sa_family != PF_KEY) { void rtfree(struct rtentry *rt) { - struct ifaddr *ifa; + struct ifaddr *ifa; if (rt == NULL) panic("rtfree"); - rt->rt_refcnt--; - if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) - panic("rtfree 2"); + panic ("rtfree 2"); rttrash--; if (rt->rt_refcnt < 0) { printf("rtfree: %p not freed (neg refs)\n", rt); @@ -365,11 +360,11 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway, struct sockaddr *netmask, int flags, struct sockaddr *src, struct rtentry **rtp) { - struct rtentry *rt; - struct rt_addrinfo info; - struct ifaddr *ifa; - int error = 0; - u_int32_t *stat = NULL; + struct rtentry *rt; + int error = 0; + u_int32_t *stat = NULL; + struct rt_addrinfo info; + struct ifaddr *ifa; splassert(IPL_SOFTNET); @@ -388,7 +383,6 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway, #define equal(a1, a2) \ ((a1)->sa_len == (a2)->sa_len && \ bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) - if (!(flags & RTF_DONE) && rt && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) error = EINVAL; @@ -414,7 +408,7 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway, * Changing from route to net => route to host. * Create new route, rather than smashing route to net. */ -create: + create: if (rt) rtfree(rt); flags |= RTF_GATEWAY | RTF_DYNAMIC; @@ -467,8 +461,8 @@ out: int rtdeletemsg(struct rtentry *rt) { - int error; - struct rt_addrinfo info; + int error; + struct rt_addrinfo info; /* * Request the new route so that the entry is not actually @@ -495,8 +489,10 @@ rtdeletemsg(struct rtentry *rt) int rtflushclone1(struct radix_node *rn, void *arg) { - struct rtentry *rt = (struct rtentry *)rn, *parent = arg; + struct rtentry *rt, *parent; + rt = (struct rtentry *)rn; + parent = (struct rtentry *)arg; if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) rtdeletemsg(rt); return 0; @@ -512,9 +508,12 @@ rtflushclone(struct radix_node_head *rnh, struct rtentry *parent) if (!rnh->rnh_walktree) panic("rtflushclone: no rnh_walktree"); #endif - rnh->rnh_walktree(rnh, rtflushclone1, parent); + rnh->rnh_walktree(rnh, rtflushclone1, (void *)parent); } +/* +* Routing table ioctl interface. +*/ int rtioctl(u_long req, caddr_t data, struct proc *p) { @@ -524,7 +523,7 @@ rtioctl(u_long req, caddr_t data, struct proc *p) struct ifaddr * ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) { - struct ifaddr *ifa; + struct ifaddr *ifa; #ifdef IPSEC /* @@ -546,7 +545,7 @@ ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) * we can use the local address. */ ifa = NULL; - if (flags & RTF_HOST) + if (flags & RTF_HOST) ifa = ifa_ifwithdstaddr(dst); if (ifa == NULL) ifa = ifa_ifwithaddr(gateway); @@ -561,9 +560,8 @@ ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) if (ifa == NULL) ifa = ifa_ifwithnet(gateway); if (ifa == NULL) { - struct rtentry *rt; - - if ((rt = rtalloc1(gateway, 0)) == NULL) + struct rtentry *rt = rtalloc1(gateway, 0); + if (rt == NULL) return (NULL); rt->rt_refcnt--; /* The gateway must be local if the same address family. */ @@ -575,8 +573,8 @@ ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) } if (ifa->ifa_addr->sa_family != dst->sa_family) { struct ifaddr *oifa = ifa; - - if ((ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp)) == NULL) + ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); + if (ifa == NULL) ifa = oifa; } return (ifa); @@ -588,7 +586,7 @@ int rtrequest(int req, struct sockaddr *dst, struct sockaddr *gateway, struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) { - struct rt_addrinfo info; + struct rt_addrinfo info; bzero(&info, sizeof(info)); info.rti_flags = flags; @@ -598,42 +596,44 @@ rtrequest(int req, struct sockaddr *dst, struct sockaddr *gateway, return (rtrequest1(req, &info, ret_nrt)); } +/* + * These (questionable) definitions of apparent local variables apply + * to the next function. XXXXXX!!! + */ +#define dst info->rti_info[RTAX_DST] +#define gateway info->rti_info[RTAX_GATEWAY] +#define netmask info->rti_info[RTAX_NETMASK] +#define ifaaddr info->rti_info[RTAX_IFA] +#define ifpaddr info->rti_info[RTAX_IFP] +#define flags info->rti_flags + int rt_getifa(struct rt_addrinfo *info) { - struct ifaddr *ifa; - int error = 0; + struct ifaddr *ifa; + int error = 0; /* * ifp may be specified by sockaddr_dl when protocol address * is ambiguous */ - if (info->rti_ifp == NULL && info->rti_info[RTAX_IFP] != NULL - && info->rti_info[RTAX_IFP]->sa_family == AF_LINK && - (ifa = ifa_ifwithnet((struct sockaddr *)info->rti_info[RTAX_IFP])) - != NULL) + if (info->rti_ifp == NULL && ifpaddr != NULL + && ifpaddr->sa_family == AF_LINK && + (ifa = ifa_ifwithnet((struct sockaddr *)ifpaddr)) != NULL) info->rti_ifp = ifa->ifa_ifp; - - if (info->rti_ifa == NULL && info->rti_info[RTAX_IFA] != NULL) - info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA]); - + if (info->rti_ifa == NULL && ifaaddr != NULL) + info->rti_ifa = ifa_ifwithaddr(ifaaddr); if (info->rti_ifa == NULL) { struct sockaddr *sa; - if ((sa = info->rti_info[RTAX_IFA]) == NULL) - if ((sa = info->rti_info[RTAX_GATEWAY]) == NULL) - sa = info->rti_info[RTAX_DST]; - + sa = ifaaddr != NULL ? ifaaddr : + (gateway != NULL ? gateway : dst); if (sa != NULL && info->rti_ifp != NULL) info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); - else if (info->rti_info[RTAX_DST] != NULL && - info->rti_info[RTAX_GATEWAY] != NULL) - info->rti_ifa = ifa_ifwithroute(info->rti_flags, - info->rti_info[RTAX_DST], - info->rti_info[RTAX_GATEWAY]); + else if (dst != NULL && gateway != NULL) + info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); else if (sa != NULL) - info->rti_ifa = ifa_ifwithroute(info->rti_flags, - sa, sa); + info->rti_ifa = ifa_ifwithroute(flags, sa, sa); } if ((ifa = info->rti_ifa) != NULL) { if (info->rti_ifp == NULL) @@ -646,25 +646,22 @@ rt_getifa(struct rt_addrinfo *info) int rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) { - int s, error = 0; - struct rtentry *rt, *crt; - struct radix_node *rn; - struct radix_node_head *rnh; - struct ifaddr *ifa; - struct sockaddr *ndst; + int s = splsoftnet(); int error = 0; + struct rtentry *rt, *crt; + struct radix_node *rn; + struct radix_node_head *rnh; + struct ifaddr *ifa; + struct sockaddr *ndst; struct sockaddr_rtlabel *sa_rl; #define senderr(x) { error = x ; goto bad; } - s = splsoftnet(); - - if ((rnh = rt_tables[info->rti_info[RTAX_DST]->sa_family]) == 0) + if ((rnh = rt_tables[dst->sa_family]) == 0) senderr(EAFNOSUPPORT); - if (info->rti_flags & RTF_HOST) - info->rti_info[RTAX_NETMASK] = NULL; + if (flags & RTF_HOST) + netmask = 0; switch (req) { case RTM_DELETE: - if ((rn = rnh->rnh_lookup(info->rti_info[RTAX_DST], - info->rti_info[RTAX_NETMASK], rnh)) == NULL) + if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL) senderr(ESRCH); rt = (struct rtentry *)rn; #ifndef SMALL_KERNEL @@ -673,40 +670,34 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) * a matching RTAX_GATEWAY. */ if (rn_mpath_capable(rnh)) { - rt = rt_mpath_matchgate(rt, - info->rti_info[RTAX_GATEWAY]); + rt = rt_mpath_matchgate(rt, gateway); rn = (struct radix_node *)rt; if (!rt) senderr(ESRCH); } #endif - if ((rn = rnh->rnh_deladdr(info->rti_info[RTAX_DST], - info->rti_info[RTAX_NETMASK], rnh, rn)) == NULL) + if ((rn = rnh->rnh_deladdr(dst, netmask, rnh, rn)) == NULL) senderr(ESRCH); rt = (struct rtentry *)rn; - - /* clean up any cloned children */ - if ((rt->rt_flags & RTF_CLONING) != 0) + if ((rt->rt_flags & RTF_CLONING) != 0) { + /* clean up any cloned children */ rtflushclone(rnh, rt); - + } if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) panic ("rtrequest delete"); - + rt = (struct rtentry *)rn; if (rt->rt_gwroute) { rt = rt->rt_gwroute; RTFREE(rt); (rt = (struct rtentry *)rn)->rt_gwroute = NULL; } - if (rt->rt_parent) { rt->rt_parent->rt_refcnt--; rt->rt_parent = NULL; } - rt->rt_flags &= ~RTF_UP; if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) ifa->ifa_rtrequest(RTM_DELETE, rt, info); rttrash++; - if (ret_nrt) *ret_nrt = rt; else if (rt->rt_refcnt <= 0) { @@ -721,41 +712,37 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) if ((rt->rt_flags & RTF_CLONING) == 0) senderr(EINVAL); ifa = rt->rt_ifa; - info->rti_flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); - info->rti_flags |= RTF_CLONED; - info->rti_info[RTAX_GATEWAY] = rt->rt_gateway; - if ((info->rti_info[RTAX_NETMASK] = rt->rt_genmask) == NULL) - info->rti_flags |= RTF_HOST; + flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); + flags |= RTF_CLONED; + gateway = rt->rt_gateway; + if ((netmask = rt->rt_genmask) == NULL) + flags |= RTF_HOST; goto makeroute; case RTM_ADD: if (info->rti_ifa == 0 && (error = rt_getifa(info))) senderr(error); ifa = info->rti_ifa; -makeroute: + makeroute: rt = pool_get(&rtentry_pool, PR_NOWAIT); if (rt == NULL) senderr(ENOBUFS); Bzero(rt, sizeof(*rt)); - rt->rt_flags = RTF_UP | info->rti_flags; + rt->rt_flags = RTF_UP | flags; LIST_INIT(&rt->rt_timer); - if (rt_setgate(rt, info->rti_info[RTAX_DST], - info->rti_info[RTAX_GATEWAY])) { + if (rt_setgate(rt, dst, gateway)) { pool_put(&rtentry_pool, rt); senderr(ENOBUFS); } ndst = rt_key(rt); - if (info->rti_info[RTAX_NETMASK] != NULL) { - rt_maskedcopy(info->rti_info[RTAX_DST], ndst, - info->rti_info[RTAX_NETMASK]); + if (netmask) { + rt_maskedcopy(dst, ndst, netmask); } else - Bcopy(info->rti_info[RTAX_DST], ndst, - info->rti_info[RTAX_DST]->sa_len); + Bcopy(dst, ndst, dst->sa_len); #ifndef SMALL_KERNEL /* do not permit exactly the same dst/mask/gw pair */ if (rn_mpath_capable(rnh) && - rt_mpath_conflict(rnh, rt, info->rti_info[RTAX_NETMASK], - info->rti_flags & RTF_MPATH)) { + rt_mpath_conflict(rnh, rt, netmask, flags & RTF_MPATH)) { if (rt->rt_gwroute) rtfree(rt->rt_gwroute); Free(rt_key(rt)); @@ -782,15 +769,14 @@ makeroute: rt->rt_parent = *ret_nrt; /* Back ptr. to parent. */ rt->rt_parent->rt_refcnt++; } - rn = rnh->rnh_addaddr((caddr_t)ndst, - (caddr_t)info->rti_info[RTAX_NETMASK], rnh, rt->rt_nodes); + rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, + rnh, rt->rt_nodes); if (rn == NULL && (crt = rtalloc1(ndst, 0)) != NULL) { /* overwrite cloned route */ if ((crt->rt_flags & RTF_CLONED) != 0) { rtdeletemsg(crt); rn = rnh->rnh_addaddr((caddr_t)ndst, - (caddr_t)info->rti_info[RTAX_NETMASK], - rnh, rt->rt_nodes); + (caddr_t)netmask, rnh, rt->rt_nodes); } RTFREE(crt); } @@ -815,8 +801,7 @@ makeroute: rtflushclone(rnh, rt); } - if_group_routechange(info->rti_info[RTAX_DST], - info->rti_info[RTAX_NETMASK]); + if_group_routechange(dst, netmask); break; } bad: @@ -824,16 +809,20 @@ bad: return (error); } +#undef dst +#undef gateway +#undef netmask +#undef ifaaddr +#undef ifpaddr +#undef flags + int rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate) { - caddr_t new, old; - int dlen, glen; + caddr_t new, old; + int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); struct rtentry *rt = rt0; - dlen = ROUNDUP(dst->sa_len); - glen = ROUNDUP(gate->sa_len); - if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) { old = (caddr_t)rt_key(rt); R_Malloc(new, caddr_t, dlen + glen); @@ -877,11 +866,11 @@ void rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask) { - u_char *cp1 = (u_char *)src; - u_char *cp2 = (u_char *)dst; - u_char *cp3 = (u_char *)netmask; - u_char *cplim = cp2 + *cp3; - u_char *cplim2 = cp2 + *cp1; + u_char *cp1 = (u_char *)src; + u_char *cp2 = (u_char *)dst; + u_char *cp3 = (u_char *)netmask; + u_char *cplim = cp2 + *cp3; + u_char *cplim2 = cp2 + *cp1; *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ cp3 += 2; @@ -900,17 +889,19 @@ rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, int rtinit(struct ifaddr *ifa, int cmd, int flags) { - struct rtentry *rt; - struct sockaddr *dst, *deldst; - struct mbuf *m = NULL; - struct rtentry *nrt = NULL; - int error; - struct rt_addrinfo info; + struct rtentry *rt; + struct sockaddr *dst; + struct sockaddr *deldst; + struct mbuf *m = NULL; + struct rtentry *nrt = NULL; + int error; + struct rt_addrinfo info; dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; if (cmd == RTM_DELETE) { if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { - if ((m = m_get(M_DONTWAIT, MT_SONAME)) == NULL) + m = m_get(M_DONTWAIT, MT_SONAME); + if (m == NULL) return (ENOBUFS); deldst = mtod(m, struct sockaddr *); rt_maskedcopy(dst, deldst, ifa->ifa_netmask); @@ -920,11 +911,9 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) rt->rt_refcnt--; if (rt->rt_ifa != ifa) { if (m != NULL) - m_free(m); - if (flags & RTF_HOST) - return (EHOSTUNREACH); - else - return (ENETUNREACH); + (void) m_free(m); + return (flags & RTF_HOST ? EHOSTUNREACH + : ENETUNREACH); } } } @@ -952,7 +941,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) rt->rt_refcnt--; if (rt->rt_ifa != ifa) { printf("rtinit: wrong ifa (%p) was (%p)\n", - ifa, rt->rt_ifa); + ifa, rt->rt_ifa); if (rt->rt_ifa->ifa_rtrequest) rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, NULL); IFAFREE(rt->rt_ifa); @@ -984,8 +973,8 @@ static int rt_init_done = 0; (*r->rtt_func)(r->rtt_rt, r); \ } else { \ rtrequest((int) RTM_DELETE, \ - (struct sockaddr *)rt_key(r->rtt_rt), \ - 0, 0, 0, 0); \ + (struct sockaddr *)rt_key(r->rtt_rt), \ + 0, 0, 0, 0); \ } \ } @@ -999,7 +988,7 @@ static int rt_init_done = 0; void rt_timer_init() { - static struct timeout rt_timer_timeout; + static struct timeout rt_timer_timeout; KASSERT(rt_init_done == 0); @@ -1015,14 +1004,14 @@ rt_timer_init() struct rttimer_queue * rt_timer_queue_create(u_int timeout) { - struct rttimer_queue *rtq; + struct rttimer_queue *rtq; if (rt_init_done == 0) rt_timer_init(); R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); if (rtq == NULL) - return (NULL); + return (NULL); Bzero(rtq, sizeof *rtq); rtq->rtq_timeout = timeout; @@ -1036,13 +1025,14 @@ rt_timer_queue_create(u_int timeout) void rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) { + rtq->rtq_timeout = timeout; } void rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) { - struct rttimer *r; + struct rttimer *r; while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { LIST_REMOVE(r, rtt_link); @@ -1066,13 +1056,14 @@ rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) unsigned long rt_timer_count(struct rttimer_queue *rtq) { + return (rtq->rtq_count); } -void +void rt_timer_remove_all(struct rtentry *rt) { - struct rttimer *r; + struct rttimer *r; while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { LIST_REMOVE(r, rtt_link); @@ -1085,13 +1076,12 @@ rt_timer_remove_all(struct rtentry *rt) } } -int -rt_timer_add(struct rtentry *rt, - void (*func)(struct rtentry *, struct rttimer *), - struct rttimer_queue *queue) +int +rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *, + struct rttimer *), struct rttimer_queue *queue) { - struct rttimer *r; - long current_time; + struct rttimer *r; + long current_time; current_time = time_uptime; @@ -1113,7 +1103,8 @@ rt_timer_add(struct rtentry *rt, } } - if ((r = pool_get(&rttimer_pool, PR_NOWAIT)) == NULL) + r = pool_get(&rttimer_pool, PR_NOWAIT); + if (r == NULL) return (ENOBUFS); Bzero(r, sizeof(*r)); @@ -1124,7 +1115,7 @@ rt_timer_add(struct rtentry *rt, LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); r->rtt_queue->rtq_count++; - + return (0); } @@ -1132,14 +1123,16 @@ rt_timer_add(struct rtentry *rt, void rt_timer_timer(void *arg) { - struct timeout *to = arg; - struct rttimer_queue *rtq; - struct rttimer *r; - long current_time = time_uptime; - int s; + struct timeout *to = (struct timeout *)arg; + struct rttimer_queue *rtq; + struct rttimer *r; + long current_time; + int s; + + current_time = time_uptime; s = splsoftnet(); - for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; + for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; rtq = LIST_NEXT(rtq, rtq_link)) { while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && (r->rtt_time + rtq->rtq_timeout) < current_time) { @@ -1235,64 +1228,3 @@ rtlabel_unref(u_int16_t id) } } } - -void -rt_if_remove(struct ifnet *ifp) -{ - struct radix_node_head *rnh; - int i; - - for (i = 1; i <= AF_MAX; i++) - if ((rnh = rt_tables[i]) != NULL) - while ((*rnh->rnh_walktree)(rnh, - rt_if_remove_rtdelete, ifp) == EAGAIN) - ; -} - -/* - * Delete a route if it has a specific interface for output. - * This function complies to the rn_walktree callback API. - * - * Note that deleting a RTF_CLONING route can trigger the - * deletion of more entries, so we need to cancel the walk - * and return EAGAIN. The caller should restart the walk - * as long as EAGAIN is returned. - */ -int -rt_if_remove_rtdelete(struct radix_node *rn, void *vifp) -{ - struct ifnet *ifp = vifp; - struct rtentry *rt = (struct rtentry *)rn; - - if (rt->rt_ifp == ifp) { - int cloning = (rt->rt_flags & RTF_CLONING); - - if (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, - rt_mask(rt), 0, NULL) == 0 && cloning) - return (EAGAIN); - } - - /* - * XXX There should be no need to check for rt_ifa belonging to this - * interface, because then rt_ifp is set, right? - */ - - return (0); -} - -struct radix_node_head * -rt_gettable(sa_family_t af, int id) -{ - /* ignore id for now */ - return (rt_tables[af]); -} - -struct radix_node * -rt_lookup(struct sockaddr *dst, struct sockaddr *mask, int tableid) -{ - struct radix_node_head *rnh; - - rnh = rt_gettable(dst->sa_family, tableid); - - return (rnh->rnh_lookup(dst, mask, rnh)); -} diff --git a/sys/net/route.h b/sys/net/route.h index d6a3d2b1992..9d935799fed 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -1,4 +1,4 @@ -/* $OpenBSD: route.h,v 1.33 2005/11/27 16:22:45 henning Exp $ */ +/* $OpenBSD: route.h,v 1.34 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* @@ -299,6 +299,7 @@ void rtlabel_unref(u_int16_t); extern struct route_cb route_cb; extern struct rtstat rtstat; +extern struct radix_node_head *rt_tables[]; extern const struct sockaddr_rtin rt_defmask4; struct socket; @@ -345,10 +346,6 @@ int rtrequest(int, struct sockaddr *, struct sockaddr *, struct sockaddr *, int, struct rtentry **); int rtrequest1(int, struct rt_addrinfo *, struct rtentry **); -void rt_if_remove(struct ifnet *); - -struct radix_node_head *rt_gettable(sa_family_t, int); -struct radix_node *rt_lookup(struct sockaddr *, struct sockaddr *, int); #endif /* _KERNEL */ #endif /* _NET_ROUTE_H_ */ diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index f08605709b0..e1299d77e0b 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.50 2005/11/27 19:33:20 deraadt Exp $ */ +/* $OpenBSD: rtsock.c,v 1.51 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -165,9 +165,7 @@ route_output(struct mbuf *m, ...) struct radix_node *rn = NULL; struct rtentry *rt = NULL; struct rtentry *saved_nrt = NULL; -#ifndef SMALL_KERNEL struct radix_node_head *rnh; -#endif struct rt_addrinfo info; int len, error = 0; struct ifnet *ifp = NULL; @@ -264,11 +262,11 @@ route_output(struct mbuf *m, ...) case RTM_GET: case RTM_CHANGE: case RTM_LOCK: - if (rt_gettable(dst->sa_family, 0) == NULL) { + if ((rnh = rt_tables[dst->sa_family]) == 0) { error = EAFNOSUPPORT; goto flush; } - rn = rt_lookup(dst, netmask, 0); + rn = rnh->rnh_lookup(dst, netmask, rnh); if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) { error = ESRCH; goto flush; @@ -906,7 +904,7 @@ sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, case NET_RT_DUMP: case NET_RT_FLAGS: for (i = 1; i <= AF_MAX; i++) - if ((rnh = rt_gettable(i, 0)) && (af == 0 || af == i) && + if ((rnh = rt_tables[i]) && (af == 0 || af == i) && (error = (*rnh->rnh_walktree)(rnh, sysctl_dumpentry, &w))) break; |