Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150802678
D9235.id24171.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.id24171.diff
View Options
Index: sys/netinet/in.h
===================================================================
--- sys/netinet/in.h
+++ sys/netinet/in.h
@@ -432,6 +432,8 @@
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
#define IP_BINDANY 24 /* bool: allow bind to any address */
+#define IP_ORIGDSTADDR 25 /* 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
@@ -546,6 +546,7 @@
#define INP_REUSEPORT 0x00000008 /* SO_REUSEPORT option is set */
#define INP_FREED 0x00000010 /* inp itself is not valid */
#define INP_REUSEADDR 0x00000020 /* SO_REUSEADDR option is set */
+#define INP_ORIGDSTADDR 0x00000040 /* 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
@@ -2292,6 +2292,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
@@ -986,6 +986,7 @@
case IP_MINTTL:
case IP_RECVOPTS:
case IP_RECVRETOPTS:
+ case IP_ORIGDSTADDR:
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
@@ -1035,6 +1036,15 @@
OPTSET(INP_RECVDSTADDR);
break;
+ case IP_ORIGDSTADDR:
+ INP_WLOCK(inp);
+ if (optval)
+ inp->inp_flags2 |= INP_ORIGDSTADDR;
+ else
+ inp->inp_flags2 &= ~INP_ORIGDSTADDR;
+ INP_WUNLOCK(inp);
+ break;
+
case IP_RECVTTL:
OPTSET(INP_RECVTTL);
break;
@@ -1160,6 +1170,7 @@
case IP_MINTTL:
case IP_RECVOPTS:
case IP_RECVRETOPTS:
+ case IP_ORIGDSTADDR:
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
@@ -1197,6 +1208,10 @@
optval = OPTBIT(INP_RECVDSTADDR);
break;
+ case IP_ORIGDSTADDR:
+ optval = inp->inp_flags2 & 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
@@ -290,7 +290,7 @@
{
struct sockaddr *append_sa;
struct socket *so;
- struct mbuf *opts = 0;
+ struct mbuf *tmpopts, *opts = 0;
#ifdef INET6
struct sockaddr_in6 udp_in6;
#endif
@@ -303,7 +303,7 @@
*/
up = intoudpcb(inp);
if (up->u_tun_func != NULL) {
- (*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);
return;
}
@@ -342,16 +342,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;
@@ -377,7 +388,7 @@
uint16_t len, ip_len;
struct inpcbinfo *pcbinfo;
struct ip save_ip;
- struct sockaddr_in udp_in;
+ struct sockaddr_in udpin[2];
struct m_tag *fwd_tag;
int cscov_partial;
uint8_t pr;
@@ -420,11 +431,16 @@
* 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(&udpin[0], sizeof(struct sockaddr_in));
+ udpin[0].sin_len = sizeof(struct sockaddr_in);
+ udpin[0].sin_family = AF_INET;
+ udpin[0].sin_port = uh->uh_sport;
+ udpin[0].sin_addr = ip->ip_src;
+ bzero(&udpin[1], sizeof(struct sockaddr_in));
+ udpin[1].sin_len = sizeof(struct sockaddr_in);
+ udpin[1].sin_family = AF_INET;
+ udpin[1].sin_port = uh->uh_dport;
+ udpin[1].sin_addr = ip->ip_dst;
/*
* Make mbuf data length reflect UDP length. If not enough data to
@@ -552,7 +568,7 @@
blocked = imo_multi_filter(imo, ifp,
(struct sockaddr *)&group,
- (struct sockaddr *)&udp_in);
+ (struct sockaddr *)&udpin[0]);
if (blocked != MCAST_PASS) {
if (blocked == MCAST_NOTGMEMBER)
IPSTAT_INC(ips_notmember);
@@ -570,7 +586,7 @@
UDP_PROBE(receive, NULL, last, ip,
last, uh);
udp_append(last, ip, n, iphlen,
- &udp_in);
+ udpin);
}
INP_RUNLOCK(last);
}
@@ -601,7 +617,7 @@
goto badunlocked;
}
UDP_PROBE(receive, NULL, last, ip, last, uh);
- udp_append(last, ip, m, iphlen, &udp_in);
+ udp_append(last, ip, m, iphlen, udpin);
INP_RUNLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
return;
@@ -690,7 +706,7 @@
}
UDP_PROBE(receive, NULL, inp, ip, inp, uh);
- udp_append(inp, ip, m, iphlen, &udp_in);
+ udp_append(inp, ip, m, iphlen, udpin);
INP_RUNLOCK(inp);
return;
Index: sys/netinet6/in6.h
===================================================================
--- sys/netinet6/in6.h
+++ sys/netinet6/in6.h
@@ -481,6 +481,9 @@
#define IPV6_BINDANY 64 /* bool: allow bind to any address */
+#define IPV6_ORIGDSTADDR 65 /* 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
@@ -118,7 +118,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
@@ -1182,7 +1182,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;
@@ -1190,7 +1190,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
@@ -1395,6 +1395,7 @@
case IPV6_RECVTCLASS:
case IPV6_V6ONLY:
case IPV6_AUTOFLOWLABEL:
+ case IPV6_ORIGDSTADDR:
case IPV6_BINDANY:
if (optname == IPV6_BINDANY && td != NULL) {
error = priv_check(td,
@@ -1560,6 +1561,14 @@
OPTSET(IN6P_AUTOFLOWLABEL);
break;
+ case IPV6_ORIGDSTADDR:
+ INP_WLOCK(in6p);
+ if (optval)
+ in6p->inp_flags2 |= INP_ORIGDSTADDR;
+ else
+ in6p->inp_flags2 &= ~INP_ORIGDSTADDR;
+ INP_WUNLOCK(in6p);
+ break;
case IPV6_BINDANY:
OPTSET(INP_BINDANY);
break;
@@ -1840,6 +1849,10 @@
optval = OPTBIT(IN6P_AUTOFLOWLABEL);
break;
+ case IPV6_ORIGDSTADDR:
+ optval = in6p->inp_flags2 & 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
@@ -174,7 +174,7 @@
return (IPPROTO_DONE);
}
- 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
@@ -138,7 +138,7 @@
struct sockaddr_in6 *fromsa)
{
struct socket *so;
- struct mbuf *opts;
+ struct mbuf *opts = NULL, *tmp_opts;
struct udpcb *up;
INP_LOCK_ASSERT(inp);
@@ -148,7 +148,7 @@
*/
up = intoudpcb(inp);
if (up->u_tun_func != NULL) {
- (*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);
return;
}
@@ -170,11 +170,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), IP_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);
@@ -198,7 +210,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;
@@ -279,8 +291,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 = get_inpcbinfo(nxt);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
@@ -351,7 +365,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);
@@ -371,7 +385,7 @@
INP_RLOCK(last);
UDP_PROBE(receive, NULL, last, ip6,
last, uh);
- udp6_append(last, n, off, &fromsa);
+ udp6_append(last, n, off, fromsa);
INP_RUNLOCK(last);
}
}
@@ -402,7 +416,7 @@
INP_RLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
UDP_PROBE(receive, NULL, last, ip6, last, uh);
- udp6_append(last, m, off, &fromsa);
+ udp6_append(last, m, off, fromsa);
INP_RUNLOCK(last);
return (IPPROTO_DONE);
}
@@ -481,7 +495,7 @@
}
}
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
- udp6_append(inp, m, off, &fromsa);
+ udp6_append(inp, m, off, fromsa);
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 5, 3:58 AM (16 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30867627
Default Alt Text
D9235.id24171.diff (11 KB)
Attached To
Mode
D9235: Provide IP_ORIGDSTADDR socket option
Attached
Detach File
Event Timeline
Log In to Comment