Hi David,

On Tue, Feb 22, 2022 at 5:27 AM David Gwynne <[email protected]> wrote:

>
>
> > On 22 Feb 2022, at 06:31, K R <[email protected]> wrote:
> >
> >> Synopsis:      UDP divert-to rule: getsockname(2) won't show original
> > destination
> >> Category:      kernel amd64
> >> Environment:
> >        System      : OpenBSD 7.1-beta
> >        Details     : OpenBSD 7.1-beta (GENERIC) #353: Sun Feb 20 17:14:05
> > MST 2022
> >
> >        Architecture: OpenBSD.amd64
> >        Machine     : amd64
> >> Description:
> >
> > getsockname(2) won't show the original destination address/port for a
> > UDP inet packet redirected using a PF divert-to rule to a local
> > socket.
> >
> > This works as expected for TCP.
> >
> >> How-To-Repeat:
> >
> > server:
> >
> > (pf.conf)
> > pass in on vio0 inet proto udp from any to 100.64.0.100 divert-to
> 127.0.0.1
> > port 9000
> >
> >>>> import socket
> >>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> >>>> s.bind(("127.0.0.1", 9000))
> >>>> s.recvfrom(1024)
> > (b'data\n', ('100.64.0.1', 16079))
> >>>> s.getsockname()
> > ('127.0.0.1', 9000)
> >
> > client:
> >
> > $ echo data | nc -u 100.64.0.100 12345
> >
> >> Fix:
> >        Unknown.
>
> This is working as expected for UDP, which is a datagram socket, not a
> connected TCP stream socket like what you're trying to compare it to. A
> locally bound but not connected UDP socket will not keep information about
> received packets on it, you have to get all that from the messages as
> they're being received.
>
> If you want the original destination address for that message, you have to
> ask for it as part of receiving the message. For IPv4 you do that by
> setting the IP_RECVDSTADDR sockopt on the UDP socket, and then using
> recvmsg() instead of recvfrom() with space for a control message set up for
> it to use.
>

Thanks, of course, you are right.  Now that you mentioned it, I could find
this information on the ip(4)

     If the IP_RECVDSTADDR option is enabled on a SOCK_DGRAM socket, the
     recvmsg(2) call will return the destination IP address for a UDP
     datagram.  The msg_control field in the msghdr structure points to a
     buffer that contains a cmsghdr structure followed by the IP address.
     [...]

and pf(4) manpages:

             getsockname(2).  For SOCK_DGRAM sockets, the ip(4) socket
             options IP_RECVDSTADDR and IP_RECVDSTPORT can be used to
             retrieve the destination address and port.

What would be nice, IMHO, is to make this clear on the pf.conf(5)
manpage when diverto-to is mentioned:

     divert-to host port port
             Used to redirect packets to a local socket bound to host and
             port.  The packets will not be modified, so getsockname(2) on
             the socket will return the original destination address of the
             packet.


> src/usr.bin/tftpd/tftpd.c does this if you want some code to refer to.
>

I believe it is src/usr.sbin/tftp-proxy/tftp-proxy.c, correct?

Thank again!

--Kor


>
> dlg

Reply via email to