Blame view

net/ipv4/ipip.c 13 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
2
   *	Linux NET3:	IP/IP protocol decoder.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   *	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.
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   *
   */
  
  /* 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...
36

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
  	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...
43

113aa838e   Alan Cox   net: Rationalise ...
44
  		-Alan Cox	(alan@lxorguk.ukuu.org.uk) 21 March 95
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
51
52
  
  	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...
53

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  */
  
  /* 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...
76
  	find out how much more space you can allocate by calling
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  	"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...
92

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

eccc1bb8d   stephen hemminger   tunnel: drop pack...
119
120
121
  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");
f99189b18   Eric Dumazet   netns: net_identi...
122
  static int ipip_net_id __read_mostly;
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
123

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

d2acc3479   Herbert Xu   [INET]: Introduce...
127
  static int ipip_err(struct sk_buff *skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129

071f92d05   Rami Rosen   net: The world is...
130
  /* All the routers (except for Linux) return only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
     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...
134
135
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
b71d1d426   Eric Dumazet   inet: constify ip...
136
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  	struct ip_tunnel *t;
d2acc3479   Herbert Xu   [INET]: Introduce...
138
  	int err;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
139
140
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141

d2acc3479   Herbert Xu   [INET]: Introduce...
142
  	err = -ENOENT;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
143
144
  	t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  			     iph->daddr, iph->saddr, 0);
363933955   David S. Miller   ipv4: Handle PMTU...
145
146
147
148
149
150
151
152
153
  	if (t == NULL)
  		goto out;
  
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
  		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
  				 t->dev->ifindex, 0, IPPROTO_IPIP, 0);
  		err = 0;
  		goto out;
  	}
55be7a9c6   David S. Miller   ipv4: Add redirec...
154
155
156
157
158
159
  	if (type == ICMP_REDIRECT) {
  		ipv4_redirect(skb, dev_net(skb->dev), t->dev->ifindex, 0,
  			      IPPROTO_IPIP, 0);
  		err = 0;
  		goto out;
  	}
363933955   David S. Miller   ipv4: Handle PMTU...
160
  	if (t->parms.iph.daddr == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  		goto out;
d2acc3479   Herbert Xu   [INET]: Introduce...
162
163
  
  	err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
  		goto out;
26d94b46d   Wei Yongjun   ipip: used time_b...
166
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
b0558ef24   stephen hemminger   xfrm: remove extr...
171

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
172
  out:
d2acc3479   Herbert Xu   [INET]: Introduce...
173
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  }
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
175
176
177
178
  static const struct tnl_ptk_info tpi = {
  	/* no tunnel info required for ipip. */
  	.proto = htons(ETH_P_IP),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  static int ipip_rcv(struct sk_buff *skb)
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
181
182
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  	struct ip_tunnel *tunnel;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
184
  	const struct iphdr *iph = ip_hdr(skb);
3c97af99a   Eric Dumazet   ipip: percpu stat...
185

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
186
187
188
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  			iph->saddr, iph->daddr, 0);
  	if (tunnel) {
eccc1bb8d   stephen hemminger   tunnel: drop pack...
189
190
  		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  			goto drop;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
191
  		return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  	return -1;
eccc1bb8d   stephen hemminger   tunnel: drop pack...
195
196
197
198
  
  drop:
  	kfree_skb(skb);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
  }
  
  /*
   *	This function assumes it is being called from dev_queue_xmit()
   *	and that skb is filled properly by that function.
   */
6fef4c0c8   Stephen Hemminger   netdev: convert p...
205
  static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
207
  	struct ip_tunnel *tunnel = netdev_priv(dev);
b71d1d426   Eric Dumazet   inet: constify ip...
208
  	const struct iphdr  *tiph = &tunnel->parms.iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
210
  	if (unlikely(skb->protocol != htons(ETH_P_IP)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  		goto tx_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
213
  	if (likely(!skb->encapsulation)) {
4f3ed9209   Pravin B Shelar   ipip: capture inn...
214
215
216
  		skb_reset_inner_headers(skb);
  		skb->encapsulation = 1;
  	}
8344bfc60   Pravin B Shelar   ipip: Use tunnel_...
217

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
218
  	ip_tunnel_xmit(skb, dev, tiph);
6ed106549   Patrick McHardy   net: use NETDEV_T...
219
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  tx_error:
3c97af99a   Eric Dumazet   ipip: percpu stat...
222
  	dev->stats.tx_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  	dev_kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
224
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
  }
  
  static int
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
228
  ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
  {
  	int err = 0;
  	struct ip_tunnel_parm p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

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

0e7eadef8   Cong Wang   ipip: fix a regre...
236
237
238
239
240
241
242
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
  		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
  		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
  			return -EINVAL;
  	}
  
  	p.i_key = p.o_key = p.i_flags = p.o_flags = 0;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
243
244
245
246
247
248
249
250
251
  	if (p.iph.ttl)
  		p.iph.frag_off |= htons(IP_DF);
  
  	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
252
253
  	return 0;
  }
