blob: 9f7e94ba66963085d0979560b3f8bd9a05c3af0a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#ifndef _NET_XFRM_H
2#define _NET_XFRM_H
3
Herbert Xuaabc9762005-05-03 16:27:10 -07004#include <linux/compiler.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/xfrm.h>
6#include <linux/spinlock.h>
7#include <linux/list.h>
8#include <linux/skbuff.h>
Arnaldo Carvalho de Melo14c85022005-12-27 02:43:12 -02009#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/pfkeyv2.h>
Masahide NAKAMURA57947082006-09-22 15:06:24 -070011#include <linux/ipsec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/in6.h>
Arjan van de Ven4a3e2f72006-03-20 22:33:17 -080013#include <linux/mutex.h>
Joy Lattenab5f5e82007-09-17 11:51:22 -070014#include <linux/audit.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090015#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
17#include <net/sock.h>
18#include <net/dst.h>
Herbert Xu436a0a42007-10-08 17:25:53 -070019#include <net/ip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <net/route.h>
21#include <net/ipv6.h>
22#include <net/ip6_fib.h>
Timo Teräsfe1a5f02010-04-07 00:30:04 +000023#include <net/flow.h>
Yury Polyanskiy9e0d57f2009-11-08 20:58:41 -080024
25#include <linux/interrupt.h>
26
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080027#ifdef CONFIG_XFRM_STATISTICS
28#include <net/snmp.h>
29#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Masahide NAKAMURAd3d6dd32007-06-26 23:57:49 -070031#define XFRM_PROTO_ESP 50
32#define XFRM_PROTO_AH 51
33#define XFRM_PROTO_COMP 108
34#define XFRM_PROTO_IPIP 4
35#define XFRM_PROTO_IPV6 41
36#define XFRM_PROTO_ROUTING IPPROTO_ROUTING
37#define XFRM_PROTO_DSTOPTS IPPROTO_DSTOPTS
38
Nicolas Dichtelfa9921e2011-02-02 06:29:02 +000039#define XFRM_ALIGN4(len) (((len) + 3) & ~3)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
Herbert Xub59f45d2006-05-27 23:05:54 -070041#define MODULE_ALIAS_XFRM_MODE(family, encap) \
42 MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
Masahide NAKAMURAd3d6dd32007-06-26 23:57:49 -070043#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
44 MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080046#ifdef CONFIG_XFRM_STATISTICS
Alexey Dobriyan59c99402008-11-25 17:59:52 -080047#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
48#define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field)
49#define XFRM_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)-mib.xfrm_statistics, field)
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080050#else
Alexey Dobriyan59c99402008-11-25 17:59:52 -080051#define XFRM_INC_STATS(net, field) ((void)(net))
52#define XFRM_INC_STATS_BH(net, field) ((void)(net))
53#define XFRM_INC_STATS_USER(net, field) ((void)(net))
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080054#endif
55
Arjan van de Ven4a3e2f72006-03-20 22:33:17 -080056extern struct mutex xfrm_cfg_mutex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58/* Organization of SPD aka "XFRM rules"
59 ------------------------------------
60
61 Basic objects:
62 - policy rule, struct xfrm_policy (=SPD entry)
63 - bundle of transformations, struct dst_entry == struct xfrm_dst (=SA bundle)
64 - instance of a transformer, struct xfrm_state (=SA)
65 - template to clone xfrm_state, struct xfrm_tmpl
66
67 SPD is plain linear list of xfrm_policy rules, ordered by priority.
68 (To be compatible with existing pfkeyv2 implementations,
69 many rules with priority of 0x7fffffff are allowed to exist and
70 such rules are ordered in an unpredictable way, thanks to bsd folks.)
71
72 Lookup is plain linear search until the first match with selector.
73
74 If "action" is "block", then we prohibit the flow, otherwise:
75 if "xfrms_nr" is zero, the flow passes untransformed. Otherwise,
76 policy entry has list of up to XFRM_MAX_DEPTH transformations,
77 described by templates xfrm_tmpl. Each template is resolved
78 to a complete xfrm_state (see below) and we pack bundle of transformations
79 to a dst_entry returned to requestor.
80
81 dst -. xfrm .-> xfrm_state #1
82 |---. child .-> dst -. xfrm .-> xfrm_state #2
83 |---. child .-> dst -. xfrm .-> xfrm_state #3
84 |---. child .-> NULL
85
86 Bundles are cached at xrfm_policy struct (field ->bundles).
87
88
89 Resolution of xrfm_tmpl
90 -----------------------
91 Template contains:
92 1. ->mode Mode: transport or tunnel
93 2. ->id.proto Protocol: AH/ESP/IPCOMP
94 3. ->id.daddr Remote tunnel endpoint, ignored for transport mode.
95 Q: allow to resolve security gateway?
96 4. ->id.spi If not zero, static SPI.
97 5. ->saddr Local tunnel endpoint, ignored for transport mode.
98 6. ->algos List of allowed algos. Plain bitmask now.
99 Q: ealgos, aalgos, calgos. What a mess...
100 7. ->share Sharing mode.
101 Q: how to implement private sharing mode? To add struct sock* to
102 flow id?
103
104 Having this template we search through SAD searching for entries
105 with appropriate mode/proto/algo, permitted by selector.
106 If no appropriate entry found, it is requested from key manager.
107
108 PROBLEMS:
109 Q: How to find all the bundles referring to a physical path for
110 PMTU discovery? Seems, dst should contain list of all parents...
111 and enter to infinite locking hierarchy disaster.
112 No! It is easier, we will not search for them, let them find us.
113 We add genid to each dst plus pointer to genid of raw IP route,
114 pmtu disc will update pmtu on raw IP route and increase its genid.
115 dst_check() will see this for top level and trigger resyncing
116 metrics. Plus, it will be made via sk->sk_dst_cache. Solved.
117 */
118
Herbert Xu12a169e2008-10-01 07:03:24 -0700119struct xfrm_state_walk {
120 struct list_head all;
121 u8 state;
122 union {
123 u8 dying;
124 u8 proto;
125 };
126 u32 seq;
127};
128
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129/* Full description of state of transformer. */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000130struct xfrm_state {
Alexey Dobriyan673c09b2008-11-25 17:15:16 -0800131#ifdef CONFIG_NET_NS
132 struct net *xs_net;
133#endif
Herbert Xuabb81c42008-09-09 19:58:29 -0700134 union {
Herbert Xu12a169e2008-10-01 07:03:24 -0700135 struct hlist_node gclist;
Herbert Xuabb81c42008-09-09 19:58:29 -0700136 struct hlist_node bydst;
137 };
David S. Miller8f126e32006-08-24 02:45:07 -0700138 struct hlist_node bysrc;
139 struct hlist_node byspi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141 atomic_t refcnt;
142 spinlock_t lock;
143
144 struct xfrm_id id;
145 struct xfrm_selector sel;
Jamal Hadi Salimbf825f82010-02-22 11:32:54 +0000146 struct xfrm_mark mark;
Martin Willi35d28562010-12-08 04:37:49 +0000147 u32 tfcpad;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
David S. Miller9d4a7062006-08-24 03:18:09 -0700149 u32 genid;
150
Herbert Xu12a169e2008-10-01 07:03:24 -0700151 /* Key manager bits */
152 struct xfrm_state_walk km;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154 /* Parameters of this state. */
155 struct {
156 u32 reqid;
157 u8 mode;
158 u8 replay_window;
159 u8 aalgo, ealgo, calgo;
160 u8 flags;
161 u16 family;
162 xfrm_address_t saddr;
163 int header_len;
164 int trailer_len;
165 } props;
166
167 struct xfrm_lifetime_cfg lft;
168
169 /* Data for transformer */
Martin Willi4447bb32009-11-25 00:29:52 +0000170 struct xfrm_algo_auth *aalg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 struct xfrm_algo *ealg;
172 struct xfrm_algo *calg;
Herbert Xu1a6509d2008-01-28 19:37:29 -0800173 struct xfrm_algo_aead *aead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
175 /* Data for encapsulator */
176 struct xfrm_encap_tmpl *encap;
177
Noriaki TAKAMIYA060f02a2006-08-23 18:18:55 -0700178 /* Data for care-of address */
179 xfrm_address_t *coaddr;
180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 /* IPComp needs an IPIP tunnel for handling uncompressed packets */
182 struct xfrm_state *tunnel;
183
184 /* If a tunnel, number of users + 1 */
185 atomic_t tunnel_users;
186
187 /* State for replay detection */
188 struct xfrm_replay_state replay;
Steffen Klassert9736acf2011-03-08 00:05:43 +0000189 struct xfrm_replay_state_esn *replay_esn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800191 /* Replay detection state at the time we sent the last notification */
192 struct xfrm_replay_state preplay;
Steffen Klassert9736acf2011-03-08 00:05:43 +0000193 struct xfrm_replay_state_esn *preplay_esn;
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800194
Steffen Klassert9fdc4882011-03-08 00:08:32 +0000195 /* The functions for replay detection. */
196 struct xfrm_replay *repl;
197
Jamal Hadi Salim27170962006-04-14 15:03:05 -0700198 /* internal flag that only holds state for delayed aevent at the
199 * moment
200 */
201 u32 xflags;
202
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800203 /* Replay detection notification settings */
204 u32 replay_maxage;
205 u32 replay_maxdiff;
206
207 /* Replay detection notification timer */
208 struct timer_list rtimer;
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /* Statistics */
211 struct xfrm_stats stats;
212
213 struct xfrm_lifetime_cur curlft;
Yury Polyanskiy9e0d57f2009-11-08 20:58:41 -0800214 struct tasklet_hrtimer mtimer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Masahide NAKAMURA9afaca02006-08-23 18:20:16 -0700216 /* Last used time */
Herbert Xud26f3982007-11-13 21:47:08 -0800217 unsigned long lastused;
Masahide NAKAMURA9afaca02006-08-23 18:20:16 -0700218
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 /* Reference to data common to all the instances of this
220 * transformer. */
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800221 const struct xfrm_type *type;
Herbert Xu13996372007-10-17 21:35:51 -0700222 struct xfrm_mode *inner_mode;
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -0700223 struct xfrm_mode *inner_mode_iaf;
Herbert Xu13996372007-10-17 21:35:51 -0700224 struct xfrm_mode *outer_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Trent Jaegerdf718372005-12-13 23:12:27 -0800226 /* Security context */
227 struct xfrm_sec_ctx *security;
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 /* Private data of this transformer, format is opaque,
230 * interpreted by xfrm_type methods. */
231 void *data;
232};
233
Alexey Dobriyan673c09b2008-11-25 17:15:16 -0800234static inline struct net *xs_net(struct xfrm_state *x)
235{
236 return read_pnet(&x->xs_net);
237}
238
Jamal Hadi Salim27170962006-04-14 15:03:05 -0700239/* xflags - make enum if more show up */
240#define XFRM_TIME_DEFER 1
241
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242enum {
243 XFRM_STATE_VOID,
244 XFRM_STATE_ACQ,
245 XFRM_STATE_VALID,
246 XFRM_STATE_ERROR,
247 XFRM_STATE_EXPIRED,
248 XFRM_STATE_DEAD
249};
250
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700251/* callback structure passed from either netlink or pfkey */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000252struct km_event {
Herbert Xubf088672005-06-18 22:44:00 -0700253 union {
254 u32 hard;
255 u32 proto;
256 u32 byid;
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800257 u32 aevent;
Masahide NAKAMURAf7b69832006-08-23 22:49:28 -0700258 u32 type;
Herbert Xubf088672005-06-18 22:44:00 -0700259 } data;
260
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700261 u32 seq;
262 u32 pid;
263 u32 event;
Alexey Dobriyan70678022008-11-25 17:50:36 -0800264 struct net *net;
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700265};
266
Steffen Klassert9fdc4882011-03-08 00:08:32 +0000267struct xfrm_replay {
268 void (*advance)(struct xfrm_state *x, __be32 net_seq);
269 int (*check)(struct xfrm_state *x,
270 struct sk_buff *skb,
271 __be32 net_seq);
Steffen Klassert20eb2082012-09-04 00:03:29 +0000272 int (*recheck)(struct xfrm_state *x,
273 struct sk_buff *skb,
274 __be32 net_seq);
Steffen Klassert9fdc4882011-03-08 00:08:32 +0000275 void (*notify)(struct xfrm_state *x, int event);
276 int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
277};
278
Herbert Xu25ee3282007-12-11 09:32:34 -0800279struct net_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280struct xfrm_type;
281struct xfrm_dst;
282struct xfrm_policy_afinfo {
283 unsigned short family;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 struct dst_ops *dst_ops;
Alexey Dobriyanddcfd792008-11-25 17:37:23 -0800285 void (*garbage_collect)(struct net *net);
Alexey Dobriyanc5b3cf42008-11-25 17:51:25 -0800286 struct dst_entry *(*dst_lookup)(struct net *net, int tos,
David S. Miller5e6b9302011-02-24 00:14:45 -0500287 const xfrm_address_t *saddr,
288 const xfrm_address_t *daddr);
Alexey Dobriyanfbda33b2008-11-25 17:56:49 -0800289 int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 void (*decode_session)(struct sk_buff *skb,
Herbert Xud5422ef2007-12-12 10:44:16 -0800291 struct flowi *fl,
292 int reverse);
David S. Miller05d84022011-02-22 17:47:10 -0800293 int (*get_tos)(const struct flowi *fl);
Masahide NAKAMURAa1b05142007-12-20 20:41:12 -0800294 int (*init_path)(struct xfrm_dst *path,
295 struct dst_entry *dst,
296 int nfheader_len);
Herbert Xu25ee3282007-12-11 09:32:34 -0800297 int (*fill_dst)(struct xfrm_dst *xdst,
Herbert Xu87c1e122010-03-02 02:51:56 +0000298 struct net_device *dev,
David S. Miller0c7b3ee2011-02-22 17:48:57 -0800299 const struct flowi *fl);
David S. Miller2774c132011-03-01 14:59:04 -0800300 struct dst_entry *(*blackhole_route)(struct net *net, struct dst_entry *orig);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301};
302
303extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
304extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
David S. Miller214e0052011-02-24 00:02:38 -0500305extern void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c);
306extern void km_state_notify(struct xfrm_state *x, const struct km_event *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308struct xfrm_tmpl;
Jamal Hadi Salim980ebd22006-03-20 19:16:40 -0800309extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
Jamal Hadi Salim53bc6b42006-03-20 19:17:03 -0800310extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
311extern int __xfrm_state_delete(struct xfrm_state *x);
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313struct xfrm_state_afinfo {
Herbert Xu17c2a422007-10-17 21:33:12 -0700314 unsigned int family;
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800315 unsigned int proto;
Al Viro8e3d7162008-03-17 22:49:16 -0700316 __be16 eth_proto;
Herbert Xu17c2a422007-10-17 21:33:12 -0700317 struct module *owner;
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800318 const struct xfrm_type *type_map[IPPROTO_MAX];
Herbert Xuaa5d62c2007-10-17 21:31:12 -0700319 struct xfrm_mode *mode_map[XFRM_MODE_MAX];
Herbert Xud094cd82005-06-20 13:19:41 -0700320 int (*init_flags)(struct xfrm_state *x);
David S. Miller73e5ebb2011-02-22 17:51:44 -0800321 void (*init_tempsel)(struct xfrm_selector *sel,
322 const struct flowi *fl);
David S. Miller19bd6242011-02-24 00:07:20 -0500323 void (*init_temprop)(struct xfrm_state *x,
324 const struct xfrm_tmpl *tmpl,
325 const xfrm_address_t *daddr,
326 const xfrm_address_t *saddr);
Masahide NAKAMURA41a49cc2006-08-23 22:48:31 -0700327 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
328 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
Miika Komucdca7262007-02-06 14:24:56 -0800329 int (*output)(struct sk_buff *skb);
Steffen Klassert43a4dea2011-05-09 19:36:38 +0000330 int (*output_finish)(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -0800331 int (*extract_input)(struct xfrm_state *x,
332 struct sk_buff *skb);
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800333 int (*extract_output)(struct xfrm_state *x,
334 struct sk_buff *skb);
Herbert Xu716062f2007-11-13 21:44:23 -0800335 int (*transport_finish)(struct sk_buff *skb,
336 int async);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337};
338
339extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
340extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
341
342extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
343
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000344struct xfrm_type {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 char *description;
346 struct module *owner;
jamala6337462010-02-09 13:21:17 +0000347 u8 proto;
348 u8 flags;
Masahide NAKAMURA1b5c2292006-08-23 18:11:50 -0700349#define XFRM_TYPE_NON_FRAGMENT 1
Herbert Xu436a0a42007-10-08 17:25:53 -0700350#define XFRM_TYPE_REPLAY_PROT 2
Herbert Xuf04e7e82007-11-13 21:36:51 -0800351#define XFRM_TYPE_LOCAL_COADDR 4
352#define XFRM_TYPE_REMOTE_COADDR 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Herbert Xu72cb6962005-06-20 13:18:08 -0700354 int (*init_state)(struct xfrm_state *x);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 void (*destructor)(struct xfrm_state *);
Herbert Xue6956332006-04-01 00:52:46 -0800356 int (*input)(struct xfrm_state *, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 int (*output)(struct xfrm_state *, struct sk_buff *pskb);
David S. Miller8f029de2011-02-22 17:59:59 -0800358 int (*reject)(struct xfrm_state *, struct sk_buff *,
359 const struct flowi *);
Masahide NAKAMURAaee5adb2006-08-23 17:57:28 -0700360 int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 /* Estimate maximal size of result of transformation of a dgram */
Patrick McHardyc5c25232007-04-09 11:47:18 -0700362 u32 (*get_mtu)(struct xfrm_state *, int size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363};
364
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800365extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
366extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Herbert Xub59f45d2006-05-27 23:05:54 -0700368struct xfrm_mode {
Herbert Xu227620e2007-11-13 21:41:28 -0800369 /*
370 * Remove encapsulation header.
371 *
372 * The IP header will be moved over the top of the encapsulation
373 * header.
374 *
375 * On entry, the transport header shall point to where the IP header
376 * should be and the network header shall be set to where the IP
377 * header currently is. skb->data shall point to the start of the
378 * payload.
379 */
380 int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
381
382 /*
383 * This is the actual input entry point.
384 *
385 * For transport mode and equivalent this would be identical to
386 * input2 (which does not need to be set). While tunnel mode
387 * and equivalent would set this to the tunnel encapsulation function
388 * xfrm4_prepare_input that would in turn call input2.
389 */
Herbert Xub59f45d2006-05-27 23:05:54 -0700390 int (*input)(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu37fedd32007-10-10 15:44:44 -0700391
392 /*
393 * Add encapsulation header.
394 *
395 * On exit, the transport header will be set to the start of the
396 * encapsulation header to be filled in by x->type->output and
397 * the mac header will be set to the nextheader (protocol for
398 * IPv4) field of the extension header directly preceding the
399 * encapsulation header, or in its absence, that of the top IP
400 * header. The value of the network header will always point
401 * to the top IP header while skb->data will point to the payload.
402 */
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800403 int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
404
405 /*
406 * This is the actual output entry point.
407 *
408 * For transport mode and equivalent this would be identical to
409 * output2 (which does not need to be set). While tunnel mode
410 * and equivalent would set this to a tunnel encapsulation function
411 * (xfrm4_prepare_output or xfrm6_prepare_output) that would in turn
412 * call output2.
413 */
414 int (*output)(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xub59f45d2006-05-27 23:05:54 -0700415
Herbert Xu17c2a422007-10-17 21:33:12 -0700416 struct xfrm_state_afinfo *afinfo;
Herbert Xub59f45d2006-05-27 23:05:54 -0700417 struct module *owner;
418 unsigned int encap;
Herbert Xu1bfcb102007-10-17 21:31:50 -0700419 int flags;
420};
421
422/* Flags for xfrm_mode. */
423enum {
424 XFRM_MODE_FLAG_TUNNEL = 1,
Herbert Xub59f45d2006-05-27 23:05:54 -0700425};
426
427extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
428extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
Herbert Xub59f45d2006-05-27 23:05:54 -0700429
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -0700430static inline int xfrm_af2proto(unsigned int family)
431{
432 switch(family) {
433 case AF_INET:
434 return IPPROTO_IPIP;
435 case AF_INET6:
436 return IPPROTO_IPV6;
437 default:
438 return 0;
439 }
440}
441
442static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
443{
444 if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
445 (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
446 return x->inner_mode;
447 else
448 return x->inner_mode_iaf;
449}
450
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000451struct xfrm_tmpl {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452/* id in template is interpreted as:
453 * daddr - destination of tunnel, may be zero for transport mode.
454 * spi - zero to acquire spi. Not zero if spi is static, then
455 * daddr must be fixed too.
456 * proto - AH/ESP/IPCOMP
457 */
458 struct xfrm_id id;
459
460/* Source address of tunnel. Ignored, if it is not a tunnel. */
461 xfrm_address_t saddr;
462
Miika Komu76b3f052006-11-30 16:40:43 -0800463 unsigned short encap_family;
464
jamala6337462010-02-09 13:21:17 +0000465 u32 reqid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Masahide NAKAMURA7e49e6d2006-09-22 15:05:15 -0700467/* Mode: transport, tunnel etc. */
jamala6337462010-02-09 13:21:17 +0000468 u8 mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470/* Sharing mode: unique, this session only, this user only etc. */
jamala6337462010-02-09 13:21:17 +0000471 u8 share;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
473/* May skip this transfomration if no SA is found */
jamala6337462010-02-09 13:21:17 +0000474 u8 optional;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Herbert Xuc5d18e92008-04-22 00:46:42 -0700476/* Skip aalgos/ealgos/calgos checks. */
jamala6337462010-02-09 13:21:17 +0000477 u8 allalgs;
Herbert Xuc5d18e92008-04-22 00:46:42 -0700478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479/* Bit mask of algos allowed for acquisition */
jamala6337462010-02-09 13:21:17 +0000480 u32 aalgos;
481 u32 ealgos;
482 u32 calgos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483};
484
Masahide NAKAMURA622dc822006-08-23 17:52:01 -0700485#define XFRM_MAX_DEPTH 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Herbert Xu12a169e2008-10-01 07:03:24 -0700487struct xfrm_policy_walk_entry {
488 struct list_head all;
489 u8 dead;
490};
491
492struct xfrm_policy_walk {
493 struct xfrm_policy_walk_entry walk;
494 u8 type;
495 u32 seq;
496};
497
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000498struct xfrm_policy {
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -0800499#ifdef CONFIG_NET_NS
500 struct net *xp_net;
501#endif
David S. Miller2518c7c2006-08-24 04:45:07 -0700502 struct hlist_node bydst;
503 struct hlist_node byidx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
505 /* This lock only affects elements except for entry. */
506 rwlock_t lock;
507 atomic_t refcnt;
508 struct timer_list timer;
509
Timo Teräsfe1a5f02010-04-07 00:30:04 +0000510 struct flow_cache_object flo;
Timo Teräs80c802f2010-04-07 00:30:05 +0000511 atomic_t genid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 u32 priority;
513 u32 index;
Jamal Hadi Salimbf825f82010-02-22 11:32:54 +0000514 struct xfrm_mark mark;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 struct xfrm_selector selector;
516 struct xfrm_lifetime_cfg lft;
517 struct xfrm_lifetime_cur curlft;
Herbert Xu12a169e2008-10-01 07:03:24 -0700518 struct xfrm_policy_walk_entry walk;
Arnaldo Carvalho de Melo46ca5f52006-11-27 17:58:59 -0200519 u8 type;
520 u8 action;
521 u8 flags;
Arnaldo Carvalho de Melo46ca5f52006-11-27 17:58:59 -0200522 u8 xfrm_nr;
Herbert Xu12a169e2008-10-01 07:03:24 -0700523 u16 family;
Trent Jaegerdf718372005-12-13 23:12:27 -0800524 struct xfrm_sec_ctx *security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
526};
527
David S. Miller63eb23f2011-02-24 01:25:19 -0500528static inline struct net *xp_net(const struct xfrm_policy *xp)
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -0800529{
530 return read_pnet(&xp->xp_net);
531}
532
Arnaud Ebalard13c1d182008-10-05 13:33:42 -0700533struct xfrm_kmaddress {
534 xfrm_address_t local;
535 xfrm_address_t remote;
536 u32 reserved;
537 u16 family;
538};
539
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -0800540struct xfrm_migrate {
541 xfrm_address_t old_daddr;
542 xfrm_address_t old_saddr;
543 xfrm_address_t new_daddr;
544 xfrm_address_t new_saddr;
545 u8 proto;
546 u8 mode;
547 u16 reserved;
548 u32 reqid;
549 u16 old_family;
550 u16 new_family;
551};
552
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800553#define XFRM_KM_TIMEOUT 30
554/* which seqno */
555#define XFRM_REPLAY_SEQ 1
556#define XFRM_REPLAY_OSEQ 2
557#define XFRM_REPLAY_SEQ_MASK 3
558/* what happened */
559#define XFRM_REPLAY_UPDATE XFRM_AE_CR
560#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
561
562/* default aevent timeout in units of 100ms */
563#define XFRM_AE_ETIME 10
564/* Async Event timer multiplier */
565#define XFRM_AE_ETH_M 10
566/* default seq threshold size */
567#define XFRM_AE_SEQT_SIZE 2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000569struct xfrm_mgr {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 struct list_head list;
571 char *id;
David S. Miller214e0052011-02-24 00:02:38 -0500572 int (*notify)(struct xfrm_state *x, const struct km_event *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
Venkat Yekkiralacb969f02006-07-24 23:32:20 -0700574 struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
Al Viro5d36b182006-11-08 00:24:06 -0800575 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
David S. Miller214e0052011-02-24 00:02:38 -0500576 int (*notify_policy)(struct xfrm_policy *x, int dir, const struct km_event *c);
Alexey Dobriyandb983c12008-11-25 17:51:01 -0800577 int (*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
David S. Miller183cad12011-02-24 00:28:01 -0500578 int (*migrate)(const struct xfrm_selector *sel,
579 u8 dir, u8 type,
580 const struct xfrm_migrate *m,
581 int num_bundles,
582 const struct xfrm_kmaddress *k);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583};
584
585extern int xfrm_register_km(struct xfrm_mgr *km);
586extern int xfrm_unregister_km(struct xfrm_mgr *km);
587
Herbert Xu436a0a42007-10-08 17:25:53 -0700588/*
589 * This structure is used for the duration where packets are being
590 * transformed by IPsec. As soon as the packet leaves IPsec the
591 * area beyond the generic IP part may be overwritten.
592 */
593struct xfrm_skb_cb {
594 union {
595 struct inet_skb_parm h4;
596 struct inet6_skb_parm h6;
597 } header;
598
599 /* Sequence number for replay protection. */
Herbert Xub318e0e2008-02-12 22:50:35 -0800600 union {
Steffen Klassert1ce36442011-03-08 00:06:31 +0000601 struct {
602 __u32 low;
603 __u32 hi;
604 } output;
605 struct {
606 __be32 low;
607 __be32 hi;
608 } input;
Herbert Xub318e0e2008-02-12 22:50:35 -0800609 } seq;
Herbert Xu436a0a42007-10-08 17:25:53 -0700610};
611
612#define XFRM_SKB_CB(__skb) ((struct xfrm_skb_cb *)&((__skb)->cb[0]))
613
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800614/*
615 * This structure is used by the afinfo prepare_input/prepare_output functions
616 * to transmit header information to the mode input/output functions.
617 */
618struct xfrm_mode_skb_cb {
619 union {
620 struct inet_skb_parm h4;
621 struct inet6_skb_parm h6;
622 } header;
623
624 /* Copied from header for IPv4, always set to zero and DF for IPv6. */
625 __be16 id;
626 __be16 frag_off;
627
Herbert Xu732c8bd2008-03-26 16:51:09 -0700628 /* IP header length (excluding options or extension headers). */
629 u8 ihl;
630
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800631 /* TOS for IPv4, class for IPv6. */
632 u8 tos;
633
634 /* TTL for IPv4, hop limitfor IPv6. */
635 u8 ttl;
636
637 /* Protocol for IPv4, NH for IPv6. */
638 u8 protocol;
639
Herbert Xu732c8bd2008-03-26 16:51:09 -0700640 /* Option length for IPv4, zero for IPv6. */
641 u8 optlen;
642
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800643 /* Used by IPv6 only, zero for IPv4. */
644 u8 flow_lbl[3];
645};
646
647#define XFRM_MODE_SKB_CB(__skb) ((struct xfrm_mode_skb_cb *)&((__skb)->cb[0]))
648
Herbert Xu716062f2007-11-13 21:44:23 -0800649/*
650 * This structure is used by the input processing to locate the SPI and
651 * related information.
652 */
653struct xfrm_spi_skb_cb {
654 union {
655 struct inet_skb_parm h4;
656 struct inet6_skb_parm h6;
657 } header;
658
Herbert Xu716062f2007-11-13 21:44:23 -0800659 unsigned int daddroff;
Herbert Xu2fcb45b2007-12-03 22:54:12 -0800660 unsigned int family;
Herbert Xu716062f2007-11-13 21:44:23 -0800661};
662
663#define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
664
Joy Latten161a09e2006-11-27 13:11:54 -0600665/* Audit Information */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000666struct xfrm_audit {
Joy Latten161a09e2006-11-27 13:11:54 -0600667 u32 secid;
Eric Paris25323862008-04-18 10:09:25 -0400668 uid_t loginuid;
669 u32 sessionid;
Joy Latten161a09e2006-11-27 13:11:54 -0600670};
Joy Lattenc9204d92006-11-30 15:50:43 -0600671
672#ifdef CONFIG_AUDITSYSCALL
Paul Mooreafeb14b2007-12-21 14:58:11 -0800673static inline struct audit_buffer *xfrm_audit_start(const char *op)
Joy Lattenab5f5e82007-09-17 11:51:22 -0700674{
675 struct audit_buffer *audit_buf = NULL;
Paul Mooreafeb14b2007-12-21 14:58:11 -0800676
677 if (audit_enabled == 0)
678 return NULL;
679 audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC,
680 AUDIT_MAC_IPSEC_EVENT);
681 if (audit_buf == NULL)
682 return NULL;
683 audit_log_format(audit_buf, "op=%s", op);
684 return audit_buf;
685}
686
Eric Paris25323862008-04-18 10:09:25 -0400687static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
Paul Mooreafeb14b2007-12-21 14:58:11 -0800688 struct audit_buffer *audit_buf)
689{
Joy Lattenab5f5e82007-09-17 11:51:22 -0700690 char *secctx;
691 u32 secctx_len;
692
Eric Paris25323862008-04-18 10:09:25 -0400693 audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
Paul Moore68277ac2007-12-20 20:49:33 -0800694 if (secid != 0 &&
695 security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
Joy Lattenab5f5e82007-09-17 11:51:22 -0700696 audit_log_format(audit_buf, " subj=%s", secctx);
697 security_release_secctx(secctx, secctx_len);
698 } else
699 audit_log_task_context(audit_buf);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700700}
701
702extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
Eric Paris25323862008-04-18 10:09:25 -0400703 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700704extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
Eric Paris25323862008-04-18 10:09:25 -0400705 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700706extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
Eric Paris25323862008-04-18 10:09:25 -0400707 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700708extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
Eric Paris25323862008-04-18 10:09:25 -0400709 u32 auid, u32 ses, u32 secid);
Paul Mooreafeb14b2007-12-21 14:58:11 -0800710extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
711 struct sk_buff *skb);
Steffen Klassert9fdc4882011-03-08 00:08:32 +0000712extern void xfrm_audit_state_replay(struct xfrm_state *x,
713 struct sk_buff *skb, __be32 net_seq);
Paul Mooreafeb14b2007-12-21 14:58:11 -0800714extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
715extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
716 __be32 net_spi, __be32 net_seq);
717extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
718 struct sk_buff *skb, u8 proto);
Joy Lattenc9204d92006-11-30 15:50:43 -0600719#else
Marcin Slusarz41fef0e2008-05-03 21:03:01 -0700720
721static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
722 u32 auid, u32 ses, u32 secid)
723{
724}
725
726static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
727 u32 auid, u32 ses, u32 secid)
728{
729}
730
731static inline void xfrm_audit_state_add(struct xfrm_state *x, int result,
732 u32 auid, u32 ses, u32 secid)
733{
734}
735
736static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result,
737 u32 auid, u32 ses, u32 secid)
738{
739}
740
741static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
742 struct sk_buff *skb)
743{
744}
745
Steffen Klassert9fdc4882011-03-08 00:08:32 +0000746static inline void xfrm_audit_state_replay(struct xfrm_state *x,
747 struct sk_buff *skb, __be32 net_seq)
748{
749}
750
Marcin Slusarz41fef0e2008-05-03 21:03:01 -0700751static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
752 u16 family)
753{
754}
755
756static inline void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
757 __be32 net_spi, __be32 net_seq)
758{
759}
760
761static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
762 struct sk_buff *skb, u8 proto)
763{
764}
Joy Lattenc9204d92006-11-30 15:50:43 -0600765#endif /* CONFIG_AUDITSYSCALL */
Joy Latten161a09e2006-11-27 13:11:54 -0600766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767static inline void xfrm_pol_hold(struct xfrm_policy *policy)
768{
769 if (likely(policy != NULL))
770 atomic_inc(&policy->refcnt);
771}
772
WANG Cong64c31b32008-01-07 22:34:29 -0800773extern void xfrm_policy_destroy(struct xfrm_policy *policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
775static inline void xfrm_pol_put(struct xfrm_policy *policy)
776{
777 if (atomic_dec_and_test(&policy->refcnt))
WANG Cong64c31b32008-01-07 22:34:29 -0800778 xfrm_policy_destroy(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -0700781static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
782{
783 int i;
784 for (i = npols - 1; i >= 0; --i)
785 xfrm_pol_put(pols[i]);
786}
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -0700787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788extern void __xfrm_state_destroy(struct xfrm_state *);
789
Herbert Xu21380b82006-02-22 14:47:13 -0800790static inline void __xfrm_state_put(struct xfrm_state *x)
791{
792 atomic_dec(&x->refcnt);
793}
794
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795static inline void xfrm_state_put(struct xfrm_state *x)
796{
797 if (atomic_dec_and_test(&x->refcnt))
798 __xfrm_state_destroy(x);
799}
800
801static inline void xfrm_state_hold(struct xfrm_state *x)
802{
803 atomic_inc(&x->refcnt);
804}
805
David S. Miller1744a8f2011-02-22 18:02:12 -0800806static inline bool addr_match(const void *token1, const void *token2,
807 int prefixlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
David S. Miller1744a8f2011-02-22 18:02:12 -0800809 const __be32 *a1 = token1;
810 const __be32 *a2 = token2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 int pdw;
812 int pbi;
813
jamala6337462010-02-09 13:21:17 +0000814 pdw = prefixlen >> 5; /* num of whole u32 in prefix */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
816
817 if (pdw)
818 if (memcmp(a1, a2, pdw << 2))
David S. Miller1744a8f2011-02-22 18:02:12 -0800819 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 if (pbi) {
Al Viro5f193432006-09-27 18:46:32 -0700822 __be32 mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824 mask = htonl((0xffffffff) << (32 - pbi));
825
826 if ((a1[pdw] ^ a2[pdw]) & mask)
David S. Miller1744a8f2011-02-22 18:02:12 -0800827 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829
David S. Miller1744a8f2011-02-22 18:02:12 -0800830 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831}
832
Alexey Dobriyan26bff942011-11-22 06:46:02 +0000833static inline bool addr4_match(__be32 a1, __be32 a2, u8 prefixlen)
834{
835 /* C99 6.5.7 (3): u32 << 32 is undefined behaviour */
836 if (prefixlen == 0)
837 return true;
838 return !((a1 ^ a2) & htonl(0xFFFFFFFFu << (32 - prefixlen)));
839}
840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841static __inline__
David S. Miller6281dcc2011-03-12 00:43:55 -0500842__be16 xfrm_flowi_sport(const struct flowi *fl, const union flowi_uli *uli)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843{
Al Virof9d07e41f82006-09-27 18:45:50 -0700844 __be16 port;
David S. Miller1d28f422011-03-12 00:29:39 -0500845 switch(fl->flowi_proto) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 case IPPROTO_TCP:
847 case IPPROTO_UDP:
Gerrit Renkerba4e58e2006-11-27 11:10:57 -0800848 case IPPROTO_UDPLITE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 case IPPROTO_SCTP:
David S. Miller6281dcc2011-03-12 00:43:55 -0500850 port = uli->ports.sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 break;
852 case IPPROTO_ICMP:
853 case IPPROTO_ICMPV6:
David S. Miller6281dcc2011-03-12 00:43:55 -0500854 port = htons(uli->icmpt.type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 break;
Masahide NAKAMURA2ce42722006-08-23 20:39:03 -0700856 case IPPROTO_MH:
David S. Miller6281dcc2011-03-12 00:43:55 -0500857 port = htons(uli->mht.type);
Masahide NAKAMURA2ce42722006-08-23 20:39:03 -0700858 break;
Timo Teräscc9ff192010-11-03 04:41:38 +0000859 case IPPROTO_GRE:
David S. Miller6281dcc2011-03-12 00:43:55 -0500860 port = htons(ntohl(uli->gre_key) >> 16);
Timo Teräscc9ff192010-11-03 04:41:38 +0000861 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 default:
863 port = 0; /*XXX*/
864 }
865 return port;
866}
867
868static __inline__
David S. Miller6281dcc2011-03-12 00:43:55 -0500869__be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870{
Al Virof9d07e41f82006-09-27 18:45:50 -0700871 __be16 port;
David S. Miller1d28f422011-03-12 00:29:39 -0500872 switch(fl->flowi_proto) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 case IPPROTO_TCP:
874 case IPPROTO_UDP:
Gerrit Renkerba4e58e2006-11-27 11:10:57 -0800875 case IPPROTO_UDPLITE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 case IPPROTO_SCTP:
David S. Miller6281dcc2011-03-12 00:43:55 -0500877 port = uli->ports.dport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 break;
879 case IPPROTO_ICMP:
880 case IPPROTO_ICMPV6:
David S. Miller6281dcc2011-03-12 00:43:55 -0500881 port = htons(uli->icmpt.code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 break;
Timo Teräscc9ff192010-11-03 04:41:38 +0000883 case IPPROTO_GRE:
David S. Miller6281dcc2011-03-12 00:43:55 -0500884 port = htons(ntohl(uli->gre_key) & 0xffff);
Timo Teräscc9ff192010-11-03 04:41:38 +0000885 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 default:
887 port = 0; /*XXX*/
888 }
889 return port;
890}
891
David S. Miller200ce962011-02-24 00:12:25 -0500892extern int xfrm_selector_match(const struct xfrm_selector *sel,
David S. Millere1ad2ab2011-02-22 18:07:39 -0800893 const struct flowi *fl,
Andrew Morton77681022006-11-08 22:46:26 -0800894 unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
Trent Jaegerdf718372005-12-13 23:12:27 -0800896#ifdef CONFIG_SECURITY_NETWORK_XFRM
897/* If neither has a context --> match
898 * Otherwise, both must have a context and the sids, doi, alg must match
899 */
900static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
901{
902 return ((!s1 && !s2) ||
903 (s1 && s2 &&
904 (s1->ctx_sid == s2->ctx_sid) &&
905 (s1->ctx_doi == s2->ctx_doi) &&
906 (s1->ctx_alg == s2->ctx_alg)));
907}
908#else
909static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
910{
911 return 1;
912}
913#endif
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915/* A struct encoding bundle of transformations to apply to some set of flow.
916 *
917 * dst->child points to the next element of bundle.
918 * dst->xfrm points to an instanse of transformer.
919 *
920 * Due to unfortunate limitations of current routing cache, which we
921 * have no time to fix, it mirrors struct rtable and bound to the same
922 * routing key, including saddr,daddr. However, we can have many of
923 * bundles differing by session id. All the bundles grow from a parent
924 * policy rule.
925 */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000926struct xfrm_dst {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 union {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 struct dst_entry dst;
929 struct rtable rt;
930 struct rt6_info rt6;
931 } u;
932 struct dst_entry *route;
Timo Teräs80c802f2010-04-07 00:30:05 +0000933 struct flow_cache_object flo;
934 struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
935 int num_pols, num_xfrms;
Masahide NAKAMURA157bfc22007-04-30 00:33:35 -0700936#ifdef CONFIG_XFRM_SUB_POLICY
937 struct flowi *origin;
938 struct xfrm_selector *partner;
939#endif
Timo Teräs80c802f2010-04-07 00:30:05 +0000940 u32 xfrm_genid;
941 u32 policy_genid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 u32 route_mtu_cached;
943 u32 child_mtu_cached;
Hideaki YOSHIFUJI92d63de2005-05-26 12:58:04 -0700944 u32 route_cookie;
945 u32 path_cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946};
947
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -0700948#ifdef CONFIG_XFRM
Herbert Xuaabc9762005-05-03 16:27:10 -0700949static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
950{
Timo Teräs80c802f2010-04-07 00:30:05 +0000951 xfrm_pols_put(xdst->pols, xdst->num_pols);
Herbert Xuaabc9762005-05-03 16:27:10 -0700952 dst_release(xdst->route);
953 if (likely(xdst->u.dst.xfrm))
954 xfrm_state_put(xdst->u.dst.xfrm);
Masahide NAKAMURA157bfc22007-04-30 00:33:35 -0700955#ifdef CONFIG_XFRM_SUB_POLICY
956 kfree(xdst->origin);
957 xdst->origin = NULL;
958 kfree(xdst->partner);
959 xdst->partner = NULL;
960#endif
Herbert Xuaabc9762005-05-03 16:27:10 -0700961}
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -0700962#endif
Herbert Xuaabc9762005-05-03 16:27:10 -0700963
964extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
965
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000966struct sec_path {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 atomic_t refcnt;
968 int len;
Herbert Xudbe5b4a2006-04-01 00:54:16 -0800969 struct xfrm_state *xvec[XFRM_MAX_DEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970};
971
Michael Smith990078a2011-04-07 04:51:51 +0000972static inline int secpath_exists(struct sk_buff *skb)
973{
974#ifdef CONFIG_XFRM
975 return skb->sp != NULL;
976#else
977 return 0;
978#endif
979}
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981static inline struct sec_path *
982secpath_get(struct sec_path *sp)
983{
984 if (sp)
985 atomic_inc(&sp->refcnt);
986 return sp;
987}
988
989extern void __secpath_destroy(struct sec_path *sp);
990
991static inline void
992secpath_put(struct sec_path *sp)
993{
994 if (sp && atomic_dec_and_test(&sp->refcnt))
995 __secpath_destroy(sp);
996}
997
998extern struct sec_path *secpath_dup(struct sec_path *src);
999
1000static inline void
1001secpath_reset(struct sk_buff *skb)
1002{
1003#ifdef CONFIG_XFRM
1004 secpath_put(skb->sp);
1005 skb->sp = NULL;
1006#endif
1007}
1008
1009static inline int
David S. Miller6cc32962011-02-24 00:19:59 -05001010xfrm_addr_any(const xfrm_address_t *addr, unsigned short family)
Patrick McHardya1e59ab2006-09-19 12:57:34 -07001011{
1012 switch (family) {
1013 case AF_INET:
1014 return addr->a4 == 0;
1015 case AF_INET6:
1016 return ipv6_addr_any((struct in6_addr *)&addr->a6);
1017 }
1018 return 0;
1019}
1020
1021static inline int
David S. Miller21eddb52011-02-24 01:35:16 -05001022__xfrm4_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023{
1024 return (tmpl->saddr.a4 &&
1025 tmpl->saddr.a4 != x->props.saddr.a4);
1026}
1027
1028static inline int
David S. Miller21eddb52011-02-24 01:35:16 -05001029__xfrm6_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030{
1031 return (!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) &&
1032 ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
1033}
1034
1035static inline int
David S. Miller21eddb52011-02-24 01:35:16 -05001036xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, unsigned short family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
1038 switch (family) {
1039 case AF_INET:
1040 return __xfrm4_state_addr_cmp(tmpl, x);
1041 case AF_INET6:
1042 return __xfrm6_state_addr_cmp(tmpl, x);
1043 }
1044 return !0;
1045}
1046
1047#ifdef CONFIG_XFRM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
1049
Herbert Xud5422ef2007-12-12 10:44:16 -08001050static inline int __xfrm_policy_check2(struct sock *sk, int dir,
1051 struct sk_buff *skb,
1052 unsigned int family, int reverse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053{
Alexey Dobriyanf6e1e252008-11-25 17:35:44 -08001054 struct net *net = dev_net(skb->dev);
Herbert Xud5422ef2007-12-12 10:44:16 -08001055 int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0);
1056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 if (sk && sk->sk_policy[XFRM_POLICY_IN])
Herbert Xud5422ef2007-12-12 10:44:16 -08001058 return __xfrm_policy_check(sk, ndir, skb, family);
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -07001059
Alexey Dobriyanf6e1e252008-11-25 17:35:44 -08001060 return (!net->xfrm.policy_count[dir] && !skb->sp) ||
Eric Dumazetadf30902009-06-02 05:19:30 +00001061 (skb_dst(skb)->flags & DST_NOPOLICY) ||
Herbert Xud5422ef2007-12-12 10:44:16 -08001062 __xfrm_policy_check(sk, ndir, skb, family);
1063}
1064
1065static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
1066{
1067 return __xfrm_policy_check2(sk, dir, skb, family, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068}
1069
1070static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1071{
1072 return xfrm_policy_check(sk, dir, skb, AF_INET);
1073}
1074
1075static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1076{
1077 return xfrm_policy_check(sk, dir, skb, AF_INET6);
1078}
1079
Herbert Xud5422ef2007-12-12 10:44:16 -08001080static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
1081 struct sk_buff *skb)
1082{
1083 return __xfrm_policy_check2(sk, dir, skb, AF_INET, 1);
1084}
1085
1086static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
1087 struct sk_buff *skb)
1088{
1089 return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1);
1090}
1091
1092extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
1093 unsigned int family, int reverse);
1094
1095static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
1096 unsigned int family)
1097{
1098 return __xfrm_decode_session(skb, fl, family, 0);
1099}
1100
1101static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
1102 struct flowi *fl,
1103 unsigned int family)
1104{
1105 return __xfrm_decode_session(skb, fl, family, 1);
1106}
1107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
1109
1110static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1111{
Alexey Dobriyan99a66652008-11-25 17:36:13 -08001112 struct net *net = dev_net(skb->dev);
1113
1114 return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
Eric Dumazetadf30902009-06-02 05:19:30 +00001115 (skb_dst(skb)->flags & DST_NOXFRM) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 __xfrm_route_forward(skb, family);
1117}
1118
1119static inline int xfrm4_route_forward(struct sk_buff *skb)
1120{
1121 return xfrm_route_forward(skb, AF_INET);
1122}
1123
1124static inline int xfrm6_route_forward(struct sk_buff *skb)
1125{
1126 return xfrm_route_forward(skb, AF_INET6);
1127}
1128
1129extern int __xfrm_sk_clone_policy(struct sock *sk);
1130
1131static inline int xfrm_sk_clone_policy(struct sock *sk)
1132{
1133 if (unlikely(sk->sk_policy[0] || sk->sk_policy[1]))
1134 return __xfrm_sk_clone_policy(sk);
1135 return 0;
1136}
1137
Herbert Xu4666faa2005-06-18 22:43:22 -07001138extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140static inline void xfrm_sk_free_policy(struct sock *sk)
1141{
1142 if (unlikely(sk->sk_policy[0] != NULL)) {
1143 xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
1144 sk->sk_policy[0] = NULL;
1145 }
1146 if (unlikely(sk->sk_policy[1] != NULL)) {
1147 xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
1148 sk->sk_policy[1] = NULL;
1149 }
1150}
1151
1152#else
1153
1154static inline void xfrm_sk_free_policy(struct sock *sk) {}
1155static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
1156static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }
1157static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; }
1158static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1159{
1160 return 1;
1161}
1162static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1163{
1164 return 1;
1165}
1166static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
1167{
1168 return 1;
1169}
Herbert Xud5422ef2007-12-12 10:44:16 -08001170static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
1171 struct flowi *fl,
1172 unsigned int family)
1173{
1174 return -ENOSYS;
1175}
1176static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
1177 struct sk_buff *skb)
1178{
1179 return 1;
1180}
1181static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
1182 struct sk_buff *skb)
1183{
1184 return 1;
1185}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186#endif
1187
1188static __inline__
David S. Millere8a4e372011-02-22 17:42:56 -08001189xfrm_address_t *xfrm_flowi_daddr(const struct flowi *fl, unsigned short family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
1191 switch (family){
1192 case AF_INET:
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001193 return (xfrm_address_t *)&fl->u.ip4.daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 case AF_INET6:
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001195 return (xfrm_address_t *)&fl->u.ip6.daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 }
1197 return NULL;
1198}
1199
1200static __inline__
David S. Millere8a4e372011-02-22 17:42:56 -08001201xfrm_address_t *xfrm_flowi_saddr(const struct flowi *fl, unsigned short family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202{
1203 switch (family){
1204 case AF_INET:
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001205 return (xfrm_address_t *)&fl->u.ip4.saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case AF_INET6:
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001207 return (xfrm_address_t *)&fl->u.ip6.saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209 return NULL;
1210}
1211
YOSHIFUJI Hideaki9bb182a2008-02-22 14:48:22 +09001212static __inline__
David S. Millere8a4e372011-02-22 17:42:56 -08001213void xfrm_flowi_addr_get(const struct flowi *fl,
YOSHIFUJI Hideaki9bb182a2008-02-22 14:48:22 +09001214 xfrm_address_t *saddr, xfrm_address_t *daddr,
1215 unsigned short family)
1216{
1217 switch(family) {
1218 case AF_INET:
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001219 memcpy(&saddr->a4, &fl->u.ip4.saddr, sizeof(saddr->a4));
1220 memcpy(&daddr->a4, &fl->u.ip4.daddr, sizeof(daddr->a4));
YOSHIFUJI Hideaki9bb182a2008-02-22 14:48:22 +09001221 break;
1222 case AF_INET6:
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001223 *(struct in6_addr *)saddr->a6 = fl->u.ip6.saddr;
1224 *(struct in6_addr *)daddr->a6 = fl->u.ip6.daddr;
YOSHIFUJI Hideaki9bb182a2008-02-22 14:48:22 +09001225 break;
1226 }
1227}
1228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229static __inline__ int
David S. Millerf8848062011-02-24 01:42:28 -05001230__xfrm4_state_addr_check(const struct xfrm_state *x,
1231 const xfrm_address_t *daddr, const xfrm_address_t *saddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
1233 if (daddr->a4 == x->id.daddr.a4 &&
1234 (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4))
1235 return 1;
1236 return 0;
1237}
1238
1239static __inline__ int
David S. Millerf8848062011-02-24 01:42:28 -05001240__xfrm6_state_addr_check(const struct xfrm_state *x,
1241 const xfrm_address_t *daddr, const xfrm_address_t *saddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242{
1243 if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) &&
1244 (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)||
1245 ipv6_addr_any((struct in6_addr *)saddr) ||
1246 ipv6_addr_any((struct in6_addr *)&x->props.saddr)))
1247 return 1;
1248 return 0;
1249}
1250
1251static __inline__ int
David S. Millerf8848062011-02-24 01:42:28 -05001252xfrm_state_addr_check(const struct xfrm_state *x,
1253 const xfrm_address_t *daddr, const xfrm_address_t *saddr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 unsigned short family)
1255{
1256 switch (family) {
1257 case AF_INET:
1258 return __xfrm4_state_addr_check(x, daddr, saddr);
1259 case AF_INET6:
1260 return __xfrm6_state_addr_check(x, daddr, saddr);
1261 }
1262 return 0;
1263}
1264
Masahide NAKAMURAe53820d2006-08-23 19:12:01 -07001265static __inline__ int
David S. Millerf8848062011-02-24 01:42:28 -05001266xfrm_state_addr_flow_check(const struct xfrm_state *x, const struct flowi *fl,
Masahide NAKAMURAe53820d2006-08-23 19:12:01 -07001267 unsigned short family)
1268{
1269 switch (family) {
1270 case AF_INET:
1271 return __xfrm4_state_addr_check(x,
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001272 (const xfrm_address_t *)&fl->u.ip4.daddr,
1273 (const xfrm_address_t *)&fl->u.ip4.saddr);
Masahide NAKAMURAe53820d2006-08-23 19:12:01 -07001274 case AF_INET6:
1275 return __xfrm6_state_addr_check(x,
David S. Miller7e1dc7b2011-03-12 02:42:11 -05001276 (const xfrm_address_t *)&fl->u.ip6.daddr,
1277 (const xfrm_address_t *)&fl->u.ip6.saddr);
Masahide NAKAMURAe53820d2006-08-23 19:12:01 -07001278 }
1279 return 0;
1280}
1281
David S. Millerf8848062011-02-24 01:42:28 -05001282static inline int xfrm_state_kern(const struct xfrm_state *x)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283{
1284 return atomic_read(&x->tunnel_users);
1285}
1286
Masahide NAKAMURA57947082006-09-22 15:06:24 -07001287static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
1288{
Masahide NAKAMURAdc00a522006-08-23 17:49:52 -07001289 return (!userproto || proto == userproto ||
1290 (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH ||
1291 proto == IPPROTO_ESP ||
1292 proto == IPPROTO_COMP)));
Masahide NAKAMURA57947082006-09-22 15:06:24 -07001293}
1294
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295/*
1296 * xfrm algorithm information
1297 */
Herbert Xu1a6509d2008-01-28 19:37:29 -08001298struct xfrm_algo_aead_info {
1299 u16 icv_truncbits;
1300};
1301
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302struct xfrm_algo_auth_info {
1303 u16 icv_truncbits;
1304 u16 icv_fullbits;
1305};
1306
1307struct xfrm_algo_encr_info {
1308 u16 blockbits;
1309 u16 defkeybits;
1310};
1311
1312struct xfrm_algo_comp_info {
1313 u16 threshold;
1314};
1315
1316struct xfrm_algo_desc {
1317 char *name;
Herbert Xu04ff1262006-08-13 08:50:00 +10001318 char *compat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 u8 available:1;
1320 union {
Herbert Xu1a6509d2008-01-28 19:37:29 -08001321 struct xfrm_algo_aead_info aead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 struct xfrm_algo_auth_info auth;
1323 struct xfrm_algo_encr_info encr;
1324 struct xfrm_algo_comp_info comp;
1325 } uinfo;
1326 struct sadb_alg desc;
1327};
1328
1329/* XFRM tunnel handlers. */
1330struct xfrm_tunnel {
1331 int (*handler)(struct sk_buff *skb);
jamala6337462010-02-09 13:21:17 +00001332 int (*err_handler)(struct sk_buff *skb, u32 info);
Herbert Xud2acc342006-03-28 01:12:13 -08001333
Eric Dumazetb33eab02010-10-25 21:01:26 +00001334 struct xfrm_tunnel __rcu *next;
Herbert Xud2acc342006-03-28 01:12:13 -08001335 int priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336};
1337
1338struct xfrm6_tunnel {
Herbert Xud2acc342006-03-28 01:12:13 -08001339 int (*handler)(struct sk_buff *skb);
1340 int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
Brian Haleyd5fdd6b2009-06-23 04:31:07 -07001341 u8 type, u8 code, int offset, __be32 info);
Eric Dumazet6f0bcf12010-10-24 21:33:16 +00001342 struct xfrm6_tunnel __rcu *next;
Herbert Xud2acc342006-03-28 01:12:13 -08001343 int priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344};
1345
1346extern void xfrm_init(void);
Neil Hormana33bc5c2009-07-30 18:52:15 -07001347extern void xfrm4_init(int rt_hash_size);
Alexey Dobriyand62ddc22008-11-25 17:14:31 -08001348extern int xfrm_state_init(struct net *net);
1349extern void xfrm_state_fini(struct net *net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350extern void xfrm4_state_init(void);
Daniel Lezcanoc35b7e72007-12-08 00:14:11 -08001351#ifdef CONFIG_XFRM
1352extern int xfrm6_init(void);
1353extern void xfrm6_fini(void);
Daniel Lezcano0013cab2007-12-07 00:42:11 -08001354extern int xfrm6_state_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355extern void xfrm6_state_fini(void);
Daniel Lezcanoc35b7e72007-12-08 00:14:11 -08001356#else
1357static inline int xfrm6_init(void)
1358{
1359 return 0;
1360}
1361static inline void xfrm6_fini(void)
1362{
1363 ;
1364}
1365#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -08001367#ifdef CONFIG_XFRM_STATISTICS
Alexey Dobriyanc68cd1a2008-11-25 18:00:14 -08001368extern int xfrm_proc_init(struct net *net);
1369extern void xfrm_proc_fini(struct net *net);
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -08001370#endif
1371
Alexey Dobriyanb27aead2008-11-25 18:00:48 -08001372extern int xfrm_sysctl_init(struct net *net);
1373#ifdef CONFIG_SYSCTL
1374extern void xfrm_sysctl_fini(struct net *net);
1375#else
1376static inline void xfrm_sysctl_fini(struct net *net)
1377{
1378}
1379#endif
1380
Herbert Xu5c182452008-09-22 19:48:19 -07001381extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
Alexey Dobriyan284fa7d2008-11-25 17:32:14 -08001382extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
Timo Teras4c563f72008-02-28 21:31:08 -08001383 int (*func)(struct xfrm_state *, int, void*), void *);
Herbert Xuabb81c42008-09-09 19:58:29 -07001384extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
Alexey Dobriyan673c09b2008-11-25 17:15:16 -08001385extern struct xfrm_state *xfrm_state_alloc(struct net *net);
David S. Miller33765d02011-02-24 01:55:45 -05001386extern struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
1387 const xfrm_address_t *saddr,
David S. Millerb520e9f2011-02-22 18:24:19 -08001388 const struct flowi *fl,
1389 struct xfrm_tmpl *tmpl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 struct xfrm_policy *pol, int *err,
1391 unsigned short family);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001392extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
Alexey Dobriyan5447c5e2008-11-25 17:31:51 -08001393 xfrm_address_t *daddr,
Jamal Hadi Salim628529b2007-07-02 22:41:14 -07001394 xfrm_address_t *saddr,
1395 unsigned short family,
1396 u8 mode, u8 proto, u32 reqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397extern int xfrm_state_check_expire(struct xfrm_state *x);
1398extern void xfrm_state_insert(struct xfrm_state *x);
1399extern int xfrm_state_add(struct xfrm_state *x);
1400extern int xfrm_state_update(struct xfrm_state *x);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001401extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
David S. Millera70486f2011-02-27 23:17:24 -08001402 const xfrm_address_t *daddr, __be32 spi,
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001403 u8 proto, unsigned short family);
1404extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
David S. Millera70486f2011-02-27 23:17:24 -08001405 const xfrm_address_t *daddr,
1406 const xfrm_address_t *saddr,
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001407 u8 proto,
1408 unsigned short family);
Masahide NAKAMURA41a49cc2006-08-23 22:48:31 -07001409#ifdef CONFIG_XFRM_SUB_POLICY
1410extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1411 int n, unsigned short family);
1412extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1413 int n, unsigned short family);
1414#else
1415static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1416 int n, unsigned short family)
1417{
1418 return -ENOSYS;
1419}
1420
1421static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1422 int n, unsigned short family)
1423{
1424 return -ENOSYS;
1425}
1426#endif
Jamal Hadi Salimaf11e312007-05-04 12:55:13 -07001427
1428struct xfrmk_sadinfo {
1429 u32 sadhcnt; /* current hash bkts */
1430 u32 sadhmcnt; /* max allowed hash bkts */
1431 u32 sadcnt; /* current running count */
1432};
1433
Jamal Hadi Salim5a6d3412007-05-04 12:55:39 -07001434struct xfrmk_spdinfo {
1435 u32 incnt;
1436 u32 outcnt;
1437 u32 fwdcnt;
1438 u32 inscnt;
1439 u32 outscnt;
1440 u32 fwdscnt;
1441 u32 spdhcnt;
1442 u32 spdhmcnt;
1443};
1444
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001445extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
1446 u32 seq);
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -07001447extern int xfrm_state_delete(struct xfrm_state *x);
Alexey Dobriyan0e602452008-11-25 17:30:18 -08001448extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
Alexey Dobriyane0710412010-01-23 13:37:10 +00001449extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
1450extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
Steffen Klassert2cd08462011-03-08 00:09:51 +00001451extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
Steffen Klassert9fdc4882011-03-08 00:08:32 +00001452extern int xfrm_init_replay(struct xfrm_state *x);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
Wei Yongjuna454f0c2011-03-21 18:08:28 -07001454extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
Herbert Xu72cb6962005-06-20 13:18:08 -07001455extern int xfrm_init_state(struct xfrm_state *x);
Herbert Xu227620e2007-11-13 21:41:28 -08001456extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu716062f2007-11-13 21:44:23 -08001457extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
1458 int encap_type);
Herbert Xu1bf06cd2007-11-19 18:50:17 -08001459extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
Herbert Xuc6581a42007-11-13 21:43:43 -08001460extern int xfrm_output_resume(struct sk_buff *skb, int err);
Herbert Xu406ef772007-10-08 17:16:30 -07001461extern int xfrm_output(struct sk_buff *skb);
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -07001462extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001463extern int xfrm4_extract_header(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -08001464extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xuc4541b42007-10-17 21:28:53 -07001465extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
1466 int encap_type);
Herbert Xu716062f2007-11-13 21:44:23 -08001467extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468extern int xfrm4_rcv(struct sk_buff *skb);
Herbert Xuc4541b42007-10-17 21:28:53 -07001469
1470static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
1471{
1472 return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
1473}
1474
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001475extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1476extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477extern int xfrm4_output(struct sk_buff *skb);
Steffen Klassert43a4dea2011-05-09 19:36:38 +00001478extern int xfrm4_output_finish(struct sk_buff *skb);
Kazunori MIYAZAWAc0d56402007-02-13 12:54:47 -08001479extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
1480extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001481extern int xfrm6_extract_header(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -08001482extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu33b5ecb2007-10-17 21:29:25 -07001483extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
Herbert Xu716062f2007-11-13 21:44:23 -08001484extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
Herbert Xue5bbef22007-10-15 12:50:28 -07001485extern int xfrm6_rcv(struct sk_buff *skb);
Masahide NAKAMURAfbd9a5b2006-08-23 18:08:21 -07001486extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
1487 xfrm_address_t *saddr, u8 proto);
Kazunori MIYAZAWA73d605d2007-02-13 12:55:55 -08001488extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
1489extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
Alexey Dobriyana1664772010-01-25 10:37:54 +00001490extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001491extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001492extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1493extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494extern int xfrm6_output(struct sk_buff *skb);
Steffen Klassert43a4dea2011-05-09 19:36:38 +00001495extern int xfrm6_output_finish(struct sk_buff *skb);
Masahide NAKAMURAaee5adb2006-08-23 17:57:28 -07001496extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
1497 u8 **prevhdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
1499#ifdef CONFIG_XFRM
James Chapman067b2072007-07-05 17:08:05 -07001500extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502#else
1503static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1504{
1505 return -ENOPROTOOPT;
1506}
1507
James Chapman067b2072007-07-05 17:08:05 -07001508static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
1510 /* should not happen */
1511 kfree_skb(skb);
1512 return 0;
1513}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514#endif
1515
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -08001516struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
Timo Teras4c563f72008-02-28 21:31:08 -08001517
Herbert Xu12a169e2008-10-01 07:03:24 -07001518extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
Alexey Dobriyancdcbca72008-11-25 17:34:49 -08001519extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
Timo Teras4c563f72008-02-28 21:31:08 -08001520 int (*func)(struct xfrm_policy *, int, int, void*), void *);
Herbert Xu12a169e2008-10-01 07:03:24 -07001521extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
Jamal Hadi Salim8ca2e932010-02-22 11:32:57 +00001523struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
1524 u8 type, int dir,
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -07001525 struct xfrm_selector *sel,
Eric Parisef41aaa2007-03-07 15:37:58 -08001526 struct xfrm_sec_ctx *ctx, int delete,
1527 int *err);
Jamal Hadi Salim8ca2e932010-02-22 11:32:57 +00001528struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err);
Alexey Dobriyan33ffbbd2008-11-25 17:33:32 -08001529int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530u32 xfrm_get_acqseq(void);
Herbert Xu658b2192007-10-09 13:29:52 -07001531extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001532struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
1533 u8 mode, u32 reqid, u8 proto,
David S. Millera70486f2011-02-27 23:17:24 -08001534 const xfrm_address_t *daddr,
1535 const xfrm_address_t *saddr, int create,
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001536 unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001539#ifdef CONFIG_XFRM_MIGRATE
David S. Miller183cad12011-02-24 00:28:01 -05001540extern int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1541 const struct xfrm_migrate *m, int num_bundles,
1542 const struct xfrm_kmaddress *k);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001543extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
1544extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
1545 struct xfrm_migrate *m);
David S. Millerb4b7c0b2011-02-24 00:35:06 -05001546extern int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
Arnaud Ebalard13c1d182008-10-05 13:33:42 -07001547 struct xfrm_migrate *m, int num_bundles,
1548 struct xfrm_kmaddress *k);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001549#endif
1550
Al Viro5d36b182006-11-08 00:24:06 -08001551extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
Jamal Hadi Salim6c5c8ca2006-03-20 19:17:25 -08001552extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
Alexey Dobriyandb983c12008-11-25 17:51:01 -08001553extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555extern void xfrm_input_init(void);
Al Viro6067b2b2006-09-27 18:47:59 -07001556extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
1558extern void xfrm_probe_algs(void);
1559extern int xfrm_count_auth_supported(void);
1560extern int xfrm_count_enc_supported(void);
1561extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
1562extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
1563extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
1564extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
1565extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
David S. Miller6f2f19e2011-02-27 23:04:45 -08001566extern struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe);
1567extern struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe);
1568extern struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe);
1569extern struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len,
Herbert Xu1a6509d2008-01-28 19:37:29 -08001570 int probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
David S. Millerff6acd12011-02-24 00:19:13 -05001572static inline int xfrm_addr_cmp(const xfrm_address_t *a,
1573 const xfrm_address_t *b,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 int family)
1575{
1576 switch (family) {
1577 default:
1578 case AF_INET:
jamala6337462010-02-09 13:21:17 +00001579 return (__force u32)a->a4 - (__force u32)b->a4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 case AF_INET6:
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001581 return ipv6_addr_cmp((const struct in6_addr *)a,
1582 (const struct in6_addr *)b);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 }
1584}
1585
Herbert Xu77d8d7a2005-10-05 12:15:12 -07001586static inline int xfrm_policy_id2dir(u32 index)
1587{
1588 return index & 7;
1589}
1590
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001591#ifdef CONFIG_XFRM
1592static inline int xfrm_aevent_is_on(struct net *net)
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001593{
Patrick McHardybe336902006-03-20 22:40:54 -08001594 struct sock *nlsk;
1595 int ret = 0;
1596
1597 rcu_read_lock();
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001598 nlsk = rcu_dereference(net->xfrm.nlsk);
Patrick McHardybe336902006-03-20 22:40:54 -08001599 if (nlsk)
1600 ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS);
1601 rcu_read_unlock();
1602 return ret;
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001603}
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001604#endif
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001605
David S. Miller85158622011-02-27 23:07:02 -08001606static inline int xfrm_alg_len(const struct xfrm_algo *alg)
Eric Dumazet0f99be02008-01-08 23:39:06 -08001607{
1608 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
1609}
1610
David S. Miller85158622011-02-27 23:07:02 -08001611static inline int xfrm_alg_auth_len(const struct xfrm_algo_auth *alg)
Martin Willi4447bb32009-11-25 00:29:52 +00001612{
1613 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
1614}
1615
Steffen Klassert9736acf2011-03-08 00:05:43 +00001616static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
1617{
1618 return sizeof(*replay_esn) + replay_esn->bmp_len * sizeof(__u32);
1619}
1620
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001621#ifdef CONFIG_XFRM_MIGRATE
Steffen Klassertaf2f4642011-03-28 19:46:39 +00001622static inline int xfrm_replay_clone(struct xfrm_state *x,
1623 struct xfrm_state *orig)
1624{
1625 x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
1626 GFP_KERNEL);
1627 if (!x->replay_esn)
1628 return -ENOMEM;
1629
1630 x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
1631 x->replay_esn->replay_window = orig->replay_esn->replay_window;
1632
1633 x->preplay_esn = kmemdup(x->replay_esn,
1634 xfrm_replay_state_esn_len(x->replay_esn),
1635 GFP_KERNEL);
1636 if (!x->preplay_esn) {
1637 kfree(x->replay_esn);
1638 return -ENOMEM;
1639 }
1640
1641 return 0;
1642}
1643
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001644static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
1645{
Eric Dumazet0f99be02008-01-08 23:39:06 -08001646 return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001647}
1648
Martin Willi4447bb32009-11-25 00:29:52 +00001649static inline struct xfrm_algo_auth *xfrm_algo_auth_clone(struct xfrm_algo_auth *orig)
1650{
1651 return kmemdup(orig, xfrm_alg_auth_len(orig), GFP_KERNEL);
1652}
1653
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001654static inline void xfrm_states_put(struct xfrm_state **states, int n)
1655{
1656 int i;
1657 for (i = 0; i < n; i++)
1658 xfrm_state_put(*(states + i));
1659}
1660
1661static inline void xfrm_states_delete(struct xfrm_state **states, int n)
1662{
1663 int i;
1664 for (i = 0; i < n; i++)
1665 xfrm_state_delete(*(states + i));
1666}
1667#endif
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001668
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07001669#ifdef CONFIG_XFRM
Herbert Xu00501122007-12-11 01:53:43 -08001670static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
1671{
1672 return skb->sp->xvec[skb->sp->len - 1];
1673}
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07001674#endif
Herbert Xu00501122007-12-11 01:53:43 -08001675
Jamal Hadi Salimbf825f82010-02-22 11:32:54 +00001676static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
1677{
1678 if (attrs[XFRMA_MARK])
Andreas Steffen4efd7e82010-06-30 10:41:15 -07001679 memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark));
Jamal Hadi Salimbf825f82010-02-22 11:32:54 +00001680 else
1681 m->v = m->m = 0;
1682
1683 return m->v & m->m;
1684}
1685
David S. Millere3dfa382011-02-27 23:20:19 -08001686static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
Jamal Hadi Salimbf825f82010-02-22 11:32:54 +00001687{
1688 if (m->m | m->v)
1689 NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
1690 return 0;
1691
1692nla_put_failure:
1693 return -1;
1694}
1695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696#endif /* _NET_XFRM_H */