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 -0000       1.108
> +++ netinet/raw_ip.c  15 Dec 2017 12:59:29 -0000
> @@ -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->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.c        4 Dec 2017 13:40:35 -0000       1.125
> +++ netinet6/raw_ip6.c        15 Dec 2017 12:59:29 -0000
> @@ -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(&rip6src, &ip6->ip6_src);
>  
> -     key = &ip6->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(&in6p->inp_laddr6) &&
> -                 !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, key))
> +                 !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, &ip6->ip6_dst) &&
> +                 /* divert-to matches on bound but unconnected socket */
> +                 (key == NULL || !IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_faddr6)
> +                 || !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))

Reply via email to