Blame view

net/ipv6/sit.c 44.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *	IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT)
   *	Linux INET6 implementation
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
6
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   *
   *	Changes:
   * Roger Venning <r.venning@telstra.com>:	6to4 support
   * Nate Thompson <nate@thebog.net>:		6to4 support
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
17
   * Fred Templin <fred.l.templin@boeing.com>:	isatap support
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
   */
f32138319   Joe Perches   net: ipv6: Standa...
19
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <linux/module.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
21
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
  #include <linux/net.h>
  #include <linux/in6.h>
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
  #include <linux/icmp.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
32
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  #include <linux/init.h>
  #include <linux/netfilter_ipv4.h>
46f25dffb   Kris Katterjohn   [NET]: Change 150...
35
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  
  #include <net/sock.h>
  #include <net/snmp.h>
  
  #include <net/ipv6.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
  #include <net/ip6_fib.h>
  #include <net/ip6_route.h>
  #include <net/ndisc.h>
  #include <net/addrconf.h>
  #include <net/ip.h>
  #include <net/udp.h>
  #include <net/icmp.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
50
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
  #include <net/dsfield.h>
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
54
55
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
  
  /*
     This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
  
     For comments look at net/ipv4/ip_gre.c --ANK
   */
e87a8f24c   Jiri Kosina   net: resolve symb...
62
  #define IP6_SIT_HASH_SIZE  16
e69a4adc6   Al Viro   [IPV6]: Misc endi...
63
  #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
65
66
67
  static bool log_ecn_error = true;
  module_param(log_ecn_error, bool, 0644);
  MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
15fc1f705   Eric Dumazet   sit: percpu stats...
68
  static int ipip6_tunnel_init(struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  static void ipip6_tunnel_setup(struct net_device *dev);
15fc1f705   Eric Dumazet   sit: percpu stats...
70
  static void ipip6_dev_free(struct net_device *dev);
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
71
72
  static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
  		      __be32 *v4dst);
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
73
  static struct rtnl_link_ops sit_link_ops __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

c7d03a00b   Alexey Dobriyan   netns: make struc...
75
  static unsigned int sit_net_id __read_mostly;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
76
  struct sit_net {
e87a8f24c   Jiri Kosina   net: resolve symb...
77
78
79
  	struct ip_tunnel __rcu *tunnels_r_l[IP6_SIT_HASH_SIZE];
  	struct ip_tunnel __rcu *tunnels_r[IP6_SIT_HASH_SIZE];
  	struct ip_tunnel __rcu *tunnels_l[IP6_SIT_HASH_SIZE];
3a43be3c3   Eric Dumazet   sit: get rid of i...
80
81
  	struct ip_tunnel __rcu *tunnels_wc[1];
  	struct ip_tunnel __rcu **tunnels[4];
291821766   Pavel Emelyanov   [SIT]: Make tunne...
82

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
83
  	struct net_device *fb_tunnel_dev;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
84
  };
