| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Linux NET3: IP/IP protocol decoder. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 16 | 17 | * Carlos Picoto : GRE over IP support |
|---|
| 17 | 18 | * Alexey Kuznetsov: Reworked. Really, now it is truncated version of ipv4/ip_gre.c. |
|---|
| 18 | 19 | * I do not want to merge them together. |
|---|
| 19 | | - * |
|---|
| 20 | | - * This program is free software; you can redistribute it and/or |
|---|
| 21 | | - * modify it under the terms of the GNU General Public License |
|---|
| 22 | | - * as published by the Free Software Foundation; either version |
|---|
| 23 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 24 | | - * |
|---|
| 25 | 20 | */ |
|---|
| 26 | 21 | |
|---|
| 27 | 22 | /* tunnel.c: an IP tunnel driver |
|---|
| .. | .. |
|---|
| 140 | 135 | struct ip_tunnel *t; |
|---|
| 141 | 136 | int err = 0; |
|---|
| 142 | 137 | |
|---|
| 138 | + t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, |
|---|
| 139 | + iph->daddr, iph->saddr, 0); |
|---|
| 140 | + if (!t) { |
|---|
| 141 | + err = -ENOENT; |
|---|
| 142 | + goto out; |
|---|
| 143 | + } |
|---|
| 144 | + |
|---|
| 143 | 145 | switch (type) { |
|---|
| 144 | 146 | case ICMP_DEST_UNREACH: |
|---|
| 145 | 147 | switch (code) { |
|---|
| .. | .. |
|---|
| 167 | 169 | goto out; |
|---|
| 168 | 170 | } |
|---|
| 169 | 171 | |
|---|
| 170 | | - t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, |
|---|
| 171 | | - iph->daddr, iph->saddr, 0); |
|---|
| 172 | | - if (!t) { |
|---|
| 173 | | - err = -ENOENT; |
|---|
| 174 | | - goto out; |
|---|
| 175 | | - } |
|---|
| 176 | | - |
|---|
| 177 | 172 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { |
|---|
| 178 | | - ipv4_update_pmtu(skb, net, info, t->parms.link, 0, |
|---|
| 179 | | - iph->protocol, 0); |
|---|
| 173 | + ipv4_update_pmtu(skb, net, info, t->parms.link, iph->protocol); |
|---|
| 180 | 174 | goto out; |
|---|
| 181 | 175 | } |
|---|
| 182 | 176 | |
|---|
| 183 | 177 | if (type == ICMP_REDIRECT) { |
|---|
| 184 | | - ipv4_redirect(skb, net, t->parms.link, 0, iph->protocol, 0); |
|---|
| 178 | + ipv4_redirect(skb, net, t->parms.link, iph->protocol); |
|---|
| 185 | 179 | goto out; |
|---|
| 186 | 180 | } |
|---|
| 187 | 181 | |
|---|
| .. | .. |
|---|
| 306 | 300 | skb_set_inner_ipproto(skb, ipproto); |
|---|
| 307 | 301 | |
|---|
| 308 | 302 | if (tunnel->collect_md) |
|---|
| 309 | | - ip_md_tunnel_xmit(skb, dev, ipproto); |
|---|
| 303 | + ip_md_tunnel_xmit(skb, dev, ipproto, 0); |
|---|
| 310 | 304 | else |
|---|
| 311 | 305 | ip_tunnel_xmit(skb, dev, tiph, ipproto); |
|---|
| 312 | 306 | return NETDEV_TX_OK; |
|---|
| .. | .. |
|---|
| 333 | 327 | } |
|---|
| 334 | 328 | |
|---|
| 335 | 329 | static int |
|---|
| 336 | | -ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
|---|
| 330 | +ipip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) |
|---|
| 337 | 331 | { |
|---|
| 338 | | - int err = 0; |
|---|
| 339 | | - struct ip_tunnel_parm p; |
|---|
| 340 | | - |
|---|
| 341 | | - if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
|---|
| 342 | | - return -EFAULT; |
|---|
| 343 | | - |
|---|
| 344 | 332 | if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { |
|---|
| 345 | | - if (p.iph.version != 4 || |
|---|
| 346 | | - !ipip_tunnel_ioctl_verify_protocol(p.iph.protocol) || |
|---|
| 347 | | - p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) |
|---|
| 333 | + if (p->iph.version != 4 || |
|---|
| 334 | + !ipip_tunnel_ioctl_verify_protocol(p->iph.protocol) || |
|---|
| 335 | + p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF))) |
|---|
| 348 | 336 | return -EINVAL; |
|---|
| 349 | 337 | } |
|---|
| 350 | 338 | |
|---|
| 351 | | - p.i_key = p.o_key = 0; |
|---|
| 352 | | - p.i_flags = p.o_flags = 0; |
|---|
| 353 | | - err = ip_tunnel_ioctl(dev, &p, cmd); |
|---|
| 354 | | - if (err) |
|---|
| 355 | | - return err; |
|---|
| 356 | | - |
|---|
| 357 | | - if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
|---|
| 358 | | - return -EFAULT; |
|---|
| 359 | | - |
|---|
| 360 | | - return 0; |
|---|
| 339 | + p->i_key = p->o_key = 0; |
|---|
| 340 | + p->i_flags = p->o_flags = 0; |
|---|
| 341 | + return ip_tunnel_ctl(dev, p, cmd); |
|---|
| 361 | 342 | } |
|---|
| 362 | 343 | |
|---|
| 363 | 344 | static const struct net_device_ops ipip_netdev_ops = { |
|---|
| 364 | 345 | .ndo_init = ipip_tunnel_init, |
|---|
| 365 | 346 | .ndo_uninit = ip_tunnel_uninit, |
|---|
| 366 | 347 | .ndo_start_xmit = ipip_tunnel_xmit, |
|---|
| 367 | | - .ndo_do_ioctl = ipip_tunnel_ioctl, |
|---|
| 348 | + .ndo_do_ioctl = ip_tunnel_ioctl, |
|---|
| 368 | 349 | .ndo_change_mtu = ip_tunnel_change_mtu, |
|---|
| 369 | 350 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
|---|
| 370 | 351 | .ndo_get_iflink = ip_tunnel_get_iflink, |
|---|
| 352 | + .ndo_tunnel_ctl = ipip_tunnel_ctl, |
|---|
| 371 | 353 | }; |
|---|
| 372 | 354 | |
|---|
| 373 | 355 | #define IPIP_FEATURES (NETIF_F_SG | \ |
|---|
| .. | .. |
|---|
| 379 | 361 | static void ipip_tunnel_setup(struct net_device *dev) |
|---|
| 380 | 362 | { |
|---|
| 381 | 363 | dev->netdev_ops = &ipip_netdev_ops; |
|---|
| 364 | + dev->header_ops = &ip_tunnel_header_ops; |
|---|
| 382 | 365 | |
|---|
| 383 | 366 | dev->type = ARPHRD_TUNNEL; |
|---|
| 384 | 367 | dev->flags = IFF_NOARP; |
|---|