Skip to content
This repository
Browse code

Added FreeBSD interface code

  • Loading branch information...
commit c32f1bf8ce54087ea757f939d64afc42dccc3135 1 parent 812e302
jercos authored September 13, 2012
2  CMakeLists.txt
@@ -43,6 +43,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL SunOS)
43 43
     set(ILLUMOS TRUE)
44 44
 elseif(CMAKE_SYSTEM_NAME STREQUAL Linux)
45 45
     set(LINUX TRUE)
  46
+elseif(CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
  47
+    set(FREEBSD TRUE)
46 48
 endif()
47 49
 
48 50
 if(CMAKE_C_COMPILER MATCHES "(.*)-gcc")
3  admin/Admin.h
@@ -19,6 +19,9 @@
19 19
 #include "exception/ExceptionHandler.h"
20 20
 #include "memory/Allocator.h"
21 21
 #include "util/Log.h"
  22
+#ifdef __FreeBSD__
  23
+#include <netinet/in.h>
  24
+#endif
22 25
 
23 26
 #include <event2/event.h>
24 27
 #include <stdbool.h>
3  admin/AdminClient.h
@@ -19,6 +19,9 @@
19 19
 #include "benc/Dict.h"
20 20
 #include "memory/Allocator.h"
21 21
 #include "util/Log.h"
  22
+#ifdef __FreeBSD__
  23
+#include <netinet/in.h>
  24
+#endif
22 25
 
23 26
 #include <event2/event.h>
24 27
 
2  contrib/python/cexec
... ...
@@ -1,4 +1,4 @@
1  
-#!/usr/bin/python
  1
+#!/usr/bin/env python
2 2
 # You may redistribute this program and/or modify it under the terms of
3 3
 # the GNU General Public License as published by the Free Software Foundation,
4 4
 # either version 3 of the License, or (at your option) any later version.
3  interface/CMakeLists.txt
@@ -23,6 +23,9 @@ else()
23 23
   elseif(ILLUMOS)
24 24
     add_definitions(-D Illumos=1)
25 25
     set(tunconf TUNConfigurator_Illumos.c)
  26
+  elseif(FREEBSD)
  27
+    add_definitions(-D FreeBSD=1)
  28
+    set(tunconf TUNConfigurator_FreeBSD.c)
26 29
   else()
27 30
     message(FATAL_ERROR "no TUN adapter to handle your system [${CMAKE_SYSTEM_NAME}]")
28 31
   endif()
213  interface/TUNConfigurator_FreeBSD.c
... ...
@@ -0,0 +1,213 @@
  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 <http://www.gnu.org/licenses/>.
  14
+ */
  15
+#include "exception/Except.h"
  16
+#include "interface/Interface.h"
  17
+#include "interface/TUNConfigurator.h"
  18
+#include "util/AddrTools.h"
  19
+
  20
+#include <ctype.h>
  21
+#include <fcntl.h>
  22
+#include <stdio.h>
  23
+#include <sys/ioctl.h>
  24
+#include <unistd.h>
  25
+#include <errno.h>
  26
+#include <sys/socket.h>
  27
+#include <sys/types.h>
  28
+#include <sys/stat.h>
  29
+#include <stdlib.h>
  30
+#include <stddef.h>
  31
+#include <net/if.h>
  32
+
  33
+#include <netdb.h>
  34
+#include <net/if_var.h>
  35
+#include <net/if_tun.h>
  36
+#include <netinet/in.h>
  37
+#include <netinet6/in6_var.h>
  38
+#include <netinet6/nd6.h>
  39
+#include <sys/errno.h>
  40
+
  41
+#define APPLE_UTUN_CONTROL "com.apple.net.utun_control"
  42
+#define UTUN_OPT_IFNAME 2
  43
+
  44
+/* Tun Configurator for Apple computers. */
  45
+
  46
+/**
  47
+ * Open the tun device.
  48
+ *
  49
+ * @param interfaceName the interface name you *want* to use or NULL to let the kernel decide.
  50
+ * @param assignedInterfaceName the interface name you get.
  51
+ * @param log
  52
+ * @param eh
  53
+ * @return a file descriptor for the tunnel.
  54
+ */
  55
+void* TUNConfigurator_initTun(const char* interfaceName,
  56
+                              char assignedInterfaceName[TUNConfigurator_IFNAMSIZ],
  57
+                              struct Log* logger,
  58
+                              struct Except* eh)
  59
+{
  60
+    // Open the descriptor
  61
+    int tunFd = open("/dev/tun", O_RDWR);
  62
+
  63
+    //Get the resulting device name
  64
+    const char* assignedDevname;
  65
+    assignedDevname = fdevname(tunFd);
  66
+
  67
+    // Extract the number eg: 0 from tun0
  68
+    int ppa = 0;
  69
+    for (uint32_t i = 0; i < strlen(assignedDevname); i++) {
  70
+        if (isdigit(assignedDevname[i])) {
  71
+            ppa = atoi(assignedDevname);
  72
+        }
  73
+    }
  74
+
  75
+    if (tunFd < 0 || ppa < 0 ) {
  76
+        int err = errno;
  77
+        close(tunFd);
  78
+
  79
+        char* error = NULL;
  80
+        if (tunFd < 0) {
  81
+            error = "open(\"/dev/tun\")";
  82
+        } else if (ppa < 0) {
  83
+            error = "fdevname/getting number from fdevname";
  84
+        }
  85
+        Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, strerror(err));
  86
+    }
  87
+
  88
+    // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
  89
+    // so we'll skip the pretty names and call everything tunX
  90
+    snprintf(assignedInterfaceName, TUNConfigurator_IFNAMSIZ, "tun%d", ppa);
  91
+
  92
+    char* error = NULL;
  93
+
  94
+    int tunhead = 1;
  95
+    if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) {
  96
+        error = "TUNSIFHEAD";
  97
+    }
  98
