diff options
-rw-r--r-- | net/ipv6/sit.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b3b8513e9cb7..1c6fddb80b37 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -669,6 +669,42 @@ tx_error: | |||
669 | return 0; | 669 | return 0; |
670 | } | 670 | } |
671 | 671 | ||
672 | static void ipip6_tunnel_bind_dev(struct net_device *dev) | ||
673 | { | ||
674 | struct net_device *tdev = NULL; | ||
675 | struct ip_tunnel *tunnel; | ||
676 | struct iphdr *iph; | ||
677 | |||
678 | tunnel = netdev_priv(dev); | ||
679 | iph = &tunnel->parms.iph; | ||
680 | |||
681 | if (iph->daddr) { | ||
682 | struct flowi fl = { .nl_u = { .ip4_u = | ||
683 | { .daddr = iph->daddr, | ||
684 | .saddr = iph->saddr, | ||
685 | .tos = RT_TOS(iph->tos) } }, | ||
686 | .oif = tunnel->parms.link, | ||
687 | .proto = IPPROTO_IPV6 }; | ||
688 | struct rtable *rt; | ||
689 | if (!ip_route_output_key(&rt, &fl)) { | ||
690 | tdev = rt->u.dst.dev; | ||
691 | ip_rt_put(rt); | ||
692 | } | ||
693 | dev->flags |= IFF_POINTOPOINT; | ||
694 | } | ||
695 | |||
696 | if (!tdev && tunnel->parms.link) | ||
697 | tdev = __dev_get_by_index(&init_net, tunnel->parms.link); | ||
698 | |||
699 | if (tdev) { | ||
700 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | ||
701 | dev->mtu = tdev->mtu - sizeof(struct iphdr); | ||
702 | if (dev->mtu < IPV6_MIN_MTU) | ||
703 | dev->mtu = IPV6_MIN_MTU; | ||
704 | } | ||
705 | dev->iflink = tunnel->parms.link; | ||
706 | } | ||
707 | |||
672 | static int | 708 | static int |
673 | ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 709 | ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) |
674 | { | 710 | { |
@@ -740,6 +776,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
740 | if (cmd == SIOCCHGTUNNEL) { | 776 | if (cmd == SIOCCHGTUNNEL) { |
741 | t->parms.iph.ttl = p.iph.ttl; | 777 | t->parms.iph.ttl = p.iph.ttl; |
742 | t->parms.iph.tos = p.iph.tos; | 778 | t->parms.iph.tos = p.iph.tos; |
779 | if (t->parms.link != p.link) { | ||
780 | t->parms.link = p.link; | ||
781 | ipip6_tunnel_bind_dev(dev); | ||
782 | netdev_state_change(dev); | ||
783 | } | ||
743 | } | 784 | } |
744 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) | 785 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) |
745 | err = -EFAULT; | 786 | err = -EFAULT; |
@@ -808,12 +849,9 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
808 | 849 | ||
809 | static int ipip6_tunnel_init(struct net_device *dev) | 850 | static int ipip6_tunnel_init(struct net_device *dev) |
810 | { | 851 | { |
811 | struct net_device *tdev = NULL; | ||
812 | struct ip_tunnel *tunnel; | 852 | struct ip_tunnel *tunnel; |
813 | struct iphdr *iph; | ||
814 | 853 | ||
815 | tunnel = netdev_priv(dev); | 854 | tunnel = netdev_priv(dev); |
816 | iph = &tunnel->parms.iph; | ||
817 | 855 | ||
818 | tunnel->dev = dev; | 856 | tunnel->dev = dev; |
819 | strcpy(tunnel->parms.name, dev->name); | 857 | strcpy(tunnel->parms.name, dev->name); |
@@ -821,31 +859,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
821 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 859 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
822 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 860 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
823 | 861 | ||
824 | if (iph->daddr) { | 862 | ipip6_tunnel_bind_dev(dev); |
825 | struct flowi fl = { .nl_u = { .ip4_u = | ||
826 | { .daddr = iph->daddr, | ||
827 | .saddr = iph->saddr, | ||
828 | .tos = RT_TOS(iph->tos) } }, | ||
829 | .oif = tunnel->parms.link, | ||
830 | .proto = IPPROTO_IPV6 }; | ||
831 | struct rtable *rt; | ||
832 | if (!ip_route_output_key(&rt, &fl)) { | ||
833 | tdev = rt->u.dst.dev; | ||
834 | ip_rt_put(rt); | ||
835 | } | ||
836 | dev->flags |= IFF_POINTOPOINT; | ||
837 | } | ||
838 | |||
839 | if (!tdev && tunnel->parms.link) | ||
840 | tdev = __dev_get_by_index(&init_net, tunnel->parms.link); | ||
841 | |||
842 | if (tdev) { | ||
843 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | ||
844 | dev->mtu = tdev->mtu - sizeof(struct iphdr); | ||
845 | if (dev->mtu < IPV6_MIN_MTU) | ||
846 | dev->mtu = IPV6_MIN_MTU; | ||
847 | } | ||
848 | dev->iflink = tunnel->parms.link; | ||
849 | 863 | ||
850 | return 0; | 864 | return 0; |
851 | } | 865 | } |