Scurry (empty) → 0.0.1
raw patch · 8 files changed
+1140/−0 lines, 8 filesdep +basedep +binarydep +bytestringsetup-changed
Dependencies added: base, binary, bytestring, containers, network, network-bytestring, parsec, random, stm, time, unix
Files
- LICENSE +27/−0
- Scurry.cabal +72/−0
- Setup.hs +4/−0
- src/C/help-bsd.c +153/−0
- src/C/help-linux.c +161/−0
- src/C/help-win.c +529/−0
- src/C/help.h +57/−0
- src/scurry.hs +137/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++Redistributions of source code must retain the above copyright+notice, this list of conditions and the following disclaimer.++Redistributions in binary form must reproduce the above copyright+notice, this list of conditions and the following disclaimer in the+documentation and/or other materials provided with the distribution.++The name of John Van Enk; nor the names of his contributors+may be used to endorse or promote products derived from this software+without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Scurry.cabal view
@@ -0,0 +1,72 @@+Name: Scurry+Version: 0.0.1+Category: Network+Description: A distributed VPN system written in Haskell.+License: BSD3+License-File: LICENSE+Author: John Van Enk+Maintainer: vanenkj@gmail.com+Copyright: John Van Enk, 2009++Synopsis: A cross platform P2P VPN application built using Haskell.+Stability: Experimental++Description: P2P VPN implementation currently without any encryption.+ Supports Windows and Unix variants. Features include:+ .+ * Simple NAT Traversal using UDP (similar to STUN, not the same).+ .+ * Automatic address assignment to new peers+ .+ * Emulates a LAN between machines+ .+ Note: Scurry currently has no encryption layer or authentication+ mechanism at all. Also, the packet switching is currently+ implemented using Data.List.lookup as opposed to something+ more appropriate. This really isn't much of a problem until+ you hit hundreds or thousands of peers.+ .+ Requires a TAP-Win32 driver to run in Windows. Requires the tun+ module to be loaded to run in Linux (expects \/dev\/net\/tun).++Homepage: http://code.google.com/p/scurry/++Cabal-Version: >= 1.2.0+Build-Type: Simple++extra-source-files: src/C/help.h++executable scurry+ build-depends: base >= 3.0.0.0+ build-depends: binary >= 0.4.3.1+ build-depends: network >= 2.1.0.0+ build-depends: network-bytestring >= 0.1.1.2+ build-depends: bytestring >= 0.9.1.3+ build-depends: stm >= 2.1.1.0+ build-depends: parsec >= 3.0.0+ build-depends: containers+ build-depends: time >= 1.1.2.2+ build-depends: random >= 1.0.0.0++ if os(mingw32)+ c-sources: src/C/help-win.c+ extra-libraries: Iphlpapi, ws2_32+ cc-options: -D MINGW32+ cpp-options: -DCALLCONV=stdcall++ if os(linux)+ build-depends: unix >= 2.3.0.0+ c-sources: src/C/help-linux.c+ cc-options: -D LINUX+ cpp-options: -DCALLCONV=ccall++ if os(darwin) || os(freebsd)+ build-depends: unix >= 2.3.0.0+ c-sources: src/C/help-bsd.c+ cc-options: -D BSD+ cpp-options: -DCALLCONV=ccall+ + hs-source-dirs: src+ ghc-options: -Wall -threaded+ main-is: scurry.hs+
+ Setup.hs view
@@ -0,0 +1,4 @@+module Main where++import Distribution.Simple+main = defaultMain
+ src/C/help-bsd.c view
@@ -0,0 +1,153 @@+#include <sys/ioctl.h>+#include <arpa/inet.h>+#include <errno.h>+#include <fcntl.h>+#include <sys/select.h>+#include <sys/socket.h>+#include <sys/stat.h>+#include <net/if.h>+#include <net/if_dl.h>+#include <net/route.h>+#include <netinet/in.h>+#include <stdarg.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <unistd.h>+#include <ifaddrs.h>++#include "help.h"+#include "tun_ioctls.h"++int get_mac(struct ifreq * ifr, int sock, struct tap_info * ti);++static int set_ip(struct ifreq * ifr, int sock, ip4_addr_t ip, ip4_addr_t mask);+static int set_mtu(struct ifreq * ifr, int sock, unsigned int mtu);++int open_tap(ip4_addr_t local_ip, ip4_addr_t local_mask, struct tap_info * ti)+{+ struct ifreq ifr_tap;+ int r = 0;++ int fd = -1;+ int sock = -1;++ if ((fd = open("/dev/tap0", O_RDWR)) < 0)+ return -1;++ memset(&ifr_tap, 0, sizeof(ifr_tap));++ /* setup tap */+ strncpy(ifr_tap.ifr_name, "tap0", IFNAMSIZ);+ + /*+ if ((ioctl(fd, TUNSIFHEAD, (void *)&ifr_tap)) < 0)+ return -2;+ */+ + /* setup ip */+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)+ return -3;++ if (set_ip(&ifr_tap, sock, local_ip, local_mask) < 0)+ return -4;++ if ( ioctl(sock, SIOCGIFFLAGS, &ifr_tap) < 0)+ return -6;++ if ( get_mac(&ifr_tap, sock, ti) < 0)+ return -7;++ ifr_tap.ifr_flags |= IFF_UP;+ ifr_tap.ifr_flags |= IFF_RUNNING;++ if (ioctl(sock, SIOCSIFFLAGS, &ifr_tap) < 0)+ return -8;++ if (set_mtu(&ifr_tap, sock, 1200) < 0)+ return -9;++ ti->desc->desc = fd;++ return fd;+}++static int set_ip(struct ifreq * ifr, int sock, ip4_addr_t ip, ip4_addr_t mask)+{+ /* Setting a single address of an interface is depreciated. Now uses ifaliasreq and it is done in one call */+ struct ifaliasreq ifa;+ struct sockaddr_in *in;+ + memset(&ifa, 0, sizeof(ifa));+ strcpy(ifa.ifra_name, ifr->ifr_name);+ + in = (struct sockaddr_in *) &ifa.ifra_addr;+ in->sin_family = AF_INET;+ in->sin_len = sizeof(ifa.ifra_addr);+ in->sin_addr.s_addr = ip;+ + in = (struct sockaddr_in *) &ifa.ifra_mask;+ in->sin_family = AF_INET;+ in->sin_len = sizeof(ifa.ifra_mask);+ in->sin_addr.s_addr = mask;+ + if ( ioctl(sock, SIOCSIFADDR, &ifa) < 0) {+ printf("SIOCAIFADDR: %s\n", strerror(errno));+ return -1;+ }++ return 0; +}++static int set_mtu(struct ifreq * ifr, int sock, unsigned int mtu)+{+ /* Set the MTU of the tap interface */+ ifr->ifr_mtu = mtu; + if (ioctl(sock, SIOCSIFMTU, ifr) < 0) {+ printf("SIOCSIFMTU: %s\n", strerror(errno));+ return -1;+ }++ return 0;+}++void close_tap(union tap_desc * td)+{+ if (0 <= td->desc) + {+ close(td->desc);+ }+}++int get_mac(struct ifreq * ifr, int sock, struct tap_info * ti)+{+ struct ifaddrs *ifap;+ + if (getifaddrs(&ifap) == 0) {+ struct ifaddrs *p;+ for (p = ifap; p; p = p->ifa_next) {+ if (p->ifa_addr->sa_family == AF_LINK && strncmp(((struct sockaddr_dl *) p->ifa_addr)->sdl_data, "tap", 3) == 0) {+ struct sockaddr_dl *sdp = (struct sockaddr_dl *) p->ifa_addr;+ memcpy(&(ti->mac), LLADDR(sdp), 6);+ freeifaddrs(ifap);+ return 0;+ }+ }+ freeifaddrs(ifap);+ }++ printf("Unable to get MAC address.");+ return -1; +}++int read_tap(union tap_desc * td, char * buf, int len)+{ + int ret = read(td->desc,buf,len);+ return ret;+}++int write_tap(union tap_desc * td, const char * buf, int len)+{+ int ret = write(td->desc,buf,len);+ return ret;+}
+ src/C/help-linux.c view
@@ -0,0 +1,161 @@+#include <arpa/inet.h>+#include <errno.h>+#include <fcntl.h>+#include <linux/if.h>+#include <linux/if_tun.h>+#include <net/route.h>+#include <netinet/if_ether.h>+#include <netinet/in.h>+#include <netinet/ip.h>+#include <stdarg.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <sys/ioctl.h>+#include <sys/socket.h>+#include <sys/stat.h>+#include <unistd.h>++#include "help.h"++int open_tap(ip4_addr_t local_ip, ip4_addr_t local_mask, struct tap_info * ti);+int get_mac(struct ifreq * ifr, int sock, struct tap_info * ti);+void close_tap(union tap_desc * td);++static int set_ip(struct ifreq * ifr, int sock, ip4_addr_t ip4);+static int set_mask(struct ifreq * ifr, int sock, ip4_addr_t ip4);+static int set_mtu(struct ifreq * ifr, int sock, unsigned int mtu);+++int open_tap(ip4_addr_t local_ip, ip4_addr_t local_mask, struct tap_info * ti)+{+ struct ifreq ifr_tap;+ int r = 0;++ int fd = -1;+ int sock = -1;++ if ((fd = open("/dev/net/tun", O_RDWR)) < 0)+ return -1;++ memset(&ifr_tap, 0, sizeof(ifr_tap));++ /* setup tap */+ ifr_tap.ifr_flags = IFF_TAP | IFF_NO_PI;++ if ((ioctl(fd, TUNSETIFF, (void *)&ifr_tap)) < 0)+ return -2;+ + /* setup ip */+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)+ return -3;++ if (set_ip(&ifr_tap, sock, local_ip) < 0)+ return -4;++ if (set_mask(&ifr_tap, sock, local_mask) < 0)+ return -5;++ if ( ioctl(sock, SIOCGIFFLAGS, &ifr_tap) < 0)+ return -6;++ if ( get_mac(&ifr_tap,sock,ti) < 0)+ return -7;++ ifr_tap.ifr_flags |= IFF_UP;+ ifr_tap.ifr_flags |= IFF_RUNNING;++ if (ioctl(sock, SIOCSIFFLAGS, &ifr_tap) < 0)+ return -8;++ if (set_mtu(&ifr_tap, sock, 1200) < 0)+ return -9;++ ti->desc->desc = fd;++ return fd;+}++static int set_ip(struct ifreq * ifr, int sock, ip4_addr_t ip4)+{+ struct sockaddr_in addr;++ /* set the IP of this end point of tunnel */+ memset( &addr, 0, sizeof(addr) );+ addr.sin_addr.s_addr = ip4; /*network byte order*/+ addr.sin_family = AF_INET;+ memcpy( &ifr->ifr_addr, &addr, sizeof(struct sockaddr) );++ if ( ioctl(sock, SIOCSIFADDR, ifr) < 0) {+ printf("SIOCSIFADDR: %s\n", strerror(errno));+ return -1;+ }++ return 0; +}++static int set_mask(struct ifreq * ifr, int sock, ip4_addr_t ip4)+{+ struct sockaddr_in addr;++ memset( &addr, 0, sizeof(addr) );+ addr.sin_addr.s_addr = ip4; /*network byte order*/+ addr.sin_family = AF_INET;+ memcpy( &ifr->ifr_addr, &addr, sizeof(struct sockaddr) );+ + if ( ioctl(sock, SIOCSIFNETMASK, ifr) < 0) {+ printf("SIOCSIFNETMASK: %s\n", strerror(errno));+ return -1;+ }++ return 0;+}++static int set_mtu(struct ifreq * ifr, int sock, unsigned int mtu)+{+ /* Set the MTU of the tap interface */+ ifr->ifr_mtu = mtu; + if (ioctl(sock, SIOCSIFMTU, ifr) < 0) {+ printf("SIOCSIFMTU: %s\n", strerror(errno));+ return -1;+ }++ return 0;+}++void close_tap(union tap_desc * td)+{+ if (0 <= td->desc) + {+ close(td->desc);+ }+}++int get_mac(struct ifreq * ifr, int sock, struct tap_info * ti)+{+ + if ( ioctl(sock, SIOCGIFHWADDR, ifr) < 0) {+ printf("SIOCGIFHWADDR: %s\n", strerror(errno));+ return -1;+ }+ else+ {+ memcpy(&(ti->mac),&(ifr->ifr_hwaddr.sa_data),6);+ }+++ return 0;+}++/* I HATE WINDOWS IT SUCKS SO HARD AHHH!! */+int read_tap(union tap_desc * td, char * buf, int len)+{+ int ret = read(td->desc,buf,len);+ return ret;+}++int write_tap(union tap_desc * td, const char * buf, int len)+{+ int ret = write(td->desc,buf,len);+ return ret;+}
+ src/C/help-win.c view
@@ -0,0 +1,529 @@+/* NOTE: most of this code is a direct copy of the qemu tap code+*/++#include <stdio.h>+#include <wchar.h>+#define WIN32_LEAN_AND_MEAN+#include <windows.h>+#include <winioctl.h>+#include <ws2tcpip.h>+#include <iphlpapi.h>+#include <io.h>+#include <Fcntl.h>+#include <malloc.h>++//=============+// TAP IOCTLs+//=============++#define TAP_CONTROL_CODE(request,method) \+ CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)++#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)++//=================+// 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 TAPSUFFIX ".tap"++#define TAP_COMPONENT_ID "tap0801"++//======================+// Compile time configuration+//======================++//#define DEBUG_TAP_WIN32 1++#define TUN_ASYNCHRONOUS_WRITES 1++#define TUN_BUFFER_SIZE 1560+#define TUN_MAX_BUFFER_COUNT 32+ ++#include "help.h"++static OVERLAPPED overlap_read, overlap_write;+++int open_tap(ip4_addr_t local_ip, ip4_addr_t local_mask, struct tap_info * ti);++static const IP_ADAPTER_INFO *+get_adapter (const IP_ADAPTER_INFO *ai, DWORD index)+{+ if (ai && index != (DWORD)~0)+ {+ const IP_ADAPTER_INFO *a;++ /* find index in the linked list */+ for (a = ai; a != NULL; a = a->Next)+ {+ if (a->Index == index)+ return a;+ }+ }+ return NULL;+}+++static void+delete_temp_addresses (DWORD index)+{+ ULONG size = 4096;+ DWORD status;+ IP_ADAPTER_INFO *adapters = (IP_ADAPTER_INFO *) malloc(size);+ if ((status = GetAdaptersInfo (adapters, &size)) != NO_ERROR)+ return;+ + const IP_ADAPTER_INFO *a = get_adapter(adapters, index);++ if (a)+ {+ const IP_ADDR_STRING *ip = &a->IpAddressList;+ while (ip)+ {+ + const DWORD context = ip->Context;++ if ((status = DeleteIPAddress ((ULONG) context)) == NO_ERROR)+ {+ //msg (M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s", ip->IpAddress.String, ip->IpMask.String);+ }+ else+ {+ const char *empty = "0.0.0.0";+ if (strcmp (ip->IpAddress.String, empty)+ || strcmp (ip->IpMask.String, empty)) {}+ //msg (M_INFO, "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)", ip->IpAddress.String, ip->IpMask.String, (unsigned int)status);+ }+ ip = ip->Next;+ }+ }+ free(adapters);+}++static int is_tap_win32_dev(const char *guid)+{+ HKEY netcard_key;+ LONG status;+ DWORD len;+ int i = 0;++ status = RegOpenKeyEx(+ HKEY_LOCAL_MACHINE,+ (LPCTSTR) ADAPTER_KEY,+ 0,+ KEY_READ,+ (PHKEY)&netcard_key);++ if (status != ERROR_SUCCESS) {+ return FALSE;+ }++ for (;;) {+ char enum_name[256];+ char unit_string[256];+ HKEY unit_key;+ char component_id_string[] = "ComponentId";+ char component_id[256];+ char net_cfg_instance_id_string[] = "NetCfgInstanceId";+ char net_cfg_instance_id[256];+ DWORD data_type;++ len = sizeof (enum_name);+ status = RegEnumKeyEx(+ netcard_key,+ i,+ (LPTSTR) enum_name,+ &len,+ NULL,+ NULL,+ NULL,+ NULL);++ if (status == ERROR_NO_MORE_ITEMS)+ break;+ else if (status != ERROR_SUCCESS) {+ return FALSE;+ }++ snprintf (unit_string, sizeof(unit_string), "%s\\%s",+ ADAPTER_KEY, enum_name);++ status = RegOpenKeyEx(+ HKEY_LOCAL_MACHINE,+ (LPCTSTR) unit_string,+ 0,+ KEY_READ,+ &unit_key);++ if (status != ERROR_SUCCESS) {+ return FALSE;+ } else {+ len = sizeof (component_id);+ status = RegQueryValueEx(+ unit_key,+ (LPCTSTR) component_id_string,+ NULL,+ &data_type,+ component_id,+ &len);++ if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {+ len = sizeof (net_cfg_instance_id);+ status = RegQueryValueEx(+ unit_key,+ (LPCTSTR) net_cfg_instance_id_string,+ NULL,+ &data_type,+ net_cfg_instance_id,+ &len);++ if (status == ERROR_SUCCESS && data_type == REG_SZ) {+ if (!strcmp (component_id, TAP_COMPONENT_ID) &&+ !strcmp (net_cfg_instance_id, guid)) {+ RegCloseKey (unit_key);+ RegCloseKey (netcard_key);+ return TRUE;+ }+ }+ }+ RegCloseKey (unit_key);+ }+ ++i;+ }++ RegCloseKey (netcard_key);+ return FALSE;+}++static int get_device_guid(+ char *name,+ int name_size,+ char *actual_name,+ int actual_name_size)+{+ LONG status;+ HKEY control_net_key;+ DWORD len;+ int i = 0;+ int stop = 0;++ status = RegOpenKeyEx(+ HKEY_LOCAL_MACHINE,+ (LPCTSTR) NETWORK_CONNECTIONS_KEY,+ 0,+ KEY_READ,+ &control_net_key);++ if (status != ERROR_SUCCESS) {+ return -1;+ }++ while (!stop)+ {+ char enum_name[256];+ char connection_string[256];+ HKEY connection_key;+ char name_data[256];+ DWORD name_type;+ const char name_string[] = "Name";++ len = sizeof (enum_name);+ status = RegEnumKeyEx(+ control_net_key,+ i,+ (LPTSTR) enum_name,+ &len,+ NULL,+ NULL,+ NULL,+ NULL);++ if (status == ERROR_NO_MORE_ITEMS)+ break;+ else if (status != ERROR_SUCCESS) {+ return -1;+ }++ snprintf(connection_string,+ sizeof(connection_string),+ "%s\\%s\\Connection",+ NETWORK_CONNECTIONS_KEY, enum_name);++ status = RegOpenKeyEx(+ HKEY_LOCAL_MACHINE,+ (LPCTSTR) connection_string,+ 0,+ KEY_READ,+ &connection_key);++ if (status == ERROR_SUCCESS) {+ len = sizeof (name_data);+ status = RegQueryValueEx(+ connection_key,+ (LPTSTR) name_string,+ NULL,+ &name_type,+ name_data,+ &len);++ if (status != ERROR_SUCCESS || name_type != REG_SZ) {+ return -1;+ }+ else {+ if (is_tap_win32_dev(enum_name)) {+ snprintf(name, name_size, "%s", enum_name);+ if (actual_name) {+ if (strcmp(actual_name, "") != 0) {+ if (strcmp(name_data, actual_name) != 0) {+ RegCloseKey (connection_key);+ ++i;+ continue;+ }+ }+ else {+ snprintf(actual_name, actual_name_size, "%s", name_data);+ }+ }+ stop = 1;+ }+ }++ RegCloseKey (connection_key);+ }+ ++i;+ }++ RegCloseKey (control_net_key);++ if (stop == 0)+ return -1;++ return 0;+}++static DWORD get_interface_index (const char *guid)+{+ ULONG index;+ DWORD status;+ wchar_t wbuf[256];+ snwprintf (wbuf, sizeof (wbuf), L"\\DEVICE\\TCPIP_%S", guid);+ wbuf [sizeof(wbuf) - 1] = 0;+ if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR)+ return (DWORD)~0;+ else+ return index;+}++static int tap_win32_set_status(HANDLE handle, int status)+{+ unsigned long len = 0;++ return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,+ &status, sizeof (status),+ &status, sizeof (status), &len, NULL);+}++int open_tap(ip4_addr_t local_ip, ip4_addr_t local_mask, struct tap_info * ti)+{+ // #TODO this function needs some pretty heavy cleanup+ const char *prefered_name = NULL;+ + DWORD err;+ char device_path[256];+ char device_guid[0x100];+ int rc;+ HANDLE handle;+ DWORD index;+ ULONG ipapi_context;+ ULONG ipapi_instance;+ BOOL bret;+ char name_buffer[0x100] = {0, };+ struct {+ unsigned long major;+ unsigned long minor;+ unsigned long debug;+ } version;+ DWORD len;++ if (prefered_name != NULL)+ snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);++ rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));+ if (rc)+ return -1;+ index = get_interface_index(device_guid);++ snprintf (device_path, sizeof(device_path), "%s%s%s",+ USERMODEDEVICEDIR,+ device_guid,+ TAPSUFFIX);++ handle = CreateFile (+ (LPCTSTR) device_path,+ GENERIC_READ | GENERIC_WRITE,+ 0,+ 0,+ OPEN_EXISTING,+ FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,+ 0 );++ if (handle == INVALID_HANDLE_VALUE) {+ return -2;+ }++ bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,+ &version, sizeof (version),+ &version, sizeof (version), &len, NULL);++ if (bret == FALSE) {+ CloseHandle(handle);+ return -3;+ }+ + if(!DeviceIoControl(handle, TAP_IOCTL_GET_MAC, ti->mac, 6, ti->mac, 6, &len, 0)) {+ return -4;+ }+ + uint32_t ep[4];+ ep[0] = local_ip;+ ep[1] = local_mask;+ ep[2] = 0xFE00000A;+ ep[3] = 0x00FFFFFF;+ if (!DeviceIoControl (handle, TAP_IOCTL_CONFIG_DHCP_MASQ,+ ep, sizeof (ep),+ ep, sizeof (ep), &len, NULL))+ return -5;+ + if (!tap_win32_set_status(handle, TRUE)) {+ return -6;+ }+ + FlushIpNetTable(index);+ + overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);+ overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);+ if (!overlap_read.hEvent || !overlap_write.hEvent) {+ return -7;+ }+ + // delete_temp_addresses (index);+ + // printf("%x\n", local_ip);+ // if ((err = AddIPAddress (local_ip,+ // local_mask,+ // index,+ // &ipapi_context,+ // &ipapi_instance)) != NO_ERROR)+ // {+ // printf("AddIPAddress failed! (%d)\n", err);++ // LPVOID lpMsgBuf;++ // if (5010 != err) {+ // if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |+ // FORMAT_MESSAGE_FROM_SYSTEM |+ // FORMAT_MESSAGE_IGNORE_INSERTS,+ // NULL, err,+ // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),+ // (LPTSTR) & lpMsgBuf, 0, NULL)) {+ // printf("\tError: %s", lpMsgBuf);+ // LocalFree(lpMsgBuf);+ // }+ // return -5;+ // }+ // }+ // if (AddIPAddress (local_ip,+ // local_mask,+ // index,+ // &ipapi_context,+ // &ipapi_instance) != NO_ERROR)+ // return -7;+ +++ + ti->desc->desc = handle;+ ti->desc->context = ipapi_context;+ + return 0;+}+++void close_tap(union tap_desc * td)+{+ //DeleteIPAddress(td->context);+ CloseHandle(td->desc);+}+++/* Read a frame from a tap device. The buffer needs+ * to be at least as large as the MTU of the device. */+int read_tap(union tap_desc * td, char * buf, int len)+{+ DWORD read_size;+ + ResetEvent(overlap_read.hEvent);+ if (ReadFile(td->desc, buf, len, &read_size, &overlap_read)) {+ return read_size;+ }+ switch (GetLastError()) {+ case ERROR_IO_PENDING:+ WaitForSingleObject(overlap_read.hEvent, INFINITE);+ GetOverlappedResult(td->desc, &overlap_read, &read_size, FALSE);+ return read_size;+ break;+ default:+ break;+ }+ + return -1;+}++/* Write a frame to a tap device. The frame length+ * must be less than the MTU of the device. */+int write_tap(union tap_desc * td, const char * buf, int len)+{ + DWORD write_size;+ + ResetEvent(overlap_write.hEvent);+ if (WriteFile(td->desc,+ buf,+ len,+ &write_size,+ &overlap_write)) {+ return write_size;+ }+ switch (GetLastError()) {+ case ERROR_IO_PENDING:+ WaitForSingleObject(overlap_write.hEvent, INFINITE);+ GetOverlappedResult(td->desc, &overlap_write,+ &write_size, FALSE);+ return write_size;+ break;+ default:+ break;+ }+ + return -1;+}++
+ src/C/help.h view
@@ -0,0 +1,57 @@+#ifndef __HELP_HASKELL_VPN__+#define __HELP_HASKELL_VPN__ __HELP_HASKELL_VPN__++#include <assert.h>++typedef uint32_t ip4_addr_t;++#define TAP_DESC_SIZE 32++/* A union that serves to be a common storage medium for+ * whatever the OS wants to use as a device descriptor+ * for the TAP device. In Linux, this is just a file + * descriptor. */+union tap_desc {+ char pad[TAP_DESC_SIZE];+#if defined(MINGW32)+ struct+ {+ HANDLE desc;+ unsigned long context;+ };+#elif defined(LINUX)+ int desc;+#elif defined(BSD)+ int desc;+#else+ #error "ERROR: This platform not supported."+#endif+};++/* A struct used to pass information about+ * a tap device around. */+struct tap_info {+ union tap_desc * desc;+ char mac[8]; /* Use 8, instead of 6, to force alignment */+};++/* Open a tap device. The file descriptor and the+ * MAC address are written to the tap_info struct.+ * On failure, a negative value is returned. */+int open_tap(ip4_addr_t local_ip,+ ip4_addr_t local_mask,+ struct tap_info * ti);++/* Close a tap device. */+void close_tap(union tap_desc * td);++/* Read a frame from a tap device. The buffer needs+ * to be at least as large as the MTU of the device. */+int read_tap(union tap_desc * td, char * buf, int len);++/* Write a frame to a tap device. The frame length+ * must be less than the MTU of the device. */+int write_tap(union tap_desc * td, const char * buf, int len);++#endif /* __HELP_HASKELL_VPN__ */+
+ src/scurry.hs view
@@ -0,0 +1,137 @@+module Main where++import System.Console.GetOpt+import System.Environment+import System.IO+import System.Exit++import Network.Socket (withSocketsDo)+import Network.BSD++import Scurry.Peer+import Scurry.Comm+-- import Scurry.Management.Config+-- import Scurry.Management.Tracker+import Scurry.State+import Scurry.Util(inet_addr)+import Scurry.Network+import Scurry.Types.Network+import Data.Word+import Data.Maybe++data ScurryOpts = ScurryOpts {+ vpnAddr :: Maybe ScurryAddress,+ vpnMask :: Maybe ScurryMask,+ bindAddr :: ScurryAddress,+ bindPort :: ScurryPort,+ peers :: [EndPoint]+} deriving (Show)++data ScurryOpt = SOVAddr ScurryAddress+ | SOVMask ScurryMask+ | SOBAddr ScurryAddress+ | SOBPort ScurryPort+ deriving (Show)++defaultPort :: ScurryPort+defaultPort = ScurryPort 24999++readPort :: String -> ScurryPort+readPort [] = error "I need some numbers!"+readPort s = let w = read s :: Word16+ in (ScurryPort . fromIntegral) w++lookupName :: String -> IO EndPoint+lookupName ep = do+ let name = takeWhile (/=':') ep+ port = case drop 1 $ dropWhile (/=':') ep of+ [] -> defaultPort+ x -> readPort x++ HostEntry { hostAddresses = as } <- getHostByName name++ return $ EndPoint (ScurryAddress (as !! 0)) port+ +parseScurryOpts :: [String] -> IO (Either String ScurryOpts)+parseScurryOpts args = let def_opt = ScurryOpts { vpnAddr = Nothing+ , vpnMask = Nothing+ , bindAddr = ScurryAddress 0+ , bindPort = ScurryPort 24999+ , peers = [] }+ va_t = SOVAddr . fromJust . inet_addr+ vm_t = SOVMask . fromJust . inet_addr+ ba_t = SOBAddr . fromJust . inet_addr+ bp_t = SOBPort . readPort+ options = [ Option "a" ["vpn-addr"] (ReqArg va_t "VPN_ADDRESS") "The IP address to use for the VPN."+ , Option "m" ["vpn-mask"] (ReqArg vm_t "VPN_NETMASK") "The network mask the for the VPN."+ , Option "b" ["bind-addr"] (ReqArg ba_t "BIND_ADDRESS") "The network interface on which listen for connections."+ , Option "p" ["bind-port"] (ReqArg bp_t "BIND_PORT") "The port on which to listen for connections." ]+ (m,o,_) = getOpt RequireOrder options args -- ignore errors for now+ u = Left (usageInfo "How to use scurry." options)+ opt' = foldr rplcOpts def_opt m+ in case args of+ ["-h"] -> return u+ ["--help"] -> return u+ _ -> do ps <- mapM lookupName o+ return $ Right (opt' { peers = ps })++ where rplcOpts (SOVAddr a) sos = sos { vpnAddr = Just a }+ rplcOpts (SOVMask m) sos = sos { vpnMask = Just m }+ rplcOpts (SOBAddr a) sos = sos { bindAddr = a }+ rplcOpts (SOBPort p) sos = sos { bindPort = p }++main :: IO ()+main = withSocketsDo $ do + args <- getArgs++ opts_ <- parseScurryOpts args+ -- let (configPath:trackerPath:_) = args++ opts <- case opts_ of+ (Left msg) -> putStrLn msg >> exitFailure+ (Right p) -> return p++ -- (Just config) <- load_scurry_config_file configPath+ -- (Just tracker) <- load_tracker_file trackerPath++ -- let (Scurry (VpnConfig tapIp tapMask) (NetworkConfig mySockAddr)) = config+ -- trackerEndPoints = filter (/= mySockAddr) $ map tToS tracker++ let initState = ScurryState {+ scurryPeers = [],+ scurryEndPoint = EndPoint (bindAddr opts) (bindPort opts),+ scurryNetwork = ScurryNetwork {+ scurryMask = vpnMask opts+ },+ scurryMyRecord = PeerRecord {+ peerMAC = Nothing,+ peerEndPoint = EndPoint (ScurryAddress 0) (ScurryPort 0),+ peerVPNAddr = vpnAddr opts,+ peerLocalPort = bindPort opts -- (\(EndPoint _ p) -> p) mySockAddr+ }+ }+ tapNet = (vpnAddr opts, vpnMask opts)++ local <- prepEndPoint (scurryEndPoint initState) -- mySockAddr++ startCom tapNet local initState (peers opts)++ {-+ where+ tToS (ScurryPeer ip port) = EndPoint ip port + -}+++{-+getAddress :: Socket -> [EndPoint] -> IO (ScurryAddress, ScurryMask)+getAddress sock (t:trackers) = do+ let msg = SAddrRequest+ cmd = sendToAddr sock msg+ + putStrLn "Requesting address..."+ cmd t++ where+ delayRead = do+ threadDelay (sToMs 1.5)+-}