[or-cvs] r17000: {torvm} Add torvm controller application for win32 to manage network (in torvm/trunk/build/win32: . files src src/torvm-w32)
coderman at seul.org
coderman at seul.org
Mon Sep 29 12:12:47 UTC 2008
Author: coderman
Date: 2008-09-29 08:12:44 -0400 (Mon, 29 Sep 2008)
New Revision: 17000
Added:
torvm/trunk/build/win32/src/
torvm/trunk/build/win32/src/torvm-w32/
torvm/trunk/build/win32/src/torvm-w32/Makefile
torvm/trunk/build/win32/src/torvm-w32/torvm.c
Modified:
torvm/trunk/build/win32/Makefile
torvm/trunk/build/win32/files/buildall.sh
Log:
Add torvm controller application for win32 to manage network and service configuration as well as Qemu VM instances.
Modified: torvm/trunk/build/win32/Makefile
===================================================================
--- torvm/trunk/build/win32/Makefile 2008-09-29 10:52:55 UTC (rev 16999)
+++ torvm/trunk/build/win32/Makefile 2008-09-29 12:12:44 UTC (rev 17000)
@@ -211,6 +211,7 @@
mv $(ISODIR)/dl/$(SDL_F) $(ISODIR)/dl/src/; \
mv $(ISODIR)/dl/$(OVPN_F) $(ISODIR)/dl/src/; \
mv $(ISODIR)/dl/$(ZLIBSRC_F) $(ISODIR)/dl/src/; \
+ ( cd src && tar zcf ../$(ISODIR)/dl/src/torvm-w32.tgz torvm-w32 ); \
touch $(ISODIR)/VMDEVISO.TXT
buildiso: extract
Modified: torvm/trunk/build/win32/files/buildall.sh
===================================================================
--- torvm/trunk/build/win32/files/buildall.sh 2008-09-29 10:52:55 UTC (rev 16999)
+++ torvm/trunk/build/win32/files/buildall.sh 2008-09-29 12:12:44 UTC (rev 17000)
@@ -249,7 +249,18 @@
cp pc-bios/vgabios.bin $bindir/
cp pc-bios/vgabios-cirrus.bin $bindir/
+echo "Building torvm-w32 controller ..."
+cd /usr/src
+tar zxvf torvm-w32.tgz
+cd torvm-w32
+make
+if (( $? != 0 )); then
+ echo "ERROR: torvm-w32 build failed." >&2
+ exit 1
+fi
+cp torvm.exe $ddir/
+
# last but not least, include the virtual disk and other parts
cp /usr/src/add/* $libdir/
cp /usr/src/add/hdd.img $statedir/
Added: torvm/trunk/build/win32/src/torvm-w32/Makefile
===================================================================
--- torvm/trunk/build/win32/src/torvm-w32/Makefile (rev 0)
+++ torvm/trunk/build/win32/src/torvm-w32/Makefile 2008-09-29 12:12:44 UTC (rev 17000)
@@ -0,0 +1,27 @@
+# Makefile for Tor VM win32 process and network control utility
+
+.PHONY: all clean distclean install
+
+BINDIR=C:\Tor_VM
+CPPFLAGS += -I. -I/usr/include -I/usr/local/include -MMD -MP
+CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#LDFLAGS += -L/usr/lib -L/usr/local/lib -lws2_32 -liphlpapi
+LDFLAGS += -lws2_32 -liphlpapi
+
+all: torvm$(EXESUF)
+
+OBJS+=torvm.o
+
+torvm$(EXESUF): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+%.o: %.c
+ $(CC) $(CPPFLAGS) -c -o $@ $<
+
+clean:
+ rm -f *.o *.d torvm$(EXESUF)
+
+
+install: all
+ ls -l torvm$(EXESUF)
+ cp -f torvm$(EXESUF) $(BINDIR)
Added: torvm/trunk/build/win32/src/torvm-w32/torvm.c
===================================================================
--- torvm/trunk/build/win32/src/torvm-w32/torvm.c (rev 0)
+++ torvm/trunk/build/win32/src/torvm-w32/torvm.c 2008-09-29 12:12:44 UTC (rev 17000)
@@ -0,0 +1,1393 @@
+/* Copyright (C) 2008 The Tor Project, Inc.
+ * See LICENSE file for rights and terms.
+ */
+
+/* enable certain parts of the win32 API for process / system functions */
+#define _WIN32_WINNT 0x0500
+
+#include <windows.h>
+#include <tchar.h>
+#include <winreg.h>
+#include <winioctl.h>
+#include <winerror.h>
+#include <wincrypt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* things that should go into configure / headers / runtime dynamic */
+#define REG_NAME_MAX 256
+#define TOR_VM_ROOT "C:\\Tor_VM"
+#define W_TOR_VM_ROOT L"C:\\Tor_VM"
+#define TOR_VM_BIN TOR_VM_ROOT "\\bin"
+#define TOR_VM_LIB TOR_VM_ROOT "\\lib"
+#define TOR_VM_STATE TOR_VM_ROOT "\\state"
+#define WIN_DRV_DIR "C:\\WINDOWS\\system32\\drivers"
+#define TOR_TAP_NAME "Tor VM Tap32"
+#define TOR_TAP_SVC "tortap91"
+
+struct s_rtcpipvals {
+ BOOL isdhcp;
+ LPTSTR ipaddr;
+ LPTSTR netmask;
+ LPTSTR gateway;
+ LPTSTR hostname;
+};
+
+struct s_rconnelem {
+ int idx;
+ BOOL isactive;
+ BOOL isdefgw;
+ LPTSTR name;
+ LPTSTR guid;
+ LPTSTR driver;
+ LPTSTR macaddr;
+ struct s_rconnelem * next;
+};
+
+
+/* jump hoops to read ethernet adapter MAC address.
+ */
+#define _NDIS_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT )
+
+/* these are not yet used, but we may need them to interact with network devices
+ * directly to enable/disable, change MAC, etc.
+ */
+#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED )
+#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED )
+#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED )
+#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED )
+#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED )
+#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT )
+
+/* OID's we need to query */
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+/* probably will never need these, but just in case ... */
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_WAN_PERMANENT_ADDRESS 0x04010101
+#define OID_WAN_CURRENT_ADDRESS 0x04010102
+#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B
+#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C
+
+/* win32 registry fun */
+#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}"
+#define NETWORK_CLIENTS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E973-E325-11CE-BFC1-08002BE10318}"
+#define NETWORK_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E974-E325-11CE-BFC1-08002BE10318}"
+#define NETWORK_PROTOCOLS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E975-E325-11CE-BFC1-08002BE10318}"
+#define TCPIP_KEY "SYSTEM\\CurrentControlSet\\Services\\Tcpip"
+
+
+/* debug, info and error logging
+ * lerror to stderr and log file (if set)
+ * linfo to log file
+ * ldebug to debug log file
+ * fatal logs error and then exits process
+ */
+static HANDLE s_logh = INVALID_HANDLE_VALUE;
+static HANDLE s_dbgh = INVALID_HANDLE_VALUE;
+
+
+void logto (LPTSTR path)
+{
+ if (s_logh != INVALID_HANDLE_VALUE) {
+ CloseHandle (s_logh);
+ }
+ s_logh = CreateFile (path,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+}
+
+
+static void _flog (HANDLE fd,
+ const char * msgtype,
+ const char * format,
+ va_list argptr)
+{
+ static const int msgmax = 4096;
+ static char * msgbuf = NULL;
+ static char * coff = NULL;
+ const char * newline = "\r\n";
+ int len;
+ DWORD written;
+ SYSTEMTIME now;
+ va_list ap;
+
+ if (fd == INVALID_HANDLE_VALUE)
+ return;
+
+ if (msgbuf == NULL) {
+ msgbuf = (char *) malloc (msgmax);
+ if (!msgbuf) return;
+ }
+ GetSystemTime (&now);
+ coff = msgbuf;
+ coff[msgmax -1] = 0;
+ len = snprintf (coff,
+ msgmax -1,
+ "[%4.4d/%-2.2d/%-2.2d %-2.2d:%-2.2d:%-2.2d.%-3.3d UTC] %s: ",
+ now.wYear,
+ now.wMonth,
+ now.wDay,
+ now.wHour,
+ now.wMinute,
+ now.wSecond,
+ now.wMilliseconds,
+ msgtype);
+ if (len > 0) {
+ coff += len;
+ len = vsnprintf (coff,
+ (msgmax -1) - len,
+ format,
+ argptr);
+ if (len > 0) {
+ len += abs(coff - msgbuf);
+ }
+ else {
+ /* full msg buffer */
+ len = msgmax -1;
+ }
+ }
+ else {
+ /* full msg buffer */
+ len = msgmax -1;
+ }
+ WriteFile (fd, msgbuf, len, &written, NULL);
+ WriteFile (fd, newline, strlen(newline), &written, NULL);
+ FlushFileBuffers (fd);
+ return;
+}
+
+
+void fatal (const char* format, ...)
+{
+ HANDLE fd = INVALID_HANDLE_VALUE;
+ va_list argptr;
+
+ fd = GetStdHandle (STD_ERROR_HANDLE);
+ if (fd == INVALID_HANDLE_VALUE)
+ fd = GetStdHandle (STD_OUTPUT_HANDLE);
+
+ va_start (argptr, format);
+ _flog (fd, "ERROR", format, argptr);
+ va_end (argptr);
+ _exit (9);
+ return;
+}
+
+
+void lerror (const char * format, ...)
+{
+ HANDLE fd = INVALID_HANDLE_VALUE;
+ va_list argptr;
+
+ fd = s_logh;
+ if (fd == INVALID_HANDLE_VALUE) {
+ fd = GetStdHandle (STD_ERROR_HANDLE);
+ if (fd == INVALID_HANDLE_VALUE)
+ fd = GetStdHandle (STD_OUTPUT_HANDLE);
+ }
+
+ va_start (argptr, format);
+ _flog (fd, "ERROR", format, argptr);
+ va_end (argptr);
+ return;
+}
+
+void linfo (const char* format, ...)
+{
+ va_list argptr;
+ if (s_logh == INVALID_HANDLE_VALUE)
+ return;
+
+ va_start (argptr, format);
+ _flog (s_logh, "info", format, argptr);
+ va_end (argptr);
+ return;
+}
+
+void debugto (LPTSTR path)
+{
+ if (s_dbgh != INVALID_HANDLE_VALUE) {
+ CloseHandle (s_dbgh);
+ }
+ s_dbgh = CreateFile (path,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+}
+
+
+void ldebug (const char* format, ...)
+{
+ va_list argptr;
+ if (s_dbgh == INVALID_HANDLE_VALUE)
+ return;
+
+ va_start (argptr, format);
+ _flog (s_dbgh, "debug", format, argptr);
+ va_end (argptr);
+ return;
+}
+
+
+BOOL setdriversigning (BOOL sigcheck)
+{
+ /* thanks to Stefan 'Sec' Zehl and Blaine Fleming for this snippet.
+ * see http://support.microsoft.com/?kbid=298503 for details on this subversion.
+ * the ideal alternative is to pay the thousands of dollars for a driver signature.
+ */
+#define HP_HASHVALUE HP_HASHVAL
+ HCRYPTPROV cryptoprovider;
+ HCRYPTHASH digest;
+ BYTE data[16];
+ DWORD len;
+ DWORD seed;
+ HKEY rkey;
+ BYTE onoff;
+ char regval[4];
+ int x;
+
+ onoff = sigcheck ? 1 : 0;
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "System\\WPA\\PnP",
+ 0,
+ KEY_READ,
+ &rkey) != ERROR_SUCCESS){
+ return FALSE;
+ }
+ len = sizeof(seed);
+ if(RegQueryValueEx(rkey,
+ "seed",
+ NULL,
+ NULL,
+ (BYTE*)&seed,
+ &len) != ERROR_SUCCESS){
+ return FALSE;
+ }
+ RegCloseKey(rkey);
+ if (!CryptAcquireContext(&cryptoprovider,
+ NULL,
+ NULL,
+ PROV_RSA_FULL,
+ 0)) {
+ if (!CryptAcquireContext(&cryptoprovider,
+ NULL,
+ NULL,
+ PROV_RSA_FULL,
+ CRYPT_NEWKEYSET)) {
+ return FALSE;
+ }
+ }
+ if (!CryptCreateHash(cryptoprovider,
+ CALG_MD5,
+ 0,
+ 0,
+ &digest)) {
+ return FALSE;
+ }
+ ZeroMemory( regval, sizeof(regval) );
+ regval[1] = onoff;
+ if (!CryptHashData(digest,
+ regval,
+ sizeof(regval),
+ 0)) {
+ return FALSE;
+ }
+ if (!CryptHashData(digest,
+ (BYTE*)&seed,
+ sizeof(seed),
+ 0)) {
+ return FALSE;
+ }
+ len = sizeof(data);
+ if (!CryptGetHashParam(digest,
+ HP_HASHVALUE,
+ data,
+ &len,
+ 0)) {
+ return FALSE;
+ }
+ CryptDestroyHash(digest);
+ CryptReleaseContext(cryptoprovider, 0);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
+ 0,
+ KEY_WRITE,
+ &rkey) != ERROR_SUCCESS) {
+ return FALSE;
+ }
+ if (RegSetValueEx(rkey,
+ "PrivateHash",
+ 0,
+ REG_BINARY,
+ data,
+ sizeof(data)) != ERROR_SUCCESS) {
+ return FALSE;
+ }
+ RegCloseKey(rkey);
+
+ /* the user preference may or may not be set. if not, go to machine pref. */
+ if (RegOpenKeyEx(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Driver Signing",
+ 0,
+ KEY_WRITE,
+ &rkey) == ERROR_SUCCESS) {
+ if(RegSetValueEx(rkey,
+ "Policy",
+ 0,
+ REG_BINARY,
+ &onoff,
+ 1) != ERROR_SUCCESS) {
+ /* return FALSE; */
+ }
+ RegCloseKey(rkey);
+ }
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Driver Signing",
+ 0,
+ KEY_WRITE,
+ &rkey) != ERROR_SUCCESS) {
+ return FALSE;
+ }
+ if(RegSetValueEx(rkey,
+ "Policy",
+ 0,
+ REG_BINARY,
+ &onoff,
+ 1) != ERROR_SUCCESS) {
+ return FALSE;
+ }
+ RegCloseKey(rkey);
+
+ return TRUE;
+}
+
+BOOL istapinstalled(struct s_rconnelem * connlist)
+{
+ return FALSE;
+}
+
+BOOL installtap(void)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ LPTSTR cmd = NULL;
+ LPTSTR dir = NULL;
+ DWORD exitcode;
+ DWORD opts = 0;
+
+ opts = CREATE_NEW_PROCESS_GROUP;
+
+ ZeroMemory( &pi, sizeof(pi) );
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ dir = TOR_VM_LIB;
+ cmd = "\"" TOR_VM_BIN "\\devcon.exe\" install tortap91.inf TORTAP91";
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ FALSE, // default handle inheritance false
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ &pi) ) {
+ lerror ("Failed to launch process. Error code: %d", GetLastError());
+ }
+
+ linfo ("waiting for TAP-Win32 driver install to complete ...");
+ while ( GetExitCodeProcess(pi.hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ Sleep (500);
+ }
+ linfo ("TAP-Win32 install exited with value %d", exitcode);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return TRUE;
+}
+
+BOOL uninstalltap(void)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ LPTSTR cmd = NULL;
+ LPTSTR dir = NULL;
+ DWORD exitcode;
+ DWORD opts = 0;
+
+ opts = CREATE_NEW_PROCESS_GROUP;
+
+ ZeroMemory( &pi, sizeof(pi) );
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ dir = TOR_VM_LIB;
+ cmd = "\"" TOR_VM_BIN "\\devcon.exe\" remove TORTAP91";
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ FALSE, // default handle inheritance false
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ &pi) ) {
+ lerror ("Failed to launch process. Error code: %d", GetLastError());
+ }
+
+ while ( GetExitCodeProcess(pi.hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ Sleep (200);
+ }
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return TRUE;
+}
+
+BOOL installtornpf (void)
+{
+ HANDLE src = NULL;
+ HANDLE dest = NULL;
+ LPTSTR srcname = TOR_VM_LIB "\\tornpf.sys";
+ LPTSTR destname = WIN_DRV_DIR "\\tornpf.sys";
+ CHAR * buff = NULL;
+ DWORD buffsz = 4096;
+ DWORD len;
+ DWORD written;
+
+ src = CreateFile (srcname,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (src == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+ dest = CreateFile (destname,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_SYSTEM,
+ NULL);
+ if (dest == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+
+ buff = (CHAR *)malloc(buffsz);
+ while (ReadFile(src, buff, buffsz, &len, NULL) && (len > 0)) {
+ WriteFile(dest, buff, len, &written, NULL);
+ }
+ free (buff);
+ CloseHandle (src);
+ CloseHandle (dest);
+
+ return TRUE;
+}
+
+BOOL uninstalltornpf (void)
+{
+ LPTSTR fname = WIN_DRV_DIR "\\tornpf.sys";
+ DeleteFile (fname);
+ return TRUE;
+}
+
+BOOL savenetconfig(void)
+{
+#define READSIZE 4096
+ HANDLE fh = NULL;
+ HANDLE stdin_rd = NULL;
+ HANDLE stdin_wr = NULL;
+ HANDLE stdout_rd = NULL;
+ HANDLE stdout_wr = NULL;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ SECURITY_ATTRIBUTES sattr;
+ LPTSTR cmd = NULL;
+ LPTSTR dir = NULL;
+ DWORD exitcode;
+ DWORD opts = 0;
+ DWORD numread;
+ DWORD numwritten;
+ CHAR * buff;
+
+ opts = CREATE_NEW_PROCESS_GROUP;
+
+ ZeroMemory( &pi, sizeof(pi) );
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sattr.bInheritHandle = TRUE;
+ sattr.lpSecurityDescriptor = NULL;
+ dir = TOR_VM_STATE;
+ /* cmd = "\"netsh.exe\" interface ip dump" */
+ cmd = "\"netsh.exe\" dump";
+
+ CreatePipe(&stdout_rd, &stdout_wr, &sattr, 0);
+ SetHandleInformation(stdout_rd, HANDLE_FLAG_INHERIT, 0);
+
+ CreatePipe(&stdin_rd, &stdin_wr, &sattr, 0);
+ SetHandleInformation(stdin_wr, HANDLE_FLAG_INHERIT, 0);
+
+ si.hStdError = stdout_wr;
+ si.hStdOutput = stdout_wr;
+ si.hStdInput = stdin_rd;
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ TRUE, // handles are inherited
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ &pi) ) {
+ lerror ("Failed to launch process. Error code: %d", GetLastError());
+ return FALSE;
+ }
+
+ CloseHandle(stdout_wr);
+ CloseHandle(stdin_rd);
+ CloseHandle(stdin_wr);
+
+ fh = CreateFile (TOR_VM_STATE "\\netcfg.save",
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ buff = (CHAR *)malloc(READSIZE);
+ while (ReadFile(stdout_rd, buff, READSIZE, &numread, NULL) && (numread > 0)) {
+ WriteFile(fh, buff, numread, &numwritten, NULL);
+ }
+ CloseHandle (fh);
+
+ linfo ("Saved current network configuration state.");
+ CloseHandle(stdout_rd);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return TRUE;
+}
+
+BOOL restorenetconfig(void)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ LPTSTR cmd = NULL;
+ LPTSTR dir = NULL;
+ DWORD exitcode;
+ DWORD opts = 0;
+
+ opts = CREATE_NEW_PROCESS_GROUP;
+
+ ZeroMemory( &pi, sizeof(pi) );
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ dir = TOR_VM_STATE;
+ cmd = "\"netsh.exe\" exec netcfg.save";
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ FALSE, // default handle inheritance false
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ &pi) ) {
+ lerror ("Failed to launch process. Error code: %d", GetLastError());
+ }
+
+ while ( GetExitCodeProcess(pi.hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ Sleep (200);
+ }
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ LPTSTR fname = TOR_VM_STATE "\\netcfg.save";
+ DeleteFile (fname);
+ linfo ("Restored current network configuration state.");
+
+ return TRUE;
+}
+
+BOOL runcommand(LPSTR cmd)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ LPTSTR dir = NULL;
+ DWORD exitcode;
+ DWORD opts = 0;
+
+ opts = CREATE_NEW_PROCESS_GROUP;
+
+ ZeroMemory( &pi, sizeof(pi) );
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ dir = TOR_VM_BIN;
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ FALSE, // default handle inheritance false
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ &pi) ) {
+ lerror ("Failed to launch process. Error code: %d", GetLastError());
+ return FALSE;
+ }
+
+ while ( GetExitCodeProcess(pi.hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ Sleep (200);
+ }
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return TRUE;
+}
+
+BOOL disableservices(void)
+{
+ /* TODO: check which of the following are running and stop them.
+ * RemoteRegistry lanmanserver TermService WebClient LmHosts Messenger mnmsrvc RDSessMgr
+ * also need to remember what was running so we can resume it at shutdown.
+ */
+ return TRUE;
+}
+
+BOOL disablefirewall(void)
+{
+ LPSTR cmd;
+ cmd = "\"netsh.exe\" firewall set opmode disable";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL cleararpcache(void)
+{
+ LPSTR cmd;
+ cmd = "\"netsh.exe\" interface ip delete arpcache";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL flushdns(void)
+{
+ LPSTR cmd;
+ cmd = "\"ipconfig.exe\" /flushdns";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL configtap(void)
+{
+ LPSTR cmd;
+ cmd = "\"netsh.exe\" interface ip set address \"" TOR_TAP_NAME "\" static 10.10.10.2 255.255.255.252 10.10.10.1 1";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ cmd = "\"netsh.exe\" interface ip set dns \"" TOR_TAP_NAME "\" static 4.2.2.2";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ cmd = "\"netsh.exe\" interface ip add dns \"" TOR_TAP_NAME "\" 4.2.2.4";
+ if (! runcommand(cmd)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL getmacaddr(const char * devguid,
+ char ** mac)
+{
+ char * devfstr = NULL;
+ unsigned char macbuf[6];
+ BOOL status;
+ HANDLE devfd;
+ DWORD retsz, oidcode;
+ BOOL retval = FALSE;
+
+ *mac = NULL;
+ devfstr = malloc(1024);
+ snprintf (devfstr, 1023, "\\\\.\\%s", devguid);
+ devfd = CreateFile(devfstr,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (devfd == INVALID_HANDLE_VALUE)
+ {
+ lerror ("Unable to open net device handle for path: %s", devfstr);
+ goto cleanup;
+ }
+
+#define MAXMAC 24
+ oidcode = OID_802_3_CURRENT_ADDRESS;
+ status = DeviceIoControl(devfd,
+ IOCTL_NDIS_QUERY_GLOBAL_STATS,
+ &oidcode, sizeof(oidcode),
+ macbuf, sizeof(macbuf),
+ &retsz,
+ (LPOVERLAPPED) NULL);
+ if (retsz == sizeof(macbuf)) {
+ *mac = malloc(MAXMAC);
+ memset(*mac, 0, MAXMAC);
+ snprintf(*mac, MAXMAC-1,
+ "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+ macbuf[0], macbuf[1], macbuf[2], macbuf[3], macbuf[4], macbuf[5]);
+ retval = TRUE;
+ }
+ else {
+ retval = FALSE;
+ }
+
+ cleanup:
+ if (devfd != INVALID_HANDLE_VALUE)
+ CloseHandle(devfd);
+ free(devfstr);
+
+ return retval;
+}
+
+int loadnetinfo(struct s_rconnelem **connlist)
+{
+ LONG status;
+ HKEY key;
+ HKEY wkey;
+ DWORD len;
+ int i = 0;
+ int stop = 0;
+ int numconn = 0;
+ struct s_rconnelem * ce = NULL;
+ const char name_string[] = "Name";
+
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ NETWORK_CONNECTIONS_KEY,
+ 0,
+ KEY_READ,
+ &key);
+ if (status != ERROR_SUCCESS) {
+ lerror ("Failed to open key for read: %d", status);
+ return -1;
+ }
+
+ while (!stop) {
+ ce = malloc(sizeof(struct s_rconnelem));
+ char enum_name[REG_NAME_MAX];
+ char connection_string[REG_NAME_MAX];
+ HKEY ckey;
+ char name_data[REG_NAME_MAX];
+ DWORD name_type;
+
+ len = sizeof (enum_name);
+ status = RegEnumKeyEx(key,
+ i,
+ 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,
+ connection_string,
+ 0,
+ KEY_READ,
+ &ckey);
+
+ if (status == ERROR_SUCCESS) {
+ len = sizeof (name_data);
+ status = RegQueryValueEx(
+ ckey,
+ name_string,
+ NULL,
+ &name_type,
+ name_data,
+ &len);
+
+ if (status != ERROR_SUCCESS || name_type != REG_SZ) {
+ return -1;
+ }
+ else {
+ if (getmacaddr (enum_name, &(ce->macaddr)) == TRUE) {
+ linfo ("Interface %s => %s mac(%s)", name_data, enum_name, ce->macaddr);
+ }
+ }
+ RegCloseKey (ckey);
+ }
+ ++i;
+ }
+
+ RegCloseKey (key);
+
+ i = 0;
+ stop = 0;
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ ADAPTER_KEY,
+ 0,
+ KEY_READ,
+ &key);
+
+ if (status != ERROR_SUCCESS) {
+ lerror ("Failed to open key for read: %d", status);
+ return -1;
+ }
+
+ while (!stop)
+ {
+ char enum_name[REG_NAME_MAX];
+ char connection_string[REG_NAME_MAX];
+ HKEY ckey;
+ char name_data[REG_NAME_MAX];
+ char cguid[REG_NAME_MAX];
+ DWORD name_type;
+
+ len = sizeof (enum_name);
+ status = RegEnumKeyEx(
+ key,
+ i,
+ 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",
+ ADAPTER_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ connection_string,
+ 0,
+ KEY_READ,
+ &ckey);
+
+ if (status == ERROR_SUCCESS) {
+ len = sizeof (name_data);
+ status = RegQueryValueEx(
+ ckey,
+ "DriverDesc",
+ NULL,
+ &name_type,
+ name_data,
+ &len);
+
+ if (status != ERROR_SUCCESS || name_type != REG_SZ) {
+ }
+ else {
+ /* printf ("-%s- %s", enum_name, name_data); */
+ }
+
+ RegCloseKey (ckey);
+ }
+ else {
+ /* printf ("Failed read key %s , errorno: %d", connection_string, status); */
+ }
+
+ snprintf(connection_string,
+ sizeof(connection_string),
+ "%s\\%s",
+ ADAPTER_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ connection_string,
+ 0,
+ KEY_READ,
+ &ckey);
+
+ if (status == ERROR_SUCCESS) {
+ len = sizeof (name_data);
+ status = RegQueryValueEx(
+ ckey,
+ "NetCfgInstanceId",
+ NULL,
+ &name_type,
+ name_data,
+ &len);
+
+ if (status != ERROR_SUCCESS || name_type != REG_SZ) {
+ /* printf ("Failed parse of key %s\\NetCfgInstanceId , errorno: %d", connection_string, status); */
+ }
+ else {
+ /* printf ("GUID: %s", name_data); */
+ strcpy (cguid, name_data);
+ }
+
+ RegCloseKey (ckey);
+ }
+ else {
+ /* printf ("Failed read key %s , errorno: %d", connection_string, status); */
+ }
+
+ snprintf(connection_string,
+ sizeof(connection_string),
+ "%s\\%s\\Ndi",
+ ADAPTER_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ connection_string,
+ 0,
+ KEY_READ,
+ &ckey);
+
+ if (status == ERROR_SUCCESS) {
+ len = sizeof (name_data);
+ status = RegQueryValueEx(
+ ckey,
+ "Service",
+ NULL,
+ &name_type,
+ name_data,
+ &len);
+
+ if (status != ERROR_SUCCESS || name_type != REG_SZ) {
+ /* printf ("Failed parse of key %s\\Service , errorno: %d", connection_string, status); */
+ }
+ else {
+ /* printf ("Service: %s", name_data); */
+ if (strcmp(name_data, TOR_TAP_SVC) == 0) {
+ snprintf(connection_string,
+ sizeof(connection_string),
+ "%s\\%s\\Connection",
+ NETWORK_CONNECTIONS_KEY, cguid);
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ connection_string,
+ 0,
+ KEY_WRITE,
+ &wkey);
+ if (status == ERROR_SUCCESS) {
+ strcpy(name_data, TOR_TAP_NAME);
+ if (RegSetValueEx(wkey,
+ name_string,
+ 0,
+ REG_SZ,
+ name_data,
+ strlen(name_data)) != ERROR_SUCCESS) {
+ lerror ("Unable to update name of Tor Tap32 device interface.");
+ }
+ RegCloseKey (wkey);
+ }
+ }
+ }
+
+ RegCloseKey (ckey);
+ }
+ else {
+ /* printf ("Failed read key %s , errorno: %d", connection_string, status); */
+ }
+
+ i++;
+ }
+
+ RegCloseKey (key);
+
+ return 0;
+}
+
+/* keep linkage to these dynamic, in case the requisite Dll's don't exist. */
+typedef BOOL (__stdcall *PFnIsUserAnAdmin)(void);
+typedef BOOL (__stdcall *PFnAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY pIdAuth, BYTE nSubAuthCount, DWORD dwSubAuth0, DWORD dwSubAuth1, DWORD dwSubAuth2, DWORD dwSubAuth3, DWORD dwSubAuth4, DWORD dwSubAuth5, DWORD dwSubAuth6, DWORD dwSubAuth7, PSID pSid);
+typedef BOOL (WINAPI *PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
+typedef PVOID (__stdcall *PFnFreeSid)(PSID pSid);
+
+BOOL haveadminrights (void)
+{
+ SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
+ PSID admgroup;
+ BOOL isadmin = FALSE;
+ HMODULE module;
+ PFnIsUserAnAdmin pfnIsUserAnAdmin = NULL;
+ PFnAllocateAndInitializeSid pfnAllocateAndInitializeSid = NULL;
+ PFnCheckTokenMembership pfnCheckTokenMembership = NULL;
+ PFnFreeSid pfnFreeSid = NULL;
+
+ /* use IsUserAnAdmin when possible (Vista or greater). otherwise we fall back to checking
+ * token membership manually. For Vista and greater we want to know if we are currently running
+ * with Administrator rights, not only that user is a member of Administrator group.
+ */
+ module = LoadLibrary("shell32.dll");
+ if (module) {
+ pfnIsUserAnAdmin = (PFnIsUserAnAdmin) GetProcAddress(module, "IsUserAnAdmin");
+ if (pfnIsUserAnAdmin) {
+ isadmin = pfnIsUserAnAdmin();
+ FreeLibrary(module);
+ return isadmin;
+ }
+ FreeLibrary(module);
+ }
+ module = LoadLibrary("advapi32.dll");
+ if (module) {
+ pfnAllocateAndInitializeSid = (PFnAllocateAndInitializeSid) GetProcAddress(module, "AllocateAndInitializeSid");
+ pfnCheckTokenMembership = (PFnCheckTokenMembership) GetProcAddress(module, "CheckTokenMembership");
+ pfnFreeSid = (PFnFreeSid) GetProcAddress(module, "FreeSid");
+ if (pfnAllocateAndInitializeSid && pfnCheckTokenMembership && pfnFreeSid) {
+ if(pfnAllocateAndInitializeSid(&ntauth,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &admgroup))
+ {
+ if( !pfnCheckTokenMembership(NULL,
+ admgroup,
+ &isadmin) )
+ {
+ /* error occurred? default to false */
+ isadmin = FALSE;
+ }
+ pfnFreeSid(admgroup);
+ }
+ }
+ FreeLibrary(module);
+ }
+
+ return isadmin;
+}
+
+BOOL launchtorvm (PROCESS_INFORMATION * pi)
+{
+ STARTUPINFO si;
+ LPTSTR cmd = NULL;
+ LPTSTR dir = NULL;
+ DWORD opts = CREATE_NEW_PROCESS_GROUP | BELOW_NORMAL_PRIORITY_CLASS;
+
+ ZeroMemory( &si, sizeof(si) );
+ ZeroMemory( pi, sizeof(PROCESS_INFORMATION) );
+ si.cb = sizeof(si);
+ dir = TOR_VM_BIN;
+ cmd = "\"" TOR_VM_BIN "\\qemu.exe\" -name \"Tor VM \" -L . -kernel ../lib/vmlinuz -append \"clocksource=hpet IP=172.16.2.42 MASK=255.255.255.0 GW=172.16.2.1 MAC=00:11:22:33:44:55 MTU=1480 PRIVIP=10.10.10.1\" -hda ../state/hdd.img -m 32 -std-vga -net nic,model=pcnet,macaddr=00:11:22:33:44:55 -net pcap,devicename=\"Local Area Connection\" -net nic,vlan=1,model=pcnet -net tap,vlan=1,ifname=\"" TOR_TAP_NAME "\" -net user,vlan=2 -net nic,vlan=2,model=pcnet";
+
+ if( !CreateProcess(NULL,
+ cmd,
+ NULL, // process handle no inherit
+ NULL, // thread handle no inherit
+ FALSE, // default handle inheritance false
+ opts,
+ NULL, // environment block
+ dir,
+ &si,
+ pi) ) {
+ lerror ("Failed to launch Qemu Tor VM process. Error code: %d", GetLastError());
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL isrunning (PROCESS_INFORMATION * pi) {
+ DWORD exitcode;
+ if (GetExitCodeProcess(pi->hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL waitforit (PROCESS_INFORMATION * pi) {
+ DWORD exitcode;
+ while ( GetExitCodeProcess(pi->hProcess, &exitcode) && (exitcode == STILL_ACTIVE) ) {
+ ldebug ("waiting for process to exit ...");
+ Sleep (2000);
+ }
+ ldebug ("Done.");
+ CloseHandle(pi->hThread);
+ CloseHandle(pi->hProcess);
+
+ return TRUE;
+}
+
+BOOL promptrunasadmin (void)
+{
+ int retval;
+ if ( MessageBox(NULL,
+ "Tor VM requires Administrator rights. Attempt run as Administrator?",
+ "Elevated Privileges Needed",
+ MB_OKCANCEL | MB_ICONQUESTION | MB_SYSTEMMODAL | MB_SETFOREGROUND) == IDOK) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL respawnasadmin (void)
+{
+ STARTUPINFOW si = {0};
+ PROCESS_INFORMATION pi = {0};
+ LPTSTR cmd = NULL;
+ LPWSTR wcmd = NULL;
+ LPCWSTR username = L"Administrator";
+ LPCWSTR password = L"";
+ DWORD exitcode;
+ DWORD authopts = 0;
+ DWORD propts = 0;
+
+ //authopts = LOGON_WITH_PROFILE;
+ propts = CREATE_NEW_PROCESS_GROUP | HIGH_PRIORITY_CLASS;
+
+ si.cb = sizeof(si);
+ wcmd = W_TOR_VM_ROOT L"\\torvm.exe";
+ cmd = TOR_VM_ROOT "\\torvm.exe";
+
+ /* first, let's see if Administrator has no password set. */
+ if( !CreateProcessWithLogonW(username,
+ NULL, // default domain
+ password,
+ authopts,
+ NULL, // no process name
+ wcmd,
+ propts,
+ NULL, // environment block
+ NULL, // keep same directory
+ &si,
+ &pi) ) {
+ linfo ("Failed to re-launch process automatically with Administrator rights. Prompting user with Runas.");
+ if (ShellExecute(NULL,
+ "runas",
+ cmd,
+ NULL,
+ NULL,
+ SW_HIDE) != ERROR_SUCCESS) {
+ lerror ("Failed to re-launch via runas with Administrator rights. Unable to continue.");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL setupenv (void)
+{
+#define EBUFSZ 4096
+#define PATHVAR TEXT("PATH")
+ DWORD retval;
+ DWORD errnum;
+ DWORD buflen;
+ LPTSTR envvar;
+ LPTSTR newvar;
+ DWORD envopts=0;
+ BOOL exists = FALSE;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ envvar = (LPTSTR) malloc(EBUFSZ * sizeof(TCHAR));
+ if(envvar == NULL) {
+ lerror ("setupenv: out of memory.");
+ return FALSE;
+ }
+
+ retval = GetEnvironmentVariable(PATHVAR, envvar, (EBUFSZ -1));
+ if(retval == 0) {
+ errnum = GetLastError();
+ if( errnum == ERROR_ENVVAR_NOT_FOUND ) {
+ exists = FALSE;
+ }
+ }
+ else if (retval >= EBUFSZ) {
+ envvar = (LPTSTR) realloc(envvar, retval*sizeof(TCHAR));
+ if(envvar == NULL) {
+ lerror ("setupenv: out of memory.");
+ return FALSE;
+ }
+ retval = GetEnvironmentVariable(PATHVAR, envvar, retval);
+ if(!retval) {
+ lerror ("setupenv: GetEnvironmentVariable failed with errornum: %d",
+ GetLastError());
+ return FALSE;
+ }
+ else exists = TRUE;
+ }
+ else exists = TRUE;
+
+ retval = (exists) ? strlen(envvar) : 0;
+ retval += EBUFSZ;
+ newvar = (LPTSTR) malloc(retval * sizeof(TCHAR));
+ if (newvar == NULL) {
+ lerror ("setupenv: out of memory.");
+ return FALSE;
+ }
+ if (exists) {
+ strcat (envvar, ";");
+ }
+ else {
+ *envvar = (TCHAR)0;
+ }
+ snprintf (newvar, retval -1, "%s;%s;%s", TOR_VM_LIB, TOR_VM_BIN, envvar);
+
+ if (! SetEnvironmentVariable(PATHVAR, newvar)) {
+ lerror ("setupenv: SetEnvironmentVariable failed with errornum: %d for new val: %s",
+ GetLastError(),
+ newvar);
+ return FALSE;
+ }
+ ldebug ("setupenv: %s => %s",
+ PATHVAR,
+ newvar);
+
+ return TRUE;
+}
+
+
+int main(int argc, char **argv)
+{
+ const char *cmd;
+ struct s_rconnelem *connlist = NULL;
+
+ if (!haveadminrights()) {
+ if (promptrunasadmin()) {
+ if (respawnasadmin() == TRUE) {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ logto (TOR_VM_STATE "\\torvm.log");
+ debugto (TOR_VM_STATE "\\debug.log");
+
+ if (!setupenv()) {
+ fatal ("Unable to prepare process environment.");
+ }
+
+ if (!savenetconfig()) {
+ fatal ("Unable to save current network configuration.");
+ }
+
+ if (!installtornpf()) {
+ lerror ("Unable to install Tor NPF service driver.");
+ goto shutdown;
+ }
+
+ uninstalltap();
+
+ if (!setdriversigning (FALSE)) {
+ lerror ("Unable to disable driver signing checks. Installing tap anyway...");
+ }
+ if (!installtap()) {
+ lerror ("Unable to load TAP-Win32 network driver.");
+ goto shutdown;
+ }
+ if (!setdriversigning (TRUE)) {
+ lerror ("Unable to restore driver signing checks.");
+ }
+
+ loadnetinfo(&connlist);
+
+ if (! disableservices()) {
+ lerror ("Unable to disable dangerous windows network services.");
+ }
+ if (! disablefirewall()) {
+ lerror ("Unable to disable windows firewall.");
+ }
+ if (! cleararpcache()) {
+ lerror ("Unable to clear arp cache.");
+ }
+ if (! flushdns()) {
+ lerror ("Unable to flush cached DNS entries.");
+ }
+
+ PROCESS_INFORMATION pi;
+ if (! launchtorvm(&pi)) {
+ lerror ("Unable to launch Qemu TorVM instance.");
+ goto shutdown;
+ }
+ Sleep (4000);
+ if (! isrunning(&pi)) {
+ lerror ("Tor VM failed to start properly.");
+ goto shutdown;
+ }
+
+ if (! configtap()) {
+ lerror ("Unable to configure tap device. Exiting.");
+ goto shutdown;
+ }
+ Sleep (4000);
+
+ waitforit(&pi);
+
+ linfo ("Tor VM closed, restoring host network and services.");
+
+ shutdown:
+ if (! uninstalltap()) {
+ lerror ("Unable to remove TAP-Win32 device.");
+ }
+ if (! uninstalltornpf()) {
+ lerror ("Unable to remove Tor NPF service driver.");
+ }
+ if (! cleararpcache()) {
+ lerror ("Unable to clear arp cache.");
+ }
+ if (! flushdns()) {
+ lerror ("Unable to flush cached DNS entries.");
+ }
+ if (! restorenetconfig()) {
+ lerror ("Unable to restore network configuration.");
+ }
+ linfo ("Tor VM shutdown completed.");
+ return 0;
+}
+
More information about the tor-commits
mailing list