Blame view

net/ipv4/ip_vti.c 15.8 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

f981c57ff   Jeremy Sowden   vti4: eliminated ...
87
88
89
  static int vti_rcv_tunnel(struct sk_buff *skb)
  {
  	return vti_rcv(skb, ip_hdr(skb)->saddr, true);
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
90
  }
df3893c17   Steffen Klassert   vti: Update the i...
91
92
93
94
95
96
  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;
4c145dce2   Florian Westphal   xfrm: make xfrm m...
97
  	const struct xfrm_mode *inner_mode;
df3893c17   Steffen Klassert   vti: Update the i...
98
  	struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
d55c670cb   Alexander Duyck   ip_vti/ip6_vti: P...
99
100
  	u32 orig_mark = skb->mark;
  	int ret;
df3893c17   Steffen Klassert   vti: Update the i...
101
102
  
  	if (!tunnel)
1181412c1   Saurabh   net/ipv4: VTI sup...
103
  		return 1;
df3893c17   Steffen Klassert   vti: Update the i...
104
105
106
107
108
109
110
111
  
  	dev = tunnel->dev;
  
  	if (err) {
  		dev->stats.rx_errors++;
  		dev->stats.rx_dropped++;
  
  		return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
112
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
113

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

c9500d7b7   Florian Westphal   xfrm: store xfrm_...
116
  	inner_mode = &x->inner_mode;
1fb81e09d   thomas.zeitlhofer+lkml@ze-it.at   vti: use right in...
117
118
119
120
121
122
123
124
125
  
  	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...
126
  	family = inner_mode->family;
df3893c17   Steffen Klassert   vti: Update the i...
127

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

a34cd4f31   Steffen Klassert   vti4: Use the on ...
178
  	if (!dst) {
c8e04566d   Nicolas Dichtel   vti[6]: fix packe...
179
180
181
182
183
184
185
186
187
188
189
  		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);
df3893c17   Steffen Klassert   vti: Update the i...
190
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
191

a34cd4f31   Steffen Klassert   vti4: Use the on ...
192
  	dst_hold(dst);
78a010cca   Steffen Klassert   vti4: Support int...
193
  	dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0);
a34cd4f31   Steffen Klassert   vti4: Use the on ...
194
  	if (IS_ERR(dst)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
195
196
197
  		dev->stats.tx_carrier_errors++;
  		goto tx_error_icmp;
  	}
df3893c17   Steffen Klassert   vti: Update the i...
198

6e2de802a   Steffen Klassert   vti4: Check the t...
199
  	if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
1181412c1   Saurabh   net/ipv4: VTI sup...
200
  		dev->stats.tx_carrier_errors++;
a34cd4f31   Steffen Klassert   vti4: Use the on ...
201
  		dst_release(dst);
1181412c1   Saurabh   net/ipv4: VTI sup...
202
203
  		goto tx_error_icmp;
  	}
6e2de802a   Steffen Klassert   vti4: Check the t...
204

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

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

b9959fd3b   Amerigo Wang   vti: switch to ne...
342
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
1181412c1   Saurabh   net/ipv4: VTI sup...
343
344
  		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
  		    p.iph.ihl != 5)
b9959fd3b   Amerigo Wang   vti: switch to ne...
345
346
  			return -EINVAL;
  	}
1181412c1   Saurabh   net/ipv4: VTI sup...
347

7c8e6b9c2   Dmitry Popov   ip_vti: Fix 'ip t...
348
349
350
351
352
353
  	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...
354
355
356
  	err = ip_tunnel_ioctl(dev, &p, cmd);
  	if (err)
  		return err;
1181412c1   Saurabh   net/ipv4: VTI sup...
357

b9959fd3b   Amerigo Wang   vti: switch to ne...
358
  	if (cmd != SIOCDELTUNNEL) {
df3893c17   Steffen Klassert   vti: Update the i...
359
  		p.i_flags |= GRE_KEY;
b9959fd3b   Amerigo Wang   vti: switch to ne...
360
  		p.o_flags |= GRE_KEY;
1181412c1   Saurabh   net/ipv4: VTI sup...
361
  	}
