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