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