Socket option to get dst port
Scot Loach
sloach at SANDVINE.com
Thu May 29 09:23:12 PDT 2003
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
More information about the freebsd-net
mailing list