Blame view

net/ipv4/ip_gre.c 43.2 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
3
   *	Linux NET3:	GRE over IP protocol decoder.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   *
   *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   */
afd465030   Joe Perches   net: ipv4: Standa...
7
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4fc268d24   Randy Dunlap   [PATCH] capable/c...
8
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/module.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
12
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
13
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/in.h>
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/if_arp.h>
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
20
  #include <linux/if_vlan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
  #include <linux/init.h>
  #include <linux/in6.h>
  #include <linux/inetdevice.h>
  #include <linux/igmp.h>
  #include <linux/netfilter_ipv4.h>
e1a800022   Herbert Xu   gre: Add Transpar...
26
  #include <linux/etherdevice.h>
46f25dffb   Kris Katterjohn   [NET]: Change 150...
27
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
32
  
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/protocol.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
33
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
  #include <net/arp.h>
  #include <net/checksum.h>
  #include <net/dsfield.h>
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
39
40
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
c19e654dd   Herbert Xu   gre: Add netlink ...
41
  #include <net/rtnetlink.h>
00959ade3   Dmitry Kozlov   PPTP: PPP over IP...
42
  #include <net/gre.h>
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
43
  #include <net/dst_metadata.h>
84e54fe0a   William Tu   gre: introduce na...
44
  #include <net/erspan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
56
57
  /*
     Problems & solutions
     --------------------
  
     1. The most important issue is detecting local dead loops.
     They would cause complete host lockup in transmit, which
     would be "resolved" by stack overflow or, if queueing is enabled,
     with infinite looping in net_bh.
  
     We cannot track such dead loops during route installation,
     it is infeasible task. The most general solutions would be
     to keep skb->encapsulation counter (sort of local ttl),
6d0722a2c   Eric Dumazet   ip_gre: comments ...
58
     and silently drop packet when it expires. It is a good
bff528578   stephen hemminger   gre: fix spelling...
59
     solution, but it supposes maintaining new variable in ALL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
     skb, even if no tunneling is used.
6d0722a2c   Eric Dumazet   ip_gre: comments ...
61
62
63
     Current solution: xmit_recursion breaks dead loops. This is a percpu
     counter, since when we enter the first ndo_xmit(), cpu migration is
     forbidden. We force an exit if this counter reaches RECURSION_LIMIT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  
     2. Networking dead loops would not kill routers, but would really
     kill network. IP hop limit plays role of "t->recursion" in this case,
     if we copy it from packet being encapsulated to upper header.
     It is very good solution, but it introduces two problems:
  
     - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
       do not work over tunnels.
     - traceroute does not work. I planned to relay ICMP from tunnel,
       so that this problem would be solved and traceroute output
       would even more informative. This idea appeared to be wrong:
       only Linux complies to rfc1812 now (yes, guys, Linux is the only
       true router now :-)), all routers (at least, in neighbourhood of mine)
       return only 8 bytes of payload. It is the end.
  
     Hence, if we want that OSPF worked or traceroute said something reasonable,
     we should search for another solution.
  
     One of them is to parse packet trying to detect inner encapsulation
     made by our node. It is difficult or even impossible, especially,
bff528578   stephen hemminger   gre: fix spelling...
84
     taking into account fragmentation. TO be short, ttl is not solution at all.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
90
  
     Current solution: The solution was UNEXPECTEDLY SIMPLE.
     We force DF flag on tunnels with preconfigured hop limit,
     that is ALL. :-) Well, it does not remove the problem completely,
     but exponential growth of network traffic is changed to linear
     (branches, that exceed pmtu are pruned) and tunnel mtu
bff528578   stephen hemminger   gre: fix spelling...
91
     rapidly degrades to value <68, where looping stops.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
     Yes, it is not good if there exists a router in the loop,
     which does not force DF, even when encapsulating packets have DF set.
     But it is not our problem! Nobody could accuse us, we made
     all that we could make. Even if it is your gated who injected
     fatal route to network, even if it were you who configured
     fatal static route: you are innocent. :-)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
     Alexey Kuznetsov.
   */
eccc1bb8d   stephen hemminger   tunnel: drop pack...
100
101
102
  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");
c19e654dd   Herbert Xu   gre: Add netlink ...
103
  static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  static int ipgre_tunnel_init(struct net_device *dev);
1a66a836d   William Tu   gre: add collect_...
105
  static void erspan_build_header(struct sk_buff *skb,
c69de58ba   William Tu   net: erspan: use ...
106
  				u32 id, u32 index,
a3222dc95   William Tu   ip_gre: Refector ...
107
  				bool truncate, bool is_ipv4);
eb8ce741a   Pavel Emelyanov   [GRE]: Make tunne...
108

c7d03a00b   Alexey Dobriyan   netns: make struc...
109
110
  static unsigned int ipgre_net_id __read_mostly;
  static unsigned int gre_tap_net_id __read_mostly;
84e54fe0a   William Tu   gre: introduce na...
111
  static unsigned int erspan_net_id __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

32bbd8793   Stefano Brivio   net: Convert prot...
113
114
  static int ipgre_err(struct sk_buff *skb, u32 info,
  		     const struct tnl_ptk_info *tpi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

c54419321   Pravin B Shelar   GRE: Refactor GRE...
117
118
119
  	/* All the routers (except for Linux) return only
  	   8 bytes of packet payload. It means, that precise relaying of
  	   ICMP in the real Internet is absolutely infeasible.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

c54419321   Pravin B Shelar   GRE: Refactor GRE...
121
122
123
124
  	   Moreover, Cisco "wise men" put GRE key to the third word
  	   in GRE header. It makes impossible maintaining even soft
  	   state for keyed GRE tunnels with enabled checksum. Tell
  	   them "thank you".
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125

c54419321   Pravin B Shelar   GRE: Refactor GRE...
126
127
128
129
130
131
  	   Well, I wonder, rfc1812 was written by Cisco employee,
  	   what the hell these idiots break standards established
  	   by themselves???
  	   */
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn;
96f5a846b   Eric Dumazet   ip_gre: fix a pos...
132
  	const struct iphdr *iph;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
133
134
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
135
  	unsigned int data_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  	struct ip_tunnel *t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

32bbd8793   Stefano Brivio   net: Convert prot...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	if (tpi->proto == htons(ETH_P_TEB))
  		itn = net_generic(net, gre_tap_net_id);
  	else if (tpi->proto == htons(ETH_P_ERSPAN) ||
  		 tpi->proto == htons(ETH_P_ERSPAN2))
  		itn = net_generic(net, erspan_net_id);
  	else
  		itn = net_generic(net, ipgre_net_id);
  
  	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
  	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
  			     iph->daddr, iph->saddr, tpi->key);
  
  	if (!t)
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  	switch (type) {
  	default:
  	case ICMP_PARAMETERPROB:
32bbd8793   Stefano Brivio   net: Convert prot...
155
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
161
  
  	case ICMP_DEST_UNREACH:
  		switch (code) {
  		case ICMP_SR_FAILED:
  		case ICMP_PORT_UNREACH:
  			/* Impossible event. */
32bbd8793   Stefano Brivio   net: Convert prot...
162
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
170
  		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;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
171

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
  	case ICMP_TIME_EXCEEDED:
  		if (code != ICMP_EXC_TTL)
32bbd8793   Stefano Brivio   net: Convert prot...
174
  			return 0;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
175
  		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  		break;
55be7a9c6   David S. Miller   ipv4: Add redirec...
177
178
179
  
  	case ICMP_REDIRECT:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  	}
9b8c6d7bf   Eric Dumazet   gre: better suppo...
181
182
  #if IS_ENABLED(CONFIG_IPV6)
         if (tpi->proto == htons(ETH_P_IPV6) &&
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
183
184
             !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
  				       type, data_len))
32bbd8793   Stefano Brivio   net: Convert prot...
185
                 return 0;
9b8c6d7bf   Eric Dumazet   gre: better suppo...
186
  #endif
363933955   David S. Miller   ipv4: Handle PMTU...
187
  	if (t->parms.iph.daddr == 0 ||
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
188
  	    ipv4_is_multicast(t->parms.iph.daddr))
32bbd8793   Stefano Brivio   net: Convert prot...
189
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
  
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
32bbd8793   Stefano Brivio   net: Convert prot...
192
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

da6185d87   Wei Yongjun   gre: used time_be...
194
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
32bbd8793   Stefano Brivio   net: Convert prot...
199
200
  
  	return 0;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  }
  
  static void gre_err(struct sk_buff *skb, u32 info)
  {
  	/* All the routers (except for Linux) return only
  	 * 8 bytes of packet payload. It means, that precise relaying of
  	 * ICMP in the real Internet is absolutely infeasible.
  	 *
  	 * Moreover, Cisco "wise men" put GRE key to the third word
  	 * in GRE header. It makes impossible maintaining even soft
  	 * state for keyed
  	 * GRE tunnels with enabled checksum. Tell them "thank you".
  	 *
  	 * Well, I wonder, rfc1812 was written by Cisco employee,
  	 * what the hell these idiots break standards established
  	 * by themselves???
  	 */
e582615ad   Eric Dumazet   gre: fix error ha...
218
  	const struct iphdr *iph = (struct iphdr *)skb->data;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
219
220
221
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
  	struct tnl_ptk_info tpi;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
222

b0350d51f   Haishuang Yan   ip_gre: fix parsi...
223
224
225
  	if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
  			     iph->ihl * 4) < 0)
  		return;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