4543c10de   Eric Dumazet   ipv6 sit: RCU con...
85
86
87
  /*
   * Must be invoked with rcu_read_lock
   */
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
88
  static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net,
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
89
  		struct net_device *dev, __be32 remote, __be32 local)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  {
3a43be3c3   Eric Dumazet   sit: get rid of i...
91
92
  	unsigned int h0 = HASH(remote);
  	unsigned int h1 = HASH(local);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  	struct ip_tunnel *t;
291821766   Pavel Emelyanov   [SIT]: Make tunne...
94
  	struct sit_net *sitn = net_generic(net, sit_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95

e086cadc0   Amerigo Wang   net: unify for_ea...
96
  	for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  		if (local == t->parms.iph.saddr &&
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
98
  		    remote == t->parms.iph.daddr &&
bc8fc7b8f   Shmulik Ladkani   sit: Fix ipip6_tu...
99
  		    (!dev || !t->parms.link || dev->ifindex == t->parms.link) &&
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
100
  		    (t->dev->flags & IFF_UP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
  			return t;
  	}
e086cadc0   Amerigo Wang   net: unify for_ea...
103
  	for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) {
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
104
  		if (remote == t->parms.iph.daddr &&
bc8fc7b8f   Shmulik Ladkani   sit: Fix ipip6_tu...
105
  		    (!dev || !t->parms.link || dev->ifindex == t->parms.link) &&
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
106
  		    (t->dev->flags & IFF_UP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
  			return t;
  	}
e086cadc0   Amerigo Wang   net: unify for_ea...
109
  	for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) {
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
110
  		if (local == t->parms.iph.saddr &&
bc8fc7b8f   Shmulik Ladkani   sit: Fix ipip6_tu...
111
  		    (!dev || !t->parms.link || dev->ifindex == t->parms.link) &&
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
112
  		    (t->dev->flags & IFF_UP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
  			return t;
  	}
4543c10de   Eric Dumazet   ipv6 sit: RCU con...
115
  	t = rcu_dereference(sitn->tunnels_wc[0]);
53b24b8f9   Ian Morris   ipv6: coding styl...
116
  	if (t && (t->dev->flags & IFF_UP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  		return t;
  	return NULL;
  }
3a43be3c3   Eric Dumazet   sit: get rid of i...
120
  static struct ip_tunnel __rcu **__ipip6_bucket(struct sit_net *sitn,
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
121
  		struct ip_tunnel_parm *parms)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  {
420fe234a   YOSHIFUJI Hideaki   [IPV6] SIT: Unify...
123
124
  	__be32 remote = parms->iph.daddr;
  	__be32 local = parms->iph.saddr;
3a43be3c3   Eric Dumazet   sit: get rid of i...
125
  	unsigned int h = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
134
135
  	int prio = 0;
  
  	if (remote) {
  		prio |= 2;
  		h ^= HASH(remote);
  	}
  	if (local) {
  		prio |= 1;
  		h ^= HASH(local);
  	}
291821766   Pavel Emelyanov   [SIT]: Make tunne...
136
  	return &sitn->tunnels[prio][h];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  }
3a43be3c3   Eric Dumazet   sit: get rid of i...
138
  static inline struct ip_tunnel __rcu **ipip6_bucket(struct sit_net *sitn,
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
139
  		struct ip_tunnel *t)
420fe234a   YOSHIFUJI Hideaki   [IPV6] SIT: Unify...
140
  {
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
141
  	return __ipip6_bucket(sitn, &t->parms);
420fe234a   YOSHIFUJI Hideaki   [IPV6] SIT: Unify...
142
  }
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
143
  static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  {
3a43be3c3   Eric Dumazet   sit: get rid of i...
145
146
147
148
149
150
151
  	struct ip_tunnel __rcu **tp;
  	struct ip_tunnel *iter;
  
  	for (tp = ipip6_bucket(sitn, t);
  	     (iter = rtnl_dereference(*tp)) != NULL;
  	     tp = &iter->next) {
  		if (t == iter) {
cf778b00e   Eric Dumazet   net: reintroduce ...
152
  			rcu_assign_pointer(*tp, t->next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
  			break;
  		}
  	}
  }
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
157
  static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  {
3a43be3c3   Eric Dumazet   sit: get rid of i...
159
  	struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160

cf778b00e   Eric Dumazet   net: reintroduce ...
161
162
  	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
  	rcu_assign_pointer(*tp, t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  }
e0c939481   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Ensure ...
164
  static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
165
166
  {
  #ifdef CONFIG_IPV6_SIT_6RD
e0c939481   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Ensure ...
167
  	struct ip_tunnel *t = netdev_priv(dev);
c3d7d3a09   Arnd Bergmann   ipv6 sit: work ar...
168
  	if (dev == sitn->fb_tunnel_dev) {
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
169
170
171
172
173
174
175
176
177
178
  		ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0);
  		t->ip6rd.relay_prefix = 0;
  		t->ip6rd.prefixlen = 16;
  		t->ip6rd.relay_prefixlen = 0;
  	} else {
  		struct ip_tunnel *t0 = netdev_priv(sitn->fb_tunnel_dev);
  		memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd));
  	}
  #endif
  }
f37234160   Nicolas Dichtel   sit: add support ...
179
180
181
182
183
184
  static int ipip6_tunnel_create(struct net_device *dev)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct net *net = dev_net(dev);
  	struct sit_net *sitn = net_generic(net, sit_net_id);
  	int err;
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
185
186
  	memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
f37234160   Nicolas Dichtel   sit: add support ...
187

d440b7206   Nicolas Dichtel   sit: fix sparse w...
188
  	if ((__force u16)t->parms.i_flags & SIT_ISATAP)
f37234160   Nicolas Dichtel   sit: add support ...
189
  		dev->priv_flags |= IFF_ISATAP;
87e57399e   Thadeu Lima de Souza Cascardo   sit: set rtnl_lin...
190
  	dev->rtnl_link_ops = &sit_link_ops;
f37234160   Nicolas Dichtel   sit: add support ...
191
192
193
  	err = register_netdevice(dev);
  	if (err < 0)
  		goto out;
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
194
  	ipip6_tunnel_clone_6rd(dev, sitn);
f37234160   Nicolas Dichtel   sit: add support ...
195
196
197
198
199
200
201
202
  	dev_hold(dev);
  
  	ipip6_tunnel_link(sitn, t);
  	return 0;
  
  out:
  	return err;
  }
3a43be3c3   Eric Dumazet   sit: get rid of i...
203
  static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
204
  		struct ip_tunnel_parm *parms, int create)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  {
e69a4adc6   Al Viro   [IPV6]: Misc endi...
206
207
  	__be32 remote = parms->iph.daddr;
  	__be32 local = parms->iph.saddr;
3a43be3c3   Eric Dumazet   sit: get rid of i...
208
209
  	struct ip_tunnel *t, *nt;
  	struct ip_tunnel __rcu **tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	struct net_device *dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  	char name[IFNAMSIZ];
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
212
  	struct sit_net *sitn = net_generic(net, sit_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213

3a43be3c3   Eric Dumazet   sit: get rid of i...
214
215
216
  	for (tp = __ipip6_bucket(sitn, parms);
  	    (t = rtnl_dereference(*tp)) != NULL;
  	     tp = &t->next) {
8db99e571   Sascha Hlusiak   sit: Fail to crea...
217
  		if (local == t->parms.iph.saddr &&
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
218
219
  		    remote == t->parms.iph.daddr &&
  		    parms->link == t->parms.link) {
8db99e571   Sascha Hlusiak   sit: Fail to crea...
220
221
222
223
224
  			if (create)
  				return NULL;
  			else
  				return t;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
  	}
  	if (!create)
  		goto failed;
a7309cad9   Eric Dumazet   ipv6: sit: better...
228
229
230
  	if (parms->name[0]) {
  		if (!dev_valid_name(parms->name))
  			goto failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  		strlcpy(name, parms->name, IFNAMSIZ);
a7309cad9   Eric Dumazet   ipv6: sit: better...
232
  	} else {
15fc1f705   Eric Dumazet   sit: percpu stats...
233
  		strcpy(name, "sit%d");
a7309cad9   Eric Dumazet   ipv6: sit: better...
234
  	}
c835a6773   Tom Gundersen   net: set name_ass...
235
236
  	dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN,
  			   ipip6_tunnel_setup);
63159f29b   Ian Morris   ipv6: coding styl...
237
  	if (!dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  		return NULL;
7a97146cc   Pavel Emelyanov   [SIT]: Allow to c...
239
  	dev_net_set(dev, net);
2941a4863   Patrick McHardy   [NET]: Convert ne...
240
  	nt = netdev_priv(dev);
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
241

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  	nt->parms = *parms;
f37234160   Nicolas Dichtel   sit: add support ...
243
  	if (ipip6_tunnel_create(dev) < 0)
b37d428b2   Pavel Emelyanov   [INET]: Don't cre...
244
  		goto failed_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  	return nt;
b37d428b2   Pavel Emelyanov   [INET]: Don't cre...
247
  failed_free:
cf124db56   David S. Miller   net: Fix inconsis...
248
  	free_netdev(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
  failed:
  	return NULL;
  }
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
252
253
254
255
  #define for_each_prl_rcu(start)			\
  	for (prl = rcu_dereference(start);	\
  	     prl;				\
  	     prl = rcu_dereference(prl->next))
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
256
  static struct ip_tunnel_prl_entry *
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
257
  __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
258
  {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
259
  	struct ip_tunnel_prl_entry *prl;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
260

ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
261
262
  	for_each_prl_rcu(t->prl)
  		if (prl->addr == addr)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
263
  			break;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
264
  	return prl;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
265
266
  
  }
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
267
268
  static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
  				struct ip_tunnel_prl __user *a)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
269
  {
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
270
  	struct ip_tunnel_prl kprl, *kp;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
271
272
273
  	struct ip_tunnel_prl_entry *prl;
  	unsigned int cmax, c = 0, ca, len;
  	int ret = 0;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
274
275
276
277
  	if (copy_from_user(&kprl, a, sizeof(kprl)))
  		return -EFAULT;
  	cmax = kprl.datalen / sizeof(kprl);
  	if (cmax > 1 && kprl.addr != htonl(INADDR_ANY))
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
278
279
280
281
282
283
  		cmax = 1;
  
  	/* For simple GET or for root users,
  	 * we try harder to allocate.
  	 */
  	kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ?
0ccc22f42   WANG Cong   sit: use __GFP_NO...
284
  		kcalloc(cmax, sizeof(*kp), GFP_KERNEL | __GFP_NOWARN) :
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
285
  		NULL;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
286
  	rcu_read_lock();
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  
  	ca = t->prl_count < cmax ? t->prl_count : cmax;
  
  	if (!kp) {
  		/* We don't try hard to allocate much memory for
  		 * non-root users.
  		 * For root users, retry allocating enough memory for
  		 * the answer.
  		 */
  		kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC);
  		if (!kp) {
  			ret = -ENOMEM;
  			goto out;
  		}
  	}
  
  	c = 0;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
304
  	for_each_prl_rcu(t->prl) {
298bf12dd   Sascha Hlusiak   sit: fix off-by-o...
305
  		if (c >= cmax)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
306
  			break;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
307
  		if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
308
309
310
311
  			continue;
  		kp[c].addr = prl->addr;
  		kp[c].flags = prl->flags;
  		c++;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
312
  		if (kprl.addr != htonl(INADDR_ANY))
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
313
314
315
  			break;
  	}
  out:
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
316
  	rcu_read_unlock();
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
317
318
  
  	len = sizeof(*kp) * c;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
319
320
321
  	ret = 0;
  	if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen))
  		ret = -EFAULT;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
322
323
  
  	kfree(kp);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
324

2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
325
  	return ret;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
326
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
327
328
329
330
  static int
  ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
  {
  	struct ip_tunnel_prl_entry *p;
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
331
  	int err = 0;
0009ae1f5   YOSHIFUJI Hideaki   [IPV6] SIT: Disal...
332
333
  	if (a->addr == htonl(INADDR_ANY))
  		return -EINVAL;
aac4dddc3   Eric Dumazet   ipv6: get rid of ...
334
  	ASSERT_RTNL();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
335

3a43be3c3   Eric Dumazet   sit: get rid of i...
336
  	for (p = rtnl_dereference(t->prl); p; p = rtnl_dereference(p->next)) {
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
337
  		if (p->addr == a->addr) {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
338
339
340
341
  			if (chg) {
  				p->flags = a->flags;
  				goto out;
  			}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
342
343
  			err = -EEXIST;
  			goto out;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
344
345
  		}
  	}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
346
347
348
349
  	if (chg) {
  		err = -ENXIO;
  		goto out;
  	}
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
350
351
  
  	p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
352
353
354
355
  	if (!p) {
  		err = -ENOBUFS;
  		goto out;
  	}
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
356

fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
357
  	p->next = t->prl;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
358
359
  	p->addr = a->addr;
  	p->flags = a->flags;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
360
  	t->prl_count++;
cf778b00e   Eric Dumazet   net: reintroduce ...
361
  	rcu_assign_pointer(t->prl, p);
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
362
  out:
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
363
  	return err;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
364
  }
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
365
366
367
368
369
370
  static void prl_list_destroy_rcu(struct rcu_head *head)
  {
  	struct ip_tunnel_prl_entry *p, *n;
  
  	p = container_of(head, struct ip_tunnel_prl_entry, rcu_head);
  	do {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
371
  		n = rcu_dereference_protected(p->next, 1);
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
372
373
374
375
  		kfree(p);
  		p = n;
  	} while (p);
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
376
377
378
  static int
  ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
  {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
379
380
  	struct ip_tunnel_prl_entry *x;
  	struct ip_tunnel_prl_entry __rcu **p;
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
381
  	int err = 0;
aac4dddc3   Eric Dumazet   ipv6: get rid of ...
382
  	ASSERT_RTNL();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
383

0009ae1f5   YOSHIFUJI Hideaki   [IPV6] SIT: Disal...
384
  	if (a && a->addr != htonl(INADDR_ANY)) {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
385
386
387
388
  		for (p = &t->prl;
  		     (x = rtnl_dereference(*p)) != NULL;
  		     p = &x->next) {
  			if (x->addr == a->addr) {
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
389
  				*p = x->next;
11c476f31   Paul E. McKenney   net,rcu: convert ...
390
  				kfree_rcu(x, rcu_head);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
391
  				t->prl_count--;
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
392
  				goto out;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
393
394
  			}
  		}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
395
  		err = -ENXIO;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
396
  	} else {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
397
398
  		x = rtnl_dereference(t->prl);
  		if (x) {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
399
  			t->prl_count = 0;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
400
401
  			call_rcu(&x->rcu_head, prl_list_destroy_rcu);
  			t->prl = NULL;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
402
403
  		}
  	}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
404
  out:
4b2796017   Sascha Hlusiak   sit: ipip6_tunnel...
405
  	return err;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
406
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
407
  static int
b71d1d426   Eric Dumazet   inet: constify ip...
408
  isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
409
  {
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
410
  	struct ip_tunnel_prl_entry *p;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
411
  	int ok = 1;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
412
  	rcu_read_lock();
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
413
  	p = __ipip6_tunnel_locate_prl(t, iph->saddr);
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
414
  	if (p) {
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
415
  		if (p->flags & PRL_DEFAULT)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
416
417
418
419
  			skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT;
  		else
  			skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
  	} else {
b71d1d426   Eric Dumazet   inet: constify ip...
420
  		const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
421
422
  		if (ipv6_addr_is_isatap(addr6) &&
  		    (addr6->s6_addr32[3] == iph->saddr) &&
52eeeb848   YOSHIFUJI Hideaki   [IPV6]: Unify ip6...
423
  		    ipv6_chk_prefix(addr6, t->dev))
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
424
425
426
427
  			skb->ndisc_nodetype = NDISC_NODETYPE_HOST;
  		else
  			ok = 0;
  	}
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
428
  	rcu_read_unlock();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
429
430
  	return ok;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
  static void ipip6_tunnel_uninit(struct net_device *dev)
  {
5e6700b3b   Nicolas Dichtel   sit: add support ...
433
434
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct sit_net *sitn = net_generic(tunnel->net, sit_net_id);
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
435

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
436
  	if (dev == sitn->fb_tunnel_dev) {
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
437
  		RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	} else {
5e6700b3b   Nicolas Dichtel   sit: add support ...
439
440
  		ipip6_tunnel_unlink(sitn, tunnel);
  		ipip6_tunnel_del_prl(tunnel, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  	}
e09acddf8   Paolo Abeni   ip_tunnel: replac...
442
  	dst_cache_reset(&tunnel->dst_cache);
3a43be3c3   Eric Dumazet   sit: get rid of i...
443
  	dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  }
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
445
  static int ipip6_err(struct sk_buff *skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  {
b71d1d426   Eric Dumazet   inet: constify ip...
447
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
448
449
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
450
  	unsigned int data_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  	struct ip_tunnel *t;
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
452
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
  
  	switch (type) {
  	default:
  	case ICMP_PARAMETERPROB:
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
457
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
  
  	case ICMP_DEST_UNREACH:
  		switch (code) {
  		case ICMP_SR_FAILED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  			/* Impossible event. */
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
463
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
469
470
471
472
473
  		default:
  			/* All others are translated to HOST_UNREACH.
  			   rfc2003 contains "deep thoughts" about NET_UNREACH,
  			   I believe they are just ether pollution. --ANK
  			 */
  			break;
  		}
  		break;
  	case ICMP_TIME_EXCEEDED:
  		if (code != ICMP_EXC_TTL)
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
474
  			return 0;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
475
  		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  		break;
ec18d9a26   David S. Miller   ipv6: Add redirec...
477
478
  	case ICMP_REDIRECT:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  	}
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
480
  	err = -ENOENT;
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
481
482
483
484
  	t = ipip6_tunnel_lookup(dev_net(skb->dev),
  				skb->dev,
  				iph->daddr,
  				iph->saddr);
63159f29b   Ian Morris   ipv6: coding styl...
485
  	if (!t)
363933955   David S. Miller   ipv4: Handle PMTU...
486
487
488
489
  		goto out;
  
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
  		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
d5d8760b7   Simon Horman   sit: correct IP p...
490
  				 t->parms.link, 0, iph->protocol, 0);
363933955   David S. Miller   ipv4: Handle PMTU...
491
492
493
  		err = 0;
  		goto out;
  	}
ec18d9a26   David S. Miller   ipv6: Add redirec...
494
  	if (type == ICMP_REDIRECT) {
2346829e6   Dmitry Popov   ipip, sit: fix ip...
495
  		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
d5d8760b7   Simon Horman   sit: correct IP p...
496
  			      iph->protocol, 0);
ec18d9a26   David S. Miller   ipv6: Add redirec...
497
498
499
  		err = 0;
  		goto out;
  	}
363933955   David S. Miller   ipv4: Handle PMTU...
500

2d7a3b276   Eric Dumazet   ipv6: translate I...
501
  	err = 0;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
502
  	if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  		goto out;
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
504

2d7a3b276   Eric Dumazet   ipv6: translate I...
505
  	if (t->parms.iph.daddr == 0)
ca15a078b   Oussama Ghorbel   sit: generate icm...
506
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
  		goto out;
bb80087a9   Wei Yongjun   sit: used time_be...
509
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
  out:
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
515
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  }
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
517
518
519
520
521
522
523
524
  static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
  				  const struct in6_addr *v6addr)
  {
  	__be32 v4embed = 0;
  	if (check_6rd(tunnel, v6addr, &v4embed) && v4addr != v4embed)
  		return true;
  	return false;
  }
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  /* Checks if an address matches an address on the tunnel interface.
   * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
   * Long story:
   * This function is called after we considered the packet as spoofed
   * in is_spoofed_6rd.
   * We may have a router that is doing NAT for proto 41 packets
   * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
   * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
   * function will return true, dropping the packet.
   * But, we can still check if is spoofed against the IP
   * addresses associated with the interface.
   */
  static bool only_dnatted(const struct ip_tunnel *tunnel,
  	const struct in6_addr *v6dst)
  {
  	int prefix_len;
  
  #ifdef CONFIG_IPV6_SIT_6RD
  	prefix_len = tunnel->ip6rd.prefixlen + 32
  		- tunnel->ip6rd.relay_prefixlen;
  #else
  	prefix_len = 48;
  #endif
  	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
  }
  
  /* Returns true if a packet is spoofed */
  static bool packet_is_spoofed(struct sk_buff *skb,
  			      const struct iphdr *iph,
  			      struct ip_tunnel *tunnel)
  {
  	const struct ipv6hdr *ipv6h;
  
  	if (tunnel->dev->priv_flags & IFF_ISATAP) {
  		if (!isatap_chksrc(skb, iph, tunnel))
  			return true;
  
  		return false;
  	}
  
  	if (tunnel->dev->flags & IFF_POINTOPOINT)
  		return false;
  
  	ipv6h = ipv6_hdr(skb);
  
  	if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
  		net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c
  ",
  				     &iph->saddr, &ipv6h->saddr,
  				     &iph->daddr, &ipv6h->daddr);
  		return true;
  	}
  
  	if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
  		return false;
  
  	if (only_dnatted(tunnel, &ipv6h->daddr))
  		return false;
  
  	net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c
  ",
  			     &iph->saddr, &ipv6h->saddr,
  			     &iph->daddr, &ipv6h->daddr);
  	return true;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
  static int ipip6_rcv(struct sk_buff *skb)
  {
1ad759d84   Hannes Frederic Sowa   ipv6: remove unne...
592
  	const struct iphdr *iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  	struct ip_tunnel *tunnel;
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
594
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595

4fddbf5d7   Sascha Hlusiak   sit: strictly res...
596
597
  	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
  				     iph->saddr, iph->daddr);
53b24b8f9   Ian Morris   ipv6: coding styl...
598
  	if (tunnel) {
8f84985fe   Li RongQing   net: unify the pc...
599
  		struct pcpu_sw_netstats *tstats;
15fc1f705   Eric Dumazet   sit: percpu stats...
600

32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
601
602
603
  		if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
  		    tunnel->parms.iph.protocol != 0)
  			goto out;
b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
604
  		skb->mac_header = skb->network_header;
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
605
  		skb_reset_network_header(skb);
8cdfab8a4   Patrick McHardy   [IPV4]: reset IPC...
606
  		IPCB(skb)->flags = 0;
a09a4c8dd   Jesse Gross   tunnels: Remove e...
607
  		skb->dev = tunnel->dev;
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
608

7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
609
610
611
  		if (packet_is_spoofed(skb, iph, tunnel)) {
  			tunnel->dev->stats.rx_errors++;
  			goto out;
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
612
  		}
a09a4c8dd   Jesse Gross   tunnels: Remove e...
613
614
615
  		if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
  		    !net_eq(tunnel->net, dev_net(tunnel->dev))))
  			goto out;
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
616
617
618
619
620
621
622
623
624
625
626
627
  
  		err = IP_ECN_decapsulate(iph, skb);
  		if (unlikely(err)) {
  			if (log_ecn_error)
  				net_info_ratelimited("non-ECT from %pI4 with TOS=%#x
  ",
  						     &iph->saddr, iph->tos);
  			if (err > 1) {
  				++tunnel->dev->stats.rx_frame_errors;
  				++tunnel->dev->stats.rx_errors;
  				goto out;
  			}
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
628
  		}
