Blame view

net/ipv4/ip_vti.c 15.1 KB
1181412c1   Saurabh   net/ipv4: VTI sup...
1
2
3
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
  /*
   *	Linux NET3: IP/IP protocol decoder modified to support
   *		    virtual tunnel interface
   *
   *	Authors:
   *		Saurabh Mohan (saurabh.mohan@vyatta.com) 05/07/2012
   *
   *	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.
   *
   */
  
  /*
     This version of net/ipv4/ip_vti.c is cloned of net/ipv4/ipip.c
  
     For comments look at net/ipv4/ip_gre.c --ANK
   */
  
  
  #include <linux/capability.h>
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/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>
1181412c1   Saurabh   net/ipv4: VTI sup...
33
34
35
  #include <linux/init.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/if_ether.h>
78a010cca   Steffen Klassert   vti4: Support int...
36
  #include <linux/icmpv6.h>
1181412c1   Saurabh   net/ipv4: VTI sup...
37
38
39
40
  
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
41
  #include <net/ip_tunnels.h>
1181412c1   Saurabh   net/ipv4: VTI sup...
42
43
44
45
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
1181412c1   Saurabh   net/ipv4: VTI sup...
46
  static struct rtnl_link_ops vti_link_ops __read_mostly;
c7d03a00b   Alexey Dobriyan   netns: make struc...
47
  static unsigned int vti_net_id __read_mostly;
1181412c1   Saurabh   net/ipv4: VTI sup...
48
  static int vti_tunnel_init(struct net_device *dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
49

df3893c17   Steffen Klassert   vti: Update the i...
50
51
  static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
  		     int encap_type)
1181412c1   Saurabh   net/ipv4: VTI sup...
52
53
54
  {
  	struct ip_tunnel *tunnel;
  	const struct iphdr *iph = ip_hdr(skb);
b9959fd3b   Amerigo Wang   vti: switch to ne...
55
56
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
1181412c1   Saurabh   net/ipv4: VTI sup...
57

b9959fd3b   Amerigo Wang   vti: switch to ne...
58
59
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  				  iph->saddr, iph->daddr, 0);
00db41243   Ian Morris   ipv4: coding styl...
60
  	if (tunnel) {
df3893c17   Steffen Klassert   vti: Update the i...
61
62
63
64
  		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  			goto drop;
  
  		XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
df3893c17   Steffen Klassert   vti: Update the i...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  
  		return xfrm_input(skb, nexthdr, spi, encap_type);
  	}
  
  	return -EINVAL;
  drop:
  	kfree_skb(skb);
  	return 0;
  }
  
  static int vti_rcv(struct sk_buff *skb)
  {
  	XFRM_SPI_SKB_CB(skb)->family = AF_INET;
  	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
  
  	return vti_input(skb, ip_hdr(skb)->protocol, 0, 0);
  }
  
  static int vti_rcv_cb(struct sk_buff *skb, int err)
  {
  	unsigned short family;
  	struct net_device *dev;
  	struct pcpu_sw_netstats *tstats;
  	struct xfrm_state *x;
1fb81e09d   thomas.zeitlhofer+lkml@ze-it.at   vti: use right in...
89
  	struct xfrm_mode *inner_mode;
df3893c17   Steffen Klassert   vti: Update the i...
90
  	struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
d55c670cb   Alexander Duyck   ip_vti/ip6_vti: P...
91
92
  	u32 orig_mark = skb->mark;
  	int ret;
df3893c17   Steffen Klassert   vti: Update the i...
93
94
  
  	if (!tunnel)
1181412c1   Saurabh   net/ipv4: VTI sup...
95
  		return 1;
df3893c17   Steffen Klassert   vti: Update the i...
96
97
98
99
100
101
102
103
  
  	dev = tunnel->dev;
  
  	if (err) {
  		dev->stats.rx_errors++;
  		dev->stats.rx_dropped++;
  
  		return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
104
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
105

df3893c17   Steffen Klassert   vti: Update the i...
106
  	x = xfrm_input_state(skb);
1fb81e09d   thomas.zeitlhofer+lkml@ze-it.at   vti: use right in...
107
108
109
110
111
112
113
114
115
116
117
118
119
  
  	inner_mode = x->inner_mode;
  
  	if (x->sel.family == AF_UNSPEC) {
  		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
  		if (inner_mode == NULL) {
  			XFRM_INC_STATS(dev_net(skb->dev),
  				       LINUX_MIB_XFRMINSTATEMODEERROR);
  			return -EINVAL;
  		}
  	}
  
  	family = inner_mode->afinfo->family;
df3893c17   Steffen Klassert   vti: Update the i...
120

d55c670cb   Alexander Duyck   ip_vti/ip6_vti: P...
121
122
123
124
125
  	skb->mark = be32_to_cpu(tunnel->parms.i_key);
  	ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
  	skb->mark = orig_mark;
  
  	if (!ret)
df3893c17   Steffen Klassert   vti: Update the i...
126
127
128
129
130
131
132
133
134
135
136
137
138
  		return -EPERM;
  
  	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
  	skb->dev = dev;
  
  	tstats = this_cpu_ptr(dev->tstats);
  
  	u64_stats_update_begin(&tstats->syncp);
  	tstats->rx_packets++;
  	tstats->rx_bytes += skb->len;
  	u64_stats_update_end(&tstats->syncp);
  
  	return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
139
  }
6e2de802a   Steffen Klassert   vti4: Check the t...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  static bool vti_state_check(const struct xfrm_state *x, __be32 dst, __be32 src)
  {
  	xfrm_address_t *daddr = (xfrm_address_t *)&dst;
  	xfrm_address_t *saddr = (xfrm_address_t *)&src;
  
  	/* if there is no transform then this tunnel is not functional.
  	 * Or if the xfrm is not mode tunnel.
  	 */
  	if (!x || x->props.mode != XFRM_MODE_TUNNEL ||
  	    x->props.family != AF_INET)
  		return false;
  
  	if (!dst)
  		return xfrm_addr_equal(saddr, &x->props.saddr, AF_INET);
  
  	if (!xfrm_state_addr_check(x, daddr, saddr, AF_INET))
  		return false;
  
  	return true;
  }
78a010cca   Steffen Klassert   vti4: Support int...
160
161
  static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
  			    struct flowi *fl)
