aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorMichal Schmidt <mschmidt@redhat.com>2007-12-13 12:47:00 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:56 -0500
commit8a4a50f98bc13670bee94c40b94bc169e1263cd9 (patch)
treeb262f239b7f91afc65b60032e64e15dba65e54ed /net/ipv6/sit.c
parentee34c1eb35923cc98b1c47488a615bf51a2a2afb (diff)
[IPV6] sit: Rebinding of SIT tunnels to other interfaces
This is similar to the change already done for IPIP tunnels. Once created, a SIT tunnel can't be bound to another device. To reproduce: # create a tunnel: ip tunnel add tunneltest0 mode sit remote 10.0.0.1 dev eth0 # try to change the bounding device from eth0 to eth1: ip tunnel change tunneltest0 dev eth1 # show the result: ip tunnel show tunneltest0 tunneltest0: ipv6/ip remote 10.0.0.1 local any dev eth0 ttl inherit Notice the bound device has not changed from eth0 to eth1. This patch fixes it. When changing the binding, it also recalculates the MTU according to the new bound device's MTU. Signed-off-by: Michal Schmidt <mschmidt@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/sit.c')
-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}