226
227
228
  
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
  		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
d888f3966   Maciej Å»enczykowski   net-ipv4: remove ...
229
  				 skb->dev->ifindex, IPPROTO_GRE);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
230
231
232
  		return;
  	}
  	if (type == ICMP_REDIRECT) {
1042caa79   Maciej Å»enczykowski   net-ipv4: remove ...
233
234
  		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
  			      IPPROTO_GRE);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
235
236
237
238
  		return;
  	}
  
  	ipgre_err(skb, info, &tpi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  }
84e54fe0a   William Tu   gre: introduce na...
240
241
242
243
244
  static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
  		      int gre_hdr_len)
  {
  	struct net *net = dev_net(skb->dev);
  	struct metadata_dst *tun_dst = NULL;
1d7e2ed22   William Tu   net: erspan: refa...
245
  	struct erspan_base_hdr *ershdr;
84e54fe0a   William Tu   gre: introduce na...
246
247
  	struct ip_tunnel_net *itn;
  	struct ip_tunnel *tunnel;
84e54fe0a   William Tu   gre: introduce na...
248
  	const struct iphdr *iph;
3df192830   William Tu   net: erspan: fix ...
249
  	struct erspan_md2 *md2;
1d7e2ed22   William Tu   net: erspan: refa...
250
  	int ver;
84e54fe0a   William Tu   gre: introduce na...
251
252
253
  	int len;
  
  	itn = net_generic(net, erspan_net_id);
84e54fe0a   William Tu   gre: introduce na...
254
255
  
  	iph = ip_hdr(skb);
1d7e2ed22   William Tu   net: erspan: refa...
256
  	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
c69de58ba   William Tu   net: erspan: use ...
257
  	ver = ershdr->ver;
84e54fe0a   William Tu   gre: introduce na...
258

84e54fe0a   William Tu   gre: introduce na...
259
260
261
262
263
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
  				  tpi->flags | TUNNEL_KEY,
  				  iph->saddr, iph->daddr, tpi->key);
  
  	if (tunnel) {
1d7e2ed22   William Tu   net: erspan: refa...
264
265
  		len = gre_hdr_len + erspan_hdr_len(ver);
  		if (unlikely(!pskb_may_pull(skb, len)))
ae3e13373   William Tu   net: erspan: fix ...
266
  			return PACKET_REJECT;
1d7e2ed22   William Tu   net: erspan: refa...
267

84e54fe0a   William Tu   gre: introduce na...
268
  		if (__iptunnel_pull_header(skb,
1d7e2ed22   William Tu   net: erspan: refa...
269
  					   len,
84e54fe0a   William Tu   gre: introduce na...
270
271
272
  					   htons(ETH_P_TEB),
  					   false, false) < 0)
  			goto drop;
1a66a836d   William Tu   gre: add collect_...
273
  		if (tunnel->collect_md) {
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
274
  			struct erspan_metadata *pkt_md, *md;
1a66a836d   William Tu   gre: add collect_...
275
  			struct ip_tunnel_info *info;
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
276
  			unsigned char *gh;
1a66a836d   William Tu   gre: add collect_...
277
278
279
280
281
282
283
284
285
286
287
  			__be64 tun_id;
  			__be16 flags;
  
  			tpi->flags |= TUNNEL_KEY;
  			flags = tpi->flags;
  			tun_id = key32_to_tunnel_id(tpi->key);
  
  			tun_dst = ip_tun_rx_dst(skb, flags,
  						tun_id, sizeof(*md));
  			if (!tun_dst)
  				return PACKET_REJECT;
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
288
289
290
291
292
293
294
295
  			/* skb can be uncloned in __iptunnel_pull_header, so
  			 * old pkt_md is no longer valid and we need to reset
  			 * it
  			 */
  			gh = skb_network_header(skb) +
  			     skb_network_header_len(skb);
  			pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
  							    sizeof(*ershdr));
1a66a836d   William Tu   gre: add collect_...
296
  			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
f551c91de   William Tu   net: erspan: intr...
297
  			md->version = ver;
3df192830   William Tu   net: erspan: fix ...
298
299
300
  			md2 = &md->u.md2;
  			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
  						       ERSPAN_V2_MDSIZE);
f551c91de   William Tu   net: erspan: intr...
301

1a66a836d   William Tu   gre: add collect_...
302
303
304
  			info = &tun_dst->u.tun_info;
  			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
  			info->options_len = sizeof(*md);
1a66a836d   William Tu   gre: add collect_...
305
  		}
84e54fe0a   William Tu   gre: introduce na...
306
307
308
309
  		skb_reset_mac_header(skb);
  		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
  		return PACKET_RCVD;
  	}
5a64506b5   Haishuang Yan   erspan: return PA...
310
  	return PACKET_REJECT;
84e54fe0a   William Tu   gre: introduce na...
311
312
313
314
  drop:
  	kfree_skb(skb);
  	return PACKET_RCVD;
  }
125372faa   Jiri Benc   gre: receive also...
315
316
  static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
  		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
318
  	struct metadata_dst *tun_dst = NULL;
b71d1d426   Eric Dumazet   inet: constify ip...
319
  	const struct iphdr *iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	struct ip_tunnel *tunnel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

c54419321   Pravin B Shelar   GRE: Refactor GRE...
322
  	iph = ip_hdr(skb);
bda7bb463   Pravin B Shelar   gre: Allow multip...
323
324
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
  				  iph->saddr, iph->daddr, tpi->key);
e1a800022   Herbert Xu   gre: Add Transpar...
325

d20832876   stephen hemminger   gre: fix handling...
326
  	if (tunnel) {
125372faa   Jiri Benc   gre: receive also...
327
328
  		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
  					   raw_proto, false) < 0)
244a797bd   Jiri Benc   gre: move iptunne...
329
  			goto drop;
e271c7b44   Jiri Benc   gre: do not keep ...
330
331
332
333
  		if (tunnel->dev->type != ARPHRD_NONE)
  			skb_pop_mac_header(skb);
  		else
  			skb_reset_mac_header(skb);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
334
  		if (tunnel->collect_md) {
c29a70d2c   Pravin B Shelar   tunnel: introduce...
335
336
  			__be16 flags;
  			__be64 tun_id;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
337

c29a70d2c   Pravin B Shelar   tunnel: introduce...
338
  			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
d817f432c   Amir Vadai   net/ip_tunnels: I...
339
  			tun_id = key32_to_tunnel_id(tpi->key);
c29a70d2c   Pravin B Shelar   tunnel: introduce...
340
  			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
341
342
  			if (!tun_dst)
  				return PACKET_REJECT;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
343
344
345
  		}
  
  		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
bda7bb463   Pravin B Shelar   gre: Allow multip...
346
  		return PACKET_RCVD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  	}
125372faa   Jiri Benc   gre: receive also...
348
  	return PACKET_NEXT;
244a797bd   Jiri Benc   gre: move iptunne...
349
350
351
352
  
  drop:
  	kfree_skb(skb);
  	return PACKET_RCVD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  }
125372faa   Jiri Benc   gre: receive also...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
  		     int hdr_len)
  {
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn;
  	int res;
  
  	if (tpi->proto == htons(ETH_P_TEB))
  		itn = net_generic(net, gre_tap_net_id);
  	else
  		itn = net_generic(net, ipgre_net_id);
  
  	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
  	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
  		/* ipgre tunnels in collect metadata mode should receive
  		 * also ETH_P_TEB traffic.
  		 */
  		itn = net_generic(net, ipgre_net_id);
  		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
  	}
  	return res;
  }
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
376
377
378
379
  static int gre_rcv(struct sk_buff *skb)
  {
  	struct tnl_ptk_info tpi;
  	bool csum_err = false;
95f5c64c3   Tom Herbert   gre: Move utility...
380
  	int hdr_len;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
381
382
383
384
385
386
387
388
  
  #ifdef CONFIG_NET_IPGRE_BROADCAST
  	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
  		/* Looped back packet, drop it! */
  		if (rt_is_output_route(skb_rtable(skb)))
  			goto drop;
  	}
  #endif
e582615ad   Eric Dumazet   gre: fix error ha...
389
  	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
f132ae7c4   Jiri Benc   gre: change gre_p...
390
  	if (hdr_len < 0)
95f5c64c3   Tom Herbert   gre: Move utility...
391
  		goto drop;
f551c91de   William Tu   net: erspan: intr...
392
393
  	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
  		     tpi.proto == htons(ETH_P_ERSPAN2))) {
84e54fe0a   William Tu   gre: introduce na...
394
395
  		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
  			return 0;
dd8d5b8c5   Haishuang Yan   ip_gre: fix error...
396
  		goto out;
84e54fe0a   William Tu   gre: introduce na...
397
  	}
244a797bd   Jiri Benc   gre: move iptunne...
398
  	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
399
  		return 0;
