diff options
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r-- | net/ipv4/ip_gre.c | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 4b93f32de10d..0832f6e028b8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -896,6 +896,59 @@ tx_error: | |||
896 | return 0; | 896 | return 0; |
897 | } | 897 | } |
898 | 898 | ||
899 | static void ipgre_tunnel_bind_dev(struct net_device *dev) | ||
900 | { | ||
901 | struct net_device *tdev = NULL; | ||
902 | struct ip_tunnel *tunnel; | ||
903 | struct iphdr *iph; | ||
904 | int hlen = LL_MAX_HEADER; | ||
905 | int mtu = ETH_DATA_LEN; | ||
906 | int addend = sizeof(struct iphdr) + 4; | ||
907 | |||
908 | tunnel = netdev_priv(dev); | ||
909 | iph = &tunnel->parms.iph; | ||
910 | |||
911 | /* Guess output device to choose reasonable mtu and hard_header_len */ | ||
912 | |||
913 | if (iph->daddr) { | ||
914 | struct flowi fl = { .oif = tunnel->parms.link, | ||
915 | .nl_u = { .ip4_u = | ||
916 | { .daddr = iph->daddr, | ||
917 | .saddr = iph->saddr, | ||
918 | .tos = RT_TOS(iph->tos) } }, | ||
919 | .proto = IPPROTO_GRE }; | ||
920 | struct rtable *rt; | ||
921 | if (!ip_route_output_key(&rt, &fl)) { | ||
922 | tdev = rt->u.dst.dev; | ||
923 | ip_rt_put(rt); | ||
924 | } | ||
925 | dev->flags |= IFF_POINTOPOINT; | ||
926 | } | ||
927 | |||
928 | if (!tdev && tunnel->parms.link) | ||
929 | tdev = __dev_get_by_index(&init_net, tunnel->parms.link); | ||
930 | |||
931 | if (tdev) { | ||
932 | hlen = tdev->hard_header_len; | ||
933 | mtu = tdev->mtu; | ||
934 | } | ||
935 | dev->iflink = tunnel->parms.link; | ||
936 | |||
937 | /* Precalculate GRE options length */ | ||
938 | if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | ||
939 | if (tunnel->parms.o_flags&GRE_CSUM) | ||
940 | addend += 4; | ||
941 | if (tunnel->parms.o_flags&GRE_KEY) | ||
942 | addend += 4; | ||
943 | if (tunnel->parms.o_flags&GRE_SEQ) | ||
944 | addend += 4; | ||
945 | } | ||
946 | dev->hard_header_len = hlen + addend; | ||
947 | dev->mtu = mtu - addend; | ||
948 | tunnel->hlen = addend; | ||
949 | |||
950 | } | ||
951 | |||
899 | static int | 952 | static int |
900 | ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 953 | ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) |
901 | { | 954 | { |
@@ -983,6 +1036,11 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
983 | t->parms.iph.ttl = p.iph.ttl; | 1036 | t->parms.iph.ttl = p.iph.ttl; |
984 | t->parms.iph.tos = p.iph.tos; | 1037 | t->parms.iph.tos = p.iph.tos; |
985 | t->parms.iph.frag_off = p.iph.frag_off; | 1038 | t->parms.iph.frag_off = p.iph.frag_off; |
1039 | if (t->parms.link != p.link) { | ||
1040 | t->parms.link = p.link; | ||
1041 | ipgre_tunnel_bind_dev(dev); | ||
1042 | netdev_state_change(dev); | ||
1043 | } | ||
986 | } | 1044 | } |
987 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) | 1045 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) |
988 | err = -EFAULT; | 1046 | err = -EFAULT; |
@@ -1162,12 +1220,8 @@ static void ipgre_tunnel_setup(struct net_device *dev) | |||
1162 | 1220 | ||
1163 | static int ipgre_tunnel_init(struct net_device *dev) | 1221 | static int ipgre_tunnel_init(struct net_device *dev) |
1164 | { | 1222 | { |
1165 | struct net_device *tdev = NULL; | ||
1166 | struct ip_tunnel *tunnel; | 1223 | struct ip_tunnel *tunnel; |
1167 | struct iphdr *iph; | 1224 | struct iphdr *iph; |
1168 | int hlen = LL_MAX_HEADER; | ||
1169 | int mtu = ETH_DATA_LEN; | ||
1170 | int addend = sizeof(struct iphdr) + 4; | ||
1171 | 1225 | ||
1172 | tunnel = netdev_priv(dev); | 1226 | tunnel = netdev_priv(dev); |
1173 | iph = &tunnel->parms.iph; | 1227 | iph = &tunnel->parms.iph; |
@@ -1178,23 +1232,9 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
1178 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 1232 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
1179 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 1233 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
1180 | 1234 | ||
1181 | /* Guess output device to choose reasonable mtu and hard_header_len */ | 1235 | ipgre_tunnel_bind_dev(dev); |
1182 | 1236 | ||
1183 | if (iph->daddr) { | 1237 | if (iph->daddr) { |
1184 | struct flowi fl = { .oif = tunnel->parms.link, | ||
1185 | .nl_u = { .ip4_u = | ||
1186 | { .daddr = iph->daddr, | ||
1187 | .saddr = iph->saddr, | ||
1188 | .tos = RT_TOS(iph->tos) } }, | ||
1189 | .proto = IPPROTO_GRE }; | ||
1190 | struct rtable *rt; | ||
1191 | if (!ip_route_output_key(&rt, &fl)) { | ||
1192 | tdev = rt->u.dst.dev; | ||
1193 | ip_rt_put(rt); | ||
1194 | } | ||
1195 | |||
1196 | dev->flags |= IFF_POINTOPOINT; | ||
1197 | |||
1198 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 1238 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
1199 | if (MULTICAST(iph->daddr)) { | 1239 | if (MULTICAST(iph->daddr)) { |
1200 | if (!iph->saddr) | 1240 | if (!iph->saddr) |
@@ -1205,31 +1245,9 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
1205 | dev->stop = ipgre_close; | 1245 | dev->stop = ipgre_close; |
1206 | } | 1246 | } |
1207 | #endif | 1247 | #endif |
1208 | } else { | 1248 | } else |
1209 | dev->header_ops = &ipgre_header_ops; | 1249 | dev->header_ops = &ipgre_header_ops; |
1210 | } | ||
1211 | |||
1212 | if (!tdev && tunnel->parms.link) | ||
1213 | tdev = __dev_get_by_index(&init_net, tunnel->parms.link); | ||
1214 | |||
1215 | if (tdev) { | ||
1216 | hlen = tdev->hard_header_len; | ||
1217 | mtu = tdev->mtu; | ||
1218 | } | ||
1219 | dev->iflink = tunnel->parms.link; | ||
1220 | 1250 | ||
1221 | /* Precalculate GRE options length */ | ||
1222 | if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | ||
1223 | if (tunnel->parms.o_flags&GRE_CSUM) | ||
1224 | addend += 4; | ||
1225 | if (tunnel->parms.o_flags&GRE_KEY) | ||
1226 | addend += 4; | ||
1227 | if (tunnel->parms.o_flags&GRE_SEQ) | ||
1228 | addend += 4; | ||
1229 | } | ||
1230 | dev->hard_header_len = hlen + addend; | ||
1231 | dev->mtu = mtu - addend; | ||
1232 | tunnel->hlen = addend; | ||
1233 | return 0; | 1251 | return 0; |
1234 | } | 1252 | } |
1235 | 1253 | ||