Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[linux-2.6-block.git] / include / net / xfrm.h
index fb5654a8ca3cee1c65923c105f3760d607eaa1de..32682ae47b3fe6d88e7750120089efc791b38894 100644 (file)
 struct xfrm_state_walk {
        struct list_head        all;
        u8                      state;
-       union {
-               u8              dying;
-               u8              proto;
-       };
+       u8                      dying;
+       u8                      proto;
        u32                     seq;
+       struct xfrm_address_filter *filter;
 };
 
 /* Full description of state of transformer. */
@@ -350,6 +349,16 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
 struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
 void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
+struct xfrm_input_afinfo {
+       unsigned int            family;
+       struct module           *owner;
+       int                     (*callback)(struct sk_buff *skb, u8 protocol,
+                                           int err);
+};
+
+int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo);
+int xfrm_input_unregister_afinfo(struct xfrm_input_afinfo *afinfo);
+
 void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
 struct xfrm_type {
@@ -594,21 +603,33 @@ struct xfrm_mgr {
                                           const struct xfrm_migrate *m,
                                           int num_bundles,
                                           const struct xfrm_kmaddress *k);
+       bool                    (*is_alive)(const struct km_event *c);
 };
 
 int xfrm_register_km(struct xfrm_mgr *km);
 int xfrm_unregister_km(struct xfrm_mgr *km);
 
+struct xfrm_tunnel_skb_cb {
+       union {
+               struct inet_skb_parm h4;
+               struct inet6_skb_parm h6;
+       } header;
+
+       union {
+               struct ip_tunnel *ip4;
+               struct ip6_tnl *ip6;
+       } tunnel;
+};
+
+#define XFRM_TUNNEL_SKB_CB(__skb) ((struct xfrm_tunnel_skb_cb *)&((__skb)->cb[0]))
+
 /*
  * This structure is used for the duration where packets are being
  * transformed by IPsec.  As soon as the packet leaves IPsec the
  * area beyond the generic IP part may be overwritten.
  */
 struct xfrm_skb_cb {
-       union {
-               struct inet_skb_parm h4;
-               struct inet6_skb_parm h6;
-        } header;
+       struct xfrm_tunnel_skb_cb header;
 
         /* Sequence number for replay protection. */
        union {
@@ -630,10 +651,7 @@ struct xfrm_skb_cb {
  * to transmit header information to the mode input/output functions.
  */
 struct xfrm_mode_skb_cb {
-       union {
-               struct inet_skb_parm h4;
-               struct inet6_skb_parm h6;
-       } header;
+       struct xfrm_tunnel_skb_cb header;
 
        /* Copied from header for IPv4, always set to zero and DF for IPv6. */
        __be16 id;
@@ -665,10 +683,7 @@ struct xfrm_mode_skb_cb {
  * related information.
  */
 struct xfrm_spi_skb_cb {
-       union {
-               struct inet_skb_parm h4;
-               struct inet6_skb_parm h6;
-       } header;
+       struct xfrm_tunnel_skb_cb header;
 
        unsigned int daddroff;
        unsigned int family;
@@ -1347,18 +1362,34 @@ struct xfrm_algo_desc {
        struct sadb_alg desc;
 };
 
-/* XFRM tunnel handlers.  */
-struct xfrm_tunnel {
+/* XFRM protocol handlers.  */
+struct xfrm4_protocol {
        int (*handler)(struct sk_buff *skb);
+       int (*input_handler)(struct sk_buff *skb, int nexthdr, __be32 spi,
+                            int encap_type);
+       int (*cb_handler)(struct sk_buff *skb, int err);
        int (*err_handler)(struct sk_buff *skb, u32 info);
 
-       struct xfrm_tunnel __rcu *next;
+       struct xfrm4_protocol __rcu *next;
+       int priority;
+};
+
+struct xfrm6_protocol {
+       int (*handler)(struct sk_buff *skb);
+       int (*cb_handler)(struct sk_buff *skb, int err);
+       int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                          u8 type, u8 code, int offset, __be32 info);
+
+       struct xfrm6_protocol __rcu *next;
        int priority;
 };
 
-struct xfrm_tunnel_notifier {
+/* XFRM tunnel handlers.  */
+struct xfrm_tunnel {
        int (*handler)(struct sk_buff *skb);
-       struct xfrm_tunnel_notifier __rcu *next;
+       int (*err_handler)(struct sk_buff *skb, u32 info);
+
+       struct xfrm_tunnel __rcu *next;
        int priority;
 };
 
@@ -1375,11 +1406,14 @@ void xfrm4_init(void);
 int xfrm_state_init(struct net *net);
 void xfrm_state_fini(struct net *net);
 void xfrm4_state_init(void);
+void xfrm4_protocol_init(void);
 #ifdef CONFIG_XFRM
 int xfrm6_init(void);
 void xfrm6_fini(void);
 int xfrm6_state_init(void);
 void xfrm6_state_fini(void);
+int xfrm6_protocol_init(void);
+void xfrm6_protocol_fini(void);
 #else
 static inline int xfrm6_init(void)
 {
@@ -1405,7 +1439,8 @@ static inline void xfrm_sysctl_fini(struct net *net)
 }
 #endif
 
-void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
+                         struct xfrm_address_filter *filter);
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
                    int (*func)(struct xfrm_state *, int, void*), void *);
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
@@ -1497,20 +1532,22 @@ int xfrm4_rcv(struct sk_buff *skb);
 
 static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 {
-       return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
+       XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
+       XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+       XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+       return xfrm_input(skb, nexthdr, spi, 0);
 }
 
 int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm4_output(struct sk_buff *skb);
 int xfrm4_output_finish(struct sk_buff *skb);
+int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
+int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
+int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char protocol);
 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
-int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
-int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
-int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
-int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
 int xfrm6_extract_header(struct sk_buff *skb);
 int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
@@ -1519,6 +1556,9 @@ int xfrm6_rcv(struct sk_buff *skb);
 int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
                     xfrm_address_t *saddr, u8 proto);
 void xfrm6_local_error(struct sk_buff *skb, u32 mtu);
+int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
+int xfrm6_protocol_register(struct xfrm6_protocol *handler, unsigned char protocol);
+int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, unsigned char protocol);
 int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
 int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
 __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
@@ -1646,6 +1686,20 @@ static inline int xfrm_aevent_is_on(struct net *net)
        rcu_read_unlock();
        return ret;
 }
+
+static inline int xfrm_acquire_is_on(struct net *net)
+{
+       struct sock *nlsk;
+       int ret = 0;
+
+       rcu_read_lock();
+       nlsk = rcu_dereference(net->xfrm.nlsk);
+       if (nlsk)
+               ret = netlink_has_listeners(nlsk, XFRMNLGRP_ACQUIRE);
+       rcu_read_unlock();
+
+       return ret;
+}
 #endif
 
 static inline int aead_len(struct xfrm_algo_aead *alg)
@@ -1748,4 +1802,24 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
        return ret;
 }
 
+static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
+                                   unsigned int family)
+{
+       bool tunnel = false;
+
+       switch(family) {
+       case AF_INET:
+               if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4)
+                       tunnel = true;
+               break;
+       case AF_INET6:
+               if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6)
+                       tunnel = true;
+               break;
+       }
+       if (tunnel && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL))
+               return -EINVAL;
+
+       return 0;
+}
 #endif /* _NET_XFRM_H */