d19d56ddc   Eric Dumazet   net: Introduce sk...
629

15fc1f705   Eric Dumazet   sit: percpu stats...
630
  		tstats = this_cpu_ptr(tunnel->dev->tstats);
c3ac17cd6   Li RongQing   ipv6: fix the use...
631
  		u64_stats_update_begin(&tstats->syncp);
15fc1f705   Eric Dumazet   sit: percpu stats...
632
633
  		tstats->rx_packets++;
  		tstats->rx_bytes += skb->len;
c3ac17cd6   Li RongQing   ipv6: fix the use...
634
  		u64_stats_update_end(&tstats->syncp);
15fc1f705   Eric Dumazet   sit: percpu stats...
635

caf586e5f   Eric Dumazet   net: add a core n...
636
  		netif_rx(skb);
8990f468a   Eric Dumazet   net: rx_dropped a...
637

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
  		return 0;
  	}
6dcdd1b36   David McCullough   net/ipv6/sit.c: r...
640
  	/* no tunnel matched,  let upstream know, ipsec may handle it */
6dcdd1b36   David McCullough   net/ipv6/sit.c: r...
641
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  out:
36ca34cc3   David S. Miller   sit: Add missing ...
643
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
  	return 0;
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
646
  static const struct tnl_ptk_info ipip_tpi = {
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
647
648
649
  	/* no tunnel info required for ipip. */
  	.proto = htons(ETH_P_IP),
  };
49dbe7ae2   Simon Horman   sit: support MPLS...
650
651
652
653
654
655
656
657
  #if IS_ENABLED(CONFIG_MPLS)
  static const struct tnl_ptk_info mplsip_tpi = {
  	/* no tunnel info required for mplsip. */
  	.proto = htons(ETH_P_MPLS_UC),
  };
  #endif
  
  static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
658
  {
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
659
  	const struct iphdr *iph;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
660
  	struct ip_tunnel *tunnel;
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
661
  	iph = ip_hdr(skb);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
662
663
  	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
  				     iph->saddr, iph->daddr);
53b24b8f9   Ian Morris   ipv6: coding styl...
664
  	if (tunnel) {
49dbe7ae2   Simon Horman   sit: support MPLS...
665
666
667
  		const struct tnl_ptk_info *tpi;
  
  		if (tunnel->parms.iph.protocol != ipproto &&
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
668
669
670
671
672
  		    tunnel->parms.iph.protocol != 0)
  			goto drop;
  
  		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  			goto drop;
49dbe7ae2   Simon Horman   sit: support MPLS...
673
674
675
676
677
678
679
  #if IS_ENABLED(CONFIG_MPLS)
  		if (ipproto == IPPROTO_MPLS)
  			tpi = &mplsip_tpi;
  		else
  #endif
  			tpi = &ipip_tpi;
  		if (iptunnel_pull_header(skb, 0, tpi->proto, false))
737e828bd   Li Hongjun   ipv4 tunnels: fix...
680
  			goto drop;
49dbe7ae2   Simon Horman   sit: support MPLS...
681
  		return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
682
683
684
685
686
687
688
689
  	}
  
  	return 1;
  
  drop:
  	kfree_skb(skb);
  	return 0;
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
690
691
692
693
694
695
696
697
698
699
700
  static int ipip_rcv(struct sk_buff *skb)
  {
  	return sit_tunnel_rcv(skb, IPPROTO_IPIP);
  }
  
  #if IS_ENABLED(CONFIG_MPLS)
  static int mplsip_rcv(struct sk_buff *skb)
  {
  	return sit_tunnel_rcv(skb, IPPROTO_MPLS);
  }
  #endif
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
701
  /*
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
702
703
   * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
   * stores the embedded IPv4 address in v4dst and returns true.
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
704
   */
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
705
706
  static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
  		      __be32 *v4dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  {
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
708
709
710
  #ifdef CONFIG_IPV6_SIT_6RD
  	if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix,
  			      tunnel->ip6rd.prefixlen)) {
3a43be3c3   Eric Dumazet   sit: get rid of i...
711
  		unsigned int pbw0, pbi0;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
712
713
714
715
716
  		int pbi1;
  		u32 d;
  
  		pbw0 = tunnel->ip6rd.prefixlen >> 5;
  		pbi0 = tunnel->ip6rd.prefixlen & 0x1f;
e7db38c38   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Fix 6rd...
717
  		d = (ntohl(v6dst->s6_addr32[pbw0]) << pbi0) >>
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
718
719
720
721
  		    tunnel->ip6rd.relay_prefixlen;
  
  		pbi1 = pbi0 - tunnel->ip6rd.relay_prefixlen;
  		if (pbi1 > 0)
e7db38c38   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Fix 6rd...
722
  			d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >>
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
723
  			     (32 - pbi1);
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
724
725
  		*v4dst = tunnel->ip6rd.relay_prefix | htonl(d);
  		return true;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
726
727
  	}
  #else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  	if (v6dst->s6_addr16[0] == htons(0x2002)) {
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
729
  		/* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
730
731
  		memcpy(v4dst, &v6dst->s6_addr16[1], 4);
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  	}
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
733
  #endif
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
734
735
736
737
738
739
740
741
  	return false;
  }
  
  static inline __be32 try_6rd(struct ip_tunnel *tunnel,
  			     const struct in6_addr *v6dst)
  {
  	__be32 dst = 0;
  	check_6rd(tunnel, v6dst, &dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
747
748
  	return dst;
  }
  
  /*
   *	This function assumes it is being called from dev_queue_xmit()
   *	and that skb is filled properly by that function.
   */
