Page MenuHomeFreeBSD

D26755.diff
No OneTemporary

D26755.diff

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

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)

Event Timeline