tunnel.c revision a7ed1520ee9645e31b94caf72cad47be31856745
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 40const 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 68int 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 92int 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 118int 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 145static 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 169int tnl_prl_ioctl(int cmd, const char *name, void *p) 170{ 171 return tnl_gen_ioctl(cmd, name, p, -1); 172} 173 174int tnl_6rd_ioctl(int cmd, const char *name, void *p) 175{ 176 return tnl_gen_ioctl(cmd, name, p, -1); 177} 178 179int 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