linux/net/core/neighbour.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *	Generic address resolution entity
 *
 *	Authors:
 *	Pedro Roque		<[email protected]>
 *	Alexey Kuznetsov	<[email protected]>
 *
 *	Fixes:
 *	Vitaly E. Lavrov	releasing NULL neighbor in neigh_add.
 *	Harald Welte		Add neighbour cache statistics like rtstat
 */

#define pr_fmt(fmt)

#include <linux/slab.h>
#include <linux/kmemleak.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
#include <linux/times.h>
#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/arp.h>
#include <net/dst.h>
#include <net/sock.h>
#include <net/netevent.h>
#include <net/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>
#include <linux/log2.h>
#include <linux/inetdevice.h>
#include <net/addrconf.h>

#include <trace/events/neigh.h>

#define NEIGH_DEBUG
#define neigh_dbg(level, fmt, ...)

#define PNEIGH_HASHMASK

static void neigh_timer_handler(struct timer_list *t);
static void __neigh_notify(struct neighbour *n, int type, int flags,
			   u32 pid);
static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
				    struct net_device *dev);

#ifdef CONFIG_PROC_FS
static const struct seq_operations neigh_stat_seq_ops;
#endif

/*
   Neighbour hash table buckets are protected with rwlock tbl->lock.

   - All the scans/updates to hash buckets MUST be made under this lock.
   - NOTHING clever should be made under this lock: no callbacks
     to protocol backends, no attempts to send something to network.
     It will result in deadlocks, if backend/driver wants to use neighbour
     cache.
   - If the entry requires some non-trivial actions, increase
     its reference count and release table lock.

   Neighbour entries are protected:
   - with reference count.
   - with rwlock neigh->lock

   Reference count prevents destruction.

   neigh->lock mainly serializes ll address data and its validity state.
   However, the same lock is used to protect another entry fields:
    - timer
    - resolution queue

   Again, nothing clever shall be made under neigh->lock,
   the most complicated procedure, which we allow is dev->hard_header.
   It is supposed, that dev->hard_header is simplistic and does
   not make callbacks to neighbour tables.
 */

static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
{}

static void neigh_cleanup_and_release(struct neighbour *neigh)
{}

/*
 * It is random distribution in the interval (1/2)*base...(3/2)*base.
 * It corresponds to default IPv6 settings and is not overridable,
 * because it is really reasonable choice.
 */

unsigned long neigh_rand_reach_time(unsigned long base)
{}
EXPORT_SYMBOL();

static void neigh_mark_dead(struct neighbour *n)
{}

static void neigh_update_gc_list(struct neighbour *n)
{}

static void neigh_update_managed_list(struct neighbour *n)
{}

static void neigh_update_flags(struct neighbour *neigh, u32 flags, int *notify,
			       bool *gc_update, bool *managed_update)
{}

static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np,
		      struct neigh_table *tbl)
{}

bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
{}

static int neigh_forced_gc(struct neigh_table *tbl)
{}

static void neigh_add_timer(struct neighbour *n, unsigned long when)
{}

static int neigh_del_timer(struct neighbour *n)
{}

static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
						   int family)
{}

static void neigh_parms_qlen_dec(struct net_device *dev, int family)
{}

static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net,
			       int family)
{}

static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
			    bool skip_perm)
{}

void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
{}
EXPORT_SYMBOL();

static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
			  bool skip_perm)
{}

int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev)
{}
EXPORT_SYMBOL();

int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
{}
EXPORT_SYMBOL();

static struct neighbour *neigh_alloc(struct neigh_table *tbl,
				     struct net_device *dev,
				     u32 flags, bool exempt_from_gc)
{}

static void neigh_get_hash_rnd(u32 *x)
{}

static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
{}

static void neigh_hash_free_rcu(struct rcu_head *head)
{}

static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
						unsigned long new_shift)
{}

struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
			       struct net_device *dev)
{}
EXPORT_SYMBOL();

static struct neighbour *
___neigh_create(struct neigh_table *tbl, const void *pkey,
		struct net_device *dev, u32 flags,
		bool exempt_from_gc, bool want_ref)
{}

struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
				 struct net_device *dev, bool want_ref)
{}
EXPORT_SYMBOL();

static u32 pneigh_hash(const void *pkey, unsigned int key_len)
{}

static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
					      struct net *net,
					      const void *pkey,
					      unsigned int key_len,
					      struct net_device *dev)
{}

struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
		struct net *net, const void *pkey, struct net_device *dev)
{}
EXPORT_SYMBOL_GPL();

struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
				    struct net *net, const void *pkey,
				    struct net_device *dev, int creat)
{}
EXPORT_SYMBOL();


int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
		  struct net_device *dev)
{}

static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
				    struct net_device *dev)
{}

static void neigh_parms_destroy(struct neigh_parms *parms);

