Blame view

net/ipv4/ip_vti.c 17 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1181412c1   Saurabh   net/ipv4: VTI sup...
2
3
4
5
6
7
  /*
   *	Linux NET3: IP/IP protocol decoder modified to support
   *		    virtual tunnel interface
   *
   *	Authors:
   *		Saurabh Mohan (saurabh.mohan@vyatta.com) 05/07/2012
1181412c1   Saurabh   net/ipv4: VTI sup...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   */
  
  /*
     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...
28
29
30
  #include <linux/init.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/if_ether.h>
78a010cca   Steffen Klassert   vti4: Support int...
31
  #include <linux/icmpv6.h>
1181412c1   Saurabh   net/ipv4: VTI sup...
32
33
34
35
  
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
36
  #include <net/ip_tunnels.h>
1181412c1   Saurabh   net/ipv4: VTI sup...
37
38
39
40
  #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...
41
  static struct rtnl_link_ops vti_link_ops __read_mostly;
c7d03a00b   Alexey Dobriyan   netns: make struc...
42
  static unsigned int vti_net_id __read_mostly;
1181412c1   Saurabh   net/ipv4: VTI sup...
43
  static int vti_tunnel_init(struct net_device *dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
44

df3893c17   Steffen Klassert   vti: Update the i...
45
  static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
f981c57ff   Jeremy Sowden   vti4: eliminated ...
46
  		     int encap_type, bool update_skb_dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
47
48
49
  {
  	struct ip_tunnel *tunnel;
  	const struct iphdr *iph = ip_hdr(skb);
b9959fd3b   Amerigo Wang   vti: switch to ne...
50
51
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
1181412c1   Saurabh   net/ipv4: VTI sup...
52

b9959fd3b   Amerigo Wang   vti: switch to ne...
53
54
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
  				  iph->saddr, iph->daddr, 0);
00db41243   Ian Morris   ipv4: coding styl...
55
  	if (tunnel) {
df3893c17   Steffen Klassert   vti: Update the i...
56
57
58
59
  		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...
60

f981c57ff   Jeremy Sowden   vti4: eliminated ...
61
62
  		if (update_skb_dev)
  			skb->dev = tunnel->dev;
df3893c17   Steffen Klassert   vti: Update the i...
63
64
65
66
67
68
69
70
  		return xfrm_input(skb, nexthdr, spi, encap_type);
  	}
  
  	return -EINVAL;
  drop:
  	kfree_skb(skb);
  	return 0;
  }
f981c57ff   Jeremy Sowden   vti4: eliminated ...
71
72
  static int vti_input_proto(struct sk_buff *skb, int nexthdr, __be32 spi,
  			   int encap_type)
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
73
  {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
74
  	return vti_input(skb, nexthdr, spi, encap_type, false);
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
75
  }
f981c57ff   Jeremy Sowden   vti4: eliminated ...
76
  static int vti_rcv(struct sk_buff *skb, __be32 spi, bool update_skb_dev)
df3893c17   Steffen Klassert   vti: Update the i...
77
78
79
  {
  	XFRM_SPI_SKB_CB(skb)->family = AF_INET;
  	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
f981c57ff   Jeremy Sowden   vti4: eliminated ...
80
  	return vti_input(skb, ip_hdr(skb)->protocol, spi, 0, update_skb_dev);
df3893c17   Steffen Klassert   vti: Update the i...
81
  }
f981c57ff   Jeremy Sowden   vti4: eliminated ...
82
  static int vti_rcv_proto(struct sk_buff *skb)
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
83
  {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
84
85
  	return vti_rcv(skb, 0, false);
  }
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
86

df3893c17   Steffen Klassert   vti: Update the i...
87
88
89
90
  static int vti_rcv_cb(struct sk_buff *skb, int err)
  {
  	unsigned short family;
  	struct net_device *dev;
df3893c17   Steffen Klassert   vti: Update the i...
91
  	struct xfrm_state *x;
4c145dce2   Florian Westphal   xfrm: make xfrm m...
92
  	const struct xfrm_mode *inner_mode;
df3893c17   Steffen Klassert   vti: Update the i...
93
  	struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
d55c670cb   Alexander Duyck   ip_vti/ip6_vti: P...
94
95
  	u32 orig_mark = skb->mark;
  	int ret;
df3893c17   Steffen Klassert   vti: Update the i...
96
97
  
  	if (!tunnel)
1181412c1   Saurabh   net/ipv4: VTI sup...
98
  		return 1;
df3893c17   Steffen Klassert   vti: Update the i...
99
100
101
102
103
104
105
106
  
  	dev = tunnel->dev;
  
  	if (err) {
  		dev->stats.rx_errors++;
  		dev->stats.rx_dropped++;
  
  		return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
107
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
108

df3893c17   Steffen Klassert   vti: Update the i...
109
  	x = xfrm_input_state(skb);
1fb81e09d   thomas.zeitlhofer+lkml@ze-it.at   vti: use right in...
110

c9500d7b7   Florian Westphal   xfrm: store xfrm_...
111
  	inner_mode = &x->inner_mode;
1fb81e09d   thomas.zeitlhofer+lkml@ze-it.at   vti: use right in...
112
113
114
115
116
117
118
119
120
  
  	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;
  		}
  	}
b45714b16   Florian Westphal   xfrm: prefer fami...
121
  	family = inner_mode->family;
df3893c17   Steffen Klassert   vti: Update the i...
122

d55c670cb   Alexander Duyck   ip_vti/ip6_vti: P...
123
124
125
126
127
  	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...
128
129
130
131
  		return -EPERM;
  
  	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
  	skb->dev = dev;
560b50cf6   Fabian Frederick   ipv4: use dev_sw_...
132
  	dev_sw_netstats_rx_add(dev, skb->len);
df3893c17   Steffen Klassert   vti: Update the i...
133
134
  
  	return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
135
  }
6e2de802a   Steffen Klassert   vti4: Check the t...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  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...
156
157
  static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
  			    struct flowi *fl)
1181412c1   Saurabh   net/ipv4: VTI sup...
158
159
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
6e2de802a   Steffen Klassert   vti4: Check the t...
160
  	struct ip_tunnel_parm *parms = &tunnel->parms;
a34cd4f31   Steffen Klassert   vti4: Use the on ...
161
  	struct dst_entry *dst = skb_dst(skb);
1181412c1   Saurabh   net/ipv4: VTI sup...
162
  	struct net_device *tdev;	/* Device to other host */
