[IPV6] MIP6: Transformation support mobility header.
[linux-2.6-microblaze.git] / include / net / xfrm.h
index 0d5529c..13488e7 100644 (file)
@@ -8,8 +8,8 @@
 #include <linux/list.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
-#include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
+#include <linux/ipsec.h>
 #include <linux/in6.h>
 #include <linux/mutex.h>
 
@@ -20,6 +20,8 @@
 #include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)       (((len) + 7) & ~7)
+#define MODULE_ALIAS_XFRM_MODE(family, encap) \
+       MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
 
 extern struct sock *xfrm_nl;
 extern u32 sysctl_xfrm_aevent_etime;
@@ -93,6 +95,7 @@ struct xfrm_state
 {
        /* Note: bydst is re-used during gc */
        struct list_head        bydst;
+       struct list_head        bysrc;
        struct list_head        byspi;
 
        atomic_t                refcnt;
@@ -131,6 +134,9 @@ struct xfrm_state
        /* Data for encapsulator */
        struct xfrm_encap_tmpl  *encap;
 
+       /* Data for care-of address */
+       xfrm_address_t  *coaddr;
+
        /* IPComp needs an IPIP tunnel for handling uncompressed packets */
        struct xfrm_state       *tunnel;
 
@@ -143,6 +149,11 @@ struct xfrm_state
        /* Replay detection state at the time we sent the last notification */
        struct xfrm_replay_state preplay;
 
+       /* internal flag that only holds state for delayed aevent at the
+        * moment
+       */
+       u32                     xflags;
+
        /* Replay detection notification settings */
        u32                     replay_maxage;
        u32                     replay_maxdiff;
@@ -156,9 +167,13 @@ struct xfrm_state
        struct xfrm_lifetime_cur curlft;
        struct timer_list       timer;
 
+       /* Last used time */
+       u64                     lastused;
+
        /* Reference to data common to all the instances of this
         * transformer. */
        struct xfrm_type        *type;
+       struct xfrm_mode        *mode;
 
        /* Security context */
        struct xfrm_sec_ctx     *security;
@@ -168,6 +183,9 @@ struct xfrm_state
        void                    *data;
 };
 