static inline void neigh_parms_put(struct neigh_parms *parms)
{}

/*
 *	neighbour must already be out of the table;
 *
 */
void neigh_destroy(struct neighbour *neigh)
{}
EXPORT_SYMBOL();

/* Neighbour state is suspicious;
   disable fast path.

   Called with write_locked neigh.
 */
static void neigh_suspect(struct neighbour *neigh)
{}

/* Neighbour state is OK;
   enable fast path.

   Called with write_locked neigh.
 */
static void neigh_connect(struct neighbour *neigh)
{}

static void neigh_periodic_work(struct work_struct *work)
{}

static __inline__ int neigh_max_probes(struct neighbour *n)
{}

static void neigh_invalidate(struct neighbour *neigh)
	__releases(neigh->lock)
	__acquires(neigh->lock)
{}

static void neigh_probe(struct neighbour *neigh)
	__releases(neigh->lock)
{}

/* Called when a timer expires for a neighbour entry. */

static void neigh_timer_handler(struct timer_list *t)
{}

int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,
		       const bool immediate_ok)
{}
EXPORT_SYMBOL();

static void neigh_update_hhs(struct neighbour *neigh)
{}

/* Generic update routine.
   -- lladdr is new lladdr or NULL, if it is not supplied.
   -- new    is new state.
   -- flags
	NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
				if it is different.
	NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
				lladdr instead of overriding it
				if it is different.
	NEIGH_UPDATE_F_ADMIN	means that the change is administrative.
	NEIGH_UPDATE_F_USE	means that the entry is user triggered.
	NEIGH_UPDATE_F_MANAGED	means that the entry will be auto-refreshed.
	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
				NTF_ROUTER flag.
	NEIGH_UPDATE_F_ISROUTER	indicates if the neighbour is known as
				a router.

   Caller MUST hold reference count on the entry.
 */
static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
			  u8 new, u32 flags, u32 nlmsg_pid,
			  struct netlink_ext_ack *extack)
{}

int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
		 u32 flags, u32 nlmsg_pid)
{}
EXPORT_SYMBOL();

/* Update the neigh to listen temporarily for probe responses, even if it is
 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
 */
void __neigh_set_probe_once(struct neighbour *neigh)
{}
EXPORT_SYMBOL();

struct neighbour *neigh_event_ns(struct neigh_table *tbl,
				 u8 *lladdr, void *saddr,
				 struct net_device *dev)
{}
EXPORT_SYMBOL();

/* called with read_lock_bh(&n->lock); */
static void neigh_hh_init(struct neighbour *n)
{}

/* Slow and careful. */

int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

/* As fast as possible without hh cache */

int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

static void neigh_managed_work(struct work_struct *work)
{}

static void neigh_proxy_process(struct timer_list *t)
{}

static unsigned long neigh_proxy_delay(struct neigh_parms *p)
{}

void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
		    struct sk_buff *skb)
{}
EXPORT_SYMBOL();

static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
						      struct net *net, int ifindex)
{}

struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
				      struct neigh_table *tbl)
{}
EXPORT_SYMBOL();

static void neigh_rcu_free_parms(struct rcu_head *head)
{}

void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
{}
EXPORT_SYMBOL();

static void neigh_parms_destroy(struct neigh_parms *parms)
{}

static struct lock_class_key neigh_table_proxy_queue_class;

static struct neigh_table __rcu *neigh_tables[NEIGH_NR_TABLES] __read_mostly;

void neigh_table_init(int index, struct neigh_table *tbl)
{}
EXPORT_SYMBOL();

/*
 * Only called from ndisc_cleanup(), which means this is dead code
 * because we no longer can unload IPv6 module.
 */
int neigh_table_clear(int index, struct neigh_table *tbl)
{}
EXPORT_SYMBOL();

static struct neigh_table *neigh_find_table(int family)
{}

const struct nla_policy nda_policy[NDA_MAX+1] =;

static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{}

static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
		     struct netlink_ext_ack *extack)
{}

static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
{}

static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
			      u32 pid, u32 seq, int type, int flags)
{}

static int neightbl_fill_param_info(struct sk_buff *skb,
				    struct neigh_table *tbl,
				    struct neigh_parms *parms,
				    u32 pid, u32 seq, int type,
				    unsigned int flags)
{}

static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] =;

static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] =;

static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{}

static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
				    struct netlink_ext_ack *extack)
{}

static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
{}

static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
			   u32 pid, u32 seq, int type, unsigned int flags)
{}

static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
			    u32 pid, u32 seq, int type, unsigned int flags,
			    struct neigh_table *tbl)
{}

static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
{}

static bool neigh_master_filtered(struct net_device *dev, int master_idx)
{}

static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
{}

struct neigh_dump_filter {};

static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
			    struct netlink_callback *cb,
			    struct neigh_dump_filter *filter)
{}

