Blame view

net/ipv4/ipip.c 18.5 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:	IP/IP protocol decoder.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   *	Authors:
   *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
   *
   *	Fixes:
   *		Alan Cox	:	Merged and made usable non modular (its so tiny its silly as
   *					a module taking up 2 pages).
   *		Alan Cox	: 	Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
   *					to keep ip_forward happy.
   *		Alan Cox	:	More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8).
   *		Kai Schulte	:	Fixed #defines for IP_FIREWALL->FIREWALL
   *              David Woodhouse :       Perform some basic ICMP handling.
   *                                      IPIP Routing without decapsulation.
   *              Carlos Picoto   :       GRE over IP support
   *		Alexey Kuznetsov:	Reworked. Really, now it is truncated version of ipv4/ip_gre.c.
   *					I do not want to merge them together.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
   */
  
  /* tunnel.c: an IP tunnel driver
  
  	The purpose of this driver is to provide an IP tunnel through
  	which you can tunnel network traffic transparently across subnets.
  
  	This was written by looking at Nick Holloway's dummy driver
  	Thanks for the great code!
  
  		-Sam Lantinga	(slouken@cs.ucdavis.edu)  02/01/95
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
31

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
  	Minor tweaks:
  		Cleaned up the code a little and added some pre-1.3.0 tweaks.
  		dev->hard_header/hard_header_len changed to use no headers.
  		Comments/bracketing tweaked.
  		Made the tunnels use dev->name not tunnel: when error reporting.
  		Added tx_dropped stat
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
38

113aa838e   Alan Cox   net: Rationalise ...
39
  		-Alan Cox	(alan@lxorguk.ukuu.org.uk) 21 March 95
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
  
  	Reworked:
  		Changed to tunnel to destination gateway in addition to the
  			tunnel's pointopoint address
  		Almost completely rewritten
  		Note:  There is currently no firewall or ICMP handling done.
  
  		-Sam Lantinga	(slouken@cs.ucdavis.edu) 02/13/96
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
48

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  */
  
  /* Things I wish I had known when writing the tunnel driver:
  
  	When the tunnel_xmit() function is called, the skb contains the
  	packet to be sent (plus a great deal of extra info), and dev
  	contains the tunnel device that _we_ are.
  
  	When we are passed a packet, we are expected to fill in the
  	source address with our source IP address.
  
  	What is the proper way to allocate, copy and free a buffer?
  	After you allocate it, it is a "0 length" chunk of memory
  	starting at zero.  If you want to add headers to the buffer
  	later, you'll have to call "skb_reserve(skb, amount)" with
  	the amount of memory you want reserved.  Then, you call
  	"skb_put(skb, amount)" with the amount of space you want in
  	the buffer.  skb_put() returns a pointer to the top (#0) of
  	that buffer.  skb->len is set to the amount of space you have
  	"allocated" with skb_put().  You can then write up to skb->len
  	bytes to that buffer.  If you need more, you can call skb_put()
  	again with the additional amount of space you need.  You can
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
71
  	find out how much more space you can allocate by calling
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  	"skb_tailroom(skb)".
  	Now, to add header space, call "skb_push(skb, header_len)".
  	This creates space at the beginning of the buffer and returns
  	a pointer to this new space.  If later you need to strip a
  	header from a buffer, call "skb_pull(skb, header_len)".
  	skb_headroom() will return how much space is left at the top
  	of the buffer (before the main data).  Remember, this headroom
  	space must be reserved before the skb_put() function is called.
  	*/
  
  /*
     This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c
  
     For comments look at net/ipv4/ip_gre.c --ANK
   */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
87

4fc268d24   Randy Dunlap   [PATCH] capable/c...
88
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
  #include <linux/module.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
92
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
93
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
  #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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
  #include <linux/init.h>
  #include <linux/netfilter_ipv4.h>
46f25dffb   Kris Katterjohn   [NET]: Change 150...
102
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
  
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
107
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
110
111
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
112
  #include <net/dst_metadata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

eccc1bb8d   stephen hemminger   tunnel: drop pack...
114
115
116
  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");
c7d03a00b   Alexey Dobriyan   netns: make struc...
117
  static unsigned int ipip_net_id __read_mostly;
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
118