dd8d5b8c5   Haishuang Yan   ip_gre: fix error...
400
  out:
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
401
402
403
404
405
  	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
  drop:
  	kfree_skb(skb);
  	return 0;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
406
407
408
409
410
  static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
  		       const struct iphdr *tnl_params,
  		       __be16 proto)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

c54419321   Pravin B Shelar   GRE: Refactor GRE...
412
413
  	if (tunnel->parms.o_flags & TUNNEL_SEQ)
  		tunnel->o_seqno++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414

c54419321   Pravin B Shelar   GRE: Refactor GRE...
415
  	/* Push GRE header. */
182a352d2   Tom Herbert   gre: Create commo...
416
417
418
  	gre_build_header(skb, tunnel->tun_hlen,
  			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
  			 htonl(tunnel->o_seqno));
54bc9bac3   Tom Herbert   gre: Set inner pr...
419

bf3d6a8f7   Nicolas Dichtel   iptunnel: specify...
420
  	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
421
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

aed069df0   Alexander Duyck   ip_tunnel_core: i...
423
  static int gre_handle_offloads(struct sk_buff *skb, bool csum)
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
424
  {
6fa79666e   Edward Cree   net: ip_tunnel: r...
425
  	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
426
  }
862a03c35   William Tu   gre: refactor the...
427
428
429
  static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
  			__be16 proto)
  {
77a5196a8   William Tu   gre: add sequence...
430
  	struct ip_tunnel *tunnel = netdev_priv(dev);
862a03c35   William Tu   gre: refactor the...
431
432
  	struct ip_tunnel_info *tun_info;
  	const struct ip_tunnel_key *key;
862a03c35   William Tu   gre: refactor the...
433
  	int tunnel_hlen;
962924fa2   wenxu   ip_gre: Refactor ...
434
  	__be16 flags;
862a03c35   William Tu   gre: refactor the...
435
436
437
438
439
440
441
442
  
  	tun_info = skb_tunnel_info(skb);
  	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
  		     ip_tunnel_info_af(tun_info) != AF_INET))
  		goto err_free_skb;
  
  	key = &tun_info->key;
  	tunnel_hlen = gre_calc_hlen(key->tun_flags);
962924fa2   wenxu   ip_gre: Refactor ...
443
444
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto err_free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
445
446
  
  	/* Push Tunnel header. */
aed069df0   Alexander Duyck   ip_tunnel_core: i...
447
  	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
962924fa2   wenxu   ip_gre: Refactor ...
448
  		goto err_free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
449

77a5196a8   William Tu   gre: add sequence...
450
451
  	flags = tun_info->key.tun_flags &
  		(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
cba653210   David S. Miller   Merge git://git.k...
452
  	gre_build_header(skb, tunnel_hlen, flags, proto,
77a5196a8   William Tu   gre: add sequence...
453
  			 tunnel_id_to_key32(tun_info->key.tun_id),
157463941   Colin Ian King   gre: fix TUNNEL_S...
454
  			 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
455

962924fa2   wenxu   ip_gre: Refactor ...
456
  	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
457

2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
458
  	return;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
459
460
461
462
  err_free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  }
20704bd16   Xin Long   erspan: build the...
463
  static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
1a66a836d   William Tu   gre: add collect_...
464
465
466
467
468
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct ip_tunnel_info *tun_info;
  	const struct ip_tunnel_key *key;
  	struct erspan_metadata *md;
1a66a836d   William Tu   gre: add collect_...
469
  	bool truncate = false;
962924fa2   wenxu   ip_gre: Refactor ...
470
  	__be16 proto;
1a66a836d   William Tu   gre: add collect_...
471
  	int tunnel_hlen;
f551c91de   William Tu   net: erspan: intr...
472
  	int version;
1baf5ebf8   William Tu   erspan: auto dete...
473
  	int nhoff;
d5db21a3e   William Tu   erspan: auto dete...
474
  	int thoff;
1a66a836d   William Tu   gre: add collect_...
475
476
477
478
479
480
481
  
  	tun_info = skb_tunnel_info(skb);
  	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
  		     ip_tunnel_info_af(tun_info) != AF_INET))
  		goto err_free_skb;
  
  	key = &tun_info->key;
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
482
  	if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
962924fa2   wenxu   ip_gre: Refactor ...
483
  		goto err_free_skb;
2eb8d6d29   Xin Long   erspan: fix the t...
484
  	if (tun_info->options_len < sizeof(*md))
962924fa2   wenxu   ip_gre: Refactor ...
485
  		goto err_free_skb;
2eb8d6d29   Xin Long   erspan: fix the t...
486
  	md = ip_tunnel_info_opts(tun_info);
1a66a836d   William Tu   gre: add collect_...
487
488
  
  	/* ERSPAN has fixed 8 byte GRE header */
f551c91de   William Tu   net: erspan: intr...
489
490
  	version = md->version;
  	tunnel_hlen = 8 + erspan_hdr_len(version);
1a66a836d   William Tu   gre: add collect_...
491

962924fa2   wenxu   ip_gre: Refactor ...
492
493
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto err_free_skb;
1a66a836d   William Tu   gre: add collect_...
494
495
  
  	if (gre_handle_offloads(skb, false))
962924fa2   wenxu   ip_gre: Refactor ...
496
  		goto err_free_skb;
1a66a836d   William Tu   gre: add collect_...
497

f192970de   William Tu   ip_gre: check pac...
498
499
  	if (skb->len > dev->mtu + dev->hard_header_len) {
  		pskb_trim(skb, dev->mtu + dev->hard_header_len);
1a66a836d   William Tu   gre: add collect_...
500
501
  		truncate = true;
  	}