1181412c1   Saurabh   net/ipv4: VTI sup...
162
163
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
6e2de802a   Steffen Klassert   vti4: Check the t...
164
  	struct ip_tunnel_parm *parms = &tunnel->parms;
a34cd4f31   Steffen Klassert   vti4: Use the on ...
165
  	struct dst_entry *dst = skb_dst(skb);
1181412c1   Saurabh   net/ipv4: VTI sup...
166
  	struct net_device *tdev;	/* Device to other host */
36f6ee22d   Alexey Kodanev   vti: fix use afte...
167
  	int pkt_len = skb->len;
b9959fd3b   Amerigo Wang   vti: switch to ne...
168
  	int err;
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
169
  	int mtu;
1181412c1   Saurabh   net/ipv4: VTI sup...
170

a34cd4f31   Steffen Klassert   vti4: Use the on ...
171
  	if (!dst) {
df3893c17   Steffen Klassert   vti: Update the i...
172
173
174
  		dev->stats.tx_carrier_errors++;
  		goto tx_error_icmp;
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
175

a34cd4f31   Steffen Klassert   vti4: Use the on ...
176
  	dst_hold(dst);
78a010cca   Steffen Klassert   vti4: Support int...
177
  	dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0);
a34cd4f31   Steffen Klassert   vti4: Use the on ...
178
  	if (IS_ERR(dst)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
179
180
181
  		dev->stats.tx_carrier_errors++;
  		goto tx_error_icmp;
  	}
df3893c17   Steffen Klassert   vti: Update the i...
182

6e2de802a   Steffen Klassert   vti4: Check the t...
183
  	if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
184
  		dev->stats.tx_carrier_errors++;
a34cd4f31   Steffen Klassert   vti4: Use the on ...
185
  		dst_release(dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
186
187
  		goto tx_error_icmp;
  	}
6e2de802a   Steffen Klassert   vti4: Check the t...
188

a34cd4f31   Steffen Klassert   vti4: Use the on ...
189
  	tdev = dst->dev;
