linux/net/xfrm/xfrm_state.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * xfrm_state.c
 *
 * Changes:
 *	Mitsuru KANDA @USAGI
 * 	Kazunori MIYAZAWA @USAGI
 * 	Kunihiro Ishiguro <[email protected]>
 * 		IPv6 support
 * 	YOSHIFUJI Hideaki @USAGI
 * 		Split up af-specific functions
 *	Derek Atkins <[email protected]>
 *		Add UDP Encapsulation
 *
 */

#include <linux/compat.h>
#include <linux/workqueue.h>
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <linux/module.h>
#include <linux/cache.h>
#include <linux/audit.h>
#include <linux/uaccess.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>

#include <crypto/aead.h>

#include "xfrm_hash.h"

#define xfrm_state_deref_prot(table, net)

static void xfrm_state_gc_task(struct work_struct *work);

/* Each xfrm_state may be linked to two tables:

   1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
   2. Hash table by (daddr,family,reqid) to find what SAs exist for given
      destination/tunnel endpoint. (output)
 */

static unsigned int xfrm_state_hashmax __read_mostly =;
static struct kmem_cache *xfrm_state_cache __ro_after_init;

static DECLARE_WORK(xfrm_state_gc_work, xfrm_state_gc_task);
static HLIST_HEAD(xfrm_state_gc_list);
static HLIST_HEAD(xfrm_state_dev_gc_list);

static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x)
{}

static inline unsigned int xfrm_dst_hash(struct net *net,
					 const xfrm_address_t *daddr,
					 const xfrm_address_t *saddr,
					 u32 reqid,
					 unsigned short family)
{}

static inline unsigned int xfrm_src_hash(struct net *net,
					 const xfrm_address_t *daddr,
					 const xfrm_address_t *saddr,
					 unsigned short family)
{}

static inline unsigned int
xfrm_spi_hash(struct net *net, const xfrm_address_t *daddr,
	      __be32 spi, u8 proto, unsigned short family)
{}

static unsigned int xfrm_seq_hash(struct net *net, u32 seq)
{}

#define XFRM_STATE_INSERT(by, _n, _h, _type)

static void xfrm_hash_transfer(struct hlist_head *list,
			       struct hlist_head *ndsttable,
			       struct hlist_head *nsrctable,
			       struct hlist_head *nspitable,
			       struct hlist_head *nseqtable,
			       unsigned int nhashmask)
{}

static unsigned long xfrm_hash_new_size(unsigned int state_hmask)
{}

static void xfrm_hash_resize(struct work_struct *work)
{}

static DEFINE_SPINLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO];

static DEFINE_SPINLOCK(xfrm_state_gc_lock);
static DEFINE_SPINLOCK(xfrm_state_dev_gc_lock);

int __xfrm_state_delete(struct xfrm_state *x);

int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
static bool km_is_alive(const struct km_event *c);
void km_state_expired(struct xfrm_state *x, int hard, u32 portid);

int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
{}
EXPORT_SYMBOL();

void xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
{}
EXPORT_SYMBOL();

static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
{}

static void xfrm_put_type(const struct xfrm_type *type)
{}

int xfrm_register_type_offload(const struct xfrm_type_offload *type,
			       unsigned short family)
{}
EXPORT_SYMBOL();

void xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
				  unsigned short family)
{}
EXPORT_SYMBOL();

static const struct xfrm_type_offload *
xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
{}

static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
{}

static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] =;

static const struct xfrm_mode xfrm6_mode_map[XFRM_MODE_MAX] =;

static const struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
{}

void xfrm_state_free(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

static void ___xfrm_state_destroy(struct xfrm_state *x)
{}

static void xfrm_state_gc_task(struct work_struct *work)
{}

static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
{}

static void xfrm_replay_timer_handler(struct timer_list *t);

struct xfrm_state *xfrm_state_alloc(struct net *net)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_XFRM_OFFLOAD
void xfrm_dev_state_delete(struct xfrm_state *x)
{}
EXPORT_SYMBOL_GPL();

void xfrm_dev_state_free(struct xfrm_state *x)
{}
#endif

void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
{}
EXPORT_SYMBOL();

int __xfrm_state_delete(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

int xfrm_state_delete(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int
xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
{}

static inline int
xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid)
{}
#else
static inline int
xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
{
	return 0;
}

static inline int
xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid)
{
	return 0;
}
#endif

int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
{}
EXPORT_SYMBOL();

int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid)
{}
EXPORT_SYMBOL();

void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
{}
EXPORT_SYMBOL();