1baf5ebf8   William Tu   erspan: auto dete...
502
503
504
505
  	nhoff = skb_network_header(skb) - skb_mac_header(skb);
  	if (skb->protocol == htons(ETH_P_IP) &&
  	    (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
  		truncate = true;
d5db21a3e   William Tu   erspan: auto dete...
506
507
508
509
510
  
  	thoff = skb_transport_header(skb) - skb_mac_header(skb);
  	if (skb->protocol == htons(ETH_P_IPV6) &&
  	    (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
  		truncate = true;
1baf5ebf8   William Tu   erspan: auto dete...
511

f551c91de   William Tu   net: erspan: intr...
512
  	if (version == 1) {
c69de58ba   William Tu   net: erspan: use ...
513
  		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
f551c91de   William Tu   net: erspan: intr...
514
  				    ntohl(md->u.index), truncate, true);
20704bd16   Xin Long   erspan: build the...
515
  		proto = htons(ETH_P_ERSPAN);
f551c91de   William Tu   net: erspan: intr...
516
  	} else if (version == 2) {
c69de58ba   William Tu   net: erspan: use ...
517
518
519
520
521
  		erspan_build_header_v2(skb,
  				       ntohl(tunnel_id_to_key32(key->tun_id)),
  				       md->u.md2.dir,
  				       get_hwid(&md->u.md2),
  				       truncate, true);
20704bd16   Xin Long   erspan: build the...
522
  		proto = htons(ETH_P_ERSPAN2);
f551c91de   William Tu   net: erspan: intr...
523
  	} else {
962924fa2   wenxu   ip_gre: Refactor ...
524
  		goto err_free_skb;
f551c91de   William Tu   net: erspan: intr...
525
  	}
1a66a836d   William Tu   gre: add collect_...
526
527
  
  	gre_build_header(skb, 8, TUNNEL_SEQ,
20704bd16   Xin Long   erspan: build the...
528
  			 proto, 0, htonl(tunnel->o_seqno++));
1a66a836d   William Tu   gre: add collect_...
529

962924fa2   wenxu   ip_gre: Refactor ...
530
  	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
1a66a836d   William Tu   gre: add collect_...
531

1a66a836d   William Tu   gre: add collect_...
532
  	return;
1a66a836d   William Tu   gre: add collect_...
533
534
535
536
  err_free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  }
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
537
538
539
  static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
  {
  	struct ip_tunnel_info *info = skb_tunnel_info(skb);
962924fa2   wenxu   ip_gre: Refactor ...
540
  	const struct ip_tunnel_key *key;
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
541
542
543
544
545
  	struct rtable *rt;
  	struct flowi4 fl4;
  
  	if (ip_tunnel_info_af(info) != AF_INET)
  		return -EINVAL;
962924fa2   wenxu   ip_gre: Refactor ...
546
547
548
  	key = &info->key;
  	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
  			    tunnel_id_to_key32(key->tun_id), key->tos, 0,
24ba14406   wenxu   route: Add multip...
549
  			    skb->mark, skb_get_hash(skb));
962924fa2   wenxu   ip_gre: Refactor ...
550
  	rt = ip_route_output_key(dev_net(dev), &fl4);
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
551
552
553
554
555
556
557
  	if (IS_ERR(rt))
  		return PTR_ERR(rt);
  
  	ip_rt_put(rt);
  	info->key.u.ipv4.src = fl4.saddr;
  	return 0;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
558
559
560
561
562
  static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
  			      struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	const struct iphdr *tnl_params;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563

cb9f1b783   Willem de Bruijn   ip: validate head...
564
565
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
566
  	if (tunnel->collect_md) {
2090714e1   Jiri Benc   gre: build header...
567
  		gre_fb_xmit(skb, dev, skb->protocol);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
568
569
  		return NETDEV_TX_OK;
  	}
c54419321   Pravin B Shelar   GRE: Refactor GRE...
570
571
572
  	if (dev->header_ops) {
  		/* Need space for new headers */
  		if (skb_cow_head(skb, dev->needed_headroom -
2bac7cb31   Chen Gang   net: ipv4: typo i...
573
  				      (tunnel->hlen + sizeof(struct iphdr))))
c54419321   Pravin B Shelar   GRE: Refactor GRE...
574
  			goto free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575

c54419321   Pravin B Shelar   GRE: Refactor GRE...
576
  		tnl_params = (const struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577

c54419321   Pravin B Shelar   GRE: Refactor GRE...
578
579
580
581
  		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
  		 * to gre header.
  		 */
  		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
8a0033a94   Timo Teräs   gre: fix the inne...
582
  		skb_reset_mac_header(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
583
584
585
  	} else {
  		if (skb_cow_head(skb, dev->needed_headroom))
  			goto free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586

c54419321   Pravin B Shelar   GRE: Refactor GRE...
587
  		tnl_params = &tunnel->parms.iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  	}
aed069df0   Alexander Duyck   ip_tunnel_core: i...
589
590
  	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
  		goto free_skb;
8a0033a94   Timo Teräs   gre: fix the inne...
591

c54419321   Pravin B Shelar   GRE: Refactor GRE...
592
  	__gre_xmit(skb, dev, tnl_params, skb->protocol);
6ed106549   Patrick McHardy   net: use NETDEV_T...
593
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

c54419321   Pravin B Shelar   GRE: Refactor GRE...
595
  free_skb:
3acfa1e73   Eric Dumazet   ipv4: be friend w...
596
  	kfree_skb(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
597
  	dev->stats.tx_dropped++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
598
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
  }
84e54fe0a   William Tu   gre: introduce na...
600
601
602
603
604
  static netdev_tx_t erspan_xmit(struct sk_buff *skb,
  			       struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	bool truncate = false;
20704bd16   Xin Long   erspan: build the...
605
  	__be16 proto;
84e54fe0a   William Tu   gre: introduce na...
606

cb9f1b783   Willem de Bruijn   ip: validate head...
607
608
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
1a66a836d   William Tu   gre: add collect_...
609
  	if (tunnel->collect_md) {
20704bd16   Xin Long   erspan: build the...
610
  		erspan_fb_xmit(skb, dev);
1a66a836d   William Tu   gre: add collect_...
611
612
  		return NETDEV_TX_OK;
  	}
84e54fe0a   William Tu   gre: introduce na...
613
614
615
616
617
  	if (gre_handle_offloads(skb, false))
  		goto free_skb;
  
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto free_skb;
f192970de   William Tu   ip_gre: check pac...
618
619
  	if (skb->len > dev->mtu + dev->hard_header_len) {
  		pskb_trim(skb, dev->mtu + dev->hard_header_len);
84e54fe0a   William Tu   gre: introduce na...
620
621
622
623
  		truncate = true;
  	}
  
  	/* Push ERSPAN header */
20704bd16   Xin Long   erspan: build the...
624
  	if (tunnel->erspan_ver == 1) {
c69de58ba   William Tu   net: erspan: use ...
625
626
  		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
  				    tunnel->index,
f551c91de   William Tu   net: erspan: intr...
627
  				    truncate, true);
20704bd16   Xin Long   erspan: build the...
628
629
  		proto = htons(ETH_P_ERSPAN);
  	} else if (tunnel->erspan_ver == 2) {
c69de58ba   William Tu   net: erspan: use ...
630
  		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
f551c91de   William Tu   net: erspan: intr...
631
632
  				       tunnel->dir, tunnel->hwid,
  				       truncate, true);
20704bd16   Xin Long   erspan: build the...
633
634
  		proto = htons(ETH_P_ERSPAN2);
  	} else {
02f99df18   William Tu   erspan: fix inval...
635
  		goto free_skb;
20704bd16   Xin Long   erspan: build the...
636
  	}
f551c91de   William Tu   net: erspan: intr...
637

84e54fe0a   William Tu   gre: introduce na...
638
  	tunnel->parms.o_flags &= ~TUNNEL_KEY;
20704bd16   Xin Long   erspan: build the...
639
  	__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
84e54fe0a   William Tu   gre: introduce na...
640
641
642
643
644
645
646
  	return NETDEV_TX_OK;
  
  free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  	return NETDEV_TX_OK;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
647
648
  static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
  				struct net_device *dev)
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
649
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
650
  	struct ip_tunnel *tunnel = netdev_priv(dev);
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
651

cb9f1b783   Willem de Bruijn   ip: validate head...
652
653
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
654
  	if (tunnel->collect_md) {
2090714e1   Jiri Benc   gre: build header...
655
  		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
656
657
  		return NETDEV_TX_OK;
  	}
aed069df0   Alexander Duyck   ip_tunnel_core: i...
658
659
  	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
  		goto free_skb;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
660

c54419321   Pravin B Shelar   GRE: Refactor GRE...
661
662
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto free_skb;
42aa91626   Herbert Xu   gre: Move MTU set...
663

c54419321   Pravin B Shelar   GRE: Refactor GRE...
664
  	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
c54419321   Pravin B Shelar   GRE: Refactor GRE...
665
  	return NETDEV_TX_OK;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
666

c54419321   Pravin B Shelar   GRE: Refactor GRE...
667
  free_skb:
3acfa1e73   Eric Dumazet   ipv4: be friend w...
668
  	kfree_skb(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
669
670
  	dev->stats.tx_dropped++;
  	return NETDEV_TX_OK;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
671
  }
dd9d598c6   Xin Long   ip_gre: add the s...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
  static void ipgre_link_update(struct net_device *dev, bool set_mtu)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	int len;
  
  	len = tunnel->tun_hlen;
  	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
  	len = tunnel->tun_hlen - len;
  	tunnel->hlen = tunnel->hlen + len;
  
  	dev->needed_headroom = dev->needed_headroom + len;
  	if (set_mtu)
  		dev->mtu = max_t(int, dev->mtu - len, 68);
  
  	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
  		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
  		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
  			dev->features |= NETIF_F_GSO_SOFTWARE;
  			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1cc5954f4   Sabrina Dubroca   ip_gre: clear fea...
691
692
693
  		} else {
  			dev->features &= ~NETIF_F_GSO_SOFTWARE;
  			dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
dd9d598c6   Xin Long   ip_gre: add the s...
694
695
  		}
  		dev->features |= NETIF_F_LLTX;
1cc5954f4   Sabrina Dubroca   ip_gre: clear fea...
696
697
698
  	} else {
  		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
  		dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
dd9d598c6   Xin Long   ip_gre: add the s...
699
700
  	}
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
701
702
  static int ipgre_tunnel_ioctl(struct net_device *dev,
  			      struct ifreq *ifr, int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  	struct ip_tunnel_parm p;
a0efab67a   Xin Long   ip_gre: add the s...
705
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706

c54419321   Pravin B Shelar   GRE: Refactor GRE...
707
708
  	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  		return -EFAULT;
a0efab67a   Xin Long   ip_gre: add the s...
709

6c734fb85   Cong Wang   gre: fix a regres...
710
711
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
  		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
a0efab67a   Xin Long   ip_gre: add the s...
712
713
  		    p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
  		    ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
6c734fb85   Cong Wang   gre: fix a regres...
714
  			return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  	}
a0efab67a   Xin Long   ip_gre: add the s...
716

c54419321   Pravin B Shelar   GRE: Refactor GRE...
717
718
  	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
  	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719

c54419321   Pravin B Shelar   GRE: Refactor GRE...
720
721
722
  	err = ip_tunnel_ioctl(dev, &p, cmd);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723

a0efab67a   Xin Long   ip_gre: add the s...
724
725
726
727
728
729
730
731
732
  	if (cmd == SIOCCHGTUNNEL) {
  		struct ip_tunnel *t = netdev_priv(dev);
  
  		t->parms.i_flags = p.i_flags;
  		t->parms.o_flags = p.o_flags;
  
  		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
  			ipgre_link_update(dev, true);
  	}
95f5c64c3   Tom Herbert   gre: Move utility...
733
734
  	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
  	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
735
736
737
  
  	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
  		return -EFAULT;
a0efab67a   Xin Long   ip_gre: add the s...
738

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
743
744
745
746
747
748
749
  /* Nice toy. Unfortunately, useless in real life :-)
     It allows to construct virtual multiprotocol broadcast "LAN"
     over the Internet, provided multicast routing is tuned.
  
  
     I have no idea was this bicycle invented before me,
     so that I had to set ARPHRD_IPGRE to a random value.
     I have an impression, that Cisco could make something similar,
     but this feature is apparently missing in IOS<=11.2(8).
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
750

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
     I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
     with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
  
     ping -t 255 224.66.66.66
  
     If nobody answers, mbone does not work.
  
     ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
     ip addr add 10.66.66.<somewhat>/24 dev Universe
     ifconfig Universe up
     ifconfig Universe add fe80::<Your_real_addr>/10
     ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
     ftp 10.66.66.66
     ...
     ftp fec0:6666:6666::193.233.7.65
     ...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
   */
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
768
769
  static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
  			unsigned short type,
