From cb0369e615ef56c1da2080a41fa13572d3f8f2d7 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Fri, 5 Jun 2009 00:05:23 +0000 Subject: Initial support for routing domains. This allows to bind interfaces to alternate routing table and separate them from other interfaces in distinct routing tables. The same network can now be used in any doamin at the same time without causing conflicts. This diff is mostly mechanical and adds the necessary rdomain checks accross net and netinet. L2 and IPv4 are mostly covered still missing pf and IPv6. input and tested by jsg@, phessler@ and reyk@. "put it in" deraadt@ --- sys/kern/uipc_mbuf.c | 3 +- sys/kern/uipc_socket.c | 4 +- sys/net/if.c | 89 +++++++++++++++++++++++++++++++++------- sys/net/if.h | 14 ++++--- sys/net/if_ethersubr.c | 23 +++++++++-- sys/net/if_fddisubr.c | 4 +- sys/net/pf.c | 46 +++++++++++++-------- sys/net/route.c | 71 ++++++++++++++++++-------------- sys/net/route.h | 8 ++-- sys/net/rtsock.c | 17 +++++--- sys/netinet/if_ether.c | 30 +++++++++----- sys/netinet/in.c | 19 ++++++--- sys/netinet/in.h | 4 +- sys/netinet/in_pcb.c | 103 +++++++++++++++++++++++------------------------ sys/netinet/in_pcb.h | 11 ++--- sys/netinet/in_var.h | 7 ++-- sys/netinet/ip_carp.c | 29 ++++++++----- sys/netinet/ip_icmp.c | 25 +++++++----- sys/netinet/ip_icmp.h | 6 +-- sys/netinet/ip_input.c | 64 +++++++++++++++++------------ sys/netinet/ip_ipip.c | 4 +- sys/netinet/ip_mroute.c | 4 +- sys/netinet/ip_output.c | 77 +++++++++++++++++++++++------------ sys/netinet/ip_var.h | 8 ++-- sys/netinet/raw_ip.c | 12 +++++- sys/netinet/tcp_input.c | 10 +++-- sys/netinet/tcp_output.c | 5 ++- sys/netinet/tcp_subr.c | 11 +++-- sys/netinet/tcp_timer.c | 7 ++-- sys/netinet/tcp_usrreq.c | 13 ++---- sys/netinet/tcp_var.h | 3 +- sys/netinet/udp_usrreq.c | 16 ++++++-- sys/netinet6/icmp6.c | 6 +-- sys/netinet6/in6_pcb.c | 14 +++---- sys/netinet6/raw_ip6.c | 5 ++- sys/sys/mbuf.h | 5 ++- sys/sys/socket.h | 6 ++- sys/sys/sockio.h | 5 ++- 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 #include #include +#include #include 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 */ -- cgit v1.2.3