Blame view

net/ipv6/sit.c 46.9 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
  /*
   *	IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT)
   *	Linux INET6 implementation
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
7
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
   *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
   *	Changes:
   * Roger Venning <r.venning@telstra.com>:	6to4 support
   * Nate Thompson <nate@thebog.net>:		6to4 support
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
13
   * Fred Templin <fred.l.templin@boeing.com>:	isatap support
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
   */
f32138319   Joe Perches   net: ipv6: Standa...
15
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/module.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
17
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
  #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: ...
27
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
28
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  #include <linux/init.h>
  #include <linux/netfilter_ipv4.h>
46f25dffb   Kris Katterjohn   [NET]: Change 150...
31
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  
  #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...
46
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
  #include <net/dsfield.h>
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
50
51
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
  
  /*
     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...
58
  #define IP6_SIT_HASH_SIZE  16
e69a4adc6   Al Viro   [IPV6]: Misc endi...
59
  #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60

f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
61
62
63
  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...
64
  static int ipip6_tunnel_init(struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  static void ipip6_tunnel_setup(struct net_device *dev);
15fc1f705   Eric Dumazet   sit: percpu stats...
66
  static void ipip6_dev_free(struct net_device *dev);
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
67
68
  static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
  		      __be32 *v4dst);
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
69
  static struct rtnl_link_ops sit_link_ops __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

c7d03a00b   Alexey Dobriyan   netns: make struc...
71
  static unsigned int sit_net_id __read_mostly;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
72
  struct sit_net {
e87a8f24c   Jiri Kosina   net: resolve symb...
73
74
75
  	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...
76
77
  	struct ip_tunnel __rcu *tunnels_wc[1];
  	struct ip_tunnel __rcu **tunnels[4];
291821766   Pavel Emelyanov   [SIT]: Make tunne...
78

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
79
  	struct net_device *fb_tunnel_dev;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
80
  };
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
81
82
83
84
85
86
  static inline struct sit_net *dev_to_sit_net(struct net_device *dev)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  
  	return net_generic(t->net, sit_net_id);
  }
4543c10de   Eric Dumazet   ipv6 sit: RCU con...
87
88
89
  /*
   * Must be invoked with rcu_read_lock
   */
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
90
  static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net,
3051fbec2   David Ahern   net: sit: Update ...
91
92
93
  					     struct net_device *dev,
  					     __be32 remote, __be32 local,
  					     int sifindex)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  {
3a43be3c3   Eric Dumazet   sit: get rid of i...
95
96
  	unsigned int h0 = HASH(remote);
  	unsigned int h1 = HASH(local);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	struct ip_tunnel *t;
291821766   Pavel Emelyanov   [SIT]: Make tunne...
98
  	struct sit_net *sitn = net_generic(net, sit_net_id);
3051fbec2   David Ahern   net: sit: Update ...
99
  	int ifindex = dev ? dev->ifindex : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

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

cf778b00e   Eric Dumazet   net: reintroduce ...
169
170
  	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
  	rcu_assign_pointer(*tp, t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  }
e0c939481   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Ensure ...
172
  static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
173
174
  {
  #ifdef CONFIG_IPV6_SIT_6RD
e0c939481   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Ensure ...
175
  	struct ip_tunnel *t = netdev_priv(dev);
79134e6ce   Eric Dumazet   net: do not creat...
176
  	if (dev == sitn->fb_tunnel_dev || !sitn->fb_tunnel_dev) {
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
177
178
179
180
181
182
183
184
185
186
  		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 ...
187
188
189
190
191
192
  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...
193
194
  	memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
f37234160   Nicolas Dichtel   sit: add support ...
195

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	return nt;
b37d428b2   Pavel Emelyanov   [INET]: Don't cre...
255
  failed_free:
cf124db56   David S. Miller   net: Fix inconsis...
256
  	free_netdev(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
  failed:
  	return NULL;
  }
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
260
261
262
263
  #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...
264
  static struct ip_tunnel_prl_entry *
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
265
  __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
266
  {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
267
  	struct ip_tunnel_prl_entry *prl;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
268

ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
269
270
  	for_each_prl_rcu(t->prl)
  		if (prl->addr == addr)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
271
  			break;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
272
  	return prl;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
273
274
  
  }
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
275
  static int ipip6_tunnel_get_prl(struct net_device *dev, struct ifreq *ifr)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
276
  {
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
277
278
  	struct ip_tunnel_prl __user *a = ifr->ifr_ifru.ifru_data;
  	struct ip_tunnel *t = netdev_priv(dev);
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
279
  	struct ip_tunnel_prl kprl, *kp;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
280
281
282
  	struct ip_tunnel_prl_entry *prl;
  	unsigned int cmax, c = 0, ca, len;
  	int ret = 0;
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
283
284
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
  		return -EINVAL;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
285
286
287
288
  	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...
289
290
291
292
293
294
  		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...
295
  		kcalloc(cmax, sizeof(*kp), GFP_KERNEL | __GFP_NOWARN) :
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
296
  		NULL;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
297
  	rcu_read_lock();
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  
  	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...
315
  	for_each_prl_rcu(t->prl) {
298bf12dd   Sascha Hlusiak   sit: fix off-by-o...
316
  		if (c >= cmax)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
317
  			break;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
318
  		if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr)
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
319
320
321
322
  			continue;
  		kp[c].addr = prl->addr;
  		kp[c].flags = prl->flags;
  		c++;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
323
  		if (kprl.addr != htonl(INADDR_ANY))
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
324
325
326
  			break;
  	}
  out:
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
327
  	rcu_read_unlock();
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
328
329
  
  	len = sizeof(*kp) * c;
2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
330
331
332
  	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...
333
334
  
  	kfree(kp);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
335

2b4743bd6   YOSHIFUJI Hideaki   ipv6 sit: Avoid e...
336
  	return ret;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
337
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
338
339
340
341
  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...
342
  	int err = 0;
0009ae1f5   YOSHIFUJI Hideaki   [IPV6] SIT: Disal...
343
344
  	if (a->addr == htonl(INADDR_ANY))
  		return -EINVAL;
aac4dddc3   Eric Dumazet   ipv6: get rid of ...
345
  	ASSERT_RTNL();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
346

3a43be3c3   Eric Dumazet   sit: get rid of i...
347
  	for (p = rtnl_dereference(t->prl); p; p = rtnl_dereference(p->next)) {
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
348
  		if (p->addr == a->addr) {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
349
350
351
352
  			if (chg) {
  				p->flags = a->flags;
  				goto out;
  			}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
353
354
  			err = -EEXIST;
  			goto out;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
355
356
  		}
  	}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
357
358
359
360
  	if (chg) {
  		err = -ENXIO;
  		goto out;
  	}
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
361
362
  
  	p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
363
364
365
366
  	if (!p) {
  		err = -ENOBUFS;
  		goto out;
  	}
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
367

fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
368
  	p->next = t->prl;
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
369
370
  	p->addr = a->addr;
  	p->flags = a->flags;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
371
  	t->prl_count++;
cf778b00e   Eric Dumazet   net: reintroduce ...
372
  	rcu_assign_pointer(t->prl, p);
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
373
  out:
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
374
  	return err;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
375
  }
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
376
377
378
379
380
381
  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...
382
  		n = rcu_dereference_protected(p->next, 1);
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
383
384
385
386
  		kfree(p);
  		p = n;
  	} while (p);
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
387
388
389
  static int
  ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
  {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
390
391
  	struct ip_tunnel_prl_entry *x;
  	struct ip_tunnel_prl_entry __rcu **p;
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
392
  	int err = 0;
aac4dddc3   Eric Dumazet   ipv6: get rid of ...
393
  	ASSERT_RTNL();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
394

0009ae1f5   YOSHIFUJI Hideaki   [IPV6] SIT: Disal...
395
  	if (a && a->addr != htonl(INADDR_ANY)) {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
396
397
398
399
  		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...
400
  				*p = x->next;
11c476f31   Paul E. McKenney   net,rcu: convert ...
401
  				kfree_rcu(x, rcu_head);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
402
  				t->prl_count--;
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
403
  				goto out;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
404
405
  			}
  		}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
406
  		err = -ENXIO;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
407
  	} else {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
408
409
  		x = rtnl_dereference(t->prl);
  		if (x) {
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
410
  			t->prl_count = 0;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
411
412
  			call_rcu(&x->rcu_head, prl_list_destroy_rcu);
  			t->prl = NULL;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
413
414
  		}
  	}
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
415
  out:
4b2796017   Sascha Hlusiak   sit: ipip6_tunnel...
416
  	return err;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
417
  }
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  static int ipip6_tunnel_prl_ctl(struct net_device *dev, struct ifreq *ifr,
  		int cmd)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_prl prl;
  	int err;
  
  	if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
  		return -EPERM;
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
  		return -EINVAL;
  
  	if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
  		return -EFAULT;
  
  	switch (cmd) {
  	case SIOCDELPRL:
  		err = ipip6_tunnel_del_prl(t, &prl);
  		break;
  	case SIOCADDPRL:
  	case SIOCCHGPRL:
  		err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
  		break;
  	}
  	dst_cache_reset(&t->dst_cache);
  	netdev_state_change(dev);
  	return err;
  }
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
446
  static int
b71d1d426   Eric Dumazet   inet: constify ip...
447
  isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
448
  {
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
449
  	struct ip_tunnel_prl_entry *p;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
450
  	int ok = 1;
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
451
  	rcu_read_lock();
3fcfa1290   YOSHIFUJI Hideaki   [IPV6] SIT: Fix l...
452
  	p = __ipip6_tunnel_locate_prl(t, iph->saddr);
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
453
  	if (p) {
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
454
  		if (p->flags & PRL_DEFAULT)
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
455
456
457
458
  			skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT;
  		else
  			skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
  	} else {
b71d1d426   Eric Dumazet   inet: constify ip...
459
  		const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr;
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
460
461
  		if (ipv6_addr_is_isatap(addr6) &&
  		    (addr6->s6_addr32[3] == iph->saddr) &&
52eeeb848   YOSHIFUJI Hideaki   [IPV6]: Unify ip6...
462
  		    ipv6_chk_prefix(addr6, t->dev))
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
463
464
465
466
  			skb->ndisc_nodetype = NDISC_NODETYPE_HOST;
  		else
  			ok = 0;
  	}
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
467
  	rcu_read_unlock();
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
468
469
  	return ok;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
  static void ipip6_tunnel_uninit(struct net_device *dev)
  {
5e6700b3b   Nicolas Dichtel   sit: add support ...
472
473
  	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...
474

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
475
  	if (dev == sitn->fb_tunnel_dev) {
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
476
  		RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  	} else {
5e6700b3b   Nicolas Dichtel   sit: add support ...
478
479
  		ipip6_tunnel_unlink(sitn, tunnel);
  		ipip6_tunnel_del_prl(tunnel, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  	}
e09acddf8   Paolo Abeni   ip_tunnel: replac...
481
  	dst_cache_reset(&tunnel->dst_cache);
3a43be3c3   Eric Dumazet   sit: get rid of i...
482
  	dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  }
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
484
  static int ipip6_err(struct sk_buff *skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  {
b71d1d426   Eric Dumazet   inet: constify ip...
486
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
487
488
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
489
  	unsigned int data_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  	struct ip_tunnel *t;
3051fbec2   David Ahern   net: sit: Update ...
491
  	int sifindex;
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
492
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
496
  
  	switch (type) {
  	default:
  	case ICMP_PARAMETERPROB:
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
497
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
500
501
  
  	case ICMP_DEST_UNREACH:
  		switch (code) {
  		case ICMP_SR_FAILED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  			/* Impossible event. */
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
503
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
511
512
513
  		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...
514
  			return 0;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
515
  		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  		break;
ec18d9a26   David S. Miller   ipv6: Add redirec...
517
518
  	case ICMP_REDIRECT:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  	}
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
520
  	err = -ENOENT;
3051fbec2   David Ahern   net: sit: Update ...
521
522
523
  	sifindex = netif_is_l3_master(skb->dev) ? IPCB(skb)->iif : 0;
  	t = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
  				iph->daddr, iph->saddr, sifindex);
63159f29b   Ian Morris   ipv6: coding styl...
524
  	if (!t)
363933955   David S. Miller   ipv4: Handle PMTU...
525
526
527
528
  		goto out;
  
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
  		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
d888f3966   Maciej Żenczykowski   net-ipv4: remove ...
529
  				 t->parms.link, iph->protocol);
363933955   David S. Miller   ipv4: Handle PMTU...
530
531
532
  		err = 0;
  		goto out;
  	}
ec18d9a26   David S. Miller   ipv6: Add redirec...
533
  	if (type == ICMP_REDIRECT) {
1042caa79   Maciej Żenczykowski   net-ipv4: remove ...
534
535
  		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link,
  			      iph->protocol);
ec18d9a26   David S. Miller   ipv6: Add redirec...
536
537
538
  		err = 0;
  		goto out;
  	}
363933955   David S. Miller   ipv4: Handle PMTU...
539

2d7a3b276   Eric Dumazet   ipv6: translate I...
540
  	err = 0;
173656acc   Hangbin Liu   sit: check if IPv...
541
542
  	if (__in6_dev_get(skb->dev) &&
  	    !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  		goto out;
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
544

2d7a3b276   Eric Dumazet   ipv6: translate I...
545
  	if (t->parms.iph.daddr == 0)
ca15a078b   Oussama Ghorbel   sit: generate icm...
546
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
  		goto out;
bb80087a9   Wei Yongjun   sit: used time_be...
549
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
553
554
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
  out:
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
555
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  }
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
557
558
559
560
561
562
563
564
  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 ...
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
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
  /* 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
630
631
  static int ipip6_rcv(struct sk_buff *skb)
  {
1ad759d84   Hannes Frederic Sowa   ipv6: remove unne...
632
  	const struct iphdr *iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
  	struct ip_tunnel *tunnel;
3051fbec2   David Ahern   net: sit: Update ...
634
  	int sifindex;
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
635
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636

3051fbec2   David Ahern   net: sit: Update ...
637
  	sifindex = netif_is_l3_master(skb->dev) ? IPCB(skb)->iif : 0;
4fddbf5d7   Sascha Hlusiak   sit: strictly res...
638
  	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
3051fbec2   David Ahern   net: sit: Update ...
639
  				     iph->saddr, iph->daddr, sifindex);
53b24b8f9   Ian Morris   ipv6: coding styl...
640
  	if (tunnel) {
8f84985fe   Li RongQing   net: unify the pc...
641
  		struct pcpu_sw_netstats *tstats;
15fc1f705   Eric Dumazet   sit: percpu stats...
642

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

7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
651
652
653
  		if (packet_is_spoofed(skb, iph, tunnel)) {
  			tunnel->dev->stats.rx_errors++;
  			goto out;
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
654
  		}
a09a4c8dd   Jesse Gross   tunnels: Remove e...
655
656
657
  		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 ...
658

bb9bd814e   Lorenzo Bianconi   ipv6: sit: reset ...
659
660
661
662
  		/* skb can be uncloned in iptunnel_pull_header, so
  		 * old iph is no longer valid
  		 */
  		iph = (const struct iphdr *)skb_mac_header(skb);
f4e0b4c5e   Nicolas Dichtel   ip6tnl/sit: drop ...
663
664
665
666
667
668
669
670
671
672
673
  		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...
674
  		}