1181412c1   Saurabh   net/ipv4: VTI sup...
190
191
  
  	if (tdev == dev) {
a34cd4f31   Steffen Klassert   vti4: Use the on ...
192
  		dst_release(dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
193
194
195
196
197
198
199
200
201
202
203
204
  		dev->stats.collisions++;
  		goto tx_error;
  	}
  
  	if (tunnel->err_count > 0) {
  		if (time_before(jiffies,
  				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
  			tunnel->err_count--;
  			dst_link_failure(skb);
  		} else
  			tunnel->err_count = 0;
  	}
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
205
206
  	mtu = dst_mtu(dst);
  	if (skb->len > mtu) {
6a3c946b2   Nicolas Dichtel   net: don't call u...
207
  		skb_dst_update_pmtu(skb, mtu);
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
208
209
210
211
212
213
214
215
216
217
218
219
220
  		if (skb->protocol == htons(ETH_P_IP)) {
  			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
  				  htonl(mtu));
  		} else {
  			if (mtu < IPV6_MIN_MTU)
  				mtu = IPV6_MIN_MTU;
  
  			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
  		}
  
  		dst_release(dst);
  		goto tx_error;
  	}
df3893c17   Steffen Klassert   vti: Update the i...
221
  	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
a34cd4f31   Steffen Klassert   vti4: Use the on ...
222
  	skb_dst_set(skb, dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
223
  	skb->dev = skb_dst(skb)->dev;
13206b6bf   Eric W. Biederman   net: Pass net int...
224
  	err = dst_output(tunnel->net, skb->sk, skb);
b9959fd3b   Amerigo Wang   vti: switch to ne...
225
  	if (net_xmit_eval(err) == 0)
36f6ee22d   Alexey Kodanev   vti: fix use afte...
226
  		err = pkt_len;
039f50629   Pravin B Shelar   ip_tunnel: Move s...
227
  	iptunnel_xmit_stats(dev, err);
1181412c1   Saurabh   net/ipv4: VTI sup...
228
229
230
231
232
233
  	return NETDEV_TX_OK;
  
  tx_error_icmp:
  	dst_link_failure(skb);
  tx_error:
  	dev->stats.tx_errors++;
3acfa1e73   Eric Dumazet   ipv4: be friend w...
234
  	kfree_skb(skb);
1181412c1   Saurabh   net/ipv4: VTI sup...
235
236
  	return NETDEV_TX_OK;
  }
78a010cca   Steffen Klassert   vti4: Support int...
237
238
239
240
241
242
243
244
245
  /* This function assumes it is being called from dev_queue_xmit()
   * and that skb is filled properly by that function.
   */
  static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct flowi fl;
  
  	memset(&fl, 0, sizeof(fl));
78a010cca   Steffen Klassert   vti4: Support int...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  	switch (skb->protocol) {
  	case htons(ETH_P_IP):
  		xfrm_decode_session(skb, &fl, AF_INET);
  		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
  		break;
  	case htons(ETH_P_IPV6):
  		xfrm_decode_session(skb, &fl, AF_INET6);
  		memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
  		break;
  	default:
  		dev->stats.tx_errors++;
  		dev_kfree_skb(skb);
  		return NETDEV_TX_OK;
  	}
cd5279c19   Alexander Duyck   ip_vti/ip6_vti: D...
260
261
  	/* override mark with tunnel output key */
  	fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
78a010cca   Steffen Klassert   vti4: Support int...
262
263
  	return vti_xmit(skb, dev, &fl);
  }
df3893c17   Steffen Klassert   vti: Update the i...
264
265
266
  static int vti4_err(struct sk_buff *skb, u32 info)
  {
  	__be32 spi;
6d004d6cc   Steffen Klassert   vti: Use the tunn...
267
  	__u32 mark;
df3893c17   Steffen Klassert   vti: Update the i...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  	struct xfrm_state *x;
  	struct ip_tunnel *tunnel;
  	struct ip_esp_hdr *esph;
  	struct ip_auth_hdr *ah ;
  	struct ip_comp_hdr *ipch;
  	struct net *net = dev_net(skb->dev);
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
  	int protocol = iph->protocol;
  	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
  
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  				  iph->daddr, iph->saddr, 0);
  	if (!tunnel)
  		return -1;
