From owner-freebsd-net@FreeBSD.ORG Thu May 29 09:23:12 2003 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E0EE337B401 for ; Thu, 29 May 2003 09:23:11 -0700 (PDT) Received: from mail.sandvine.com (sandvine.com [199.243.201.138]) by mx1.FreeBSD.org (Postfix) with ESMTP id 13A1943F85 for ; Thu, 29 May 2003 09:23:11 -0700 (PDT) (envelope-from sloach@SANDVINE.com) Received: by mail.sandvine.com with Internet Mail Service (5.5.2653.19) id ; Thu, 29 May 2003 12:23:10 -0400 Message-ID: From: Scot Loach To: "'freebsd-net@freebsd.org'" Date: Thu, 29 May 2003 12:23:06 -0400 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2653.19) Content-Type: text/plain; charset="iso-8859-1" Subject: Socket option to get dst port X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 May 2003 16:23:12 -0000 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