3c97af99a   Eric Dumazet   ipip: percpu stat...
119
  static int ipip_tunnel_init(struct net_device *dev);
0974658da   Nicolas Dichtel   ipip: advertise t...
120
  static struct rtnl_link_ops ipip_link_ops __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

d2acc3479   Herbert Xu   [INET]: Introduce...
122
  static int ipip_err(struct sk_buff *skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  {
f3594f0a7   Xin Long   ipip: only increa...
124
125
126
127
  	/* 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.
  	 */
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
128
129
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
b71d1d426   Eric Dumazet   inet: constify ip...
130
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
131
132
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
f3594f0a7   Xin Long   ipip: only increa...
133
134
  	struct ip_tunnel *t;
  	int err = 0;
32bbd8793   Stefano Brivio   net: Convert prot...
135
136
137
138
139
140
  	t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  			     iph->daddr, iph->saddr, 0);
  	if (!t) {
  		err = -ENOENT;
  		goto out;
  	}
f3594f0a7   Xin Long   ipip: only increa...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  	switch (type) {
  	case ICMP_DEST_UNREACH:
  		switch (code) {
  		case ICMP_SR_FAILED:
  			/* Impossible event. */
  			goto out;
  		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)
  			goto out;
  		break;
  
  	case ICMP_REDIRECT:
  		break;
  
  	default:
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167

363933955   David S. Miller   ipv4: Handle PMTU...
168
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
d888f3966   Maciej Żenczykowski   net-ipv4: remove ...
169
  		ipv4_update_pmtu(skb, net, info, t->parms.link, iph->protocol);
363933955   David S. Miller   ipv4: Handle PMTU...
170
171
  		goto out;
  	}
55be7a9c6   David S. Miller   ipv4: Add redirec...
172
  	if (type == ICMP_REDIRECT) {
1042caa79   Maciej Żenczykowski   net-ipv4: remove ...
173
  		ipv4_redirect(skb, net, t->parms.link, iph->protocol);
55be7a9c6   David S. Miller   ipv4: Add redirec...
174
175
  		goto out;
  	}
f3594f0a7   Xin Long   ipip: only increa...
176
177
  	if (t->parms.iph.daddr == 0) {
  		err = -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  		goto out;
f3594f0a7   Xin Long   ipip: only increa...
179
  	}
d2acc3479   Herbert Xu   [INET]: Introduce...
180

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
  		goto out;
26d94b46d   Wei Yongjun   ipip: used time_b...
183
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
b0558ef24   stephen hemminger   xfrm: remove extr...
188

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
189
  out:
d2acc3479   Herbert Xu   [INET]: Introduce...
190
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  }
1b69e7e6c   Simon Horman   ipip: support MPL...
192
  static const struct tnl_ptk_info ipip_tpi = {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
193
194
195
  	/* no tunnel info required for ipip. */
  	.proto = htons(ETH_P_IP),
  };
1b69e7e6c   Simon Horman   ipip: support MPL...
196
197
198
199
200
201
202
203
  #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 ipip_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
205
206
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
207
  	struct metadata_dst *tun_dst = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	struct ip_tunnel *tunnel;
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
209
  	const struct iphdr *iph;
3c97af99a   Eric Dumazet   ipip: percpu stat...
210

3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
211
  	iph = ip_hdr(skb);
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
212
213
214
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  			iph->saddr, iph->daddr, 0);
  	if (tunnel) {
1b69e7e6c   Simon Horman   ipip: support MPL...
215
216
217
218
219
  		const struct tnl_ptk_info *tpi;
  
  		if (tunnel->parms.iph.protocol != ipproto &&
  		    tunnel->parms.iph.protocol != 0)
  			goto drop;
eccc1bb8d   stephen hemminger   tunnel: drop pack...
220
221
  		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  			goto drop;
1b69e7e6c   Simon Horman   ipip: support MPL...
222
223
224
225
226
227
228
  #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...
229
  			goto drop;
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
230
231
232
233
234
235
  		if (tunnel->collect_md) {
  			tun_dst = ip_tun_rx_dst(skb, 0, 0, 0);
  			if (!tun_dst)
  				return 0;
  		}
  		return ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	return -1;
eccc1bb8d   stephen hemminger   tunnel: drop pack...
239
240
241
242
  
  drop:
  	kfree_skb(skb);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  }
