Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 May 2003 12:23:06 -0400
From:      Scot Loach <sloach@SANDVINE.com>
To:        "'freebsd-net@freebsd.org'" <freebsd-net@freebsd.org>
Subject:   Socket option to get dst port
Message-ID:  <FE045D4D9F7AED4CBFF1B3B813C8533701AE82E6@mail.sandvine.com>

next in thread | raw e-mail | index | archive | help
When a UDP packet is read from a socket, the userland program can get the
destination IP address by using the IP_RECVDSTADDR socket option.  This
returns the destination address as ancillary data in the msg_control member
of the msghdr structure passed to recvmsg().

I needed a way to get the destination port for UDP packets that were
forwarded to a local UDP port using ipfw, with the "fwd" option.  There
doesn't seem to be any way to get this information currently.  I added a
IP_RECVDSTPORT socket option for this purpose.  Unfortunately I had to add
the control mbuf within udp_input() instead of within ip_savecontrol() since
that's the only place I have the UDP header.

Patch to 4.7 is below.  Please let me know if you see any problems with it.
If this is generally useful, it could be committed.

Index: in.h
===================================================================
RCS file: /usr/cvs/src/sys/netinet/in.h,v
retrieving revision 1.48.2.9
diff -U3 -r1.48.2.9 in.h
--- in.h        1 Dec 2002 14:03:10 -0000       1.48.2.9
+++ in.h        29 May 2003 15:56:19 -0000
@@ -333,6 +333,8 @@
 #define        IP_DUMMYNET_FLUSH       62   /* flush dummynet */
 #define        IP_DUMMYNET_GET         64   /* get entire dummynet pipes */

+#define IP_RECVDSTPORT          80   /* bool; receive IP dst port w/dgram
*/
+
 /*
  * Defaults and limits for options
  */
Index: in_pcb.h
===================================================================
RCS file: /usr/cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.32.2.6
diff -U3 -r1.32.2.6 in_pcb.h
--- in_pcb.h    29 Jul 2002 18:56:37 -0000      1.32.2.6
+++ in_pcb.h    29 May 2003 15:56:13 -0000
@@ -273,8 +273,10 @@
 #define        IN6P_RTHDRDSTOPTS       0x200000 /* receive dstoptions
before rt
hdr */
 #define IN6P_AUTOFLOWLABEL     0x800000 /* attach flowlabel automatically
*/

+#define INP_RECVDSTPORT         0x01000000 /* receive UDP dst port */
+
 #define        INP_CONTROLOPTS
(INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDS
TADDR|\
-                                       INP_RECVIF|\
+                                       INP_RECVIF| INP_RECVDSTPORT |\
                                 IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
                                 IN6P_DSTOPTS|IN6P_RTHDR|IN6P_RTHDRDSTOPTS|\
                                 IN6P_AUTOFLOWLABEL)
Index: ip_output.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.99.2.31
diff -U3 -r1.99.2.31 ip_output.c
--- ip_output.c 12 Jul 2002 22:14:12 -0000      1.99.2.31
+++ ip_output.c 28 May 2003 19:32:57 -0000
@@ -1181,6 +1181,7 @@
                case IP_RECVOPTS:
                case IP_RECVRETOPTS:
                case IP_RECVDSTADDR:
+                case IP_RECVDSTPORT:
                case IP_RECVIF:
                case IP_FAITH:
                        error = sooptcopyin(sopt, &optval, sizeof optval,
@@ -1213,6 +1214,10 @@
                        case IP_RECVDSTADDR:
                                OPTSET(INP_RECVDSTADDR);
                                break;
+
+                        case IP_RECVDSTPORT:
+                                OPTSET(INP_RECVDSTPORT);
+                                break;

                        case IP_RECVIF:
                                OPTSET(INP_RECVIF);
Index: udp_usrreq.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.64.2.16.1000.2
diff -U3 -r1.64.2.16.1000.2 udp_usrreq.c
--- udp_usrreq.c        27 Jan 2003 16:38:06 -0000      1.64.2.16.1000.2
+++ udp_usrreq.c        29 May 2003 15:55:24 -0000
@@ -450,7 +450,18 @@
                        inp->inp_flags = savedflags;
                } else
 #endif
-               ip_savecontrol(inp, &opts, ip, m);
+               {
+                       ip_savecontrol(inp, &opts, ip, m);
+                       if (inp->inp_flags & INP_RECVDSTPORT) {
+                               struct mbuf **mp = &opts;
+                               while (*mp) {
+                                       mp = &(*mp)->m_next;
+                               }
+                               *mp = sbcreatecontrol((caddr_t)
&uh->uh_dport,
+                                    sizeof(u_int16_t), IP_RECVDSTPORT,
+                                    IPPROTO_IP);
+                       }
+               }
        }
        m_adj(m, iphlen + sizeof(struct udphdr));
 #ifdef INET6



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?FE045D4D9F7AED4CBFF1B3B813C8533701AE82E6>