36f6ee22d   Alexey Kodanev   vti: fix use afte...
163
  	int pkt_len = skb->len;
b9959fd3b   Amerigo Wang   vti: switch to ne...
164
  	int err;
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
165
  	int mtu;
1181412c1   Saurabh   net/ipv4: VTI sup...
166

a34cd4f31   Steffen Klassert   vti4: Use the on ...
167
  	if (!dst) {
f1ed10264   Nicolas Dichtel   vti[6]: fix packe...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  		switch (skb->protocol) {
  		case htons(ETH_P_IP): {
  			struct rtable *rt;
  
  			fl->u.ip4.flowi4_oif = dev->ifindex;
  			fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
  			rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
  			if (IS_ERR(rt)) {
  				dev->stats.tx_carrier_errors++;
  				goto tx_error_icmp;
  			}
  			dst = &rt->dst;
  			skb_dst_set(skb, dst);
  			break;
  		}
  #if IS_ENABLED(CONFIG_IPV6)
  		case htons(ETH_P_IPV6):
  			fl->u.ip6.flowi6_oif = dev->ifindex;
  			fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
  			dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
  			if (dst->error) {
  				dst_release(dst);
  				dst = NULL;
  				dev->stats.tx_carrier_errors++;
  				goto tx_error_icmp;
  			}
  			skb_dst_set(skb, dst);
  			break;
  #endif
  		default:
95224166a   Nicolas Dichtel   vti[6]: fix packe...
198
199
200
  			dev->stats.tx_carrier_errors++;
  			goto tx_error_icmp;
  		}
df3893c17   Steffen Klassert   vti: Update the i...
201
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
202

a34cd4f31   Steffen Klassert   vti4: Use the on ...
203
  	dst_hold(dst);
b328ecc46   Steffen Klassert   xfrm: Make the po...
204
  	dst = xfrm_lookup_route(tunnel->net, dst, fl, NULL, 0);
a34cd4f31   Steffen Klassert   vti4: Use the on ...
205
  	if (IS_ERR(dst)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
206
207
208
  		dev->stats.tx_carrier_errors++;
  		goto tx_error_icmp;
  	}
df3893c17   Steffen Klassert   vti: Update the i...
209

b328ecc46   Steffen Klassert   xfrm: Make the po...
210
211
  	if (dst->flags & DST_XFRM_QUEUE)
  		goto queued;
6e2de802a   Steffen Klassert   vti4: Check the t...
212
  	if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
213
  		dev->stats.tx_carrier_errors++;
a34cd4f31   Steffen Klassert   vti4: Use the on ...
214
  		dst_release(dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
215
216
  		goto tx_error_icmp;
  	}
6e2de802a   Steffen Klassert   vti4: Check the t...
217

a34cd4f31   Steffen Klassert   vti4: Use the on ...
218
  	tdev = dst->dev;
1181412c1   Saurabh   net/ipv4: VTI sup...
219
220
  
  	if (tdev == dev) {
a34cd4f31   Steffen Klassert   vti4: Use the on ...
221
  		dst_release(dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
222
223
224
  		dev->stats.collisions++;
  		goto tx_error;
  	}
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
225
226
  	mtu = dst_mtu(dst);
  	if (skb->len > mtu) {
8247a79ef   Hangbin Liu   vti: do not confi...
227
  		skb_dst_update_pmtu_no_confirm(skb, mtu);
d6af1a31c   Steffen Klassert   vti: Add pmtu han...
228
229
230
231
232
233
234
235
236
237
238
239
240
  		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;
  	}
b328ecc46   Steffen Klassert   xfrm: Make the po...
241
  queued:
df3893c17   Steffen Klassert   vti: Update the i...
242
  	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
a34cd4f31   Steffen Klassert   vti4: Use the on ...
243
  	skb_dst_set(skb, dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
244
  	skb->dev = skb_dst(skb)->dev;
13206b6bf   Eric W. Biederman   net: Pass net int...
245
  	err = dst_output(tunnel->net, skb->sk, skb);
b9959fd3b   Amerigo Wang   vti: switch to ne...
246
  	if (net_xmit_eval(err) == 0)
36f6ee22d   Alexey Kodanev   vti: fix use afte...
247
  		err = pkt_len;
039f50629   Pravin B Shelar   ip_tunnel: Move s...
248
  	iptunnel_xmit_stats(dev, err);
1181412c1   Saurabh   net/ipv4: VTI sup...
249
250
251
252
253
254
  	return NETDEV_TX_OK;
  
  tx_error_icmp:
  	dst_link_failure(skb);
  tx_error:
  	dev->stats.tx_errors++;
3acfa1e73   Eric Dumazet   ipv4: be friend w...
255
  	kfree_skb(skb);
1181412c1   Saurabh   net/ipv4: VTI sup...
256
257
  	return NETDEV_TX_OK;
  }
78a010cca   Steffen Klassert   vti4: Support int...
258
259
260
261
262
263
264
  /* 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;
cb9f1b783   Willem de Bruijn   ip: validate head...
265
266
  	if (!pskb_inet_may_pull(skb))
  		goto tx_err;
78a010cca   Steffen Klassert   vti4: Support int...
267
  	memset(&fl, 0, sizeof(fl));
78a010cca   Steffen Klassert   vti4: Support int...
268
269
270
271
272
273
274
275
276
277
  	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:
cb9f1b783   Willem de Bruijn   ip: validate head...
278
  		goto tx_err;
78a010cca   Steffen Klassert   vti4: Support int...
279
  	}
cd5279c19   Alexander Duyck   ip_vti/ip6_vti: D...
280
281
  	/* override mark with tunnel output key */
  	fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
78a010cca   Steffen Klassert   vti4: Support int...
282
  	return vti_xmit(skb, dev, &fl);
cb9f1b783   Willem de Bruijn   ip: validate head...
283
284
285
286
287
  
  tx_err:
  	dev->stats.tx_errors++;
  	kfree_skb(skb);
  	return NETDEV_TX_OK;
78a010cca   Steffen Klassert   vti4: Support int...
288
  }
df3893c17   Steffen Klassert   vti: Update the i...
289
290
291
  static int vti4_err(struct sk_buff *skb, u32 info)
  {
  	__be32 spi;
6d004d6cc   Steffen Klassert   vti: Use the tunn...
292
  	__u32 mark;
df3893c17   Steffen Klassert   vti: Update the i...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  	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...
307
  	mark = be32_to_cpu(tunnel->parms.o_key);
df3893c17   Steffen Klassert   vti: Update the i...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  	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...
334
  	x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
df3893c17   Steffen Klassert   vti: Update the i...
335
336
337
338
339
  			      spi, protocol, AF_INET);
  	if (!x)
  		return 0;
  
  	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
d888f3966   Maciej Å»enczykowski   net-ipv4: remove ...
340
  		ipv4_update_pmtu(skb, net, info, 0, protocol);
df3893c17   Steffen Klassert   vti: Update the i...
341
  	else
1042caa79   Maciej Å»enczykowski   net-ipv4: remove ...
342
  		ipv4_redirect(skb, net, 0, protocol);
df3893c17   Steffen Klassert   vti: Update the i...
343
344
345
346
  	xfrm_state_put(x);
  
  	return 0;
  }