b9959fd3b   Amerigo Wang   vti: switch to ne...
362
363
  	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
  		return -EFAULT;
1181412c1   Saurabh   net/ipv4: VTI sup...
364
365
366
367
368
  	return 0;
  }
  
  static const struct net_device_ops vti_netdev_ops = {
  	.ndo_init	= vti_tunnel_init,
b9959fd3b   Amerigo Wang   vti: switch to ne...
369
  	.ndo_uninit	= ip_tunnel_uninit,
1181412c1   Saurabh   net/ipv4: VTI sup...
370
371
  	.ndo_start_xmit	= vti_tunnel_xmit,
  	.ndo_do_ioctl	= vti_tunnel_ioctl,
b9959fd3b   Amerigo Wang   vti: switch to ne...
372
  	.ndo_change_mtu	= ip_tunnel_change_mtu,
f61dd388a   Pravin B Shelar   Tunneling: use IP...
373
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
374
  	.ndo_get_iflink = ip_tunnel_get_iflink,
1181412c1   Saurabh   net/ipv4: VTI sup...
375
  };
b9959fd3b   Amerigo Wang   vti: switch to ne...
376
  static void vti_tunnel_setup(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
377
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
378
  	dev->netdev_ops		= &vti_netdev_ops;
8d89dcdf8   Nicolas Dichtel   vti: don't allow ...
379
  	dev->type		= ARPHRD_TUNNEL;
b9959fd3b   Amerigo Wang   vti: switch to ne...
380
  	ip_tunnel_setup(dev, vti_net_id);
1181412c1   Saurabh   net/ipv4: VTI sup...
381
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
382
  static int vti_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
383
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
384
385
386
387
388
  	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...
389

1181412c1   Saurabh   net/ipv4: VTI sup...
390
  	dev->flags		= IFF_NOARP;
1181412c1   Saurabh   net/ipv4: VTI sup...
391
  	dev->addr_len		= 4;
1181412c1   Saurabh   net/ipv4: VTI sup...
392
  	dev->features		|= NETIF_F_LLTX;
028758788   Eric Dumazet   net: better IFF_X...
393
  	netif_keep_dst(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
394

b9959fd3b   Amerigo Wang   vti: switch to ne...
395
  	return ip_tunnel_init(dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
396
  }
b9959fd3b   Amerigo Wang   vti: switch to ne...
397
  static void __net_init vti_fb_tunnel_init(struct net_device *dev)
1181412c1   Saurabh   net/ipv4: VTI sup...
398
399
400
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
1181412c1   Saurabh   net/ipv4: VTI sup...
401

1181412c1   Saurabh   net/ipv4: VTI sup...
402
403
404
  	iph->version		= 4;
  	iph->protocol		= IPPROTO_IPIP;
  	iph->ihl		= 5;
1181412c1   Saurabh   net/ipv4: VTI sup...
405
  }
df3893c17   Steffen Klassert   vti: Update the i...
406
  static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
407
408
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
409
410
411
412
413
414
  	.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 ...
415
416
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
417
418
419
420
421
422
  	.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 ...
423
424
  	.handler	=	vti_rcv_proto,
  	.input_handler	=	vti_input_proto,
df3893c17   Steffen Klassert   vti: Update the i...
425
426
427
  	.cb_handler	=	vti_rcv_cb,
  	.err_handler	=	vti4_err,
  	.priority	=	100,
1181412c1   Saurabh   net/ipv4: VTI sup...
428
  };
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
429
  static struct xfrm_tunnel ipip_handler __read_mostly = {
f981c57ff   Jeremy Sowden   vti4: eliminated ...
430
  	.handler	=	vti_rcv_tunnel,
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
431
432
433
  	.err_handler	=	vti4_err,
  	.priority	=	0,
  };