d19d56ddc   Eric Dumazet   net: Introduce sk...
675

15fc1f705   Eric Dumazet   sit: percpu stats...
676
  		tstats = this_cpu_ptr(tunnel->dev->tstats);
c3ac17cd6   Li RongQing   ipv6: fix the use...
677
  		u64_stats_update_begin(&tstats->syncp);
15fc1f705   Eric Dumazet   sit: percpu stats...
678
679
  		tstats->rx_packets++;
  		tstats->rx_bytes += skb->len;
c3ac17cd6   Li RongQing   ipv6: fix the use...
680
  		u64_stats_update_end(&tstats->syncp);
15fc1f705   Eric Dumazet   sit: percpu stats...
681

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
  		return 0;
  	}
6dcdd1b36   David McCullough   net/ipv6/sit.c: r...
686
  	/* no tunnel matched,  let upstream know, ipsec may handle it */
6dcdd1b36   David McCullough   net/ipv6/sit.c: r...
687
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
  out:
36ca34cc3   David S. Miller   sit: Add missing ...
689
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
  	return 0;
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
692
  static const struct tnl_ptk_info ipip_tpi = {
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
693
694
695
  	/* no tunnel info required for ipip. */
  	.proto = htons(ETH_P_IP),
  };
49dbe7ae2   Simon Horman   sit: support MPLS...
696
697
698
699
700
701
702
703
  #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...
704
  {
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
705
  	const struct iphdr *iph;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
706
  	struct ip_tunnel *tunnel;
3051fbec2   David Ahern   net: sit: Update ...
707
708
709
  	int sifindex;
  
  	sifindex = netif_is_l3_master(skb->dev) ? IPCB(skb)->iif : 0;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
710

3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
711
  	iph = ip_hdr(skb);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
712
  	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
3051fbec2   David Ahern   net: sit: Update ...
713
  				     iph->saddr, iph->daddr, sifindex);
53b24b8f9   Ian Morris   ipv6: coding styl...
714
  	if (tunnel) {
49dbe7ae2   Simon Horman   sit: support MPLS...
715
716
717
  		const struct tnl_ptk_info *tpi;
  
  		if (tunnel->parms.iph.protocol != ipproto &&
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
718
719
720
721
722
  		    tunnel->parms.iph.protocol != 0)
  			goto drop;
  
  		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  			goto drop;
49dbe7ae2   Simon Horman   sit: support MPLS...
723
724
725
726
727
728
729
  #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...
730
  			goto drop;
49dbe7ae2   Simon Horman   sit: support MPLS...
731
  		return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
732
733
734
735
736
737
738
739
  	}
  
  	return 1;
  
  drop:
  	kfree_skb(skb);
  	return 0;
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
740
741
742
743
744
745
746
747
748
749
750
  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...
