2005-01-07 02:30:35 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
1999-11-22 02:45:11 +00:00
|
|
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
2007-12-10 16:03:40 +00:00
|
|
|
*
|
|
|
|
* $KAME: icmp6.c,v 1.211 2001/04/04 05:56:20 itojun Exp $
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
|
|
|
|
2005-01-07 02:30:35 +00:00
|
|
|
/*-
|
1999-11-22 02:45:11 +00:00
|
|
|
* Copyright (c) 1982, 1986, 1988, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
2017-02-28 23:42:47 +00:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1999-11-22 02:45:11 +00:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
|
|
|
*
|
|
|
|
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
|
|
|
*/
|
|
|
|
|
2007-12-10 16:03:40 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2014-10-12 15:49:52 +00:00
|
|
|
#define MBUF_PRIVATE /* XXXRW: Optimisation tries to avoid M_EXT mbufs */
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_inet6.h"
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
#include <sys/param.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/domain.h>
|
2009-05-29 21:27:12 +00:00
|
|
|
#include <sys/jail.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/lock.h>
|
2001-06-11 12:39:29 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/mbuf.h>
|
2009-08-01 19:26:27 +00:00
|
|
|
#include <sys/proc.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/protosw.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/signalvar.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/sx.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/syslog.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/time.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <net/if_dl.h>
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
#include <net/if_llatbl.h>
|
2023-01-23 15:05:29 +00:00
|
|
|
#include <net/if_private.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <net/if_types.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <net/route.h>
|
2020-06-01 20:49:42 +00:00
|
|
|
#include <net/route/route_ctl.h>
|
2020-04-14 23:06:25 +00:00
|
|
|
#include <net/route/nhop.h>
|
2008-12-02 21:37:28 +00:00
|
|
|
#include <net/vnet.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <netinet/in_pcb.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet/in_var.h>
|
2000-07-04 16:35:15 +00:00
|
|
|
#include <netinet/ip6.h>
|
|
|
|
#include <netinet/icmp6.h>
|
2003-11-20 20:07:39 +00:00
|
|
|
#include <netinet/tcp_var.h>
|
2008-12-02 21:37:28 +00:00
|
|
|
|
2015-12-09 11:14:27 +00:00
|
|
|
#include <netinet6/in6_fib.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet6/in6_ifattach.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <netinet6/in6_pcb.h>
|
|
|
|
#include <netinet6/ip6_var.h>
|
2005-07-25 12:31:43 +00:00
|
|
|
#include <netinet6/scope6_var.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <netinet6/mld6_var.h>
|
|
|
|
#include <netinet6/nd6.h>
|
2010-08-19 11:31:03 +00:00
|
|
|
#include <netinet6/send.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2022-10-04 03:53:04 +00:00
|
|
|
extern ip6proto_ctlinput_t *ip6_ctlprotox[];
|
2008-11-26 22:32:07 +00:00
|
|
|
|
2013-07-09 09:54:54 +00:00
|
|
|
VNET_PCPUSTAT_DEFINE(struct icmp6stat, icmp6stat);
|
|
|
|
VNET_PCPUSTAT_SYSINIT(icmp6stat);
|
|
|
|
|
|
|
|
#ifdef VIMAGE
|
|
|
|
VNET_PCPUSTAT_SYSUNINIT(icmp6stat);
|
|
|
|
#endif /* VIMAGE */
|
2010-04-29 11:52:42 +00:00
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
|
|
|
|
VNET_DECLARE(int, icmp6errppslim);
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(int, icmp6errpps_count) = 0;
|
|
|
|
VNET_DEFINE_STATIC(struct timeval, icmp6errppslim_last);
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DECLARE(int, icmp6_nodeinfo);
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_ripcbinfo VNET(ripcbinfo)
|
|
|
|
#define V_icmp6errppslim VNET(icmp6errppslim)
|
2010-04-29 11:52:42 +00:00
|
|
|
#define V_icmp6errpps_count VNET(icmp6errpps_count)
|
|
|
|
#define V_icmp6errppslim_last VNET(icmp6errppslim_last)
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
2013-06-19 15:59:21 +00:00
|
|
|
static void icmp6_errcount(int, int);
|
2008-01-08 19:08:58 +00:00
|
|
|
static int icmp6_rip6_input(struct mbuf **, int);
|
2019-12-03 14:46:38 +00:00
|
|
|
static void icmp6_reflect(struct mbuf *, size_t);
|
2012-10-22 21:49:56 +00:00
|
|
|
static const char *icmp6_redirect_diag(struct in6_addr *,
|
|
|
|
struct in6_addr *, struct in6_addr *);
|
2019-05-16 19:09:41 +00:00
|
|
|
static struct mbuf *ni6_input(struct mbuf *, int, struct prison *);
|
2008-01-08 19:08:58 +00:00
|
|
|
static struct mbuf *ni6_nametodns(const char *, int, int);
|
|
|
|
static int ni6_dnsmatch(const char *, int, const char *, int);
|
2012-10-22 21:49:56 +00:00
|
|
|
static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
|
|
|
|
struct ifnet **, struct in6_addr *);
|
|
|
|
static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
|
|
|
|
struct ifnet *, int);
|
2022-10-04 03:53:04 +00:00
|
|
|
static int icmp6_notify_error(struct mbuf **, int, int);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2009-08-02 19:43:32 +00:00
|
|
|
/*
|
|
|
|
* Kernel module interface for updating icmp6stat. The argument is an index
|
|
|
|
* into icmp6stat treated as an array of u_quad_t. While this encodes the
|
|
|
|
* general layout of icmp6stat into the caller, it doesn't encode its
|
|
|
|
* location, so that future changes to add, for example, per-CPU stats
|
|
|
|
* support won't cause binary compatibility problems for kernel modules.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
kmod_icmp6stat_inc(int statnum)
|
|
|
|
{
|
|
|
|
|
2013-07-09 09:54:54 +00:00
|
|
|
counter_u64_add(VNET(icmp6stat)[statnum], 1);
|
2009-08-02 19:43:32 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
static void
|
2013-06-19 15:59:21 +00:00
|
|
|
icmp6_errcount(int type, int code)
|
2000-07-04 16:35:15 +00:00
|
|
|
{
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (type) {
|
2000-07-04 16:35:15 +00:00
|
|
|
case ICMP6_DST_UNREACH:
|
|
|
|
switch (code) {
|
|
|
|
case ICMP6_DST_UNREACH_NOROUTE:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_odst_unreach_noroute);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_DST_UNREACH_ADMIN:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_odst_unreach_admin);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_DST_UNREACH_BEYONDSCOPE:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_odst_unreach_beyondscope);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_DST_UNREACH_ADDR:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_odst_unreach_addr);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_DST_UNREACH_NOPORT:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_odst_unreach_noport);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ICMP6_PACKET_TOO_BIG:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_opacket_too_big);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_TIME_EXCEEDED:
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (code) {
|
2000-07-04 16:35:15 +00:00
|
|
|
case ICMP6_TIME_EXCEED_TRANSIT:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_otime_exceed_transit);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_TIME_EXCEED_REASSEMBLY:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_otime_exceed_reassembly);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ICMP6_PARAM_PROB:
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (code) {
|
2000-07-04 16:35:15 +00:00
|
|
|
case ICMP6_PARAMPROB_HEADER:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_oparamprob_header);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_PARAMPROB_NEXTHEADER:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_oparamprob_nextheader);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
case ICMP6_PARAMPROB_OPTION:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_oparamprob_option);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ND_REDIRECT:
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_oredirect);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-06-19 15:59:21 +00:00
|
|
|
ICMP6STAT_INC(icp6s_ounknown);
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
|
2005-07-25 12:31:43 +00:00
|
|
|
/*
|
|
|
|
* A wrapper function for icmp6_error() necessary when the erroneous packet
|
|
|
|
* may not contain enough scope zone information.
|
|
|
|
*/
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_error2(struct mbuf *m, int type, int code, int param,
|
|
|
|
struct ifnet *ifp)
|
2005-07-25 12:31:43 +00:00
|
|
|
{
|
|
|
|
struct ip6_hdr *ip6;
|
|
|
|
|
|
|
|
if (ifp == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m->m_len < sizeof(struct ip6_hdr)) {
|
|
|
|
m = m_pullup(m, sizeof(struct ip6_hdr));
|
2019-11-15 21:40:40 +00:00
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
2005-07-25 12:31:43 +00:00
|
|
|
return;
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
2005-07-25 12:31:43 +00:00
|
|
|
}
|
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
|
|
|
|
if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0)
|
|
|
|
return;
|
|
|
|
if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
icmp6_error(m, type, code, param);
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Generate an error packet of type error in response to bad IP6 packet.
|
|
|
|
*/
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_error(struct mbuf *m, int type, int code, int param)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct ip6_hdr *oip6, *nip6;
|
|
|
|
struct icmp6_hdr *icmp6;
|
2021-02-13 14:32:10 +00:00
|
|
|
struct epoch_tracker et;
|
2000-07-04 16:35:15 +00:00
|
|
|
u_int preplen;
|
1999-11-22 02:45:11 +00:00
|
|
|
int off;
|
2000-07-04 16:35:15 +00:00
|
|
|
int nxt;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_error);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/* count per-type-code statistics */
|
2013-06-19 15:59:21 +00:00
|
|
|
icmp6_errcount(type, code);
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
#ifdef M_DECRYPTED /*not openbsd*/
|
|
|
|
if (m->m_flags & M_DECRYPTED) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_canterror);
|
1999-11-22 02:45:11 +00:00
|
|
|
goto freeit;
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
if (m->m_len < sizeof(struct ip6_hdr)) {
|
|
|
|
m = m_pullup(m, sizeof(struct ip6_hdr));
|
2019-11-15 21:40:40 +00:00
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
2000-07-04 16:35:15 +00:00
|
|
|
return;
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
oip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
|
|
|
|
/*
|
2003-10-24 18:26:30 +00:00
|
|
|
* If the destination address of the erroneous packet is a multicast
|
|
|
|
* address, or the packet was sent using link-layer multicast,
|
|
|
|
* we should basically suppress sending an error (RFC 2463, Section
|
|
|
|
* 2.4).
|
|
|
|
* We have two exceptions (the item e.2 in that section):
|
2010-01-06 23:05:00 +00:00
|
|
|
* - the Packet Too Big message can be sent for path MTU discovery.
|
2003-10-24 18:26:30 +00:00
|
|
|
* - the Parameter Problem Message that can be allowed an icmp6 error
|
|
|
|
* in the option type field. This check has been done in
|
|
|
|
* ip6_unknown_opt(), so we can just check the type and code.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
|
|
|
if ((m->m_flags & (M_BCAST|M_MCAST) ||
|
|
|
|
IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
|
|
|
|
(type != ICMP6_PACKET_TOO_BIG &&
|
|
|
|
(type != ICMP6_PARAM_PROB ||
|
|
|
|
code != ICMP6_PARAMPROB_OPTION)))
|
|
|
|
goto freeit;
|
|
|
|
|
2003-10-24 18:26:30 +00:00
|
|
|
/*
|
|
|
|
* RFC 2463, 2.4 (e.5): source address check.
|
|
|
|
* XXX: the case of anycast source?
|
|
|
|
*/
|
1999-11-22 02:45:11 +00:00
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
|
|
|
|
IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
|
|
|
|
goto freeit;
|
|
|
|
|
|
|
|
/*
|
2000-07-04 16:35:15 +00:00
|
|
|
* If we are about to send ICMPv6 against ICMPv6 error/redirect,
|
|
|
|
* don't do it.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2000-07-04 16:35:15 +00:00
|
|
|
nxt = -1;
|
|
|
|
off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
|
|
|
|
if (off >= 0 && nxt == IPPROTO_ICMPV6) {
|
1999-11-22 02:45:11 +00:00
|
|
|
struct icmp6_hdr *icp;
|
|
|
|
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
|
|
|
|
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
return;
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
oip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
|
|
|
|
icp->icmp6_type == ND_REDIRECT) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2000-07-04 16:35:15 +00:00
|
|
|
* ICMPv6 error
|
|
|
|
* Special case: for redirect (which is
|
|
|
|
* informational) we must not send icmp6 error.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_canterror);
|
2000-07-04 16:35:15 +00:00
|
|
|
goto freeit;
|
|
|
|
} else {
|
|
|
|
/* ICMPv6 informational - send the error */
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
} else {
|
|
|
|
/* non-ICMPv6 - send the error */
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, do rate limitation check. */
|
|
|
|
if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_toofreq);
|
1999-11-22 02:45:11 +00:00
|
|
|
goto freeit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, ICMP6 can be generated.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
|
|
|
|
m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
|
2012-12-05 08:04:20 +00:00
|
|
|
M_PREPEND(m, preplen, M_NOWAIT); /* FIB is also copied over. */
|
1999-11-22 02:45:11 +00:00
|
|
|
if (m == NULL) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
|
1999-11-22 02:45:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
nip6->ip6_src = oip6->ip6_src;
|
|
|
|
nip6->ip6_dst = oip6->ip6_dst;
|
|
|
|
|
2003-10-21 20:05:32 +00:00
|
|
|
in6_clearscope(&oip6->ip6_src);
|
|
|
|
in6_clearscope(&oip6->ip6_dst);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
icmp6 = (struct icmp6_hdr *)(nip6 + 1);
|
|
|
|
icmp6->icmp6_type = type;
|
|
|
|
icmp6->icmp6_code = code;
|
|
|
|
icmp6->icmp6_pptr = htonl((u_int32_t)param);
|
|
|
|
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_outhist[type]);
|
2021-02-13 14:32:10 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2002-04-19 04:46:24 +00:00
|
|
|
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
|
2021-02-13 14:32:10 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
freeit:
|
|
|
|
/*
|
2005-08-12 15:27:25 +00:00
|
|
|
* If we can't tell whether or not we can generate ICMP6, free it.
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
|
|
|
m_freem(m);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2022-10-04 03:53:04 +00:00
|
|
|
int
|
|
|
|
icmp6_errmap(const struct icmp6_hdr *icmp6)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (icmp6->icmp6_type) {
|
|
|
|
case ICMP6_DST_UNREACH:
|
|
|
|
switch (icmp6->icmp6_code) {
|
|
|
|
case ICMP6_DST_UNREACH_NOROUTE:
|
|
|
|
case ICMP6_DST_UNREACH_ADDR:
|
|
|
|
return (EHOSTUNREACH);
|
|
|
|
case ICMP6_DST_UNREACH_NOPORT:
|
|
|
|
case ICMP6_DST_UNREACH_ADMIN:
|
|
|
|
return (ECONNREFUSED);
|
|
|
|
case ICMP6_DST_UNREACH_BEYONDSCOPE:
|
|
|
|
return (ENOPROTOOPT);
|
|
|
|
default:
|
|
|
|
return (0); /* Shouldn't happen. */
|
|
|
|
}
|
|
|
|
case ICMP6_PACKET_TOO_BIG:
|
|
|
|
return (EMSGSIZE);
|
|
|
|
case ICMP6_TIME_EXCEEDED:
|
|
|
|
switch (icmp6->icmp6_code) {
|
|
|
|
case ICMP6_TIME_EXCEED_TRANSIT:
|
|
|
|
return (EHOSTUNREACH);
|
|
|
|
case ICMP6_TIME_EXCEED_REASSEMBLY:
|
|
|
|
return (0);
|
|
|
|
default:
|
|
|
|
return (0); /* Shouldn't happen. */
|
|
|
|
}
|
|
|
|
case ICMP6_PARAM_PROB:
|
|
|
|
switch (icmp6->icmp6_code) {
|
|
|
|
case ICMP6_PARAMPROB_NEXTHEADER:
|
|
|
|
return (ECONNREFUSED);
|
|
|
|
case ICMP6_PARAMPROB_HEADER:
|
|
|
|
case ICMP6_PARAMPROB_OPTION:
|
|
|
|
return (ENOPROTOOPT);
|
|
|
|
default:
|
|
|
|
return (0); /* Shouldn't happen. */
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Process a received ICMP6 message.
|
|
|
|
*/
|
|
|
|
int
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_input(struct mbuf **mp, int *offp, int proto)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2019-11-07 18:29:51 +00:00
|
|
|
struct mbuf *m, *n;
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
struct ifnet *ifp;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct ip6_hdr *ip6, *nip6;
|
|
|
|
struct icmp6_hdr *icmp6, *nicmp6;
|
2006-12-12 12:17:58 +00:00
|
|
|
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
|
2019-11-07 18:29:51 +00:00
|
|
|
int code, error, icmp6len, ip6len, noff, off, sum;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2020-05-28 08:00:08 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
m = *mp;
|
|
|
|
off = *offp;
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + sizeof(struct icmp6_hdr)) {
|
|
|
|
m = m_pullup(m, off + sizeof(struct icmp6_hdr));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (IPPROTO_DONE);
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Locate icmp6 structure in mbuf, and check
|
|
|
|
* that not corrupted and of at least minimum length
|
|
|
|
*/
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
icmp6len = m->m_pkthdr.len - off;
|
1999-11-22 02:45:11 +00:00
|
|
|
if (icmp6len < sizeof(struct icmp6_hdr)) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_tooshort);
|
1999-11-22 02:45:11 +00:00
|
|
|
goto freeit;
|
|
|
|
}
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
ifp = m->m_pkthdr.rcvif;
|
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes:
* Connect netinet6/in6_mcast.c to build.
The legacy KAME KPIs are mostly preserved.
* Eliminate now dead code from ip6_output.c.
Don't do mbuf bingo, we are not going to do RFC 2292 style
CMSG tricks for multicast options as they are not required
by any current IPv6 normative reference.
* Refactor transports (UDP, raw_ip6) to do own mcast filtering.
SCTP, TCP unaffected by this change.
* Add ip6_msource, in6_msource structs to in6_var.h.
* Hookup mld_ifinfo state to in6_ifextra, allocate from
domifattach path.
* Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced.
Kernel consumers which need this should use in6m_lookup().
* Refactor IPv6 socket group memberships to use a vector (like IPv4).
* Update ifmcstat(8) for IPv6 SSM.
* Add witness lock order for IN6_MULTI_LOCK.
* Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths.
* Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup.
* Update carp(4) for new IPv6 SSM KPIs.
* Virtualize ip6_mrouter socket.
Changes mostly localized to IPv6 MROUTING.
* Don't do a local group lookup in MROUTING.
* Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge().
* Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode.
* Bump __FreeBSD_version to 800084.
* Update UPDATING.
NOTE WELL:
* This code hasn't been tested against real MLDv2 queriers
(yet), although the on-wire protocol has been verified in Wireshark.
* There are a few unresolved issues in the socket layer APIs to
do with scope ID propagation.
* There is a LOR present in ip6_output()'s use of
in6_setscope() which needs to be resolved. See comments in mld6.c.
This is believed to be benign and can't be avoided for the moment
without re-introducing an indirect netisr.
This work was mostly derived from the IGMPv3 implementation, and
has been sponsored by a third party.
2009-04-29 19:19:13 +00:00
|
|
|
/*
|
|
|
|
* Check multicast group membership.
|
|
|
|
* Note: SSM filters are not applied for ICMPv6 traffic.
|
|
|
|
*/
|
|
|
|
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
struct in6_multi *inm;
|
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes:
* Connect netinet6/in6_mcast.c to build.
The legacy KAME KPIs are mostly preserved.
* Eliminate now dead code from ip6_output.c.
Don't do mbuf bingo, we are not going to do RFC 2292 style
CMSG tricks for multicast options as they are not required
by any current IPv6 normative reference.
* Refactor transports (UDP, raw_ip6) to do own mcast filtering.
SCTP, TCP unaffected by this change.
* Add ip6_msource, in6_msource structs to in6_var.h.
* Hookup mld_ifinfo state to in6_ifextra, allocate from
domifattach path.
* Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced.
Kernel consumers which need this should use in6m_lookup().
* Refactor IPv6 socket group memberships to use a vector (like IPv4).
* Update ifmcstat(8) for IPv6 SSM.
* Add witness lock order for IN6_MULTI_LOCK.
* Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths.
* Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup.
* Update carp(4) for new IPv6 SSM KPIs.
* Virtualize ip6_mrouter socket.
Changes mostly localized to IPv6 MROUTING.
* Don't do a local group lookup in MROUTING.
* Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge().
* Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode.
* Bump __FreeBSD_version to 800084.
* Update UPDATING.
NOTE WELL:
* This code hasn't been tested against real MLDv2 queriers
(yet), although the on-wire protocol has been verified in Wireshark.
* There are a few unresolved issues in the socket layer APIs to
do with scope ID propagation.
* There is a LOR present in ip6_output()'s use of
in6_setscope() which needs to be resolved. See comments in mld6.c.
This is believed to be benign and can't be avoided for the moment
without re-introducing an indirect netisr.
This work was mostly derived from the IGMPv3 implementation, and
has been sponsored by a third party.
2009-04-29 19:19:13 +00:00
|
|
|
|
|
|
|
inm = in6m_lookup(ifp, &ip6->ip6_dst);
|
|
|
|
if (inm == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_notmember);
|
|
|
|
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
|
|
|
|
goto freeit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
/* Calculate the checksum. */
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
|
|
|
|
code = icmp6->icmp6_code;
|
|
|
|
if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
1999-11-22 02:45:11 +00:00
|
|
|
"ICMP6 checksum error(%d|%x) %s\n",
|
2006-12-12 12:17:58 +00:00
|
|
|
icmp6->icmp6_type, sum,
|
|
|
|
ip6_sprintf(ip6bufs, &ip6->ip6_src)));
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_checksum);
|
1999-11-22 02:45:11 +00:00
|
|
|
goto freeit;
|
|
|
|
}
|
|
|
|
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]);
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_msg);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_error);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
|
1999-11-22 02:45:11 +00:00
|
|
|
switch (icmp6->icmp6_type) {
|
|
|
|
case ICMP6_DST_UNREACH:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_dstunreach);
|
1999-11-22 02:45:11 +00:00
|
|
|
switch (code) {
|
|
|
|
case ICMP6_DST_UNREACH_ADMIN:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_adminprohib);
|
2022-10-04 03:53:04 +00:00
|
|
|
case ICMP6_DST_UNREACH_NOROUTE:
|
|
|
|
case ICMP6_DST_UNREACH_ADDR:
|
2000-07-04 16:35:15 +00:00
|
|
|
case ICMP6_DST_UNREACH_BEYONDSCOPE:
|
1999-11-22 02:45:11 +00:00
|
|
|
case ICMP6_DST_UNREACH_NOPORT:
|
2022-10-04 03:53:04 +00:00
|
|
|
goto deliver;
|
1999-11-22 02:45:11 +00:00
|
|
|
default:
|
|
|
|
goto badcode;
|
|
|
|
}
|
|
|
|
case ICMP6_PACKET_TOO_BIG:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig);
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
2022-10-04 03:53:04 +00:00
|
|
|
* Validation is made in icmp6_mtudisc_update.
|
2000-07-04 16:35:15 +00:00
|
|
|
* Updating the path MTU will be done after examining
|
|
|
|
* intermediate extension headers.
|
|
|
|
*/
|
1999-11-22 02:45:11 +00:00
|
|
|
goto deliver;
|
|
|
|
case ICMP6_TIME_EXCEEDED:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_timeexceed);
|
1999-11-22 02:45:11 +00:00
|
|
|
switch (code) {
|
|
|
|
case ICMP6_TIME_EXCEED_TRANSIT:
|
|
|
|
case ICMP6_TIME_EXCEED_REASSEMBLY:
|
2022-10-04 03:53:04 +00:00
|
|
|
goto deliver;
|
1999-11-22 02:45:11 +00:00
|
|
|
default:
|
|
|
|
goto badcode;
|
|
|
|
}
|
|
|
|
case ICMP6_PARAM_PROB:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_paramprob);
|
1999-11-22 02:45:11 +00:00
|
|
|
switch (code) {
|
|
|
|
case ICMP6_PARAMPROB_NEXTHEADER:
|
|
|
|
case ICMP6_PARAMPROB_HEADER:
|
|
|
|
case ICMP6_PARAMPROB_OPTION:
|
2022-10-04 03:53:04 +00:00
|
|
|
goto deliver;
|
1999-11-22 02:45:11 +00:00
|
|
|
default:
|
|
|
|
goto badcode;
|
|
|
|
}
|
|
|
|
case ICMP6_ECHO_REQUEST:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_echo);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
2016-09-15 07:41:48 +00:00
|
|
|
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/* Give up remote */
|
|
|
|
break;
|
|
|
|
}
|
2014-10-12 15:49:52 +00:00
|
|
|
if (!M_WRITABLE(n)
|
2000-07-04 16:35:15 +00:00
|
|
|
|| n->m_len < off + sizeof(struct icmp6_hdr)) {
|
1999-11-22 02:45:11 +00:00
|
|
|
struct mbuf *n0 = n;
|
2003-01-05 22:37:36 +00:00
|
|
|
int n0len;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2013-03-15 13:48:53 +00:00
|
|
|
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) <= MHLEN);
|
2013-03-15 12:50:29 +00:00
|
|
|
n = m_gethdr(M_NOWAIT, n0->m_type);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (n == NULL) {
|
|
|
|
/* Give up remote */
|
|
|
|
m_freem(n0);
|
|
|
|
break;
|
|
|
|
}
|
2013-03-15 13:48:53 +00:00
|
|
|
|
|
|
|
m_move_pkthdr(n, n0); /* FIB copied. */
|
|
|
|
n0len = n0->m_pkthdr.len; /* save for use below */
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Copy IPv6 and ICMPv6 only.
|
|
|
|
*/
|
|
|
|
nip6 = mtod(n, struct ip6_hdr *);
|
|
|
|
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
|
|
|
|
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
|
|
|
|
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
|
2000-07-04 16:35:15 +00:00
|
|
|
noff = sizeof(struct ip6_hdr);
|
2003-01-05 22:37:36 +00:00
|
|
|
/* new mbuf contains only ipv6+icmpv6 headers */
|
|
|
|
n->m_len = noff + sizeof(struct icmp6_hdr);
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2003-10-07 17:46:18 +00:00
|
|
|
* Adjust mbuf. ip6_plen will be adjusted in
|
2000-07-04 16:35:15 +00:00
|
|
|
* ip6_output().
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2000-07-04 16:35:15 +00:00
|
|
|
m_adj(n0, off + sizeof(struct icmp6_hdr));
|
2003-01-05 22:37:36 +00:00
|
|
|
/* recalculate complete packet size */
|
|
|
|
n->m_pkthdr.len = n0len + (noff - off);
|
2000-07-04 16:35:15 +00:00
|
|
|
n->m_next = n0;
|
1999-11-22 02:45:11 +00:00
|
|
|
} else {
|
2019-12-01 00:22:04 +00:00
|
|
|
if (n->m_len < off + sizeof(*nicmp6)) {
|
|
|
|
n = m_pullup(n, off + sizeof(*nicmp6));
|
|
|
|
if (n == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
break;
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
|
|
|
nicmp6 = (struct icmp6_hdr *)(mtod(n, caddr_t) + off);
|
1999-11-22 02:45:11 +00:00
|
|
|
noff = off;
|
|
|
|
}
|
|
|
|
if (n) {
|
2017-05-30 14:41:31 +00:00
|
|
|
nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
|
|
|
|
nicmp6->icmp6_code = 0;
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_reflect);
|
|
|
|
ICMP6STAT_INC(icp6s_outhist[ICMP6_ECHO_REPLY]);
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6_reflect(n, noff);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ICMP6_ECHO_REPLY:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_echoreply);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
break;
|
|
|
|
|
2002-05-06 16:28:25 +00:00
|
|
|
case MLD_LISTENER_QUERY:
|
|
|
|
case MLD_LISTENER_REPORT:
|
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes:
* Connect netinet6/in6_mcast.c to build.
The legacy KAME KPIs are mostly preserved.
* Eliminate now dead code from ip6_output.c.
Don't do mbuf bingo, we are not going to do RFC 2292 style
CMSG tricks for multicast options as they are not required
by any current IPv6 normative reference.
* Refactor transports (UDP, raw_ip6) to do own mcast filtering.
SCTP, TCP unaffected by this change.
* Add ip6_msource, in6_msource structs to in6_var.h.
* Hookup mld_ifinfo state to in6_ifextra, allocate from
domifattach path.
* Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced.
Kernel consumers which need this should use in6m_lookup().
* Refactor IPv6 socket group memberships to use a vector (like IPv4).
* Update ifmcstat(8) for IPv6 SSM.
* Add witness lock order for IN6_MULTI_LOCK.
* Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths.
* Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup.
* Update carp(4) for new IPv6 SSM KPIs.
* Virtualize ip6_mrouter socket.
Changes mostly localized to IPv6 MROUTING.
* Don't do a local group lookup in MROUTING.
* Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge().
* Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode.
* Bump __FreeBSD_version to 800084.
* Update UPDATING.
NOTE WELL:
* This code hasn't been tested against real MLDv2 queriers
(yet), although the on-wire protocol has been verified in Wireshark.
* There are a few unresolved issues in the socket layer APIs to
do with scope ID propagation.
* There is a LOR present in ip6_output()'s use of
in6_setscope() which needs to be resolved. See comments in mld6.c.
This is believed to be benign and can't be avoided for the moment
without re-introducing an indirect netisr.
This work was mostly derived from the IGMPv3 implementation, and
has been sponsored by a third party.
2009-04-29 19:19:13 +00:00
|
|
|
case MLD_LISTENER_DONE:
|
|
|
|
case MLDV2_LISTENER_REPORT:
|
|
|
|
/*
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
* Drop MLD traffic which is not link-local, has a hop limit
|
|
|
|
* of greater than 1 hop, or which does not have the
|
|
|
|
* IPv6 HBH Router Alert option.
|
|
|
|
* As IPv6 HBH options are stripped in ip6_input() we must
|
|
|
|
* check an mbuf header flag.
|
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes:
* Connect netinet6/in6_mcast.c to build.
The legacy KAME KPIs are mostly preserved.
* Eliminate now dead code from ip6_output.c.
Don't do mbuf bingo, we are not going to do RFC 2292 style
CMSG tricks for multicast options as they are not required
by any current IPv6 normative reference.
* Refactor transports (UDP, raw_ip6) to do own mcast filtering.
SCTP, TCP unaffected by this change.
* Add ip6_msource, in6_msource structs to in6_var.h.
* Hookup mld_ifinfo state to in6_ifextra, allocate from
domifattach path.
* Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced.
Kernel consumers which need this should use in6m_lookup().
* Refactor IPv6 socket group memberships to use a vector (like IPv4).
* Update ifmcstat(8) for IPv6 SSM.
* Add witness lock order for IN6_MULTI_LOCK.
* Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths.
* Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup.
* Update carp(4) for new IPv6 SSM KPIs.
* Virtualize ip6_mrouter socket.
Changes mostly localized to IPv6 MROUTING.
* Don't do a local group lookup in MROUTING.
* Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge().
* Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode.
* Bump __FreeBSD_version to 800084.
* Update UPDATING.
NOTE WELL:
* This code hasn't been tested against real MLDv2 queriers
(yet), although the on-wire protocol has been verified in Wireshark.
* There are a few unresolved issues in the socket layer APIs to
do with scope ID propagation.
* There is a LOR present in ip6_output()'s use of
in6_setscope() which needs to be resolved. See comments in mld6.c.
This is believed to be benign and can't be avoided for the moment
without re-introducing an indirect netisr.
This work was mostly derived from the IGMPv3 implementation, and
has been sponsored by a third party.
2009-04-29 19:19:13 +00:00
|
|
|
* XXX Should we also sanity check that these messages
|
|
|
|
* were directed to a link-local multicast prefix?
|
|
|
|
*/
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0)
|
2000-07-04 16:35:15 +00:00
|
|
|
goto freeit;
|
2019-11-18 21:59:47 +00:00
|
|
|
if (mld_input(&m, off, icmp6len) != 0) {
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes:
* Connect netinet6/in6_mcast.c to build.
The legacy KAME KPIs are mostly preserved.
* Eliminate now dead code from ip6_output.c.
Don't do mbuf bingo, we are not going to do RFC 2292 style
CMSG tricks for multicast options as they are not required
by any current IPv6 normative reference.
* Refactor transports (UDP, raw_ip6) to do own mcast filtering.
SCTP, TCP unaffected by this change.
* Add ip6_msource, in6_msource structs to in6_var.h.
* Hookup mld_ifinfo state to in6_ifextra, allocate from
domifattach path.
* Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced.
Kernel consumers which need this should use in6m_lookup().
* Refactor IPv6 socket group memberships to use a vector (like IPv4).
* Update ifmcstat(8) for IPv6 SSM.
* Add witness lock order for IN6_MULTI_LOCK.
* Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths.
* Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup.
* Update carp(4) for new IPv6 SSM KPIs.
* Virtualize ip6_mrouter socket.
Changes mostly localized to IPv6 MROUTING.
* Don't do a local group lookup in MROUTING.
* Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge().
* Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode.
* Bump __FreeBSD_version to 800084.
* Update UPDATING.
NOTE WELL:
* This code hasn't been tested against real MLDv2 queriers
(yet), although the on-wire protocol has been verified in Wireshark.
* There are a few unresolved issues in the socket layer APIs to
do with scope ID propagation.
* There is a LOR present in ip6_output()'s use of
in6_setscope() which needs to be resolved. See comments in mld6.c.
This is believed to be benign and can't be avoided for the moment
without re-introducing an indirect netisr.
This work was mostly derived from the IGMPv3 implementation, and
has been sponsored by a third party.
2009-04-29 19:19:13 +00:00
|
|
|
return (IPPROTO_DONE);
|
2019-11-12 15:46:28 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
/* m stays. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
|
|
|
|
{
|
|
|
|
enum { WRU, FQDN } mode;
|
2019-05-16 19:09:41 +00:00
|
|
|
struct prison *pr;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (!V_icmp6_nodeinfo)
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
if (icmp6len == sizeof(struct icmp6_hdr) + 4)
|
|
|
|
mode = WRU;
|
2000-07-04 16:35:15 +00:00
|
|
|
else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
|
1999-11-22 02:45:11 +00:00
|
|
|
mode = FQDN;
|
|
|
|
else
|
|
|
|
goto badlen;
|
|
|
|
|
2019-05-16 19:09:41 +00:00
|
|
|
pr = NULL;
|
|
|
|
sx_slock(&allprison_lock);
|
|
|
|
TAILQ_FOREACH(pr, &allprison, pr_list)
|
|
|
|
if (pr->pr_vnet == ifp->if_vnet)
|
|
|
|
break;
|
|
|
|
sx_sunlock(&allprison_lock);
|
|
|
|
if (pr == NULL)
|
|
|
|
pr = curthread->td_ucred->cr_prison;
|
1999-11-22 02:45:11 +00:00
|
|
|
if (mode == FQDN) {
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + sizeof(struct icmp6_nodeinfo)) {
|
|
|
|
m = m_pullup(m, off +
|
|
|
|
sizeof(struct icmp6_nodeinfo));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (IPPROTO_DONE);
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
2016-09-15 07:41:48 +00:00
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
2000-07-04 16:35:15 +00:00
|
|
|
if (n)
|
2019-05-16 19:09:41 +00:00
|
|
|
n = ni6_input(n, off, pr);
|
2000-07-04 16:35:15 +00:00
|
|
|
/* XXX meaningless if n == NULL */
|
1999-11-22 02:45:11 +00:00
|
|
|
noff = sizeof(struct ip6_hdr);
|
|
|
|
} else {
|
|
|
|
u_char *p;
|
2013-03-15 13:48:53 +00:00
|
|
|
int maxhlen, hlen;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2007-05-17 21:20:24 +00:00
|
|
|
/*
|
|
|
|
* XXX: this combination of flags is pointless,
|
|
|
|
* but should we keep this for compatibility?
|
|
|
|
*/
|
2016-05-15 03:22:13 +00:00
|
|
|
if ((V_icmp6_nodeinfo & (ICMP6_NODEINFO_FQDNOK |
|
|
|
|
ICMP6_NODEINFO_TMPADDROK)) !=
|
|
|
|
(ICMP6_NODEINFO_FQDNOK | ICMP6_NODEINFO_TMPADDROK))
|
2001-06-11 12:39:29 +00:00
|
|
|
break;
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
2013-03-15 13:48:53 +00:00
|
|
|
|
|
|
|
CTASSERT(sizeof(*nip6) + sizeof(*nicmp6) + 4 <= MHLEN);
|
|
|
|
n = m_gethdr(M_NOWAIT, m->m_type);
|
|
|
|
if (n == NULL) {
|
2000-07-04 16:35:15 +00:00
|
|
|
/* Give up remote */
|
|
|
|
break;
|
|
|
|
}
|
2013-03-15 13:48:53 +00:00
|
|
|
if (!m_dup_pkthdr(n, m, M_NOWAIT)) {
|
2002-12-30 20:22:40 +00:00
|
|
|
/*
|
|
|
|
* Previous code did a blind M_COPY_PKTHDR
|
|
|
|
* and said "just for rcvif". If true, then
|
|
|
|
* we could tolerate the dup failing (due to
|
|
|
|
* the deep copy of the tag chain). For now
|
|
|
|
* be conservative and just fail.
|
|
|
|
*/
|
|
|
|
m_free(n);
|
|
|
|
n = NULL;
|
2017-05-30 14:41:31 +00:00
|
|
|
break;
|
2002-12-30 20:22:40 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Copy IPv6 and ICMPv6 only.
|
|
|
|
*/
|
|
|
|
nip6 = mtod(n, struct ip6_hdr *);
|
|
|
|
bcopy(ip6, nip6, sizeof(struct ip6_hdr));
|
|
|
|
nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
|
|
|
|
bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
|
|
|
|
p = (u_char *)(nicmp6 + 1);
|
|
|
|
bzero(p, 4);
|
2019-05-16 19:09:41 +00:00
|
|
|
|
|
|
|
maxhlen = M_TRAILINGSPACE(n) -
|
|
|
|
(sizeof(*nip6) + sizeof(*nicmp6) + 4);
|
|
|
|
mtx_lock(&pr->pr_mtx);
|
|
|
|
hlen = strlen(pr->pr_hostname);
|
|
|
|
if (maxhlen > hlen)
|
|
|
|
maxhlen = hlen;
|
2009-06-13 15:39:12 +00:00
|
|
|
/* meaningless TTL */
|
|
|
|
bcopy(pr->pr_hostname, p + 4, maxhlen);
|
2009-05-29 21:27:12 +00:00
|
|
|
mtx_unlock(&pr->pr_mtx);
|
1999-11-22 02:45:11 +00:00
|
|
|
noff = sizeof(struct ip6_hdr);
|
|
|
|
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
|
2000-07-04 16:35:15 +00:00
|
|
|
sizeof(struct icmp6_hdr) + 4 + maxhlen;
|
1999-11-22 02:45:11 +00:00
|
|
|
nicmp6->icmp6_type = ICMP6_WRUREPLY;
|
|
|
|
nicmp6->icmp6_code = 0;
|
|
|
|
}
|
|
|
|
if (n) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_reflect);
|
|
|
|
ICMP6STAT_INC(icp6s_outhist[ICMP6_WRUREPLY]);
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6_reflect(n, noff);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ICMP6_WRUREPLY:
|
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ND_ROUTER_SOLICIT:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_routersolicit);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct nd_router_solicit))
|
|
|
|
goto badlen;
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + icmp6len) {
|
|
|
|
m = m_pullup(m, off + icmp6len);
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = NULL;
|
|
|
|
return (IPPROTO_DONE);
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
2016-09-20 18:08:17 +00:00
|
|
|
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
|
|
|
|
if (error == 0) {
|
|
|
|
m = NULL;
|
2010-08-19 23:16:44 +00:00
|
|
|
goto freeit;
|
2016-09-20 18:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
nd6_rs_input(m, off, icmp6len);
|
|
|
|
m = n;
|
|
|
|
if (m == NULL)
|
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ND_ROUTER_ADVERT:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_routeradvert);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct nd_router_advert))
|
|
|
|
goto badlen;
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
2016-09-20 18:08:17 +00:00
|
|
|
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
|
|
|
|
if (error == 0) {
|
|
|
|
m = NULL;
|
2010-08-19 23:16:44 +00:00
|
|
|
goto freeit;
|
2016-09-20 18:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
nd6_ra_input(m, off, icmp6len);
|
|
|
|
m = n;
|
|
|
|
if (m == NULL)
|
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ND_NEIGHBOR_SOLICIT:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_neighborsolicit);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct nd_neighbor_solicit))
|
|
|
|
goto badlen;
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
2016-09-20 18:08:17 +00:00
|
|
|
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
|
|
|
|
if (error == 0) {
|
|
|
|
m = NULL;
|
2010-08-19 23:16:44 +00:00
|
|
|
goto freeit;
|
2016-09-20 18:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
nd6_ns_input(m, off, icmp6len);
|
|
|
|
m = n;
|
|
|
|
if (m == NULL)
|
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ND_NEIGHBOR_ADVERT:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_neighboradvert);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct nd_neighbor_advert))
|
|
|
|
goto badlen;
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
2016-09-20 18:08:17 +00:00
|
|
|
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
|
|
|
|
if (error == 0) {
|
|
|
|
m = NULL;
|
2010-08-19 23:16:44 +00:00
|
|
|
goto freeit;
|
2016-09-20 18:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
nd6_na_input(m, off, icmp6len);
|
|
|
|
m = n;
|
|
|
|
if (m == NULL)
|
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ND_REDIRECT:
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
icmp6_ifstat_inc(ifp, ifs6_in_redirect);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (code != 0)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct nd_redirect))
|
|
|
|
goto badlen;
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
2016-09-20 18:08:17 +00:00
|
|
|
error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
|
|
|
|
if (error == 0) {
|
|
|
|
m = NULL;
|
2010-08-19 23:16:44 +00:00
|
|
|
goto freeit;
|
2016-09-20 18:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
icmp6_redirect_input(m, off);
|
|
|
|
m = n;
|
|
|
|
if (m == NULL)
|
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ICMP6_ROUTER_RENUMBERING:
|
|
|
|
if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
|
|
|
|
code != ICMP6_ROUTER_RENUMBERING_RESULT)
|
|
|
|
goto badcode;
|
|
|
|
if (icmp6len < sizeof(struct icmp6_router_renum))
|
|
|
|
goto badlen;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG,
|
|
|
|
"icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
|
2006-12-12 12:17:58 +00:00
|
|
|
icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
|
|
|
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
|
Merge final round of MLD changes from p4:
ip6_input.c, in6.h:
* Add netinet6-specific mbuf flag M_RTALERT_MLD, shadowing M_PROTO6.
* Always set this flag if HBH Router Alert option is present for MLD,
even when not forwarding.
icmp6.c:
* In icmp6_input(), spell m->m_pkthdr.rcvif as ifp to be consistent.
* Use scope ID for verifying input. Do not apply SSM filters here, no inpcb.
* Check for M_RTALERT_MLD when validating MLD traffic, as we can't see
IPv6 hop options outside of ip6_input().
in6_mcast.c:
* Use KAME scope/zone ID in in6_multi.
* Update net.inet6.ip6.mcast.filters implementation to use scope IDs
for comparisons.
* Fix scope ID treatment in multicast socket option processing.
Scope IDs passed in from userland will be ignored as other less
ambiguous APIs exist for specifying the link.
* Tighten userland input checks in IPv6 SSM delta and full-state ops.
* Source filter embedded scope IDs need to be revisited, for now
just clear them and ignore them on input.
* Adapt KAME behaviour of looking up the scope ID in the default zone
for multicast leaves, when the interface is ambiguous.
mld6.c:
* Tighten origin checks on MLD traffic as per RFC3810 Section 6.2:
* ip6_src MAY be the unspecified address for MLDv1 reports.
* ip6_src MAY have link-local address scope for MLDv1 reports,
MLDv1 queries, and MLDv2 queries.
* Perform address field validation *before* accepting queries.
* Use KAME scope/zone ID in query/report processing.
* Break const correctness for mld_v1_input_report(), mld_v1_input_query()
as we temporarily modify the input mbuf chain.
* Clear the scope ID before handoff to userland MLD daemon.
* Fix MLDv1 old querier present timer processing.
With the protocol defaults, hosts should revert to MLDv2 after 260s.
* Add net.inet6.mld.v1enable sysctl, default to on.
ifmcstat.c:
* Use sysctl by default; -K requests kvm(3) if so compiled.
mld.4:
* Connect man page to build.
Tested using PCS.
2009-05-27 18:57:13 +00:00
|
|
|
ifp ? ifp->if_index : 0));
|
1999-11-22 02:45:11 +00:00
|
|
|
if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
|
|
|
|
/* ICMPv6 error: MUST deliver it by spec... */
|
2022-10-04 03:53:04 +00:00
|
|
|
goto deliver;
|
1999-11-22 02:45:11 +00:00
|
|
|
} else {
|
|
|
|
/* ICMPv6 informational: MUST not deliver */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
deliver:
|
2022-10-04 03:53:04 +00:00
|
|
|
if (icmp6_notify_error(&m, off, icmp6len) != 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
/* In this case, m should've been freed. */
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
2003-10-06 14:02:09 +00:00
|
|
|
return (IPPROTO_DONE);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
badcode:
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_badcode);
|
2001-06-11 12:39:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
badlen:
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_badlen);
|
2001-06-11 12:39:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* deliver the packet to appropriate sockets */
|
|
|
|
icmp6_rip6_input(&m, *offp);
|
|
|
|
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = m;
|
|
|
|
return (IPPROTO_DONE);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
freeit:
|
|
|
|
m_freem(m);
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
|
|
|
return (IPPROTO_DONE);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-10-04 03:53:04 +00:00
|
|
|
icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
|
2001-06-11 12:39:29 +00:00
|
|
|
{
|
2019-11-07 18:29:51 +00:00
|
|
|
struct mbuf *m;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct icmp6_hdr *icmp6;
|
|
|
|
struct ip6_hdr *eip6;
|
|
|
|
u_int32_t notifymtu;
|
|
|
|
struct sockaddr_in6 icmp6src, icmp6dst;
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
m = *mp;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_tooshort);
|
2001-06-11 12:39:29 +00:00
|
|
|
goto freeit;
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + sizeof(*icmp6) + sizeof(struct ip6_hdr)) {
|
|
|
|
m = m_pullup(m, off + sizeof(*icmp6) + sizeof(struct ip6_hdr));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (-1);
|
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
2001-06-11 12:39:29 +00:00
|
|
|
eip6 = (struct ip6_hdr *)(icmp6 + 1);
|
2020-10-28 20:22:20 +00:00
|
|
|
bzero(&icmp6dst, sizeof(icmp6dst));
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
/* Detect the upper level protocol */
|
|
|
|
{
|
1999-11-22 02:45:11 +00:00
|
|
|
u_int8_t nxt = eip6->ip6_nxt;
|
|
|
|
int eoff = off + sizeof(struct icmp6_hdr) +
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(struct ip6_hdr);
|
1999-11-22 02:45:11 +00:00
|
|
|
struct ip6ctlparam ip6cp;
|
2000-07-04 16:35:15 +00:00
|
|
|
int icmp6type = icmp6->icmp6_type;
|
|
|
|
struct ip6_frag *fh;
|
|
|
|
struct ip6_rthdr *rth;
|
|
|
|
struct ip6_rthdr0 *rth0;
|
|
|
|
int rthlen;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2002-04-19 04:46:24 +00:00
|
|
|
while (1) { /* XXX: should avoid infinite loop explicitly? */
|
1999-11-22 02:45:11 +00:00
|
|
|
struct ip6_ext *eh;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (nxt) {
|
1999-11-22 02:45:11 +00:00
|
|
|
case IPPROTO_HOPOPTS:
|
|
|
|
case IPPROTO_DSTOPTS:
|
|
|
|
case IPPROTO_AH:
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < eoff + sizeof(struct ip6_ext)) {
|
|
|
|
m = m_pullup(m, eoff +
|
|
|
|
sizeof(struct ip6_ext));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (-1);
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
eh = (struct ip6_ext *)
|
|
|
|
(mtod(m, caddr_t) + eoff);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (nxt == IPPROTO_AH)
|
|
|
|
eoff += (eh->ip6e_len + 2) << 2;
|
|
|
|
else
|
|
|
|
eoff += (eh->ip6e_len + 1) << 3;
|
|
|
|
nxt = eh->ip6e_nxt;
|
|
|
|
break;
|
2000-07-04 16:35:15 +00:00
|
|
|
case IPPROTO_ROUTING:
|
|
|
|
/*
|
|
|
|
* When the erroneous packet contains a
|
|
|
|
* routing header, we should examine the
|
|
|
|
* header to determine the final destination.
|
|
|
|
* Otherwise, we can't properly update
|
|
|
|
* information that depends on the final
|
|
|
|
* destination (e.g. path MTU).
|
|
|
|
*/
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < eoff + sizeof(*rth)) {
|
|
|
|
m = m_pullup(m, eoff + sizeof(*rth));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (-1);
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
rth = (struct ip6_rthdr *)
|
|
|
|
(mtod(m, caddr_t) + eoff);
|
2000-07-04 16:35:15 +00:00
|
|
|
rthlen = (rth->ip6r_len + 1) << 3;
|
|
|
|
/*
|
|
|
|
* XXX: currently there is no
|
|
|
|
* officially defined type other
|
|
|
|
* than type-0.
|
|
|
|
* Note that if the segment left field
|
|
|
|
* is 0, all intermediate hops must
|
|
|
|
* have been passed.
|
|
|
|
*/
|
|
|
|
if (rth->ip6r_segleft &&
|
|
|
|
rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
|
|
|
|
int hops;
|
|
|
|
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < eoff + rthlen) {
|
|
|
|
m = m_pullup(m, eoff + rthlen);
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(
|
|
|
|
ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (-1);
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
rth0 = (struct ip6_rthdr0 *)
|
|
|
|
(mtod(m, caddr_t) + eoff);
|
2020-10-28 20:22:20 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/* just ignore a bogus header */
|
|
|
|
if ((rth0->ip6r0_len % 2) == 0 &&
|
|
|
|
(hops = rth0->ip6r0_len/2))
|
2020-10-28 20:22:20 +00:00
|
|
|
icmp6dst.sin6_addr = *((struct in6_addr *)(rth0 + 1) + (hops - 1));
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
eoff += rthlen;
|
|
|
|
nxt = rth->ip6r_nxt;
|
|
|
|
break;
|
|
|
|
case IPPROTO_FRAGMENT:
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < eoff + sizeof(struct ip6_frag)) {
|
|
|
|
m = m_pullup(m, eoff +
|
|
|
|
sizeof(struct ip6_frag));
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
*mp = m;
|
|
|
|
return (-1);
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
fh = (struct ip6_frag *)(mtod(m, caddr_t) +
|
|
|
|
eoff);
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* Data after a fragment header is meaningless
|
|
|
|
* unless it is the first fragment, but
|
|
|
|
* we'll go to the notify label for path MTU
|
|
|
|
* discovery.
|
|
|
|
*/
|
|
|
|
if (fh->ip6f_offlg & IP6F_OFF_MASK)
|
|
|
|
goto notify;
|
|
|
|
|
|
|
|
eoff += sizeof(struct ip6_frag);
|
|
|
|
nxt = fh->ip6f_nxt;
|
|
|
|
break;
|
1999-11-22 02:45:11 +00:00
|
|
|
default:
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* This case includes ESP and the No Next
|
2002-04-19 04:46:24 +00:00
|
|
|
* Header. In such cases going to the notify
|
2000-07-04 16:35:15 +00:00
|
|
|
* label does not have any meaning
|
|
|
|
* (i.e. ctlfunc will be NULL), but we go
|
|
|
|
* anyway since we might have to update
|
|
|
|
* path MTU information.
|
|
|
|
*/
|
1999-11-22 02:45:11 +00:00
|
|
|
goto notify;
|
|
|
|
}
|
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
notify:
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2003-10-07 17:46:18 +00:00
|
|
|
/*
|
|
|
|
* retrieve parameters from the inner IPv6 header, and convert
|
|
|
|
* them into sockaddr structures.
|
|
|
|
* XXX: there is no guarantee that the source or destination
|
|
|
|
* addresses of the inner packet are in the same scope as
|
|
|
|
* the addresses of the icmp packet. But there is no other
|
|
|
|
* way to determine the zone.
|
|
|
|
*/
|
2001-06-11 12:39:29 +00:00
|
|
|
eip6 = (struct ip6_hdr *)(icmp6 + 1);
|
2003-10-07 17:46:18 +00:00
|
|
|
|
2023-03-13 14:45:56 +00:00
|
|
|
/*
|
|
|
|
* Protocol layers can't do anything useful with unspecified
|
|
|
|
* addresses.
|
|
|
|
*/
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
|
|
|
|
IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
|
|
|
|
goto freeit;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
icmp6dst.sin6_family = AF_INET6;
|
2020-10-28 20:22:20 +00:00
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
|
2001-06-11 12:39:29 +00:00
|
|
|
icmp6dst.sin6_addr = eip6->ip6_dst;
|
2005-07-25 12:31:43 +00:00
|
|
|
if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
|
2001-06-11 12:39:29 +00:00
|
|
|
goto freeit;
|
|
|
|
bzero(&icmp6src, sizeof(icmp6src));
|
|
|
|
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
icmp6src.sin6_family = AF_INET6;
|
|
|
|
icmp6src.sin6_addr = eip6->ip6_src;
|
2005-07-25 12:31:43 +00:00
|
|
|
if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
|
2001-06-11 12:39:29 +00:00
|
|
|
goto freeit;
|
2005-07-25 12:31:43 +00:00
|
|
|
icmp6src.sin6_flowinfo =
|
|
|
|
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
ip6cp.ip6c_m = m;
|
|
|
|
ip6cp.ip6c_icmp6 = icmp6;
|
|
|
|
ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
|
|
|
|
ip6cp.ip6c_off = eoff;
|
2022-10-04 03:53:04 +00:00
|
|
|
ip6cp.ip6c_finaldst = &icmp6dst;
|
2001-06-11 12:39:29 +00:00
|
|
|
ip6cp.ip6c_src = &icmp6src;
|
|
|
|
ip6cp.ip6c_nxt = nxt;
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
if (icmp6type == ICMP6_PACKET_TOO_BIG) {
|
2001-06-11 12:39:29 +00:00
|
|
|
notifymtu = ntohl(icmp6->icmp6_mtu);
|
|
|
|
ip6cp.ip6c_cmdarg = (void *)¬ifymtu;
|
|
|
|
icmp6_mtudisc_update(&ip6cp, 1); /*XXX*/
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
|
2022-08-17 18:50:31 +00:00
|
|
|
if (ip6_ctlprotox[nxt] != NULL)
|
2022-10-04 03:53:04 +00:00
|
|
|
ip6_ctlprotox[nxt](&ip6cp);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2005-02-27 18:57:10 +00:00
|
|
|
*mp = m;
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
freeit:
|
1999-11-22 02:45:11 +00:00
|
|
|
m_freem(m);
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
2003-10-06 14:02:09 +00:00
|
|
|
return (-1);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
|
2000-07-04 16:35:15 +00:00
|
|
|
{
|
2022-10-04 03:53:04 +00:00
|
|
|
struct in6_addr *dst = &ip6cp->ip6c_finaldst->sin6_addr;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
|
|
|
|
struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
|
2000-07-04 16:35:15 +00:00
|
|
|
u_int mtu = ntohl(icmp6->icmp6_mtu);
|
2003-11-20 20:07:39 +00:00
|
|
|
struct in_conninfo inc;
|
2022-07-20 07:22:34 +00:00
|
|
|
uint32_t max_mtu;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2003-10-24 18:26:30 +00:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* RFC2460 section 5, last paragraph.
|
|
|
|
* even though minimum link MTU for IPv6 is IPV6_MMTU,
|
|
|
|
* we may see ICMPv6 too big with mtu < IPV6_MMTU
|
|
|
|
* due to packet translator in the middle.
|
|
|
|
* see ip6_output() and ip6_getpmtu() "alwaysfrag" case for
|
|
|
|
* special handling.
|
|
|
|
*/
|
|
|
|
if (mtu < IPV6_MMTU)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we reject ICMPv6 too big with abnormally small value.
|
|
|
|
* XXX what is the good definition of "abnormally small"?
|
|
|
|
*/
|
|
|
|
if (mtu < sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + 8)
|
|
|
|
return;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if (!validated)
|
|
|
|
return;
|
|
|
|
|
2008-09-03 19:09:47 +00:00
|
|
|
/*
|
|
|
|
* In case the suggested mtu is less than IPV6_MMTU, we
|
|
|
|
* only need to remember that it was for above mentioned
|
|
|
|
* "alwaysfrag" case.
|
|
|
|
* Try to be as close to the spec as possible.
|
|
|
|
*/
|
|
|
|
if (mtu < IPV6_MMTU)
|
|
|
|
mtu = IPV6_MMTU - 8;
|
|
|
|
|
2003-11-20 20:07:39 +00:00
|
|
|
bzero(&inc, sizeof(inc));
|
2013-10-25 01:02:25 +00:00
|
|
|
inc.inc_fibnum = M_GETFIB(m);
|
2008-12-17 12:52:34 +00:00
|
|
|
inc.inc_flags |= INC_ISIPV6;
|
2003-11-20 20:07:39 +00:00
|
|
|
inc.inc6_faddr = *dst;
|
2005-07-25 12:31:43 +00:00
|
|
|
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
|
|
|
|
return;
|
2003-11-20 20:07:39 +00:00
|
|
|
|
2022-07-20 07:22:34 +00:00
|
|
|
max_mtu = tcp_hc_getmtu(&inc);
|
|
|
|
if (max_mtu == 0)
|
|
|
|
max_mtu = tcp_maxmtu6(&inc, NULL);
|
|
|
|
|
|
|
|
if (mtu < max_mtu) {
|
2003-11-20 20:07:39 +00:00
|
|
|
tcp_hc_updatemtu(&inc, mtu);
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_pmtuchg);
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2001-06-11 12:39:29 +00:00
|
|
|
* Process a Node Information Query packet, based on
|
|
|
|
* draft-ietf-ipngwg-icmp-name-lookups-07.
|
2003-10-07 17:46:18 +00:00
|
|
|
*
|
2000-07-04 16:35:15 +00:00
|
|
|
* Spec incompatibilities:
|
|
|
|
* - IPv6 Subject address handling
|
|
|
|
* - IPv4 Subject address handling support missing
|
|
|
|
* - Proxy reply (answer even if it's not for me)
|
|
|
|
* - joins NI group address at in6_ifattach() time only, does not cope
|
|
|
|
* with hostname changes by sethostname(3)
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2019-05-16 19:09:41 +00:00
|
|
|
ni6_input(struct mbuf *m, int off, struct prison *pr)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2000-07-04 16:35:15 +00:00
|
|
|
struct icmp6_nodeinfo *ni6, *nni6;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct mbuf *n = NULL;
|
2000-07-04 16:35:15 +00:00
|
|
|
u_int16_t qtype;
|
|
|
|
int subjlen;
|
1999-11-22 02:45:11 +00:00
|
|
|
int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
|
|
|
|
struct ni_reply_fqdn *fqdn;
|
|
|
|
int addrs; /* for NI_QTYPE_NODEADDR */
|
|
|
|
struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
|
2005-07-25 12:31:43 +00:00
|
|
|
struct in6_addr in6_subj; /* subject address */
|
2000-07-04 16:35:15 +00:00
|
|
|
struct ip6_hdr *ip6;
|
|
|
|
int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
|
2001-06-11 12:39:29 +00:00
|
|
|
char *subj = NULL;
|
|
|
|
struct in6_ifaddr *ia6 = NULL;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
|
|
|
|
|
2007-05-17 21:20:24 +00:00
|
|
|
/*
|
|
|
|
* Validate IPv6 source address.
|
|
|
|
* The default configuration MUST be to refuse answering queries from
|
|
|
|
* global-scope addresses according to RFC4602.
|
|
|
|
* Notes:
|
|
|
|
* - it's not very clear what "refuse" means; this implementation
|
|
|
|
* simply drops it.
|
|
|
|
* - it's not very easy to identify global-scope (unicast) addresses
|
|
|
|
* since there are many prefixes for them. It should be safer
|
|
|
|
* and in practice sufficient to check "all" but loopback and
|
|
|
|
* link-local (note that site-local unicast was deprecated and
|
|
|
|
* ULA is defined as global scope-wise)
|
|
|
|
*/
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
|
2007-05-17 21:20:24 +00:00
|
|
|
!IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
|
|
|
|
!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
|
|
|
|
goto bad;
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* Validate IPv6 destination address.
|
|
|
|
*
|
2001-06-11 12:39:29 +00:00
|
|
|
* The Responder must discard the Query without further processing
|
|
|
|
* unless it is one of the Responder's unicast or anycast addresses, or
|
|
|
|
* a link-local scope multicast address which the Responder has joined.
|
2007-05-17 21:20:24 +00:00
|
|
|
* [RFC4602, Section 5.]
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
2003-10-28 16:29:26 +00:00
|
|
|
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
|
|
|
if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
|
|
|
|
goto bad;
|
|
|
|
/* else it's a link-local multicast, fine */
|
|
|
|
} else { /* unicast or anycast */
|
2021-02-15 21:59:21 +00:00
|
|
|
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
|
2014-11-08 19:38:34 +00:00
|
|
|
if (ia6 == NULL)
|
2003-10-28 16:29:26 +00:00
|
|
|
goto bad; /* XXX impossible */
|
|
|
|
|
|
|
|
if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
!(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
|
|
|
|
"a temporary address in %s:%d",
|
|
|
|
__FILE__, __LINE__));
|
|
|
|
goto bad;
|
|
|
|
}
|
2003-10-28 16:29:26 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
/* validate query Subject field. */
|
2001-06-11 12:39:29 +00:00
|
|
|
qtype = ntohs(ni6->ni_qtype);
|
2000-07-04 16:35:15 +00:00
|
|
|
subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
|
|
|
|
switch (qtype) {
|
|
|
|
case NI_QTYPE_NOOP:
|
|
|
|
case NI_QTYPE_SUPTYPES:
|
2001-06-11 12:39:29 +00:00
|
|
|
/* 07 draft */
|
|
|
|
if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0)
|
|
|
|
break;
|
|
|
|
/* FALLTHROUGH */
|
2000-07-04 16:35:15 +00:00
|
|
|
case NI_QTYPE_FQDN:
|
|
|
|
case NI_QTYPE_NODEADDR:
|
2005-10-19 16:27:33 +00:00
|
|
|
case NI_QTYPE_IPV4ADDR:
|
2000-07-04 16:35:15 +00:00
|
|
|
switch (ni6->ni_code) {
|
|
|
|
case ICMP6_NI_SUBJ_IPV6:
|
|
|
|
#if ICMP6_NI_SUBJ_IPV6 != 0
|
|
|
|
case 0:
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* backward compatibility - try to accept 03 draft
|
|
|
|
* format, where no Subject is present.
|
|
|
|
*/
|
2001-06-11 12:39:29 +00:00
|
|
|
if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
|
|
|
|
subjlen == 0) {
|
2000-07-04 16:35:15 +00:00
|
|
|
oldfqdn++;
|
|
|
|
break;
|
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
#if ICMP6_NI_SUBJ_IPV6 != 0
|
|
|
|
if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6)
|
|
|
|
goto bad;
|
|
|
|
#endif
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2003-10-28 16:29:26 +00:00
|
|
|
if (subjlen != sizeof(struct in6_addr))
|
2000-07-04 16:35:15 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* Validate Subject address.
|
|
|
|
*
|
2001-06-11 12:39:29 +00:00
|
|
|
* Not sure what exactly "address belongs to the node"
|
|
|
|
* means in the spec, is it just unicast, or what?
|
2000-07-04 16:35:15 +00:00
|
|
|
*
|
|
|
|
* At this moment we consider Subject address as
|
|
|
|
* "belong to the node" if the Subject address equals
|
|
|
|
* to the IPv6 destination address; validation for
|
|
|
|
* IPv6 destination address should have done enough
|
|
|
|
* check for us.
|
|
|
|
*
|
|
|
|
* We do not do proxy at this moment.
|
|
|
|
*/
|
|
|
|
m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
|
2005-07-25 12:31:43 +00:00
|
|
|
subjlen, (caddr_t)&in6_subj);
|
|
|
|
if (in6_setscope(&in6_subj, m->m_pkthdr.rcvif, NULL))
|
2003-10-21 20:05:32 +00:00
|
|
|
goto bad;
|
2003-10-28 16:29:26 +00:00
|
|
|
|
2005-07-25 12:31:43 +00:00
|
|
|
subj = (char *)&in6_subj;
|
|
|
|
if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &in6_subj))
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* XXX if we are to allow other cases, we should really
|
|
|
|
* be careful about scope here.
|
|
|
|
* basically, we should disallow queries toward IPv6
|
2003-10-07 17:46:18 +00:00
|
|
|
* destination X with subject Y,
|
|
|
|
* if scope(X) > scope(Y).
|
2000-07-04 16:35:15 +00:00
|
|
|
* if we allow scope(X) > scope(Y), it will result in
|
|
|
|
* information leakage across scope boundary.
|
|
|
|
*/
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
case ICMP6_NI_SUBJ_FQDN:
|
|
|
|
/*
|
|
|
|
* Validate Subject name with gethostname(3).
|
|
|
|
*
|
|
|
|
* The behavior may need some debate, since:
|
|
|
|
* - we are not sure if the node has FQDN as
|
|
|
|
* hostname (returned by gethostname(3)).
|
|
|
|
* - the code does wildcard match for truncated names.
|
|
|
|
* however, we are not sure if we want to perform
|
|
|
|
* wildcard match, if gethostname(3) side has
|
|
|
|
* truncated hostname.
|
|
|
|
*/
|
2009-05-29 21:27:12 +00:00
|
|
|
mtx_lock(&pr->pr_mtx);
|
2009-06-13 15:39:12 +00:00
|
|
|
n = ni6_nametodns(pr->pr_hostname,
|
|
|
|
strlen(pr->pr_hostname), 0);
|
2009-05-29 21:27:12 +00:00
|
|
|
mtx_unlock(&pr->pr_mtx);
|
2000-07-04 16:35:15 +00:00
|
|
|
if (!n || n->m_next || n->m_len == 0)
|
|
|
|
goto bad;
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + sizeof(struct icmp6_nodeinfo) +
|
|
|
|
subjlen) {
|
|
|
|
m = m_pullup(m, off +
|
|
|
|
sizeof(struct icmp6_nodeinfo) + subjlen);
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
goto bad;
|
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
}
|
|
|
|
/* ip6 possibly invalid but not used after. */
|
|
|
|
ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
|
|
|
|
subj = (char *)(mtod(m, caddr_t) + off +
|
|
|
|
sizeof(struct icmp6_nodeinfo));
|
2000-07-04 16:35:15 +00:00
|
|
|
if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
|
2003-10-07 17:46:18 +00:00
|
|
|
n->m_len)) {
|
2000-07-04 16:35:15 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
m_freem(n);
|
|
|
|
n = NULL;
|
|
|
|
break;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */
|
2000-07-04 16:35:15 +00:00
|
|
|
default:
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
|
|
|
|
switch (qtype) {
|
|
|
|
case NI_QTYPE_FQDN:
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0)
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_NODEADDR:
|
2005-10-19 16:27:33 +00:00
|
|
|
case NI_QTYPE_IPV4ADDR:
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0)
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
|
|
|
break;
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
/* guess reply length */
|
|
|
|
switch (qtype) {
|
|
|
|
case NI_QTYPE_NOOP:
|
|
|
|
break; /* no reply data */
|
|
|
|
case NI_QTYPE_SUPTYPES:
|
|
|
|
replylen += sizeof(u_int32_t);
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_FQDN:
|
|
|
|
/* XXX will append an mbuf */
|
|
|
|
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_NODEADDR:
|
2005-08-09 12:24:11 +00:00
|
|
|
addrs = ni6_addrs(ni6, m, &ifp, (struct in6_addr *)subj);
|
2001-06-11 12:39:29 +00:00
|
|
|
if ((replylen += addrs * (sizeof(struct in6_addr) +
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(u_int32_t))) > MCLBYTES)
|
2001-06-11 12:39:29 +00:00
|
|
|
replylen = MCLBYTES; /* XXX: will truncate pkt later */
|
|
|
|
break;
|
2005-10-19 16:27:33 +00:00
|
|
|
case NI_QTYPE_IPV4ADDR:
|
|
|
|
/* unsupported - should respond with unknown Qtype? */
|
|
|
|
break;
|
2000-07-04 16:35:15 +00:00
|
|
|
default:
|
2001-06-11 12:39:29 +00:00
|
|
|
/*
|
|
|
|
* XXX: We must return a reply with the ICMP6 code
|
2003-10-07 17:46:18 +00:00
|
|
|
* `unknown Qtype' in this case. However we regard the case
|
2001-06-11 12:39:29 +00:00
|
|
|
* as an FQDN query for backward compatibility.
|
|
|
|
* Older versions set a random value to this field,
|
|
|
|
* so it rarely varies in the defined qtypes.
|
|
|
|
* But the mechanism is not reliable...
|
|
|
|
* maybe we should obsolete older versions.
|
|
|
|
*/
|
|
|
|
qtype = NI_QTYPE_FQDN;
|
|
|
|
/* XXX will append an mbuf */
|
|
|
|
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
|
|
|
|
oldfqdn++;
|
|
|
|
break;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2013-03-15 13:48:53 +00:00
|
|
|
/* Allocate an mbuf to reply. */
|
|
|
|
if (replylen > MCLBYTES) {
|
|
|
|
/*
|
|
|
|
* XXX: should we try to allocate more? But MCLBYTES
|
|
|
|
* is probably much larger than IPV6_MMTU...
|
|
|
|
*/
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (replylen > MHLEN)
|
|
|
|
n = m_getcl(M_NOWAIT, m->m_type, M_PKTHDR);
|
|
|
|
else
|
|
|
|
n = m_gethdr(M_NOWAIT, m->m_type);
|
2000-07-04 16:35:15 +00:00
|
|
|
if (n == NULL) {
|
|
|
|
m_freem(m);
|
2003-10-06 14:02:09 +00:00
|
|
|
return (NULL);
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2013-03-15 13:48:53 +00:00
|
|
|
m_move_pkthdr(n, m); /* just for recvif and FIB */
|
1999-11-22 02:45:11 +00:00
|
|
|
n->m_pkthdr.len = n->m_len = replylen;
|
|
|
|
|
|
|
|
/* copy mbuf header and IPv6 + Node Information base headers */
|
|
|
|
bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
|
|
|
|
nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
|
2000-07-04 16:35:15 +00:00
|
|
|
bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/* qtype dependent procedure */
|
|
|
|
switch (qtype) {
|
2000-07-04 16:35:15 +00:00
|
|
|
case NI_QTYPE_NOOP:
|
2001-06-11 12:39:29 +00:00
|
|
|
nni6->ni_code = ICMP6_NI_SUCCESS;
|
2000-07-04 16:35:15 +00:00
|
|
|
nni6->ni_flags = 0;
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_SUPTYPES:
|
2001-06-11 12:39:29 +00:00
|
|
|
{
|
|
|
|
u_int32_t v;
|
|
|
|
nni6->ni_code = ICMP6_NI_SUCCESS;
|
|
|
|
nni6->ni_flags = htons(0x0000); /* raw bitmap */
|
|
|
|
/* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
|
|
|
|
v = (u_int32_t)htonl(0x0000000f);
|
|
|
|
bcopy(&v, nni6 + 1, sizeof(u_int32_t));
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
case NI_QTYPE_FQDN:
|
2001-06-11 12:39:29 +00:00
|
|
|
nni6->ni_code = ICMP6_NI_SUCCESS;
|
2000-07-04 16:35:15 +00:00
|
|
|
fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo));
|
2000-07-04 16:35:15 +00:00
|
|
|
nni6->ni_flags = 0; /* XXX: meaningless TTL */
|
|
|
|
fqdn->ni_fqdn_ttl = 0; /* ditto. */
|
|
|
|
/*
|
2009-05-29 21:27:12 +00:00
|
|
|
* XXX do we really have FQDN in hostname?
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
2009-05-29 21:27:12 +00:00
|
|
|
mtx_lock(&pr->pr_mtx);
|
2009-06-13 15:39:12 +00:00
|
|
|
n->m_next = ni6_nametodns(pr->pr_hostname,
|
|
|
|
strlen(pr->pr_hostname), oldfqdn);
|
2009-05-29 21:27:12 +00:00
|
|
|
mtx_unlock(&pr->pr_mtx);
|
2000-07-04 16:35:15 +00:00
|
|
|
if (n->m_next == NULL)
|
|
|
|
goto bad;
|
|
|
|
/* XXX we assume that n->m_next is not a chain */
|
|
|
|
if (n->m_next->m_next != NULL)
|
|
|
|
goto bad;
|
|
|
|
n->m_pkthdr.len += n->m_next->m_len;
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_NODEADDR:
|
|
|
|
{
|
|
|
|
int lenlim, copied;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
nni6->ni_code = ICMP6_NI_SUCCESS;
|
|
|
|
n->m_pkthdr.len = n->m_len =
|
|
|
|
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
|
|
|
|
lenlim = M_TRAILINGSPACE(n);
|
2000-07-04 16:35:15 +00:00
|
|
|
copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
|
|
|
|
/* XXX: reset mbuf length */
|
|
|
|
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(struct icmp6_nodeinfo) + copied;
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break; /* XXX impossible! */
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nni6->ni_type = ICMP6_NI_REPLY;
|
2000-07-04 16:35:15 +00:00
|
|
|
m_freem(m);
|
2003-10-06 14:02:09 +00:00
|
|
|
return (n);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
bad:
|
2000-07-04 16:35:15 +00:00
|
|
|
m_freem(m);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (n)
|
|
|
|
m_freem(n);
|
2003-10-06 14:02:09 +00:00
|
|
|
return (NULL);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* make a mbuf with DNS-encoded string. no compression support.
|
|
|
|
*
|
|
|
|
* XXX names with less than 2 dots (like "foo" or "foo.section") will be
|
|
|
|
* treated as truncated name (two \0 at the end). this is a wild guess.
|
2007-07-05 16:23:49 +00:00
|
|
|
*
|
|
|
|
* old - return pascal string if non-zero
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2007-07-05 16:23:49 +00:00
|
|
|
ni6_nametodns(const char *name, int namelen, int old)
|
2000-07-04 16:35:15 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
char *cp, *ep;
|
|
|
|
const char *p, *q;
|
|
|
|
int i, len, nterm;
|
|
|
|
|
|
|
|
if (old)
|
|
|
|
len = namelen + 1;
|
|
|
|
else
|
|
|
|
len = MCLBYTES;
|
|
|
|
|
2013-03-15 12:50:29 +00:00
|
|
|
/* Because MAXHOSTNAMELEN is usually 256, we use cluster mbuf. */
|
|
|
|
if (len > MLEN)
|
|
|
|
m = m_getcl(M_NOWAIT, MT_DATA, 0);
|
|
|
|
else
|
|
|
|
m = m_get(M_NOWAIT, MT_DATA);
|
|
|
|
if (m == NULL)
|
2000-07-04 16:35:15 +00:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (old) {
|
|
|
|
m->m_len = len;
|
|
|
|
*mtod(m, char *) = namelen;
|
|
|
|
bcopy(name, mtod(m, char *) + 1, namelen);
|
|
|
|
return m;
|
|
|
|
} else {
|
|
|
|
m->m_len = 0;
|
|
|
|
cp = mtod(m, char *);
|
|
|
|
ep = mtod(m, char *) + M_TRAILINGSPACE(m);
|
|
|
|
|
|
|
|
/* if not certain about my name, return empty buffer */
|
|
|
|
if (namelen == 0)
|
|
|
|
return m;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* guess if it looks like shortened hostname, or FQDN.
|
|
|
|
* shortened hostname needs two trailing "\0".
|
|
|
|
*/
|
|
|
|
i = 0;
|
|
|
|
for (p = name; p < name + namelen; p++) {
|
|
|
|
if (*p && *p == '.')
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (i < 2)
|
|
|
|
nterm = 2;
|
|
|
|
else
|
|
|
|
nterm = 1;
|
|
|
|
|
|
|
|
p = name;
|
|
|
|
while (cp < ep && p < name + namelen) {
|
|
|
|
i = 0;
|
|
|
|
for (q = p; q < name + namelen && *q && *q != '.'; q++)
|
|
|
|
i++;
|
|
|
|
/* result does not fit into mbuf */
|
|
|
|
if (cp + i + 1 >= ep)
|
|
|
|
goto fail;
|
2001-06-24 14:59:34 +00:00
|
|
|
/*
|
|
|
|
* DNS label length restriction, RFC1035 page 8.
|
|
|
|
* "i == 0" case is included here to avoid returning
|
|
|
|
* 0-length label on "foo..bar".
|
|
|
|
*/
|
|
|
|
if (i <= 0 || i >= 64)
|
2000-07-04 16:35:15 +00:00
|
|
|
goto fail;
|
|
|
|
*cp++ = i;
|
|
|
|
bcopy(p, cp, i);
|
|
|
|
cp += i;
|
|
|
|
p = q;
|
|
|
|
if (p < name + namelen && *p == '.')
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
/* termination */
|
|
|
|
if (cp + nterm >= ep)
|
|
|
|
goto fail;
|
|
|
|
while (nterm-- > 0)
|
|
|
|
*cp++ = '\0';
|
|
|
|
m->m_len = cp - mtod(m, char *);
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("should not reach here");
|
2002-04-19 04:46:24 +00:00
|
|
|
/* NOTREACHED */
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
fail:
|
|
|
|
if (m)
|
|
|
|
m_freem(m);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if two DNS-encoded string matches. takes care of truncated
|
|
|
|
* form (with \0\0 at the end). no compression support.
|
2001-06-11 12:39:29 +00:00
|
|
|
* XXX upper/lowercase match (see RFC2065)
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
|
2000-07-04 16:35:15 +00:00
|
|
|
{
|
|
|
|
const char *a0, *b0;
|
|
|
|
int l;
|
|
|
|
|
|
|
|
/* simplest case - need validation? */
|
|
|
|
if (alen == blen && bcmp(a, b, alen) == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
a0 = a;
|
|
|
|
b0 = b;
|
|
|
|
|
|
|
|
/* termination is mandatory */
|
|
|
|
if (alen < 2 || blen < 2)
|
|
|
|
return 0;
|
|
|
|
if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
|
|
|
|
return 0;
|
|
|
|
alen--;
|
|
|
|
blen--;
|
|
|
|
|
|
|
|
while (a - a0 < alen && b - b0 < blen) {
|
|
|
|
if (a - a0 + 1 > alen || b - b0 + 1 > blen)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
|
|
|
|
return 0;
|
|
|
|
/* we don't support compression yet */
|
|
|
|
if (a[0] >= 64 || b[0] >= 64)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* truncated case */
|
|
|
|
if (a[0] == 0 && a - a0 == alen - 1)
|
|
|
|
return 1;
|
|
|
|
if (b[0] == 0 && b - b0 == blen - 1)
|
|
|
|
return 1;
|
|
|
|
if (a[0] == 0 || b[0] == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (a[0] != b[0])
|
|
|
|
return 0;
|
|
|
|
l = a[0];
|
|
|
|
if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
|
|
|
|
return 0;
|
|
|
|
if (bcmp(a + 1, b + 1, l) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
a += 1 + l;
|
|
|
|
b += 1 + l;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a - a0 == alen && b - b0 == blen)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* calculate the number of addresses to be returned in the node info reply.
|
|
|
|
*/
|
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
|
|
|
|
struct in6_addr *subj)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2001-06-11 12:39:29 +00:00
|
|
|
struct ifnet *ifp;
|
|
|
|
struct in6_ifaddr *ifa6;
|
|
|
|
struct ifaddr *ifa;
|
1999-11-22 02:45:11 +00:00
|
|
|
int addrs = 0, addrsofif, iffound = 0;
|
2001-06-11 12:39:29 +00:00
|
|
|
int niflags = ni6->ni_flags;
|
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
|
|
|
|
switch (ni6->ni_code) {
|
|
|
|
case ICMP6_NI_SUBJ_IPV6:
|
|
|
|
if (subj == NULL) /* must be impossible... */
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0);
|
2001-06-11 12:39:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* XXX: we only support IPv6 subject address for
|
|
|
|
* this Qtype.
|
|
|
|
*/
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2018-05-23 21:02:14 +00:00
|
|
|
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
|
1999-11-22 02:45:11 +00:00
|
|
|
addrsofif = 0;
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
1999-11-22 02:45:11 +00:00
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
|
|
continue;
|
|
|
|
ifa6 = (struct in6_ifaddr *)ifa;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
|
2005-08-09 12:24:11 +00:00
|
|
|
IN6_ARE_ADDR_EQUAL(subj, &ifa6->ia_addr.sin6_addr))
|
1999-11-22 02:45:11 +00:00
|
|
|
iffound = 1;
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* IPv4-mapped addresses can only be returned by a
|
|
|
|
* Node Information proxy, since they represent
|
|
|
|
* addresses of IPv4-only nodes, which perforce do
|
|
|
|
* not implement this protocol.
|
2001-06-11 12:39:29 +00:00
|
|
|
* [icmp-name-lookups-07, Section 5.4]
|
2000-07-04 16:35:15 +00:00
|
|
|
* So we don't support NI_NODEADDR_FLAG_COMPAT in
|
|
|
|
* this function at this moment.
|
|
|
|
*/
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/* What do we have to do about ::1? */
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
|
|
|
|
case IPV6_ADDR_SCOPE_LINKLOCAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
case IPV6_ADDR_SCOPE_SITELOCAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
case IPV6_ADDR_SCOPE_GLOBAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if anycast is okay.
|
2002-04-19 04:46:24 +00:00
|
|
|
* XXX: just experimental. not in the spec.
|
2001-06-11 12:39:29 +00:00
|
|
|
*/
|
|
|
|
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
|
|
|
|
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
|
|
|
|
continue; /* we need only unicast addresses */
|
|
|
|
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
addrsofif++; /* count the address */
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
if (iffound) {
|
|
|
|
*ifpp = ifp;
|
2003-10-06 14:02:09 +00:00
|
|
|
return (addrsofif);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
addrs += addrsofif;
|
|
|
|
}
|
|
|
|
|
2003-10-06 14:02:09 +00:00
|
|
|
return (addrs);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
|
|
|
|
struct ifnet *ifp0, int resid)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2011-12-24 18:11:54 +00:00
|
|
|
struct ifnet *ifp;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct in6_ifaddr *ifa6;
|
|
|
|
struct ifaddr *ifa;
|
|
|
|
struct ifnet *ifp_dep = NULL;
|
|
|
|
int copied = 0, allow_deprecated = 0;
|
1999-11-22 02:45:11 +00:00
|
|
|
u_char *cp = (u_char *)(nni6 + 1);
|
2001-06-11 12:39:29 +00:00
|
|
|
int niflags = ni6->ni_flags;
|
|
|
|
u_int32_t ltime;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0); /* needless to copy */
|
2003-10-07 17:46:18 +00:00
|
|
|
|
2018-05-23 21:02:14 +00:00
|
|
|
ifp = ifp0 ? ifp0 : CK_STAILQ_FIRST(&V_ifnet);
|
2001-06-11 12:39:29 +00:00
|
|
|
again:
|
2003-10-07 19:51:22 +00:00
|
|
|
|
2018-05-23 21:02:14 +00:00
|
|
|
for (; ifp; ifp = CK_STAILQ_NEXT(ifp, if_link)) {
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
1999-11-22 02:45:11 +00:00
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
|
|
continue;
|
|
|
|
ifa6 = (struct in6_ifaddr *)ifa;
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
|
|
|
|
allow_deprecated == 0) {
|
|
|
|
/*
|
|
|
|
* prefererred address should be put before
|
|
|
|
* deprecated addresses.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* record the interface for later search */
|
|
|
|
if (ifp_dep == NULL)
|
|
|
|
ifp_dep = ifp;
|
|
|
|
|
|
|
|
continue;
|
2003-10-07 17:46:18 +00:00
|
|
|
} else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
|
|
|
|
allow_deprecated != 0)
|
2001-06-11 12:39:29 +00:00
|
|
|
continue; /* we now collect deprecated addrs */
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/* What do we have to do about ::1? */
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
|
|
|
|
case IPV6_ADDR_SCOPE_LINKLOCAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
case IPV6_ADDR_SCOPE_SITELOCAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
case IPV6_ADDR_SCOPE_GLOBAL:
|
|
|
|
if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2001-06-11 12:39:29 +00:00
|
|
|
default:
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
/*
|
|
|
|
* check if anycast is okay.
|
2003-10-07 17:46:18 +00:00
|
|
|
* XXX: just experimental. not in the spec.
|
2001-06-11 12:39:29 +00:00
|
|
|
*/
|
|
|
|
if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
|
|
|
|
(niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
|
|
|
|
continue;
|
|
|
|
if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
/* now we can copy the address */
|
|
|
|
if (resid < sizeof(struct in6_addr) +
|
|
|
|
sizeof(u_int32_t)) {
|
|
|
|
/*
|
|
|
|
* We give up much more copy.
|
|
|
|
* Set the truncate flag and return.
|
|
|
|
*/
|
2003-10-07 17:46:18 +00:00
|
|
|
nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
|
2003-10-06 14:02:09 +00:00
|
|
|
return (copied);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the TTL of the address.
|
|
|
|
* The TTL value should be one of the following
|
|
|
|
* according to the specification:
|
|
|
|
*
|
|
|
|
* 1. The remaining lifetime of a DHCP lease on the
|
|
|
|
* address, or
|
|
|
|
* 2. The remaining Valid Lifetime of a prefix from
|
|
|
|
* which the address was derived through Stateless
|
|
|
|
* Autoconfiguration.
|
|
|
|
*
|
|
|
|
* Note that we currently do not support stateful
|
|
|
|
* address configuration by DHCPv6, so the former
|
|
|
|
* case can't happen.
|
|
|
|
*/
|
|
|
|
if (ifa6->ia6_lifetime.ia6t_expire == 0)
|
|
|
|
ltime = ND6_INFINITE_LIFETIME;
|
|
|
|
else {
|
|
|
|
if (ifa6->ia6_lifetime.ia6t_expire >
|
2013-08-05 20:13:02 +00:00
|
|
|
time_uptime)
|
|
|
|
ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_uptime);
|
2001-06-11 12:39:29 +00:00
|
|
|
else
|
|
|
|
ltime = 0;
|
|
|
|
}
|
2003-10-07 17:46:18 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
bcopy(<ime, cp, sizeof(u_int32_t));
|
|
|
|
cp += sizeof(u_int32_t);
|
|
|
|
|
|
|
|
/* copy the address itself */
|
|
|
|
bcopy(&ifa6->ia_addr.sin6_addr, cp,
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(struct in6_addr));
|
2003-10-21 20:05:32 +00:00
|
|
|
in6_clearscope((struct in6_addr *)cp); /* XXX */
|
2001-06-11 12:39:29 +00:00
|
|
|
cp += sizeof(struct in6_addr);
|
2003-10-07 17:46:18 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
|
2003-10-07 17:46:18 +00:00
|
|
|
copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
if (ifp0) /* we need search only on the specified IF */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
if (allow_deprecated == 0 && ifp_dep != NULL) {
|
|
|
|
ifp = ifp_dep;
|
|
|
|
allow_deprecated = 1;
|
|
|
|
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
|
2003-10-06 14:02:09 +00:00
|
|
|
return (copied);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 22:45:04 +00:00
|
|
|
static bool
|
|
|
|
icmp6_rip6_match(const struct inpcb *inp, void *v)
|
|
|
|
{
|
|
|
|
struct ip6_hdr *ip6 = v;
|
|
|
|
|
|
|
|
if ((inp->inp_vflag & INP_IPV6) == 0)
|
|
|
|
return (false);
|
|
|
|
if (inp->inp_ip_p != IPPROTO_ICMPV6)
|
|
|
|
return (false);
|
|
|
|
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
|
|
|
|
!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ip6->ip6_dst))
|
|
|
|
return (false);
|
|
|
|
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
|
|
|
|
!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ip6->ip6_src))
|
|
|
|
return (false);
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* XXX almost dup'ed code with rip6_input.
|
|
|
|
*/
|
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_rip6_input(struct mbuf **mp, int off)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2021-12-02 22:45:04 +00:00
|
|
|
struct mbuf *n, *m = *mp;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
|
2021-12-02 22:45:04 +00:00
|
|
|
struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo,
|
|
|
|
INPLOOKUP_RLOCKPCB, icmp6_rip6_match, ip6);
|
2019-08-02 07:41:36 +00:00
|
|
|
struct inpcb *inp;
|
2003-10-21 20:05:32 +00:00
|
|
|
struct sockaddr_in6 fromsa;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct icmp6_hdr *icmp6;
|
|
|
|
struct mbuf *opts = NULL;
|
2021-12-02 22:45:04 +00:00
|
|
|
int delivered = 0;
|
2019-11-07 20:43:12 +00:00
|
|
|
|
2019-11-15 21:40:40 +00:00
|
|
|
/* This is assumed to be safe; icmp6_input() does a pullup. */
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
|
|
|
|
|
2005-07-25 12:31:43 +00:00
|
|
|
/*
|
|
|
|
* XXX: the address may have embedded scope zone ID, which should be
|
|
|
|
* hidden from applications.
|
|
|
|
*/
|
2003-10-21 20:05:32 +00:00
|
|
|
bzero(&fromsa, sizeof(fromsa));
|
|
|
|
fromsa.sin6_family = AF_INET6;
|
2005-07-25 12:31:43 +00:00
|
|
|
fromsa.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
fromsa.sin6_addr = ip6->ip6_src;
|
|
|
|
if (sa6_recoverscope(&fromsa)) {
|
|
|
|
m_freem(m);
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
2005-07-25 12:31:43 +00:00
|
|
|
return (IPPROTO_DONE);
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2021-12-02 22:45:04 +00:00
|
|
|
while ((inp = inp_next(&inpi)) != NULL) {
|
2008-07-29 18:09:46 +00:00
|
|
|
if (ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
|
2021-12-02 22:45:04 +00:00
|
|
|
inp->in6p_icmp6filt))
|
2008-07-27 20:30:34 +00:00
|
|
|
continue;
|
2021-12-02 22:45:04 +00:00
|
|
|
/*
|
|
|
|
* Recent network drivers tend to allocate a single
|
|
|
|
* mbuf cluster, rather than to make a couple of
|
|
|
|
* mbufs without clusters. Also, since the IPv6 code
|
|
|
|
* path tries to avoid m_pullup(), it is highly
|
|
|
|
* probable that we still have an mbuf cluster here
|
|
|
|
* even though the necessary length can be stored in an
|
|
|
|
* mbuf's internal buffer.
|
|
|
|
* Meanwhile, the default size of the receive socket
|
|
|
|
* buffer for raw sockets is not so large. This means
|
|
|
|
* the possibility of packet loss is relatively higher
|
|
|
|
* than before. To avoid this scenario, we copy the
|
|
|
|
* received data to a separate mbuf that does not use
|
|
|
|
* a cluster, if possible.
|
|
|
|
* XXX: it is better to copy the data after stripping
|
|
|
|
* intermediate headers.
|
|
|
|
*/
|
2003-10-31 16:21:26 +00:00
|
|
|
if ((m->m_flags & M_EXT) && m->m_next == NULL &&
|
|
|
|
m->m_len <= MHLEN) {
|
2013-03-15 12:50:29 +00:00
|
|
|
n = m_get(M_NOWAIT, m->m_type);
|
2003-10-31 16:21:26 +00:00
|
|
|
if (n != NULL) {
|
2005-04-14 11:41:23 +00:00
|
|
|
if (m_dup_pkthdr(n, m, M_NOWAIT)) {
|
|
|
|
bcopy(m->m_data, n->m_data, m->m_len);
|
|
|
|
n->m_len = m->m_len;
|
|
|
|
} else {
|
2021-12-02 22:45:04 +00:00
|
|
|
m_free(n);
|
2005-04-14 11:41:23 +00:00
|
|
|
n = NULL;
|
|
|
|
}
|
2003-10-31 16:21:26 +00:00
|
|
|
}
|
2021-12-02 22:45:04 +00:00
|
|
|
} else
|
|
|
|
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
|
|
|
|
if (n == NULL)
|
|
|
|
continue;
|
|
|
|
if (inp->inp_flags & INP_CONTROLOPTS)
|
|
|
|
ip6_savecontrol(inp, n, &opts);
|
|
|
|
/* strip intermediate headers */
|
|
|
|
m_adj(n, off);
|
|
|
|
SOCKBUF_LOCK(&inp->inp_socket->so_rcv);
|
|
|
|
if (sbappendaddr_locked(&inp->inp_socket->so_rcv,
|
|
|
|
(struct sockaddr *)&fromsa, n, opts) == 0) {
|
|
|
|
soroverflow_locked(inp->inp_socket);
|
|
|
|
m_freem(n);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (opts)
|
|
|
|
m_freem(opts);
|
2021-12-02 22:45:04 +00:00
|
|
|
} else {
|
|
|
|
sorwakeup_locked(inp->inp_socket);
|
|
|
|
delivered++;
|
|
|
|
}
|
|
|
|
opts = NULL;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2021-12-02 22:45:04 +00:00
|
|
|
m_freem(m);
|
2019-11-12 15:46:28 +00:00
|
|
|
*mp = NULL;
|
2021-12-02 22:45:04 +00:00
|
|
|
if (delivered == 0)
|
|
|
|
IP6STAT_DEC(ip6s_delivered);
|
2019-11-12 15:46:28 +00:00
|
|
|
return (IPPROTO_DONE);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reflect the ip6 packet back to the source.
|
2000-07-04 16:35:15 +00:00
|
|
|
* OFF points to the icmp6 header, counted from the top of the mbuf.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2019-12-03 14:46:38 +00:00
|
|
|
static void
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_reflect(struct mbuf *m, size_t off)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2016-01-10 11:59:55 +00:00
|
|
|
struct in6_addr src6, *srcp;
|
2000-07-04 16:35:15 +00:00
|
|
|
struct ip6_hdr *ip6;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct icmp6_hdr *icmp6;
|
2009-06-23 20:19:09 +00:00
|
|
|
struct in6_ifaddr *ia = NULL;
|
2014-11-08 19:38:34 +00:00
|
|
|
struct ifnet *outif = NULL;
|
2000-07-04 16:35:15 +00:00
|
|
|
int plen;
|
2016-01-10 11:59:55 +00:00
|
|
|
int type, code, hlim;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/* too short to reflect */
|
|
|
|
if (off < sizeof(struct ip6_hdr)) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG,
|
|
|
|
"sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
|
|
|
|
(u_long)off, (u_long)sizeof(struct ip6_hdr),
|
|
|
|
__FILE__, __LINE__));
|
2000-07-04 16:35:15 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* If there are extra headers between IPv6 and ICMPv6, strip
|
|
|
|
* off that header first.
|
|
|
|
*/
|
2000-07-04 16:35:15 +00:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
|
|
|
|
panic("assumption failed in icmp6_reflect");
|
|
|
|
#endif
|
|
|
|
if (off > sizeof(struct ip6_hdr)) {
|
|
|
|
size_t l;
|
|
|
|
struct ip6_hdr nip6;
|
|
|
|
|
|
|
|
l = off - sizeof(struct ip6_hdr);
|
|
|
|
m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
|
|
|
|
m_adj(m, l);
|
|
|
|
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
|
|
|
|
if (m->m_len < l) {
|
|
|
|
if ((m = m_pullup(m, l)) == NULL)
|
|
|
|
return;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
|
|
|
|
} else /* off == sizeof(struct ip6_hdr) */ {
|
|
|
|
size_t l;
|
|
|
|
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
|
|
|
|
if (m->m_len < l) {
|
|
|
|
if ((m = m_pullup(m, l)) == NULL)
|
|
|
|
return;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
|
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
1999-11-22 02:45:11 +00:00
|
|
|
icmp6 = (struct icmp6_hdr *)(ip6 + 1);
|
|
|
|
type = icmp6->icmp6_type; /* keep type for statistics */
|
|
|
|
code = icmp6->icmp6_code; /* ditto. */
|
2016-01-10 11:59:55 +00:00
|
|
|
hlim = 0;
|
|
|
|
srcp = NULL;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
2003-10-07 17:46:18 +00:00
|
|
|
* If the incoming packet was addressed directly to us (i.e. unicast),
|
1999-11-22 02:45:11 +00:00
|
|
|
* use dst as the src for the reply.
|
2003-10-07 17:46:18 +00:00
|
|
|
* The IN6_IFF_NOTREADY case should be VERY rare, but is possible
|
2000-07-04 16:35:15 +00:00
|
|
|
* (for example) when we encounter an error while forwarding procedure
|
|
|
|
* destined to a duplicated address of ours.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2014-11-08 19:38:34 +00:00
|
|
|
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
2021-02-15 21:59:21 +00:00
|
|
|
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false);
|
2014-11-08 19:38:34 +00:00
|
|
|
if (ia != NULL && !(ia->ia6_flags &
|
2016-01-10 11:59:55 +00:00
|
|
|
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
|
|
|
|
src6 = ia->ia_addr.sin6_addr;
|
|
|
|
srcp = &src6;
|
|
|
|
|
|
|
|
if (m->m_pkthdr.rcvif != NULL) {
|
|
|
|
/* XXX: This may not be the outgoing interface */
|
|
|
|
hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
|
|
|
|
} else
|
|
|
|
hlim = V_ip6_defhlim;
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2009-06-23 22:08:55 +00:00
|
|
|
if (srcp == NULL) {
|
2016-01-10 13:40:29 +00:00
|
|
|
int error;
|
|
|
|
struct in6_addr dst6;
|
|
|
|
uint32_t scopeid;
|
2001-06-11 12:39:29 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2000-07-04 16:35:15 +00:00
|
|
|
* This case matches to multicasts, our anycast, or unicasts
|
2002-04-19 04:46:24 +00:00
|
|
|
* that we do not own. Select a source address based on the
|
2001-06-11 12:39:29 +00:00
|
|
|
* source address of the erroneous packet.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2016-09-29 19:57:37 +00:00
|
|
|
in6_splitscope(&ip6->ip6_src, &dst6, &scopeid);
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
error = in6_selectsrc_addr(M_GETFIB(m), &dst6,
|
2016-01-10 13:40:29 +00:00
|
|
|
scopeid, NULL, &src6, &hlim);
|
2005-07-25 12:31:43 +00:00
|
|
|
|
2016-01-10 13:40:29 +00:00
|
|
|
if (error) {
|
2006-12-12 12:17:58 +00:00
|
|
|
char ip6buf[INET6_ADDRSTRLEN];
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG,
|
|
|
|
"icmp6_reflect: source can't be determined: "
|
|
|
|
"dst=%s, error=%d\n",
|
2016-01-10 13:40:29 +00:00
|
|
|
ip6_sprintf(ip6buf, &ip6->ip6_dst), error));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
2016-01-10 11:59:55 +00:00
|
|
|
srcp = &src6;
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2014-11-08 19:38:34 +00:00
|
|
|
/*
|
|
|
|
* ip6_input() drops a packet if its src is multicast.
|
|
|
|
* So, the src is never multicast.
|
|
|
|
*/
|
|
|
|
ip6->ip6_dst = ip6->ip6_src;
|
2009-06-23 22:08:55 +00:00
|
|
|
ip6->ip6_src = *srcp;
|
1999-11-22 02:45:11 +00:00
|
|
|
ip6->ip6_flow = 0;
|
2000-07-04 16:35:15 +00:00
|
|
|
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
|
|
|
|
ip6->ip6_vfc |= IPV6_VERSION;
|
1999-11-22 02:45:11 +00:00
|
|
|
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
2016-01-10 13:40:29 +00:00
|
|
|
ip6->ip6_hlim = hlim;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
icmp6->icmp6_cksum = 0;
|
|
|
|
icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
|
2003-10-07 17:46:18 +00:00
|
|
|
sizeof(struct ip6_hdr), plen);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
2001-06-11 12:39:29 +00:00
|
|
|
* XXX option handling
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
m->m_flags &= ~(M_BCAST|M_MCAST);
|
2018-04-23 12:20:07 +00:00
|
|
|
m->m_pkthdr.rcvif = NULL;
|
2002-10-16 01:54:46 +00:00
|
|
|
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (outif)
|
|
|
|
icmp6_ifoutstat_inc(outif, type, code);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
bad:
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6,
|
|
|
|
struct in6_addr *tgt6)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
static char buf[1024];
|
2006-12-12 12:17:58 +00:00
|
|
|
char ip6bufs[INET6_ADDRSTRLEN];
|
|
|
|
char ip6bufd[INET6_ADDRSTRLEN];
|
|
|
|
char ip6buft[INET6_ADDRSTRLEN];
|
1999-11-22 02:45:11 +00:00
|
|
|
snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
|
2006-12-12 12:17:58 +00:00
|
|
|
ip6_sprintf(ip6bufs, src6), ip6_sprintf(ip6bufd, dst6),
|
|
|
|
ip6_sprintf(ip6buft, tgt6));
|
1999-11-22 02:45:11 +00:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_redirect_input(struct mbuf *m, int off)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2007-07-01 11:41:27 +00:00
|
|
|
struct ifnet *ifp;
|
2019-11-07 18:29:51 +00:00
|
|
|
struct ip6_hdr *ip6;
|
2000-07-04 16:35:15 +00:00
|
|
|
struct nd_redirect *nd_rd;
|
2019-11-15 21:40:40 +00:00
|
|
|
struct in6_addr src6, redtgt6, reddst6;
|
1999-11-22 02:45:11 +00:00
|
|
|
union nd_opts ndopts;
|
2006-12-12 12:17:58 +00:00
|
|
|
char ip6buf[INET6_ADDRSTRLEN];
|
2019-11-07 18:29:51 +00:00
|
|
|
char *lladdr;
|
|
|
|
int icmp6len, is_onlink, is_router, lladdrlen;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2011-11-07 14:22:18 +00:00
|
|
|
M_ASSERTPKTHDR(m);
|
|
|
|
KASSERT(m->m_pkthdr.rcvif != NULL, ("%s: no rcvif", __func__));
|
2007-07-01 11:41:27 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/* XXX if we are router, we don't update route by icmp6 redirect */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_ip6_forwarding)
|
2000-07-04 16:35:15 +00:00
|
|
|
goto freeit;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (!V_icmp6_rediraccept)
|
2000-07-04 16:35:15 +00:00
|
|
|
goto freeit;
|
2017-12-15 12:37:32 +00:00
|
|
|
|
|
|
|
/* RFC 6980: Nodes MUST silently ignore fragments */
|
|
|
|
if(m->m_flags & M_FRAGMENTED)
|
|
|
|
goto freeit;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
icmp6len = ntohs(ip6->ip6_plen);
|
2019-12-01 00:22:04 +00:00
|
|
|
if (m->m_len < off + icmp6len) {
|
|
|
|
m = m_pullup(m, off + icmp6len);
|
|
|
|
if (m == NULL) {
|
|
|
|
IP6STAT_INC(ip6s_exthdrtoolong);
|
|
|
|
return;
|
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
2019-11-15 21:40:40 +00:00
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
|
2019-11-07 18:29:51 +00:00
|
|
|
|
|
|
|
ifp = m->m_pkthdr.rcvif;
|
2000-07-04 16:35:15 +00:00
|
|
|
redtgt6 = nd_rd->nd_rd_target;
|
|
|
|
reddst6 = nd_rd->nd_rd_dst;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
if (in6_setscope(&redtgt6, ifp, NULL) ||
|
|
|
|
in6_setscope(&reddst6, ifp, NULL)) {
|
2005-07-25 12:31:43 +00:00
|
|
|
goto freeit;
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/* validation */
|
2019-11-07 18:29:51 +00:00
|
|
|
src6 = ip6->ip6_src;
|
1999-11-22 02:45:11 +00:00
|
|
|
if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect sent from %s rejected; "
|
|
|
|
"must be from linklocal\n",
|
2006-12-12 12:17:58 +00:00
|
|
|
ip6_sprintf(ip6buf, &src6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2020-10-19 17:07:19 +00:00
|
|
|
if (__predict_false(ip6->ip6_hlim != 255)) {
|
|
|
|
ICMP6STAT_INC(icp6s_invlhlim);
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect sent from %s rejected; "
|
|
|
|
"hlim=%d (must be 255)\n",
|
2006-12-12 12:17:58 +00:00
|
|
|
ip6_sprintf(ip6buf, &src6), ip6->ip6_hlim));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
{
|
|
|
|
/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
|
2020-07-02 21:04:08 +00:00
|
|
|
struct nhop_object *nh;
|
2015-12-09 11:14:27 +00:00
|
|
|
struct in6_addr kdst;
|
|
|
|
uint32_t scopeid;
|
|
|
|
|
|
|
|
in6_splitscope(&reddst6, &kdst, &scopeid);
|
2020-07-02 21:04:08 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
nh = fib6_lookup(ifp->if_fib, &kdst, scopeid, 0, 0);
|
2020-07-03 08:06:26 +00:00
|
|
|
if (nh != NULL) {
|
2020-07-02 21:04:08 +00:00
|
|
|
struct in6_addr nh_addr;
|
|
|
|
nh_addr = ifatoia6(nh->nh_ifa)->ia_addr.sin6_addr;
|
|
|
|
if ((nh->nh_flags & NHF_GATEWAY) == 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2000-09-15 17:21:35 +00:00
|
|
|
"ICMP6 redirect rejected; no route "
|
|
|
|
"with inet6 gateway found for redirect dst: %s\n",
|
2001-06-11 12:39:29 +00:00
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
|
|
|
goto bad;
|
2000-09-15 17:21:35 +00:00
|
|
|
}
|
|
|
|
|
2018-02-09 00:13:05 +00:00
|
|
|
/*
|
2020-07-02 21:04:08 +00:00
|
|
|
* Embed scope zone id into next hop address.
|
2018-02-09 00:13:05 +00:00
|
|
|
*/
|
2020-07-02 21:04:08 +00:00
|
|
|
nh_addr = nh->gw6_sa.sin6_addr;
|
2018-02-09 00:13:05 +00:00
|
|
|
|
2020-07-02 21:04:08 +00:00
|
|
|
if (IN6_ARE_ADDR_EQUAL(&src6, &nh_addr) == 0) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect rejected; "
|
|
|
|
"not equal to gw-for-src=%s (must be same): "
|
|
|
|
"%s\n",
|
2020-07-02 21:04:08 +00:00
|
|
|
ip6_sprintf(ip6buf, &nh_addr),
|
2003-10-07 17:46:18 +00:00
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect rejected; "
|
|
|
|
"no route found for redirect dst: %s\n",
|
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect rejected; "
|
|
|
|
"redirect dst must be unicast: %s\n",
|
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is_router = is_onlink = 0;
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
|
|
|
|
is_router = 1; /* router case */
|
|
|
|
if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
|
|
|
|
is_onlink = 1; /* on-link destination case */
|
|
|
|
if (!is_router && !is_onlink) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_ERR,
|
2003-10-07 17:46:18 +00:00
|
|
|
"ICMP6 redirect rejected; "
|
|
|
|
"neither router case nor onlink case: %s\n",
|
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
icmp6len -= sizeof(*nd_rd);
|
|
|
|
nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
|
|
|
|
if (nd6_options(&ndopts) < 0) {
|
2011-11-07 14:22:18 +00:00
|
|
|
nd6log((LOG_INFO, "%s: invalid ND option, rejected: %s\n",
|
|
|
|
__func__, icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
/* nd6_options have incremented stats */
|
2000-07-04 16:35:15 +00:00
|
|
|
goto freeit;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 18:29:51 +00:00
|
|
|
lladdr = NULL;
|
|
|
|
lladdrlen = 0;
|
1999-11-22 02:45:11 +00:00
|
|
|
if (ndopts.nd_opts_tgt_lladdr) {
|
|
|
|
lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
|
|
|
|
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
|
2011-11-07 14:22:18 +00:00
|
|
|
nd6log((LOG_INFO, "%s: lladdrlen mismatch for %s "
|
2003-10-07 17:46:18 +00:00
|
|
|
"(if %d, icmp6 packet %d): %s\n",
|
2011-11-07 14:22:18 +00:00
|
|
|
__func__, ip6_sprintf(ip6buf, &redtgt6),
|
2006-12-12 12:17:58 +00:00
|
|
|
ifp->if_addrlen, lladdrlen - 2,
|
2003-10-07 17:46:18 +00:00
|
|
|
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
2001-06-11 12:39:29 +00:00
|
|
|
goto bad;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2015-07-03 09:53:56 +00:00
|
|
|
/* Validation passed. */
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/* RFC 2461 8.3 */
|
|
|
|
nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
|
2003-10-07 17:46:18 +00:00
|
|
|
is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
Fix the handling of IPv6 On-Link Redirects.
On receipt of a redirect message, install an interface route for the
redirected destination. On removal of the corresponding Neighbor Cache
entry, remove the interface route.
This requires changes in rtredirect_fib() to cope with an AF_LINK
address for the gateway and with the absence of RTF_GATEWAY.
This fixes the "Redirected On-Link" test cases in the Tahi IPv6 Ready Logo
Phase 2 test suite.
Unrelated to the above, fix a recursion on the radix node head lock
triggered by the Tahi Redirected to Alternate Router test cases.
When I first wrote this patch in October 2012, all Section 2
(Neighbor Discovery) test cases passed on 10-CURRENT, 9-STABLE,
and 8-STABLE. cem@ recently rebased the 10.x patch onto head and reported
that it passes Tahi. (Thanks!)
These other test cases also passed in 2012:
* the RTF_MODIFIED case, with IPv4 and IPv6 (using a
RTF_HOST|RTF_GATEWAY route for the destination)
* the redirected-to-self case, with IPv4 and IPv6
* a valid IPv4 redirect
All testing in 2012 was done with WITNESS and INVARIANTS.
Tested by: EMC / Isilon Storage Division via Conrad Meyer (cem) in 2015,
Mark Kelley <mark_kelley@dell.com> in 2012,
TC Telkamp <terence_telkamp@dell.com> in 2012
PR: 152791
Reviewed by: melifaro (current rev), bz (earlier rev)
Approved by: kib (mentor)
MFC after: 1 month
Relnotes: yes
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D3602
2015-09-14 19:17:25 +00:00
|
|
|
/*
|
|
|
|
* Install a gateway route in the better-router case or an interface
|
|
|
|
* route in the on-link-destination case.
|
|
|
|
*/
|
|
|
|
{
|
1999-11-22 02:45:11 +00:00
|
|
|
struct sockaddr_in6 sdst;
|
|
|
|
struct sockaddr_in6 sgw;
|
|
|
|
struct sockaddr_in6 ssrc;
|
Fix the handling of IPv6 On-Link Redirects.
On receipt of a redirect message, install an interface route for the
redirected destination. On removal of the corresponding Neighbor Cache
entry, remove the interface route.
This requires changes in rtredirect_fib() to cope with an AF_LINK
address for the gateway and with the absence of RTF_GATEWAY.
This fixes the "Redirected On-Link" test cases in the Tahi IPv6 Ready Logo
Phase 2 test suite.
Unrelated to the above, fix a recursion on the radix node head lock
triggered by the Tahi Redirected to Alternate Router test cases.
When I first wrote this patch in October 2012, all Section 2
(Neighbor Discovery) test cases passed on 10-CURRENT, 9-STABLE,
and 8-STABLE. cem@ recently rebased the 10.x patch onto head and reported
that it passes Tahi. (Thanks!)
These other test cases also passed in 2012:
* the RTF_MODIFIED case, with IPv4 and IPv6 (using a
RTF_HOST|RTF_GATEWAY route for the destination)
* the redirected-to-self case, with IPv4 and IPv6
* a valid IPv4 redirect
All testing in 2012 was done with WITNESS and INVARIANTS.
Tested by: EMC / Isilon Storage Division via Conrad Meyer (cem) in 2015,
Mark Kelley <mark_kelley@dell.com> in 2012,
TC Telkamp <terence_telkamp@dell.com> in 2012
PR: 152791
Reviewed by: melifaro (current rev), bz (earlier rev)
Approved by: kib (mentor)
MFC after: 1 month
Relnotes: yes
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D3602
2015-09-14 19:17:25 +00:00
|
|
|
struct sockaddr *gw;
|
|
|
|
int rt_flags;
|
2012-02-03 13:08:44 +00:00
|
|
|
u_int fibnum;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
bzero(&sdst, sizeof(sdst));
|
|
|
|
bzero(&ssrc, sizeof(ssrc));
|
Fix the handling of IPv6 On-Link Redirects.
On receipt of a redirect message, install an interface route for the
redirected destination. On removal of the corresponding Neighbor Cache
entry, remove the interface route.
This requires changes in rtredirect_fib() to cope with an AF_LINK
address for the gateway and with the absence of RTF_GATEWAY.
This fixes the "Redirected On-Link" test cases in the Tahi IPv6 Ready Logo
Phase 2 test suite.
Unrelated to the above, fix a recursion on the radix node head lock
triggered by the Tahi Redirected to Alternate Router test cases.
When I first wrote this patch in October 2012, all Section 2
(Neighbor Discovery) test cases passed on 10-CURRENT, 9-STABLE,
and 8-STABLE. cem@ recently rebased the 10.x patch onto head and reported
that it passes Tahi. (Thanks!)
These other test cases also passed in 2012:
* the RTF_MODIFIED case, with IPv4 and IPv6 (using a
RTF_HOST|RTF_GATEWAY route for the destination)
* the redirected-to-self case, with IPv4 and IPv6
* a valid IPv4 redirect
All testing in 2012 was done with WITNESS and INVARIANTS.
Tested by: EMC / Isilon Storage Division via Conrad Meyer (cem) in 2015,
Mark Kelley <mark_kelley@dell.com> in 2012,
TC Telkamp <terence_telkamp@dell.com> in 2012
PR: 152791
Reviewed by: melifaro (current rev), bz (earlier rev)
Approved by: kib (mentor)
MFC after: 1 month
Relnotes: yes
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D3602
2015-09-14 19:17:25 +00:00
|
|
|
sdst.sin6_family = ssrc.sin6_family = AF_INET6;
|
|
|
|
sdst.sin6_len = ssrc.sin6_len = sizeof(struct sockaddr_in6);
|
1999-11-22 02:45:11 +00:00
|
|
|
bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
|
|
|
|
bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
|
2020-01-22 13:53:18 +00:00
|
|
|
rt_flags = 0;
|
Fix the handling of IPv6 On-Link Redirects.
On receipt of a redirect message, install an interface route for the
redirected destination. On removal of the corresponding Neighbor Cache
entry, remove the interface route.
This requires changes in rtredirect_fib() to cope with an AF_LINK
address for the gateway and with the absence of RTF_GATEWAY.
This fixes the "Redirected On-Link" test cases in the Tahi IPv6 Ready Logo
Phase 2 test suite.
Unrelated to the above, fix a recursion on the radix node head lock
triggered by the Tahi Redirected to Alternate Router test cases.
When I first wrote this patch in October 2012, all Section 2
(Neighbor Discovery) test cases passed on 10-CURRENT, 9-STABLE,
and 8-STABLE. cem@ recently rebased the 10.x patch onto head and reported
that it passes Tahi. (Thanks!)
These other test cases also passed in 2012:
* the RTF_MODIFIED case, with IPv4 and IPv6 (using a
RTF_HOST|RTF_GATEWAY route for the destination)
* the redirected-to-self case, with IPv4 and IPv6
* a valid IPv4 redirect
All testing in 2012 was done with WITNESS and INVARIANTS.
Tested by: EMC / Isilon Storage Division via Conrad Meyer (cem) in 2015,
Mark Kelley <mark_kelley@dell.com> in 2012,
TC Telkamp <terence_telkamp@dell.com> in 2012
PR: 152791
Reviewed by: melifaro (current rev), bz (earlier rev)
Approved by: kib (mentor)
MFC after: 1 month
Relnotes: yes
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D3602
2015-09-14 19:17:25 +00:00
|
|
|
if (is_router) {
|
|
|
|
bzero(&sgw, sizeof(sgw));
|
|
|
|
sgw.sin6_family = AF_INET6;
|
|
|
|
sgw.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
bcopy(&redtgt6, &sgw.sin6_addr,
|
|
|
|
sizeof(struct in6_addr));
|
|
|
|
gw = (struct sockaddr *)&sgw;
|
|
|
|
rt_flags |= RTF_GATEWAY;
|
|
|
|
} else
|
|
|
|
gw = ifp->if_addr->ifa_addr;
|
2012-02-03 13:08:44 +00:00
|
|
|
for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
|
2020-01-22 13:53:18 +00:00
|
|
|
rib_add_redirect(fibnum, (struct sockaddr *)&sdst, gw,
|
|
|
|
(struct sockaddr *)&ssrc, ifp, rt_flags,
|
|
|
|
V_icmp6_redirtimeout);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
freeit:
|
|
|
|
m_freem(m);
|
2001-06-11 12:39:29 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
bad:
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_badredirect);
|
2001-06-11 12:39:29 +00:00
|
|
|
m_freem(m);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-14 23:06:25 +00:00
|
|
|
icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct ifnet *ifp; /* my outgoing interface */
|
|
|
|
struct in6_addr *ifp_ll6;
|
|
|
|
struct in6_addr *router_ll6;
|
|
|
|
struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
|
|
|
|
struct mbuf *m = NULL; /* newly allocated one */
|
2010-08-19 11:31:03 +00:00
|
|
|
struct m_tag *mtag;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct ip6_hdr *ip6; /* m as struct ip6_hdr */
|
|
|
|
struct nd_redirect *nd_rd;
|
2008-12-16 02:06:26 +00:00
|
|
|
struct llentry *ln = NULL;
|
1999-11-22 02:45:11 +00:00
|
|
|
size_t maxlen;
|
|
|
|
u_char *p;
|
|
|
|
struct ifnet *outif = NULL;
|
2000-07-04 16:35:15 +00:00
|
|
|
struct sockaddr_in6 src_sa;
|
|
|
|
|
2013-06-19 15:59:21 +00:00
|
|
|
icmp6_errcount(ND_REDIRECT, 0);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/* if we are not router, we don't send icmp6 redirect */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (!V_ip6_forwarding)
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* sanity check */
|
2020-04-14 23:06:25 +00:00
|
|
|
if (!m0 || !nh || !(NH_IS_VALID(nh)) || !(ifp = nh->nh_ifp))
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Address check:
|
|
|
|
* the source address must identify a neighbor, and
|
|
|
|
* the destination address must not be a multicast address
|
|
|
|
* [RFC 2461, sec 8.2]
|
|
|
|
*/
|
|
|
|
sip6 = mtod(m0, struct ip6_hdr *);
|
2000-07-04 16:35:15 +00:00
|
|
|
bzero(&src_sa, sizeof(src_sa));
|
|
|
|
src_sa.sin6_family = AF_INET6;
|
|
|
|
src_sa.sin6_len = sizeof(src_sa);
|
|
|
|
src_sa.sin6_addr = sip6->ip6_src;
|
|
|
|
if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
|
|
|
if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
|
|
|
|
goto fail; /* what should we do here? */
|
|
|
|
|
|
|
|
/* rate limit */
|
|
|
|
if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since we are going to append up to 1280 bytes (= IPV6_MMTU),
|
|
|
|
* we almost always ask for an mbuf cluster for simplicity.
|
|
|
|
* (MHLEN < IPV6_MMTU is almost always true)
|
|
|
|
*/
|
2000-07-04 16:35:15 +00:00
|
|
|
#if IPV6_MMTU >= MCLBYTES
|
|
|
|
# error assumption failed about IPV6_MMTU and MCLBYTES
|
|
|
|
#endif
|
2013-03-15 12:50:29 +00:00
|
|
|
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
|
|
|
if (m == NULL)
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
2020-04-14 23:06:25 +00:00
|
|
|
M_SETFIB(m, M_GETFIB(m0));
|
2001-06-11 12:39:29 +00:00
|
|
|
maxlen = M_TRAILINGSPACE(m);
|
1999-11-22 02:45:11 +00:00
|
|
|
maxlen = min(IPV6_MMTU, maxlen);
|
|
|
|
/* just for safety */
|
2000-07-04 16:35:15 +00:00
|
|
|
if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
|
|
|
|
((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
/* get ip6 linklocal address for ifp(my outgoing interface). */
|
2000-07-04 16:35:15 +00:00
|
|
|
struct in6_ifaddr *ia;
|
|
|
|
if ((ia = in6ifa_ifpforlinklocal(ifp,
|
|
|
|
IN6_IFF_NOTREADY|
|
|
|
|
IN6_IFF_ANYCAST)) == NULL)
|
1999-11-22 02:45:11 +00:00
|
|
|
goto fail;
|
|
|
|
ifp_ll6 = &ia->ia_addr.sin6_addr;
|
2009-06-23 20:19:09 +00:00
|
|
|
/* XXXRW: reference released prematurely. */
|
|
|
|
ifa_free(&ia->ia_ifa);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get ip6 linklocal address for the router. */
|
2020-04-14 23:06:25 +00:00
|
|
|
if (nh->nh_flags & NHF_GATEWAY) {
|
1999-11-22 02:45:11 +00:00
|
|
|
struct sockaddr_in6 *sin6;
|
2020-04-14 23:06:25 +00:00
|
|
|
sin6 = &nh->gw6_sa;
|
1999-11-22 02:45:11 +00:00
|
|
|
router_ll6 = &sin6->sin6_addr;
|
|
|
|
if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
|
|
|
|
router_ll6 = (struct in6_addr *)NULL;
|
|
|
|
} else
|
|
|
|
router_ll6 = (struct in6_addr *)NULL;
|
|
|
|
|
|
|
|
/* ip6 */
|
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
ip6->ip6_flow = 0;
|
2000-07-04 16:35:15 +00:00
|
|
|
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
|
|
|
|
ip6->ip6_vfc |= IPV6_VERSION;
|
1999-11-22 02:45:11 +00:00
|
|
|
/* ip6->ip6_plen will be set later */
|
|
|
|
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
|
|
|
ip6->ip6_hlim = 255;
|
|
|
|
/* ip6->ip6_src must be linklocal addr for my outgoing if. */
|
|
|
|
bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
|
|
|
|
bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
|
|
|
|
|
|
|
|
/* ND Redirect */
|
|
|
|
nd_rd = (struct nd_redirect *)(ip6 + 1);
|
|
|
|
nd_rd->nd_rd_type = ND_REDIRECT;
|
|
|
|
nd_rd->nd_rd_code = 0;
|
|
|
|
nd_rd->nd_rd_reserved = 0;
|
2020-04-14 23:06:25 +00:00
|
|
|
if (nh->nh_flags & NHF_GATEWAY) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* nd_rd->nd_rd_target must be a link-local address in
|
|
|
|
* better router cases.
|
|
|
|
*/
|
|
|
|
if (!router_ll6)
|
|
|
|
goto fail;
|
|
|
|
bcopy(router_ll6, &nd_rd->nd_rd_target,
|
2003-10-07 19:51:22 +00:00
|
|
|
sizeof(nd_rd->nd_rd_target));
|
1999-11-22 02:45:11 +00:00
|
|
|
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
|
2003-10-07 19:51:22 +00:00
|
|
|
sizeof(nd_rd->nd_rd_dst));
|
1999-11-22 02:45:11 +00:00
|
|
|
} else {
|
|
|
|
/* make sure redtgt == reddst */
|
|
|
|
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
|
2003-10-07 19:51:22 +00:00
|
|
|
sizeof(nd_rd->nd_rd_target));
|
1999-11-22 02:45:11 +00:00
|
|
|
bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
|
2003-10-07 19:51:22 +00:00
|
|
|
sizeof(nd_rd->nd_rd_dst));
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p = (u_char *)(nd_rd + 1);
|
|
|
|
|
|
|
|
if (!router_ll6)
|
|
|
|
goto nolladdropt;
|
|
|
|
|
2003-10-07 19:51:22 +00:00
|
|
|
{
|
|
|
|
/* target lladdr option */
|
|
|
|
int len;
|
|
|
|
struct nd_opt_hdr *nd_opt;
|
|
|
|
char *lladdr;
|
|
|
|
|
lltable: Add support for "child" LLEs holding encap for IPv4oIPv6 entries.
Currently we use pre-calculated headers inside LLE entries as prepend data
for `if_output` functions. Using these headers allows saving some
CPU cycles/memory accesses on the fast path.
However, this approach makes adding L2 header for IPv4 traffic with IPv6
nexthops more complex, as it is not possible to store multiple
pre-calculated headers inside lle. Additionally, the solution space is
limited by the fact that PCB caching saves LLEs in addition to the nexthop.
Thus, add support for creating special "child" LLEs for the purpose of holding
custom family encaps and store mbufs pending resolution. To simplify handling
of those LLEs, store them in a linked-list inside a "parent" (e.g. normal) LLE.
Such LLEs are not visible when iterating LLE table. Their lifecycle is bound
to the "parent" LLE - it is not possible to delete "child" when parent is alive.
Furthermore, "child" LLEs are static (RTF_STATIC), avoding complex state
machine used by the standard LLEs.
nd6_lookup() and nd6_resolve() now accepts an additional argument, family,
allowing to return such child LLEs. This change uses `LLE_SF()` macro which
packs family and flags in a single int field. This is done to simplify merging
back to stable/. Once this code lands, most of the cases will be converted to
use a dedicated `family` parameter.
Differential Revision: https://reviews.freebsd.org/D31379
MFC after: 2 weeks
2021-08-21 14:13:32 +00:00
|
|
|
ln = nd6_lookup(router_ll6, LLE_SF(AF_INET6, 0), ifp);
|
2008-12-16 02:06:26 +00:00
|
|
|
if (ln == NULL)
|
2003-10-07 19:51:22 +00:00
|
|
|
goto nolladdropt;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
2003-10-07 19:51:22 +00:00
|
|
|
len = sizeof(*nd_opt) + ifp->if_addrlen;
|
|
|
|
len = (len + 7) & ~7; /* round by 8 */
|
|
|
|
/* safety check */
|
2008-12-16 02:06:26 +00:00
|
|
|
if (len + (p - (u_char *)ip6) > maxlen)
|
2003-10-07 19:51:22 +00:00
|
|
|
goto nolladdropt;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
|
|
|
if (ln->la_flags & LLE_VALID) {
|
2003-10-07 19:51:22 +00:00
|
|
|
nd_opt = (struct nd_opt_hdr *)p;
|
|
|
|
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
|
|
|
|
nd_opt->nd_opt_len = len >> 3;
|
|
|
|
lladdr = (char *)(nd_opt + 1);
|
2015-12-31 05:03:27 +00:00
|
|
|
bcopy(ln->ll_addr, lladdr, ifp->if_addrlen);
|
2003-10-07 19:51:22 +00:00
|
|
|
p += len;
|
|
|
|
}
|
2003-10-07 20:22:01 +00:00
|
|
|
}
|
2008-12-16 02:06:26 +00:00
|
|
|
nolladdropt:
|
|
|
|
if (ln != NULL)
|
|
|
|
LLE_RUNLOCK(ln);
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
|
|
|
|
|
|
|
|
/* just to be safe */
|
2000-07-04 16:35:15 +00:00
|
|
|
#ifdef M_DECRYPTED /*not openbsd*/
|
1999-11-22 02:45:11 +00:00
|
|
|
if (m0->m_flags & M_DECRYPTED)
|
|
|
|
goto noredhdropt;
|
2000-07-04 16:35:15 +00:00
|
|
|
#endif
|
|
|
|
if (p - (u_char *)ip6 > maxlen)
|
|
|
|
goto noredhdropt;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2003-10-07 17:46:18 +00:00
|
|
|
{
|
|
|
|
/* redirected header option */
|
|
|
|
int len;
|
|
|
|
struct nd_opt_rd_hdr *nd_opt_rh;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2003-10-07 17:46:18 +00:00
|
|
|
/*
|
|
|
|
* compute the maximum size for icmp6 redirect header option.
|
|
|
|
* XXX room for auth header?
|
|
|
|
*/
|
|
|
|
len = maxlen - (p - (u_char *)ip6);
|
|
|
|
len &= ~7;
|
|
|
|
|
|
|
|
/* This is just for simplicity. */
|
|
|
|
if (m0->m_pkthdr.len != m0->m_len) {
|
|
|
|
if (m0->m_next) {
|
|
|
|
m_freem(m0->m_next);
|
|
|
|
m0->m_next = NULL;
|
|
|
|
}
|
|
|
|
m0->m_pkthdr.len = m0->m_len;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2003-10-07 17:46:18 +00:00
|
|
|
/*
|
|
|
|
* Redirected header option spec (RFC2461 4.6.3) talks nothing
|
|
|
|
* about padding/truncate rule for the original IP packet.
|
|
|
|
* From the discussion on IPv6imp in Feb 1999,
|
|
|
|
* the consensus was:
|
|
|
|
* - "attach as much as possible" is the goal
|
|
|
|
* - pad if not aligned (original size can be guessed by
|
|
|
|
* original ip6 header)
|
|
|
|
* Following code adds the padding if it is simple enough,
|
|
|
|
* and truncates if not.
|
|
|
|
*/
|
|
|
|
if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
|
|
|
|
panic("assumption failed in %s:%d", __FILE__,
|
|
|
|
__LINE__);
|
|
|
|
|
|
|
|
if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
|
|
|
|
/* not enough room, truncate */
|
|
|
|
m0->m_pkthdr.len = m0->m_len = len -
|
|
|
|
sizeof(*nd_opt_rh);
|
|
|
|
} else {
|
|
|
|
/* enough room, pad or truncate */
|
|
|
|
size_t extra;
|
|
|
|
|
|
|
|
extra = m0->m_pkthdr.len % 8;
|
|
|
|
if (extra) {
|
|
|
|
/* pad if easy enough, truncate if not */
|
|
|
|
if (8 - extra <= M_TRAILINGSPACE(m0)) {
|
|
|
|
/* pad */
|
|
|
|
m0->m_len += (8 - extra);
|
|
|
|
m0->m_pkthdr.len += (8 - extra);
|
|
|
|
} else {
|
|
|
|
/* truncate */
|
|
|
|
m0->m_pkthdr.len -= extra;
|
|
|
|
m0->m_len -= extra;
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2003-10-07 17:46:18 +00:00
|
|
|
len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
|
|
|
|
m0->m_pkthdr.len = m0->m_len = len -
|
|
|
|
sizeof(*nd_opt_rh);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2003-10-07 17:46:18 +00:00
|
|
|
nd_opt_rh = (struct nd_opt_rd_hdr *)p;
|
|
|
|
bzero(nd_opt_rh, sizeof(*nd_opt_rh));
|
|
|
|
nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
|
|
|
|
nd_opt_rh->nd_opt_rh_len = len >> 3;
|
|
|
|
p += sizeof(*nd_opt_rh);
|
|
|
|
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
|
|
|
|
|
|
|
|
/* connect m0 to m */
|
|
|
|
m_tag_delete_chain(m0, NULL);
|
|
|
|
m0->m_flags &= ~M_PKTHDR;
|
|
|
|
m->m_next = m0;
|
|
|
|
m->m_pkthdr.len = m->m_len + m0->m_len;
|
|
|
|
m0 = NULL;
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
noredhdropt:;
|
2003-03-29 08:31:28 +00:00
|
|
|
if (m0) {
|
|
|
|
m_freem(m0);
|
|
|
|
m0 = NULL;
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2003-10-21 20:05:32 +00:00
|
|
|
/* XXX: clear embedded link IDs in the inner header */
|
|
|
|
in6_clearscope(&sip6->ip6_src);
|
|
|
|
in6_clearscope(&sip6->ip6_dst);
|
|
|
|
in6_clearscope(&nd_rd->nd_rd_target);
|
|
|
|
in6_clearscope(&nd_rd->nd_rd_dst);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
|
|
|
|
|
|
|
|
nd_rd->nd_rd_cksum = 0;
|
2003-10-07 17:46:18 +00:00
|
|
|
nd_rd->nd_rd_cksum = in6_cksum(m, IPPROTO_ICMPV6,
|
|
|
|
sizeof(*ip6), ntohs(ip6->ip6_plen));
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2010-08-19 11:31:03 +00:00
|
|
|
if (send_sendso_input_hook != NULL) {
|
|
|
|
mtag = m_tag_get(PACKET_TAG_ND_OUTGOING, sizeof(unsigned short),
|
|
|
|
M_NOWAIT);
|
|
|
|
if (mtag == NULL)
|
|
|
|
goto fail;
|
|
|
|
*(unsigned short *)(mtag + 1) = nd_rd->nd_rd_type;
|
|
|
|
m_tag_prepend(m, mtag);
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/* send the packet to outside... */
|
2002-10-16 01:54:46 +00:00
|
|
|
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (outif) {
|
|
|
|
icmp6_ifstat_inc(outif, ifs6_out_msg);
|
|
|
|
icmp6_ifstat_inc(outif, ifs6_out_redirect);
|
|
|
|
}
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_outhist[ND_REDIRECT]);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (m)
|
|
|
|
m_freem(m);
|
|
|
|
if (m0)
|
|
|
|
m_freem(m0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ICMPv6 socket option processing.
|
|
|
|
*/
|
|
|
|
int
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
int optlen;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct inpcb *inp = sotoinpcb(so);
|
1999-11-22 02:45:11 +00:00
|
|
|
int level, op, optname;
|
|
|
|
|
|
|
|
if (sopt) {
|
|
|
|
level = sopt->sopt_level;
|
|
|
|
op = sopt->sopt_dir;
|
|
|
|
optname = sopt->sopt_name;
|
|
|
|
optlen = sopt->sopt_valsize;
|
|
|
|
} else
|
|
|
|
level = op = optname = optlen = 0;
|
2001-06-11 12:39:29 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
if (level != IPPROTO_ICMPV6) {
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
switch (op) {
|
1999-11-22 02:45:11 +00:00
|
|
|
case PRCO_SETOPT:
|
|
|
|
switch (optname) {
|
|
|
|
case ICMP6_FILTER:
|
|
|
|
{
|
2008-07-29 19:37:16 +00:00
|
|
|
struct icmp6_filter ic6f;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2008-07-29 19:37:16 +00:00
|
|
|
if (optlen != sizeof(ic6f)) {
|
1999-11-22 02:45:11 +00:00
|
|
|
error = EMSGSIZE;
|
|
|
|
break;
|
|
|
|
}
|
2008-07-29 19:37:16 +00:00
|
|
|
error = sooptcopyin(sopt, &ic6f, optlen, optlen);
|
|
|
|
if (error == 0) {
|
|
|
|
INP_WLOCK(inp);
|
|
|
|
*inp->in6p_icmp6filt = ic6f;
|
|
|
|
INP_WUNLOCK(inp);
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = ENOPROTOOPT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRCO_GETOPT:
|
|
|
|
switch (optname) {
|
|
|
|
case ICMP6_FILTER:
|
|
|
|
{
|
2008-07-29 19:37:16 +00:00
|
|
|
struct icmp6_filter ic6f;
|
|
|
|
|
|
|
|
INP_RLOCK(inp);
|
|
|
|
ic6f = *inp->in6p_icmp6filt;
|
|
|
|
INP_RUNLOCK(inp);
|
|
|
|
error = sooptcopyout(sopt, &ic6f, sizeof(ic6f));
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = ENOPROTOOPT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-10-06 14:02:09 +00:00
|
|
|
return (error);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Perform rate limit check.
|
|
|
|
* Returns 0 if it is okay to send the icmp6 packet.
|
|
|
|
* Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
|
|
|
|
* limitation.
|
|
|
|
*
|
|
|
|
* XXX per-destination/type check necessary?
|
2007-07-05 16:23:49 +00:00
|
|
|
*
|
|
|
|
* dst - not used at this moment
|
|
|
|
* type - not used at this moment
|
|
|
|
* code - not used at this moment
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2022-10-07 14:22:57 +00:00
|
|
|
int
|
2007-07-05 16:23:49 +00:00
|
|
|
icmp6_ratelimit(const struct in6_addr *dst, const int type,
|
|
|
|
const int code)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2000-07-04 16:35:15 +00:00
|
|
|
int ret;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2002-04-19 04:46:24 +00:00
|
|
|
ret = 0; /* okay to send */
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/* PPS limit */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (!ppsratecheck(&V_icmp6errppslim_last, &V_icmp6errpps_count,
|
|
|
|
V_icmp6errppslim)) {
|
2000-07-04 16:35:15 +00:00
|
|
|
/* The packet is subject to rate limit */
|
|
|
|
ret++;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
return ret;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|