On Fri, Dec 15, 2017 at 03:10:49PM +0100, Alexander Bluhm wrote:
> Hi,
>
> With pf divert raw sockets behave differently than TCP or UDP.
>
> TCP and UDP first make an exact match without divert in_pcbhashlookup().
> Then they do the divert-to match in in_pcblookup_listen().
>
> This diff makes it consistent. Search for bound and connected
> sockets in raw_input() also if diverted, only use unconnected sockets
> with divert-to.
>
> ok?
Anyone?
> Index: netinet/raw_ip.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v
> retrieving revision 1.108
> diff -u -p -r1.108 raw_ip.c
> --- netinet/raw_ip.c 4 Dec 2017 13:40:34 - 1.108
> +++ netinet/raw_ip.c 15 Dec 2017 12:59:29 -
> @@ -121,7 +121,7 @@ rip_input(struct mbuf **mp, int *offp, i
> struct mbuf *m = *mp;
> struct ip *ip = mtod(m, struct ip *);
> struct inpcb *inp, *last = NULL;
> - struct in_addr *key;
> + struct in_addr *key = NULL;
> struct mbuf *opts = NULL;
> struct counters_ref ref;
> uint64_t *counters;
> @@ -129,7 +129,6 @@ rip_input(struct mbuf **mp, int *offp, i
> KASSERT(af == AF_INET);
>
> ripsrc.sin_addr = ip->ip_src;
> - key = >ip_dst;
> #if NPF > 0
> if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
> struct pf_divert *divert;
> @@ -163,7 +162,10 @@ rip_input(struct mbuf **mp, int *offp, i
> if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
> continue;
> if (inp->inp_laddr.s_addr &&
> - inp->inp_laddr.s_addr != key->s_addr)
> + inp->inp_laddr.s_addr != ip->ip_dst.s_addr &&
> + /* divert-to matches on bound but unconnected socket */
> + (key == NULL || inp->inp_faddr.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)
> Index: netinet6/raw_ip6.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v
> retrieving revision 1.125
> diff -u -p -r1.125 raw_ip6.c
> --- netinet6/raw_ip6.c4 Dec 2017 13:40:35 - 1.125
> +++ netinet6/raw_ip6.c15 Dec 2017 12:59:29 -
> @@ -122,7 +122,7 @@ rip6_input(struct mbuf **mp, int *offp,
> struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
> struct inpcb *in6p;
> struct inpcb *last = NULL;
> - struct in6_addr *key;
> + struct in6_addr *key = NULL;
> struct sockaddr_in6 rip6src;
> struct mbuf *opts = NULL;
>
> @@ -137,7 +137,6 @@ rip6_input(struct mbuf **mp, int *offp,
> /* KAME hack: recover scopeid */
> in6_recoverscope(, >ip6_src);
>
> - key = >ip6_dst;
> #if NPF > 0
> if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
> struct pf_divert *divert;
> @@ -167,7 +166,10 @@ rip6_input(struct mbuf **mp, int *offp,
> in6p->inp_ipv6.ip6_nxt != proto)
> continue;
> if (!IN6_IS_ADDR_UNSPECIFIED(>inp_laddr6) &&
> - !IN6_ARE_ADDR_EQUAL(>inp_laddr6, key))
> + !IN6_ARE_ADDR_EQUAL(>inp_laddr6, >ip6_dst) &&
> + /* divert-to matches on bound but unconnected socket */
> + (key == NULL || !IN6_IS_ADDR_UNSPECIFIED(>inp_faddr6)
> + || !IN6_ARE_ADDR_EQUAL(>inp_laddr6, key)))
> continue;
> if (!IN6_IS_ADDR_UNSPECIFIED(>inp_faddr6) &&
> !IN6_ARE_ADDR_EQUAL(>inp_faddr6, >ip6_src))