Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145794259
D26755.1778509418.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D26755.1778509418.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) + (*laddr) + (*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.s6_addr,
+ inp->in6p_faddr.s6_addr, 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.
*/
@@ -151,6 +189,64 @@
int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
int (*mrt6_ioctl)(u_long, caddr_t);
+static void
+rip6_hash_lookup(struct mbuf *m, struct inpcb *inp, struct inpcb *last,
+ struct ip6_hdr *ip6, struct sockaddr_in6 fromsa, struct mbuf *opts,
+ int *offp, int hash, int proto)
+{
+ 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->in6p_laddr.s6_addr != ip6->ip6_dst.s6_addr)
+ continue;
+ if (inp->in6p_faddr.s6_addr != ip6->ip6_src.s6_addr)
+ continue;
+ if (last != NULL) {
+ struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+
+ if (n != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
+ ip6_savecontrol(last, n, &opts);
+ /* strip intermediate headers */
+ m_adj(n, *offp);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&fromsa,
+ n, opts) == 0) {
+ m_freem(n);
+ if (opts)
+ m_freem(opts);
+ RIP6STAT_INC(rip6s_fullsock);
+ } else
+ sorwakeup(last->inp_socket);
+ }
+ /* XXX count dropped packet */
+ INP_RUNLOCK(last);
+ last = NULL;
+ }
+ INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED))
+ goto skip_1;
+ if (jailed_without_vnet(inp->inp_cred)) {
+ /*
+ * XXX: If faddr was bound to multicast group,
+ * jailed raw socket will drop datagram.
+ */
+ if (prison_check_ip6(inp->inp_cred, &ip6->ip6_dst) != 0)
+ goto skip_1;
+ }
+ last = inp;
+ continue;
+ skip_1:
+ INP_RUNLOCK(inp);
+ }
+
+
+}
+
/*
* Setup generic address and protocol structures for raw_input routine, then
* pass them along with mbuf chain.
@@ -161,10 +257,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,7 +271,11 @@
ifp = m->m_pkthdr.rcvif;
- CK_LIST_FOREACH(inp, &V_ripcb, inp_list) {
+ hash = INP_PCBHASH_RAW(proto, ip6->ip6_src.s6_addr,
+ ip6->ip6_dst.s6_addr, V_ripcbinfo.ipi_hashmask);
+ rip6_hash_lookup(m, inp, last, ip6, fromsa, opts, offp, hash, proto);
+
+ CK_LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[0], inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -665,13 +766,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 +791,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 +873,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 +914,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 +926,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,57 @@
+#!/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
+
+ s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, proto)
+ s.sendto(msg, (ip, 0))
+
+
+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
Mon, May 11, 2:23 PM (7 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28683028
Default Alt Text
D26755.1778509418.diff (9 KB)
Attached To
Mode
D26755: Add hash table lookup for IPv6 raw sockets.
Attached
Detach File
Event Timeline
Log In to Comment