Pau Espin Pedrol | fdd732b | 2017-10-13 14:32:24 +0200 | [diff] [blame] | 1 | /* |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 2 | * TUN interface functions. |
jjako | 0fe0df0 | 2004-09-17 11:30:40 +0000 | [diff] [blame] | 3 | * Copyright (C) 2002, 2003, 2004 Mondru AB. |
Harald Welte | df3dcac | 2018-04-25 16:20:32 +0200 | [diff] [blame] | 4 | * Copyright (C) 2017-2018 by Harald Welte <laforge@gnumonks.org> |
Pau Espin Pedrol | fdd732b | 2017-10-13 14:32:24 +0200 | [diff] [blame] | 5 | * |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 6 | * The contents of this file may be used under the terms of the GNU |
| 7 | * General Public License Version 2, provided that the above copyright |
| 8 | * notice and this permission notice is included in all copies or |
| 9 | * substantial portions of the software. |
Pau Espin Pedrol | fdd732b | 2017-10-13 14:32:24 +0200 | [diff] [blame] | 10 | * |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 11 | */ |
| 12 | |
| 13 | /* |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 14 | * tun.c: Contains all TUN functionality. Is able to handle multiple |
| 15 | * tunnels in the same program. Each tunnel is identified by the struct, |
| 16 | * which is passed to functions. |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 17 | * |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 18 | */ |
| 19 | |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 20 | #include <stdio.h> |
| 21 | #include <stdlib.h> |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 22 | #include <stdbool.h> |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 23 | #include <sys/types.h> |
| 24 | #include <sys/socket.h> |
| 25 | #include <netinet/in.h> |
| 26 | #include <arpa/inet.h> |
| 27 | #include <sys/stat.h> |
| 28 | #include <sys/time.h> |
| 29 | #include <unistd.h> |
| 30 | #include <string.h> |
| 31 | #include <errno.h> |
| 32 | #include <fcntl.h> |
| 33 | |
| 34 | #include <stdio.h> |
| 35 | #include <fcntl.h> |
| 36 | #include <unistd.h> |
| 37 | #include <sys/time.h> |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 38 | #include <sys/ioctl.h> |
| 39 | #include <sys/socket.h> |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 40 | #include <errno.h> |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 41 | #include <net/route.h> |
Harald Welte | 2e48a44 | 2017-08-03 00:47:03 +0200 | [diff] [blame] | 42 | #include <net/if.h> |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 43 | |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 44 | #if defined(__linux__) |
jjako | 0141d20 | 2004-01-09 15:19:20 +0000 | [diff] [blame] | 45 | #include <linux/if_tun.h> |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 46 | |
| 47 | #elif defined (__FreeBSD__) |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 48 | #include <net/if_tun.h> |
Harald Welte | 2e48a44 | 2017-08-03 00:47:03 +0200 | [diff] [blame] | 49 | #include <net/if_var.h> |
| 50 | #include <netinet/in_var.h> |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 51 | |
jjako | 0fe0df0 | 2004-09-17 11:30:40 +0000 | [diff] [blame] | 52 | #elif defined (__APPLE__) |
| 53 | #include <net/if.h> |
| 54 | |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 55 | #else |
| 56 | #error "Unknown platform!" |
jjako | 0141d20 | 2004-01-09 15:19:20 +0000 | [diff] [blame] | 57 | #endif |
| 58 | |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 59 | #include "tun.h" |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 60 | #include "syserr.h" |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 61 | #include "gtp-kernel.h" |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 62 | |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 63 | static int tun_setaddr4(struct tun_t *this, struct in_addr *addr, |
| 64 | struct in_addr *dstaddr, struct in_addr *netmask) |
| 65 | { |
| 66 | int rc; |
| 67 | rc = netdev_setaddr4(this->devname, addr, dstaddr, netmask); |
| 68 | if (rc < 0) |
| 69 | return rc; |
| 70 | |
Stefan Sperling | b0b9c28 | 2018-11-22 08:36:35 +0100 | [diff] [blame] | 71 | if (addr) { |
| 72 | this->addr.len = sizeof(struct in_addr); |
| 73 | this->addr.v4.s_addr = addr->s_addr; |
| 74 | } |
| 75 | if (dstaddr) { |
| 76 | this->dstaddr.len = sizeof(struct in_addr); |
| 77 | this->dstaddr.v4.s_addr = dstaddr->s_addr; |
| 78 | } |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 79 | if (netmask) |
| 80 | this->netmask.s_addr = netmask->s_addr; |
| 81 | this->addrs++; |
| 82 | #if defined(__FreeBSD__) || defined (__APPLE__) |
| 83 | this->routes = 1; |
| 84 | #endif |
| 85 | |
| 86 | return rc; |
| 87 | } |
| 88 | |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 89 | static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr, |
| 90 | size_t prefixlen) |
| 91 | { |
| 92 | int rc; |
| 93 | rc = netdev_setaddr6(this->devname, addr, dstaddr, prefixlen); |
| 94 | if (rc < 0) |
| 95 | return rc; |
Stefan Sperling | b0b9c28 | 2018-11-22 08:36:35 +0100 | [diff] [blame] | 96 | if (dstaddr) { |
| 97 | this->dstaddr.len = sizeof(*dstaddr); |
| 98 | memcpy(&this->dstaddr.v6, dstaddr, sizeof(*dstaddr)); |
| 99 | } |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 100 | this->addrs++; |
| 101 | #if defined(__FreeBSD__) || defined (__APPLE__) |
| 102 | this->routes = 1; |
| 103 | #endif |
| 104 | |
| 105 | return rc; |
| 106 | } |
| 107 | |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 108 | static int tun_addaddr4(struct tun_t *this, struct in_addr *addr, |
| 109 | struct in_addr *dstaddr, struct in_addr *netmask) |
| 110 | { |
| 111 | int rc; |
| 112 | |
| 113 | /* TODO: Is this needed on FreeBSD? */ |
| 114 | if (!this->addrs) /* Use ioctl for first addr to make ping work */ |
| 115 | return tun_setaddr4(this, addr, dstaddr, netmask); /* TODO dstaddr */ |
| 116 | |
| 117 | rc = netdev_addaddr4(this->devname, addr, dstaddr, netmask); |
| 118 | if (rc < 0) |
| 119 | return rc; |
| 120 | |
| 121 | this->addrs++; |
| 122 | |
| 123 | return rc; |
| 124 | } |
| 125 | |
Harald Welte | 9a6da45 | 2018-04-25 17:19:18 +0200 | [diff] [blame] | 126 | static int tun_addaddr6(struct tun_t *this, |
| 127 | struct in6_addr *addr, |
| 128 | struct in6_addr *dstaddr, int prefixlen) |
| 129 | { |
| 130 | int rc; |
| 131 | |
| 132 | if (!this->addrs) /* Use ioctl for first addr to make ping work */ |
| 133 | return tun_setaddr6(this, addr, dstaddr, prefixlen); |
| 134 | |
| 135 | rc = netdev_addaddr6(this->devname, addr, dstaddr, prefixlen); |
| 136 | if (rc < 0) |
| 137 | return rc; |
| 138 | |
| 139 | this->addrs++; |
| 140 | |
| 141 | return rc; |
| 142 | } |
| 143 | |
Pau Espin Pedrol | f5e40b7 | 2017-12-14 14:01:23 +0100 | [diff] [blame] | 144 | int tun_addaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen) |
| 145 | { |
| 146 | struct in_addr netmask; |
| 147 | switch (addr->len) { |
| 148 | case 4: |
| 149 | netmask.s_addr = htonl(0xffffffff << (32 - prefixlen)); |
| 150 | return tun_addaddr4(this, &addr->v4, dstaddr ? &dstaddr->v4 : NULL, &netmask); |
| 151 | case 16: |
| 152 | return tun_addaddr6(this, &addr->v6, dstaddr ? &dstaddr->v6 : NULL, prefixlen); |
| 153 | default: |
| 154 | return -1; |
| 155 | } |
| 156 | } |
| 157 | |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 158 | int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, int fd0, int fd1u) |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 159 | { |
jjako | ec89e9f | 2004-01-10 06:38:43 +0000 | [diff] [blame] | 160 | |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 161 | #if defined(__linux__) |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 162 | struct ifreq ifr; |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 163 | |
jjako | 0fe0df0 | 2004-09-17 11:30:40 +0000 | [diff] [blame] | 164 | #elif defined(__FreeBSD__) || defined (__APPLE__) |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 165 | char devname[IFNAMSIZ + 5]; /* "/dev/" + ifname */ |
| 166 | int devnum; |
| 167 | struct ifaliasreq areq; |
| 168 | int fd; |
jjako | ec89e9f | 2004-01-10 06:38:43 +0000 | [diff] [blame] | 169 | #endif |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 170 | |
| 171 | if (!(*tun = calloc(1, sizeof(struct tun_t)))) { |
Holger Hans Peter Freyther | 9c7fd8e | 2014-12-04 16:32:37 +0100 | [diff] [blame] | 172 | SYS_ERR(DTUN, LOGL_ERROR, errno, "calloc() failed"); |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 173 | return EOF; |
| 174 | } |
| 175 | |
| 176 | (*tun)->cb_ind = NULL; |
| 177 | (*tun)->addrs = 0; |
| 178 | (*tun)->routes = 0; |
| 179 | |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 180 | #if defined(__linux__) |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 181 | if (!use_kernel) { |
| 182 | /* Open the actual tun device */ |
| 183 | if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) { |
| 184 | SYS_ERR(DTUN, LOGL_ERROR, errno, "open() failed"); |
| 185 | goto err_free; |
| 186 | } |
| 187 | |
| 188 | /* Set device flags. For some weird reason this is also the method |
| 189 | used to obtain the network interface name */ |
| 190 | memset(&ifr, 0, sizeof(ifr)); |
| 191 | if (dev_name) |
| 192 | strcpy(ifr.ifr_name, dev_name); |
| 193 | ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */ |
| 194 | if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) { |
| 195 | SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed"); |
| 196 | goto err_close; |
| 197 | } |
| 198 | |
| 199 | strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ); |
| 200 | (*tun)->devname[IFNAMSIZ - 1] = 0; |
| 201 | |
Stefan Sperling | aee905b | 2018-11-21 14:12:22 +0100 | [diff] [blame] | 202 | /* Disable checksums */ |
| 203 | if (ioctl((*tun)->fd, TUNSETNOCSUM, 1) < 0) { |
| 204 | SYS_ERR(DTUN, LOGL_NOTICE, errno, "could not disable checksum on %s", (*tun)->devname); |
| 205 | } |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 206 | return 0; |
| 207 | } else { |
| 208 | strncpy((*tun)->devname, dev_name, IFNAMSIZ); |
| 209 | (*tun)->devname[IFNAMSIZ - 1] = 0; |
| 210 | (*tun)->fd = -1; |
| 211 | |
| 212 | if (gtp_kernel_create(-1, dev_name, fd0, fd1u) < 0) { |
| 213 | LOGP(DTUN, LOGL_ERROR, "cannot create GTP tunnel device: %s\n", |
| 214 | strerror(errno)); |
| 215 | return -1; |
| 216 | } |
| 217 | LOGP(DTUN, LOGL_NOTICE, "GTP kernel configured\n"); |
| 218 | return 0; |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 219 | } |
| 220 | |
jjako | 0fe0df0 | 2004-09-17 11:30:40 +0000 | [diff] [blame] | 221 | #elif defined(__FreeBSD__) || defined (__APPLE__) |
jjako | ec89e9f | 2004-01-10 06:38:43 +0000 | [diff] [blame] | 222 | |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 223 | if (use_kernel) { |
| 224 | LOGP(DTUN, LOGL_ERROR, "No kernel GTP-U support in FreeBSD!\n"); |
| 225 | return -1; |
| 226 | } |
| 227 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 228 | /* Find suitable device */ |
| 229 | for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */ |
| 230 | snprintf(devname, sizeof(devname), "/dev/tun%d", devnum); |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 231 | if (((*tun)->fd = open(devname, O_RDWR)) >= 0) |
| 232 | break; |
| 233 | if (errno != EBUSY) |
| 234 | break; |
| 235 | } |
| 236 | if ((*tun)->fd < 0) { |
Holger Hans Peter Freyther | 9c7fd8e | 2014-12-04 16:32:37 +0100 | [diff] [blame] | 237 | SYS_ERR(DTUN, LOGL_ERROR, errno, |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 238 | "Can't find tunnel device"); |
Harald Welte | 9e6dfa0 | 2017-08-12 15:06:19 +0200 | [diff] [blame] | 239 | goto err_free; |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 240 | } |
jjako | ec89e9f | 2004-01-10 06:38:43 +0000 | [diff] [blame] | 241 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 242 | snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum); |
Harald Welte | 81bc2ae | 2017-08-11 12:56:30 +0200 | [diff] [blame] | 243 | (*tun)->devname[sizeof((*tun)->devname)-1] = 0; |
jjako | 1f15864 | 2004-02-05 20:39:57 +0000 | [diff] [blame] | 244 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 245 | /* The tun device we found might have "old" IP addresses allocated */ |
| 246 | /* We need to delete those. This problem is not present on Linux */ |
jjako | 1f15864 | 2004-02-05 20:39:57 +0000 | [diff] [blame] | 247 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 248 | memset(&areq, 0, sizeof(areq)); |
jjako | 1f15864 | 2004-02-05 20:39:57 +0000 | [diff] [blame] | 249 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 250 | /* Set up interface name */ |
| 251 | strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ); |
| 252 | areq.ifra_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */ |
jjako | 1f15864 | 2004-02-05 20:39:57 +0000 | [diff] [blame] | 253 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 254 | /* Create a channel to the NET kernel. */ |
| 255 | if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
Holger Hans Peter Freyther | 9c7fd8e | 2014-12-04 16:32:37 +0100 | [diff] [blame] | 256 | SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed"); |
Harald Welte | 9e6dfa0 | 2017-08-12 15:06:19 +0200 | [diff] [blame] | 257 | goto err_close; |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 258 | } |
jjako | 1f15864 | 2004-02-05 20:39:57 +0000 | [diff] [blame] | 259 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 260 | /* Delete any IP addresses until SIOCDIFADDR fails */ |
| 261 | while (ioctl(fd, SIOCDIFADDR, (void *)&areq) != -1) ; |
| 262 | |
| 263 | close(fd); |
| 264 | return 0; |
jjako | 409b855 | 2004-02-04 22:57:41 +0000 | [diff] [blame] | 265 | #endif |
| 266 | |
Harald Welte | 9e6dfa0 | 2017-08-12 15:06:19 +0200 | [diff] [blame] | 267 | err_close: |
| 268 | close((*tun)->fd); |
| 269 | err_free: |
| 270 | free(*tun); |
| 271 | *tun = NULL; |
| 272 | return -1; |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 273 | } |
| 274 | |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 275 | int tun_free(struct tun_t *tun) |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 276 | { |
jjako | 163b455 | 2004-12-30 15:33:58 +0000 | [diff] [blame] | 277 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 278 | if (tun->routes) { |
Stefan Sperling | b0b9c28 | 2018-11-22 08:36:35 +0100 | [diff] [blame] | 279 | netdev_delroute(&tun->dstaddr.v4, &tun->addr.v4, &tun->netmask); |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 280 | } |
jjako | 163b455 | 2004-12-30 15:33:58 +0000 | [diff] [blame] | 281 | |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 282 | if (tun->fd >= 0) { |
| 283 | if (close(tun->fd)) { |
| 284 | SYS_ERR(DTUN, LOGL_ERROR, errno, "close() failed"); |
| 285 | } |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 286 | } |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 287 | |
Harald Welte | f228639 | 2018-04-25 19:02:31 +0200 | [diff] [blame] | 288 | gtp_kernel_stop(tun->devname); |
| 289 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 290 | /* TODO: For solaris we need to unlink streams */ |
jjako | ec89e9f | 2004-01-10 06:38:43 +0000 | [diff] [blame] | 291 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 292 | free(tun); |
| 293 | return 0; |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 294 | } |
| 295 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 296 | int tun_set_cb_ind(struct tun_t *this, |
| 297 | int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len)) |
| 298 | { |
| 299 | this->cb_ind = cb_ind; |
| 300 | return 0; |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 301 | } |
| 302 | |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 303 | int tun_decaps(struct tun_t *this) |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 304 | { |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 305 | unsigned char buffer[PACKET_MAX]; |
| 306 | int status; |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 307 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 308 | if ((status = read(this->fd, buffer, sizeof(buffer))) <= 0) { |
Holger Hans Peter Freyther | 9c7fd8e | 2014-12-04 16:32:37 +0100 | [diff] [blame] | 309 | SYS_ERR(DTUN, LOGL_ERROR, errno, "read() failed"); |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 310 | return -1; |
| 311 | } |
| 312 | |
| 313 | if (this->cb_ind) |
| 314 | return this->cb_ind(this, buffer, status); |
| 315 | |
| 316 | return 0; |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 317 | } |
| 318 | |
| 319 | int tun_encaps(struct tun_t *tun, void *pack, unsigned len) |
| 320 | { |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 321 | return write(tun->fd, pack, len); |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 322 | } |
| 323 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 324 | int tun_runscript(struct tun_t *tun, char *script) |
| 325 | { |
jjako | a7cd249 | 2003-04-11 09:40:12 +0000 | [diff] [blame] | 326 | |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 327 | char buf[TUN_SCRIPTSIZE]; |
| 328 | char snet[TUN_ADDRSIZE]; |
| 329 | char smask[TUN_ADDRSIZE]; |
| 330 | int rc; |
| 331 | |
Stefan Sperling | b0b9c28 | 2018-11-22 08:36:35 +0100 | [diff] [blame] | 332 | strncpy(snet, inet_ntoa(tun->addr.v4), sizeof(snet)); |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 333 | snet[sizeof(snet) - 1] = 0; |
| 334 | strncpy(smask, inet_ntoa(tun->netmask), sizeof(smask)); |
| 335 | smask[sizeof(smask) - 1] = 0; |
| 336 | |
| 337 | /* system("ipup /dev/tun0 192.168.0.10 255.255.255.0"); */ |
| 338 | snprintf(buf, sizeof(buf), "%s %s %s %s", |
| 339 | script, tun->devname, snet, smask); |
| 340 | buf[sizeof(buf) - 1] = 0; |
| 341 | rc = system(buf); |
| 342 | if (rc == -1) { |
Holger Hans Peter Freyther | 9c7fd8e | 2014-12-04 16:32:37 +0100 | [diff] [blame] | 343 | SYS_ERR(DTUN, LOGL_ERROR, errno, |
Harald Welte | bed35df | 2011-11-02 13:06:18 +0100 | [diff] [blame] | 344 | "Error executing command %s", buf); |
| 345 | return -1; |
| 346 | } |
| 347 | return 0; |
jjako | 52c2414 | 2002-12-16 13:33:51 +0000 | [diff] [blame] | 348 | } |
Harald Welte | f85fe97 | 2017-09-24 20:00:34 +0800 | [diff] [blame] | 349 | |
Harald Welte | 4c7d291 | 2017-11-08 15:19:17 +0900 | [diff] [blame] | 350 | /*! Obtain the local address of the tun device. |
| 351 | * \param[in] tun Target device owning the IP |
| 352 | * \param[out] prefix_list List of prefix structures to fill with each IPv4/6 and prefix length found. |
| 353 | * \param[in] prefix_size Amount of elements allowed to be fill in the prefix_list array. |
| 354 | * \param[in] flags Specify which kind of IP to look for: IP_TYPE_IPv4, IP_TYPE_IPv6_LINK, IP_TYPE_IPv6_NONLINK |
| 355 | * \returns The number of ips found following the criteria specified by flags, -1 on error. |
| 356 | * |
| 357 | * This function will fill prefix_list with up to prefix_size IPs following the |
| 358 | * criteria specified by flags parameter. It returns the number of IPs matching |
| 359 | * the criteria. As a result, the number returned can be bigger than |
| 360 | * prefix_size. It can be used with prefix_size=0 to get an estimate of the size |
| 361 | * needed for prefix_list. |
| 362 | */ |
| 363 | int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list, size_t prefix_size, int flags) |
| 364 | { |
| 365 | return netdev_ip_local_get(tun->devname, prefix_list, prefix_size, flags); |
| 366 | } |