1181412c1   Saurabh   net/ipv4: VTI sup...
347
  static int
607259a69   Christoph Hellwig   net: add a new nd...
348
  vti_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
1181412c1   Saurabh   net/ipv4: VTI sup...
349
350
  {
  	int err = 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
351

b9959fd3b   Amerigo Wang   vti: switch to ne...
352
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
607259a69   Christoph Hellwig   net: add a new nd...
353
354
  		if (p->iph.version != 4 || p->iph.protocol != IPPROTO_IPIP ||
  		    p->iph.ihl != 5)
b9959fd3b   Amerigo Wang   vti: switch to ne...
355
356
  			return -EINVAL;
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
357

607259a69   Christoph Hellwig   net: add a new nd...
358
359
360
361
  	if (!(p->i_flags & GRE_KEY))
  		p->i_key = 0;
  	if (!(p->o_flags & GRE_KEY))
  		p->o_key = 0;
7c8e6b9c2   Dmitry Popov   ip_vti: Fix 'ip t...
362

607259a69   Christoph Hellwig   net: add a new nd...
363
  	p->i_flags = VTI_ISVTI;
7c8e6b9c2   Dmitry Popov   ip_vti: Fix 'ip t...
364

607259a69   Christoph Hellwig   net: add a new nd...
365
  	err = ip_tunnel_ctl(dev, p, cmd);
b9959fd3b   Amerigo Wang   vti: switch to ne...
366
367
  	if (err)
  		return err;
1181412c1   Saurabh   net/ipv4: VTI sup...
368

b9959fd3b   Amerigo Wang   vti: switch to ne...
369
  	if (cmd != SIOCDELTUNNEL) {
607259a69   Christoph Hellwig   net: add a new nd...
370
371
  		p->i_flags |= GRE_KEY;
  		p->o_flags |= GRE_KEY;
1181412c1   Saurabh   net/ipv4: VTI sup...
372
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
373
374
375
376
377
  	return 0;
  }
  
  static const struct net_device_ops vti_netdev_ops = {
  	.ndo_init	= vti_tunnel_init,
b9959fd3b   Amerigo Wang   vti: switch to ne...
378
  	.ndo_uninit	= ip_tunnel_uninit,
1181412c1   Saurabh   net/ipv4: VTI sup...
379
  	.ndo_start_xmit	= vti_tunnel_xmit,
607259a69   Christoph Hellwig   net: add a new nd...
380
  	.ndo_do_ioctl	= ip_tunnel_ioctl,
b9959fd3b   Amerigo Wang   vti: switch to ne...
381
  	.ndo_change_mtu	= ip_tunnel_change_mtu,
f61dd388a   Pravin B Shelar   Tunneling: use IP...
382
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
383
  	.ndo_get_iflink = ip_tunnel_get_iflink,
607259a69   Christoph Hellwig   net: add a new nd...
384
  	.ndo_tunnel_ctl	= vti_tunnel_ctl,
1181412c1   Saurabh   net/ipv4: VTI sup...
385
  };
b9959fd3b   Amerigo Wang   vti: switch to ne...
386
  static void vti_tunnel_setup(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
387
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
388
  	dev->netdev_ops		= &vti_netdev_ops;
ab59d2b69   Jason A. Donenfeld   net: vti: impleme...
389
  	dev->header_ops		= &ip_tunnel_header_ops;
8d89dcdf8   Nicolas Dichtel   vti: don't allow ...
390
  	dev->type		= ARPHRD_TUNNEL;
b9959fd3b   Amerigo Wang   vti: switch to ne...
391
  	ip_tunnel_setup(dev, vti_net_id);
1181412c1   Saurabh   net/ipv4: VTI sup...
392
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
393
  static int vti_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
394
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
395
396
397
398
399
  	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...
400

1181412c1   Saurabh   net/ipv4: VTI sup...
401
  	dev->flags		= IFF_NOARP;
1181412c1   Saurabh   net/ipv4: VTI sup...
402
  	dev->addr_len		= 4;
1181412c1   Saurabh   net/ipv4: VTI sup...
403
  	dev->features		|= NETIF_F_LLTX;
028758788   Eric Dumazet   net: better IFF_X...
404
  	netif_keep_dst(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
405

b9959fd3b   Amerigo Wang   vti: switch to ne...
406
  	return ip_tunnel_init(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
407
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
408
  static void __net_init vti_fb_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
409
410
411
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
1181412c1   Saurabh   net/ipv4: VTI sup...
412

1181412c1   Saurabh   net/ipv4: VTI sup...
413
414
415
  	iph->version		= 4;
  	iph->protocol		= IPPROTO_IPIP;
  	iph->ihl		= 5;
1181412c1   Saurabh   net/ipv4: VTI sup...
416
  }
df3893c17   Steffen Klassert   vti: Update the i...
417
  static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
418
419
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
420
421
422
423
424
425
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
  };
  
  static struct xfrm4_protocol vti_ah4_protocol __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
426
427
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
428
429
430
431
432
433
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
  };
  
  static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
434
435
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
436
437
438
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
1181412c1   Saurabh   net/ipv4: VTI sup...
439
  };
