diff --git a/docs/gnb_config_manual_cn.md b/docs/gnb_config_manual_cn.md index 7909b6b..e5907a8 100644 --- a/docs/gnb_config_manual_cn.md +++ b/docs/gnb_config_manual_cn.md @@ -226,6 +226,7 @@ forward节点可以为无法直接互访的GNB节点中转ip分组,这些节 |-t, --selftest|self test| |-p, --passcode|a hexadecimal string of 32-bit unsigned integer, use to strengthen safety| |-l, --listen|listen address default is '0.0.0.0:9001'| +|-b, --ctl-block|ctl block mapper file| |-e, --es-argv|pass-through gnb_es argv| |--node-woker-queue-length|node woker queue length| |--index-woker-queue-length|index woker queue length| diff --git a/src/Darwin/gnb_drv_darwin.c b/src/Darwin/gnb_drv_darwin.c new file mode 100644 index 0000000..8b25764 --- /dev/null +++ b/src/Darwin/gnb_drv_darwin.c @@ -0,0 +1,460 @@ +/* + Copyright (C) gnbdev + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "gnb.h" +#include "gnb_tun_drv.h" +#include "gnb_payload16.h" + + +void bind_socket_if(gnb_core_t *gnb_core){ + + if ( '\0' == gnb_core->conf->socket_ifname[0] ) { + return; + } + + int i; + + for ( i=0; i < gnb_core->conf->udp6_socket_num; i++ ) { + setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); + } + + for ( i=0; i < gnb_core->conf->udp4_socket_num; i++ ) { + setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); + } + +} + +static void if_up_script(gnb_core_t *gnb_core){ + + int ret; + + char cmd[1024]; + + snprintf(cmd,1024,"%s/script/%s > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_darwin.sh"); + + ret = system(cmd); + + if ( -1==ret || 0 ==ret ) { + return; + } + + return; + +} + +static void if_down_script(gnb_core_t *gnb_core){ + + int ret; + + char cmd[1024]; + + snprintf(cmd,1024,"%s/script/%s > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_darwin.sh"); + + ret = system(cmd); + + if ( -1==ret || 0 ==ret ) { + return; + } + + return; + +} + + +/* + set_route4的作用是 创建一条路由,以 tun ip 为 10.1.0.15 的local node为例: + route -n add -net 10.1.0.0 -netmask 255.255.255.0 10.1.0.15 + */ +static void set_route4(gnb_core_t *gnb_core){ + + struct{ + struct rt_msghdr hdr; + struct sockaddr_in dst; + struct sockaddr_in gateway; + struct sockaddr_in mask; + }rtmsg; + + uint32_t network_u32; + + int s; + + ssize_t wlen; + + //算出 节点的 ipv4 network + network_u32 = gnb_core->local_node->tun_netmask_addr4.s_addr & gnb_core->local_node->tun_addr4.s_addr; + + s = socket(PF_ROUTE, SOCK_RAW, 0); + + if ( s < 0 ) { + printf("error: socket\n"); + return; + } + + shutdown(s, SHUT_RD); + + bzero(&rtmsg, sizeof(rtmsg)); + + rtmsg.hdr.rtm_type = RTM_ADD; + rtmsg.hdr.rtm_version = RTM_VERSION; + + rtmsg.hdr.rtm_addrs = 0; + + rtmsg.hdr.rtm_addrs |= RTA_DST; + rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; + rtmsg.hdr.rtm_addrs |= RTA_NETMASK; + + + rtmsg.hdr.rtm_flags = RTF_STATIC; + rtmsg.hdr.rtm_flags |= RTF_GATEWAY; + rtmsg.hdr.rtm_flags |= RTF_GATEWAY; + + rtmsg.dst.sin_len = sizeof(rtmsg.dst); + rtmsg.dst.sin_family = AF_INET; + rtmsg.dst.sin_addr.s_addr = network_u32; + + rtmsg.mask.sin_len = sizeof(rtmsg.mask); + rtmsg.mask.sin_family = AF_INET; + rtmsg.mask.sin_addr.s_addr = gnb_core->local_node->tun_netmask_addr4.s_addr; + + rtmsg.gateway.sin_len = sizeof(rtmsg.gateway); + rtmsg.gateway.sin_family = AF_INET; + rtmsg.gateway.sin_addr.s_addr = gnb_core->local_node->tun_addr4.s_addr; + + rtmsg.hdr.rtm_msglen = sizeof(rtmsg); + + wlen = write(s, &rtmsg, sizeof(rtmsg)); + + if ( -1==wlen ){ + perror("#set_route4 write"); + return; + } + + return; + +} + +static int set_addr6(char *if_name, char *ip, char *netmask) { + + //不要设置 in6_addreq.ifra_dstaddr 成员, ioctl 会提示参数不正确 + struct in6_aliasreq in6_addreq = { + { 0 }, + { 0 }, + { 0 }, + { 0 }, + 0, + { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } + }; + + struct addrinfo *srcres, *netmaskres; + + struct addrinfo hints; + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + + getaddrinfo(ip, NULL, &hints, &srcres); + + getaddrinfo(netmask, NULL, &hints, &netmaskres); + + strncpy(in6_addreq.ifra_name, if_name, IFNAMSIZ); + + memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); + memcpy(&in6_addreq.ifra_prefixmask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); + + freeaddrinfo(srcres); + freeaddrinfo(netmaskres); + + int socket_fd; + + if ( (socket_fd = socket(AF_INET6, SOCK_DGRAM, 0) ) < 0) { + perror("socket "); + return -1; + } + + int ret = ioctl(socket_fd, SIOCAIFADDR_IN6, &in6_addreq); + + if ( -1 == ret ) { + perror("ioctl"); + } + + close(socket_fd); + + return ret; +} + + +static int tun_alloc(char *dev) { + + int fd; + + struct ctl_info ctlInfo; + + strncpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)); + + fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + + if ( fd < 0 ) { + perror("socket"); + return fd; + } + + struct sockaddr_ctl sc; + + if ( ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1 ) { + close(fd); + perror("ioctl"); + return -1; + } + + sc.sc_id = ctlInfo.ctl_id; + sc.sc_len = sizeof(sc); + sc.sc_family = AF_SYSTEM; + sc.ss_sysaddr = AF_SYS_CONTROL; + + //sc.sc_unit = 1; // faile + //sc.sc_unit = 10; // ok + sc.sc_unit = 0; // ok + + if ( connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0 ) { + perror("connect"); + close(fd); + return -1; + } + + return fd; + +} + + +int init_tun_darwin(gnb_core_t *gnb_core){ + + gnb_core->tun_fd = -1; + + return 0; + +} + + +static void setifmtu(char *if_name,int mtu) { + + int socket_fd; + + struct ifreq ifr; + + memset(&ifr,0,sizeof(struct ifreq)); + + strncpy(ifr.ifr_name, if_name, IFNAMSIZ); + + ifr.ifr_mtu = mtu; + + if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { + perror("socket "); + + } + + int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); + + if ( -1 == ret ) { + perror("ioctl"); + } + + close(socket_fd); +} + + +static int set_addr4(char *if_name, char *ip, char *netmask) { + + struct addrinfo *srcres, *dstres, *netmaskres; + + struct ifaliasreq in_addreq; + + memset(&in_addreq, 0, sizeof(in_addreq)); + + getaddrinfo(ip, NULL, NULL, &srcres); + getaddrinfo(ip, NULL, NULL, &dstres); + getaddrinfo(netmask, NULL, NULL, &netmaskres); + + + strncpy(in_addreq.ifra_name, if_name, IFNAMSIZ); + memcpy(&in_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); + memcpy(&in_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); + memcpy(&in_addreq.ifra_mask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); + + freeaddrinfo(srcres); + freeaddrinfo(dstres); + freeaddrinfo(netmaskres); + + int socket_fd; + + if((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket "); + return -1; + } + + int ret = ioctl(socket_fd, SIOCAIFADDR, &in_addreq); + + if ( -1 == ret ) { + perror("ioctl"); + } + + return 0; +} + + +static int open_tun_darwin(gnb_core_t *gnb_core){ + + if ( -1 != gnb_core->tun_fd ) { + return -1; + } + + gnb_core->tun_fd = tun_alloc(gnb_core->ifname); + + memset(gnb_core->ifname,0,IFNAMSIZ); + + socklen_t ifname_len = IFNAMSIZ; + + getsockopt (gnb_core->tun_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gnb_core->ifname, &ifname_len); + + set_addr4(gnb_core->ifname, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR_PLAINTEXT2(&gnb_core->local_node->tun_netmask_addr4)); + set_addr6(gnb_core->ifname, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); + set_route4(gnb_core); + setifmtu(gnb_core->ifname, gnb_core->conf->mtu); + + if_up_script(gnb_core); + + return 0; + +} + + +static int read_tun_darwin(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + ssize_t rlen; + + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if ( 6 == iph->ip_v ) { + type = htonl(AF_INET6); + } else { + type = htonl(AF_INET); + } + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = buf_size; + + rlen = readv(gnb_core->tun_fd, iv, 2); + + if ( -1 == rlen ) { + return rlen; + } + + if ( rlen - sizeof(u_int32_t) <=0 ) { + return -1; + } + + return rlen - sizeof(u_int32_t); + +} + + +static int write_tun_darwin(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if ( 6 == iph->ip_v ) { + type = htonl(AF_INET6); + } else { + type = htonl(AF_INET); + } + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = buf_size; + + writev(gnb_core->tun_fd, iv, 2); + + return 0; +} + + +static int close_tun_darwin(gnb_core_t *gnb_core){ + + if_down_script(gnb_core); + + close(gnb_core->tun_fd); + + return 0; + +} + +static int release_tun_darwin(gnb_core_t *gnb_core){ + + return 0; +} + +gnb_tun_drv_t gnb_tun_drv_darwin = { + + init_tun_darwin, + + open_tun_darwin, + + read_tun_darwin, + + write_tun_darwin, + + close_tun_darwin, + + release_tun_darwin + +}; diff --git a/src/cli/gnb_ctl.c b/src/cli/gnb_ctl.c index 4c12a92..728bb71 100644 --- a/src/cli/gnb_ctl.c +++ b/src/cli/gnb_ctl.c @@ -40,7 +40,11 @@ void gnb_ctl_dump_address_list(gnb_ctl_block_t *ctl_block,int reachabl_opt); static void show_useage(int argc,char *argv[]){ printf("GNB Ctl version 1.0.0 protocol version 1.1.2\n"); - printf("Build[%s %s]\n",__DATE__,__TIME__); + + #ifndef GNB_SKIP_BUILD_TIME + printf("Build[%s %s]\n", __DATE__, __TIME__); + #endif + printf("Copyright (C) 2019 gnbdev\n"); printf("Usage: %s -b CTL_BLOCK [OPTION]\n", argv[0]); printf("Command Summary:\n"); diff --git a/src/cli/gnb_es.c b/src/cli/gnb_es.c index 44744c8..cbf809a 100644 --- a/src/cli/gnb_es.c +++ b/src/cli/gnb_es.c @@ -65,7 +65,11 @@ void gnb_start_environment_service(gnb_es_ctx *es_ctx); static void show_useage(int argc,char *argv[]){ printf("GNB Environment Service version 1.0.0 protocol version 1.1.2\n"); - printf("Build[%s %s]\n",__DATE__,__TIME__); + + #ifndef GNB_SKIP_BUILD_TIME + printf("Build[%s %s]\n", __DATE__, __TIME__); + #endif + printf("Copyright (C) 2019 gnbdev\n"); printf("Usage: %s -b CTL_BLOCK [OPTION]\n", argv[0]); printf("Command Summary:\n"); diff --git a/src/gnb.exe.manifest b/src/gnb.exe.manifest new file mode 100644 index 0000000..2635b76 --- /dev/null +++ b/src/gnb.exe.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/gnb_argv.c b/src/gnb_argv.c index 1cb3279..8bdfb60 100644 --- a/src/gnb_argv.c +++ b/src/gnb_argv.c @@ -899,12 +899,16 @@ gnb_conf_t* gnb_argv(int argc,char *argv[]){ static void show_version_buildtime(){ printf("GNB version 1.2.8.1 protocol version 1.1.2\n"); - printf("Build[%s %s]\n",__DATE__,__TIME__); + + #ifndef GNB_SKIP_BUILD_TIME + printf("Build[%s %s]\n", __DATE__, __TIME__); + #endif + printf("Copyright (C) 2019 gnbdev\n"); int idx = 0; - printf("registed packet filter:"); + printf("registered packet filter:"); while ( NULL != gnb_pf_mods[idx] ) { printf(" %s",gnb_pf_mods[idx]->name); diff --git a/src/gnb_crypto.c b/src/gnb_crypto.c index 3a50255..192b093 100644 --- a/src/gnb_crypto.c +++ b/src/gnb_crypto.c @@ -70,7 +70,6 @@ static void create_keypair(uint32_t uuid32, const char *private_key_file, const close(public_file_fd); - gnb_bin2hex(ed25519_private_key, 64, hex_string); private_file_fd = open(private_key_file, O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); @@ -139,7 +138,12 @@ int main (int argc,char *argv[]){ } - if ( NULL==cmd || NULL==private_key_file || NULL==public_key_file ){ + if ( NULL==cmd || NULL==private_key_file || NULL==public_key_file ) { + + #ifndef GNB_SKIP_BUILD_TIME + printf("Build[%s %s]\n", __DATE__, __TIME__); + #endif + printf("usage: %s -c -p private_key_file -k public_key_file\n",argv[0]); exit(0); } @@ -150,10 +154,8 @@ int main (int argc,char *argv[]){ } - /* ./gnb_crypto -c -p 1010.private -k 1010.public */ - diff --git a/src/gnb_res.rc b/src/gnb_res.rc new file mode 100644 index 0000000..b5f60b8 --- /dev/null +++ b/src/gnb_res.rc @@ -0,0 +1,2 @@ +1 24 "gnb.exe.manifest" + diff --git a/src/mingw/gnb_drv_win32.c b/src/mingw/gnb_drv_win32.c new file mode 100644 index 0000000..9b7cb87 --- /dev/null +++ b/src/mingw/gnb_drv_win32.c @@ -0,0 +1,653 @@ +/* + Copyright (C) gnbdev + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 + +#include +#include + +#include +#include + +#include + +#include "tap-windows/tap-windows.h" + +#include "gnb.h" +#include "gnb_exec.h" +#include "gnb_tun_drv.h" +#include "gnb_payload16.h" + + +typedef struct _gnb_core_win_ctx_t{ + + char tap_file_name[PATH_MAX]; + + char if_name[PATH_MAX]; + + char deviceid[PATH_MAX]; + + ULONG tun_if_id; + + HANDLE device_handle; + + OVERLAPPED read_olpd; + OVERLAPPED write_olpd; + + int skip_if_script; + +}gnb_core_win_ctx_t; + + +static int close_tun_win32(gnb_core_t *gnb_core); +static int open_tun_win32(gnb_core_t *gnb_core); + + +#define MAX_KEY_LENGTH 255 + +/* {xxxxxxxxxxxx} 形式的字符串 */ +static char *get_if_deviceid() { + + HKEY adapters, adapter; + DWORD i, ret, len; + char *deviceid = NULL; + DWORD sub_keys = 0; + + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(ADAPTER_KEY), 0, KEY_READ, &adapters); + + if (ret != ERROR_SUCCESS) { + return NULL; + } + + ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (ret != ERROR_SUCCESS) { + return NULL; + } + + if (sub_keys <= 0) { + return NULL; + } + + /* Walk througt all adapters */ + for (i = 0; i < sub_keys; i++) { + char new_key[MAX_KEY_LENGTH]; + char data[256]; + TCHAR key[MAX_KEY_LENGTH]; + DWORD keylen = MAX_KEY_LENGTH; + + /* Get the adapter key name */ + ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL); + if (ret != ERROR_SUCCESS) { + continue; + } + + /* Append it to NETWORK_ADAPTERS and open it */ + snprintf(new_key, sizeof(new_key), "%s\\%s", ADAPTER_KEY, key); + + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter); + if (ret != ERROR_SUCCESS) { + continue; + } + + len = sizeof(data); + ret = RegQueryValueEx(adapter, "DriverDesc", NULL, NULL, (LPBYTE)data, &len); + if (ret != ERROR_SUCCESS) { + goto clean; + } + + if (strncmp(data, "TAP-Windows", sizeof("TAP-Windows")-1) == 0) { + + DWORD type; + + len = sizeof(data); + ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type, (LPBYTE)data, &len); + if (ret != ERROR_SUCCESS) { + goto clean; + } + deviceid = strdup(data); + break; + } + +clean: + RegCloseKey(adapter); + } + + RegCloseKey(adapters); + + return deviceid; + +} + +/* 网络连接的名字 */ +static char* get_if_devicename(const char *if_deviceid){ + + HKEY key; + DWORD ret; + + char regpath[MAX_KEY_LENGTH]; + + char devicename[PATH_MAX]; + long name_len = PATH_MAX; + + snprintf(regpath, MAX_KEY_LENGTH, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, if_deviceid); + + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(regpath), 0, KEY_READ, &key); + + if (ret != ERROR_SUCCESS) { + RegCloseKey(key); + return NULL; + } + + ret = RegQueryValueEx(key, "Name", 0, 0, devicename, &name_len); + + if (ret != ERROR_SUCCESS) { + RegCloseKey(key); + return NULL; + } + + RegCloseKey(key); + + return strdup(devicename); +} + + +int init_tun_win32(gnb_core_t *gnb_core){ + + char *deviceid; + + char *devicename; + + gnb_core_win_ctx_t *tun_win_ctx = (gnb_core_win_ctx_t *)malloc(sizeof(gnb_core_win_ctx_t)); + + tun_win_ctx->skip_if_script = 0; + + tun_win_ctx->device_handle = INVALID_HANDLE_VALUE; + + gnb_core->platform_ctx = tun_win_ctx; + + deviceid = get_if_deviceid(); + + if ( NULL==deviceid ) { + return -1; + } + + snprintf(tun_win_ctx->deviceid, PATH_MAX, "%s", deviceid); + + snprintf(tun_win_ctx->tap_file_name, PATH_MAX, "%s%s%s", USERMODEDEVICEDIR, deviceid, TAP_WIN_SUFFIX); + + devicename = get_if_devicename(deviceid); + + if ( NULL != devicename ){ + snprintf(tun_win_ctx->if_name, PATH_MAX, "%s", devicename); + free(devicename); + } + + free(deviceid); + + if ( tun_win_ctx->if_name && 0 != strncmp(gnb_core->ifname,tun_win_ctx->if_name,256) ){ + snprintf(gnb_core->ifname, 256, "%s", tun_win_ctx->if_name); + } + + snprintf(gnb_core->if_device_string, 256, "%s", deviceid); + + return 0; + +} + + +#define WORKING_BUFFER_SIZE 15000 +#define MAX_TRIES 3 +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +/* 网络接口id */ +static ULONG get_if_id(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + ULONG family = AF_UNSPEC; //AF_INET AF_INET6 AF_UNSPEC + + DWORD dwRetVal = 0; + ULONG outBufLen = 0; + ULONG Iterations = 0; + + ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_INCLUDE_GATEWAYS; + + outBufLen = WORKING_BUFFER_SIZE; + + PIP_ADAPTER_ADDRESSES pAddresses = NULL; + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; + + struct sockaddr_in *sa_in; + struct sockaddr_in6 *sa_in6; + + do { + + pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); + + if (pAddresses == NULL) { + GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); + exit(1); + } + + dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); + + if (dwRetVal == ERROR_BUFFER_OVERFLOW) { + FREE(pAddresses); + pAddresses = NULL; + } else { + break; + } + + Iterations++; + + } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES)); + + if (dwRetVal != NO_ERROR) { + return 0l; + } + + pCurrAddresses = pAddresses; + + char friendlyname_string[256]; + char description_string[256]; + + char ipv4_string[INET_ADDRSTRLEN]; + char ipv6_string[INET6_ADDRSTRLEN]; + + tun_win_ctx->tun_if_id = -1; + + while (pCurrAddresses) { + + if(IfOperStatusUp != pCurrAddresses->OperStatus){ + goto next; + } + + WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->Description,-1,description_string,256,NULL,NULL); + WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pCurrAddresses->FriendlyName,-1,friendlyname_string,256,NULL,NULL); + + if ( 0==strncmp( description_string,"TAP-Windows Adapter V9", sizeof("TAP-Windows Adapter V9")-1 ) ){ + + //需要比较 pCurrAddresses->AdapterName 找出真正的 tun_if_id + if ( !strncmp(pCurrAddresses->AdapterName, tun_win_ctx->deviceid, PATH_MAX) ){ + return pCurrAddresses->IfIndex; + } + + goto next; + } + +next: + + pCurrAddresses = pCurrAddresses->Next; + + } + + FREE(pAddresses); + + return 0l; + +} + + + +static void if_up(gnb_core_t *gnb_core){ + + char bin_path[PATH_MAX+NAME_MAX]; + char bin_path_q[PATH_MAX+NAME_MAX]; + char map_path_q[PATH_MAX+NAME_MAX]; + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + strncpy(gnb_core->ctl_block->conf_zone->conf_st.ifname, tun_win_ctx->if_name, NAME_MAX); + + snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); + snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); + snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); + + gnb_arg_list_t *arg_list; + arg_list = gnb_arg_list_init(32); + + gnb_arg_append(arg_list, bin_path_q); + + gnb_arg_append(arg_list, "-b"); + gnb_arg_append(arg_list, map_path_q); + + gnb_arg_append(arg_list, "--if-up"); + + gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); + + gnb_arg_list_release(arg_list); + +} + + +static void if_down(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + char bin_path[PATH_MAX+NAME_MAX]; + char bin_path_q[PATH_MAX+NAME_MAX]; + char map_path_q[PATH_MAX+NAME_MAX]; + + snprintf(bin_path, PATH_MAX+NAME_MAX, "%s\\gnb_es.exe", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); + snprintf(bin_path_q, PATH_MAX+NAME_MAX, "\"%s\\gnb_es.exe\"", gnb_core->ctl_block->conf_zone->conf_st.binary_dir); + snprintf(map_path_q, PATH_MAX+NAME_MAX, "\"%s\"", gnb_core->ctl_block->conf_zone->conf_st.map_file); + + gnb_arg_list_t *arg_list; + arg_list = gnb_arg_list_init(32); + + gnb_arg_append(arg_list, bin_path_q); + + gnb_arg_append(arg_list, "-b"); + gnb_arg_append(arg_list, map_path_q); + + gnb_arg_append(arg_list, "--if-down"); + + gnb_exec(bin_path, gnb_core->ctl_block->conf_zone->conf_st.binary_dir, arg_list, GNB_EXEC_BACKGROUND|GNB_EXEC_WAIT); + + gnb_arg_list_release(arg_list); + +} + + +static int ntod(uint32_t mask) { + int i, n = 0; + int bits = sizeof(uint32_t) * 8; + for(i = bits - 1; i >= 0; i--) { + if (mask & (0x01 << i)) + n++; + } + return n; +} + + +static int set_addr4(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + DWORD dwRetVal = 0; + + DWORD dwSize = 0; + unsigned long status = 0; + + DWORD lastError = 0; + SOCKADDR_IN localAddress; + + MIB_UNICASTIPADDRESS_ROW ipRow; + + InitializeUnicastIpAddressEntry( &ipRow ); + + ipRow.InterfaceIndex = tun_win_ctx->tun_if_id; + + ipRow.Address.si_family = AF_INET; + + ipRow.OnLinkPrefixLength = (UINT8)ntod( gnb_core->local_node->tun_netmask_addr4.s_addr ); + + InetPton(AF_INET, GNB_ADDR4STR_PLAINTEXT1(&gnb_core->local_node->tun_addr4), &ipRow.Address.Ipv4.sin_addr); + + status = DeleteUnicastIpAddressEntry(&ipRow); + + status = CreateUnicastIpAddressEntry(&ipRow); + + return 0; + +} + + +static int set_addr6(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + DWORD dwRetVal = 0; + + DWORD dwSize = 0; + unsigned long status = 0; + + DWORD lastError = 0; + SOCKADDR_IN localAddress; + + MIB_UNICASTIPADDRESS_ROW ipRow; + + InitializeUnicastIpAddressEntry( &ipRow ); + + ipRow.InterfaceIndex = tun_win_ctx->tun_if_id; + + ipRow.Address.si_family = AF_INET6; + ipRow.OnLinkPrefixLength = 96; + + InetPton(AF_INET6, GNB_ADDR6STR_PLAINTEXT1(&gnb_core->local_node->tun_ipv6_addr), &ipRow.Address.Ipv6.sin6_addr); + + status = DeleteUnicastIpAddressEntry(&ipRow); + + status = CreateUnicastIpAddressEntry(&ipRow); + + return 0; + +} + + +static int open_tun_win32(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + int ret; + + if ( INVALID_HANDLE_VALUE != tun_win_ctx->device_handle ){ + return -1; + } + + tun_win_ctx->device_handle = CreateFile(tun_win_ctx->tap_file_name, GENERIC_WRITE|GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, 0); + + if ( INVALID_HANDLE_VALUE == tun_win_ctx->device_handle ){ + return -2; + } + + ULONG data[4]; + DWORD len; + + data[0] = 1; + ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, data, sizeof(data), data, sizeof(data), &len, NULL); + + if ( ret == 0 ){ + //GetLastError(); + return -4; + } + + if ( data[0]>0 ){ + GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Device[%s] up succeed\n", tun_win_ctx->tap_file_name); + } + + tun_win_ctx->read_olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + tun_win_ctx->write_olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + tun_win_ctx->tun_if_id = get_if_id(gnb_core); + + gnb_core->ctl_block->core_zone->tun_if_id = tun_win_ctx->tun_if_id; + + + int netmask = gnb_core->local_node->tun_netmask_addr4.s_addr; + data[0] = gnb_core->local_node->tun_addr4.s_addr; + data[1] = data[0] & netmask; + data[2] = netmask; + + ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_CONFIG_TUN, &data, sizeof(data), &data, sizeof(data), &len, NULL); + + if ( 0==ret ){ + return -5; + } + + if ( tun_win_ctx->tun_if_id > 0 ){ + set_addr4(gnb_core); + set_addr6(gnb_core); + + } + + if ( !tun_win_ctx->skip_if_script ){ + if_up(gnb_core); + } + + return 0; + +} + + +static int read_tun_win32(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + int res; + + DWORD frame_size = 0; + + res = ReadFile(tun_win_ctx->device_handle, buf, buf_size, &frame_size, &tun_win_ctx->read_olpd); + + if (!res) { + + res = WaitForSingleObject(tun_win_ctx->read_olpd.hEvent, INFINITE); + //res = WaitForSingleObject(tun_win_ctx->read_olpd.hEvent, 100); + + if ( WAIT_TIMEOUT == res ){ + frame_size = -1; + goto finish; + } + + res = GetOverlappedResult(tun_win_ctx->device_handle, &tun_win_ctx->read_olpd, (LPDWORD) &frame_size, FALSE); + + if ( frame_size<=0 ) { + + tun_win_ctx->skip_if_script = 0; + + close_tun_win32(gnb_core); + + open_tun_win32(gnb_core); + + tun_win_ctx->skip_if_script = 1; + + GNB_ERROR3(gnb_core->log,GNB_LOG_ID_CORE,"read_tun_win32 ERROR frame_size=%d\n", frame_size); + + goto finish; + + } + + }else{ + + goto finish; + + } + +finish: + + return frame_size; + +} + + +static int write_tun_win32(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + DWORD written; + + int res; + + res = WriteFile(tun_win_ctx->device_handle, buf, buf_size, &written, &tun_win_ctx->write_olpd); + + if (!res && GetLastError() == ERROR_IO_PENDING) { + + WaitForSingleObject(tun_win_ctx->write_olpd.hEvent, INFINITE); + + res = GetOverlappedResult(tun_win_ctx->device_handle, &tun_win_ctx->write_olpd, &written, FALSE); + + if ( written != buf_size ) { + GNB_ERROR3(gnb_core->log, GNB_LOG_ID_CORE, "write_tun_win32 ERROR buf_size=%d written=%d\n", buf_size,written); + return -1; + } + + } + + return 0; + +} + + +static int close_tun_win32(gnb_core_t *gnb_core){ + + gnb_core_win_ctx_t *tun_win_ctx = gnb_core->platform_ctx; + + if (INVALID_HANDLE_VALUE==tun_win_ctx->device_handle){ + GNB_ERROR3(gnb_core->log, GNB_LOG_ID_CORE,"if[%s] aready closeed\n", gnb_core->ifname); + return 0; + } + + int ret; + + unsigned long status = 0l; + + DWORD len; + + ret = DeviceIoControl(tun_win_ctx->device_handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL); + + if ( ret == 0 ){ + //GetLastError(); + return -1; + } + + if ( status>0 ){ + GNB_LOG3(gnb_core->log, GNB_LOG_ID_CORE, "Device[%s] down succeed\n",tun_win_ctx->tap_file_name); + } + + CloseHandle(tun_win_ctx->device_handle); + + tun_win_ctx->device_handle = INVALID_HANDLE_VALUE; + + if ( !tun_win_ctx->skip_if_script ){ + if_down(gnb_core); + } + + return 0; + +} + +static int release_tun_win32(gnb_core_t *gnb_core){ + + free(gnb_core->platform_ctx); + + return 0; +} + +gnb_tun_drv_t gnb_tun_drv_win32 = { + + init_tun_win32, + + open_tun_win32, + + read_tun_win32, + + write_tun_win32, + + close_tun_win32, + + release_tun_win32 + +}; + diff --git a/src/mingw/windows_platform.c b/src/mingw/windows_platform.c new file mode 100644 index 0000000..58b104a --- /dev/null +++ b/src/mingw/windows_platform.c @@ -0,0 +1,122 @@ +/* + Copyright (C) gnbdev + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include + +#include "gnb_exec.h" +#include "gnb_arg_list.h" + + +int gnb_get_pid(){ + int pid; + pid = GetCurrentProcessId(); + return pid; +} + + +void gnb_set_env(const char *name, const char *value){ + + _putenv_s(name, value); + +} + + +int gnb_exec(char *app_filename, char *current_path, gnb_arg_list_t *gnb_arg_list, int flag){ + + int rc; + + wchar_t app_filename_w[PATH_MAX+NAME_MAX]; + wchar_t gnb_arg_string_w[PATH_MAX+NAME_MAX]; + wchar_t current_path_w[PATH_MAX+NAME_MAX]; + + STARTUPINFOW si; + PROCESS_INFORMATION pi = {0}; + DWORD creation_flags; + + ZeroMemory(&si,sizeof(si)); + + si.cb = sizeof(si); + + char gnb_arg_string[GNB_ARG_STRING_MAX_SIZE]; + + rc = gnb_arg_list_to_string(gnb_arg_list, gnb_arg_string, GNB_ARG_STRING_MAX_SIZE); + + if ( flag & GNB_EXEC_BACKGROUND ) { + + si.wShowWindow = SW_HIDE; + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + creation_flags = CREATE_NO_WINDOW; + + } else { + + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_SHOW; + creation_flags = CREATE_NEW_CONSOLE; + } + + memset(app_filename_w, 0, PATH_MAX+NAME_MAX); + MultiByteToWideChar(CP_ACP, 0, app_filename, -1, app_filename_w, PATH_MAX+NAME_MAX); + + memset(current_path_w, 0, PATH_MAX+NAME_MAX); + MultiByteToWideChar(CP_ACP, 0, current_path, -1, current_path_w, PATH_MAX+NAME_MAX); + + memset(gnb_arg_string_w, 0, PATH_MAX+NAME_MAX); + MultiByteToWideChar(CP_ACP, 0, gnb_arg_string, -1, gnb_arg_string_w, PATH_MAX+NAME_MAX); + + rc = CreateProcessW(app_filename_w, gnb_arg_string_w, NULL,NULL,TRUE, creation_flags, NULL, current_path_w, &si,&pi); + + if ( !rc ) { + return -1; + } + + if ( flag & GNB_EXEC_WAIT ) { + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exitcode; + + rc = GetExitCodeProcess(pi.hProcess, &exitcode); + + } + + if (pi.hProcess) { + CloseHandle(pi.hProcess); + pi.hProcess = NULL; + } + + if (pi.hThread) { + CloseHandle(pi.hThread); + pi.hThread = NULL; + } + + return pi.dwProcessId; + +} + + +int gnb_kill(DWORD pid){ + + HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,FALSE, pid); + + TerminateProcess(hProcess, 0); + + return 0; +} + diff --git a/src/openbsd/gnb_drv_openbsd.c b/src/openbsd/gnb_drv_openbsd.c new file mode 100644 index 0000000..1d7048a --- /dev/null +++ b/src/openbsd/gnb_drv_openbsd.c @@ -0,0 +1,431 @@ +/* + Copyright (C) gnbdev + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include + +#include + +#include "gnb.h" + +#include "gnb_tun_drv.h" + +#include "gnb_payload16.h" + + +void bind_socket_if(gnb_core_t *gnb_core){ + + if( '\0' == gnb_core->conf->socket_ifname[0] ){ + return; + } + + int i; + + for( i=0; i < gnb_core->conf->udp6_socket_num; i++ ){ + setsockopt(gnb_core->udp_ipv6_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); + } + + for( i=0; i < gnb_core->conf->udp4_socket_num; i++ ){ + setsockopt(gnb_core->udp_ipv4_sockets[i], SOL_SOCKET,IP_RECVIF, gnb_core->conf->socket_ifname, strlen(gnb_core->conf->socket_ifname)); + } + +} + + +static void if_up_script(gnb_core_t *gnb_core){ + + int ret; + + char cmd[1024]; + + snprintf(cmd,1024,"\"%s/script/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_up_openbsd.sh"); + + ret = system(cmd); + + if ( -1==ret || 0 ==ret ){ + return; + } + + return; + +} + +static void if_down_script(gnb_core_t *gnb_core){ + + int ret; + + char cmd[1024]; + + snprintf(cmd,1024,"\"%s/script/%s\" > /dev/null 2>&1",gnb_core->conf->conf_dir,"if_down_openbsd.sh"); + + ret = system(cmd); + + if ( -1==ret || 0 ==ret ){ + return; + } + + return; + +} + +/* + set_route4的作用是 创建一条路由,以 tun ip 为 10.1.0.15 的local node为例: + route -n add -net 10.1.0.0 -netmask 255.255.255.0 10.1.0.15 + */ +static void set_route4(gnb_core_t *gnb_core){ + + struct{ + struct rt_msghdr hdr; + struct sockaddr_in dst; + struct sockaddr_in gateway; + struct sockaddr_in mask; + }rtmsg; + + uint32_t network_u32; + + int s; + + ssize_t wlen; + + //算出 节点的 ipv4 network + network_u32 = gnb_core->local_node->tun_netmask_addr4.s_addr & gnb_core->local_node->tun_addr4.s_addr; + + s = socket(PF_ROUTE, SOCK_RAW, 0); + + if (s < 0) { + perror("socket\n"); + return; + } + + shutdown(s, SHUT_RD); + + bzero(&rtmsg, sizeof(rtmsg)); + + rtmsg.hdr.rtm_type = RTM_ADD; + rtmsg.hdr.rtm_version = RTM_VERSION; + + rtmsg.hdr.rtm_addrs = 0; + + rtmsg.hdr.rtm_addrs |= RTA_DST; + rtmsg.hdr.rtm_addrs |= RTA_GATEWAY; + rtmsg.hdr.rtm_addrs |= RTA_NETMASK; + + + rtmsg.hdr.rtm_flags = RTF_STATIC; + rtmsg.hdr.rtm_flags |= RTF_GATEWAY; + rtmsg.hdr.rtm_flags |= RTF_GATEWAY; + + rtmsg.dst.sin_len = sizeof(rtmsg.dst); + rtmsg.dst.sin_family = AF_INET; + rtmsg.dst.sin_addr.s_addr = network_u32; + + rtmsg.mask.sin_len = sizeof(rtmsg.mask); + rtmsg.mask.sin_family = AF_INET; + rtmsg.mask.sin_addr.s_addr = gnb_core->local_node->tun_netmask_addr4.s_addr; + + + rtmsg.gateway.sin_len = sizeof(rtmsg.gateway); + rtmsg.gateway.sin_family = AF_INET; + rtmsg.gateway.sin_addr.s_addr = gnb_core->local_node->tun_addr4.s_addr; + + rtmsg.hdr.rtm_msglen = sizeof(rtmsg); + + wlen = write(s, &rtmsg, sizeof(rtmsg)); + + if ( -1==wlen ){ + perror("#set_route4 write"); + return; + } + + return; + +} + +static void setifmtu(char *if_name,int mtu) { + + int socket_fd; + + struct ifreq ifr; + + memset(&ifr,0,sizeof(struct ifreq)); + + strncpy(ifr.ifr_name, if_name, IFNAMSIZ); + + ifr.ifr_mtu = mtu; + + if((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket "); + + } + + int ret = ioctl(socket_fd, SIOCSIFMTU, &ifr); + + if (-1==ret) { + perror("ioctl"); + } + + close(socket_fd); +} + +static int set_addr4(char *if_name, char *ip, char *netmask) { + + struct addrinfo *srcres, *dstres, *netmaskres; + + struct ifaliasreq in_addreq; + + memset(&in_addreq, 0, sizeof(in_addreq)); + + getaddrinfo(ip, NULL, NULL, &srcres); + getaddrinfo(ip, NULL, NULL, &dstres); + getaddrinfo(netmask, NULL, NULL, &netmaskres); + + + strncpy(in_addreq.ifra_name, if_name, IFNAMSIZ); + memcpy(&in_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); + memcpy(&in_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); + memcpy(&in_addreq.ifra_mask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); + + freeaddrinfo(srcres); + freeaddrinfo(dstres); + freeaddrinfo(netmaskres); + + int socket_fd; + + if((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("socket "); + return -1; + } + + int ret = ioctl(socket_fd, SIOCAIFADDR, &in_addreq); + + if (-1==ret) { + perror("ioctl"); + } + + return 0; +} + +static int set_addr6(char *if_name, char *ip, char *netmask) { + + //不要设置 in6_addreq.ifra_dstaddr 成员, ioctl 会提示参数不正确 + struct in6_aliasreq in6_addreq = + { { 0 }, + { 0 }, + { 0 }, + { 0 }, + 0, + { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; + + struct addrinfo *srcres, *netmaskres; + + struct addrinfo hints; + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + + getaddrinfo(ip, NULL, &hints, &srcres); + + getaddrinfo(netmask, NULL, &hints, &netmaskres); + + strncpy(in6_addreq.ifra_name, if_name, IFNAMSIZ); + + memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); + memcpy(&in6_addreq.ifra_prefixmask, netmaskres->ai_addr, netmaskres->ai_addr->sa_len); + + freeaddrinfo(srcres); + freeaddrinfo(netmaskres); + + int socket_fd; + + if((socket_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + perror("socket "); + return -1; + } + + int ret = ioctl(socket_fd, SIOCAIFADDR_IN6, &in6_addreq); + + if (-1==ret) { + perror("ioctl"); + } + + close(socket_fd); + + return ret; +} + +int init_tun_openbsd(gnb_core_t *gnb_core){ + + gnb_core->tun_fd = -1; + + return 0; + +} + + +static int open_tun_openbsd(gnb_core_t *gnb_core){ + + if ( -1 != gnb_core->tun_fd ){ + return -1; + } + + char name[PATH_MAX]; + + int t = 0; + + snprintf(name, PATH_MAX, "/dev/%s",gnb_core->ifname); + + gnb_core->tun_fd = open(name, O_RDWR); + + if (-1==gnb_core->tun_fd){ + perror("open"); + exit(1); + } + + int flags; + flags = fcntl(gnb_core->tun_fd, F_GETFD); + flags |= FD_CLOEXEC; + fcntl(gnb_core->tun_fd, F_SETFD, flags); + + set_addr4(gnb_core->ifname, GNB_ADDR4STR1(&gnb_core->local_node->tun_addr4), GNB_ADDR4STR2(&gnb_core->local_node->tun_netmask_addr4)); + set_addr6(gnb_core->ifname, GNB_ADDR6STR1(&gnb_core->local_node->tun_ipv6_addr), "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000"); + set_route4(gnb_core); + setifmtu(gnb_core->ifname, gnb_core->conf->mtu); + if_up_script(gnb_core); + + return 0; + +} + +static int read_tun_openbsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + ssize_t rlen; + + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if(iph->ip_v == 6) + type = htonl(AF_INET6); + else + type = htonl(AF_INET); + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = buf_size; + + rlen = readv(gnb_core->tun_fd, iv, 2); + + if (-1==rlen) { + return rlen; + } + + if ( rlen - sizeof(u_int32_t) <=0 ) { + return -1; + } + + return rlen - sizeof(u_int32_t); + +} + + +static int write_tun_openbsd(gnb_core_t *gnb_core, void *buf, size_t buf_size){ + + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if(iph->ip_v == 6) + type = htonl(AF_INET6); + else + type = htonl(AF_INET); + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = buf_size; + + writev(gnb_core->tun_fd, iv, 2); + return 0; + +} + + +static int close_tun_openbsd(gnb_core_t *gnb_core){ + + if_down_script(gnb_core); + + close(gnb_core->tun_fd); + + return 0; + +} + +static int release_tun_openbsd(gnb_core_t *gnb_core){ + + return 0; +} + + +gnb_tun_drv_t gnb_tun_drv_openbsd = { + + init_tun_openbsd, + + open_tun_openbsd, + + read_tun_openbsd, + + write_tun_openbsd, + + close_tun_openbsd, + + release_tun_openbsd + +}; + +