diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 89 | ||||
-rw-r--r-- | sys/net/if.h | 14 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 23 | ||||
-rw-r--r-- | sys/net/if_fddisubr.c | 4 | ||||
-rw-r--r-- | sys/net/pf.c | 46 | ||||
-rw-r--r-- | sys/net/route.c | 71 | ||||
-rw-r--r-- | sys/net/route.h | 8 | ||||
-rw-r--r-- | sys/net/rtsock.c | 17 |
8 files changed, 188 insertions, 84 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 061b8772190..8dd2fd9582b 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.193 2009/06/04 19:07:21 henning Exp $ */ +/* $OpenBSD: if.c,v 1.194 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -878,7 +878,7 @@ if_congestion_clear(void *arg) */ /*ARGSUSED*/ struct ifaddr * -ifa_ifwithaddr(struct sockaddr *addr) +ifa_ifwithaddr(struct sockaddr *addr, u_int rdomain) { struct ifnet *ifp; struct ifaddr *ifa; @@ -887,6 +887,8 @@ ifa_ifwithaddr(struct sockaddr *addr) (bcmp((caddr_t)(a1), (caddr_t)(a2), \ ((struct sockaddr *)(a1))->sa_len) == 0) TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != rdomain) + continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; @@ -906,20 +908,22 @@ ifa_ifwithaddr(struct sockaddr *addr) */ /*ARGSUSED*/ struct ifaddr * -ifa_ifwithdstaddr(struct sockaddr *addr) +ifa_ifwithdstaddr(struct sockaddr *addr, u_int rdomain) { struct ifnet *ifp; struct ifaddr *ifa; TAILQ_FOREACH(ifp, &ifnet, if_list) { - if (ifp->if_flags & IFF_POINTOPOINT) - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { - if (ifa->ifa_addr->sa_family != addr->sa_family || - ifa->ifa_dstaddr == NULL) - continue; - if (equal(addr, ifa->ifa_dstaddr)) - return (ifa); - } + if (ifp->if_rdomain != rdomain) + continue; + if (ifp->if_flags & IFF_POINTOPOINT) + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != + addr->sa_family || ifa->ifa_dstaddr == NULL) + continue; + if (equal(addr, ifa->ifa_dstaddr)) + return (ifa); + } } return (NULL); } @@ -929,7 +933,7 @@ ifa_ifwithdstaddr(struct sockaddr *addr) * is most specific found. */ struct ifaddr * -ifa_ifwithnet(struct sockaddr *addr) +ifa_ifwithnet(struct sockaddr *addr, u_int rdomain) { struct ifnet *ifp; struct ifaddr *ifa; @@ -944,6 +948,8 @@ ifa_ifwithnet(struct sockaddr *addr) return (ifnet_addrs[sdl->sdl_index]); } TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != rdomain) + continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { char *cp, *cp2, *cp3; @@ -972,12 +978,14 @@ ifa_ifwithnet(struct sockaddr *addr) * Find an interface using a specific address family */ struct ifaddr * -ifa_ifwithaf(int af) +ifa_ifwithaf(int af, u_int rdomain) { struct ifnet *ifp; struct ifaddr *ifa; TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != rdomain) + continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == af) return (ifa); @@ -1202,7 +1210,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) { struct ifnet *ifp; struct ifreq *ifr; - struct ifaddr *ifa; + struct ifaddr *ifa, *nifa; struct sockaddr_dl *sdl; struct ifgroupreq *ifgr; char ifdescrbuf[IFDESCRSIZE]; @@ -1403,6 +1411,59 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) ifp->if_priority = ifr->ifr_metric; break; + case SIOCGIFRTABLEID: + ifr->ifr_rdomainid = ifp->if_rdomain; + break; + + case SIOCSIFRTABLEID: + if ((error = suser(p, 0)) != 0) + return (error); + if (ifr->ifr_rdomainid < 0 || + ifr->ifr_rdomainid > RT_TABLEID_MAX) + return (EINVAL); + /* remove all routing entries when switching domains */ + /* XXX hell this is ugly */ + if (ifr->ifr_rdomainid != ifp->if_rdomain) { + rt_if_remove(ifp); +#ifdef INET + rti_delete(ifp); +#if NETHER > 0 + myip_ifp = NULL; +#endif +#ifdef MROUTING + vif_delete(ifp); +#endif +#endif +#ifdef INET6 + in6_ifdetach(ifp); +#endif +#ifdef INET + for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; + ifa = nifa) { + nifa = TAILQ_NEXT(ifa, ifa_list); + + /* only remove AF_INET */ + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + TAILQ_REMOVE(&in_ifaddr, + (struct in_ifaddr *)ifa, ia_list); + TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); + ifa->ifa_ifp = NULL; + IFAFREE(ifa); + } +#endif + } + + /* make sure that the routing table exists */ + if (!rtable_exists(ifr->ifr_rdomainid)) { + if (rtable_add(ifr->ifr_rdomainid) == -1) + panic("rtinit: rtable_add"); + } + + ifp->if_rdomain = ifr->ifr_rdomainid; + break; + case SIOCAIFGROUP: if ((error = suser(p, 0))) return (error); diff --git a/sys/net/if.h b/sys/net/if.h index 94885445c40..65e40ef621f 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.105 2009/06/04 19:07:21 henning Exp $ */ +/* $OpenBSD: if.h,v 1.106 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -215,6 +215,7 @@ struct ifnet { /* and the entries */ struct if_data if_data; /* stats and other data about if */ u_int32_t if_hardmtu; /* maximum MTU device supports */ int if_capabilities; /* interface capabilities */ + u_int if_rdomain; /* routing instance */ char if_description[IFDESCRSIZE]; /* interface description */ u_short if_rtlabelid; /* next route label */ u_int8_t if_priority; @@ -588,6 +589,7 @@ struct ifreq { #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_metric /* mtu (overload) */ #define ifr_media ifr_ifru.ifru_metric /* media options (overload) */ +#define ifr_rdomainid ifr_ifru.ifru_metric /* VRF instance (overload) */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ }; @@ -804,12 +806,12 @@ void if_group_routechange(struct sockaddr *, struct sockaddr *); struct ifnet *ifunit(const char *); void if_start(struct ifnet *); -struct ifaddr *ifa_ifwithaddr(struct sockaddr *); -struct ifaddr *ifa_ifwithaf(int); -struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); -struct ifaddr *ifa_ifwithnet(struct sockaddr *); +struct ifaddr *ifa_ifwithaddr(struct sockaddr *, u_int); +struct ifaddr *ifa_ifwithaf(int, u_int); +struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *, u_int); +struct ifaddr *ifa_ifwithnet(struct sockaddr *, u_int); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, - struct sockaddr *); + struct sockaddr *, u_int); struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); void ifafree(struct ifaddr *); void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 5a6ce60cc0d..d0166e2e84a 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.132 2009/03/05 19:47:05 michele Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.133 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -230,6 +230,15 @@ ether_output(ifp0, m0, dst, rt0) short mflags; struct ifnet *ifp = ifp0; +#ifdef DIAGNOSTIC + if (ifp->if_rdomain != m->m_pkthdr.rdomain) { + printf("%s: trying to send packet on wrong domain. " + "%d vs. %d, AF %d\n", ifp->if_xname, ifp->if_rdomain, + m->m_pkthdr.rdomain, dst->sa_family); + senderr(ENETDOWN); + } +#endif + #if NTRUNK > 0 if (ifp->if_type == IFT_IEEE8023ADLAG) senderr(EBUSY); @@ -241,7 +250,8 @@ ether_output(ifp0, m0, dst, rt0) /* loop back if this is going to the carp interface */ if (dst != NULL && LINK_STATE_IS_UP(ifp0->if_link_state) && - (ifa = ifa_ifwithaddr(dst)) != NULL && + /* XXX why ifa_ifwithaddr() and not ifaof_ifpforaddr() */ + (ifa = ifa_ifwithaddr(dst, ifp->if_rdomain)) != NULL && ifa->ifa_ifp == ifp0) return (looutput(ifp0, m, dst, rt0)); @@ -258,7 +268,8 @@ ether_output(ifp0, m0, dst, rt0) senderr(ENETDOWN); if ((rt = rt0) != NULL) { if ((rt->rt_flags & RTF_UP) == 0) { - if ((rt0 = rt = rtalloc1(dst, 1, 0)) != NULL) + if ((rt0 = rt = rtalloc1(dst, 1, + m->m_pkthdr.pf.rtableid)) != NULL) rt->rt_refcnt--; else senderr(EHOSTUNREACH); @@ -274,7 +285,8 @@ ether_output(ifp0, m0, dst, rt0) goto lookup; if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { rtfree(rt); rt = rt0; - lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0); + lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, + ifp->if_rdomain); if ((rt = rt->rt_gwroute) == 0) senderr(EHOSTUNREACH); } @@ -532,6 +544,9 @@ ether_input(ifp0, eh, m) m_cluncount(m, 1); + /* mark incomming routing domain */ + m->m_pkthdr.rdomain = ifp->if_rdomain; + if (eh == NULL) { eh = mtod(m, struct ether_header *); m_adj(m, ETHER_HDR_LEN); diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index e33adfb9a0a..a43177f5089 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_fddisubr.c,v 1.54 2008/05/07 13:45:35 dlg Exp $ */ +/* $OpenBSD: if_fddisubr.c,v 1.55 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: if_fddisubr.c,v 1.5 1996/05/07 23:20:21 christos Exp $ */ /* @@ -154,7 +154,7 @@ fddi_output(ifp0, m0, dst, rt0) /* loop back if this is going to the carp interface */ if (dst != NULL && LINK_STATE_IS_UP(ifp0->if_link_state) && - (ifa = ifa_ifwithaddr(dst)) != NULL && + (ifa = ifa_ifwithaddr(dst, ifp->if_rdomain)) != NULL && ifa->ifa_ifp == ifp0) return (looutput(ifp0, m, dst, rt0)); diff --git a/sys/net/pf.c b/sys/net/pf.c index 2c68a807512..b3da5a1ca67 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.648 2009/05/18 20:37:13 bluhm Exp $ */ +/* $OpenBSD: pf.c,v 1.649 2009/06/05 00:05:21 claudio Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -153,8 +153,8 @@ void pf_send_tcp(const struct pf_rule *, sa_family_t, const struct pf_addr *, const struct pf_addr *, u_int16_t, u_int16_t, u_int32_t, u_int32_t, u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, - u_int16_t, struct ether_header *, struct ifnet *, - int); + u_int16_t, u_short, struct ether_header *, + struct ifnet *, int); void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, sa_family_t, struct pf_rule *, int); void pf_detach_state(struct pf_state *); @@ -1093,6 +1093,10 @@ pf_src_tree_remove_state(struct pf_state *s) void pf_unlink_state(struct pf_state *cur) { + /* + * XXX XXX XXX state needs to know routing domain so that states + * XXX XXX XXX can not float between domain. May simplify other code. + */ splsoftassert(IPL_SOFTNET); if (cur->src.state == PF_TCPS_PROXY_DST) { @@ -1103,7 +1107,7 @@ pf_unlink_state(struct pf_state *cur) cur->key[PF_SK_WIRE]->port[1], cur->key[PF_SK_WIRE]->port[0], cur->src.seqhi, cur->src.seqlo + 1, - TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL, + TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, 0, NULL, NULL, cur->rtableid); } RB_REMOVE(pf_state_tree_id, &tree_id, cur); @@ -1878,7 +1882,8 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af, const struct pf_addr *saddr, const struct pf_addr *daddr, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, - u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp, int rtableid) + u_int16_t rtag, u_short rdom, struct ether_header *eh, struct ifnet *ifp, + int rtableid) { struct mbuf *m; int len, tlen; @@ -1916,6 +1921,7 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af, if (tag) m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; m->m_pkthdr.pf.tag = rtag; + m->m_pkthdr.rdomain = rdom; if (rtableid >= 0) m->m_pkthdr.pf.rtableid = rtableid; @@ -2040,6 +2046,7 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af, return; m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED; + m0->m_pkthdr.rdomain = m->m_pkthdr.rdomain; if (rtableid >= 0) m0->m_pkthdr.pf.rtableid = rtableid; @@ -2402,10 +2409,11 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd) switch (pd->af) { #ifdef INET case AF_INET: - inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport); + inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport, + /* XXX */ 0); if (inp == NULL) { inp = in_pcblookup_listen(tb, daddr->v4, dport, 0, - NULL); + NULL, 0); if (inp == NULL) return (-1); } @@ -2526,6 +2534,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer) int hlen; u_int16_t mss = tcp_mssdflt; + /* XXX needs to know about routing domain or actually rtableid */ switch (af) { #ifdef INET case AF_INET: @@ -3018,8 +3027,8 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, pf_send_tcp(r, af, pd->dst, pd->src, th->th_dport, th->th_sport, ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0, - r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp, - act.rtableid); + r->return_ttl, 1, 0, m->m_pkthdr.rdomain, + pd->eh, kif->pfik_ifp, act.rtableid); } } else if (pd->proto != IPPROTO_ICMP && af == AF_INET && r->return_icmp) @@ -3280,8 +3289,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, s->src.mss = mss; pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1, - TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL, - act->rtableid); + TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, /* XXX */ 0, NULL, NULL, act->rtableid); REASON_SET(&reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } @@ -3694,7 +3702,8 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, th->th_sport, ntohl(th->th_ack), 0, TH_RST, 0, 0, (*state)->rule.ptr->return_ttl, 1, 0, - pd->eh, kif->pfik_ifp, (*state)->rtableid); + m->m_pkthdr.rdomain, pd->eh, + kif->pfik_ifp, (*state)->rtableid); src->seqlo = 0; src->seqhi = 1; src->max_win = 1; @@ -3846,7 +3855,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, pd->src, th->th_dport, th->th_sport, (*state)->src.seqhi, ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1, - 0, NULL, NULL, (*state)->rtableid); + 0, /* XXX */ 0, NULL, NULL, (*state)->rtableid); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if (!(th->th_flags & TH_ACK) || @@ -3876,8 +3885,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, &sk->addr[pd->sidx], &sk->addr[pd->didx], sk->port[pd->sidx], sk->port[pd->didx], (*state)->dst.seqhi, 0, TH_SYN, 0, - (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL, - (*state)->rtableid); + (*state)->src.mss, 0, 0, (*state)->tag, /* XXX */ 0, + NULL, NULL, (*state)->rtableid); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if (((th->th_flags & (TH_SYN|TH_ACK)) != @@ -3892,13 +3901,14 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, pd->src, th->th_dport, th->th_sport, ntohl(th->th_ack), ntohl(th->th_seq) + 1, TH_ACK, (*state)->src.max_win, 0, 0, 0, - (*state)->tag, NULL, NULL, (*state)->rtableid); + (*state)->tag, /* XXX */ 0, NULL, NULL, + (*state)->rtableid); pf_send_tcp((*state)->rule.ptr, pd->af, &sk->addr[pd->sidx], &sk->addr[pd->didx], sk->port[pd->sidx], sk->port[pd->didx], (*state)->src.seqhi + 1, (*state)->src.seqlo + 1, TH_ACK, (*state)->dst.max_win, 0, 0, 1, - 0, NULL, NULL, (*state)->rtableid); + 0, /* XXX */ 0, NULL, NULL, (*state)->rtableid); (*state)->src.seqdiff = (*state)->dst.seqhi - (*state)->src.seqlo; (*state)->dst.seqdiff = (*state)->src.seqhi - @@ -4827,6 +4837,7 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif) struct rtentry *rt; struct ifnet *ifp; + /* XXX needs to know about routing domain or actually rtableid */ check_mpath = 0; bzero(&ro, sizeof(ro)); switch (af) { @@ -4908,6 +4919,7 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw) #endif int ret = 0; + /* XXX needs to know about routing domain or actually rtableid */ bzero(&ro, sizeof(ro)); switch (af) { case AF_INET: diff --git a/sys/net/route.c b/sys/net/route.c index c09effaf253..d2acd43bd47 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.108 2009/05/31 04:07:03 claudio Exp $ */ +/* $OpenBSD: route.c,v 1.109 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -251,7 +251,7 @@ rtable_exists(u_int id) /* verify table with that ID exists */ if (id > rtbl_id_max) return (0); - if (rt_tables[id] == NULL) /* should not happen */ + if (rt_tables[id] == NULL) return (0); return (1); @@ -450,7 +450,7 @@ ifafree(struct ifaddr *ifa) void rtredirect(struct sockaddr *dst, struct sockaddr *gateway, struct sockaddr *netmask, int flags, struct sockaddr *src, - struct rtentry **rtp) + struct rtentry **rtp, u_int rdomain) { struct rtentry *rt; int error = 0; @@ -462,12 +462,12 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway, splsoftassert(IPL_SOFTNET); /* verify the gateway is directly reachable */ - if ((ifa = ifa_ifwithnet(gateway)) == NULL) { + if ((ifa = ifa_ifwithnet(gateway, rdomain)) == NULL) { error = ENETUNREACH; goto out; } ifp = ifa->ifa_ifp; - rt = rtalloc1(dst, 0, 0); + rt = rtalloc1(dst, 0, rdomain); /* * If the redirect isn't from our current router for this dst, * it's either old or wrong. If it redirects us to ourselves, @@ -480,7 +480,7 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway, if (!(flags & RTF_DONE) && rt && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) error = EINVAL; - else if (ifa_ifwithaddr(gateway) != NULL) + else if (ifa_ifwithaddr(gateway, rdomain) != NULL) error = EHOSTUNREACH; if (error) goto done; @@ -513,7 +513,8 @@ create: info.rti_ifa = ifa; info.rti_flags = flags; rt = NULL; - error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &rt, 0); + error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &rt, + rdomain); if (rt != NULL) flags = rt->rt_flags; stat = &rtstat.rts_dynamic; @@ -525,7 +526,7 @@ create: rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; stat = &rtstat.rts_newgateway; - rt_setgate(rt, rt_key(rt), gateway, 0); + rt_setgate(rt, rt_key(rt), gateway, rdomain); } } else error = EHOSTUNREACH; @@ -546,7 +547,7 @@ out: info.rti_info[RTAX_GATEWAY] = gateway; info.rti_info[RTAX_NETMASK] = netmask; info.rti_info[RTAX_AUTHOR] = src; - rt_missmsg(RTM_REDIRECT, &info, flags, ifp, error, 0); + rt_missmsg(RTM_REDIRECT, &info, flags, ifp, error, rdomain); } /* @@ -614,7 +615,8 @@ rtioctl(u_long req, caddr_t data, struct proc *p) } struct ifaddr * -ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) +ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway, + u_int rdomain) { struct ifaddr *ifa; @@ -639,21 +641,21 @@ ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) */ ifa = NULL; if (flags & RTF_HOST) - ifa = ifa_ifwithdstaddr(dst); + ifa = ifa_ifwithdstaddr(dst, rdomain); if (ifa == NULL) - ifa = ifa_ifwithaddr(gateway); + ifa = ifa_ifwithaddr(gateway, rdomain); } else { /* * If we are adding a route to a remote net * or host, the gateway may still be on the * other end of a pt to pt link. */ - ifa = ifa_ifwithdstaddr(gateway); + ifa = ifa_ifwithdstaddr(gateway, rdomain); } if (ifa == NULL) - ifa = ifa_ifwithnet(gateway); + ifa = ifa_ifwithnet(gateway, rdomain); if (ifa == NULL) { - struct rtentry *rt = rtalloc1(gateway, 0, 0); + struct rtentry *rt = rtalloc1(gateway, 0, rdomain); if (rt == NULL) return (NULL); rt->rt_refcnt--; @@ -676,7 +678,7 @@ ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int -rt_getifa(struct rt_addrinfo *info) +rt_getifa(struct rt_addrinfo *info, u_int rdom) { struct ifaddr *ifa; int error = 0; @@ -687,12 +689,12 @@ rt_getifa(struct rt_addrinfo *info) */ 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) + (ifa = ifa_ifwithnet((struct sockaddr *)info->rti_info[RTAX_IFP], + rdom)) != 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]); + info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA], rdom); if (info->rti_ifa == NULL) { struct sockaddr *sa; @@ -707,10 +709,11 @@ rt_getifa(struct rt_addrinfo *info) info->rti_info[RTAX_GATEWAY] != NULL) info->rti_ifa = ifa_ifwithroute(info->rti_flags, info->rti_info[RTAX_DST], - info->rti_info[RTAX_GATEWAY]); + info->rti_info[RTAX_GATEWAY], + rdom); else if (sa != NULL) info->rti_ifa = ifa_ifwithroute(info->rti_flags, - sa, sa); + sa, sa, rdom); } if ((ifa = info->rti_ifa) != NULL) { if (info->rti_ifp == NULL) @@ -820,7 +823,8 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, goto makeroute; case RTM_ADD: - if (info->rti_ifa == 0 && (error = rt_getifa(info))) + if (info->rti_ifa == 0 && (error = rt_getifa(info, + /* XXX wrong because only rdomains allowed */ tableid))) senderr(error); ifa = info->rti_ifa; makeroute: @@ -1057,6 +1061,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) int error; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; + u_short rtableid = ifa->ifa_ifp->if_rdomain; dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; if (cmd == RTM_DELETE) { @@ -1068,7 +1073,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) rt_maskedcopy(dst, deldst, ifa->ifa_netmask); dst = deldst; } - if ((rt = rtalloc1(dst, 0, 0)) != NULL) { + if ((rt = rtalloc1(dst, 0, rtableid)) != NULL) { rt->rt_refcnt--; if (rt->rt_ifa != ifa) { if (m != NULL) @@ -1094,7 +1099,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) * change it to meet bsdi4 behavior. */ info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; - error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, 0); + error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, rtableid); if (cmd == RTM_DELETE && error == 0 && (rt = nrt) != NULL) { rt_newaddrmsg(cmd, ifa, error, nrt); if (rt->rt_refcnt <= 0) { @@ -1289,6 +1294,8 @@ rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *, struct radix_node_head * rt_gettable(sa_family_t af, u_int id) { + if (id > rtbl_id_max) + return (NULL); return (rt_tables[id] ? rt_tables[id][af2rtafidx[af]] : NULL); } @@ -1431,13 +1438,17 @@ void rt_if_remove(struct ifnet *ifp) { int i; + u_int tid; struct radix_node_head *rnh; - for (i = 1; i <= AF_MAX; i++) - if ((rnh = rt_gettable(i, 0)) != NULL) - while ((*rnh->rnh_walktree)(rnh, - rt_if_remove_rtdelete, ifp) == EAGAIN) - ; /* nothing */ + for (tid = 0; tid <= rtbl_id_max; tid++) { + for (i = 1; i <= AF_MAX; i++) { + if ((rnh = rt_gettable(i, tid)) != NULL) + while ((*rnh->rnh_walktree)(rnh, + rt_if_remove_rtdelete, ifp) == EAGAIN) + ; /* nothing */ + } + } } /* @@ -1455,7 +1466,7 @@ rt_if_remove_rtdelete(struct radix_node *rn, void *vifp) if (rt->rt_ifp == ifp) { int cloning = (rt->rt_flags & RTF_CLONING); - if (rtdeletemsg(rt, 0) == 0 && cloning) + if (rtdeletemsg(rt, ifp->if_rdomain /* XXX wrong */) == 0 && cloning) return (EAGAIN); } diff --git a/sys/net/route.h b/sys/net/route.h index 728ce54a6d6..d79c3d93883 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -1,4 +1,4 @@ -/* $OpenBSD: route.h,v 1.62 2009/05/26 08:29:44 reyk Exp $ */ +/* $OpenBSD: route.h,v 1.63 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* @@ -351,8 +351,6 @@ struct sockaddr_rtlabel { char sr_label[RTLABEL_LEN]; }; -#define RT_TABLEID_MAX 255 - #ifdef _KERNEL const char *rtlabel_id2name(u_int16_t); u_int16_t rtlabel_name2id(char *); @@ -416,12 +414,12 @@ void rtalloc_noclone(struct route *, int); struct rtentry * rtalloc2(struct sockaddr *, int, int); void rtfree(struct rtentry *); -int rt_getifa(struct rt_addrinfo *); +int rt_getifa(struct rt_addrinfo *, u_int); int rtinit(struct ifaddr *, int, int); int rtioctl(u_long, caddr_t, struct proc *); void rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, int, struct sockaddr *, - struct rtentry **); + struct rtentry **, u_int); int rtrequest1(int, struct rt_addrinfo *, u_int8_t, struct rtentry **, u_int); void rt_if_remove(struct ifnet *); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 536debd3bb4..f1615869a99 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.87 2009/05/31 18:00:54 claudio Exp $ */ +/* $OpenBSD: rtsock.c,v 1.88 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -620,19 +620,22 @@ report: * flags may also be different; ifp may be specified * by ll sockaddr when protocol address is ambiguous */ - if ((error = rt_getifa(&info)) != 0) + if ((error = rt_getifa(&info, + /* XXX wrong, only rdomain */ tableid)) != 0) goto flush; if (gate && rt_setgate(rt, rt_key(rt), gate, tableid)) { error = EDQUOT; goto flush; } - if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && + if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr, + /* XXX again rtable vs. rdomain */ tableid)) && (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, - ifp); - else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || + ifp); + else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr, + /* XXX one more time */ tableid))) || (gate && (ifa = ifa_ifwithroute(rt->rt_flags, - rt_key(rt), gate)))) + rt_key(rt), gate, /* XXX again */ tableid)))) ifp = ifa->ifa_ifp; if (ifa) { struct ifaddr *oifa = rt->rt_ifa; @@ -1062,6 +1065,7 @@ rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) ifam->ifam_metric = ifa->ifa_metric; ifam->ifam_flags = ifa->ifa_flags; ifam->ifam_addrs = info.rti_addrs; + ifam->ifam_tableid = ifp->if_rdomain; } if ((cmd == RTM_ADD && pass == 2) || (cmd == RTM_DELETE && pass == 1)) { @@ -1079,6 +1083,7 @@ rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) rtm->rtm_flags |= rt->rt_flags; rtm->rtm_errno = error; rtm->rtm_addrs = info.rti_addrs; + rtm->rtm_tableid = ifp->if_rdomain; } if (sa == NULL) route_proto.sp_protocol = 0; |