+
  99
+    if (error) {
  100
+        int err = errno;
  101
+        close(tunFd);
  102
+        Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, strerror(err));
  103
+    }
  104
+
  105
+
  106
+    intptr_t ret = (intptr_t) tunFd;
  107
+    return (void*) ret;
  108
+}
  109
+
  110
+void TUNConfigurator_setIpAddress(const char* interfaceName,
  111
+                                  const uint8_t address[16],
  112
+                                  int prefixLen,
  113
+                                  struct Log* logger,
  114
+                                  struct Except* eh)
  115
+{
  116
+    /* stringify our IP address */
  117
+    char myIp[40];
  118
+    AddrTools_printIp((uint8_t*)myIp, address);
  119
+
  120
+    /* set up the interface ip assignment request */
  121
+    struct in6_aliasreq in6_addreq;
  122
+    memset(&in6_addreq, 0, sizeof(in6_addreq));
  123
+    in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
  124
+    in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
  125
+
  126
+    /* parse the IPv6 address and add it to the request */
  127
+    struct addrinfo hints, *result;
  128
+
  129
+    bzero(&hints, sizeof(struct addrinfo));
  130
+    hints.ai_family = AF_INET6;
  131
+    int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
  132
+    if (err) {
  133
+        // Should never happen since the address is specified as binary.
  134
+        Except_raise(eh,
  135
+                     TUNConfigurator_setIpAddress_INTERNAL,
  136
+                     "bad IPv6 address [%s]",
  137
+                     gai_strerror(err));
  138
+    }
  139
+
  140
+    bcopy(result->ai_addr, &in6_addreq.ifra_addr, result->ai_addrlen);
  141
+
  142
+    /* turn the prefixlen into a mask, and add it to the request */
  143
+    struct sockaddr_in6* mask = &in6_addreq.ifra_prefixmask;
  144
+    u_char *cp;
  145
+
  146
+    int len = prefixLen;
  147
+    mask->sin6_len = sizeof(*mask);
  148
+    if ((prefixLen == 0) || (prefixLen == 128)) {
  149
+        memset(&mask->sin6_addr, 0xff, sizeof(struct in6_addr));
  150
+    } else {
  151
+        memset((void *)&mask->sin6_addr, 0x00, sizeof(mask->sin6_addr));
  152
+        for (cp = (u_char *)&mask->sin6_addr; len > 7; len -= 8) {
  153
+            *cp++ = 0xff;
  154
+        }
  155
+        *cp = 0xff << (8 - len);
  156
+    }
  157
+
  158
+    strncpy(in6_addreq.ifra_name, interfaceName, sizeof(in6_addreq.ifra_name));
  159
+
  160
+    /* do the actual assignment ioctl */
  161
+    int s = socket(AF_INET6, SOCK_DGRAM, 0);
  162
+    if (s < 0) {
  163
+        Except_raise(eh,
  164
+                     TUNConfigurator_setIpAddress_INTERNAL,
  165
+                     "socket() failed [%s]",
  166
+                     strerror(errno));
  167
+    }
  168
+
  169
+    if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
  170
+        int err = errno;
  171
+        close(s);
  172
+        Except_raise(eh,
  173
+                     TUNConfigurator_setIpAddress_INTERNAL,
  174
+                     "ioctl(SIOCAIFADDR) failed [%s]",
  175
+                     strerror(err));
  176
+    }
  177
+
  178
+    Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);
  179
+
  180
+    close(s);
  181
+}
  182
+
  183
+void TUNConfigurator_setMTU(const char* interfaceName,
  184
+                            uint32_t mtu,
  185
+                            struct Log* logger,
  186
+                            struct Except* eh)
  187
+{
  188
+    int s = socket(AF_INET6, SOCK_DGRAM, 0);
  189
+
  190
+    if (s < 0) {
  191
+        Except_raise(eh,
  192
+                     TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET,
  193
+                     "socket() failed [%s]",
  194
+                     strerror(errno));
  195
+    }
  196
+
  197
+
  198
+    struct ifreq ifRequest;
  199
+
  200
+    strncpy(ifRequest.ifr_name, interfaceName, IFNAMSIZ);
  201
+    ifRequest.ifr_mtu = mtu;
  202
+
  203
+    Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);
  204
+
  205
+    if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
  206
+       int err = errno;
  207
+       close(s);
  208
+       Except_raise(eh,
  209
+                    TUNConfigurator_setMTU_INTERNAL,
  210
+                    "ioctl(SIOCSIFMTU) failed [%s]",
  211
+                    strerror(err));
  212
+    }
  213
+}
2  interface/TUNInterface.c
@@ -26,7 +26,7 @@
26 26
 #include <unistd.h>
27 27
 #include <errno.h>
28 28
 
29  
-#if defined(__APPLE__) || defined(Illumos)
  29
+#if defined(__APPLE__) || defined(Illumos) || defined(FreeBSD)
30 30
     #include <netinet/if_ether.h>
31 31
     #define INET6_ETHERTYPE PF_INET6
32 32
 #else

0 notes on commit c32f1bf

Please sign in to comment.
Something went wrong with that request. Please try again.