diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2005-06-07 18:21:45 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2005-06-07 18:21:45 +0000 |
commit | b7e47a80cdc66f2726bd38e4b86ede0e27c29d02 (patch) | |
tree | aed7102a128bb77122f71da6681450c9a562f482 | |
parent | f3618e3949557b2911745765284653291329f89d (diff) |
introduce a default "external" interface group, containing the interface(s)
the the default route(s) point to.
handles IPv4 and IPv6 as well as multipath routes.
follows default route changes, of course.
eases writing pf rulesets especially on laptops etc. that use different
interfaces depending on the environment (wired, wireless, ...)
ok theo ryan
-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); |