1b69e7e6c   Simon Horman   ipip: support MPL...
244
245
246
247
248
249
250
251
252
253
254
  static int ipip_rcv(struct sk_buff *skb)
  {
  	return ipip_tunnel_rcv(skb, IPPROTO_IPIP);
  }
  
  #if IS_ENABLED(CONFIG_MPLS)
  static int mplsip_rcv(struct sk_buff *skb)
  {
  	return ipip_tunnel_rcv(skb, IPPROTO_MPLS);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
  /*
   *	This function assumes it is being called from dev_queue_xmit()
   *	and that skb is filled properly by that function.
   */
1b69e7e6c   Simon Horman   ipip: support MPL...
259
260
  static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
  				    struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
262
  	struct ip_tunnel *tunnel = netdev_priv(dev);
b71d1d426   Eric Dumazet   inet: constify ip...
263
  	const struct iphdr  *tiph = &tunnel->parms.iph;
1b69e7e6c   Simon Horman   ipip: support MPL...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	u8 ipproto;
  
  	switch (skb->protocol) {
  	case htons(ETH_P_IP):
  		ipproto = IPPROTO_IPIP;
  		break;
  #if IS_ENABLED(CONFIG_MPLS)
  	case htons(ETH_P_MPLS_UC):
  		ipproto = IPPROTO_MPLS;
  		break;
  #endif
  	default:
  		goto tx_error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

1b69e7e6c   Simon Horman   ipip: support MPL...
279
  	if (tiph->protocol != ipproto && tiph->protocol != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

7e13318da   Tom Herbert   net: define gso t...
282
  	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
aed069df0   Alexander Duyck   ip_tunnel_core: i...
283
  		goto tx_error;
8344bfc60   Pravin B Shelar   ipip: Use tunnel_...
284

1b69e7e6c   Simon Horman   ipip: support MPL...
285
  	skb_set_inner_ipproto(skb, ipproto);
077c5a094   Tom Herbert   ipip: Set inner I...
286

cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
287
  	if (tunnel->collect_md)
c8b34e680   wenxu   ip_tunnel: Add tn...
288
  		ip_md_tunnel_xmit(skb, dev, ipproto, 0);
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
289
290
  	else
  		ip_tunnel_xmit(skb, dev, tiph, ipproto);
6ed106549   Patrick McHardy   net: use NETDEV_T...
291
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  tx_error:
3acfa1e73   Eric Dumazet   ipv4: be friend w...
294
  	kfree_skb(skb);
aed069df0   Alexander Duyck   ip_tunnel_core: i...
295

cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
296
  	dev->stats.tx_errors++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
297
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  }
1b69e7e6c   Simon Horman   ipip: support MPL...
299
300
301
302
303
304
305
306
307
308
309
310
311
  static bool ipip_tunnel_ioctl_verify_protocol(u8 ipproto)
  {
  	switch (ipproto) {
  	case 0:
  	case IPPROTO_IPIP:
  #if IS_ENABLED(CONFIG_MPLS)
  	case IPPROTO_MPLS:
  #endif
  		return true;
  	}
  
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  static int
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
313
  ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
  {
  	int err = 0;
  	struct ip_tunnel_parm p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
318
319
  	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

3b7b514f4   Cong Wang   ipip: fix a regre...
321
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
1b69e7e6c   Simon Horman   ipip: support MPL...
322
323
  		if (p.iph.version != 4 ||
  		    !ipip_tunnel_ioctl_verify_protocol(p.iph.protocol) ||
3b7b514f4   Cong Wang   ipip: fix a regre...
324
325
326
  		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
  			return -EINVAL;
  	}
252a8fbe8   Eric Dumazet   ipip: fix one spa...
327
328
  	p.i_key = p.o_key = 0;
  	p.i_flags = p.o_flags = 0;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
329
330
331
332
333
334
  	err = ip_tunnel_ioctl(dev, &p, cmd);
  	if (err)
  		return err;
  
  	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	return 0;
  }
23a12b147   Stephen Hemminger   ipip: convert to ...
337
  static const struct net_device_ops ipip_netdev_ops = {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
338
339
  	.ndo_init       = ipip_tunnel_init,
  	.ndo_uninit     = ip_tunnel_uninit,
23a12b147   Stephen Hemminger   ipip: convert to ...
340
341
  	.ndo_start_xmit	= ipip_tunnel_xmit,
  	.ndo_do_ioctl	= ipip_tunnel_ioctl,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
342
343
  	.ndo_change_mtu = ip_tunnel_change_mtu,
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
344
  	.ndo_get_iflink = ip_tunnel_get_iflink,
23a12b147   Stephen Hemminger   ipip: convert to ...
345
  };
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
346
347
348
  #define IPIP_FEATURES (NETIF_F_SG |		\
  		       NETIF_F_FRAGLIST |	\
  		       NETIF_F_HIGHDMA |	\
cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
349
  		       NETIF_F_GSO_SOFTWARE |	\
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
350
  		       NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
  static void ipip_tunnel_setup(struct net_device *dev)
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
353
  	dev->netdev_ops		= &ipip_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  
  	dev->type		= ARPHRD_TUNNEL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  	dev->flags		= IFF_NOARP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	dev->addr_len		= 4;
153f09433   Eric Dumazet   ipip: enable lock...
358
  	dev->features		|= NETIF_F_LLTX;
028758788   Eric Dumazet   net: better IFF_X...
359
  	netif_keep_dst(dev);
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
360
361
362
  
  	dev->features		|= IPIP_FEATURES;
  	dev->hw_features	|= IPIP_FEATURES;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
363
  	ip_tunnel_setup(dev, ipip_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  }
3c97af99a   Eric Dumazet   ipip: percpu stat...
365
  static int ipip_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
367
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
473ab820d   Tom Herbert   ipip: Setup and T...
371
372
  	tunnel->tun_hlen = 0;
  	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
373
  	return ip_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  }
a8b8a889e   Matthias Schiffer   net: add netlink_...
375
376
  static int ipip_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  				struct netlink_ext_ack *extack)
1b69e7e6c   Simon Horman   ipip: support MPL...
377
378
379
380
381
382
383
384
385
386
387
388
  {
  	u8 proto;
  
  	if (!data || !data[IFLA_IPTUN_PROTO])
  		return 0;
  
  	proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
  	if (proto != IPPROTO_IPIP && proto != IPPROTO_MPLS && proto != 0)
  		return -EINVAL;
  
  	return 0;
  }
be42da0e1   Nicolas Dichtel   ipip: add support...
389
  static void ipip_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
390
391
  			       struct ip_tunnel_parm *parms, bool *collect_md,
  			       __u32 *fwmark)