6d004d6cc   Steffen Klassert   vti: Use the tunn...
282
  	mark = be32_to_cpu(tunnel->parms.o_key);
df3893c17   Steffen Klassert   vti: Update the i...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  	switch (protocol) {
  	case IPPROTO_ESP:
  		esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
  		spi = esph->spi;
  		break;
  	case IPPROTO_AH:
  		ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
  		spi = ah->spi;
  		break;
  	case IPPROTO_COMP:
  		ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
  		spi = htonl(ntohs(ipch->cpi));
  		break;
  	default:
  		return 0;
  	}
  
  	switch (icmp_hdr(skb)->type) {
  	case ICMP_DEST_UNREACH:
  		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
  			return 0;
  	case ICMP_REDIRECT:
  		break;
  	default:
  		return 0;
  	}
6d004d6cc   Steffen Klassert   vti: Use the tunn...
309
  	x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
df3893c17   Steffen Klassert   vti: Update the i...
310
311
312
313
314
315
316
317
318
319
320
321
  			      spi, protocol, AF_INET);
  	if (!x)
  		return 0;
  
  	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
  		ipv4_update_pmtu(skb, net, info, 0, 0, protocol, 0);
  	else
  		ipv4_redirect(skb, net, 0, 0, protocol, 0);
  	xfrm_state_put(x);
  
  	return 0;
  }
1181412c1   Saurabh   net/ipv4: VTI sup...
322
323
324
325
326
  static int
  vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
  	int err = 0;
  	struct ip_tunnel_parm p;
1181412c1   Saurabh   net/ipv4: VTI sup...
327

b9959fd3b   Amerigo Wang   vti: switch to ne...
328
329
  	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
  		return -EFAULT;
1181412c1   Saurabh   net/ipv4: VTI sup...
330

b9959fd3b   Amerigo Wang   vti: switch to ne...
331
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
1181412c1   Saurabh   net/ipv4: VTI sup...
332
333
  		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
  		    p.iph.ihl != 5)
b9959fd3b   Amerigo Wang   vti: switch to ne...
334
335
  			return -EINVAL;
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
336

7c8e6b9c2   Dmitry Popov   ip_vti: Fix 'ip t...
337
338
339
340
341
342
  	if (!(p.i_flags & GRE_KEY))
  		p.i_key = 0;
  	if (!(p.o_flags & GRE_KEY))
  		p.o_key = 0;
  
  	p.i_flags = VTI_ISVTI;
b9959fd3b   Amerigo Wang   vti: switch to ne...
343
344
345
  	err = ip_tunnel_ioctl(dev, &p, cmd);
  	if (err)
  		return err;
1181412c1   Saurabh   net/ipv4: VTI sup...
346

b9959fd3b   Amerigo Wang   vti: switch to ne...
347
  	if (cmd != SIOCDELTUNNEL) {
df3893c17   Steffen Klassert   vti: Update the i...
348
  		p.i_flags |= GRE_KEY;
b9959fd3b   Amerigo Wang   vti: switch to ne...
349
  		p.o_flags |= GRE_KEY;
1181412c1   Saurabh   net/ipv4: VTI sup...
350
  	}
b9959fd3b   Amerigo Wang   vti: switch to ne...
351
352
  	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
  		return -EFAULT;
1181412c1   Saurabh   net/ipv4: VTI sup...
353
354
355
356
357
  	return 0;
  }
  
  static const struct net_device_ops vti_netdev_ops = {
  	.ndo_init	= vti_tunnel_init,
b9959fd3b   Amerigo Wang   vti: switch to ne...
358
  	.ndo_uninit	= ip_tunnel_uninit,
1181412c1   Saurabh   net/ipv4: VTI sup...
359
360
  	.ndo_start_xmit	= vti_tunnel_xmit,
  	.ndo_do_ioctl	= vti_tunnel_ioctl,
b9959fd3b   Amerigo Wang   vti: switch to ne...
361
  	.ndo_change_mtu	= ip_tunnel_change_mtu,
f61dd388a   Pravin B Shelar   Tunneling: use IP...
362
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
363
  	.ndo_get_iflink = ip_tunnel_get_iflink,
1181412c1   Saurabh   net/ipv4: VTI sup...
364
  };
