diff options
38 files changed, 501 insertions, 287 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index acd7a7f4330..cd45d0d0491 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.120 2009/06/02 00:05:13 blambert Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.121 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -224,6 +224,7 @@ m_gethdr(int nowait, int type) m->m_data = m->m_pktdat; m->m_flags = M_PKTHDR; m->m_pkthdr.rcvif = NULL; + m->m_pkthdr.rdomain = 0; SLIST_INIT(&m->m_pkthdr.tags); m->m_pkthdr.csum_flags = 0; m->m_pkthdr.ether_vtag = 0; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 9841a6396e0..3c56aee1b3e 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.76 2009/03/15 19:40:41 miod Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.77 2009/06/05 00:05:21 claudio Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -46,6 +46,7 @@ #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/resourcevar.h> +#include <net/route.h> #include <sys/pool.h> void filt_sordetach(struct knote *kn); @@ -986,6 +987,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) } else { switch (optname) { case SO_BINDANY: + case SO_RDOMAIN: if ((error = suser(curproc, 0)) != 0) /* XXX */ goto bad; break; 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; diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 695ecbbea4b..cd814028cee 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.c,v 1.79 2008/12/24 08:26:27 claudio Exp $ */ +/* $OpenBSD: if_ether.c,v 1.80 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* @@ -82,7 +82,7 @@ int arpt_down = 20; /* once declared down, don't send for 20 secs */ void arptfree(struct llinfo_arp *); void arptimer(void *); -struct llinfo_arp *arplookup(u_int32_t, int, int); +struct llinfo_arp *arplookup(u_int32_t, int, int, u_int); void in_arpinput(struct mbuf *); LIST_HEAD(, llinfo_arp) llinfo_arp; @@ -200,7 +200,8 @@ arp_rtrequest(req, rt, info) * Case 1: This route should come from a route to iface. */ rt_setgate(rt, rt_key(rt), - (struct sockaddr *)&null_sdl, 0); + (struct sockaddr *)&null_sdl, + rt->rt_ifp->if_rdomain); gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; @@ -338,6 +339,7 @@ arprequest(ifp, sip, tip, enaddr) return; m->m_len = sizeof(*ea); m->m_pkthdr.len = sizeof(*ea); + m->m_pkthdr.rdomain = ifp->if_rdomain; MH_ALIGN(m, sizeof(*ea)); ea = mtod(m, struct ether_arp *); eh = (struct ether_header *)sa.sa_data; @@ -397,7 +399,8 @@ arpresolve(ac, rt, m, dst, desten) log(LOG_DEBUG, "arpresolve: %s: route without link " "local address\n", inet_ntoa(SIN(dst)->sin_addr)); } else { - if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)) != NULL) + if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0, + ac->ac_if.if_rdomain)) != NULL) rt = la->la_rt; else log(LOG_DEBUG, @@ -689,7 +692,8 @@ in_arpinput(m) itaddr = myaddr; goto reply; } - la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); + la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0, + m->m_pkthdr.rdomain); if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { if (sdl->sdl_alen) { if (bcmp(ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) { @@ -771,7 +775,8 @@ reply: bcopy(ea->arp_sha, ea->arp_tha, sizeof(ea->arp_sha)); bcopy(enaddr, ea->arp_sha, sizeof(ea->arp_sha)); } else { - la = arplookup(itaddr.s_addr, 0, SIN_PROXY); + la = arplookup(itaddr.s_addr, 0, SIN_PROXY, + m->m_pkthdr.rdomain); if (la == 0) goto out; rt = la->la_rt; @@ -812,6 +817,7 @@ arptfree(la) struct rtentry *rt = la->la_rt; struct sockaddr_dl *sdl; struct rt_addrinfo info; + u_int tid = 0; if (rt == 0) panic("arptfree"); @@ -826,16 +832,20 @@ arptfree(la) info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_NETMASK] = rt_mask(rt); - rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL, 0); + if (rt->rt_ifp) + tid = rt->rt_ifp->if_rdomain; + + rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL, tid); } /* * Lookup or enter a new address in arptab. */ struct llinfo_arp * -arplookup(addr, create, proxy) +arplookup(addr, create, proxy, tableid) u_int32_t addr; int create, proxy; + u_int tableid; { struct rtentry *rt; static struct sockaddr_inarp sin; @@ -844,7 +854,7 @@ arplookup(addr, create, proxy) sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; sin.sin_other = proxy ? SIN_PROXY : 0; - rt = rtalloc1(sintosa(&sin), create, 0); + rt = rtalloc1(sintosa(&sin), create, tableid); if (rt == 0) return (0); rt->rt_refcnt--; @@ -861,7 +871,7 @@ arplookup(addr, create, proxy) info.rti_info[RTAX_NETMASK] = rt_mask(rt); rtrequest1(RTM_DELETE, &info, rt->rt_priority, - NULL, 0); + NULL, tableid); } } return (0); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 887b3fda6b0..13e22342aed 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in.c,v 1.53 2009/03/15 19:40:41 miod Exp $ */ +/* $OpenBSD: in.c,v 1.54 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */ /* @@ -113,19 +113,24 @@ int hostzeroisbroadcast = HOSTZEROBROADCAST; * Otherwise, it includes only the directly-connected (sub)nets. */ int -in_localaddr(in) - struct in_addr in; +in_localaddr(struct in_addr in, u_int rdomain) { struct in_ifaddr *ia; if (subnetsarelocal) { - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) + TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp->if_rdomain != rdomain) + continue; if ((in.s_addr & ia->ia_netmask) == ia->ia_net) return (1); + } } else { - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) + TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp->if_rdomain != rdomain) + continue; if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet) return (1); + } } return (0); } @@ -786,6 +791,8 @@ in_addprefix(target, flags) } TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp->if_rdomain != target->ia_ifp->if_rdomain) + continue; if (rtinitflags(ia)) { p = ia->ia_dstaddr.sin_addr; if (prefix.s_addr != p.s_addr) @@ -857,6 +864,8 @@ in_scrubprefix(target) p.s_addr &= ia->ia_sockmask.sin_addr.s_addr; } + if (ia->ia_ifp->if_rdomain != target->ia_ifp->if_rdomain) + continue; if (prefix.s_addr != p.s_addr) continue; diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 18835e77c81..3e9256327ba 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.78 2008/12/24 07:41:59 dlg Exp $ */ +/* $OpenBSD: in.h,v 1.79 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -766,7 +766,7 @@ int in_canforward(struct in_addr); int in_cksum(struct mbuf *, int); int in4_cksum(struct mbuf *, u_int8_t, int, int); void in_delayed_cksum(struct mbuf *); -int in_localaddr(struct in_addr); +int in_localaddr(struct in_addr, u_int); void in_socktrim(struct sockaddr_in *); char *inet_ntoa(struct in_addr); diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 0077d250628..2a0cf48040f 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.104 2009/03/15 19:40:41 miod Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.105 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -121,17 +121,17 @@ int ipport_hilastauto = IPPORT_HILASTAUTO; struct pool inpcb_pool; int inpcb_pool_initialized = 0; -#define INPCBHASH(table, faddr, fport, laddr, lport) \ +#define INPCBHASH(table, faddr, fport, laddr, lport, rdom) \ &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \ - ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)] + ntohs((fport)) + ntohs((lport)) + (rdom)) & (table->inpt_hash)] #define IN6PCBHASH(table, faddr, fport, laddr, lport) \ &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \ (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport))) & \ (table->inpt_hash)] -#define INPCBLHASH(table, lport) \ - &(table)->inpt_lhashtbl[lport & table->inpt_lhash] +#define INPCBLHASH(table, lport, rdom) \ + &(table)->inpt_lhashtbl[(ntohs((lport)) + (rdom)) & table->inpt_lhash] void in_pcbinit(table, hashsize) @@ -200,9 +200,10 @@ in_pcballoc(so, v) inp->inp_seclevel[SL_IPCOMP] = ipsec_ipcomp_default_level; s = splnet(); CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); - LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash); + LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport, inp->inp_rdomain), + inp, inp_lhash); LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport, - &inp->inp_laddr, inp->inp_lport), inp, inp_hash); + &inp->inp_laddr, inp->inp_lport, inp->inp_rdomain), inp, inp_hash); splx(s); so->so_pcb = inp; inp->inp_hops = -1; @@ -274,7 +275,8 @@ in_pcbbind(v, nam, p) } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ if (!(so->so_options & SO_BINDANY) && - in_iawithaddr(sin->sin_addr, NULL) == 0) + in_iawithaddr(sin->sin_addr, NULL, + inp->inp_rdomain) == 0) return (EADDRNOTAVAIL); } if (lport) { @@ -286,12 +288,13 @@ in_pcbbind(v, nam, p) return (EACCES); if (so->so_euid) { t = in_pcblookup(table, &zeroin_addr, 0, - &sin->sin_addr, lport, INPLOOKUP_WILDCARD); + &sin->sin_addr, lport, INPLOOKUP_WILDCARD, + inp->inp_rdomain); if (t && (so->so_euid != t->inp_socket->so_euid)) return (EADDRINUSE); } t = in_pcblookup(table, &zeroin_addr, 0, - &sin->sin_addr, lport, wild); + &sin->sin_addr, lport, wild, inp->inp_rdomain); if (t && (reuseport & t->inp_socket->so_options) == 0) return (EADDRINUSE); } @@ -339,7 +342,7 @@ in_pcbbind(v, nam, p) lport = htons(*lastport); } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || in_pcblookup(table, &zeroin_addr, 0, - &inp->inp_laddr, lport, wild)); + &inp->inp_laddr, lport, wild, inp->inp_rdomain)); } else { /* * counting up @@ -357,7 +360,7 @@ in_pcbbind(v, nam, p) lport = htons(*lastport); } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || in_pcblookup(table, &zeroin_addr, 0, - &inp->inp_laddr, lport, wild)); + &inp->inp_laddr, lport, wild, inp->inp_rdomain)); } } inp->inp_lport = lport; @@ -410,7 +413,8 @@ in_pcbconnect(v, nam) if (inp->inp_laddr.s_addr == INADDR_ANY) { int error; ifaddr = in_selectsrc(sin, &inp->inp_route, - inp->inp_socket->so_options, inp->inp_moptions, &error); + inp->inp_socket->so_options, inp->inp_moptions, &error, + inp->inp_rdomain); if (ifaddr == NULL) { if (error == 0) error = EADDRNOTAVAIL; @@ -419,7 +423,7 @@ in_pcbconnect(v, nam) } if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port, inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, - inp->inp_lport) != 0) + inp->inp_lport, inp->inp_rdomain) != 0) return (EADDRINUSE); if (inp->inp_laddr.s_addr == INADDR_ANY) { if (inp->inp_lport == 0 && @@ -630,10 +634,11 @@ in_losing(inp) info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst; info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); - rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_ifp, 0, 0); + rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_ifp, 0, + inp->inp_rdomain); if (rt->rt_flags & RTF_DYNAMIC) (void)rtrequest1(RTM_DELETE, &info, rt->rt_priority, - (struct rtentry **)0, 0); + (struct rtentry **)0, inp->inp_rdomain); /* * A new route can be allocated * the next time output is attempted. @@ -664,11 +669,7 @@ in_rtchange(inp, errno) } struct inpcb * -in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags) - struct inpcbtable *table; - void *faddrp, *laddrp; - u_int fport_arg, lport_arg; - int flags; +in_pcblookup(struct inpcbtable *table, void *faddrp, u_int fport_arg, void *laddrp, u_int lport_arg, int flags, u_int rdomain) { struct inpcb *inp, *match = 0; int matchwild = 3, wildcard; @@ -676,8 +677,10 @@ in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags) struct in_addr faddr = *(struct in_addr *)faddrp; struct in_addr laddr = *(struct in_addr *)laddrp; - for (inp = LIST_FIRST(INPCBLHASH(table, lport)); inp; + for (inp = LIST_FIRST(INPCBLHASH(table, lport, rdomain)); inp; inp = LIST_NEXT(inp, inp_lhash)) { + if (inp->inp_rdomain != rdomain) + continue; if (inp->inp_lport != lport) continue; wildcard = 0; @@ -791,12 +794,8 @@ in_pcbrtentry(inp) } struct sockaddr_in * -in_selectsrc(sin, ro, soopts, mopts, errorp) - struct sockaddr_in *sin; - struct route *ro; - int soopts; - struct ip_moptions *mopts; - int *errorp; +in_selectsrc(struct sockaddr_in *sin, struct route *ro, int soopts, + struct ip_moptions *mopts, int *errorp, u_int rdomain) { struct sockaddr_in *sin2; struct in_ifaddr *ia; @@ -820,7 +819,7 @@ in_selectsrc(sin, ro, soopts, mopts, errorp) ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(struct sockaddr_in); satosin(&ro->ro_dst)->sin_addr = sin->sin_addr; - rtalloc_mpath(ro, NULL, 0); + rtalloc_mpath(ro, NULL, rdomain); /* * It is important to bzero out the rest of the @@ -841,9 +840,9 @@ in_selectsrc(sin, ro, soopts, mopts, errorp) u_int16_t fport = sin->sin_port; sin->sin_port = 0; - ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); + ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin), rdomain)); if (ia == 0) - ia = ifatoia(ifa_ifwithnet(sintosa(sin))); + ia = ifatoia(ifa_ifwithnet(sintosa(sin), rdomain)); sin->sin_port = fport; if (ia == 0) ia = TAILQ_FIRST(&in_ifaddr); @@ -885,7 +884,8 @@ in_pcbrehash(inp) s = splnet(); LIST_REMOVE(inp, inp_lhash); - LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash); + LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport, inp->inp_rdomain), + inp, inp_lhash); LIST_REMOVE(inp, inp_hash); #ifdef INET6 if (inp->inp_flags & INP_IPV6) { @@ -895,8 +895,8 @@ in_pcbrehash(inp) } else { #endif /* INET6 */ LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, - inp->inp_fport, &inp->inp_laddr, inp->inp_lport), - inp, inp_hash); + inp->inp_fport, &inp->inp_laddr, inp->inp_lport, + inp->inp_rdomain), inp, inp_hash); #ifdef INET6 } #endif /* INET6 */ @@ -917,16 +917,14 @@ int in_pcbnotifymiss = 0; * After those two lookups no other are necessary. */ struct inpcb * -in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) - struct inpcbtable *table; - struct in_addr faddr, laddr; - u_int fport_arg, lport_arg; +in_pcbhashlookup(struct inpcbtable *table, struct in_addr faddr, + u_int fport_arg, struct in_addr laddr, u_int lport_arg, u_int rdomain) { struct inpcbhead *head; struct inpcb *inp; u_int16_t fport = fport_arg, lport = lport_arg; - head = INPCBHASH(table, &faddr, fport, &laddr, lport); + head = INPCBHASH(table, &faddr, fport, &laddr, lport, rdomain); LIST_FOREACH(inp, head, inp_hash) { #ifdef INET6 if (inp->inp_flags & INP_IPV6) @@ -935,7 +933,8 @@ in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) if (inp->inp_faddr.s_addr == faddr.s_addr && inp->inp_fport == fport && inp->inp_lport == lport && - inp->inp_laddr.s_addr == laddr.s_addr) { + inp->inp_laddr.s_addr == laddr.s_addr && + inp->inp_rdomain == rdomain) { /* * Move this PCB to the head of hash chain so that * repeated accesses are quicker. This is analogous to @@ -950,9 +949,9 @@ in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) } #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { - printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n", + printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d rdom=%d\n", ntohl(faddr.s_addr), ntohs(fport), - ntohl(laddr.s_addr), ntohs(lport)); + ntohl(laddr.s_addr), ntohs(lport), rdomain); } #endif return (inp); @@ -960,10 +959,8 @@ in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) #ifdef INET6 struct inpcb * -in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) - struct inpcbtable *table; - struct in6_addr *faddr, *laddr; - u_int fport_arg, lport_arg; +in6_pcbhashlookup(struct inpcbtable *table, struct in6_addr *faddr, + u_int fport_arg, struct in6_addr *laddr, u_int lport_arg) { struct inpcbhead *head; struct inpcb *inp; @@ -1008,7 +1005,7 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) */ struct inpcb * in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, - u_int lport_arg, int reverse, struct mbuf *m) + u_int lport_arg, int reverse, struct mbuf *m, u_int rdomain) { struct inpcbhead *head; struct in_addr *key1, *key2; @@ -1018,7 +1015,7 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, #if NPF > 0 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; - + /* XXX rdomain */ if ((divert = pf_find_divert(m)) == NULL) return (NULL); key1 = key2 = &divert->addr.ipv4; @@ -1033,7 +1030,7 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, key2 = &zeroin_addr; } - head = INPCBHASH(table, &zeroin_addr, 0, key1, lport); + head = INPCBHASH(table, &zeroin_addr, 0, key1, lport, rdomain); LIST_FOREACH(inp, head, inp_hash) { #ifdef INET6 if (inp->inp_flags & INP_IPV6) @@ -1041,11 +1038,12 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, #endif if (inp->inp_lport == lport && inp->inp_fport == 0 && inp->inp_laddr.s_addr == key1->s_addr && - inp->inp_faddr.s_addr == INADDR_ANY) + inp->inp_faddr.s_addr == INADDR_ANY && + inp->inp_rdomain == rdomain) break; } if (inp == NULL && key1->s_addr != key2->s_addr) { - head = INPCBHASH(table, &zeroin_addr, 0, key2, lport); + head = INPCBHASH(table, &zeroin_addr, 0, key2, lport, rdomain); LIST_FOREACH(inp, head, inp_hash) { #ifdef INET6 if (inp->inp_flags & INP_IPV6) @@ -1053,7 +1051,8 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, #endif if (inp->inp_lport == lport && inp->inp_fport == 0 && inp->inp_laddr.s_addr == key2->s_addr && - inp->inp_faddr.s_addr == INADDR_ANY) + inp->inp_faddr.s_addr == INADDR_ANY && + inp->inp_rdomain == rdomain) break; } } diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index d3188b12adc..7e75d8294c6 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.66 2008/07/10 02:19:28 djm Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.67 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -146,6 +146,7 @@ struct inpcb { #endif struct icmp6_filter *inp_icmp6filt; void *inp_pf_sk; + u_int inp_rdomain; }; struct inpcbtable { @@ -250,10 +251,10 @@ void in_pcbdetach(void *); void in_pcbdisconnect(void *); struct inpcb * in_pcbhashlookup(struct inpcbtable *, struct in_addr, - u_int, struct in_addr, u_int); + u_int, struct in_addr, u_int, u_int); struct inpcb * in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int, int, - struct mbuf *); + struct mbuf *, u_int); #ifdef INET6 struct inpcb * in6_pcbhashlookup(struct inpcbtable *, struct in6_addr *, @@ -269,7 +270,7 @@ int in6_setpeeraddr(struct inpcb *, struct mbuf *); void in_pcbinit(struct inpcbtable *, int); struct inpcb * in_pcblookup(struct inpcbtable *, void *, u_int, void *, - u_int, int); + u_int, int, u_int); void in_pcbnotifyall(struct inpcbtable *, struct sockaddr *, int, void (*)(struct inpcb *, int)); void in_pcbrehash(struct inpcb *); @@ -278,7 +279,7 @@ void in_setpeeraddr(struct inpcb *, struct mbuf *); void in_setsockaddr(struct inpcb *, struct mbuf *); int in_baddynamic(u_int16_t, u_int16_t); extern struct sockaddr_in *in_selectsrc(struct sockaddr_in *, - struct route *, int, struct ip_moptions *, int *); + struct route *, int, struct ip_moptions *, int *, u_int); struct rtentry * in_pcbrtentry(struct inpcb *); diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 8ebf216cb61..ac078c83fe5 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_var.h,v 1.11 2008/11/08 12:54:58 dlg Exp $ */ +/* $OpenBSD: in_var.h,v 1.12 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: in_var.h,v 1.16 1996/02/13 23:42:15 christos Exp $ */ /* @@ -89,14 +89,15 @@ void in_socktrim(struct sockaddr_in *); * Macro for finding the interface (ifnet structure) corresponding to one * of our IP addresses. */ -#define INADDR_TO_IFP(addr, ifp) \ +#define INADDR_TO_IFP(addr, ifp, rdomain) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ do { \ struct in_ifaddr *ia; \ \ for (ia = TAILQ_FIRST(&in_ifaddr); ia != TAILQ_END(&in_ifaddr) && \ - ia->ia_addr.sin_addr.s_addr != (addr).s_addr; \ + (ia->ia_ifp->if_rdomain != rdomain || \ + ia->ia_addr.sin_addr.s_addr != (addr).s_addr); \ ia = TAILQ_NEXT(ia, ia_list)) \ continue; \ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 228163fcf6c..87be99facf6 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.169 2008/10/28 23:07:12 mpf Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.170 2009/06/05 00:05:22 claudio Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -424,9 +424,9 @@ carp_setroute(struct carp_softc *sc, int cmd) info.rti_info[RTAX_DST] = ifa->ifa_addr; info.rti_flags = RTF_HOST; error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, - NULL, 0); + NULL, sc->sc_if.if_rdomain); rt_missmsg(RTM_DELETE, &info, info.rti_flags, NULL, - error, 0); + error, sc->sc_if.if_rdomain); /* Check for our address on another interface */ /* XXX cries for proper API */ @@ -441,7 +441,7 @@ carp_setroute(struct carp_softc *sc, int cmd) 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); + ifa->ifa_netmask, sc->sc_if.if_rdomain); nr_ourif = (rt && rt->rt_ifp == &sc->sc_if); /* Restore the route label */ @@ -465,9 +465,11 @@ carp_setroute(struct carp_softc *sc, int cmd) info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_flags = RTF_UP | RTF_HOST; error = rtrequest1(RTM_ADD, &info, - RTP_CONNECTED, NULL, 0); - rt_missmsg(RTM_ADD, &info, info.rti_flags, - &sc->sc_if, error, 0); + RTP_CONNECTED, NULL, + sc->sc_if.if_rdomain); + rt_missmsg(RTM_ADD, &info, + info.rti_flags, &sc->sc_if, + error, sc->sc_if.if_rdomain); } if (!hr_otherif || nr_ourif || !rt) { if (nr_ourif && !(rt->rt_flags & @@ -475,9 +477,11 @@ carp_setroute(struct carp_softc *sc, int cmd) bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = &sa; info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; - error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, NULL, 0); + error = rtrequest1(RTM_DELETE, + &info, RTP_CONNECTED, NULL, + sc->sc_if.if_rdomain); rt_missmsg(RTM_DELETE, &info, info.rti_flags, NULL, - error, 0); + error, sc->sc_if.if_rdomain); } ifa->ifa_rtrequest = arp_rtrequest; @@ -489,11 +493,13 @@ carp_setroute(struct carp_softc *sc, int cmd) info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; info.rti_info[RTAX_LABEL] = (struct sockaddr *)&sa_rl; - error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, NULL, 0); + error = rtrequest1(RTM_ADD, &info, + RTP_CONNECTED, NULL, + sc->sc_if.if_rdomain); if (error == 0) ifa->ifa_flags |= IFA_ROUTE; rt_missmsg(RTM_ADD, &info, info.rti_flags, - &sc->sc_if, error, 0); + &sc->sc_if, error, sc->sc_if.if_rdomain); } break; case RTM_DELETE: @@ -1996,6 +2002,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) if (ia->ia_ifp != &sc->sc_if && ia->ia_ifp->if_type != IFT_CARP && (ia->ia_ifp->if_flags & IFF_MULTICAST) && + ia->ia_ifp->if_rdomain == sc->sc_if.if_rdomain && (sin->sin_addr.s_addr & ia->ia_subnetmask) == ia->ia_subnet) { if (!ia_if) diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 337490e5b83..c60ad936701 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_icmp.c,v 1.82 2008/09/10 09:10:55 henning Exp $ */ +/* $OpenBSD: ip_icmp.c,v 1.83 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ /* @@ -213,6 +213,8 @@ icmp_do_error(struct mbuf *n, int type, int code, n_long dest, int destmtu) } if (m == NULL) goto freeit; + /* keep in same domain and rtable (the latter is a bit unclear) */ + m->m_pkthdr.rdomain = n->m_pkthdr.rdomain; m->m_len = icmplen + ICMP_MINLEN; if ((m->m_flags & M_EXT) == 0) MH_ALIGN(m, m->m_len); @@ -587,9 +589,11 @@ reflect: goto freeit; #endif rt = NULL; + /* XXX rdomain vs. rtable */ rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst), (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, - sintosa(&icmpgw), (struct rtentry **)&rt); + sintosa(&icmpgw), (struct rtentry **)&rt, + m->m_pkthdr.rdomain); if (rt != NULL && icmp_redirtimeout != 0) { (void)rt_timer_add(rt, icmp_redirect_timeout, icmp_redirect_timeout_q); @@ -659,6 +663,8 @@ icmp_reflect(struct mbuf *m) * the address which corresponds to the incoming interface. */ TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp->if_rdomain != m->m_pkthdr.rdomain) + continue; if (t.s_addr == ia->ia_addr.sin_addr.s_addr) break; if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && @@ -680,7 +686,9 @@ icmp_reflect(struct mbuf *m) dst->sin_len = sizeof(*dst); dst->sin_addr = ip->ip_src; - rtalloc(&ro); + /* keep packet in the original VRF instance */ + ro.ro_rt = rtalloc1(&ro.ro_dst, 1, + m->m_pkthdr.rdomain); if (ro.ro_rt == 0) { ipstat.ips_noroute++; m_freem(m); @@ -863,14 +871,13 @@ icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, } -/* XXX only handles table 0 right now */ struct rtentry * -icmp_mtudisc_clone(struct sockaddr *dst) +icmp_mtudisc_clone(struct sockaddr *dst, u_int rtableid) { struct rtentry *rt; int error; - rt = rtalloc1(dst, 1, 0); + rt = rtalloc1(dst, 1, rtableid); if (rt == 0) return (NULL); @@ -885,7 +892,7 @@ icmp_mtudisc_clone(struct sockaddr *dst) info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; - error = rtrequest1(RTM_ADD, &info, rt->rt_priority, &nrt, 0); + error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &nrt, rtableid); if (error) { rtfree(rt); return (NULL); @@ -904,7 +911,7 @@ icmp_mtudisc_clone(struct sockaddr *dst) } void -icmp_mtudisc(struct icmp *icp) +icmp_mtudisc(struct icmp *icp, u_int rtableid) { struct rtentry *rt; struct sockaddr *dst = sintosa(&icmpsrc); @@ -917,7 +924,7 @@ icmp_mtudisc(struct icmp *icp) 4352, 2002, 1492, 1006, 508, 296, 68, 0 }; - rt = icmp_mtudisc_clone(dst); + rt = icmp_mtudisc_clone(dst, rtableid); if (rt == 0) return; diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index 1a79d3a06bd..6e89454fe33 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_icmp.h,v 1.21 2005/07/31 03:30:55 pascoe Exp $ */ +/* $OpenBSD: ip_icmp.h,v 1.22 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_icmp.h,v 1.10 1996/02/13 23:42:28 christos Exp $ */ /* @@ -214,7 +214,7 @@ void icmp_reflect(struct mbuf *); void icmp_send(struct mbuf *, struct mbuf *); int icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); struct rtentry * - icmp_mtudisc_clone(struct sockaddr *); -void icmp_mtudisc(struct icmp *); + icmp_mtudisc_clone(struct sockaddr *, u_int); +void icmp_mtudisc(struct icmp *, u_int); #endif /* _KERNEL */ #endif /* _NETINET_IP_ICMP_H_ */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 1413f0244cc..d709855848e 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.163 2009/06/04 05:02:25 henning Exp $ */ +/* $OpenBSD: ip_input.c,v 1.164 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -172,7 +172,7 @@ static struct ip_srcrt { } ip_srcrt; void save_rte(u_char *, struct in_addr); -int ip_weadvertise(u_int32_t); +int ip_weadvertise(u_int32_t, u_int); /* * IP initialization: fill in IP protocol switch table. @@ -401,8 +401,8 @@ ipv4_input(m) if (!m->m_pkthdr.pf.statekey || !((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse) #endif - if ((ia = in_iawithaddr(ip->ip_dst, m)) != NULL && - (ia->ia_ifp->if_flags & IFF_UP)) + if ((ia = in_iawithaddr(ip->ip_dst, m, m->m_pkthdr.rdomain)) != + NULL && (ia->ia_ifp->if_flags & IFF_UP)) goto ours; if (IN_MULTICAST(ip->ip_dst.s_addr)) { @@ -677,13 +677,13 @@ bad: } struct in_ifaddr * -in_iawithaddr(ina, m) - struct in_addr ina; - struct mbuf *m; +in_iawithaddr(struct in_addr ina, struct mbuf *m, u_int rdomain) { struct in_ifaddr *ia; TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp->if_rdomain != rdomain) + continue; if ((ina.s_addr == ia->ia_addr.sin_addr.s_addr) || ((ia->ia_ifp->if_flags & (IFF_LOOPBACK|IFF_LINK1)) == (IFF_LOOPBACK|IFF_LINK1) && @@ -1040,7 +1040,8 @@ ip_dooptions(m) goto bad; } ipaddr.sin_addr = ip->ip_dst; - ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))); + ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr), + m->m_pkthdr.rdomain)); if (ia == 0) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; @@ -1070,10 +1071,15 @@ ip_dooptions(m) if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * #define SA struct sockaddr * - if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) - ia = (INA)ifa_ifwithnet((SA)&ipaddr); + if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr, + m->m_pkthdr.rdomain)) == 0) + ia = (INA)ifa_ifwithnet((SA)&ipaddr, + m->m_pkthdr.rdomain); } else - ia = ip_rtaddr(ipaddr.sin_addr); + /* keep packet in the original VRF instance */ + /* XXX rdomain or rtableid ??? */ + ia = ip_rtaddr(ipaddr.sin_addr, + m->m_pkthdr.rdomain); if (ia == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; @@ -1110,9 +1116,13 @@ ip_dooptions(m) /* * locate outgoing interface; if we're the destination, * use the incoming interface (should be same). + * Again keep the packet inside the VRF instance. + * XXX rdomain vs. rtableid ??? */ - if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && - (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { + if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr, + m->m_pkthdr.rdomain)) == 0 && + (ia = ip_rtaddr(ipaddr.sin_addr, + m->m_pkthdr.rdomain)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; @@ -1160,7 +1170,8 @@ ip_dooptions(m) goto bad; bcopy((caddr_t)&sin, (caddr_t)&ipaddr.sin_addr, sizeof(struct in_addr)); - if (ifa_ifwithaddr((SA)&ipaddr) == 0) + if (ifa_ifwithaddr((SA)&ipaddr, + m->m_pkthdr.rdomain) == 0) continue; ipt.ipt_ptr += sizeof(struct in_addr); break; @@ -1193,8 +1204,7 @@ bad: * return internet address info of interface to be used to get there. */ struct in_ifaddr * -ip_rtaddr(dst) - struct in_addr dst; +ip_rtaddr(struct in_addr dst, u_int rtableid) { struct sockaddr_in *sin; @@ -1209,7 +1219,8 @@ ip_rtaddr(dst) sin->sin_len = sizeof(*sin); sin->sin_addr = dst; - rtalloc(&ipforward_rt); + ipforward_rt.ro_rt = rtalloc1(&ipforward_rt.ro_dst, 1, + rtableid); } if (ipforward_rt.ro_rt == 0) return ((struct in_ifaddr *)0); @@ -1244,8 +1255,7 @@ save_rte(option, dst) * Code shamelessly copied from arplookup(). */ int -ip_weadvertise(addr) - u_int32_t addr; +ip_weadvertise(u_int32_t addr, u_int rtableid) { struct rtentry *rt; struct ifnet *ifp; @@ -1256,7 +1266,7 @@ ip_weadvertise(addr) sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; sin.sin_other = SIN_PROXY; - rt = rtalloc1(sintosa(&sin), 0, 0); /* XXX other tables? */ + rt = rtalloc1(sintosa(&sin), 0, rtableid); if (rt == 0) return 0; @@ -1266,7 +1276,9 @@ ip_weadvertise(addr) return 0; } - TAILQ_FOREACH(ifp, &ifnet, if_list) + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != rtableid) + continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family) continue; @@ -1278,6 +1290,7 @@ ip_weadvertise(addr) return 1; } } + } RTFREE(rt); return 0; @@ -1431,9 +1444,9 @@ ip_forward(m, srcrt) return; } -#if NPF > 0 - rtableid = m->m_pkthdr.pf.rtableid; -#endif + rtableid = m->m_pkthdr.rdomain; + if (m->m_pkthdr.pf.rtableid) + rtableid = m->m_pkthdr.pf.rtableid; sin = satosin(&ipforward_rt.ro_dst); if ((rt = ipforward_rt.ro_rt) == 0 || @@ -1481,7 +1494,8 @@ ip_forward(m, srcrt) (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt && - !ip_weadvertise(satosin(rt_key(rt))->sin_addr.s_addr)) { + !ip_weadvertise(satosin(rt_key(rt))->sin_addr.s_addr, + m->m_pkthdr.rdomain)) { if (rt->rt_ifa && (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) == ifatoia(rt->rt_ifa)->ia_subnet) { diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c index 81c7d75a07b..e37cefa04aa 100644 --- a/sys/netinet/ip_ipip.c +++ b/sys/netinet/ip_ipip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipip.c,v 1.42 2008/11/26 16:08:17 henning Exp $ */ +/* $OpenBSD: ip_ipip.c,v 1.43 2009/06/05 00:05:22 claudio Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -288,6 +288,8 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && ipip_allow != 2) { TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != m->m_pkthdr.rdomain) + continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { #ifdef INET if (ipo) { diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index bdd8d221f6d..38e16eac821 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_mroute.c,v 1.52 2008/09/16 21:33:37 chl Exp $ */ +/* $OpenBSD: ip_mroute.c,v 1.53 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */ /* @@ -840,7 +840,7 @@ add_vif(struct mbuf *m) #endif { sin.sin_addr = vifcp->vifc_lcl_addr; - ifa = ifa_ifwithaddr(sintosa(&sin)); + ifa = ifa_ifwithaddr(sintosa(&sin), /* XXX */ 0); if (ifa == NULL) return (EADDRNOTAVAIL); } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index ab65a4b0eb4..8247955acab 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.193 2009/01/30 20:46:33 claudio Exp $ */ +/* $OpenBSD: ip_output.c,v 1.194 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -201,11 +201,13 @@ ip_output(struct mbuf *m0, ...) * If routing to interface only, short-circuit routing lookup. */ if (flags & IP_ROUTETOIF) { - if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 && - (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) { - ipstat.ips_noroute++; - error = ENETUNREACH; - goto bad; + if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst), + m->m_pkthdr.rdomain))) == 0 && + (ia = ifatoia(ifa_ifwithnet(sintosa(dst), + m->m_pkthdr.rdomain))) == 0) { + ipstat.ips_noroute++; + error = ENETUNREACH; + goto bad; } ifp = ia->ia_ifp; @@ -219,7 +221,8 @@ ip_output(struct mbuf *m0, ...) IFP_TO_IA(ifp, ia); } else { if (ro->ro_rt == 0) - rtalloc_mpath(ro, NULL, 0); + rtalloc_mpath(ro, NULL, + m->m_pkthdr.rdomain); if (ro->ro_rt == 0) { ipstat.ips_noroute++; @@ -371,11 +374,13 @@ ip_output(struct mbuf *m0, ...) * If routing to interface only, short-circuit routing lookup. */ if (flags & IP_ROUTETOIF) { - if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 && - (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) { - ipstat.ips_noroute++; - error = ENETUNREACH; - goto bad; + if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst), + m->m_pkthdr.rdomain))) == 0 && + (ia = ifatoia(ifa_ifwithnet(sintosa(dst), + m->m_pkthdr.rdomain))) == 0) { + ipstat.ips_noroute++; + error = ENETUNREACH; + goto bad; } ifp = ia->ia_ifp; @@ -389,7 +394,8 @@ ip_output(struct mbuf *m0, ...) IFP_TO_IA(ifp, ia); } else { if (ro->ro_rt == 0) - rtalloc_mpath(ro, &ip->ip_src.s_addr, 0); + rtalloc_mpath(ro, &ip->ip_src.s_addr, + m->m_pkthdr.rdomain); if (ro->ro_rt == 0) { ipstat.ips_noroute++; @@ -623,7 +629,8 @@ sendit: struct sockaddr_in dst = { sizeof(struct sockaddr_in), AF_INET}; dst.sin_addr = ip->ip_dst; - rt = icmp_mtudisc_clone((struct sockaddr *)&dst); + rt = icmp_mtudisc_clone((struct sockaddr *)&dst, + m->m_pkthdr.rdomain); rt_mtucloned = 1; } DPRINTF(("ip_output: spi %08x mtu %d rt %p cloned %d\n", @@ -632,8 +639,9 @@ sendit: rt->rt_rmx.rmx_mtu = icmp_mtu; if (ro && ro->ro_rt != NULL) { RTFREE(ro->ro_rt); - ro->ro_rt = (struct rtentry *) 0; - rtalloc(ro); + ro->ro_rt = NULL; + rtalloc1(&ro->ro_dst, 1, + m->m_pkthdr.rdomain); } if (rt_mtucloned) rtfree(rt); @@ -1037,6 +1045,7 @@ ip_ctloutput(op, so, level, optname, mp) u_int16_t opt16val; #endif int error = 0; + u_int rtid = 0; if (level != IPPROTO_IP) { error = EINVAL; @@ -1121,7 +1130,8 @@ ip_ctloutput(op, so, level, optname, mp) case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_setmoptions(optname, &inp->inp_moptions, m); + error = ip_setmoptions(optname, &inp->inp_moptions, m, + inp->inp_rdomain); break; case IP_PORTRANGE: @@ -1385,6 +1395,18 @@ ip_ctloutput(op, so, level, optname, mp) } #endif break; + case SO_RDOMAIN: + if (m == NULL || m->m_len < sizeof(u_int)) { + error = EINVAL; + break; + } + rtid = *mtod(m, u_int *); + if (!rtable_exists(rtid)) { + error = EINVAL; + break; + } + inp->inp_rdomain = rtid; + break; default: error = ENOPROTOOPT; break; @@ -1575,6 +1597,11 @@ ip_ctloutput(op, so, level, optname, mp) } #endif break; + case SO_RDOMAIN: + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(u_int); + *mtod(m, u_int *) = inp->inp_rdomain; + break; default: error = ENOPROTOOPT; break; @@ -1696,10 +1723,8 @@ bad: * Set the IP multicast options in response to user setsockopt(). */ int -ip_setmoptions(optname, imop, m) - int optname; - struct ip_moptions **imop; - struct mbuf *m; +ip_setmoptions(int optname, struct ip_moptions **imop, struct mbuf *m, + u_int rdomain) { int error = 0; u_char loop; @@ -1756,7 +1781,7 @@ ip_setmoptions(optname, imop, m) * IP address. Find the interface and confirm that * it supports multicasting. */ - INADDR_TO_IFP(addr, ifp); + INADDR_TO_IFP(addr, ifp, rdomain); if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { error = EADDRNOTAVAIL; break; @@ -1812,7 +1837,9 @@ ip_setmoptions(optname, imop, m) dst->sin_len = sizeof(*dst); dst->sin_family = AF_INET; dst->sin_addr = mreq->imr_multiaddr; - rtalloc(&ro); + if (!(ro.ro_rt && ro.ro_rt->rt_ifp && + (ro.ro_rt->rt_flags & RTF_UP))) + ro.ro_rt = rtalloc1(&ro.ro_dst, 1, rdomain); if (ro.ro_rt == NULL) { error = EADDRNOTAVAIL; break; @@ -1820,7 +1847,7 @@ ip_setmoptions(optname, imop, m) ifp = ro.ro_rt->rt_ifp; rtfree(ro.ro_rt); } else { - INADDR_TO_IFP(mreq->imr_interface, ifp); + INADDR_TO_IFP(mreq->imr_interface, ifp, rdomain); } /* * See if we found an interface, and confirm that it @@ -1906,7 +1933,7 @@ ip_setmoptions(optname, imop, m) if (mreq->imr_interface.s_addr == INADDR_ANY) ifp = NULL; else { - INADDR_TO_IFP(mreq->imr_interface, ifp); + INADDR_TO_IFP(mreq->imr_interface, ifp, rdomain); if (ifp == NULL) { error = EADDRNOTAVAIL; break; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index bc72a08ff57..853b4816e85 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.38 2008/05/23 15:51:12 thib Exp $ */ +/* $OpenBSD: ip_var.h,v 1.39 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -172,12 +172,12 @@ int ip_pcbopts(struct mbuf **, struct mbuf *); struct mbuf * ip_reass(struct ipqent *, struct ipq *); struct in_ifaddr * - in_iawithaddr(struct in_addr, struct mbuf *); + in_iawithaddr(struct in_addr, struct mbuf *, u_int); struct in_ifaddr * - ip_rtaddr(struct in_addr); + ip_rtaddr(struct in_addr, u_int); u_int16_t ip_randomid(void); -int ip_setmoptions(int, struct ip_moptions **, struct mbuf *); +int ip_setmoptions(int, struct ip_moptions **, struct mbuf *, u_int); void ip_slowtimo(void); struct mbuf * ip_srcroute(void); diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 032b83e0a27..0cbaa96a5c2 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.46 2008/10/23 22:22:44 deraadt Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.47 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -132,12 +132,16 @@ rip_input(struct mbuf *m, ...) if (inp->inp_flags & INP_IPV6) continue; #endif + if (inp->inp_rdomain != m->m_pkthdr.rdomain) + continue; + if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) continue; #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; + /* XXX rdomain support */ if ((divert = pf_find_divert(m)) == NULL) continue; if (inp->inp_laddr.s_addr != divert->addr.ipv4.s_addr) @@ -267,6 +271,9 @@ rip_output(struct mbuf *m, ...) * ip_output should be guarded against v6/v4 problems. */ #endif + /* force routing domain */ + m->m_pkthdr.rdomain = inp->inp_rdomain; + return (ip_output(m, inp->inp_options, &inp->inp_route, flags, inp->inp_moptions, inp)); } @@ -411,7 +418,8 @@ rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, (addr->sin_family != AF_IMPLINK)) || (addr->sin_addr.s_addr && (!(so->so_options & SO_BINDANY) && - in_iawithaddr(addr->sin_addr, NULL) == 0))) { + in_iawithaddr(addr->sin_addr, NULL, inp->inp_rdomain) == + 0))) { error = EADDRNOTAVAIL; break; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index aee2240007e..c8912fccf68 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.225 2009/06/03 18:22:44 naddy Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.226 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -605,7 +605,8 @@ findpcb: #endif case AF_INET: inp = in_pcbhashlookup(&tcbtable, ip->ip_src, - th->th_sport, ip->ip_dst, th->th_dport); + th->th_sport, ip->ip_dst, th->th_dport, + m->m_pkthdr.rdomain); break; } #if NPF > 0 @@ -630,7 +631,8 @@ findpcb: #endif /* INET6 */ case AF_INET: inp = in_pcblookup_listen(&tcbtable, - ip->ip_dst, th->th_dport, inpl_flags, m); + ip->ip_dst, th->th_dport, inpl_flags, m, + m->m_pkthdr.rdomain); break; } /* @@ -3033,7 +3035,7 @@ tcp_mss(struct tcpcb *tp, int offer) else if (tp->pf == AF_INET) { if (ip_mtudisc) mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); - else if (inp && in_localaddr(inp->inp_faddr)) + else if (inp && in_localaddr(inp->inp_faddr, inp->inp_rdomain)) mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); } #ifdef INET6 diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 8e0ca68f182..d4da8619528 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.86 2008/09/03 12:51:39 henning Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.87 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -1059,6 +1059,9 @@ send: } #endif + /* force routing domain */ + m->m_pkthdr.rdomain = tp->t_inpcb->inp_rdomain; + switch (tp->pf) { case 0: /*default to PF_INET*/ #ifdef INET diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 5b482b0ce9d..e6b0cf18732 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.105 2008/06/09 07:07:17 djm Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.106 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -809,7 +809,8 @@ tcp_ctlinput(cmd, sa, v) th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); seq = ntohl(th->th_seq); inp = in_pcbhashlookup(&tcbtable, - ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport); + ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, + /* XXX */ 0); if (inp && (tp = intotcpcb(inp)) && SEQ_GEQ(seq, tp->snd_una) && SEQ_LT(seq, tp->snd_max)) { @@ -831,7 +832,8 @@ tcp_ctlinput(cmd, sa, v) * route (traditional PMTUD). */ tp->t_flags &= ~TF_PMTUD_PEND; - icmp_mtudisc(icp); + /* XXX inherit rdomain from PCB */ + icmp_mtudisc(icp, 0); } else { /* * Record the information got in the ICMP @@ -866,7 +868,8 @@ tcp_ctlinput(cmd, sa, v) if (ip) { th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); inp = in_pcbhashlookup(&tcbtable, - ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport); + ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, + /* XXX */ 0); if (inp) { seq = ntohl(th->th_seq); if (inp->inp_socket && diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 69c70b9cc29..f939e3faa0a 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_timer.c,v 1.42 2008/02/20 11:24:03 markus Exp $ */ +/* $OpenBSD: tcp_timer.c,v 1.43 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_timer.c,v 1.14 1996/02/13 23:44:09 christos Exp $ */ /* @@ -213,7 +213,7 @@ tcp_timer_rexmt(void *arg) icmp.icmp_ip.ip_len = tp->t_pmtud_ip_len; icmp.icmp_ip.ip_hl = tp->t_pmtud_ip_hl; icmpsrc.sin_addr = tp->t_inpcb->inp_faddr; - icmp_mtudisc(&icmp); + icmp_mtudisc(&icmp, tp->t_inpcb->inp_rdomain); /* * Notify all connections to the same peer about @@ -285,7 +285,8 @@ tcp_timer_rexmt(void *arg) sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_addr = inp->inp_faddr; - rt = icmp_mtudisc_clone(sintosa(&sin)); + rt = icmp_mtudisc_clone(sintosa(&sin), + inp->inp_rdomain); break; } if (rt != NULL) { diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 00997e16a02..facb9830def 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.99 2008/05/24 19:48:32 thib Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.100 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -764,12 +764,7 @@ tcp_usrclosed(tp) * Look up a socket for ident or tcpdrop, ... */ int -tcp_ident(oldp, oldlenp, newp, newlen, dodrop) - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - int dodrop; +tcp_ident(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int dodrop) { int error = 0, s; struct tcp_ident_mapping tir; @@ -830,7 +825,7 @@ tcp_ident(oldp, oldlenp, newp, newlen, dodrop) #endif case AF_INET: inp = in_pcbhashlookup(&tcbtable, fin->sin_addr, - fin->sin_port, lin->sin_addr, lin->sin_port); + fin->sin_port, lin->sin_addr, lin->sin_port , tir.rdomain); break; } @@ -855,7 +850,7 @@ tcp_ident(oldp, oldlenp, newp, newlen, dodrop) #endif case AF_INET: inp = in_pcblookup_listen(&tcbtable, - lin->sin_addr, lin->sin_port, 0, NULL); + lin->sin_addr, lin->sin_port, 0, NULL, tir.rdomain); break; } } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index dcd291b0124..4fa1bda8c61 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.90 2008/11/08 12:54:58 dlg Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.91 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -520,6 +520,7 @@ struct tcpstat { struct tcp_ident_mapping { struct sockaddr_storage faddr, laddr; int euid, ruid; + u_int rdomain; }; #ifdef _KERNEL diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index d93dcd1b26a..94ee74c0d7b 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.128 2009/06/03 18:22:44 naddy Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.129 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -440,6 +440,8 @@ udp_input(struct mbuf *m, ...) if (!ip6 && (inp->inp_flags & INP_IPV6)) continue; #endif + if (inp->inp_rdomain != m->m_pkthdr.rdomain) + continue; if (inp->inp_lport != uh->uh_dport) continue; #ifdef INET6 @@ -558,7 +560,7 @@ udp_input(struct mbuf *m, ...) else #endif /* INET6 */ inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, - ip->ip_dst, uh->uh_dport); + ip->ip_dst, uh->uh_dport, m->m_pkthdr.rdomain); #if NPF > 0 if (m->m_pkthdr.pf.statekey && inp) { ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->inp = @@ -579,7 +581,8 @@ udp_input(struct mbuf *m, ...) } else #endif /* INET6 */ inp = in_pcblookup_listen(&udbtable, - ip->ip_dst, uh->uh_dport, inpl_reverse, m); + ip->ip_dst, uh->uh_dport, inpl_reverse, m, + m->m_pkthdr.rdomain); if (inp == 0) { udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { @@ -901,7 +904,8 @@ udp_ctlinput(int cmd, struct sockaddr *sa, void *v) } #endif inp = in_pcbhashlookup(&udbtable, - ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport); + ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport, + /* XXX */ 0); if (inp && inp->inp_socket != NULL) notify(inp, errno); } else @@ -1001,6 +1005,10 @@ udp_output(struct mbuf *m, ...) ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; udpstat.udps_opackets++; + + /* force routing domain */ + m->m_pkthdr.rdomain = inp->inp_rdomain; + error = ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST | SO_JUMBO), diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 67e3904a4f7..7453fe1e7b0 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: icmp6.c,v 1.104 2009/02/22 17:43:20 claudio Exp $ */ +/* $OpenBSD: icmp6.c,v 1.105 2009/06/05 00:05:22 claudio Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -1217,7 +1217,7 @@ ni6_input(struct mbuf *m, int off) sin6.sin6_len = sizeof(struct sockaddr_in6); bcopy(&ip6->ip6_dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); /* XXX scopeid */ - if (ifa_ifwithaddr((struct sockaddr *)&sin6)) + if (ifa_ifwithaddr((struct sockaddr *)&sin6, /* XXX */ 0)) ; /* unicast/anycast, fine */ else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) ; /* link-local multicast, fine */ @@ -2336,7 +2336,7 @@ icmp6_redirect_input(struct mbuf *m, int off) rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw, (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&ssrc, - &newrt); + &newrt, /* XXX */ 0); if (newrt) { (void)rt_timer_add(newrt, icmp6_redirect_timeout, diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index a008f565912..a5f4f9502f7 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_pcb.c,v 1.48 2008/11/23 13:30:59 claudio Exp $ */ +/* $OpenBSD: in6_pcb.c,v 1.49 2009/06/05 00:05:22 claudio Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -235,8 +235,8 @@ in6_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) */ sin6->sin6_flowinfo = 0; if (!(so->so_options & SO_BINDANY) && - ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) - == NULL)) + (ia = ifa_ifwithaddr((struct sockaddr *)sin6, + /* XXX */ 0)) == NULL) return EADDRNOTAVAIL; /* @@ -276,7 +276,7 @@ in6_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) t = in_pcblookup(head, (struct in_addr *)&zeroin6_addr, 0, (struct in_addr *)&sin6->sin6_addr, lport, - wild); + wild, /* XXX */ 0); if (t && (reuseport & t->inp_socket->so_options) == 0) return EADDRINUSE; @@ -353,7 +353,7 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct proc *p) lport = htons(*lastport); } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || in_pcblookup(table, &zeroin6_addr, 0, - &inp->inp_laddr6, lport, wild)); + &inp->inp_laddr6, lport, wild, /* XXX */ 0)); } else { /* * counting up @@ -371,7 +371,7 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct proc *p) lport = htons(*lastport); } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || in_pcblookup(table, &zeroin6_addr, 0, - &inp->inp_laddr6, lport, wild)); + &inp->inp_laddr6, lport, wild, /* XXX */ 0)); } inp->inp_lport = lport; @@ -452,7 +452,7 @@ in6_pcbconnect(struct inpcb *inp, struct mbuf *nam) if (in_pcblookup(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) ? in6a : &inp->inp_laddr6, - inp->inp_lport, INPLOOKUP_IPV6)) { + inp->inp_lport, INPLOOKUP_IPV6, /* XXX */ 0)) { return (EADDRINUSE); } if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 94ebaee050e..ec91971dd13 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.38 2008/11/23 13:30:59 claudio Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.39 2009/06/05 00:05:22 claudio Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -673,7 +673,8 @@ rip6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, * this in a more natural way. */ if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && - (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) { + (ia = ifa_ifwithaddr((struct sockaddr *)addr, + /* XXX */ 0)) == 0) { error = EADDRNOTAVAIL; break; } diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 75d73b52c1f..68871411ce6 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbuf.h,v 1.122 2009/06/02 00:05:13 blambert Exp $ */ +/* $OpenBSD: mbuf.h,v 1.123 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ /* @@ -78,8 +78,8 @@ struct m_hdr { struct pkthdr_pf { void *hdr; /* saved hdr pos in mbuf, for ECN */ void *statekey; /* pf stackside statekey */ - u_int rtableid; /* alternate routing table id */ u_int32_t qid; /* queue id */ + u_int rtableid; /* alternate routing table id */ u_int16_t tag; /* tag id */ u_int8_t flags; u_int8_t routed; @@ -98,6 +98,7 @@ struct pkthdr { int len; /* total packet length */ u_int16_t csum_flags; /* checksum flags */ u_int16_t ether_vtag; /* Ethernet 802.1p+Q vlan tag */ + u_int rdomain; /* routing domain id */ struct pkthdr_pf pf; }; diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 76788cf0629..771bc58ec37 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socket.h,v 1.59 2008/09/16 15:48:12 gollo Exp $ */ +/* $OpenBSD: socket.h,v 1.60 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $ */ /* @@ -44,6 +44,9 @@ * Definitions related to sockets: types, address families, options. */ +/* Maximum number of alternate routing tables */ +#define RT_TABLEID_MAX 255 + /* * Types */ @@ -82,6 +85,7 @@ #define SO_ERROR 0x1007 /* get error status and clear */ #define SO_TYPE 0x1008 /* get socket type */ #define SO_NETPROC 0x1020 /* multiplex; network processing */ +#define SO_RDOMAIN 0x1021 /* routing domain socket belongs to */ /* * Structure used for manipulating linger option. diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index b1480572a3a..4e2c89e190d 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sockio.h,v 1.44 2009/06/04 19:07:21 henning Exp $ */ +/* $OpenBSD: sockio.h,v 1.45 2009/06/05 00:05:22 claudio Exp $ */ /* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */ /*- @@ -173,6 +173,9 @@ #define SIOCSIFXFLAGS _IOW('i', 157, struct ifreq) /* set ifnet xflags */ #define SIOCGIFXFLAGS _IOWR('i', 158, struct ifreq) /* get ifnet xflags */ +#define SIOCSIFRTABLEID _IOW('i', 159, struct ifreq) /* set ifnet VRF id */ +#define SIOCGIFRTABLEID _IOWR('i', 160, struct ifreq) /* get ifnet VRF id */ + #define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp param */ #define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp param */ |