ALSA: Revert "ALSA: snd-usb-caiaq: Set default input mode of A4DJ"
[safe/jmp/linux-2.6] / net / ipv4 / ip_gre.c
index 71a3242..fe381d1 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -125,7 +126,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev);
 
 #define HASH_SIZE  16
 
-static int ipgre_net_id;
+static int ipgre_net_id __read_mostly;
 struct ipgre_net {
        struct ip_tunnel *tunnels[4][HASH_SIZE];
 
@@ -793,7 +794,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                }
 
                if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
                }
@@ -810,11 +811,13 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        tunnel->err_count = 0;
        }
 
-       max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
+       max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->u.dst.header_len;
 
        if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
            (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
                struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+               if (max_headroom > dev->needed_headroom)
+                       dev->needed_headroom = max_headroom;
                if (!new_skb) {
                        ip_rt_put(rt);
                        txq->tx_dropped++;
@@ -1144,12 +1147,9 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
 
        if (saddr)
                memcpy(&iph->saddr, saddr, 4);
-
-       if (daddr) {
+       if (daddr)
                memcpy(&iph->daddr, daddr, 4);
-               return t->hlen;
-       }
-       if (iph->daddr && !ipv4_is_multicast(iph->daddr))
+       if (iph->daddr)
                return t->hlen;
 
        return -t->hlen;
@@ -1307,19 +1307,10 @@ static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
        }
 }
 
-static int ipgre_init_net(struct net *net)
+static int __net_init ipgre_init_net(struct net *net)
 {
+       struct ipgre_net *ign = net_generic(net, ipgre_net_id);
        int err;
-       struct ipgre_net *ign;
-
-       err = -ENOMEM;
-       ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
-       if (ign == NULL)
-               goto err_alloc;
-
-       err = net_assign_generic(net, ipgre_net_id, ign);
-       if (err < 0)
-               goto err_assign;
 
        ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
                                           ipgre_tunnel_setup);
@@ -1340,14 +1331,10 @@ static int ipgre_init_net(struct net *net)
 err_reg_dev:
        free_netdev(ign->fb_tunnel_dev);
 err_alloc_dev:
-       /* nothing */
-err_assign:
-       kfree(ign);
-err_alloc:
        return err;
 }
 
-static void ipgre_exit_net(struct net *net)
+static void __net_exit ipgre_exit_net(struct net *net)
 {
        struct ipgre_net *ign;
        LIST_HEAD(list);
@@ -1357,12 +1344,13 @@ static void ipgre_exit_net(struct net *net)
        ipgre_destroy_tunnels(ign, &list);
        unregister_netdevice_many(&list);
        rtnl_unlock();
-       kfree(ign);
 }
 
 static struct pernet_operations ipgre_net_ops = {
        .init = ipgre_init_net,
        .exit = ipgre_exit_net,
+       .id   = &ipgre_net_id,
+       .size = sizeof(struct ipgre_net),
 };
 
 static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1483,7 +1471,7 @@ static void ipgre_tap_setup(struct net_device *dev)
        dev->features           |= NETIF_F_NETNS_LOCAL;
 }
 
-static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[],
+static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
                         struct nlattr *data[])
 {
        struct ip_tunnel *nt;
@@ -1677,15 +1665,16 @@ static int __init ipgre_init(void)
 
        printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
 
-       if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
+       err = register_pernet_device(&ipgre_net_ops);
+       if (err < 0)
+               return err;
+
+       err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE);
+       if (err < 0) {
                printk(KERN_INFO "ipgre init: can't add protocol\n");
-               return -EAGAIN;
+               goto add_proto_failed;
        }
 
-       err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
-       if (err < 0)
-               goto gen_device_failed;
-
        err = rtnl_link_register(&ipgre_link_ops);
        if (err < 0)
                goto rtnl_link_failed;
@@ -1700,9 +1689,9 @@ out:
 tap_ops_failed:
        rtnl_link_unregister(&ipgre_link_ops);
 rtnl_link_failed:
-       unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
-gen_device_failed:
        inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+add_proto_failed:
+       unregister_pernet_device(&ipgre_net_ops);
        goto out;
 }
 
@@ -1710,9 +1699,9 @@ static void __exit ipgre_fini(void)
 {
        rtnl_link_unregister(&ipgre_tap_ops);
        rtnl_link_unregister(&ipgre_link_ops);
-       unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
        if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
                printk(KERN_INFO "ipgre close: can't remove protocol\n");
+       unregister_pernet_device(&ipgre_net_ops);
 }
 
 module_init(ipgre_init);