Blame view

net/ipv4/ipip.c 18.4 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
  	u8 ipproto;
47d858d0b   Haishuang Yan   ipip: validate he...
265
266
  	if (!pskb_inet_may_pull(skb))
  		goto tx_error;
1b69e7e6c   Simon Horman   ipip: support MPL...
267
268
269
270
271
272
273
274
275
276
277
278
  	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
279

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

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

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

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

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

cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
297
  	dev->stats.tx_errors++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
298
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  }
1b69e7e6c   Simon Horman   ipip: support MPL...
300
301
302
303
304
305
306
307
308
309
310
311
312
  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
313
  static int
607259a69   Christoph Hellwig   net: add a new nd...
314
  ipip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  {
3b7b514f4   Cong Wang   ipip: fix a regre...
316
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
607259a69   Christoph Hellwig   net: add a new nd...
317
318
319
  		if (p->iph.version != 4 ||
  		    !ipip_tunnel_ioctl_verify_protocol(p->iph.protocol) ||
  		    p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)))
3b7b514f4   Cong Wang   ipip: fix a regre...
320
321
  			return -EINVAL;
  	}
607259a69   Christoph Hellwig   net: add a new nd...
322
323
324
  	p->i_key = p->o_key = 0;
  	p->i_flags = p->o_flags = 0;
  	return ip_tunnel_ctl(dev, p, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  }
23a12b147   Stephen Hemminger   ipip: convert to ...
326
  static const struct net_device_ops ipip_netdev_ops = {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
327
328
  	.ndo_init       = ipip_tunnel_init,
  	.ndo_uninit     = ip_tunnel_uninit,
23a12b147   Stephen Hemminger   ipip: convert to ...
329
  	.ndo_start_xmit	= ipip_tunnel_xmit,
607259a69   Christoph Hellwig   net: add a new nd...
330
  	.ndo_do_ioctl	= ip_tunnel_ioctl,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
331
332
  	.ndo_change_mtu = ip_tunnel_change_mtu,
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
333
  	.ndo_get_iflink = ip_tunnel_get_iflink,
607259a69   Christoph Hellwig   net: add a new nd...
334
  	.ndo_tunnel_ctl	= ipip_tunnel_ctl,
23a12b147   Stephen Hemminger   ipip: convert to ...
335
  };
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
336
337
338
  #define IPIP_FEATURES (NETIF_F_SG |		\
  		       NETIF_F_FRAGLIST |	\
  		       NETIF_F_HIGHDMA |	\
cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
339
  		       NETIF_F_GSO_SOFTWARE |	\
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
340
  		       NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  static void ipip_tunnel_setup(struct net_device *dev)
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
343
  	dev->netdev_ops		= &ipip_netdev_ops;
e53ac9322   Jason A. Donenfeld   net: ipip: implem...
344
  	dev->header_ops		= &ip_tunnel_header_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
  
  	dev->type		= ARPHRD_TUNNEL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  	dev->flags		= IFF_NOARP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	dev->addr_len		= 4;
153f09433   Eric Dumazet   ipip: enable lock...
349
  	dev->features		|= NETIF_F_LLTX;
028758788   Eric Dumazet   net: better IFF_X...
350
  	netif_keep_dst(dev);
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
351
352
353
  
  	dev->features		|= IPIP_FEATURES;
  	dev->hw_features	|= IPIP_FEATURES;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
354
  	ip_tunnel_setup(dev, ipip_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  }
3c97af99a   Eric Dumazet   ipip: percpu stat...
356
  static int ipip_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
358
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359

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

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

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

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