]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/ip_gre.c
[IPV4] net/core: Use ipv4_is_<type>
[net-next-2.6.git] / net / ipv4 / ip_gre.c
index 02b02a8d681c85680d33d05bc2bdd7b710ef2672..0832f6e028b85927d07099e43a37ca1f24f4e764 100644 (file)
@@ -613,7 +613,7 @@ static int ipgre_rcv(struct sk_buff *skb)
                                offset += 4;
                }
 
-               skb_reset_mac_header(skb);
+               skb->mac_header = skb->network_header;
                __pskb_pull(skb, offset);
                skb_reset_network_header(skb);
                skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
@@ -896,6 +896,59 @@ tx_error:
        return 0;
 }
 
+static void ipgre_tunnel_bind_dev(struct net_device *dev)
+{
+       struct net_device *tdev = NULL;
+       struct ip_tunnel *tunnel;
+       struct iphdr *iph;
+       int hlen = LL_MAX_HEADER;
+       int mtu = ETH_DATA_LEN;
+       int addend = sizeof(struct iphdr) + 4;
+
+       tunnel = netdev_priv(dev);
+       iph = &tunnel->parms.iph;
+
+       /* Guess output device to choose reasonable mtu and hard_header_len */
+
+       if (iph->daddr) {
+               struct flowi fl = { .oif = tunnel->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = iph->daddr,
+                                               .saddr = iph->saddr,
+                                               .tos = RT_TOS(iph->tos) } },
+                                   .proto = IPPROTO_GRE };
+               struct rtable *rt;
+               if (!ip_route_output_key(&rt, &fl)) {
+                       tdev = rt->u.dst.dev;
+                       ip_rt_put(rt);
+               }
+               dev->flags |= IFF_POINTOPOINT;
+       }
+
+       if (!tdev && tunnel->parms.link)
+               tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
+
+       if (tdev) {
+               hlen = tdev->hard_header_len;
+               mtu = tdev->mtu;
+       }
+       dev->iflink = tunnel->parms.link;
+
+       /* Precalculate GRE options length */
+       if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
+               if (tunnel->parms.o_flags&GRE_CSUM)
+                       addend += 4;
+               if (tunnel->parms.o_flags&GRE_KEY)
+                       addend += 4;
+               if (tunnel->parms.o_flags&GRE_SEQ)
+                       addend += 4;
+       }
+       dev->hard_header_len = hlen + addend;
+       dev->mtu = mtu - addend;
+       tunnel->hlen = addend;
+
+}
+
 static int
 ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -983,6 +1036,11 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                                t->parms.iph.ttl = p.iph.ttl;
                                t->parms.iph.tos = p.iph.tos;
                                t->parms.iph.frag_off = p.iph.frag_off;
+                               if (t->parms.link != p.link) {
+                                       t->parms.link = p.link;
+                                       ipgre_tunnel_bind_dev(dev);
+                                       netdev_state_change(dev);
+                               }
                        }
                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
                                err = -EFAULT;
@@ -1162,12 +1220,8 @@ static void ipgre_tunnel_setup(struct net_device *dev)
 
 static int ipgre_tunnel_init(struct net_device *dev)
 {
-       struct net_device *tdev = NULL;
        struct ip_tunnel *tunnel;
        struct iphdr *iph;
-       int hlen = LL_MAX_HEADER;
-       int mtu = ETH_DATA_LEN;
-       int addend = sizeof(struct iphdr) + 4;
 
        tunnel = netdev_priv(dev);
        iph = &tunnel->parms.iph;
@@ -1178,23 +1232,9 @@ static int ipgre_tunnel_init(struct net_device *dev)
        memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
        memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
 
-       /* Guess output device to choose reasonable mtu and hard_header_len */
+       ipgre_tunnel_bind_dev(dev);
 
        if (iph->daddr) {
-               struct flowi fl = { .oif = tunnel->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = iph->daddr,
-                                               .saddr = iph->saddr,
-                                               .tos = RT_TOS(iph->tos) } },
-                                   .proto = IPPROTO_GRE };
-               struct rtable *rt;
-               if (!ip_route_output_key(&rt, &fl)) {
-                       tdev = rt->u.dst.dev;
-                       ip_rt_put(rt);
-               }
-
-               dev->flags |= IFF_POINTOPOINT;
-
 #ifdef CONFIG_NET_IPGRE_BROADCAST
                if (MULTICAST(iph->daddr)) {
                        if (!iph->saddr)
@@ -1205,31 +1245,9 @@ static int ipgre_tunnel_init(struct net_device *dev)
                        dev->stop = ipgre_close;
                }
 #endif
-       } else {
+       } else
                dev->header_ops = &ipgre_header_ops;
-       }
-
-       if (!tdev && tunnel->parms.link)
-               tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
-
-       if (tdev) {
-               hlen = tdev->hard_header_len;
-               mtu = tdev->mtu;
-       }
-       dev->iflink = tunnel->parms.link;
 
-       /* Precalculate GRE options length */
-       if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
-               if (tunnel->parms.o_flags&GRE_CSUM)
-                       addend += 4;
-               if (tunnel->parms.o_flags&GRE_KEY)
-                       addend += 4;
-               if (tunnel->parms.o_flags&GRE_SEQ)
-                       addend += 4;
-       }
-       dev->hard_header_len = hlen + addend;
-       dev->mtu = mtu - addend;
-       tunnel->hlen = addend;
        return 0;
 }