6fef4c0c8   Stephen Hemminger   netdev: convert p...
749
750
  static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
  				     struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
752
  	struct ip_tunnel *tunnel = netdev_priv(dev);
b71d1d426   Eric Dumazet   inet: constify ip...
753
754
  	const struct iphdr  *tiph = &tunnel->parms.iph;
  	const struct ipv6hdr *iph6 = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  	u8     tos = tunnel->parms.iph.tos;
292f4f3ce   Herbert Xu   sit: Clean up DF ...
756
  	__be16 df = tiph->frag_off;
67ba4152e   Ian Morris   ipv6: White-space...
757
758
759
  	struct rtable *rt;		/* Route to the other host */
  	struct net_device *tdev;	/* Device to other host */
  	unsigned int max_headroom;	/* The extra header space needed */
e69a4adc6   Al Viro   [IPV6]: Misc endi...
760
  	__be32 dst = tiph->daddr;
31e4543db   David S. Miller   ipv4: Make caller...
761
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  	int    mtu;
b71d1d426   Eric Dumazet   inet: constify ip...
763
  	const struct in6_addr *addr6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  	int addr_type;
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
765
  	u8 ttl;
14909664e   Tom Herbert   sit: Setup and TX...
766
767
  	u8 protocol = IPPROTO_IPV6;
  	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768

c2bceb3d7   Lionel Elie Mamane   sit tunnels: prop...
769
770
  	if (tos == 1)
  		tos = ipv6_get_dsfield(iph6);
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
771
772
773
  	/* ISATAP (RFC4214) - must come before 6to4 */
  	if (dev->priv_flags & IFF_ISATAP) {
  		struct neighbour *neigh = NULL;
1e2927b08   David S. Miller   ipv6: sit: Conver...
774
  		bool do_tx_error = false;
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
775

adf30907d   Eric Dumazet   net: skb->dst acc...
776
  		if (skb_dst(skb))
1e2927b08   David S. Miller   ipv6: sit: Conver...
777
  			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
778

63159f29b   Ian Morris   ipv6: coding styl...
779
  		if (!neigh) {
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
780
781
  			net_dbg_ratelimited("nexthop == NULL
  ");
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
782
783
  			goto tx_error;
  		}
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
784
  		addr6 = (const struct in6_addr *)&neigh->primary_key;
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
785
786
787
788
789
790
  		addr_type = ipv6_addr_type(addr6);
  
  		if ((addr_type & IPV6_ADDR_UNICAST) &&
  		     ipv6_addr_is_isatap(addr6))
  			dst = addr6->s6_addr32[3];
  		else
1e2927b08   David S. Miller   ipv6: sit: Conver...
791
792
793
794
  			do_tx_error = true;
  
  		neigh_release(neigh);
  		if (do_tx_error)
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
795
796
  			goto tx_error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  	if (!dst)
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
798
  		dst = try_6rd(tunnel, &iph6->daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
801
  
  	if (!dst) {
  		struct neighbour *neigh = NULL;
1e2927b08   David S. Miller   ipv6: sit: Conver...
802
  		bool do_tx_error = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803

adf30907d   Eric Dumazet   net: skb->dst acc...
804
  		if (skb_dst(skb))
1e2927b08   David S. Miller   ipv6: sit: Conver...
805
  			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806

63159f29b   Ian Morris   ipv6: coding styl...
807
  		if (!neigh) {
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
808
809
  			net_dbg_ratelimited("nexthop == NULL
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
  			goto tx_error;
  		}
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
812
  		addr6 = (const struct in6_addr *)&neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
815
  		addr_type = ipv6_addr_type(addr6);
  
  		if (addr_type == IPV6_ADDR_ANY) {
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
816
  			addr6 = &ipv6_hdr(skb)->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  			addr_type = ipv6_addr_type(addr6);
  		}
1e2927b08   David S. Miller   ipv6: sit: Conver...
819
820
821
822
  		if ((addr_type & IPV6_ADDR_COMPATv4) != 0)
  			dst = addr6->s6_addr32[3];
  		else
  			do_tx_error = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823

1e2927b08   David S. Miller   ipv6: sit: Conver...
824
825
826
  		neigh_release(neigh);
  		if (do_tx_error)
  			goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
828
829
830
831
832
  	flowi4_init_output(&fl4, tunnel->parms.link, tunnel->fwmark,
  			   RT_TOS(tos), RT_SCOPE_UNIVERSE, IPPROTO_IPV6,
  			   0, dst, tiph->saddr, 0, 0,
  			   sock_net_uid(tunnel->net, NULL));
  	rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
78fbfd8a6   David S. Miller   ipv4: Create and ...
833
834
835
  	if (IS_ERR(rt)) {
  		dev->stats.tx_carrier_errors++;
  		goto tx_error_icmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
838
  	}
  	if (rt->rt_type != RTN_UNICAST) {
  		ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
839
  		dev->stats.tx_carrier_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
  		goto tx_error_icmp;
  	}
d8d1f30b9   Changli Gao   net-next: remove ...
842
  	tdev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
  
  	if (tdev == dev) {
  		ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
846
  		dev->stats.collisions++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
848
  		goto tx_error;
  	}
7e13318da   Tom Herbert   net: define gso t...
849
  	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) {
14909664e   Tom Herbert   sit: Setup and TX...
850
  		ip_rt_put(rt);
aed069df0   Alexander Duyck   ip_tunnel_core: i...
851
  		goto tx_error;
14909664e   Tom Herbert   sit: Setup and TX...
852
  	}
292f4f3ce   Herbert Xu   sit: Clean up DF ...
853
  	if (df) {
14909664e   Tom Herbert   sit: Setup and TX...
854
  		mtu = dst_mtu(&rt->dst) - t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855

292f4f3ce   Herbert Xu   sit: Clean up DF ...
856
  		if (mtu < 68) {
15fc1f705   Eric Dumazet   sit: percpu stats...
857
  			dev->stats.collisions++;
292f4f3ce   Herbert Xu   sit: Clean up DF ...
858
859
860
  			ip_rt_put(rt);
  			goto tx_error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861

292f4f3ce   Herbert Xu   sit: Clean up DF ...
862
863
864
865
  		if (mtu < IPV6_MIN_MTU) {
  			mtu = IPV6_MIN_MTU;
  			df = 0;
  		}
6a3c946b2   Nicolas Dichtel   net: don't call u...
866
867
  		if (tunnel->parms.iph.daddr)
  			skb_dst_update_pmtu(skb, mtu);
292f4f3ce   Herbert Xu   sit: Clean up DF ...
868

58a478244   Eric Dumazet   ipv6: sit: update...
869
  		if (skb->len > mtu && !skb_is_gso(skb)) {
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
870
  			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
292f4f3ce   Herbert Xu   sit: Clean up DF ...
871
872
873
  			ip_rt_put(rt);
  			goto tx_error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
876
  	}
  
  	if (tunnel->err_count > 0) {
bb80087a9   Wei Yongjun   sit: used time_be...
877
878
  		if (time_before(jiffies,
  				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
884
885
886
887
  			tunnel->err_count--;
  			dst_link_failure(skb);
  		} else
  			tunnel->err_count = 0;
  	}
  
  	/*
  	 * Okay, now see if we can stuff it in the buffer as-is.
  	 */
14909664e   Tom Herbert   sit: Setup and TX...
888
  	max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889

cfbba49d8   Patrick McHardy   [NET]: Avoid copy...
890
891
  	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
  	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
  		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
  		if (!new_skb) {
  			ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
895
  			dev->stats.tx_dropped++;
66028310a   Gao feng   sit: use kfree_sk...
896
  			kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
897
  			return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
900
901
902
  		}
  		if (skb->sk)
  			skb_set_owner_w(new_skb, skb->sk);
  		dev_kfree_skb(skb);
  		skb = new_skb;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
903
  		iph6 = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
  	}
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
905
906
907
908
  	ttl = tiph->ttl;
  	if (ttl == 0)
  		ttl = iph6->hop_limit;
  	tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909

14909664e   Tom Herbert   sit: Setup and TX...
910
  	if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) {
6a9eadccf   Li RongQing   ipv6: release dst...
911
  		ip_rt_put(rt);
14909664e   Tom Herbert   sit: Setup and TX...
912
  		goto tx_error;
6a9eadccf   Li RongQing   ipv6: release dst...
913
  	}
3d483058c   Hannes Frederic Sowa   ipv6: wire up skb...
914

469471cdf   Tom Herbert   sit: Set inner IP...
915
  	skb_set_inner_ipproto(skb, IPPROTO_IPV6);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
916
917
  	iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
  		      df, !net_eq(tunnel->net, dev_net(dev)));
6ed106549   Patrick McHardy   net: use NETDEV_T...
918
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
  
  tx_error_icmp:
  	dst_link_failure(skb);
  tx_error:
66028310a   Gao feng   sit: use kfree_sk...
923
  	kfree_skb(skb);
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
924
  	dev->stats.tx_errors++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
925
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
927
928
  static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
  				     struct net_device *dev, u8 ipproto)
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
929
930
931
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	const struct iphdr  *tiph = &tunnel->parms.iph;
7e13318da   Tom Herbert   net: define gso t...
932
  	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
aed069df0   Alexander Duyck   ip_tunnel_core: i...
933
  		goto tx_error;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
934

49dbe7ae2   Simon Horman   sit: support MPLS...
935
  	skb_set_inner_ipproto(skb, ipproto);
469471cdf   Tom Herbert   sit: Set inner IP...
936

49dbe7ae2   Simon Horman   sit: support MPLS...
937
  	ip_tunnel_xmit(skb, dev, tiph, ipproto);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
938
  	return NETDEV_TX_OK;
aed069df0   Alexander Duyck   ip_tunnel_core: i...
939
940
  tx_error:
  	kfree_skb(skb);
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
941
942
  	dev->stats.tx_errors++;
  	return NETDEV_TX_OK;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
943
944
945
946
947
948
949
  }
  
  static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
  				   struct net_device *dev)
  {
  	switch (skb->protocol) {
  	case htons(ETH_P_IP):
49dbe7ae2   Simon Horman   sit: support MPLS...
950
  		sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
951
952
953
954
  		break;
  	case htons(ETH_P_IPV6):
  		ipip6_tunnel_xmit(skb, dev);
  		break;
49dbe7ae2   Simon Horman   sit: support MPLS...
955
956
957
958
959
  #if IS_ENABLED(CONFIG_MPLS)
  	case htons(ETH_P_MPLS_UC):
  		sit_tunnel_xmit__(skb, dev, IPPROTO_MPLS);
  		break;
  #endif
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
960
961
962
963
964
965
966
967
  	default:
  		goto tx_err;
  	}
  
  	return NETDEV_TX_OK;
  
  tx_err:
  	dev->stats.tx_errors++;
66028310a   Gao feng   sit: use kfree_sk...
968
  	kfree_skb(skb);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
969
970
971
  	return NETDEV_TX_OK;
  
  }
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
972
973
974
975
  static void ipip6_tunnel_bind_dev(struct net_device *dev)
  {
  	struct net_device *tdev = NULL;
  	struct ip_tunnel *tunnel;
b71d1d426   Eric Dumazet   inet: constify ip...
976
  	const struct iphdr *iph;
31e4543db   David S. Miller   ipv4: Make caller...
977
  	struct flowi4 fl4;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
978
979
980
981
982
  
  	tunnel = netdev_priv(dev);
  	iph = &tunnel->parms.iph;
  
  	if (iph->daddr) {
5e6700b3b   Nicolas Dichtel   sit: add support ...
983
984
  		struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4,
  							  NULL,
78fbfd8a6   David S. Miller   ipv4: Create and ...
985
986
987
988
989
  							  iph->daddr, iph->saddr,
  							  0, 0,
  							  IPPROTO_IPV6,
  							  RT_TOS(iph->tos),
  							  tunnel->parms.link);
b23dd4fe4   David S. Miller   ipv4: Make output...
990
991
  
  		if (!IS_ERR(rt)) {
d8d1f30b9   Changli Gao   net-next: remove ...
992
  			tdev = rt->dst.dev;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
993
994
995
996
997
998
  			ip_rt_put(rt);
  		}
  		dev->flags |= IFF_POINTOPOINT;
  	}
  
  	if (!tdev && tunnel->parms.link)
5e6700b3b   Nicolas Dichtel   sit: add support ...
999
  		tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1000
1001
  
  	if (tdev) {
14909664e   Tom Herbert   sit: Setup and TX...
1002
  		int t_hlen = tunnel->hlen + sizeof(struct iphdr);
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1003
  		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
14909664e   Tom Herbert   sit: Setup and TX...
1004
  		dev->mtu = tdev->mtu - t_hlen;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1005
1006
1007
  		if (dev->mtu < IPV6_MIN_MTU)
  			dev->mtu = IPV6_MIN_MTU;
  	}
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1008
  }
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1009
1010
  static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p,
  				__u32 fwmark)