23a12b147   Stephen Hemminger   ipip: convert to ...
254
  static const struct net_device_ops ipip_netdev_ops = {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
255
256
  	.ndo_init       = ipip_tunnel_init,
  	.ndo_uninit     = ip_tunnel_uninit,
23a12b147   Stephen Hemminger   ipip: convert to ...
257
258
  	.ndo_start_xmit	= ipip_tunnel_xmit,
  	.ndo_do_ioctl	= ipip_tunnel_ioctl,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
259
260
  	.ndo_change_mtu = ip_tunnel_change_mtu,
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
23a12b147   Stephen Hemminger   ipip: convert to ...
261
  };
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
262
263
264
265
  #define IPIP_FEATURES (NETIF_F_SG |		\
  		       NETIF_F_FRAGLIST |	\
  		       NETIF_F_HIGHDMA |	\
  		       NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  static void ipip_tunnel_setup(struct net_device *dev)
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
268
  	dev->netdev_ops		= &ipip_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  
  	dev->type		= ARPHRD_TUNNEL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  	dev->flags		= IFF_NOARP;
  	dev->iflink		= 0;
  	dev->addr_len		= 4;
0a826406d   Pavel Emelyanov   [IPIP]: Allow to ...
274
  	dev->features		|= NETIF_F_NETNS_LOCAL;
153f09433   Eric Dumazet   ipip: enable lock...
275
  	dev->features		|= NETIF_F_LLTX;
28e72216d   Eric Dumazet   net: unset IFF_XM...
276
  	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
c3b89fbba   Eric Dumazet   ipip: add GSO sup...
277
278
279
  
  	dev->features		|= IPIP_FEATURES;
  	dev->hw_features	|= IPIP_FEATURES;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
280
  	ip_tunnel_setup(dev, ipip_net_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  }
3c97af99a   Eric Dumazet   ipip: percpu stat...
282
  static int ipip_tunnel_init(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  {
23a12b147   Stephen Hemminger   ipip: convert to ...
284
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
  	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
288
289
290
  	tunnel->hlen = 0;
  	tunnel->parms.iph.protocol = IPPROTO_IPIP;
  	return ip_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  }
be42da0e1   Nicolas Dichtel   ipip: add support...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  static void ipip_netlink_parms(struct nlattr *data[],
  			       struct ip_tunnel_parm *parms)
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.version = 4;
  	parms->iph.protocol = IPPROTO_IPIP;
  	parms->iph.ihl = 5;
  
  	if (!data)
  		return;
  
  	if (data[IFLA_IPTUN_LINK])
  		parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
  
  	if (data[IFLA_IPTUN_LOCAL])
fea379b2d   Nicolas Dichtel   ipip: fix sparse ...
308
  		parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
be42da0e1   Nicolas Dichtel   ipip: add support...
309
310
  
  	if (data[IFLA_IPTUN_REMOTE])
fea379b2d   Nicolas Dichtel   ipip: fix sparse ...
311
  		parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
be42da0e1   Nicolas Dichtel   ipip: add support...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  
  	if (data[IFLA_IPTUN_TTL]) {
  		parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
  		if (parms->iph.ttl)
  			parms->iph.frag_off = htons(IP_DF);
  	}
  
  	if (data[IFLA_IPTUN_TOS])
  		parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
  
  	if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
  		parms->iph.frag_off = htons(IP_DF);
  }
  
  static int ipip_newlink(struct net *src_net, struct net_device *dev,
  			struct nlattr *tb[], struct nlattr *data[])
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
329
  	struct ip_tunnel_parm p;
be42da0e1   Nicolas Dichtel   ipip: add support...
330

fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
331
332
  	ipip_netlink_parms(data, &p);
  	return ip_tunnel_newlink(dev, tb, &p);
be42da0e1   Nicolas Dichtel   ipip: add support...
333
334
335
336
337
  }
  
  static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
  			   struct nlattr *data[])
  {
be42da0e1   Nicolas Dichtel   ipip: add support...
338
  	struct ip_tunnel_parm p;
be42da0e1   Nicolas Dichtel   ipip: add support...
339
340
341
342
343
344
  
  	ipip_netlink_parms(data, &p);
  
  	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
  	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
  		return -EINVAL;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
345
  	return ip_tunnel_changelink(dev, tb, &p);
be42da0e1   Nicolas Dichtel   ipip: add support...
346
  }
