xref: /aosp_15_r20/external/iproute2/ip/tunnel.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * Copyright (C)2006 USAGI/WIDE Project
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
5*de1e4e89SAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
6*de1e4e89SAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
7*de1e4e89SAndroid Build Coastguard Worker  * (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
10*de1e4e89SAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*de1e4e89SAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*de1e4e89SAndroid Build Coastguard Worker  * GNU General Public License for more details.
13*de1e4e89SAndroid Build Coastguard Worker  *
14*de1e4e89SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
15*de1e4e89SAndroid Build Coastguard Worker  * along with this program; if not, see <http://www.gnu.org/licenses>.
16*de1e4e89SAndroid Build Coastguard Worker  */
17*de1e4e89SAndroid Build Coastguard Worker /*
18*de1e4e89SAndroid Build Coastguard Worker  * split from ip_tunnel.c
19*de1e4e89SAndroid Build Coastguard Worker  */
20*de1e4e89SAndroid Build Coastguard Worker /*
21*de1e4e89SAndroid Build Coastguard Worker  * Author:
22*de1e4e89SAndroid Build Coastguard Worker  *	Masahide NAKAMURA @USAGI
23*de1e4e89SAndroid Build Coastguard Worker  */
24*de1e4e89SAndroid Build Coastguard Worker 
25*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <sys/types.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
31*de1e4e89SAndroid Build Coastguard Worker #include <sys/ioctl.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
33*de1e4e89SAndroid Build Coastguard Worker #include <linux/if.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <linux/ip.h>
35*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_tunnel.h>
36*de1e4e89SAndroid Build Coastguard Worker 
37*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
38*de1e4e89SAndroid Build Coastguard Worker #include "tunnel.h"
39*de1e4e89SAndroid Build Coastguard Worker 
tnl_strproto(__u8 proto)40*de1e4e89SAndroid Build Coastguard Worker const char *tnl_strproto(__u8 proto)
41*de1e4e89SAndroid Build Coastguard Worker {
42*de1e4e89SAndroid Build Coastguard Worker 	static char buf[16];
43*de1e4e89SAndroid Build Coastguard Worker 
44*de1e4e89SAndroid Build Coastguard Worker 	switch (proto) {
45*de1e4e89SAndroid Build Coastguard Worker 	case IPPROTO_IPIP:
46*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "ip");
47*de1e4e89SAndroid Build Coastguard Worker 		break;
48*de1e4e89SAndroid Build Coastguard Worker 	case IPPROTO_GRE:
49*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "gre");
50*de1e4e89SAndroid Build Coastguard Worker 		break;
51*de1e4e89SAndroid Build Coastguard Worker 	case IPPROTO_IPV6:
52*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "ipv6");
53*de1e4e89SAndroid Build Coastguard Worker 		break;
54*de1e4e89SAndroid Build Coastguard Worker 	case IPPROTO_ESP:
55*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "esp");
56*de1e4e89SAndroid Build Coastguard Worker 		break;
57*de1e4e89SAndroid Build Coastguard Worker 	case IPPROTO_MPLS:
58*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "mpls");
59*de1e4e89SAndroid Build Coastguard Worker 		break;
60*de1e4e89SAndroid Build Coastguard Worker 	case 0:
61*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "any");
62*de1e4e89SAndroid Build Coastguard Worker 		break;
63*de1e4e89SAndroid Build Coastguard Worker 	default:
64*de1e4e89SAndroid Build Coastguard Worker 		strcpy(buf, "unknown");
65*de1e4e89SAndroid Build Coastguard Worker 		break;
66*de1e4e89SAndroid Build Coastguard Worker 	}
67*de1e4e89SAndroid Build Coastguard Worker 
68*de1e4e89SAndroid Build Coastguard Worker 	return buf;
69*de1e4e89SAndroid Build Coastguard Worker }
70*de1e4e89SAndroid Build Coastguard Worker 
tnl_get_ioctl(const char * basedev,void * p)71*de1e4e89SAndroid Build Coastguard Worker int tnl_get_ioctl(const char *basedev, void *p)
72*de1e4e89SAndroid Build Coastguard Worker {
73*de1e4e89SAndroid Build Coastguard Worker 	struct ifreq ifr;
74*de1e4e89SAndroid Build Coastguard Worker 	int fd;
75*de1e4e89SAndroid Build Coastguard Worker 	int err;
76*de1e4e89SAndroid Build Coastguard Worker 
77*de1e4e89SAndroid Build Coastguard Worker 	strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
78*de1e4e89SAndroid Build Coastguard Worker 	ifr.ifr_ifru.ifru_data = (void *)p;
79*de1e4e89SAndroid Build Coastguard Worker 
80*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(preferred_family, SOCK_DGRAM, 0);
81*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
82*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "create socket failed: %s\n", strerror(errno));
83*de1e4e89SAndroid Build Coastguard Worker 		return -1;
84*de1e4e89SAndroid Build Coastguard Worker 	}
85*de1e4e89SAndroid Build Coastguard Worker 
86*de1e4e89SAndroid Build Coastguard Worker 	err = ioctl(fd, SIOCGETTUNNEL, &ifr);
87*de1e4e89SAndroid Build Coastguard Worker 	if (err)
88*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "get tunnel \"%s\" failed: %s\n", basedev,
89*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
90*de1e4e89SAndroid Build Coastguard Worker 
91*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
92*de1e4e89SAndroid Build Coastguard Worker 	return err;
93*de1e4e89SAndroid Build Coastguard Worker }
94*de1e4e89SAndroid Build Coastguard Worker 
tnl_add_ioctl(int cmd,const char * basedev,const char * name,void * p)95*de1e4e89SAndroid Build Coastguard Worker int tnl_add_ioctl(int cmd, const char *basedev, const char *name, void *p)
96*de1e4e89SAndroid Build Coastguard Worker {
97*de1e4e89SAndroid Build Coastguard Worker 	struct ifreq ifr;
98*de1e4e89SAndroid Build Coastguard Worker 	int fd;
99*de1e4e89SAndroid Build Coastguard Worker 	int err;
100*de1e4e89SAndroid Build Coastguard Worker 
101*de1e4e89SAndroid Build Coastguard Worker 	if (cmd == SIOCCHGTUNNEL && name[0])
102*de1e4e89SAndroid Build Coastguard Worker 		strncpy(ifr.ifr_name, name, IFNAMSIZ);
103*de1e4e89SAndroid Build Coastguard Worker 	else
104*de1e4e89SAndroid Build Coastguard Worker 		strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
105*de1e4e89SAndroid Build Coastguard Worker 	ifr.ifr_ifru.ifru_data = p;
106*de1e4e89SAndroid Build Coastguard Worker 
107*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(preferred_family, SOCK_DGRAM, 0);
108*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
109*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "create socket failed: %s\n", strerror(errno));
110*de1e4e89SAndroid Build Coastguard Worker 		return -1;
111*de1e4e89SAndroid Build Coastguard Worker 	}
112*de1e4e89SAndroid Build Coastguard Worker 
113*de1e4e89SAndroid Build Coastguard Worker 	err = ioctl(fd, cmd, &ifr);
114*de1e4e89SAndroid Build Coastguard Worker 	if (err)
115*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "add tunnel \"%s\" failed: %s\n", ifr.ifr_name,
116*de1e4e89SAndroid Build Coastguard Worker 			strerror(errno));
117*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
118*de1e4e89SAndroid Build Coastguard Worker 	return err;
119*de1e4e89SAndroid Build Coastguard Worker }
120*de1e4e89SAndroid Build Coastguard Worker 
tnl_del_ioctl(const char * basedev,const char * name,void * p)121*de1e4e89SAndroid Build Coastguard Worker int tnl_del_ioctl(const char *basedev, const char *name, void *p)
122*de1e4e89SAndroid Build Coastguard Worker {
123*de1e4e89SAndroid Build Coastguard Worker 	struct ifreq ifr;
124*de1e4e89SAndroid Build Coastguard Worker 	int fd;
125*de1e4e89SAndroid Build Coastguard Worker 	int err;
126*de1e4e89SAndroid Build Coastguard Worker 
127*de1e4e89SAndroid Build Coastguard Worker 	if (name[0])
128*de1e4e89SAndroid Build Coastguard Worker 		strncpy(ifr.ifr_name, name, IFNAMSIZ);
129*de1e4e89SAndroid Build Coastguard Worker 	else
130*de1e4e89SAndroid Build Coastguard Worker 		strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
131*de1e4e89SAndroid Build Coastguard Worker 
132*de1e4e89SAndroid Build Coastguard Worker 	ifr.ifr_ifru.ifru_data = p;
133*de1e4e89SAndroid Build Coastguard Worker 
134*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(preferred_family, SOCK_DGRAM, 0);
135*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
136*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "create socket failed: %s\n", strerror(errno));
137*de1e4e89SAndroid Build Coastguard Worker 		return -1;
138*de1e4e89SAndroid Build Coastguard Worker 	}
139*de1e4e89SAndroid Build Coastguard Worker 
140*de1e4e89SAndroid Build Coastguard Worker 	err = ioctl(fd, SIOCDELTUNNEL, &ifr);
141*de1e4e89SAndroid Build Coastguard Worker 	if (err)
142*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "delete tunnel \"%s\" failed: %s\n",
143*de1e4e89SAndroid Build Coastguard Worker 			ifr.ifr_name, strerror(errno));
144*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
145*de1e4e89SAndroid Build Coastguard Worker 	return err;
146*de1e4e89SAndroid Build Coastguard Worker }
147*de1e4e89SAndroid Build Coastguard Worker 
tnl_gen_ioctl(int cmd,const char * name,void * p,int skiperr)148*de1e4e89SAndroid Build Coastguard Worker static int tnl_gen_ioctl(int cmd, const char *name,
149*de1e4e89SAndroid Build Coastguard Worker 			 void *p, int skiperr)
150*de1e4e89SAndroid Build Coastguard Worker {
151*de1e4e89SAndroid Build Coastguard Worker 	struct ifreq ifr;
152*de1e4e89SAndroid Build Coastguard Worker 	int fd;
153*de1e4e89SAndroid Build Coastguard Worker 	int err;
154*de1e4e89SAndroid Build Coastguard Worker 
155*de1e4e89SAndroid Build Coastguard Worker 	strncpy(ifr.ifr_name, name, IFNAMSIZ);
156*de1e4e89SAndroid Build Coastguard Worker 	ifr.ifr_ifru.ifru_data = p;
157*de1e4e89SAndroid Build Coastguard Worker 
158*de1e4e89SAndroid Build Coastguard Worker 	fd = socket(preferred_family, SOCK_DGRAM, 0);
159*de1e4e89SAndroid Build Coastguard Worker 	if (fd < 0) {
160*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "create socket failed: %s\n", strerror(errno));
161*de1e4e89SAndroid Build Coastguard Worker 		return -1;
162*de1e4e89SAndroid Build Coastguard Worker 	}
163*de1e4e89SAndroid Build Coastguard Worker 
164*de1e4e89SAndroid Build Coastguard Worker 	err = ioctl(fd, cmd, &ifr);
165*de1e4e89SAndroid Build Coastguard Worker 	if (err && errno != skiperr)
166*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: ioctl %x failed: %s\n", name,
167*de1e4e89SAndroid Build Coastguard Worker 			cmd, strerror(errno));
168*de1e4e89SAndroid Build Coastguard Worker 	close(fd);
169*de1e4e89SAndroid Build Coastguard Worker 	return err;
170*de1e4e89SAndroid Build Coastguard Worker }
171*de1e4e89SAndroid Build Coastguard Worker 
tnl_prl_ioctl(int cmd,const char * name,void * p)172*de1e4e89SAndroid Build Coastguard Worker int tnl_prl_ioctl(int cmd, const char *name, void *p)
173*de1e4e89SAndroid Build Coastguard Worker {
174*de1e4e89SAndroid Build Coastguard Worker 	return tnl_gen_ioctl(cmd, name, p, -1);
175*de1e4e89SAndroid Build Coastguard Worker }
176*de1e4e89SAndroid Build Coastguard Worker 
tnl_6rd_ioctl(int cmd,const char * name,void * p)177*de1e4e89SAndroid Build Coastguard Worker int tnl_6rd_ioctl(int cmd, const char *name, void *p)
178*de1e4e89SAndroid Build Coastguard Worker {
179*de1e4e89SAndroid Build Coastguard Worker 	return tnl_gen_ioctl(cmd, name, p, -1);
180*de1e4e89SAndroid Build Coastguard Worker }
181*de1e4e89SAndroid Build Coastguard Worker 
tnl_ioctl_get_6rd(const char * name,void * p)182*de1e4e89SAndroid Build Coastguard Worker int tnl_ioctl_get_6rd(const char *name, void *p)
183*de1e4e89SAndroid Build Coastguard Worker {
184*de1e4e89SAndroid Build Coastguard Worker 	return tnl_gen_ioctl(SIOCGET6RD, name, p, EINVAL);
185*de1e4e89SAndroid Build Coastguard Worker }
186*de1e4e89SAndroid Build Coastguard Worker 
tnl_parse_key(const char * name,const char * key)187*de1e4e89SAndroid Build Coastguard Worker __be32 tnl_parse_key(const char *name, const char *key)
188*de1e4e89SAndroid Build Coastguard Worker {
189*de1e4e89SAndroid Build Coastguard Worker 	unsigned int uval;
190*de1e4e89SAndroid Build Coastguard Worker 
191*de1e4e89SAndroid Build Coastguard Worker 	if (strchr(key, '.'))
192*de1e4e89SAndroid Build Coastguard Worker 		return get_addr32(key);
193*de1e4e89SAndroid Build Coastguard Worker 
194*de1e4e89SAndroid Build Coastguard Worker 	if (get_unsigned(&uval, key, 0) < 0) {
195*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "invalid value for \"%s\": \"%s\";", name, key);
196*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " it should be an unsigned integer\n");
197*de1e4e89SAndroid Build Coastguard Worker 		exit(-1);
198*de1e4e89SAndroid Build Coastguard Worker 	}
199*de1e4e89SAndroid Build Coastguard Worker 	return htonl(uval);
200*de1e4e89SAndroid Build Coastguard Worker }
201*de1e4e89SAndroid Build Coastguard Worker 
202*de1e4e89SAndroid Build Coastguard Worker /* tnl_print_stats - print tunnel statistics
203*de1e4e89SAndroid Build Coastguard Worker  *
204*de1e4e89SAndroid Build Coastguard Worker  * @buf - tunnel interface's line in /proc/net/dev,
205*de1e4e89SAndroid Build Coastguard Worker  *        starting past the interface name and following colon
206*de1e4e89SAndroid Build Coastguard Worker  */
tnl_print_stats(const char * buf)207*de1e4e89SAndroid Build Coastguard Worker void tnl_print_stats(const char *buf)
208*de1e4e89SAndroid Build Coastguard Worker {
209*de1e4e89SAndroid Build Coastguard Worker 	unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
210*de1e4e89SAndroid Build Coastguard Worker 		      rx_fifo, rx_frame,
211*de1e4e89SAndroid Build Coastguard Worker 		      tx_bytes, tx_packets, tx_errs, tx_drops,
212*de1e4e89SAndroid Build Coastguard Worker 		      tx_fifo, tx_colls, tx_carrier, rx_multi;
213*de1e4e89SAndroid Build Coastguard Worker 
214*de1e4e89SAndroid Build Coastguard Worker 	if (sscanf(buf, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
215*de1e4e89SAndroid Build Coastguard Worker 		   &rx_bytes, &rx_packets, &rx_errs, &rx_drops,
216*de1e4e89SAndroid Build Coastguard Worker 		   &rx_fifo, &rx_frame, &rx_multi,
217*de1e4e89SAndroid Build Coastguard Worker 		   &tx_bytes, &tx_packets, &tx_errs, &tx_drops,
218*de1e4e89SAndroid Build Coastguard Worker 		   &tx_fifo, &tx_colls, &tx_carrier) != 14)
219*de1e4e89SAndroid Build Coastguard Worker 		return;
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 	printf("%s", _SL_);
222*de1e4e89SAndroid Build Coastguard Worker 	printf("RX: Packets    Bytes        Errors CsumErrs OutOfSeq Mcasts%s", _SL_);
223*de1e4e89SAndroid Build Coastguard Worker 	printf("    %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld%s",
224*de1e4e89SAndroid Build Coastguard Worker 	       rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi, _SL_);
225*de1e4e89SAndroid Build Coastguard Worker 	printf("TX: Packets    Bytes        Errors DeadLoop NoRoute  NoBufs%s", _SL_);
226*de1e4e89SAndroid Build Coastguard Worker 	printf("    %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld",
227*de1e4e89SAndroid Build Coastguard Worker 	       tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops);
228*de1e4e89SAndroid Build Coastguard Worker }
229