be42da0e1   Nicolas Dichtel   ipip: add support...
392
393
394
395
396
397
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.version = 4;
  	parms->iph.protocol = IPPROTO_IPIP;
  	parms->iph.ihl = 5;
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
398
  	*collect_md = false;
be42da0e1   Nicolas Dichtel   ipip: add support...
399
400
401
402
403
404
405
406
  
  	if (!data)
  		return;
  
  	if (data[IFLA_IPTUN_LINK])
  		parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
  
  	if (data[IFLA_IPTUN_LOCAL])
67b61f6c1   Jiri Benc   netlink: implemen...
407
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_IPTUN_LOCAL]);
be42da0e1   Nicolas Dichtel   ipip: add support...
408
409
  
  	if (data[IFLA_IPTUN_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
410
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_IPTUN_REMOTE]);
be42da0e1   Nicolas Dichtel   ipip: add support...
411
412
413
414
415
416
417
418
419
  
  	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]);
1b69e7e6c   Simon Horman   ipip: support MPL...
420
421
  	if (data[IFLA_IPTUN_PROTO])
  		parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
be42da0e1   Nicolas Dichtel   ipip: add support...
422
423
  	if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
  		parms->iph.frag_off = htons(IP_DF);
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
424
425
426
  
  	if (data[IFLA_IPTUN_COLLECT_METADATA])
  		*collect_md = true;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
