linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / include / net / xfrm.h
index 0de0ac0..8d362c4 100644 (file)
@@ -1,11 +1,13 @@
 #ifndef _NET_XFRM_H
 #define _NET_XFRM_H
 
+#include <linux/compiler.h>
+#include <linux/in.h>
 #include <linux/xfrm.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/skbuff.h>
-#include <linux/netdevice.h>
+#include <linux/socket.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <linux/in6.h>
@@ -143,6 +145,9 @@ struct xfrm_state
         * transformer. */
        struct xfrm_type        *type;
 
+       /* Security context */
+       struct xfrm_sec_ctx     *security;
+
        /* Private data of this transformer, format is opaque,
         * interpreted by xfrm_type methods. */
        void                    *data;
@@ -157,6 +162,20 @@ enum {
        XFRM_STATE_DEAD
 };
 
+/* callback structure passed from either netlink or pfkey */
+struct km_event
+{
+       union {
+               u32 hard;
+               u32 proto;
+               u32 byid;
+       } data;
+
+       u32     seq;
+       u32     pid;
+       u32     event;
+};
+
 struct xfrm_type;
 struct xfrm_dst;
 struct xfrm_policy_afinfo {
@@ -178,8 +197,8 @@ struct xfrm_policy_afinfo {
 
 extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
 extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
-extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
+extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
 
 #define XFRM_ACQ_EXPIRES       30
 
@@ -189,6 +208,7 @@ struct xfrm_state_afinfo {
        rwlock_t                lock;
        struct list_head        *state_bydst;
        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);
@@ -200,8 +220,6 @@ struct xfrm_state_afinfo {
 
 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
-extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
-extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
@@ -212,11 +230,10 @@ struct xfrm_type
        struct module           *owner;
        __u8                    proto;
 
-       int                     (*init_state)(struct xfrm_state *x, void *args);
+       int                     (*init_state)(struct xfrm_state *x);
        void                    (*destructor)(struct xfrm_state *);
        int                     (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
-       int                     (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
-       int                     (*output)(struct sk_buff *skb);
+       int                     (*output)(struct xfrm_state *, struct sk_buff *pskb);
        /* Estimate maximal size of result of transformation of a dgram */
        u32                     (*get_max_size)(struct xfrm_state *, int size);
 };
@@ -284,6 +301,7 @@ struct xfrm_policy
        __u8                    flags;
        __u8                    dead;
        __u8                    xfrm_nr;
+       struct xfrm_sec_ctx     *security;
        struct xfrm_tmpl        xfrm_vec[XFRM_MAX_DEPTH];
 };
 
@@ -293,58 +311,17 @@ struct xfrm_mgr
 {
        struct list_head        list;
        char                    *id;
-       int                     (*notify)(struct xfrm_state *x, int event);
+       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);
        int                     (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
-       int                     (*notify_policy)(struct xfrm_policy *x, int dir, int event);
+       int                     (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
 extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 
-#define XFRM_FLOWCACHE_HASH_SIZE       1024
-
-static inline u32 __flow_hash4(struct flowi *fl)
-{
-       u32 hash = fl->fl4_src ^ fl->fl_ip_sport;
-
-       hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-       hash ^= fl->fl4_dst ^ fl->fl_ip_dport;
-       hash ^= (hash >> 10);
-       hash ^= (hash >> 20);
-       return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 __flow_hash6(struct flowi *fl)
-{
-       u32 hash = fl->fl6_src.s6_addr32[2] ^
-                  fl->fl6_src.s6_addr32[3] ^ 
-                  fl->fl_ip_sport;
-
-       hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-       hash ^= fl->fl6_dst.s6_addr32[2] ^
-               fl->fl6_dst.s6_addr32[3] ^ 
-               fl->fl_ip_dport;
-       hash ^= (hash >> 10);
-       hash ^= (hash >> 20);
-       return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 flow_hash(struct flowi *fl, unsigned short family)
-{
-       switch (family) {
-       case AF_INET:
-               return __flow_hash4(fl);
-       case AF_INET6:
-               return __flow_hash6(fl);
-       }
-       return 0;       /*XXX*/
-}
-
 extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
@@ -425,6 +402,11 @@ unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short f
 
 extern void __xfrm_state_destroy(struct xfrm_state *);
 
+static inline void __xfrm_state_put(struct xfrm_state *x)
+{
+       atomic_dec(&x->refcnt);
+}
+
 static inline void xfrm_state_put(struct xfrm_state *x)
 {
        if (atomic_dec_and_test(&x->refcnt))
@@ -462,13 +444,53 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
        return 1;
 }
 
+static __inline__
+u16 xfrm_flowi_sport(struct flowi *fl)
+{
+       u16 port;
+       switch(fl->proto) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
+       case IPPROTO_SCTP:
+               port = fl->fl_ip_sport;
+               break;
+       case IPPROTO_ICMP:
+       case IPPROTO_ICMPV6:
+               port = htons(fl->fl_icmp_type);
+               break;
+       default:
+               port = 0;       /*XXX*/
+       }
+       return port;
+}
+
+static __inline__
+u16 xfrm_flowi_dport(struct flowi *fl)
+{
+       u16 port;
+       switch(fl->proto) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
+       case IPPROTO_SCTP:
+               port = fl->fl_ip_dport;
+               break;
+       case IPPROTO_ICMP:
+       case IPPROTO_ICMPV6:
+               port = htons(fl->fl_icmp_code);
+               break;
+       default:
+               port = 0;       /*XXX*/
+       }
+       return port;
+}
+
 static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
        return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
                addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-               !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-               !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+               !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+               !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
                (fl->proto == sel->proto || !sel->proto) &&
                (fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -478,8 +500,8 @@ __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
        return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
                addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-               !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-               !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+               !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+               !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
                (fl->proto == sel->proto || !sel->proto) &&
                (fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -497,9 +519,24 @@ xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
        return 0;
 }
 
-/* placeholder until xfrm6_tunnel.c is written */
-static inline int xfrm6_tunnel_check_size(struct sk_buff *skb)
-{ return 0; }
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+/*     If neither has a context --> match
+ *     Otherwise, both must have a context and the sids, doi, alg must match
+ */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+       return ((!s1 && !s2) ||
+               (s1 && s2 &&
+                (s1->ctx_sid == s2->ctx_sid) &&
+                (s1->ctx_doi == s2->ctx_doi) &&
+                (s1->ctx_alg == s2->ctx_alg)));
+}
+#else
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+       return 1;
+}
+#endif
 
 /* A struct encoding bundle of transformations to apply to some set of flow.
  *
@@ -520,8 +557,22 @@ struct xfrm_dst
                struct rtable           rt;
                struct rt6_info         rt6;
        } u;
+       struct dst_entry *route;
+       u32 route_mtu_cached;
+       u32 child_mtu_cached;
+       u32 route_cookie;
+       u32 path_cookie;
 };
 
+static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
+{
+       dst_release(xdst->route);
+       if (likely(xdst->u.dst.xfrm))
+               xfrm_state_put(xdst->u.dst.xfrm);
+}
+
+extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
+
 /* Decapsulation state, used by the input to store data during
  * decapsulation procedure, to be used later (during the policy
  * check
@@ -606,7 +657,7 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk
        if (sk && sk->sk_policy[XFRM_POLICY_IN])
                return __xfrm_policy_check(sk, dir, skb, family);
                
-       return  !xfrm_policy_list[dir] ||
+       return  (!xfrm_policy_list[dir] && !skb->sp) ||
                (skb->dst->flags & DST_NOPOLICY) ||
                __xfrm_policy_check(sk, dir, skb, family);
 }
@@ -621,7 +672,7 @@ static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *s
        return xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
-
+extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
 extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
@@ -650,7 +701,7 @@ static inline int xfrm_sk_clone_policy(struct sock *sk)
        return 0;
 }
 
-extern void xfrm_policy_delete(struct xfrm_policy *pol, int dir);
+extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
@@ -780,17 +831,21 @@ struct xfrm_algo_desc {
 /* XFRM tunnel handlers.  */
 struct xfrm_tunnel {
        int (*handler)(struct sk_buff *skb);
-       void (*err_handler)(struct sk_buff *skb, void *info);
+       void (*err_handler)(struct sk_buff *skb, __u32 info);
+};
+
+struct xfrm6_tunnel {
+       int (*handler)(struct sk_buff **pskb);
+       void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                           int type, int code, int offset, __u32 info);
 };
 
 extern void xfrm_init(void);
 extern void xfrm4_init(void);
-extern void xfrm4_fini(void);
 extern void xfrm6_init(void);
 extern void xfrm6_fini(void);
 extern void xfrm_state_init(void);
 extern void xfrm4_state_init(void);
-extern void xfrm4_state_fini(void);
 extern void xfrm6_state_init(void);
 extern void xfrm6_state_fini(void);
 
@@ -804,27 +859,34 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
-extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
 extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
-extern void xfrm_state_delete(struct xfrm_state *x);
+extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
 extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
-extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
-extern int xfrm_check_output(struct xfrm_state *x, struct sk_buff *skb, unsigned short family);
+extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm4_rcv(struct sk_buff *skb);
+extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm4_tunnel_check_size(struct sk_buff *skb);
-extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv(struct sk_buff **pskb);
+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);
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
-extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
+extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
 extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 #else
-static inline int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen)
+static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
 {
        return -ENOPROTOOPT;
 } 
@@ -841,14 +903,11 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig
 } 
 #endif
 
