2005-04-17 02:20:36 +04:00
/* xfrm4_tunnel.c: Generic IP tunnel transformer.
*
* Copyright ( C ) 2003 David S . Miller ( davem @ redhat . com )
*/
2012-03-12 11:03:32 +04:00
# define pr_fmt(fmt) "IPsec: " fmt
2005-04-17 02:20:36 +04:00
# include <linux/skbuff.h>
# include <linux/module.h>
2006-03-21 09:33:17 +03:00
# include <linux/mutex.h>
2005-04-17 02:20:36 +04:00
# include <net/xfrm.h>
# include <net/ip.h>
# include <net/protocol.h>
static int ipip_output ( struct xfrm_state * x , struct sk_buff * skb )
{
2007-10-11 02:44:06 +04:00
skb_push ( skb , - skb_network_offset ( skb ) ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-04-01 12:52:46 +04:00
static int ipip_xfrm_rcv ( struct xfrm_state * x , struct sk_buff * skb )
2005-04-17 02:20:36 +04:00
{
2007-10-18 08:28:06 +04:00
return ip_hdr ( skb ) - > protocol ;
2005-04-17 02:20:36 +04:00
}
2005-06-21 00:18:08 +04:00
static int ipip_init_state ( struct xfrm_state * x )
2005-04-17 02:20:36 +04:00
{
2006-09-23 02:05:15 +04:00
if ( x - > props . mode ! = XFRM_MODE_TUNNEL )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
if ( x - > encap )
return - EINVAL ;
x - > props . header_len = sizeof ( struct iphdr ) ;
return 0 ;
}
static void ipip_destroy ( struct xfrm_state * x )
{
}
2008-01-31 06:11:50 +03:00
static const struct xfrm_type ipip_type = {
2005-04-17 02:20:36 +04:00
. description = " IPIP " ,
. owner = THIS_MODULE ,
. proto = IPPROTO_IPIP ,
. init_state = ipip_init_state ,
. destructor = ipip_destroy ,
. input = ipip_xfrm_rcv ,
. output = ipip_output
} ;
2007-10-18 08:28:53 +04:00
static int xfrm_tunnel_rcv ( struct sk_buff * skb )
{
2008-01-31 08:48:24 +03:00
return xfrm4_rcv_spi ( skb , IPPROTO_IPIP , ip_hdr ( skb ) - > saddr ) ;
2007-10-18 08:28:53 +04:00
}
2006-03-28 13:12:13 +04:00
static int xfrm_tunnel_err ( struct sk_buff * skb , u32 info )
{
return - ENOENT ;
}
2010-08-30 11:04:14 +04:00
static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
2007-10-18 08:28:53 +04:00
. handler = xfrm_tunnel_rcv ,
2006-03-28 13:12:13 +04:00
. err_handler = xfrm_tunnel_err ,
. priority = 2 ,
2005-04-17 02:20:36 +04:00
} ;
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2010-08-30 11:04:14 +04:00
static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = {
2007-10-18 08:28:53 +04:00
. handler = xfrm_tunnel_rcv ,
2007-02-13 23:54:47 +03:00
. err_handler = xfrm_tunnel_err ,
. priority = 2 ,
} ;
# endif
2005-04-17 02:20:36 +04:00
static int __init ipip_init ( void )
{
if ( xfrm_register_type ( & ipip_type , AF_INET ) < 0 ) {
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't add xfrm type \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
return - EAGAIN ;
}
2007-02-13 23:54:47 +03:00
if ( xfrm4_tunnel_register ( & xfrm_tunnel_handler , AF_INET ) ) {
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't add xfrm handler for AF_INET \n " , __func__ ) ;
2007-02-13 23:54:47 +03:00
xfrm_unregister_type ( & ipip_type , AF_INET ) ;
return - EAGAIN ;
}
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2007-02-13 23:54:47 +03:00
if ( xfrm4_tunnel_register ( & xfrm64_tunnel_handler , AF_INET6 ) ) {
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't add xfrm handler for AF_INET6 \n " , __func__ ) ;
2007-02-13 23:54:47 +03:00
xfrm4_tunnel_deregister ( & xfrm_tunnel_handler , AF_INET ) ;
2005-04-17 02:20:36 +04:00
xfrm_unregister_type ( & ipip_type , AF_INET ) ;
return - EAGAIN ;
}
2007-02-13 23:54:47 +03:00
# endif
2005-04-17 02:20:36 +04:00
return 0 ;
}
static void __exit ipip_fini ( void )
{
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2007-02-13 23:54:47 +03:00
if ( xfrm4_tunnel_deregister ( & xfrm64_tunnel_handler , AF_INET6 ) )
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't remove xfrm handler for AF_INET6 \n " ,
__func__ ) ;
2007-02-13 23:54:47 +03:00
# endif
if ( xfrm4_tunnel_deregister ( & xfrm_tunnel_handler , AF_INET ) )
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't remove xfrm handler for AF_INET \n " ,
__func__ ) ;
2005-04-17 02:20:36 +04:00
if ( xfrm_unregister_type ( & ipip_type , AF_INET ) < 0 )
2012-03-11 22:36:11 +04:00
pr_info ( " %s: can't remove xfrm type \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( ipip_init ) ;
module_exit ( ipip_fini ) ;
MODULE_LICENSE ( " GPL " ) ;
2007-06-27 10:57:49 +04:00
MODULE_ALIAS_XFRM_TYPE ( AF_INET , XFRM_PROTO_IPIP ) ;