blob: 693523c870b9fed2b33787d3e891afa3d3e5ca3b [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
16#include <net/sock.h>
17#include <net/dst.h>
Herbert Xu436a0a42007-10-08 17:25:53 -070018#include <net/ip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <net/route.h>
20#include <net/ipv6.h>
21#include <net/ip6_fib.h>
Yury Polyanskiy9e0d57f2009-11-08 20:58:41 -080022
23#include <linux/interrupt.h>
24
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080025#ifdef CONFIG_XFRM_STATISTICS
26#include <net/snmp.h>
27#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Masahide NAKAMURAd3d6dd32007-06-26 23:57:49 -070029#define XFRM_PROTO_ESP 50
30#define XFRM_PROTO_AH 51
31#define XFRM_PROTO_COMP 108
32#define XFRM_PROTO_IPIP 4
33#define XFRM_PROTO_IPV6 41
34#define XFRM_PROTO_ROUTING IPPROTO_ROUTING
35#define XFRM_PROTO_DSTOPTS IPPROTO_DSTOPTS
36
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
Herbert Xub59f45d2006-05-27 23:05:54 -070038#define MODULE_ALIAS_XFRM_MODE(family, encap) \
39 MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
Masahide NAKAMURAd3d6dd32007-06-26 23:57:49 -070040#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
41 MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080043#ifdef CONFIG_XFRM_STATISTICS
Alexey Dobriyan59c99402008-11-25 17:59:52 -080044#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
45#define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field)
46#define XFRM_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)-mib.xfrm_statistics, field)
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080047#else
Alexey Dobriyan59c99402008-11-25 17:59:52 -080048#define XFRM_INC_STATS(net, field) ((void)(net))
49#define XFRM_INC_STATS_BH(net, field) ((void)(net))
50#define XFRM_INC_STATS_USER(net, field) ((void)(net))
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -080051#endif
52
Arjan van de Ven4a3e2f72006-03-20 22:33:17 -080053extern struct mutex xfrm_cfg_mutex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55/* Organization of SPD aka "XFRM rules"
56 ------------------------------------
57
58 Basic objects:
59 - policy rule, struct xfrm_policy (=SPD entry)
60 - bundle of transformations, struct dst_entry == struct xfrm_dst (=SA bundle)
61 - instance of a transformer, struct xfrm_state (=SA)
62 - template to clone xfrm_state, struct xfrm_tmpl
63
64 SPD is plain linear list of xfrm_policy rules, ordered by priority.
65 (To be compatible with existing pfkeyv2 implementations,
66 many rules with priority of 0x7fffffff are allowed to exist and
67 such rules are ordered in an unpredictable way, thanks to bsd folks.)
68
69 Lookup is plain linear search until the first match with selector.
70
71 If "action" is "block", then we prohibit the flow, otherwise:
72 if "xfrms_nr" is zero, the flow passes untransformed. Otherwise,
73 policy entry has list of up to XFRM_MAX_DEPTH transformations,
74 described by templates xfrm_tmpl. Each template is resolved
75 to a complete xfrm_state (see below) and we pack bundle of transformations
76 to a dst_entry returned to requestor.
77
78 dst -. xfrm .-> xfrm_state #1
79 |---. child .-> dst -. xfrm .-> xfrm_state #2
80 |---. child .-> dst -. xfrm .-> xfrm_state #3
81 |---. child .-> NULL
82
83 Bundles are cached at xrfm_policy struct (field ->bundles).
84
85
86 Resolution of xrfm_tmpl
87 -----------------------
88 Template contains:
89 1. ->mode Mode: transport or tunnel
90 2. ->id.proto Protocol: AH/ESP/IPCOMP
91 3. ->id.daddr Remote tunnel endpoint, ignored for transport mode.
92 Q: allow to resolve security gateway?
93 4. ->id.spi If not zero, static SPI.
94 5. ->saddr Local tunnel endpoint, ignored for transport mode.
95 6. ->algos List of allowed algos. Plain bitmask now.
96 Q: ealgos, aalgos, calgos. What a mess...
97 7. ->share Sharing mode.
98 Q: how to implement private sharing mode? To add struct sock* to
99 flow id?
100
101 Having this template we search through SAD searching for entries
102 with appropriate mode/proto/algo, permitted by selector.
103 If no appropriate entry found, it is requested from key manager.
104
105 PROBLEMS:
106 Q: How to find all the bundles referring to a physical path for
107 PMTU discovery? Seems, dst should contain list of all parents...
108 and enter to infinite locking hierarchy disaster.
109 No! It is easier, we will not search for them, let them find us.
110 We add genid to each dst plus pointer to genid of raw IP route,
111 pmtu disc will update pmtu on raw IP route and increase its genid.
112 dst_check() will see this for top level and trigger resyncing
113 metrics. Plus, it will be made via sk->sk_dst_cache. Solved.
114 */
115
Herbert Xu12a169e2008-10-01 07:03:24 -0700116struct xfrm_state_walk {
117 struct list_head all;
118 u8 state;
119 union {
120 u8 dying;
121 u8 proto;
122 };
123 u32 seq;
124};
125
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126/* Full description of state of transformer. */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000127struct xfrm_state {
Alexey Dobriyan673c09b2008-11-25 17:15:16 -0800128#ifdef CONFIG_NET_NS
129 struct net *xs_net;
130#endif
Herbert Xuabb81c42008-09-09 19:58:29 -0700131 union {
Herbert Xu12a169e2008-10-01 07:03:24 -0700132 struct hlist_node gclist;
Herbert Xuabb81c42008-09-09 19:58:29 -0700133 struct hlist_node bydst;
134 };
David S. Miller8f126e32006-08-24 02:45:07 -0700135 struct hlist_node bysrc;
136 struct hlist_node byspi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 atomic_t refcnt;
139 spinlock_t lock;
140
141 struct xfrm_id id;
142 struct xfrm_selector sel;
Jamal Hadi Salimbf825f812010-02-22 11:32:54 +0000143 struct xfrm_mark mark;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
David S. Miller9d4a7062006-08-24 03:18:09 -0700145 u32 genid;
146
Herbert Xu12a169e2008-10-01 07:03:24 -0700147 /* Key manager bits */
148 struct xfrm_state_walk km;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 /* Parameters of this state. */
151 struct {
152 u32 reqid;
153 u8 mode;
154 u8 replay_window;
155 u8 aalgo, ealgo, calgo;
156 u8 flags;
157 u16 family;
158 xfrm_address_t saddr;
159 int header_len;
160 int trailer_len;
161 } props;
162
163 struct xfrm_lifetime_cfg lft;
164
165 /* Data for transformer */
Martin Willi4447bb32009-11-25 00:29:52 +0000166 struct xfrm_algo_auth *aalg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 struct xfrm_algo *ealg;
168 struct xfrm_algo *calg;
Herbert Xu1a6509d2008-01-28 19:37:29 -0800169 struct xfrm_algo_aead *aead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171 /* Data for encapsulator */
172 struct xfrm_encap_tmpl *encap;
173
Noriaki TAKAMIYA060f02a2006-08-23 18:18:55 -0700174 /* Data for care-of address */
175 xfrm_address_t *coaddr;
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 /* IPComp needs an IPIP tunnel for handling uncompressed packets */
178 struct xfrm_state *tunnel;
179
180 /* If a tunnel, number of users + 1 */
181 atomic_t tunnel_users;
182
183 /* State for replay detection */
184 struct xfrm_replay_state replay;
185
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800186 /* Replay detection state at the time we sent the last notification */
187 struct xfrm_replay_state preplay;
188
Jamal Hadi Salim27170962006-04-14 15:03:05 -0700189 /* internal flag that only holds state for delayed aevent at the
190 * moment
191 */
192 u32 xflags;
193
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800194 /* Replay detection notification settings */
195 u32 replay_maxage;
196 u32 replay_maxdiff;
197
198 /* Replay detection notification timer */
199 struct timer_list rtimer;
200
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 /* Statistics */
202 struct xfrm_stats stats;
203
204 struct xfrm_lifetime_cur curlft;
Yury Polyanskiy9e0d57f2009-11-08 20:58:41 -0800205 struct tasklet_hrtimer mtimer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Masahide NAKAMURA9afaca02006-08-23 18:20:16 -0700207 /* Last used time */
Herbert Xud26f3982007-11-13 21:47:08 -0800208 unsigned long lastused;
Masahide NAKAMURA9afaca02006-08-23 18:20:16 -0700209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /* Reference to data common to all the instances of this
211 * transformer. */
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800212 const struct xfrm_type *type;
Herbert Xu13996372007-10-17 21:35:51 -0700213 struct xfrm_mode *inner_mode;
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -0700214 struct xfrm_mode *inner_mode_iaf;
Herbert Xu13996372007-10-17 21:35:51 -0700215 struct xfrm_mode *outer_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
Trent Jaegerdf718372005-12-13 23:12:27 -0800217 /* Security context */
218 struct xfrm_sec_ctx *security;
219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 /* Private data of this transformer, format is opaque,
221 * interpreted by xfrm_type methods. */
222 void *data;
223};
224
Alexey Dobriyan673c09b2008-11-25 17:15:16 -0800225static inline struct net *xs_net(struct xfrm_state *x)
226{
227 return read_pnet(&x->xs_net);
228}
229
Jamal Hadi Salim27170962006-04-14 15:03:05 -0700230/* xflags - make enum if more show up */
231#define XFRM_TIME_DEFER 1
232
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233enum {
234 XFRM_STATE_VOID,
235 XFRM_STATE_ACQ,
236 XFRM_STATE_VALID,
237 XFRM_STATE_ERROR,
238 XFRM_STATE_EXPIRED,
239 XFRM_STATE_DEAD
240};
241
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700242/* callback structure passed from either netlink or pfkey */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000243struct km_event {
Herbert Xubf088672005-06-18 22:44:00 -0700244 union {
245 u32 hard;
246 u32 proto;
247 u32 byid;
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800248 u32 aevent;
Masahide NAKAMURAf7b69832006-08-23 22:49:28 -0700249 u32 type;
Herbert Xubf088672005-06-18 22:44:00 -0700250 } data;
251
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700252 u32 seq;
253 u32 pid;
254 u32 event;
Alexey Dobriyan70678022008-11-25 17:50:36 -0800255 struct net *net;
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700256};
257
Herbert Xu25ee3282007-12-11 09:32:34 -0800258struct net_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259struct xfrm_type;
260struct xfrm_dst;
261struct xfrm_policy_afinfo {
262 unsigned short family;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 struct dst_ops *dst_ops;
Alexey Dobriyanddcfd792008-11-25 17:37:23 -0800264 void (*garbage_collect)(struct net *net);
Alexey Dobriyanc5b3cf42008-11-25 17:51:25 -0800265 struct dst_entry *(*dst_lookup)(struct net *net, int tos,
266 xfrm_address_t *saddr,
Herbert Xu66cdb3c2007-11-13 21:37:28 -0800267 xfrm_address_t *daddr);
Alexey Dobriyanfbda33b2008-11-25 17:56:49 -0800268 int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 void (*decode_session)(struct sk_buff *skb,
Herbert Xud5422ef2007-12-12 10:44:16 -0800271 struct flowi *fl,
272 int reverse);
Herbert Xu25ee3282007-12-11 09:32:34 -0800273 int (*get_tos)(struct flowi *fl);
Masahide NAKAMURAa1b05142007-12-20 20:41:12 -0800274 int (*init_path)(struct xfrm_dst *path,
275 struct dst_entry *dst,
276 int nfheader_len);
Herbert Xu25ee3282007-12-11 09:32:34 -0800277 int (*fill_dst)(struct xfrm_dst *xdst,
278 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279};
280
281extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
282extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700283extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
284extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286struct xfrm_tmpl;
Jamal Hadi Salim980ebd22006-03-20 19:16:40 -0800287extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
Jamal Hadi Salim53bc6b42006-03-20 19:17:03 -0800288extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
289extern int __xfrm_state_delete(struct xfrm_state *x);
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291struct xfrm_state_afinfo {
Herbert Xu17c2a422007-10-17 21:33:12 -0700292 unsigned int family;
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800293 unsigned int proto;
Al Viro8e3d7162008-03-17 22:49:16 -0700294 __be16 eth_proto;
Herbert Xu17c2a422007-10-17 21:33:12 -0700295 struct module *owner;
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800296 const struct xfrm_type *type_map[IPPROTO_MAX];
Herbert Xuaa5d62c2007-10-17 21:31:12 -0700297 struct xfrm_mode *mode_map[XFRM_MODE_MAX];
Herbert Xud094cd82005-06-20 13:19:41 -0700298 int (*init_flags)(struct xfrm_state *x);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
300 struct xfrm_tmpl *tmpl,
301 xfrm_address_t *daddr, xfrm_address_t *saddr);
Masahide NAKAMURA41a49cc2006-08-23 22:48:31 -0700302 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
303 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
Miika Komucdca7262007-02-06 14:24:56 -0800304 int (*output)(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -0800305 int (*extract_input)(struct xfrm_state *x,
306 struct sk_buff *skb);
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800307 int (*extract_output)(struct xfrm_state *x,
308 struct sk_buff *skb);
Herbert Xu716062f2007-11-13 21:44:23 -0800309 int (*transport_finish)(struct sk_buff *skb,
310 int async);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311};
312
313extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
314extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
315
316extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
317
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000318struct xfrm_type {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 char *description;
320 struct module *owner;
jamala6337462010-02-09 13:21:17 +0000321 u8 proto;
322 u8 flags;
Masahide NAKAMURA1b5c2292006-08-23 18:11:50 -0700323#define XFRM_TYPE_NON_FRAGMENT 1
Herbert Xu436a0a42007-10-08 17:25:53 -0700324#define XFRM_TYPE_REPLAY_PROT 2
Herbert Xuf04e7e82007-11-13 21:36:51 -0800325#define XFRM_TYPE_LOCAL_COADDR 4
326#define XFRM_TYPE_REMOTE_COADDR 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Herbert Xu72cb6962005-06-20 13:18:08 -0700328 int (*init_state)(struct xfrm_state *x);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 void (*destructor)(struct xfrm_state *);
Herbert Xue6956332006-04-01 00:52:46 -0800330 int (*input)(struct xfrm_state *, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 int (*output)(struct xfrm_state *, struct sk_buff *pskb);
Masahide NAKAMURAdf0ba922006-08-23 20:41:00 -0700332 int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
Masahide NAKAMURAaee5adb2006-08-23 17:57:28 -0700333 int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 /* Estimate maximal size of result of transformation of a dgram */
Patrick McHardyc5c25232007-04-09 11:47:18 -0700335 u32 (*get_mtu)(struct xfrm_state *, int size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336};
337
Eric Dumazet533cb5b2008-01-30 19:11:50 -0800338extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
339extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Herbert Xub59f45d2006-05-27 23:05:54 -0700341struct xfrm_mode {
Herbert Xu227620e2007-11-13 21:41:28 -0800342 /*
343 * Remove encapsulation header.
344 *
345 * The IP header will be moved over the top of the encapsulation
346 * header.
347 *
348 * On entry, the transport header shall point to where the IP header
349 * should be and the network header shall be set to where the IP
350 * header currently is. skb->data shall point to the start of the
351 * payload.
352 */
353 int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
354
355 /*
356 * This is the actual input entry point.
357 *
358 * For transport mode and equivalent this would be identical to
359 * input2 (which does not need to be set). While tunnel mode
360 * and equivalent would set this to the tunnel encapsulation function
361 * xfrm4_prepare_input that would in turn call input2.
362 */
Herbert Xub59f45d2006-05-27 23:05:54 -0700363 int (*input)(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu37fedd32007-10-10 15:44:44 -0700364
365 /*
366 * Add encapsulation header.
367 *
368 * On exit, the transport header will be set to the start of the
369 * encapsulation header to be filled in by x->type->output and
370 * the mac header will be set to the nextheader (protocol for
371 * IPv4) field of the extension header directly preceding the
372 * encapsulation header, or in its absence, that of the top IP
373 * header. The value of the network header will always point
374 * to the top IP header while skb->data will point to the payload.
375 */
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800376 int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
377
378 /*
379 * This is the actual output entry point.
380 *
381 * For transport mode and equivalent this would be identical to
382 * output2 (which does not need to be set). While tunnel mode
383 * and equivalent would set this to a tunnel encapsulation function
384 * (xfrm4_prepare_output or xfrm6_prepare_output) that would in turn
385 * call output2.
386 */
387 int (*output)(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xub59f45d2006-05-27 23:05:54 -0700388
Herbert Xu17c2a422007-10-17 21:33:12 -0700389 struct xfrm_state_afinfo *afinfo;
Herbert Xub59f45d2006-05-27 23:05:54 -0700390 struct module *owner;
391 unsigned int encap;
Herbert Xu1bfcb102007-10-17 21:31:50 -0700392 int flags;
393};
394
395/* Flags for xfrm_mode. */
396enum {
397 XFRM_MODE_FLAG_TUNNEL = 1,
Herbert Xub59f45d2006-05-27 23:05:54 -0700398};
399
400extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
401extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
Herbert Xub59f45d2006-05-27 23:05:54 -0700402
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -0700403static inline int xfrm_af2proto(unsigned int family)
404{
405 switch(family) {
406 case AF_INET:
407 return IPPROTO_IPIP;
408 case AF_INET6:
409 return IPPROTO_IPV6;
410 default:
411 return 0;
412 }
413}
414
415static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
416{
417 if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
418 (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
419 return x->inner_mode;
420 else
421 return x->inner_mode_iaf;
422}
423
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000424struct xfrm_tmpl {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425/* id in template is interpreted as:
426 * daddr - destination of tunnel, may be zero for transport mode.
427 * spi - zero to acquire spi. Not zero if spi is static, then
428 * daddr must be fixed too.
429 * proto - AH/ESP/IPCOMP
430 */
431 struct xfrm_id id;
432
433/* Source address of tunnel. Ignored, if it is not a tunnel. */
434 xfrm_address_t saddr;
435
Miika Komu76b3f052006-11-30 16:40:43 -0800436 unsigned short encap_family;
437
jamala6337462010-02-09 13:21:17 +0000438 u32 reqid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Masahide NAKAMURA7e49e6d2006-09-22 15:05:15 -0700440/* Mode: transport, tunnel etc. */
jamala6337462010-02-09 13:21:17 +0000441 u8 mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443/* Sharing mode: unique, this session only, this user only etc. */
jamala6337462010-02-09 13:21:17 +0000444 u8 share;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
446/* May skip this transfomration if no SA is found */
jamala6337462010-02-09 13:21:17 +0000447 u8 optional;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
Herbert Xuc5d18e92008-04-22 00:46:42 -0700449/* Skip aalgos/ealgos/calgos checks. */
jamala6337462010-02-09 13:21:17 +0000450 u8 allalgs;
Herbert Xuc5d18e92008-04-22 00:46:42 -0700451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452/* Bit mask of algos allowed for acquisition */
jamala6337462010-02-09 13:21:17 +0000453 u32 aalgos;
454 u32 ealgos;
455 u32 calgos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456};
457
Masahide NAKAMURA622dc822006-08-23 17:52:01 -0700458#define XFRM_MAX_DEPTH 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Herbert Xu12a169e2008-10-01 07:03:24 -0700460struct xfrm_policy_walk_entry {
461 struct list_head all;
462 u8 dead;
463};
464
465struct xfrm_policy_walk {
466 struct xfrm_policy_walk_entry walk;
467 u8 type;
468 u32 seq;
469};
470
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000471struct xfrm_policy {
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -0800472#ifdef CONFIG_NET_NS
473 struct net *xp_net;
474#endif
David S. Miller2518c7c2006-08-24 04:45:07 -0700475 struct hlist_node bydst;
476 struct hlist_node byidx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
478 /* This lock only affects elements except for entry. */
479 rwlock_t lock;
480 atomic_t refcnt;
481 struct timer_list timer;
482
483 u32 priority;
484 u32 index;
Jamal Hadi Salimbf825f812010-02-22 11:32:54 +0000485 struct xfrm_mark mark;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 struct xfrm_selector selector;
487 struct xfrm_lifetime_cfg lft;
488 struct xfrm_lifetime_cur curlft;
489 struct dst_entry *bundles;
Herbert Xu12a169e2008-10-01 07:03:24 -0700490 struct xfrm_policy_walk_entry walk;
Arnaldo Carvalho de Melo46ca5f52006-11-27 17:58:59 -0200491 u8 type;
492 u8 action;
493 u8 flags;
Arnaldo Carvalho de Melo46ca5f52006-11-27 17:58:59 -0200494 u8 xfrm_nr;
Herbert Xu12a169e2008-10-01 07:03:24 -0700495 u16 family;
Trent Jaegerdf718372005-12-13 23:12:27 -0800496 struct xfrm_sec_ctx *security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
498};
499
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -0800500static inline struct net *xp_net(struct xfrm_policy *xp)
501{
502 return read_pnet(&xp->xp_net);
503}
504
Arnaud Ebalard13c1d182008-10-05 13:33:42 -0700505struct xfrm_kmaddress {
506 xfrm_address_t local;
507 xfrm_address_t remote;
508 u32 reserved;
509 u16 family;
510};
511
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -0800512struct xfrm_migrate {
513 xfrm_address_t old_daddr;
514 xfrm_address_t old_saddr;
515 xfrm_address_t new_daddr;
516 xfrm_address_t new_saddr;
517 u8 proto;
518 u8 mode;
519 u16 reserved;
520 u32 reqid;
521 u16 old_family;
522 u16 new_family;
523};
524
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -0800525#define XFRM_KM_TIMEOUT 30
526/* which seqno */
527#define XFRM_REPLAY_SEQ 1
528#define XFRM_REPLAY_OSEQ 2
529#define XFRM_REPLAY_SEQ_MASK 3
530/* what happened */
531#define XFRM_REPLAY_UPDATE XFRM_AE_CR
532#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
533
534/* default aevent timeout in units of 100ms */
535#define XFRM_AE_ETIME 10
536/* Async Event timer multiplier */
537#define XFRM_AE_ETH_M 10
538/* default seq threshold size */
539#define XFRM_AE_SEQT_SIZE 2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000541struct xfrm_mgr {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 struct list_head list;
543 char *id;
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700544 int (*notify)(struct xfrm_state *x, struct km_event *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
Venkat Yekkiralacb969f02006-07-24 23:32:20 -0700546 struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
Al Viro5d36b182006-11-08 00:24:06 -0800547 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -0700548 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
Alexey Dobriyandb983c12008-11-25 17:51:01 -0800549 int (*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
Arnaud Ebalard13c1d182008-10-05 13:33:42 -0700550 int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551};
552
553extern int xfrm_register_km(struct xfrm_mgr *km);
554extern int xfrm_unregister_km(struct xfrm_mgr *km);
555
Herbert Xu436a0a42007-10-08 17:25:53 -0700556/*
557 * This structure is used for the duration where packets are being
558 * transformed by IPsec. As soon as the packet leaves IPsec the
559 * area beyond the generic IP part may be overwritten.
560 */
561struct xfrm_skb_cb {
562 union {
563 struct inet_skb_parm h4;
564 struct inet6_skb_parm h6;
565 } header;
566
567 /* Sequence number for replay protection. */
Herbert Xub318e0e2008-02-12 22:50:35 -0800568 union {
569 u64 output;
570 __be32 input;
571 } seq;
Herbert Xu436a0a42007-10-08 17:25:53 -0700572};
573
574#define XFRM_SKB_CB(__skb) ((struct xfrm_skb_cb *)&((__skb)->cb[0]))
575
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800576/*
577 * This structure is used by the afinfo prepare_input/prepare_output functions
578 * to transmit header information to the mode input/output functions.
579 */
580struct xfrm_mode_skb_cb {
581 union {
582 struct inet_skb_parm h4;
583 struct inet6_skb_parm h6;
584 } header;
585
586 /* Copied from header for IPv4, always set to zero and DF for IPv6. */
587 __be16 id;
588 __be16 frag_off;
589
Herbert Xu732c8bd2008-03-26 16:51:09 -0700590 /* IP header length (excluding options or extension headers). */
591 u8 ihl;
592
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800593 /* TOS for IPv4, class for IPv6. */
594 u8 tos;
595
596 /* TTL for IPv4, hop limitfor IPv6. */
597 u8 ttl;
598
599 /* Protocol for IPv4, NH for IPv6. */
600 u8 protocol;
601
Herbert Xu732c8bd2008-03-26 16:51:09 -0700602 /* Option length for IPv4, zero for IPv6. */
603 u8 optlen;
604
Herbert Xu36cf9ac2007-11-13 21:40:52 -0800605 /* Used by IPv6 only, zero for IPv4. */
606 u8 flow_lbl[3];
607};
608
609#define XFRM_MODE_SKB_CB(__skb) ((struct xfrm_mode_skb_cb *)&((__skb)->cb[0]))
610
Herbert Xu716062f2007-11-13 21:44:23 -0800611/*
612 * This structure is used by the input processing to locate the SPI and
613 * related information.
614 */
615struct xfrm_spi_skb_cb {
616 union {
617 struct inet_skb_parm h4;
618 struct inet6_skb_parm h6;
619 } header;
620
Herbert Xu716062f2007-11-13 21:44:23 -0800621 unsigned int daddroff;
Herbert Xu2fcb45b2007-12-03 22:54:12 -0800622 unsigned int family;
Herbert Xu716062f2007-11-13 21:44:23 -0800623};
624
625#define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
626
Joy Latten161a09e2006-11-27 13:11:54 -0600627/* Audit Information */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000628struct xfrm_audit {
Joy Latten161a09e2006-11-27 13:11:54 -0600629 u32 secid;
Eric Paris25323862008-04-18 10:09:25 -0400630 uid_t loginuid;
631 u32 sessionid;
Joy Latten161a09e2006-11-27 13:11:54 -0600632};
Joy Lattenc9204d92006-11-30 15:50:43 -0600633
634#ifdef CONFIG_AUDITSYSCALL
Paul Mooreafeb14b2007-12-21 14:58:11 -0800635static inline struct audit_buffer *xfrm_audit_start(const char *op)
Joy Lattenab5f5e82007-09-17 11:51:22 -0700636{
637 struct audit_buffer *audit_buf = NULL;
Paul Mooreafeb14b2007-12-21 14:58:11 -0800638
639 if (audit_enabled == 0)
640 return NULL;
641 audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC,
642 AUDIT_MAC_IPSEC_EVENT);
643 if (audit_buf == NULL)
644 return NULL;
645 audit_log_format(audit_buf, "op=%s", op);
646 return audit_buf;
647}
648
Eric Paris25323862008-04-18 10:09:25 -0400649static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
Paul Mooreafeb14b2007-12-21 14:58:11 -0800650 struct audit_buffer *audit_buf)
651{
Joy Lattenab5f5e82007-09-17 11:51:22 -0700652 char *secctx;
653 u32 secctx_len;
654
Eric Paris25323862008-04-18 10:09:25 -0400655 audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
Paul Moore68277ac2007-12-20 20:49:33 -0800656 if (secid != 0 &&
657 security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
Joy Lattenab5f5e82007-09-17 11:51:22 -0700658 audit_log_format(audit_buf, " subj=%s", secctx);
659 security_release_secctx(secctx, secctx_len);
660 } else
661 audit_log_task_context(audit_buf);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700662}
663
664extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
Eric Paris25323862008-04-18 10:09:25 -0400665 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700666extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
Eric Paris25323862008-04-18 10:09:25 -0400667 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700668extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
Eric Paris25323862008-04-18 10:09:25 -0400669 u32 auid, u32 ses, u32 secid);
Joy Lattenab5f5e82007-09-17 11:51:22 -0700670extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
Eric Paris25323862008-04-18 10:09:25 -0400671 u32 auid, u32 ses, u32 secid);
Paul Mooreafeb14b2007-12-21 14:58:11 -0800672extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
673 struct sk_buff *skb);
674extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
675extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
676 __be32 net_spi, __be32 net_seq);
677extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
678 struct sk_buff *skb, u8 proto);
Joy Lattenc9204d92006-11-30 15:50:43 -0600679#else
Marcin Slusarz41fef0e2008-05-03 21:03:01 -0700680
681static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
682 u32 auid, u32 ses, u32 secid)
683{
684}
685
686static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
687 u32 auid, u32 ses, u32 secid)
688{
689}
690
691static inline void xfrm_audit_state_add(struct xfrm_state *x, int result,
692 u32 auid, u32 ses, u32 secid)
693{
694}
695
696static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result,
697 u32 auid, u32 ses, u32 secid)
698{
699}
700
701static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
702 struct sk_buff *skb)
703{
704}
705
706static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
707 u16 family)
708{
709}
710
711static inline void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
712 __be32 net_spi, __be32 net_seq)
713{
714}
715
716static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
717 struct sk_buff *skb, u8 proto)
718{
719}
Joy Lattenc9204d92006-11-30 15:50:43 -0600720#endif /* CONFIG_AUDITSYSCALL */
Joy Latten161a09e2006-11-27 13:11:54 -0600721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722static inline void xfrm_pol_hold(struct xfrm_policy *policy)
723{
724 if (likely(policy != NULL))
725 atomic_inc(&policy->refcnt);
726}
727
WANG Cong64c31b32008-01-07 22:34:29 -0800728extern void xfrm_policy_destroy(struct xfrm_policy *policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730static inline void xfrm_pol_put(struct xfrm_policy *policy)
731{
732 if (atomic_dec_and_test(&policy->refcnt))
WANG Cong64c31b32008-01-07 22:34:29 -0800733 xfrm_policy_destroy(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734}
735
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -0700736#ifdef CONFIG_XFRM_SUB_POLICY
737static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
738{
739 int i;
740 for (i = npols - 1; i >= 0; --i)
741 xfrm_pol_put(pols[i]);
742}
743#else
744static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
745{
746 xfrm_pol_put(pols[0]);
747}
748#endif
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750extern void __xfrm_state_destroy(struct xfrm_state *);
751
Herbert Xu21380b82006-02-22 14:47:13 -0800752static inline void __xfrm_state_put(struct xfrm_state *x)
753{
754 atomic_dec(&x->refcnt);
755}
756
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757static inline void xfrm_state_put(struct xfrm_state *x)
758{
759 if (atomic_dec_and_test(&x->refcnt))
760 __xfrm_state_destroy(x);
761}
762
763static inline void xfrm_state_hold(struct xfrm_state *x)
764{
765 atomic_inc(&x->refcnt);
766}
767
768static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
769{
Al Viro5f193432006-09-27 18:46:32 -0700770 __be32 *a1 = token1;
771 __be32 *a2 = token2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 int pdw;
773 int pbi;
774
jamala6337462010-02-09 13:21:17 +0000775 pdw = prefixlen >> 5; /* num of whole u32 in prefix */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
777
778 if (pdw)
779 if (memcmp(a1, a2, pdw << 2))
780 return 0;
781
782 if (pbi) {
Al Viro5f193432006-09-27 18:46:32 -0700783 __be32 mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
785 mask = htonl((0xffffffff) << (32 - pbi));
786
787 if ((a1[pdw] ^ a2[pdw]) & mask)
788 return 0;
789 }
790
791 return 1;
792}
793
794static __inline__
Al Virof9d07e41f82006-09-27 18:45:50 -0700795__be16 xfrm_flowi_sport(struct flowi *fl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796{
Al Virof9d07e41f82006-09-27 18:45:50 -0700797 __be16 port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 switch(fl->proto) {
799 case IPPROTO_TCP:
800 case IPPROTO_UDP:
Gerrit Renkerba4e58e2006-11-27 11:10:57 -0800801 case IPPROTO_UDPLITE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 case IPPROTO_SCTP:
803 port = fl->fl_ip_sport;
804 break;
805 case IPPROTO_ICMP:
806 case IPPROTO_ICMPV6:
807 port = htons(fl->fl_icmp_type);
808 break;
Masahide NAKAMURA2ce42722006-08-23 20:39:03 -0700809 case IPPROTO_MH:
810 port = htons(fl->fl_mh_type);
811 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 default:
813 port = 0; /*XXX*/
814 }
815 return port;
816}
817
818static __inline__
Al Virof9d07e41f82006-09-27 18:45:50 -0700819__be16 xfrm_flowi_dport(struct flowi *fl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
Al Virof9d07e41f82006-09-27 18:45:50 -0700821 __be16 port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 switch(fl->proto) {
823 case IPPROTO_TCP:
824 case IPPROTO_UDP:
Gerrit Renkerba4e58e2006-11-27 11:10:57 -0800825 case IPPROTO_UDPLITE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 case IPPROTO_SCTP:
827 port = fl->fl_ip_dport;
828 break;
829 case IPPROTO_ICMP:
830 case IPPROTO_ICMPV6:
831 port = htons(fl->fl_icmp_code);
832 break;
833 default:
834 port = 0; /*XXX*/
835 }
836 return port;
837}
838
Andrew Morton77681022006-11-08 22:46:26 -0800839extern int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
840 unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Trent Jaegerdf718372005-12-13 23:12:27 -0800842#ifdef CONFIG_SECURITY_NETWORK_XFRM
843/* If neither has a context --> match
844 * Otherwise, both must have a context and the sids, doi, alg must match
845 */
846static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
847{
848 return ((!s1 && !s2) ||
849 (s1 && s2 &&
850 (s1->ctx_sid == s2->ctx_sid) &&
851 (s1->ctx_doi == s2->ctx_doi) &&
852 (s1->ctx_alg == s2->ctx_alg)));
853}
854#else
855static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
856{
857 return 1;
858}
859#endif
860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861/* A struct encoding bundle of transformations to apply to some set of flow.
862 *
863 * dst->child points to the next element of bundle.
864 * dst->xfrm points to an instanse of transformer.
865 *
866 * Due to unfortunate limitations of current routing cache, which we
867 * have no time to fix, it mirrors struct rtable and bound to the same
868 * routing key, including saddr,daddr. However, we can have many of
869 * bundles differing by session id. All the bundles grow from a parent
870 * policy rule.
871 */
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000872struct xfrm_dst {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 union {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 struct dst_entry dst;
875 struct rtable rt;
876 struct rt6_info rt6;
877 } u;
878 struct dst_entry *route;
Masahide NAKAMURA157bfc22007-04-30 00:33:35 -0700879#ifdef CONFIG_XFRM_SUB_POLICY
880 struct flowi *origin;
881 struct xfrm_selector *partner;
882#endif
David S. Miller9d4a7062006-08-24 03:18:09 -0700883 u32 genid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 u32 route_mtu_cached;
885 u32 child_mtu_cached;
Hideaki YOSHIFUJI92d63dec2005-05-26 12:58:04 -0700886 u32 route_cookie;
887 u32 path_cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888};
889
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -0700890#ifdef CONFIG_XFRM
Herbert Xuaabc9762005-05-03 16:27:10 -0700891static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
892{
893 dst_release(xdst->route);
894 if (likely(xdst->u.dst.xfrm))
895 xfrm_state_put(xdst->u.dst.xfrm);
Masahide NAKAMURA157bfc22007-04-30 00:33:35 -0700896#ifdef CONFIG_XFRM_SUB_POLICY
897 kfree(xdst->origin);
898 xdst->origin = NULL;
899 kfree(xdst->partner);
900 xdst->partner = NULL;
901#endif
Herbert Xuaabc9762005-05-03 16:27:10 -0700902}
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -0700903#endif
Herbert Xuaabc9762005-05-03 16:27:10 -0700904
905extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
906
Eric Dumazetfd2c3ef2009-11-03 03:26:03 +0000907struct sec_path {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 atomic_t refcnt;
909 int len;
Herbert Xudbe5b4a2006-04-01 00:54:16 -0800910 struct xfrm_state *xvec[XFRM_MAX_DEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911};
912
913static inline struct sec_path *
914secpath_get(struct sec_path *sp)
915{
916 if (sp)
917 atomic_inc(&sp->refcnt);
918 return sp;
919}
920
921extern void __secpath_destroy(struct sec_path *sp);
922
923static inline void
924secpath_put(struct sec_path *sp)
925{
926 if (sp && atomic_dec_and_test(&sp->refcnt))
927 __secpath_destroy(sp);
928}
929
930extern struct sec_path *secpath_dup(struct sec_path *src);
931
932static inline void
933secpath_reset(struct sk_buff *skb)
934{
935#ifdef CONFIG_XFRM
936 secpath_put(skb->sp);
937 skb->sp = NULL;
938#endif
939}
940
941static inline int
Patrick McHardya1e59ab2006-09-19 12:57:34 -0700942xfrm_addr_any(xfrm_address_t *addr, unsigned short family)
943{
944 switch (family) {
945 case AF_INET:
946 return addr->a4 == 0;
947 case AF_INET6:
948 return ipv6_addr_any((struct in6_addr *)&addr->a6);
949 }
950 return 0;
951}
952
953static inline int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954__xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
955{
956 return (tmpl->saddr.a4 &&
957 tmpl->saddr.a4 != x->props.saddr.a4);
958}
959
960static inline int
961__xfrm6_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
962{
963 return (!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) &&
964 ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
965}
966
967static inline int
968xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short family)
969{
970 switch (family) {
971 case AF_INET:
972 return __xfrm4_state_addr_cmp(tmpl, x);
973 case AF_INET6:
974 return __xfrm6_state_addr_cmp(tmpl, x);
975 }
976 return !0;
977}
978
979#ifdef CONFIG_XFRM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
981
Herbert Xud5422ef2007-12-12 10:44:16 -0800982static inline int __xfrm_policy_check2(struct sock *sk, int dir,
983 struct sk_buff *skb,
984 unsigned int family, int reverse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
Alexey Dobriyanf6e1e252008-11-25 17:35:44 -0800986 struct net *net = dev_net(skb->dev);
Herbert Xud5422ef2007-12-12 10:44:16 -0800987 int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0);
988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 if (sk && sk->sk_policy[XFRM_POLICY_IN])
Herbert Xud5422ef2007-12-12 10:44:16 -0800990 return __xfrm_policy_check(sk, ndir, skb, family);
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -0700991
Alexey Dobriyanf6e1e252008-11-25 17:35:44 -0800992 return (!net->xfrm.policy_count[dir] && !skb->sp) ||
Eric Dumazetadf30902009-06-02 05:19:30 +0000993 (skb_dst(skb)->flags & DST_NOPOLICY) ||
Herbert Xud5422ef2007-12-12 10:44:16 -0800994 __xfrm_policy_check(sk, ndir, skb, family);
995}
996
997static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
998{
999 return __xfrm_policy_check2(sk, dir, skb, family, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000}
1001
1002static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1003{
1004 return xfrm_policy_check(sk, dir, skb, AF_INET);
1005}
1006
1007static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1008{
1009 return xfrm_policy_check(sk, dir, skb, AF_INET6);
1010}
1011
Herbert Xud5422ef2007-12-12 10:44:16 -08001012static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
1013 struct sk_buff *skb)
1014{
1015 return __xfrm_policy_check2(sk, dir, skb, AF_INET, 1);
1016}
1017
1018static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
1019 struct sk_buff *skb)
1020{
1021 return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1);
1022}
1023
1024extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
1025 unsigned int family, int reverse);
1026
1027static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
1028 unsigned int family)
1029{
1030 return __xfrm_decode_session(skb, fl, family, 0);
1031}
1032
1033static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
1034 struct flowi *fl,
1035 unsigned int family)
1036{
1037 return __xfrm_decode_session(skb, fl, family, 1);
1038}
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
1041
1042static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1043{
Alexey Dobriyan99a66652008-11-25 17:36:13 -08001044 struct net *net = dev_net(skb->dev);
1045
1046 return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
Eric Dumazetadf30902009-06-02 05:19:30 +00001047 (skb_dst(skb)->flags & DST_NOXFRM) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 __xfrm_route_forward(skb, family);
1049}
1050
1051static inline int xfrm4_route_forward(struct sk_buff *skb)
1052{
1053 return xfrm_route_forward(skb, AF_INET);
1054}
1055
1056static inline int xfrm6_route_forward(struct sk_buff *skb)
1057{
1058 return xfrm_route_forward(skb, AF_INET6);
1059}
1060
1061extern int __xfrm_sk_clone_policy(struct sock *sk);
1062
1063static inline int xfrm_sk_clone_policy(struct sock *sk)
1064{
1065 if (unlikely(sk->sk_policy[0] || sk->sk_policy[1]))
1066 return __xfrm_sk_clone_policy(sk);
1067 return 0;
1068}
1069
Herbert Xu4666faa2005-06-18 22:43:22 -07001070extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072static inline void xfrm_sk_free_policy(struct sock *sk)
1073{
1074 if (unlikely(sk->sk_policy[0] != NULL)) {
1075 xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
1076 sk->sk_policy[0] = NULL;
1077 }
1078 if (unlikely(sk->sk_policy[1] != NULL)) {
1079 xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
1080 sk->sk_policy[1] = NULL;
1081 }
1082}
1083
1084#else
1085
1086static inline void xfrm_sk_free_policy(struct sock *sk) {}
1087static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
1088static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }
1089static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; }
1090static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1091{
1092 return 1;
1093}
1094static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
1095{
1096 return 1;
1097}
1098static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
1099{
1100 return 1;
1101}
Herbert Xud5422ef2007-12-12 10:44:16 -08001102static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
1103 struct flowi *fl,
1104 unsigned int family)
1105{
1106 return -ENOSYS;
1107}
1108static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
1109 struct sk_buff *skb)
1110{
1111 return 1;
1112}
1113static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
1114 struct sk_buff *skb)
1115{
1116 return 1;
1117}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118#endif
1119
1120static __inline__
1121xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family)
1122{
1123 switch (family){
1124 case AF_INET:
1125 return (xfrm_address_t *)&fl->fl4_dst;
1126 case AF_INET6:
1127 return (xfrm_address_t *)&fl->fl6_dst;
1128 }
1129 return NULL;
1130}
1131
1132static __inline__
1133xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
1134{
1135 switch (family){
1136 case AF_INET:
1137 return (xfrm_address_t *)&fl->fl4_src;
1138 case AF_INET6:
1139 return (xfrm_address_t *)&fl->fl6_src;
1140 }
1141 return NULL;
1142}
1143
YOSHIFUJI Hideaki9bb182a2008-02-22 14:48:22 +09001144static __inline__
1145void xfrm_flowi_addr_get(struct flowi *fl,
1146 xfrm_address_t *saddr, xfrm_address_t *daddr,
1147 unsigned short family)
1148{
1149 switch(family) {
1150 case AF_INET:
1151 memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
1152 memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
1153 break;
1154 case AF_INET6:
1155 ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
1156 ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
1157 break;
1158 }
1159}
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161static __inline__ int
1162__xfrm4_state_addr_check(struct xfrm_state *x,
1163 xfrm_address_t *daddr, xfrm_address_t *saddr)
1164{
1165 if (daddr->a4 == x->id.daddr.a4 &&
1166 (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4))
1167 return 1;
1168 return 0;
1169}
1170
1171static __inline__ int
1172__xfrm6_state_addr_check(struct xfrm_state *x,
1173 xfrm_address_t *daddr, xfrm_address_t *saddr)
1174{
1175 if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) &&
1176 (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)||
1177 ipv6_addr_any((struct in6_addr *)saddr) ||
1178 ipv6_addr_any((struct in6_addr *)&x->props.saddr)))
1179 return 1;
1180 return 0;
1181}
1182
1183static __inline__ int
1184xfrm_state_addr_check(struct xfrm_state *x,
1185 xfrm_address_t *daddr, xfrm_address_t *saddr,
1186 unsigned short family)
1187{
1188 switch (family) {
1189 case AF_INET:
1190 return __xfrm4_state_addr_check(x, daddr, saddr);
1191 case AF_INET6:
1192 return __xfrm6_state_addr_check(x, daddr, saddr);
1193 }
1194 return 0;
1195}
1196
Masahide NAKAMURAe53820d2006-08-23 19:12:01 -07001197static __inline__ int
1198xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl,
1199 unsigned short family)
1200{
1201 switch (family) {
1202 case AF_INET:
1203 return __xfrm4_state_addr_check(x,
1204 (xfrm_address_t *)&fl->fl4_dst,
1205 (xfrm_address_t *)&fl->fl4_src);
1206 case AF_INET6:
1207 return __xfrm6_state_addr_check(x,
1208 (xfrm_address_t *)&fl->fl6_dst,
1209 (xfrm_address_t *)&fl->fl6_src);
1210 }
1211 return 0;
1212}
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214static inline int xfrm_state_kern(struct xfrm_state *x)
1215{
1216 return atomic_read(&x->tunnel_users);
1217}
1218
Masahide NAKAMURA57947082006-09-22 15:06:24 -07001219static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
1220{
Masahide NAKAMURAdc00a522006-08-23 17:49:52 -07001221 return (!userproto || proto == userproto ||
1222 (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH ||
1223 proto == IPPROTO_ESP ||
1224 proto == IPPROTO_COMP)));
Masahide NAKAMURA57947082006-09-22 15:06:24 -07001225}
1226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227/*
1228 * xfrm algorithm information
1229 */
Herbert Xu1a6509d2008-01-28 19:37:29 -08001230struct xfrm_algo_aead_info {
1231 u16 icv_truncbits;
1232};
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234struct xfrm_algo_auth_info {
1235 u16 icv_truncbits;
1236 u16 icv_fullbits;
1237};
1238
1239struct xfrm_algo_encr_info {
1240 u16 blockbits;
1241 u16 defkeybits;
1242};
1243
1244struct xfrm_algo_comp_info {
1245 u16 threshold;
1246};
1247
1248struct xfrm_algo_desc {
1249 char *name;
Herbert Xu04ff1262006-08-13 08:50:00 +10001250 char *compat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 u8 available:1;
1252 union {
Herbert Xu1a6509d2008-01-28 19:37:29 -08001253 struct xfrm_algo_aead_info aead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 struct xfrm_algo_auth_info auth;
1255 struct xfrm_algo_encr_info encr;
1256 struct xfrm_algo_comp_info comp;
1257 } uinfo;
1258 struct sadb_alg desc;
1259};
1260
1261/* XFRM tunnel handlers. */
1262struct xfrm_tunnel {
1263 int (*handler)(struct sk_buff *skb);
jamala6337462010-02-09 13:21:17 +00001264 int (*err_handler)(struct sk_buff *skb, u32 info);
Herbert Xud2acc342006-03-28 01:12:13 -08001265
1266 struct xfrm_tunnel *next;
1267 int priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268};
1269
1270struct xfrm6_tunnel {
Herbert Xud2acc342006-03-28 01:12:13 -08001271 int (*handler)(struct sk_buff *skb);
1272 int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
Brian Haleyd5fdd6b2009-06-23 04:31:07 -07001273 u8 type, u8 code, int offset, __be32 info);
Herbert Xud2acc342006-03-28 01:12:13 -08001274 struct xfrm6_tunnel *next;
1275 int priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276};
1277
1278extern void xfrm_init(void);
Neil Hormana33bc5c2009-07-30 18:52:15 -07001279extern void xfrm4_init(int rt_hash_size);
Alexey Dobriyand62ddc22008-11-25 17:14:31 -08001280extern int xfrm_state_init(struct net *net);
1281extern void xfrm_state_fini(struct net *net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282extern void xfrm4_state_init(void);
Daniel Lezcanoc35b7e72007-12-08 00:14:11 -08001283#ifdef CONFIG_XFRM
1284extern int xfrm6_init(void);
1285extern void xfrm6_fini(void);
Daniel Lezcano0013cab2007-12-07 00:42:11 -08001286extern int xfrm6_state_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287extern void xfrm6_state_fini(void);
Daniel Lezcanoc35b7e72007-12-08 00:14:11 -08001288#else
1289static inline int xfrm6_init(void)
1290{
1291 return 0;
1292}
1293static inline void xfrm6_fini(void)
1294{
1295 ;
1296}
1297#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -08001299#ifdef CONFIG_XFRM_STATISTICS
Alexey Dobriyanc68cd1a2008-11-25 18:00:14 -08001300extern int xfrm_proc_init(struct net *net);
1301extern void xfrm_proc_fini(struct net *net);
Masahide NAKAMURA558f82e2007-12-20 20:42:57 -08001302#endif
1303
Alexey Dobriyanb27aead2008-11-25 18:00:48 -08001304extern int xfrm_sysctl_init(struct net *net);
1305#ifdef CONFIG_SYSCTL
1306extern void xfrm_sysctl_fini(struct net *net);
1307#else
1308static inline void xfrm_sysctl_fini(struct net *net)
1309{
1310}
1311#endif
1312
Herbert Xu5c182452008-09-22 19:48:19 -07001313extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
Alexey Dobriyan284fa7d2008-11-25 17:32:14 -08001314extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
Timo Teras4c563f72008-02-28 21:31:08 -08001315 int (*func)(struct xfrm_state *, int, void*), void *);
Herbert Xuabb81c42008-09-09 19:58:29 -07001316extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
Alexey Dobriyan673c09b2008-11-25 17:15:16 -08001317extern struct xfrm_state *xfrm_state_alloc(struct net *net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
1319 struct flowi *fl, struct xfrm_tmpl *tmpl,
1320 struct xfrm_policy *pol, int *err,
1321 unsigned short family);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001322extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
Alexey Dobriyan5447c5e2008-11-25 17:31:51 -08001323 xfrm_address_t *daddr,
Jamal Hadi Salim628529b2007-07-02 22:41:14 -07001324 xfrm_address_t *saddr,
1325 unsigned short family,
1326 u8 mode, u8 proto, u32 reqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327extern int xfrm_state_check_expire(struct xfrm_state *x);
1328extern void xfrm_state_insert(struct xfrm_state *x);
1329extern int xfrm_state_add(struct xfrm_state *x);
1330extern int xfrm_state_update(struct xfrm_state *x);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001331extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
1332 xfrm_address_t *daddr, __be32 spi,
1333 u8 proto, unsigned short family);
1334extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1335 xfrm_address_t *daddr,
1336 xfrm_address_t *saddr,
1337 u8 proto,
1338 unsigned short family);
Masahide NAKAMURA41a49cc2006-08-23 22:48:31 -07001339#ifdef CONFIG_XFRM_SUB_POLICY
1340extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1341 int n, unsigned short family);
1342extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1343 int n, unsigned short family);
1344#else
1345static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1346 int n, unsigned short family)
1347{
1348 return -ENOSYS;
1349}
1350
1351static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1352 int n, unsigned short family)
1353{
1354 return -ENOSYS;
1355}
1356#endif
Jamal Hadi Salimaf11e312007-05-04 12:55:13 -07001357
1358struct xfrmk_sadinfo {
1359 u32 sadhcnt; /* current hash bkts */
1360 u32 sadhmcnt; /* max allowed hash bkts */
1361 u32 sadcnt; /* current running count */
1362};
1363
Jamal Hadi Salim5a6d3412007-05-04 12:55:39 -07001364struct xfrmk_spdinfo {
1365 u32 incnt;
1366 u32 outcnt;
1367 u32 fwdcnt;
1368 u32 inscnt;
1369 u32 outscnt;
1370 u32 fwdscnt;
1371 u32 spdhcnt;
1372 u32 spdhmcnt;
1373};
1374
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001375extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
1376 u32 seq);
Jamal Hadi Salim26b15da2005-06-18 22:42:13 -07001377extern int xfrm_state_delete(struct xfrm_state *x);
Alexey Dobriyan0e602452008-11-25 17:30:18 -08001378extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
Alexey Dobriyane0710412010-01-23 13:37:10 +00001379extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
1380extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
Paul Mooreafeb14b2007-12-21 14:58:11 -08001381extern int xfrm_replay_check(struct xfrm_state *x,
1382 struct sk_buff *skb, __be32 seq);
Al Viro61f46272006-09-27 18:48:33 -07001383extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001384extern void xfrm_replay_notify(struct xfrm_state *x, int event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
Herbert Xu72cb6962005-06-20 13:18:08 -07001386extern int xfrm_init_state(struct xfrm_state *x);
Herbert Xu227620e2007-11-13 21:41:28 -08001387extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu716062f2007-11-13 21:44:23 -08001388extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
1389 int encap_type);
Herbert Xu1bf06cd2007-11-19 18:50:17 -08001390extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
Herbert Xuc6581a42007-11-13 21:43:43 -08001391extern int xfrm_output_resume(struct sk_buff *skb, int err);
Herbert Xu406ef772007-10-08 17:16:30 -07001392extern int xfrm_output(struct sk_buff *skb);
Kazunori MIYAZAWAdf9dcb42008-03-24 14:51:51 -07001393extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001394extern int xfrm4_extract_header(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -08001395extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xuc4541b42007-10-17 21:28:53 -07001396extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
1397 int encap_type);
Herbert Xu716062f2007-11-13 21:44:23 -08001398extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399extern int xfrm4_rcv(struct sk_buff *skb);
Herbert Xuc4541b42007-10-17 21:28:53 -07001400
1401static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
1402{
1403 return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
1404}
1405
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001406extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1407extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408extern int xfrm4_output(struct sk_buff *skb);
Kazunori MIYAZAWAc0d56402007-02-13 12:54:47 -08001409extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
1410extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001411extern int xfrm6_extract_header(struct sk_buff *skb);
Herbert Xu227620e2007-11-13 21:41:28 -08001412extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
Herbert Xu33b5ecb2007-10-17 21:29:25 -07001413extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
Herbert Xu716062f2007-11-13 21:44:23 -08001414extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
Herbert Xue5bbef22007-10-15 12:50:28 -07001415extern int xfrm6_rcv(struct sk_buff *skb);
Masahide NAKAMURAfbd9a5b2006-08-23 18:08:21 -07001416extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
1417 xfrm_address_t *saddr, u8 proto);
Kazunori MIYAZAWA73d605d2007-02-13 12:55:55 -08001418extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
1419extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
Alexey Dobriyana1664772010-01-25 10:37:54 +00001420extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
1421extern void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr);
1422extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr);
Herbert Xu36cf9ac2007-11-13 21:40:52 -08001423extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1424extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425extern int xfrm6_output(struct sk_buff *skb);
Masahide NAKAMURAaee5adb2006-08-23 17:57:28 -07001426extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
1427 u8 **prevhdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429#ifdef CONFIG_XFRM
James Chapman067b2072007-07-05 17:08:05 -07001430extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432#else
1433static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1434{
1435 return -ENOPROTOOPT;
1436}
1437
James Chapman067b2072007-07-05 17:08:05 -07001438static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
1440 /* should not happen */
1441 kfree_skb(skb);
1442 return 0;
1443}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444#endif
1445
Alexey Dobriyan0331b1f2008-11-25 17:21:45 -08001446struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
Timo Teras4c563f72008-02-28 21:31:08 -08001447
Herbert Xu12a169e2008-10-01 07:03:24 -07001448extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
Alexey Dobriyancdcbca72008-11-25 17:34:49 -08001449extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
Timo Teras4c563f72008-02-28 21:31:08 -08001450 int (*func)(struct xfrm_policy *, int, int, void*), void *);
Herbert Xu12a169e2008-10-01 07:03:24 -07001451extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
Alexey Dobriyan8d1211a2008-11-25 17:34:20 -08001453struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
Masahide NAKAMURA4e81bb82006-08-23 22:43:30 -07001454 struct xfrm_selector *sel,
Eric Parisef41aaa2007-03-07 15:37:58 -08001455 struct xfrm_sec_ctx *ctx, int delete,
1456 int *err);
Alexey Dobriyan8d1211a2008-11-25 17:34:20 -08001457struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err);
Alexey Dobriyan33ffbbd2008-11-25 17:33:32 -08001458int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459u32 xfrm_get_acqseq(void);
Herbert Xu658b2192007-10-09 13:29:52 -07001460extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
Jamal Hadi Salimbd557752010-02-22 16:20:22 -08001461struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
1462 u8 mode, u32 reqid, u8 proto,
1463 xfrm_address_t *daddr,
1464 xfrm_address_t *saddr, int create,
1465 unsigned short family);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
Venkat Yekkirala5b368e62006-10-05 15:42:18 -05001467extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
1468 struct flowi *fl, int family, int strict);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001470#ifdef CONFIG_XFRM_MIGRATE
1471extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
Arnaud Ebalard13c1d182008-10-05 13:33:42 -07001472 struct xfrm_migrate *m, int num_bundles,
1473 struct xfrm_kmaddress *k);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001474extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
1475extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
1476 struct xfrm_migrate *m);
1477extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
Arnaud Ebalard13c1d182008-10-05 13:33:42 -07001478 struct xfrm_migrate *m, int num_bundles,
1479 struct xfrm_kmaddress *k);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001480#endif
1481
Al Viro5d36b182006-11-08 00:24:06 -08001482extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
Jamal Hadi Salim6c5c8ca2006-03-20 19:17:25 -08001483extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
Alexey Dobriyandb983c12008-11-25 17:51:01 -08001484extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486extern void xfrm_input_init(void);
Al Viro6067b2b2006-09-27 18:47:59 -07001487extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
1489extern void xfrm_probe_algs(void);
1490extern int xfrm_count_auth_supported(void);
1491extern int xfrm_count_enc_supported(void);
1492extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
1493extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
1494extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
1495extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
1496extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
1497extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
1498extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
1499extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
Herbert Xu1a6509d2008-01-28 19:37:29 -08001500extern struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len,
1501 int probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Herbert Xu07d4ee52006-08-20 14:24:50 +10001503struct hash_desc;
Herbert Xu9409f382006-08-06 19:49:12 +10001504struct scatterlist;
Herbert Xu07d4ee52006-08-20 14:24:50 +10001505typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
1506 unsigned int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
1509 int family)
1510{
1511 switch (family) {
1512 default:
1513 case AF_INET:
jamala6337462010-02-09 13:21:17 +00001514 return (__force u32)a->a4 - (__force u32)b->a4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 case AF_INET6:
1516 return ipv6_addr_cmp((struct in6_addr *)a,
1517 (struct in6_addr *)b);
1518 }
1519}
1520
Herbert Xu77d8d7a2005-10-05 12:15:12 -07001521static inline int xfrm_policy_id2dir(u32 index)
1522{
1523 return index & 7;
1524}
1525
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001526#ifdef CONFIG_XFRM
1527static inline int xfrm_aevent_is_on(struct net *net)
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001528{
Patrick McHardybe336902006-03-20 22:40:54 -08001529 struct sock *nlsk;
1530 int ret = 0;
1531
1532 rcu_read_lock();
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001533 nlsk = rcu_dereference(net->xfrm.nlsk);
Patrick McHardybe336902006-03-20 22:40:54 -08001534 if (nlsk)
1535 ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS);
1536 rcu_read_unlock();
1537 return ret;
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001538}
Alexey Dobriyana6483b72008-11-25 17:38:20 -08001539#endif
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001540
Eric Dumazet0f99be02008-01-08 23:39:06 -08001541static inline int xfrm_alg_len(struct xfrm_algo *alg)
1542{
1543 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
1544}
1545
Martin Willi4447bb32009-11-25 00:29:52 +00001546static inline int xfrm_alg_auth_len(struct xfrm_algo_auth *alg)
1547{
1548 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
1549}
1550
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001551#ifdef CONFIG_XFRM_MIGRATE
1552static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
1553{
Eric Dumazet0f99be02008-01-08 23:39:06 -08001554 return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001555}
1556
Martin Willi4447bb32009-11-25 00:29:52 +00001557static inline struct xfrm_algo_auth *xfrm_algo_auth_clone(struct xfrm_algo_auth *orig)
1558{
1559 return kmemdup(orig, xfrm_alg_auth_len(orig), GFP_KERNEL);
1560}
1561
Shinta Sugimoto80c9aba2007-02-08 13:11:42 -08001562static inline void xfrm_states_put(struct xfrm_state **states, int n)
1563{
1564 int i;
1565 for (i = 0; i < n; i++)
1566 xfrm_state_put(*(states + i));
1567}
1568
1569static inline void xfrm_states_delete(struct xfrm_state **states, int n)
1570{
1571 int i;
1572 for (i = 0; i < n; i++)
1573 xfrm_state_delete(*(states + i));
1574}
1575#endif
Jamal Hadi Salimf8cd5482006-03-20 19:15:11 -08001576
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07001577#ifdef CONFIG_XFRM
Herbert Xu00501122007-12-11 01:53:43 -08001578static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
1579{
1580 return skb->sp->xvec[skb->sp->len - 1];
1581}
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07001582#endif
Herbert Xu00501122007-12-11 01:53:43 -08001583
Jamal Hadi Salimbf825f812010-02-22 11:32:54 +00001584static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
1585{
1586 if (attrs[XFRMA_MARK])
1587 memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m));
1588 else
1589 m->v = m->m = 0;
1590
1591 return m->v & m->m;
1592}
1593
1594static inline int xfrm_mark_put(struct sk_buff *skb, struct xfrm_mark *m)
1595{
1596 if (m->m | m->v)
1597 NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
1598 return 0;
1599
1600nla_put_failure:
1601 return -1;
1602}
1603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604#endif /* _NET_XFRM_H */