427
428
429
  
  	if (data[IFLA_IPTUN_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
be42da0e1   Nicolas Dichtel   ipip: add support...
430
  }
473ab820d   Tom Herbert   ipip: Setup and T...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  /* This function returns true when ENCAP attributes are present in the nl msg */
  static bool ipip_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;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
454
  		ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
473ab820d   Tom Herbert   ipip: Setup and T...
455
456
457
458
  	}
  
  	if (data[IFLA_IPTUN_ENCAP_DPORT]) {
  		ret = true;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
459
  		ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
473ab820d   Tom Herbert   ipip: Setup and T...
460
461
462
463
  	}
  
  	return ret;
  }
be42da0e1   Nicolas Dichtel   ipip: add support...
464
  static int ipip_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
465
466
  			struct nlattr *tb[], struct nlattr *data[],
  			struct netlink_ext_ack *extack)
be42da0e1   Nicolas Dichtel   ipip: add support...
467
  {
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
468
  	struct ip_tunnel *t = netdev_priv(dev);
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
469
  	struct ip_tunnel_parm p;
473ab820d   Tom Herbert   ipip: Setup and T...
470
  	struct ip_tunnel_encap ipencap;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
471
  	__u32 fwmark = 0;
473ab820d   Tom Herbert   ipip: Setup and T...
472
473
  
  	if (ipip_netlink_encap_parms(data, &ipencap)) {
473ab820d   Tom Herbert   ipip: Setup and T...
474
475
476
477
478
  		int err = ip_tunnel_encap_setup(t, &ipencap);
  
  		if (err < 0)
  			return err;
  	}
be42da0e1   Nicolas Dichtel   ipip: add support...
479

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
480
481
  	ipip_netlink_parms(data, &p, &t->collect_md, &fwmark);
  	return ip_tunnel_newlink(dev, tb, &p, fwmark);
be42da0e1   Nicolas Dichtel   ipip: add support...
482
483
484
  }
  
  static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
485
486
  			   struct nlattr *data[],
  			   struct netlink_ext_ack *extack)
be42da0e1   Nicolas Dichtel   ipip: add support...
487
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
488
  	struct ip_tunnel *t = netdev_priv(dev);
be42da0e1   Nicolas Dichtel   ipip: add support...
489
  	struct ip_tunnel_parm p;
473ab820d   Tom Herbert   ipip: Setup and T...
490
  	struct ip_tunnel_encap ipencap;
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
491
  	bool collect_md;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
492
  	__u32 fwmark = t->fwmark;
473ab820d   Tom Herbert   ipip: Setup and T...
493
494
  
  	if (ipip_netlink_encap_parms(data, &ipencap)) {
473ab820d   Tom Herbert   ipip: Setup and T...
495
496
497
498
499
  		int err = ip_tunnel_encap_setup(t, &ipencap);
  
  		if (err < 0)
  			return err;
  	}
be42da0e1   Nicolas Dichtel   ipip: add support...
500

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
501
  	ipip_netlink_parms(data, &p, &collect_md, &fwmark);
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
502
503
  	if (collect_md)
  		return -EINVAL;
be42da0e1   Nicolas Dichtel   ipip: add support...
504
505
506
507
  
  	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
  	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
  		return -EINVAL;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
508
  	return ip_tunnel_changelink(dev, tb, &p, fwmark);
be42da0e1   Nicolas Dichtel   ipip: add support...
509
  }
0974658da   Nicolas Dichtel   ipip: advertise t...
510
511
512
513
514
515
516
517
518
519
520
521
522
  static size_t ipip_get_size(const struct net_device *dev)
  {
  	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) +
1b69e7e6c   Simon Horman   ipip: support MPL...
523
524
  		/* IFLA_IPTUN_PROTO */
  		nla_total_size(1) +
befe2aa1b   Nicolas Dichtel   ipip/rtnl: add IF...
525
526
  		/* IFLA_IPTUN_PMTUDISC */
  		nla_total_size(1) +
473ab820d   Tom Herbert   ipip: Setup and T...
527
528
529
530
531
532
533
534
  		/* 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) +
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
535
536
  		/* IFLA_IPTUN_COLLECT_METADATA */
  		nla_total_size(0) +
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
537
538
  		/* IFLA_IPTUN_FWMARK */
  		nla_total_size(4) +