87e66b968   Xin Long   ip_vti: support I...
440
441
442
443
444
445
446
447
448
449
  #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
  static int vti_rcv_tunnel(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, IPPROTO_IPIP, ip_hdr(skb)->saddr, 0, false);
  }
  
  static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
450
  	.handler	=	vti_rcv_tunnel,
87e66b968   Xin Long   ip_vti: support I...
451
  	.cb_handler	=	vti_rcv_cb,
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
452
453
454
  	.err_handler	=	vti4_err,
  	.priority	=	0,
  };
55a48c7ec   Xin Long   ip_vti: not regis...
455

61ee4137b   YueHaibing   ip_vti: Fix unuse...
456
  #if IS_ENABLED(CONFIG_IPV6)
55a48c7ec   Xin Long   ip_vti: not regis...
457
  static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
458
  	.handler	=	vti_rcv_tunnel,
55a48c7ec   Xin Long   ip_vti: not regis...
459
  	.cb_handler	=	vti_rcv_cb,
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
460
461
462
  	.err_handler	=	vti4_err,
  	.priority	=	0,
  };
87e66b968   Xin Long   ip_vti: support I...
463
  #endif
61ee4137b   YueHaibing   ip_vti: Fix unuse...
464
  #endif
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
465

1181412c1   Saurabh   net/ipv4: VTI sup...
466
467
468
  static int __net_init vti_init_net(struct net *net)
  {
  	int err;
b9959fd3b   Amerigo Wang   vti: switch to ne...
469
  	struct ip_tunnel_net *itn;
1181412c1   Saurabh   net/ipv4: VTI sup...
470

b9959fd3b   Amerigo Wang   vti: switch to ne...
471
  	err = ip_tunnel_init_net(net, vti_net_id, &vti_link_ops, "ip_vti0");
1181412c1   Saurabh   net/ipv4: VTI sup...
472
  	if (err)
b9959fd3b   Amerigo Wang   vti: switch to ne...
473
474
  		return err;
  	itn = net_generic(net, vti_net_id);
cd1aa9c2c   Haishuang Yan   ip_vti: fix a nul...
475
476
  	if (itn->fb_tunnel_dev)
  		vti_fb_tunnel_init(itn->fb_tunnel_dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
477
  	return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
478
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
479
  static void __net_exit vti_exit_batch_net(struct list_head *list_net)
1181412c1   Saurabh   net/ipv4: VTI sup...
480
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
481
  	ip_tunnel_delete_nets(list_net, vti_net_id, &vti_link_ops);
1181412c1   Saurabh   net/ipv4: VTI sup...
482
483
484
485
  }
  
  static struct pernet_operations vti_net_ops = {
  	.init = vti_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
486
  	.exit_batch = vti_exit_batch_net,
1181412c1   Saurabh   net/ipv4: VTI sup...
487
  	.id   = &vti_net_id,
b9959fd3b   Amerigo Wang   vti: switch to ne...
488
  	.size = sizeof(struct ip_tunnel_net),
1181412c1   Saurabh   net/ipv4: VTI sup...
489
  };
a8b8a889e   Matthias Schiffer   net: add netlink_...
490
491
  static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  			       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
492
493
494
495
496
  {
  	return 0;
  }
  
  static void vti_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
497
498
  			      struct ip_tunnel_parm *parms,
  			      __u32 *fwmark)