static void
__xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
{}

static void
__xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
{}

static void
xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
		    const struct xfrm_tmpl *tmpl,
		    const xfrm_address_t *daddr, const xfrm_address_t *saddr,
		    unsigned short family)
{}

static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
						  const xfrm_address_t *daddr,
						  __be32 spi, u8 proto,
						  unsigned short family,
						  struct xfrm_dev_offload *xdo)
{}

static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
					      const xfrm_address_t *daddr,
					      __be32 spi, u8 proto,
					      unsigned short family)
{}

static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
						     const xfrm_address_t *daddr,
						     const xfrm_address_t *saddr,
						     u8 proto, unsigned short family)
{}

static inline struct xfrm_state *
__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
{}

static void xfrm_hash_grow_check(struct net *net, int have_hash_collision)
{}

static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
			       const struct flowi *fl, unsigned short family,
			       struct xfrm_state **best, int *acq_in_progress,
			       int *error)
{}

struct xfrm_state *
xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
		const struct flowi *fl, struct xfrm_tmpl *tmpl,
		struct xfrm_policy *pol, int *err,
		unsigned short family, u32 if_id)
{}

struct xfrm_state *
xfrm_stateonly_find(struct net *net, u32 mark, u32 if_id,
		    xfrm_address_t *daddr, xfrm_address_t *saddr,
		    unsigned short family, u8 mode, u8 proto, u32 reqid)
{}
EXPORT_SYMBOL();

struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
					      unsigned short family)
{}
EXPORT_SYMBOL();

static void __xfrm_state_insert(struct xfrm_state *x)
{}

/* net->xfrm.xfrm_state_lock is held */
static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
{}

void xfrm_state_insert(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

/* net->xfrm.xfrm_state_lock is held */
static struct xfrm_state *__find_acq_core(struct net *net,
					  const struct xfrm_mark *m,
					  unsigned short family, u8 mode,
					  u32 reqid, u32 if_id, u8 proto,
					  const xfrm_address_t *daddr,
					  const xfrm_address_t *saddr,
					  int create)
{}

static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);

int xfrm_state_add(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_XFRM_MIGRATE
static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *security)
{}

static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
					   struct xfrm_encap_tmpl *encap)
{}

struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
						u32 if_id)
{}
EXPORT_SYMBOL();

struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
				      struct xfrm_migrate *m,
				      struct xfrm_encap_tmpl *encap)
{}
EXPORT_SYMBOL();
#endif

int xfrm_state_update(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

int xfrm_state_check_expire(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

void xfrm_state_update_stats(struct net *net)
{}

struct xfrm_state *
xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32 spi,
		  u8 proto, unsigned short family)
{}
EXPORT_SYMBOL();

struct xfrm_state *
xfrm_state_lookup_byaddr(struct net *net, u32 mark,
			 const xfrm_address_t *daddr, const xfrm_address_t *saddr,
			 u8 proto, unsigned short family)
{}
EXPORT_SYMBOL();

struct xfrm_state *
xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
	      u32 if_id, u8 proto, const xfrm_address_t *daddr,
	      const xfrm_address_t *saddr, int create, unsigned short family)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_XFRM_SUB_POLICY
#if IS_ENABLED(CONFIG_IPV6)
/* distribution counting sort function for xfrm_state and xfrm_tmpl */
static void
__xfrm6_sort(void **dst, void **src, int n,
	     int (*cmp)(const void *p), int maxclass)
{}

/* Rule for xfrm_state:
 *
 * rule 1: select IPsec transport except AH
 * rule 2: select MIPv6 RO or inbound trigger
 * rule 3: select IPsec transport AH
 * rule 4: select IPsec tunnel
 * rule 5: others
 */
static int __xfrm6_state_sort_cmp(const void *p)
{}

/* Rule for xfrm_tmpl:
 *
 * rule 1: select IPsec transport
 * rule 2: select MIPv6 RO or inbound trigger
 * rule 3: select IPsec tunnel
 * rule 4: others
 */
static int __xfrm6_tmpl_sort_cmp(const void *p)
{}
#else
static inline int __xfrm6_state_sort_cmp(const void *p) { return 5; }
static inline int __xfrm6_tmpl_sort_cmp(const void *p) { return 4; }

static inline void
__xfrm6_sort(void **dst, void **src, int n,
	     int (*cmp)(const void *p), int maxclass)
{
	int i;

	for (i = 0; i < n; i++)
		dst[i] = src[i];
}
#endif /* CONFIG_IPV6 */