0974658da   Nicolas Dichtel   ipip: advertise t...
539
540
541
542
543
544
545
546
547
  		0;
  }
  
  static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
  {
  	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...
548
549
  	    nla_put_in_addr(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
  	    nla_put_in_addr(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
0974658da   Nicolas Dichtel   ipip: advertise t...
550
  	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
befe2aa1b   Nicolas Dichtel   ipip/rtnl: add IF...
551
  	    nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
1b69e7e6c   Simon Horman   ipip: support MPL...
552
  	    nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
befe2aa1b   Nicolas Dichtel   ipip/rtnl: add IF...
553
  	    nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
554
555
  		       !!(parm->iph.frag_off & htons(IP_DF))) ||
  	    nla_put_u32(skb, IFLA_IPTUN_FWMARK, tunnel->fwmark))
0974658da   Nicolas Dichtel   ipip: advertise t...
556
  		goto nla_put_failure;
473ab820d   Tom Herbert   ipip: Setup and T...
557
558
559
  
  	if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
  			tunnel->encap.type) ||
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
560
561
562
563
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
  			 tunnel->encap.sport) ||
  	    nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
  			 tunnel->encap.dport) ||
473ab820d   Tom Herbert   ipip: Setup and T...
564
  	    nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
e1b2cb655   Tom Herbert   fou: Fix typo in ...
565
  			tunnel->encap.flags))
473ab820d   Tom Herbert   ipip: Setup and T...
566
  		goto nla_put_failure;
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
567
568
569
  	if (tunnel->collect_md)
  		if (nla_put_flag(skb, IFLA_IPTUN_COLLECT_METADATA))
  			goto nla_put_failure;
0974658da   Nicolas Dichtel   ipip: advertise t...
570
571
572
573
574
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
be42da0e1   Nicolas Dichtel   ipip: add support...
575
576
577
578
579
580
  static const struct nla_policy ipip_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 },
1b69e7e6c   Simon Horman   ipip: support MPL...
581
  	[IFLA_IPTUN_PROTO]		= { .type = NLA_U8 },
be42da0e1   Nicolas Dichtel   ipip: add support...
582
  	[IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 },
473ab820d   Tom Herbert   ipip: Setup and T...
583
584
585
586
  	[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 },
cfc7381b3   Alexei Starovoitov   ip_tunnel: add co...
587
  	[IFLA_IPTUN_COLLECT_METADATA]	= { .type = NLA_FLAG },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
588
  	[IFLA_IPTUN_FWMARK]		= { .type = NLA_U32 },
be42da0e1   Nicolas Dichtel   ipip: add support...
589
  };
0974658da   Nicolas Dichtel   ipip: advertise t...
590
591
592
  static struct rtnl_link_ops ipip_link_ops __read_mostly = {
  	.kind		= "ipip",
  	.maxtype	= IFLA_IPTUN_MAX,
be42da0e1   Nicolas Dichtel   ipip: add support...
593
  	.policy		= ipip_policy,
0974658da   Nicolas Dichtel   ipip: advertise t...
594
  	.priv_size	= sizeof(struct ip_tunnel),
be42da0e1   Nicolas Dichtel   ipip: add support...
595
  	.setup		= ipip_tunnel_setup,
1b69e7e6c   Simon Horman   ipip: support MPL...
596
  	.validate	= ipip_tunnel_validate,
be42da0e1   Nicolas Dichtel   ipip: add support...
597
598
  	.newlink	= ipip_newlink,
  	.changelink	= ipip_changelink,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
599
  	.dellink	= ip_tunnel_dellink,
0974658da   Nicolas Dichtel   ipip: advertise t...
600
601
  	.get_size	= ipip_get_size,
  	.fill_info	= ipip_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
602
  	.get_link_net	= ip_tunnel_get_link_net,
0974658da   Nicolas Dichtel   ipip: advertise t...
603
  };
6dcd814bd   Eric Dumazet   net: struct xfrm_...
604
  static struct xfrm_tunnel ipip_handler __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
  	.handler	=	ipip_rcv,
  	.err_handler	=	ipip_err,
d2acc3479   Herbert Xu   [INET]: Introduce...
607
  	.priority	=	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  };