1181412c1   Saurabh   net/ipv4: VTI sup...
499
500
501
502
503
504
505
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.protocol = IPPROTO_IPIP;
  
  	if (!data)
  		return;
df3893c17   Steffen Klassert   vti: Update the i...
506
  	parms->i_flags = VTI_ISVTI;
1181412c1   Saurabh   net/ipv4: VTI sup...
507
508
509
510
511
512
513
514
515
516
  	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...
517
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_VTI_LOCAL]);
1181412c1   Saurabh   net/ipv4: VTI sup...
518
519
  
  	if (data[IFLA_VTI_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
520
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_VTI_REMOTE]);
1181412c1   Saurabh   net/ipv4: VTI sup...
521

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
522
523
  	if (data[IFLA_VTI_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]);
1181412c1   Saurabh   net/ipv4: VTI sup...
524
525
526
  }
  
  static int vti_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
527
528
  		       struct nlattr *tb[], struct nlattr *data[],
  		       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
529
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
530
  	struct ip_tunnel_parm parms;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
531
  	__u32 fwmark = 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
532

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
533
534
  	vti_netlink_parms(data, &parms, &fwmark);
  	return ip_tunnel_newlink(dev, tb, &parms, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
535
536
537
  }
  
  static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
538
539
  			  struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