b9959fd3b   Amerigo Wang   vti: switch to ne...
365
  static void vti_tunnel_setup(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
366
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
367
  	dev->netdev_ops		= &vti_netdev_ops;
8d89dcdf8   Nicolas Dichtel   vti: don't allow ...
368
  	dev->type		= ARPHRD_TUNNEL;
b9959fd3b   Amerigo Wang   vti: switch to ne...
369
  	ip_tunnel_setup(dev, vti_net_id);
1181412c1   Saurabh   net/ipv4: VTI sup...
370
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
371
  static int vti_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
372
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
373
374
375
376
377
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
  
  	memcpy(dev->dev_addr, &iph->saddr, 4);
  	memcpy(dev->broadcast, &iph->daddr, 4);
1181412c1   Saurabh   net/ipv4: VTI sup...
378

3e496be20   Greg Kroah-Hartman   Revert "vti4: Don...
379
  	dev->mtu		= ETH_DATA_LEN;
1181412c1   Saurabh   net/ipv4: VTI sup...
380
  	dev->flags		= IFF_NOARP;
1181412c1   Saurabh   net/ipv4: VTI sup...
381
  	dev->addr_len		= 4;
1181412c1   Saurabh   net/ipv4: VTI sup...
382
  	dev->features		|= NETIF_F_LLTX;
028758788   Eric Dumazet   net: better IFF_X...
383
  	netif_keep_dst(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
384

b9959fd3b   Amerigo Wang   vti: switch to ne...
385
  	return ip_tunnel_init(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
386
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
387
  static void __net_init vti_fb_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
388
389
390
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
1181412c1   Saurabh   net/ipv4: VTI sup...
391

1181412c1   Saurabh   net/ipv4: VTI sup...
392
393
394
  	iph->version		= 4;
  	iph->protocol		= IPPROTO_IPIP;
  	iph->ihl		= 5;
1181412c1   Saurabh   net/ipv4: VTI sup...
395
  }
df3893c17   Steffen Klassert   vti: Update the i...
396
  static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
1181412c1   Saurabh   net/ipv4: VTI sup...
397
  	.handler	=	vti_rcv,
df3893c17   Steffen Klassert   vti: Update the i...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  	.input_handler	=	vti_input,
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
  };
  
  static struct xfrm4_protocol vti_ah4_protocol __read_mostly = {
  	.handler	=	vti_rcv,
  	.input_handler	=	vti_input,
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
  };
  
  static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
  	.handler	=	vti_rcv,
  	.input_handler	=	vti_input,
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
1181412c1   Saurabh   net/ipv4: VTI sup...
418
  };
1181412c1   Saurabh   net/ipv4: VTI sup...
419
420
421
  static int __net_init vti_init_net(struct net *net)
  {
  	int err;
b9959fd3b   Amerigo Wang   vti: switch to ne...
422
  	struct ip_tunnel_net *itn;
1181412c1   Saurabh   net/ipv4: VTI sup...
423

b9959fd3b   Amerigo Wang   vti: switch to ne...
424
  	err = ip_tunnel_init_net(net, vti_net_id, &vti_link_ops, "ip_vti0");
1181412c1   Saurabh   net/ipv4: VTI sup...
425
  	if (err)
b9959fd3b   Amerigo Wang   vti: switch to ne...
426
427
428
  		return err;
  	itn = net_generic(net, vti_net_id);
  	vti_fb_tunnel_init(itn->fb_tunnel_dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
429
  	return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
430
431
432
433
  }
  
  static void __net_exit vti_exit_net(struct net *net)
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
434
  	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
6c742e714   Nicolas Dichtel   ipip: add x-netns...
435
  	ip_tunnel_delete_net(itn, &vti_link_ops);
1181412c1   Saurabh   net/ipv4: VTI sup...
436
437
438
439
440
441
  }
  
  static struct pernet_operations vti_net_ops = {
  	.init = vti_init_net,
  	.exit = vti_exit_net,
  	.id   = &vti_net_id,
b9959fd3b   Amerigo Wang   vti: switch to ne...
442
  	.size = sizeof(struct ip_tunnel_net),
1181412c1   Saurabh   net/ipv4: VTI sup...
443
  };
