aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c102
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
899static 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
899static int 952static int
900ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) 953ipgre_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
1163static int ipgre_tunnel_init(struct net_device *dev) 1221static 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