1181412c1   Saurabh   net/ipv4: VTI sup...
434
435
436
  static int __net_init vti_init_net(struct net *net)
  {
  	int err;
b9959fd3b   Amerigo Wang   vti: switch to ne...
437
  	struct ip_tunnel_net *itn;
1181412c1   Saurabh   net/ipv4: VTI sup...
438

b9959fd3b   Amerigo Wang   vti: switch to ne...
439
  	err = ip_tunnel_init_net(net, vti_net_id, &vti_link_ops, "ip_vti0");
1181412c1   Saurabh   net/ipv4: VTI sup...
440
  	if (err)
b9959fd3b   Amerigo Wang   vti: switch to ne...
441
442
  		return err;
  	itn = net_generic(net, vti_net_id);
cd1aa9c2c   Haishuang Yan   ip_vti: fix a nul...
443
444
  	if (itn->fb_tunnel_dev)
  		vti_fb_tunnel_init(itn->fb_tunnel_dev);
1181412c1   Saurabh   net/ipv4: VTI sup...
445
  	return 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
446
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
447
  static void __net_exit vti_exit_batch_net(struct list_head *list_net)
1181412c1   Saurabh   net/ipv4: VTI sup...
448
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
449
  	ip_tunnel_delete_nets(list_net, vti_net_id, &vti_link_ops);
1181412c1   Saurabh   net/ipv4: VTI sup...
450
451
452
453
  }
  
  static struct pernet_operations vti_net_ops = {
  	.init = vti_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
454
  	.exit_batch = vti_exit_batch_net,
1181412c1   Saurabh   net/ipv4: VTI sup...
455
  	.id   = &vti_net_id,
b9959fd3b   Amerigo Wang   vti: switch to ne...
456
  	.size = sizeof(struct ip_tunnel_net),
1181412c1   Saurabh   net/ipv4: VTI sup...
457
  };
a8b8a889e   Matthias Schiffer   net: add netlink_...
458
459
  static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  			       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
460
461
462
463
464
  {
  	return 0;
  }
  
  static void vti_netlink_parms(struct nlattr *data[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
465
466
  			      struct ip_tunnel_parm *parms,
  			      __u32 *fwmark)
1181412c1   Saurabh   net/ipv4: VTI sup...
467
468
469
470
471
472
473
  {
  	memset(parms, 0, sizeof(*parms));
  
  	parms->iph.protocol = IPPROTO_IPIP;
  
  	if (!data)
  		return;
df3893c17   Steffen Klassert   vti: Update the i...
474
  	parms->i_flags = VTI_ISVTI;
1181412c1   Saurabh   net/ipv4: VTI sup...
475
476
477
478
479
480
481
482
483
484
  	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...
485
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_VTI_LOCAL]);
1181412c1   Saurabh   net/ipv4: VTI sup...
486
487
  
  	if (data[IFLA_VTI_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
488
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_VTI_REMOTE]);
1181412c1   Saurabh   net/ipv4: VTI sup...
489

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
490
491
  	if (data[IFLA_VTI_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]);
1181412c1   Saurabh   net/ipv4: VTI sup...
492
493
494
  }
  
  static int vti_newlink(struct net *src_net, struct net_device *dev,
7a3f4a185   Matthias Schiffer   net: add netlink_...
495
496
  		       struct nlattr *tb[], struct nlattr *data[],
  		       struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
497
  {
b9959fd3b   Amerigo Wang   vti: switch to ne...
498
  	struct ip_tunnel_parm parms;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
499
  	__u32 fwmark = 0;
1181412c1   Saurabh   net/ipv4: VTI sup...
500

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
501
502
  	vti_netlink_parms(data, &parms, &fwmark);
  	return ip_tunnel_newlink(dev, tb, &parms, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
503
504
505
  }
  
  static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
506
507
  			  struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
1181412c1   Saurabh   net/ipv4: VTI sup...
508
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
509
510
  	struct ip_tunnel *t = netdev_priv(dev);
  	__u32 fwmark = t->fwmark;
1181412c1   Saurabh   net/ipv4: VTI sup...
511
  	struct ip_tunnel_parm p;
1181412c1   Saurabh   net/ipv4: VTI sup...
512

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
513
514
  	vti_netlink_parms(data, &p, &fwmark);
  	return ip_tunnel_changelink(dev, tb, &p, fwmark);
1181412c1   Saurabh   net/ipv4: VTI sup...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  }
  
  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 ...
530
531
  		/* IFLA_VTI_FWMARK */
  		nla_total_size(4) +
1181412c1   Saurabh   net/ipv4: VTI sup...
532
533
534
535
536
537
538
  		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...
539
540
541
542
543
544
545
  	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...
546
547
548
549
550
551
552
553
554
555
  
  	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 ...
556
  	[IFLA_VTI_FWMARK]	= { .type = NLA_U32 },
1181412c1   Saurabh   net/ipv4: VTI sup...
557
558
559
560
561
562
563
564
565
566
567
  };
  
  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...