a8b8a889e   Matthias Schiffer   net: add netlink_...
444
445
  static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  			       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
446
447
448
449
450
  {
  	return 0;
  }
  
  static void vti_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
451
452
  			      struct ip_tunnel_parm *parms,
  			      __u32 *fwmark)
1181412c1   Saurabh   net/ipv4: VTI sup...
453
454
455
456
457
458
459
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.protocol = IPPROTO_IPIP;
  
  	if (!data)
  		return;
df3893c17   Steffen Klassert   vti: Update the i...
460
  	parms->i_flags = VTI_ISVTI;
1181412c1   Saurabh   net/ipv4: VTI sup...
461
462
463
464
465
466
467
468
469
470
  	if (data[IFLA_VTI_LINK])
  		parms->link = nla_get_u32(data[IFLA_VTI_LINK]);
  
  	if (data[IFLA_VTI_IKEY])
  		parms->i_key = nla_get_be32(data[IFLA_VTI_IKEY]);
  
  	if (data[IFLA_VTI_OKEY])
  		parms->o_key = nla_get_be32(data[IFLA_VTI_OKEY]);
  
  	if (data[IFLA_VTI_LOCAL])
67b61f6c1   Jiri Benc   netlink: implemen...
471
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_VTI_LOCAL]);
1181412c1   Saurabh   net/ipv4: VTI sup...
472
473
  
  	if (data[IFLA_VTI_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
474
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_VTI_REMOTE]);
1181412c1   Saurabh   net/ipv4: VTI sup...
475

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
476
477
  	if (data[IFLA_VTI_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]);
1181412c1   Saurabh   net/ipv4: VTI sup...
478
479
480
  }
  
  static int vti_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
481
482
  		       struct nlattr *tb[], struct nlattr *data[],
  		       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
483
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
484
  	struct ip_tunnel_parm parms;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
485
  	__u32 fwmark = 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
486

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
487
488
  	vti_netlink_parms(data, &parms, &fwmark);
  	return ip_tunnel_newlink(dev, tb, &parms, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
489
490
491
  }
  
  static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
492
493
  			  struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
494
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
495
496
  	struct ip_tunnel *t = netdev_priv(dev);
  	__u32 fwmark = t->fwmark;
1181412c1   Saurabh   net/ipv4: VTI sup...
497
  	struct ip_tunnel_parm p;
1181412c1   Saurabh   net/ipv4: VTI sup...
498

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
499
500
  	vti_netlink_parms(data, &p, &fwmark);
  	return ip_tunnel_changelink(dev, tb, &p, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  }
  
  static size_t vti_get_size(const struct net_device *dev)
  {
  	return
  		/* IFLA_VTI_LINK */
  		nla_total_size(4) +
  		/* IFLA_VTI_IKEY */
  		nla_total_size(4) +
  		/* IFLA_VTI_OKEY */
  		nla_total_size(4) +
  		/* IFLA_VTI_LOCAL */
  		nla_total_size(4) +
  		/* IFLA_VTI_REMOTE */
  		nla_total_size(4) +
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
516
517
  		/* IFLA_VTI_FWMARK */
  		nla_total_size(4) +
1181412c1   Saurabh   net/ipv4: VTI sup...
518
519
520
521
522
523
524
  		0;
  }
  
  static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_parm *p = &t->parms;
8ed508fd4   Hangbin Liu   vti: check nla_pu...
525
526
527
528
529
530
531
  	if (nla_put_u32(skb, IFLA_VTI_LINK, p->link) ||
  	    nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key) ||
  	    nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key) ||
  	    nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr) ||
  	    nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr) ||
  	    nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark))
  		return -EMSGSIZE;
