From 721e4caee0f7c6e003c297c95fb6d93bd4102219 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 29 Jul 2003 22:59:01 +0000 Subject: [PATCH] Native Windows support. --- lib/dropin.c | 16 ++++- lib/dropin.h | 10 ++- src/logger.c | 3 +- src/meta.c | 6 +- src/mingw/device.c | 157 ++++++++++++++++++++++++++++++++++++++++----- src/net.c | 7 +- src/net.h | 6 +- src/net_setup.c | 14 ++-- src/net_socket.c | 18 +++--- src/netutl.c | 26 ++++---- src/protocol.h | 8 ++- src/tincd.c | 13 +++- system.h | 2 +- 13 files changed, 227 insertions(+), 59 deletions(-) diff --git a/lib/dropin.c b/lib/dropin.c index c92c0b81..d4756010 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: dropin.c,v 1.1.2.17 2003/07/28 22:06:09 guus Exp $ + $Id: dropin.c,v 1.1.2.18 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -139,7 +139,7 @@ int asprintf(char **buf, const char *fmt, ...) va_end(ap); if(status >= 0) - *buf = xrealloc(*buf, status); + *buf = xrealloc(*buf, status + 1); if(status > len - 1) { len = status; @@ -159,3 +159,15 @@ int gettimeofday(struct timeval *tv, void *tz) { return 0; } #endif + +#ifndef HAVE_RANDOM +#include + +long int random(void) { + long int x; + + RAND_pseudo_bytes((unsigned char *)&x, sizeof(x)); + + return x; +} +#endif diff --git a/lib/dropin.h b/lib/dropin.h index 3afa69cc..a3afa719 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: dropin.h,v 1.1.2.13 2003/07/18 13:42:35 guus Exp $ + $Id: dropin.h,v 1.1.2.14 2003/07/29 22:59:00 guus Exp $ */ #ifndef __DROPIN_H__ @@ -43,4 +43,12 @@ extern int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); #endif +#ifndef HAVE_GETTIMEOFDAY +extern int gettimeofday(struct timeval *, void *); +#endif + +#ifndef HAVE_RANDOM +extern long int random(void); +#endif + #endif /* __DROPIN_H__ */ diff --git a/src/logger.c b/src/logger.c index 871f2c14..f85bd152 100644 --- a/src/logger.c +++ b/src/logger.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: logger.c,v 1.1.2.7 2003/07/29 10:50:15 guus Exp $ + $Id: logger.c,v 1.1.2.8 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -65,6 +65,7 @@ void logger(int priority, const char *format, ...) { case LOGMODE_STDERR: vfprintf(stderr, format, ap); fprintf(stderr, "\n"); + fflush(stderr); break; case LOGMODE_FILE: fprintf(logfile, "%ld %s[%d]: ", time(NULL), logident, logpid); diff --git a/src/meta.c b/src/meta.c index e818b0b4..0d103c03 100644 --- a/src/meta.c +++ b/src/meta.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: meta.c,v 1.1.2.37 2003/07/22 20:55:19 guus Exp $ + $Id: meta.c,v 1.1.2.38 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -52,7 +52,7 @@ bool send_meta(connection_t *c, char *buffer, int length) bufp = buffer; while(length) { - result = write(c->socket, bufp, length); + result = send(c->socket, bufp, length, 0); if(result <= 0) { if(errno == EINTR) continue; @@ -114,7 +114,7 @@ bool receive_meta(connection_t *c) - If not, keep stuff in buffer and exit. */ - lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen); + lenin = recv(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen, 0); if(lenin <= 0) { if(lenin == 0) { diff --git a/src/mingw/device.c b/src/mingw/device.c index d005a63b..dfda0895 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.5 2003/07/29 12:38:49 guus Exp $ + $Id: device.c,v 1.1.2.6 2003/07/29 22:59:01 guus Exp $ */ #include "system.h" @@ -51,7 +51,8 @@ /* FIXME: This only works for Windows 2000 */ #define OSTYPE 5 -HANDLE device_fd = INVALID_HANDLE_VALUE; +int device_fd = 0; +HANDLE device_handle = INVALID_HANDLE_VALUE; char *device = NULL; char *iface = NULL; char *device_info = NULL; @@ -59,6 +60,72 @@ char *device_info = NULL; int device_total_in = 0; int device_total_out = 0; +DWORD WINAPI tapreader(void *bla) { + int sock, err, status; + struct addrinfo *ai; + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP, + .ai_flags = 0, + }; + char buf[MTU]; + long len; + OVERLAPPED overlapped; + + /* Open a socket to the parent process */ + + err = getaddrinfo(NULL, "12345", &hint, &ai); + + if(err || !ai) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); + return -1; + } + + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + + freeaddrinfo(ai); + + if(sock < 0) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); + return -1; + } + + if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "connect", strerror(errno)); + return -1; + } + + logger(LOG_DEBUG, _("Tap reader running")); + + /* Read from tap device and send to parent */ + + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + for(;;) { + overlapped.Offset = 0; + overlapped.OffsetHigh = 0; + ResetEvent(overlapped.hEvent); + + status = ReadFile(device_handle, buf, sizeof(buf), &len, &overlapped); + + if(!status) { + if(GetLastError() == ERROR_IO_PENDING) { + WaitForSingleObject(overlapped.hEvent, INFINITE); + if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE)) + continue; + } else { + logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } + } + + if(send(sock, buf, len, 0) <= 0) + return -1; + } +} + bool setup_device(void) { HKEY key, key2; @@ -68,11 +135,21 @@ bool setup_device(void) char adapterid[1024]; char adaptername[1024]; char tapname[1024]; - char gelukt = 0; long len; bool found = false; + int sock, err; + HANDLE thread; + + struct addrinfo *ai; + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP, + .ai_flags = AI_PASSIVE, + }; + cp(); get_config_string(lookup_config(config_tree, "Device"), &device); @@ -117,8 +194,8 @@ bool setup_device(void) } snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); - device_fd = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); - if(device_fd != INVALID_HANDLE_VALUE) { + device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + if(device_handle != INVALID_HANDLE_VALUE) { found = true; break; } @@ -129,24 +206,27 @@ bool setup_device(void) return false; } - device = adapterid; - iface = adaptername; + if(!device) + device = xstrdup(adapterid); + + if(!iface) + iface = xstrdup(adaptername); /* Try to open the corresponding tap device */ - if(device_fd == INVALID_HANDLE_VALUE) { + if(device_handle == INVALID_HANDLE_VALUE) { snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device); - device_fd = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); } - if(device_fd == INVALID_HANDLE_VALUE) { + if(device_handle == INVALID_HANDLE_VALUE) { logger(LOG_ERR, _("%s (%s) is no a usable Windows tap device!"), device, iface); return false; } /* Get MAC address from tap device */ - if(!DeviceIoControl(device_fd, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { + if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { logger(LOG_ERR, _("Could not get MAC address from Windows tap device!")); return false; } @@ -155,6 +235,52 @@ bool setup_device(void) overwrite_mac = 1; } + /* Create a listening socket */ + + err = getaddrinfo(NULL, "12345", &hint, &ai); + + if(err || !ai) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); + return false; + } + + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + + if(sock < 0) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); + return false; + } + + if(bind(sock, ai->ai_addr, ai->ai_addrlen)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "bind", strerror(errno)); + return false; + } + + freeaddrinfo(ai); + + if(listen(sock, 1)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); + return false; + } + + /* Start the tap reader */ + + thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL); + + if(!thread) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "CreateThread", strerror(errno)); + return false; + } + + /* Wait for the tap reader to connect back to us */ + + if((device_fd = accept(sock, NULL, 0)) == -1) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "accept", strerror(errno)); + return false; + } + + closesocket(sock); + device_info = _("Windows tap device"); logger(LOG_INFO, _("%s (%s) is a %s"), device, iface, device_info); @@ -166,16 +292,16 @@ void close_device(void) { cp(); - CloseHandle(device_fd); + CloseHandle(device_handle); } bool read_packet(vpn_packet_t *packet) { - long lenin; + int lenin; cp(); - if(!ReadFile(device_fd, packet->data, MTU, &lenin, NULL)) { + if((lenin = recv(device_fd, packet->data, MTU, 0)) <= 0) { logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); return false; @@ -194,13 +320,14 @@ bool read_packet(vpn_packet_t *packet) bool write_packet(vpn_packet_t *packet) { long lenout; + OVERLAPPED overlapped = {0}; cp(); ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"), packet->len, device_info); - if(!WriteFile(device_fd, packet->data, packet->len, &lenout, NULL)) { + if(!WriteFile(device_handle, packet->data, packet->len, &lenout, &overlapped)) { logger(LOG_ERR, _("Error while writing to %s %s"), device_info, device); return false; } diff --git a/src/net.c b/src/net.c index c4637dab..e1580e65 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.194 2003/07/29 10:50:15 guus Exp $ + $Id: net.c,v 1.35.4.195 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -39,6 +39,7 @@ #include "protocol.h" #include "route.h" #include "subnet.h" +#include "xalloc.h" bool do_purge = false; @@ -153,7 +154,7 @@ void terminate_connection(connection_t *c, bool report) c->node->connection = NULL; if(c->socket) - close(c->socket); + closesocket(c->socket); if(c->edge) { if(report) @@ -254,7 +255,7 @@ static void check_network_activity(fd_set * f) ifdebug(CONNECTIONS) logger(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result)); - close(c->socket); + closesocket(c->socket); do_outgoing_connection(c); continue; } diff --git a/src/net.h b/src/net.h index 8ab33615..f1494666 100644 --- a/src/net.h +++ b/src/net.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.h,v 1.9.4.67 2003/07/24 12:08:15 guus Exp $ + $Id: net.h,v 1.9.4.68 2003/07/29 22:59:00 guus Exp $ */ #ifndef __TINC_NET_H__ @@ -140,4 +140,8 @@ extern void terminate_connection(struct connection_t *, bool); extern void flush_queue(struct node_t *); extern bool read_rsa_public_key(struct connection_t *); +#ifndef HAVE_MINGW +#define closesocket(s) close(s) +#endif + #endif /* __TINC_NET_H__ */ diff --git a/src/net_setup.c b/src/net_setup.c index 6f7f70ad..3695e18e 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_setup.c,v 1.1.2.39 2003/07/23 22:17:31 guus Exp $ + $Id: net_setup.c,v 1.1.2.40 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -444,14 +444,14 @@ bool setup_myself(void) /* Open sockets */ - memset(&hint, 0, sizeof(hint)); - get_config_string(lookup_config(config_tree, "BindToAddress"), &address); - hint.ai_family = addressfamily; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - hint.ai_flags = AI_PASSIVE; + hint = (struct addrinfo) { + .ai_family = addressfamily, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + .ai_flags = AI_PASSIVE, + }; err = getaddrinfo(address, myport, &hint, &ai); diff --git a/src/net_socket.c b/src/net_socket.c index 5f9e2173..78e1ad2c 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_socket.c,v 1.1.2.32 2003/07/28 22:06:09 guus Exp $ + $Id: net_socket.c,v 1.1.2.33 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -70,7 +70,7 @@ int setup_listen_socket(const sockaddr_t *sa) flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { - close(nfd); + closesocket(nfd); logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); return -1; @@ -98,7 +98,7 @@ int setup_listen_socket(const sockaddr_t *sa) strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) { - close(nfd); + closesocket(nfd); logger(LOG_ERR, _("Can't bind to interface %s: %s"), iface, strerror(errno)); return -1; @@ -109,7 +109,7 @@ int setup_listen_socket(const sockaddr_t *sa) } if(bind(nfd, &sa->sa, SALEN(sa->sa))) { - close(nfd); + closesocket(nfd); addrstr = sockaddr2hostname(sa); logger(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno)); @@ -118,7 +118,7 @@ int setup_listen_socket(const sockaddr_t *sa) } if(listen(nfd, 3)) { - close(nfd); + closesocket(nfd); logger(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); return -1; @@ -149,7 +149,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) #ifdef O_NONBLOCK flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { - close(nfd); + closesocket(nfd); logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); return -1; @@ -166,7 +166,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) { - close(nfd); + closesocket(nfd); logger(LOG_ERR, _("Can't bind to interface %s: %s"), iface, strerror(errno)); return -1; @@ -175,7 +175,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) #endif if(bind(nfd, &sa->sa, SALEN(sa->sa))) { - close(nfd); + closesocket(nfd); addrstr = sockaddr2hostname(sa); logger(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno)); @@ -308,7 +308,7 @@ begin: return; } - close(c->socket); + closesocket(c->socket); ifdebug(CONNECTIONS) logger(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); diff --git a/src/netutl.c b/src/netutl.c index cd50792f..1ec6e5a8 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: netutl.c,v 1.12.4.49 2003/07/24 12:08:15 guus Exp $ + $Id: netutl.c,v 1.12.4.50 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -36,16 +36,15 @@ bool hostnames = false; */ struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) { - struct addrinfo hint, *ai; + struct addrinfo *ai; + struct addrinfo hint = { + .ai_family = addressfamily, + .ai_socktype = socktype, + }; int err; cp(); - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = addressfamily; - hint.ai_socktype = socktype; - err = getaddrinfo(address, service, &hint, &ai); if(err) { @@ -59,18 +58,17 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock sockaddr_t str2sockaddr(const char *address, const char *port) { - struct addrinfo hint, *ai; + struct addrinfo *ai; + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_NUMERICHOST, + .ai_socktype = SOCK_STREAM, + }; sockaddr_t result; int err; cp(); - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = AF_UNSPEC; - hint.ai_flags = AI_NUMERICHOST; - hint.ai_socktype = SOCK_STREAM; - err = getaddrinfo(address, port, &hint, &ai); if(err || !ai) { diff --git a/src/protocol.h b/src/protocol.h index 0eae830d..7a32a17a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol.h,v 1.5.4.42 2003/07/29 10:50:15 guus Exp $ + $Id: protocol.h,v 1.5.4.43 2003/07/29 22:59:00 guus Exp $ */ #ifndef __TINC_PROTOCOL_H__ @@ -29,6 +29,12 @@ #define PROT_CURRENT 17 +/* Silly Windows */ + +#ifdef ERROR +#undef ERROR +#endif + /* Request numbers */ typedef enum request_t { diff --git a/src/tincd.c b/src/tincd.c index d2179ab1..6b90de76 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: tincd.c,v 1.10.4.77 2003/07/28 22:06:09 guus Exp $ + $Id: tincd.c,v 1.10.4.78 2003/07/29 22:59:00 guus Exp $ */ #include "system.h" @@ -93,6 +93,10 @@ static struct option const long_options[] = { {NULL, 0, NULL, 0} }; +#ifdef HAVE_MINGW +static struct WSAData wsa_state; +#endif + static void usage(bool status) { if(status) @@ -417,6 +421,13 @@ int main(int argc, char **argv, char **envp) exit(1); } +#ifdef HAVE_MINGW + if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "WSAStartup", strerror(errno)); + exit(1); + } +#endif + if(!detach()) exit(1); diff --git a/system.h b/system.h index d4381dc5..73f7aeb1 100644 --- a/system.h +++ b/system.h @@ -115,7 +115,7 @@ #ifdef HAVE_MINGW #include -#include +#include #endif /* Include localisation support */ -- 2.20.1