diff options
Diffstat (limited to 'sys')
-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 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_carp.c | 16 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 4 |
8 files changed, 262 insertions, 273 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; diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 1fc87a02cf6..4bd58fa0e4f 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.c,v 1.60 2005/11/27 16:22:45 henning Exp $ */ +/* $OpenBSD: if_ether.c,v 1.61 2005/11/29 02:59:42 jolan Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* @@ -1077,7 +1077,7 @@ int db_show_arptab() { struct radix_node_head *rnh; - rnh = rt_gettable(AF_INET, 0); + rnh = rt_tables[AF_INET]; db_printf("Route tree for AF_INET\n"); if (rnh == NULL) { db_printf(" (not initialized)\n"); diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index ded38f8d7a7..0f48a1d7681 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.116 2005/11/27 16:22:45 henning Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.117 2005/11/29 02:59:42 jolan Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -339,8 +339,10 @@ carp_setroute(struct carp_softc *sc, int cmd) case AF_INET: { int count = 0; struct sockaddr sa; - struct sockaddr_in mask; struct rtentry *rt; + struct radix_node_head *rnh = + rt_tables[ifa->ifa_addr->sa_family]; + struct radix_node *rn; int hr_otherif, nr_ourif; /* @@ -364,9 +366,8 @@ carp_setroute(struct carp_softc *sc, int cmd) RTF_HOST, NULL); /* Check for our address on another interface */ - memset(&mask, 1, sizeof(mask)); - rt = (struct rtentry *)rt_lookup(ifa->ifa_addr, - sintosa(&mask), 0); + rn = rnh->rnh_matchaddr(ifa->ifa_addr, rnh); + rt = (struct rtentry *)rn; hr_otherif = (rt && rt->rt_ifp != &sc->sc_if && rt->rt_flags & (RTF_CLONING|RTF_CLONED)); @@ -374,9 +375,8 @@ carp_setroute(struct carp_softc *sc, int cmd) bcopy(ifa->ifa_addr, &sa, sizeof(sa)); satosin(&sa)->sin_addr.s_addr = satosin(ifa->ifa_netmask )->sin_addr.s_addr & satosin(&sa)->sin_addr.s_addr; - - rt = (struct rtentry *)rt_lookup(&sa, - ifa->ifa_netmask, 0); + rn = rnh->rnh_lookup(&sa, ifa->ifa_netmask, rnh); + rt = (struct rtentry *)rn; nr_ourif = (rt && rt->rt_ifp == &sc->sc_if); switch (cmd) { diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 4bbd7e1dc03..30a39d7b299 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_rtr.c,v 1.34 2005/11/27 16:22:45 henning Exp $ */ +/* $OpenBSD: nd6_rtr.c,v 1.35 2005/11/29 02:59:42 jolan Exp $ */ /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */ /* @@ -1789,7 +1789,7 @@ rt6_flush(gateway, ifp) struct in6_addr *gateway; struct ifnet *ifp; { - struct radix_node_head *rnh = rt_gettable(AF_INET6, 0); + struct radix_node_head *rnh = rt_tables[AF_INET6]; int s = splsoftnet(); /* We'll care only link-local addresses */ |