f37234160   Nicolas Dichtel   sit: add support ...
1011
  {
5e6700b3b   Nicolas Dichtel   sit: add support ...
1012
  	struct net *net = t->net;
f37234160   Nicolas Dichtel   sit: add support ...
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  	struct sit_net *sitn = net_generic(net, sit_net_id);
  
  	ipip6_tunnel_unlink(sitn, t);
  	synchronize_net();
  	t->parms.iph.saddr = p->iph.saddr;
  	t->parms.iph.daddr = p->iph.daddr;
  	memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
  	memcpy(t->dev->broadcast, &p->iph.daddr, 4);
  	ipip6_tunnel_link(sitn, t);
  	t->parms.iph.ttl = p->iph.ttl;
  	t->parms.iph.tos = p->iph.tos;
dacf12738   Hangbin Liu   sit: update frag_...
1024
  	t->parms.iph.frag_off = p->iph.frag_off;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1025
  	if (t->parms.link != p->link || t->fwmark != fwmark) {
f37234160   Nicolas Dichtel   sit: add support ...
1026
  		t->parms.link = p->link;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1027
  		t->fwmark = fwmark;
f37234160   Nicolas Dichtel   sit: add support ...
1028
1029
  		ipip6_tunnel_bind_dev(t->dev);
  	}
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1030
  	dst_cache_reset(&t->dst_cache);
f37234160   Nicolas Dichtel   sit: add support ...
1031
1032
  	netdev_state_change(t->dev);
  }
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  #ifdef CONFIG_IPV6_SIT_6RD
  static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
  				   struct ip_tunnel_6rd *ip6rd)
  {
  	struct in6_addr prefix;
  	__be32 relay_prefix;
  
  	if (ip6rd->relay_prefixlen > 32 ||
  	    ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
  		return -EINVAL;
  
  	ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
  	if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
  		return -EINVAL;
  	if (ip6rd->relay_prefixlen)
  		relay_prefix = ip6rd->relay_prefix &
  			       htonl(0xffffffffUL <<
  				     (32 - ip6rd->relay_prefixlen));
  	else
  		relay_prefix = 0;
  	if (relay_prefix != ip6rd->relay_prefix)
  		return -EINVAL;
  
  	t->ip6rd.prefix = prefix;
  	t->ip6rd.relay_prefix = relay_prefix;
  	t->ip6rd.prefixlen = ip6rd->prefixlen;
  	t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1060
  	dst_cache_reset(&t->dst_cache);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1061
1062
1063
1064
  	netdev_state_change(t->dev);
  	return 0;
  }
  #endif
03ff49793   Wei Yongjun   sit: make functio...
1065
  static bool ipip6_valid_ip_proto(u8 ipproto)
49dbe7ae2   Simon Horman   sit: support MPLS...
1066
1067
1068
1069
1070
1071
1072
1073
  {
  	return ipproto == IPPROTO_IPV6 ||
  		ipproto == IPPROTO_IPIP ||
  #if IS_ENABLED(CONFIG_MPLS)
  		ipproto == IPPROTO_MPLS ||
  #endif
  		ipproto == 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
  static int
67ba4152e   Ian Morris   ipv6: White-space...
1075
  ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
  {
  	int err = 0;
  	struct ip_tunnel_parm p;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1079
  	struct ip_tunnel_prl prl;
9aad77c3b   Nicolas Dichtel   sit: use the righ...
1080
1081
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct net *net = t->net;
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
1082
  	struct sit_net *sitn = net_generic(net, sit_net_id);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1083
1084
1085
  #ifdef CONFIG_IPV6_SIT_6RD
  	struct ip_tunnel_6rd ip6rd;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
1088
  
  	switch (cmd) {
  	case SIOCGETTUNNEL:
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1089
1090
1091
  #ifdef CONFIG_IPV6_SIT_6RD
  	case SIOCGET6RD:
  #endif
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1092
  		if (dev == sitn->fb_tunnel_dev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093
1094
1095
1096
  			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
  				err = -EFAULT;
  				break;
  			}
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
1097
  			t = ipip6_tunnel_locate(net, &p, 0);
63159f29b   Ian Morris   ipv6: coding styl...
1098
  			if (!t)
9aad77c3b   Nicolas Dichtel   sit: use the righ...
1099
  				t = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  		}
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1101
1102
1103
1104
1105
1106
1107
1108
1109
  
  		err = -EFAULT;
  		if (cmd == SIOCGETTUNNEL) {
  			memcpy(&p, &t->parms, sizeof(p));
  			if (copy_to_user(ifr->ifr_ifru.ifru_data, &p,
  					 sizeof(p)))
  				goto done;
  #ifdef CONFIG_IPV6_SIT_6RD
  		} else {
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1110
  			ip6rd.prefix = t->ip6rd.prefix;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1111
1112
1113
1114
1115
1116
1117
1118
1119
  			ip6rd.relay_prefix = t->ip6rd.relay_prefix;
  			ip6rd.prefixlen = t->ip6rd.prefixlen;
  			ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
  			if (copy_to_user(ifr->ifr_ifru.ifru_data, &ip6rd,
  					 sizeof(ip6rd)))
  				goto done;
  #endif
  		}
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
1123
1124
  		break;
  
  	case SIOCADDTUNNEL:
  	case SIOCCHGTUNNEL:
  		err = -EPERM;
af31f412c   Eric W. Biederman   net: Allow userns...
1125
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126
1127
1128
1129
1130
1131
1132
  			goto done;
  
  		err = -EFAULT;
  		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  			goto done;
  
  		err = -EINVAL;
49dbe7ae2   Simon Horman   sit: support MPLS...
1133
  		if (!ipip6_valid_ip_proto(p.iph.protocol))
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1134
1135
  			goto done;
  		if (p.iph.version != 4 ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
1138
1139
  		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
  			goto done;
  		if (p.iph.ttl)
  			p.iph.frag_off |= htons(IP_DF);
ca8def148   Pavel Emelyanov   [SIT]: Add net/si...
1140
  		t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1142
  		if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
53b24b8f9   Ian Morris   ipv6: coding styl...
1143
  			if (t) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
  				if (t->dev != dev) {
  					err = -EEXIST;
  					break;
  				}
  			} else {
  				if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
  				    (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
  					err = -EINVAL;
  					break;
  				}
2941a4863   Patrick McHardy   [NET]: Convert ne...
1154
  				t = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
  			}
f9cd5a553   Nicolas Dichtel   sit: always notif...
1156

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1157
  			ipip6_tunnel_update(t, &p, t->fwmark);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
1160
1161
  		}
  
  		if (t) {
  			err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
1165
1166
1167
1168
1169
  			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
  				err = -EFAULT;
  		} else
  			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
  		break;
  
  	case SIOCDELTUNNEL:
  		err = -EPERM;
af31f412c   Eric W. Biederman   net: Allow userns...
1170
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  			goto done;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1172
  		if (dev == sitn->fb_tunnel_dev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
1174
1175
1176
  			err = -EFAULT;
  			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  				goto done;
  			err = -ENOENT;
e5d08d718   Ian Morris   ipv6: coding styl...
1177
  			t = ipip6_tunnel_locate(net, &p, 0);
63159f29b   Ian Morris   ipv6: coding styl...
1178
  			if (!t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
  				goto done;
  			err = -EPERM;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1181
  			if (t == netdev_priv(sitn->fb_tunnel_dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
1184
  				goto done;
  			dev = t->dev;
  		}
22f8cde5b   Stephen Hemminger   [NET]: unregister...
1185
1186
  		unregister_netdevice(dev);
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
  		break;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1188
  	case SIOCGETPRL:
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
1189
1190
1191
  		err = -EINVAL;
  		if (dev == sitn->fb_tunnel_dev)
  			goto done;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
1192
1193
  		err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
  		break;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1194
1195
1196
1197
  	case SIOCADDPRL:
  	case SIOCDELPRL:
  	case SIOCCHGPRL:
  		err = -EPERM;
af31f412c   Eric W. Biederman   net: Allow userns...
1198
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1199
1200
  			goto done;
  		err = -EINVAL;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1201
  		if (dev == sitn->fb_tunnel_dev)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1202
1203
1204
1205
  			goto done;
  		err = -EFAULT;
  		if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
  			goto done;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1206

300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1207
  		switch (cmd) {
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1208
  		case SIOCDELPRL:
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1209
  			err = ipip6_tunnel_del_prl(t, &prl);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1210
1211
1212
  			break;
  		case SIOCADDPRL:
  		case SIOCCHGPRL:
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1213
  			err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1214
1215
  			break;
  		}
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1216
  		dst_cache_reset(&t->dst_cache);
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
1217
  		netdev_state_change(dev);
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1218
  		break;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1219
1220
1221
1222
1223
  #ifdef CONFIG_IPV6_SIT_6RD
  	case SIOCADD6RD:
  	case SIOCCHG6RD:
  	case SIOCDEL6RD:
  		err = -EPERM;
af31f412c   Eric W. Biederman   net: Allow userns...
1224
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1225
1226
1227
1228
1229
1230
  			goto done;
  
  		err = -EFAULT;
  		if (copy_from_user(&ip6rd, ifr->ifr_ifru.ifru_data,
  				   sizeof(ip6rd)))
  			goto done;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1231
  		if (cmd != SIOCDEL6RD) {
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1232
1233
  			err = ipip6_tunnel_update_6rd(t, &ip6rd);
  			if (err < 0)
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1234
  				goto done;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1235
  		} else
e0c939481   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Ensure ...
1236
  			ipip6_tunnel_clone_6rd(dev, sitn);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1237
1238
1239
1240
  
  		err = 0;
  		break;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
1244
1245
1246
1247
  	default:
  		err = -EINVAL;
  	}
  
  done:
  	return err;
  }
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1248
  static const struct net_device_ops ipip6_netdev_ops = {
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
1249
  	.ndo_init	= ipip6_tunnel_init,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1250
  	.ndo_uninit	= ipip6_tunnel_uninit,
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1251
  	.ndo_start_xmit	= sit_tunnel_xmit,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1252
  	.ndo_do_ioctl	= ipip6_tunnel_ioctl,
f61dd388a   Pravin B Shelar   Tunneling: use IP...
1253
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
1254
  	.ndo_get_iflink = ip_tunnel_get_iflink,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1255
  };
15fc1f705   Eric Dumazet   sit: percpu stats...
1256
1257
  static void ipip6_dev_free(struct net_device *dev)
  {
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1258
  	struct ip_tunnel *tunnel = netdev_priv(dev);
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1259
  	dst_cache_destroy(&tunnel->dst_cache);
15fc1f705   Eric Dumazet   sit: percpu stats...
1260
  	free_percpu(dev->tstats);
15fc1f705   Eric Dumazet   sit: percpu stats...
1261
  }
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
1262
1263
1264
1265
1266
  #define SIT_FEATURES (NETIF_F_SG	   | \
  		      NETIF_F_FRAGLIST	   | \
  		      NETIF_F_HIGHDMA	   | \
  		      NETIF_F_GSO_SOFTWARE | \
  		      NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
  static void ipip6_tunnel_setup(struct net_device *dev)
  {
14909664e   Tom Herbert   sit: Setup and TX...
1269
1270
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1271
  	dev->netdev_ops		= &ipip6_netdev_ops;
cf124db56   David S. Miller   net: Fix inconsis...
1272
1273
  	dev->needs_free_netdev	= true;
  	dev->priv_destructor	= ipip6_dev_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
  
  	dev->type		= ARPHRD_SIT;
14909664e   Tom Herbert   sit: Setup and TX...
1276
1277
  	dev->hard_header_len	= LL_MAX_HEADER + t_hlen;
  	dev->mtu		= ETH_DATA_LEN - t_hlen;
b96f9afee   Jarod Wilson   ipv4/6: use core ...
1278
  	dev->min_mtu		= IPV6_MIN_MTU;
f200de49d   Nicolas Dichtel   ip6_tunnel: remov...
1279
  	dev->max_mtu		= IP6_MAX_MTU - t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
  	dev->flags		= IFF_NOARP;
028758788   Eric Dumazet   net: better IFF_X...
1281
  	netif_keep_dst(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
  	dev->addr_len		= 4;
8df40d103   Eric Dumazet   sit: enable lockl...
1283
  	dev->features		|= NETIF_F_LLTX;
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
1284
1285
  	dev->features		|= SIT_FEATURES;
  	dev->hw_features	|= SIT_FEATURES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  }
15fc1f705   Eric Dumazet   sit: percpu stats...
1287
  static int ipip6_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  {
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1289
  	struct ip_tunnel *tunnel = netdev_priv(dev);
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1290
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
1292
  
  	tunnel->dev = dev;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1293
  	tunnel->net = dev_net(dev);
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
1294
  	strcpy(tunnel->parms.name, dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295

8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1296
  	ipip6_tunnel_bind_dev(dev);
1c213bd24   WANG Cong   net: introduce ne...
1297
  	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
15fc1f705   Eric Dumazet   sit: percpu stats...
1298
1299
  	if (!dev->tstats)
  		return -ENOMEM;
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1300
1301
  	err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
  	if (err) {
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1302
  		free_percpu(dev->tstats);
d7426c69a   WANG Cong   sit: fix a double...
1303
  		dev->tstats = NULL;
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1304
  		return err;
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1305
  	}
15fc1f705   Eric Dumazet   sit: percpu stats...
1306
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
  }
4ece90097   Eric Dumazet   sit: fix sit0 per...
1308
  static void __net_init ipip6_fb_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
1310
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
  	struct iphdr *iph = &tunnel->parms.iph;
291821766   Pavel Emelyanov   [SIT]: Make tunne...
1312
1313
  	struct net *net = dev_net(dev);
  	struct sit_net *sitn = net_generic(net, sit_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
1316
1317
1318
1319
1320
  	iph->version		= 4;
  	iph->protocol		= IPPROTO_IPV6;
  	iph->ihl		= 5;
  	iph->ttl		= 64;
  
  	dev_hold(dev);
cf778b00e   Eric Dumazet   net: reintroduce ...
1321
  	rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  }
a8b8a889e   Matthias Schiffer   net: add netlink_...
1323
1324
  static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1325
1326
  {
  	u8 proto;
c2ff682a6   Nicolas Dichtel   sit: fix an oops ...
1327
  	if (!data || !data[IFLA_IPTUN_PROTO])
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1328
1329
1330
  		return 0;
  
  	proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
49dbe7ae2   Simon Horman   sit: support MPLS...
1331
  	if (!ipip6_valid_ip_proto(proto))
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1332
1333
1334
1335
  		return -EINVAL;
  
  	return 0;
  }
f37234160   Nicolas Dichtel   sit: add support ...
1336
  static void ipip6_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1337
1338
  				struct ip_tunnel_parm *parms,
  				__u32 *fwmark)
f37234160   Nicolas Dichtel   sit: add support ...
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.version = 4;
  	parms->iph.protocol = IPPROTO_IPV6;
  	parms->iph.ihl = 5;
  	parms->iph.ttl = 64;
  
  	if (!data)
  		return;
  
  	if (data[IFLA_IPTUN_LINK])
  		parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
  
  	if (data[IFLA_IPTUN_LOCAL])
d440b7206   Nicolas Dichtel   sit: fix sparse w...
1354
  		parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
f37234160   Nicolas Dichtel   sit: add support ...
1355
1356
  
  	if (data[IFLA_IPTUN_REMOTE])
d440b7206   Nicolas Dichtel   sit: fix sparse w...
1357
  		parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
f37234160   Nicolas Dichtel   sit: add support ...
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
  
  	if (data[IFLA_IPTUN_TTL]) {
  		parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
  		if (parms->iph.ttl)
  			parms->iph.frag_off = htons(IP_DF);
  	}
  
  	if (data[IFLA_IPTUN_TOS])
  		parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
  
  	if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
  		parms->iph.frag_off = htons(IP_DF);
  
  	if (data[IFLA_IPTUN_FLAGS])
d440b7206   Nicolas Dichtel   sit: fix sparse w...
1372
  		parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1373
1374
1375
  
  	if (data[IFLA_IPTUN_PROTO])
  		parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1376
1377
  	if (data[IFLA_IPTUN_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
f37234160   Nicolas Dichtel   sit: add support ...
1378
  }
14909664e   Tom Herbert   sit: Setup and TX...
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
  /* This function returns true when ENCAP attributes are present in the nl msg */
  static bool ipip6_netlink_encap_parms(struct nlattr *data[],
  				      struct ip_tunnel_encap *ipencap)
  {
  	bool ret = false;
  
  	memset(ipencap, 0, sizeof(*ipencap));
  
  	if (!data)
  		return ret;
  
  	if (data[IFLA_IPTUN_ENCAP_TYPE]) {
  		ret = true;
  		ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
  	}
  
  	if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
  		ret = true;
  		ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
  	}
  
  	if (data[IFLA_IPTUN_ENCAP_SPORT]) {
  		ret = true;
a409caecb   Eric Dumazet   sit: fix some __b...
1402
  		ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
14909664e   Tom Herbert   sit: Setup and TX...
1403
1404
1405
1406
  	}
  
  	if (data[IFLA_IPTUN_ENCAP_DPORT]) {
  		ret = true;
a409caecb   Eric Dumazet   sit: fix some __b...
1407
  		ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
14909664e   Tom Herbert   sit: Setup and TX...
1408
1409
1410
1411
  	}
  
  	return ret;
  }
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  #ifdef CONFIG_IPV6_SIT_6RD
  /* This function returns true when 6RD attributes are present in the nl msg */
  static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
  				    struct ip_tunnel_6rd *ip6rd)
  {
  	bool ret = false;
  	memset(ip6rd, 0, sizeof(*ip6rd));
  
  	if (!data)
  		return ret;
  
  	if (data[IFLA_IPTUN_6RD_PREFIX]) {
  		ret = true;
67b61f6c1   Jiri Benc   netlink: implemen...
1425
  		ip6rd->prefix = nla_get_in6_addr(data[IFLA_IPTUN_6RD_PREFIX]);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
  	}
  
  	if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
  		ret = true;
  		ip6rd->relay_prefix =
  			nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
  	}
  
  	if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
  		ret = true;
  		ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
  	}
  
  	if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
  		ret = true;
  		ip6rd->relay_prefixlen =
  			nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
  	}
  
  	return ret;
  }
  #endif