+/* xflags - make enum if more show up */
+#define XFRM_TIME_DEFER        1
+
 enum {
        XFRM_STATE_VOID,
        XFRM_STATE_ACQ,
@@ -196,8 +214,8 @@ struct xfrm_type;
 struct xfrm_dst;
 struct xfrm_policy_afinfo {
        unsigned short          family;
-       rwlock_t                lock;
-       struct xfrm_type_map    *type_map;
+       struct xfrm_type        *type_map[IPPROTO_MAX];
+       struct xfrm_mode        *mode_map[XFRM_MODE_MAX];
        struct dst_ops          *dst_ops;
        void                    (*garbage_collect)(void);
        int                     (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -224,14 +242,15 @@ extern int __xfrm_state_delete(struct xfrm_state *x);
 
 struct xfrm_state_afinfo {
        unsigned short          family;
-       rwlock_t                lock;
        struct list_head        *state_bydst;
+       struct list_head        *state_bysrc;
        struct list_head        *state_byspi;
        int                     (*init_flags)(struct xfrm_state *x);
        void                    (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
                                                struct xfrm_tmpl *tmpl,
                                                xfrm_address_t *daddr, xfrm_address_t *saddr);
        struct xfrm_state       *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto);
+       struct xfrm_state       *(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto);
        struct xfrm_state       *(*find_acq)(u8 mode, u32 reqid, u8 proto, 
                                             xfrm_address_t *daddr, xfrm_address_t *saddr, 
                                             int create);
@@ -247,25 +266,38 @@ struct xfrm_type
        char                    *description;
        struct module           *owner;
        __u8                    proto;
+       __u8                    flags;
+#define XFRM_TYPE_NON_FRAGMENT 1
 
        int                     (*init_state)(struct xfrm_state *x);
        void                    (*destructor)(struct xfrm_state *);
        int                     (*input)(struct xfrm_state *, struct sk_buff *skb);
        int                     (*output)(struct xfrm_state *, struct sk_buff *pskb);
+       int                     (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
+       xfrm_address_t          *(*local_addr)(struct xfrm_state *, xfrm_address_t *);
+       xfrm_address_t          *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);
        /* Estimate maximal size of result of transformation of a dgram */
        u32                     (*get_max_size)(struct xfrm_state *, int size);
 };
 
-struct xfrm_type_map {
-       rwlock_t                lock;
-       struct xfrm_type        *map[256];
-};
-
 extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
 extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
 extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
 extern void xfrm_put_type(struct xfrm_type *type);
 
+struct xfrm_mode {
+       int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+       int (*output)(struct sk_buff *skb);
+
+       struct module *owner;
+       unsigned int encap;
+};
+
+extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
+extern void xfrm_put_mode(struct xfrm_mode *mode);
+
 struct xfrm_tmpl
 {
 /* id in template is interpreted as:
@@ -281,7 +313,7 @@ struct xfrm_tmpl
 
        __u32                   reqid;
 
-/* Mode: transport/tunnel */
+/* Mode: transport, tunnel etc. */
        __u8                    mode;
 
 /* Sharing mode: unique, this session only, this user only etc. */
@@ -296,7 +328,7 @@ struct xfrm_tmpl
        __u32                   calgos;
 };
 
-#define XFRM_MAX_DEPTH         4
+#define XFRM_MAX_DEPTH         6
 
 struct xfrm_policy
 {
@@ -345,7 +377,7 @@ struct xfrm_mgr
        char                    *id;
        int                     (*notify)(struct xfrm_state *x, struct km_event *c);
        int                     (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
-       struct xfrm_policy      *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
+       struct xfrm_policy      *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
        int                     (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
        int                     (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
 };
@@ -402,6 +434,30 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family)
        return 0;
 }
 
+static __inline__
+unsigned __xfrm4_src_hash(xfrm_address_t *addr)
+{
+       return __xfrm4_dst_hash(addr);
+}
+
+static __inline__
+unsigned __xfrm6_src_hash(xfrm_address_t *addr)
+{
+       return __xfrm6_dst_hash(addr);
+}
+
+static __inline__
+unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family)
+{
+       switch (family) {
+       case AF_INET:
+               return __xfrm4_src_hash(addr);
+       case AF_INET6:
+               return __xfrm6_src_hash(addr);
+       }
+       return 0;
+}
+
 static __inline__
 unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
 {
@@ -490,6 +546,11 @@ u16 xfrm_flowi_sport(struct flowi *fl)
        case IPPROTO_ICMPV6:
                port = htons(fl->fl_icmp_type);
                break;
+#ifdef CONFIG_IPV6_MIP6
+       case IPPROTO_MH:
+               port = htons(fl->fl_mh_type);
+               break;
+#endif
        default:
                port = 0;       /*XXX*/
        }
@@ -813,11 +874,36 @@ xfrm_state_addr_check(struct xfrm_state *x,
        return 0;
 }
 
+static __inline__ int
+xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl,
+                          unsigned short family)
+{
+       switch (family) {
+       case AF_INET:
+               return __xfrm4_state_addr_check(x,
+                                               (xfrm_address_t *)&fl->fl4_dst,
+                                               (xfrm_address_t *)&fl->fl4_src);
+       case AF_INET6:
+               return __xfrm6_state_addr_check(x,
+                                               (xfrm_address_t *)&fl->fl6_dst,
+                                               (xfrm_address_t *)&fl->fl6_src);
+       }
+       return 0;
+}
+
 static inline int xfrm_state_kern(struct xfrm_state *x)
 {
        return atomic_read(&x->tunnel_users);
 }
 
+static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
+{
+       return (!userproto || proto == userproto ||
+               (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH ||
+                                                 proto == IPPROTO_ESP ||
+                                                 proto == IPPROTO_COMP)));
+}
+
 /*
  * xfrm algorithm information
  */
@@ -837,6 +923,7 @@ struct xfrm_algo_comp_info {
 
 struct xfrm_algo_desc {
        char *name;
+       char *compat;
        u8 available:1;
        union {
                struct xfrm_algo_auth_info auth;
@@ -884,6 +971,7 @@ extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
 extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
@@ -899,12 +987,16 @@ extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
 extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb);
+extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+                           xfrm_address_t *saddr, u8 proto);
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
 extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
 extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
 extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
 extern int xfrm6_output(struct sk_buff *skb);
+extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
+                                u8 **prevhdr);
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
@@ -944,7 +1036,7 @@ extern void xfrm_policy_flush(void);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_flush_bundles(void);
 extern void xfrm_flush_all_bundles(void);
-extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family);
+extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 
 extern wait_queue_head_t km_waitq;
@@ -966,11 +1058,13 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
 extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
 
-struct crypto_tfm;
-typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int);
+struct hash_desc;
+struct scatterlist;
+typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
+                             unsigned int);
 
-extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
-                        int offset, int len, icv_update_fn_t icv_update);
+extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
+                       int offset, int len, icv_update_fn_t icv_update);
 
 static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
                                int family)