static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
			     struct netlink_callback *cb,
			     struct neigh_dump_filter *filter)
{}

static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
				bool strict_check,
				struct neigh_dump_filter *filter,
				struct netlink_ext_ack *extack)
{}

static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
{}

static int neigh_valid_get_req(const struct nlmsghdr *nlh,
			       struct neigh_table **tbl,
			       void **dst, int *dev_idx, u8 *ndm_flags,
			       struct netlink_ext_ack *extack)
{}

static inline size_t neigh_nlmsg_size(void)
{}

static int neigh_get_reply(struct net *net, struct neighbour *neigh,
			   u32 pid, u32 seq)
{}

static inline size_t pneigh_nlmsg_size(void)
{}

static int pneigh_get_reply(struct net *net, struct pneigh_entry *neigh,
			    u32 pid, u32 seq, struct neigh_table *tbl)
{}

static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
		     struct netlink_ext_ack *extack)
{}

void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
{}
EXPORT_SYMBOL();

/* The tbl->lock must be held as a writer and BH disabled. */
void __neigh_for_each_release(struct neigh_table *tbl,
			      int (*cb)(struct neighbour *))
{}
EXPORT_SYMBOL();

int neigh_xmit(int index, struct net_device *dev,
	       const void *addr, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_PROC_FS

static struct neighbour *neigh_get_first(struct seq_file *seq)
{}

static struct neighbour *neigh_get_next(struct seq_file *seq,
					struct neighbour *n,
					loff_t *pos)
{}

static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
{}

static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
{}

static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
					    struct pneigh_entry *pn,
					    loff_t *pos)
{}

static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
{}

static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
{}

void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
	__acquires(tbl->lock)
	__acquires(rcu)
{}
EXPORT_SYMBOL();

void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{}
EXPORT_SYMBOL();

void neigh_seq_stop(struct seq_file *seq, void *v)
	__releases(tbl->lock)
	__releases(rcu)
{}
EXPORT_SYMBOL();

/* statistics via seq_file */

static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
{}

static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{}

static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
{}

static int neigh_stat_seq_show(struct seq_file *seq, void *v)
{}

static const struct seq_operations neigh_stat_seq_ops =;
#endif /* CONFIG_PROC_FS */

static void __neigh_notify(struct neighbour *n, int type, int flags,
			   u32 pid)
{}

void neigh_app_ns(struct neighbour *n)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_SYSCTL
static int unres_qlen_max =;

static int proc_unres_qlen(const struct ctl_table *ctl, int write,
			   void *buffer, size_t *lenp, loff_t *ppos)
{}

static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
				  int index)
{}

static void neigh_proc_update(const struct ctl_table *ctl, int write)
{}

static int neigh_proc_dointvec_zero_intmax(const struct ctl_table *ctl, int write,
					   void *buffer, size_t *lenp,
					   loff_t *ppos)
{}

static int neigh_proc_dointvec_ms_jiffies_positive(const struct ctl_table *ctl, int write,
						   void *buffer, size_t *lenp, loff_t *ppos)
{}

int neigh_proc_dointvec(const struct ctl_table *ctl, int write, void *buffer,
			size_t *lenp, loff_t *ppos)
{}
EXPORT_SYMBOL();

int neigh_proc_dointvec_jiffies(const struct ctl_table *ctl, int write, void *buffer,
				size_t *lenp, loff_t *ppos)
{}
EXPORT_SYMBOL();

static int neigh_proc_dointvec_userhz_jiffies(const struct ctl_table *ctl, int write,
					      void *buffer, size_t *lenp,
					      loff_t *ppos)
{}

int neigh_proc_dointvec_ms_jiffies(const struct ctl_table *ctl, int write,
				   void *buffer, size_t *lenp, loff_t *ppos)
{}
EXPORT_SYMBOL();

static int neigh_proc_dointvec_unres_qlen(const struct ctl_table *ctl, int write,
					  void *buffer, size_t *lenp,
					  loff_t *ppos)
{}

static int neigh_proc_base_reachable_time(const struct ctl_table *ctl, int write,
					  void *buffer, size_t *lenp,
					  loff_t *ppos)
{}

#define NEIGH_PARMS_DATA_OFFSET(index)

#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc)

#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name)

#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name)

#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name)

#define NEIGH_SYSCTL_MS_JIFFIES_POSITIVE_ENTRY(attr, name)

#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name)

#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name)

static struct neigh_sysctl_table {} neigh_sysctl_template __read_mostly =;

int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
			  proc_handler *handler)
{}
EXPORT_SYMBOL();

void neigh_sysctl_unregister(struct neigh_parms *p)
{}
EXPORT_SYMBOL();

#endif	/* CONFIG_SYSCTL */

static int __init neigh_init(void)
{}

subsys_initcall(neigh_init);