1 /* vim: set expandtab ts=4 sw=4: */
2 /*
3 * You may redistribute this program and/or modify it under the terms of
4 * the GNU General Public License as published by the Free Software Foundation,
5 * either version 3 of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <https://www.gnu.org/licenses/>.
14 */
15 #include "interface/tuntap/TUNInterface.h"
16 #include "exception/Except.h"
17 #include "interface/tuntap/BSDMessageTypeWrapper.h"
18 #include "util/AddrTools.h"
19 #include "util/events/Pipe.h"
20
21 #include <errno.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <net/if.h>
33 #include <string.h>
34 #include <netdb.h>
35 #include <net/if_tun.h>
36 #include <netinet/in.h>
37 #include <netinet6/in6_var.h>
38 #include <netinet6/nd6.h>
39
40 /* Tun Configurator for NetBSD. */
41
Er_DEFUN(struct Iface * TUNInterface_new (const char * interfaceName,char assignedInterfaceName[TUNInterface_IFNAMSIZ],int isTapMode,struct EventBase * base,struct Log * logger,struct Allocator * alloc))42 Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
43 char assignedInterfaceName[TUNInterface_IFNAMSIZ],
44 int isTapMode,
45 struct EventBase* base,
46 struct Log* logger,
47 struct Allocator* alloc))
48 {
49 if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
50 int err;
51 char file[TUNInterface_IFNAMSIZ];
52 int i;
53 int ppa = -1; // to store the tunnel device index
54 int tunFd = -1;
55 if (interfaceName && strlen(interfaceName) > 3 && !strncmp(interfaceName, "tun", 3)) {
56 snprintf(file, TUNInterface_IFNAMSIZ, "/dev/%s", interfaceName);
57 tunFd = open(file, O_RDWR);
58 } else {
59 for (ppa = 0;tunFd == -1 && ppa < 99;ppa++) {
60 snprintf(file, TUNInterface_IFNAMSIZ, "/dev/tun%d", ppa);
61 tunFd = open(file, O_RDWR);
62 }
63 }
64 if (tunFd < 0 ) {
65 err = errno;
66 close(tunFd);
67 Er_raise(alloc, "%s [%s]", "open(\"/dev/tunX\")", strerror(err));
68 }
69 /* from the NetBSD tun man page:
70 TUNSIFHEAD The argument should be a pointer to an int; a non-zero value
71 turns off ``link-layer'' mode, and enables ``multi-af'' mode,
72 where every packet is preceded with a four byte address
73 family.
74 */
75 i = 2;
76 if (ioctl(tunFd, TUNSIFHEAD, &i) == -1) {
77 err = errno;
78 close(tunFd);
79 Er_raise(alloc, "%s [%s]", "ioctl(tunFd,TUNSIFHEAD,&2)", strerror(err));
80 }
81 // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
82 // so we'll skip the pretty names and call everything tunX
83 if (assignedInterfaceName) {
84 if (ppa == -1) {
85 snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "%s", interfaceName);
86 } else {
87 snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "tun%d", ppa);
88 }
89 }
90 struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
91
92 struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger);
93 Iface_plumb(&p->iface, &bmtw->wireSide);
94 Er_ret(&bmtw->inside);
95 }
96