1
|
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
|
2
|
index 0c6f98e..6c77e2d 100644
|
3
|
--- a/sys/netinet/udp_usrreq.c
|
4
|
+++ b/sys/netinet/udp_usrreq.c
|
5
|
@@ -610,6 +610,49 @@ udp_input(struct mbuf *m, int off)
|
6
|
return;
|
7
|
}
|
8
|
|
9
|
+ if (inp->inp_phd != NULL) {
|
10
|
+ struct inpcb *local_inp;
|
11
|
+ struct mbuf *n;
|
12
|
+
|
13
|
+ LIST_FOREACH(local_inp, &inp->inp_phd->phd_pcblist, inp_portlist) {
|
14
|
+ if (local_inp == inp)
|
15
|
+ continue;
|
16
|
+
|
17
|
+ if ((local_inp->inp_vflag & INP_IPV4) == 0)
|
18
|
+ continue;
|
19
|
+ if (local_inp->inp_lport != uh->uh_dport)
|
20
|
+ continue;
|
21
|
+ if (local_inp->inp_laddr.s_addr != INADDR_ANY &&
|
22
|
+ local_inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
|
23
|
+ continue;
|
24
|
+
|
25
|
+ /*
|
26
|
+ * Check the minimum TTL for socket.
|
27
|
+ */
|
28
|
+ if (local_inp->inp_ip_minttl && local_inp->inp_ip_minttl > ip->ip_ttl)
|
29
|
+ continue;
|
30
|
+
|
31
|
+ if ((n = m_copy(m, 0, M_COPYALL)) == NULL)
|
32
|
+ continue; /* XXX: Log about this? */
|
33
|
+ INP_RLOCK(local_inp);
|
34
|
+ UDP_PROBE(receive, NULL, local_inp, ip, local_inp, uh);
|
35
|
+ udp_append(local_inp, ip, n, iphlen, &udp_in);
|
36
|
+ INP_RUNLOCK(local_inp);
|
37
|
+ /*
|
38
|
+ * Don't look for additional matches if this one does
|
39
|
+ * not have either the SO_REUSEPORT or SO_REUSEADDR
|
40
|
+ * socket options set. This heuristic avoids
|
41
|
+ * searching through all pcbs in the common case of a
|
42
|
+ * non-shared port. It assumes that an application
|
43
|
+ * will never clear these options after setting them.
|
44
|
+ */
|
45
|
+ if ((local_inp->inp_socket->so_options &
|
46
|
+ (SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
47
|
+ break;
|
48
|
+ }
|
49
|
+
|
50
|
+ }
|
51
|
+
|
52
|
/*
|
53
|
* Check the minimum TTL for socket.
|
54
|
*/
|
55
|
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
|
56
|
index e4963e2..cd1c9c1 100644
|
57
|
--- a/sys/netinet6/udp6_usrreq.c
|
58
|
+++ b/sys/netinet6/udp6_usrreq.c
|
59
|
@@ -457,6 +457,52 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
60
|
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
|
61
|
return (IPPROTO_DONE);
|
62
|
}
|
63
|
+ if (inp->inp_phd != NULL) {
|
64
|
+ struct inpcb *local_inp;
|
65
|
+ struct mbuf *n;
|
66
|
+
|
67
|
+ LIST_FOREACH(local_inp, &inp->inp_phd->phd_pcblist, inp_portlist) {
|
68
|
+ if (local_inp == inp)
|
69
|
+ continue;
|
70
|
+
|
71
|
+ if ((local_inp->inp_vflag & INP_IPV6) == 0)
|
72
|
+ continue;
|
73
|
+ if (local_inp->inp_lport != uh->uh_dport)
|
74
|
+ continue;
|
75
|
+ if (!IN6_IS_ADDR_UNSPECIFIED(&local_inp->in6p_laddr)) {
|
76
|
+ if (!IN6_ARE_ADDR_EQUAL(&local_inp->in6p_laddr,
|
77
|
+ &ip6->ip6_dst))
|
78
|
+ continue;
|
79
|
+ }
|
80
|
+
|
81
|
+ if ((n = m_copy(m, 0, M_COPYALL)) == NULL)
|
82
|
+ continue; /* XXX: Log about this? */
|
83
|
+ INP_RLOCK(local_inp);
|
84
|
+ up = intoudpcb(local_inp);
|
85
|
+ UDP_PROBE(receive, NULL, local_inp, ip6, local_inp, uh);
|
86
|
+ if (up->u_tun_func == NULL) {
|
87
|
+ udp6_append(local_inp, n, off, &fromsa);
|
88
|
+ } else {
|
89
|
+ /*
|
90
|
+ * Engage the tunneling protocol.
|
91
|
+ */
|
92
|
+
|
93
|
+ (*up->u_tun_func)(n, off, local_inp);
|
94
|
+ }
|
95
|
+ INP_RUNLOCK(local_inp);
|
96
|
+ /*
|
97
|
+ * Don't look for additional matches if this one does
|
98
|
+ * not have either the SO_REUSEPORT or SO_REUSEADDR
|
99
|
+ * socket options set. This heuristic avoids
|
100
|
+ * searching through all pcbs in the common case of a
|
101
|
+ * non-shared port. It assumes that an application
|
102
|
+ * will never clear these options after setting them.
|
103
|
+ */
|
104
|
+ if ((local_inp->inp_socket->so_options &
|
105
|
+ (SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
106
|
+ break;
|
107
|
+ }
|
108
|
+ }
|
109
|
INP_RLOCK_ASSERT(inp);
|
110
|
up = intoudpcb(inp);
|
111
|
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
|