summaryrefslogtreecommitdiff
path: root/include/net/xfrm.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/xfrm.h')
-rw-r--r--include/net/xfrm.h176
1 files changed, 107 insertions, 69 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 736bca450886..b9f385da758e 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -12,6 +12,7 @@
#include <linux/in6.h>
#include <linux/mutex.h>
#include <linux/audit.h>
+#include <linux/slab.h>
#include <net/sock.h>
#include <net/dst.h>
@@ -19,6 +20,10 @@
#include <net/route.h>
#include <net/ipv6.h>
#include <net/ip6_fib.h>
+#include <net/flow.h>
+
+#include <linux/interrupt.h>
+
#ifdef CONFIG_XFRM_STATISTICS
#include <net/snmp.h>
#endif
@@ -121,8 +126,7 @@ struct xfrm_state_walk {
};
/* Full description of state of transformer. */
-struct xfrm_state
-{
+struct xfrm_state {
#ifdef CONFIG_NET_NS
struct net *xs_net;
#endif
@@ -138,6 +142,8 @@ struct xfrm_state
struct xfrm_id id;
struct xfrm_selector sel;
+ struct xfrm_mark mark;
+ u32 tfcpad;
u32 genid;
@@ -160,7 +166,7 @@ struct xfrm_state
struct xfrm_lifetime_cfg lft;
/* Data for transformer */
- struct xfrm_algo *aalg;
+ struct xfrm_algo_auth *aalg;
struct xfrm_algo *ealg;
struct xfrm_algo *calg;
struct xfrm_algo_aead *aead;
@@ -199,7 +205,7 @@ struct xfrm_state
struct xfrm_stats stats;
struct xfrm_lifetime_cur curlft;
- struct timer_list timer;
+ struct tasklet_hrtimer mtimer;
/* Last used time */
unsigned long lastused;
@@ -237,8 +243,7 @@ enum {
};
/* callback structure passed from either netlink or pfkey */
-struct km_event
-{
+struct km_event {
union {
u32 hard;
u32 proto;
@@ -264,7 +269,6 @@ struct xfrm_policy_afinfo {
xfrm_address_t *saddr,
xfrm_address_t *daddr);
int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
- struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
void (*decode_session)(struct sk_buff *skb,
struct flowi *fl,
int reverse);
@@ -273,7 +277,8 @@ struct xfrm_policy_afinfo {
struct dst_entry *dst,
int nfheader_len);
int (*fill_dst)(struct xfrm_dst *xdst,
- struct net_device *dev);
+ struct net_device *dev,
+ struct flowi *fl);
};
extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
@@ -294,8 +299,8 @@ struct xfrm_state_afinfo {
const struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
int (*init_flags)(struct xfrm_state *x);
- void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ void (*init_tempsel)(struct xfrm_selector *sel, struct flowi *fl);
+ void (*init_temprop)(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
xfrm_address_t *daddr, xfrm_address_t *saddr);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
@@ -313,12 +318,11 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
-struct xfrm_type
-{
+struct xfrm_type {
char *description;
struct module *owner;
- __u8 proto;
- __u8 flags;
+ u8 proto;
+ u8 flags;
#define XFRM_TYPE_NON_FRAGMENT 1
#define XFRM_TYPE_REPLAY_PROT 2
#define XFRM_TYPE_LOCAL_COADDR 4
@@ -420,8 +424,7 @@ static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipp
return x->inner_mode_iaf;
}
-struct xfrm_tmpl
-{
+struct xfrm_tmpl {
/* id in template is interpreted as:
* daddr - destination of tunnel, may be zero for transport mode.
* spi - zero to acquire spi. Not zero if spi is static, then
@@ -435,24 +438,24 @@ struct xfrm_tmpl
unsigned short encap_family;
- __u32 reqid;
+ u32 reqid;
/* Mode: transport, tunnel etc. */
- __u8 mode;
+ u8 mode;
/* Sharing mode: unique, this session only, this user only etc. */
- __u8 share;
+ u8 share;
/* May skip this transfomration if no SA is found */
- __u8 optional;
+ u8 optional;
/* Skip aalgos/ealgos/calgos checks. */
- __u8 allalgs;
+ u8 allalgs;
/* Bit mask of algos allowed for acquisition */
- __u32 aalgos;
- __u32 ealgos;
- __u32 calgos;
+ u32 aalgos;
+ u32 ealgos;
+ u32 calgos;
};
#define XFRM_MAX_DEPTH 6
@@ -468,8 +471,7 @@ struct xfrm_policy_walk {
u32 seq;
};
-struct xfrm_policy
-{
+struct xfrm_policy {
#ifdef CONFIG_NET_NS
struct net *xp_net;
#endif
@@ -481,12 +483,14 @@ struct xfrm_policy
atomic_t refcnt;
struct timer_list timer;
+ struct flow_cache_object flo;
+ atomic_t genid;
u32 priority;
u32 index;
+ struct xfrm_mark mark;
struct xfrm_selector selector;
struct xfrm_lifetime_cfg lft;
struct xfrm_lifetime_cur curlft;
- struct dst_entry *bundles;
struct xfrm_policy_walk_entry walk;
u8 type;
u8 action;
@@ -538,8 +542,7 @@ struct xfrm_migrate {
/* default seq threshold size */
#define XFRM_AE_SEQT_SIZE 2
-struct xfrm_mgr
-{
+struct xfrm_mgr {
struct list_head list;
char *id;
int (*notify)(struct xfrm_state *x, struct km_event *c);
@@ -626,8 +629,7 @@ struct xfrm_spi_skb_cb {
#define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
/* Audit Information */
-struct xfrm_audit
-{
+struct xfrm_audit {
u32 secid;
uid_t loginuid;
u32 sessionid;
@@ -735,19 +737,12 @@ static inline void xfrm_pol_put(struct xfrm_policy *policy)
xfrm_policy_destroy(policy);
}
-#ifdef CONFIG_XFRM_SUB_POLICY
static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
{
int i;
for (i = npols - 1; i >= 0; --i)
xfrm_pol_put(pols[i]);
}
-#else
-static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
-{
- xfrm_pol_put(pols[0]);
-}
-#endif
extern void __xfrm_state_destroy(struct xfrm_state *);
@@ -774,7 +769,7 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
int pdw;
int pbi;
- pdw = prefixlen >> 5; /* num of whole __u32 in prefix */
+ pdw = prefixlen >> 5; /* num of whole u32 in prefix */
pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
if (pdw)
@@ -811,6 +806,9 @@ __be16 xfrm_flowi_sport(struct flowi *fl)
case IPPROTO_MH:
port = htons(fl->fl_mh_type);
break;
+ case IPPROTO_GRE:
+ port = htons(ntohl(fl->fl_gre_key) >> 16);
+ break;
default:
port = 0; /*XXX*/
}
@@ -832,6 +830,9 @@ __be16 xfrm_flowi_dport(struct flowi *fl)
case IPPROTO_ICMPV6:
port = htons(fl->fl_icmp_code);
break;
+ case IPPROTO_GRE:
+ port = htons(ntohl(fl->fl_gre_key) & 0xffff);
+ break;
default:
port = 0; /*XXX*/
}
@@ -871,19 +872,22 @@ static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ct
* bundles differing by session id. All the bundles grow from a parent
* policy rule.
*/
-struct xfrm_dst
-{
+struct xfrm_dst {
union {
struct dst_entry dst;
struct rtable rt;
struct rt6_info rt6;
} u;
struct dst_entry *route;
+ struct flow_cache_object flo;
+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
+ int num_pols, num_xfrms;
#ifdef CONFIG_XFRM_SUB_POLICY
struct flowi *origin;
struct xfrm_selector *partner;
#endif
- u32 genid;
+ u32 xfrm_genid;
+ u32 policy_genid;
u32 route_mtu_cached;
u32 child_mtu_cached;
u32 route_cookie;
@@ -893,6 +897,7 @@ struct xfrm_dst
#ifdef CONFIG_XFRM
static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
{
+ xfrm_pols_put(xdst->pols, xdst->num_pols);
dst_release(xdst->route);
if (likely(xdst->u.dst.xfrm))
xfrm_state_put(xdst->u.dst.xfrm);
@@ -907,8 +912,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
-struct sec_path
-{
+struct sec_path {
atomic_t refcnt;
int len;
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
@@ -1265,22 +1269,22 @@ struct xfrm_algo_desc {
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
- int (*err_handler)(struct sk_buff *skb, __u32 info);
+ int (*err_handler)(struct sk_buff *skb, u32 info);
- struct xfrm_tunnel *next;
+ struct xfrm_tunnel __rcu *next;
int priority;
};
struct xfrm6_tunnel {
int (*handler)(struct sk_buff *skb);
int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __be32 info);
- struct xfrm6_tunnel *next;
+ u8 type, u8 code, int offset, __be32 info);
+ struct xfrm6_tunnel __rcu *next;
int priority;
};
extern void xfrm_init(void);
-extern void xfrm4_init(void);
+extern void xfrm4_init(int rt_hash_size);
extern int xfrm_state_init(struct net *net);
extern void xfrm_state_fini(struct net *net);
extern void xfrm4_state_init(void);
@@ -1323,7 +1327,7 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
struct flowi *fl, struct xfrm_tmpl *tmpl,
struct xfrm_policy *pol, int *err,
unsigned short family);
-extern struct xfrm_state * xfrm_stateonly_find(struct net *net,
+extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family,
@@ -1332,8 +1336,14 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
-extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family);
-extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
+ xfrm_address_t *daddr, __be32 spi,
+ u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr,
+ u8 proto,
+ unsigned short family);
#ifdef CONFIG_XFRM_SUB_POLICY
extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family);
@@ -1370,11 +1380,12 @@ struct xfrmk_spdinfo {
u32 spdhmcnt;
};
-extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq);
+extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
+ u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
-extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
-extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
+extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
+extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x,
struct sk_buff *skb, __be32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
@@ -1414,9 +1425,8 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
-extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
-extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
-extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
+extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
+extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr);
extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_output(struct sk_buff *skb);
@@ -1447,20 +1457,21 @@ extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
int (*func)(struct xfrm_policy *, int, int, void*), void *);
extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
-struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
+struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
+ u8 type, int dir,
struct xfrm_selector *sel,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
-struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err);
+struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto,
- xfrm_address_t *daddr, xfrm_address_t *saddr,
- int create, unsigned short family);
+struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
+ u8 mode, u32 reqid, u8 proto,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr, int create,
+ unsigned short family);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
-extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
- struct flowi *fl, int family, int strict);
#ifdef CONFIG_XFRM_MIGRATE
extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
@@ -1500,16 +1511,13 @@ struct scatterlist;
typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
unsigned int);
-extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
- int offset, int len, icv_update_fn_t icv_update);
-
static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
int family)
{
switch (family) {
default:
case AF_INET:
- return (__force __u32)a->a4 - (__force __u32)b->a4;
+ return (__force u32)a->a4 - (__force u32)b->a4;
case AF_INET6:
return ipv6_addr_cmp((struct in6_addr *)a,
(struct in6_addr *)b);
@@ -1541,12 +1549,22 @@ static inline int xfrm_alg_len(struct xfrm_algo *alg)
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
}
+static inline int xfrm_alg_auth_len(struct xfrm_algo_auth *alg)
+{
+ return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
#ifdef CONFIG_XFRM_MIGRATE
static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
{
return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
}
+static inline struct xfrm_algo_auth *xfrm_algo_auth_clone(struct xfrm_algo_auth *orig)
+{
+ return kmemdup(orig, xfrm_alg_auth_len(orig), GFP_KERNEL);
+}
+
static inline void xfrm_states_put(struct xfrm_state **states, int n)
{
int i;
@@ -1569,4 +1587,24 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
}
#endif
+static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
+{
+ if (attrs[XFRMA_MARK])
+ memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark));
+ else
+ m->v = m->m = 0;
+
+ return m->v & m->m;
+}
+
+static inline int xfrm_mark_put(struct sk_buff *skb, struct xfrm_mark *m)
+{
+ if (m->m | m->v)
+ NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
#endif /* _NET_XFRM_H */