diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if.c | 81 | ||||
-rw-r--r-- | sys/net/if.h | 6 | ||||
-rw-r--r-- | sys/net/route.c | 4 | ||||
-rw-r--r-- | sys/net/rtsock.c | 3 |
4 files changed, 89 insertions, 5 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 12767ea05ee..f6b668015ae 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.127 2005/06/07 02:45:11 henning Exp $ */ +/* $OpenBSD: if.c,v 1.128 2005/06/07 18:21:44 henning Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -140,6 +140,7 @@ int if_clone_list(struct if_clonereq *); struct if_clone *if_clone_lookup(const char *, int *); void if_congestion_clear(void *); +int if_group_ext_build(void); TAILQ_HEAD(, ifg_group) ifg_head; LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); @@ -1717,6 +1718,84 @@ if_getgroup(caddr_t data, struct ifnet *ifp) return (0); } +void +if_group_routechange(struct sockaddr *dst, struct sockaddr *mask) +{ + switch (dst->sa_family) { + case AF_INET: + if (satosin(dst)->sin_addr.s_addr == INADDR_ANY && + satosin(mask)->sin_addr.s_addr == INADDR_ANY) + if_group_ext_build(); + break; + case AF_INET6: + if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr, + &in6addr_any) && + IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr, + &in6addr_any)) + if_group_ext_build(); + break; + } +} + +int +if_group_ext_build(void) +{ + struct ifg_group *ifg; + struct ifg_member *ifgm, *next; + struct sockaddr_in sa_in; + struct sockaddr_in6 sa_in6; + struct radix_node_head *rnh; + struct radix_node *rn; + struct rtentry *rt; + + TAILQ_FOREACH(ifg, &ifg_head, ifg_next) + if (!strcmp(ifg->ifg_group, IFG_EXTERNAL)) + break; + + if (ifg != NULL) + for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) { + next = TAILQ_NEXT(ifgm, ifgm_next); + if_delgroup(ifgm->ifgm_ifp, IFG_EXTERNAL); + } + + 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 = rnh->rnh_lookup(&sa_in, &sa_in, rnh))) { + do { + rt = (struct rtentry *)rn; + if (rt->rt_ifp) + if_addgroup(rt->rt_ifp, IFG_EXTERNAL); + if (rn_mpath_capable(rnh)) + rn = rn_mpath_next(rn); + else + 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 = rnh->rnh_lookup(&sa_in6, &sa_in6, rnh))) { + do { + rt = (struct rtentry *)rn; + if (rt->rt_ifp) + if_addgroup(rt->rt_ifp, IFG_EXTERNAL); + if (rn_mpath_capable(rnh)) + rn = rn_mpath_next(rn); + else + rn = NULL; + } while (rn != NULL); + } +#endif + + return (0); +} /* * Set/clear promiscuous mode on interface ifp based on the truth value diff --git a/sys/net/if.h b/sys/net/if.h index 96a8f974b7e..97207738034 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.72 2005/06/06 03:44:21 henning Exp $ */ +/* $OpenBSD: if.h,v 1.73 2005/06/07 18:21:44 henning Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -425,7 +425,8 @@ struct if_announcemsghdr { * interface groups */ -#define IFG_ALL "all" /* group containing all interfaces */ +#define IFG_ALL "all" /* group contains all interfaces */ +#define IFG_EXTERNAL "external" /* if(s) default route(s) point to */ struct ifg_group { char ifg_group[IFNAMSIZ]; @@ -690,6 +691,7 @@ int ifpromisc(struct ifnet *, int); int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); int if_getgroup(caddr_t, struct ifnet *); +void if_group_routechange(struct sockaddr *, struct sockaddr *); struct ifnet *ifunit(const char *); struct ifaddr *ifa_ifwithaddr(struct sockaddr *); diff --git a/sys/net/route.c b/sys/net/route.c index c5864cbcbd0..c5f8baa38a4 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.51 2005/05/15 16:40:09 henning Exp $ */ +/* $OpenBSD: route.c,v 1.52 2005/06/07 18:21:44 henning Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -804,6 +804,8 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) /* clean up any cloned children */ rtflushclone(rnh, rt); } + + if_group_routechange(dst, netmask); break; } bad: diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 2b52966aac8..9fecef9a33d 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.46 2005/05/27 22:37:46 mcbride Exp $ */ +/* $OpenBSD: rtsock.c,v 1.47 2005/06/07 18:21:44 henning Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -416,6 +416,7 @@ report: rt->rt_labelid = rtlabel_name2id(rtlabel); } + if_group_routechange(dst, netmask); /* fallthrough */ case RTM_LOCK: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); |