2005-04-17 02:20:36 +04:00
/*
* xfrm6_output . c - Common IPsec encapsulation code for IPv6 .
* Copyright ( C ) 2002 USAGI / WIDE Project
* Copyright ( c ) 2004 Herbert Xu < herbert @ gondor . apana . org . au >
2007-02-09 17:24:49 +03:00
*
2005-04-17 02:20:36 +04:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
2007-10-09 04:16:30 +04:00
# include <linux/if_ether.h>
2007-11-14 08:40:52 +03:00
# include <linux/kernel.h>
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/skbuff.h>
# include <linux/icmpv6.h>
2006-01-07 10:01:48 +03:00
# include <linux/netfilter_ipv6.h>
2007-11-14 08:40:52 +03:00
# include <net/dst.h>
2005-04-17 02:20:36 +04:00
# include <net/ipv6.h>
# include <net/xfrm.h>
2006-08-24 04:57:28 +04:00
int xfrm6_find_1stfragopt ( struct xfrm_state * x , struct sk_buff * skb ,
u8 * * prevhdr )
{
return ip6_find_1stfragopt ( skb , prevhdr ) ;
}
2007-02-22 16:05:40 +03:00
EXPORT_SYMBOL ( xfrm6_find_1stfragopt ) ;
2005-04-17 02:20:36 +04:00
static int xfrm6_tunnel_check_size ( struct sk_buff * skb )
{
int mtu , ret = 0 ;
struct dst_entry * dst = skb - > dst ;
mtu = dst_mtu ( dst ) ;
if ( mtu < IPV6_MIN_MTU )
mtu = IPV6_MIN_MTU ;
2008-02-13 05:07:27 +03:00
if ( ! skb - > local_df & & skb - > len > mtu ) {
2005-05-24 00:11:07 +04:00
skb - > dev = dst - > dev ;
2005-04-17 02:20:36 +04:00
icmpv6_send ( skb , ICMPV6_PKT_TOOBIG , 0 , mtu , skb - > dev ) ;
ret = - EMSGSIZE ;
}
return ret ;
}
2007-11-14 08:40:52 +03:00
int xfrm6_extract_output ( struct xfrm_state * x , struct sk_buff * skb )
{
int err ;
err = xfrm6_tunnel_check_size ( skb ) ;
if ( err )
return err ;
2007-11-20 05:47:58 +03:00
XFRM_MODE_SKB_CB ( skb ) - > protocol = ipv6_hdr ( skb ) - > nexthdr ;
2007-11-14 08:40:52 +03:00
return xfrm6_extract_header ( skb ) ;
}
int xfrm6_prepare_output ( struct xfrm_state * x , struct sk_buff * skb )
{
int err ;
2008-03-25 00:51:51 +03:00
err = xfrm_inner_extract_output ( x , skb ) ;
2007-11-14 08:40:52 +03:00
if ( err )
return err ;
memset ( IP6CB ( skb ) , 0 , sizeof ( * IP6CB ( skb ) ) ) ;
2007-11-14 08:43:11 +03:00
# ifdef CONFIG_NETFILTER
IP6CB ( skb ) - > flags | = IP6SKB_XFRM_TRANSFORMED ;
# endif
2007-11-14 08:40:52 +03:00
skb - > protocol = htons ( ETH_P_IPV6 ) ;
return x - > outer_mode - > output2 ( x , skb ) ;
}
EXPORT_SYMBOL ( xfrm6_prepare_output ) ;
2006-06-22 14:08:03 +04:00
static int xfrm6_output_finish ( struct sk_buff * skb )
{
2007-11-14 08:43:11 +03:00
# ifdef CONFIG_NETFILTER
IP6CB ( skb ) - > flags | = IP6SKB_XFRM_TRANSFORMED ;
# endif
2006-06-22 14:08:03 +04:00
2006-07-31 07:19:11 +04:00
skb - > protocol = htons ( ETH_P_IPV6 ) ;
2007-11-14 08:43:11 +03:00
return xfrm_output ( skb ) ;
2006-06-22 14:08:03 +04:00
}
2006-01-07 10:01:48 +03:00
int xfrm6_output ( struct sk_buff * skb )
{
2007-11-20 05:53:30 +03:00
return NF_HOOK ( PF_INET6 , NF_INET_POST_ROUTING , skb , NULL , skb - > dst - > dev ,
2006-01-07 10:01:48 +03:00
xfrm6_output_finish ) ;
}