751
  /*
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
752
753
   * 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...
754
   */
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
755
756
  static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
  		      __be32 *v4dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
  {
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
758
759
760
  #ifdef CONFIG_IPV6_SIT_6RD
  	if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix,
  			      tunnel->ip6rd.prefixlen)) {
3a43be3c3   Eric Dumazet   sit: get rid of i...
761
  		unsigned int pbw0, pbi0;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
762
763
764
765
766
  		int pbi1;
  		u32 d;
  
  		pbw0 = tunnel->ip6rd.prefixlen >> 5;
  		pbi0 = tunnel->ip6rd.prefixlen & 0x1f;
a843dc4eb   Miaohe Lin   net: sit: fix UBS...
767
768
769
  		d = tunnel->ip6rd.relay_prefixlen < 32 ?
  			(ntohl(v6dst->s6_addr32[pbw0]) << pbi0) >>
  		    tunnel->ip6rd.relay_prefixlen : 0;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
770
771
772
  
  		pbi1 = pbi0 - tunnel->ip6rd.relay_prefixlen;
  		if (pbi1 > 0)
e7db38c38   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: Fix 6rd...
773
  			d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >>
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
774
  			     (32 - pbi1);
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
775
776
  		*v4dst = tunnel->ip6rd.relay_prefix | htonl(d);
  		return true;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
777
778
  	}
  #else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
  	if (v6dst->s6_addr16[0] == htons(0x2002)) {
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
780
  		/* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
781
782
  		memcpy(v4dst, &v6dst->s6_addr16[1], 4);
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
  	}
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
784
  #endif
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
785
786
787
788
789
790
791
792
  	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
793
794
795
796
797
798
799
  	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...
800
801
  static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
  				     struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
803
  	struct ip_tunnel *tunnel = netdev_priv(dev);
b71d1d426   Eric Dumazet   inet: constify ip...
804
805
  	const struct iphdr  *tiph = &tunnel->parms.iph;
  	const struct ipv6hdr *iph6 = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  	u8     tos = tunnel->parms.iph.tos;
292f4f3ce   Herbert Xu   sit: Clean up DF ...
807
  	__be16 df = tiph->frag_off;
67ba4152e   Ian Morris   ipv6: White-space...
808
809
810
  	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...
811
  	__be32 dst = tiph->daddr;
31e4543db   David S. Miller   ipv4: Make caller...
812
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
  	int    mtu;
b71d1d426   Eric Dumazet   inet: constify ip...
814
  	const struct in6_addr *addr6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  	int addr_type;
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
816
  	u8 ttl;
14909664e   Tom Herbert   sit: Setup and TX...
817
818
  	u8 protocol = IPPROTO_IPV6;
  	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819

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

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

63159f29b   Ian Morris   ipv6: coding styl...
830
  		if (!neigh) {
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
831
832
  			net_dbg_ratelimited("nexthop == NULL
  ");
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
833
834
  			goto tx_error;
  		}
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
835
  		addr6 = (const struct in6_addr *)&neigh->primary_key;
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
836
837
838
839
840
841
  		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...
842
843
844
845
  			do_tx_error = true;
  
  		neigh_release(neigh);
  		if (do_tx_error)
c7dc89c0a   Fred L. Templin   [IPV6]: Add RFC42...
846
847
  			goto tx_error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  	if (!dst)
218774dc3   Hannes Frederic Sowa   ipv6: add anti-sp...
849
  		dst = try_6rd(tunnel, &iph6->daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
  
  	if (!dst) {
  		struct neighbour *neigh = NULL;
1e2927b08   David S. Miller   ipv6: sit: Conver...
853
  		bool do_tx_error = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

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

63159f29b   Ian Morris   ipv6: coding styl...
858
  		if (!neigh) {
7df37ff33   Catalin\(ux\) M. BOIE   IPv6 NAT: Do not ...
859
860
  			net_dbg_ratelimited("nexthop == NULL
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
  			goto tx_error;
  		}
3e866703c   Eldad Zack   net/ipv6/sit.c: C...
863
  		addr6 = (const struct in6_addr *)&neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
  		addr_type = ipv6_addr_type(addr6);
  
  		if (addr_type == IPV6_ADDR_ANY) {
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
867
  			addr6 = &ipv6_hdr(skb)->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
  			addr_type = ipv6_addr_type(addr6);
  		}
1e2927b08   David S. Miller   ipv6: sit: Conver...
870
871
872
873
  		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
874

1e2927b08   David S. Miller   ipv6: sit: Conver...
875
876
877
  		neigh_release(neigh);
  		if (do_tx_error)
  			goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
879
880
881
882
  	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));
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
883

6e3d1bbbb   Haishuang Yan   sit: use dst_cach...
884
885
886
887
888
889
890
891
  	rt = dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr);
  	if (!rt) {
  		rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
  		if (IS_ERR(rt)) {
  			dev->stats.tx_carrier_errors++;
  			goto tx_error_icmp;
  		}
  		dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, fl4.saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  	}
6e3d1bbbb   Haishuang Yan   sit: use dst_cach...
893

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
  	if (rt->rt_type != RTN_UNICAST) {
  		ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
896
  		dev->stats.tx_carrier_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
  		goto tx_error_icmp;
  	}
d8d1f30b9   Changli Gao   net-next: remove ...
899
  	tdev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
902
  
  	if (tdev == dev) {
  		ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
903
  		dev->stats.collisions++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
  		goto tx_error;
  	}
7e13318da   Tom Herbert   net: define gso t...
906
  	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) {
14909664e   Tom Herbert   sit: Setup and TX...
907
  		ip_rt_put(rt);
aed069df0   Alexander Duyck   ip_tunnel_core: i...
908
  		goto tx_error;
14909664e   Tom Herbert   sit: Setup and TX...
909
  	}
292f4f3ce   Herbert Xu   sit: Clean up DF ...
910
  	if (df) {
14909664e   Tom Herbert   sit: Setup and TX...
911
  		mtu = dst_mtu(&rt->dst) - t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912

292f4f3ce   Herbert Xu   sit: Clean up DF ...
913
  		if (mtu < 68) {
15fc1f705   Eric Dumazet   sit: percpu stats...
914
  			dev->stats.collisions++;
292f4f3ce   Herbert Xu   sit: Clean up DF ...
915
916
917
  			ip_rt_put(rt);
  			goto tx_error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918

292f4f3ce   Herbert Xu   sit: Clean up DF ...
919
920
921
922
  		if (mtu < IPV6_MIN_MTU) {
  			mtu = IPV6_MIN_MTU;
  			df = 0;
  		}
f15ca723c   Nicolas Dichtel   net: don't call u...
923
  		if (tunnel->parms.iph.daddr)
4d42df46d   Hangbin Liu   sit: do not confi...
924
  			skb_dst_update_pmtu_no_confirm(skb, mtu);
292f4f3ce   Herbert Xu   sit: Clean up DF ...
925

58a478244   Eric Dumazet   ipv6: sit: update...
926
  		if (skb->len > mtu && !skb_is_gso(skb)) {
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
927
  			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
292f4f3ce   Herbert Xu   sit: Clean up DF ...
928
929
930
  			ip_rt_put(rt);
  			goto tx_error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
  	}
  
  	if (tunnel->err_count > 0) {
bb80087a9   Wei Yongjun   sit: used time_be...
934
935
  		if (time_before(jiffies,
  				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
938
939
940
941
942
943
944
  			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...
945
  	max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946

cfbba49d8   Patrick McHardy   [NET]: Avoid copy...
947
948
  	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
949
950
951
  		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
  		if (!new_skb) {
  			ip_rt_put(rt);
15fc1f705   Eric Dumazet   sit: percpu stats...
952
  			dev->stats.tx_dropped++;
66028310a   Gao feng   sit: use kfree_sk...
953
  			kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
954
  			return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
957
958
959
  		}
  		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...
960
  		iph6 = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  	}
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
962
963
964
965
  	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
966

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

469471cdf   Tom Herbert   sit: Set inner IP...
972
  	skb_set_inner_ipproto(skb, IPPROTO_IPV6);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
973
974
  	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...
975
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
977
978
979
  
  tx_error_icmp:
  	dst_link_failure(skb);
  tx_error:
66028310a   Gao feng   sit: use kfree_sk...
980
  	kfree_skb(skb);
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
981
  	dev->stats.tx_errors++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
982
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  }
49dbe7ae2   Simon Horman   sit: support MPLS...
984
985
  static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
  				     struct net_device *dev, u8 ipproto)
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
986
987
988
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	const struct iphdr  *tiph = &tunnel->parms.iph;
7e13318da   Tom Herbert   net: define gso t...
989
  	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
aed069df0   Alexander Duyck   ip_tunnel_core: i...
990
  		goto tx_error;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
991

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

49dbe7ae2   Simon Horman   sit: support MPLS...
994
  	ip_tunnel_xmit(skb, dev, tiph, ipproto);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
995
  	return NETDEV_TX_OK;
aed069df0   Alexander Duyck   ip_tunnel_core: i...
996
997
  tx_error:
  	kfree_skb(skb);
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
998
999
  	dev->stats.tx_errors++;
  	return NETDEV_TX_OK;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1000
1001
1002
1003
1004
  }
  
  static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
  				   struct net_device *dev)
  {
cb9f1b783   Willem de Bruijn   ip: validate head...
1005
1006
  	if (!pskb_inet_may_pull(skb))
  		goto tx_err;
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1007
1008
  	switch (skb->protocol) {
  	case htons(ETH_P_IP):
49dbe7ae2   Simon Horman   sit: support MPLS...
1009
  		sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1010
1011
1012
1013
  		break;
  	case htons(ETH_P_IPV6):
  		ipip6_tunnel_xmit(skb, dev);
  		break;
49dbe7ae2   Simon Horman   sit: support MPLS...
1014
1015
1016
1017
1018
  #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...
1019
1020
1021
1022
1023
1024
1025
1026
  	default:
  		goto tx_err;
  	}
  
  	return NETDEV_TX_OK;
  
  tx_err:
  	dev->stats.tx_errors++;
66028310a   Gao feng   sit: use kfree_sk...
1027
  	kfree_skb(skb);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1028
1029
1030
  	return NETDEV_TX_OK;
  
  }
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1031
1032
1033
1034
  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...
1035
  	const struct iphdr *iph;
31e4543db   David S. Miller   ipv4: Make caller...
1036
  	struct flowi4 fl4;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1037
1038
1039
1040
1041
  
  	tunnel = netdev_priv(dev);
  	iph = &tunnel->parms.iph;
  
  	if (iph->daddr) {
5e6700b3b   Nicolas Dichtel   sit: add support ...
1042
1043
  		struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4,
  							  NULL,
78fbfd8a6   David S. Miller   ipv4: Create and ...
1044
1045
1046
1047
1048
  							  iph->daddr, iph->saddr,
  							  0, 0,
  							  IPPROTO_IPV6,
  							  RT_TOS(iph->tos),
  							  tunnel->parms.link);
b23dd4fe4   David S. Miller   ipv4: Make output...
1049
1050
  
  		if (!IS_ERR(rt)) {
d8d1f30b9   Changli Gao   net-next: remove ...
1051
  			tdev = rt->dst.dev;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1052
1053
1054
1055
1056
1057
  			ip_rt_put(rt);
  		}
  		dev->flags |= IFF_POINTOPOINT;
  	}
  
  	if (!tdev && tunnel->parms.link)
5e6700b3b   Nicolas Dichtel   sit: add support ...
1058
  		tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1059

ff6ab32bd   Stephen Suryaputra   vrf: sit mtu shou...
1060
  	if (tdev && !netif_is_l3_master(tdev)) {
14909664e   Tom Herbert   sit: Setup and TX...
1061
  		int t_hlen = tunnel->hlen + sizeof(struct iphdr);
14909664e   Tom Herbert   sit: Setup and TX...
1062
  		dev->mtu = tdev->mtu - t_hlen;
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1063
1064
1065
  		if (dev->mtu < IPV6_MIN_MTU)
  			dev->mtu = IPV6_MIN_MTU;
  	}
8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1066
  }
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1067
1068
  static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p,
  				__u32 fwmark)
f37234160   Nicolas Dichtel   sit: add support ...
1069
  {
5e6700b3b   Nicolas Dichtel   sit: add support ...
1070
  	struct net *net = t->net;
f37234160   Nicolas Dichtel   sit: add support ...
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
  	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;
f859b4af1   Hangbin Liu   sit: update frag_...
1082
  	t->parms.iph.frag_off = p->iph.frag_off;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1083
  	if (t->parms.link != p->link || t->fwmark != fwmark) {
f37234160   Nicolas Dichtel   sit: add support ...
1084
  		t->parms.link = p->link;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1085
  		t->fwmark = fwmark;
f37234160   Nicolas Dichtel   sit: add support ...
1086
1087
  		ipip6_tunnel_bind_dev(t->dev);
  	}
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1088
  	dst_cache_reset(&t->dst_cache);
f37234160   Nicolas Dichtel   sit: add support ...
1089
1090
  	netdev_state_change(t->dev);
  }
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  #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...
1118
  	dst_cache_reset(&t->dst_cache);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1119
1120
1121
  	netdev_state_change(t->dev);
  	return 0;
  }
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  
  static int
  ipip6_tunnel_get6rd(struct net_device *dev, struct ifreq *ifr)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_6rd ip6rd;
  	struct ip_tunnel_parm p;
  
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
  		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  			return -EFAULT;
  		t = ipip6_tunnel_locate(t->net, &p, 0);
  	}
  	if (!t)
  		t = netdev_priv(dev);
  
  	ip6rd.prefix = t->ip6rd.prefix;
  	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)))
  		return -EFAULT;
  	return 0;
  }
  
  static int
  ipip6_tunnel_6rdctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_6rd ip6rd;
  	int err;
  
  	if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
  		return -EPERM;
  	if (copy_from_user(&ip6rd, ifr->ifr_ifru.ifru_data, sizeof(ip6rd)))
  		return -EFAULT;
  
  	if (cmd != SIOCDEL6RD) {
  		err = ipip6_tunnel_update_6rd(t, &ip6rd);
  		if (err < 0)
  			return err;
  	} else
  		ipip6_tunnel_clone_6rd(dev, dev_to_sit_net(dev));
  	return 0;
  }
  
  #endif /* CONFIG_IPV6_SIT_6RD */
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1169

03ff49793   Wei Yongjun   sit: make functio...
1170
  static bool ipip6_valid_ip_proto(u8 ipproto)
49dbe7ae2   Simon Horman   sit: support MPLS...
1171
1172
1173
1174
1175
1176
1177
1178
  {
  	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
1179
  static int
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1180
  __ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
  {
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
  		return -EPERM;
  
  	if (!ipip6_valid_ip_proto(p->iph.protocol))
  		return -EINVAL;
  	if (p->iph.version != 4 ||
  	    p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)))
  		return -EINVAL;
  
  	if (p->iph.ttl)
  		p->iph.frag_off |= htons(IP_DF);
  	return 0;
  }
  
  static int
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1197
  ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm *p)
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1198
1199
  {
  	struct ip_tunnel *t = netdev_priv(dev);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1200

f60fe2df9   Christoph Hellwig   sit: impement ->n...
1201
1202
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
  		t = ipip6_tunnel_locate(t->net, p, 0);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1203
1204
  	if (!t)
  		t = netdev_priv(dev);
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1205
  	memcpy(p, &t->parms, sizeof(*p));
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1206
1207
1208
1209
  	return 0;
  }
  
  static int
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1210
  ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm *p)
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1211
  {
9aad77c3b   Nicolas Dichtel   sit: use the righ...
1212
  	struct ip_tunnel *t = netdev_priv(dev);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1213
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214

f60fe2df9   Christoph Hellwig   sit: impement ->n...
1215
  	err = __ipip6_tunnel_ioctl_validate(t->net, p);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1216
1217
  	if (err)
  		return err;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1218

f60fe2df9   Christoph Hellwig   sit: impement ->n...
1219
  	t = ipip6_tunnel_locate(t->net, p, 1);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1220
1221
  	if (!t)
  		return -ENOBUFS;
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1222
1223
1224
1225
  	return 0;
  }
  
  static int
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1226
  ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm *p)
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1227
1228
  {
  	struct ip_tunnel *t = netdev_priv(dev);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1229
  	int err;
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1230
  	err = __ipip6_tunnel_ioctl_validate(t->net, p);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1231
1232
  	if (err)
  		return err;
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1233
  	t = ipip6_tunnel_locate(t->net, p, 0);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1234
1235
1236
1237
1238
1239
1240
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
  		if (!t)
  			return -ENOENT;
  	} else {
  		if (t) {
  			if (t->dev != dev)
  				return -EEXIST;
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1241
  		} else {
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1242
1243
  			if (((dev->flags & IFF_POINTOPOINT) && !p->iph.daddr) ||
  			    (!(dev->flags & IFF_POINTOPOINT) && p->iph.daddr))
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1244
1245
  				return -EINVAL;
  			t = netdev_priv(dev);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1246
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247

f60fe2df9   Christoph Hellwig   sit: impement ->n...
1248
  		ipip6_tunnel_update(t, p, t->fwmark);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1249
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250

fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1251
1252
  	return 0;
  }
f9cd5a553   Nicolas Dichtel   sit: always notif...
1253

fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1254
  static int
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1255
  ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm *p)
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1256
1257
  {
  	struct ip_tunnel *t = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258

fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1259
1260
  	if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261

fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1262
  	if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1263
  		t = ipip6_tunnel_locate(t->net, p, 0);
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1264
1265
1266
1267
1268
1269
1270
1271
1272
  		if (!t)
  			return -ENOENT;
  		if (t == netdev_priv(dev_to_sit_net(dev)->fb_tunnel_dev))
  			return -EPERM;
  		dev = t->dev;
  	}
  	unregister_netdevice(dev);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273

fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1274
  static int
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
  ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
  {
  	switch (cmd) {
  	case SIOCGETTUNNEL:
  		return ipip6_tunnel_get(dev, p);
  	case SIOCADDTUNNEL:
  		return ipip6_tunnel_add(dev, p);
  	case SIOCCHGTUNNEL:
  		return ipip6_tunnel_change(dev, p);
  	case SIOCDELTUNNEL:
  		return ipip6_tunnel_del(dev, p);
  	default:
  		return -EINVAL;
  	}
  }
  
  static int
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1292
1293
1294
1295
  ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
  	switch (cmd) {
  	case SIOCGETTUNNEL:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1296
  	case SIOCADDTUNNEL:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1297
  	case SIOCCHGTUNNEL:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1298
  	case SIOCDELTUNNEL:
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1299
  		return ip_tunnel_ioctl(dev, ifr, cmd);
300aaeeaa   YOSHIFUJI Hideaki   [IPV6] SIT: Add S...
1300
  	case SIOCGETPRL:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1301
  		return ipip6_tunnel_get_prl(dev, ifr);
fadf6bf06   Templin, Fred L   [IPV6] SIT: Add P...
1302
1303
1304
  	case SIOCADDPRL:
  	case SIOCDELPRL:
  	case SIOCCHGPRL:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1305
  		return ipip6_tunnel_prl_ctl(dev, ifr, cmd);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1306
  #ifdef CONFIG_IPV6_SIT_6RD
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1307
1308
  	case SIOCGET6RD:
  		return ipip6_tunnel_get6rd(dev, ifr);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1309
1310
1311
  	case SIOCADD6RD:
  	case SIOCCHG6RD:
  	case SIOCDEL6RD:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1312
  		return ipip6_tunnel_6rdctl(dev, ifr, cmd);
fa857afcf   YOSHIFUJI Hideaki / 吉藤英明   ipv6 sit: 6rd (IP...
1313
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
  	default:
fd5d687b7   Christoph Hellwig   sit: refactor ipi...
1315
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  }
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1318
  static const struct net_device_ops ipip6_netdev_ops = {
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
1319
  	.ndo_init	= ipip6_tunnel_init,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1320
  	.ndo_uninit	= ipip6_tunnel_uninit,
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1321
  	.ndo_start_xmit	= sit_tunnel_xmit,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1322
  	.ndo_do_ioctl	= ipip6_tunnel_ioctl,
f61dd388a   Pravin B Shelar   Tunneling: use IP...
1323
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
1324
  	.ndo_get_iflink = ip_tunnel_get_iflink,
f60fe2df9   Christoph Hellwig   sit: impement ->n...
1325
  	.ndo_tunnel_ctl = ipip6_tunnel_ctl,
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1326
  };
15fc1f705   Eric Dumazet   sit: percpu stats...
1327
1328
  static void ipip6_dev_free(struct net_device *dev)
  {
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1329
  	struct ip_tunnel *tunnel = netdev_priv(dev);
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1330
  	dst_cache_destroy(&tunnel->dst_cache);
15fc1f705   Eric Dumazet   sit: percpu stats...
1331
  	free_percpu(dev->tstats);
15fc1f705   Eric Dumazet   sit: percpu stats...
1332
  }
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
1333
1334
1335
1336
1337
  #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
1338
1339
  static void ipip6_tunnel_setup(struct net_device *dev)
  {
14909664e   Tom Herbert   sit: Setup and TX...
1340
1341
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1342
  	dev->netdev_ops		= &ipip6_netdev_ops;
75ea1f477   Jason A. Donenfeld   net: sit: impleme...
1343
  	dev->header_ops		= &ip_tunnel_header_ops;
cf124db56   David S. Miller   net: Fix inconsis...
1344
1345
  	dev->needs_free_netdev	= true;
  	dev->priv_destructor	= ipip6_dev_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
  
  	dev->type		= ARPHRD_SIT;
14909664e   Tom Herbert   sit: Setup and TX...
1348
  	dev->mtu		= ETH_DATA_LEN - t_hlen;
b96f9afee   Jarod Wilson   ipv4/6: use core ...
1349
  	dev->min_mtu		= IPV6_MIN_MTU;
f7ff1fde9   Nicolas Dichtel   ip6_tunnel: remov...
1350
  	dev->max_mtu		= IP6_MAX_MTU - t_hlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  	dev->flags		= IFF_NOARP;
028758788   Eric Dumazet   net: better IFF_X...
1352
  	netif_keep_dst(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  	dev->addr_len		= 4;
8df40d103   Eric Dumazet   sit: enable lockl...
1354
  	dev->features		|= NETIF_F_LLTX;
61c1db7fa   Eric Dumazet   ipv6: sit: add GS...
1355
1356
  	dev->features		|= SIT_FEATURES;
  	dev->hw_features	|= SIT_FEATURES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
  }
15fc1f705   Eric Dumazet   sit: percpu stats...
1358
  static int ipip6_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  {
1326c3d5a   Stephen Hemminger   ipv6: convert tun...
1360
  	struct ip_tunnel *tunnel = netdev_priv(dev);
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1361
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
1363
  
  	tunnel->dev = dev;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1364
  	tunnel->net = dev_net(dev);
ebe084aaf   Steffen Klassert   sit: Use ipip6_tu...
1365
  	strcpy(tunnel->parms.name, dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366

8a4a50f98   Michal Schmidt   [IPV6] sit: Rebin...
1367
  	ipip6_tunnel_bind_dev(dev);
1c213bd24   WANG Cong   net: introduce ne...
1368
  	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
15fc1f705   Eric Dumazet   sit: percpu stats...
1369
1370
  	if (!dev->tstats)
  		return -ENOMEM;
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1371
1372
  	err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
  	if (err) {
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1373
  		free_percpu(dev->tstats);
d7426c69a   WANG Cong   sit: fix a double...
1374
  		dev->tstats = NULL;
e09acddf8   Paolo Abeni   ip_tunnel: replac...
1375
  		return err;
cf71d2bc0   Nicolas Dichtel   sit: fix panic wi...
1376
  	}
15fc1f705   Eric Dumazet   sit: percpu stats...
1377
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
  }
4ece90097   Eric Dumazet   sit: fix sit0 per...
1379
  static void __net_init ipip6_fb_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
1381
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
  	struct iphdr *iph = &tunnel->parms.iph;
291821766   Pavel Emelyanov   [SIT]: Make tunne...
1383
1384
  	struct net *net = dev_net(dev);
  	struct sit_net *sitn = net_generic(net, sit_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
1388
1389
1390
1391
  	iph->version		= 4;
  	iph->protocol		= IPPROTO_IPV6;
  	iph->ihl		= 5;
  	iph->ttl		= 64;
  
  	dev_hold(dev);
cf778b00e   Eric Dumazet   net: reintroduce ...
1392
  	rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
  }
a8b8a889e   Matthias Schiffer   net: add netlink_...
1394
1395
  static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1396
1397
  {
  	u8 proto;
c2ff682a6   Nicolas Dichtel   sit: fix an oops ...
1398
  	if (!data || !data[IFLA_IPTUN_PROTO])
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1399
1400
1401
  		return 0;
  
  	proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
49dbe7ae2   Simon Horman   sit: support MPLS...
1402
  	if (!ipip6_valid_ip_proto(proto))
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1403
1404
1405
1406
  		return -EINVAL;
  
  	return 0;
  }
f37234160   Nicolas Dichtel   sit: add support ...
1407
  static void ipip6_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1408
1409
  				struct ip_tunnel_parm *parms,
  				__u32 *fwmark)
f37234160   Nicolas Dichtel   sit: add support ...
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  {
  	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...
1425
  		parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
f37234160   Nicolas Dichtel   sit: add support ...
1426
1427
  
  	if (data[IFLA_IPTUN_REMOTE])
d440b7206   Nicolas Dichtel   sit: fix sparse w...
1428
  		parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
f37234160   Nicolas Dichtel   sit: add support ...
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
  
  	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...
1443
  		parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1444
1445
1446
  
  	if (data[IFLA_IPTUN_PROTO])
  		parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1447
1448
  	if (data[IFLA_IPTUN_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
f37234160   Nicolas Dichtel   sit: add support ...
1449
  }
14909664e   Tom Herbert   sit: Setup and TX...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  /* 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...
1473
  		ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
14909664e   Tom Herbert   sit: Setup and TX...
1474
1475
1476
1477
  	}
  
  	if (data[IFLA_IPTUN_ENCAP_DPORT]) {
  		ret = true;
a409caecb   Eric Dumazet   sit: fix some __b...
1478
  		ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
14909664e   Tom Herbert   sit: Setup and TX...
1479
1480
1481
1482
  	}
  
  	return ret;
  }
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
  #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...
1496
  		ip6rd->prefix = nla_get_in6_addr(data[IFLA_IPTUN_6RD_PREFIX]);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
  	}
  
  	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 ...
1519
  static int ipip6_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
1520
1521
  			 struct nlattr *tb[], struct nlattr *data[],
  			 struct netlink_ext_ack *extack)
f37234160   Nicolas Dichtel   sit: add support ...
1522
1523
1524
  {
  	struct net *net = dev_net(dev);
  	struct ip_tunnel *nt;
14909664e   Tom Herbert   sit: Setup and TX...
1525
  	struct ip_tunnel_encap ipencap;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1526
1527
1528
1529
  #ifdef CONFIG_IPV6_SIT_6RD
  	struct ip_tunnel_6rd ip6rd;
  #endif
  	int err;
f37234160   Nicolas Dichtel   sit: add support ...
1530
1531
  
  	nt = netdev_priv(dev);
14909664e   Tom Herbert   sit: Setup and TX...
1532
1533
1534
1535
1536
1537
  
  	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 ...
1538
  	ipip6_netlink_parms(data, &nt->parms, &nt->fwmark);
f37234160   Nicolas Dichtel   sit: add support ...
1539
1540
1541
  
  	if (ipip6_tunnel_locate(net, &nt->parms, 0))
  		return -EEXIST;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1542
1543
1544
  	err = ipip6_tunnel_create(dev);
  	if (err < 0)
  		return err;
2b3957c34   Xin Long   sit: fix IFLA_MTU...
1545
1546
  	if (tb[IFLA_MTU]) {
  		u32 mtu = nla_get_u32(tb[IFLA_MTU]);
f7ff1fde9   Nicolas Dichtel   ip6_tunnel: remov...
1547
1548
  		if (mtu >= IPV6_MIN_MTU &&
  		    mtu <= IP6_MAX_MTU - dev->hard_header_len)
2b3957c34   Xin Long   sit: fix IFLA_MTU...
1549
1550
  			dev->mtu = mtu;
  	}
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1551
1552
1553
1554
1555
1556
  #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 ...
1557
1558
1559
  }
  
  static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
1560
1561
  			    struct nlattr *data[],
  			    struct netlink_ext_ack *extack)
f37234160   Nicolas Dichtel   sit: add support ...
1562
  {
86bd68bfd   Nicolas Dichtel   sit: fix tunnel u...
1563
  	struct ip_tunnel *t = netdev_priv(dev);
f37234160   Nicolas Dichtel   sit: add support ...
1564
  	struct ip_tunnel_parm p;
14909664e   Tom Herbert   sit: Setup and TX...
1565
  	struct ip_tunnel_encap ipencap;
86bd68bfd   Nicolas Dichtel   sit: fix tunnel u...
1566
  	struct net *net = t->net;
f37234160   Nicolas Dichtel   sit: add support ...
1567
  	struct sit_net *sitn = net_generic(net, sit_net_id);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1568
1569
1570
  #ifdef CONFIG_IPV6_SIT_6RD
  	struct ip_tunnel_6rd ip6rd;
  #endif
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1571
  	__u32 fwmark = t->fwmark;
14909664e   Tom Herbert   sit: Setup and TX...
1572
  	int err;
f37234160   Nicolas Dichtel   sit: add support ...
1573
1574
1575
  
  	if (dev == sitn->fb_tunnel_dev)
  		return -EINVAL;
14909664e   Tom Herbert   sit: Setup and TX...
1576
1577
1578
1579
1580
  	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 ...
1581
  	ipip6_netlink_parms(data, &p, &fwmark);
f37234160   Nicolas Dichtel   sit: add support ...
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
  
  	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 ...
1594
  	ipip6_tunnel_update(t, &p, fwmark);
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1595
1596
1597
1598
1599
  
  #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 ...
1600
1601
  	return 0;
  }
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1602
  static size_t ipip6_get_size(const struct net_device *dev)
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
  {
  	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...
1615
1616
1617
1618
  		/* IFLA_IPTUN_PMTUDISC */
  		nla_total_size(1) +
  		/* IFLA_IPTUN_FLAGS */
  		nla_total_size(2) +
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1619
1620
  		/* IFLA_IPTUN_PROTO */
  		nla_total_size(1) +
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
  #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...
1631
1632
1633
1634
1635
1636
1637
1638
  		/* 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 ...
1639
1640
  		/* IFLA_IPTUN_FWMARK */
  		nla_total_size(4) +
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1641
1642
  		0;
  }
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1643
  static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1644
1645
1646
1647
1648
  {
  	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...
1649
1650
  	    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...
1651
  	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
a12c9a858   Nicolas Dichtel   sit/rtnl: add mis...
1652
1653
1654
  	    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...
1655
  	    nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1656
1657
  	    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...
1658
  		goto nla_put_failure;
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1659
1660
  
  #ifdef CONFIG_IPV6_SIT_6RD
930345ea6   Jiri Benc   netlink: implemen...
1661
1662
1663
1664
  	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...
1665
1666
1667
1668
1669
1670
  	    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...
1671
1672
  	if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
  			tunnel->encap.type) ||
a409caecb   Eric Dumazet   sit: fix some __b...
1673
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
14909664e   Tom Herbert   sit: Setup and TX...
1674
  			tunnel->encap.sport) ||
a409caecb   Eric Dumazet   sit: fix some __b...
1675
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
14909664e   Tom Herbert   sit: Setup and TX...
1676
1677
  			tunnel->encap.dport) ||
  	    nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
e1b2cb655   Tom Herbert   fou: Fix typo in ...
1678
  			tunnel->encap.flags))
