Page MenuHomeFreeBSD

D9235.id24171.diff
No OneTemporary

D9235.id24171.diff

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

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)

Event Timeline