f37234160   Nicolas Dichtel   sit: add support ...
1448
  static int ipip6_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
1449
1450
  			 struct nlattr *tb[], struct nlattr *data[],
  			 struct netlink_ext_ack *extack)
f37234160   Nicolas Dichtel   sit: add support ...
1451
1452
1453
  {
  	struct net *net = dev_net(dev);
  	struct ip_tunnel *nt;
14909664e   Tom Herbert   sit: Setup and TX...
1454
  	struct ip_tunnel_encap ipencap;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1455
1456
1457
1458
  #ifdef CONFIG_IPV6_SIT_6RD
  	struct ip_tunnel_6rd ip6rd;
  #endif
  	int err;
f37234160   Nicolas Dichtel   sit: add support ...
1459
1460
  
  	nt = netdev_priv(dev);
14909664e   Tom Herbert   sit: Setup and TX...
1461
1462
1463
1464
1465
1466
  
  	if (ipip6_netlink_encap_parms(data, &ipencap)) {
  		err = ip_tunnel_encap_setup(nt, &ipencap);
  		if (err < 0)
  			return err;
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1467
  	ipip6_netlink_parms(data, &nt->parms, &nt->fwmark);
f37234160   Nicolas Dichtel   sit: add support ...
1468
1469
1470
  
  	if (ipip6_tunnel_locate(net, &nt->parms, 0))
  		return -EEXIST;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1471
1472
1473
  	err = ipip6_tunnel_create(dev);
  	if (err < 0)
  		return err;
d2e2e20bb   Xin Long   sit: fix IFLA_MTU...
1474
1475
  	if (tb[IFLA_MTU]) {
  		u32 mtu = nla_get_u32(tb[IFLA_MTU]);
f200de49d   Nicolas Dichtel   ip6_tunnel: remov...
1476
1477
  		if (mtu >= IPV6_MIN_MTU &&
  		    mtu <= IP6_MAX_MTU - dev->hard_header_len)
d2e2e20bb   Xin Long   sit: fix IFLA_MTU...
1478
1479
  			dev->mtu = mtu;
  	}
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1480
1481
1482
1483
1484
1485
  #ifdef CONFIG_IPV6_SIT_6RD
  	if (ipip6_netlink_6rd_parms(data, &ip6rd))
  		err = ipip6_tunnel_update_6rd(nt, &ip6rd);
  #endif
  
  	return err;
f37234160   Nicolas Dichtel   sit: add support ...
1486
1487
1488
  }
  
  static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
1489
1490
  			    struct nlattr *data[],
  			    struct netlink_ext_ack *extack)