void
xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
	       unsigned short family)
{}

void
xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
		unsigned short family)
{}
#endif

/* Silly enough, but I'm lazy to build resolution list */

static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
{}

struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
{}
EXPORT_SYMBOL();

u32 xfrm_get_acqseq(void)
{}
EXPORT_SYMBOL();

int verify_spi_info(u8 proto, u32 min, u32 max, struct netlink_ext_ack *extack)
{}
EXPORT_SYMBOL();

int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
		   struct netlink_ext_ack *extack)
{}
EXPORT_SYMBOL();

static bool __xfrm_state_filter_match(struct xfrm_state *x,
				      struct xfrm_address_filter *filter)
{}

int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
		    int (*func)(struct xfrm_state *, int, void*),
		    void *data)
{}
EXPORT_SYMBOL();

void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
			  struct xfrm_address_filter *filter)
{}
EXPORT_SYMBOL();

void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net)
{}
EXPORT_SYMBOL();

static void xfrm_replay_timer_handler(struct timer_list *t)
{}

static LIST_HEAD(xfrm_km_list);

void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
{}

void km_state_notify(struct xfrm_state *x, const struct km_event *c)
{}

EXPORT_SYMBOL();
EXPORT_SYMBOL();

void km_state_expired(struct xfrm_state *x, int hard, u32 portid)
{}

EXPORT_SYMBOL();
/*
 * We send to all registered managers regardless of failure
 * We are happy with one success
*/
int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
{}
EXPORT_SYMBOL();

static int __km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
{}

int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
{}
EXPORT_SYMBOL();

void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
	       const struct xfrm_migrate *m, int num_migrate,
	       const struct xfrm_kmaddress *k,
	       const struct xfrm_encap_tmpl *encap)
{}
EXPORT_SYMBOL();
#endif

int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
{}
EXPORT_SYMBOL();

static bool km_is_alive(const struct km_event *c)
{}

#if IS_ENABLED(CONFIG_XFRM_USER_COMPAT)
static DEFINE_SPINLOCK(xfrm_translator_lock);
static struct xfrm_translator __rcu *xfrm_translator;

struct xfrm_translator *xfrm_get_translator(void)
{}
EXPORT_SYMBOL_GPL();

void xfrm_put_translator(struct xfrm_translator *xtr)
{}
EXPORT_SYMBOL_GPL();

int xfrm_register_translator(struct xfrm_translator *xtr)
{}
EXPORT_SYMBOL_GPL();

int xfrm_unregister_translator(struct xfrm_translator *xtr)
{}
EXPORT_SYMBOL_GPL();
#endif

int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen)
{}
EXPORT_SYMBOL();

static DEFINE_SPINLOCK(xfrm_km_lock);

void xfrm_register_km(struct xfrm_mgr *km)
{}
EXPORT_SYMBOL();

void xfrm_unregister_km(struct xfrm_mgr *km)
{}
EXPORT_SYMBOL();

int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
{}
EXPORT_SYMBOL();

int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
{}
EXPORT_SYMBOL();

struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family)
{}
EXPORT_SYMBOL_GPL();

struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
{}

void xfrm_flush_gc(void)
{}
EXPORT_SYMBOL();

/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
void xfrm_state_delete_tunnel(struct xfrm_state *x)
{}
EXPORT_SYMBOL();

u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
{}
EXPORT_SYMBOL_GPL();

int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
		      struct netlink_ext_ack *extack)
{}

EXPORT_SYMBOL();

int xfrm_init_state(struct xfrm_state *x)
{}

EXPORT_SYMBOL();

int __net_init xfrm_state_init(struct net *net)
{}

void xfrm_state_fini(struct net *net)
{}

#ifdef CONFIG_AUDITSYSCALL
static void xfrm_audit_helper_sainfo(struct xfrm_state *x,
				     struct audit_buffer *audit_buf)
{}

static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
				      struct audit_buffer *audit_buf)
{}

void xfrm_audit_state_add(struct xfrm_state *x, int result, bool task_valid)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_delete(struct xfrm_state *x, int result, bool task_valid)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
				      struct sk_buff *skb)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_replay(struct xfrm_state *x,
			     struct sk_buff *skb, __be32 net_seq)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
			       __be32 net_spi, __be32 net_seq)
{}
EXPORT_SYMBOL_GPL();

void xfrm_audit_state_icvfail(struct xfrm_state *x,
			      struct sk_buff *skb, u8 proto)
{}
EXPORT_SYMBOL_GPL();
#endif /* CONFIG_AUDITSYSCALL */