Re: pf divert raw sockets

2017-12-22 Thread Alexander Bluhm
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))



pf divert raw sockets

2017-12-15 Thread Alexander Bluhm
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?

bluhm

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.c4 Dec 2017 13:40:34 -   1.108
+++ netinet/raw_ip.c15 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.c  4 Dec 2017 13:40:35 -   1.125
+++ netinet6/raw_ip6.c  15 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))