summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Cohen <bencoh@notk.org>2012-04-23 00:39:22 +0200
committerBenjamin Cohen <bencoh@notk.org>2012-04-23 00:39:22 +0200
commitf24cfe6c89b9943e63927c769024d4e0e146e79e (patch)
tree9beda9f4d8e1ab498edf7bfbe15a193303f2f6a5
parent7339ae0b22820cd29cb59d8cbcab4263a2a16cf0 (diff)
peervpn v0.022 (2012-04-22)v0.022
from http://www.peervpn.net/files/peervpn-0-022.tar.gz http://www.peervpn.net/
-rw-r--r--Makefile5
-rw-r--r--config.ic8
-rw-r--r--console.ic10
-rw-r--r--globals.ic5
-rw-r--r--helpers.ic4
-rw-r--r--init.ic34
-rw-r--r--io.c436
-rw-r--r--libp2psec/peermgt.c2
-rw-r--r--mainloop.ic6
-rw-r--r--peervpn.c11
-rw-r--r--peervpn.conf26
-rw-r--r--platform/ifconfig.c175
-rw-r--r--platform/io.c855
-rw-r--r--platform/tapwin.h73
-rw-r--r--pwd.ic26
15 files changed, 1203 insertions, 473 deletions
diff --git a/Makefile b/Makefile
index c226cb5..abf8563 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,5 @@
-CC=cc
-CFLAGS=-Os
-LDFLAGS=-lcrypto -ldl -lz
+CFLAGS+=-O2
+LDFLAGS+=-lcrypto -ldl -lz
all: peervpn
peervpn: peervpn.o
diff --git a/config.ic b/config.ic
index 304cba9..32862ab 100644
--- a/config.ic
+++ b/config.ic
@@ -123,6 +123,14 @@ static int parseConfigLine(char *line, int len, struct s_initconfig *cs) {
strncpy(cs->tapname,&line[vpos],CONFPARSER_NAMEBUF_SIZE);
return 1;
}
+ else if(parseConfigLineCheckCommand(line,len,"ifconfig4",&vpos)) {
+ strncpy(cs->ifconfig4,&line[vpos],CONFPARSER_NAMEBUF_SIZE);
+ return 1;
+ }
+ else if(parseConfigLineCheckCommand(line,len,"ifconfig6",&vpos)) {
+ strncpy(cs->ifconfig6,&line[vpos],CONFPARSER_NAMEBUF_SIZE);
+ return 1;
+ }
else if(parseConfigLineCheckCommand(line,len,"upcmd",&vpos)) {
strncpy(cs->upcmd,&line[vpos],CONFPARSER_NAMEBUF_SIZE);
return 1;
diff --git a/console.ic b/console.ic
index 0e67ecf..7f24053 100644
--- a/console.ic
+++ b/console.ic
@@ -27,7 +27,7 @@ static void printActivePeerTable() {
// parse command
-static void parseCMD(char *cmd, int cmdlen) {
+static void decodeConsole(char *cmd, int cmdlen) {
char text[4096];
unsigned char new_peeraddr[peeraddr_SIZE];
if(cmd[0] == 'A' || cmd[0] == 'a') {
@@ -59,11 +59,3 @@ static void parseCMD(char *cmd, int cmdlen) {
printActivePeerTable();
}
}
-
-
-// decode console command
-static void decodeConsole() {
- char cmd[COMMAND_BUFSIZE] = {0,0};
- int len = read(STDIN_FILENO, cmd, COMMAND_BUFSIZE);
- if(len > 0) parseCMD(cmd,len);
-}
diff --git a/globals.ic b/globals.ic
index c8d3de5..f9af9e3 100644
--- a/globals.ic
+++ b/globals.ic
@@ -19,12 +19,11 @@
// version information
#define PEERVPN_VERSION_MAJOR 0
-#define PEERVPN_VERSION_MINOR 21
+#define PEERVPN_VERSION_MINOR 22
// compile time options & timing parameters
#define INITPEER_STORAGE 1024
-#define COMMAND_BUFSIZE 1024
#define POLLWAIT 1000
@@ -42,6 +41,8 @@ struct s_initconfig {
char groupstr[CONFPARSER_NAMEBUF_SIZE+1];
char chrootstr[CONFPARSER_NAMEBUF_SIZE+1];
char networkname[CONFPARSER_NAMEBUF_SIZE+1];
+ char ifconfig4[CONFPARSER_NAMEBUF_SIZE+1];
+ char ifconfig6[CONFPARSER_NAMEBUF_SIZE+1];
char upcmd[CONFPARSER_NAMEBUF_SIZE+1];
char initpeers[CONFPARSER_NAMEBUF_SIZE+1];
char engines[CONFPARSER_NAMEBUF_SIZE+1];
diff --git a/helpers.ic b/helpers.ic
index 8e83c76..002c359 100644
--- a/helpers.ic
+++ b/helpers.ic
@@ -18,7 +18,7 @@
// converts a big endian byte array to a hexstring (size of *out must be 2*len+1)
-static void byteArrayToString(char *out, u_int8_t *in, int len) {
+static void byteArrayToString(char *out, unsigned char *in, int len) {
int i;
out[0] = '\0';
for(i=0; i<len; i++) sprintf(&out[i*2], "%02X", in[i]);
@@ -59,7 +59,7 @@ static void connectInitpeers() {
unsigned char new_peeraddr[peeraddr_SIZE];
i=0;j=0;k=0;
for(;;) {
- j = *(u_int8_t *)(&g_initpeers[i]);
+ j = g_initpeers[i];
if((j > 0) && (i+j+1 < INITPEER_STORAGE)) {
if(k) {
port = &g_initpeers[i+1];
diff --git a/init.ic b/init.ic
index 0c77604..b6d74ba 100644
--- a/init.ic
+++ b/init.ic
@@ -61,6 +61,7 @@ int loadengine(const char *engine_name) {
void init(struct s_initconfig *initconfig) {
int c,i,j,k,l,m;
char str[256];
+ char tapname[256];
// initialize signal handler
g_mainloop = 1;
@@ -71,7 +72,7 @@ void init(struct s_initconfig *initconfig) {
// load initpeers
i=0;j=0;k=0;l=0;m=0;
- *(u_int8_t *)(&g_initpeers[0]) = 0;
+ g_initpeers[0] = 0;
for(;;) {
c = initconfig->initpeers[i];
if(m) {
@@ -80,11 +81,11 @@ void init(struct s_initconfig *initconfig) {
m=k-j;
if(m>0) {
if(m > 254) m = 254;
- *(u_int8_t *)(&g_initpeers[l]) = (m+1);
+ g_initpeers[l] = (m+1);
memcpy(&g_initpeers[l+1],&initconfig->initpeers[j],m);
g_initpeers[l+1+m] = '\0';
l = l+2+m;
- *(u_int8_t *)(&g_initpeers[l]) = 0;
+ g_initpeers[l] = 0;
}
m=0;
}
@@ -104,8 +105,12 @@ void init(struct s_initconfig *initconfig) {
// enable console
if(initconfig->enableconsole) {
- g_enableconsole = 1;
- if((fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK)) < 0) throwError("could not initialize console!");
+ if(ioOpenSTDIN(&iostate)) {
+ g_enableconsole = 1;
+ }
+ else {
+ throwError("could not initialize console!");
+ }
}
else {
g_enableconsole = 0;
@@ -139,16 +144,29 @@ void init(struct s_initconfig *initconfig) {
// open tap device
if(initconfig->enableeth) {
printf("opening TAP device...\n");
- if(!ioOpenTap(&iostate, initconfig->tapname)) {
+ if(!ioOpenTap(&iostate, tapname, initconfig->tapname)) {
g_enableeth = 0;
throwError("tap device could not be opened!");
}
else {
g_enableeth = 1;
+ printf(" device \"%s\": ok.\n", tapname);
+ if(strlen(initconfig->ifconfig4) > 0) {
+ // configure IPv4 address
+ if(!(ifconfig4(tapname, strlen(tapname), initconfig->ifconfig4, strlen(initconfig->ifconfig4)))) {
+ logWarning("could not automatically configure IPv4 address!");
+ }
+ }
+ if(strlen(initconfig->ifconfig6) > 0) {
+ // configure IPv6 address
+ if(!(ifconfig6(tapname, strlen(tapname), initconfig->ifconfig6, strlen(initconfig->ifconfig6)))) {
+ logWarning("could not automatically configure IPv6 address!");
+ }
+ }
if(strlen(initconfig->upcmd) > 0) {
// execute shell command
- if((system(initconfig->upcmd)) < 0) {
- throwError("upcmd failed!");
+ if((ifconfigExec(initconfig->upcmd)) < 0) {
+ logWarning("upcmd failed!");
}
}
}
diff --git a/io.c b/io.c
deleted file mode 100644
index 64908df..0000000
--- a/io.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Tobias Volk *
- * mail@tobiasvolk.de *
- * *
- * 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 <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-
-#ifndef F_IO_C
-#define F_IO_C
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <poll.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <net/if.h>
-#include <linux/if_tun.h>
-
-
-// IDs.
-#define IO_FDID_CONSOLE 0
-#define IO_FDID_UDPV4SOCKET 1
-#define IO_FDID_UDPV6SOCKET 2
-#define IO_FDID_TAP 3
-#define IO_FDID_COUNT 4
-
-
-// The IO state structure.
-struct s_io_state {
- struct pollfd fd[IO_FDID_COUNT];
-};
-
-
-// The IPv4 addr/port structure.
-struct s_io_v4addr {
- unsigned char addr[4];
- unsigned char port[2];
-};
-
-
-// The IPv6 addr/port structure.
-struct s_io_v6addr {
- unsigned char addr[16];
- unsigned char port[2];
-};
-
-
-// Opens TAP device. Returns 1 if successful.
-static int ioOpenTap(struct s_io_state *iostate, const char *tapname) {
- struct ifreq ifr;
- char *file = "/dev/net/tun";
- int tapfd = open(file,(O_RDWR | O_NONBLOCK));
-
- if(tapfd < 0) {
- return 0;
- }
-
- memset(&ifr,0,sizeof(ifr));
- ifr.ifr_flags = (IFF_TAP | IFF_NO_PI);
- strncpy(ifr.ifr_name, tapname, sizeof(ifr.ifr_name) - 1);
- if(ioctl(tapfd,TUNSETIFF,(void *)&ifr) < 0) {
- return 0;
- }
-
- iostate->fd[IO_FDID_TAP].fd = tapfd;
- iostate->fd[IO_FDID_TAP].events = POLLIN;
- return 1;
-}
-
-
-// Writes to TAP device. Returns number of bytes written.
-static int ioWriteTap(struct s_io_state *iostate, const unsigned char *buf, const int len) {
- return write(iostate->fd[IO_FDID_TAP].fd, buf, len);
-}
-
-
-// Reads from TAP device. Returns number of bytes read.
-static int ioReadTap(struct s_io_state *iostate, unsigned char *buf, const int len) {
- return read(iostate->fd[IO_FDID_TAP].fd, buf, len);
-}
-
-
-// Opens a socket. Returns 1 if successful.
-static int ioOpenSocket(int *handle, const char *bindaddress, const char *bindport, const int domain, const int type, const int protocol) {
- int ret;
- int fd;
- int one = 1;
- const char *zeroport = "0";
- const char *useport;
- const char *useaddr;
- struct addrinfo *d = NULL;
- struct addrinfo *di;
- struct addrinfo hints;
- if((fd = socket(domain, type, 0)) < 0) return 0;
- if((fcntl(fd,F_SETFL,O_NONBLOCK)) < 0) return 0;
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
- memset(&hints,0,sizeof(struct addrinfo));
- hints.ai_family = domain;
- hints.ai_socktype = type;
- hints.ai_flags = AI_PASSIVE;
- if(bindaddress == NULL) {
- useaddr = NULL;
- }
- else {
- if(strlen(bindaddress) > 0) {
- useaddr = bindaddress;
- }
- else {
- useaddr = NULL;
- }
- }
- if(bindport == NULL) {
- useport = zeroport;
- }
- else {
- useport = bindport;
- }
- if(getaddrinfo(useaddr, useport, &hints, &d) == 0) {
- ret = -1;
- di = d;
- while(di != NULL) {
- if(bind(fd, di->ai_addr, di->ai_addrlen) == 0) {
- ret = fd;
- break;
- }
- di = di->ai_next;
- }
- freeaddrinfo(d);
- if(ret < 0) {
- close(fd);
- return 0;
- }
- *handle = ret;
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-// Get IPv6 UDP address from name. Returns 1 if successful.
-static int ioGetUDPv6Address(struct s_io_v6addr *addr, const char *hostname, const char *port) {
- int ret;
- struct sockaddr_in6 *saddr;
- struct addrinfo *d = NULL;
- struct addrinfo hints;
- if(hostname != NULL && port != NULL) {
- memset(&hints,0,sizeof(struct addrinfo));
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = 0;
- if(getaddrinfo(hostname, port, &hints, &d) == 0) {
- if(d != NULL) {
- saddr = (struct sockaddr_in6 *)d->ai_addr;
- memcpy(addr->addr, saddr->sin6_addr.s6_addr, 16);
- memcpy(addr->port, &saddr->sin6_port, 2);
- ret = 1;
- }
- else {
- ret = 0;
- }
- freeaddrinfo(d);
- }
- else {
- ret = 0;
- }
- return ret;
- }
- else {
- return 0;
- }
-}
-
-
-// Opens an IPv6 UDP socket. Returns 1 if successful.
-static int ioOpenUDPv6Socket(struct s_io_state *iostate, const char *bindaddress, const char *bindport) {
- int fd;
- if(ioOpenSocket(&fd, bindaddress, bindport, AF_INET6, SOCK_DGRAM, 0)) {
- iostate->fd[IO_FDID_UDPV6SOCKET].fd = fd;
- iostate->fd[IO_FDID_UDPV6SOCKET].events = POLLIN;
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-// Sends an IPv6 UDP packet. Returns length of sent message.
-static int ioSendUDPv6Packet(struct s_io_state *iostate, const unsigned char *buf, const int len, struct s_io_v6addr *destination) {
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(struct sockaddr_in6));
- addr.sin6_family = AF_INET6;
- memcpy(addr.sin6_addr.s6_addr, destination->addr, 16);
- memcpy(&addr.sin6_port, destination->port, 2);
- return sendto(iostate->fd[IO_FDID_UDPV6SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6));
-}
-
-
-// Receives an IPv6 UDP packet. Returns length of received message.
-static int ioRecvUDPv6Packet(struct s_io_state *iostate, unsigned char *buf, const int len, struct s_io_v6addr *source) {
- struct sockaddr_in6 addr;
- socklen_t addrlen = sizeof(struct sockaddr_in6);
- int ret = recvfrom(iostate->fd[IO_FDID_UDPV6SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, &addrlen);
- if(ret > 0) {
- memcpy(source->addr, addr.sin6_addr.s6_addr, 16);
- memcpy(source->port, &addr.sin6_port, 2);
- }
- return ret;
-}
-
-
-// Convert UDPv6 address to 24 bit address.
-static void ioConvertAddressFromUDPv6(unsigned char *address, const struct s_io_v6addr *v6addr) {
- memset(address, 0, 24);
- address[0] = 1;
- address[1] = 6;
- address[2] = 1;
- memcpy(&address[4], &v6addr->addr, 16);
- memcpy(&address[20], v6addr->port, 2);
-}
-
-
-// Get IPv4 UDP address from name. Returns 1 if successful.
-static int ioGetUDPv4Address(struct s_io_v4addr *addr, const char *hostname, const char *port) {
- int ret;
- struct sockaddr_in *saddr;
- struct addrinfo *d = NULL;
- struct addrinfo hints;
- if(hostname != NULL && port != NULL) {
- memset(&hints,0,sizeof(struct addrinfo));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = 0;
- if(getaddrinfo(hostname, port, &hints, &d) == 0) {
- if(d != NULL) {
- saddr = (struct sockaddr_in *)d->ai_addr;
- memcpy(addr->addr, &saddr->sin_addr.s_addr, 4);
- memcpy(addr->port, &saddr->sin_port, 2);
- ret = 1;
- }
- else {
- ret = 0;
- }
- freeaddrinfo(d);
- }
- else {
- ret = 0;
- }
- return ret;
- }
- else {
- return 0;
- }
-}
-
-
-// Opens an IPv4 UDP socket. Returns 1 if successful.
-static int ioOpenUDPv4Socket(struct s_io_state *iostate, const char *bindaddress, const char *bindport) {
- int fd;
- if(ioOpenSocket(&fd, bindaddress, bindport, AF_INET, SOCK_DGRAM, 0)) {
- iostate->fd[IO_FDID_UDPV4SOCKET].fd = fd;
- iostate->fd[IO_FDID_UDPV4SOCKET].events = POLLIN;
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-// Sends an IPv4 UDP packet. Returns length of sent message.
-static int ioSendUDPv4Packet(struct s_io_state *iostate, const unsigned char *buf, const int len, const struct s_io_v4addr *destination) {
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(struct sockaddr_in));
- addr.sin_family = AF_INET;
- memcpy(&addr.sin_addr.s_addr, destination->addr, 4);
- memcpy(&addr.sin_port, destination->port, 2);
- return sendto(iostate->fd[IO_FDID_UDPV4SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
-}
-
-
-// Receives an IPv4 UDP packet. Returns length of received message.
-static int ioRecvUDPv4Packet(struct s_io_state *iostate, unsigned char *buf, const int len, struct s_io_v4addr *source) {
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(struct sockaddr_in);
- int ret = recvfrom(iostate->fd[IO_FDID_UDPV4SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, &addrlen);
- if(ret > 0) {
- memcpy(source->addr, &addr.sin_addr.s_addr, 4);
- memcpy(source->port, &addr.sin_port, 2);
- }
- return ret;
-}
-
-
-// Convert UDPv4 address to 24 bit address.
-static void ioConvertAddressFromUDPv4(unsigned char *address, const struct s_io_v4addr *v4addr) {
- memset(address, 0, 24);
- address[0] = 1;
- address[1] = 4;
- address[2] = 1;
- memcpy(&address[4], v4addr->addr, 4);
- memcpy(&address[8], v4addr->port, 2);
-}
-
-
-// Get 24 bit address (UDP over IPv4 or IPv6) from hostname/port. Returns 1 if successful.
-static int ioGetUDPAddress(struct s_io_state *iostate, unsigned char *address, const char *hostname, const char *port) {
- struct s_io_v4addr v4addr;
- struct s_io_v6addr v6addr;
-
- if((!(iostate->fd[IO_FDID_UDPV6SOCKET].fd < 0)) && (ioGetUDPv6Address(&v6addr, hostname, port))) {
- ioConvertAddressFromUDPv6(address, &v6addr);
- return 1;
- }
- if((!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0)) && (ioGetUDPv4Address(&v4addr, hostname, port))) {
- ioConvertAddressFromUDPv4(address, &v4addr);
- return 1;
- }
-
- return 0;
-}
-
-
-// Send a packet and detect protocol using the 24 bit destination address. Returns length of sent message.
-static int ioSendPacket(struct s_io_state *iostate, const unsigned char *buf, const int len, const unsigned char *destination) {
- struct s_io_v4addr v4addr;
- struct s_io_v6addr v6addr;
-
- // char text[64]; utilByteArrayToHexstring(text, 64, destination, 24); printf("(debug) sending packet to %s\n", text);
-
- switch(destination[0]) {
- case 1:
- // default protocol set
- switch(destination[1]) {
- case 6:
- // IPv6
- switch(destination[2]) {
- case 1:
- // UDP over IPv6
- memcpy(v6addr.addr, &destination[4], 16);
- memcpy(v6addr.port, &destination[20], 2);
- return ioSendUDPv6Packet(iostate, buf, len, &v6addr);
- break;
- }
- break;
- case 4:
- // IPv4
- switch(destination[2]) {
- case 1:
- // UDP over IPv4
- memcpy(v4addr.addr, &destination[4], 4);
- memcpy(v4addr.port, &destination[8], 2);
- return ioSendUDPv4Packet(iostate, buf, len, &v4addr);
- break;
- }
- break;
- }
- break;
- }
-
- return -1;
-}
-
-
-// Receive a packet and generate the 24 bit source address depending on the protocol. Returns length of received message.
-static int ioRecvPacket(struct s_io_state *iostate, unsigned char *buf, const int len, unsigned char *source) {
- int ret;
- struct s_io_v4addr v4addr;
- struct s_io_v6addr v6addr;
-
- if((!(iostate->fd[IO_FDID_UDPV6SOCKET].fd < 0)) && ((ret = (ioRecvUDPv6Packet(iostate, buf, len, &v6addr))) > 0)) {
- // received UDP over IPv6
- ioConvertAddressFromUDPv6(source, &v6addr);
- // char text[64]; utilByteArrayToHexstring(text, 64, source, 24); printf("(debug) received packet from %s\n", text);
- return ret;
- }
- if((!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0)) && ((ret = (ioRecvUDPv4Packet(iostate, buf, len, &v4addr))) > 0)) {
- // received UDP over IPv4
- ioConvertAddressFromUDPv4(source, &v4addr);
- // char text[64]; utilByteArrayToHexstring(text, 64, source, 24); printf("(debug) received packet from %s\n", text);
- return ret;
- }
-
- return -1;
-}
-
-
-// Wait for data.
-static void ioWait(struct s_io_state *iostate, const int max_wait) {
- poll(iostate->fd,IO_FDID_COUNT,max_wait);
-}
-
-
-// Initialize IO state.
-static void ioCreate(struct s_io_state *iostate) {
- int i;
- for(i=0; i<IO_FDID_COUNT; i++) {
- iostate->fd[i].fd = -1;
- iostate->fd[i].events = 0;
- }
-}
-
-
-// Close all opened FDs.
-static void ioReset(struct s_io_state *iostate) {
- int i;
- for(i=0; i<IO_FDID_COUNT; i++) {
- if(!(iostate->fd[i].fd < 0)) {
- close(iostate->fd[i].fd);
- }
- }
- ioCreate(iostate);
-}
-
-
-#endif // F_IO_C
diff --git a/libp2psec/peermgt.c b/libp2psec/peermgt.c
index d828d37..edfce2a 100644
--- a/libp2psec/peermgt.c
+++ b/libp2psec/peermgt.c
@@ -474,7 +474,7 @@ static int peermgtDecodePacketAuth(struct s_peermgt *mgt, const struct s_packet_
struct s_nodeid peer_nodeid;
int peerid;
int dupid;
- int64_t remoteflags;
+ int64_t remoteflags = 0;
if(authmgtDecodeMsg(authmgt, data->pl_buf, data->pl_length, source_addr)) {
if(authmgtGetAuthedPeerNodeID(authmgt, &peer_nodeid)) {
diff --git a/mainloop.ic b/mainloop.ic
index 604ea32..a96d31e 100644
--- a/mainloop.ic
+++ b/mainloop.ic
@@ -22,6 +22,7 @@ static void mainLoop() {
int tnow;
unsigned char buf[4096];
unsigned char msgbuf[4096];
+ unsigned char cmdbuf[1024];
unsigned char *msg;
int lastinit = 0;
int laststatus = 0;
@@ -80,7 +81,10 @@ static void mainLoop() {
// check console
if(g_enableconsole > 0) {
- decodeConsole();
+ len = ioReadSTDIN(&iostate, cmdbuf, 1024);
+ if(len > 0) {
+ decodeConsole((char *)cmdbuf, len);
+ }
}
}
}
diff --git a/peervpn.c b/peervpn.c
index 85fdc94..4d171f0 100644
--- a/peervpn.c
+++ b/peervpn.c
@@ -19,17 +19,12 @@
#include <signal.h>
#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <grp.h>
#include <openssl/engine.h>
#include "libp2psec/p2psec.c"
-#include "io.c"
+#include "platform/io.c"
+#include "platform/ifconfig.c"
#include "globals.ic"
#include "helpers.ic"
#include "console.ic"
@@ -47,6 +42,8 @@ int main(int argc, char **argv) {
// default configuration
strcpy(config.tapname,"");
+ strcpy(config.ifconfig4,"");
+ strcpy(config.ifconfig6,"");
strcpy(config.upcmd,"");
strcpy(config.sourceip,"");
strcpy(config.sourceport,"");
diff --git a/peervpn.conf b/peervpn.conf
index 16e827b..70dbf6c 100644
--- a/peervpn.conf
+++ b/peervpn.conf
@@ -25,7 +25,7 @@
## Option: enableipv4 <yes|no>
-## Description: Enables IPv4 support.
+## Description: Enables IPv4 sockets.
## Defaults to "yes".
## Example: enableipv4 yes
@@ -34,7 +34,7 @@
## Option: enableipv6 <yes|no>
-## Description: Enables IPv6 support.
+## Description: Enables IPv6 sockets.
## Defaults to "yes".
## Example: enableipv6 yes
@@ -81,14 +81,32 @@
+## Option: ifconfig4 <address>/<prefixlen>
+## Description: Defines the IPv4 address and its prefix length that
+## should be assigned to the TAP device.
+## Example: ifconfig4 10.1.2.3/24
+
+#ifconfig4 10.1.2.3/24
+
+
+
+## Option: ifconfig6 <address>/<prefixlen>
+## Description: Defines the IPv6 address and its prefix length that
+## should be assigned to the TAP device.
+## Example: ifconfig6 2001:DB8:1:2::3/64
+
+#ifconfig6 2001:DB8:1:2::3/64
+
+
+
## Option: upcmd <command>
## Description: Defines a shell command that will be executed after
## the TAP device has been opened. This can be used to
## invoke a program/script or to control interface
## parameters (IP address, MTU, etc.).
-## Example: upcmd ifconfig peervpn0 up 10.1.2.3 netmask 255.255.255.0
+## Example: upcmd echo virtual interface is up
-#upcmd ifconfig peervpn0 up && echo virtual interface is up
+#upcmd echo virtual interface is up
diff --git a/platform/ifconfig.c b/platform/ifconfig.c
new file mode 100644
index 0000000..b639aee
--- /dev/null
+++ b/platform/ifconfig.c
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * Copyright (C) 2012 by Tobias Volk *
+ * mail@tobiasvolk.de *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+
+#ifndef F_IFCONFIG_C
+#define F_IFCONFIG_C
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#ifdef WIN32
+#define IFCONFIG_WINDOWS
+#endif
+
+
+// Execute command.
+static int ifconfigExec(const char *cmd) {
+ int ret = system(cmd);
+#ifdef IFCONFIG_DEBUG
+ printf("executed=\"%s\", result=\"%d\"\n", cmd, ret);
+#endif
+ return ret;
+}
+
+
+// Check & copy input.
+static int ifconfigCheckCopyInput(char *out, const int out_len, const char *in, const int in_len) {
+ int i;
+ char c;
+ if(!(in_len < out_len)) return 0;
+ i = 0;
+ while(i < in_len) {
+ c = in[i];
+ if(!(c >= 32 && c < 127)) return 0;
+ switch(c) {
+ case ';':
+ case '\'':
+ case '\"':
+ case '?':
+ case '!':
+ case '`':
+ return 0;
+ }
+ i++;
+ }
+ memcpy(out, in, in_len);
+ out[in_len] = '\0';
+ return 1;
+}
+
+
+// Split input.
+static int ifconfigSplit(char *a_out, const int a_len, char *b_out, const int b_len, const char *in, const int in_len, const char split_char) {
+ int i;
+ int s;
+ if((a_len + 1 + b_len) < in_len) return 0;
+ i = 0;
+ s = 0;
+ while(i < in_len) {
+ if(in[i] == split_char) {
+ s = i;
+ break;
+ }
+ i++;
+ }
+ if(!(s > 0)) return 0;
+ if(!ifconfigCheckCopyInput(a_out, a_len, &in[0], s)) return 0;
+ if(!ifconfigCheckCopyInput(b_out, b_len, &in[(s + 1)], (in_len - (s + 1)))) return 0;
+ return 1;
+}
+
+
+// Calculate netmask from prefixlen.
+static void ifconfig4Netmask(char *out, const int prefixlen) {
+ int mask[4];
+ int i, j, p;
+ for(j=0; j<4; j++) {
+ mask[j] = 0;
+ }
+ p = prefixlen;
+ j = 0;
+ while(p > 0 && j < 4) {
+ i = 0;
+ while(p > 0 && i < 8) {
+ mask[j] = (mask[j] | (1 << (8 - i - 1)));
+ p--;
+ i++;
+ }
+ j++;
+ }
+ snprintf(out, 16, "%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]);
+}
+
+
+// Configure IPv4 address on specified interface.
+static int ifconfig4(const char *ifname, const int ifname_len, const char *addr, const int addr_len) {
+ char cmd[1024]; memset(cmd, 0, 1024);
+ char ifname_s[256]; memset(ifname_s, 0, 256);
+ char ip_s[256]; memset(ip_s, 0, 256);
+ char netmask_s[16]; memset(netmask_s, 0, 16);
+ char prefixlen_s[4]; memset(prefixlen_s, 0, 4);
+ int ret;
+
+ if(!ifconfigCheckCopyInput(ifname_s, 256, ifname, ifname_len)) return 0;
+ if(!ifconfigSplit(ip_s, 256, prefixlen_s, 4, addr, addr_len, '/')) return 0;
+ if(strlen(prefixlen_s) == 0) memcpy(prefixlen_s, "32", 2);
+ ret = 0; sscanf(prefixlen_s, "%d", &ret); ifconfig4Netmask(netmask_s, ret);
+
+#ifdef IFCONFIG_WINDOWS
+ sprintf(cmd, "netsh interface ip set address name=\"%s\" static \"%s\" \"%s\"", ifname_s, ip_s, netmask_s); ret = ifconfigExec(cmd);
+ return(ret == 0);
+#else
+ sprintf(cmd, "ip link set dev \"%s\" up", ifname_s); ret = ifconfigExec(cmd);
+ if(ret == 0) {
+ sprintf(cmd, "ip -4 addr add dev \"%s\" \"%s/%s\" broadcast +", ifname_s, ip_s, prefixlen_s); ret = ifconfigExec(cmd);
+ return(ret == 0);
+ }
+
+ sprintf(cmd, "ifconfig \"%s\" up", ifname_s); ret = ifconfigExec(cmd);
+ if(ret == 0) {
+ sprintf(cmd, "ifconfig \"%s\" \"%s\" netmask \"%s\"", ifname_s, ip_s, netmask_s); ret = ifconfigExec(cmd);
+ return(ret == 0);
+ }
+#endif
+
+ return 0;
+}
+
+
+// Configure IPv6 address on specified interface.
+static int ifconfig6(const char *ifname, const int ifname_len, const char *addr, const int addr_len) {
+ char cmd[1024]; memset(cmd, 0, 1024);
+ char ifname_s[256]; memset(ifname_s, 0, 256);
+ char ip_s[256]; memset(ip_s, 0, 256);
+ char netmask_s[16]; memset(netmask_s, 0, 16);
+ char prefixlen_s[4]; memset(prefixlen_s, 0, 4);
+ int ret;
+
+ if(!ifconfigCheckCopyInput(ifname_s, 256, ifname, ifname_len)) return 0;
+ if(!ifconfigSplit(ip_s, 256, prefixlen_s, 4, addr, addr_len, '/')) return 0;
+ if(strlen(prefixlen_s) == 0) memcpy(prefixlen_s, "128", 2);
+ ret = 0; sscanf(prefixlen_s, "%d", &ret); ifconfig4Netmask(netmask_s, ret);
+
+#ifdef IFCONFIG_WINDOWS
+#else
+ sprintf(cmd, "ip link set dev \"%s\" up", ifname_s); ret = ifconfigExec(cmd);
+ if(ret == 0) {
+ sprintf(cmd, "ip -6 addr add dev \"%s\" \"%s/%s\"", ifname_s, ip_s, prefixlen_s); ret = ifconfigExec(cmd);
+ return(ret == 0);
+ }
+#endif
+
+ return 0;
+}
+
+
+#endif // F_IFCONFIG_C
diff --git a/platform/io.c b/platform/io.c
new file mode 100644
index 0000000..acdb450
--- /dev/null
+++ b/platform/io.c
@@ -0,0 +1,855 @@
+/***************************************************************************
+ * Copyright (C) 2012 by Tobias Volk *
+ * mail@tobiasvolk.de *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+
+#ifndef F_IO_C
+#define F_IO_C
+
+
+#ifdef WIN32
+#define IO_WINDOWS
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef IO_WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <winioctl.h>
+#include "tapwin.h"
+#else
+#include <poll.h>
+#include <netdb.h>
+#include <linux/if_tun.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <net/if.h>
+#endif
+
+
+// IDs.
+#define IO_FDID_STDIN 0
+#define IO_FDID_UDPV4SOCKET 1
+#define IO_FDID_UDPV6SOCKET 2
+#define IO_FDID_TAP 3
+#define IO_FDID_COUNT 4
+
+
+// The IO state structure.
+#ifdef IO_WINDOWS
+struct s_io_state_fd {
+ int fd;
+};
+#endif
+struct s_io_state {
+#ifdef IO_WINDOWS
+ OVERLAPPED overlapped_read[IO_FDID_COUNT];
+ OVERLAPPED overlapped_write[IO_FDID_COUNT];
+ HANDLE event_read[IO_FDID_COUNT];
+ unsigned char readbuf[(4096 * IO_FDID_COUNT)];
+ struct sockaddr readaddr[IO_FDID_COUNT];
+ socklen_t readaddr_len[IO_FDID_COUNT];
+ DWORD readbuf_len[IO_FDID_COUNT];
+ int readbuf_used[IO_FDID_COUNT];
+ struct s_io_state_fd fd[IO_FDID_COUNT];
+ HANDLE handle[IO_FDID_COUNT];
+#else
+ struct pollfd fd[IO_FDID_COUNT];
+#endif
+};
+
+
+// The IPv4 addr/port structure.
+struct s_io_v4addr {
+ unsigned char addr[4];
+ unsigned char port[2];
+};
+
+
+// The IPv6 addr/port structure.
+struct s_io_v6addr {
+ unsigned char addr[16];
+ unsigned char port[2];
+};
+
+
+// Opens STDIN. Returns 1 if successful.
+static int ioOpenSTDIN(struct s_io_state *iostate) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ if(!((fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK)) < 0)) {
+ iostate->fd[IO_FDID_STDIN].fd = STDIN_FILENO;
+ iostate->fd[IO_FDID_STDIN].events = POLLIN;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+#endif
+}
+
+
+// Reads from STDIN. Returns number of bytes read.
+static int ioReadSTDIN(struct s_io_state *iostate, unsigned char *buf, const int len) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ return read(iostate->fd[IO_FDID_STDIN].fd, buf, len);
+#endif
+}
+
+
+// Helper functions for TAP devices on Windows.
+#ifdef IO_WINDOWS
+#define IO_TAPSEARCH_IF_GUID_FROM_NAME 0
+#define IO_TAPSEARCH_IF_NAME_FROM_GUID 1
+static char *ioOpenTapSearch(char *value, char *key, int type)
+{
+ int i = 0;
+ LONG status;
+ DWORD len;
+ HKEY net_conn_key;
+ BOOL found = FALSE;
+ char guid[256];
+ char ifname[256];
+ char conn_string[512];
+ HKEY conn_key;
+ DWORD value_type;
+ if (!value || !key) {
+ return NULL;
+ }
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &net_conn_key);
+ if (status != ERROR_SUCCESS) {
+ return NULL;
+ }
+ while (!found) {
+ len = sizeof(guid);
+ status = RegEnumKeyEx(net_conn_key, i++, guid, &len,
+ NULL, NULL, NULL, NULL);
+ if (status == ERROR_NO_MORE_ITEMS) {
+ break;
+ } else if (status != ERROR_SUCCESS) {
+ continue;
+ }
+ snprintf(conn_string, sizeof(conn_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, guid);
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, conn_string, 0, KEY_READ, &conn_key);
+ if (status != ERROR_SUCCESS) {
+ continue;
+ }
+ len = sizeof(ifname);
+ status = RegQueryValueEx(conn_key, "Name", NULL, &value_type, (BYTE *)ifname, &len);
+ if (status != ERROR_SUCCESS || value_type != REG_SZ) {
+ RegCloseKey(conn_key);
+ continue;
+ }
+ switch (type) {
+ case IO_TAPSEARCH_IF_GUID_FROM_NAME:
+ if (!strcmp(key, ifname)) {
+ strcpy(value, guid);
+ found = TRUE;
+ }
+ break;
+ case IO_TAPSEARCH_IF_NAME_FROM_GUID:
+ if (!strcmp(key, guid)) {
+ strcpy(value, ifname);
+ found = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ RegCloseKey(conn_key);
+ }
+ RegCloseKey(net_conn_key);
+ if (found) {
+ return value;
+ }
+ return NULL;
+}
+static HANDLE ioOpenTapDev(char *guid, char *dev) {
+ HANDLE handle;
+ ULONG len, status;
+ char device_path[512];
+ snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, guid, TAPSUFFIX);
+ handle = CreateFile(device_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
+ if (handle == INVALID_HANDLE_VALUE) {
+ return INVALID_HANDLE_VALUE;
+ }
+ status = TRUE;
+ if (!DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
+ &status, sizeof(status),
+ &status, sizeof(status), &len, NULL)) {
+ }
+ return handle;
+}
+#endif
+
+
+// Opens TAP device. Returns 1 and a tapname (max. 256 bytes) if successful.
+static int ioOpenTap(struct s_io_state *iostate, char *tapname, const char *reqname) {
+#ifdef IO_WINDOWS
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ HKEY unit_key;
+ char guid[256];
+ char comp_id[256];
+ char enum_name[256];
+ char unit_string[512];
+ char tmpname[256];
+ int tmpname_len;
+ BOOL found = FALSE;
+ HKEY adapter_key;
+ DWORD value_type;
+ LONG status;
+ DWORD len;
+
+ tmpname_len = strlen(reqname);
+ if(tmpname_len >= 256) {
+ tmpname_len = 255;
+ }
+ if(tmpname_len > 0) {
+ memcpy(tmpname, reqname, tmpname_len);
+ }
+ else {
+ tmpname_len = 0;
+ }
+ tmpname[tmpname_len] = '\0';
+
+ if(tmpname != NULL) {
+ if (tmpname[0] != '\0') {
+ if (!ioOpenTapSearch(guid, tmpname, IO_TAPSEARCH_IF_GUID_FROM_NAME)) {
+ return 0;
+ }
+ handle = ioOpenTapDev(guid, tmpname);
+ if(handle != INVALID_HANDLE_VALUE) {
+ if(tapname != NULL) {
+ tapname[0] = '\0';
+ tmpname_len = strlen(tmpname);
+ if(tmpname_len > 0 && tmpname_len < 256) {
+ memcpy(tapname, tmpname, tmpname_len);
+ tapname[tmpname_len] = '\0';
+ }
+ }
+ iostate->handle[IO_FDID_TAP] = handle;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ }
+
+ int i = 0;
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &adapter_key);
+ if (status != ERROR_SUCCESS) {
+ return 0;
+ }
+ while (!found) {
+ len = sizeof(enum_name);
+ status = RegEnumKeyEx(adapter_key, i++,
+ enum_name, &len,
+ NULL, NULL, NULL, NULL);
+ if (status == ERROR_NO_MORE_ITEMS) {
+ break;
+ } else if (status != ERROR_SUCCESS) {
+ continue;
+ }
+ snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name);
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key);
+ if (status != ERROR_SUCCESS) {
+ continue;
+ }
+ len = sizeof(comp_id);
+ status = RegQueryValueEx(unit_key, "ComponentId", NULL, &value_type, (BYTE *)comp_id, &len);
+ if (status != ERROR_SUCCESS || value_type != REG_SZ) {
+ RegCloseKey(unit_key);
+ continue;
+ }
+ len = sizeof(guid);
+ status = RegQueryValueEx(unit_key, "NetCfgInstanceId", NULL, &value_type, (BYTE *)guid, &len);
+ if (status != ERROR_SUCCESS || value_type != REG_SZ) {
+ RegCloseKey(unit_key);
+ continue;
+ }
+ ioOpenTapSearch(tmpname, guid, IO_TAPSEARCH_IF_NAME_FROM_GUID);
+ handle = ioOpenTapDev(guid, tmpname);
+ if (handle != INVALID_HANDLE_VALUE) {
+ found = TRUE;
+ }
+ RegCloseKey(unit_key);
+ }
+ RegCloseKey(adapter_key);
+ if(handle != INVALID_HANDLE_VALUE) {
+ if(tapname != NULL) {
+ tapname[0] = '\0';
+ tmpname_len = strlen(tmpname);
+ if(tmpname_len > 0 && tmpname_len < 256) {
+ memcpy(tapname, tmpname, tmpname_len);
+ tapname[tmpname_len] = '\0';
+ }
+ }
+ iostate->handle[IO_FDID_TAP] = handle;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+#else
+ struct ifreq ifr;
+ char *file = "/dev/net/tun";
+ int tapfd = open(file,(O_RDWR | O_NONBLOCK));
+ int name_len;
+
+ if(tapfd < 0) {
+ return 0;
+ }
+
+ memset(&ifr,0,sizeof(struct ifreq));
+ ifr.ifr_flags = (IFF_TAP | IFF_NO_PI);
+ strncpy(ifr.ifr_name, reqname, sizeof(ifr.ifr_name) - 1);
+ if(ioctl(tapfd,TUNSETIFF,(void *)&ifr) < 0) {
+ return 0;
+ }
+
+ iostate->fd[IO_FDID_TAP].fd = tapfd;
+ iostate->fd[IO_FDID_TAP].events = POLLIN;
+
+ if(tapname != NULL) {
+ name_len = strlen(ifr.ifr_name);
+ tapname[0] = '\0';
+ if(name_len > 0 && name_len < 256) {
+ memcpy(tapname, ifr.ifr_name, name_len);
+ tapname[name_len] = '\0';
+ }
+ }
+
+ return 1;
+#endif
+}
+
+
+// Writes to TAP device. Returns number of bytes written.
+static int ioWriteTap(struct s_io_state *iostate, const unsigned char *buf, const int len) {
+#ifdef IO_WINDOWS
+ DWORD ret;
+ ret = 0;
+ WriteFile(iostate->handle[IO_FDID_TAP], buf, len, NULL, &iostate->overlapped_write[IO_FDID_TAP]);
+ GetOverlappedResult(iostate->handle[IO_FDID_TAP], &iostate->overlapped_write[IO_FDID_TAP], &ret, TRUE);
+ if(ret > 0) {
+ return ret;
+ }
+ else {
+ return 0;
+ }
+#else
+ return write(iostate->fd[IO_FDID_TAP].fd, buf, len);
+#endif
+}
+
+
+// Reads from TAP device. Returns number of bytes read.
+static int ioReadTap(struct s_io_state *iostate, unsigned char *buf, const int len) {
+#ifdef IO_WINDOWS
+ int buflen = iostate->readbuf_len[IO_FDID_TAP];
+ if(buflen > 0) {
+ iostate->readbuf_len[IO_FDID_TAP] = 0;
+ if(buflen > 0 && buflen < len) {
+ memcpy(buf, &iostate->readbuf[(4096 * IO_FDID_TAP)], buflen);
+ return buflen;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 0;
+ }
+#else
+ return read(iostate->fd[IO_FDID_TAP].fd, buf, len);
+#endif
+}
+
+
+// Opens a socket. Returns 1 if successful.
+static int ioOpenSocket(int *handle, const char *bindaddress, const char *bindport, const int domain, const int type, const int protocol) {
+ int ret;
+ int fd;
+ const char *zeroport = "0";
+ const char *useport;
+ const char *useaddr;
+ struct addrinfo *d = NULL;
+ struct addrinfo *di;
+ struct addrinfo hints;
+ memset(&hints,0,sizeof(struct addrinfo));
+#ifdef IO_WINDOWS
+ if((fd = WSASocket(domain, type, 0, 0, 0, WSA_FLAG_OVERLAPPED)) < 0) return 0;
+#else
+ if((fd = socket(domain, type, 0)) < 0) return 0;
+ int one = 1;
+ if((fcntl(fd,F_SETFL,O_NONBLOCK)) < 0) return 0;
+ if(domain == AF_INET6) setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+#endif
+ hints.ai_family = domain;
+ hints.ai_socktype = type;
+ hints.ai_protocol = protocol;
+ hints.ai_flags = AI_PASSIVE;
+ if(bindaddress == NULL) {
+ useaddr = NULL;
+ }
+ else {
+ if(strlen(bindaddress) > 0) {
+ useaddr = bindaddress;
+ }
+ else {
+ useaddr = NULL;
+ }
+ }
+ if(bindport == NULL) {
+ useport = zeroport;
+ }
+ else {
+ useport = bindport;
+ }
+ if(getaddrinfo(useaddr, useport, &hints, &d) == 0) {
+ ret = -1;
+ di = d;
+ while(di != NULL) {
+ if(bind(fd, di->ai_addr, di->ai_addrlen) == 0) {
+ ret = fd;
+ break;
+ }
+ di = di->ai_next;
+ }
+ freeaddrinfo(d);
+ if(ret < 0) {
+ close(fd);
+ return 0;
+ }
+ *handle = ret;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+// Get IPv6 UDP address from name. Returns 1 if successful.
+static int ioGetUDPv6Address(struct s_io_v6addr *addr, const char *hostname, const char *port) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ int ret;
+ struct sockaddr_in6 *saddr;
+ struct addrinfo *d = NULL;
+ struct addrinfo hints;
+ if(hostname != NULL && port != NULL) {
+ memset(&hints,0,sizeof(struct addrinfo));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = 0;
+ if(getaddrinfo(hostname, port, &hints, &d) == 0) {
+ if(d != NULL) {
+ saddr = (struct sockaddr_in6 *)d->ai_addr;
+ memcpy(addr->addr, saddr->sin6_addr.s6_addr, 16);
+ memcpy(addr->port, &saddr->sin6_port, 2);
+ ret = 1;
+ }
+ else {
+ ret = 0;
+ }
+ freeaddrinfo(d);
+ }
+ else {
+ ret = 0;
+ }
+ return ret;
+ }
+ else {
+ return 0;
+ }
+#endif
+}
+
+
+// Opens an IPv6 UDP socket. Returns 1 if successful.
+static int ioOpenUDPv6Socket(struct s_io_state *iostate, const char *bindaddress, const char *bindport) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ int fd;
+ if(ioOpenSocket(&fd, bindaddress, bindport, AF_INET6, SOCK_DGRAM, 0)) {
+ iostate->fd[IO_FDID_UDPV6SOCKET].fd = fd;
+ iostate->fd[IO_FDID_UDPV6SOCKET].events = POLLIN;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+#endif
+}
+
+
+// Sends an IPv6 UDP packet. Returns length of sent message.
+static int ioSendUDPv6Packet(struct s_io_state *iostate, const unsigned char *buf, const int len, struct s_io_v6addr *destination) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ int ret;
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(struct sockaddr_in6));
+ addr.sin6_family = AF_INET6;
+ memcpy(addr.sin6_addr.s6_addr, destination->addr, 16);
+ memcpy(&addr.sin6_port, destination->port, 2);
+ ret = sendto(iostate->fd[IO_FDID_UDPV6SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6));
+ return ret;
+#endif
+}
+
+
+// Receives an IPv6 UDP packet. Returns length of received message.
+static int ioRecvUDPv6Packet(struct s_io_state *iostate, unsigned char *buf, const int len, struct s_io_v6addr *source) {
+#ifdef IO_WINDOWS
+ return 0; // not implemented
+#else
+ struct sockaddr_in6 addr;
+ socklen_t addrlen = sizeof(struct sockaddr_in6);
+ int ret = recvfrom(iostate->fd[IO_FDID_UDPV6SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, &addrlen);
+ if(ret > 0) {
+ memcpy(source->addr, addr.sin6_addr.s6_addr, 16);
+ memcpy(source->port, &addr.sin6_port, 2);
+ }
+ return ret;
+#endif
+}
+
+
+// Convert UDPv6 address to 24 bit address.
+static void ioConvertAddressFromUDPv6(unsigned char *address, const struct s_io_v6addr *v6addr) {
+ memset(address, 0, 24);
+ address[0] = 1;
+ address[1] = 6;
+ address[2] = 1;
+ memcpy(&address[4], &v6addr->addr, 16);
+ memcpy(&address[20], v6addr->port, 2);
+}
+
+
+// Get IPv4 UDP address from name. Returns 1 if successful.
+static int ioGetUDPv4Address(struct s_io_v4addr *addr, const char *hostname, const char *port) {
+ int ret;
+ struct sockaddr_in *saddr;
+ struct addrinfo *d = NULL;
+ struct addrinfo hints;
+ if(hostname != NULL && port != NULL) {
+ memset(&hints,0,sizeof(struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = 0;
+ if(getaddrinfo(hostname, port, &hints, &d) == 0) {
+ if(d != NULL) {
+ saddr = (struct sockaddr_in *)d->ai_addr;
+ memcpy(addr->addr, &saddr->sin_addr.s_addr, 4);
+ memcpy(addr->port, &saddr->sin_port, 2);
+ ret = 1;
+ }
+ else {
+ ret = 0;
+ }
+ freeaddrinfo(d);
+ }
+ else {
+ ret = 0;
+ }
+ return ret;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+// Opens an IPv4 UDP socket. Returns 1 if successful.
+static int ioOpenUDPv4Socket(struct s_io_state *iostate, const char *bindaddress, const char *bindport) {
+ int fd;
+ if(ioOpenSocket(&fd, bindaddress, bindport, AF_INET, SOCK_DGRAM, 0)) {
+ iostate->fd[IO_FDID_UDPV4SOCKET].fd = fd;
+#ifdef IO_WINDOWS
+#else
+ iostate->fd[IO_FDID_UDPV4SOCKET].events = POLLIN;
+#endif
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+// Sends an IPv4 UDP packet. Returns length of sent message.
+static int ioSendUDPv4Packet(struct s_io_state *iostate, const unsigned char *buf, const int len, const struct s_io_v4addr *destination) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ memcpy(&addr.sin_addr.s_addr, destination->addr, 4);
+ memcpy(&addr.sin_port, destination->port, 2);
+#ifdef IO_WINDOWS
+ DWORD ret = 0;
+ DWORD flags = 0;
+ WSABUF wsabuf;
+ wsabuf.buf = (char *)buf;
+ wsabuf.len = len;
+ WSASendTo(iostate->fd[IO_FDID_UDPV4SOCKET].fd, &wsabuf, 1, NULL, flags, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), &iostate->overlapped_write[IO_FDID_UDPV4SOCKET], NULL);
+ WSAGetOverlappedResult(iostate->fd[IO_FDID_UDPV4SOCKET].fd, &iostate->overlapped_write[IO_FDID_UDPV4SOCKET], &ret, TRUE, &flags);
+#else
+ int ret;
+ ret = sendto(iostate->fd[IO_FDID_UDPV4SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+#endif
+ if(ret > 0) {
+ return ret;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+// Receives an IPv4 UDP packet. Returns length of received message.
+static int ioRecvUDPv4Packet(struct s_io_state *iostate, unsigned char *buf, const int len, struct s_io_v4addr *source) {
+#ifdef IO_WINDOWS
+ struct sockaddr_in *readaddr = (struct sockaddr_in *)&iostate->readaddr[IO_FDID_UDPV4SOCKET];
+ int buflen = iostate->readbuf_len[IO_FDID_UDPV4SOCKET];
+ if(buflen > 0) {
+ iostate->readbuf_len[IO_FDID_UDPV4SOCKET] = 0;
+ if(buflen < len) {
+ memcpy(buf, &iostate->readbuf[(4096 * IO_FDID_UDPV4SOCKET)], buflen);
+ memcpy(source->addr, &readaddr->sin_addr.s_addr, 4);
+ memcpy(source->port, &readaddr->sin_port, 2);
+ return buflen;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 0;
+ }
+#else
+ struct sockaddr_in addr;
+ socklen_t addrlen = sizeof(struct sockaddr_in);
+ int ret = recvfrom(iostate->fd[IO_FDID_UDPV4SOCKET].fd, buf, len, 0, (struct sockaddr *)&addr, &addrlen);
+ if(ret > 0) {
+ memcpy(source->addr, &addr.sin_addr.s_addr, 4);
+ memcpy(source->port, &addr.sin_port, 2);
+ }
+ return ret;
+#endif
+}
+
+
+// Convert UDPv4 address to 24 bit address.
+static void ioConvertAddressFromUDPv4(unsigned char *address, const struct s_io_v4addr *v4addr) {
+ memset(address, 0, 24);
+ address[0] = 1;
+ address[1] = 4;
+ address[2] = 1;
+ memcpy(&address[4], v4addr->addr, 4);
+ memcpy(&address[8], v4addr->port, 2);
+}
+
+
+// Get 24 bit address (UDP over IPv4 or IPv6) from hostname/port. Returns 1 if successful.
+static int ioGetUDPAddress(struct s_io_state *iostate, unsigned char *address, const char *hostname, const char *port) {
+ struct s_io_v4addr v4addr;
+ struct s_io_v6addr v6addr;
+
+ if((!(iostate->fd[IO_FDID_UDPV6SOCKET].fd < 0)) && (ioGetUDPv6Address(&v6addr, hostname, port))) {
+ ioConvertAddressFromUDPv6(address, &v6addr);
+ return 1;
+ }
+ if((!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0)) && (ioGetUDPv4Address(&v4addr, hostname, port))) {
+ ioConvertAddressFromUDPv4(address, &v4addr);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// Send a packet and detect protocol using the 24 bit destination address. Returns length of sent message.
+static int ioSendPacket(struct s_io_state *iostate, const unsigned char *buf, const int len, const unsigned char *destination) {
+ struct s_io_v4addr v4addr;
+ struct s_io_v6addr v6addr;
+
+ switch(destination[0]) {
+ case 1:
+ // default protocol set
+ switch(destination[1]) {
+ case 6:
+ // IPv6
+ switch(destination[2]) {
+ case 1:
+ // UDP over IPv6
+ memcpy(v6addr.addr, &destination[4], 16);
+ memcpy(v6addr.port, &destination[20], 2);
+ return ioSendUDPv6Packet(iostate, buf, len, &v6addr);
+ break;
+ }
+ break;
+ case 4:
+ // IPv4
+ switch(destination[2]) {
+ case 1:
+ // UDP over IPv4
+ memcpy(v4addr.addr, &destination[4], 4);
+ memcpy(v4addr.port, &destination[8], 2);
+ return ioSendUDPv4Packet(iostate, buf, len, &v4addr);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+
+// Receive a packet and generate the 24 bit source address depending on the protocol. Returns length of received message.
+static int ioRecvPacket(struct s_io_state *iostate, unsigned char *buf, const int len, unsigned char *source) {
+ int ret;
+ struct s_io_v4addr v4addr;
+ struct s_io_v6addr v6addr;
+
+ if((!(iostate->fd[IO_FDID_UDPV6SOCKET].fd < 0)) && ((ret = (ioRecvUDPv6Packet(iostate, buf, len, &v6addr))) > 0)) {
+ // received UDP over IPv6
+ ioConvertAddressFromUDPv6(source, &v6addr);
+ return ret;
+ }
+ if((!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0)) && ((ret = (ioRecvUDPv4Packet(iostate, buf, len, &v4addr))) > 0)) {
+ // received UDP over IPv4
+ ioConvertAddressFromUDPv4(source, &v4addr);
+ return ret;
+ }
+
+ return -1;
+}
+
+
+// Wait for data.
+static void ioWait(struct s_io_state *iostate, const int max_wait) {
+#ifdef IO_WINDOWS
+ // start reading UDPv4 socket
+ DWORD udpv4recvlen;
+ DWORD udpv4flags;
+ udpv4flags = 0;
+ WSABUF udpv4wsabuf;
+ udpv4wsabuf.buf = (char *)&iostate->readbuf[(4096 * IO_FDID_UDPV4SOCKET)];
+ udpv4wsabuf.len = 4096;
+ iostate->readaddr_len[IO_FDID_UDPV4SOCKET] = sizeof(struct sockaddr_in);
+ if((!(iostate->readbuf_used[IO_FDID_UDPV4SOCKET])) && (!(iostate->readbuf_len[IO_FDID_UDPV4SOCKET] > 0)) && (!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0))) {
+ iostate->readbuf_used[IO_FDID_UDPV4SOCKET] = 1;
+ WSARecvFrom(iostate->fd[IO_FDID_UDPV4SOCKET].fd, &udpv4wsabuf, 1, NULL, &udpv4flags, &iostate->readaddr[IO_FDID_UDPV4SOCKET], &iostate->readaddr_len[IO_FDID_UDPV4SOCKET], &iostate->overlapped_read[IO_FDID_UDPV4SOCKET], 0);
+ }
+
+ // start reading TAP device
+ DWORD tapreadlen;
+ if((!(iostate->readbuf_used[IO_FDID_TAP])) && (!(iostate->readbuf_len[IO_FDID_TAP] > 0)) && (iostate->handle[IO_FDID_TAP] != INVALID_HANDLE_VALUE)) {
+ iostate->readbuf_used[IO_FDID_TAP] = 1;
+ ReadFile(iostate->handle[IO_FDID_TAP], &iostate->readbuf[(4096 * IO_FDID_TAP)], 4096, NULL, &iostate->overlapped_read[IO_FDID_TAP]);
+ }
+
+ // check for events
+ WaitForMultipleObjects(IO_FDID_COUNT, iostate->event_read, FALSE, max_wait);
+ if((iostate->readbuf_used[IO_FDID_UDPV4SOCKET]) && (!(iostate->readbuf_len[IO_FDID_UDPV4SOCKET] > 0)) && (!(iostate->fd[IO_FDID_UDPV4SOCKET].fd < 0))) {
+ udpv4flags = 0; udpv4recvlen = 0;
+ if(WSAGetOverlappedResult(iostate->fd[IO_FDID_UDPV4SOCKET].fd, &iostate->overlapped_read[IO_FDID_UDPV4SOCKET], &udpv4recvlen, FALSE, &udpv4flags) == TRUE) {
+ iostate->readbuf_used[IO_FDID_UDPV4SOCKET] = 0;
+ if(udpv4recvlen > 0) {
+ iostate->readbuf_len[IO_FDID_UDPV4SOCKET] = udpv4recvlen;
+ }
+ }
+ else {
+ if(WSAGetLastError() != WSA_IO_INCOMPLETE) {
+ iostate->readbuf_used[IO_FDID_UDPV4SOCKET] = 0;
+ }
+ }
+ }
+ if((iostate->readbuf_used[IO_FDID_TAP]) && (!(iostate->readbuf_len[IO_FDID_TAP] > 0)) && (iostate->handle[IO_FDID_TAP] != INVALID_HANDLE_VALUE)) {
+ tapreadlen = 0;
+ if(GetOverlappedResult(iostate->handle[IO_FDID_TAP], &iostate->overlapped_read[IO_FDID_TAP], &tapreadlen, FALSE) != 0) {
+ iostate->readbuf_used[IO_FDID_TAP] = 0;
+ if(tapreadlen > 0) {
+ iostate->readbuf_len[IO_FDID_TAP] = tapreadlen;
+ }
+ }
+ else {
+ if(GetLastError() != ERROR_IO_INCOMPLETE) {
+ iostate->readbuf_used[IO_FDID_TAP] = 0;
+ }
+ }
+ }
+#else
+ poll(iostate->fd,IO_FDID_COUNT,max_wait);
+#endif
+}
+
+
+// Initialize IO state.
+static void ioCreate(struct s_io_state *iostate) {
+#ifdef IO_WINDOWS
+ WSADATA wsadata;
+ WSAStartup(MAKEWORD(2,2), &wsadata);
+#endif
+ int i;
+ for(i=0; i<IO_FDID_COUNT; i++) {
+#ifdef IO_WINDOWS
+ iostate->readbuf_len[i] = 0;
+ iostate->readbuf_used[i] = 0;
+ iostate->handle[i] = INVALID_HANDLE_VALUE;
+ memset(&iostate->overlapped_read[i], 0, sizeof(OVERLAPPED));
+ memset(&iostate->overlapped_write[i], 0, sizeof(OVERLAPPED));
+ iostate->overlapped_read[i].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ iostate->overlapped_write[i].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ iostate->event_read[i] = iostate->overlapped_read[i].hEvent;
+#else
+ iostate->fd[i].events = 0;
+#endif
+ iostate->fd[i].fd = -1;
+ }
+}
+
+
+// Close all opened FDs.
+static void ioReset(struct s_io_state *iostate) {
+ int i;
+ for(i=0; i<IO_FDID_COUNT; i++) {
+ if(!(iostate->fd[i].fd < 0)) {
+ close(iostate->fd[i].fd);
+ }
+ }
+ ioCreate(iostate);
+}
+
+
+#endif // F_IO_C
diff --git a/platform/tapwin.h b/platform/tapwin.h
new file mode 100644
index 0000000..5dbd4b0
--- /dev/null
+++ b/platform/tapwin.h
@@ -0,0 +1,73 @@
+/*
+ * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap
+ * device functionality on Windows.
+ *
+ * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
+ *
+ * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
+ * and is released under the GPL version 2 (see below).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+//=============
+// TAP IOCTLs
+//=============
+
+#define TAP_CONTROL_CODE(request,method) \
+ CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
+
+// Present in 8.1
+
+#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
+#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
+
+// Added in 8.2
+
+/* obsoletes TAP_IOCTL_CONFIG_POINT_TO_POINT */
+#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE (10, METHOD_BUFFERED)
+
+//=================
+// Registry keys
+//=================
+
+#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+//======================
+// Filesystem prefixes
+//======================
+
+#define USERMODEDEVICEDIR "\\\\.\\Global\\"
+#define SYSDEVICEDIR "\\Device\\"
+#define USERDEVICEDIR "\\DosDevices\\Global\\"
+#define TAPSUFFIX ".tap"
+
+//=========================================================
+// TAP_COMPONENT_ID -- This string defines the TAP driver
+// type -- different component IDs can reside in the system
+// simultaneously.
+//=========================================================
+
+#define TAP_COMPONENT_ID TAP_ID
diff --git a/pwd.ic b/pwd.ic
index 1c988e2..671ddb1 100644
--- a/pwd.ic
+++ b/pwd.ic
@@ -17,6 +17,29 @@
***************************************************************************/
+#ifdef WIN32
+ static void dropPrivileges(char *username, char *groupname, char *chrootdir) {
+ int error = 0;
+ if(strlen(username) > 0) {
+ error = 1;
+ }
+ if(strlen(groupname) > 0) {
+ error = 1;
+ }
+ if(strlen(chrootdir) > 0) {
+ error = 1;
+ }
+ if(error) {
+ throwError("user/group changing not implemented in windows version!\n");
+ }
+ }
+#else
+
+
+#include <pwd.h>
+#include <grp.h>
+
+
// drop privileges
static void dropPrivileges(char *username, char *groupname, char *chrootdir) {
struct passwd *pwd = NULL;
@@ -46,3 +69,6 @@ static void dropPrivileges(char *username, char *groupname, char *chrootdir) {
if(swgroup) if(setgid(grp->gr_gid) < 0) throwError("could not switch group!");
if(swuser) if(setuid(pwd->pw_uid) < 0) throwError("could not switch user!");
}
+
+
+#endif \ No newline at end of file