14909664e   Tom Herbert   sit: Setup and TX...
1679
  		goto nla_put_failure;
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1680
1681
1682
1683
1684
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
f37234160   Nicolas Dichtel   sit: add support ...
1685
1686
1687
1688
1689
1690
1691
1692
  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...
1693
  	[IFLA_IPTUN_PROTO]		= { .type = NLA_U8 },
e2f1f072d   Nicolas Dichtel   sit: allow to con...
1694
1695
1696
1697
1698
1699
  #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...
1700
1701
1702
1703
  	[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 ...
1704
  	[IFLA_IPTUN_FWMARK]		= { .type = NLA_U32 },
f37234160   Nicolas Dichtel   sit: add support ...
1705
  };
9434266f2   Willem de Bruijn   sit: fix use afte...
1706
1707
1708
1709
1710
1711
1712
1713
  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...
1714
1715
1716
  static struct rtnl_link_ops sit_link_ops __read_mostly = {
  	.kind		= "sit",
  	.maxtype	= IFLA_IPTUN_MAX,
f37234160   Nicolas Dichtel   sit: add support ...
1717
  	.policy		= ipip6_policy,
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1718
  	.priv_size	= sizeof(struct ip_tunnel),
f37234160   Nicolas Dichtel   sit: add support ...
1719
  	.setup		= ipip6_tunnel_setup,
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1720
  	.validate	= ipip6_validate,
f37234160   Nicolas Dichtel   sit: add support ...
1721
1722
  	.newlink	= ipip6_newlink,
  	.changelink	= ipip6_changelink,
e4c94a9cd   Nicolas Dichtel   sit: rename rtnl ...
1723
1724
  	.get_size	= ipip6_get_size,
  	.fill_info	= ipip6_fill_info,
9434266f2   Willem de Bruijn   sit: fix use afte...
1725
  	.dellink	= ipip6_dellink,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1726
  	.get_link_net	= ip_tunnel_get_link_net,
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1727
  };
