Hello,

I have added IPV6_RECVDSTPORT socket option, which enables us to get
original (= before divert) destination port of a UDP packet. The way to
use this option is same as IP_RECVDSTPORT.

The values of IPV6_RECVDSTPORT and IN6P_RECVDSTPORT are temporary.

------------------------------------------------------------------------
UMEZAWA Takeshi (FAMILY Given) <[email protected]>
Internet Initiative Japan Inc.


diff --git a/share/man/man4/ip6.4 b/share/man/man4/ip6.4
index dc54d77..0090b85 100644
--- a/share/man/man4/ip6.4
+++ b/share/man/man4/ip6.4
@@ -421,6 +421,16 @@ Get or set the ESP encapsulation level.
 Get or set the
 .Xr ipcomp 4
 level.
+.It Dv IPV6_RECVDSTPORT Fa "int *"
+Get or set the status of whether the destination port for a UDP datagram
+will be provided as ancillary data along with the payload in subsequent 
+.Xr recvmsg 2
+calls. The information is stored as a single value of type
+.Vt u_int16_t
+in network byte order.
+.Pp
+Turning this option on will result in this socket getting cmsg data of
+type IPV6_RECVDSTPORT.
 .El
 .Pp
 The
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 9d4f0d9..def52de 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -196,6 +196,7 @@ struct inpcbtable {
  */
 #define IN6P_HIGHPORT          INP_HIGHPORT    /* user wants "high" port */
 #define IN6P_LOWPORT           INP_LOWPORT     /* user wants "low" port */
+#define IN6P_RECVDSTPORT       INP_RECVDSTPORT /* receive IP dst addr before 
rdr */
 #define IN6P_PKTINFO           0x010000 /* receive IP6 dst and I/F */
 #define IN6P_HOPLIMIT          0x020000 /* receive hoplimit */
 #define IN6P_HOPOPTS           0x040000 /* receive hop-by-hop options */
@@ -215,7 +216,7 @@ struct inpcbtable {
 #define IN6P_CONTROLOPTS       (IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
                                 IN6P_DSTOPTS|IN6P_RTHDR|IN6P_RTHDRDSTOPTS|\
                                 IN6P_TCLASS|IN6P_AUTOFLOWLABEL|IN6P_RFC2292|\
-                                IN6P_MTU)
+                                IN6P_MTU|IN6P_RECVDSTPORT)
 #endif
 
 #define        INPLOOKUP_WILDCARD      1
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 5a8d8e5..44c3472 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -688,6 +688,16 @@ udp_input(struct mbuf *m, ...)
        if (ip && (inp->inp_flags & INP_CONTROLOPTS ||
            inp->inp_socket->so_options & SO_TIMESTAMP))
                ip_savecontrol(inp, &opts, ip, m);
+#ifdef INET6
+       if (ip6 && (inp->inp_flags & IN6P_RECVDSTPORT)) {
+               struct mbuf **mp = &opts;
+
+               while (*mp)
+                       mp = &(*mp)->m_next;
+               *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t),
+                   IPV6_RECVDSTPORT, IPPROTO_IPV6);
+       }
+#endif /* INET6 */
        if (ip && (inp->inp_flags & INP_RECVDSTPORT)) {
                struct mbuf **mp = &opts;
 
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index 664bca9..395ef9d 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -451,6 +451,8 @@ struct route_in6 {
 #define IPV6_DONTFRAG          62   /* bool; disable IPv6 fragmentation */
 #define IPV6_PIPEX             63   /* bool; using PIPEX */
 
+#define IPV6_RECVDSTPORT       64   /* bool; receive IP dst port w/dgram */
+
 #define IPV6_RTABLE            0x1021  /* int; routing table, see SO_RTABLE */
 
 /* to define items, should talk with KAME guys first, for *BSD compatibility */
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 07aedee..d4a371d 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1356,6 +1356,7 @@ ip6_ctloutput(int op, struct socket *so, int level, int 
optname,
                        case IPV6_RECVTCLASS:
                        case IPV6_V6ONLY:
                        case IPV6_AUTOFLOWLABEL:
+                       case IPV6_RECVDSTPORT:
                                if (m == NULL || m->m_len != sizeof(int)) {
                                        error = EINVAL;
                                        break;
@@ -1504,6 +1505,9 @@ do { \
                                        OPTSET(IN6P_AUTOFLOWLABEL);
                                        break;
 
+                               case IPV6_RECVDSTPORT:
+                                       OPTSET(IN6P_RECVDSTPORT);
+                                       break;
                                }
                                break;
 
@@ -1766,6 +1770,7 @@ do { \
                        case IPV6_PORTRANGE:
                        case IPV6_RECVTCLASS:
                        case IPV6_AUTOFLOWLABEL:
+                       case IPV6_RECVDSTPORT:
                                switch (optname) {
 
                                case IPV6_RECVHOPOPTS:
@@ -1827,6 +1832,10 @@ do { \
                                case IPV6_AUTOFLOWLABEL:
                                        optval = OPTBIT(IN6P_AUTOFLOWLABEL);
                                        break;
+
+                               case IPV6_RECVDSTPORT:
+                                       optval = OPTBIT(IN6P_RECVDSTPORT);
+                                       break;
                                }
                                if (error)
                                        break;

Reply via email to