aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/sit.c70
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
672static 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
672static int 708static int
673ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) 709ipip6_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
809static int ipip6_tunnel_init(struct net_device *dev) 850static 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}