568
  	.dellink        = ip_tunnel_dellink,
1181412c1   Saurabh   net/ipv4: VTI sup...
569
570
  	.get_size	= vti_get_size,
  	.fill_info	= vti_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
571
  	.get_link_net	= ip_tunnel_get_link_net,
1181412c1   Saurabh   net/ipv4: VTI sup...
572
573
574
575
  };
  
  static int __init vti_init(void)
  {
1990e4f88   Mathias Krause   vti: Simplify err...
576
  	const char *msg;
1181412c1   Saurabh   net/ipv4: VTI sup...
577
  	int err;
1990e4f88   Mathias Krause   vti: Simplify err...
578
579
  	pr_info("IPv4 over IPsec tunneling driver
  ");
1181412c1   Saurabh   net/ipv4: VTI sup...
580

1990e4f88   Mathias Krause   vti: Simplify err...
581
  	msg = "tunnel device";
1181412c1   Saurabh   net/ipv4: VTI sup...
582
583
  	err = register_pernet_device(&vti_net_ops);
  	if (err < 0)
1990e4f88   Mathias Krause   vti: Simplify err...
584
  		goto pernet_dev_failed;
df3893c17   Steffen Klassert   vti: Update the i...
585

1990e4f88   Mathias Krause   vti: Simplify err...
586
587
588
589
  	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...
590
  	err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
591
592
  	if (err < 0)
  		goto xfrm_proto_ah_failed;
df3893c17   Steffen Klassert   vti: Update the i...
593
  	err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
594
595
  	if (err < 0)
  		goto xfrm_proto_comp_failed;
1181412c1   Saurabh   net/ipv4: VTI sup...
596

dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
597
598
  	msg = "ipip tunnel";
  	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
01ce31c57   Jeremy Sowden   vti4: removed dup...
599
  	if (err < 0)
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
600
  		goto xfrm_tunnel_failed;
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
601

1990e4f88   Mathias Krause   vti: Simplify err...
602
  	msg = "netlink interface";
1181412c1   Saurabh   net/ipv4: VTI sup...
603
604
605
606
607
608
609
  	err = rtnl_link_register(&vti_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
  
  	return err;
  
  rtnl_link_failed:
dd9ee3444   Su Yanjun   vti4: Fix a ipip ...
610
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
5483844c3   Jeremy Sowden   vti4: ipip tunnel...
611
612
  xfrm_tunnel_failed:
  	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
1990e4f88   Mathias Krause   vti: Simplify err...
613
  xfrm_proto_comp_failed:
df3893c17   Steffen Klassert   vti: Update the i...
614
  	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
1990e4f88   Mathias Krause   vti: Simplify err...
615
  xfrm_proto_ah_failed:
df3893c17   Steffen Klassert   vti: Update the i...
616
  	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
1990e4f88   Mathias Krause   vti: Simplify err...
617
  xfrm_proto_esp_failed:
1181412c1   Saurabh   net/ipv4: VTI sup...
618
  	unregister_pernet_device(&vti_net_ops);
1990e4f88   Mathias Krause   vti: Simplify err...
619
620
621
  pernet_dev_failed:
  	pr_err("vti init: failed to register %s
  ", msg);
1181412c1   Saurabh   net/ipv4: VTI sup...
622
623
624
625
626
627
  	return err;
  }
  
  static void __exit vti_fini(void)
  {
  	rtnl_link_unregister(&vti_link_ops);
5483844c3   Jeremy Sowden   vti4: ipip tunnel...
628
  	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
1990e4f88   Mathias Krause   vti: Simplify err...
629
630
631
  	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...
632
633
634
635
636
637
638
639
  	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");