540
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
541
542
  	struct ip_tunnel *t = netdev_priv(dev);
  	__u32 fwmark = t->fwmark;
1181412c1   Saurabh   net/ipv4: VTI sup...
543
  	struct ip_tunnel_parm p;
1181412c1   Saurabh   net/ipv4: VTI sup...
544

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
545
546
  	vti_netlink_parms(data, &p, &fwmark);
  	return ip_tunnel_changelink(dev, tb, &p, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
  }
  
  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 ...
562
563
  		/* IFLA_VTI_FWMARK */
  		nla_total_size(4) +
1181412c1   Saurabh   net/ipv4: VTI sup...
564
565
566
567
568
569
570
  		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...
571
572
573
574
575
576
577
  	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...
578
579
580
581
582
583
584
585
  
  	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 },
c593642c8   Pankaj Bharadiya   treewide: Use siz...
586
587
  	[IFLA_VTI_LOCAL]	= { .len = sizeof_field(struct iphdr, saddr) },
  	[IFLA_VTI_REMOTE]	= { .len = sizeof_field(struct iphdr, daddr) },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
588
  	[IFLA_VTI_FWMARK]	= { .type = NLA_U32 },
1181412c1   Saurabh   net/ipv4: VTI sup...
589
590
591
592
593
594
595
596
597
598
599
  };
  
  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...
600
  	.dellink        = ip_tunnel_dellink,
1181412c1   Saurabh   net/ipv4: VTI sup...
601
602
  	.get_size	= vti_get_size,
  	.fill_info	= vti_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
603
  	.get_link_net	= ip_tunnel_get_link_net,