1181412c1   Saurabh   net/ipv4: VTI sup...
532
533
534
535
536
537
538
539
540
541
  
  	return 0;
  }
  
  static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = {
  	[IFLA_VTI_LINK]		= { .type = NLA_U32 },
  	[IFLA_VTI_IKEY]		= { .type = NLA_U32 },
  	[IFLA_VTI_OKEY]		= { .type = NLA_U32 },
  	[IFLA_VTI_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
  	[IFLA_VTI_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
542
  	[IFLA_VTI_FWMARK]	= { .type = NLA_U32 },
1181412c1   Saurabh   net/ipv4: VTI sup...
543
544
545
546
547
548
549
550
551
552
553
  };
  
  static struct rtnl_link_ops vti_link_ops __read_mostly = {
  	.kind		= "vti",
  	.maxtype	= IFLA_VTI_MAX,
  	.policy		= vti_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= vti_tunnel_setup,
  	.validate	= vti_tunnel_validate,
  	.newlink	= vti_newlink,
  	.changelink	= vti_changelink,
20ea60ca9   lucien   ip_tunnel: the la...
554
  	.dellink        = ip_tunnel_dellink,
1181412c1   Saurabh   net/ipv4: VTI sup...
555
556
  	.get_size	= vti_get_size,
  	.fill_info	= vti_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
557
  	.get_link_net	= ip_tunnel_get_link_net,
1181412c1   Saurabh   net/ipv4: VTI sup...
558
559
560
561
  };
  
  static int __init vti_init(void)
  {
1990e4f88   Mathias Krause   vti: Simplify err...
562
  	const char *msg;
1181412c1   Saurabh   net/ipv4: VTI sup...
563
  	int err;
1990e4f88   Mathias Krause   vti: Simplify err...
564
565
  	pr_info("IPv4 over IPsec tunneling driver
  ");
1181412c1   Saurabh   net/ipv4: VTI sup...
566

1990e4f88   Mathias Krause   vti: Simplify err...
567
  	msg = "tunnel device";
1181412c1   Saurabh   net/ipv4: VTI sup...
568
569
  	err = register_pernet_device(&vti_net_ops);
  	if (err < 0)
1990e4f88   Mathias Krause   vti: Simplify err...
570
  		goto pernet_dev_failed;
df3893c17   Steffen Klassert   vti: Update the i...
571

1990e4f88   Mathias Krause   vti: Simplify err...
572
573
574
575
  	msg = "tunnel protocols";
  	err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP);
  	if (err < 0)
  		goto xfrm_proto_esp_failed;
df3893c17   Steffen Klassert   vti: Update the i...
576
  	err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
577
578
  	if (err < 0)
  		goto xfrm_proto_ah_failed;
df3893c17   Steffen Klassert   vti: Update the i...
579
  	err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
580
581
  	if (err < 0)
  		goto xfrm_proto_comp_failed;
1181412c1   Saurabh   net/ipv4: VTI sup...
582

1990e4f88   Mathias Krause   vti: Simplify err...
583
  	msg = "netlink interface";
1181412c1   Saurabh   net/ipv4: VTI sup...
584
585
586
587
588
589
590
  	err = rtnl_link_register(&vti_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  	return err;
  
  rtnl_link_failed:
df3893c17   Steffen Klassert   vti: Update the i...
591
  	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
592
  xfrm_proto_comp_failed:
df3893c17   Steffen Klassert   vti: Update the i...
593
  	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
594
  xfrm_proto_ah_failed:
df3893c17   Steffen Klassert   vti: Update the i...
595
  	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
1990e4f88   Mathias Krause   vti: Simplify err...
596
  xfrm_proto_esp_failed:
1181412c1   Saurabh   net/ipv4: VTI sup...
597
  	unregister_pernet_device(&vti_net_ops);
1990e4f88   Mathias Krause   vti: Simplify err...
598
599
600
  pernet_dev_failed:
  	pr_err("vti init: failed to register %s
  ", msg);
1181412c1   Saurabh   net/ipv4: VTI sup...
601
602
603
604
605
606
  	return err;
  }
  
  static void __exit vti_fini(void)
  {
  	rtnl_link_unregister(&vti_link_ops);
1990e4f88   Mathias Krause   vti: Simplify err...
607
608
609
  	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
  	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
  	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
1181412c1   Saurabh   net/ipv4: VTI sup...
610
611
612
613
614
615
616
617
  	unregister_pernet_device(&vti_net_ops);
  }
  
  module_init(vti_init);
  module_exit(vti_fini);
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_RTNL_LINK("vti");
  MODULE_ALIAS_NETDEV("ip_vti0");