diff options
Diffstat (limited to 'net/ipv6/ipcomp6.c')
| -rw-r--r-- | net/ipv6/ipcomp6.c | 51 | 
1 files changed, 33 insertions, 18 deletions
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85cccd6ed0b..d1c793cffcb 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -16,8 +16,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /*   * [Memo] @@ -30,6 +29,9 @@   *  The decompression of IP datagram MUST be done after the reassembly,   *  AH/ESP processing.   */ + +#define pr_fmt(fmt) "IPv6: " fmt +  #include <linux/module.h>  #include <net/ip.h>  #include <net/xfrm.h> @@ -43,6 +45,7 @@  #include <linux/list.h>  #include <linux/vmalloc.h>  #include <linux/rtnetlink.h> +#include <net/ip6_route.h>  #include <net/icmp.h>  #include <net/ipv6.h>  #include <net/protocol.h> @@ -50,27 +53,33 @@  #include <linux/icmpv6.h>  #include <linux/mutex.h> -static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, +static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  				u8 type, u8 code, int offset, __be32 info)  {  	struct net *net = dev_net(skb->dev);  	__be32 spi; -	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; +	const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;  	struct ip_comp_hdr *ipcomph =  		(struct ip_comp_hdr *)(skb->data + offset);  	struct xfrm_state *x; -	if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG) -		return; +	if (type != ICMPV6_PKT_TOOBIG && +	    type != NDISC_REDIRECT) +		return 0;  	spi = htonl(ntohs(ipcomph->cpi)); -	x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); +	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, +			      spi, IPPROTO_COMP, AF_INET6);  	if (!x) -		return; +		return 0; -	printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI6\n", -			spi, &iph->daddr); +	if (type == NDISC_REDIRECT) +		ip6_redirect(skb, net, skb->dev->ifindex, 0); +	else +		ip6_update_pmtu(skb, net, info, 0, 0);  	xfrm_state_put(x); + +	return 0;  }  static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) @@ -167,6 +176,11 @@ out:  	return err;  } +static int ipcomp6_rcv_cb(struct sk_buff *skb, int err) +{ +	return 0; +} +  static const struct xfrm_type ipcomp6_type =  {  	.description	= "IPCOMP6", @@ -179,21 +193,22 @@ static const struct xfrm_type ipcomp6_type =  	.hdr_offset	= xfrm6_find_1stfragopt,  }; -static const struct inet6_protocol ipcomp6_protocol = +static struct xfrm6_protocol ipcomp6_protocol =  {  	.handler	= xfrm6_rcv, +	.cb_handler	= ipcomp6_rcv_cb,  	.err_handler	= ipcomp6_err, -	.flags		= INET6_PROTO_NOPOLICY, +	.priority	= 0,  };  static int __init ipcomp6_init(void)  {  	if (xfrm_register_type(&ipcomp6_type, AF_INET6) < 0) { -		printk(KERN_INFO "ipcomp6 init: can't add xfrm type\n"); +		pr_info("%s: can't add xfrm type\n", __func__);  		return -EAGAIN;  	} -	if (inet6_add_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) { -		printk(KERN_INFO "ipcomp6 init: can't add protocol\n"); +	if (xfrm6_protocol_register(&ipcomp6_protocol, IPPROTO_COMP) < 0) { +		pr_info("%s: can't add protocol\n", __func__);  		xfrm_unregister_type(&ipcomp6_type, AF_INET6);  		return -EAGAIN;  	} @@ -202,10 +217,10 @@ static int __init ipcomp6_init(void)  static void __exit ipcomp6_fini(void)  { -	if (inet6_del_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) -		printk(KERN_INFO "ipv6 ipcomp close: can't remove protocol\n"); +	if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0) +		pr_info("%s: can't remove protocol\n", __func__);  	if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0) -		printk(KERN_INFO "ipv6 ipcomp close: can't remove xfrm type\n"); +		pr_info("%s: can't remove xfrm type\n", __func__);  }  module_init(ipcomp6_init);  | 