1181412c1   Saurabh   net/ipv4: VTI sup...
604
605
606
607
  };
  
  static int __init vti_init(void)
  {
1990e4f88   Mathias Krause   vti: Simplify err...
608
  	const char *msg;
1181412c1   Saurabh   net/ipv4: VTI sup...
609
  	int err;
1990e4f88   Mathias Krause   vti: Simplify err...
610
611
  	pr_info("IPv4 over IPsec tunneling driver
  ");
1181412c1   Saurabh   net/ipv4: VTI sup...
612

1990e4f88   Mathias Krause   vti: Simplify err...
613
  	msg = "tunnel device";
1181412c1   Saurabh   net/ipv4: VTI sup...
614
615
  	err = register_pernet_device(&vti_net_ops);
  	if (err < 0)
1990e4f88   Mathias Krause   vti: Simplify err...
616
  		goto pernet_dev_failed;
df3893c17   Steffen Klassert   vti: Update the i...
617

1990e4f88   Mathias Krause   vti: Simplify err...
618
619
620
621
  	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...
622
  	err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
623
624
  	if (err < 0)
  		goto xfrm_proto_ah_failed;
df3893c17   Steffen Klassert   vti: Update the i...
625
  	err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
626
627
  	if (err < 0)
  		goto xfrm_proto_comp_failed;
1181412c1   Saurabh   net/ipv4: VTI sup...
628

87e66b968   Xin Long   ip_vti: support I...
629
  #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
630
  	msg = "ipip tunnel";
87e66b968   Xin Long   ip_vti: support I...
631
  	err = xfrm4_tunnel_register(&vti_ipip_handler, AF_INET);
01ce31c57   Jeremy Sowden   vti4: removed dup...
632
  	if (err < 0)
e6ce64570   Xin Long   ip_vti: support I...
633
634
  		goto xfrm_tunnel_ipip_failed;
  #if IS_ENABLED(CONFIG_IPV6)
55a48c7ec   Xin Long   ip_vti: not regis...
635
  	err = xfrm4_tunnel_register(&vti_ipip6_handler, AF_INET6);
01ce31c57   Jeremy Sowden   vti4: removed dup...
636
  	if (err < 0)
e6ce64570   Xin Long   ip_vti: support I...
637
638
  		goto xfrm_tunnel_ipip6_failed;
  #endif
87e66b968   Xin Long   ip_vti: support I...
639
  #endif
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
640

1990e4f88   Mathias Krause   vti: Simplify err...
641
  	msg = "netlink interface";
1181412c1   Saurabh   net/ipv4: VTI sup...
642
643
644
645
646
647
648
  	err = rtnl_link_register(&vti_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  	return err;
  
  rtnl_link_failed:
87e66b968   Xin Long   ip_vti: support I...
649
  #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
e6ce64570   Xin Long   ip_vti: support I...
650
  #if IS_ENABLED(CONFIG_IPV6)
55a48c7ec   Xin Long   ip_vti: not regis...
651
  	xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
e6ce64570   Xin Long   ip_vti: support I...
652
653
  xfrm_tunnel_ipip6_failed:
  #endif
87e66b968   Xin Long   ip_vti: support I...
654
  	xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
e6ce64570   Xin Long   ip_vti: support I...
655
  xfrm_tunnel_ipip_failed:
87e66b968   Xin Long   ip_vti: support I...
656
  #endif
5483844c3   Jeremy Sowden   vti4: ipip tunnel...
657
  	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
658
  xfrm_proto_comp_failed:
df3893c17   Steffen Klassert   vti: Update the i...
659
  	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
660
  xfrm_proto_ah_failed:
df3893c17   Steffen Klassert   vti: Update the i...
661
  	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
1990e4f88   Mathias Krause   vti: Simplify err...
662
  xfrm_proto_esp_failed:
1181412c1   Saurabh   net/ipv4: VTI sup...
663
  	unregister_pernet_device(&vti_net_ops);
1990e4f88   Mathias Krause   vti: Simplify err...
664
665
666
  pernet_dev_failed:
  	pr_err("vti init: failed to register %s
  ", msg);
1181412c1   Saurabh   net/ipv4: VTI sup...
667
668
669
670
671
672
  	return err;
  }
  
  static void __exit vti_fini(void)
  {
  	rtnl_link_unregister(&vti_link_ops);
87e66b968   Xin Long   ip_vti: support I...
673
  #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
e6ce64570   Xin Long   ip_vti: support I...
674
  #if IS_ENABLED(CONFIG_IPV6)
55a48c7ec   Xin Long   ip_vti: not regis...
675
  	xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
e6ce64570   Xin Long   ip_vti: support I...
676
  #endif
87e66b968   Xin Long   ip_vti: support I...
677
678
  	xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
  #endif
1990e4f88   Mathias Krause   vti: Simplify err...
679
680
681
  	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...
682
683
684
685
686
687
688
689
  	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");