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
+
+};
+
+