#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);
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)
{ … }
static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
{ … }
void xfrm_state_insert(struct xfrm_state *x)
{ … }
EXPORT_SYMBOL(…);
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)
static void
__xfrm6_sort(void **dst, void **src, int n,
int (*cmp)(const void *p), int maxclass)
{ … }
static int __xfrm6_state_sort_cmp(const void *p)
{ … }
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
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
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(…);
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(…);
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