6dcd814bd   Eric Dumazet   net: struct xfrm_...
1728
  static struct xfrm_tunnel sit_handler __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
1730
  	.handler	=	ipip6_rcv,
  	.err_handler	=	ipip6_err,
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
1731
  	.priority	=	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
  };
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1733
1734
1735
1736
1737
  static struct xfrm_tunnel ipip_handler __read_mostly = {
  	.handler	=	ipip_rcv,
  	.err_handler	=	ipip6_err,
  	.priority	=	2,
  };
49dbe7ae2   Simon Horman   sit: support MPLS...
1738
1739
1740
1741
1742
1743
1744
  #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...
1745
1746
  static void __net_exit sit_destroy_tunnels(struct net *net,
  					   struct list_head *head)
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1747
  {
9434266f2   Willem de Bruijn   sit: fix use afte...
1748
  	struct sit_net *sitn = net_generic(net, sit_net_id);
5e6700b3b   Nicolas Dichtel   sit: add support ...
1749
  	struct net_device *dev, *aux;
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1750
  	int prio;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1751
1752
1753
  	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...
1754
1755
  	for (prio = 1; prio < 4; prio++) {
  		int h;
e87a8f24c   Jiri Kosina   net: resolve symb...
1756
  		for (h = 0; h < IP6_SIT_HASH_SIZE; h++) {
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1757
  			struct ip_tunnel *t;
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1758

753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1759
  			t = rtnl_dereference(sitn->tunnels[prio][h]);
53b24b8f9   Ian Morris   ipv6: coding styl...
1760
  			while (t) {
5e6700b3b   Nicolas Dichtel   sit: add support ...
1761
1762
1763
  				/* 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...
1764
  				if (!net_eq(dev_net(t->dev), net))
5e6700b3b   Nicolas Dichtel   sit: add support ...
1765
1766
  					unregister_netdevice_queue(t->dev,
  								   head);
753ea8e96   Eric Dumazet   net: ipv6: sit: f...
1767
  				t = rtnl_dereference(t->next);
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1768
  			}
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1769
1770
1771
  		}
  	}
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
1772
  static int __net_init sit_init_net(struct net *net)
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1773
  {
671011720   Eric W. Biederman   net: Simplify ipi...
1774
  	struct sit_net *sitn = net_generic(net, sit_net_id);
72b36015b   Ted Feng   ipip, sit: copy p...
1775
  	struct ip_tunnel *t;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1776
  	int err;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1777

291821766   Pavel Emelyanov   [SIT]: Make tunne...
1778
1779
1780
1781
  	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;
79134e6ce   Eric Dumazet   net: do not creat...
1782
1783
  	if (!net_has_fallback_tunnels(net))
  		return 0;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1784
  	sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
c835a6773   Tom Gundersen   net: set name_ass...
1785
  					   NET_NAME_UNKNOWN,
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1786
1787
1788
1789
1790
  					   ipip6_tunnel_setup);
  	if (!sitn->fb_tunnel_dev) {
  		err = -ENOMEM;
  		goto err_alloc_dev;
  	}
be77e5930   Alexey Dobriyan   net: fix tunnels ...
1791
  	dev_net_set(sitn->fb_tunnel_dev, net);
205983c43   Nicolas Dichtel   sit: allow to use...
1792
  	sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops;
5e6700b3b   Nicolas Dichtel   sit: add support ...
1793
1794
1795
1796
  	/* 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...
1797

e5d08d718   Ian Morris   ipv6: coding styl...
1798
1799
  	err = register_netdev(sitn->fb_tunnel_dev);
  	if (err)
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1800
  		goto err_reg_dev;
4ece90097   Eric Dumazet   sit: fix sit0 per...
1801
1802
  	ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
  	ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
72b36015b   Ted Feng   ipip, sit: copy p...
1803
1804
1805
  	t = netdev_priv(sitn->fb_tunnel_dev);
  
  	strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1806
  	return 0;
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1807
  err_reg_dev:
dd4080ee5   Eric Dumazet   sit: fix percpu s...
1808
  	ipip6_dev_free(sitn->fb_tunnel_dev);
07f12b26e   Mao Wenan   net: sit: fix mem...
1809
  	free_netdev(sitn->fb_tunnel_dev);
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1810
  err_alloc_dev:
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1811
1812
  	return err;
  }
bb401caef   Eric Dumazet   ipv6: speedup ipv...
1813
  static void __net_exit sit_exit_batch_net(struct list_head *net_list)
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1814
  {
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1815
  	LIST_HEAD(list);
bb401caef   Eric Dumazet   ipv6: speedup ipv...
1816
  	struct net *net;
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1817

cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1818
  	rtnl_lock();
bb401caef   Eric Dumazet   ipv6: speedup ipv...
1819
1820
  	list_for_each_entry(net, net_list, exit_list)
  		sit_destroy_tunnels(net, &list);
62808f912   Eric Dumazet   ipv6 sit: Optimiz...
1821
  	unregister_netdevice_many(&list);
cd3dbc194   Pavel Emelyanov   [SIT]: Make the f...
1822
  	rtnl_unlock();
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1823
1824
1825
1826
  }
  
  static struct pernet_operations sit_net_ops = {
  	.init = sit_init_net,
bb401caef   Eric Dumazet   ipv6: speedup ipv...
1827
  	.exit_batch = sit_exit_batch_net,
671011720   Eric W. Biederman   net: Simplify ipi...
1828
1829
  	.id   = &sit_net_id,
  	.size = sizeof(struct sit_net),
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1830
  };
89c894581   Adrian Bunk   [IPV6] net/ipv6/s...
1831
  static void __exit sit_cleanup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1832
  {
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1833
  	rtnl_link_unregister(&sit_link_ops);
c73cb5a2d   Kazunori MIYAZAWA   [IPSEC]: make sit...
1834
  	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1835
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
49dbe7ae2   Simon Horman   sit: support MPLS...
1836
1837
1838
  #if IS_ENABLED(CONFIG_MPLS)
  	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
  #endif
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1839

671011720   Eric W. Biederman   net: Simplify ipi...
1840
  	unregister_pernet_device(&sit_net_ops);
ef9a9d118   Eric Dumazet   ipv6 sit: RCU con...
1841
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1842
  }
89c894581   Adrian Bunk   [IPV6] net/ipv6/s...
1843
  static int __init sit_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
1845
  {
  	int err;
49dbe7ae2   Simon Horman   sit: support MPLS...
1846
1847
  	pr_info("IPv6, IPv4 and MPLS over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848

671011720   Eric W. Biederman   net: Simplify ipi...
1849
  	err = register_pernet_device(&sit_net_ops);
8190d9009   Pavel Emelyanov   [SIT]: Introduce ...
1850
  	if (err < 0)
d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
1851
1852
1853
  		return err;
  	err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
  	if (err < 0) {
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1854
1855
  		pr_info("%s: can't register ip6ip4
  ", __func__);
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1856
  		goto xfrm_tunnel_failed;
d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
1857
  	}
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1858
1859
1860
1861
1862
1863
  	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...
1864
1865
1866
1867
1868
1869
1870
1871
  #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...
1872
1873
1874
1875
1876
  	err = rtnl_link_register(&sit_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877
  	return err;
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1878
1879
  
  rtnl_link_failed:
49dbe7ae2   Simon Horman   sit: support MPLS...
1880
1881
1882
1883
  #if IS_ENABLED(CONFIG_MPLS)
  	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
  xfrm_tunnel_mpls_failed:
  #endif
32b8a8e59   Nicolas Dichtel   sit: add IPv4 ove...
1884
1885
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
  xfrm_tunnel4_failed:
ba3e3f50a   Nicolas Dichtel   sit: advertise tu...
1886
1887
1888
1889
  	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
1890
  }
989e5b96e   Joerg Roedel   [IPV6]: Seperate ...
1891
1892
1893
  
  module_init(sit_init);
  module_exit(sit_cleanup);
39c850863   Jan Dittmer   [IPV6] sit: Add m...
1894
  MODULE_LICENSE("GPL");
f98f89a01   Tom Gundersen   net: tunnels - en...
1895
  MODULE_ALIAS_RTNL_LINK("sit");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
1896
  MODULE_ALIAS_NETDEV("sit0");