1507850b4   Eric Dumazet   gre: get rid of i...
770
  			const void *daddr, const void *saddr, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
772
  	struct ip_tunnel *t = netdev_priv(dev);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
773
774
  	struct iphdr *iph;
  	struct gre_base_hdr *greh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775

d58ff3512   Johannes Berg   networking: make ...
776
  	iph = skb_push(skb, t->hlen + sizeof(*iph));
c54419321   Pravin B Shelar   GRE: Refactor GRE...
777
  	greh = (struct gre_base_hdr *)(iph+1);
95f5c64c3   Tom Herbert   gre: Move utility...
778
  	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
779
  	greh->protocol = htons(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780

c54419321   Pravin B Shelar   GRE: Refactor GRE...
781
  	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
782

c54419321   Pravin B Shelar   GRE: Refactor GRE...
783
  	/* Set the source hardware address. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
  	if (saddr)
  		memcpy(&iph->saddr, saddr, 4);
6d55cb91a   Timo Teräs   gre: fix hard hea...
786
  	if (daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  		memcpy(&iph->daddr, daddr, 4);
6d55cb91a   Timo Teräs   gre: fix hard hea...
788
  	if (iph->daddr)
77a482bdb   Timo Teräs   ip_gre: fix ipgre...
789
  		return t->hlen + sizeof(*iph);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
790

c54419321   Pravin B Shelar   GRE: Refactor GRE...
791
  	return -(t->hlen + sizeof(*iph));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  }
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
793
794
  static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
795
  	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
796
797
798
  	memcpy(haddr, &iph->saddr, 4);
  	return 4;
  }
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
799
800
  static const struct header_ops ipgre_header_ops = {
  	.create	= ipgre_header,
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
801
  	.parse	= ipgre_header_parse,
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
802
  };
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
803
  #ifdef CONFIG_NET_IPGRE_BROADCAST
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
805
  static int ipgre_open(struct net_device *dev)
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
806
  	struct ip_tunnel *t = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807

f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
808
  	if (ipv4_is_multicast(t->parms.iph.daddr)) {
cbb1e85f9   David S. Miller   ipv4: Kill rt->rt...
809
810
  		struct flowi4 fl4;
  		struct rtable *rt;
b57708add   Nicolas Dichtel   gre: add x-netns ...
811
  		rt = ip_route_output_gre(t->net, &fl4,
cbb1e85f9   David S. Miller   ipv4: Kill rt->rt...
812
813
814
815
816
  					 t->parms.iph.daddr,
  					 t->parms.iph.saddr,
  					 t->parms.o_key,
  					 RT_TOS(t->parms.iph.tos),
  					 t->parms.link);
b23dd4fe4   David S. Miller   ipv4: Make output...
817
  		if (IS_ERR(rt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
  			return -EADDRNOTAVAIL;
d8d1f30b9   Changli Gao   net-next: remove ...
819
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  		ip_rt_put(rt);
51456b291   Ian Morris   ipv4: coding styl...
821
  		if (!__in_dev_get_rtnl(dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  			return -EADDRNOTAVAIL;
  		t->mlink = dev->ifindex;
e5ed63991   Herbert Xu   [IPV4]: Replace _...
824
  		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
826
827
828
829
830
  	}
  	return 0;
  }
  
  static int ipgre_close(struct net_device *dev)
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
831
  	struct ip_tunnel *t = netdev_priv(dev);
b8c26a33c   Stephen Hemminger   ipgre: convert to...
832

f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
833
  	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
7fee0ca23   Denis V. Lunev   [NETNS]: Add netn...
834
  		struct in_device *in_dev;
b57708add   Nicolas Dichtel   gre: add x-netns ...
835
  		in_dev = inetdev_by_index(t->net, t->mlink);
8723e1b4a   Eric Dumazet   inet: RCU changes...
836
  		if (in_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  #endif
b8c26a33c   Stephen Hemminger   ipgre: convert to...
842
843
  static const struct net_device_ops ipgre_netdev_ops = {
  	.ndo_init		= ipgre_tunnel_init,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
844
  	.ndo_uninit		= ip_tunnel_uninit,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
845
846
847
848
  #ifdef CONFIG_NET_IPGRE_BROADCAST
  	.ndo_open		= ipgre_open,
  	.ndo_stop		= ipgre_close,
  #endif
c54419321   Pravin B Shelar   GRE: Refactor GRE...
849
  	.ndo_start_xmit		= ipgre_xmit,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
850
  	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
851
852
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
853
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
854
  };
6b78f16e4   Eric Dumazet   gre: add GSO support
855
856
857
858
  #define GRE_FEATURES (NETIF_F_SG |		\
  		      NETIF_F_FRAGLIST |	\
  		      NETIF_F_HIGHDMA |		\
  		      NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
  static void ipgre_tunnel_setup(struct net_device *dev)
  {
b8c26a33c   Stephen Hemminger   ipgre: convert to...
861
  	dev->netdev_ops		= &ipgre_netdev_ops;
5a4552752   Nicolas Dichtel   gre: don't allow ...
862
  	dev->type		= ARPHRD_IPGRE;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
863
864
  	ip_tunnel_setup(dev, ipgre_net_id);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865

c54419321   Pravin B Shelar   GRE: Refactor GRE...
866
867
868
869
870
  static void __gre_tunnel_init(struct net_device *dev)
  {
  	struct ip_tunnel *tunnel;
  
  	tunnel = netdev_priv(dev);
95f5c64c3   Tom Herbert   gre: Move utility...
871
  	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
872
  	tunnel->parms.iph.protocol = IPPROTO_GRE;
4565e9919   Tom Herbert   gre: Setup and TX...
873
  	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
b57708add   Nicolas Dichtel   gre: add x-netns ...
874
  	dev->features		|= GRE_FEATURES;
6b78f16e4   Eric Dumazet   gre: add GSO support
875
  	dev->hw_features	|= GRE_FEATURES;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
876
877
  
  	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
a0ca153f9   Alexander Duyck   GRE: Disable segm...
878
879
880
881
882
883
884
885
886
  		/* TCP offload with GRE SEQ is not supported, nor
  		 * can we support 2 levels of outer headers requiring
  		 * an update.
  		 */
  		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
  		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
  			dev->features    |= NETIF_F_GSO_SOFTWARE;
  			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
  		}
c54419321   Pravin B Shelar   GRE: Refactor GRE...
887
888
889
890
891
  		/* Can use a lockless transmit, unless we generate
  		 * output sequences
  		 */
  		dev->features |= NETIF_F_LLTX;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
895
  }
  
  static int ipgre_tunnel_init(struct net_device *dev)
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
896
897
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898

c54419321   Pravin B Shelar   GRE: Refactor GRE...
899
  	__gre_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900

