From c7745dcb75536400e2a7cb73741b11d0410874cf Mon Sep 17 00:00:00 2001 From: bluhm Date: Mon, 4 Dec 2017 13:40:34 +0000 Subject: [PATCH] Make divert lookup similar for all socket types. If PF_TAG_DIVERTED is set, pf_find_divert() cannot fail so put an assert there. Explicitly check all possible divert types, panic in the default case. For raw sockets call pf_find_divert() before of the socket loop. Divert reply should not match on TCP or UDP listen sockets. OK sashan@ visa@ --- sys/netinet/in_pcb.c | 32 +++++++++++++++++++++++++------- sys/netinet/ip_input.c | 11 +++++++---- sys/netinet/raw_ip.c | 38 ++++++++++++++++++++++---------------- sys/netinet/tcp_input.c | 14 +++++++------- sys/netinet6/raw_ip6.c | 40 +++++++++++++++++++++++----------------- 5 files changed, 84 insertions(+), 51 deletions(-) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 785a34c1d5e..82c95755f82 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.226 2017/12/01 12:40:58 bluhm Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.227 2017/12/04 13:40:34 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -1147,10 +1147,19 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; - if ((divert = pf_find_divert(m)) == NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key1 = key2 = &divert->addr.v4; + lport = divert->port; + break; + case PF_DIVERT_REPLY: return (NULL); - key1 = key2 = &divert->addr.v4; - lport = divert->port; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { key1 = &zeroin_addr; key2 = &laddr; @@ -1218,10 +1227,19 @@ in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr, if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; - if ((divert = pf_find_divert(m)) == NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key1 = key2 = &divert->addr.v6; + lport = divert->port; + break; + case PF_DIVERT_REPLY: return (NULL); - key1 = key2 = &divert->addr.v6; - lport = divert->port; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { key1 = &zeroin6_addr; key2 = laddr; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 695cf415b1c..8428a893976 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.334 2017/11/23 13:45:46 mpi Exp $ */ +/* $OpenBSD: ip_input.c,v 1.335 2017/12/04 13:40:34 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -1769,12 +1769,15 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, } if (inp->inp_flags & INP_RECVRTABLE) { u_int rtableid = inp->inp_rtableid; + #if NPF > 0 - struct pf_divert *divert; + if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; - if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED && - (divert = pf_find_divert(m)) != NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); rtableid = divert->rdomain; + } #endif *mp = sbcreatecontrol((caddr_t) &rtableid, diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 85986a64900..79f2a0ca94a 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.107 2017/11/28 16:05:46 bluhm Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.108 2017/12/04 13:40:34 bluhm Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -121,6 +121,7 @@ rip_input(struct mbuf **mp, int *offp, int proto, int af) struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct inpcb *inp, *last = NULL; + struct in_addr *key; struct mbuf *opts = NULL; struct counters_ref ref; uint64_t *counters; @@ -128,6 +129,25 @@ rip_input(struct mbuf **mp, int *offp, int proto, int af) KASSERT(af == AF_INET); ripsrc.sin_addr = ip->ip_src; + key = &ip->ip_dst; +#if NPF > 0 + if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; + + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key = &divert->addr.v4; + break; + case PF_DIVERT_REPLY: + break; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } + } +#endif NET_ASSERT_LOCKED(); TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { if (inp->inp_socket->so_state & SS_CANTRCVMORE) @@ -142,22 +162,8 @@ rip_input(struct mbuf **mp, int *offp, int proto, int af) 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 (divert->type == PF_DIVERT_REPLY) - goto divert_reply; - if (inp->inp_laddr.s_addr != divert->addr.v4.s_addr) - continue; - } else - divert_reply: -#endif if (inp->inp_laddr.s_addr && - inp->inp_laddr.s_addr != ip->ip_dst.s_addr) + inp->inp_laddr.s_addr != key->s_addr) continue; if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 1112bce418d..d52fd579650 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.353 2017/12/01 10:33:33 bluhm Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.354 2017/12/04 13:40:34 bluhm Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -3454,9 +3454,6 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th, struct tcpcb *tp = NULL; struct mbuf *am; struct socket *oso; -#if NPF > 0 - struct pf_divert *divert = NULL; -#endif NET_ASSERT_LOCKED(); @@ -3517,10 +3514,13 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th, } #if NPF > 0 - if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED && - (divert = pf_find_divert(m)) != NULL) + if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; + + divert = pf_find_divert(m); + KASSERT(divert != NULL); inp->inp_rtableid = divert->rdomain; - else + } else #endif /* inherit rtable from listening socket */ inp->inp_rtableid = sc->sc_rtableid; diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 17987db85ad..8824f88987d 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.124 2017/11/28 16:05:46 bluhm Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.125 2017/12/04 13:40:35 bluhm Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -122,6 +122,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct inpcb *in6p; struct inpcb *last = NULL; + struct in6_addr *key; struct sockaddr_in6 rip6src; struct mbuf *opts = NULL; @@ -136,6 +137,26 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) /* KAME hack: recover scopeid */ in6_recoverscope(&rip6src, &ip6->ip6_src); + key = &ip6->ip6_dst; +#if NPF > 0 + if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; + + /* XXX rdomain support */ + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key = &divert->addr.v6; + break; + case PF_DIVERT_REPLY: + break; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } + } +#endif NET_ASSERT_LOCKED(); TAILQ_FOREACH(in6p, &rawin6pcbtable.inpt_queue, inp_queue) { if (in6p->inp_socket->so_state & SS_CANTRCVMORE) @@ -145,23 +166,8 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) if ((in6p->inp_ipv6.ip6_nxt || proto == IPPROTO_ICMPV6) && in6p->inp_ipv6.ip6_nxt != proto) 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 (divert->type == PF_DIVERT_REPLY) - goto divert_reply; - if (!IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, - &divert->addr.v6)) - continue; - } else - divert_reply: -#endif if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_laddr6) && - !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, &ip6->ip6_dst)) + !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, key)) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_faddr6) && !IN6_ARE_ADDR_EQUAL(&in6p->inp_faddr6, &ip6->ip6_src)) -- 2.20.1