linux/net/ipv6/icmp.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *	Internet Control Message Protocol (ICMPv6)
 *	Linux INET6 implementation
 *
 *	Authors:
 *	Pedro Roque		<[email protected]>
 *
 *	Based on net/ipv4/icmp.c
 *
 *	RFC 1885
 */

/*
 *	Changes:
 *
 *	Andi Kleen		:	exception handling
 *	Andi Kleen			add rate limits. never reply to a icmp.
 *					add more length checks and other fixes.
 *	yoshfuji		:	ensure to sent parameter problem for
 *					fragments.
 *	YOSHIFUJI Hideaki @USAGI:	added sysctl for icmp rate limit.
 *	Randy Dunlap and
 *	YOSHIFUJI Hideaki @USAGI:	Per-interface statistics support
 *	Kazunori MIYAZAWA @USAGI:       change output process to use ip6_append_data
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/netfilter.h>
#include <linux/slab.h>

#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif

#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/icmpv6.h>

#include <net/ip.h>
#include <net/sock.h>

#include <net/ipv6.h>
#include <net/ip6_checksum.h>
#include <net/ping.h>
#include <net/protocol.h>
#include <net/raw.h>
#include <net/rawv6.h>
#include <net/seg6.h>
#include <net/transp_v6.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/icmp.h>
#include <net/xfrm.h>
#include <net/inet_common.h>
#include <net/dsfield.h>
#include <net/l3mdev.h>

#include <linux/uaccess.h>

static DEFINE_PER_CPU(struct sock *, ipv6_icmp_sk);

static int icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
		       u8 type, u8 code, int offset, __be32 info)
{}

static int icmpv6_rcv(struct sk_buff *skb);

static const struct inet6_protocol icmpv6_protocol =;

/* Called with BH disabled */
static struct sock *icmpv6_xmit_lock(struct net *net)
{}

static void icmpv6_xmit_unlock(struct sock *sk)
{}

/*
 * Figure out, may we reply to this packet with icmp error.
 *
 * We do not reply, if:
 *	- it was icmp error message.
 *	- it is truncated, so that it is known, that protocol is ICMPV6
 *	  (i.e. in the middle of some exthdr)
 *
 *	--ANK (980726)
 */

static bool is_ineligible(const struct sk_buff *skb)
{}

static bool icmpv6_mask_allow(struct net *net, int type)
{}

static bool icmpv6_global_allow(struct net *net, int type)
{}

/*
 * Check the ICMP output rate limit
 */
static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
			       struct flowi6 *fl6)
{}

static bool icmpv6_rt_has_prefsrc(struct sock *sk, u8 type,
				  struct flowi6 *fl6)
{}

/*
 *	an inline helper for the "simple" if statement below
 *	checks if parameter problem report is caused by an
 *	unrecognized IPv6 option that has the Option Type
 *	highest-order two bits set to 10
 */

static bool opt_unrec(struct sk_buff *skb, __u32 offset)
{}

void icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
				struct icmp6hdr *thdr, int len)
{}

struct icmpv6_msg {};

static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{}

#if IS_ENABLED(CONFIG_IPV6_MIP6)
static void mip6_addr_swap(struct sk_buff *skb, const struct inet6_skb_parm *opt)
{}
#else
static inline void mip6_addr_swap(struct sk_buff *skb, const struct inet6_skb_parm *opt) {}
#endif

static struct dst_entry *icmpv6_route_lookup(struct net *net,
					     struct sk_buff *skb,
					     struct sock *sk,
					     struct flowi6 *fl6)
{}

static struct net_device *icmp6_dev(const struct sk_buff *skb)
{}

static int icmp6_iif(const struct sk_buff *skb)
{}

/*
 *	Send an ICMP message in response to a packet in error
 */
void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
		const struct in6_addr *force_saddr,
		const struct inet6_skb_parm *parm)
{}
EXPORT_SYMBOL();

/* Slightly more convenient version of icmp6_send with drop reasons.
 */
void icmpv6_param_prob_reason(struct sk_buff *skb, u8 code, int pos,
			      enum skb_drop_reason reason)
{}

/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
 * if sufficient data bytes are available
 * @nhs is the size of the tunnel header(s) :
 *  Either an IPv4 header for SIT encap
 *         an IPv4 header + GRE header for GRE encap
 */
int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
			       unsigned int data_len)
{}
EXPORT_SYMBOL();

static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb)
{}

enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,
				   u8 code, __be32 info)
{}

/*
 *	Handle icmp messages
 */

static int icmpv6_rcv(struct sk_buff *skb)
{}

void icmpv6_flow_init(const struct sock *sk, struct flowi6 *fl6, u8 type,
		      const struct in6_addr *saddr,
		      const struct in6_addr *daddr, int oif)
{}

int __init icmpv6_init(void)
{}

void icmpv6_cleanup(void)
{}


static const struct icmp6_err {} tab_unreach[] =;

int icmpv6_err_convert(u8 type, u8 code, int *err)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_SYSCTL
static struct ctl_table ipv6_icmp_table_template[] =;

struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
{}

size_t ipv6_icmp_sysctl_table_size(void)
{}
#endif