On Thu, Jan 28, 2021 at 08:15:06AM +0100, Claudio Jeker wrote:
> On Thu, Jan 28, 2021 at 09:57:33AM +1000, David Gwynne wrote:
> > calling if_output with a route to a local IP is confusing, and I'm not
> > sure it makes sense anyway.
> > 
> > this treats a an RTF_LOCAL route like an invalid round and drops the
> > packet.
> > 
> > ok?
> 
> Isn't this a change of behaviour? I think ip_output() fill pass the packet
> via loopback back into the system. Which is probably strange for route-to
> / reply-to (since there is divert-to and rdr-to for this). What about
> dup-to? 

Yes, it's a deliberate change of behaviour. If pf_route resolves an
RTF_LOCAL route, it tries to push it straight out the interface output
routine. For tunnel style interfaces, it pushes the packet straight over
to the other side. For broadcast (Ethernet), I'd have to read some code,
but my guess is that we'll send an ethernet packet to ourselves.

Neither of those are desirable. So do we reject the packet like this
diff suggests? Or do I copy more of ip_output into pf_route? Or do we
look at cutting ip_output in half so pf_route can call the tail of it?

The only difference between route-to/reply-to and dup-to is that dup-to
does not get the icmp error generated. The RTF_LOCAL destined packets
would still be dropped though.

dlg

>  
> > Index: pf.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/pf.c,v
> > retrieving revision 1.1104
> > diff -u -p -r1.1104 pf.c
> > --- pf.c    27 Jan 2021 23:53:35 -0000      1.1104
> > +++ pf.c    27 Jan 2021 23:55:49 -0000
> > @@ -6054,7 +6054,7 @@ pf_route(struct pf_pdesc *pd, struct pf_
> >     }
> >  
> >     rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
> > -   if (!rtisvalid(rt)) {
> > +   if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_LOCAL)) {
> >             if (r->rt != PF_DUPTO) {
> >                     pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST,
> >                         0, pd->af, s->rule.ptr, pd->rdomain);
> > @@ -6213,7 +6213,7 @@ pf_route6(struct pf_pdesc *pd, struct pf
> >     if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr))
> >             dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
> >     rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
> > -   if (!rtisvalid(rt)) {
> > +   if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_LOCAL)) {
> >             if (r->rt != PF_DUPTO) {
> >                     pf_send_icmp(m0, ICMP6_DST_UNREACH,
> >                         ICMP6_DST_UNREACH_NOROUTE, 0,
> > 
> 
> -- 
> :wq Claudio

Reply via email to