-void xfrm_policy_init(void);
-void xfrm4_policy_init(void);
-void xfrm6_policy_init(void);
-struct xfrm_policy *xfrm_policy_alloc(int gfp);
+struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
-struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
-                                     int delete);
+struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
+                                         struct xfrm_sec_ctx *ctx, int delete);
 struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
 void xfrm_policy_flush(void);
 u32 xfrm_get_acqseq(void);
@@ -857,14 +916,13 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
                                  xfrm_address_t *daddr, xfrm_address_t *saddr, 
                                  int create, unsigned short family);
 extern void xfrm_policy_flush(void);
-extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
-extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
 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 void xfrm_init_pmtu(struct dst_entry *dst);
 
 extern wait_queue_head_t km_waitq;
-extern void km_state_expired(struct xfrm_state *x, int hard);
-extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
 extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard);
 
@@ -876,13 +934,12 @@ extern int xfrm_count_auth_supported(void);
 extern int xfrm_count_enc_supported(void);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
-extern struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
-extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
-extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
-extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name);
+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);
@@ -890,4 +947,22 @@ typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsign
 extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
                         int offset, int len, icv_update_fn_t icv_update);
 
+static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
+                               int family)
+{
+       switch (family) {
+       default:
+       case AF_INET:
+               return a->a4 - b->a4;
+       case AF_INET6:
+               return ipv6_addr_cmp((struct in6_addr *)a,
+                                    (struct in6_addr *)b);
+       }
+}
+
+static inline int xfrm_policy_id2dir(u32 index)
+{
+       return index & 7;
+}
+
 #endif /* _NET_XFRM_H */