c54419321   Pravin B Shelar   GRE: Refactor GRE...
901
902
  	memcpy(dev->dev_addr, &iph->saddr, 4);
  	memcpy(dev->broadcast, &iph->daddr, 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

c54419321   Pravin B Shelar   GRE: Refactor GRE...
904
  	dev->flags		= IFF_NOARP;
028758788   Eric Dumazet   net: better IFF_X...
905
  	netif_keep_dst(dev);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
906
  	dev->addr_len		= 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907

a64b04d86   Jiri Benc   gre: do not assig...
908
  	if (iph->daddr && !tunnel->collect_md) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
  #ifdef CONFIG_NET_IPGRE_BROADCAST
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
910
  		if (ipv4_is_multicast(iph->daddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
  			if (!iph->saddr)
  				return -EINVAL;
  			dev->flags = IFF_BROADCAST;
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
914
  			dev->header_ops = &ipgre_header_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
  		}
  #endif
a64b04d86   Jiri Benc   gre: do not assig...
917
  	} else if (!tunnel->collect_md) {
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
918
  		dev->header_ops = &ipgre_header_ops;
a64b04d86   Jiri Benc   gre: do not assig...
919
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920

c54419321   Pravin B Shelar   GRE: Refactor GRE...
921
  	return ip_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
  }
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
923
924
925
  static const struct gre_protocol ipgre_protocol = {
  	.handler     = gre_rcv,
  	.err_handler = gre_err,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
927
  static int __net_init ipgre_init_net(struct net *net)
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
928
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
929
  	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
930
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
931
  static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
932
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
933
  	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
934
935
936
937
  }
  
  static struct pernet_operations ipgre_net_ops = {
  	.init = ipgre_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
938
  	.exit_batch = ipgre_exit_batch_net,
cfb8fbf22   Eric W. Biederman   net: Simplify ip_...
939
  	.id   = &ipgre_net_id,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
940
  	.size = sizeof(struct ip_tunnel_net),
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
941
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942

a8b8a889e   Matthias Schiffer   net: add netlink_...
943
944
  static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  				 struct netlink_ext_ack *extack)
c19e654dd   Herbert Xu   gre: Add netlink ...
945
946
947
948
949
950
951
952
953
954
955
956
957
  {
  	__be16 flags;
  
  	if (!data)
  		return 0;
  
  	flags = 0;
  	if (data[IFLA_GRE_IFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
  	if (data[IFLA_GRE_OFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
  	if (flags & (GRE_VERSION|GRE_ROUTING))
  		return -EINVAL;
946b636f1   Jiri Benc   gre: reject GUE a...
958
959
960
961
  	if (data[IFLA_GRE_COLLECT_METADATA] &&
  	    data[IFLA_GRE_ENCAP_TYPE] &&
  	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
  		return -EINVAL;
c19e654dd   Herbert Xu   gre: Add netlink ...
962
963
  	return 0;
  }
a8b8a889e   Matthias Schiffer   net: add netlink_...
964
965
  static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
  			      struct netlink_ext_ack *extack)
e1a800022   Herbert Xu   gre: Add Transpar...
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
  {
  	__be32 daddr;
  
  	if (tb[IFLA_ADDRESS]) {
  		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
  			return -EINVAL;
  		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
  			return -EADDRNOTAVAIL;
  	}
  
  	if (!data)
  		goto out;
  
  	if (data[IFLA_GRE_REMOTE]) {
  		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
  		if (!daddr)
  			return -EINVAL;
  	}
  
  out:
a8b8a889e   Matthias Schiffer   net: add netlink_...
986
  	return ipgre_tunnel_validate(tb, data, extack);
e1a800022   Herbert Xu   gre: Add Transpar...
987
  }
84e54fe0a   William Tu   gre: introduce na...
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
  			   struct netlink_ext_ack *extack)
  {
  	__be16 flags = 0;
  	int ret;
  
  	if (!data)
  		return 0;
  
  	ret = ipgre_tap_validate(tb, data, extack);
  	if (ret)
  		return ret;
  
  	/* ERSPAN should only have GRE sequence and key flag */
1a66a836d   William Tu   gre: add collect_...
1002
1003
1004
1005
1006
1007
  	if (data[IFLA_GRE_OFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
  	if (data[IFLA_GRE_IFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
  	if (!data[IFLA_GRE_COLLECT_METADATA] &&
  	    flags != (GRE_SEQ | GRE_KEY))
84e54fe0a   William Tu   gre: introduce na...
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
  		return -EINVAL;
  
  	/* ERSPAN Session ID only has 10-bit. Since we reuse
  	 * 32-bit key field as ID, check it's range.
  	 */
  	if (data[IFLA_GRE_IKEY] &&
  	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
  		return -EINVAL;
  
  	if (data[IFLA_GRE_OKEY] &&
  	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
  		return -EINVAL;
  
  	return 0;
  }
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1023
  static int ipgre_netlink_parms(struct net_device *dev,
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1024
1025
  				struct nlattr *data[],
  				struct nlattr *tb[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1026
1027
  				struct ip_tunnel_parm *parms,
  				__u32 *fwmark)
c19e654dd   Herbert Xu   gre: Add netlink ...
1028
  {
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1029
  	struct ip_tunnel *t = netdev_priv(dev);
7bb82d924   Herbert Xu   gre: Initialise r...
1030
  	memset(parms, 0, sizeof(*parms));
c19e654dd   Herbert Xu   gre: Add netlink ...
1031
1032
1033
1034
  
  	parms->iph.protocol = IPPROTO_GRE;
  
  	if (!data)
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1035
  		return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1036
1037
1038
1039
1040
  
  	if (data[IFLA_GRE_LINK])
  		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
  
  	if (data[IFLA_GRE_IFLAGS])
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1041
  		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
c19e654dd   Herbert Xu   gre: Add netlink ...
1042
1043
  
  	if (data[IFLA_GRE_OFLAGS])
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1044
  		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
c19e654dd   Herbert Xu   gre: Add netlink ...
1045
1046
1047
1048
1049
1050
1051
1052
  
  	if (data[IFLA_GRE_IKEY])
  		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
  
  	if (data[IFLA_GRE_OKEY])
  		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
  
  	if (data[IFLA_GRE_LOCAL])
67b61f6c1   Jiri Benc   netlink: implemen...
1053
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
c19e654dd   Herbert Xu   gre: Add netlink ...
1054
1055
  
  	if (data[IFLA_GRE_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
1056
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
c19e654dd   Herbert Xu   gre: Add netlink ...
1057
1058
1059
1060
1061
1062
  
  	if (data[IFLA_GRE_TTL])
  		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
  
  	if (data[IFLA_GRE_TOS])
  		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1063
1064
1065
  	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
  		if (t->ignore_df)
  			return -EINVAL;
c19e654dd   Herbert Xu   gre: Add netlink ...
1066
  		parms->iph.frag_off = htons(IP_DF);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1067
  	}
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1068
1069
  
  	if (data[IFLA_GRE_COLLECT_METADATA]) {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1070
  		t->collect_md = true;
e271c7b44   Jiri Benc   gre: do not keep ...
1071
1072
  		if (dev->type == ARPHRD_IPGRE)
  			dev->type = ARPHRD_NONE;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1073
  	}
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1074
1075
1076
1077
1078
1079
1080
  
  	if (data[IFLA_GRE_IGNORE_DF]) {
  		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
  		  && (parms->iph.frag_off & htons(IP_DF)))
  			return -EINVAL;
  		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1081
1082
  	if (data[IFLA_GRE_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
f551c91de   William Tu   net: erspan: intr...
1083
1084
  	if (data[IFLA_GRE_ERSPAN_VER]) {
  		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
84e54fe0a   William Tu   gre: introduce na...
1085

f551c91de   William Tu   net: erspan: intr...
1086
  		if (t->erspan_ver != 1 && t->erspan_ver != 2)
84e54fe0a   William Tu   gre: introduce na...
1087
1088
  			return -EINVAL;
  	}
f551c91de   William Tu   net: erspan: intr...
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  	if (t->erspan_ver == 1) {
  		if (data[IFLA_GRE_ERSPAN_INDEX]) {
  			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
  			if (t->index & ~INDEX_MASK)
  				return -EINVAL;
  		}
  	} else if (t->erspan_ver == 2) {
  		if (data[IFLA_GRE_ERSPAN_DIR]) {
  			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
  			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
  				return -EINVAL;
  		}
  		if (data[IFLA_GRE_ERSPAN_HWID]) {
  			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
  			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
  				return -EINVAL;
  		}
  	}
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1107
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1108
  }
4565e9919   Tom Herbert   gre: Setup and TX...
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  /* This function returns true when ENCAP attributes are present in the nl msg */
  static bool ipgre_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_GRE_ENCAP_TYPE]) {
  		ret = true;
  		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
  	}
  
  	if (data[IFLA_GRE_ENCAP_FLAGS]) {
  		ret = true;
  		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
  	}
  
  	if (data[IFLA_GRE_ENCAP_SPORT]) {
  		ret = true;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1132
  		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
4565e9919   Tom Herbert   gre: Setup and TX...
1133
1134
1135
1136
  	}
  
  	if (data[IFLA_GRE_ENCAP_DPORT]) {
  		ret = true;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1137
  		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
4565e9919   Tom Herbert   gre: Setup and TX...
1138
1139
1140
1141
  	}
  
  	return ret;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1142
  static int gre_tap_init(struct net_device *dev)
e1a800022   Herbert Xu   gre: Add Transpar...
1143
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1144
  	__gre_tunnel_init(dev);
bec94d430   stephen hemminger   gre: allow live a...
1145
  	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
d51711c05   Xin Long   ip_gre: ipgre_tap...
1146
  	netif_keep_dst(dev);
e1a800022   Herbert Xu   gre: Add Transpar...
1147

c54419321   Pravin B Shelar   GRE: Refactor GRE...
1148
  	return ip_tunnel_init(dev);
e1a800022   Herbert Xu   gre: Add Transpar...
1149
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1150
1151
1152
1153
  static const struct net_device_ops gre_tap_netdev_ops = {
  	.ndo_init		= gre_tap_init,
  	.ndo_uninit		= ip_tunnel_uninit,
  	.ndo_start_xmit		= gre_tap_xmit,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
1154
1155
  	.ndo_set_mac_address 	= eth_mac_addr,
  	.ndo_validate_addr	= eth_validate_addr,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1156
1157
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
1158
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
1159
  	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
1160
  };
84e54fe0a   William Tu   gre: introduce na...
1161
1162
1163
  static int erspan_tunnel_init(struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
84e54fe0a   William Tu   gre: introduce na...
1164
1165
1166
  
  	tunnel->tun_hlen = 8;
  	tunnel->parms.iph.protocol = IPPROTO_GRE;
c122fda27   Xin Long   ip_gre: set tunne...
1167
  	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
f551c91de   William Tu   net: erspan: intr...
1168
  		       erspan_hdr_len(tunnel->erspan_ver);
84e54fe0a   William Tu   gre: introduce na...
1169

84e54fe0a   William Tu   gre: introduce na...
1170
1171
1172
  	dev->features		|= GRE_FEATURES;
  	dev->hw_features	|= GRE_FEATURES;
  	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
c84bed440   Xin Long   ip_gre: erspan de...
1173
  	netif_keep_dst(dev);
84e54fe0a   William Tu   gre: introduce na...
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  
  	return ip_tunnel_init(dev);
  }
  
  static const struct net_device_ops erspan_netdev_ops = {
  	.ndo_init		= erspan_tunnel_init,
  	.ndo_uninit		= ip_tunnel_uninit,
  	.ndo_start_xmit		= erspan_xmit,
  	.ndo_set_mac_address	= eth_mac_addr,
  	.ndo_validate_addr	= eth_validate_addr,
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
  	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
  };
e1a800022   Herbert Xu   gre: Add Transpar...
1189
1190
  static void ipgre_tap_setup(struct net_device *dev)
  {
e1a800022   Herbert Xu   gre: Add Transpar...
1191
  	ether_setup(dev);
cfddd4c33   Xin Long   ip_gre: remove th...
1192
  	dev->max_mtu = 0;
d13b161c2   Jiri Benc   gre: clear IFF_TX...
1193
1194
1195
  	dev->netdev_ops	= &gre_tap_netdev_ops;
  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
  	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1196
  	ip_tunnel_setup(dev, gre_tap_net_id);
e1a800022   Herbert Xu   gre: Add Transpar...
1197
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1198
  static int ipgre_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
1199
1200
  			 struct nlattr *tb[], struct nlattr *data[],
  			 struct netlink_ext_ack *extack)
c19e654dd   Herbert Xu   gre: Add netlink ...
1201
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1202
  	struct ip_tunnel_parm p;
4565e9919   Tom Herbert   gre: Setup and TX...
1203
  	struct ip_tunnel_encap ipencap;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1204
  	__u32 fwmark = 0;
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1205
  	int err;
4565e9919   Tom Herbert   gre: Setup and TX...
1206
1207
1208
  
  	if (ipgre_netlink_encap_parms(data, &ipencap)) {
  		struct ip_tunnel *t = netdev_priv(dev);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1209
  		err = ip_tunnel_encap_setup(t, &ipencap);
4565e9919   Tom Herbert   gre: Setup and TX...
1210
1211
1212
1213
  
  		if (err < 0)
  			return err;
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1214

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1215
  	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1216
1217
  	if (err < 0)
  		return err;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1218
  	return ip_tunnel_newlink(dev, tb, &p, fwmark);
c19e654dd   Herbert Xu   gre: Add netlink ...
1219
1220
1221
  }
  
  static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
1222
1223
  			    struct nlattr *data[],
  			    struct netlink_ext_ack *extack)
c19e654dd   Herbert Xu   gre: Add netlink ...
1224
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1225
  	struct ip_tunnel *t = netdev_priv(dev);
4565e9919   Tom Herbert   gre: Setup and TX...
1226
  	struct ip_tunnel_encap ipencap;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1227
  	__u32 fwmark = t->fwmark;
dd9d598c6   Xin Long   ip_gre: add the s...
1228
  	struct ip_tunnel_parm p;
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1229
  	int err;
4565e9919   Tom Herbert   gre: Setup and TX...
1230
1231
  
  	if (ipgre_netlink_encap_parms(data, &ipencap)) {
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1232
  		err = ip_tunnel_encap_setup(t, &ipencap);
4565e9919   Tom Herbert   gre: Setup and TX...
1233
1234
1235
1236
  
  		if (err < 0)
  			return err;
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1237

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1238
  	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1239
1240
  	if (err < 0)
  		return err;
dd9d598c6   Xin Long   ip_gre: add the s...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
  
  	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
  	if (err < 0)
  		return err;
  
  	t->parms.i_flags = p.i_flags;
  	t->parms.o_flags = p.o_flags;
  
  	if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
  		ipgre_link_update(dev, !tb[IFLA_MTU]);
  
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
  }
  
  static size_t ipgre_get_size(const struct net_device *dev)
  {
  	return
  		/* IFLA_GRE_LINK */
  		nla_total_size(4) +
  		/* IFLA_GRE_IFLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_OFLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_IKEY */
  		nla_total_size(4) +
  		/* IFLA_GRE_OKEY */
  		nla_total_size(4) +
  		/* IFLA_GRE_LOCAL */
  		nla_total_size(4) +
  		/* IFLA_GRE_REMOTE */
  		nla_total_size(4) +
  		/* IFLA_GRE_TTL */
  		nla_total_size(1) +
  		/* IFLA_GRE_TOS */
  		nla_total_size(1) +
  		/* IFLA_GRE_PMTUDISC */
  		nla_total_size(1) +
4565e9919   Tom Herbert   gre: Setup and TX...
1278
1279
1280
1281
1282
1283
1284
1285
  		/* IFLA_GRE_ENCAP_TYPE */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_FLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_SPORT */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_DPORT */
  		nla_total_size(2) +
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1286
1287
  		/* IFLA_GRE_COLLECT_METADATA */
  		nla_total_size(0) +
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1288
1289
  		/* IFLA_GRE_IGNORE_DF */
  		nla_total_size(1) +
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1290
1291
  		/* IFLA_GRE_FWMARK */
  		nla_total_size(4) +
84e54fe0a   William Tu   gre: introduce na...
1292
1293
  		/* IFLA_GRE_ERSPAN_INDEX */
  		nla_total_size(4) +
f551c91de   William Tu   net: erspan: intr...
1294
1295
1296
1297
1298
1299
  		/* IFLA_GRE_ERSPAN_VER */
  		nla_total_size(1) +
  		/* IFLA_GRE_ERSPAN_DIR */
  		nla_total_size(1) +
  		/* IFLA_GRE_ERSPAN_HWID */
  		nla_total_size(2) +
c19e654dd   Herbert Xu   gre: Add netlink ...
1300
1301
1302
1303
1304
1305
1306
  		0;
  }
  
  static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_parm *p = &t->parms;
feaf5c796   Lorenzo Bianconi   net: ip_gre: alwa...
1307
  	__be16 o_flags = p->o_flags;
2bdf700e5   Lorenzo Bianconi   net: ip_gre: do n...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
  	if (t->erspan_ver == 1 || t->erspan_ver == 2) {
  		if (!t->collect_md)
  			o_flags |= TUNNEL_KEY;
  
  		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
  			goto nla_put_failure;
  
  		if (t->erspan_ver == 1) {
  			if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
  				goto nla_put_failure;
  		} else {
  			if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
  				goto nla_put_failure;
  			if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
  				goto nla_put_failure;
  		}
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1325

f3756b79e   David S. Miller   ipv4: Stop using ...
1326
  	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
95f5c64c3   Tom Herbert   gre: Move utility...
1327
1328
1329
  	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
  			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
  	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
feaf5c796   Lorenzo Bianconi   net: ip_gre: alwa...
1330
  			 gre_tnl_flags_to_gre_flags(o_flags)) ||
f3756b79e   David S. Miller   ipv4: Stop using ...
1331
1332
  	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
  	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
930345ea6   Jiri Benc   netlink: implemen...
1333
1334
  	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
  	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
f3756b79e   David S. Miller   ipv4: Stop using ...
1335
1336
1337
  	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
  	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
  	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1338
1339
  		       !!(p->iph.frag_off & htons(IP_DF))) ||
  	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
f3756b79e   David S. Miller   ipv4: Stop using ...
1340
  		goto nla_put_failure;
4565e9919   Tom Herbert   gre: Setup and TX...
1341
1342
1343
  
  	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
  			t->encap.type) ||
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1344
1345
1346
1347
  	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
  			 t->encap.sport) ||
  	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
  			 t->encap.dport) ||
4565e9919   Tom Herbert   gre: Setup and TX...
1348
  	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
e1b2cb655   Tom Herbert   fou: Fix typo in ...
1349
  			t->encap.flags))
4565e9919   Tom Herbert   gre: Setup and TX...
1350
  		goto nla_put_failure;
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1351
1352
  	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
  		goto nla_put_failure;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1353
1354
1355
1356
  	if (t->collect_md) {
  		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
  			goto nla_put_failure;
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1357
1358
1359
1360
1361
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
84e54fe0a   William Tu   gre: introduce na...
1362
1363
  static void erspan_setup(struct net_device *dev)
  {
84581bdae   Xin Long   erspan: set erspa...
1364
  	struct ip_tunnel *t = netdev_priv(dev);
84e54fe0a   William Tu   gre: introduce na...
1365
  	ether_setup(dev);
0e141f757   Haishuang Yan   erspan: remove th...
1366
  	dev->max_mtu = 0;
84e54fe0a   William Tu   gre: introduce na...
1367
1368
1369
1370
  	dev->netdev_ops = &erspan_netdev_ops;
  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
  	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
  	ip_tunnel_setup(dev, erspan_net_id);
84581bdae   Xin Long   erspan: set erspa...
1371
  	t->erspan_ver = 1;
84e54fe0a   William Tu   gre: introduce na...
1372
  }
c19e654dd   Herbert Xu   gre: Add netlink ...
1373
1374
1375
1376
1377
1378
  static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
  	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
  	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
  	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
4d74f8ba1   Patrick McHardy   gre: minor cleanu...
1379
1380
  	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
  	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
c19e654dd   Herbert Xu   gre: Add netlink ...
1381
1382
1383
  	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
  	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
  	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
4565e9919   Tom Herbert   gre: Setup and TX...
1384
1385
1386
1387
  	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1388
  	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1389
  	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1390
  	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
84e54fe0a   William Tu   gre: introduce na...
1391
  	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
f551c91de   William Tu   net: erspan: intr...
1392
1393
1394
  	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
  	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
  	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
c19e654dd   Herbert Xu   gre: Add netlink ...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
  };
  
  static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
  	.kind		= "gre",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= ipgre_tunnel_setup,
  	.validate	= ipgre_tunnel_validate,
  	.newlink	= ipgre_newlink,
  	.changelink	= ipgre_changelink,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1406
  	.dellink	= ip_tunnel_dellink,
c19e654dd   Herbert Xu   gre: Add netlink ...
1407
1408
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1409
  	.get_link_net	= ip_tunnel_get_link_net,
c19e654dd   Herbert Xu   gre: Add netlink ...
1410
  };
e1a800022   Herbert Xu   gre: Add Transpar...
1411
1412
1413
1414
1415
1416
1417
1418
1419
  static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
  	.kind		= "gretap",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= ipgre_tap_setup,
  	.validate	= ipgre_tap_validate,
  	.newlink	= ipgre_newlink,
  	.changelink	= ipgre_changelink,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1420
  	.dellink	= ip_tunnel_dellink,
e1a800022   Herbert Xu   gre: Add Transpar...
1421
1422
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1423
  	.get_link_net	= ip_tunnel_get_link_net,
e1a800022   Herbert Xu   gre: Add Transpar...
1424
  };
84e54fe0a   William Tu   gre: introduce na...
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
  static struct rtnl_link_ops erspan_link_ops __read_mostly = {
  	.kind		= "erspan",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= erspan_setup,
  	.validate	= erspan_validate,
  	.newlink	= ipgre_newlink,
  	.changelink	= ipgre_changelink,
  	.dellink	= ip_tunnel_dellink,
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
  	.get_link_net	= ip_tunnel_get_link_net,
  };
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1439
1440
1441
1442
1443
  struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
  					u8 name_assign_type)
  {
  	struct nlattr *tb[IFLA_MAX + 1];
  	struct net_device *dev;
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1444
  	LIST_HEAD(list_kill);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1445
1446
1447
1448
1449
1450
  	struct ip_tunnel *t;
  	int err;
  
  	memset(&tb, 0, sizeof(tb));
  
  	dev = rtnl_create_link(net, name, name_assign_type,
d0522f1cd   David Ahern   net: Add extack a...
1451
  			       &ipgre_tap_ops, tb, NULL);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1452
1453
1454
1455
1456
1457
  	if (IS_ERR(dev))
  		return dev;
  
  	/* Configure flow based GRE device. */
  	t = netdev_priv(dev);
  	t->collect_md = true;
7a3f4a185   Matthias Schiffer   net: add netlink_...
1458
  	err = ipgre_newlink(net, dev, tb, NULL, NULL);
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1459
1460
1461
1462
  	if (err < 0) {
  		free_netdev(dev);
  		return ERR_PTR(err);
  	}
7e059158d   David Wragg   vxlan, gre, genev...
1463
1464
1465
1466
1467
1468
1469
  
  	/* openvswitch users expect packet sizes to be unrestricted,
  	 * so set the largest MTU we can.
  	 */
  	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
  	if (err)
  		goto out;
da6f1da81   Nicolas Dichtel   ovs/gre: fix rtnl...
1470
1471
1472
  	err = rtnl_configure_link(dev, NULL);
  	if (err < 0)
  		goto out;
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1473
1474
  	return dev;
  out:
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1475
1476
  	ip_tunnel_dellink(dev, &list_kill);
  	unregister_netdevice_many(&list_kill);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1477
1478
1479
  	return ERR_PTR(err);
  }
  EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1480
1481
  static int __net_init ipgre_tap_init_net(struct net *net)
  {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1482
  	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1483
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1484
  static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1485
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1486
  	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1487
1488
1489
1490
  }
  
  static struct pernet_operations ipgre_tap_net_ops = {
  	.init = ipgre_tap_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1491
  	.exit_batch = ipgre_tap_exit_batch_net,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1492
1493
1494
  	.id   = &gre_tap_net_id,
  	.size = sizeof(struct ip_tunnel_net),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495

84e54fe0a   William Tu   gre: introduce na...
1496
1497
1498
1499
1500
  static int __net_init erspan_init_net(struct net *net)
  {
  	return ip_tunnel_init_net(net, erspan_net_id,
  				  &erspan_link_ops, "erspan0");
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1501
  static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
84e54fe0a   William Tu   gre: introduce na...
1502
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1503
  	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
84e54fe0a   William Tu   gre: introduce na...
1504
1505
1506
1507
  }
  
  static struct pernet_operations erspan_net_ops = {
  	.init = erspan_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1508
  	.exit_batch = erspan_exit_batch_net,
84e54fe0a   William Tu   gre: introduce na...
1509
1510
1511
  	.id   = &erspan_net_id,
  	.size = sizeof(struct ip_tunnel_net),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512
1513
1514
  static int __init ipgre_init(void)
  {
  	int err;
058bd4d2a   Joe Perches   net: Convert prin...
1515
1516
  	pr_info("GRE over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517

cfb8fbf22   Eric W. Biederman   net: Simplify ip_...
1518
  	err = register_pernet_device(&ipgre_net_ops);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
1519
  	if (err < 0)
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1520
  		return err;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1521
1522
  	err = register_pernet_device(&ipgre_tap_net_ops);
  	if (err < 0)
e3d0328c7   William Tu   gre: fix goto sta...
1523
  		goto pnet_tap_failed;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1524

84e54fe0a   William Tu   gre: introduce na...
1525
1526
1527
  	err = register_pernet_device(&erspan_net_ops);
  	if (err < 0)
  		goto pnet_erspan_failed;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1528
  	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1529
  	if (err < 0) {
058bd4d2a   Joe Perches   net: Convert prin...
1530
1531
  		pr_info("%s: can't add protocol
  ", __func__);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1532
1533
  		goto add_proto_failed;
  	}
7daa00048   Pavel Emelyanov   [GRE]: Make the f...
1534

c19e654dd   Herbert Xu   gre: Add netlink ...
1535
1536
1537
  	err = rtnl_link_register(&ipgre_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
e1a800022   Herbert Xu   gre: Add Transpar...
1538
1539
1540
  	err = rtnl_link_register(&ipgre_tap_ops);
  	if (err < 0)
  		goto tap_ops_failed;
84e54fe0a   William Tu   gre: introduce na...
1541
1542
1543
  	err = rtnl_link_register(&erspan_link_ops);
  	if (err < 0)
  		goto erspan_link_failed;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1544
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1545

84e54fe0a   William Tu   gre: introduce na...
1546
1547
  erspan_link_failed:
  	rtnl_link_unregister(&ipgre_tap_ops);
e1a800022   Herbert Xu   gre: Add Transpar...
1548
1549
  tap_ops_failed:
  	rtnl_link_unregister(&ipgre_link_ops);
c19e654dd   Herbert Xu   gre: Add netlink ...
1550
  rtnl_link_failed:
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1551
  	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1552
  add_proto_failed:
84e54fe0a   William Tu   gre: introduce na...
1553
1554
  	unregister_pernet_device(&erspan_net_ops);
  pnet_erspan_failed:
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1555
  	unregister_pernet_device(&ipgre_tap_net_ops);
e3d0328c7   William Tu   gre: fix goto sta...
1556
  pnet_tap_failed:
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1557
  	unregister_pernet_device(&ipgre_net_ops);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1558
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1559
  }
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1560
  static void __exit ipgre_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
  {
e1a800022   Herbert Xu   gre: Add Transpar...
1562
  	rtnl_link_unregister(&ipgre_tap_ops);
c19e654dd   Herbert Xu   gre: Add netlink ...
1563
  	rtnl_link_unregister(&ipgre_link_ops);
84e54fe0a   William Tu   gre: introduce na...
1564
  	rtnl_link_unregister(&erspan_link_ops);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1565
  	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1566
  	unregister_pernet_device(&ipgre_tap_net_ops);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1567
  	unregister_pernet_device(&ipgre_net_ops);
84e54fe0a   William Tu   gre: introduce na...
1568
  	unregister_pernet_device(&erspan_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
1570
1571
1572
1573
  }
  
  module_init(ipgre_init);
  module_exit(ipgre_fini);
  MODULE_LICENSE("GPL");
4d74f8ba1   Patrick McHardy   gre: minor cleanu...
1574
1575
  MODULE_ALIAS_RTNL_LINK("gre");
  MODULE_ALIAS_RTNL_LINK("gretap");
84e54fe0a   William Tu   gre: introduce na...
1576
  MODULE_ALIAS_RTNL_LINK("erspan");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
1577
  MODULE_ALIAS_NETDEV("gre0");
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1578
  MODULE_ALIAS_NETDEV("gretap0");
84e54fe0a   William Tu   gre: introduce na...
1579
  MODULE_ALIAS_NETDEV("erspan0");