aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/ipip.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 8c2b2b0741da..160535b51705 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -651,6 +651,40 @@ tx_error:
651 return 0; 651 return 0;
652} 652}
653 653
654static void ipip_tunnel_bind_dev(struct net_device *dev)
655{
656 struct net_device *tdev = NULL;
657 struct ip_tunnel *tunnel;
658 struct iphdr *iph;
659
660 tunnel = netdev_priv(dev);
661 iph = &tunnel->parms.iph;
662
663 if (iph->daddr) {
664 struct flowi fl = { .oif = tunnel->parms.link,
665 .nl_u = { .ip4_u =
666 { .daddr = iph->daddr,
667 .saddr = iph->saddr,
668 .tos = RT_TOS(iph->tos) } },
669 .proto = IPPROTO_IPIP };
670 struct rtable *rt;
671 if (!ip_route_output_key(&rt, &fl)) {
672 tdev = rt->u.dst.dev;
673 ip_rt_put(rt);
674 }
675 dev->flags |= IFF_POINTOPOINT;
676 }
677
678 if (!tdev && tunnel->parms.link)
679 tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
680
681 if (tdev) {
682 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
683 dev->mtu = tdev->mtu - sizeof(struct iphdr);
684 }
685 dev->iflink = tunnel->parms.link;
686}
687
654static int 688static int
655ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) 689ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
656{ 690{
@@ -723,6 +757,11 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
723 t->parms.iph.ttl = p.iph.ttl; 757 t->parms.iph.ttl = p.iph.ttl;
724 t->parms.iph.tos = p.iph.tos; 758 t->parms.iph.tos = p.iph.tos;
725 t->parms.iph.frag_off = p.iph.frag_off; 759 t->parms.iph.frag_off = p.iph.frag_off;
760 if (t->parms.link != p.link) {
761 t->parms.link = p.link;
762 ipip_tunnel_bind_dev(dev);
763 netdev_state_change(dev);
764 }
726 } 765 }
727 if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) 766 if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
728 err = -EFAULT; 767 err = -EFAULT;
@@ -791,12 +830,9 @@ static void ipip_tunnel_setup(struct net_device *dev)
791 830
792static int ipip_tunnel_init(struct net_device *dev) 831static int ipip_tunnel_init(struct net_device *dev)
793{ 832{
794 struct net_device *tdev = NULL;
795 struct ip_tunnel *tunnel; 833 struct ip_tunnel *tunnel;
796 struct iphdr *iph;
797 834
798 tunnel = netdev_priv(dev); 835 tunnel = netdev_priv(dev);
799 iph = &tunnel->parms.iph;
800 836
801 tunnel->dev = dev; 837 tunnel->dev = dev;
802 strcpy(tunnel->parms.name, dev->name); 838 strcpy(tunnel->parms.name, dev->name);
@@ -804,29 +840,7 @@ static int ipip_tunnel_init(struct net_device *dev)
804 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); 840 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
805 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); 841 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
806 842
807 if (iph->daddr) { 843 ipip_tunnel_bind_dev(dev);
808 struct flowi fl = { .oif = tunnel->parms.link,
809 .nl_u = { .ip4_u =
810 { .daddr = iph->daddr,
811 .saddr = iph->saddr,
812 .tos = RT_TOS(iph->tos) } },
813 .proto = IPPROTO_IPIP };
814 struct rtable *rt;
815 if (!ip_route_output_key(&rt, &fl)) {
816 tdev = rt->u.dst.dev;
817 ip_rt_put(rt);
818 }
819 dev->flags |= IFF_POINTOPOINT;
820 }
821
822 if (!tdev && tunnel->parms.link)
823 tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
824
825 if (tdev) {
826 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
827 dev->mtu = tdev->mtu - sizeof(struct iphdr);
828 }
829 dev->iflink = tunnel->parms.link;
830 844
831 return 0; 845 return 0;
832} 846}