1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Linux NET3: IP/IP protocol decoder modified to support
4*4882a593Smuzhiyun * virtual tunnel interface
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Authors:
7*4882a593Smuzhiyun * Saurabh Mohan (saurabh.mohan@vyatta.com) 05/07/2012
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun This version of net/ipv4/ip_vti.c is cloned of net/ipv4/ipip.c
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun For comments look at net/ipv4/ip_gre.c --ANK
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/capability.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/types.h>
20*4882a593Smuzhiyun #include <linux/kernel.h>
21*4882a593Smuzhiyun #include <linux/uaccess.h>
22*4882a593Smuzhiyun #include <linux/skbuff.h>
23*4882a593Smuzhiyun #include <linux/netdevice.h>
24*4882a593Smuzhiyun #include <linux/in.h>
25*4882a593Smuzhiyun #include <linux/tcp.h>
26*4882a593Smuzhiyun #include <linux/udp.h>
27*4882a593Smuzhiyun #include <linux/if_arp.h>
28*4882a593Smuzhiyun #include <linux/init.h>
29*4882a593Smuzhiyun #include <linux/netfilter_ipv4.h>
30*4882a593Smuzhiyun #include <linux/if_ether.h>
31*4882a593Smuzhiyun #include <linux/icmpv6.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <net/sock.h>
34*4882a593Smuzhiyun #include <net/ip.h>
35*4882a593Smuzhiyun #include <net/icmp.h>
36*4882a593Smuzhiyun #include <net/ip_tunnels.h>
37*4882a593Smuzhiyun #include <net/inet_ecn.h>
38*4882a593Smuzhiyun #include <net/xfrm.h>
39*4882a593Smuzhiyun #include <net/net_namespace.h>
40*4882a593Smuzhiyun #include <net/netns/generic.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static struct rtnl_link_ops vti_link_ops __read_mostly;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static unsigned int vti_net_id __read_mostly;
45*4882a593Smuzhiyun static int vti_tunnel_init(struct net_device *dev);
46*4882a593Smuzhiyun
vti_input(struct sk_buff * skb,int nexthdr,__be32 spi,int encap_type,bool update_skb_dev)47*4882a593Smuzhiyun static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
48*4882a593Smuzhiyun int encap_type, bool update_skb_dev)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun struct ip_tunnel *tunnel;
51*4882a593Smuzhiyun const struct iphdr *iph = ip_hdr(skb);
52*4882a593Smuzhiyun struct net *net = dev_net(skb->dev);
53*4882a593Smuzhiyun struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
56*4882a593Smuzhiyun iph->saddr, iph->daddr, 0);
57*4882a593Smuzhiyun if (tunnel) {
58*4882a593Smuzhiyun if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
59*4882a593Smuzhiyun goto drop;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (update_skb_dev)
64*4882a593Smuzhiyun skb->dev = tunnel->dev;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun return xfrm_input(skb, nexthdr, spi, encap_type);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun return -EINVAL;
70*4882a593Smuzhiyun drop:
71*4882a593Smuzhiyun kfree_skb(skb);
72*4882a593Smuzhiyun return 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
vti_input_proto(struct sk_buff * skb,int nexthdr,__be32 spi,int encap_type)75*4882a593Smuzhiyun static int vti_input_proto(struct sk_buff *skb, int nexthdr, __be32 spi,
76*4882a593Smuzhiyun int encap_type)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun return vti_input(skb, nexthdr, spi, encap_type, false);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
vti_rcv(struct sk_buff * skb,__be32 spi,bool update_skb_dev)81*4882a593Smuzhiyun static int vti_rcv(struct sk_buff *skb, __be32 spi, bool update_skb_dev)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun XFRM_SPI_SKB_CB(skb)->family = AF_INET;
84*4882a593Smuzhiyun XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun return vti_input(skb, ip_hdr(skb)->protocol, spi, 0, update_skb_dev);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
vti_rcv_proto(struct sk_buff * skb)89*4882a593Smuzhiyun static int vti_rcv_proto(struct sk_buff *skb)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun return vti_rcv(skb, 0, false);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
vti_rcv_cb(struct sk_buff * skb,int err)94*4882a593Smuzhiyun static int vti_rcv_cb(struct sk_buff *skb, int err)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun unsigned short family;
97*4882a593Smuzhiyun struct net_device *dev;
98*4882a593Smuzhiyun struct xfrm_state *x;
99*4882a593Smuzhiyun const struct xfrm_mode *inner_mode;
100*4882a593Smuzhiyun struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
101*4882a593Smuzhiyun u32 orig_mark = skb->mark;
102*4882a593Smuzhiyun int ret;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (!tunnel)
105*4882a593Smuzhiyun return 1;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun dev = tunnel->dev;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun if (err) {
110*4882a593Smuzhiyun dev->stats.rx_errors++;
111*4882a593Smuzhiyun dev->stats.rx_dropped++;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun x = xfrm_input_state(skb);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun inner_mode = &x->inner_mode;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (x->sel.family == AF_UNSPEC) {
121*4882a593Smuzhiyun inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
122*4882a593Smuzhiyun if (inner_mode == NULL) {
123*4882a593Smuzhiyun XFRM_INC_STATS(dev_net(skb->dev),
124*4882a593Smuzhiyun LINUX_MIB_XFRMINSTATEMODEERROR);
125*4882a593Smuzhiyun return -EINVAL;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun family = inner_mode->family;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun skb->mark = be32_to_cpu(tunnel->parms.i_key);
132*4882a593Smuzhiyun ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
133*4882a593Smuzhiyun skb->mark = orig_mark;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (!ret)
136*4882a593Smuzhiyun return -EPERM;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
139*4882a593Smuzhiyun skb->dev = dev;
140*4882a593Smuzhiyun dev_sw_netstats_rx_add(dev, skb->len);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun return 0;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
vti_state_check(const struct xfrm_state * x,__be32 dst,__be32 src)145*4882a593Smuzhiyun static bool vti_state_check(const struct xfrm_state *x, __be32 dst, __be32 src)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun xfrm_address_t *daddr = (xfrm_address_t *)&dst;
148*4882a593Smuzhiyun xfrm_address_t *saddr = (xfrm_address_t *)&src;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* if there is no transform then this tunnel is not functional.
151*4882a593Smuzhiyun * Or if the xfrm is not mode tunnel.
152*4882a593Smuzhiyun */
153*4882a593Smuzhiyun if (!x || x->props.mode != XFRM_MODE_TUNNEL ||
154*4882a593Smuzhiyun x->props.family != AF_INET)
155*4882a593Smuzhiyun return false;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (!dst)
158*4882a593Smuzhiyun return xfrm_addr_equal(saddr, &x->props.saddr, AF_INET);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (!xfrm_state_addr_check(x, daddr, saddr, AF_INET))
161*4882a593Smuzhiyun return false;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return true;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
vti_xmit(struct sk_buff * skb,struct net_device * dev,struct flowi * fl)166*4882a593Smuzhiyun static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
167*4882a593Smuzhiyun struct flowi *fl)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun struct ip_tunnel *tunnel = netdev_priv(dev);
170*4882a593Smuzhiyun struct ip_tunnel_parm *parms = &tunnel->parms;
171*4882a593Smuzhiyun struct dst_entry *dst = skb_dst(skb);
172*4882a593Smuzhiyun struct net_device *tdev; /* Device to other host */
173*4882a593Smuzhiyun int pkt_len = skb->len;
174*4882a593Smuzhiyun int err;
175*4882a593Smuzhiyun int mtu;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (!dst) {
178*4882a593Smuzhiyun switch (skb->protocol) {
179*4882a593Smuzhiyun case htons(ETH_P_IP): {
180*4882a593Smuzhiyun struct rtable *rt;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun fl->u.ip4.flowi4_oif = dev->ifindex;
183*4882a593Smuzhiyun fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
184*4882a593Smuzhiyun rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
185*4882a593Smuzhiyun if (IS_ERR(rt)) {
186*4882a593Smuzhiyun dev->stats.tx_carrier_errors++;
187*4882a593Smuzhiyun goto tx_error_icmp;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun dst = &rt->dst;
190*4882a593Smuzhiyun skb_dst_set(skb, dst);
191*4882a593Smuzhiyun break;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
194*4882a593Smuzhiyun case htons(ETH_P_IPV6):
195*4882a593Smuzhiyun fl->u.ip6.flowi6_oif = dev->ifindex;
196*4882a593Smuzhiyun fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
197*4882a593Smuzhiyun dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
198*4882a593Smuzhiyun if (dst->error) {
199*4882a593Smuzhiyun dst_release(dst);
200*4882a593Smuzhiyun dst = NULL;
201*4882a593Smuzhiyun dev->stats.tx_carrier_errors++;
202*4882a593Smuzhiyun goto tx_error_icmp;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun skb_dst_set(skb, dst);
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun #endif
207*4882a593Smuzhiyun default:
208*4882a593Smuzhiyun dev->stats.tx_carrier_errors++;
209*4882a593Smuzhiyun goto tx_error_icmp;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun dst_hold(dst);
214*4882a593Smuzhiyun dst = xfrm_lookup_route(tunnel->net, dst, fl, NULL, 0);
215*4882a593Smuzhiyun if (IS_ERR(dst)) {
216*4882a593Smuzhiyun dev->stats.tx_carrier_errors++;
217*4882a593Smuzhiyun goto tx_error_icmp;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (dst->flags & DST_XFRM_QUEUE)
221*4882a593Smuzhiyun goto queued;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
224*4882a593Smuzhiyun dev->stats.tx_carrier_errors++;
225*4882a593Smuzhiyun dst_release(dst);
226*4882a593Smuzhiyun goto tx_error_icmp;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun tdev = dst->dev;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun if (tdev == dev) {
232*4882a593Smuzhiyun dst_release(dst);
233*4882a593Smuzhiyun dev->stats.collisions++;
234*4882a593Smuzhiyun goto tx_error;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun mtu = dst_mtu(dst);
238*4882a593Smuzhiyun if (skb->len > mtu) {
239*4882a593Smuzhiyun skb_dst_update_pmtu_no_confirm(skb, mtu);
240*4882a593Smuzhiyun if (skb->protocol == htons(ETH_P_IP)) {
241*4882a593Smuzhiyun icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
242*4882a593Smuzhiyun htonl(mtu));
243*4882a593Smuzhiyun } else {
244*4882a593Smuzhiyun if (mtu < IPV6_MIN_MTU)
245*4882a593Smuzhiyun mtu = IPV6_MIN_MTU;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun dst_release(dst);
251*4882a593Smuzhiyun goto tx_error;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun queued:
255*4882a593Smuzhiyun skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
256*4882a593Smuzhiyun skb_dst_set(skb, dst);
257*4882a593Smuzhiyun skb->dev = skb_dst(skb)->dev;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun err = dst_output(tunnel->net, skb->sk, skb);
260*4882a593Smuzhiyun if (net_xmit_eval(err) == 0)
261*4882a593Smuzhiyun err = pkt_len;
262*4882a593Smuzhiyun iptunnel_xmit_stats(dev, err);
263*4882a593Smuzhiyun return NETDEV_TX_OK;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun tx_error_icmp:
266*4882a593Smuzhiyun dst_link_failure(skb);
267*4882a593Smuzhiyun tx_error:
268*4882a593Smuzhiyun dev->stats.tx_errors++;
269*4882a593Smuzhiyun kfree_skb(skb);
270*4882a593Smuzhiyun return NETDEV_TX_OK;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /* This function assumes it is being called from dev_queue_xmit()
274*4882a593Smuzhiyun * and that skb is filled properly by that function.
275*4882a593Smuzhiyun */
vti_tunnel_xmit(struct sk_buff * skb,struct net_device * dev)276*4882a593Smuzhiyun static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct ip_tunnel *tunnel = netdev_priv(dev);
279*4882a593Smuzhiyun struct flowi fl;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (!pskb_inet_may_pull(skb))
282*4882a593Smuzhiyun goto tx_err;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun memset(&fl, 0, sizeof(fl));
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun switch (skb->protocol) {
287*4882a593Smuzhiyun case htons(ETH_P_IP):
288*4882a593Smuzhiyun xfrm_decode_session(skb, &fl, AF_INET);
289*4882a593Smuzhiyun memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
290*4882a593Smuzhiyun break;
291*4882a593Smuzhiyun case htons(ETH_P_IPV6):
292*4882a593Smuzhiyun xfrm_decode_session(skb, &fl, AF_INET6);
293*4882a593Smuzhiyun memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
294*4882a593Smuzhiyun break;
295*4882a593Smuzhiyun default:
296*4882a593Smuzhiyun goto tx_err;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun /* override mark with tunnel output key */
300*4882a593Smuzhiyun fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return vti_xmit(skb, dev, &fl);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun tx_err:
305*4882a593Smuzhiyun dev->stats.tx_errors++;
306*4882a593Smuzhiyun kfree_skb(skb);
307*4882a593Smuzhiyun return NETDEV_TX_OK;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
vti4_err(struct sk_buff * skb,u32 info)310*4882a593Smuzhiyun static int vti4_err(struct sk_buff *skb, u32 info)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun __be32 spi;
313*4882a593Smuzhiyun __u32 mark;
314*4882a593Smuzhiyun struct xfrm_state *x;
315*4882a593Smuzhiyun struct ip_tunnel *tunnel;
316*4882a593Smuzhiyun struct ip_esp_hdr *esph;
317*4882a593Smuzhiyun struct ip_auth_hdr *ah ;
318*4882a593Smuzhiyun struct ip_comp_hdr *ipch;
319*4882a593Smuzhiyun struct net *net = dev_net(skb->dev);
320*4882a593Smuzhiyun const struct iphdr *iph = (const struct iphdr *)skb->data;
321*4882a593Smuzhiyun int protocol = iph->protocol;
322*4882a593Smuzhiyun struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
325*4882a593Smuzhiyun iph->daddr, iph->saddr, 0);
326*4882a593Smuzhiyun if (!tunnel)
327*4882a593Smuzhiyun return -1;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun mark = be32_to_cpu(tunnel->parms.o_key);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun switch (protocol) {
332*4882a593Smuzhiyun case IPPROTO_ESP:
333*4882a593Smuzhiyun esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
334*4882a593Smuzhiyun spi = esph->spi;
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun case IPPROTO_AH:
337*4882a593Smuzhiyun ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
338*4882a593Smuzhiyun spi = ah->spi;
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun case IPPROTO_COMP:
341*4882a593Smuzhiyun ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
342*4882a593Smuzhiyun spi = htonl(ntohs(ipch->cpi));
343*4882a593Smuzhiyun break;
344*4882a593Smuzhiyun default:
345*4882a593Smuzhiyun return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun switch (icmp_hdr(skb)->type) {
349*4882a593Smuzhiyun case ICMP_DEST_UNREACH:
350*4882a593Smuzhiyun if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
351*4882a593Smuzhiyun return 0;
352*4882a593Smuzhiyun case ICMP_REDIRECT:
353*4882a593Smuzhiyun break;
354*4882a593Smuzhiyun default:
355*4882a593Smuzhiyun return 0;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
359*4882a593Smuzhiyun spi, protocol, AF_INET);
360*4882a593Smuzhiyun if (!x)
361*4882a593Smuzhiyun return 0;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
364*4882a593Smuzhiyun ipv4_update_pmtu(skb, net, info, 0, protocol);
365*4882a593Smuzhiyun else
366*4882a593Smuzhiyun ipv4_redirect(skb, net, 0, protocol);
367*4882a593Smuzhiyun xfrm_state_put(x);
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun return 0;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun static int
vti_tunnel_ctl(struct net_device * dev,struct ip_tunnel_parm * p,int cmd)373*4882a593Smuzhiyun vti_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun int err = 0;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
378*4882a593Smuzhiyun if (p->iph.version != 4 || p->iph.protocol != IPPROTO_IPIP ||
379*4882a593Smuzhiyun p->iph.ihl != 5)
380*4882a593Smuzhiyun return -EINVAL;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (!(p->i_flags & GRE_KEY))
384*4882a593Smuzhiyun p->i_key = 0;
385*4882a593Smuzhiyun if (!(p->o_flags & GRE_KEY))
386*4882a593Smuzhiyun p->o_key = 0;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun p->i_flags = VTI_ISVTI;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun err = ip_tunnel_ctl(dev, p, cmd);
391*4882a593Smuzhiyun if (err)
392*4882a593Smuzhiyun return err;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun if (cmd != SIOCDELTUNNEL) {
395*4882a593Smuzhiyun p->i_flags |= GRE_KEY;
396*4882a593Smuzhiyun p->o_flags |= GRE_KEY;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun static const struct net_device_ops vti_netdev_ops = {
402*4882a593Smuzhiyun .ndo_init = vti_tunnel_init,
403*4882a593Smuzhiyun .ndo_uninit = ip_tunnel_uninit,
404*4882a593Smuzhiyun .ndo_start_xmit = vti_tunnel_xmit,
405*4882a593Smuzhiyun .ndo_do_ioctl = ip_tunnel_ioctl,
406*4882a593Smuzhiyun .ndo_change_mtu = ip_tunnel_change_mtu,
407*4882a593Smuzhiyun .ndo_get_stats64 = ip_tunnel_get_stats64,
408*4882a593Smuzhiyun .ndo_get_iflink = ip_tunnel_get_iflink,
409*4882a593Smuzhiyun .ndo_tunnel_ctl = vti_tunnel_ctl,
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
vti_tunnel_setup(struct net_device * dev)412*4882a593Smuzhiyun static void vti_tunnel_setup(struct net_device *dev)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun dev->netdev_ops = &vti_netdev_ops;
415*4882a593Smuzhiyun dev->header_ops = &ip_tunnel_header_ops;
416*4882a593Smuzhiyun dev->type = ARPHRD_TUNNEL;
417*4882a593Smuzhiyun ip_tunnel_setup(dev, vti_net_id);
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
vti_tunnel_init(struct net_device * dev)420*4882a593Smuzhiyun static int vti_tunnel_init(struct net_device *dev)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct ip_tunnel *tunnel = netdev_priv(dev);
423*4882a593Smuzhiyun struct iphdr *iph = &tunnel->parms.iph;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun memcpy(dev->dev_addr, &iph->saddr, 4);
426*4882a593Smuzhiyun memcpy(dev->broadcast, &iph->daddr, 4);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun dev->flags = IFF_NOARP;
429*4882a593Smuzhiyun dev->addr_len = 4;
430*4882a593Smuzhiyun dev->features |= NETIF_F_LLTX;
431*4882a593Smuzhiyun netif_keep_dst(dev);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun return ip_tunnel_init(dev);
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
vti_fb_tunnel_init(struct net_device * dev)436*4882a593Smuzhiyun static void __net_init vti_fb_tunnel_init(struct net_device *dev)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun struct ip_tunnel *tunnel = netdev_priv(dev);
439*4882a593Smuzhiyun struct iphdr *iph = &tunnel->parms.iph;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun iph->version = 4;
442*4882a593Smuzhiyun iph->protocol = IPPROTO_IPIP;
443*4882a593Smuzhiyun iph->ihl = 5;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
447*4882a593Smuzhiyun .handler = vti_rcv_proto,
448*4882a593Smuzhiyun .input_handler = vti_input_proto,
449*4882a593Smuzhiyun .cb_handler = vti_rcv_cb,
450*4882a593Smuzhiyun .err_handler = vti4_err,
451*4882a593Smuzhiyun .priority = 100,
452*4882a593Smuzhiyun };
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun static struct xfrm4_protocol vti_ah4_protocol __read_mostly = {
455*4882a593Smuzhiyun .handler = vti_rcv_proto,
456*4882a593Smuzhiyun .input_handler = vti_input_proto,
457*4882a593Smuzhiyun .cb_handler = vti_rcv_cb,
458*4882a593Smuzhiyun .err_handler = vti4_err,
459*4882a593Smuzhiyun .priority = 100,
460*4882a593Smuzhiyun };
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
463*4882a593Smuzhiyun .handler = vti_rcv_proto,
464*4882a593Smuzhiyun .input_handler = vti_input_proto,
465*4882a593Smuzhiyun .cb_handler = vti_rcv_cb,
466*4882a593Smuzhiyun .err_handler = vti4_err,
467*4882a593Smuzhiyun .priority = 100,
468*4882a593Smuzhiyun };
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
vti_rcv_tunnel(struct sk_buff * skb)471*4882a593Smuzhiyun static int vti_rcv_tunnel(struct sk_buff *skb)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun XFRM_SPI_SKB_CB(skb)->family = AF_INET;
474*4882a593Smuzhiyun XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return vti_input(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr, 0, false);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
480*4882a593Smuzhiyun .handler = vti_rcv_tunnel,
481*4882a593Smuzhiyun .cb_handler = vti_rcv_cb,
482*4882a593Smuzhiyun .err_handler = vti4_err,
483*4882a593Smuzhiyun .priority = 0,
484*4882a593Smuzhiyun };
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
487*4882a593Smuzhiyun static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
488*4882a593Smuzhiyun .handler = vti_rcv_tunnel,
489*4882a593Smuzhiyun .cb_handler = vti_rcv_cb,
490*4882a593Smuzhiyun .err_handler = vti4_err,
491*4882a593Smuzhiyun .priority = 0,
492*4882a593Smuzhiyun };
493*4882a593Smuzhiyun #endif
494*4882a593Smuzhiyun #endif
495*4882a593Smuzhiyun
vti_init_net(struct net * net)496*4882a593Smuzhiyun static int __net_init vti_init_net(struct net *net)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun int err;
499*4882a593Smuzhiyun struct ip_tunnel_net *itn;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun err = ip_tunnel_init_net(net, vti_net_id, &vti_link_ops, "ip_vti0");
502*4882a593Smuzhiyun if (err)
503*4882a593Smuzhiyun return err;
504*4882a593Smuzhiyun itn = net_generic(net, vti_net_id);
505*4882a593Smuzhiyun if (itn->fb_tunnel_dev)
506*4882a593Smuzhiyun vti_fb_tunnel_init(itn->fb_tunnel_dev);
507*4882a593Smuzhiyun return 0;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
vti_exit_batch_net(struct list_head * list_net)510*4882a593Smuzhiyun static void __net_exit vti_exit_batch_net(struct list_head *list_net)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun ip_tunnel_delete_nets(list_net, vti_net_id, &vti_link_ops);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun static struct pernet_operations vti_net_ops = {
516*4882a593Smuzhiyun .init = vti_init_net,
517*4882a593Smuzhiyun .exit_batch = vti_exit_batch_net,
518*4882a593Smuzhiyun .id = &vti_net_id,
519*4882a593Smuzhiyun .size = sizeof(struct ip_tunnel_net),
520*4882a593Smuzhiyun };
521*4882a593Smuzhiyun
vti_tunnel_validate(struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)522*4882a593Smuzhiyun static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
523*4882a593Smuzhiyun struct netlink_ext_ack *extack)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
vti_netlink_parms(struct nlattr * data[],struct ip_tunnel_parm * parms,__u32 * fwmark)528*4882a593Smuzhiyun static void vti_netlink_parms(struct nlattr *data[],
529*4882a593Smuzhiyun struct ip_tunnel_parm *parms,
530*4882a593Smuzhiyun __u32 *fwmark)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun memset(parms, 0, sizeof(*parms));
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun parms->iph.protocol = IPPROTO_IPIP;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (!data)
537*4882a593Smuzhiyun return;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun parms->i_flags = VTI_ISVTI;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (data[IFLA_VTI_LINK])
542*4882a593Smuzhiyun parms->link = nla_get_u32(data[IFLA_VTI_LINK]);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun if (data[IFLA_VTI_IKEY])
545*4882a593Smuzhiyun parms->i_key = nla_get_be32(data[IFLA_VTI_IKEY]);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (data[IFLA_VTI_OKEY])
548*4882a593Smuzhiyun parms->o_key = nla_get_be32(data[IFLA_VTI_OKEY]);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun if (data[IFLA_VTI_LOCAL])
551*4882a593Smuzhiyun parms->iph.saddr = nla_get_in_addr(data[IFLA_VTI_LOCAL]);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (data[IFLA_VTI_REMOTE])
554*4882a593Smuzhiyun parms->iph.daddr = nla_get_in_addr(data[IFLA_VTI_REMOTE]);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun if (data[IFLA_VTI_FWMARK])
557*4882a593Smuzhiyun *fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]);
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
vti_newlink(struct net * src_net,struct net_device * dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)560*4882a593Smuzhiyun static int vti_newlink(struct net *src_net, struct net_device *dev,
561*4882a593Smuzhiyun struct nlattr *tb[], struct nlattr *data[],
562*4882a593Smuzhiyun struct netlink_ext_ack *extack)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun struct ip_tunnel_parm parms;
565*4882a593Smuzhiyun __u32 fwmark = 0;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun vti_netlink_parms(data, &parms, &fwmark);
568*4882a593Smuzhiyun return ip_tunnel_newlink(dev, tb, &parms, fwmark);
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
vti_changelink(struct net_device * dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)571*4882a593Smuzhiyun static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
572*4882a593Smuzhiyun struct nlattr *data[],
573*4882a593Smuzhiyun struct netlink_ext_ack *extack)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun struct ip_tunnel *t = netdev_priv(dev);
576*4882a593Smuzhiyun __u32 fwmark = t->fwmark;
577*4882a593Smuzhiyun struct ip_tunnel_parm p;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun vti_netlink_parms(data, &p, &fwmark);
580*4882a593Smuzhiyun return ip_tunnel_changelink(dev, tb, &p, fwmark);
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
vti_get_size(const struct net_device * dev)583*4882a593Smuzhiyun static size_t vti_get_size(const struct net_device *dev)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun return
586*4882a593Smuzhiyun /* IFLA_VTI_LINK */
587*4882a593Smuzhiyun nla_total_size(4) +
588*4882a593Smuzhiyun /* IFLA_VTI_IKEY */
589*4882a593Smuzhiyun nla_total_size(4) +
590*4882a593Smuzhiyun /* IFLA_VTI_OKEY */
591*4882a593Smuzhiyun nla_total_size(4) +
592*4882a593Smuzhiyun /* IFLA_VTI_LOCAL */
593*4882a593Smuzhiyun nla_total_size(4) +
594*4882a593Smuzhiyun /* IFLA_VTI_REMOTE */
595*4882a593Smuzhiyun nla_total_size(4) +
596*4882a593Smuzhiyun /* IFLA_VTI_FWMARK */
597*4882a593Smuzhiyun nla_total_size(4) +
598*4882a593Smuzhiyun 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
vti_fill_info(struct sk_buff * skb,const struct net_device * dev)601*4882a593Smuzhiyun static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun struct ip_tunnel *t = netdev_priv(dev);
604*4882a593Smuzhiyun struct ip_tunnel_parm *p = &t->parms;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun if (nla_put_u32(skb, IFLA_VTI_LINK, p->link) ||
607*4882a593Smuzhiyun nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key) ||
608*4882a593Smuzhiyun nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key) ||
609*4882a593Smuzhiyun nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr) ||
610*4882a593Smuzhiyun nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr) ||
611*4882a593Smuzhiyun nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark))
612*4882a593Smuzhiyun return -EMSGSIZE;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun return 0;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = {
618*4882a593Smuzhiyun [IFLA_VTI_LINK] = { .type = NLA_U32 },
619*4882a593Smuzhiyun [IFLA_VTI_IKEY] = { .type = NLA_U32 },
620*4882a593Smuzhiyun [IFLA_VTI_OKEY] = { .type = NLA_U32 },
621*4882a593Smuzhiyun [IFLA_VTI_LOCAL] = { .len = sizeof_field(struct iphdr, saddr) },
622*4882a593Smuzhiyun [IFLA_VTI_REMOTE] = { .len = sizeof_field(struct iphdr, daddr) },
623*4882a593Smuzhiyun [IFLA_VTI_FWMARK] = { .type = NLA_U32 },
624*4882a593Smuzhiyun };
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun static struct rtnl_link_ops vti_link_ops __read_mostly = {
627*4882a593Smuzhiyun .kind = "vti",
628*4882a593Smuzhiyun .maxtype = IFLA_VTI_MAX,
629*4882a593Smuzhiyun .policy = vti_policy,
630*4882a593Smuzhiyun .priv_size = sizeof(struct ip_tunnel),
631*4882a593Smuzhiyun .setup = vti_tunnel_setup,
632*4882a593Smuzhiyun .validate = vti_tunnel_validate,
633*4882a593Smuzhiyun .newlink = vti_newlink,
634*4882a593Smuzhiyun .changelink = vti_changelink,
635*4882a593Smuzhiyun .dellink = ip_tunnel_dellink,
636*4882a593Smuzhiyun .get_size = vti_get_size,
637*4882a593Smuzhiyun .fill_info = vti_fill_info,
638*4882a593Smuzhiyun .get_link_net = ip_tunnel_get_link_net,
639*4882a593Smuzhiyun };
640*4882a593Smuzhiyun
vti_init(void)641*4882a593Smuzhiyun static int __init vti_init(void)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun const char *msg;
644*4882a593Smuzhiyun int err;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun pr_info("IPv4 over IPsec tunneling driver\n");
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun msg = "tunnel device";
649*4882a593Smuzhiyun err = register_pernet_device(&vti_net_ops);
650*4882a593Smuzhiyun if (err < 0)
651*4882a593Smuzhiyun goto pernet_dev_failed;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun msg = "tunnel protocols";
654*4882a593Smuzhiyun err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP);
655*4882a593Smuzhiyun if (err < 0)
656*4882a593Smuzhiyun goto xfrm_proto_esp_failed;
657*4882a593Smuzhiyun err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH);
658*4882a593Smuzhiyun if (err < 0)
659*4882a593Smuzhiyun goto xfrm_proto_ah_failed;
660*4882a593Smuzhiyun err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP);
661*4882a593Smuzhiyun if (err < 0)
662*4882a593Smuzhiyun goto xfrm_proto_comp_failed;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
665*4882a593Smuzhiyun msg = "ipip tunnel";
666*4882a593Smuzhiyun err = xfrm4_tunnel_register(&vti_ipip_handler, AF_INET);
667*4882a593Smuzhiyun if (err < 0)
668*4882a593Smuzhiyun goto xfrm_tunnel_ipip_failed;
669*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
670*4882a593Smuzhiyun err = xfrm4_tunnel_register(&vti_ipip6_handler, AF_INET6);
671*4882a593Smuzhiyun if (err < 0)
672*4882a593Smuzhiyun goto xfrm_tunnel_ipip6_failed;
673*4882a593Smuzhiyun #endif
674*4882a593Smuzhiyun #endif
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun msg = "netlink interface";
677*4882a593Smuzhiyun err = rtnl_link_register(&vti_link_ops);
678*4882a593Smuzhiyun if (err < 0)
679*4882a593Smuzhiyun goto rtnl_link_failed;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun return err;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun rtnl_link_failed:
684*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
685*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
686*4882a593Smuzhiyun xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
687*4882a593Smuzhiyun xfrm_tunnel_ipip6_failed:
688*4882a593Smuzhiyun #endif
689*4882a593Smuzhiyun xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
690*4882a593Smuzhiyun xfrm_tunnel_ipip_failed:
691*4882a593Smuzhiyun #endif
692*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
693*4882a593Smuzhiyun xfrm_proto_comp_failed:
694*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
695*4882a593Smuzhiyun xfrm_proto_ah_failed:
696*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
697*4882a593Smuzhiyun xfrm_proto_esp_failed:
698*4882a593Smuzhiyun unregister_pernet_device(&vti_net_ops);
699*4882a593Smuzhiyun pernet_dev_failed:
700*4882a593Smuzhiyun pr_err("vti init: failed to register %s\n", msg);
701*4882a593Smuzhiyun return err;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
vti_fini(void)704*4882a593Smuzhiyun static void __exit vti_fini(void)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun rtnl_link_unregister(&vti_link_ops);
707*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
708*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
709*4882a593Smuzhiyun xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
710*4882a593Smuzhiyun #endif
711*4882a593Smuzhiyun xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
712*4882a593Smuzhiyun #endif
713*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
714*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
715*4882a593Smuzhiyun xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
716*4882a593Smuzhiyun unregister_pernet_device(&vti_net_ops);
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun module_init(vti_init);
720*4882a593Smuzhiyun module_exit(vti_fini);
721*4882a593Smuzhiyun MODULE_LICENSE("GPL");
722*4882a593Smuzhiyun MODULE_ALIAS_RTNL_LINK("vti");
723*4882a593Smuzhiyun MODULE_ALIAS_NETDEV("ip_vti0");
724