0974658da   Nicolas Dichtel   ipip: advertise t...
347
348
349
350
351
352
353
354
355
356
357
358
359
  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) +
befe2aa1b   Nicolas Dichtel   ipip/rtnl: add IF...
360
361
  		/* IFLA_IPTUN_PMTUDISC */
  		nla_total_size(1) +
0974658da   Nicolas Dichtel   ipip: advertise t...
362
363
364
365
366
367
368
369
370
371
372
373
  		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) ||
  	    nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
  	    nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
  	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
befe2aa1b   Nicolas Dichtel   ipip/rtnl: add IF...
374
375
376
  	    nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
  	    nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
  		       !!(parm->iph.frag_off & htons(IP_DF))))
0974658da   Nicolas Dichtel   ipip: advertise t...
377
378
379
380
381
382
  		goto nla_put_failure;
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
be42da0e1   Nicolas Dichtel   ipip: add support...
383
384
385
386
387
388
389
390
  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 },
  	[IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 },
  };
0974658da   Nicolas Dichtel   ipip: advertise t...
391
392
393
  static struct rtnl_link_ops ipip_link_ops __read_mostly = {
  	.kind		= "ipip",
  	.maxtype	= IFLA_IPTUN_MAX,
be42da0e1   Nicolas Dichtel   ipip: add support...
394
  	.policy		= ipip_policy,
0974658da   Nicolas Dichtel   ipip: advertise t...
395
  	.priv_size	= sizeof(struct ip_tunnel),
be42da0e1   Nicolas Dichtel   ipip: add support...
396
397
398
  	.setup		= ipip_tunnel_setup,
  	.newlink	= ipip_newlink,
  	.changelink	= ipip_changelink,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
399
  	.dellink	= ip_tunnel_dellink,
0974658da   Nicolas Dichtel   ipip: advertise t...
400
401
402
  	.get_size	= ipip_get_size,
  	.fill_info	= ipip_fill_info,
  };
6dcd814bd   Eric Dumazet   net: struct xfrm_...
403
  static struct xfrm_tunnel ipip_handler __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
  	.handler	=	ipip_rcv,
  	.err_handler	=	ipip_err,
d2acc3479   Herbert Xu   [INET]: Introduce...
406
  	.priority	=	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
408
  static int __net_init ipip_init_net(struct net *net)
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
409
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
410
  	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
411
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
412
  static void __net_exit ipip_exit_net(struct net *net)
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
413
  {
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
414
415
  	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
  	ip_tunnel_delete_net(itn);
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
416
417
418
419
420
  }
  
  static struct pernet_operations ipip_net_ops = {
  	.init = ipip_init_net,
  	.exit = ipip_exit_net,
86de8a631   Eric W. Biederman   net: Simplify ipi...
421
  	.id   = &ipip_net_id,
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
422
  	.size = sizeof(struct ip_tunnel_net),
10dc4c7bb   Pavel Emelyanov   [IPIP]: Introduce...
423
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
  static int __init ipip_init(void)
  {
  	int err;
fd58156e4   Pravin B Shelar   IPIP: Use ip-tunn...
427
428
  	pr_info("ipip: IPv4 over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429

d5aa407f5   Alexey Dobriyan   tunnels: fix netn...
430
431
432
433
434
  	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...
435
436
  		pr_info("%s: can't register tunnel
  ", __func__);
0974658da   Nicolas Dichtel   ipip: advertise t...
437
  		goto xfrm_tunnel_failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	}
0974658da   Nicolas Dichtel   ipip: advertise t...
439
440
441
442
443
  	err = rtnl_link_register(&ipip_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	return err;
0974658da   Nicolas Dichtel   ipip: advertise t...
445
446
447
448
449
450
  
  rtnl_link_failed:
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
  xfrm_tunnel_failed:
  	unregister_pernet_device(&ipip_net_ops);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
  }
  
  static void __exit ipip_fini(void)
  {
0974658da   Nicolas Dichtel   ipip: advertise t...
455
  	rtnl_link_unregister(&ipip_link_ops);
c0d56408e   Kazunori MIYAZAWA   [IPSEC]: Changing...
456
  	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
058bd4d2a   Joe Perches   net: Convert prin...
457
458
  		pr_info("%s: can't deregister tunnel
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459

86de8a631   Eric W. Biederman   net: Simplify ipi...
460
  	unregister_pernet_device(&ipip_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
464
465
  }
  
  module_init(ipip_init);
  module_exit(ipip_fini);
  MODULE_LICENSE("GPL");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
466
  MODULE_ALIAS_NETDEV("tunl0");