diff options
-rw-r--r-- | net/ipv4/ipip.c | 66 |
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 | ||
654 | static 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 | |||
654 | static int | 688 | static int |
655 | ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 689 | ipip_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 | ||
792 | static int ipip_tunnel_init(struct net_device *dev) | 831 | static 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 | } |