Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106955207
D26755.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
D26755.diff
View Options
Index: sys/netinet6/raw_ip6.c
===================================================================
--- sys/netinet6/raw_ip6.c
+++ sys/netinet6/raw_ip6.c
@@ -133,6 +133,44 @@
#endif /* VIMAGE */
/*
+ * Hash functions
+ */
+
+#define INP_PCBHASH_RAW_SIZE 256
+#define INP_PCBHASH_RAW(proto, laddr, faddr, mask) \
+ (((proto) + IN6ADDR_HASHVAL(laddr) + IN6ADDR_HASHVAL(faddr)) % (mask) + 1)
+
+static void
+rip6_inshash(struct inpcb *inp)
+{
+ struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+ struct inpcbhead *pcbhash;
+ int hash;
+
+ INP_INFO_WLOCK_ASSERT(pcbinfo);
+ INP_WLOCK_ASSERT(inp);
+
+ if (inp->inp_ip_p != 0 && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
+ hash = INP_PCBHASH_RAW(inp->inp_ip_p, &inp->in6p_laddr,
+ &inp->in6p_faddr, pcbinfo->ipi_hashmask);
+ } else
+ hash = 0;
+ pcbhash = &pcbinfo->ipi_hashbase[hash];
+ CK_LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
+}
+
+static void
+rip6_delhash(struct inpcb *inp)
+{
+
+ INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
+ INP_WLOCK_ASSERT(inp);
+
+ CK_LIST_REMOVE(inp, inp_hash);
+}
+
+/*
* Hooks for multicast routing. They all default to NULL, so leave them not
* initialized and rely on BSS being set to 0.
*/
@@ -161,10 +199,11 @@
struct ifnet *ifp;
struct mbuf *m = *mp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct inpcb *inp;
+ struct inpcb *inp = NULL;
struct inpcb *last = NULL;
struct mbuf *opts = NULL;
struct sockaddr_in6 fromsa;
+ int hash;
NET_EPOCH_ASSERT();
@@ -174,36 +213,22 @@
ifp = m->m_pkthdr.rcvif;
- CK_LIST_FOREACH(inp, &V_ripcb, inp_list) {
+ hash = INP_PCBHASH_RAW(proto, &ip6->ip6_src, &ip6->ip6_dst,
+ V_ripcbinfo.ipi_hashmask);
+ CK_LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[hash], inp_hash) {
+ if (inp->inp_ip_p != proto)
+ continue;
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
- if (inp->inp_ip_p &&
- inp->inp_ip_p != proto)
+ if (inp->in6p_laddr.s6_addr != ip6->ip6_dst.s6_addr)
continue;
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
- !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ip6->ip6_dst))
+ if (inp->in6p_faddr.s6_addr != ip6->ip6_src.s6_addr)
continue;
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
- !IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ip6->ip6_src))
- continue;
if (last != NULL) {
struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
- /*
- * Check AH/ESP integrity.
- */
- if (IPSEC_ENABLED(ipv6)) {
- if (n != NULL &&
- IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
- m_freem(n);
- /* Do not inject data into pcb. */
- n = NULL;
- }
- }
-#endif /* IPSEC */
- if (n) {
+ if (n != NULL) {
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, n, &opts);
@@ -218,89 +243,25 @@
RIP6STAT_INC(rip6s_fullsock);
} else
sorwakeup(last->inp_socket);
- opts = NULL;
}
+ /* XXX count dropped packet */
INP_RUNLOCK(last);
last = NULL;
}
INP_RLOCK(inp);
if (__predict_false(inp->inp_flags2 & INP_FREED))
- goto skip_2;
+ goto skip_1;
if (jailed_without_vnet(inp->inp_cred)) {
/*
- * Allow raw socket in jail to receive multicast;
- * assume process had PRIV_NETINET_RAW at attach,
- * and fall through into normal filter path if so.
+ * XXX: If faddr was bound to multicast group,
+ * jailed raw socket will drop datagram.
*/
- if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
- prison_check_ip6(inp->inp_cred,
- &ip6->ip6_dst) != 0)
- goto skip_2;
+ if (prison_check_ip6(inp->inp_cred, &ip6->ip6_dst) != 0)
+ goto skip_1;
}
- if (inp->in6p_cksum != -1) {
- RIP6STAT_INC(rip6s_isum);
- if (m->m_pkthdr.len - (*offp + inp->in6p_cksum) < 2 ||
- in6_cksum(m, proto, *offp,
- m->m_pkthdr.len - *offp)) {
- RIP6STAT_INC(rip6s_badsum);
- /*
- * Drop the received message, don't send an
- * ICMP6 message. Set proto to IPPROTO_NONE
- * to achieve that.
- */
- proto = IPPROTO_NONE;
- goto skip_2;
- }
- }
- /*
- * If this raw socket has multicast state, and we
- * have received a multicast, check if this socket
- * should receive it, as multicast filtering is now
- * the responsibility of the transport layer.
- */
- if (inp->in6p_moptions &&
- IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- /*
- * If the incoming datagram is for MLD, allow it
- * through unconditionally to the raw socket.
- *
- * Use the M_RTALERT_MLD flag to check for MLD
- * traffic without having to inspect the mbuf chain
- * more deeply, as all MLDv1/v2 host messages MUST
- * contain the Router Alert option.
- *
- * In the case of MLDv1, we may not have explicitly
- * joined the group, and may have set IFF_ALLMULTI
- * on the interface. im6o_mc_filter() may discard
- * control traffic we actually need to see.
- *
- * Userland multicast routing daemons should continue
- * filter the control traffic appropriately.
- */
- int blocked;
-
- blocked = MCAST_PASS;
- if ((m->m_flags & M_RTALERT_MLD) == 0) {
- struct sockaddr_in6 mcaddr;
-
- bzero(&mcaddr, sizeof(struct sockaddr_in6));
- mcaddr.sin6_len = sizeof(struct sockaddr_in6);
- mcaddr.sin6_family = AF_INET6;
- mcaddr.sin6_addr = ip6->ip6_dst;
-
- blocked = im6o_mc_filter(inp->in6p_moptions,
- ifp,
- (struct sockaddr *)&mcaddr,
- (struct sockaddr *)&fromsa);
- }
- if (blocked != MCAST_PASS) {
- IP6STAT_INC(ip6s_notmember);
- goto skip_2;
- }
- }
last = inp;
continue;
-skip_2:
+ skip_1:
INP_RUNLOCK(inp);
}
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
@@ -665,13 +626,14 @@
return (error);
}
inp = (struct inpcb *)so->so_pcb;
- INP_INFO_WUNLOCK(&V_ripcbinfo);
inp->inp_vflag |= INP_IPV6;
inp->inp_ip_p = (long)proto;
inp->in6p_hops = -1; /* use kernel default */
inp->in6p_cksum = -1;
inp->in6p_icmp6filt = filter;
ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
+ rip6_inshash(inp);
+ INP_INFO_WUNLOCK(&V_ripcbinfo);
INP_WUNLOCK(inp);
return (0);
}
@@ -689,6 +651,7 @@
/* xxx: RSVP */
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
+ rip6_delhash(inp);
free(inp->in6p_icmp6filt, M_PCB);
in_pcbdetach(inp);
in_pcbfree(inp);
@@ -770,7 +733,9 @@
NET_EPOCH_EXIT(et);
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
+ rip6_delhash(inp);
inp->in6p_laddr = addr->sin6_addr;
+ rip6_inshash(inp);
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (0);
@@ -809,6 +774,7 @@
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
+ rip6_delhash(inp);
/* Source address selection. XXX: need pcblookup? */
error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
inp, so->so_cred, scope_ambiguous, &in6a, NULL);
@@ -820,6 +786,7 @@
inp->in6p_faddr = addr->sin6_addr;
inp->in6p_laddr = in6a;
+ rip6_inshash(inp);
soisconnected(so);
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
Index: tests/sys/netinet6/Makefile
===================================================================
--- tests/sys/netinet6/Makefile
+++ tests/sys/netinet6/Makefile
@@ -14,18 +14,21 @@
forward6 \
output6 \
lpm6 \
- fibs6
+ fibs6 \
+ rawsocket
TEST_METADATA.output6+= required_programs="python"
${PACKAGE}FILES+= exthdr.py
${PACKAGE}FILES+= mld.py
${PACKAGE}FILES+= scapyi386.py
${PACKAGE}FILES+= redirect.py
+${PACKAGE}FILES+= rawsocket.py
${PACKAGE}FILESMODE_exthdr.py= 0555
${PACKAGE}FILESMODE_mld.py= 0555
${PACKAGE}FILESMODE_scapyi386.py=0555
${PACKAGE}FILESMODE_redirect.py=0555
+${PACKAGE}FILESMODE_rawsocket.py=0555
TESTS_SUBDIRS+= frag6
Index: tests/sys/netinet6/rawsocket.py
===================================================================
--- tests/sys/netinet6/rawsocket.py
+++ tests/sys/netinet6/rawsocket.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# -
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2020 Neel Chauhan
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+import argparse
+import socket
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='Raw Socket ICMPv6 Ping')
+ parser.add_argument('--ip', type=str, required=True,
+ help='destination ip')
+ return parser.parse_args()
+
+
+def ping(ip):
+ proto = 58 # ICMP
+
+ msg = b'\x80\0\0\0\0\0\0\0' # Barebones ICMPv6 message
+
+ snd = socket.socket(socket.AF_INET6, socket.SOCK_RAW, proto)
+ snd.sendto(msg, (ip, 0))
+
+ rcv = socket.socket(socket.AF_INET6, socket.SOCK_RAW, proto)
+ if rcv.recv(1024) is None:
+ raise TypeError
+
+
+def main():
+ args = parse_args()
+ ping(args.ip)
+
+
+if __name__ == '__main__':
+ main()
Index: tests/sys/netinet6/rawsocket.sh
===================================================================
--- tests/sys/netinet6/rawsocket.sh
+++ tests/sys/netinet6/rawsocket.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env atf-sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2020 Neel Chauhan
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+atf_test_case "raw_ping" "cleanup"
+raw_ping_head() {
+
+ atf_set descr 'Test valid ICMPv6 raw socket'
+ atf_set require.user root
+}
+
+raw_ping_body() {
+
+ script_name="rawsocket.py"
+ ip="::1"
+
+ atf_check -s exit:0 $(atf_get_srcdir)/${script_name} --ip ${ip}
+}
+
+raw_ping_cleanup() {
+
+}
+
+atf_init_test_cases()
+{
+
+ atf_add_test_case "raw_ping"
+}
+
+# end
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 9, 12:59 AM (4 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15728109
Default Alt Text
D26755.diff (11 KB)
Attached To
Mode
D26755: Add hash table lookup for IPv6 raw sockets.
Attached
Detach File
Event Timeline
Log In to Comment