| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 2 | /* | 
|---|
| 3 | *	IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT) | 
|---|
| 4 | *	Linux INET6 implementation | 
|---|
| 5 | * | 
|---|
| 6 | *	Authors: | 
|---|
| 7 | *	Pedro Roque		<roque@di.fc.ul.pt> | 
|---|
| 8 | *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru> | 
|---|
| 9 | * | 
|---|
| 10 | *	Changes: | 
|---|
| 11 | * Roger Venning <r.venning@telstra.com>:	6to4 support | 
|---|
| 12 | * Nate Thompson <nate@thebog.net>:		6to4 support | 
|---|
| 13 | * Fred Templin <fred.l.templin@boeing.com>:	isatap support | 
|---|
| 14 | */ | 
|---|
| 15 |  | 
|---|
| 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 
|---|
| 17 |  | 
|---|
| 18 | #include <linux/module.h> | 
|---|
| 19 | #include <linux/capability.h> | 
|---|
| 20 | #include <linux/errno.h> | 
|---|
| 21 | #include <linux/types.h> | 
|---|
| 22 | #include <linux/socket.h> | 
|---|
| 23 | #include <linux/sockios.h> | 
|---|
| 24 | #include <linux/net.h> | 
|---|
| 25 | #include <linux/in6.h> | 
|---|
| 26 | #include <linux/netdevice.h> | 
|---|
| 27 | #include <linux/if_arp.h> | 
|---|
| 28 | #include <linux/icmp.h> | 
|---|
| 29 | #include <linux/slab.h> | 
|---|
| 30 | #include <linux/uaccess.h> | 
|---|
| 31 | #include <linux/init.h> | 
|---|
| 32 | #include <linux/netfilter_ipv4.h> | 
|---|
| 33 | #include <linux/if_ether.h> | 
|---|
| 34 |  | 
|---|
| 35 | #include <net/sock.h> | 
|---|
| 36 | #include <net/snmp.h> | 
|---|
| 37 |  | 
|---|
| 38 | #include <net/ipv6.h> | 
|---|
| 39 | #include <net/protocol.h> | 
|---|
| 40 | #include <net/transp_v6.h> | 
|---|
| 41 | #include <net/ip6_fib.h> | 
|---|
| 42 | #include <net/ip6_route.h> | 
|---|
| 43 | #include <net/ndisc.h> | 
|---|
| 44 | #include <net/addrconf.h> | 
|---|
| 45 | #include <net/ip.h> | 
|---|
| 46 | #include <net/udp.h> | 
|---|
| 47 | #include <net/icmp.h> | 
|---|
| 48 | #include <net/ip_tunnels.h> | 
|---|
| 49 | #include <net/inet_ecn.h> | 
|---|
| 50 | #include <net/xfrm.h> | 
|---|
| 51 | #include <net/dsfield.h> | 
|---|
| 52 | #include <net/net_namespace.h> | 
|---|
| 53 | #include <net/netns/generic.h> | 
|---|
| 54 | #include <net/netdev_lock.h> | 
|---|
| 55 | #include <net/inet_dscp.h> | 
|---|
| 56 |  | 
|---|
| 57 | /* | 
|---|
| 58 | This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c | 
|---|
| 59 |  | 
|---|
| 60 | For comments look at net/ipv4/ip_gre.c --ANK | 
|---|
| 61 | */ | 
|---|
| 62 |  | 
|---|
| 63 | #define IP6_SIT_HASH_SIZE  16 | 
|---|
| 64 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) | 
|---|
| 65 |  | 
|---|
| 66 | static bool log_ecn_error = true; | 
|---|
| 67 | module_param(log_ecn_error, bool, 0644); | 
|---|
| 68 | MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); | 
|---|
| 69 |  | 
|---|
| 70 | static int ipip6_tunnel_init(struct net_device *dev); | 
|---|
| 71 | static void ipip6_tunnel_setup(struct net_device *dev); | 
|---|
| 72 | static void ipip6_dev_free(struct net_device *dev); | 
|---|
| 73 | static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst, | 
|---|
| 74 | __be32 *v4dst); | 
|---|
| 75 | static struct rtnl_link_ops sit_link_ops __read_mostly; | 
|---|
| 76 |  | 
|---|
| 77 | static unsigned int sit_net_id __read_mostly; | 
|---|
| 78 | struct sit_net { | 
|---|
| 79 | struct ip_tunnel __rcu *tunnels_r_l[IP6_SIT_HASH_SIZE]; | 
|---|
| 80 | struct ip_tunnel __rcu *tunnels_r[IP6_SIT_HASH_SIZE]; | 
|---|
| 81 | struct ip_tunnel __rcu *tunnels_l[IP6_SIT_HASH_SIZE]; | 
|---|
| 82 | struct ip_tunnel __rcu *tunnels_wc[1]; | 
|---|
| 83 | struct ip_tunnel __rcu **tunnels[4]; | 
|---|
| 84 |  | 
|---|
| 85 | struct net_device *fb_tunnel_dev; | 
|---|
| 86 | }; | 
|---|
| 87 |  | 
|---|
| 88 | static inline struct sit_net *dev_to_sit_net(struct net_device *dev) | 
|---|
| 89 | { | 
|---|
| 90 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 91 |  | 
|---|
| 92 | return net_generic(net: t->net, id: sit_net_id); | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | /* | 
|---|
| 96 | * Must be invoked with rcu_read_lock | 
|---|
| 97 | */ | 
|---|
| 98 | static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, | 
|---|
| 99 | struct net_device *dev, | 
|---|
| 100 | __be32 remote, __be32 local, | 
|---|
| 101 | int sifindex) | 
|---|
| 102 | { | 
|---|
| 103 | unsigned int h0 = HASH(remote); | 
|---|
| 104 | unsigned int h1 = HASH(local); | 
|---|
| 105 | struct ip_tunnel *t; | 
|---|
| 106 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 107 | int ifindex = dev ? dev->ifindex : 0; | 
|---|
| 108 |  | 
|---|
| 109 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { | 
|---|
| 110 | if (local == t->parms.iph.saddr && | 
|---|
| 111 | remote == t->parms.iph.daddr && | 
|---|
| 112 | (!dev || !t->parms.link || ifindex == t->parms.link || | 
|---|
| 113 | sifindex == t->parms.link) && | 
|---|
| 114 | (t->dev->flags & IFF_UP)) | 
|---|
| 115 | return t; | 
|---|
| 116 | } | 
|---|
| 117 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { | 
|---|
| 118 | if (remote == t->parms.iph.daddr && | 
|---|
| 119 | (!dev || !t->parms.link || ifindex == t->parms.link || | 
|---|
| 120 | sifindex == t->parms.link) && | 
|---|
| 121 | (t->dev->flags & IFF_UP)) | 
|---|
| 122 | return t; | 
|---|
| 123 | } | 
|---|
| 124 | for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { | 
|---|
| 125 | if (local == t->parms.iph.saddr && | 
|---|
| 126 | (!dev || !t->parms.link || ifindex == t->parms.link || | 
|---|
| 127 | sifindex == t->parms.link) && | 
|---|
| 128 | (t->dev->flags & IFF_UP)) | 
|---|
| 129 | return t; | 
|---|
| 130 | } | 
|---|
| 131 | t = rcu_dereference(sitn->tunnels_wc[0]); | 
|---|
| 132 | if (t && (t->dev->flags & IFF_UP)) | 
|---|
| 133 | return t; | 
|---|
| 134 | return NULL; | 
|---|
| 135 | } | 
|---|
| 136 |  | 
|---|
| 137 | static struct ip_tunnel __rcu ** | 
|---|
| 138 | __ipip6_bucket(struct sit_net *sitn, struct ip_tunnel_parm_kern *parms) | 
|---|
| 139 | { | 
|---|
| 140 | __be32 remote = parms->iph.daddr; | 
|---|
| 141 | __be32 local = parms->iph.saddr; | 
|---|
| 142 | unsigned int h = 0; | 
|---|
| 143 | int prio = 0; | 
|---|
| 144 |  | 
|---|
| 145 | if (remote) { | 
|---|
| 146 | prio |= 2; | 
|---|
| 147 | h ^= HASH(remote); | 
|---|
| 148 | } | 
|---|
| 149 | if (local) { | 
|---|
| 150 | prio |= 1; | 
|---|
| 151 | h ^= HASH(local); | 
|---|
| 152 | } | 
|---|
| 153 | return &sitn->tunnels[prio][h]; | 
|---|
| 154 | } | 
|---|
| 155 |  | 
|---|
| 156 | static inline struct ip_tunnel __rcu **ipip6_bucket(struct sit_net *sitn, | 
|---|
| 157 | struct ip_tunnel *t) | 
|---|
| 158 | { | 
|---|
| 159 | return __ipip6_bucket(sitn, parms: &t->parms); | 
|---|
| 160 | } | 
|---|
| 161 |  | 
|---|
| 162 | static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t) | 
|---|
| 163 | { | 
|---|
| 164 | struct ip_tunnel __rcu **tp; | 
|---|
| 165 | struct ip_tunnel *iter; | 
|---|
| 166 |  | 
|---|
| 167 | for (tp = ipip6_bucket(sitn, t); | 
|---|
| 168 | (iter = rtnl_dereference(*tp)) != NULL; | 
|---|
| 169 | tp = &iter->next) { | 
|---|
| 170 | if (t == iter) { | 
|---|
| 171 | rcu_assign_pointer(*tp, t->next); | 
|---|
| 172 | break; | 
|---|
| 173 | } | 
|---|
| 174 | } | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t) | 
|---|
| 178 | { | 
|---|
| 179 | struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); | 
|---|
| 180 |  | 
|---|
| 181 | rcu_assign_pointer(t->next, rtnl_dereference(*tp)); | 
|---|
| 182 | rcu_assign_pointer(*tp, t); | 
|---|
| 183 | } | 
|---|
| 184 |  | 
|---|
| 185 | static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) | 
|---|
| 186 | { | 
|---|
| 187 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 188 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 189 |  | 
|---|
| 190 | if (dev == sitn->fb_tunnel_dev || !sitn->fb_tunnel_dev) { | 
|---|
| 191 | ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0); | 
|---|
| 192 | t->ip6rd.relay_prefix = 0; | 
|---|
| 193 | t->ip6rd.prefixlen = 16; | 
|---|
| 194 | t->ip6rd.relay_prefixlen = 0; | 
|---|
| 195 | } else { | 
|---|
| 196 | struct ip_tunnel *t0 = netdev_priv(sitn->fb_tunnel_dev); | 
|---|
| 197 | memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd)); | 
|---|
| 198 | } | 
|---|
| 199 | #endif | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | static int ipip6_tunnel_create(struct net_device *dev) | 
|---|
| 203 | { | 
|---|
| 204 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 205 | struct sit_net *sitn = net_generic(net: t->net, id: sit_net_id); | 
|---|
| 206 | int err; | 
|---|
| 207 |  | 
|---|
| 208 | __dev_addr_set(dev, addr: &t->parms.iph.saddr, len: 4); | 
|---|
| 209 | memcpy(to: dev->broadcast, from: &t->parms.iph.daddr, len: 4); | 
|---|
| 210 |  | 
|---|
| 211 | if (test_bit(IP_TUNNEL_SIT_ISATAP_BIT, t->parms.i_flags)) | 
|---|
| 212 | dev->priv_flags |= IFF_ISATAP; | 
|---|
| 213 |  | 
|---|
| 214 | dev->rtnl_link_ops = &sit_link_ops; | 
|---|
| 215 |  | 
|---|
| 216 | err = register_netdevice(dev); | 
|---|
| 217 | if (err < 0) | 
|---|
| 218 | goto out; | 
|---|
| 219 |  | 
|---|
| 220 | ipip6_tunnel_clone_6rd(dev, sitn); | 
|---|
| 221 |  | 
|---|
| 222 | ipip6_tunnel_link(sitn, t); | 
|---|
| 223 | return 0; | 
|---|
| 224 |  | 
|---|
| 225 | out: | 
|---|
| 226 | return err; | 
|---|
| 227 | } | 
|---|
| 228 |  | 
|---|
| 229 | static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | 
|---|
| 230 | struct ip_tunnel_parm_kern *parms, | 
|---|
| 231 | int create) | 
|---|
| 232 | { | 
|---|
| 233 | __be32 remote = parms->iph.daddr; | 
|---|
| 234 | __be32 local = parms->iph.saddr; | 
|---|
| 235 | struct ip_tunnel *t, *nt; | 
|---|
| 236 | struct ip_tunnel __rcu **tp; | 
|---|
| 237 | struct net_device *dev; | 
|---|
| 238 | char name[IFNAMSIZ]; | 
|---|
| 239 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 240 |  | 
|---|
| 241 | for (tp = __ipip6_bucket(sitn, parms); | 
|---|
| 242 | (t = rtnl_dereference(*tp)) != NULL; | 
|---|
| 243 | tp = &t->next) { | 
|---|
| 244 | if (local == t->parms.iph.saddr && | 
|---|
| 245 | remote == t->parms.iph.daddr && | 
|---|
| 246 | parms->link == t->parms.link) { | 
|---|
| 247 | if (create) | 
|---|
| 248 | return NULL; | 
|---|
| 249 | else | 
|---|
| 250 | return t; | 
|---|
| 251 | } | 
|---|
| 252 | } | 
|---|
| 253 | if (!create) | 
|---|
| 254 | goto failed; | 
|---|
| 255 |  | 
|---|
| 256 | if (parms->name[0]) { | 
|---|
| 257 | if (!dev_valid_name(name: parms->name)) | 
|---|
| 258 | goto failed; | 
|---|
| 259 | strscpy(name, parms->name, IFNAMSIZ); | 
|---|
| 260 | } else { | 
|---|
| 261 | strcpy(name, "sit%d"); | 
|---|
| 262 | } | 
|---|
| 263 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, | 
|---|
| 264 | ipip6_tunnel_setup); | 
|---|
| 265 | if (!dev) | 
|---|
| 266 | return NULL; | 
|---|
| 267 |  | 
|---|
| 268 | dev_net_set(dev, net); | 
|---|
| 269 |  | 
|---|
| 270 | nt = netdev_priv(dev); | 
|---|
| 271 |  | 
|---|
| 272 | nt->net = net; | 
|---|
| 273 | nt->parms = *parms; | 
|---|
| 274 | if (ipip6_tunnel_create(dev) < 0) | 
|---|
| 275 | goto failed_free; | 
|---|
| 276 |  | 
|---|
| 277 | if (!parms->name[0]) | 
|---|
| 278 | strcpy(parms->name, dev->name); | 
|---|
| 279 |  | 
|---|
| 280 | return nt; | 
|---|
| 281 |  | 
|---|
| 282 | failed_free: | 
|---|
| 283 | free_netdev(dev); | 
|---|
| 284 | failed: | 
|---|
| 285 | return NULL; | 
|---|
| 286 | } | 
|---|
| 287 |  | 
|---|
| 288 | #define for_each_prl_rcu(start)			\ | 
|---|
| 289 | for (prl = rcu_dereference(start);	\ | 
|---|
| 290 | prl;				\ | 
|---|
| 291 | prl = rcu_dereference(prl->next)) | 
|---|
| 292 |  | 
|---|
| 293 | static struct ip_tunnel_prl_entry * | 
|---|
| 294 | __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | 
|---|
| 295 | { | 
|---|
| 296 | struct ip_tunnel_prl_entry *prl; | 
|---|
| 297 |  | 
|---|
| 298 | for_each_prl_rcu(t->prl) | 
|---|
| 299 | if (prl->addr == addr) | 
|---|
| 300 | break; | 
|---|
| 301 | return prl; | 
|---|
| 302 |  | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __user *a) | 
|---|
| 306 | { | 
|---|
| 307 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 308 | struct ip_tunnel_prl kprl, *kp; | 
|---|
| 309 | struct ip_tunnel_prl_entry *prl; | 
|---|
| 310 | unsigned int cmax, c = 0, ca, len; | 
|---|
| 311 | int ret = 0; | 
|---|
| 312 |  | 
|---|
| 313 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) | 
|---|
| 314 | return -EINVAL; | 
|---|
| 315 |  | 
|---|
| 316 | if (copy_from_user(to: &kprl, from: a, n: sizeof(kprl))) | 
|---|
| 317 | return -EFAULT; | 
|---|
| 318 | cmax = kprl.datalen / sizeof(kprl); | 
|---|
| 319 | if (cmax > 1 && kprl.addr != htonl(INADDR_ANY)) | 
|---|
| 320 | cmax = 1; | 
|---|
| 321 |  | 
|---|
| 322 | /* For simple GET or for root users, | 
|---|
| 323 | * we try harder to allocate. | 
|---|
| 324 | */ | 
|---|
| 325 | kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ? | 
|---|
| 326 | kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) : | 
|---|
| 327 | NULL; | 
|---|
| 328 |  | 
|---|
| 329 | ca = min(t->prl_count, cmax); | 
|---|
| 330 |  | 
|---|
| 331 | if (!kp) { | 
|---|
| 332 | /* We don't try hard to allocate much memory for | 
|---|
| 333 | * non-root users. | 
|---|
| 334 | * For root users, retry allocating enough memory for | 
|---|
| 335 | * the answer. | 
|---|
| 336 | */ | 
|---|
| 337 | kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC | __GFP_ACCOUNT | | 
|---|
| 338 | __GFP_NOWARN); | 
|---|
| 339 | if (!kp) { | 
|---|
| 340 | ret = -ENOMEM; | 
|---|
| 341 | goto out; | 
|---|
| 342 | } | 
|---|
| 343 | } | 
|---|
| 344 |  | 
|---|
| 345 | rcu_read_lock(); | 
|---|
| 346 | for_each_prl_rcu(t->prl) { | 
|---|
| 347 | if (c >= cmax) | 
|---|
| 348 | break; | 
|---|
| 349 | if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr) | 
|---|
| 350 | continue; | 
|---|
| 351 | kp[c].addr = prl->addr; | 
|---|
| 352 | kp[c].flags = prl->flags; | 
|---|
| 353 | c++; | 
|---|
| 354 | if (kprl.addr != htonl(INADDR_ANY)) | 
|---|
| 355 | break; | 
|---|
| 356 | } | 
|---|
| 357 |  | 
|---|
| 358 | rcu_read_unlock(); | 
|---|
| 359 |  | 
|---|
| 360 | len = sizeof(*kp) * c; | 
|---|
| 361 | ret = 0; | 
|---|
| 362 | if ((len && copy_to_user(to: a + 1, from: kp, n: len)) || put_user(len, &a->datalen)) | 
|---|
| 363 | ret = -EFAULT; | 
|---|
| 364 |  | 
|---|
| 365 | kfree(objp: kp); | 
|---|
| 366 | out: | 
|---|
| 367 | return ret; | 
|---|
| 368 | } | 
|---|
| 369 |  | 
|---|
| 370 | static int | 
|---|
| 371 | ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | 
|---|
| 372 | { | 
|---|
| 373 | struct ip_tunnel_prl_entry *p; | 
|---|
| 374 | int err = 0; | 
|---|
| 375 |  | 
|---|
| 376 | if (a->addr == htonl(INADDR_ANY)) | 
|---|
| 377 | return -EINVAL; | 
|---|
| 378 |  | 
|---|
| 379 | ASSERT_RTNL(); | 
|---|
| 380 |  | 
|---|
| 381 | for (p = rtnl_dereference(t->prl); p; p = rtnl_dereference(p->next)) { | 
|---|
| 382 | if (p->addr == a->addr) { | 
|---|
| 383 | if (chg) { | 
|---|
| 384 | p->flags = a->flags; | 
|---|
| 385 | goto out; | 
|---|
| 386 | } | 
|---|
| 387 | err = -EEXIST; | 
|---|
| 388 | goto out; | 
|---|
| 389 | } | 
|---|
| 390 | } | 
|---|
| 391 |  | 
|---|
| 392 | if (chg) { | 
|---|
| 393 | err = -ENXIO; | 
|---|
| 394 | goto out; | 
|---|
| 395 | } | 
|---|
| 396 |  | 
|---|
| 397 | p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL); | 
|---|
| 398 | if (!p) { | 
|---|
| 399 | err = -ENOBUFS; | 
|---|
| 400 | goto out; | 
|---|
| 401 | } | 
|---|
| 402 |  | 
|---|
| 403 | p->next = t->prl; | 
|---|
| 404 | p->addr = a->addr; | 
|---|
| 405 | p->flags = a->flags; | 
|---|
| 406 | t->prl_count++; | 
|---|
| 407 | rcu_assign_pointer(t->prl, p); | 
|---|
| 408 | out: | 
|---|
| 409 | return err; | 
|---|
| 410 | } | 
|---|
| 411 |  | 
|---|
| 412 | static void prl_list_destroy_rcu(struct rcu_head *head) | 
|---|
| 413 | { | 
|---|
| 414 | struct ip_tunnel_prl_entry *p, *n; | 
|---|
| 415 |  | 
|---|
| 416 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); | 
|---|
| 417 | do { | 
|---|
| 418 | n = rcu_dereference_protected(p->next, 1); | 
|---|
| 419 | kfree(objp: p); | 
|---|
| 420 | p = n; | 
|---|
| 421 | } while (p); | 
|---|
| 422 | } | 
|---|
| 423 |  | 
|---|
| 424 | static int | 
|---|
| 425 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 
|---|
| 426 | { | 
|---|
| 427 | struct ip_tunnel_prl_entry *x; | 
|---|
| 428 | struct ip_tunnel_prl_entry __rcu **p; | 
|---|
| 429 | int err = 0; | 
|---|
| 430 |  | 
|---|
| 431 | ASSERT_RTNL(); | 
|---|
| 432 |  | 
|---|
| 433 | if (a && a->addr != htonl(INADDR_ANY)) { | 
|---|
| 434 | for (p = &t->prl; | 
|---|
| 435 | (x = rtnl_dereference(*p)) != NULL; | 
|---|
| 436 | p = &x->next) { | 
|---|
| 437 | if (x->addr == a->addr) { | 
|---|
| 438 | *p = x->next; | 
|---|
| 439 | kfree_rcu(x, rcu_head); | 
|---|
| 440 | t->prl_count--; | 
|---|
| 441 | goto out; | 
|---|
| 442 | } | 
|---|
| 443 | } | 
|---|
| 444 | err = -ENXIO; | 
|---|
| 445 | } else { | 
|---|
| 446 | x = rtnl_dereference(t->prl); | 
|---|
| 447 | if (x) { | 
|---|
| 448 | t->prl_count = 0; | 
|---|
| 449 | call_rcu(head: &x->rcu_head, func: prl_list_destroy_rcu); | 
|---|
| 450 | t->prl = NULL; | 
|---|
| 451 | } | 
|---|
| 452 | } | 
|---|
| 453 | out: | 
|---|
| 454 | return err; | 
|---|
| 455 | } | 
|---|
| 456 |  | 
|---|
| 457 | static int ipip6_tunnel_prl_ctl(struct net_device *dev, | 
|---|
| 458 | struct ip_tunnel_prl __user *data, int cmd) | 
|---|
| 459 | { | 
|---|
| 460 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 461 | struct ip_tunnel_prl prl; | 
|---|
| 462 | int err; | 
|---|
| 463 |  | 
|---|
| 464 | if (!ns_capable(ns: t->net->user_ns, CAP_NET_ADMIN)) | 
|---|
| 465 | return -EPERM; | 
|---|
| 466 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) | 
|---|
| 467 | return -EINVAL; | 
|---|
| 468 |  | 
|---|
| 469 | if (copy_from_user(to: &prl, from: data, n: sizeof(prl))) | 
|---|
| 470 | return -EFAULT; | 
|---|
| 471 |  | 
|---|
| 472 | switch (cmd) { | 
|---|
| 473 | case SIOCDELPRL: | 
|---|
| 474 | err = ipip6_tunnel_del_prl(t, a: &prl); | 
|---|
| 475 | break; | 
|---|
| 476 | case SIOCADDPRL: | 
|---|
| 477 | case SIOCCHGPRL: | 
|---|
| 478 | err = ipip6_tunnel_add_prl(t, a: &prl, chg: cmd == SIOCCHGPRL); | 
|---|
| 479 | break; | 
|---|
| 480 | } | 
|---|
| 481 | dst_cache_reset(dst_cache: &t->dst_cache); | 
|---|
| 482 | netdev_state_change(dev); | 
|---|
| 483 | return err; | 
|---|
| 484 | } | 
|---|
| 485 |  | 
|---|
| 486 | static int | 
|---|
| 487 | isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) | 
|---|
| 488 | { | 
|---|
| 489 | struct ip_tunnel_prl_entry *p; | 
|---|
| 490 | int ok = 1; | 
|---|
| 491 |  | 
|---|
| 492 | rcu_read_lock(); | 
|---|
| 493 | p = __ipip6_tunnel_locate_prl(t, addr: iph->saddr); | 
|---|
| 494 | if (p) { | 
|---|
| 495 | if (p->flags & PRL_DEFAULT) | 
|---|
| 496 | skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; | 
|---|
| 497 | else | 
|---|
| 498 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; | 
|---|
| 499 | } else { | 
|---|
| 500 | const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; | 
|---|
| 501 |  | 
|---|
| 502 | if (ipv6_addr_is_isatap(addr: addr6) && | 
|---|
| 503 | (addr6->s6_addr32[3] == iph->saddr) && | 
|---|
| 504 | ipv6_chk_prefix(addr: addr6, dev: t->dev)) | 
|---|
| 505 | skb->ndisc_nodetype = NDISC_NODETYPE_HOST; | 
|---|
| 506 | else | 
|---|
| 507 | ok = 0; | 
|---|
| 508 | } | 
|---|
| 509 | rcu_read_unlock(); | 
|---|
| 510 | return ok; | 
|---|
| 511 | } | 
|---|
| 512 |  | 
|---|
| 513 | static void ipip6_tunnel_uninit(struct net_device *dev) | 
|---|
| 514 | { | 
|---|
| 515 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 516 | struct sit_net *sitn = net_generic(net: tunnel->net, id: sit_net_id); | 
|---|
| 517 |  | 
|---|
| 518 | if (dev == sitn->fb_tunnel_dev) { | 
|---|
| 519 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); | 
|---|
| 520 | } else { | 
|---|
| 521 | ipip6_tunnel_unlink(sitn, t: tunnel); | 
|---|
| 522 | ipip6_tunnel_del_prl(t: tunnel, NULL); | 
|---|
| 523 | } | 
|---|
| 524 | dst_cache_reset(dst_cache: &tunnel->dst_cache); | 
|---|
| 525 | netdev_put(dev, tracker: &tunnel->dev_tracker); | 
|---|
| 526 | } | 
|---|
| 527 |  | 
|---|
| 528 | static int ipip6_err(struct sk_buff *skb, u32 info) | 
|---|
| 529 | { | 
|---|
| 530 | const struct iphdr *iph = (const struct iphdr *)skb->data; | 
|---|
| 531 | const int type = icmp_hdr(skb)->type; | 
|---|
| 532 | const int code = icmp_hdr(skb)->code; | 
|---|
| 533 | unsigned int data_len = 0; | 
|---|
| 534 | struct ip_tunnel *t; | 
|---|
| 535 | int sifindex; | 
|---|
| 536 | int err; | 
|---|
| 537 |  | 
|---|
| 538 | switch (type) { | 
|---|
| 539 | default: | 
|---|
| 540 | case ICMP_PARAMETERPROB: | 
|---|
| 541 | return 0; | 
|---|
| 542 |  | 
|---|
| 543 | case ICMP_DEST_UNREACH: | 
|---|
| 544 | switch (code) { | 
|---|
| 545 | case ICMP_SR_FAILED: | 
|---|
| 546 | /* Impossible event. */ | 
|---|
| 547 | return 0; | 
|---|
| 548 | default: | 
|---|
| 549 | /* All others are translated to HOST_UNREACH. | 
|---|
| 550 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 
|---|
| 551 | I believe they are just ether pollution. --ANK | 
|---|
| 552 | */ | 
|---|
| 553 | break; | 
|---|
| 554 | } | 
|---|
| 555 | break; | 
|---|
| 556 | case ICMP_TIME_EXCEEDED: | 
|---|
| 557 | if (code != ICMP_EXC_TTL) | 
|---|
| 558 | return 0; | 
|---|
| 559 | data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ | 
|---|
| 560 | break; | 
|---|
| 561 | case ICMP_REDIRECT: | 
|---|
| 562 | break; | 
|---|
| 563 | } | 
|---|
| 564 |  | 
|---|
| 565 | err = -ENOENT; | 
|---|
| 566 |  | 
|---|
| 567 | sifindex = netif_is_l3_master(dev: skb->dev) ? IPCB(skb)->iif : 0; | 
|---|
| 568 | t = ipip6_tunnel_lookup(net: dev_net(dev: skb->dev), dev: skb->dev, | 
|---|
| 569 | remote: iph->daddr, local: iph->saddr, sifindex); | 
|---|
| 570 | if (!t) | 
|---|
| 571 | goto out; | 
|---|
| 572 |  | 
|---|
| 573 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { | 
|---|
| 574 | ipv4_update_pmtu(skb, net: dev_net(dev: skb->dev), mtu: info, | 
|---|
| 575 | oif: t->parms.link, protocol: iph->protocol); | 
|---|
| 576 | err = 0; | 
|---|
| 577 | goto out; | 
|---|
| 578 | } | 
|---|
| 579 | if (type == ICMP_REDIRECT) { | 
|---|
| 580 | ipv4_redirect(skb, net: dev_net(dev: skb->dev), oif: t->parms.link, | 
|---|
| 581 | protocol: iph->protocol); | 
|---|
| 582 | err = 0; | 
|---|
| 583 | goto out; | 
|---|
| 584 | } | 
|---|
| 585 |  | 
|---|
| 586 | err = 0; | 
|---|
| 587 | if (__in6_dev_get(dev: skb->dev) && | 
|---|
| 588 | !ip6_err_gen_icmpv6_unreach(skb, nhs: iph->ihl * 4, type, data_len)) | 
|---|
| 589 | goto out; | 
|---|
| 590 |  | 
|---|
| 591 | if (t->parms.iph.daddr == 0) | 
|---|
| 592 | goto out; | 
|---|
| 593 |  | 
|---|
| 594 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 
|---|
| 595 | goto out; | 
|---|
| 596 |  | 
|---|
| 597 | if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) | 
|---|
| 598 | t->err_count++; | 
|---|
| 599 | else | 
|---|
| 600 | t->err_count = 1; | 
|---|
| 601 | t->err_time = jiffies; | 
|---|
| 602 | out: | 
|---|
| 603 | return err; | 
|---|
| 604 | } | 
|---|
| 605 |  | 
|---|
| 606 | static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr, | 
|---|
| 607 | const struct in6_addr *v6addr) | 
|---|
| 608 | { | 
|---|
| 609 | __be32 v4embed = 0; | 
|---|
| 610 | if (check_6rd(tunnel, v6dst: v6addr, v4dst: &v4embed) && v4addr != v4embed) | 
|---|
| 611 | return true; | 
|---|
| 612 | return false; | 
|---|
| 613 | } | 
|---|
| 614 |  | 
|---|
| 615 | /* Checks if an address matches an address on the tunnel interface. | 
|---|
| 616 | * Used to detect the NAT of proto 41 packets and let them pass spoofing test. | 
|---|
| 617 | * Long story: | 
|---|
| 618 | * This function is called after we considered the packet as spoofed | 
|---|
| 619 | * in is_spoofed_6rd. | 
|---|
| 620 | * We may have a router that is doing NAT for proto 41 packets | 
|---|
| 621 | * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb | 
|---|
| 622 | * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd | 
|---|
| 623 | * function will return true, dropping the packet. | 
|---|
| 624 | * But, we can still check if is spoofed against the IP | 
|---|
| 625 | * addresses associated with the interface. | 
|---|
| 626 | */ | 
|---|
| 627 | static bool only_dnatted(const struct ip_tunnel *tunnel, | 
|---|
| 628 | const struct in6_addr *v6dst) | 
|---|
| 629 | { | 
|---|
| 630 | int prefix_len; | 
|---|
| 631 |  | 
|---|
| 632 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 633 | prefix_len = tunnel->ip6rd.prefixlen + 32 | 
|---|
| 634 | - tunnel->ip6rd.relay_prefixlen; | 
|---|
| 635 | #else | 
|---|
| 636 | prefix_len = 48; | 
|---|
| 637 | #endif | 
|---|
| 638 | return ipv6_chk_custom_prefix(addr: v6dst, prefix_len, dev: tunnel->dev); | 
|---|
| 639 | } | 
|---|
| 640 |  | 
|---|
| 641 | /* Returns true if a packet is spoofed */ | 
|---|
| 642 | static bool packet_is_spoofed(struct sk_buff *skb, | 
|---|
| 643 | const struct iphdr *iph, | 
|---|
| 644 | struct ip_tunnel *tunnel) | 
|---|
| 645 | { | 
|---|
| 646 | const struct ipv6hdr *ipv6h; | 
|---|
| 647 |  | 
|---|
| 648 | if (tunnel->dev->priv_flags & IFF_ISATAP) { | 
|---|
| 649 | if (!isatap_chksrc(skb, iph, t: tunnel)) | 
|---|
| 650 | return true; | 
|---|
| 651 |  | 
|---|
| 652 | return false; | 
|---|
| 653 | } | 
|---|
| 654 |  | 
|---|
| 655 | if (tunnel->dev->flags & IFF_POINTOPOINT) | 
|---|
| 656 | return false; | 
|---|
| 657 |  | 
|---|
| 658 | ipv6h = ipv6_hdr(skb); | 
|---|
| 659 |  | 
|---|
| 660 | if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) { | 
|---|
| 661 | net_warn_ratelimited( "Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n", | 
|---|
| 662 | &iph->saddr, &ipv6h->saddr, | 
|---|
| 663 | &iph->daddr, &ipv6h->daddr); | 
|---|
| 664 | return true; | 
|---|
| 665 | } | 
|---|
| 666 |  | 
|---|
| 667 | if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr))) | 
|---|
| 668 | return false; | 
|---|
| 669 |  | 
|---|
| 670 | if (only_dnatted(tunnel, v6dst: &ipv6h->daddr)) | 
|---|
| 671 | return false; | 
|---|
| 672 |  | 
|---|
| 673 | net_warn_ratelimited( "Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n", | 
|---|
| 674 | &iph->saddr, &ipv6h->saddr, | 
|---|
| 675 | &iph->daddr, &ipv6h->daddr); | 
|---|
| 676 | return true; | 
|---|
| 677 | } | 
|---|
| 678 |  | 
|---|
| 679 | static int ipip6_rcv(struct sk_buff *skb) | 
|---|
| 680 | { | 
|---|
| 681 | const struct iphdr *iph = ip_hdr(skb); | 
|---|
| 682 | struct ip_tunnel *tunnel; | 
|---|
| 683 | int sifindex; | 
|---|
| 684 | int err; | 
|---|
| 685 |  | 
|---|
| 686 | sifindex = netif_is_l3_master(dev: skb->dev) ? IPCB(skb)->iif : 0; | 
|---|
| 687 | tunnel = ipip6_tunnel_lookup(net: dev_net(dev: skb->dev), dev: skb->dev, | 
|---|
| 688 | remote: iph->saddr, local: iph->daddr, sifindex); | 
|---|
| 689 | if (tunnel) { | 
|---|
| 690 | if (tunnel->parms.iph.protocol != IPPROTO_IPV6 && | 
|---|
| 691 | tunnel->parms.iph.protocol != 0) | 
|---|
| 692 | goto out; | 
|---|
| 693 |  | 
|---|
| 694 | skb->mac_header = skb->network_header; | 
|---|
| 695 | skb_reset_network_header(skb); | 
|---|
| 696 | IPCB(skb)->flags = 0; | 
|---|
| 697 | skb->dev = tunnel->dev; | 
|---|
| 698 |  | 
|---|
| 699 | if (packet_is_spoofed(skb, iph, tunnel)) { | 
|---|
| 700 | DEV_STATS_INC(tunnel->dev, rx_errors); | 
|---|
| 701 | goto out; | 
|---|
| 702 | } | 
|---|
| 703 |  | 
|---|
| 704 | if (iptunnel_pull_header(skb, hdr_len: 0, htons(ETH_P_IPV6), | 
|---|
| 705 | xnet: !net_eq(net1: tunnel->net, net2: dev_net(dev: tunnel->dev)))) | 
|---|
| 706 | goto out; | 
|---|
| 707 |  | 
|---|
| 708 | /* skb can be uncloned in iptunnel_pull_header, so | 
|---|
| 709 | * old iph is no longer valid | 
|---|
| 710 | */ | 
|---|
| 711 | iph = (const struct iphdr *)skb_mac_header(skb); | 
|---|
| 712 | skb_reset_mac_header(skb); | 
|---|
| 713 |  | 
|---|
| 714 | err = IP_ECN_decapsulate(oiph: iph, skb); | 
|---|
| 715 | if (unlikely(err)) { | 
|---|
| 716 | if (log_ecn_error) | 
|---|
| 717 | net_info_ratelimited( "non-ECT from %pI4 with TOS=%#x\n", | 
|---|
| 718 | &iph->saddr, iph->tos); | 
|---|
| 719 | if (err > 1) { | 
|---|
| 720 | DEV_STATS_INC(tunnel->dev, rx_frame_errors); | 
|---|
| 721 | DEV_STATS_INC(tunnel->dev, rx_errors); | 
|---|
| 722 | goto out; | 
|---|
| 723 | } | 
|---|
| 724 | } | 
|---|
| 725 |  | 
|---|
| 726 | dev_sw_netstats_rx_add(dev: tunnel->dev, len: skb->len); | 
|---|
| 727 |  | 
|---|
| 728 | netif_rx(skb); | 
|---|
| 729 |  | 
|---|
| 730 | return 0; | 
|---|
| 731 | } | 
|---|
| 732 |  | 
|---|
| 733 | /* no tunnel matched,  let upstream know, ipsec may handle it */ | 
|---|
| 734 | return 1; | 
|---|
| 735 | out: | 
|---|
| 736 | kfree_skb(skb); | 
|---|
| 737 | return 0; | 
|---|
| 738 | } | 
|---|
| 739 |  | 
|---|
| 740 | static const struct tnl_ptk_info ipip_tpi = { | 
|---|
| 741 | /* no tunnel info required for ipip. */ | 
|---|
| 742 | .proto = htons(ETH_P_IP), | 
|---|
| 743 | }; | 
|---|
| 744 |  | 
|---|
| 745 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 746 | static const struct tnl_ptk_info mplsip_tpi = { | 
|---|
| 747 | /* no tunnel info required for mplsip. */ | 
|---|
| 748 | .proto = htons(ETH_P_MPLS_UC), | 
|---|
| 749 | }; | 
|---|
| 750 | #endif | 
|---|
| 751 |  | 
|---|
| 752 | static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto) | 
|---|
| 753 | { | 
|---|
| 754 | const struct iphdr *iph; | 
|---|
| 755 | struct ip_tunnel *tunnel; | 
|---|
| 756 | int sifindex; | 
|---|
| 757 |  | 
|---|
| 758 | sifindex = netif_is_l3_master(dev: skb->dev) ? IPCB(skb)->iif : 0; | 
|---|
| 759 |  | 
|---|
| 760 | iph = ip_hdr(skb); | 
|---|
| 761 | tunnel = ipip6_tunnel_lookup(net: dev_net(dev: skb->dev), dev: skb->dev, | 
|---|
| 762 | remote: iph->saddr, local: iph->daddr, sifindex); | 
|---|
| 763 | if (tunnel) { | 
|---|
| 764 | const struct tnl_ptk_info *tpi; | 
|---|
| 765 |  | 
|---|
| 766 | if (tunnel->parms.iph.protocol != ipproto && | 
|---|
| 767 | tunnel->parms.iph.protocol != 0) | 
|---|
| 768 | goto drop; | 
|---|
| 769 |  | 
|---|
| 770 | if (!xfrm4_policy_check(NULL, dir: XFRM_POLICY_IN, skb)) | 
|---|
| 771 | goto drop; | 
|---|
| 772 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 773 | if (ipproto == IPPROTO_MPLS) | 
|---|
| 774 | tpi = &mplsip_tpi; | 
|---|
| 775 | else | 
|---|
| 776 | #endif | 
|---|
| 777 | tpi = &ipip_tpi; | 
|---|
| 778 | if (iptunnel_pull_header(skb, hdr_len: 0, inner_proto: tpi->proto, xnet: false)) | 
|---|
| 779 | goto drop; | 
|---|
| 780 | skb_reset_mac_header(skb); | 
|---|
| 781 |  | 
|---|
| 782 | return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error); | 
|---|
| 783 | } | 
|---|
| 784 |  | 
|---|
| 785 | return 1; | 
|---|
| 786 |  | 
|---|
| 787 | drop: | 
|---|
| 788 | kfree_skb(skb); | 
|---|
| 789 | return 0; | 
|---|
| 790 | } | 
|---|
| 791 |  | 
|---|
| 792 | static int ipip_rcv(struct sk_buff *skb) | 
|---|
| 793 | { | 
|---|
| 794 | return sit_tunnel_rcv(skb, IPPROTO_IPIP); | 
|---|
| 795 | } | 
|---|
| 796 |  | 
|---|
| 797 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 798 | static int mplsip_rcv(struct sk_buff *skb) | 
|---|
| 799 | { | 
|---|
| 800 | return sit_tunnel_rcv(skb, IPPROTO_MPLS); | 
|---|
| 801 | } | 
|---|
| 802 | #endif | 
|---|
| 803 |  | 
|---|
| 804 | /* | 
|---|
| 805 | * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function | 
|---|
| 806 | * stores the embedded IPv4 address in v4dst and returns true. | 
|---|
| 807 | */ | 
|---|
| 808 | static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst, | 
|---|
| 809 | __be32 *v4dst) | 
|---|
| 810 | { | 
|---|
| 811 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 812 | if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix, | 
|---|
| 813 | tunnel->ip6rd.prefixlen)) { | 
|---|
| 814 | unsigned int pbw0, pbi0; | 
|---|
| 815 | int pbi1; | 
|---|
| 816 | u32 d; | 
|---|
| 817 |  | 
|---|
| 818 | pbw0 = tunnel->ip6rd.prefixlen >> 5; | 
|---|
| 819 | pbi0 = tunnel->ip6rd.prefixlen & 0x1f; | 
|---|
| 820 |  | 
|---|
| 821 | d = tunnel->ip6rd.relay_prefixlen < 32 ? | 
|---|
| 822 | (ntohl(v6dst->s6_addr32[pbw0]) << pbi0) >> | 
|---|
| 823 | tunnel->ip6rd.relay_prefixlen : 0; | 
|---|
| 824 |  | 
|---|
| 825 | pbi1 = pbi0 - tunnel->ip6rd.relay_prefixlen; | 
|---|
| 826 | if (pbi1 > 0) | 
|---|
| 827 | d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >> | 
|---|
| 828 | (32 - pbi1); | 
|---|
| 829 |  | 
|---|
| 830 | *v4dst = tunnel->ip6rd.relay_prefix | htonl(d); | 
|---|
| 831 | return true; | 
|---|
| 832 | } | 
|---|
| 833 | #else | 
|---|
| 834 | if (v6dst->s6_addr16[0] == htons(0x2002)) { | 
|---|
| 835 | /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ | 
|---|
| 836 | memcpy(to: v4dst, from: &v6dst->s6_addr16[1], len: 4); | 
|---|
| 837 | return true; | 
|---|
| 838 | } | 
|---|
| 839 | #endif | 
|---|
| 840 | return false; | 
|---|
| 841 | } | 
|---|
| 842 |  | 
|---|
| 843 | static inline __be32 try_6rd(struct ip_tunnel *tunnel, | 
|---|
| 844 | const struct in6_addr *v6dst) | 
|---|
| 845 | { | 
|---|
| 846 | __be32 dst = 0; | 
|---|
| 847 | check_6rd(tunnel, v6dst, v4dst: &dst); | 
|---|
| 848 | return dst; | 
|---|
| 849 | } | 
|---|
| 850 |  | 
|---|
| 851 | static bool ipip6_tunnel_dst_find(struct sk_buff *skb, __be32 *dst, | 
|---|
| 852 | bool is_isatap) | 
|---|
| 853 | { | 
|---|
| 854 | const struct ipv6hdr *iph6 = ipv6_hdr(skb); | 
|---|
| 855 | struct neighbour *neigh = NULL; | 
|---|
| 856 | const struct in6_addr *addr6; | 
|---|
| 857 | bool found = false; | 
|---|
| 858 | int addr_type; | 
|---|
| 859 |  | 
|---|
| 860 | if (skb_dst(skb)) | 
|---|
| 861 | neigh = dst_neigh_lookup(dst: skb_dst(skb), daddr: &iph6->daddr); | 
|---|
| 862 |  | 
|---|
| 863 | if (!neigh) { | 
|---|
| 864 | net_dbg_ratelimited( "nexthop == NULL\n"); | 
|---|
| 865 | return false; | 
|---|
| 866 | } | 
|---|
| 867 |  | 
|---|
| 868 | addr6 = (const struct in6_addr *)&neigh->primary_key; | 
|---|
| 869 | addr_type = ipv6_addr_type(addr: addr6); | 
|---|
| 870 |  | 
|---|
| 871 | if (is_isatap) { | 
|---|
| 872 | if ((addr_type & IPV6_ADDR_UNICAST) && | 
|---|
| 873 | ipv6_addr_is_isatap(addr: addr6)) { | 
|---|
| 874 | *dst = addr6->s6_addr32[3]; | 
|---|
| 875 | found = true; | 
|---|
| 876 | } | 
|---|
| 877 | } else { | 
|---|
| 878 | if (addr_type == IPV6_ADDR_ANY) { | 
|---|
| 879 | addr6 = &ipv6_hdr(skb)->daddr; | 
|---|
| 880 | addr_type = ipv6_addr_type(addr: addr6); | 
|---|
| 881 | } | 
|---|
| 882 |  | 
|---|
| 883 | if ((addr_type & IPV6_ADDR_COMPATv4) != 0) { | 
|---|
| 884 | *dst = addr6->s6_addr32[3]; | 
|---|
| 885 | found = true; | 
|---|
| 886 | } | 
|---|
| 887 | } | 
|---|
| 888 |  | 
|---|
| 889 | neigh_release(neigh); | 
|---|
| 890 |  | 
|---|
| 891 | return found; | 
|---|
| 892 | } | 
|---|
| 893 |  | 
|---|
| 894 | /* | 
|---|
| 895 | *	This function assumes it is being called from dev_queue_xmit() | 
|---|
| 896 | *	and that skb is filled properly by that function. | 
|---|
| 897 | */ | 
|---|
| 898 |  | 
|---|
| 899 | static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | 
|---|
| 900 | struct net_device *dev) | 
|---|
| 901 | { | 
|---|
| 902 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 903 | const struct iphdr  *tiph = &tunnel->parms.iph; | 
|---|
| 904 | const struct ipv6hdr *iph6 = ipv6_hdr(skb); | 
|---|
| 905 | u8     tos = tunnel->parms.iph.tos; | 
|---|
| 906 | __be16 df = tiph->frag_off; | 
|---|
| 907 | struct rtable *rt;		/* Route to the other host */ | 
|---|
| 908 | struct net_device *tdev;	/* Device to other host */ | 
|---|
| 909 | unsigned int max_headroom;	/* The extra header space needed */ | 
|---|
| 910 | __be32 dst = tiph->daddr; | 
|---|
| 911 | struct flowi4 fl4; | 
|---|
| 912 | int    mtu; | 
|---|
| 913 | u8 ttl; | 
|---|
| 914 | u8 protocol = IPPROTO_IPV6; | 
|---|
| 915 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 
|---|
| 916 |  | 
|---|
| 917 | if (tos == 1) | 
|---|
| 918 | tos = ipv6_get_dsfield(ipv6h: iph6); | 
|---|
| 919 |  | 
|---|
| 920 | /* ISATAP (RFC4214) - must come before 6to4 */ | 
|---|
| 921 | if ((dev->priv_flags & IFF_ISATAP) && | 
|---|
| 922 | !ipip6_tunnel_dst_find(skb, dst: &dst, is_isatap: true)) | 
|---|
| 923 | goto tx_error; | 
|---|
| 924 |  | 
|---|
| 925 | if (!dst) | 
|---|
| 926 | dst = try_6rd(tunnel, v6dst: &iph6->daddr); | 
|---|
| 927 |  | 
|---|
| 928 | if (!dst && !ipip6_tunnel_dst_find(skb, dst: &dst, is_isatap: false)) | 
|---|
| 929 | goto tx_error; | 
|---|
| 930 |  | 
|---|
| 931 | flowi4_init_output(fl4: &fl4, oif: tunnel->parms.link, mark: tunnel->fwmark, | 
|---|
| 932 | tos: tos & INET_DSCP_MASK, scope: RT_SCOPE_UNIVERSE, | 
|---|
| 933 | IPPROTO_IPV6, flags: 0, daddr: dst, saddr: tiph->saddr, dport: 0, sport: 0, | 
|---|
| 934 | uid: sock_net_uid(net: tunnel->net, NULL)); | 
|---|
| 935 |  | 
|---|
| 936 | rt = dst_cache_get_ip4(dst_cache: &tunnel->dst_cache, saddr: &fl4.saddr); | 
|---|
| 937 | if (!rt) { | 
|---|
| 938 | rt = ip_route_output_flow(tunnel->net, flp: &fl4, NULL); | 
|---|
| 939 | if (IS_ERR(ptr: rt)) { | 
|---|
| 940 | DEV_STATS_INC(dev, tx_carrier_errors); | 
|---|
| 941 | goto tx_error_icmp; | 
|---|
| 942 | } | 
|---|
| 943 | dst_cache_set_ip4(dst_cache: &tunnel->dst_cache, dst: &rt->dst, saddr: fl4.saddr); | 
|---|
| 944 | } | 
|---|
| 945 |  | 
|---|
| 946 | if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) { | 
|---|
| 947 | ip_rt_put(rt); | 
|---|
| 948 | DEV_STATS_INC(dev, tx_carrier_errors); | 
|---|
| 949 | goto tx_error_icmp; | 
|---|
| 950 | } | 
|---|
| 951 | tdev = rt->dst.dev; | 
|---|
| 952 |  | 
|---|
| 953 | if (tdev == dev) { | 
|---|
| 954 | ip_rt_put(rt); | 
|---|
| 955 | DEV_STATS_INC(dev, collisions); | 
|---|
| 956 | goto tx_error; | 
|---|
| 957 | } | 
|---|
| 958 |  | 
|---|
| 959 | if (iptunnel_handle_offloads(skb, gso_type_mask: SKB_GSO_IPXIP4)) { | 
|---|
| 960 | ip_rt_put(rt); | 
|---|
| 961 | goto tx_error; | 
|---|
| 962 | } | 
|---|
| 963 |  | 
|---|
| 964 | if (df) { | 
|---|
| 965 | mtu = dst_mtu(dst: &rt->dst) - t_hlen; | 
|---|
| 966 |  | 
|---|
| 967 | if (mtu < IPV4_MIN_MTU) { | 
|---|
| 968 | DEV_STATS_INC(dev, collisions); | 
|---|
| 969 | ip_rt_put(rt); | 
|---|
| 970 | goto tx_error; | 
|---|
| 971 | } | 
|---|
| 972 |  | 
|---|
| 973 | if (mtu < IPV6_MIN_MTU) { | 
|---|
| 974 | mtu = IPV6_MIN_MTU; | 
|---|
| 975 | df = 0; | 
|---|
| 976 | } | 
|---|
| 977 |  | 
|---|
| 978 | if (tunnel->parms.iph.daddr) | 
|---|
| 979 | skb_dst_update_pmtu_no_confirm(skb, mtu); | 
|---|
| 980 |  | 
|---|
| 981 | if (skb->len > mtu && !skb_is_gso(skb)) { | 
|---|
| 982 | icmpv6_ndo_send(skb_in: skb, ICMPV6_PKT_TOOBIG, code: 0, info: mtu); | 
|---|
| 983 | ip_rt_put(rt); | 
|---|
| 984 | goto tx_error; | 
|---|
| 985 | } | 
|---|
| 986 | } | 
|---|
| 987 |  | 
|---|
| 988 | if (tunnel->err_count > 0) { | 
|---|
| 989 | if (time_before(jiffies, | 
|---|
| 990 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | 
|---|
| 991 | tunnel->err_count--; | 
|---|
| 992 | dst_link_failure(skb); | 
|---|
| 993 | } else | 
|---|
| 994 | tunnel->err_count = 0; | 
|---|
| 995 | } | 
|---|
| 996 |  | 
|---|
| 997 | /* | 
|---|
| 998 | * Okay, now see if we can stuff it in the buffer as-is. | 
|---|
| 999 | */ | 
|---|
| 1000 | max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen; | 
|---|
| 1001 |  | 
|---|
| 1002 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || | 
|---|
| 1003 | (skb_cloned(skb) && !skb_clone_writable(skb, len: 0))) { | 
|---|
| 1004 | struct sk_buff *new_skb = skb_realloc_headroom(skb, headroom: max_headroom); | 
|---|
| 1005 | if (!new_skb) { | 
|---|
| 1006 | ip_rt_put(rt); | 
|---|
| 1007 | DEV_STATS_INC(dev, tx_dropped); | 
|---|
| 1008 | kfree_skb(skb); | 
|---|
| 1009 | return NETDEV_TX_OK; | 
|---|
| 1010 | } | 
|---|
| 1011 | if (skb->sk) | 
|---|
| 1012 | skb_set_owner_w(skb: new_skb, sk: skb->sk); | 
|---|
| 1013 | dev_kfree_skb(skb); | 
|---|
| 1014 | skb = new_skb; | 
|---|
| 1015 | iph6 = ipv6_hdr(skb); | 
|---|
| 1016 | } | 
|---|
| 1017 | ttl = tiph->ttl; | 
|---|
| 1018 | if (ttl == 0) | 
|---|
| 1019 | ttl = iph6->hop_limit; | 
|---|
| 1020 | tos = INET_ECN_encapsulate(outer: tos, inner: ipv6_get_dsfield(ipv6h: iph6)); | 
|---|
| 1021 |  | 
|---|
| 1022 | if (ip_tunnel_encap(skb, e: &tunnel->encap, protocol: &protocol, fl4: &fl4) < 0) { | 
|---|
| 1023 | ip_rt_put(rt); | 
|---|
| 1024 | goto tx_error; | 
|---|
| 1025 | } | 
|---|
| 1026 |  | 
|---|
| 1027 | skb_set_inner_ipproto(skb, IPPROTO_IPV6); | 
|---|
| 1028 |  | 
|---|
| 1029 | iptunnel_xmit(NULL, rt, skb, src: fl4.saddr, dst: fl4.daddr, proto: protocol, tos, ttl, | 
|---|
| 1030 | df, xnet: !net_eq(net1: tunnel->net, net2: dev_net(dev)), ipcb_flags: 0); | 
|---|
| 1031 | return NETDEV_TX_OK; | 
|---|
| 1032 |  | 
|---|
| 1033 | tx_error_icmp: | 
|---|
| 1034 | dst_link_failure(skb); | 
|---|
| 1035 | tx_error: | 
|---|
| 1036 | kfree_skb(skb); | 
|---|
| 1037 | DEV_STATS_INC(dev, tx_errors); | 
|---|
| 1038 | return NETDEV_TX_OK; | 
|---|
| 1039 | } | 
|---|
| 1040 |  | 
|---|
| 1041 | static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb, | 
|---|
| 1042 | struct net_device *dev, u8 ipproto) | 
|---|
| 1043 | { | 
|---|
| 1044 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1045 | const struct iphdr  *tiph = &tunnel->parms.iph; | 
|---|
| 1046 |  | 
|---|
| 1047 | if (iptunnel_handle_offloads(skb, gso_type_mask: SKB_GSO_IPXIP4)) | 
|---|
| 1048 | goto tx_error; | 
|---|
| 1049 |  | 
|---|
| 1050 | skb_set_inner_ipproto(skb, ipproto); | 
|---|
| 1051 |  | 
|---|
| 1052 | ip_tunnel_xmit(skb, dev, tnl_params: tiph, protocol: ipproto); | 
|---|
| 1053 | return NETDEV_TX_OK; | 
|---|
| 1054 | tx_error: | 
|---|
| 1055 | kfree_skb(skb); | 
|---|
| 1056 | DEV_STATS_INC(dev, tx_errors); | 
|---|
| 1057 | return NETDEV_TX_OK; | 
|---|
| 1058 | } | 
|---|
| 1059 |  | 
|---|
| 1060 | static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, | 
|---|
| 1061 | struct net_device *dev) | 
|---|
| 1062 | { | 
|---|
| 1063 | if (!pskb_inet_may_pull(skb)) | 
|---|
| 1064 | goto tx_err; | 
|---|
| 1065 |  | 
|---|
| 1066 | switch (skb->protocol) { | 
|---|
| 1067 | case htons(ETH_P_IP): | 
|---|
| 1068 | sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP); | 
|---|
| 1069 | break; | 
|---|
| 1070 | case htons(ETH_P_IPV6): | 
|---|
| 1071 | ipip6_tunnel_xmit(skb, dev); | 
|---|
| 1072 | break; | 
|---|
| 1073 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1074 | case htons(ETH_P_MPLS_UC): | 
|---|
| 1075 | sit_tunnel_xmit__(skb, dev, IPPROTO_MPLS); | 
|---|
| 1076 | break; | 
|---|
| 1077 | #endif | 
|---|
| 1078 | default: | 
|---|
| 1079 | goto tx_err; | 
|---|
| 1080 | } | 
|---|
| 1081 |  | 
|---|
| 1082 | return NETDEV_TX_OK; | 
|---|
| 1083 |  | 
|---|
| 1084 | tx_err: | 
|---|
| 1085 | DEV_STATS_INC(dev, tx_errors); | 
|---|
| 1086 | kfree_skb(skb); | 
|---|
| 1087 | return NETDEV_TX_OK; | 
|---|
| 1088 |  | 
|---|
| 1089 | } | 
|---|
| 1090 |  | 
|---|
| 1091 | static void ipip6_tunnel_bind_dev(struct net_device *dev) | 
|---|
| 1092 | { | 
|---|
| 1093 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1094 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 
|---|
| 1095 | struct net_device *tdev = NULL; | 
|---|
| 1096 | int hlen = LL_MAX_HEADER; | 
|---|
| 1097 | const struct iphdr *iph; | 
|---|
| 1098 | struct flowi4 fl4; | 
|---|
| 1099 |  | 
|---|
| 1100 | iph = &tunnel->parms.iph; | 
|---|
| 1101 |  | 
|---|
| 1102 | if (iph->daddr) { | 
|---|
| 1103 | struct rtable *rt = ip_route_output_ports(net: tunnel->net, fl4: &fl4, | 
|---|
| 1104 | NULL, | 
|---|
| 1105 | daddr: iph->daddr, saddr: iph->saddr, | 
|---|
| 1106 | dport: 0, sport: 0, | 
|---|
| 1107 | IPPROTO_IPV6, | 
|---|
| 1108 | tos: iph->tos & INET_DSCP_MASK, | 
|---|
| 1109 | oif: tunnel->parms.link); | 
|---|
| 1110 |  | 
|---|
| 1111 | if (!IS_ERR(ptr: rt)) { | 
|---|
| 1112 | tdev = rt->dst.dev; | 
|---|
| 1113 | ip_rt_put(rt); | 
|---|
| 1114 | } | 
|---|
| 1115 | dev->flags |= IFF_POINTOPOINT; | 
|---|
| 1116 | } | 
|---|
| 1117 |  | 
|---|
| 1118 | if (!tdev && tunnel->parms.link) | 
|---|
| 1119 | tdev = __dev_get_by_index(net: tunnel->net, ifindex: tunnel->parms.link); | 
|---|
| 1120 |  | 
|---|
| 1121 | if (tdev && !netif_is_l3_master(dev: tdev)) { | 
|---|
| 1122 | int mtu; | 
|---|
| 1123 |  | 
|---|
| 1124 | mtu = tdev->mtu - t_hlen; | 
|---|
| 1125 | if (mtu < IPV6_MIN_MTU) | 
|---|
| 1126 | mtu = IPV6_MIN_MTU; | 
|---|
| 1127 | WRITE_ONCE(dev->mtu, mtu); | 
|---|
| 1128 | hlen = tdev->hard_header_len + tdev->needed_headroom; | 
|---|
| 1129 | } | 
|---|
| 1130 | dev->needed_headroom = t_hlen + hlen; | 
|---|
| 1131 | } | 
|---|
| 1132 |  | 
|---|
| 1133 | static void ipip6_tunnel_update(struct ip_tunnel *t, | 
|---|
| 1134 | struct ip_tunnel_parm_kern *p, | 
|---|
| 1135 | __u32 fwmark) | 
|---|
| 1136 | { | 
|---|
| 1137 | struct net *net = t->net; | 
|---|
| 1138 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1139 |  | 
|---|
| 1140 | ipip6_tunnel_unlink(sitn, t); | 
|---|
| 1141 | synchronize_net(); | 
|---|
| 1142 | t->parms.iph.saddr = p->iph.saddr; | 
|---|
| 1143 | t->parms.iph.daddr = p->iph.daddr; | 
|---|
| 1144 | __dev_addr_set(dev: t->dev, addr: &p->iph.saddr, len: 4); | 
|---|
| 1145 | memcpy(to: t->dev->broadcast, from: &p->iph.daddr, len: 4); | 
|---|
| 1146 | ipip6_tunnel_link(sitn, t); | 
|---|
| 1147 | t->parms.iph.ttl = p->iph.ttl; | 
|---|
| 1148 | t->parms.iph.tos = p->iph.tos; | 
|---|
| 1149 | t->parms.iph.frag_off = p->iph.frag_off; | 
|---|
| 1150 | if (t->parms.link != p->link || t->fwmark != fwmark) { | 
|---|
| 1151 | t->parms.link = p->link; | 
|---|
| 1152 | t->fwmark = fwmark; | 
|---|
| 1153 | ipip6_tunnel_bind_dev(dev: t->dev); | 
|---|
| 1154 | } | 
|---|
| 1155 | dst_cache_reset(dst_cache: &t->dst_cache); | 
|---|
| 1156 | netdev_state_change(dev: t->dev); | 
|---|
| 1157 | } | 
|---|
| 1158 |  | 
|---|
| 1159 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1160 | static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, | 
|---|
| 1161 | struct ip_tunnel_6rd *ip6rd) | 
|---|
| 1162 | { | 
|---|
| 1163 | struct in6_addr prefix; | 
|---|
| 1164 | __be32 relay_prefix; | 
|---|
| 1165 |  | 
|---|
| 1166 | if (ip6rd->relay_prefixlen > 32 || | 
|---|
| 1167 | ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64) | 
|---|
| 1168 | return -EINVAL; | 
|---|
| 1169 |  | 
|---|
| 1170 | ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen); | 
|---|
| 1171 | if (!ipv6_addr_equal(&prefix, &ip6rd->prefix)) | 
|---|
| 1172 | return -EINVAL; | 
|---|
| 1173 | if (ip6rd->relay_prefixlen) | 
|---|
| 1174 | relay_prefix = ip6rd->relay_prefix & | 
|---|
| 1175 | htonl(0xffffffffUL << | 
|---|
| 1176 | (32 - ip6rd->relay_prefixlen)); | 
|---|
| 1177 | else | 
|---|
| 1178 | relay_prefix = 0; | 
|---|
| 1179 | if (relay_prefix != ip6rd->relay_prefix) | 
|---|
| 1180 | return -EINVAL; | 
|---|
| 1181 |  | 
|---|
| 1182 | t->ip6rd.prefix = prefix; | 
|---|
| 1183 | t->ip6rd.relay_prefix = relay_prefix; | 
|---|
| 1184 | t->ip6rd.prefixlen = ip6rd->prefixlen; | 
|---|
| 1185 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; | 
|---|
| 1186 | dst_cache_reset(&t->dst_cache); | 
|---|
| 1187 | netdev_state_change(t->dev); | 
|---|
| 1188 | return 0; | 
|---|
| 1189 | } | 
|---|
| 1190 |  | 
|---|
| 1191 | static int | 
|---|
| 1192 | ipip6_tunnel_get6rd(struct net_device *dev, struct ip_tunnel_parm __user *data) | 
|---|
| 1193 | { | 
|---|
| 1194 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1195 | struct ip_tunnel_parm_kern p; | 
|---|
| 1196 | struct ip_tunnel_6rd ip6rd; | 
|---|
| 1197 |  | 
|---|
| 1198 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) { | 
|---|
| 1199 | if (!ip_tunnel_parm_from_user(&p, data)) | 
|---|
| 1200 | return -EFAULT; | 
|---|
| 1201 | t = ipip6_tunnel_locate(t->net, &p, 0); | 
|---|
| 1202 | } | 
|---|
| 1203 | if (!t) | 
|---|
| 1204 | t = netdev_priv(dev); | 
|---|
| 1205 |  | 
|---|
| 1206 | ip6rd.prefix = t->ip6rd.prefix; | 
|---|
| 1207 | ip6rd.relay_prefix = t->ip6rd.relay_prefix; | 
|---|
| 1208 | ip6rd.prefixlen = t->ip6rd.prefixlen; | 
|---|
| 1209 | ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen; | 
|---|
| 1210 | if (copy_to_user(data, &ip6rd, sizeof(ip6rd))) | 
|---|
| 1211 | return -EFAULT; | 
|---|
| 1212 | return 0; | 
|---|
| 1213 | } | 
|---|
| 1214 |  | 
|---|
| 1215 | static int | 
|---|
| 1216 | ipip6_tunnel_6rdctl(struct net_device *dev, struct ip_tunnel_6rd __user *data, | 
|---|
| 1217 | int cmd) | 
|---|
| 1218 | { | 
|---|
| 1219 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1220 | struct ip_tunnel_6rd ip6rd; | 
|---|
| 1221 | int err; | 
|---|
| 1222 |  | 
|---|
| 1223 | if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN)) | 
|---|
| 1224 | return -EPERM; | 
|---|
| 1225 | if (copy_from_user(&ip6rd, data, sizeof(ip6rd))) | 
|---|
| 1226 | return -EFAULT; | 
|---|
| 1227 |  | 
|---|
| 1228 | if (cmd != SIOCDEL6RD) { | 
|---|
| 1229 | err = ipip6_tunnel_update_6rd(t, &ip6rd); | 
|---|
| 1230 | if (err < 0) | 
|---|
| 1231 | return err; | 
|---|
| 1232 | } else | 
|---|
| 1233 | ipip6_tunnel_clone_6rd(dev, dev_to_sit_net(dev)); | 
|---|
| 1234 | return 0; | 
|---|
| 1235 | } | 
|---|
| 1236 |  | 
|---|
| 1237 | #endif /* CONFIG_IPV6_SIT_6RD */ | 
|---|
| 1238 |  | 
|---|
| 1239 | static bool ipip6_valid_ip_proto(u8 ipproto) | 
|---|
| 1240 | { | 
|---|
| 1241 | return ipproto == IPPROTO_IPV6 || | 
|---|
| 1242 | ipproto == IPPROTO_IPIP || | 
|---|
| 1243 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1244 | ipproto == IPPROTO_MPLS || | 
|---|
| 1245 | #endif | 
|---|
| 1246 | ipproto == 0; | 
|---|
| 1247 | } | 
|---|
| 1248 |  | 
|---|
| 1249 | static int | 
|---|
| 1250 | __ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm_kern *p) | 
|---|
| 1251 | { | 
|---|
| 1252 | if (!ns_capable(ns: net->user_ns, CAP_NET_ADMIN)) | 
|---|
| 1253 | return -EPERM; | 
|---|
| 1254 |  | 
|---|
| 1255 | if (!ipip6_valid_ip_proto(ipproto: p->iph.protocol)) | 
|---|
| 1256 | return -EINVAL; | 
|---|
| 1257 | if (p->iph.version != 4 || | 
|---|
| 1258 | p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF))) | 
|---|
| 1259 | return -EINVAL; | 
|---|
| 1260 |  | 
|---|
| 1261 | if (p->iph.ttl) | 
|---|
| 1262 | p->iph.frag_off |= htons(IP_DF); | 
|---|
| 1263 | return 0; | 
|---|
| 1264 | } | 
|---|
| 1265 |  | 
|---|
| 1266 | static int | 
|---|
| 1267 | ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm_kern *p) | 
|---|
| 1268 | { | 
|---|
| 1269 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1270 |  | 
|---|
| 1271 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) | 
|---|
| 1272 | t = ipip6_tunnel_locate(net: t->net, parms: p, create: 0); | 
|---|
| 1273 | if (!t) | 
|---|
| 1274 | t = netdev_priv(dev); | 
|---|
| 1275 | memcpy(to: p, from: &t->parms, len: sizeof(*p)); | 
|---|
| 1276 | return 0; | 
|---|
| 1277 | } | 
|---|
| 1278 |  | 
|---|
| 1279 | static int | 
|---|
| 1280 | ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm_kern *p) | 
|---|
| 1281 | { | 
|---|
| 1282 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1283 | int err; | 
|---|
| 1284 |  | 
|---|
| 1285 | err = __ipip6_tunnel_ioctl_validate(net: t->net, p); | 
|---|
| 1286 | if (err) | 
|---|
| 1287 | return err; | 
|---|
| 1288 |  | 
|---|
| 1289 | t = ipip6_tunnel_locate(net: t->net, parms: p, create: 1); | 
|---|
| 1290 | if (!t) | 
|---|
| 1291 | return -ENOBUFS; | 
|---|
| 1292 | return 0; | 
|---|
| 1293 | } | 
|---|
| 1294 |  | 
|---|
| 1295 | static int | 
|---|
| 1296 | ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm_kern *p) | 
|---|
| 1297 | { | 
|---|
| 1298 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1299 | int err; | 
|---|
| 1300 |  | 
|---|
| 1301 | err = __ipip6_tunnel_ioctl_validate(net: t->net, p); | 
|---|
| 1302 | if (err) | 
|---|
| 1303 | return err; | 
|---|
| 1304 |  | 
|---|
| 1305 | t = ipip6_tunnel_locate(net: t->net, parms: p, create: 0); | 
|---|
| 1306 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) { | 
|---|
| 1307 | if (!t) | 
|---|
| 1308 | return -ENOENT; | 
|---|
| 1309 | } else { | 
|---|
| 1310 | if (t) { | 
|---|
| 1311 | if (t->dev != dev) | 
|---|
| 1312 | return -EEXIST; | 
|---|
| 1313 | } else { | 
|---|
| 1314 | if (((dev->flags & IFF_POINTOPOINT) && !p->iph.daddr) || | 
|---|
| 1315 | (!(dev->flags & IFF_POINTOPOINT) && p->iph.daddr)) | 
|---|
| 1316 | return -EINVAL; | 
|---|
| 1317 | t = netdev_priv(dev); | 
|---|
| 1318 | } | 
|---|
| 1319 |  | 
|---|
| 1320 | ipip6_tunnel_update(t, p, fwmark: t->fwmark); | 
|---|
| 1321 | } | 
|---|
| 1322 |  | 
|---|
| 1323 | return 0; | 
|---|
| 1324 | } | 
|---|
| 1325 |  | 
|---|
| 1326 | static int | 
|---|
| 1327 | ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm_kern *p) | 
|---|
| 1328 | { | 
|---|
| 1329 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1330 |  | 
|---|
| 1331 | if (!ns_capable(ns: t->net->user_ns, CAP_NET_ADMIN)) | 
|---|
| 1332 | return -EPERM; | 
|---|
| 1333 |  | 
|---|
| 1334 | if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) { | 
|---|
| 1335 | t = ipip6_tunnel_locate(net: t->net, parms: p, create: 0); | 
|---|
| 1336 | if (!t) | 
|---|
| 1337 | return -ENOENT; | 
|---|
| 1338 | if (t == netdev_priv(dev: dev_to_sit_net(dev)->fb_tunnel_dev)) | 
|---|
| 1339 | return -EPERM; | 
|---|
| 1340 | dev = t->dev; | 
|---|
| 1341 | } | 
|---|
| 1342 | unregister_netdevice(dev); | 
|---|
| 1343 | return 0; | 
|---|
| 1344 | } | 
|---|
| 1345 |  | 
|---|
| 1346 | static int | 
|---|
| 1347 | ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p, | 
|---|
| 1348 | int cmd) | 
|---|
| 1349 | { | 
|---|
| 1350 | switch (cmd) { | 
|---|
| 1351 | case SIOCGETTUNNEL: | 
|---|
| 1352 | return ipip6_tunnel_get(dev, p); | 
|---|
| 1353 | case SIOCADDTUNNEL: | 
|---|
| 1354 | return ipip6_tunnel_add(dev, p); | 
|---|
| 1355 | case SIOCCHGTUNNEL: | 
|---|
| 1356 | return ipip6_tunnel_change(dev, p); | 
|---|
| 1357 | case SIOCDELTUNNEL: | 
|---|
| 1358 | return ipip6_tunnel_del(dev, p); | 
|---|
| 1359 | default: | 
|---|
| 1360 | return -EINVAL; | 
|---|
| 1361 | } | 
|---|
| 1362 | } | 
|---|
| 1363 |  | 
|---|
| 1364 | static int | 
|---|
| 1365 | ipip6_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr, | 
|---|
| 1366 | void __user *data, int cmd) | 
|---|
| 1367 | { | 
|---|
| 1368 | switch (cmd) { | 
|---|
| 1369 | case SIOCGETTUNNEL: | 
|---|
| 1370 | case SIOCADDTUNNEL: | 
|---|
| 1371 | case SIOCCHGTUNNEL: | 
|---|
| 1372 | case SIOCDELTUNNEL: | 
|---|
| 1373 | return ip_tunnel_siocdevprivate(dev, ifr, data, cmd); | 
|---|
| 1374 | case SIOCGETPRL: | 
|---|
| 1375 | return ipip6_tunnel_get_prl(dev, a: data); | 
|---|
| 1376 | case SIOCADDPRL: | 
|---|
| 1377 | case SIOCDELPRL: | 
|---|
| 1378 | case SIOCCHGPRL: | 
|---|
| 1379 | return ipip6_tunnel_prl_ctl(dev, data, cmd); | 
|---|
| 1380 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1381 | case SIOCGET6RD: | 
|---|
| 1382 | return ipip6_tunnel_get6rd(dev, data); | 
|---|
| 1383 | case SIOCADD6RD: | 
|---|
| 1384 | case SIOCCHG6RD: | 
|---|
| 1385 | case SIOCDEL6RD: | 
|---|
| 1386 | return ipip6_tunnel_6rdctl(dev, data, cmd); | 
|---|
| 1387 | #endif | 
|---|
| 1388 | default: | 
|---|
| 1389 | return -EINVAL; | 
|---|
| 1390 | } | 
|---|
| 1391 | } | 
|---|
| 1392 |  | 
|---|
| 1393 | static const struct net_device_ops ipip6_netdev_ops = { | 
|---|
| 1394 | .ndo_init	= ipip6_tunnel_init, | 
|---|
| 1395 | .ndo_uninit	= ipip6_tunnel_uninit, | 
|---|
| 1396 | .ndo_start_xmit	= sit_tunnel_xmit, | 
|---|
| 1397 | .ndo_siocdevprivate = ipip6_tunnel_siocdevprivate, | 
|---|
| 1398 | .ndo_get_iflink = ip_tunnel_get_iflink, | 
|---|
| 1399 | .ndo_tunnel_ctl = ipip6_tunnel_ctl, | 
|---|
| 1400 | }; | 
|---|
| 1401 |  | 
|---|
| 1402 | static void ipip6_dev_free(struct net_device *dev) | 
|---|
| 1403 | { | 
|---|
| 1404 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1405 |  | 
|---|
| 1406 | dst_cache_destroy(dst_cache: &tunnel->dst_cache); | 
|---|
| 1407 | } | 
|---|
| 1408 |  | 
|---|
| 1409 | #define SIT_FEATURES (NETIF_F_SG	   | \ | 
|---|
| 1410 | NETIF_F_FRAGLIST	   | \ | 
|---|
| 1411 | NETIF_F_HIGHDMA	   | \ | 
|---|
| 1412 | NETIF_F_GSO_SOFTWARE | \ | 
|---|
| 1413 | NETIF_F_HW_CSUM) | 
|---|
| 1414 |  | 
|---|
| 1415 | static void ipip6_tunnel_setup(struct net_device *dev) | 
|---|
| 1416 | { | 
|---|
| 1417 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1418 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 
|---|
| 1419 |  | 
|---|
| 1420 | dev->netdev_ops		= &ipip6_netdev_ops; | 
|---|
| 1421 | dev->header_ops		= &ip_tunnel_header_ops; | 
|---|
| 1422 | dev->needs_free_netdev	= true; | 
|---|
| 1423 | dev->priv_destructor	= ipip6_dev_free; | 
|---|
| 1424 |  | 
|---|
| 1425 | dev->type		= ARPHRD_SIT; | 
|---|
| 1426 | dev->mtu		= ETH_DATA_LEN - t_hlen; | 
|---|
| 1427 | dev->min_mtu		= IPV6_MIN_MTU; | 
|---|
| 1428 | dev->max_mtu		= IP6_MAX_MTU - t_hlen; | 
|---|
| 1429 | dev->flags		= IFF_NOARP; | 
|---|
| 1430 | netif_keep_dst(dev); | 
|---|
| 1431 | dev->addr_len		= 4; | 
|---|
| 1432 | dev->lltx		= true; | 
|---|
| 1433 | dev->features		|= SIT_FEATURES; | 
|---|
| 1434 | dev->hw_features	|= SIT_FEATURES; | 
|---|
| 1435 | dev->pcpu_stat_type	= NETDEV_PCPU_STAT_TSTATS; | 
|---|
| 1436 |  | 
|---|
| 1437 | } | 
|---|
| 1438 |  | 
|---|
| 1439 | static int ipip6_tunnel_init(struct net_device *dev) | 
|---|
| 1440 | { | 
|---|
| 1441 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1442 | int err; | 
|---|
| 1443 |  | 
|---|
| 1444 | tunnel->dev = dev; | 
|---|
| 1445 | strcpy(tunnel->parms.name, dev->name); | 
|---|
| 1446 |  | 
|---|
| 1447 | ipip6_tunnel_bind_dev(dev); | 
|---|
| 1448 |  | 
|---|
| 1449 | err = dst_cache_init(dst_cache: &tunnel->dst_cache, GFP_KERNEL); | 
|---|
| 1450 | if (err) | 
|---|
| 1451 | return err; | 
|---|
| 1452 |  | 
|---|
| 1453 | netdev_hold(dev, tracker: &tunnel->dev_tracker, GFP_KERNEL); | 
|---|
| 1454 | netdev_lockdep_set_classes(dev); | 
|---|
| 1455 | return 0; | 
|---|
| 1456 | } | 
|---|
| 1457 |  | 
|---|
| 1458 | static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) | 
|---|
| 1459 | { | 
|---|
| 1460 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1461 | struct iphdr *iph = &tunnel->parms.iph; | 
|---|
| 1462 | struct net *net = dev_net(dev); | 
|---|
| 1463 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1464 |  | 
|---|
| 1465 | iph->version		= 4; | 
|---|
| 1466 | iph->protocol		= IPPROTO_IPV6; | 
|---|
| 1467 | iph->ihl		= 5; | 
|---|
| 1468 | iph->ttl		= 64; | 
|---|
| 1469 |  | 
|---|
| 1470 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 
|---|
| 1471 | } | 
|---|
| 1472 |  | 
|---|
| 1473 | static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[], | 
|---|
| 1474 | struct netlink_ext_ack *extack) | 
|---|
| 1475 | { | 
|---|
| 1476 | u8 proto; | 
|---|
| 1477 |  | 
|---|
| 1478 | if (!data || !data[IFLA_IPTUN_PROTO]) | 
|---|
| 1479 | return 0; | 
|---|
| 1480 |  | 
|---|
| 1481 | proto = nla_get_u8(nla: data[IFLA_IPTUN_PROTO]); | 
|---|
| 1482 | if (!ipip6_valid_ip_proto(ipproto: proto)) | 
|---|
| 1483 | return -EINVAL; | 
|---|
| 1484 |  | 
|---|
| 1485 | return 0; | 
|---|
| 1486 | } | 
|---|
| 1487 |  | 
|---|
| 1488 | static void ipip6_netlink_parms(struct nlattr *data[], | 
|---|
| 1489 | struct ip_tunnel_parm_kern *parms, | 
|---|
| 1490 | __u32 *fwmark) | 
|---|
| 1491 | { | 
|---|
| 1492 | memset(s: parms, c: 0, n: sizeof(*parms)); | 
|---|
| 1493 |  | 
|---|
| 1494 | parms->iph.version = 4; | 
|---|
| 1495 | parms->iph.protocol = IPPROTO_IPV6; | 
|---|
| 1496 | parms->iph.ihl = 5; | 
|---|
| 1497 | parms->iph.ttl = 64; | 
|---|
| 1498 |  | 
|---|
| 1499 | if (!data) | 
|---|
| 1500 | return; | 
|---|
| 1501 |  | 
|---|
| 1502 | ip_tunnel_netlink_parms(data, parms); | 
|---|
| 1503 |  | 
|---|
| 1504 | if (data[IFLA_IPTUN_FWMARK]) | 
|---|
| 1505 | *fwmark = nla_get_u32(nla: data[IFLA_IPTUN_FWMARK]); | 
|---|
| 1506 | } | 
|---|
| 1507 |  | 
|---|
| 1508 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1509 | /* This function returns true when 6RD attributes are present in the nl msg */ | 
|---|
| 1510 | static bool ipip6_netlink_6rd_parms(struct nlattr *data[], | 
|---|
| 1511 | struct ip_tunnel_6rd *ip6rd) | 
|---|
| 1512 | { | 
|---|
| 1513 | bool ret = false; | 
|---|
| 1514 | memset(ip6rd, 0, sizeof(*ip6rd)); | 
|---|
| 1515 |  | 
|---|
| 1516 | if (!data) | 
|---|
| 1517 | return ret; | 
|---|
| 1518 |  | 
|---|
| 1519 | if (data[IFLA_IPTUN_6RD_PREFIX]) { | 
|---|
| 1520 | ret = true; | 
|---|
| 1521 | ip6rd->prefix = nla_get_in6_addr(data[IFLA_IPTUN_6RD_PREFIX]); | 
|---|
| 1522 | } | 
|---|
| 1523 |  | 
|---|
| 1524 | if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) { | 
|---|
| 1525 | ret = true; | 
|---|
| 1526 | ip6rd->relay_prefix = | 
|---|
| 1527 | nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]); | 
|---|
| 1528 | } | 
|---|
| 1529 |  | 
|---|
| 1530 | if (data[IFLA_IPTUN_6RD_PREFIXLEN]) { | 
|---|
| 1531 | ret = true; | 
|---|
| 1532 | ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]); | 
|---|
| 1533 | } | 
|---|
| 1534 |  | 
|---|
| 1535 | if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) { | 
|---|
| 1536 | ret = true; | 
|---|
| 1537 | ip6rd->relay_prefixlen = | 
|---|
| 1538 | nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); | 
|---|
| 1539 | } | 
|---|
| 1540 |  | 
|---|
| 1541 | return ret; | 
|---|
| 1542 | } | 
|---|
| 1543 | #endif | 
|---|
| 1544 |  | 
|---|
| 1545 | static int ipip6_newlink(struct net_device *dev, | 
|---|
| 1546 | struct rtnl_newlink_params *params, | 
|---|
| 1547 | struct netlink_ext_ack *extack) | 
|---|
| 1548 | { | 
|---|
| 1549 | struct nlattr **data = params->data; | 
|---|
| 1550 | struct nlattr **tb = params->tb; | 
|---|
| 1551 | struct ip_tunnel *nt; | 
|---|
| 1552 | struct ip_tunnel_encap ipencap; | 
|---|
| 1553 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1554 | struct ip_tunnel_6rd ip6rd; | 
|---|
| 1555 | #endif | 
|---|
| 1556 | struct net *net; | 
|---|
| 1557 | int err; | 
|---|
| 1558 |  | 
|---|
| 1559 | net = params->link_net ? : dev_net(dev); | 
|---|
| 1560 | nt = netdev_priv(dev); | 
|---|
| 1561 | nt->net = net; | 
|---|
| 1562 |  | 
|---|
| 1563 | if (ip_tunnel_netlink_encap_parms(data, encap: &ipencap)) { | 
|---|
| 1564 | err = ip_tunnel_encap_setup(t: nt, ipencap: &ipencap); | 
|---|
| 1565 | if (err < 0) | 
|---|
| 1566 | return err; | 
|---|
| 1567 | } | 
|---|
| 1568 |  | 
|---|
| 1569 | ipip6_netlink_parms(data, parms: &nt->parms, fwmark: &nt->fwmark); | 
|---|
| 1570 |  | 
|---|
| 1571 | if (ipip6_tunnel_locate(net, parms: &nt->parms, create: 0)) | 
|---|
| 1572 | return -EEXIST; | 
|---|
| 1573 |  | 
|---|
| 1574 | err = ipip6_tunnel_create(dev); | 
|---|
| 1575 | if (err < 0) | 
|---|
| 1576 | return err; | 
|---|
| 1577 |  | 
|---|
| 1578 | if (tb[IFLA_MTU]) { | 
|---|
| 1579 | u32 mtu = nla_get_u32(nla: tb[IFLA_MTU]); | 
|---|
| 1580 |  | 
|---|
| 1581 | if (mtu >= IPV6_MIN_MTU && | 
|---|
| 1582 | mtu <= IP6_MAX_MTU - dev->hard_header_len) | 
|---|
| 1583 | dev->mtu = mtu; | 
|---|
| 1584 | } | 
|---|
| 1585 |  | 
|---|
| 1586 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1587 | if (ipip6_netlink_6rd_parms(data, &ip6rd)) { | 
|---|
| 1588 | err = ipip6_tunnel_update_6rd(nt, &ip6rd); | 
|---|
| 1589 | if (err < 0) | 
|---|
| 1590 | unregister_netdevice_queue(dev, NULL); | 
|---|
| 1591 | } | 
|---|
| 1592 | #endif | 
|---|
| 1593 |  | 
|---|
| 1594 | return err; | 
|---|
| 1595 | } | 
|---|
| 1596 |  | 
|---|
| 1597 | static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], | 
|---|
| 1598 | struct nlattr *data[], | 
|---|
| 1599 | struct netlink_ext_ack *extack) | 
|---|
| 1600 | { | 
|---|
| 1601 | struct ip_tunnel *t = netdev_priv(dev); | 
|---|
| 1602 | struct ip_tunnel_encap ipencap; | 
|---|
| 1603 | struct ip_tunnel_parm_kern p; | 
|---|
| 1604 | struct net *net = t->net; | 
|---|
| 1605 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1606 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1607 | struct ip_tunnel_6rd ip6rd; | 
|---|
| 1608 | #endif | 
|---|
| 1609 | __u32 fwmark = t->fwmark; | 
|---|
| 1610 | int err; | 
|---|
| 1611 |  | 
|---|
| 1612 | if (dev == sitn->fb_tunnel_dev) | 
|---|
| 1613 | return -EINVAL; | 
|---|
| 1614 |  | 
|---|
| 1615 | if (ip_tunnel_netlink_encap_parms(data, encap: &ipencap)) { | 
|---|
| 1616 | err = ip_tunnel_encap_setup(t, ipencap: &ipencap); | 
|---|
| 1617 | if (err < 0) | 
|---|
| 1618 | return err; | 
|---|
| 1619 | } | 
|---|
| 1620 |  | 
|---|
| 1621 | ipip6_netlink_parms(data, parms: &p, fwmark: &fwmark); | 
|---|
| 1622 |  | 
|---|
| 1623 | if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) || | 
|---|
| 1624 | (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr)) | 
|---|
| 1625 | return -EINVAL; | 
|---|
| 1626 |  | 
|---|
| 1627 | t = ipip6_tunnel_locate(net, parms: &p, create: 0); | 
|---|
| 1628 |  | 
|---|
| 1629 | if (t) { | 
|---|
| 1630 | if (t->dev != dev) | 
|---|
| 1631 | return -EEXIST; | 
|---|
| 1632 | } else | 
|---|
| 1633 | t = netdev_priv(dev); | 
|---|
| 1634 |  | 
|---|
| 1635 | ipip6_tunnel_update(t, p: &p, fwmark); | 
|---|
| 1636 |  | 
|---|
| 1637 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1638 | if (ipip6_netlink_6rd_parms(data, &ip6rd)) | 
|---|
| 1639 | return ipip6_tunnel_update_6rd(t, &ip6rd); | 
|---|
| 1640 | #endif | 
|---|
| 1641 |  | 
|---|
| 1642 | return 0; | 
|---|
| 1643 | } | 
|---|
| 1644 |  | 
|---|
| 1645 | static size_t ipip6_get_size(const struct net_device *dev) | 
|---|
| 1646 | { | 
|---|
| 1647 | return | 
|---|
| 1648 | /* IFLA_IPTUN_LINK */ | 
|---|
| 1649 | nla_total_size(payload: 4) + | 
|---|
| 1650 | /* IFLA_IPTUN_LOCAL */ | 
|---|
| 1651 | nla_total_size(payload: 4) + | 
|---|
| 1652 | /* IFLA_IPTUN_REMOTE */ | 
|---|
| 1653 | nla_total_size(payload: 4) + | 
|---|
| 1654 | /* IFLA_IPTUN_TTL */ | 
|---|
| 1655 | nla_total_size(payload: 1) + | 
|---|
| 1656 | /* IFLA_IPTUN_TOS */ | 
|---|
| 1657 | nla_total_size(payload: 1) + | 
|---|
| 1658 | /* IFLA_IPTUN_PMTUDISC */ | 
|---|
| 1659 | nla_total_size(payload: 1) + | 
|---|
| 1660 | /* IFLA_IPTUN_FLAGS */ | 
|---|
| 1661 | nla_total_size(payload: 2) + | 
|---|
| 1662 | /* IFLA_IPTUN_PROTO */ | 
|---|
| 1663 | nla_total_size(payload: 1) + | 
|---|
| 1664 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1665 | /* IFLA_IPTUN_6RD_PREFIX */ | 
|---|
| 1666 | nla_total_size(sizeof(struct in6_addr)) + | 
|---|
| 1667 | /* IFLA_IPTUN_6RD_RELAY_PREFIX */ | 
|---|
| 1668 | nla_total_size(4) + | 
|---|
| 1669 | /* IFLA_IPTUN_6RD_PREFIXLEN */ | 
|---|
| 1670 | nla_total_size(2) + | 
|---|
| 1671 | /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */ | 
|---|
| 1672 | nla_total_size(2) + | 
|---|
| 1673 | #endif | 
|---|
| 1674 | /* IFLA_IPTUN_ENCAP_TYPE */ | 
|---|
| 1675 | nla_total_size(payload: 2) + | 
|---|
| 1676 | /* IFLA_IPTUN_ENCAP_FLAGS */ | 
|---|
| 1677 | nla_total_size(payload: 2) + | 
|---|
| 1678 | /* IFLA_IPTUN_ENCAP_SPORT */ | 
|---|
| 1679 | nla_total_size(payload: 2) + | 
|---|
| 1680 | /* IFLA_IPTUN_ENCAP_DPORT */ | 
|---|
| 1681 | nla_total_size(payload: 2) + | 
|---|
| 1682 | /* IFLA_IPTUN_FWMARK */ | 
|---|
| 1683 | nla_total_size(payload: 4) + | 
|---|
| 1684 | 0; | 
|---|
| 1685 | } | 
|---|
| 1686 |  | 
|---|
| 1687 | static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) | 
|---|
| 1688 | { | 
|---|
| 1689 | struct ip_tunnel *tunnel = netdev_priv(dev); | 
|---|
| 1690 | struct ip_tunnel_parm_kern *parm = &tunnel->parms; | 
|---|
| 1691 |  | 
|---|
| 1692 | if (nla_put_u32(skb, attrtype: IFLA_IPTUN_LINK, value: parm->link) || | 
|---|
| 1693 | nla_put_in_addr(skb, attrtype: IFLA_IPTUN_LOCAL, addr: parm->iph.saddr) || | 
|---|
| 1694 | nla_put_in_addr(skb, attrtype: IFLA_IPTUN_REMOTE, addr: parm->iph.daddr) || | 
|---|
| 1695 | nla_put_u8(skb, attrtype: IFLA_IPTUN_TTL, value: parm->iph.ttl) || | 
|---|
| 1696 | nla_put_u8(skb, attrtype: IFLA_IPTUN_TOS, value: parm->iph.tos) || | 
|---|
| 1697 | nla_put_u8(skb, attrtype: IFLA_IPTUN_PMTUDISC, | 
|---|
| 1698 | value: !!(parm->iph.frag_off & htons(IP_DF))) || | 
|---|
| 1699 | nla_put_u8(skb, attrtype: IFLA_IPTUN_PROTO, value: parm->iph.protocol) || | 
|---|
| 1700 | nla_put_be16(skb, attrtype: IFLA_IPTUN_FLAGS, | 
|---|
| 1701 | value: ip_tunnel_flags_to_be16(flags: parm->i_flags)) || | 
|---|
| 1702 | nla_put_u32(skb, attrtype: IFLA_IPTUN_FWMARK, value: tunnel->fwmark)) | 
|---|
| 1703 | goto nla_put_failure; | 
|---|
| 1704 |  | 
|---|
| 1705 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1706 | if (nla_put_in6_addr(skb, IFLA_IPTUN_6RD_PREFIX, | 
|---|
| 1707 | &tunnel->ip6rd.prefix) || | 
|---|
| 1708 | nla_put_in_addr(skb, IFLA_IPTUN_6RD_RELAY_PREFIX, | 
|---|
| 1709 | tunnel->ip6rd.relay_prefix) || | 
|---|
| 1710 | nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN, | 
|---|
| 1711 | tunnel->ip6rd.prefixlen) || | 
|---|
| 1712 | nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, | 
|---|
| 1713 | tunnel->ip6rd.relay_prefixlen)) | 
|---|
| 1714 | goto nla_put_failure; | 
|---|
| 1715 | #endif | 
|---|
| 1716 |  | 
|---|
| 1717 | if (nla_put_u16(skb, attrtype: IFLA_IPTUN_ENCAP_TYPE, | 
|---|
| 1718 | value: tunnel->encap.type) || | 
|---|
| 1719 | nla_put_be16(skb, attrtype: IFLA_IPTUN_ENCAP_SPORT, | 
|---|
| 1720 | value: tunnel->encap.sport) || | 
|---|
| 1721 | nla_put_be16(skb, attrtype: IFLA_IPTUN_ENCAP_DPORT, | 
|---|
| 1722 | value: tunnel->encap.dport) || | 
|---|
| 1723 | nla_put_u16(skb, attrtype: IFLA_IPTUN_ENCAP_FLAGS, | 
|---|
| 1724 | value: tunnel->encap.flags)) | 
|---|
| 1725 | goto nla_put_failure; | 
|---|
| 1726 |  | 
|---|
| 1727 | return 0; | 
|---|
| 1728 |  | 
|---|
| 1729 | nla_put_failure: | 
|---|
| 1730 | return -EMSGSIZE; | 
|---|
| 1731 | } | 
|---|
| 1732 |  | 
|---|
| 1733 | static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { | 
|---|
| 1734 | [IFLA_IPTUN_LINK]		= { .type = NLA_U32 }, | 
|---|
| 1735 | [IFLA_IPTUN_LOCAL]		= { .type = NLA_U32 }, | 
|---|
| 1736 | [IFLA_IPTUN_REMOTE]		= { .type = NLA_U32 }, | 
|---|
| 1737 | [IFLA_IPTUN_TTL]		= { .type = NLA_U8 }, | 
|---|
| 1738 | [IFLA_IPTUN_TOS]		= { .type = NLA_U8 }, | 
|---|
| 1739 | [IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 }, | 
|---|
| 1740 | [IFLA_IPTUN_FLAGS]		= { .type = NLA_U16 }, | 
|---|
| 1741 | [IFLA_IPTUN_PROTO]		= { .type = NLA_U8 }, | 
|---|
| 1742 | #ifdef CONFIG_IPV6_SIT_6RD | 
|---|
| 1743 | [IFLA_IPTUN_6RD_PREFIX]		= { .len = sizeof(struct in6_addr) }, | 
|---|
| 1744 | [IFLA_IPTUN_6RD_RELAY_PREFIX]	= { .type = NLA_U32 }, | 
|---|
| 1745 | [IFLA_IPTUN_6RD_PREFIXLEN]	= { .type = NLA_U16 }, | 
|---|
| 1746 | [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 }, | 
|---|
| 1747 | #endif | 
|---|
| 1748 | [IFLA_IPTUN_ENCAP_TYPE]		= { .type = NLA_U16 }, | 
|---|
| 1749 | [IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 }, | 
|---|
| 1750 | [IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 }, | 
|---|
| 1751 | [IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 }, | 
|---|
| 1752 | [IFLA_IPTUN_FWMARK]		= { .type = NLA_U32 }, | 
|---|
| 1753 | }; | 
|---|
| 1754 |  | 
|---|
| 1755 | static void ipip6_dellink(struct net_device *dev, struct list_head *head) | 
|---|
| 1756 | { | 
|---|
| 1757 | struct net *net = dev_net(dev); | 
|---|
| 1758 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1759 |  | 
|---|
| 1760 | if (dev != sitn->fb_tunnel_dev) | 
|---|
| 1761 | unregister_netdevice_queue(dev, head); | 
|---|
| 1762 | } | 
|---|
| 1763 |  | 
|---|
| 1764 | static struct rtnl_link_ops sit_link_ops __read_mostly = { | 
|---|
| 1765 | .kind		= "sit", | 
|---|
| 1766 | .maxtype	= IFLA_IPTUN_MAX, | 
|---|
| 1767 | .policy		= ipip6_policy, | 
|---|
| 1768 | .priv_size	= sizeof(struct ip_tunnel), | 
|---|
| 1769 | .setup		= ipip6_tunnel_setup, | 
|---|
| 1770 | .validate	= ipip6_validate, | 
|---|
| 1771 | .newlink	= ipip6_newlink, | 
|---|
| 1772 | .changelink	= ipip6_changelink, | 
|---|
| 1773 | .get_size	= ipip6_get_size, | 
|---|
| 1774 | .fill_info	= ipip6_fill_info, | 
|---|
| 1775 | .dellink	= ipip6_dellink, | 
|---|
| 1776 | .get_link_net	= ip_tunnel_get_link_net, | 
|---|
| 1777 | }; | 
|---|
| 1778 |  | 
|---|
| 1779 | static struct xfrm_tunnel sit_handler __read_mostly = { | 
|---|
| 1780 | .handler	=	ipip6_rcv, | 
|---|
| 1781 | .err_handler	=	ipip6_err, | 
|---|
| 1782 | .priority	=	1, | 
|---|
| 1783 | }; | 
|---|
| 1784 |  | 
|---|
| 1785 | static struct xfrm_tunnel ipip_handler __read_mostly = { | 
|---|
| 1786 | .handler	=	ipip_rcv, | 
|---|
| 1787 | .err_handler	=	ipip6_err, | 
|---|
| 1788 | .priority	=	2, | 
|---|
| 1789 | }; | 
|---|
| 1790 |  | 
|---|
| 1791 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1792 | static struct xfrm_tunnel mplsip_handler __read_mostly = { | 
|---|
| 1793 | .handler	=	mplsip_rcv, | 
|---|
| 1794 | .err_handler	=	ipip6_err, | 
|---|
| 1795 | .priority	=	2, | 
|---|
| 1796 | }; | 
|---|
| 1797 | #endif | 
|---|
| 1798 |  | 
|---|
| 1799 | static void __net_exit sit_exit_rtnl_net(struct net *net, struct list_head *head) | 
|---|
| 1800 | { | 
|---|
| 1801 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1802 | struct net_device *dev, *aux; | 
|---|
| 1803 | int prio; | 
|---|
| 1804 |  | 
|---|
| 1805 | for_each_netdev_safe(net, dev, aux) | 
|---|
| 1806 | if (dev->rtnl_link_ops == &sit_link_ops) | 
|---|
| 1807 | unregister_netdevice_queue(dev, head); | 
|---|
| 1808 |  | 
|---|
| 1809 | for (prio = 0; prio < 4; prio++) { | 
|---|
| 1810 | int h; | 
|---|
| 1811 | for (h = 0; h < (prio ? IP6_SIT_HASH_SIZE : 1); h++) { | 
|---|
| 1812 | struct ip_tunnel *t; | 
|---|
| 1813 |  | 
|---|
| 1814 | t = rtnl_net_dereference(net, sitn->tunnels[prio][h]); | 
|---|
| 1815 | while (t) { | 
|---|
| 1816 | /* If dev is in the same netns, it has already | 
|---|
| 1817 | * been added to the list by the previous loop. | 
|---|
| 1818 | */ | 
|---|
| 1819 | if (!net_eq(net1: dev_net(dev: t->dev), net2: net)) | 
|---|
| 1820 | unregister_netdevice_queue(dev: t->dev, head); | 
|---|
| 1821 |  | 
|---|
| 1822 | t = rtnl_net_dereference(net, t->next); | 
|---|
| 1823 | } | 
|---|
| 1824 | } | 
|---|
| 1825 | } | 
|---|
| 1826 | } | 
|---|
| 1827 |  | 
|---|
| 1828 | static int __net_init sit_init_net(struct net *net) | 
|---|
| 1829 | { | 
|---|
| 1830 | struct sit_net *sitn = net_generic(net, id: sit_net_id); | 
|---|
| 1831 | struct ip_tunnel *t; | 
|---|
| 1832 | int err; | 
|---|
| 1833 |  | 
|---|
| 1834 | sitn->tunnels[0] = sitn->tunnels_wc; | 
|---|
| 1835 | sitn->tunnels[1] = sitn->tunnels_l; | 
|---|
| 1836 | sitn->tunnels[2] = sitn->tunnels_r; | 
|---|
| 1837 | sitn->tunnels[3] = sitn->tunnels_r_l; | 
|---|
| 1838 |  | 
|---|
| 1839 | if (!net_has_fallback_tunnels(net)) | 
|---|
| 1840 | return 0; | 
|---|
| 1841 |  | 
|---|
| 1842 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | 
|---|
| 1843 | NET_NAME_UNKNOWN, | 
|---|
| 1844 | ipip6_tunnel_setup); | 
|---|
| 1845 | if (!sitn->fb_tunnel_dev) { | 
|---|
| 1846 | err = -ENOMEM; | 
|---|
| 1847 | goto err_alloc_dev; | 
|---|
| 1848 | } | 
|---|
| 1849 | dev_net_set(dev: sitn->fb_tunnel_dev, net); | 
|---|
| 1850 | sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops; | 
|---|
| 1851 | /* FB netdevice is special: we have one, and only one per netns. | 
|---|
| 1852 | * Allowing to move it to another netns is clearly unsafe. | 
|---|
| 1853 | */ | 
|---|
| 1854 | sitn->fb_tunnel_dev->netns_immutable = true; | 
|---|
| 1855 |  | 
|---|
| 1856 | t = netdev_priv(dev: sitn->fb_tunnel_dev); | 
|---|
| 1857 | t->net = net; | 
|---|
| 1858 |  | 
|---|
| 1859 | err = register_netdev(dev: sitn->fb_tunnel_dev); | 
|---|
| 1860 | if (err) | 
|---|
| 1861 | goto err_reg_dev; | 
|---|
| 1862 |  | 
|---|
| 1863 | ipip6_tunnel_clone_6rd(dev: sitn->fb_tunnel_dev, sitn); | 
|---|
| 1864 | ipip6_fb_tunnel_init(dev: sitn->fb_tunnel_dev); | 
|---|
| 1865 |  | 
|---|
| 1866 | strcpy(t->parms.name, sitn->fb_tunnel_dev->name); | 
|---|
| 1867 | return 0; | 
|---|
| 1868 |  | 
|---|
| 1869 | err_reg_dev: | 
|---|
| 1870 | free_netdev(dev: sitn->fb_tunnel_dev); | 
|---|
| 1871 | err_alloc_dev: | 
|---|
| 1872 | return err; | 
|---|
| 1873 | } | 
|---|
| 1874 |  | 
|---|
| 1875 | static struct pernet_operations sit_net_ops = { | 
|---|
| 1876 | .init = sit_init_net, | 
|---|
| 1877 | .exit_rtnl = sit_exit_rtnl_net, | 
|---|
| 1878 | .id   = &sit_net_id, | 
|---|
| 1879 | .size = sizeof(struct sit_net), | 
|---|
| 1880 | }; | 
|---|
| 1881 |  | 
|---|
| 1882 | static void __exit sit_cleanup(void) | 
|---|
| 1883 | { | 
|---|
| 1884 | rtnl_link_unregister(ops: &sit_link_ops); | 
|---|
| 1885 | xfrm4_tunnel_deregister(handler: &sit_handler, AF_INET6); | 
|---|
| 1886 | xfrm4_tunnel_deregister(handler: &ipip_handler, AF_INET); | 
|---|
| 1887 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1888 | xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS); | 
|---|
| 1889 | #endif | 
|---|
| 1890 |  | 
|---|
| 1891 | unregister_pernet_device(&sit_net_ops); | 
|---|
| 1892 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 
|---|
| 1893 | } | 
|---|
| 1894 |  | 
|---|
| 1895 | static int __init sit_init(void) | 
|---|
| 1896 | { | 
|---|
| 1897 | int err; | 
|---|
| 1898 |  | 
|---|
| 1899 | pr_info( "IPv6, IPv4 and MPLS over IPv4 tunneling driver\n"); | 
|---|
| 1900 |  | 
|---|
| 1901 | err = register_pernet_device(&sit_net_ops); | 
|---|
| 1902 | if (err < 0) | 
|---|
| 1903 | return err; | 
|---|
| 1904 | err = xfrm4_tunnel_register(handler: &sit_handler, AF_INET6); | 
|---|
| 1905 | if (err < 0) { | 
|---|
| 1906 | pr_info( "%s: can't register ip6ip4\n", __func__); | 
|---|
| 1907 | goto xfrm_tunnel_failed; | 
|---|
| 1908 | } | 
|---|
| 1909 | err = xfrm4_tunnel_register(handler: &ipip_handler, AF_INET); | 
|---|
| 1910 | if (err < 0) { | 
|---|
| 1911 | pr_info( "%s: can't register ip4ip4\n", __func__); | 
|---|
| 1912 | goto xfrm_tunnel4_failed; | 
|---|
| 1913 | } | 
|---|
| 1914 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1915 | err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS); | 
|---|
| 1916 | if (err < 0) { | 
|---|
| 1917 | pr_info( "%s: can't register mplsip\n", __func__); | 
|---|
| 1918 | goto xfrm_tunnel_mpls_failed; | 
|---|
| 1919 | } | 
|---|
| 1920 | #endif | 
|---|
| 1921 | err = rtnl_link_register(ops: &sit_link_ops); | 
|---|
| 1922 | if (err < 0) | 
|---|
| 1923 | goto rtnl_link_failed; | 
|---|
| 1924 |  | 
|---|
| 1925 | out: | 
|---|
| 1926 | return err; | 
|---|
| 1927 |  | 
|---|
| 1928 | rtnl_link_failed: | 
|---|
| 1929 | #if IS_ENABLED(CONFIG_MPLS) | 
|---|
| 1930 | xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS); | 
|---|
| 1931 | xfrm_tunnel_mpls_failed: | 
|---|
| 1932 | #endif | 
|---|
| 1933 | xfrm4_tunnel_deregister(handler: &ipip_handler, AF_INET); | 
|---|
| 1934 | xfrm_tunnel4_failed: | 
|---|
| 1935 | xfrm4_tunnel_deregister(handler: &sit_handler, AF_INET6); | 
|---|
| 1936 | xfrm_tunnel_failed: | 
|---|
| 1937 | unregister_pernet_device(&sit_net_ops); | 
|---|
| 1938 | goto out; | 
|---|
| 1939 | } | 
|---|
| 1940 |  | 
|---|
| 1941 | module_init(sit_init); | 
|---|
| 1942 | module_exit(sit_cleanup); | 
|---|
| 1943 | MODULE_DESCRIPTION( "IPv6-in-IPv4 tunnel SIT driver"); | 
|---|
| 1944 | MODULE_LICENSE( "GPL"); | 
|---|
| 1945 | MODULE_ALIAS_RTNL_LINK( "sit"); | 
|---|
| 1946 | MODULE_ALIAS_NETDEV( "sit0"); | 
|---|
| 1947 |  | 
|---|