Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135301473
D9235.id25451.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D9235.id25451.diff
View Options
Index: sys/netinet/in.h
===================================================================
--- sys/netinet/in.h
+++ sys/netinet/in.h
@@ -433,6 +433,8 @@
#define IP_BINDANY 24 /* bool: allow bind to any address */
#define IP_BINDMULTI 25 /* bool: allow multiple listeners on a tuple */
#define IP_RSS_LISTEN_BUCKET 26 /* int; set RSS listen bucket */
+#define IP_ORIGDSTADDR 27 /* bool: receive IP dst addr/port w/dgram */
+#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR
/*
* Options for controlling the firewall and dummynet.
Index: sys/netinet/in_pcb.h
===================================================================
--- sys/netinet/in_pcb.h
+++ sys/netinet/in_pcb.h
@@ -618,6 +618,7 @@
#define INP_RECVFLOWID 0x00000100 /* populate recv datagram with flow info */
#define INP_RECVRSSBUCKETID 0x00000200 /* populate recv datagram with bucket id */
#define INP_RATE_LIMIT_CHANGED 0x00000400 /* rate limit needs attention */
+#define INP_ORIGDSTADDR 0x00000800 /* receive IP dst address/port */
/*
* Flags passed to in_pcblookup*() functions.
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c
+++ sys/netinet/in_pcb.c
@@ -2492,6 +2492,10 @@
db_printf("%sINP_RECVDSTADDR", comma ? ", " : "");
comma = 1;
}
+ if (inp_flags & INP_ORIGDSTADDR) {
+ db_printf("%sINP_ORIGDSTADDR", comma ? ", " : "");
+ comma = 1;
+ }
if (inp_flags & INP_HDRINCL) {
db_printf("%sINP_HDRINCL", comma ? ", " : "");
comma = 1;
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -1065,6 +1065,7 @@
case IP_MINTTL:
case IP_RECVOPTS:
case IP_RECVRETOPTS:
+ case IP_ORIGDSTADDR:
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
@@ -1126,6 +1127,10 @@
OPTSET(INP_RECVDSTADDR);
break;
+ case IP_ORIGDSTADDR:
+ OPTSET2(INP_ORIGDSTADDR, optval);
+ break;
+
case IP_RECVTTL:
OPTSET(INP_RECVTTL);
break;
@@ -1258,6 +1263,7 @@
case IP_MINTTL:
case IP_RECVOPTS:
case IP_RECVRETOPTS:
+ case IP_ORIGDSTADDR:
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
@@ -1303,6 +1309,10 @@
optval = OPTBIT(INP_RECVDSTADDR);
break;
+ case IP_ORIGDSTADDR:
+ optval = OPTBIT2(INP_ORIGDSTADDR);
+ break;
+
case IP_RECVTTL:
optval = OPTBIT(INP_RECVTTL);
break;
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -304,7 +304,7 @@
{
struct sockaddr *append_sa;
struct socket *so;
- struct mbuf *opts = NULL;
+ struct mbuf *tmpopts, *opts = NULL;
#ifdef INET6
struct sockaddr_in6 udp_in6;
#endif
@@ -319,7 +319,7 @@
if (up->u_tun_func != NULL) {
in_pcbref(inp);
INP_RUNLOCK(inp);
- (*up->u_tun_func)(n, off, inp, (struct sockaddr *)udp_in,
+ (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0],
up->u_tun_ctx);
INP_RLOCK(inp);
return (in_pcbrele_rlocked(inp));
@@ -355,16 +355,27 @@
#endif /* INET6 */
ip_savecontrol(inp, &opts, ip, n);
}
+ if ((inp->inp_vflag & INP_IPV4) && (inp->inp_flags2 & INP_ORIGDSTADDR)) {
+ tmpopts = sbcreatecontrol((caddr_t)&udp_in[1],
+ sizeof(struct sockaddr_in), IP_ORIGDSTADDR, IPPROTO_IP);
+ if (tmpopts) {
+ if (opts) {
+ tmpopts->m_next = opts;
+ opts = tmpopts;
+ } else
+ opts = tmpopts;
+ }
+ }
#ifdef INET6
if (inp->inp_vflag & INP_IPV6) {
bzero(&udp_in6, sizeof(udp_in6));
udp_in6.sin6_len = sizeof(udp_in6);
udp_in6.sin6_family = AF_INET6;
- in6_sin_2_v4mapsin6(udp_in, &udp_in6);
+ in6_sin_2_v4mapsin6(&udp_in[0], &udp_in6);
append_sa = (struct sockaddr *)&udp_in6;
} else
#endif /* INET6 */
- append_sa = (struct sockaddr *)udp_in;
+ append_sa = (struct sockaddr *)&udp_in[0];
m_adj(n, off);
so = inp->inp_socket;
@@ -390,7 +401,7 @@
uint16_t len, ip_len;
struct inpcbinfo *pcbinfo;
struct ip save_ip;
- struct sockaddr_in udp_in;
+ struct sockaddr_in udp_in[2];
struct mbuf *m;
struct m_tag *fwd_tag;
int cscov_partial, iphlen;
@@ -435,11 +446,15 @@
* Construct sockaddr format source address. Stuff source address
* and datagram in user buffer.
*/
- bzero(&udp_in, sizeof(udp_in));
- udp_in.sin_len = sizeof(udp_in);
- udp_in.sin_family = AF_INET;
- udp_in.sin_port = uh->uh_sport;
- udp_in.sin_addr = ip->ip_src;
+ bzero(&udp_in[0], sizeof(struct sockaddr_in) * 2);
+ udp_in[0].sin_len = sizeof(struct sockaddr_in);
+ udp_in[0].sin_family = AF_INET;
+ udp_in[0].sin_port = uh->uh_sport;
+ udp_in[0].sin_addr = ip->ip_src;
+ udp_in[1].sin_len = sizeof(struct sockaddr_in);
+ udp_in[1].sin_family = AF_INET;
+ udp_in[1].sin_port = uh->uh_dport;
+ udp_in[1].sin_addr = ip->ip_dst;
/*
* Make mbuf data length reflect UDP length. If not enough data to
@@ -568,7 +583,7 @@
blocked = imo_multi_filter(imo, ifp,
(struct sockaddr *)&group,
- (struct sockaddr *)&udp_in);
+ (struct sockaddr *)&udp_in[0]);
if (blocked != MCAST_PASS) {
if (blocked == MCAST_NOTGMEMBER)
IPSTAT_INC(ips_notmember);
@@ -587,7 +602,7 @@
UDP_PROBE(receive, NULL, last, ip,
last, uh);
if (udp_append(last, ip, n, iphlen,
- &udp_in)) {
+ udp_in)) {
goto inp_lost;
}
}
@@ -620,7 +635,7 @@
goto badunlocked;
}
UDP_PROBE(receive, NULL, last, ip, last, uh);
- if (udp_append(last, ip, m, iphlen, &udp_in) == 0)
+ if (udp_append(last, ip, m, iphlen, udp_in) == 0)
INP_RUNLOCK(last);
inp_lost:
INP_INFO_RUNLOCK(pcbinfo);
@@ -710,7 +725,7 @@
}
UDP_PROBE(receive, NULL, inp, ip, inp, uh);
- if (udp_append(inp, ip, m, iphlen, &udp_in) == 0)
+ if (udp_append(inp, ip, m, iphlen, udp_in) == 0)
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
Index: sys/netinet6/in6.h
===================================================================
--- sys/netinet6/in6.h
+++ sys/netinet6/in6.h
@@ -497,6 +497,9 @@
#define IPV6_RECVFLOWID 70 /* bool; receive IP6 flowid/flowtype w/ datagram */
#define IPV6_RECVRSSBUCKETID 71 /* bool; receive IP6 RSS bucket id w/ datagram */
+#define IPV6_ORIGDSTADDR 72 /* bool: allow getting dstaddr /port info */
+#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
+
/*
* The following option is private; do not use it from user applications.
* It is deliberately defined to the same value as IP_MSFILTER.
Index: sys/netinet6/in6_pcb.h
===================================================================
--- sys/netinet6/in6_pcb.h
+++ sys/netinet6/in6_pcb.h
@@ -113,7 +113,7 @@
int in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam);
int in6_selecthlim(struct in6pcb *, struct ifnet *);
int in6_pcbsetport(struct in6_addr *, struct inpcb *, struct ucred *);
-void init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m);
+void init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int);
#endif /* _KERNEL */
#endif /* !_NETINET6_IN6_PCB_H_ */
Index: sys/netinet6/in6_pcb.c
===================================================================
--- sys/netinet6/in6_pcb.c
+++ sys/netinet6/in6_pcb.c
@@ -1267,7 +1267,7 @@
}
void
-init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
+init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int srcordst)
{
struct ip6_hdr *ip;
@@ -1275,7 +1275,7 @@
bzero(sin6, sizeof(*sin6));
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_family = AF_INET6;
- sin6->sin6_addr = ip->ip6_src;
+ sin6->sin6_addr = srcordst ? ip->ip6_dst : ip->ip6_src;
(void)sa6_recoverscope(sin6); /* XXX: should catch errors... */
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -1545,6 +1545,7 @@
#endif
case IPV6_V6ONLY:
case IPV6_AUTOFLOWLABEL:
+ case IPV6_ORIGDSTADDR:
case IPV6_BINDANY:
case IPV6_BINDMULTI:
#ifdef RSS
@@ -1730,6 +1731,9 @@
OPTSET(IN6P_AUTOFLOWLABEL);
break;
+ case IPV6_ORIGDSTADDR:
+ OPTSET2(INP_ORIGDSTADDR, optval);
+ break;
case IPV6_BINDANY:
OPTSET(INP_BINDANY);
break;
@@ -2018,6 +2022,10 @@
optval = OPTBIT(IN6P_AUTOFLOWLABEL);
break;
+ case IPV6_ORIGDSTADDR:
+ optval = OPTBIT2(INP_ORIGDSTADDR);
+ break;
+
case IPV6_BINDANY:
optval = OPTBIT(INP_BINDANY);
break;
Index: sys/netinet6/raw_ip6.c
===================================================================
--- sys/netinet6/raw_ip6.c
+++ sys/netinet6/raw_ip6.c
@@ -166,7 +166,7 @@
RIP6STAT_INC(rip6s_ipackets);
- init_sin6(&fromsa, m); /* general init */
+ init_sin6(&fromsa, m, 0); /* general init */
ifp = m->m_pkthdr.rcvif;
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c
+++ sys/netinet6/udp6_usrreq.c
@@ -137,7 +137,7 @@
struct sockaddr_in6 *fromsa)
{
struct socket *so;
- struct mbuf *opts;
+ struct mbuf *opts = NULL, *tmp_opts;
struct udpcb *up;
INP_LOCK_ASSERT(inp);
@@ -149,7 +149,7 @@
if (up->u_tun_func != NULL) {
in_pcbref(inp);
INP_RUNLOCK(inp);
- (*up->u_tun_func)(n, off, inp, (struct sockaddr *)fromsa,
+ (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&fromsa[0],
up->u_tun_ctx);
INP_RLOCK(inp);
return (in_pcbrele_rlocked(inp));
@@ -173,11 +173,23 @@
if (inp->inp_flags & INP_CONTROLOPTS ||
inp->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(inp, n, &opts);
+ if ((inp->inp_vflag & INP_IPV6) && (inp->inp_flags2 & INP_ORIGDSTADDR)) {
+ tmp_opts = sbcreatecontrol((caddr_t)&fromsa[1],
+ sizeof(struct sockaddr_in6), IPV6_ORIGDSTADDR, IPPROTO_IPV6);
+ if (tmp_opts) {
+ if (opts) {
+ tmp_opts->m_next = opts;
+ opts = tmp_opts;
+ } else
+ opts = tmp_opts;
+ }
+
+ }
m_adj(n, off + sizeof(struct udphdr));
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
- if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)fromsa, n,
+ if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n,
opts) == 0) {
SOCKBUF_UNLOCK(&so->so_rcv);
m_freem(n);
@@ -202,7 +214,7 @@
int off = *offp;
int cscov_partial;
int plen, ulen;
- struct sockaddr_in6 fromsa;
+ struct sockaddr_in6 fromsa[2];
struct m_tag *fwd_tag;
uint16_t uh_sum;
uint8_t nxt;
@@ -277,8 +289,10 @@
/*
* Construct sockaddr format source address.
*/
- init_sin6(&fromsa, m);
- fromsa.sin6_port = uh->uh_sport;
+ init_sin6(&fromsa[0], m, 0);
+ fromsa[0].sin6_port = uh->uh_sport;
+ init_sin6(&fromsa[1], m, 1);
+ fromsa[1].sin6_port = uh->uh_dport;
pcbinfo = udp_get_inpcbinfo(nxt);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
@@ -349,7 +363,7 @@
blocked = im6o_mc_filter(imo, ifp,
(struct sockaddr *)&mcaddr,
- (struct sockaddr *)&fromsa);
+ (struct sockaddr *)&fromsa[0]);
if (blocked != MCAST_PASS) {
if (blocked == MCAST_NOTGMEMBER)
IP6STAT_INC(ip6s_notmember);
@@ -370,7 +384,7 @@
INP_RLOCK(last);
UDP_PROBE(receive, NULL, last, ip6,
last, uh);
- if (udp6_append(last, n, off, &fromsa))
+ if (udp6_append(last, n, off, fromsa))
goto inp_lost;
INP_RUNLOCK(last);
}
@@ -402,7 +416,7 @@
INP_RLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
UDP_PROBE(receive, NULL, last, ip6, last, uh);
- if (udp6_append(last, m, off, &fromsa) == 0)
+ if (udp6_append(last, m, off, fromsa) == 0)
INP_RUNLOCK(last);
inp_lost:
return (IPPROTO_DONE);
@@ -482,7 +496,7 @@
}
}
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
- if (udp6_append(inp, m, off, &fromsa) == 0)
+ if (udp6_append(inp, m, off, fromsa) == 0)
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 9, 12:24 PM (14 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25071969
Default Alt Text
D9235.id25451.diff (11 KB)
Attached To
Mode
D9235: Provide IP_ORIGDSTADDR socket option
Attached
Detach File
Event Timeline
Log In to Comment