1b69e7e6c   Simon Horman   ipip: support MPL...
609
610
611
612
613
614
615
  #if IS_ENABLED(CONFIG_MPLS)
  static struct xfrm_tunnel mplsip_handler __read_mostly = {
  	.handler	=	mplsip_rcv,
  	.err_handler	=	ipip_err,
  	.priority	=	1,
  };
  #endif
2c8c1e729   Alexey Dobriyan   net: spread __net...
616
  static int __net_init ipip_init_net(struct net *net)
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
617
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
618
  	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
619
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
620
  static void __net_exit ipip_exit_batch_net(struct list_head *list_net)
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
621
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
622
  	ip_tunnel_delete_nets(list_net, ipip_net_id, &ipip_link_ops);
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
623
624
625
626
  }
  
  static struct pernet_operations ipip_net_ops = {
  	.init = ipip_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
627
  	.exit_batch = ipip_exit_batch_net,
86de8a631   Eric W. Biederman   net: Simplify ipi...
628
  	.id   = &ipip_net_id,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
629
  	.size = sizeof(struct ip_tunnel_net),
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
630
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
633
  static int __init ipip_init(void)
  {
  	int err;
1b69e7e6c   Simon Horman   ipip: support MPL...
634
635
  	pr_info("ipip: IPv4 and MPLS over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636

d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
637
638
639
640
641
  	err = register_pernet_device(&ipip_net_ops);
  	if (err < 0)
  		return err;
  	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
  	if (err < 0) {
058bd4d2a   Joe Perches   net: Convert prin...
642
643
  		pr_info("%s: can't register tunnel
  ", __func__);
1b69e7e6c   Simon Horman   ipip: support MPL...
644
645
646
647
648
649
650
651
  		goto xfrm_tunnel_ipip_failed;
  	}
  #if IS_ENABLED(CONFIG_MPLS)
  	err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
  	if (err < 0) {
  		pr_info("%s: can't register tunnel
  ", __func__);
  		goto xfrm_tunnel_mplsip_failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  	}
1b69e7e6c   Simon Horman   ipip: support MPL...
653
  #endif
0974658da   Nicolas Dichtel   ipip: advertise t...
654
655
656
657
658
  	err = rtnl_link_register(&ipip_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
  	return err;
0974658da   Nicolas Dichtel   ipip: advertise t...
660
661
  
  rtnl_link_failed:
1b69e7e6c   Simon Horman   ipip: support MPL...
662
663
664
665
666
  #if IS_ENABLED(CONFIG_MPLS)
  	xfrm4_tunnel_deregister(&mplsip_handler, AF_INET);
  xfrm_tunnel_mplsip_failed:
  
  #endif
0974658da   Nicolas Dichtel   ipip: advertise t...
667
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
1b69e7e6c   Simon Horman   ipip: support MPL...
668
  xfrm_tunnel_ipip_failed:
0974658da   Nicolas Dichtel   ipip: advertise t...
669
670
  	unregister_pernet_device(&ipip_net_ops);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
  }
  
  static void __exit ipip_fini(void)
  {
0974658da   Nicolas Dichtel   ipip: advertise t...
675
  	rtnl_link_unregister(&ipip_link_ops);
c0d56408e   Kazunori MIYAZAWA   [IPSEC]: Changing...
676
  	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
058bd4d2a   Joe Perches   net: Convert prin...
677
678
  		pr_info("%s: can't deregister tunnel
  ", __func__);
1b69e7e6c   Simon Horman   ipip: support MPL...
679
680
681
682
683
  #if IS_ENABLED(CONFIG_MPLS)
  	if (xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS))
  		pr_info("%s: can't deregister tunnel
  ", __func__);
  #endif
86de8a631   Eric W. Biederman   net: Simplify ipi...
684
  	unregister_pernet_device(&ipip_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
687
688
689
  }
  
  module_init(ipip_init);
  module_exit(ipip_fini);
  MODULE_LICENSE("GPL");
f98f89a01   Tom Gundersen   net: tunnels - en...
690
  MODULE_ALIAS_RTNL_LINK("ipip");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
691
  MODULE_ALIAS_NETDEV("tunl0");