f37234160   Nicolas Dichtel   sit: add support ...
1491
  {
86bd68bfd   Nicolas Dichtel   sit: fix tunnel u...
1492
  	struct ip_tunnel *t = netdev_priv(dev);
f37234160   Nicolas Dichtel   sit: add support ...
1493
  	struct ip_tunnel_parm p;
14909664e   Tom Herbert   sit: Setup and TX...
1494
  	struct ip_tunnel_encap ipencap;
86bd68bfd   Nicolas Dichtel   sit: fix tunnel u...
1495
  	struct net *net = t->net;
f37234160   Nicolas Dichtel   sit: add support ...
1496
  	struct sit_net *sitn = net_generic(net, sit_net_id);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1497
1498
1499
  #ifdef CONFIG_IPV6_SIT_6RD
  	struct ip_tunnel_6rd ip6rd;
  #endif
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1500
  	__u32 fwmark = t->fwmark;
14909664e   Tom Herbert   sit: Setup and TX...
1501
  	int err;
f37234160   Nicolas Dichtel   sit: add support ...
1502
1503
1504
  
  	if (dev == sitn->fb_tunnel_dev)
  		return -EINVAL;
14909664e   Tom Herbert   sit: Setup and TX...
1505
1506
1507
1508
1509
  	if (ipip6_netlink_encap_parms(data, &ipencap)) {
  		err = ip_tunnel_encap_setup(t, &ipencap);
  		if (err < 0)
  			return err;
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1510
  	ipip6_netlink_parms(data, &p, &fwmark);
f37234160   Nicolas Dichtel   sit: add support ...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  
  	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
  	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
  		return -EINVAL;
  
  	t = ipip6_tunnel_locate(net, &p, 0);
  
  	if (t) {
  		if (t->dev != dev)
  			return -EEXIST;
  	} else
  		t = netdev_priv(dev);
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1523
  	ipip6_tunnel_update(t, &p, fwmark);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1524
1525
1526
1527
1528
  
  #ifdef CONFIG_IPV6_SIT_6RD
  	if (ipip6_netlink_6rd_parms(data, &ip6rd))
  		return ipip6_tunnel_update_6rd(t, &ip6rd);
  #endif
f37234160   Nicolas Dichtel   sit: add support ...
1529
1530
  	return 0;
  }
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1531
  static size_t ipip6_get_size(const struct net_device *dev)
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  {
  	return
  		/* IFLA_IPTUN_LINK */
  		nla_total_size(4) +
  		/* IFLA_IPTUN_LOCAL */
  		nla_total_size(4) +
  		/* IFLA_IPTUN_REMOTE */
  		nla_total_size(4) +
  		/* IFLA_IPTUN_TTL */
  		nla_total_size(1) +
  		/* IFLA_IPTUN_TOS */
  		nla_total_size(1) +
a12c9a858   Nicolas Dichtel   sit/rtnl: add mis...
1544
1545
1546
1547
  		/* IFLA_IPTUN_PMTUDISC */
  		nla_total_size(1) +
  		/* IFLA_IPTUN_FLAGS */
  		nla_total_size(2) +
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1548
1549
  		/* IFLA_IPTUN_PROTO */
  		nla_total_size(1) +
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
  #ifdef CONFIG_IPV6_SIT_6RD
  		/* IFLA_IPTUN_6RD_PREFIX */
  		nla_total_size(sizeof(struct in6_addr)) +
  		/* IFLA_IPTUN_6RD_RELAY_PREFIX */
  		nla_total_size(4) +
  		/* IFLA_IPTUN_6RD_PREFIXLEN */
  		nla_total_size(2) +
  		/* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
  		nla_total_size(2) +
  #endif
14909664e   Tom Herbert   sit: Setup and TX...
1560
1561
1562
1563
1564
1565
1566
1567
  		/* IFLA_IPTUN_ENCAP_TYPE */
  		nla_total_size(2) +
  		/* IFLA_IPTUN_ENCAP_FLAGS */
  		nla_total_size(2) +
  		/* IFLA_IPTUN_ENCAP_SPORT */
  		nla_total_size(2) +
  		/* IFLA_IPTUN_ENCAP_DPORT */
  		nla_total_size(2) +
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1568
1569
  		/* IFLA_IPTUN_FWMARK */
  		nla_total_size(4) +
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1570
1571
  		0;
  }
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1572
  static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1573
1574
1575
1576
1577
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct ip_tunnel_parm *parm = &tunnel->parms;
  
  	if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
930345ea6   Jiri Benc   netlink: implemen...
1578
1579
  	    nla_put_in_addr(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
  	    nla_put_in_addr(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1580
  	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
a12c9a858   Nicolas Dichtel   sit/rtnl: add mis...
1581
1582
1583
  	    nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
  	    nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
  		       !!(parm->iph.frag_off & htons(IP_DF))) ||
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1584
  	    nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1585
1586
  	    nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags) ||
  	    nla_put_u32(skb, IFLA_IPTUN_FWMARK, tunnel->fwmark))
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1587
  		goto nla_put_failure;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1588
1589
  
  #ifdef CONFIG_IPV6_SIT_6RD
930345ea6   Jiri Benc   netlink: implemen...
1590
1591
1592
1593
  	if (nla_put_in6_addr(skb, IFLA_IPTUN_6RD_PREFIX,
  			     &tunnel->ip6rd.prefix) ||
  	    nla_put_in_addr(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
  			    tunnel->ip6rd.relay_prefix) ||
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1594
1595
1596
1597
1598
1599
  	    nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
  			tunnel->ip6rd.prefixlen) ||
  	    nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
  			tunnel->ip6rd.relay_prefixlen))
  		goto nla_put_failure;
  #endif
14909664e   Tom Herbert   sit: Setup and TX...
1600
1601
  	if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
  			tunnel->encap.type) ||
a409caecb   Eric Dumazet   sit: fix some __b...
1602
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
14909664e   Tom Herbert   sit: Setup and TX...
1603
  			tunnel->encap.sport) ||
a409caecb   Eric Dumazet   sit: fix some __b...
1604
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
14909664e   Tom Herbert   sit: Setup and TX...
1605
1606
  			tunnel->encap.dport) ||
  	    nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
e1b2cb655   Tom Herbert   fou: Fix typo in ...
1607
  			tunnel->encap.flags))
14909664e   Tom Herbert   sit: Setup and TX...
1608
  		goto nla_put_failure;
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1609
1610
1611
1612
1613
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
f37234160   Nicolas Dichtel   sit: add support ...
1614
1615
1616
1617
1618
1619
1620
1621
  static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
  	[IFLA_IPTUN_LINK]		= { .type = NLA_U32 },
  	[IFLA_IPTUN_LOCAL]		= { .type = NLA_U32 },
  	[IFLA_IPTUN_REMOTE]		= { .type = NLA_U32 },
  	[IFLA_IPTUN_TTL]		= { .type = NLA_U8 },
  	[IFLA_IPTUN_TOS]		= { .type = NLA_U8 },
  	[IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 },
  	[IFLA_IPTUN_FLAGS]		= { .type = NLA_U16 },
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1622
  	[IFLA_IPTUN_PROTO]		= { .type = NLA_U8 },
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1623
1624
1625
1626
1627
1628
  #ifdef CONFIG_IPV6_SIT_6RD
  	[IFLA_IPTUN_6RD_PREFIX]		= { .len = sizeof(struct in6_addr) },
  	[IFLA_IPTUN_6RD_RELAY_PREFIX]	= { .type = NLA_U32 },
  	[IFLA_IPTUN_6RD_PREFIXLEN]	= { .type = NLA_U16 },
  	[IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
  #endif
14909664e   Tom Herbert   sit: Setup and TX...
1629
1630
1631
1632
  	[IFLA_IPTUN_ENCAP_TYPE]		= { .type = NLA_U16 },
  	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
  	[IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 },
  	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1633
  	[IFLA_IPTUN_FWMARK]		= { .type = NLA_U32 },
f37234160   Nicolas Dichtel   sit: add support ...
1634
  };
