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