9434266f2   Willem de Bruijn   sit: fix use afte...
1635
1636
1637
1638
1639
1640
1641
1642
  static void ipip6_dellink(struct net_device *dev, struct list_head *head)
  {
  	struct net *net = dev_net(dev);
  	struct sit_net *sitn = net_generic(net, sit_net_id);
  
  	if (dev != sitn->fb_tunnel_dev)
  		unregister_netdevice_queue(dev, head);
  }
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1643
1644
1645
  static struct rtnl_link_ops sit_link_ops __read_mostly = {
  	.kind		= "sit",
  	.maxtype	= IFLA_IPTUN_MAX,
f37234160   Nicolas Dichtel   sit: add support ...
1646
  	.policy		= ipip6_policy,
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1647
  	.priv_size	= sizeof(struct ip_tunnel),
f37234160   Nicolas Dichtel   sit: add support ...
1648
  	.setup		= ipip6_tunnel_setup,
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1649
  	.validate	= ipip6_validate,
f37234160   Nicolas Dichtel   sit: add support ...
1650
1651
  	.newlink	= ipip6_newlink,
  	.changelink	= ipip6_changelink,
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1652
1653
  	.get_size	= ipip6_get_size,
  	.fill_info	= ipip6_fill_info,
9434266f2   Willem de Bruijn   sit: fix use afte...
1654
  	.dellink	= ipip6_dellink,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1655
  	.get_link_net	= ip_tunnel_get_link_net,
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1656
  };
6dcd814bd   Eric Dumazet   net: struct xfrm_...
1657
  static struct xfrm_tunnel sit_handler __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
1659
  	.handler	=	ipip6_rcv,
  	.err_handler	=	ipip6_err,
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
1660
  	.priority	=	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
  };
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1662
1663
1664
1665
1666
  static struct xfrm_tunnel ipip_handler __read_mostly = {
  	.handler	=	ipip_rcv,
  	.err_handler	=	ipip6_err,
  	.priority	=	2,
  };
49dbe7ae2   Simon Horman   sit: support MPLS...
1667
1668
1669
1670
1671
1672
1673
  #if IS_ENABLED(CONFIG_MPLS)
  static struct xfrm_tunnel mplsip_handler __read_mostly = {
  	.handler	=	mplsip_rcv,
  	.err_handler	=	ipip6_err,
  	.priority	=	2,
  };
  #endif
9434266f2   Willem de Bruijn   sit: fix use afte...
1674
1675
  static void __net_exit sit_destroy_tunnels(struct net *net,
  					   struct list_head *head)
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1676
  {
9434266f2   Willem de Bruijn   sit: fix use afte...
1677
  	struct sit_net *sitn = net_generic(net, sit_net_id);
5e6700b3b   Nicolas Dichtel   sit: add support ...
1678
  	struct net_device *dev, *aux;
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1679
  	int prio;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1680
1681
1682
  	for_each_netdev_safe(net, dev, aux)
  		if (dev->rtnl_link_ops == &sit_link_ops)
  			unregister_netdevice_queue(dev, head);
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1683
1684
  	for (prio = 1; prio < 4; prio++) {
  		int h;
e87a8f24c   Jiri Kosina   net: resolve symb...
1685
  		for (h = 0; h < IP6_SIT_HASH_SIZE; h++) {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1686
  			struct ip_tunnel *t;
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1687

753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1688
  			t = rtnl_dereference(sitn->tunnels[prio][h]);
53b24b8f9   Ian Morris   ipv6: coding styl...
1689
  			while (t) {
5e6700b3b   Nicolas Dichtel   sit: add support ...
1690
1691
1692
  				/* If dev is in the same netns, it has already
  				 * been added to the list by the previous loop.
  				 */
fc8f999da   Nicolas Dichtel   ipv4 tunnels: use...
1693
  				if (!net_eq(dev_net(t->dev), net))
5e6700b3b   Nicolas Dichtel   sit: add support ...
1694
1695
  					unregister_netdevice_queue(t->dev,
  								   head);
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1696
  				t = rtnl_dereference(t->next);
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1697
  			}
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1698
1699
1700
  		}
  	}
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
1701
  static int __net_init sit_init_net(struct net *net)
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1702
  {
671011720   Eric W. Biederman   net: Simplify ipi...
1703
  	struct sit_net *sitn = net_generic(net, sit_net_id);
72b36015b   Ted Feng   ipip, sit: copy p...
1704
  	struct ip_tunnel *t;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1705
  	int err;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1706

291821766   Pavel Emelyanov   [SIT]: Make tunne...
1707
1708
1709
1710
  	sitn->tunnels[0] = sitn->tunnels_wc;
  	sitn->tunnels[1] = sitn->tunnels_l;
  	sitn->tunnels[2] = sitn->tunnels_r;
  	sitn->tunnels[3] = sitn->tunnels_r_l;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1711
  	sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
c835a6773   Tom Gundersen   net: set name_ass...
1712
  					   NET_NAME_UNKNOWN,
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1713
1714
1715
1716
1717
  					   ipip6_tunnel_setup);
  	if (!sitn->fb_tunnel_dev) {
  		err = -ENOMEM;
  		goto err_alloc_dev;
  	}
be77e5930   Alexey Dobriyan   net: fix tunnels ...
1718
  	dev_net_set(sitn->fb_tunnel_dev, net);
205983c43   Nicolas Dichtel   sit: allow to use...
1719
  	sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1720
1721
1722
1723
  	/* FB netdevice is special: we have one, and only one per netns.
  	 * Allowing to move it to another netns is clearly unsafe.
  	 */
  	sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1724

e5d08d718   Ian Morris   ipv6: coding styl...
1725
1726
  	err = register_netdev(sitn->fb_tunnel_dev);
  	if (err)
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1727
  		goto err_reg_dev;
4ece90097   Eric Dumazet   sit: fix sit0 per...
1728
1729
  	ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
  	ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
72b36015b   Ted Feng   ipip, sit: copy p...
1730
1731
1732
  	t = netdev_priv(sitn->fb_tunnel_dev);
  
  	strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1733
  	return 0;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1734
  err_reg_dev:
dd4080ee5   Eric Dumazet   sit: fix percpu s...
1735
  	ipip6_dev_free(sitn->fb_tunnel_dev);
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1736
  err_alloc_dev:
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1737
1738
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
1739
  static void __net_exit sit_exit_net(struct net *net)
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1740
  {
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1741
  	LIST_HEAD(list);
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1742

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1743
  	rtnl_lock();
9434266f2   Willem de Bruijn   sit: fix use afte...
1744
  	sit_destroy_tunnels(net, &list);
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1745
  	unregister_netdevice_many(&list);
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1746
  	rtnl_unlock();
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1747
1748
1749
1750
1751
  }
  
  static struct pernet_operations sit_net_ops = {
  	.init = sit_init_net,
  	.exit = sit_exit_net,
671011720   Eric W. Biederman   net: Simplify ipi...
1752
1753
  	.id   = &sit_net_id,
  	.size = sizeof(struct sit_net),
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1754
  };
89c894581   Adrian Bunk   [IPV6] net/ipv6/s...
1755
  static void __exit sit_cleanup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756
  {
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1757
  	rtnl_link_unregister(&sit_link_ops);
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
1758
  	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1759
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
49dbe7ae2   Simon Horman   sit: support MPLS...
1760
1761
1762
  #if IS_ENABLED(CONFIG_MPLS)
  	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
  #endif
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1763

671011720   Eric W. Biederman   net: Simplify ipi...
1764
  	unregister_pernet_device(&sit_net_ops);
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
1765
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
  }
89c894581   Adrian Bunk   [IPV6] net/ipv6/s...
1767
  static int __init sit_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
  {
  	int err;
49dbe7ae2   Simon Horman   sit: support MPLS...
1770
1771
  	pr_info("IPv6, IPv4 and MPLS over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772

671011720   Eric W. Biederman   net: Simplify ipi...
1773
  	err = register_pernet_device(&sit_net_ops);
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1774
  	if (err < 0)
d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
1775
1776
1777
  		return err;
  	err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
  	if (err < 0) {
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1778
1779
  		pr_info("%s: can't register ip6ip4
  ", __func__);
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1780
  		goto xfrm_tunnel_failed;
d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
1781
  	}
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1782
1783
1784
1785
1786
1787
  	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
  	if (err < 0) {
  		pr_info("%s: can't register ip4ip4
  ", __func__);
  		goto xfrm_tunnel4_failed;
  	}
49dbe7ae2   Simon Horman   sit: support MPLS...
1788
1789
1790
1791
1792
1793
1794
1795
  #if IS_ENABLED(CONFIG_MPLS)
  	err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
  	if (err < 0) {
  		pr_info("%s: can't register mplsip
  ", __func__);
  		goto xfrm_tunnel_mpls_failed;
  	}
  #endif
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1796
1797
1798
1799
1800
  	err = rtnl_link_register(&sit_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  	return err;
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1802
1803
  
  rtnl_link_failed:
49dbe7ae2   Simon Horman   sit: support MPLS...
1804
1805
1806
1807
  #if IS_ENABLED(CONFIG_MPLS)
  	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
  xfrm_tunnel_mpls_failed:
  #endif
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1808
1809
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
  xfrm_tunnel4_failed:
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1810
1811
1812
1813
  	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
  xfrm_tunnel_failed:
  	unregister_pernet_device(&sit_net_ops);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
  }
989e5b96e   Joerg Roedel   [IPV6]: Seperate ...
1815
1816
1817
  
  module_init(sit_init);
  module_exit(sit_cleanup);
39c850863   Jan Dittmer   [IPV6] sit: Add m...
1818
  MODULE_LICENSE("GPL");
f98f89a01   Tom Gundersen   net: tunnels - en...
1819
  MODULE_ALIAS_RTNL_LINK("sit");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
1820
  MODULE_ALIAS_NETDEV("sit0");