summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorng0 <ng0@n0.is>2019-09-10 16:59:32 +0000
committerng0 <ng0@n0.is>2019-09-10 16:59:32 +0000
commit04b6df21cd281e8cd540139f8d9ae85defc1961c (patch)
tree6357199445df8d5c0c631bc8f10aef838b1f9f1e /src
parent483b0139a218a5f8a8311bda3eb23bcd88f57688 (diff)
downloadgnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.tar.gz
gnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.zip
remove CYGWIN codeblocks, drop vendored Windows openvpn, drop win32 specific files.
configures and builds okay. testsuite wasn't checked, will be checked. diff including the plibc removal is now around 14370 lines of code less.
Diffstat (limited to 'src')
-rw-r--r--src/arm/Makefile.am4
-rw-r--r--src/ats-tests/Makefile.am4
-rw-r--r--src/ats-tool/Makefile.am10
-rw-r--r--src/ats/Makefile.am4
-rw-r--r--src/auction/Makefile.am4
-rw-r--r--src/block/Makefile.am4
-rw-r--r--src/cadet/Makefile.am6
-rw-r--r--src/consensus/Makefile.am4
-rw-r--r--src/conversation/Makefile.am4
-rw-r--r--src/conversation/gnunet_gst_def.h2
-rw-r--r--src/core/Makefile.am4
-rw-r--r--src/datacache/Makefile.am4
-rw-r--r--src/datastore/Makefile.am4
-rw-r--r--src/dht/Makefile.am3
-rw-r--r--src/dns/Makefile.am4
-rw-r--r--src/exit/Makefile.am19
-rw-r--r--src/exit/gnunet-helper-exit-windows.c1699
-rw-r--r--src/fragmentation/Makefile.am4
-rw-r--r--src/fs/Makefile.am4
-rw-r--r--src/gns/Makefile.am60
-rw-r--r--src/gns/gns-helper-service-w32.conf4
-rw-r--r--src/gns/gnunet-gns-helper-service-w32.c803
-rw-r--r--src/gns/nss/Makefile.am5
-rw-r--r--src/gns/w32nsp-install.c143
-rw-r--r--src/gns/w32nsp-resolve.c464
-rw-r--r--src/gns/w32nsp-uninstall.c31
-rw-r--r--src/gns/w32nsp.c711
-rw-r--r--src/gns/w32nsp.def2
-rw-r--r--src/gnsrecord/Makefile.am4
-rw-r--r--src/hello/Makefile.am4
-rw-r--r--src/identity/Makefile.am4
-rw-r--r--src/include/Makefile.am8
-rw-r--r--src/include/gnunet_common.h30
-rw-r--r--src/include/tap-windows.h81
-rw-r--r--src/include/winproc.h235
-rw-r--r--src/integration-tests/Makefile.am4
-rw-r--r--src/my/Makefile.am4
-rw-r--r--src/mysql/Makefile.am4
-rw-r--r--src/namecache/Makefile.am5
-rw-r--r--src/namestore/Makefile.am5
-rw-r--r--src/nat/Makefile.am9
-rw-r--r--src/nat/gnunet-helper-nat-client-windows.c529
-rw-r--r--src/nat/gnunet-helper-nat-server-windows.c614
-rw-r--r--src/nse/Makefile.am4
-rw-r--r--src/nt/Makefile.am4
-rw-r--r--src/peerinfo-tool/Makefile.am4
-rw-r--r--src/peerinfo/Makefile.am4
-rw-r--r--src/peerstore/Makefile.am4
-rw-r--r--src/pq/Makefile.am4
-rw-r--r--src/pt/Makefile.am18
-rw-r--r--src/pt/test_gnunet_vpn.c3
-rw-r--r--src/reclaim-attribute/Makefile.am4
-rw-r--r--src/reclaim/Makefile.am4
-rw-r--r--src/regex/Makefile.am4
-rw-r--r--src/rest/Makefile.am4
-rw-r--r--src/revocation/Makefile.am4
-rw-r--r--src/rps/Makefile.am4
-rw-r--r--src/scalarproduct/Makefile.am4
-rw-r--r--src/secretsharing/Makefile.am4
-rw-r--r--src/set/Makefile.am4
-rw-r--r--src/sq/Makefile.am4
-rw-r--r--src/statistics/Makefile.am4
-rw-r--r--src/template/Makefile.am4
-rw-r--r--src/testbed-logger/Makefile.am4
-rw-r--r--src/testbed/Makefile.am4
-rw-r--r--src/testbed/gnunet-service-testbed_cpustatus.c117
-rw-r--r--src/testbed/test_testbed_api_testbed_run.c13
-rw-r--r--src/testing/Makefile.am4
-rw-r--r--src/transport/Makefile.am18
-rw-r--r--src/transport/gnunet-helper-transport-bluetooth.c352
-rw-r--r--src/transport/plugin_transport_udp.c15
-rw-r--r--src/transport/plugin_transport_wlan.h7
-rw-r--r--src/transport/tcp_service_legacy.c111
-rw-r--r--src/util/Makefile.am43
-rw-r--r--src/util/disk.c88
-rw-r--r--src/util/dnsstub.c6
-rw-r--r--src/util/gnunet-timeout-w32.c193
-rw-r--r--src/util/network.c866
-rw-r--r--src/util/os_installation.c78
-rw-r--r--src/util/os_network.c29
-rw-r--r--src/util/os_priority.c615
-rw-r--r--src/util/scheduler.c46
-rw-r--r--src/util/service.c110
-rw-r--r--src/util/strings.c35
-rw-r--r--src/util/test_common_logging_runtime_loglevels.c4
-rw-r--r--src/util/test_configuration.c6
-rw-r--r--src/util/test_getopt.c4
-rw-r--r--src/util/test_resolver_api.c5
-rw-r--r--src/util/test_scheduler.c4
-rw-r--r--src/util/test_service.c3
-rw-r--r--src/util/test_strings.c6
-rw-r--r--src/util/w32cat.c154
-rw-r--r--src/util/win.c1365
-rw-r--r--src/util/winproc.c340
-rw-r--r--src/vpn/Makefile.am20
-rw-r--r--src/vpn/gnunet-helper-vpn-windows.c1610
-rw-r--r--src/zonemaster/Makefile.am4
97 files changed, 74 insertions, 11852 deletions
diff --git a/src/arm/Makefile.am b/src/arm/Makefile.am
index b1706a479..28440d857 100644
--- a/src/arm/Makefile.am
+++ b/src/arm/Makefile.am
@@ -8,10 +8,6 @@ libexecdir= $(pkglibdir)/libexec/
8pkgcfg_DATA = \ 8pkgcfg_DATA = \
9 arm.conf 9 arm.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = --coverage -O0 12 AM_CFLAGS = --coverage -O0
17 XLIB = -lgcov 13 XLIB = -lgcov
diff --git a/src/ats-tests/Makefile.am b/src/ats-tests/Makefile.am
index 83f9e1b6a..1804a43bf 100644
--- a/src/ats-tests/Makefile.am
+++ b/src/ats-tests/Makefile.am
@@ -5,10 +5,6 @@ pkgcfgdir= $(pkgdatadir)/config.d/
5 5
6libexecdir= $(pkglibdir)/libexec/ 6libexecdir= $(pkglibdir)/libexec/
7 7
8if MINGW
9 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
10endif
11
12if USE_COVERAGE 8if USE_COVERAGE
13 AM_CFLAGS = -fprofile-arcs -ftest-coverage 9 AM_CFLAGS = -fprofile-arcs -ftest-coverage
14endif 10endif
diff --git a/src/ats-tool/Makefile.am b/src/ats-tool/Makefile.am
index 55bfe1322..3bb99aa08 100644
--- a/src/ats-tool/Makefile.am
+++ b/src/ats-tool/Makefile.am
@@ -1,23 +1,19 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = -fprofile-arcs -ftest-coverage 5 AM_CFLAGS = -fprofile-arcs -ftest-coverage
10endif 6endif
11 7
12bin_PROGRAMS = \ 8bin_PROGRAMS = \
13 gnunet-ats 9 gnunet-ats
14 10
15gnunet_ats_SOURCES = \ 11gnunet_ats_SOURCES = \
16 gnunet-ats.c 12 gnunet-ats.c
17gnunet_ats_LDADD = \ 13gnunet_ats_LDADD = \
18 $(top_builddir)/src/util/libgnunetutil.la \ 14 $(top_builddir)/src/util/libgnunetutil.la \
19 $(top_builddir)/src/ats/libgnunetats.la \ 15 $(top_builddir)/src/ats/libgnunetats.la \
20 $(top_builddir)/src/nt/libgnunetnt.la \ 16 $(top_builddir)/src/nt/libgnunetnt.la \
21 $(top_builddir)/src/transport/libgnunettransport.la \ 17 $(top_builddir)/src/transport/libgnunettransport.la \
22 $(top_builddir)/src/hello/libgnunethello.la \ 18 $(top_builddir)/src/hello/libgnunethello.la \
23 $(GN_LIBINTL) 19 $(GN_LIBINTL)
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am
index ac8a411eb..d7e5b68c7 100644
--- a/src/ats/Makefile.am
+++ b/src/ats/Makefile.am
@@ -10,10 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 ats.conf 11 ats.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = -fprofile-arcs -ftest-coverage 14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
19endif 15endif
diff --git a/src/auction/Makefile.am b/src/auction/Makefile.am
index f86e846e2..0cb5d5a84 100644
--- a/src/auction/Makefile.am
+++ b/src/auction/Makefile.am
@@ -9,10 +9,6 @@ libexecdir = $(pkglibdir)/libexec/
9pkgcfg_DATA = \ 9pkgcfg_DATA = \
10 auction.conf 10 auction.conf
11 11
12if MINGW
13 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
14endif
15
16if USE_COVERAGE 12if USE_COVERAGE
17 AM_CFLAGS = -fprofile-arcs -ftest-coverage 13 AM_CFLAGS = -fprofile-arcs -ftest-coverage
18endif 14endif
diff --git a/src/block/Makefile.am b/src/block/Makefile.am
index 05df7541d..d769f7d47 100644
--- a/src/block/Makefile.am
+++ b/src/block/Makefile.am
@@ -3,10 +3,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
5 5
6if MINGW
7 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
8endif
9
10if USE_COVERAGE 6if USE_COVERAGE
11 AM_CFLAGS = --coverage 7 AM_CFLAGS = --coverage
12endif 8endif
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am
index e7d42f60f..cd4beb4b7 100644
--- a/src/cadet/Makefile.am
+++ b/src/cadet/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
@@ -38,7 +34,7 @@ libgnunetcadet_la_SOURCES = \
38 cadet_api_get_path.c \ 34 cadet_api_get_path.c \
39 cadet_api_list_peers.c \ 35 cadet_api_list_peers.c \
40 cadet_api_list_tunnels.c \ 36 cadet_api_list_tunnels.c \
41 cadet_api_helper.c 37 cadet_api_helper.c
42libgnunetcadet_la_LIBADD = \ 38libgnunetcadet_la_LIBADD = \
43 $(top_builddir)/src/util/libgnunetutil.la \ 39 $(top_builddir)/src/util/libgnunetutil.la \
44 $(XLIB) \ 40 $(XLIB) \
diff --git a/src/consensus/Makefile.am b/src/consensus/Makefile.am
index 991e36a95..4ad224aa3 100644
--- a/src/consensus/Makefile.am
+++ b/src/consensus/Makefile.am
@@ -10,10 +10,6 @@ plugindir = $(libdir)/gnunet
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 consensus.conf 11 consensus.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = -fprofile-arcs -ftest-coverage 14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
19endif 15endif
diff --git a/src/conversation/Makefile.am b/src/conversation/Makefile.am
index c329bebf5..dc8283e9b 100644
--- a/src/conversation/Makefile.am
+++ b/src/conversation/Makefile.am
@@ -3,10 +3,6 @@ SUBDIRS = .
3 3
4plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
5 5
6if MINGW
7 WINFLAGS = -no-undefined -Wl,--export-all-symbols
8endif
9
10AM_CPPFLAGS = \ 6AM_CPPFLAGS = \
11 $(GNUNET_CPPFLAGS) \ 7 $(GNUNET_CPPFLAGS) \
12 -I$(top_srcdir)/src/include \ 8 -I$(top_srcdir)/src/include \
diff --git a/src/conversation/gnunet_gst_def.h b/src/conversation/gnunet_gst_def.h
index 341341f24..5f5910121 100644
--- a/src/conversation/gnunet_gst_def.h
+++ b/src/conversation/gnunet_gst_def.h
@@ -65,14 +65,12 @@
65#include <gst/app/gstappsink.h> 65#include <gst/app/gstappsink.h>
66 66
67// sockets 67// sockets
68#ifndef MINGW
69#if HAVE_NETINET_IN_H 68#if HAVE_NETINET_IN_H
70#include <netinet/in.h> 69#include <netinet/in.h>
71#endif 70#endif
72#include <sys/socket.h> 71#include <sys/socket.h>
73#include <arpa/inet.h> 72#include <arpa/inet.h>
74#include <netdb.h> 73#include <netdb.h>
75#endif
76 74
77#include <sys/types.h> 75#include <sys/types.h>
78#include <fcntl.h> 76#include <fcntl.h>
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 70ec91fbc..902be3599 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -8,10 +8,6 @@ libexecdir= $(pkglibdir)/libexec/
8pkgcfg_DATA = \ 8pkgcfg_DATA = \
9 core.conf 9 core.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = --coverage -O0 12 AM_CFLAGS = --coverage -O0
17 XLIB = -lgcov 13 XLIB = -lgcov
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am
index 898b51563..9fc00bace 100644
--- a/src/datacache/Makefile.am
+++ b/src/datacache/Makefile.am
@@ -8,10 +8,6 @@ pkgcfgdir= $(pkgdatadir)/config.d/
8dist_pkgcfg_DATA = \ 8dist_pkgcfg_DATA = \
9 datacache.conf 9 datacache.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = --coverage -O0 12 AM_CFLAGS = --coverage -O0
17 XLIBS = -lgcov 13 XLIBS = -lgcov
diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am
index 240abbc67..ba65143af 100644
--- a/src/datastore/Makefile.am
+++ b/src/datastore/Makefile.am
@@ -10,10 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 datastore.conf 11 datastore.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
19 XLIBS = -lgcov 15 XLIBS = -lgcov
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index c52ac93c7..82d76f33c 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -1,8 +1,5 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32
5endif
6 3
7plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
8 5
diff --git a/src/dns/Makefile.am b/src/dns/Makefile.am
index ca2685765..33ec8ef85 100644
--- a/src/dns/Makefile.am
+++ b/src/dns/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10endif 6endif
diff --git a/src/exit/Makefile.am b/src/exit/Makefile.am
index ea4f08c73..b7286349d 100644
--- a/src/exit/Makefile.am
+++ b/src/exit/Makefile.am
@@ -1,11 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined,--export-all-symbols
6 EXITBIN = gnunet-helper-exit
7endif
8
9if USE_COVERAGE 4if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
11endif 6endif
@@ -32,20 +27,10 @@ libexec_PROGRAMS = \
32 gnunet-daemon-exit \ 27 gnunet-daemon-exit \
33 $(EXITBIN) 28 $(EXITBIN)
34 29
35if MINGW
36 gnunet_helper_exit_LDFLAGS = \
37 -no-undefined -Wl,--export-all-symbols
38 30
39 gnunet_helper_exit_LDADD = \ 31gnunet_helper_exit_SOURCES = \
40 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ 32 gnunet-helper-exit.c
41 -lcomdlg32 -lgdi32 -liphlpapi
42 33
43 gnunet_helper_exit_SOURCES = \
44 gnunet-helper-exit-windows.c
45else
46 gnunet_helper_exit_SOURCES = \
47 gnunet-helper-exit.c
48endif
49gnunet_daemon_exit_SOURCES = \ 34gnunet_daemon_exit_SOURCES = \
50 gnunet-daemon-exit.c exit.h 35 gnunet-daemon-exit.c exit.h
51gnunet_daemon_exit_LDADD = \ 36gnunet_daemon_exit_LDADD = \
diff --git a/src/exit/gnunet-helper-exit-windows.c b/src/exit/gnunet-helper-exit-windows.c
deleted file mode 100644
index 0ffd28148..000000000
--- a/src/exit/gnunet-helper-exit-windows.c
+++ /dev/null
@@ -1,1699 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010, 2012 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file exit/gnunet-helper-exit-windows.c
22 * @brief the helper for the EXIT service in win32 builds.
23 * Opens a virtual network-interface, sends data received on the if to stdout,
24 * sends data received on stdin to the interface
25 * @author Christian M. Fuchs
26 *
27 * The following list of people have reviewed this code and considered
28 * it safe since the last modification (if you reviewed it, please
29 * have your name added to the list):
30 *
31 */
32
33#include <stdio.h>
34#include <Winsock2.h>
35#include <windows.h>
36#include <setupapi.h>
37#ifndef __MINGW64_VERSION_MAJOR
38#include <ddk/cfgmgr32.h>
39#include <ddk/newdev.h>
40#else
41#include <cfgmgr32.h>
42#include <newdev.h>
43#endif
44#include <time.h>
45#include "platform.h"
46#include "tap-windows.h"
47/**
48 * Need 'struct GNUNET_HashCode' and 'struct GNUNET_PeerIdentity'.
49 */
50#include "gnunet_crypto_lib.h"
51/**
52 * Need 'struct GNUNET_MessageHeader'.
53 */
54#include "gnunet_common.h"
55
56/**
57 * Need VPN message types.
58 */
59#include "gnunet_protocols.h"
60
61/**
62 * Should we print (interesting|debug) messages that can happen during
63 * normal operation?
64 */
65#define DEBUG GNUNET_NO
66
67#if DEBUG
68/* FIXME: define with varargs... */
69#define LOG_DEBUG(msg) fprintf(stderr, "%s", msg);
70#else
71#define LOG_DEBUG(msg) do {} while (0)
72#endif
73
74/**
75 * Will this binary be run in permissions testing mode?
76 */
77static boolean privilege_testing = FALSE;
78
79/**
80 * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
81 */
82#define MAX_SIZE 65536
83
84/**
85 * Name or Path+Name of our win32 driver.
86 * The .sys and .cat files HAVE to be in the same location as this file!
87 */
88#define INF_FILE "share/gnunet/openvpn-tap32/tapw32/OemWin2k.inf"
89
90/**
91 * Name or Path+Name of our win64 driver.
92 * The .sys and .cat files HAVE to be in the same location as this file!
93 */
94#define INF_FILE64 "share/gnunet/openvpn-tap32/tapw64/OemWin2k.inf"
95
96/**
97 * Hardware ID used in the inf-file.
98 * This might change over time, as openvpn advances their driver
99 */
100#define HARDWARE_ID "tap0901"
101
102/**
103 * Minimum major-id of the driver version we can work with
104 */
105#define TAP_WIN_MIN_MAJOR 9
106
107/**
108 * Minimum minor-id of the driver version we can work with.
109 * v <= 7 has buggy IPv6.
110 * v == 8 is broken for small IPv4 Packets
111 */
112#define TAP_WIN_MIN_MINOR 9
113
114/**
115 * Time in seconds to wait for our virtual device to go up after telling it to do so.
116 *
117 * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt
118 * (in fact, 4 was chosen by a fair dice roll...)
119 */
120#define TAP32_POSTUP_WAITTIME 4
121
122/**
123 * Location of the network interface list resides in registry.
124 */
125#define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
126
127/**
128 * Our local process' PID. Used for creating a sufficiently unique additional
129 * hardware ID for our device.
130 */
131static char secondary_hwid[LINE_LEN / 2];
132
133/**
134 * Device's visible Name, used to identify a network device in netsh.
135 * eg: "Local Area Connection 9"
136 */
137static char device_visible_name[256];
138
139/**
140 * This is our own local instance of a virtual network interface
141 * It is (somewhat) equivalent to using tun/tap in unixoid systems
142 *
143 * Upon initialization, we create such an device node.
144 * Upon termination, we remove it again.
145 *
146 * If we crash this device might stay around.
147 */
148static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE;
149
150/**
151 * Registry Key we hand over to windows to spawn a new virtual interface
152 */
153static SP_DEVINFO_DATA DeviceNode;
154
155/**
156 * GUID of our virtual device in the form of
157 * {12345678-1234-1234-1234-123456789abc} - in hex
158 */
159static char device_guid[256];
160
161
162/**
163 * Possible states of an IO facility.
164 */
165enum IO_State {
166 /**
167 * overlapped I/O is ready for work
168 */
169 IOSTATE_READY = 0,
170
171 /**
172 * overlapped I/O has been queued
173 */
174 IOSTATE_QUEUED,
175
176 /**
177 * overlapped I/O has finished, but is waiting for it's write-partner
178 */
179 IOSTATE_WAITING,
180
181 /**
182 * there is a full buffer waiting
183 */
184 IOSTATE_RESUME,
185
186 /**
187 * Operlapped IO states for facility objects
188 * overlapped I/O has failed, stop processing
189 */
190 IOSTATE_FAILED
191};
192
193
194/**
195 * A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling
196 */
197struct io_facility {
198 /**
199 * The mode the state machine associated with this object is in.
200 */
201 enum IO_State facility_state;
202
203 /**
204 * If the path is open or blocked in general (used for quickly checking)
205 */
206 BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)!
207
208 /**
209 * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT)
210 */
211 HANDLE handle;
212
213 /**
214 * Overlaped IO structure used for asynchronous IO in windows.
215 */
216 OVERLAPPED overlapped;
217
218 /**
219 * Buffer for reading things to and writing from...
220 */
221 unsigned char buffer[MAX_SIZE];
222
223 /**
224 * How much of this buffer was used when reading or how much data can be written
225 */
226 DWORD buffer_size;
227
228 /**
229 * Amount of data actually written or read by readfile/writefile.
230 */
231 DWORD buffer_size_processed;
232
233 /**
234 * How much of this buffer we have written in total
235 */
236 DWORD buffer_size_written;
237};
238
239/**
240 * ReOpenFile is only available as of XP SP2 and 2003 SP1
241 */
242WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE, DWORD, DWORD, DWORD);
243
244/**
245 * IsWow64Process definition for our is_win64, as this is a kernel function
246 */
247typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
248
249
250/**
251 * Like strlcpy but portable. The given string @a src is copied until its null
252 * byte or until @a n - 1 bytes have been read. The destination buffer is
253 * guaranteed to be null-terminated.
254 *
255 * @param dst destination of the copy (must be @a n bytes long)
256 * @param src source of the copy (at most @a n - 1 bytes will be read)
257 * @param n the length of the string to copy, including its terminating null
258 * byte
259 * @return the length of the string that was copied, excluding the terminating
260 * null byte
261 */
262size_t
263GNUNET_strlcpy(char *dst, const char *src, size_t n)
264{
265 size_t ret;
266 size_t slen;
267
268 GNUNET_assert(0 != n);
269 slen = strnlen(src, n - 1);
270 memcpy(dst, src, slen);
271 dst[slen] = '\0';
272 return slen;
273}
274
275
276/**
277 * Determines if the host OS is win32 or win64
278 *
279 * @return true if
280 */
281BOOL
282is_win64()
283{
284#if defined(_WIN64)
285 //this is a win64 binary,
286 return TRUE;
287#elif defined(_WIN32)
288 //this is a 32bit binary, and we need to check if we are running in WOW64
289 BOOL success = FALSE;
290 BOOL on_wow64 = FALSE;
291 LPFN_ISWOW64PROCESS IsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
292
293 if (NULL != IsWow64Process)
294 success = IsWow64Process(GetCurrentProcess(), &on_wow64);
295
296 return success && on_wow64;
297#endif
298}
299/**
300 * Wrapper for executing a shellcommand in windows.
301 *
302 * @param command - the command + parameters to execute
303 * @return * exitcode of the program executed,
304 * * EINVAL (cmd/file not found)
305 * * EPIPE (could not read STDOUT)
306 */
307static int
308execute_shellcommand(const char *command)
309{
310 FILE *pipe;
311
312 if ((NULL == command) ||
313 (NULL == (pipe = _popen(command, "rt"))))
314 return EINVAL;
315
316#if DEBUG
317 fprintf(stderr, "DEBUG: Command output: \n");
318 char output[LINE_LEN];
319 while (NULL != fgets(output, sizeof(output), pipe))
320 fprintf(stderr, "%s", output);
321#endif
322
323 return _pclose(pipe);
324}
325
326
327/**
328 * @brief Sets the IPv6-Address given in address on the interface dev
329 *
330 * @param address the IPv6-Address
331 * @param prefix_len the length of the network-prefix
332 */
333static int
334set_address6(const char *address, unsigned long prefix_len)
335{
336 int ret = EINVAL;
337 char command[LINE_LEN];
338 struct sockaddr_in6 sa6;
339
340 /*
341 * parse the new address
342 */
343 memset(&sa6, 0, sizeof(struct sockaddr_in6));
344 sa6.sin6_family = AF_INET6;
345 if (1 != inet_pton(AF_INET6, address, &sa6.sin6_addr.s6_addr))
346 {
347 fprintf(stderr, "ERROR: Failed to parse address `%s': %s\n", address,
348 strerror(errno));
349 return -1;
350 }
351
352 /*
353 * prepare the command
354 */
355 snprintf(command, LINE_LEN,
356 "netsh interface ipv6 add address \"%s\" %s/%d store=active",
357 device_visible_name, address, prefix_len);
358 /*
359 * Set the address
360 */
361 ret = execute_shellcommand(command);
362
363 /* Did it work?*/
364 if (0 != ret)
365 fprintf(stderr, "FATAL: Setting IPv6 address failed: %s\n", strerror(ret));
366 return ret;
367}
368
369
370/**
371 * @brief Removes the IPv6-Address given in address from the interface dev
372 *
373 * @param address the IPv4-Address
374 */
375static void
376remove_address6(const char *address)
377{
378 char command[LINE_LEN];
379 int ret = EINVAL;
380
381 // sanity checking was already done in set_address6
382 /*
383 * prepare the command
384 */
385 snprintf(command, LINE_LEN,
386 "netsh interface ipv6 delete address \"%s\" store=persistent",
387 device_visible_name);
388 /*
389 * Set the address
390 */
391 ret = execute_shellcommand(command);
392
393 /* Did it work?*/
394 if (0 != ret)
395 fprintf(stderr, "FATAL: removing IPv6 address failed: %s\n", strerror(ret));
396}
397
398
399/**
400 * @brief Sets the IPv4-Address given in address on the interface dev
401 *
402 * @param address the IPv4-Address
403 * @param mask the netmask
404 */
405static int
406set_address4(const char *address, const char *mask)
407{
408 int ret = EINVAL;
409 char command[LINE_LEN];
410
411 struct sockaddr_in addr;
412
413 addr.sin_family = AF_INET;
414
415 /*
416 * Parse the address
417 */
418 if (1 != inet_pton(AF_INET, address, &addr.sin_addr.s_addr))
419 {
420 fprintf(stderr, "ERROR: Failed to parse address `%s': %s\n", address,
421 strerror(errno));
422 return -1;
423 }
424 // Set Device to Subnet-Mode?
425 // do we really need tun.c:2925 ?
426
427 /*
428 * prepare the command
429 */
430 snprintf(command, LINE_LEN,
431 "netsh interface ipv4 add address \"%s\" %s %s store=active",
432 device_visible_name, address, mask);
433 /*
434 * Set the address
435 */
436 ret = execute_shellcommand(command);
437
438 /* Did it work?*/
439 if (0 != ret)
440 fprintf(stderr, "FATAL: Setting IPv4 address failed: %s\n", strerror(ret));
441 return ret;
442}
443
444
445/**
446 * @brief Removes the IPv4-Address given in address from the interface dev
447 *
448 * @param address the IPv4-Address
449 */
450static void
451remove_address4(const char *address)
452{
453 char command[LINE_LEN];
454 int ret = EINVAL;
455
456 // sanity checking was already done in set_address4
457
458 /*
459 * prepare the command
460 */
461 snprintf(command, LINE_LEN,
462 "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent",
463 device_visible_name);
464 /*
465 * Set the address
466 */
467 ret = execute_shellcommand(command);
468
469 /* Did it work?*/
470 if (0 != ret)
471 fprintf(stderr, "FATAL: removing IPv4 address failed: %s\n", strerror(ret));
472}
473
474
475/**
476 * Setup a new virtual interface to use for tunneling.
477 *
478 * @return: TRUE if setup was successful, else FALSE
479 */
480static BOOL
481setup_interface()
482{
483 /*
484 * where to find our inf-file. (+ the "full" path, after windows found")
485 *
486 * We do not directly input all the props here, because openvpn will update
487 * these details over time.
488 */
489 char inf_file_path[MAX_PATH];
490 char * temp_inf_filename;
491 char hwidlist[LINE_LEN + 4];
492 char class_name[128];
493 GUID class_guid;
494 int str_length = 0;
495
496 /**
497 * Set the device's hardware ID and add it to a list.
498 * This information will later on identify this device in registry.
499 */
500 str_length = GNUNET_strlcpy(hwidlist,
501 HARDWARE_ID,
502 sizeof(hwidlist)) + 1;
503 /**
504 * this is kind of over-complicated, but allows keeps things independent of
505 * how the openvpn-hwid is actually stored.
506 *
507 * A HWID list is double-\0 terminated and \0 separated
508 */
509 str_length = strlen(hwidlist) + 1;
510 str_length += GNUNET_strlcpy(&hwidlist[str_length],
511 secondary_hwid,
512 sizeof(hwidlist) - str_length) + 1;
513 GNUNET_assert(str_length < sizeof(hwidlist));
514 hwidlist[str_length] = '\0';
515 ++str_length;
516
517 /**
518 * Locate the inf-file, we need to store it somewhere where the system can
519 * find it. We need to pick the correct driver for win32/win64.
520 */
521 if (is_win64())
522 GetFullPathNameA(INF_FILE64, MAX_PATH, inf_file_path, &temp_inf_filename);
523 else
524 GetFullPathNameA(INF_FILE, MAX_PATH, inf_file_path, &temp_inf_filename);
525
526 fprintf(stderr, "INFO: Located our driver's .inf file at %s\n", inf_file_path);
527 /**
528 * Bootstrap our device info using the drivers inf-file
529 */
530 if (!SetupDiGetINFClassA(inf_file_path,
531 &class_guid,
532 class_name, sizeof(class_name) / sizeof(char),
533 NULL))
534 return FALSE;
535
536 /**
537 * Collect all the other needed information...
538 * let the system fill our this form
539 */
540 DeviceInfo = SetupDiCreateDeviceInfoList(&class_guid, NULL);
541 if (DeviceInfo == INVALID_HANDLE_VALUE)
542 return FALSE;
543
544 DeviceNode.cbSize = sizeof(SP_DEVINFO_DATA);
545 if (!SetupDiCreateDeviceInfoA(DeviceInfo,
546 class_name,
547 &class_guid,
548 NULL,
549 0,
550 DICD_GENERATE_ID,
551 &DeviceNode))
552 return FALSE;
553
554 /* Deploy all the information collected into the registry */
555 if (!SetupDiSetDeviceRegistryPropertyA(DeviceInfo,
556 &DeviceNode,
557 SPDRP_HARDWAREID,
558 (LPBYTE)hwidlist,
559 str_length * sizeof(char)))
560 return FALSE;
561
562 /* Install our new class(=device) into the system */
563 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
564 DeviceInfo,
565 &DeviceNode))
566 return FALSE;
567
568 /* This system call tends to take a while (several seconds!) on
569 "modern" Windoze systems */
570 if (!UpdateDriverForPlugAndPlayDevicesA(NULL,
571 secondary_hwid,
572 inf_file_path,
573 INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE,
574 NULL)) //reboot required? NEVER!
575 return FALSE;
576
577 fprintf(stderr, "DEBUG: successfully created a network device\n");
578 return TRUE;
579}
580
581
582/**
583 * Remove our new virtual interface to use for tunneling.
584 * This function must be called AFTER setup_interface!
585 *
586 * @return: TRUE if destruction was successful, else FALSE
587 */
588static BOOL
589remove_interface()
590{
591 SP_REMOVEDEVICE_PARAMS remove;
592
593 if (INVALID_HANDLE_VALUE == DeviceInfo)
594 return FALSE;
595
596 remove.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
597 remove.HwProfile = 0;
598 remove.Scope = DI_REMOVEDEVICE_GLOBAL;
599 remove.ClassInstallHeader.InstallFunction = DIF_REMOVE;
600 /*
601 * 1. Prepare our existing device information set, and place the
602 * uninstall related information into the structure
603 */
604 if (!SetupDiSetClassInstallParamsA(DeviceInfo,
605 (PSP_DEVINFO_DATA)&DeviceNode,
606 &remove.ClassInstallHeader,
607 sizeof(remove)))
608 return FALSE;
609 /*
610 * 2. Uninstall the virtual interface using the class installer
611 */
612 if (!SetupDiCallClassInstaller(DIF_REMOVE,
613 DeviceInfo,
614 (PSP_DEVINFO_DATA)&DeviceNode))
615 return FALSE;
616
617 SetupDiDestroyDeviceInfoList(DeviceInfo);
618
619 fprintf(stderr, "DEBUG: removed interface successfully\n");
620
621 return TRUE;
622}
623
624
625/**
626 * Do all the lookup necessary to retrieve the inteface's actual name
627 * off the registry.
628 *
629 * @return: TRUE if we were able to lookup the interface's name, else FALSE
630 */
631static BOOL
632resolve_interface_name()
633{
634 SP_DEVINFO_LIST_DETAIL_DATA device_details;
635 char pnp_instance_id [MAX_DEVICE_ID_LEN];
636 HKEY adapter_key_handle;
637 LONG status;
638 DWORD len;
639 int i = 0;
640 int retrys;
641 BOOL retval = FALSE;
642 char adapter[] = INTERFACE_REGISTRY_LOCATION;
643
644 /* We can obtain the PNP instance ID from our setupapi handle */
645 device_details.cbSize = sizeof(device_details);
646 if (CR_SUCCESS != CM_Get_Device_ID_ExA(DeviceNode.DevInst,
647 (PCHAR)pnp_instance_id,
648 MAX_DEVICE_ID_LEN,
649 0, //must be 0
650 NULL)) //hMachine, we are local
651 return FALSE;
652
653 fprintf(stderr, "DEBUG: Resolving interface name for network device %s\n", pnp_instance_id);
654
655 /* Registry is incredibly slow, retry for up to 30 seconds to allow registry to refresh */
656 for (retrys = 0; retrys < 120 && !retval; retrys++)
657 {
658 /* sleep for 250ms*/
659 Sleep(250);
660
661 /* Now we can use this ID to locate the correct networks interface in registry */
662 if (ERROR_SUCCESS != RegOpenKeyExA(
663 HKEY_LOCAL_MACHINE,
664 adapter,
665 0,
666 KEY_READ,
667 &adapter_key_handle))
668 return FALSE;
669
670 /* Of course there is a multitude of entries here, with arbitrary names,
671 * thus we need to iterate through there.
672 */
673 while (!retval)
674 {
675 char instance_key[256];
676 char query_key [256];
677 HKEY instance_key_handle;
678 char pnpinstanceid_name[] = "PnpInstanceID";
679 char pnpinstanceid_value[256];
680 char adaptername_name[] = "Name";
681 DWORD data_type;
682
683 len = 256 * sizeof(char);
684 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */
685 status = RegEnumKeyExA(
686 adapter_key_handle,
687 i,
688 instance_key,
689 &len,
690 NULL,
691 NULL,
692 NULL,
693 NULL);
694
695 /* this may fail due to one of two reasons:
696 * we are at the end of the list*/
697 if (ERROR_NO_MORE_ITEMS == status)
698 break;
699 // * we found a broken registry key, continue with the next key.
700 if (ERROR_SUCCESS != status)
701 goto cleanup;
702
703 /* prepare our new query string: */
704 snprintf(query_key, 256, "%s\\%s\\Connection",
705 adapter,
706 instance_key);
707
708 /* look inside instance_key\\Connection */
709 if (ERROR_SUCCESS != RegOpenKeyExA(
710 HKEY_LOCAL_MACHINE,
711 query_key,
712 0,
713 KEY_READ,
714 &instance_key_handle))
715 goto cleanup;
716
717 /* now, read our PnpInstanceID */
718 len = sizeof(pnpinstanceid_value);
719 status = RegQueryValueExA(instance_key_handle,
720 pnpinstanceid_name,
721 NULL, //reserved, always NULL according to MSDN
722 &data_type,
723 (LPBYTE)pnpinstanceid_value,
724 &len);
725
726 if (status != ERROR_SUCCESS || data_type != REG_SZ)
727 goto cleanup;
728
729 /* compare the value we got to our devices PNPInstanceID*/
730 if (0 != strncmp(pnpinstanceid_value, pnp_instance_id,
731 sizeof(pnpinstanceid_value) / sizeof(char)))
732 goto cleanup;
733
734 len = sizeof(device_visible_name);
735 status = RegQueryValueExA(
736 instance_key_handle,
737 adaptername_name,
738 NULL, //reserved, always NULL according to MSDN
739 &data_type,
740 (LPBYTE)device_visible_name,
741 &len);
742
743 if (status != ERROR_SUCCESS || data_type != REG_SZ)
744 goto cleanup;
745
746 /*
747 * we have successfully found OUR instance,
748 * save the device GUID before exiting
749 */
750 GNUNET_strlcpy(device_guid, instance_key, sizeof(device_guid));
751 retval = TRUE;
752 fprintf(stderr, "DEBUG: Interface Name lookup succeeded on retry %d, got \"%s\" %s\n", retrys, device_visible_name, device_guid);
753
754cleanup:
755 RegCloseKey(instance_key_handle);
756
757 ++i;
758 }
759
760 RegCloseKey(adapter_key_handle);
761 }
762 return retval;
763}
764
765
766/**
767 * Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET
768 *
769 * @param handle the handle to our tap device
770 * @return TRUE if the version is sufficient, else FALSE
771 */
772static BOOL
773check_tapw32_version(HANDLE handle)
774{
775 ULONG version[3];
776 DWORD len;
777
778 memset(&(version), 0, sizeof(version));
779
780 if (DeviceIoControl(handle, TAP_WIN_IOCTL_GET_VERSION,
781 &version, sizeof(version),
782 &version, sizeof(version), &len, NULL))
783 fprintf(stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n",
784 (int)version[0],
785 (int)version[1],
786 (version[2] ? "(DEBUG)" : ""));
787
788 if ((version[0] != TAP_WIN_MIN_MAJOR) ||
789 (version[1] < TAP_WIN_MIN_MINOR))
790 {
791 fprintf(stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d\n",
792 TAP_WIN_MIN_MAJOR,
793 TAP_WIN_MIN_MINOR);
794 return FALSE;
795 }
796
797 return TRUE;
798}
799
800
801/**
802 * Creates a tun-interface called dev;
803 *
804 * @return the fd to the tun or -1 on error
805 */
806static HANDLE
807init_tun()
808{
809 char device_path[256];
810 HANDLE handle;
811
812 if (!setup_interface())
813 {
814 errno = ENODEV;
815 return INVALID_HANDLE_VALUE;
816 }
817
818 if (!resolve_interface_name())
819 {
820 errno = ENODEV;
821 return INVALID_HANDLE_VALUE;
822 }
823
824 /* Open Windows TAP-Windows adapter */
825 snprintf(device_path, sizeof(device_path), "%s%s%s",
826 USERMODEDEVICEDIR,
827 device_guid,
828 TAP_WIN_SUFFIX);
829
830 handle = CreateFile(
831 device_path,
832 GENERIC_READ | GENERIC_WRITE,
833 0, /* was: FILE_SHARE_READ */
834 0,
835 OPEN_EXISTING,
836 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
837 0
838 );
839
840 if (INVALID_HANDLE_VALUE == handle)
841 {
842 fprintf(stderr, "FATAL: CreateFile failed on TAP device: %s\n", device_path);
843 return handle;
844 }
845
846 /* get driver version info */
847 if (!check_tapw32_version(handle))
848 {
849 CloseHandle(handle);
850 return INVALID_HANDLE_VALUE;
851 }
852
853 /* TODO (opt?): get MTU-Size */
854
855 fprintf(stderr, "DEBUG: successfully opened TAP device\n");
856 return handle;
857}
858
859
860/**
861 * Brings a TAP device up and sets it to connected state.
862 *
863 * @param handle the handle to our TAP device
864 * @return True if the operation succeeded, else false
865 */
866static BOOL
867tun_up(HANDLE handle)
868{
869 ULONG status = TRUE;
870 DWORD len;
871
872 if (!DeviceIoControl(handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
873 &status, sizeof(status),
874 &status, sizeof(status), &len, NULL))
875 {
876 fprintf(stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)\n");
877 return FALSE;
878 }
879
880 /* Wait for the device to go UP, might take some time. */
881 Sleep(TAP32_POSTUP_WAITTIME * 1000);
882 fprintf(stderr, "DEBUG: successfully set TAP device to UP\n");
883
884 return TRUE;
885}
886
887
888/**
889 * Attempts to read off an input facility (tap or named pipe) in overlapped mode.
890 *
891 * 1.
892 * If the input facility is in IOSTATE_READY, it will issue a new read operation to the
893 * input handle. Then it goes into IOSTATE_QUEUED state.
894 * In case the read succeeded instantly the input facility enters 3.
895 *
896 * 2.
897 * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already.
898 * If it has finished, go to state 3.
899 * If it has failed, set IOSTATE_FAILED
900 *
901 * 3.
902 * If the output facility is in state IOSTATE_READY, the read-buffer is copied to the output buffer.
903 * The input facility enters state IOSTATE_READY
904 * The output facility enters state IOSTATE_READY
905 * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING
906 *
907 * IOSTATE_WAITING is reset by the output facility, once it has completed.
908 *
909 * @param input_facility input named pipe or file to work with.
910 * @param output_facility output pipe or file to hand over data to.
911 * @return false if an event reset was impossible (OS error), else true
912 */
913static BOOL
914attempt_read_tap(struct io_facility * input_facility,
915 struct io_facility * output_facility)
916{
917 struct GNUNET_MessageHeader * hdr;
918 unsigned short size;
919
920 switch (input_facility->facility_state)
921 {
922 case IOSTATE_READY:
923 {
924 if (!ResetEvent(input_facility->overlapped.hEvent))
925 {
926 return FALSE;
927 }
928
929 input_facility->buffer_size = 0;
930
931 /* Check how the task is handled */
932 if (ReadFile(input_facility->handle,
933 input_facility->buffer,
934 sizeof(input_facility->buffer) - sizeof(struct GNUNET_MessageHeader),
935 &input_facility->buffer_size,
936 &input_facility->overlapped))
937 { /* async event processed immediately*/
938 /* reset event manually*/
939 if (!SetEvent(input_facility->overlapped.hEvent))
940 return FALSE;
941
942 fprintf(stderr, "DEBUG: tap read succeeded immediately\n");
943
944 /* we successfully read something from the TAP and now need to
945 * send it our via STDOUT. Is that possible at the moment? */
946 if ((IOSTATE_READY == output_facility->facility_state ||
947 IOSTATE_WAITING == output_facility->facility_state)
948 && (0 < input_facility->buffer_size))
949 { /* hand over this buffers content and apply message header for gnunet */
950 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
951 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
952
953 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
954 input_facility->buffer,
955 input_facility->buffer_size);
956
957 output_facility->buffer_size = size;
958 hdr->size = htons(size);
959 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
960 output_facility->facility_state = IOSTATE_READY;
961 }
962 else if (0 < input_facility->buffer_size)
963 /* If we have have read our buffer, wait for our write-partner*/
964 input_facility->facility_state = IOSTATE_WAITING;
965 }
966 else /* operation was either queued or failed*/
967 {
968 int err = GetLastError();
969 if (ERROR_IO_PENDING == err)
970 { /* operation queued */
971 input_facility->facility_state = IOSTATE_QUEUED;
972 }
973 else
974 { /* error occurred, let the rest of the elements finish */
975 input_facility->path_open = FALSE;
976 input_facility->facility_state = IOSTATE_FAILED;
977 if (IOSTATE_WAITING == output_facility->facility_state)
978 output_facility->path_open = FALSE;
979
980 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
981 }
982 }
983 }
984 return TRUE;
985
986 // We are queued and should check if the read has finished
987 case IOSTATE_QUEUED:
988 {
989 // there was an operation going on already, check if that has completed now.
990
991 if (GetOverlappedResult(input_facility->handle,
992 &input_facility->overlapped,
993 &input_facility->buffer_size,
994 FALSE))
995 { /* successful return for a queued operation */
996 if (!ResetEvent(input_facility->overlapped.hEvent))
997 return FALSE;
998
999 fprintf(stderr, "DEBUG: tap read succeeded delayed\n");
1000
1001 /* we successfully read something from the TAP and now need to
1002 * send it our via STDOUT. Is that possible at the moment? */
1003 if ((IOSTATE_READY == output_facility->facility_state ||
1004 IOSTATE_WAITING == output_facility->facility_state)
1005 && 0 < input_facility->buffer_size)
1006 { /* hand over this buffers content and apply message header for gnunet */
1007 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
1008 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
1009
1010 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1011 input_facility->buffer,
1012 input_facility->buffer_size);
1013
1014 output_facility->buffer_size = size;
1015 hdr->size = htons(size);
1016 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1017 output_facility->facility_state = IOSTATE_READY;
1018 input_facility->facility_state = IOSTATE_READY;
1019 }
1020 else if (0 < input_facility->buffer_size)
1021 { /* If we have have read our buffer, wait for our write-partner*/
1022 input_facility->facility_state = IOSTATE_WAITING;
1023 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
1024 }
1025 }
1026 else
1027 { /* operation still pending/queued or failed? */
1028 int err = GetLastError();
1029 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1030 { /* error occurred, let the rest of the elements finish */
1031 input_facility->path_open = FALSE;
1032 input_facility->facility_state = IOSTATE_FAILED;
1033 if (IOSTATE_WAITING == output_facility->facility_state)
1034 output_facility->path_open = FALSE;
1035 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1036 }
1037 }
1038 }
1039 return TRUE;
1040
1041 case IOSTATE_RESUME:
1042 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
1043 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
1044
1045 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1046 input_facility->buffer,
1047 input_facility->buffer_size);
1048
1049 output_facility->buffer_size = size;
1050 hdr->size = htons(size);
1051 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1052 output_facility->facility_state = IOSTATE_READY;
1053 input_facility->facility_state = IOSTATE_READY;
1054 return TRUE;
1055
1056 default:
1057 return TRUE;
1058 }
1059}
1060
1061
1062/**
1063 * Attempts to read off an input facility (tap or named pipe) in overlapped mode.
1064 *
1065 * 1.
1066 * If the input facility is in IOSTATE_READY, it will issue a new read operation to the
1067 * input handle. Then it goes into IOSTATE_QUEUED state.
1068 * In case the read succeeded instantly the input facility enters 3.
1069 *
1070 * 2.
1071 * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already.
1072 * If it has finished, go to state 3.
1073 * If it has failed, set IOSTATE_FAILED
1074 *
1075 * 3.
1076 * If the facility is finished with ready
1077 * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader.
1078 * The input facility enters state IOSTATE_READY
1079 * The output facility enters state IOSTATE_READY
1080 * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING
1081 *
1082 * IOSTATE_WAITING is reset by the output facility, once it has completed.
1083 *
1084 * @param input_facility input named pipe or file to work with.
1085 * @param output_facility output pipe or file to hand over data to.
1086 * @return false if an event reset was impossible (OS error), else true
1087 */
1088static BOOL
1089attempt_read_stdin(struct io_facility * input_facility,
1090 struct io_facility * output_facility)
1091{
1092 struct GNUNET_MessageHeader * hdr;
1093
1094 switch (input_facility->facility_state)
1095 {
1096 case IOSTATE_READY:
1097 {
1098 input_facility->buffer_size = 0;
1099
1100partial_read_iostate_ready:
1101 if (!ResetEvent(input_facility->overlapped.hEvent))
1102 return FALSE;
1103
1104 /* Check how the task is handled */
1105 if (ReadFile(input_facility->handle,
1106 input_facility->buffer + input_facility->buffer_size,
1107 sizeof(input_facility->buffer) - input_facility->buffer_size,
1108 &input_facility->buffer_size_processed,
1109 &input_facility->overlapped))
1110 { /* async event processed immediately*/
1111 hdr = (struct GNUNET_MessageHeader *)input_facility->buffer;
1112
1113 /* reset event manually*/
1114 if (!SetEvent(input_facility->overlapped.hEvent))
1115 return FALSE;
1116
1117 fprintf(stderr, "DEBUG: stdin read succeeded immediately\n");
1118 input_facility->buffer_size += input_facility->buffer_size_processed;
1119
1120 if (ntohs(hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER ||
1121 ntohs(hdr->size) > sizeof(input_facility->buffer))
1122 {
1123 fprintf(stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->type), ntohs(hdr->size));
1124 input_facility->facility_state = IOSTATE_READY;
1125 return TRUE;
1126 }
1127 /* we got the a part of a packet */
1128 if (ntohs(hdr->size) > input_facility->buffer_size)
1129 goto partial_read_iostate_ready;
1130
1131 /* have we read more than 0 bytes of payload? (sizeread > header)*/
1132 if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader) &&
1133 ((IOSTATE_READY == output_facility->facility_state) ||
1134 (IOSTATE_WAITING == output_facility->facility_state)))
1135 { /* we successfully read something from the TAP and now need to
1136 * send it our via STDOUT. Is that possible at the moment? */
1137 /* hand over this buffers content and strip gnunet message header */
1138 GNUNET_memcpy(output_facility->buffer,
1139 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1140 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1141 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1142 output_facility->facility_state = IOSTATE_READY;
1143 input_facility->facility_state = IOSTATE_READY;
1144 }
1145 else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1146 /* If we have have read our buffer, wait for our write-partner*/
1147 input_facility->facility_state = IOSTATE_WAITING;
1148 else /* we read nothing */
1149 input_facility->facility_state = IOSTATE_READY;
1150 }
1151 else /* operation was either queued or failed*/
1152 {
1153 int err = GetLastError();
1154 if (ERROR_IO_PENDING == err) /* operation queued */
1155 input_facility->facility_state = IOSTATE_QUEUED;
1156 else
1157 { /* error occurred, let the rest of the elements finish */
1158 input_facility->path_open = FALSE;
1159 input_facility->facility_state = IOSTATE_FAILED;
1160 if (IOSTATE_WAITING == output_facility->facility_state)
1161 output_facility->path_open = FALSE;
1162
1163 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1164 }
1165 }
1166 }
1167 return TRUE;
1168
1169 // We are queued and should check if the read has finished
1170 case IOSTATE_QUEUED:
1171 {
1172 // there was an operation going on already, check if that has completed now.
1173 if (GetOverlappedResult(input_facility->handle,
1174 &input_facility->overlapped,
1175 &input_facility->buffer_size_processed,
1176 FALSE))
1177 { /* successful return for a queued operation */
1178 hdr = (struct GNUNET_MessageHeader *)input_facility->buffer;
1179
1180 if (!ResetEvent(input_facility->overlapped.hEvent))
1181 return FALSE;
1182
1183 fprintf(stderr, "DEBUG: stdin read succeeded delayed\n");
1184 input_facility->buffer_size += input_facility->buffer_size_processed;
1185
1186 if ((ntohs(hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1187 (ntohs(hdr->size) > sizeof(input_facility->buffer)))
1188 {
1189 fprintf(stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->type), ntohs(hdr->size));
1190 input_facility->facility_state = IOSTATE_READY;
1191 return TRUE;
1192 }
1193 /* we got the a part of a packet */
1194 if (ntohs(hdr->size) > input_facility->buffer_size)
1195 ;
1196 goto partial_read_iostate_ready;
1197
1198 /* we successfully read something from the TAP and now need to
1199 * send it our via STDOUT. Is that possible at the moment? */
1200 if ((IOSTATE_READY == output_facility->facility_state ||
1201 IOSTATE_WAITING == output_facility->facility_state)
1202 && input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1203 { /* hand over this buffers content and strip gnunet message header */
1204 GNUNET_memcpy(output_facility->buffer,
1205 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1206 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1207 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1208 output_facility->facility_state = IOSTATE_READY;
1209 input_facility->facility_state = IOSTATE_READY;
1210 }
1211 else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1212 input_facility->facility_state = IOSTATE_WAITING;
1213 else
1214 input_facility->facility_state = IOSTATE_READY;
1215 }
1216 else
1217 { /* operation still pending/queued or failed? */
1218 int err = GetLastError();
1219 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1220 { /* error occurred, let the rest of the elements finish */
1221 input_facility->path_open = FALSE;
1222 input_facility->facility_state = IOSTATE_FAILED;
1223 if (IOSTATE_WAITING == output_facility->facility_state)
1224 output_facility->path_open = FALSE;
1225 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1226 }
1227 }
1228 }
1229 return TRUE;
1230
1231 case IOSTATE_RESUME: /* Our buffer was filled already but our write facility was busy. */
1232 GNUNET_memcpy(output_facility->buffer,
1233 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1234 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1235 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1236 output_facility->facility_state = IOSTATE_READY;
1237 input_facility->facility_state = IOSTATE_READY;
1238 return TRUE;
1239
1240 default:
1241 return TRUE;
1242 }
1243}
1244
1245
1246/**
1247 * Attempts to write to an output facility (tap or named pipe) in overlapped mode.
1248 *
1249 * TODO: high level description
1250 *
1251 * @param output_facility output pipe or file to hand over data to.
1252 * @param input_facility input named pipe or file to work with.
1253 * @return false if an event reset was impossible (OS error), else true
1254 */
1255static BOOL
1256attempt_write(struct io_facility * output_facility,
1257 struct io_facility * input_facility)
1258{
1259 switch (output_facility->facility_state)
1260 {
1261 case IOSTATE_READY:
1262 output_facility->buffer_size_written = 0;
1263
1264continue_partial_write:
1265 if (!ResetEvent(output_facility->overlapped.hEvent))
1266 return FALSE;
1267
1268 /* Check how the task was handled */
1269 if (WriteFile(output_facility->handle,
1270 output_facility->buffer + output_facility->buffer_size_written,
1271 output_facility->buffer_size - output_facility->buffer_size_written,
1272 &output_facility->buffer_size_processed,
1273 &output_facility->overlapped))
1274 {/* async event processed immediately*/
1275 fprintf(stderr, "DEBUG: write succeeded immediately\n");
1276 output_facility->buffer_size_written += output_facility->buffer_size_processed;
1277
1278 /* reset event manually*/
1279 if (!SetEvent(output_facility->overlapped.hEvent))
1280 return FALSE;
1281
1282 /* partial write */
1283 if (output_facility->buffer_size_written < output_facility->buffer_size)
1284 goto continue_partial_write;
1285
1286 /* we are now waiting for our buffer to be filled*/
1287 output_facility->facility_state = IOSTATE_WAITING;
1288
1289 /* we successfully wrote something and now need to reset our reader */
1290 if (IOSTATE_WAITING == input_facility->facility_state)
1291 input_facility->facility_state = IOSTATE_RESUME;
1292 else if (IOSTATE_FAILED == input_facility->facility_state)
1293 output_facility->path_open = FALSE;
1294 }
1295 else /* operation was either queued or failed*/
1296 {
1297 int err = GetLastError();
1298 if (ERROR_IO_PENDING == err)
1299 { /* operation queued */
1300 output_facility->facility_state = IOSTATE_QUEUED;
1301 }
1302 else
1303 { /* error occurred, close this path */
1304 output_facility->path_open = FALSE;
1305 output_facility->facility_state = IOSTATE_FAILED;
1306 fprintf(stderr, "FATAL: Write to handle failed, exiting\n");
1307 }
1308 }
1309 return TRUE;
1310
1311 case IOSTATE_QUEUED:
1312 // there was an operation going on already, check if that has completed now.
1313
1314 if (GetOverlappedResult(output_facility->handle,
1315 &output_facility->overlapped,
1316 &output_facility->buffer_size_processed,
1317 FALSE))
1318 {/* successful return for a queued operation */
1319 if (!ResetEvent(output_facility->overlapped.hEvent))
1320 return FALSE;
1321
1322 fprintf(stderr, "DEBUG: write succeeded delayed\n");
1323 output_facility->buffer_size_written += output_facility->buffer_size_processed;
1324
1325 /* partial write */
1326 if (output_facility->buffer_size_written < output_facility->buffer_size)
1327 goto continue_partial_write;
1328
1329 /* we are now waiting for our buffer to be filled*/
1330 output_facility->facility_state = IOSTATE_WAITING;
1331
1332 /* we successfully wrote something and now need to reset our reader */
1333 if (IOSTATE_WAITING == input_facility->facility_state)
1334 input_facility->facility_state = IOSTATE_RESUME;
1335 else if (IOSTATE_FAILED == input_facility->facility_state)
1336 output_facility->path_open = FALSE;
1337 }
1338 else
1339 { /* operation still pending/queued or failed? */
1340 int err = GetLastError();
1341 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1342 { /* error occurred, close this path */
1343 output_facility->path_open = FALSE;
1344 output_facility->facility_state = IOSTATE_FAILED;
1345 fprintf(stderr, "FATAL: Write to handle failed, exiting\n");
1346 }
1347 }
1348
1349 default:
1350 return TRUE;
1351 }
1352}
1353
1354
1355/**
1356 * Initialize a overlapped structure
1357 *
1358 * @param elem the element to initilize
1359 * @param initial_state the initial state for this instance
1360 * @param signaled if the hEvent created should default to signaled or not
1361 * @return true on success, else false
1362 */
1363static BOOL
1364initialize_io_facility(struct io_facility * elem,
1365 int initial_state,
1366 BOOL signaled)
1367{
1368 elem->path_open = TRUE;
1369 elem->handle = INVALID_HANDLE_VALUE;
1370 elem->facility_state = initial_state;
1371 elem->buffer_size = 0;
1372 elem->overlapped.hEvent = CreateEvent(NULL, TRUE, signaled, NULL);
1373 if (NULL == elem->overlapped.hEvent)
1374 return FALSE;
1375
1376 return TRUE;
1377}
1378
1379
1380/**
1381 * Start forwarding to and from the tunnel.
1382 *
1383 * @param tap_handle device handle for interacting with the Virtual interface
1384 */
1385static void
1386run(HANDLE tap_handle)
1387{
1388 /* IO-Facility for reading from our virtual interface */
1389 struct io_facility tap_read;
1390 /* IO-Facility for writing to our virtual interface */
1391 struct io_facility tap_write;
1392 /* IO-Facility for reading from stdin */
1393 struct io_facility std_in;
1394 /* IO-Facility for writing to stdout */
1395 struct io_facility std_out;
1396
1397 HANDLE parent_std_in_handle = GetStdHandle(STD_INPUT_HANDLE);
1398 HANDLE parent_std_out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
1399
1400 /* tun up: */
1401 /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn
1402 * to remove the need to flush the arp cache, handle DHCP and wrong IPs.
1403 *
1404 * DHCP and such are all features we will never use in gnunet afaik.
1405 * But for openvpn those are essential.
1406 */
1407 if ((privilege_testing) || (!tun_up(tap_handle)))
1408 goto teardown_final;
1409
1410 /* Initialize our overlapped IO structures*/
1411 if (!(initialize_io_facility(&tap_read, IOSTATE_READY, FALSE)
1412 && initialize_io_facility(&tap_write, IOSTATE_WAITING, TRUE)
1413 && initialize_io_facility(&std_in, IOSTATE_READY, FALSE)
1414 && initialize_io_facility(&std_out, IOSTATE_WAITING, TRUE)))
1415 goto teardown_final;
1416
1417 /* Handles for STDIN and STDOUT */
1418 tap_read.handle = tap_handle;
1419 tap_write.handle = tap_handle;
1420
1421#ifdef DEBUG_TO_CONSOLE
1422 /* Debug output to console STDIN/STDOUT*/
1423 std_in.handle = parent_std_in_handle;
1424 std_out.handle = parent_std_out_handle;
1425#else
1426 fprintf(stderr, "DEBUG: reopening stdin/out for overlapped IO\n");
1427 /*
1428 * Find out the types of our handles.
1429 * This part is a problem, because in windows we need to handle files,
1430 * pipes and the console differently.
1431 */
1432 if ((FILE_TYPE_PIPE != GetFileType(parent_std_in_handle)) ||
1433 (FILE_TYPE_PIPE != GetFileType(parent_std_out_handle)))
1434 {
1435 fprintf(stderr, "ERROR: stdin/stdout must be named pipes\n");
1436 goto teardown;
1437 }
1438
1439 std_in.handle = ReOpenFile(parent_std_in_handle,
1440 GENERIC_READ,
1441 FILE_SHARE_WRITE | FILE_SHARE_READ,
1442 FILE_FLAG_OVERLAPPED);
1443
1444 if (INVALID_HANDLE_VALUE == std_in.handle)
1445 {
1446 fprintf(stderr, "FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe\n");
1447 goto teardown;
1448 }
1449
1450 std_out.handle = ReOpenFile(parent_std_out_handle,
1451 GENERIC_WRITE,
1452 FILE_SHARE_READ,
1453 FILE_FLAG_OVERLAPPED);
1454
1455 if (INVALID_HANDLE_VALUE == std_out.handle)
1456 {
1457 fprintf(stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe\n");
1458 goto teardown;
1459 }
1460#endif
1461
1462 fprintf(stderr, "DEBUG: mainloop has begun\n");
1463
1464 while (std_out.path_open || tap_write.path_open)
1465 {
1466 /* perform READ from stdin if possible */
1467 if (std_in.path_open && (!attempt_read_stdin(&std_in, &tap_write)))
1468 break;
1469
1470 /* perform READ from tap if possible */
1471 if (tap_read.path_open && (!attempt_read_tap(&tap_read, &std_out)))
1472 break;
1473
1474 /* perform WRITE to tap if possible */
1475 if (tap_write.path_open && (!attempt_write(&tap_write, &std_in)))
1476 break;
1477
1478 /* perform WRITE to STDOUT if possible */
1479 if (std_out.path_open && (!attempt_write(&std_out, &tap_read)))
1480 break;
1481 }
1482 fprintf(stderr, "DEBUG: teardown initiated\n");
1483
1484teardown:
1485
1486 CancelIo(tap_handle);
1487 CancelIo(std_in.handle);
1488 CancelIo(std_out.handle);
1489
1490teardown_final:
1491
1492 CloseHandle(tap_handle);
1493}
1494
1495
1496/**
1497 * Open VPN tunnel interface.
1498 *
1499 * @param argc must be 6
1500 * @param argv 0: binary name ("gnunet-helper-exit")
1501 * 1: tunnel interface name ("gnunet-exit")
1502 * 2: IPv4 "physical" interface name ("eth0"), or "-" to not do IPv4 NAT
1503 * 3: IPv6 address ("::1"), or "-" to skip IPv6
1504 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
1505 * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
1506 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
1507 */
1508int
1509main(int argc, char **argv)
1510{
1511 char hwid[LINE_LEN];
1512 HANDLE handle;
1513 int global_ret = 1;
1514 int local_ret = EINVAL;
1515 BOOL have_ip4 = FALSE;
1516 BOOL have_ip6 = FALSE;
1517 BOOL have_nat44 = FALSE;
1518
1519 if ((1 < argc) && (0 != strcmp(argv[1], "-d")))
1520 {
1521 privilege_testing = TRUE;
1522 fprintf(stderr,
1523 "%s",
1524 "DEBUG: Running binary in privilege testing mode.");
1525 argv++;
1526 argc--;
1527 }
1528
1529 if (6 != argc)
1530 {
1531 fprintf(stderr,
1532 "%s",
1533 "FATAL: must supply 6 arguments\nUsage:\ngnunet-helper-exit [-d] <if name prefix> <uplink-interface name> <address6 or \"-\"> <netbits6> <address4 or \"-\"> <netmask4>\n");
1534 return 1;
1535 }
1536
1537 GNUNET_strlcpy(hwid, argv[1], sizeof(hwid));
1538
1539 /*
1540 * We use our PID for finding/resolving the control-panel name of our virtual
1541 * device. PIDs are (of course) unique at runtime, thus we can safely use it
1542 * as additional hardware-id for our device.
1543 */
1544 snprintf(secondary_hwid, LINE_LEN / 2, "%s-%d",
1545 hwid,
1546 _getpid());
1547
1548 if (INVALID_HANDLE_VALUE == (handle = init_tun()))
1549 {
1550 fprintf(stderr, "FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n",
1551 hwid,
1552 argv[3],
1553 argv[4],
1554 argv[5],
1555 argv[6]);
1556 global_ret = -1;
1557 goto cleanup;
1558 }
1559
1560 fprintf(stderr, "DEBUG: Setting IPs, if needed\n");
1561 if (0 != strcmp(argv[3], "-"))
1562 {
1563 char command[LINE_LEN];
1564 const char *address = argv[3];
1565 long prefix_len = atol(argv[4]);
1566
1567 if ((prefix_len < 1) || (prefix_len > 127))
1568 {
1569 fprintf(stderr, "FATAL: ipv6 prefix_len out of range\n");
1570 global_ret = -1;
1571 goto cleanup;
1572 }
1573
1574 fprintf(stderr, "DEBUG: Setting IP6 address: %s/%d\n", address, prefix_len);
1575 if (0 != (global_ret = set_address6(address, prefix_len)))
1576 goto cleanup;
1577
1578 have_ip6 = TRUE;
1579
1580 /* install our the windows NAT module*/
1581 fprintf(stderr, "DEBUG: Setting IPv6 Forwarding for internal and external interface.\n");
1582 /* outside interface (maybe that's already set) */
1583 snprintf(command, LINE_LEN,
1584 "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled store=active",
1585 argv[2]);
1586 local_ret = execute_shellcommand(command);
1587 if (0 != local_ret)
1588 {
1589 fprintf(stderr, "FATAL: Could not enable forwarding via netsh: %s\n", strerror(local_ret));
1590 goto cleanup;
1591 }
1592 /* internal interface */
1593 snprintf(command, LINE_LEN,
1594 "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled advertise=enabled store=active",
1595 device_visible_name);
1596 local_ret = execute_shellcommand(command);
1597 if (0 != local_ret)
1598 {
1599 fprintf(stderr, "FATAL: Could not enable forwarding via netsh: %s\n", strerror(local_ret));
1600 goto cleanup;
1601 }
1602 /* we can keep IPv6 forwarding around, as all interfaces have
1603 * their forwarding mode reset to false at bootup. */
1604 }
1605
1606 if (0 != strcmp(argv[5], "-"))
1607 {
1608 const char *address = argv[5];
1609 const char *mask = argv[6];
1610
1611 fprintf(stderr, "DEBUG: Setting IP4 address: %s/%s\n", address, mask);
1612 if (0 != (global_ret = set_address4(address, mask)))
1613 goto cleanup;
1614
1615 // setup NAPT, if possible
1616 /* MS has REMOVED the routing/nat capabilities from Vista+, thus
1617 * we can not setup NAT like in XP or on the server. Actually the
1618 * the only feasible solution seems to be to use
1619 * Internet Connection Sharing, which introduces a horde of problems
1620 * such as sending out rogue-RAs on the external interface in an ipv6
1621 * network.
1622 * Thus, below stuff ONLY works on
1623 * WinXP SP3
1624 * Win Server 2003 SP1+
1625 * Win Server 2008
1626 * ...
1627 */
1628 have_ip4 = TRUE;
1629 if (0 != strcmp(argv[2], "-"))
1630 {
1631 char command[LINE_LEN];
1632
1633 /* install our the windows NAT module*/
1634 fprintf(stderr, "DEBUG: Adding NAPT/Masquerading between external IF %s and mine.\n", argv[2]);
1635 local_ret = execute_shellcommand("netsh routing ip nat install");
1636 if (0 != local_ret)
1637 {
1638 fprintf(stderr, "FATAL: Could not install NAPT support via Netsh: %s\n", strerror(local_ret));
1639 goto cleanup;
1640 }
1641 /* external IF */
1642 snprintf(command, LINE_LEN,
1643 "netsh routing ip nat add interface \"%s\" full", /*full = NAPT (addr+port)*/
1644 argv[2]);
1645 local_ret = execute_shellcommand(command);
1646 if (0 != local_ret)
1647 {
1648 fprintf(stderr, "FATAL: IPv4-NAPT on external interface failed: %s\n", strerror(local_ret));
1649 goto cleanup;
1650 }
1651 /* private/internal/virtual IF */
1652 snprintf(command, LINE_LEN,
1653 "netsh routing ip nat add interface \"%s\" private",
1654 device_visible_name);
1655 local_ret = execute_shellcommand(command);
1656 if (0 != local_ret)
1657 {
1658 fprintf(stderr, "FATAL: IPv4-NAPT on internal interface failed: %s\n", strerror(local_ret));
1659 goto cleanup;
1660
1661 have_nat44 = TRUE;
1662 }
1663 }
1664 }
1665
1666 run(handle);
1667cleanup:
1668
1669 if (have_ip4)
1670 {
1671 const char *address = argv[5];
1672 if (have_nat44)
1673 {
1674 char command[LINE_LEN];
1675 fprintf(stderr, "DEBUG: removing IP4 NAPT from virtual interface \n");
1676 snprintf(command, LINE_LEN,
1677 "netsh routing ip nat del interface \"%s\"",
1678 device_visible_name);
1679 local_ret = execute_shellcommand(command);
1680 if (0 != local_ret)
1681 fprintf(stderr, "WARNING: Could not remove IPv4-NAPT from internal interface, hopefully this will have no effect in future runs: %s\n", strerror(local_ret));
1682 }
1683
1684 fprintf(stderr, "DEBUG: Removing IP4 address\n");
1685 remove_address4(address);
1686 }
1687 if (have_ip6)
1688 {
1689 const char *address = argv[3];
1690 fprintf(stderr, "DEBUG: Removing IP6 address\n");
1691 remove_address6(address);
1692 }
1693
1694 fprintf(stderr, "DEBUG: removing interface\n");
1695 remove_interface();
1696 fprintf(stderr, "DEBUG: graceful exit completed\n");
1697
1698 return global_ret;
1699}
diff --git a/src/fragmentation/Makefile.am b/src/fragmentation/Makefile.am
index 85c4767c0..85df01ff5 100644
--- a/src/fragmentation/Makefile.am
+++ b/src/fragmentation/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am
index 80316dc2e..0840242ea 100644
--- a/src/fs/Makefile.am
+++ b/src/fs/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 0d38cb51e..4a152a6df 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -15,7 +15,6 @@ EXTRA_DIST = \
15 test_gns_lookup.conf \ 15 test_gns_lookup.conf \
16 test_gns_proxy.conf \ 16 test_gns_proxy.conf \
17 test_gns_simple_lookup.conf \ 17 test_gns_simple_lookup.conf \
18 gns-helper-service-w32.conf \
19 w32nsp.def \ 18 w32nsp.def \
20 openssl.cnf \ 19 openssl.cnf \
21 gnunet-gns-proxy-setup-ca.in \ 20 gnunet-gns-proxy-setup-ca.in \
@@ -25,14 +24,6 @@ EXTRA_DIST = \
25 $(check_SCRIPTS) \ 24 $(check_SCRIPTS) \
26 $(pkgdata_DATA) 25 $(pkgdata_DATA)
27 26
28if MINGW
29 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
30 DO_W32_HELPER = gnunet-gns-helper-service-w32
31 DO_W32_NSP = libw32nsp.la
32 DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve
33 DO_W32_HS_CONF = gns-helper-service-w32.conf
34 DO_NONPOSIX_GNSIMPORT = gnunet-gns-import
35endif
36USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la 27USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la
37 28
38if USE_COVERAGE 29if USE_COVERAGE
@@ -46,11 +37,9 @@ libexecdir= $(pkglibdir)/libexec/
46plugindir = $(libdir)/gnunet 37plugindir = $(libdir)/gnunet
47 38
48pkgcfg_DATA = \ 39pkgcfg_DATA = \
49 gns.conf \ 40 gns.conf
50 $(DO_W32_HS_CONF)
51 41
52lib_LTLIBRARIES = \ 42lib_LTLIBRARIES = \
53 $(DO_W32_NSP) \
54 libgnunetgns.la 43 libgnunetgns.la
55 44
56 45
@@ -73,12 +62,9 @@ endif
73libexec_PROGRAMS = \ 62libexec_PROGRAMS = \
74 gnunet-service-gns \ 63 gnunet-service-gns \
75 gnunet-dns2gns \ 64 gnunet-dns2gns \
76 $(DO_W32_HELPER) \
77 $(DO_PROXY) 65 $(DO_PROXY)
78 66
79bin_PROGRAMS = \ 67bin_PROGRAMS = \
80 $(DO_W32_NSPTOOLS) \
81 $(DO_NONPOSIX_GNSIMPORT) \
82 gnunet-gns 68 gnunet-gns
83 69
84noinst_PROGRAMS = \ 70noinst_PROGRAMS = \
@@ -199,35 +185,15 @@ test_gns_proxy_LDADD = $(MHD_LIBS) $(LIB_GNURL) -lgnutls \
199 $(GN_LIBINTL) 185 $(GN_LIBINTL)
200test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) 186test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS)
201 187
202gnunet_gns_helper_service_w32_SOURCES = \ 188#gnunet_gns_import_SOURCES = \
203 gnunet-gns-helper-service-w32.c 189# gnunet-gns-import.c
204gnunet_gns_helper_service_w32_LDADD = \ 190#gnunet_gns_import_LDADD = \
205 libgnunetgns.la \ 191# $(top_builddir)/src/identity/libgnunetidentity.la \
206 $(top_builddir)/src/identity/libgnunetidentity.la \ 192# $(top_builddir)/src/namestore/libgnunetnamestore.la \
207 $(top_builddir)/src/util/libgnunetutil.la \ 193# $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
208 $(GN_LIBINTL) 194# $(top_builddir)/src/util/libgnunetutil.la \
209 195# $(GN_LIBINTL)
210gnunet_gns_import_SOURCES = \
211 gnunet-gns-import.c
212gnunet_gns_import_LDADD = \
213 $(top_builddir)/src/identity/libgnunetidentity.la \
214 $(top_builddir)/src/namestore/libgnunetnamestore.la \
215 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
216 $(top_builddir)/src/util/libgnunetutil.la \
217 $(GN_LIBINTL)
218
219 196
220w32nsp_install_SOURCES = \
221 w32nsp-install.c
222w32nsp_install_LDADD = -lws2_32
223
224w32nsp_uninstall_SOURCES = \
225 w32nsp-uninstall.c
226w32nsp_uninstall_LDADD = -lws2_32
227
228w32nsp_resolve_SOURCES = \
229 w32nsp-resolve.c
230w32nsp_resolve_LDADD = -lws2_32
231 197
232gnunet_service_gns_SOURCES = \ 198gnunet_service_gns_SOURCES = \
233 gnunet-service-gns.c gnunet-service-gns.h \ 199 gnunet-service-gns.c gnunet-service-gns.h \
@@ -247,14 +213,6 @@ gnunet_service_gns_LDADD = \
247 $(GN_LIBINTL) 213 $(GN_LIBINTL)
248 214
249 215
250libw32nsp_la_SOURCES = \
251 w32nsp.c
252libw32nsp_la_LIBADD = \
253 -lole32 -lws2_32
254libw32nsp_la_LDFLAGS = \
255 -export-symbols $(top_srcdir)/src/gns/w32nsp.def \
256 -no-undefined -static-libgcc
257
258libgnunetgns_la_SOURCES = \ 216libgnunetgns_la_SOURCES = \
259 gns_api.c gns_api.h \ 217 gns_api.c gns_api.h \
260 gns_tld_api.c gns.h 218 gns_tld_api.c gns.h
diff --git a/src/gns/gns-helper-service-w32.conf b/src/gns/gns-helper-service-w32.conf
deleted file mode 100644
index a7b9fdd70..000000000
--- a/src/gns/gns-helper-service-w32.conf
+++ /dev/null
@@ -1,4 +0,0 @@
1[gns-helper-service-w32]
2START_ON_DEMAND = YES
3BINARY = gnunet-gns-helper-service-w32
4PORT = 5353
diff --git a/src/gns/gnunet-gns-helper-service-w32.c b/src/gns/gnunet-gns-helper-service-w32.c
deleted file mode 100644
index 4c4803556..000000000
--- a/src/gns/gnunet-gns-helper-service-w32.c
+++ /dev/null
@@ -1,803 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gnunet-gns-helper-service-w32.c
22 * @brief an intermediary service to access distributed GNS
23 * @author Christian Grothoff
24 * @author LRN
25 */
26#include "platform.h"
27#include <gnunet_util_lib.h>
28#include <gnunet_identity_service.h>
29#include <gnunet_dnsparser_lib.h>
30#include <gnunet_namestore_service.h>
31#include <gnunet_gns_service.h>
32#include <initguid.h>
33#include "gnunet_w32nsp_lib.h"
34#include "w32resolver.h"
35#include <nspapi.h>
36#include <unistr.h>
37
38#define DEFINE_DNS_GUID(a, x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
39DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
40DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
41DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
42DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
43DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
44DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
45DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
46DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
47DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
48DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
49DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
50
51
52struct request {
53 /**
54 * We keep these in a doubly-linked list (for cleanup).
55 */
56 struct request *next;
57
58 /**
59 * We keep these in a doubly-linked list (for cleanup).
60 */
61 struct request *prev;
62
63 /**
64 * Client that issued the request
65 */
66 struct GNUNET_SERVICE_Client *client;
67
68 GUID sc;
69
70 int af;
71
72 wchar_t *name;
73
74 char *u8name;
75
76 struct GNUNET_GNS_LookupRequest *lookup_request;
77};
78
79
80/**
81 * Head of the doubly-linked list (for cleanup).
82 */
83static struct request *rq_head;
84
85/**
86 * Tail of the doubly-linked list (for cleanup).
87 */
88static struct request *rq_tail;
89
90/**
91 * Handle to GNS service.
92 */
93static struct GNUNET_GNS_Handle *gns;
94
95/**
96 * Active operation on identity service.
97 */
98static struct GNUNET_IDENTITY_Operation *id_op;
99
100/**
101 * Handle for identity service.
102 */
103static struct GNUNET_IDENTITY_Handle *identity;
104
105/**
106 * Public key of the gns-master ego
107 */
108static struct GNUNET_CRYPTO_EcdsaPublicKey gns_master_pubkey;
109
110/**
111 * Set to 1 once egos are obtained.
112 */
113static int got_egos;
114
115
116/**
117 * Task run on shutdown. Cleans up everything.
118 *
119 * @param cls unused
120 */
121static void
122do_shutdown(void *cls)
123{
124 struct request *rq;
125
126 if (NULL != id_op)
127 {
128 GNUNET_IDENTITY_cancel(id_op);
129 id_op = NULL;
130 }
131 if (NULL != identity)
132 {
133 GNUNET_IDENTITY_disconnect(identity);
134 identity = NULL;
135 }
136 while (NULL != (rq = rq_head))
137 {
138 if (NULL != rq->lookup_request)
139 GNUNET_GNS_lookup_cancel(rq->lookup_request);
140 GNUNET_CONTAINER_DLL_remove(rq_head,
141 rq_tail,
142 rq);
143 GNUNET_free_non_null(rq->name);
144 if (rq->u8name)
145 free(rq->u8name);
146 GNUNET_free(rq);
147 }
148 if (NULL != gns)
149 {
150 GNUNET_GNS_disconnect(gns);
151 gns = NULL;
152 }
153}
154
155
156#define MarshallPtr(ptr, base, type) \
157 if (ptr) \
158 ptr = (type *) ((char *)ptr - (char *)base)
159
160
161void
162MarshallWSAQUERYSETW(WSAQUERYSETW *qs, GUID *sc)
163{
164 MarshallPtr(qs->lpszServiceInstanceName, qs, wchar_t);
165 MarshallPtr(qs->lpServiceClassId, qs, GUID);
166 MarshallPtr(qs->lpVersion, qs, WSAVERSION);
167 MarshallPtr(qs->lpNSProviderId, qs, GUID);
168 MarshallPtr(qs->lpszContext, qs, wchar_t);
169 MarshallPtr(qs->lpafpProtocols, qs, AFPROTOCOLS);
170 MarshallPtr(qs->lpszQueryString, qs, wchar_t);
171 for (int i = 0; i < qs->dwNumberOfCsAddrs; i++)
172 {
173 MarshallPtr(qs->lpcsaBuffer[i].LocalAddr.lpSockaddr, qs, SOCKADDR);
174 MarshallPtr(qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr, qs, SOCKADDR);
175 }
176 MarshallPtr(qs->lpcsaBuffer, qs, CSADDR_INFO);
177 if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, sc) && qs->lpBlob != NULL && qs->lpBlob->pBlobData != NULL)
178 {
179 struct hostent *he;
180
181 he = (struct hostent *)qs->lpBlob->pBlobData;
182 for (int i = 0; he->h_aliases[i] != NULL; i++)
183 MarshallPtr(he->h_aliases[i], he, char);
184 MarshallPtr(he->h_aliases, he, char *);
185 MarshallPtr(he->h_name, he, char);
186 for (int i = 0; he->h_addr_list[i] != NULL; i++)
187 MarshallPtr(he->h_addr_list[i], he, void);
188 MarshallPtr(he->h_addr_list, he, char *);
189 MarshallPtr(qs->lpBlob->pBlobData, qs, void);
190 }
191 MarshallPtr(qs->lpBlob, qs, BLOB);
192}
193
194
195static void
196process_lookup_result(void *cls,
197 uint32_t rd_count,
198 const struct GNUNET_GNSRECORD_Data *rd)
199{
200 struct request *rq = cls;
201 int i, j, csanum;
202 struct GNUNET_W32RESOLVER_GetMessage *msg;
203 struct GNUNET_MQ_Envelope *msg_env;
204 struct GNUNET_MessageHeader *msgend;
205 struct GNUNET_MQ_Envelope *msgend_env;
206 WSAQUERYSETW *qs;
207 size_t size;
208 size_t size_recalc;
209 char *ptr;
210 size_t blobsize = 0;
211 size_t blobaddrcount = 0;
212
213 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
214 "Got lookup result with count %u for rq %p with client %p\n",
215 rd_count,
216 rq,
217 rq->client);
218 rq->lookup_request = NULL;
219
220 if (0 == rd_count)
221 {
222 msgend_env = GNUNET_MQ_msg(msgend, GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE);
223 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client),
224 msgend_env);
225 GNUNET_CONTAINER_DLL_remove(rq_head,
226 rq_tail,
227 rq);
228 GNUNET_free_non_null(rq->name);
229 if (rq->u8name)
230 free(rq->u8name);
231 GNUNET_free(rq);
232 return;
233 }
234
235 size = sizeof(struct GNUNET_W32RESOLVER_GetMessage) + sizeof(WSAQUERYSETW);
236 size += (wcslen(rq->name) + 1) * sizeof(wchar_t);
237 size += sizeof(GUID);
238 /* lpszComment ? a TXT record? */
239 size += sizeof(GUID);
240 /* lpszContext ? Not sure what it is */
241 csanum = 0;
242 for (i = 0; i < rd_count; i++)
243 {
244 switch (rd[i].record_type)
245 {
246 case GNUNET_DNSPARSER_TYPE_A:
247 if (rd[i].data_size != sizeof(struct in_addr))
248 continue;
249 size += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in) * 2;
250 csanum++;
251 break;
252
253 case GNUNET_DNSPARSER_TYPE_AAAA:
254 if (rd[i].data_size != sizeof(struct in6_addr))
255 continue;
256 size += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in6) * 2;
257 csanum++;
258 break;
259 }
260 }
261 if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &rq->sc))
262 {
263 size += sizeof(BLOB);
264 blobsize += sizeof(struct hostent);
265 blobsize += strlen(rq->u8name) + 1;
266 blobsize += sizeof(void *); /* For aliases */
267 blobsize += sizeof(void *); /* For addresses */
268 for (i = 0; i < rd_count; i++)
269 {
270 if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && rd[i].record_type == GNUNET_DNSPARSER_TYPE_A)
271 {
272 blobsize += sizeof(void *);
273 blobsize += sizeof(struct in_addr);
274 blobaddrcount++;
275 }
276 else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA)
277 {
278 blobsize += sizeof(void *);
279 blobsize += sizeof(struct in6_addr);
280 blobaddrcount++;
281 }
282 }
283 size += blobsize;
284 }
285 size_recalc = sizeof(struct GNUNET_W32RESOLVER_GetMessage) + sizeof(WSAQUERYSETW);
286 msg_env = GNUNET_MQ_msg_extra(msg,
287 size - sizeof(struct GNUNET_MessageHeader),
288 GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE);
289 msg->af = htonl(rq->af);
290 msg->sc_data1 = htonl(rq->sc.Data1);
291 msg->sc_data2 = htons(rq->sc.Data2);
292 msg->sc_data3 = htons(rq->sc.Data3);
293 for (i = 0; i < 8; i++)
294 msg->sc_data4[i] = rq->sc.Data4[i];
295 qs = (WSAQUERYSETW *)&msg[1];
296 ptr = (char *)&qs[1];
297 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
298 qs->dwSize = sizeof(WSAQUERYSETW);
299 qs->lpszServiceInstanceName = (wchar_t *)ptr;
300 ptr += (wcslen(rq->name) + 1) * sizeof(wchar_t);
301 size_recalc += (wcslen(rq->name) + 1) * sizeof(wchar_t);
302 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
303 wcscpy(qs->lpszServiceInstanceName, rq->name);
304 qs->lpServiceClassId = (GUID *)ptr;
305 ptr += sizeof(GUID);
306 size_recalc += sizeof(GUID);
307 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
308 GNUNET_memcpy(qs->lpServiceClassId, &rq->sc, sizeof(GUID));
309 qs->lpVersion = NULL;
310 qs->dwNameSpace = NS_DNS;
311 qs->lpNSProviderId = (GUID *)ptr;
312 ptr += sizeof(GUID);
313 size_recalc += sizeof(GUID);
314 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
315 GNUNET_memcpy(qs->lpNSProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS, sizeof(GUID));
316 qs->lpszContext = NULL;
317 qs->dwNumberOfProtocols = 0;
318 qs->lpafpProtocols = NULL;
319 /* Don't bother with this... */
320 qs->lpszQueryString = NULL;
321 qs->dwNumberOfCsAddrs = rd_count;
322 qs->lpcsaBuffer = (CSADDR_INFO *)ptr;
323 ptr += sizeof(CSADDR_INFO) * csanum;
324 j = 0;
325 for (i = 0; i < rd_count; i++)
326 {
327 switch (rd[i].record_type)
328 {
329 case GNUNET_DNSPARSER_TYPE_A:
330 if (rd[i].data_size != sizeof(struct in_addr))
331 continue;
332 qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM;
333 qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP;
334
335 qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof(struct sockaddr_in);
336 qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *)ptr;
337 ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength;
338 memset(qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength);
339 ((struct sockaddr_in *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin_family = AF_INET;
340
341 qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof(struct sockaddr_in);
342 qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *)ptr;
343 ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength;
344 memset(qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength);
345 ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_family = AF_INET;
346 ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_port = htonl(53); /* Don't ask why it's 53 */
347 ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_addr = *(struct in_addr *)rd[i].data;
348 size_recalc += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in) * 2;
349 j++;
350 break;
351
352 case GNUNET_DNSPARSER_TYPE_AAAA:
353 if (rd[i].data_size != sizeof(struct in6_addr))
354 continue;
355 qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM;
356 qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP;
357
358 qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof(struct sockaddr_in6);
359 qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *)ptr;
360 ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength;
361 memset(qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength);
362 ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin6_family = AF_INET6;
363
364 qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof(struct sockaddr_in6);
365 qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *)ptr;
366 ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength;
367 memset(qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength);
368 ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_family = AF_INET6;
369 ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_port = htonl(53); /* Don't ask why it's 53 */
370 ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_addr = *(struct in6_addr *)rd[i].data;
371 size_recalc += sizeof(CSADDR_INFO) + sizeof(struct sockaddr_in6) * 2;
372 j++;
373 break;
374
375 default:
376 break;
377 }
378 }
379 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
380 qs->dwOutputFlags = 0;
381 if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &rq->sc))
382 {
383 struct hostent *he;
384 qs->lpBlob = (BLOB *)ptr;
385 ptr += sizeof(BLOB);
386
387 size_recalc += sizeof(BLOB);
388 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
389
390 qs->lpBlob->cbSize = blobsize;
391 qs->lpBlob->pBlobData = (BYTE *)ptr;
392 ptr += sizeof(struct hostent);
393
394 size_recalc += sizeof(struct hostent);
395 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
396
397 he = (struct hostent *)qs->lpBlob->pBlobData;
398 he->h_name = (char *)ptr;
399 ptr += strlen(rq->u8name) + 1;
400
401 size_recalc += strlen(rq->u8name) + 1;
402 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
403
404 strcpy(he->h_name, rq->u8name);
405 he->h_aliases = (char **)ptr;
406 ptr += sizeof(void *);
407
408 size_recalc += sizeof(void *); /* For aliases */
409 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
410
411 he->h_aliases[0] = NULL;
412 he->h_addrtype = rq->af;
413 he->h_length = rq->af == AF_INET || rq->af == AF_UNSPEC ? sizeof(struct in_addr) : sizeof(struct in6_addr);
414 he->h_addr_list = (char **)ptr;
415 ptr += sizeof(void *) * (blobaddrcount + 1);
416
417 size_recalc += sizeof(void *) * (blobaddrcount + 1); /* For addresses */
418 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
419
420 j = 0;
421 for (i = 0; i < rd_count; i++)
422 {
423 if ((rq->af == AF_INET || rq->af == AF_UNSPEC) &&
424 rd[i].record_type == GNUNET_DNSPARSER_TYPE_A)
425 {
426 he->h_addr_list[j] = (char *)ptr;
427 ptr += sizeof(struct in_addr);
428
429 size_recalc += sizeof(struct in_addr);
430 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
431
432 GNUNET_memcpy(he->h_addr_list[j], rd[i].data, sizeof(struct in_addr));
433 j++;
434 }
435 else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA)
436 {
437 he->h_addr_list[j] = (char *)ptr;
438 ptr += sizeof(struct in6_addr);
439
440 size_recalc += sizeof(struct in6_addr);
441 GNUNET_break(size_recalc == (size_t)((char *)ptr - (char *)msg));
442
443 GNUNET_memcpy(he->h_addr_list[j], rd[i].data, sizeof(struct in6_addr));
444 j++;
445 }
446 }
447 he->h_addr_list[j] = NULL;
448 }
449 msgend_env = GNUNET_MQ_msg(msgend, GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE);
450
451 if ((char *)ptr - (char *)msg != size || size_recalc != size || size_recalc != ((char *)ptr - (char *)msg))
452 {
453 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
454 "Error in WSAQUERYSETW size calc: expected %u, got %lu (recalc %u)\n",
455 size,
456 (unsigned long)((char *)ptr - (char *)msg),
457 size_recalc);
458 }
459 MarshallWSAQUERYSETW(qs, &rq->sc);
460 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client),
461 msg_env);
462 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(rq->client),
463 msgend_env);
464 GNUNET_CONTAINER_DLL_remove(rq_head,
465 rq_tail,
466 rq);
467 GNUNET_free_non_null(rq->name);
468 if (rq->u8name)
469 free(rq->u8name);
470 GNUNET_free(rq);
471}
472
473
474static void
475get_ip_from_hostname(struct GNUNET_SERVICE_Client *client,
476 const wchar_t *name,
477 int af,
478 GUID sc)
479{
480 struct request *rq;
481 char *hostname;
482 size_t strl;
483 size_t namelen;
484 uint32_t rtype;
485
486 if (IsEqualGUID(&SVCID_DNS_TYPE_A, &sc))
487 rtype = GNUNET_DNSPARSER_TYPE_A;
488 else if (IsEqualGUID(&SVCID_DNS_TYPE_NS, &sc))
489 rtype = GNUNET_DNSPARSER_TYPE_NS;
490 else if (IsEqualGUID(&SVCID_DNS_TYPE_CNAME, &sc))
491 rtype = GNUNET_DNSPARSER_TYPE_CNAME;
492 else if (IsEqualGUID(&SVCID_DNS_TYPE_SOA, &sc))
493 rtype = GNUNET_DNSPARSER_TYPE_SOA;
494 else if (IsEqualGUID(&SVCID_DNS_TYPE_PTR, &sc))
495 rtype = GNUNET_DNSPARSER_TYPE_PTR;
496 else if (IsEqualGUID(&SVCID_DNS_TYPE_MX, &sc))
497 rtype = GNUNET_DNSPARSER_TYPE_MX;
498 else if (IsEqualGUID(&SVCID_DNS_TYPE_TEXT, &sc))
499 rtype = GNUNET_DNSPARSER_TYPE_TXT;
500 else if (IsEqualGUID(&SVCID_DNS_TYPE_AAAA, &sc))
501 rtype = GNUNET_DNSPARSER_TYPE_AAAA;
502 else if (IsEqualGUID(&SVCID_DNS_TYPE_SRV, &sc))
503 rtype = GNUNET_DNSPARSER_TYPE_SRV;
504 else if (IsEqualGUID(&SVCID_INET_HOSTADDRBYNAME, &sc))
505 rtype = GNUNET_DNSPARSER_TYPE_A;
506 else
507 {
508 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
509 "Unknown GUID: %08lX-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
510 sc.Data1,
511 sc.Data2,
512 sc.Data3,
513 sc.Data4[0],
514 sc.Data4[1],
515 sc.Data4[2],
516 sc.Data4[3],
517 sc.Data4[4],
518 sc.Data4[5],
519 sc.Data4[6],
520 sc.Data4[7]);
521 GNUNET_SERVICE_client_drop(client);
522 return;
523 }
524
525 if (name)
526 namelen = wcslen(name);
527 else
528 namelen = 0;
529 if (namelen > 0)
530 hostname = (char *)u16_to_u8(name, namelen + 1, NULL, &strl);
531 else
532 hostname = NULL;
533
534 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
535 "W32 DNS resolver asked to look up %s for `%s'.\n",
536 af == AF_INET ? "IPv4" : af == AF_INET6 ? "IPv6" : "anything",
537 hostname);
538
539 rq = GNUNET_new(struct request);
540 rq->sc = sc;
541 rq->client = client;
542 rq->af = af;
543 if (rq->af != AF_INET && rq->af != AF_INET6)
544 rq->af = AF_INET;
545 if (namelen)
546 {
547 rq->name = GNUNET_malloc((namelen + 1) * sizeof(wchar_t));
548 GNUNET_memcpy(rq->name,
549 name,
550 (namelen + 1) * sizeof(wchar_t));
551 rq->u8name = hostname;
552 }
553
554 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
555 "Launching a lookup for client %p with rq %p\n",
556 client,
557 rq);
558 rq->lookup_request = GNUNET_GNS_lookup(gns,
559 hostname,
560 &gns_master_pubkey,
561 rtype,
562 GNUNET_NO /* Use DHT */,
563 &process_lookup_result,
564 rq);
565 if (NULL != rq->lookup_request)
566 {
567 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
568 "Lookup launched, waiting for a reply\n");
569 GNUNET_SERVICE_client_continue(client);
570 GNUNET_CONTAINER_DLL_insert(rq_head,
571 rq_tail,
572 rq);
573 }
574 else
575 {
576 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
577 "Lookup was not launched, disconnecting the client\n");
578 GNUNET_free_non_null(rq->name);
579 if (rq->u8name)
580 free(rq->u8name);
581 GNUNET_free(rq);
582 GNUNET_SERVICE_client_drop(client);
583 }
584}
585
586
587/**
588 * Check GET-message.
589 *
590 * @param cls identification of the client
591 * @param msg the actual message
592 * @return #GNUNET_OK if @a msg is well-formed
593 */
594static int
595check_get(void *cls,
596 const struct GNUNET_W32RESOLVER_GetMessage *msg)
597{
598 uint16_t size;
599 const wchar_t *hostname;
600
601 if (!got_egos)
602 {
603 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
604 _("Not ready to process requests, lacking ego data\n"));
605 return GNUNET_SYSERR;
606 }
607 size = ntohs(msg->header.size) - sizeof(struct GNUNET_W32RESOLVER_GetMessage);
608 hostname = (const wchar_t *)&msg[1];
609 if (hostname[size / 2 - 1] != L'\0')
610 {
611 GNUNET_break(0);
612 return GNUNET_SYSERR;
613 }
614 return GNUNET_OK;
615}
616
617
618/**
619 * Handle GET-message.
620 *
621 * @param cls identification of the client
622 * @param msg the actual message
623 */
624static void
625handle_get(void *cls,
626 const struct GNUNET_W32RESOLVER_GetMessage *msg)
627{
628 struct GNUNET_SERVICE_Client *client = cls;
629 GUID sc;
630 uint16_t size;
631 const wchar_t *hostname;
632 int af;
633
634 size = ntohs(msg->header.size) - sizeof(struct GNUNET_W32RESOLVER_GetMessage);
635 af = ntohl(msg->af);
636 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
637 "Got NBO GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
638 msg->sc_data1,
639 msg->sc_data2,
640 msg->sc_data3,
641 msg->sc_data4[0],
642 msg->sc_data4[1],
643 msg->sc_data4[2],
644 msg->sc_data4[3],
645 msg->sc_data4[4],
646 msg->sc_data4[5],
647 msg->sc_data4[6],
648 msg->sc_data4[7]);
649 sc.Data1 = ntohl(msg->sc_data1);
650 sc.Data2 = ntohs(msg->sc_data2);
651 sc.Data3 = ntohs(msg->sc_data3);
652 for (int i = 0; i < 8; i++)
653 sc.Data4[i] = msg->sc_data4[i];
654 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
655 "Got GUID: %08lX-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
656 sc.Data1,
657 sc.Data2,
658 sc.Data3,
659 sc.Data4[0],
660 sc.Data4[1],
661 sc.Data4[2],
662 sc.Data4[3],
663 sc.Data4[4],
664 sc.Data4[5],
665 sc.Data4[6],
666 sc.Data4[7]);
667 hostname = (const wchar_t *)&msg[1];
668 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
669 "Name of %u bytes (last word is 0x%0X): %*S\n",
670 size,
671 hostname[size / 2 - 2],
672 size / 2,
673 hostname);
674 get_ip_from_hostname(client,
675 hostname,
676 af,
677 sc);
678}
679
680
681/**
682 * Method called to with the ego we are to use for the lookup,
683 * when the ego is the one for the default master zone.
684 *
685 * @param cls closure (NULL, unused)
686 * @param ego ego handle, NULL if not found
687 * @param ctx context for application to store data for this ego
688 * (during the lifetime of this process, initially NULL)
689 * @param name name assigned by the user for this ego,
690 * NULL if the user just deleted the ego and it
691 * must thus no longer be used
692 */
693static void
694identity_master_cb(void *cls,
695 struct GNUNET_IDENTITY_Ego *ego,
696 void **ctx,
697 const char *name)
698{
699 id_op = NULL;
700 if (NULL == ego)
701 {
702 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
703 _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
704 GNUNET_SCHEDULER_shutdown();
705 return;
706 }
707 GNUNET_IDENTITY_ego_get_public_key(ego,
708 &gns_master_pubkey);
709 got_egos = 1;
710}
711
712
713/**
714 * Start up gns-helper-w32 service.
715 *
716 * @param cls closure
717 * @param cfg configuration to use
718 * @param service the initialized service
719 */
720static void
721run(void *cls,
722 const struct GNUNET_CONFIGURATION_Handle *cfg,
723 struct GNUNET_SERVICE_Handle *service)
724{
725 gns = GNUNET_GNS_connect(cfg);
726 if (NULL == gns)
727 {
728 fprintf(stderr,
729 _("Failed to connect to GNS\n"));
730 GNUNET_SCHEDULER_shutdown();
731 return;
732 }
733 GNUNET_SCHEDULER_add_shutdown(&do_shutdown,
734 NULL);
735 identity = GNUNET_IDENTITY_connect(cfg,
736 NULL,
737 NULL);
738 if (NULL == identity)
739 {
740 fprintf(stderr,
741 _("Failed to connect to identity service\n"));
742 GNUNET_SCHEDULER_shutdown();
743 return;
744 }
745 id_op = GNUNET_IDENTITY_get(identity,
746 "gns-master",
747 &identity_master_cb,
748 NULL);
749 GNUNET_assert(NULL != id_op);
750}
751
752
753/**
754 * Handle client connecting to the service.
755 *
756 * @param cls NULL
757 * @param client the new client
758 * @param mq the message queue of @a client
759 * @return @a client
760 */
761static void *
762client_connect_cb(void *cls,
763 struct GNUNET_SERVICE_Client *client,
764 struct GNUNET_MQ_Handle *mq)
765{
766 return client;
767}
768
769
770/**
771 * Callback called when a client disconnected from the service
772 *
773 * @param cls closure for the service
774 * @param c the client that disconnected
775 * @param internal_cls should be equal to @a c
776 */
777static void
778client_disconnect_cb(void *cls,
779 struct GNUNET_SERVICE_Client *client,
780 void *internal_cls)
781{
782 GNUNET_assert(internal_cls == client);
783}
784
785
786/**
787 * Define "main" method using service macro.
788 */
789GNUNET_SERVICE_MAIN
790 ("gns-helper-service-w32",
791 GNUNET_SERVICE_OPTION_NONE,
792 &run,
793 &client_connect_cb,
794 &client_disconnect_cb,
795 NULL,
796 GNUNET_MQ_hd_var_size(get,
797 GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST,
798 struct GNUNET_W32RESOLVER_GetMessage,
799 NULL),
800 GNUNET_MQ_handler_end());
801
802
803/* end of gnunet-gns-helper-service-w32.c */
diff --git a/src/gns/nss/Makefile.am b/src/gns/nss/Makefile.am
index 5d42f777f..f4a12ddee 100644
--- a/src/gns/nss/Makefile.am
+++ b/src/gns/nss/Makefile.am
@@ -18,18 +18,16 @@
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19# USA. 19# USA.
20 20
21EXTRA_DIST = map-file 21EXTRA_DIST = map-file
22 22
23AM_LDFLAGS=-avoid-version -module -export-dynamic 23AM_LDFLAGS=-avoid-version -module -export-dynamic
24 24
25nssdir = $(libdir)/gnunet/nss 25nssdir = $(libdir)/gnunet/nss
26 26
27if !MINGW
28nss_LTLIBRARIES = \ 27nss_LTLIBRARIES = \
29 libnss_gns.la \ 28 libnss_gns.la \
30 libnss_gns4.la \ 29 libnss_gns4.la \
31 libnss_gns6.la 30 libnss_gns6.la
32endif
33 31
34sources = nss_gns_query.h nss_gns_query.c 32sources = nss_gns_query.h nss_gns_query.c
35 33
@@ -45,4 +43,3 @@ libnss_gns4_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
45libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) 43libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES)
46libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 44libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1
47libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) 45libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
48
diff --git a/src/gns/w32nsp-install.c b/src/gns/w32nsp-install.c
deleted file mode 100644
index 2674359fb..000000000
--- a/src/gns/w32nsp-install.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gns/w32nsp-install.c
22 * @brief W32 integration installer for GNS
23 * @author LRN
24 */
25
26#include <ws2spi.h>
27#include <windows.h>
28#include <nspapi.h>
29#include <initguid.h>
30#include "gnunet_w32nsp_lib.h"
31#include <stdio.h>
32
33int
34main(int argc, char **argv)
35{
36 int ret;
37 int r = 1;
38 WSADATA wsd;
39 GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
40 wchar_t *cmdl;
41 int wargc;
42 wchar_t **wargv;
43 /* Allocate a 4K buffer to retrieve all the namespace providers */
44 DWORD dwInitialBufferLen = 4096;
45 DWORD dwBufferLen;
46 WSANAMESPACE_INFO *pi;
47 int p_count;
48 int i;
49
50 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
51 {
52 fprintf(stderr, "WSAStartup () failed: %lu\n", GetLastError());
53 return 5;
54 }
55
56 dwBufferLen = dwInitialBufferLen;
57 pi = malloc(dwBufferLen);
58 if (NULL == pi)
59 {
60 fprintf(stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno);
61 WSACleanup();
62 return 6;
63 }
64 p_count = WSAEnumNameSpaceProviders(&dwBufferLen, pi);
65 if (SOCKET_ERROR == p_count)
66 {
67 DWORD err = GetLastError();
68 if (WSAEFAULT == err && dwBufferLen != dwInitialBufferLen)
69 {
70 free(pi);
71
72 pi = malloc(dwBufferLen);
73 if (pi == NULL)
74 {
75 fprintf(stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno);
76 WSACleanup();
77 return 6;
78 }
79
80 p_count = WSAEnumNameSpaceProviders(&dwBufferLen, pi);
81 if (SOCKET_ERROR == p_count)
82 {
83 fprintf(stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError());
84 free(pi);
85 WSACleanup();
86 return 7;
87 }
88 }
89 else
90 {
91 fprintf(stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError());
92 free(pi);
93 WSACleanup();
94 return 8;
95 }
96 }
97 for (i = 0; i < p_count; i++)
98 {
99 if (IsEqualGUID(&pi[i].NSProviderId, &id))
100 {
101 fprintf(stderr, "GNUnet DNS provider is already installed\n");
102 free(pi);
103 WSACleanup();
104 return 0;
105 }
106 }
107 free(pi);
108
109 cmdl = GetCommandLineW();
110 if (cmdl == NULL)
111 {
112 WSACleanup();
113 return 2;
114 }
115 wargv = CommandLineToArgvW(cmdl, &wargc);
116 if (wargv == NULL)
117 {
118 WSACleanup();
119 return 3;
120 }
121 r = 4;
122
123 if (wargc == 2)
124 {
125 ret = WSCInstallNameSpace(L"GNUnet DNS provider", wargv[1], NS_DNS, 0, &id);
126 if (ret == NO_ERROR)
127 {
128 fprintf(stderr, "Installed GNUnet DNS provider\n");
129 r = 0;
130 }
131 else
132 {
133 r = 1;
134 fprintf(stderr,
135 "WSCInstallNameSpace (L\"GNUnet DNS provider\", \"%S\", %d, 0, %p) failed: %lu\n",
136 wargv[1], NS_DNS, &id, GetLastError());
137 }
138 }
139 else
140 fprintf(stderr, "Usage: %S <path-to-libw32nsp>\n", wargv[0]);
141 WSACleanup();
142 return r;
143}
diff --git a/src/gns/w32nsp-resolve.c b/src/gns/w32nsp-resolve.c
deleted file mode 100644
index ad0fd3586..000000000
--- a/src/gns/w32nsp-resolve.c
+++ /dev/null
@@ -1,464 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gns/w32nsp-resolve.c
22 * @brief W32 integration for GNS
23 * @author LRN
24 */
25/* Instead of including gnunet_common.h */
26#define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
27
28#include <ws2tcpip.h>
29#include <windows.h>
30#include <nspapi.h>
31#include <ws2spi.h>
32#include <nspapi.h>
33#include <initguid.h>
34#include "gnunet_w32nsp_lib.h"
35#include <stdio.h>
36
37typedef int (WSPAPI *LPNSPSTARTUP)(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
38
39GUID host = { 0x0002a800, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
40GUID ip4 = { 0x00090035, 0, 1, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
41GUID ip6 = { 0x00090035, 0, 0x001c, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
42
43DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
44
45#define DEFINE_DNS_GUID(a, x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
46DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
47DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
48DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
49DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
50DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
51DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
52DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
53DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
54DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
55DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
56DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
57
58//
59// Utility to turn a list of offsets into a list of addresses. Used
60// to convert structures returned as BLOBs.
61//
62
63VOID
64FixList(PCHAR ** List, PCHAR Base)
65{
66 if (*List)
67 {
68 PCHAR * Addr;
69
70 Addr = *List = (PCHAR *)(((DWORD)*List + Base));
71 while (*Addr)
72 {
73 *Addr = (PCHAR)(((DWORD)*Addr + Base));
74 Addr++;
75 }
76 }
77}
78
79
80//
81// Routine to convert a hostent returned in a BLOB to one with
82// usable pointers. The structure is converted in-place.
83//
84VOID
85UnpackHostEnt(struct hostent * hostent)
86{
87 PCHAR pch;
88
89 pch = (PCHAR)hostent;
90
91 if (hostent->h_name)
92 {
93 hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
94 }
95 FixList(&hostent->h_aliases, pch);
96 FixList(&hostent->h_addr_list, pch);
97}
98
99
100static void
101print_hostent(struct hostent *he)
102{
103 int i;
104 char **pAlias;
105
106 printf("\tOfficial name: %s\n", he->h_name);
107 for (i = 0, pAlias = he->h_aliases; *pAlias != 0; pAlias++)
108 {
109 printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
110 }
111 printf("\tAddress type: ");
112 switch (he->h_addrtype)
113 {
114 case AF_INET:
115 printf("AF_INET\n");
116 break;
117
118 case AF_INET6:
119 printf("AF_INET6\n");
120 break;
121
122 case AF_NETBIOS:
123 printf("AF_NETBIOS\n");
124 break;
125
126 default:
127 printf(" %d\n", he->h_addrtype);
128 break;
129 }
130 printf("\tAddress length: %d\n", he->h_length);
131
132 if (he->h_addrtype == AF_INET)
133 {
134 struct sockaddr_in addr;
135 memset(&addr, 0, sizeof(addr));
136 addr.sin_family = AF_INET;
137 addr.sin_port = 0;
138 i = 0;
139 while (he->h_addr_list[i] != 0)
140 {
141 char buf[1024];
142 DWORD buflen = 1024;
143 addr.sin_addr = *(struct in_addr *)he->h_addr_list[i++];
144 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
145 printf("\tIPv4 Address #%d: %s\n", i, buf);
146 else
147 printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError());
148 }
149 }
150 else if (he->h_addrtype == AF_INET6)
151 {
152 struct sockaddr_in6 addr;
153 memset(&addr, 0, sizeof(addr));
154 addr.sin6_family = AF_INET6;
155 addr.sin6_port = 0;
156 i = 0;
157 while (he->h_addr_list[i] != 0)
158 {
159 char buf[1024];
160 DWORD buflen = 1024;
161 addr.sin6_addr = *(struct in6_addr *)he->h_addr_list[i++];
162 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
163 printf("\tIPv6 Address #%d: %s\n", i, buf);
164 else
165 printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError());
166 }
167 }
168}
169
170
171int
172main(int argc, char **argv)
173{
174 int ret;
175 int r = 1;
176 WSADATA wsd;
177 GUID prov;
178 GUID sc;
179 wchar_t *cmdl;
180 int wargc;
181 wchar_t **wargv;
182
183 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
184 {
185 fprintf(stderr, "WSAStartup() failed: %lu\n", GetLastError());
186 return 5;
187 }
188
189 cmdl = GetCommandLineW();
190 if (cmdl == NULL)
191 {
192 WSACleanup();
193 return 2;
194 }
195 wargv = CommandLineToArgvW(cmdl, &wargc);
196 if (wargv == NULL)
197 {
198 WSACleanup();
199 return 3;
200 }
201 r = 4;
202
203 if (wargc == 5)
204 {
205 if (wcscmp(wargv[1], L"A") == 0)
206 sc = SVCID_DNS_TYPE_A;
207 else if (wcscmp(wargv[1], L"AAAA") == 0)
208 sc = SVCID_DNS_TYPE_AAAA;
209 else if (wcscmp(wargv[1], L"name") == 0)
210 sc = SVCID_HOSTNAME;
211 else if (wcscmp(wargv[1], L"addr") == 0)
212 sc = SVCID_INET_HOSTADDRBYNAME;
213 else
214 wargc -= 1;
215 if (wcscmp(wargv[4], L"mswdns") == 0)
216 prov = W32_DNS;
217 else if (wcscmp(wargv[4], L"gnunetdns") == 0)
218 prov = GNUNET_NAMESPACE_PROVIDER_DNS;
219 else
220 wargc -= 1;
221 }
222 else if (wargc == 3)
223 {
224 }
225 else
226 {
227 fprintf(stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
228 "record type - one of the following: A | AAAA | name | addr\n"
229 "service name - a string to resolve; \" \" (a space) means 'blank'\n"
230 "NSP library path - path to libw32nsp\n"
231 "NSP id - one of the following: mswdns | gnunetdns\n",
232 wargv[0]);
233 }
234
235 if (wargc == 5)
236 {
237 HMODULE nsp;
238
239 nsp = LoadLibraryW(wargv[3]);
240 if (nsp == NULL)
241 {
242 fprintf(stderr, "Failed to load library `%S'\n", wargv[3]);
243 }
244 else
245 {
246 LPNSPSTARTUP startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup");
247 if (startup == NULL)
248 startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup@8");
249 if (startup != NULL)
250 {
251 NSP_ROUTINE api;
252 api.cbSize = sizeof(api);
253 ret = startup(&prov, &api);
254 if (NO_ERROR != ret)
255 fprintf(stderr, "startup failed: %lu\n", GetLastError());
256 else
257 {
258 HANDLE lookup;
259 WSAQUERYSETW search;
260 char buf[4096];
261 WSAQUERYSETW *result = (WSAQUERYSETW *)buf;
262 DWORD resultsize;
263 DWORD err;
264 memset(&search, 0, sizeof(search));
265 search.dwSize = sizeof(search);
266 search.lpszServiceInstanceName = (wcscmp(wargv[2], L" ") == 0) ? NULL : wargv[2];
267 search.lpServiceClassId = &sc;
268 search.lpNSProviderId = &prov;
269 search.dwNameSpace = NS_ALL;
270 ret = api.NSPLookupServiceBegin(&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
271 if (ret != NO_ERROR)
272 {
273 fprintf(stderr, "lookup start failed\n");
274 }
275 else
276 {
277 resultsize = 4096;
278 ret = api.NSPLookupServiceNext(lookup, LUP_RETURN_ALL, &resultsize, result);
279 err = GetLastError();
280 if (ret != NO_ERROR)
281 {
282 fprintf(stderr, "lookup next failed: %lu\n", err);
283 }
284 else
285 {
286 int i;
287 printf("Got result:\n");
288 printf(" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
289 if (result->lpServiceClassId)
290 printf(" lpServiceClassId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
291 result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
292 result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
293 result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
294 else
295 printf(" lpServiceClassId: NULL\n");
296 if (result->lpVersion)
297 printf(" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
298 else
299 printf(" lpVersion: NULL\n");
300 printf(" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL");
301 printf(" dwNameSpace: %lu\n", result->dwNameSpace);
302 if (result->lpNSProviderId)
303 printf(" lpNSProviderId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
304 result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
305 result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
306 result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
307 else
308 printf(" lpNSProviderId: NULL\n");
309 printf(" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL");
310 printf(" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols);
311 printf(" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
312 printf(" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs);
313 for (i = 0; i < result->dwNumberOfCsAddrs; i++)
314 {
315 switch (result->lpcsaBuffer[i].iSocketType)
316 {
317 case SOCK_STREAM:
318 printf(" %d: iSocketType = SOCK_STREAM\n", i);
319 break;
320
321 case SOCK_DGRAM:
322 printf(" %d: iSocketType = SOCK_DGRAM\n", i);
323 break;
324
325 default:
326 printf(" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
327 }
328 switch (result->lpcsaBuffer[i].iProtocol)
329 {
330 case IPPROTO_TCP:
331 printf(" %d: iProtocol = IPPROTO_TCP\n", i);
332 break;
333
334 case IPPROTO_UDP:
335 printf(" %d: iProtocol = IPPROTO_UDP\n", i);
336 break;
337
338 default:
339 printf(" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol);
340 }
341 switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
342 {
343 case AF_INET:
344 printf(" %d: loc family = AF_INET\n", i);
345 break;
346
347 case AF_INET6:
348 printf(" %d: loc family = AF_INET6\n", i);
349 break;
350
351 default:
352 printf(" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
353 }
354 switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
355 {
356 case AF_INET:
357 printf(" %d: rem family = AF_INET\n", i);
358 break;
359
360 case AF_INET6:
361 printf(" %d: rem family = AF_INET6\n", i);
362 break;
363
364 default:
365 printf(" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
366 }
367 char buf[1024];
368 DWORD buflen = 1024;
369 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
370 printf("\tLocal Address #%d: %s\n", i, buf);
371 else
372 printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError());
373 buflen = 1024;
374 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
375 printf("\tRemote Address #%d: %s\n", i, buf);
376 else
377 printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError());
378 }
379 printf(" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags);
380 printf(" lpBlob: 0x%p\n", result->lpBlob);
381 if (result->lpBlob)
382 {
383 struct hostent *he = malloc(result->lpBlob->cbSize);
384 if (he != NULL)
385 {
386 GNUNET_memcpy(he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
387 UnpackHostEnt(he);
388 print_hostent(he);
389 free(he);
390 }
391 }
392 }
393 ret = api.NSPLookupServiceEnd(lookup);
394 if (ret != NO_ERROR)
395 printf("NSPLookupServiceEnd() failed: %lu\n", GetLastError());
396 }
397 api.NSPCleanup(&prov);
398 }
399 }
400 FreeLibrary(nsp);
401 }
402 }
403 else if (wargc == 3)
404 {
405 int s;
406 ADDRINFOW hints;
407 ADDRINFOW *result;
408 ADDRINFOW *pos;
409
410 memset(&hints, 0, sizeof(struct addrinfo));
411 hints.ai_family = AF_UNSPEC;
412 hints.ai_socktype = SOCK_STREAM;
413
414 if (0 != (s = GetAddrInfoW(wargv[2], NULL, &hints, &result)))
415 {
416 fprintf(stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
417 wargv[2], GetLastError());
418 }
419 else
420 {
421 for (pos = result; pos != NULL; pos = pos->ai_next)
422 {
423 wchar_t tmpbuf[1024];
424 DWORD buflen = 1024;
425 if (0 == WSAAddressToStringW(pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
426 fprintf(stderr, "Result:\n"
427 " flags: 0x%X\n"
428 " family: 0x%X\n"
429 " socktype: 0x%X\n"
430 " protocol: 0x%X\n"
431 " addrlen: %u\n"
432 " addr: %S\n"
433 " canonname: %S\n",
434 pos->ai_flags,
435 pos->ai_family,
436 pos->ai_socktype,
437 pos->ai_protocol,
438 pos->ai_addrlen,
439 tmpbuf,
440 pos->ai_canonname);
441 else
442 fprintf(stderr, "Result:\n"
443 " flags: 0x%X\n"
444 " family: 0x%X\n"
445 " socktype: 0x%X\n"
446 " protocol: 0x%X\n"
447 " addrlen: %u\n"
448 " addr: %S\n"
449 " canonname: %S\n",
450 pos->ai_flags,
451 pos->ai_family,
452 pos->ai_socktype,
453 pos->ai_protocol,
454 pos->ai_addrlen,
455 L"<can't stringify>",
456 pos->ai_canonname);
457 }
458 if (NULL != result)
459 FreeAddrInfoW(result);
460 }
461 }
462 WSACleanup();
463 return r;
464}
diff --git a/src/gns/w32nsp-uninstall.c b/src/gns/w32nsp-uninstall.c
deleted file mode 100644
index f5031f341..000000000
--- a/src/gns/w32nsp-uninstall.c
+++ /dev/null
@@ -1,31 +0,0 @@
1#include <ws2spi.h>
2#include <windows.h>
3#include <nspapi.h>
4#include <initguid.h>
5#include "gnunet_w32nsp_lib.h"
6#include <stdio.h>
7
8int
9main(int argc, char **argv)
10{
11 int ret;
12 GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
13 WSADATA wsd;
14
15 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
16 {
17 fprintf(stderr, "WSAStartup () failed: %lu\n", GetLastError());
18 return 5;
19 }
20
21 ret = WSCUnInstallNameSpace(&id);
22 if (ret == NO_ERROR)
23 {
24 fprintf(stderr, "Uninstalled GNUnet DNS provider\n");
25 WSACleanup();
26 return 0;
27 }
28 fprintf(stderr, "WSCUnInstallNameSpace () failed: %lu\n", GetLastError());
29 WSACleanup();
30 return 1;
31} \ No newline at end of file
diff --git a/src/gns/w32nsp.c b/src/gns/w32nsp.c
deleted file mode 100644
index 3de4452f0..000000000
--- a/src/gns/w32nsp.c
+++ /dev/null
@@ -1,711 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gns/w32nsp.c
22 * @brief W32 integration for GNS
23 * @author LRN
24 */
25/* This code is partially based upon samples from the book
26 * "Network Programming For Microsoft Windows, 2Nd Edition".
27 */
28
29#define VERBOSE 0
30#if !VERBOSE
31# define DEBUGLOG(s, ...)
32#endif
33#if VERBOSE
34# define __printf__ printf
35# define DEBUGLOG(s, ...) printf(s, ## __VA_ARGS__)
36#endif
37
38#include <stdint.h>
39#include <ws2tcpip.h>
40#include <ws2spi.h>
41#include <windows.h>
42#include <nspapi.h>
43
44#define WINDOWS 1
45#define MINGW 1
46#ifndef __BYTE_ORDER
47#ifdef _BYTE_ORDER
48#define __BYTE_ORDER _BYTE_ORDER
49#else
50#ifdef BYTE_ORDER
51#define __BYTE_ORDER BYTE_ORDER
52#endif
53#endif
54#endif
55#ifndef __BIG_ENDIAN
56#ifdef _BIG_ENDIAN
57#define __BIG_ENDIAN _BIG_ENDIAN
58#else
59#ifdef BIG_ENDIAN
60#define __BIG_ENDIAN BIG_ENDIAN
61#endif
62#endif
63#endif
64#ifndef __LITTLE_ENDIAN
65#ifdef _LITTLE_ENDIAN
66#define __LITTLE_ENDIAN _LITTLE_ENDIAN
67#else
68#ifdef LITTLE_ENDIAN
69#define __LITTLE_ENDIAN LITTLE_ENDIAN
70#endif
71#endif
72#endif
73#include "w32resolver.h"
74#include <initguid.h>
75#include "gnunet_w32nsp_lib.h"
76#undef INITGUID
77
78#define NSPAPI_VERSION_MAJOR 4
79#define NSPAPI_VERSION_MINOR 4
80
81static CRITICAL_SECTION records_cs;
82
83struct record {
84 _win_socket s;
85 DWORD flags;
86 uint8_t state;
87 char *buf;
88 wchar_t *name;
89};
90
91static struct record *records = NULL;
92static size_t records_len = 0;
93static size_t records_size = 0;
94
95static int
96resize_records()
97{
98 size_t new_size = records_len > 0 ? records_len * 2 : 5;
99 struct record *new_records = malloc(new_size * sizeof(struct record));
100
101 if (new_records == NULL)
102 {
103 SetLastError(WSA_NOT_ENOUGH_MEMORY);
104 return 0;
105 }
106 GNUNET_memcpy(new_records, records, records_len * sizeof(struct record));
107 memset(&new_records[records_len], 0, sizeof(struct record) * (new_size - records_len));
108 records_size = new_size;
109 free(records);
110 records = new_records;
111 return 1;
112}
113
114static int
115add_record(_win_socket s, const wchar_t *name, DWORD flags)
116{
117 int res = 1;
118 int i;
119 int empty = -1;
120
121 //EnterCriticalSection (&records_cs);
122 for (i = 0; i < records_len; i++)
123 if (records[i].state == 0)
124 break;
125 empty = i;
126 if (i == records_len)
127 {
128 res = resize_records();
129 if (res)
130 empty = records_len++;
131 }
132 if (res)
133 {
134 struct record r;
135 r.s = s;
136 r.flags = flags;
137 r.name = (wchar_t *)name;
138 r.state = 1;
139 r.buf = NULL;
140 if (name)
141 r.name = wcsdup(name);
142 records[empty] = r;
143 }
144 //LeaveCriticalSection (&records_cs);
145 return res;
146}
147
148/* These are not defined by mingw.org headers at the moment*/
149typedef INT (WSPAPI *LPNSPIOCTL)(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPWSACOMPLETION, LPWSATHREADID);
150typedef struct _NSP_ROUTINE_XP {
151 DWORD cbSize;
152 DWORD dwMajorVersion;
153 DWORD dwMinorVersion;
154 LPNSPCLEANUP NSPCleanup;
155 LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin;
156 LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext;
157 LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd;
158 LPNSPSETSERVICE NSPSetService;
159 LPNSPINSTALLSERVICECLASS NSPInstallServiceClass;
160 LPNSPREMOVESERVICECLASS NSPRemoveServiceClass;
161 LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo;
162 LPNSPIOCTL NSPIoctl;
163} NSP_ROUTINE_XP;
164
165static _win_socket
166connect_to_dns_resolver()
167{
168 struct sockaddr_in addr;
169 _win_socket r;
170 int ret;
171
172 r = _win_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
173 if (INVALID_SOCKET == r)
174 {
175 SetLastError(16004);
176 return r;
177 }
178
179 addr.sin_family = AF_INET;
180 addr.sin_port = htons(5353); /* TCP 5353 is not registered; UDP 5353 is */
181 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
182
183 ret = _win_connect(r, (struct sockaddr *)&addr, sizeof(addr));
184 if (SOCKET_ERROR == ret)
185 {
186 DWORD err = GetLastError();
187 closesocket(r);
188 SetLastError(err);
189 SetLastError(16005);
190 r = INVALID_SOCKET;
191 }
192 return r;
193}
194
195static int
196send_name_to_ip_request(LPWSAQUERYSETW lpqsRestrictions,
197 LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
198 _win_socket *resolver)
199{
200 struct GNUNET_W32RESOLVER_GetMessage *msg;
201 int af4 = 0;
202 int af6 = 0;
203 char *buf;
204 int ret = 1;
205 int i;
206 size_t size = sizeof(struct GNUNET_W32RESOLVER_GetMessage);
207 size_t namelen = 0;
208
209 if (lpqsRestrictions->lpszServiceInstanceName)
210 namelen = sizeof(wchar_t) * (wcslen(lpqsRestrictions->lpszServiceInstanceName) + 1);
211 size += namelen;
212 buf = malloc(size);
213 msg = (struct GNUNET_W32RESOLVER_GetMessage *)buf;
214 msg->header.size = htons(size);
215 msg->header.type = htons(GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST);
216 if (lpqsRestrictions->dwNumberOfProtocols > 0)
217 {
218 int i;
219 for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++)
220 {
221 if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET)
222 af4 = 1;
223 if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6)
224 af6 = 1;
225 }
226 }
227 if (af4 && !af6)
228 msg->af = htonl(AF_INET);
229 else if (af6 && !af4)
230 msg->af = htonl(AF_INET6);
231 else
232 msg->af = htonl(AF_UNSPEC);
233 if (lpqsRestrictions->lpszServiceInstanceName)
234 GNUNET_memcpy(&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen);
235 msg->sc_data1 = htonl(lpqsRestrictions->lpServiceClassId->Data1);
236 msg->sc_data2 = htons(lpqsRestrictions->lpServiceClassId->Data2);
237 msg->sc_data3 = htons(lpqsRestrictions->lpServiceClassId->Data3);
238 for (i = 0; i < 8; i++)
239 msg->sc_data4[i] = lpqsRestrictions->lpServiceClassId->Data4[i];
240 *resolver = connect_to_dns_resolver();
241 if (*resolver != INVALID_SOCKET)
242 {
243 if (size != send(*resolver, buf, size, 0))
244 {
245#if VERBOSE
246 DWORD err = GetLastError();
247#endif
248 closesocket(*resolver);
249 *resolver = INVALID_SOCKET;
250 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err);
251 SetLastError(WSATRY_AGAIN);
252 ret = 0;
253 }
254 }
255 else
256 ret = 0;
257 free(buf);
258 return ret;
259}
260
261static int WSPAPI
262NSPCleanup(LPGUID lpProviderId)
263{
264 DEBUGLOG("NSPCleanup\n");
265 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
266 {
267 return NO_ERROR;
268 }
269 SetLastError(WSAEINVALIDPROVIDER);
270 return SOCKET_ERROR;
271}
272
273BOOL WINAPI
274DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
275{
276 switch (fdwReason)
277 {
278 case DLL_PROCESS_ATTACH:
279 if (!InitializeCriticalSectionAndSpinCount(&records_cs, 0x00000400))
280 {
281 return FALSE;
282 }
283 break;
284
285 case DLL_THREAD_ATTACH:
286 break;
287
288 case DLL_THREAD_DETACH:
289 break;
290
291 case DLL_PROCESS_DETACH:
292 DeleteCriticalSection(&records_cs);
293 break;
294 }
295 return TRUE;
296}
297
298
299
300
301static int WSPAPI
302GNUNET_W32NSP_LookupServiceBegin(LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions,
303 LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
304 LPHANDLE lphLookup)
305{
306 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin\n");
307 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
308 {
309 SOCKET s;
310 if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL)
311 {
312 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n");
313 SetLastError(WSAEINVAL);
314 return SOCKET_ERROR;
315 }
316 if (lpqsRestrictions->lpszServiceInstanceName != NULL)
317 {
318 wchar_t *s = lpqsRestrictions->lpszServiceInstanceName;
319 size_t len = wcslen(s);
320 if (len >= 5 && wcscmp(&s[len - 5], L".zkey") == 0)
321 {
322 }
323 else if (len >= 4 && wcscmp(&s[len - 4], L".gnu") == 0)
324 {
325 }
326 else
327 {
328 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n");
329 SetLastError(WSAEINVAL);
330 return SOCKET_ERROR;
331 }
332 }
333
334 if (send_name_to_ip_request(lpqsRestrictions,
335 lpServiceClassInfo, dwControlFlags, &s))
336 {
337 if (!(add_record(s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags)))
338 {
339 DWORD err = GetLastError();
340 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n");
341 closesocket(s);
342 SetLastError(err);
343 return SOCKET_ERROR;
344 }
345 *lphLookup = (HANDLE)s;
346 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError());
347 return NO_ERROR;
348 }
349 return SOCKET_ERROR;
350 }
351 DEBUGLOG("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n");
352 SetLastError(WSAEINVALIDPROVIDER);
353 return SOCKET_ERROR;
354}
355
356#define UnmarshallPtr(ptr, ptrtype, base) \
357 if (ptr) \
358 ptr = (ptrtype *) (base + (uintptr_t)ptr)
359
360static void
361UnmarshallWSAQUERYSETW(LPWSAQUERYSETW req)
362{
363 int i;
364 char *base = (char *)req;
365
366 UnmarshallPtr(req->lpszServiceInstanceName, wchar_t, base);
367 UnmarshallPtr(req->lpServiceClassId, GUID, base);
368 UnmarshallPtr(req->lpVersion, WSAVERSION, base);
369 UnmarshallPtr(req->lpszComment, wchar_t, base);
370 UnmarshallPtr(req->lpNSProviderId, GUID, base);
371 UnmarshallPtr(req->lpszContext, wchar_t, base);
372 UnmarshallPtr(req->lpafpProtocols, AFPROTOCOLS, base);
373 UnmarshallPtr(req->lpszQueryString, wchar_t, base);
374 UnmarshallPtr(req->lpcsaBuffer, CSADDR_INFO, base);
375 for (i = 0; i < req->dwNumberOfCsAddrs; i++)
376 {
377 UnmarshallPtr(req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base);
378 UnmarshallPtr(req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base);
379 }
380 UnmarshallPtr(req->lpBlob, BLOB, base);
381 if (req->lpBlob)
382 UnmarshallPtr(req->lpBlob->pBlobData, BYTE, base);
383}
384
385static int WSAAPI
386GNUNET_W32NSP_LookupServiceNext(HANDLE hLookup, DWORD dwControlFlags,
387 LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
388{
389 /*DWORD effective_flags;*/
390 int i;
391 struct GNUNET_MessageHeader header = { 0, 0 };
392 int rec = -1;
393 int rc;
394 int to_receive;
395 int t;
396 char *buf;
397
398 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext\n");
399 //EnterCriticalSection (&records_cs);
400 for (i = 0; i < records_len; i++)
401 {
402 if (records[i].s == (_win_socket)hLookup)
403 {
404 rec = i;
405 break;
406 }
407 }
408 if (rec == -1)
409 {
410 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: invalid handle\n");
411 SetLastError(WSA_INVALID_HANDLE);
412 //LeaveCriticalSection (&records_cs);
413 return SOCKET_ERROR;
414 }
415 if (records[rec].state & 4)
416 {
417 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: session is closed\n");
418 SetLastError(WSA_E_NO_MORE);
419 //LeaveCriticalSection (&records_cs);
420 return SOCKET_ERROR;
421 }
422 /*effective_flags = dwControlFlags & records[rec].flags;*/
423 if (records[rec].buf)
424 {
425 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: checking buffer\n");
426 header = *((struct GNUNET_MessageHeader *)records[rec].buf);
427 if (*lpdwBufferLength < header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage))
428 {
429 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
430 SetLastError(WSAEFAULT);
431 //LeaveCriticalSection (&records_cs);
432 return SOCKET_ERROR;
433 }
434 GNUNET_memcpy(lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
435 free(records[rec].buf);
436 records[rec].buf = NULL;
437 //LeaveCriticalSection (&records_cs);
438 UnmarshallWSAQUERYSETW((LPWSAQUERYSETW)lpqsResults);
439 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n");
440 return NO_ERROR;
441 }
442 records[rec].state |= 8;
443 //LeaveCriticalSection (&records_cs);
444 to_receive = sizeof(header);
445 rc = 0;
446#if VERBOSE
447 {
448 unsigned long have;
449 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
450 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a header from %p, %lu bytes available\n", to_receive, hLookup, have);
451 }
452#endif
453 while (to_receive > 0)
454 {
455 t = recv((_win_socket)hLookup, &((char *)&header)[rc], to_receive, 0);
456 if (t > 0)
457 {
458 rc += t;
459 to_receive -= t;
460 }
461 else
462 break;
463 }
464#if VERBOSE
465 {
466 unsigned long have;
467 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
468 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a header from %p, %lu bytes available\n", rc, hLookup, have);
469 }
470#endif
471 //EnterCriticalSection (&records_cs);
472 records[rec].state &= ~8;
473 if (rc != sizeof(header))
474 {
475 if (records[rec].state & 2)
476 {
477 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
478 SetLastError(WSA_E_CANCELLED);
479 }
480 else
481 {
482 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for a header (rc %d != %u, state is 0x%0X)\n", rc, sizeof(header), records[rec].state);
483 SetLastError(WSA_E_NO_MORE);
484 }
485 records[rec].state |= 4;
486 //LeaveCriticalSection (&records_cs);
487 return SOCKET_ERROR;
488 }
489 records[rec].state &= ~8;
490 header.type = ntohs(header.type);
491 header.size = ntohs(header.size);
492 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: header type %d, header size %u\n", header.type, header.size);
493 if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE ||
494 (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE &&
495 header.size == sizeof(header)))
496 {
497 records[rec].state |= 4;
498 if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE)
499 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: header type is wrong\n");
500 else
501 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: empty header - no data\n");
502 //LeaveCriticalSection (&records_cs);
503 SetLastError(WSA_E_NO_MORE);
504 return SOCKET_ERROR;
505 }
506 buf = malloc(header.size);
507 if (buf == NULL)
508 {
509 records[rec].state |= 4;
510 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n");
511 //LeaveCriticalSection (&records_cs);
512 SetLastError(WSA_E_NO_MORE);
513 return SOCKET_ERROR;
514 }
515 records[rec].state |= 8;
516 //LeaveCriticalSection (&records_cs);
517 GNUNET_memcpy(buf, &header, sizeof(header));
518 to_receive = header.size - sizeof(header);
519 rc = 0;
520#if VERBOSE
521 {
522 unsigned long have;
523 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
524 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a body from %p, %lu bytes available\n", to_receive, hLookup, have);
525 }
526#endif
527 while (to_receive > 0)
528 {
529 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: recv (%d)\n", to_receive);
530 t = recv((_win_socket)hLookup, &((char *)&((struct GNUNET_MessageHeader *)buf)[1])[rc], to_receive, 0);
531 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: recv returned %d\n", t);
532 if (t > 0)
533 {
534 rc += t;
535 to_receive -= t;
536 }
537 else
538 break;
539 }
540#if VERBOSE
541 {
542 unsigned long have;
543 int ior = ioctlsocket((_win_socket)hLookup, FIONREAD, &have);
544 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a body from %p, %lu bytes available\n", rc, hLookup, have);
545 }
546#endif
547 //EnterCriticalSection (&records_cs);
548 records[rec].state &= ~8;
549 if (rc != header.size - sizeof(header))
550 {
551 free(buf);
552 if (records[rec].state & 2)
553 {
554 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
555 SetLastError(WSA_E_CANCELLED);
556 }
557 else
558 {
559 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for the rest (rc %d != %d, state is 0x%0X)\n", rc, header.size - sizeof(header), records[rec].state);
560 SetLastError(WSA_E_NO_MORE);
561 }
562 records[rec].state |= 4;
563 //LeaveCriticalSection (&records_cs);
564 return SOCKET_ERROR;
565 }
566 if (*lpdwBufferLength < header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage))
567 {
568 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
569 SetLastError(WSAEFAULT);
570 records[rec].buf = buf;
571 //LeaveCriticalSection (&records_cs);
572 return SOCKET_ERROR;
573 }
574 //LeaveCriticalSection (&records_cs);
575 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: writing %d bytes into result buffer\n", header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
576 GNUNET_memcpy(lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof(struct GNUNET_W32RESOLVER_GetMessage));
577 free(buf);
578 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: OK\n");
579 UnmarshallWSAQUERYSETW((LPWSAQUERYSETW)lpqsResults);
580 DEBUGLOG("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError());
581 return NO_ERROR;
582}
583
584static int WSPAPI
585GNUNET_W32NSP_LookupServiceEnd(HANDLE hLookup)
586{
587 int i;
588 int rec = -1;
589
590 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd\n");
591 //EnterCriticalSection (&records_cs);
592 for (i = 0; i < records_len; i++)
593 {
594 if (records[i].s == (_win_socket)hLookup)
595 {
596 rec = i;
597 break;
598 }
599 }
600 if (rec == -1)
601 {
602 SetLastError(WSA_INVALID_HANDLE);
603 //LeaveCriticalSection (&records_cs);
604 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n");
605 return SOCKET_ERROR;
606 }
607 records[rec].state |= 2;
608 closesocket(records[rec].s);
609 while (records[rec].state & 8)
610 {
611 //LeaveCriticalSection (&records_cs);
612 Sleep(10);
613 //EnterCriticalSection (&records_cs);
614 }
615 if (records[rec].buf)
616 free(records[rec].buf);
617 records[rec].buf = NULL;
618 records[rec].state = 0;
619 if (records[rec].name)
620 free(records[rec].name);
621 //LeaveCriticalSection (&records_cs);
622 DEBUGLOG("GNUNET_W32NSP_LookupServiceEnd: OK\n");
623 return NO_ERROR;
624}
625
626static int WSAAPI
627GNUNET_W32NSP_SetService(LPGUID lpProviderId,
628 LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo,
629 WSAESETSERVICEOP essOperation, DWORD dwControlFlags)
630{
631 DEBUGLOG("GNUNET_W32NSP_SetService\n");
632 SetLastError(WSAEOPNOTSUPP);
633 return SOCKET_ERROR;
634}
635
636static int WSAAPI
637GNUNET_W32NSP_InstallServiceClass(LPGUID lpProviderId,
638 LPWSASERVICECLASSINFOW lpServiceClassInfo)
639{
640 DEBUGLOG("GNUNET_W32NSP_InstallServiceClass\n");
641 SetLastError(WSAEOPNOTSUPP);
642 return SOCKET_ERROR;
643}
644
645
646static int WSAAPI
647GNUNET_W32NSP_RemoveServiceClass(LPGUID lpProviderId, LPGUID lpServiceClassId)
648{
649 DEBUGLOG("GNUNET_W32NSP_RemoveServiceClass\n");
650 SetLastError(WSAEOPNOTSUPP);
651 return SOCKET_ERROR;
652}
653
654static int WSAAPI
655GNUNET_W32NSP_GetServiceClassInfo(LPGUID lpProviderId, LPDWORD lpdwBufSize,
656 LPWSASERVICECLASSINFOW lpServiceClassInfo)
657{
658 DEBUGLOG("GNUNET_W32NSP_GetServiceClassInfo\n");
659 SetLastError(WSAEOPNOTSUPP);
660 return SOCKET_ERROR;
661}
662
663static int WSAAPI
664GNUNET_W32NSP_Ioctl(HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
665 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
666 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,
667 LPWSATHREADID lpThreadId)
668{
669 DEBUGLOG("GNUNET_W32NSP_Ioctl\n");
670 SetLastError(WSAEOPNOTSUPP);
671 return SOCKET_ERROR;
672}
673
674/**
675 * This function is called by Winsock to hook up our provider.
676 * It is the only function that [should be/is] exported by the
677 * provider. All other routines are passed as pointers in lpnspRoutines.
678 */
679int WSAAPI
680GNUNET_W32NSP_NSPStartup(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)
681{
682 if (IsEqualGUID(lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
683 {
684 if (!connect_to_dns_resolver())
685 {
686 return SOCKET_ERROR;
687 }
688 /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member.
689 * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl
690 * and use that offset as cbSize.
691 */
692 lpnspRoutines->cbSize = sizeof(NSP_ROUTINE);
693
694 lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR;
695 lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR;
696 lpnspRoutines->NSPCleanup = NSPCleanup;
697 lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin;
698 lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext;
699 lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd;
700 lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService;
701 lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass;
702 lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass;
703 lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo;
704 /*((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;*/
705 lpnspRoutines->NSPIoctl = GNUNET_W32NSP_Ioctl;
706 return NO_ERROR;
707 }
708 SetLastError(WSAEINVALIDPROVIDER);
709 return SOCKET_ERROR;
710}
711
diff --git a/src/gns/w32nsp.def b/src/gns/w32nsp.def
deleted file mode 100644
index 6bd28b283..000000000
--- a/src/gns/w32nsp.def
+++ /dev/null
@@ -1,2 +0,0 @@
1EXPORTS
2NSPStartup=GNUNET_W32NSP_NSPStartup
diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am
index f840a31a4..81bee5a6b 100644
--- a/src/gnsrecord/Makefile.am
+++ b/src/gnsrecord/Makefile.am
@@ -7,10 +7,6 @@ pkgcfgdir= $(pkgdatadir)/config.d/
7 7
8libexecdir= $(pkglibdir)/libexec/ 8libexecdir= $(pkglibdir)/libexec/
9 9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
12endif
13
14if USE_COVERAGE 10if USE_COVERAGE
15 AM_CFLAGS = --coverage -O0 11 AM_CFLAGS = --coverage -O0
16 XLIBS = -lgcov 12 XLIBS = -lgcov
diff --git a/src/hello/Makefile.am b/src/hello/Makefile.am
index 00357f9e1..7cb71cdce 100644
--- a/src/hello/Makefile.am
+++ b/src/hello/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 9c87ec2c0..39d423506 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -3,10 +3,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
5 5
6if MINGW
7 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
8endif
9
10if USE_COVERAGE 6if USE_COVERAGE
11 AM_CFLAGS = --coverage -O0 7 AM_CFLAGS = --coverage -O0
12 XLIB = -lgcov 8 XLIB = -lgcov
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 775257768..d5c097341 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -3,10 +3,6 @@ SUBDIRS = .
3 3
4gnunetincludedir = $(includedir)/gnunet 4gnunetincludedir = $(includedir)/gnunet
5 5
6if MINGW
7 WINPROC = winproc.h
8endif
9
10EXTRA_DIST = \ 6EXTRA_DIST = \
11 gauger.h \ 7 gauger.h \
12 block_fs.h \ 8 block_fs.h \
@@ -15,7 +11,7 @@ EXTRA_DIST = \
15 11
16if TALER_ONLY 12if TALER_ONLY
17gnunetinclude_HEADERS = \ 13gnunetinclude_HEADERS = \
18 platform.h plibc.h $(WINPROC) gettext.h \ 14 platform.h gettext.h \
19 gnunet_common.h \ 15 gnunet_common.h \
20 gnunet_container_lib.h \ 16 gnunet_container_lib.h \
21 gnunet_crypto_lib.h \ 17 gnunet_crypto_lib.h \
@@ -25,7 +21,7 @@ gnunetinclude_HEADERS = \
25else 21else
26 22
27gnunetinclude_HEADERS = \ 23gnunetinclude_HEADERS = \
28 platform.h $(WINPROC) gettext.h \ 24 platform.h gettext.h \
29 compat.h \ 25 compat.h \
30 gnunet_applications.h \ 26 gnunet_applications.h \
31 gnunet_arm_service.h \ 27 gnunet_arm_service.h \
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index afaf3a4de..555a98eb5 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -42,9 +42,6 @@
42#if HAVE_NETINET_IN_H 42#if HAVE_NETINET_IN_H
43#include <netinet/in.h> 43#include <netinet/in.h>
44#endif 44#endif
45#ifdef MINGW
46#include "winproc.h"
47#endif
48#ifdef HAVE_STDINT_H 45#ifdef HAVE_STDINT_H
49#include <stdint.h> 46#include <stdint.h>
50#endif 47#endif
@@ -189,11 +186,7 @@ extern "C" {
189/** 186/**
190 * gcc-ism to get gcc bitfield layout when compiling with -mms-bitfields 187 * gcc-ism to get gcc bitfield layout when compiling with -mms-bitfields
191 */ 188 */
192#if MINGW
193#define GNUNET_GCC_STRUCT_LAYOUT __attribute__ ((gcc_struct))
194#else
195#define GNUNET_GCC_STRUCT_LAYOUT 189#define GNUNET_GCC_STRUCT_LAYOUT
196#endif
197 190
198/** 191/**
199 * gcc-ism to force alignment; we use this to align char-arrays 192 * gcc-ism to force alignment; we use this to align char-arrays
@@ -216,28 +209,6 @@ extern "C" {
216 */ 209 */
217#define GNUNET_NORETURN __attribute__ ((noreturn)) 210#define GNUNET_NORETURN __attribute__ ((noreturn))
218 211
219#if MINGW
220#if __GNUC__ > 3
221/**
222 * gcc 4.x-ism to pack structures even on W32 (to be used before structs);
223 * Using this would cause structs to be unaligned on the stack on Sparc,
224 * so we *only* use this on W32 (see #670578 from Debian); fortunately,
225 * W32 doesn't run on sparc anyway.
226 */
227#define GNUNET_NETWORK_STRUCT_BEGIN _Pragma("pack(push)") _Pragma ("pack(1)")
228
229/**
230 * gcc 4.x-ism to pack structures even on W32 (to be used after structs)
231 * Using this would cause structs to be unaligned on the stack on Sparc,
232 * so we *only* use this on W32 (see #670578 from Debian); fortunately,
233 * W32 doesn't run on sparc anyway.
234 */
235#define GNUNET_NETWORK_STRUCT_END _Pragma("pack(pop)")
236
237#else
238#error gcc 4.x or higher required on W32 systems
239#endif
240#else
241/** 212/**
242 * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32 213 * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32
243 */ 214 */
@@ -247,7 +218,6 @@ extern "C" {
247 * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32; 218 * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;
248 */ 219 */
249#define GNUNET_NETWORK_STRUCT_END 220#define GNUNET_NETWORK_STRUCT_END
250#endif
251 221
252/* ************************ super-general types *********************** */ 222/* ************************ super-general types *********************** */
253 223
diff --git a/src/include/tap-windows.h b/src/include/tap-windows.h
deleted file mode 100644
index 37f4129c0..000000000
--- a/src/include/tap-windows.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2 * TAP-Windows -- A kernel driver to provide virtual tap
3 * device functionality on Windows.
4 *
5 * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
6 *
7 * This source code is Copyright Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
8 * and is released under the GPL version 2 (see below).
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24/**
25 * @file
26 * TAP32 virtual network driver defines
27 *
28 * @attention This file is part of openvpn and for kept
29 * as a separate file to allow easier upgrading.
30 */
31#ifndef __TAP_WIN_H
32#define __TAP_WIN_H
33
34/*
35 * =============
36 * TAP IOCTLs
37 * =============
38 */
39
40#define TAP_WIN_CONTROL_CODE(request, method) \
41 CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
42
43/* Present in 8.1 */
44
45#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE(1, METHOD_BUFFERED)
46#define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE(2, METHOD_BUFFERED)
47#define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE(3, METHOD_BUFFERED)
48#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE(4, METHOD_BUFFERED)
49#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE(5, METHOD_BUFFERED)
50#define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE(6, METHOD_BUFFERED)
51#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE(7, METHOD_BUFFERED)
52#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE(8, METHOD_BUFFERED)
53#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE(9, METHOD_BUFFERED)
54
55/* Added in 8.2 */
56
57/* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */
58#define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE(10, METHOD_BUFFERED)
59
60/*
61 * =================
62 * Registry keys
63 * =================
64 */
65
66#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
67
68#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
69
70/*
71 * ======================
72 * Filesystem prefixes
73 * ======================
74 */
75
76#define USERMODEDEVICEDIR "\\\\.\\Global\\"
77#define SYSDEVICEDIR "\\Device\\"
78#define USERDEVICEDIR "\\DosDevices\\Global\\"
79#define TAP_WIN_SUFFIX ".tap"
80
81#endif
diff --git a/src/include/winproc.h b/src/include/winproc.h
deleted file mode 100644
index 139f07e61..000000000
--- a/src/include/winproc.h
+++ /dev/null
@@ -1,235 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author Nils Durner
23 *
24 * @file
25 * Definitions for MS Windows
26 */
27
28#ifndef _WINPROC_H
29#define _WINPROC_H
30
31#include <io.h>
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/timeb.h>
36#include <time.h>
37#include <dirent.h>
38#ifndef FD_SETSIZE
39#define FD_SETSIZE 1024
40#endif
41#include <winsock2.h>
42#include <ws2tcpip.h>
43#include <windows.h>
44#include <winerror.h>
45#include <iphlpapi.h>
46#include <shlobj.h>
47#include <objbase.h>
48#include <sys/param.h> /* #define BYTE_ORDER */
49#include <ntsecapi.h>
50#include <lm.h>
51#include <aclapi.h>
52
53
54#ifdef __cplusplus
55extern "C"
56{
57#endif
58
59#ifndef MAX_NAME_LENGTH
60#define MAX_NAME_LENGTH 25
61#endif
62
63typedef DWORD WINAPI (*TNtQuerySystemInformation) (int, PVOID, ULONG, PULONG);
64typedef DWORD WINAPI (*TGetIfEntry) (PMIB_IFROW pIfRow);
65typedef DWORD WINAPI (*TGetIpAddrTable) (PMIB_IPADDRTABLE pIpAddrTable,
66 PULONG pdwSize, BOOL bOrder);
67typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize,
68 BOOL bOrder);
69typedef DWORD WINAPI (*TGetBestInterfaceEx) (struct sockaddr *, PDWORD);
70/* TODO: Explicitly import -A variants (i.e. TCreateHardLinkA) or -W
71 * variants (TCreateHardLinkW), etc.
72 */
73typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName,
74 LPCTSTR lpExistingFileName,
75 LPSECURITY_ATTRIBUTES
76 lpSecurityAttributes);
77typedef SC_HANDLE WINAPI (*TOpenSCManager) (LPCTSTR lpMachineName,
78 LPCTSTR lpDatabaseName,
79 DWORD dwDesiredAccess);
80typedef SC_HANDLE WINAPI (*TCreateService) (SC_HANDLE hSCManager,
81 LPCTSTR lpServiceName,
82 LPCTSTR lpDisplayName,
83 DWORD dwDesiredAccess,
84 DWORD dwServiceType,
85 DWORD dwStartType,
86 DWORD dwErrorControl,
87 LPCTSTR lpBinaryPathName,
88 LPCTSTR lpLoadOrderGroup,
89 LPDWORD lpdwTagId,
90 LPCTSTR lpDependencies,
91 LPCTSTR lpServiceStartName,
92 LPCTSTR lpPassword);
93typedef BOOL WINAPI (*TCloseServiceHandle) (SC_HANDLE hSCObject);
94typedef BOOL WINAPI (*TDeleteService) (SC_HANDLE hService);
95typedef SERVICE_STATUS_HANDLE WINAPI (*TRegisterServiceCtrlHandler) (LPCTSTR
96 lpServiceName,
97 LPHANDLER_FUNCTION
98 lpHandlerProc);
99typedef BOOL WINAPI (*TSetServiceStatus) (SERVICE_STATUS_HANDLE
100 hServiceStatus,
101 LPSERVICE_STATUS lpServiceStatus);
102typedef BOOL WINAPI (*TStartServiceCtrlDispatcher) (const
103 LPSERVICE_TABLE_ENTRY
104 lpServiceTable);
105typedef BOOL WINAPI (*TControlService) (SC_HANDLE hService, DWORD dwControl,
106 LPSERVICE_STATUS lpServiceStatus);
107typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager,
108 LPCTSTR lpServiceName,
109 DWORD dwDesiredAccess);
110typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo,
111 PULONG pOutBufLen);
112typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD);
113typedef NET_API_STATUS WINAPI (*TNetUserSetInfo) (LPCWSTR servername,
114 LPCWSTR username,
115 DWORD level, LPBYTE buf,
116 LPDWORD param_err);
117typedef NTSTATUS NTAPI (*TLsaOpenPolicy) (PLSA_UNICODE_STRING,
118 PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK,
119 PLSA_HANDLE);
120typedef NTSTATUS NTAPI (*TLsaAddAccountRights) (LSA_HANDLE, PSID,
121 PLSA_UNICODE_STRING, ULONG);
122typedef NTSTATUS NTAPI (*TLsaRemoveAccountRights) (LSA_HANDLE, PSID, BOOLEAN,
123 PLSA_UNICODE_STRING,
124 ULONG);
125typedef NTSTATUS NTAPI (*TLsaClose) (LSA_HANDLE);
126typedef BOOL WINAPI (*TLookupAccountName) (LPCTSTR lpSystemName,
127 LPCTSTR lpAccountName, PSID Sid,
128 LPDWORD cbSid,
129 LPTSTR ReferencedDomainName,
130 LPDWORD cchReferencedDomainName,
131 PSID_NAME_USE peUse);
132
133typedef BOOL WINAPI (*TGetFileSecurity) (LPCTSTR lpFileName,
134 SECURITY_INFORMATION
135 RequestedInformation,
136 PSECURITY_DESCRIPTOR
137 pSecurityDescriptor, DWORD nLength,
138 LPDWORD lpnLengthNeeded);
139typedef BOOL WINAPI (*TInitializeSecurityDescriptor) (PSECURITY_DESCRIPTOR
140 pSecurityDescriptor,
141 DWORD dwRevision);
142typedef BOOL WINAPI (*TGetSecurityDescriptorDacl) (PSECURITY_DESCRIPTOR
143 pSecurityDescriptor,
144 LPBOOL lpbDaclPresent,
145 PACL * pDacl,
146 LPBOOL lpbDaclDefaulted);
147typedef BOOL WINAPI (*TGetAclInformation) (PACL pAcl, LPVOID pAclInformation,
148 DWORD nAclInformationLength,
149 ACL_INFORMATION_CLASS
150 dwAclInformationClass);
151typedef BOOL WINAPI (*TInitializeAcl) (PACL pAcl, DWORD nAclLength,
152 DWORD dwAclRevision);
153typedef BOOL WINAPI (*TGetAce) (PACL pAcl, DWORD dwAceIndex, LPVOID * pAce);
154typedef BOOL WINAPI (*TEqualSid) (PSID pSid1, PSID pSid2);
155typedef BOOL WINAPI (*TAddAce) (PACL pAcl, DWORD dwAceRevision,
156 DWORD dwStartingAceIndex, LPVOID pAceList,
157 DWORD nAceListLength);
158typedef BOOL WINAPI (*TAddAccessAllowedAce) (PACL pAcl, DWORD dwAceRevision,
159 DWORD AccessMask, PSID pSid);
160typedef BOOL WINAPI (*TSetNamedSecurityInfo) (LPTSTR pObjectName,
161 SE_OBJECT_TYPE ObjectType,
162 SECURITY_INFORMATION
163 SecurityInfo, PSID psidOwner,
164 PSID psidGroup, PACL pDacl,
165 PACL pSacl);
166
167extern TGetBestInterfaceEx GNGetBestInterfaceEx;
168extern TNtQuerySystemInformation GNNtQuerySystemInformation;
169extern TGetIfEntry GNGetIfEntry;
170extern TGetIpAddrTable GNGetIpAddrTable;
171extern TGetIfTable GNGetIfTable;
172extern TCreateHardLink GNCreateHardLink;
173extern TOpenSCManager GNOpenSCManager;
174extern TCreateService GNCreateService;
175extern TCloseServiceHandle GNCloseServiceHandle;
176extern TDeleteService GNDeleteService;
177extern TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler;
178extern TSetServiceStatus GNSetServiceStatus;
179extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
180extern TControlService GNControlService;
181extern TOpenService GNOpenService;
182extern TGetAdaptersInfo GNGetAdaptersInfo;
183extern TNetUserAdd GNNetUserAdd;
184extern TNetUserSetInfo GNNetUserSetInfo;
185extern TLsaOpenPolicy GNLsaOpenPolicy;
186extern TLsaAddAccountRights GNLsaAddAccountRights;
187extern TLsaRemoveAccountRights GNLsaRemoveAccountRights;
188extern TLsaClose GNLsaClose;
189extern TLookupAccountName GNLookupAccountName;
190extern TGetFileSecurity GNGetFileSecurity;
191extern TInitializeSecurityDescriptor GNInitializeSecurityDescriptor;
192extern TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl;
193extern TGetAclInformation GNGetAclInformation;
194extern TInitializeAcl GNInitializeAcl;
195extern TGetAce GNGetAce;
196extern TEqualSid GNEqualSid;
197extern TAddAce GNAddAce;
198extern TAddAccessAllowedAce GNAddAccessAllowedAce;
199extern TSetNamedSecurityInfo GNSetNamedSecurityInfo;
200
201
202BOOL CreateShortcut(const char *pszSrc, const char *pszDest);
203BOOL DereferenceShortcut(char *pszShortcut);
204long QueryRegistry(HKEY hMainKey, const char *pszKey, const char *pszSubKey,
205 char *pszBuffer, long *pdLength);
206int ListNICs(void (*callback)(void *, const char *, int), void *cls);
207BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,
208 DWORD dwAccessMask);
209char *winErrorStr(const char *prefix, int dwErr);
210void EnumNICs(PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable);
211
212#define ENUMNICS3_MASK_OK 0x01
213#define ENUMNICS3_BCAST_OK 0x02
214
215struct EnumNICs3_results {
216 unsigned char flags;
217 int is_default;
218 char pretty_name[1001];
219 size_t addr_size;
220 SOCKADDR_STORAGE address;
221 SOCKADDR_STORAGE mask;
222 SOCKADDR_STORAGE broadcast;
223};
224
225int EnumNICs3(struct EnumNICs3_results **, int *EnumNICs3_results_count);
226void EnumNICs3_free(struct EnumNICs3_results *);
227int GNInitWinEnv();
228void GNShutdownWinEnv();
229
230BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode, DWORD dwTimeout);
231#ifdef __cplusplus
232}
233#endif
234
235#endif
diff --git a/src/integration-tests/Makefile.am b/src/integration-tests/Makefile.am
index 26dd4f92d..8b50def4d 100644
--- a/src/integration-tests/Makefile.am
+++ b/src/integration-tests/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/my/Makefile.am b/src/my/Makefile.am
index cead9a8b4..51e20e6bf 100644
--- a/src/my/Makefile.am
+++ b/src/my/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/mysql/Makefile.am b/src/mysql/Makefile.am
index 889562d60..3bfb929cd 100644
--- a/src/mysql/Makefile.am
+++ b/src/mysql/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/namecache/Makefile.am b/src/namecache/Makefile.am
index c62ca6a2b..8abae68a4 100644
--- a/src/namecache/Makefile.am
+++ b/src/namecache/Makefile.am
@@ -10,11 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 namecache.conf 11 namecache.conf
12 12
13
14if MINGW
15 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
16endif
17
18if USE_COVERAGE 13if USE_COVERAGE
19 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
20 XLIBS = -lgcov 15 XLIBS = -lgcov
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index ad99a3f0b..b9fa83103 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -10,11 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 namestore.conf 11 namestore.conf
12 12
13
14if MINGW
15 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
16endif
17
18if USE_COVERAGE 13if USE_COVERAGE
19 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
20 XLIBS = -lgcov 15 XLIBS = -lgcov
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index f0d5639a1..db104d194 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -1,13 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6 NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client
7 NATSERVER = gnunet-helper-nat-server-windows.c
8 NATCLIENT = gnunet-helper-nat-client-windows.c
9endif
10
11libexecdir= $(pkglibdir)/libexec/ 4libexecdir= $(pkglibdir)/libexec/
12 5
13pkgcfgdir= $(pkgdatadir)/config.d/ 6pkgcfgdir= $(pkgdatadir)/config.d/
@@ -45,7 +38,7 @@ gnunet_helper_nat_server_SOURCES = \
45 $(NATSERVER) 38 $(NATSERVER)
46 39
47gnunet_helper_nat_client_SOURCES = \ 40gnunet_helper_nat_client_SOURCES = \
48 $(NATCLIENT) 41 $(NATCLIENT)
49 42
50 43
51gnunet_nat_SOURCES = \ 44gnunet_nat_SOURCES = \
diff --git a/src/nat/gnunet-helper-nat-client-windows.c b/src/nat/gnunet-helper-nat-client-windows.c
deleted file mode 100644
index 1be31ae42..000000000
--- a/src/nat/gnunet-helper-nat-client-windows.c
+++ /dev/null
@@ -1,529 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/nat/gnunet-helper-nat-client-windows.c
23 * @brief Tool to help bypass NATs using ICMP method; must run as
24 * administrator on W32
25 * This code is for W32.
26 * @author Nathan Evans
27 *
28 * This program will send ONE ICMP message using RAW sockets
29 * to the IP address specified as the second argument. Since
30 * it uses RAW sockets, it must be installed SUID or run as 'root'.
31 * In order to keep the security risk of the resulting SUID binary
32 * minimal, the program ONLY opens the RAW socket with root
33 * privileges, then drops them and only then starts to process
34 * command line arguments. The code also does not link against
35 * any shared libraries (except libc) and is strictly minimal
36 * (except for checking for errors). The following list of people
37 * have reviewed this code and considered it safe since the last
38 * modification (if you reviewed it, please have your name added
39 * to the list):
40 *
41 * - Christian Grothoff
42 * - Nathan Evans
43 */
44#define _GNU_SOURCE
45/* Instead of including gnunet_common.h */
46#define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
47
48#define FD_SETSIZE 1024
49#include <winsock2.h>
50#include <ws2tcpip.h>
51#include <sys/time.h>
52#include <sys/types.h>
53#include <unistd.h>
54#include <stdio.h>
55#include <string.h>
56#include <errno.h>
57#include <stdlib.h>
58#include <stdint.h>
59#include <time.h>
60
61
62#define ICMP_ECHO 8
63#define IPDEFTTL 64
64#define ICMP_TIME_EXCEEDED 11
65
66/**
67 * Must match IP given in the server.
68 */
69#define DUMMY_IP "192.0.2.86"
70
71#define NAT_TRAV_PORT 22225
72
73/**
74 * IPv4 header.
75 */
76struct ip_header {
77 /**
78 * Version (4 bits) + Internet header length (4 bits)
79 */
80 uint8_t vers_ihl;
81
82 /**
83 * Type of service
84 */
85 uint8_t tos;
86
87 /**
88 * Total length
89 */
90 uint16_t pkt_len;
91
92 /**
93 * Identification
94 */
95 uint16_t id;
96
97 /**
98 * Flags (3 bits) + Fragment offset (13 bits)
99 */
100 uint16_t flags_frag_offset;
101
102 /**
103 * Time to live
104 */
105 uint8_t ttl;
106
107 /**
108 * Protocol
109 */
110 uint8_t proto;
111
112 /**
113 * Header checksum
114 */
115 uint16_t checksum;
116
117 /**
118 * Source address
119 */
120 uint32_t src_ip;
121
122 /**
123 * Destination address
124 */
125 uint32_t dst_ip;
126};
127
128
129/**
130 * Format of ICMP packet.
131 */
132struct icmp_ttl_exceeded_header {
133 uint8_t type;
134
135 uint8_t code;
136
137 uint16_t checksum;
138
139 uint32_t unused;
140
141 /* followed by original payload */
142};
143
144struct icmp_echo_header {
145 uint8_t type;
146
147 uint8_t code;
148
149 uint16_t checksum;
150
151 uint32_t reserved;
152};
153
154/**
155 * Beginning of UDP packet.
156 */
157struct udp_header {
158 uint16_t src_port;
159
160 uint16_t dst_port;
161
162 uint16_t length;
163
164 uint16_t crc;
165};
166
167/**
168 * Will this binary be run in permissions testing mode?
169 */
170static boolean privilege_testing = FALSE;
171
172/**
173 * Socket we use to send our ICMP packets.
174 */
175static _win_socket rawsock;
176
177/**
178 * Target "dummy" address.
179 */
180static struct in_addr dummy;
181
182/**
183 * Port we are listening on (communicated to the server).
184 */
185static uint16_t port;
186
187
188
189/**
190 * Convert IPv4 address from text to binary form.
191 *
192 * @param af address family
193 * @param cp the address to print
194 * @param buf where to write the address result
195 * @return 1 on success
196 */
197static int
198inet_pton(int af, const char *cp, struct in_addr *buf)
199{
200 buf->s_addr = inet_addr(cp);
201 if (buf->s_addr == INADDR_NONE)
202 {
203 fprintf(stderr, "Error %d handling address %s", WSAGetLastError(), cp);
204 return 0;
205 }
206 return 1;
207}
208
209
210/**
211 * CRC-16 for IP/ICMP headers.
212 *
213 * @param data what to calculate the CRC over
214 * @param bytes number of bytes in data (must be multiple of 2)
215 * @return the CRC 16.
216 */
217static uint16_t
218calc_checksum(const uint16_t * data, unsigned int bytes)
219{
220 uint32_t sum;
221 unsigned int i;
222
223 sum = 0;
224 for (i = 0; i < bytes / 2; i++)
225 sum += data[i];
226 sum = (sum & 0xffff) + (sum >> 16);
227 sum = htons(0xffff - sum);
228 return sum;
229}
230
231
232/**
233 * Send an ICMP message to the target.
234 *
235 * @param my_ip source address
236 * @param other target address
237 */
238static void
239send_icmp_udp(const struct in_addr *my_ip, const struct in_addr *other)
240{
241 char packet[sizeof(struct ip_header) * 2 +
242 sizeof(struct icmp_ttl_exceeded_header) +
243 sizeof(struct udp_header)];
244 struct ip_header ip_pkt;
245 struct icmp_ttl_exceeded_header icmp_pkt;
246 struct udp_header udp_pkt;
247 struct sockaddr_in dst;
248 size_t off;
249 int err;
250
251 /* ip header: send to (known) ip address */
252 off = 0;
253 ip_pkt.vers_ihl = 0x45;
254 ip_pkt.tos = 0;
255 ip_pkt.pkt_len = htons(sizeof(packet));
256 ip_pkt.id = htons(256);
257 ip_pkt.flags_frag_offset = 0;
258 ip_pkt.ttl = 128;
259 ip_pkt.proto = IPPROTO_ICMP;
260 ip_pkt.checksum = 0;
261 ip_pkt.src_ip = my_ip->s_addr;
262 ip_pkt.dst_ip = other->s_addr;
263 ip_pkt.checksum =
264 htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header)));
265 GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header));
266 off += sizeof(struct ip_header);
267
268 icmp_pkt.type = ICMP_TIME_EXCEEDED;
269 icmp_pkt.code = 0;
270 icmp_pkt.checksum = 0;
271 icmp_pkt.unused = 0;
272 GNUNET_memcpy(&packet[off], &icmp_pkt, sizeof(struct icmp_ttl_exceeded_header));
273 off += sizeof(struct icmp_ttl_exceeded_header);
274
275 /* ip header of the presumably 'lost' udp packet */
276 ip_pkt.vers_ihl = 0x45;
277 ip_pkt.tos = 0;
278 ip_pkt.pkt_len =
279 htons(sizeof(struct ip_header) + sizeof(struct udp_header));
280 ip_pkt.id = htons(0);
281 ip_pkt.flags_frag_offset = 0;
282 ip_pkt.ttl = 128;
283 ip_pkt.proto = IPPROTO_UDP;
284 ip_pkt.checksum = 0;
285 ip_pkt.src_ip = other->s_addr;
286 ip_pkt.dst_ip = dummy.s_addr;
287 ip_pkt.checksum =
288 htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header)));
289 GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header));
290 off += sizeof(struct ip_header);
291
292 /* build UDP header */
293 udp_pkt.src_port = htons(NAT_TRAV_PORT);
294 udp_pkt.dst_port = htons(NAT_TRAV_PORT);
295 udp_pkt.length = htons(port);
296 udp_pkt.crc = 0;
297 GNUNET_memcpy(&packet[off], &udp_pkt, sizeof(struct udp_header));
298 off += sizeof(struct udp_header);
299
300 /* no go back to calculate ICMP packet checksum */
301 icmp_pkt.checksum =
302 htons(calc_checksum
303 ((uint16_t *)&packet[off],
304 sizeof(struct icmp_ttl_exceeded_header) +
305 sizeof(struct ip_header) + sizeof(struct udp_header)));
306 GNUNET_memcpy(&packet[sizeof(struct ip_header)], &icmp_pkt,
307 sizeof(struct icmp_ttl_exceeded_header));
308
309 memset(&dst, 0, sizeof(dst));
310 dst.sin_family = AF_INET;
311 dst.sin_addr = *other;
312 err =
313 sendto(rawsock, packet, sizeof(packet), 0, (struct sockaddr *)&dst,
314 sizeof(dst));
315 if (err < 0)
316 {
317 fprintf(stderr, "sendto failed: %s\n", strerror(errno));
318 }
319 else if (sizeof(packet) != (size_t)err)
320 {
321 fprintf(stderr, "Error: partial send of ICMP message\n");
322 }
323}
324
325
326/**
327 * Send an ICMP message to the target.
328 *
329 * @param my_ip source address
330 * @param other target address
331 */
332static void
333send_icmp(const struct in_addr *my_ip, const struct in_addr *other)
334{
335 struct ip_header ip_pkt;
336 struct icmp_ttl_exceeded_header icmp_ttl;
337 struct icmp_echo_header icmp_echo;
338 struct sockaddr_in dst;
339 char packet[sizeof(struct ip_header) * 2 +
340 sizeof(struct icmp_ttl_exceeded_header) +
341 sizeof(struct icmp_echo_header)];
342 size_t off;
343 int err;
344
345 /* ip header: send to (known) ip address */
346 off = 0;
347 ip_pkt.vers_ihl = 0x45;
348 ip_pkt.tos = 0;
349 ip_pkt.pkt_len = htons(sizeof(packet));
350 ip_pkt.id = htons(256);
351 ip_pkt.flags_frag_offset = 0;
352 ip_pkt.ttl = IPDEFTTL;
353 ip_pkt.proto = IPPROTO_ICMP;
354 ip_pkt.checksum = 0;
355 ip_pkt.src_ip = my_ip->s_addr;
356 ip_pkt.dst_ip = other->s_addr;
357 ip_pkt.checksum =
358 htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header)));
359 GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header));
360 off += sizeof(ip_pkt);
361
362 /* icmp reply: time exceeded */
363 icmp_ttl.type = ICMP_TIME_EXCEEDED;
364 icmp_ttl.code = 0;
365 icmp_ttl.checksum = 0;
366 icmp_ttl.unused = 0;
367 GNUNET_memcpy(&packet[off], &icmp_ttl, sizeof(struct icmp_ttl_exceeded_header));
368 off += sizeof(struct icmp_ttl_exceeded_header);
369
370 /* ip header of the presumably 'lost' udp packet */
371 ip_pkt.vers_ihl = 0x45;
372 ip_pkt.tos = 0;
373 ip_pkt.pkt_len =
374 htons(sizeof(struct ip_header) + sizeof(struct icmp_echo_header));
375 ip_pkt.id = htons(256);
376 ip_pkt.flags_frag_offset = 0;
377 ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */
378 ip_pkt.proto = IPPROTO_ICMP;
379 ip_pkt.src_ip = other->s_addr;
380 ip_pkt.dst_ip = dummy.s_addr;
381 ip_pkt.checksum = 0;
382 ip_pkt.checksum =
383 htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header)));
384 GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header));
385 off += sizeof(struct ip_header);
386
387 icmp_echo.type = ICMP_ECHO;
388 icmp_echo.code = 0;
389 icmp_echo.reserved = htonl(port);
390 icmp_echo.checksum = 0;
391 icmp_echo.checksum =
392 htons(calc_checksum
393 ((uint16_t *)&icmp_echo, sizeof(struct icmp_echo_header)));
394 GNUNET_memcpy(&packet[off], &icmp_echo, sizeof(struct icmp_echo_header));
395
396 /* no go back to calculate ICMP packet checksum */
397 off = sizeof(struct ip_header);
398 icmp_ttl.checksum =
399 htons(calc_checksum
400 ((uint16_t *)&packet[off],
401 sizeof(struct icmp_ttl_exceeded_header) +
402 sizeof(struct ip_header) + sizeof(struct icmp_echo_header)));
403 GNUNET_memcpy(&packet[off], &icmp_ttl, sizeof(struct icmp_ttl_exceeded_header));
404
405 memset(&dst, 0, sizeof(dst));
406 dst.sin_family = AF_INET;
407 dst.sin_addr = *other;
408
409 err =
410 sendto(rawsock, packet, sizeof(packet), 0, (struct sockaddr *)&dst,
411 sizeof(dst));
412
413 if (err < 0)
414 {
415 fprintf(stderr, "sendto failed: %s\n", strerror(errno));
416 }
417 else if (sizeof(packet) != (size_t)err)
418 {
419 fprintf(stderr, "Error: partial send of ICMP message\n");
420 }
421}
422
423
424/**
425 * Create an ICMP raw socket.
426 *
427 * @return INVALID_SOCKET on error
428 */
429static _win_socket
430make_raw_socket()
431{
432 DWORD bOptVal = TRUE;
433 int bOptLen = sizeof(bOptVal);
434 _win_socket ret;
435
436 ret = _win_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
437 if (INVALID_SOCKET == ret)
438 {
439 fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno));
440 return INVALID_SOCKET;
441 }
442 if (0 !=
443 _win_setsockopt(ret, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, bOptLen))
444 {
445 fprintf(stderr, "Error setting SO_BROADCAST to ON: %s\n",
446 strerror(errno));
447 closesocket(rawsock);
448 return INVALID_SOCKET;
449 }
450
451 if (0 != _win_setsockopt(ret, IPPROTO_IP, IP_HDRINCL, (char *)&bOptVal, bOptLen))
452 {
453 fprintf(stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror(errno));
454 closesocket(rawsock);
455 return INVALID_SOCKET;
456 }
457 return ret;
458}
459
460
461int
462main(int argc, char *const *argv)
463{
464 struct in_addr external;
465 struct in_addr target;
466 WSADATA wsaData;
467 unsigned int p;
468
469 if (argc > 1 && 0 != strcmp(argv[1], "-d"))
470 {
471 privilege_testing = TRUE;
472 fprintf(stderr,
473 "%s",
474 "DEBUG: Running binary in privilege testing mode.");
475 argv++;
476 argc--;
477 }
478
479 if (argc != 4)
480 {
481 fprintf(stderr,
482 "%s",
483 "This program must be started with our IP, the targets external IP, and our port as arguments.\n");
484 return 1;
485 }
486 if ((1 != inet_pton(AF_INET, argv[1], &external)) ||
487 (1 != inet_pton(AF_INET, argv[2], &target)))
488 {
489 fprintf(stderr,
490 "Error parsing IPv4 address: %s\n",
491 strerror(errno));
492 return 1;
493 }
494 if ((1 != sscanf(argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p))
495 {
496 fprintf(stderr,
497 "Error parsing port value `%s'\n",
498 argv[3]);
499 return 1;
500 }
501 port = (uint16_t)p;
502
503 if (0 != WSAStartup(MAKEWORD(2, 1), &wsaData))
504 {
505 fprintf(stderr,
506 "%s",
507 "Failed to find Winsock 2.1 or better.\n");
508 return 2;
509 }
510 if (1 != inet_pton(AF_INET, DUMMY_IP, &dummy))
511 {
512 fprintf(stderr,
513 "%s",
514 "Internal error converting dummy IP to binary.\n");
515 return 2;
516 }
517 if (-1 == (rawsock = make_raw_socket()))
518 return 3;
519 if (!privilege_testing)
520 {
521 send_icmp(&external, &target);
522 send_icmp_udp(&external, &target);
523 }
524 closesocket(rawsock);
525 WSACleanup();
526 return 0;
527}
528
529/* end of gnunet-helper-nat-client-windows.c */
diff --git a/src/nat/gnunet-helper-nat-server-windows.c b/src/nat/gnunet-helper-nat-server-windows.c
deleted file mode 100644
index 688dde165..000000000
--- a/src/nat/gnunet-helper-nat-server-windows.c
+++ /dev/null
@@ -1,614 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/nat/gnunet-helper-nat-server-windows.c
23 * @brief Windows tool to help bypass NATs using ICMP method
24 * This code will work under W32 only
25 * @author Christian Grothoff
26 *
27 * This program will send ONE ICMP message every 500 ms RAW sockets
28 * to a DUMMY IP address and also listens for ICMP replies. Since
29 * it uses RAW sockets, it must be run as an administrative user.
30 * In order to keep the security risk of the resulting binary
31 * minimal, the program ONLY opens the two RAW sockets with administrative
32 * privileges, then drops them and only then starts to process
33 * command line arguments. The code also does not link against
34 * any shared libraries (except libc) and is strictly minimal
35 * (except for checking for errors). The following list of people
36 * have reviewed this code and considered it safe since the last
37 * modification (if you reviewed it, please have your name added
38 * to the list):
39 *
40 * - Nathan Evans
41 * - Christian Grothoff
42 */
43#define _GNU_SOURCE
44/* Instead of including gnunet_common.h */
45#define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
46
47#define FD_SETSIZE 1024
48#include <winsock2.h>
49#include <ws2tcpip.h>
50#include <sys/time.h>
51#include <sys/types.h>
52#include <unistd.h>
53#include <stdio.h>
54#include <string.h>
55#include <errno.h>
56#include <stdlib.h>
57#include <stdint.h>
58#include <time.h>
59
60/**
61 * Should we print some debug output?
62 */
63#define VERBOSE 0
64
65/**
66 * Must match IP given in the client.
67 */
68#define DUMMY_IP "192.0.2.86"
69
70/**
71 * Default Port
72 */
73#define NAT_TRAV_PORT 22225
74
75/**
76 * Must match packet ID used by gnunet-helper-nat-client.c
77 */
78#define PACKET_ID 256
79
80/**
81 * TTL to use for our outgoing messages.
82 */
83#define IPDEFTTL 64
84
85#define ICMP_ECHO 8
86
87#define ICMP_TIME_EXCEEDED 11
88
89/**
90 * How often do we send our ICMP messages to receive replies?
91 */
92#define ICMP_SEND_FREQUENCY_MS 500
93
94/**
95 * IPv4 header.
96 */
97struct ip_header {
98 /**
99 * Version (4 bits) + Internet header length (4 bits)
100 */
101 uint8_t vers_ihl;
102
103 /**
104 * Type of service
105 */
106 uint8_t tos;
107
108 /**
109 * Total length
110 */
111 uint16_t pkt_len;
112
113 /**
114 * Identification
115 */
116 uint16_t id;
117
118 /**
119 * Flags (3 bits) + Fragment offset (13 bits)
120 */
121 uint16_t flags_frag_offset;
122
123 /**
124 * Time to live
125 */
126 uint8_t ttl;
127
128 /**
129 * Protocol
130 */
131 uint8_t proto;
132
133 /**
134 * Header checksum
135 */
136 uint16_t checksum;
137
138 /**
139 * Source address
140 */
141 uint32_t src_ip;
142
143 /**
144 * Destination address
145 */
146 uint32_t dst_ip;
147};
148
149/**
150 * Format of ICMP packet.
151 */
152struct icmp_ttl_exceeded_header {
153 uint8_t type;
154
155 uint8_t code;
156
157 uint16_t checksum;
158
159 uint32_t unused;
160
161 /* followed by original payload */
162};
163
164struct icmp_echo_header {
165 uint8_t type;
166
167 uint8_t code;
168
169 uint16_t checksum;
170
171 uint32_t reserved;
172};
173
174/**
175 * Beginning of UDP packet.
176 */
177struct udp_header {
178 uint16_t src_port;
179
180 uint16_t dst_port;
181
182 uint16_t length;
183
184 uint16_t crc;
185};
186
187/**
188 * Will this binary be run in permissions testing mode?
189 */
190static boolean privilege_testing = FALSE;
191
192/**
193 * Socket we use to receive "fake" ICMP replies.
194 */
195static _win_socket icmpsock;
196
197/**
198 * Socket we use to send our ICMP requests.
199 */
200static _win_socket rawsock;
201
202/**
203 * Socket we use to send our UDP requests.
204 */
205static _win_socket udpsock;
206
207/**
208 * Target "dummy" address.
209 */
210static struct in_addr dummy;
211
212
213/**
214 * CRC-16 for IP/ICMP headers.
215 *
216 * @param data what to calculate the CRC over
217 * @param bytes number of bytes in data (must be multiple of 2)
218 * @return the CRC 16.
219 */
220static uint16_t
221calc_checksum(const uint16_t * data, unsigned int bytes)
222{
223 uint32_t sum;
224 unsigned int i;
225
226 sum = 0;
227 for (i = 0; i < bytes / 2; i++)
228 sum += data[i];
229 sum = (sum & 0xffff) + (sum >> 16);
230 sum = htons(0xffff - sum);
231 return sum;
232}
233
234
235/**
236 * Convert IPv4 address from text to binary form.
237 *
238 * @param af address family
239 * @param cp the address to print
240 * @param buf where to write the address result
241 * @return 1 on success
242 */
243static int
244inet_pton(int af, const char *cp, struct in_addr *buf)
245{
246 buf->s_addr = inet_addr(cp);
247 if (buf->s_addr == INADDR_NONE)
248 {
249 fprintf(stderr, "Error %d handling address %s", WSAGetLastError(), cp);
250 return 0;
251 }
252 return 1;
253}
254
255
256/**
257 * Send an ICMP message to the dummy IP.
258 *
259 * @param my_ip source address (our ip address)
260 */
261static void
262send_icmp_echo(const struct in_addr *my_ip)
263{
264 char packet[sizeof(struct ip_header) + sizeof(struct icmp_echo_header)];
265 struct icmp_echo_header icmp_echo;
266 struct ip_header ip_pkt;
267 struct sockaddr_in dst;
268 size_t off;
269 int err;
270
271 off = 0;
272 ip_pkt.vers_ihl = 0x45;
273 ip_pkt.tos = 0;
274 ip_pkt.pkt_len = htons(sizeof(packet));
275 ip_pkt.id = htons(PACKET_ID);
276 ip_pkt.flags_frag_offset = 0;
277 ip_pkt.ttl = IPDEFTTL;
278 ip_pkt.proto = IPPROTO_ICMP;
279 ip_pkt.checksum = 0;
280 ip_pkt.src_ip = my_ip->s_addr;
281 ip_pkt.dst_ip = dummy.s_addr;
282 ip_pkt.checksum =
283 htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header)));
284 GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header));
285 off += sizeof(struct ip_header);
286
287 icmp_echo.type = ICMP_ECHO;
288 icmp_echo.code = 0;
289 icmp_echo.reserved = 0;
290 icmp_echo.checksum = 0;
291 icmp_echo.checksum =
292 htons(calc_checksum
293 ((uint16_t *)&icmp_echo, sizeof(struct icmp_echo_header)));
294 GNUNET_memcpy(&packet[off], &icmp_echo, sizeof(struct icmp_echo_header));
295 off += sizeof(struct icmp_echo_header);
296
297 memset(&dst, 0, sizeof(dst));
298 dst.sin_family = AF_INET;
299 dst.sin_addr = dummy;
300 err =
301 sendto(rawsock, packet, off, 0, (struct sockaddr *)&dst, sizeof(dst));
302 if (err < 0)
303 {
304#if VERBOSE
305 fprintf(stderr, "sendto failed: %s\n", strerror(errno));
306#endif
307 }
308 else if (err != off)
309 {
310 fprintf(stderr, "Error: partial send of ICMP message\n");
311 }
312}
313
314
315/**
316 * Send a UDP message to the dummy IP.
317 */
318static void
319send_udp()
320{
321 struct sockaddr_in dst;
322 ssize_t err;
323
324 memset(&dst, 0, sizeof(dst));
325 dst.sin_family = AF_INET;
326 dst.sin_addr = dummy;
327 dst.sin_port = htons(NAT_TRAV_PORT);
328 err = sendto(udpsock, NULL, 0, 0, (struct sockaddr *)&dst, sizeof(dst));
329 if (err < 0)
330 {
331#if VERBOSE
332 fprintf(stderr, "sendto failed: %s\n", strerror(errno));
333#endif
334 }
335 else if (0 != err)
336 {
337 fprintf(stderr, "Error: partial send of ICMP message\n");
338 }
339}
340
341
342/**
343 * We've received an ICMP response. Process it.
344 */
345static void
346process_icmp_response()
347{
348 char buf[65536];
349 ssize_t have;
350 struct in_addr source_ip;
351 struct ip_header ip_pkt;
352 struct icmp_ttl_exceeded_header icmp_ttl;
353 struct icmp_echo_header icmp_echo;
354 struct udp_header udp_pkt;
355 size_t off;
356 uint16_t port;
357 DWORD ssize;
358
359 have = read(icmpsock, buf, sizeof(buf));
360 if (have == -1)
361 {
362 fprintf(stderr, "Error reading raw socket: %s\n", strerror(errno));
363 return;
364 }
365#if VERBOSE
366 fprintf(stderr, "Received message of %u bytes\n", (unsigned int)have);
367#endif
368 if (have <
369 (ssize_t)(sizeof(struct ip_header) +
370 sizeof(struct icmp_ttl_exceeded_header) +
371 sizeof(struct ip_header)))
372 {
373 /* malformed */
374 return;
375 }
376 off = 0;
377 GNUNET_memcpy(&ip_pkt, &buf[off], sizeof(struct ip_header));
378 off += sizeof(struct ip_header);
379 GNUNET_memcpy(&source_ip, &ip_pkt.src_ip, sizeof(source_ip));
380 GNUNET_memcpy(&icmp_ttl, &buf[off], sizeof(struct icmp_ttl_exceeded_header));
381 off += sizeof(struct icmp_ttl_exceeded_header);
382 if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code))
383 {
384 /* different type than what we want */
385 return;
386 }
387 /* skip 2nd IP header */
388 GNUNET_memcpy(&ip_pkt, &buf[off], sizeof(struct ip_header));
389 off += sizeof(struct ip_header);
390
391 switch (ip_pkt.proto)
392 {
393 case IPPROTO_ICMP:
394 if (have !=
395 (sizeof(struct ip_header) * 2 +
396 sizeof(struct icmp_ttl_exceeded_header) +
397 sizeof(struct icmp_echo_header)))
398 {
399 /* malformed */
400 return;
401 }
402 /* grab ICMP ECHO content */
403 GNUNET_memcpy(&icmp_echo, &buf[off], sizeof(struct icmp_echo_header));
404 port = (uint16_t)ntohl(icmp_echo.reserved);
405 break;
406
407 case IPPROTO_UDP:
408 if (have !=
409 (sizeof(struct ip_header) * 2 +
410 sizeof(struct icmp_ttl_exceeded_header) + sizeof(struct udp_header)))
411 {
412 /* malformed */
413 return;
414 }
415 /* grab UDP content */
416 GNUNET_memcpy(&udp_pkt, &buf[off], sizeof(struct udp_header));
417 port = ntohs(udp_pkt.length);
418 break;
419
420 default:
421 /* different type than what we want */
422 return;
423 }
424
425 ssize = sizeof(buf);
426 WSAAddressToString((LPSOCKADDR)&source_ip, sizeof(source_ip), NULL, buf,
427 &ssize);
428 if (port == 0)
429 fprintf(stdout, "%s\n", buf);
430 else
431 fprintf(stdout, "%s:%u\n", buf, (unsigned int)port);
432 fflush(stdout);
433}
434
435
436/**
437 * Create an ICMP raw socket for reading.
438 *
439 * @return INVALID_SOCKET on error
440 */
441static _win_socket
442make_icmp_socket()
443{
444 _win_socket ret;
445
446 ret = _win_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
447 if (INVALID_SOCKET == ret)
448 {
449 fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno));
450 return INVALID_SOCKET;
451 }
452 return ret;
453}
454
455
456/**
457 * Create an ICMP raw socket for writing.
458 *
459 * @return INVALID_SOCKET on error
460 */
461static _win_socket
462make_raw_socket()
463{
464 DWORD bOptVal = TRUE;
465 int bOptLen = sizeof(bOptVal);
466
467 rawsock = _win_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
468 if (INVALID_SOCKET == rawsock)
469 {
470 fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno));
471 return INVALID_SOCKET;
472 }
473
474 if (0 !=
475 _win_setsockopt(rawsock, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal,
476 bOptLen))
477 {
478 fprintf(stderr, "Error setting SO_BROADCAST to ON: %s\n",
479 strerror(errno));
480 closesocket(rawsock);
481 return INVALID_SOCKET;
482 }
483 if (0 !=
484 _win_setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL, (char *)&bOptVal, bOptLen))
485 {
486 fprintf(stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror(errno));
487 closesocket(rawsock);
488 return INVALID_SOCKET;
489 }
490 return rawsock;
491}
492
493
494/**
495 * Create a UDP socket for writing.
496 *
497 * @param my_ip source address (our ip address)
498 * @return INVALID_SOCKET on error
499 */
500static _win_socket
501make_udp_socket(const struct in_addr *my_ip)
502{
503 _win_socket ret;
504 struct sockaddr_in addr;
505
506 ret = _win_socket(AF_INET, SOCK_DGRAM, 0);
507 if (INVALID_SOCKET == ret)
508 {
509 fprintf(stderr, "Error opening UDP socket: %s\n", strerror(errno));
510 return INVALID_SOCKET;
511 }
512 memset(&addr, 0, sizeof(addr));
513 addr.sin_family = AF_INET;
514 addr.sin_addr = *my_ip;
515 addr.sin_port = htons(NAT_TRAV_PORT);
516 if (0 != bind(ret, (struct sockaddr *)&addr, sizeof(addr)))
517 {
518 fprintf(stderr, "Error binding UDP socket to port %u: %s\n", NAT_TRAV_PORT,
519 strerror(errno));
520 /* likely problematic, but not certain, try to continue */
521 }
522 return ret;
523}
524
525
526int
527main(int argc, char *const *argv)
528{
529 struct in_addr external;
530 fd_set rs;
531 struct timeval tv;
532 WSADATA wsaData;
533 unsigned int alt = 0;
534
535 if ((argc > 1) && (0 != strcmp(argv[1], "-d")))
536 {
537 privilege_testing = TRUE;
538 fprintf(stderr,
539 "%s",
540 "DEBUG: Running binary in privilege testing mode.");
541 argv++;
542 argc--;
543 }
544
545 if (2 != argc)
546 {
547 fprintf(stderr,
548 "This program must be started with our (internal NAT) IP as the only argument.\n");
549 return 1;
550 }
551 if (1 != inet_pton(AF_INET, argv[1], &external))
552 {
553 fprintf(stderr, "Error parsing IPv4 address: %s, error %s\n", argv[1],
554 strerror(errno));
555 return 1;
556 }
557 if (1 != inet_pton(AF_INET, DUMMY_IP, &dummy))
558 {
559 fprintf(stderr, "Internal error converting dummy IP to binary.\n");
560 return 2;
561 }
562 if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0)
563 {
564 fprintf(stderr, "Failed to find Winsock 2.1 or better.\n");
565 return 2;
566 }
567 if (INVALID_SOCKET == (icmpsock = make_icmp_socket()))
568 {
569 return 3;
570 }
571 if (INVALID_SOCKET == (make_raw_socket()))
572 {
573 closesocket(icmpsock);
574 return 3;
575 }
576 if (INVALID_SOCKET == (udpsock = make_udp_socket(&external)))
577 {
578 closesocket(icmpsock);
579 closesocket(rawsock);
580 return 3;
581 }
582
583 while (!privilege_testing)
584 {
585 FD_ZERO(&rs);
586 FD_SET(icmpsock, &rs);
587 tv.tv_sec = 0;
588 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
589 if (-1 == select(icmpsock + 1, &rs, NULL, NULL, &tv))
590 {
591 if (errno == EINTR)
592 continue;
593 fprintf(stderr, "select failed: %s\n", strerror(errno));
594 break;
595 }
596 if (FD_ISSET(icmpsock, &rs))
597 process_icmp_response();
598 if (0 == (++alt % 2))
599 send_icmp_echo(&external);
600 else
601 send_udp();
602 }
603 /* select failed (internal error or OS out of resources) */
604 closesocket(icmpsock);
605 closesocket(rawsock);
606 closesocket(udpsock);
607 WSACleanup();
608 if (privilege_testing)
609 return 0;
610 return 4;
611}
612
613
614/* end of gnunet-helper-nat-server-windows.c */
diff --git a/src/nse/Makefile.am b/src/nse/Makefile.am
index 618489780..3a79cdd97 100644
--- a/src/nse/Makefile.am
+++ b/src/nse/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/nt/Makefile.am b/src/nt/Makefile.am
index 68b6a55e7..57b8d1936 100644
--- a/src/nt/Makefile.am
+++ b/src/nt/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/peerinfo-tool/Makefile.am b/src/peerinfo-tool/Makefile.am
index 8293288c8..3c133427c 100644
--- a/src/peerinfo-tool/Makefile.am
+++ b/src/peerinfo-tool/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/peerinfo/Makefile.am b/src/peerinfo/Makefile.am
index d07ed3a5b..7d1204100 100644
--- a/src/peerinfo/Makefile.am
+++ b/src/peerinfo/Makefile.am
@@ -10,10 +10,6 @@ plugindir = $(libdir)/gnunet
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 peerinfo.conf 11 peerinfo.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
19 XLIB = -lgcov 15 XLIB = -lgcov
diff --git a/src/peerstore/Makefile.am b/src/peerstore/Makefile.am
index c6acdce56..003bac36d 100644
--- a/src/peerstore/Makefile.am
+++ b/src/peerstore/Makefile.am
@@ -10,10 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10dist_pkgcfg_DATA = \ 10dist_pkgcfg_DATA = \
11 peerstore.conf 11 peerstore.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = -fprofile-arcs -ftest-coverage 14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
19endif 15endif
diff --git a/src/pq/Makefile.am b/src/pq/Makefile.am
index d0c71703b..9270e6fe0 100644
--- a/src/pq/Makefile.am
+++ b/src/pq/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) 2AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/pt/Makefile.am b/src/pt/Makefile.am
index 1d94a3429..09a68b779 100644
--- a/src/pt/Makefile.am
+++ b/src/pt/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10endif 6endif
@@ -46,13 +42,6 @@ if LINUX
46 test_gnunet_vpn-4_over \ 42 test_gnunet_vpn-4_over \
47 test_gns_vpn 43 test_gns_vpn
48endif 44endif
49if MINGW
50 VPN_TEST = \
51 test_gnunet_vpn-4_to_6 \
52 test_gnunet_vpn-6_to_4 \
53 test_gnunet_vpn-6_over \
54 test_gnunet_vpn-4_over
55endif
56else 45else
57if HAVE_LIBCURL 46if HAVE_LIBCURL
58LIB_GNURL=@LIBCURL@ 47LIB_GNURL=@LIBCURL@
@@ -65,13 +54,6 @@ if LINUX
65 test_gnunet_vpn-4_over \ 54 test_gnunet_vpn-4_over \
66 test_gns_vpn 55 test_gns_vpn
67endif 56endif
68if MINGW
69 VPN_TEST = \
70 test_gnunet_vpn-4_to_6 \
71 test_gnunet_vpn-6_to_4 \
72 test_gnunet_vpn-6_over \
73 test_gnunet_vpn-4_over
74endif
75endif 57endif
76endif 58endif
77 59
diff --git a/src/pt/test_gnunet_vpn.c b/src/pt/test_gnunet_vpn.c
index 60f4aad2a..c52c0c6c9 100644
--- a/src/pt/test_gnunet_vpn.c
+++ b/src/pt/test_gnunet_vpn.c
@@ -420,7 +420,6 @@ main(int argc, char *const *argv)
420 char *exit_binary; 420 char *exit_binary;
421 int ret = 0; 421 int ret = 0;
422 422
423#ifndef MINGW
424 if (0 != access("/dev/net/tun", R_OK)) 423 if (0 != access("/dev/net/tun", R_OK))
425 { 424 {
426 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR, 425 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR,
@@ -430,7 +429,7 @@ main(int argc, char *const *argv)
430 "WARNING: System unable to run test, skipping.\n"); 429 "WARNING: System unable to run test, skipping.\n");
431 return 77; 430 return 77;
432 } 431 }
433#endif 432
434 vpn_binary = GNUNET_OS_get_libexec_binary_path("gnunet-helper-vpn"); 433 vpn_binary = GNUNET_OS_get_libexec_binary_path("gnunet-helper-vpn");
435 exit_binary = GNUNET_OS_get_libexec_binary_path("gnunet-helper-exit"); 434 exit_binary = GNUNET_OS_get_libexec_binary_path("gnunet-helper-exit");
436 if ((GNUNET_YES != (ret = GNUNET_OS_check_helper_binary(vpn_binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))) || //ipv4 only please! 435 if ((GNUNET_YES != (ret = GNUNET_OS_check_helper_binary(vpn_binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))) || //ipv4 only please!
diff --git a/src/reclaim-attribute/Makefile.am b/src/reclaim-attribute/Makefile.am
index e53f527b3..cbbcb37d6 100644
--- a/src/reclaim-attribute/Makefile.am
+++ b/src/reclaim-attribute/Makefile.am
@@ -7,10 +7,6 @@ pkgcfgdir= $(pkgdatadir)/config.d/
7 7
8libexecdir= $(pkglibdir)/libexec/ 8libexecdir= $(pkglibdir)/libexec/
9 9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
12endif
13
14if USE_COVERAGE 10if USE_COVERAGE
15 AM_CFLAGS = --coverage -O0 11 AM_CFLAGS = --coverage -O0
16 XLIBS = -lgcov 12 XLIBS = -lgcov
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
index 69dcc605e..851b0d71e 100644
--- a/src/reclaim/Makefile.am
+++ b/src/reclaim/Makefile.am
@@ -3,10 +3,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4 plugindir = $(libdir)/gnunet 4 plugindir = $(libdir)/gnunet
5 5
6if MINGW
7 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
8endif
9
10if USE_COVERAGE 6if USE_COVERAGE
11 AM_CFLAGS = --coverage -O0 7 AM_CFLAGS = --coverage -O0
12 XLIB = -lgcov 8 XLIB = -lgcov
diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am
index 2af6dcccd..ba5e0af00 100644
--- a/src/regex/Makefile.am
+++ b/src/regex/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/rest/Makefile.am b/src/rest/Makefile.am
index 1fd2816c0..41b4c6508 100644
--- a/src/rest/Makefile.am
+++ b/src/rest/Makefile.am
@@ -10,10 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 rest.conf 11 rest.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
19 XLIBS = -lgcov 15 XLIBS = -lgcov
diff --git a/src/revocation/Makefile.am b/src/revocation/Makefile.am
index 82755b485..a6fff3524 100644
--- a/src/revocation/Makefile.am
+++ b/src/revocation/Makefile.am
@@ -3,10 +3,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4plugindir = $(libdir)/gnunet 4plugindir = $(libdir)/gnunet
5 5
6if MINGW
7 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
8endif
9
10if USE_COVERAGE 6if USE_COVERAGE
11 AM_CFLAGS = --coverage -O0 7 AM_CFLAGS = --coverage -O0
12 XLIB = -lgcov 8 XLIB = -lgcov
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am
index ce73caa0f..0c739589f 100644
--- a/src/rps/Makefile.am
+++ b/src/rps/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/scalarproduct/Makefile.am b/src/scalarproduct/Makefile.am
index 10e04284f..311cfd1af 100644
--- a/src/scalarproduct/Makefile.am
+++ b/src/scalarproduct/Makefile.am
@@ -8,10 +8,6 @@ libexecdir= $(pkglibdir)/libexec/
8pkgcfg_DATA = \ 8pkgcfg_DATA = \
9 scalarproduct.conf 9 scalarproduct.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = -fprofile-arcs -ftest-coverage 12 AM_CFLAGS = -fprofile-arcs -ftest-coverage
17endif 13endif
diff --git a/src/secretsharing/Makefile.am b/src/secretsharing/Makefile.am
index c808e8200..787cfa0c1 100644
--- a/src/secretsharing/Makefile.am
+++ b/src/secretsharing/Makefile.am
@@ -8,10 +8,6 @@ libexecdir= $(pkglibdir)/libexec/
8pkgcfg_DATA = \ 8pkgcfg_DATA = \
9 secretsharing.conf 9 secretsharing.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = -fprofile-arcs -ftest-coverage 12 AM_CFLAGS = -fprofile-arcs -ftest-coverage
17endif 13endif
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
index df17fa1ab..d6b10a1f8 100644
--- a/src/set/Makefile.am
+++ b/src/set/Makefile.am
@@ -10,10 +10,6 @@ plugindir = $(libdir)/gnunet
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 set.conf 11 set.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = -fprofile-arcs -ftest-coverage 14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
19endif 15endif
diff --git a/src/sq/Makefile.am b/src/sq/Makefile.am
index fb9364005..893c8eac3 100644
--- a/src/sq/Makefile.am
+++ b/src/sq/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage 5 AM_CFLAGS = --coverage
10endif 6endif
diff --git a/src/statistics/Makefile.am b/src/statistics/Makefile.am
index 16a1ea2d0..bde35da2d 100644
--- a/src/statistics/Makefile.am
+++ b/src/statistics/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/template/Makefile.am b/src/template/Makefile.am
index 5a27a6d60..4d2e58083 100644
--- a/src/template/Makefile.am
+++ b/src/template/Makefile.am
@@ -8,10 +8,6 @@ libexecdir= $(pkglibdir)/libexec/
8dist_pkgcfg_DATA = \ 8dist_pkgcfg_DATA = \
9 template.conf 9 template.conf
10 10
11if MINGW
12 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
13endif
14
15if USE_COVERAGE 11if USE_COVERAGE
16 AM_CFLAGS = -fprofile-arcs -ftest-coverage 12 AM_CFLAGS = -fprofile-arcs -ftest-coverage
17endif 13endif
diff --git a/src/testbed-logger/Makefile.am b/src/testbed-logger/Makefile.am
index a8c4c7b05..96b68df27 100644
--- a/src/testbed-logger/Makefile.am
+++ b/src/testbed-logger/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index e858e44b4..c27a81ae9 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/testbed/gnunet-service-testbed_cpustatus.c b/src/testbed/gnunet-service-testbed_cpustatus.c
index b659b5dc3..f3df9a96e 100644
--- a/src/testbed/gnunet-service-testbed_cpustatus.c
+++ b/src/testbed/gnunet-service-testbed_cpustatus.c
@@ -398,114 +398,6 @@ ABORT_KSTAT:
398 } 398 }
399#endif 399#endif
400 400
401#if MINGW
402 /* Win NT? */
403 if (GNNtQuerySystemInformation)
404 {
405 static double dLastKernel;
406 static double dLastIdle;
407 static double dLastUser;
408 double dKernel;
409 double dIdle;
410 double dUser;
411 double dDiffKernel;
412 double dDiffIdle;
413 double dDiffUser;
414 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo;
415
416 if (GNNtQuerySystemInformation(SystemProcessorPerformanceInformation,
417 &theInfo,
418 sizeof(theInfo), NULL) == NO_ERROR)
419 {
420 /* PORT-ME MINGW: Multi-processor? */
421 dKernel = Li2Double(theInfo.KernelTime);
422 dIdle = Li2Double(theInfo.IdleTime);
423 dUser = Li2Double(theInfo.UserTime);
424 dDiffKernel = dKernel - dLastKernel;
425 dDiffIdle = dIdle - dLastIdle;
426 dDiffUser = dUser - dLastUser;
427
428 if (((dDiffKernel + dDiffUser) > 0) &&
429 (dLastIdle + dLastKernel + dLastUser > 0))
430 currentCPULoad =
431 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0;
432 else
433 currentCPULoad = -1; /* don't know (yet) */
434
435 dLastKernel = dKernel;
436 dLastIdle = dIdle;
437 dLastUser = dUser;
438
439 currentIOLoad = -1; /* FIXME-MINGW */
440 return GNUNET_OK;
441 }
442 else
443 {
444 /* only warn once, if there is a problem with
445 NtQuery..., we're going to hit it frequently... */
446 static int once;
447 if (once == 0)
448 {
449 once = 1;
450 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
451 "Cannot query the CPU usage (Windows NT).\n");
452 }
453 return GNUNET_SYSERR;
454 }
455 }
456 else
457 { /* Win 9x */
458 HKEY hKey;
459 DWORD dwDataSize, dwType, dwDummy;
460
461 /* Start query */
462 if (RegOpenKeyEx(HKEY_DYN_DATA,
463 "PerfStats\\StartSrv",
464 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
465 {
466 /* only warn once */
467 static int once = 0;
468 if (once == 0)
469 {
470 once = 1;
471 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
472 "Cannot query the CPU usage (Win 9x)\n");
473 }
474 }
475
476 RegOpenKeyEx(HKEY_DYN_DATA,
477 "PerfStats\\StartStat", 0, KEY_ALL_ACCESS, &hKey);
478 dwDataSize = sizeof(dwDummy);
479 RegQueryValueEx(hKey,
480 "KERNEL\\CPUUsage",
481 NULL, &dwType, (LPBYTE)&dwDummy, &dwDataSize);
482 RegCloseKey(hKey);
483
484 /* Get CPU usage */
485 RegOpenKeyEx(HKEY_DYN_DATA,
486 "PerfStats\\StatData", 0, KEY_ALL_ACCESS, &hKey);
487 dwDataSize = sizeof(currentCPULoad);
488 RegQueryValueEx(hKey,
489 "KERNEL\\CPUUsage",
490 NULL, &dwType, (LPBYTE)&currentCPULoad, &dwDataSize);
491 RegCloseKey(hKey);
492 currentIOLoad = -1; /* FIXME-MINGW! */
493
494 /* Stop query */
495 RegOpenKeyEx(HKEY_DYN_DATA,
496 "PerfStats\\StopStat", 0, KEY_ALL_ACCESS, &hKey);
497 RegOpenKeyEx(HKEY_DYN_DATA,
498 "PerfStats\\StopSrv", 0, KEY_ALL_ACCESS, &hKey);
499 dwDataSize = sizeof(dwDummy);
500 RegQueryValueEx(hKey,
501 "KERNEL\\CPUUsage",
502 NULL, &dwType, (LPBYTE)&dwDummy, &dwDataSize);
503 RegCloseKey(hKey);
504
505 return GNUNET_OK;
506 }
507#endif
508
509 /* loadaverage not defined and no platform 401 /* loadaverage not defined and no platform
510 specific alternative defined 402 specific alternative defined
511 => default: error 403 => default: error
@@ -695,12 +587,6 @@ GST_stats_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
695 char *fn; 587 char *fn;
696 size_t len; 588 size_t len;
697 589
698#if MINGW
699 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
700 "Load statistics logging now available for windows\n");
701 return; /* No logging on windows for now :( */
702#endif
703
704 if (GNUNET_OK != 590 if (GNUNET_OK !=
705 GNUNET_CONFIGURATION_get_value_filename(cfg, "testbed", 591 GNUNET_CONFIGURATION_get_value_filename(cfg, "testbed",
706 "STATS_DIR", &stats_dir)) 592 "STATS_DIR", &stats_dir))
@@ -747,9 +633,6 @@ GST_stats_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
747void 633void
748GST_stats_destroy() 634GST_stats_destroy()
749{ 635{
750#if MINGW
751 return;
752#endif
753 if (NULL == bw) 636 if (NULL == bw)
754 return; 637 return;
755#ifdef LINUX 638#ifdef LINUX
diff --git a/src/testbed/test_testbed_api_testbed_run.c b/src/testbed/test_testbed_api_testbed_run.c
index 39bc9bfe7..a3bd415dd 100644
--- a/src/testbed/test_testbed_api_testbed_run.c
+++ b/src/testbed/test_testbed_api_testbed_run.c
@@ -215,18 +215,7 @@ main(int argc, char **argv)
215 } 215 }
216 testname++; 216 testname++;
217 testname = GNUNET_strdup(testname); 217 testname = GNUNET_strdup(testname);
218#ifdef MINGW 218
219 {
220 char *period;
221
222 /* check and remove .exe extension */
223 period = strrchr(testname, (int)'.');
224 if (NULL != period)
225 *period = '\0';
226 else
227 GNUNET_break(0); /* Windows with no .exe? */
228 }
229#endif
230 if (0 == strcmp("waitforever", testname)) 219 if (0 == strcmp("waitforever", testname))
231 wait_forever = GNUNET_YES; 220 wait_forever = GNUNET_YES;
232 if ((GNUNET_YES != wait_forever) && (0 != strcmp("run", testname))) 221 if ((GNUNET_YES != wait_forever) && (0 != strcmp("run", testname)))
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 39e5f1574..9c6357455 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -1,10 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE 4if USE_COVERAGE
9 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
10 XLIB = -lgcov 6 XLIB = -lgcov
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index a9b0d19d6..0f5b2e8be 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -114,18 +114,12 @@ if HAVE_LIBBLUETOOTH
114 BT_QUOTA_TEST = test_quota_compliance_bluetooth \ 114 BT_QUOTA_TEST = test_quota_compliance_bluetooth \
115 test_quota_compliance_bluetooth_asymmetric 115 test_quota_compliance_bluetooth_asymmetric
116endif 116endif
117else
118if MINGW
119 BT_BIN = gnunet-helper-transport-bluetooth
120 BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la
121endif
122endif 117endif
123 118
124# end of HAVE_EXPERIMENTAL 119# end of HAVE_EXPERIMENTAL
125endif 120endif
126 121
127 122
128if !MINGW
129UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la 123UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la
130UNIX_PLUGIN_TEST = test_transport_api_unix 124UNIX_PLUGIN_TEST = test_transport_api_unix
131UNIX_TEST = test_plugin_unix 125UNIX_TEST = test_plugin_unix
@@ -136,7 +130,7 @@ UNIX_QUOTA_TEST = test_quota_compliance_unix \
136if LINUX 130if LINUX
137 UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract 131 UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract
138endif 132endif
139endif 133
140 134
141noinst_PROGRAMS = \ 135noinst_PROGRAMS = \
142 gnunet-transport-profiler \ 136 gnunet-transport-profiler \
@@ -319,13 +313,9 @@ gnunet_transport_wlan_receiver_LDADD = \
319 313
320gnunet_helper_transport_bluetooth_SOURCES = \ 314gnunet_helper_transport_bluetooth_SOURCES = \
321 gnunet-helper-transport-bluetooth.c 315 gnunet-helper-transport-bluetooth.c
322if MINGW 316
323 gnunet_helper_transport_bluetooth_LDADD = \ 317gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth
324 $(top_builddir)/src/util/libgnunetutil.la 318
325 gnunet_helper_transport_bluetooth_LDFLAGS = -lws2_32
326else
327 gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth
328endif
329 319
330gnunet_transport_profiler_SOURCES = \ 320gnunet_transport_profiler_SOURCES = \
331 gnunet-transport-profiler.c 321 gnunet-transport-profiler.c
diff --git a/src/transport/gnunet-helper-transport-bluetooth.c b/src/transport/gnunet-helper-transport-bluetooth.c
index 2ac705996..4696f48f8 100644
--- a/src/transport/gnunet-helper-transport-bluetooth.c
+++ b/src/transport/gnunet-helper-transport-bluetooth.c
@@ -21,30 +21,23 @@
21 */ 21 */
22#include "gnunet_config.h" 22#include "gnunet_config.h"
23 23
24#ifdef MINGW 24#define SOCKTYPE int
25 #include "platform.h" 25#include <bluetooth/bluetooth.h>
26 #include "gnunet_util_lib.h" 26#include <bluetooth/hci.h>
27 #include <bthdef.h> 27#include <bluetooth/hci_lib.h>
28 #include <ws2bth.h> 28#include <bluetooth/rfcomm.h>
29#else 29#include <bluetooth/sdp.h>
30 #define SOCKTYPE int 30#include <bluetooth/sdp_lib.h>
31 #include <bluetooth/bluetooth.h> 31#include <errno.h>
32 #include <bluetooth/hci.h> 32#include <linux/if.h>
33 #include <bluetooth/hci_lib.h> 33#include <stdio.h>
34 #include <bluetooth/rfcomm.h> 34#include <stdlib.h>
35 #include <bluetooth/sdp.h> 35#include <sys/ioctl.h>
36 #include <bluetooth/sdp_lib.h> 36#include <sys/param.h>
37 #include <errno.h> 37#include <sys/socket.h>
38 #include <linux/if.h> 38#include <sys/stat.h>
39 #include <stdio.h> 39#include <sys/types.h>
40 #include <stdlib.h> 40#include <unistd.h>
41 #include <sys/ioctl.h>
42 #include <sys/param.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47#endif
48 41
49#include "plugin_transport_wlan.h" 42#include "plugin_transport_wlan.h"
50#include "gnunet_protocols.h" 43#include "gnunet_protocols.h"
@@ -67,34 +60,6 @@
67 */ 60 */
68#define MAX_LOOPS 5 61#define MAX_LOOPS 5
69 62
70#ifdef MINGW
71/* Maximum size of the interface's name */
72 #define IFNAMSIZ 16
73
74 #ifndef NS_BTH
75 #define NS_BTH 16
76 #endif
77/**
78 * A copy of the MAC Address.
79 */
80struct GNUNET_TRANSPORT_WLAN_MacAddress_Copy {
81 UINT8 mac[MAC_ADDR_SIZE];
82};
83
84/**
85 * The UUID used for the SDP service.
86 * {31191E56-FA7E-4517-870E-71B86BBCC52F}
87 */
88 #define GNUNET_BLUETOOTH_SDP_UUID \
89 { \
90 0x31, 0x19, 0x1E, 0x56, \
91 0xFA, 0x7E, \
92 0x45, 0x17, \
93 0x87, 0x0E, \
94 0x71, 0xB8, 0x6B, 0xBC, 0xC5, 0x2F \
95 }
96#endif
97
98/** 63/**
99 * In bluez library, the maximum name length of a device is 8 64 * In bluez library, the maximum name length of a device is 8
100 */ 65 */
@@ -110,17 +75,6 @@ struct HardwareInfos {
110 */ 75 */
111 char iface[IFNAMSIZ]; 76 char iface[IFNAMSIZ];
112 77
113 #ifdef MINGW
114 /**
115 * socket handle
116 */
117 struct GNUNET_NETWORK_Handle *handle;
118
119 /**
120 * MAC address of our own bluetooth interface.
121 */
122 struct GNUNET_TRANSPORT_WLAN_MacAddress_Copy pl_mac;
123 #else
124 /** 78 /**
125 * file descriptor for the rfcomm socket 79 * file descriptor for the rfcomm socket
126 */ 80 */
@@ -135,7 +89,6 @@ struct HardwareInfos {
135 * SDP session 89 * SDP session
136 */ 90 */
137 sdp_session_t *session; 91 sdp_session_t *session;
138 #endif
139}; 92};
140 93
141/** 94/**
@@ -606,61 +559,6 @@ check_crc_buf_osdep(const unsigned char *buf, size_t len)
606 559
607 560
608/* ************** end of clone ***************** */ 561/* ************** end of clone ***************** */
609
610#ifdef MINGW
611/**
612 * Function used to get the code of last error and to print the type of error.
613 */
614static void
615print_last_error()
616{
617 LPVOID lpMsgBuf = NULL;
618
619 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
620 NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL))
621 fprintf(stderr, "%s\n", (char *)lpMsgBuf);
622 else
623 fprintf(stderr, "Failed to format the message for the last error! Error number : %d\n", GetLastError());
624}
625
626/**
627 * Function used to initialize the Windows Sockets
628 */
629static void
630initialize_windows_sockets()
631{
632 WSADATA wsaData;
633 WORD wVersionRequested = MAKEWORD(2, 0);
634
635 if (WSAStartup(wVersionRequested, &wsaData) != NO_ERROR)
636 {
637 fprintf(stderr, "Error initializing window sockets!\n");
638 print_last_error();
639 ExitProcess(2);
640 }
641}
642
643/**
644 * Function used to convert the GUID.
645 * @param bytes the GUID represented as a char array
646 * @param uuid pointer to the GUID
647 */
648static void
649convert_guid(char *bytes, GUID * uuid)
650{
651 int i;
652
653 uuid->Data1 = ((bytes[0] << 24) & 0xff000000) | ((bytes[1] << 16) & 0x00ff0000) | ((bytes[2] << 8) & 0x0000ff00) | (bytes[3] & 0x000000ff);
654 uuid->Data2 = ((bytes[4] << 8) & 0xff00) | (bytes[5] & 0x00ff);
655 uuid->Data3 = ((bytes[6] << 8) & 0xff00) | (bytes[7] & 0x00ff);
656
657 for (i = 0; i < 8; i++)
658 {
659 uuid->Data4[i] = bytes[i + 8];
660 }
661}
662#endif
663
664#ifdef LINUX 562#ifdef LINUX
665/** 563/**
666 * Function for assigning a port number 564 * Function for assigning a port number
@@ -688,79 +586,6 @@ bind_socket(int socket, struct sockaddr_rc *addr)
688} 586}
689#endif 587#endif
690 588
691#ifdef MINGW
692/**
693 * Function used for creating the service record and registering it.
694 *
695 * @param dev pointer to the device struct
696 * @return 0 on success
697 */
698static int
699register_service(struct HardwareInfos *dev)
700{
701 /* advertise the service */
702 CSADDR_INFO addr_info;
703 WSAQUERYSET wqs;
704 GUID guid;
705 unsigned char uuid[] = GNUNET_BLUETOOTH_SDP_UUID;
706 SOCKADDR_BTH addr;
707 int addr_len = sizeof(SOCKADDR_BTH);
708 int fd;
709
710 /* get the port on which we are listening on */
711 memset(&addr, 0, sizeof(SOCKADDR_BTH));
712 fd = GNUNET_NETWORK_get_fd(dev->handle);
713 if (fd <= 0)
714 {
715 fprintf(stderr, "Failed to get the file descriptor\n");
716 return -1;
717 }
718 if (SOCKET_ERROR == getsockname(fd, (SOCKADDR*)&addr, &addr_len))
719 {
720 fprintf(stderr, "Failed to get the port on which we are listening on: \n");
721 print_last_error();
722 return -1;
723 }
724
725 /* save the device address */
726 GNUNET_memcpy(&dev->pl_mac, &addr.btAddr, sizeof(BTH_ADDR));
727
728 /* set the address information */
729 memset(&addr_info, 0, sizeof(CSADDR_INFO));
730 addr_info.iProtocol = BTHPROTO_RFCOMM;
731 addr_info.iSocketType = SOCK_STREAM;
732 addr_info.LocalAddr.lpSockaddr = (LPSOCKADDR)&addr;
733 addr_info.LocalAddr.iSockaddrLength = sizeof(addr);
734 addr_info.RemoteAddr.lpSockaddr = (LPSOCKADDR)&addr;
735 addr_info.RemoteAddr.iSockaddrLength = sizeof(addr);
736
737 convert_guid((char *)uuid, &guid);
738
739 /* register the service */
740 memset(&wqs, 0, sizeof(WSAQUERYSET));
741 wqs.dwSize = sizeof(WSAQUERYSET);
742 wqs.dwNameSpace = NS_BTH;
743 wqs.lpszServiceInstanceName = "GNUnet Bluetooth Service";
744 wqs.lpszComment = "This is the service used by the GNUnnet plugin transport";
745 wqs.lpServiceClassId = &guid;
746 wqs.dwNumberOfCsAddrs = 1;
747 wqs.lpcsaBuffer = &addr_info;
748 wqs.lpBlob = 0;
749
750 if (SOCKET_ERROR == WSASetService(&wqs, RNRSERVICE_REGISTER, 0))
751 {
752 fprintf(stderr, "Failed to register the SDP service: ");
753 print_last_error();
754 return -1;
755 }
756 else
757 {
758 fprintf(stderr, "The SDP service was registered\n");
759 }
760
761 return 0;
762}
763#else
764/** 589/**
765 * Function used for creating the service record and registering it. 590 * Function used for creating the service record and registering it.
766 * 591 *
@@ -849,96 +674,7 @@ register_service(struct HardwareInfos *dev, int rc_channel)
849 674
850 return 0; 675 return 0;
851} 676}
852#endif
853 677
854#ifdef MINGW
855/**
856 * Function for searching and browsing for a service. This will return the
857 * port number on which the service is running.
858 *
859 * @param dest target address
860 * @return channel
861 */
862static int
863get_channel(const char *dest)
864{
865 HANDLE h;
866 WSAQUERYSET *wqs;
867 DWORD wqs_len = sizeof(WSAQUERYSET);
868 int done = 0;
869 int channel = -1;
870 GUID guid;
871 unsigned char uuid[] = GNUNET_BLUETOOTH_SDP_UUID;
872
873 convert_guid((char *)uuid, &guid);
874
875 wqs = (WSAQUERYSET*)malloc(wqs_len);
876 ZeroMemory(wqs, wqs_len);
877
878 wqs->dwSize = sizeof(WSAQUERYSET);
879 wqs->lpServiceClassId = &guid;
880 wqs->dwNameSpace = NS_BTH;
881 wqs->dwNumberOfCsAddrs = 0;
882 wqs->lpszContext = (LPSTR)dest;
883
884 if (SOCKET_ERROR == WSALookupServiceBegin(wqs, LUP_FLUSHCACHE | LUP_RETURN_ALL, &h))
885 {
886 if (GetLastError() == WSASERVICE_NOT_FOUND)
887 {
888 fprintf(stderr, "WARNING! The device with address %s wasn't found. Skipping the message!", dest);
889 return -1;
890 }
891 else
892 {
893 fprintf(stderr, "Failed to find the port number: ");
894 print_last_error();
895 ExitProcess(2);
896 return -1;
897 }
898 }
899
900 /* search the sdp service */
901 while (!done)
902 {
903 if (SOCKET_ERROR == WSALookupServiceNext(h, LUP_FLUSHCACHE | LUP_RETURN_ALL, &wqs_len, wqs))
904 {
905 int error = WSAGetLastError();
906
907 switch (error)
908 {
909 case WSAEFAULT:
910 free(wqs);
911 wqs = (WSAQUERYSET*)malloc(wqs_len);
912 break;
913
914 case WSANO_DATA:
915 fprintf(stderr, "Failed! The address was valid but there was no data record of requested type\n");
916 done = 1;
917 break;
918
919 case WSA_E_NO_MORE:
920 done = 1;
921 break;
922
923 default:
924 fprintf(stderr, "Failed to look over the services: ");
925 print_last_error();
926 WSALookupServiceEnd(h);
927 ExitProcess(2);
928 }
929 }
930 else
931 {
932 channel = ((SOCKADDR_BTH*)wqs->lpcsaBuffer->RemoteAddr.lpSockaddr)->port;
933 }
934 }
935
936 free(wqs);
937 WSALookupServiceEnd(h);
938
939 return channel;
940}
941#else
942/** 678/**
943 * Function used for searching and browsing for a service. This will return the 679 * Function used for searching and browsing for a service. This will return the
944 * port number on which the service is running. 680 * port number on which the service is running.
@@ -1011,7 +747,6 @@ get_channel(struct HardwareInfos *dev, bdaddr_t dest)
1011 747
1012 return channel; 748 return channel;
1013} 749}
1014#endif
1015 750
1016/** 751/**
1017 * Read from the socket and put the result into the buffer for transmission to 'stdout'. 752 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
@@ -1030,22 +765,14 @@ read_from_the_socket(void *sock,
1030{ 765{
1031 unsigned char tmpbuf[buf_size]; 766 unsigned char tmpbuf[buf_size];
1032 ssize_t count; 767 ssize_t count;
1033
1034 #ifdef MINGW
1035 count = GNUNET_NETWORK_socket_recv((struct GNUNET_NETWORK_Handle *)sock, tmpbuf, buf_size);
1036 #else
1037 count = read(*((int *)sock), tmpbuf, buf_size); 768 count = read(*((int *)sock), tmpbuf, buf_size);
1038 #endif
1039 769
1040 if (0 > count) 770 if (0 > count)
1041 { 771 {
1042 if (EAGAIN == errno) 772 if (EAGAIN == errno)
1043 return 0; 773 return 0;
1044 #if MINGW 774
1045 print_last_error();
1046 #else
1047 fprintf(stderr, "Failed to read from the HCI socket: %s\n", strerror(errno)); 775 fprintf(stderr, "Failed to read from the HCI socket: %s\n", strerror(errno));
1048 #endif
1049 776
1050 return -1; 777 return -1;
1051 } 778 }
@@ -1088,43 +815,6 @@ read_from_the_socket(void *sock,
1088static int 815static int
1089open_device(struct HardwareInfos *dev) 816open_device(struct HardwareInfos *dev)
1090{ 817{
1091 #ifdef MINGW
1092 SOCKADDR_BTH addr;
1093
1094 /* bind the RFCOMM socket to the interface */
1095 addr.addressFamily = AF_BTH;
1096 addr.btAddr = 0;
1097 addr.port = BT_PORT_ANY;
1098
1099 if (GNUNET_OK !=
1100 GNUNET_NETWORK_socket_bind(dev->handle, (const SOCKADDR*)&addr, sizeof(SOCKADDR_BTH)))
1101 {
1102 fprintf(stderr, "Failed to bind the socket: ");
1103 if (GetLastError() == WSAENETDOWN)
1104 {
1105 fprintf(stderr, "Please make sure that your Bluetooth device is ON!\n");
1106 ExitProcess(2);
1107 }
1108 print_last_error();
1109 return -1;
1110 }
1111
1112 /* start listening on the socket */
1113 if (GNUNET_NETWORK_socket_listen(dev->handle, 4) != GNUNET_OK)
1114 {
1115 fprintf(stderr, "Failed to listen on the socket: ");
1116 print_last_error();
1117 return -1;
1118 }
1119
1120 /* register the sdp service */
1121 if (register_service(dev) != 0)
1122 {
1123 fprintf(stderr, "Failed to register a service: ");
1124 print_last_error();
1125 return 1;
1126 }
1127 #else
1128 int i, dev_id = -1, fd_hci; 818 int i, dev_id = -1, fd_hci;
1129 struct { 819 struct {
1130 struct hci_dev_list_req list; 820 struct hci_dev_list_req list;
@@ -1279,7 +969,6 @@ open_device(struct HardwareInfos *dev)
1279 dev->iface, strerror(errno)); 969 dev->iface, strerror(errno));
1280 return 1; 970 return 1;
1281 } 971 }
1282 #endif
1283 972
1284 return 0; 973 return 0;
1285} 974}
@@ -1299,12 +988,7 @@ mac_set(struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
1299{ 988{
1300 taIeeeHeader->frame_control = htons(IEEE80211_FC0_TYPE_DATA); 989 taIeeeHeader->frame_control = htons(IEEE80211_FC0_TYPE_DATA);
1301 taIeeeHeader->addr3 = mac_bssid_gnunet; 990 taIeeeHeader->addr3 = mac_bssid_gnunet;
1302
1303 #ifdef MINGW
1304 GNUNET_memcpy(&taIeeeHeader->addr2, &dev->pl_mac, sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress));
1305 #else
1306 taIeeeHeader->addr2 = dev->pl_mac; 991 taIeeeHeader->addr2 = dev->pl_mac;
1307 #endif
1308} 992}
1309 993
1310#ifdef LINUX 994#ifdef LINUX
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 755809194..c056bb79c 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -2929,20 +2929,7 @@ udp_select_read(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
2929 (struct sockaddr *)&addr, 2929 (struct sockaddr *)&addr,
2930 &fromlen); 2930 &fromlen);
2931 sa = (const struct sockaddr *)&addr; 2931 sa = (const struct sockaddr *)&addr;
2932#if MINGW 2932
2933 /* On SOCK_DGRAM UDP sockets recvfrom might fail with a
2934 * WSAECONNRESET error to indicate that previous sendto() (yes, sendto!)
2935 * on this socket has failed.
2936 * Quote from MSDN:
2937 * WSAECONNRESET - The virtual circuit was reset by the remote side
2938 * executing a hard or abortive close. The application should close
2939 * the socket; it is no longer usable. On a UDP-datagram socket this
2940 * error indicates a previous send operation resulted in an ICMP Port
2941 * Unreachable message.
2942 */
2943 if ((-1 == size) && (ECONNRESET == errno))
2944 return;
2945#endif
2946 if (-1 == size) 2933 if (-1 == size)
2947 { 2934 {
2948 LOG(GNUNET_ERROR_TYPE_DEBUG, 2935 LOG(GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/transport/plugin_transport_wlan.h b/src/transport/plugin_transport_wlan.h
index cdc3e34ff..bf1a90dba 100644
--- a/src/transport/plugin_transport_wlan.h
+++ b/src/transport/plugin_transport_wlan.h
@@ -32,12 +32,7 @@
32/** 32/**
33 * Number fo bytes in a mac address. 33 * Number fo bytes in a mac address.
34 */ 34 */
35#ifdef MINGW 35#define MAC_ADDR_SIZE 6
36 #define MAC_ADDR_SIZE 8
37typedef uint8_t u_int8_t;
38#else
39 #define MAC_ADDR_SIZE 6
40#endif
41 36
42/** 37/**
43 * Value for "Management" in the 'frame_control' field of the 38 * Value for "Management" in the 'frame_control' field of the
diff --git a/src/transport/tcp_service_legacy.c b/src/transport/tcp_service_legacy.c
index 8f3f43718..129511fec 100644
--- a/src/transport/tcp_service_legacy.c
+++ b/src/transport/tcp_service_legacy.c
@@ -849,95 +849,6 @@ LEGACY_SERVICE_get_server_addresses(
849} 849}
850 850
851 851
852#ifdef MINGW
853/**
854 * Read listen sockets from the parent process (ARM).
855 *
856 * @param sctx service context to initialize
857 * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
858 * and #GNUNET_SYSERR on error.
859 */
860static int
861receive_sockets_from_parent(struct LEGACY_SERVICE_Context *sctx)
862{
863 const char *env_buf;
864 int fail;
865 uint64_t count;
866 uint64_t i;
867 HANDLE lsocks_pipe;
868
869 env_buf = getenv("GNUNET_OS_READ_LSOCKS");
870 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
871 return GNUNET_NO;
872 /* Using W32 API directly here, because this pipe will
873 * never be used outside of this function, and it's just too much of a bother
874 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
875 */
876 lsocks_pipe = (HANDLE)strtoul(env_buf, NULL, 10);
877 if ((0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
878 return GNUNET_NO;
879 fail = 1;
880 do
881 {
882 int ret;
883 int fail2;
884 DWORD rd;
885
886 ret = ReadFile(lsocks_pipe, &count, sizeof(count), &rd, NULL);
887 if ((0 == ret) || (sizeof(count) != rd) || (0 == count))
888 break;
889 sctx->lsocks =
890 GNUNET_malloc(sizeof(struct GNUNET_NETWORK_Handle *) * (count + 1));
891
892 fail2 = 1;
893 for (i = 0; i < count; i++)
894 {
895 WSAPROTOCOL_INFOA pi;
896 uint64_t size;
897 socket s;
898
899 ret = ReadFile(lsocks_pipe, &size, sizeof(size), &rd, NULL);
900 if ((0 == ret) || (sizeof(size) != rd) || (sizeof(pi) != size))
901 break;
902 ret = ReadFile(lsocks_pipe, &pi, sizeof(pi), &rd, NULL);
903 if ((0 == ret) || (sizeof(pi) != rd))
904 break;
905 s = WSASocketA(pi.iAddressFamily,
906 pi.iSocketType,
907 pi.iProtocol,
908 &pi,
909 0,
910 WSA_FLAG_OVERLAPPED);
911 sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native(s);
912 if (NULL == sctx->lsocks[i])
913 break;
914 else if (i == count - 1)
915 fail2 = 0;
916 }
917 if (fail2)
918 break;
919 sctx->lsocks[count] = NULL;
920 fail = 0;
921 }
922 while (fail);
923
924 CloseHandle(lsocks_pipe);
925
926 if (fail)
927 {
928 LOG(GNUNET_ERROR_TYPE_ERROR,
929 _("Could not access a pre-bound socket, will try to bind myself\n"));
930 for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++)
931 GNUNET_break(0 == GNUNET_NETWORK_socket_close(sctx->lsocks[i]));
932 GNUNET_free_non_null(sctx->lsocks);
933 sctx->lsocks = NULL;
934 return GNUNET_NO;
935 }
936 return GNUNET_YES;
937}
938#endif
939
940
941/** 852/**
942 * Setup addr, addrlen, idle_timeout 853 * Setup addr, addrlen, idle_timeout
943 * based on configuration! 854 * based on configuration!
@@ -961,12 +872,9 @@ setup_service(struct LEGACY_SERVICE_Context *sctx)
961{ 872{
962 struct GNUNET_TIME_Relative idleout; 873 struct GNUNET_TIME_Relative idleout;
963 int tolerant; 874 int tolerant;
964
965#ifndef MINGW
966 const char *nfds; 875 const char *nfds;
967 unsigned int cnt; 876 unsigned int cnt;
968 int flags; 877 int flags;
969#endif
970 878
971 if (GNUNET_CONFIGURATION_have_value(sctx->cfg, 879 if (GNUNET_CONFIGURATION_have_value(sctx->cfg,
972 sctx->service_name, 880 sctx->service_name,
@@ -1007,7 +915,6 @@ setup_service(struct LEGACY_SERVICE_Context *sctx)
1007 else 915 else
1008 tolerant = GNUNET_NO; 916 tolerant = GNUNET_NO;
1009 917
1010#ifndef MINGW
1011 errno = 0; 918 errno = 0;
1012 if ((NULL != (nfds = getenv("LISTEN_FDS"))) && 919 if ((NULL != (nfds = getenv("LISTEN_FDS"))) &&
1013 (1 == sscanf(nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) && 920 (1 == sscanf(nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
@@ -1036,13 +943,6 @@ setup_service(struct LEGACY_SERVICE_Context *sctx)
1036 } 943 }
1037 unsetenv("LISTEN_FDS"); 944 unsetenv("LISTEN_FDS");
1038 } 945 }
1039#else
1040 if (getenv("GNUNET_OS_READ_LSOCKS") != NULL)
1041 {
1042 receive_sockets_from_parent(sctx);
1043 putenv("GNUNET_OS_READ_LSOCKS=");
1044 }
1045#endif
1046 946
1047 if ((NULL == sctx->lsocks) && 947 if ((NULL == sctx->lsocks) &&
1048 (GNUNET_SYSERR == LEGACY_SERVICE_get_server_addresses(sctx->service_name, 948 (GNUNET_SYSERR == LEGACY_SERVICE_get_server_addresses(sctx->service_name,
@@ -1257,7 +1157,6 @@ service_task(void *cls)
1257static int 1157static int
1258detach_terminal(struct LEGACY_SERVICE_Context *sctx) 1158detach_terminal(struct LEGACY_SERVICE_Context *sctx)
1259{ 1159{
1260#ifndef MINGW
1261 pid_t pid; 1160 pid_t pid;
1262 int nullfd; 1161 int nullfd;
1263 int filedes[2]; 1162 int filedes[2];
@@ -1324,11 +1223,7 @@ detach_terminal(struct LEGACY_SERVICE_Context *sctx)
1324 if (-1 == pid) 1223 if (-1 == pid)
1325 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid"); 1224 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid");
1326 sctx->ready_confirm_fd = filedes[1]; 1225 sctx->ready_confirm_fd = filedes[1];
1327#else 1226
1328 /* FIXME: we probably need to do something else
1329 * elsewhere in order to fork the process itself... */
1330 FreeConsole();
1331#endif
1332 return GNUNET_OK; 1227 return GNUNET_OK;
1333} 1228}
1334 1229
@@ -1346,7 +1241,7 @@ set_user_id(struct LEGACY_SERVICE_Context *sctx)
1346 1241
1347 if (NULL == (user = get_user_name(sctx))) 1242 if (NULL == (user = get_user_name(sctx)))
1348 return GNUNET_OK; /* keep */ 1243 return GNUNET_OK; /* keep */
1349#ifndef MINGW 1244
1350 struct passwd *pws; 1245 struct passwd *pws;
1351 1246
1352 errno = 0; 1247 errno = 0;
@@ -1377,7 +1272,7 @@ set_user_id(struct LEGACY_SERVICE_Context *sctx)
1377 return GNUNET_SYSERR; 1272 return GNUNET_SYSERR;
1378 } 1273 }
1379 } 1274 }
1380#endif 1275
1381 GNUNET_free(user); 1276 GNUNET_free(user);
1382 return GNUNET_OK; 1277 return GNUNET_OK;
1383} 1278}
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 647f09224..c240053ff 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -13,27 +13,7 @@ dist_pkgcfg_DATA = \
13pkgcfg_DATA = \ 13pkgcfg_DATA = \
14 resolver.conf 14 resolver.conf
15 15
16if MINGW 16TEST_CLIENT_UNIX_NC = test_client_unix.nc
17noinst_LTLIBRARIES = \
18 libgnunetutilwin.la
19libgnunetutilwin_la_SOURCES = \
20 win.c \
21 winproc.c
22libgnunetutilwin_la_LDFLAGS = \
23 -no-undefined -Wl,--export-all-symbols
24libgnunetutilwin_la_LIBADD = \
25 -lshell32 -liconv -lstdc++ \
26 -lcomdlg32 -lgdi32 -liphlpapi
27WINLIB = libgnunetutilwin.la
28W32CAT = w32cat
29W32CONSOLEHELPER = gnunet-helper-w32-console
30endif
31
32if !MINGW
33 TEST_CLIENT_UNIX_NC = test_client_unix.nc
34else
35 TEST_CLIENT_UNIX_NC =
36endif
37 17
38if USE_COVERAGE 18if USE_COVERAGE
39 AM_CFLAGS = --coverage -O0 19 AM_CFLAGS = --coverage -O0
@@ -45,14 +25,6 @@ if ENABLE_BENCHMARK
45 PTHREAD = -lpthread 25 PTHREAD = -lpthread
46endif 26endif
47 27
48w32cat_SOURCES = w32cat.c
49
50gnunet_helper_w32_console_SOURCES = \
51 gnunet-helper-w32-console.c \
52 gnunet-helper-w32-console.h
53gnunet_helper_w32_console_LDADD = \
54 libgnunetutil.la
55
56gnunet_config_diff_SOURCES = \ 28gnunet_config_diff_SOURCES = \
57 gnunet-config-diff.c 29 gnunet-config-diff.c
58gnunet_config_diff_LDADD = \ 30gnunet_config_diff_LDADD = \
@@ -202,8 +174,7 @@ lib_LTLIBRARIES = libgnunetutil.la
202 174
203libexec_PROGRAMS = \ 175libexec_PROGRAMS = \
204 gnunet-service-resolver \ 176 gnunet-service-resolver \
205 gnunet-timeout \ 177 gnunet-timeout
206 $(W32CONSOLEHELPER)
207 178
208bin_PROGRAMS = \ 179bin_PROGRAMS = \
209 gnunet-resolver \ 180 gnunet-resolver \
@@ -217,7 +188,6 @@ endif
217 188
218noinst_PROGRAMS = \ 189noinst_PROGRAMS = \
219 gnunet-config-diff \ 190 gnunet-config-diff \
220 $(W32CAT) \
221 test_common_logging_dummy 191 test_common_logging_dummy
222 192
223 193
@@ -228,14 +198,8 @@ endif
228 198
229endif 199endif
230 200
231
232if !MINGW
233gnunet_timeout_SOURCES = \ 201gnunet_timeout_SOURCES = \
234 gnunet-timeout.c 202 gnunet-timeout.c
235else
236gnunet_timeout_SOURCES = \
237 gnunet-timeout-w32.c
238endif
239 203
240gnunet_service_resolver_SOURCES = \ 204gnunet_service_resolver_SOURCES = \
241 gnunet-service-resolver.c 205 gnunet-service-resolver.c
@@ -393,8 +357,7 @@ test_os_start_process_SOURCES = \
393test_os_start_process_LDADD = \ 357test_os_start_process_LDADD = \
394 libgnunetutil.la 358 libgnunetutil.la
395test_os_start_process_DEPENDENCIES = \ 359test_os_start_process_DEPENDENCIES = \
396 libgnunetutil.la \ 360 libgnunetutil.la
397 $(WINCAT)
398 361
399test_client_nc_SOURCES = \ 362test_client_nc_SOURCES = \
400 test_client.c 363 test_client.c
diff --git a/src/util/disk.c b/src/util/disk.c
index 01d5efbe2..8b474542b 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -96,7 +96,6 @@ struct GetFileSizeData {
96}; 96};
97 97
98 98
99#ifndef MINGW
100/** 99/**
101 * Translate GNUnet-internal permission bitmap to UNIX file 100 * Translate GNUnet-internal permission bitmap to UNIX file
102 * access permission bitmap. 101 * access permission bitmap.
@@ -131,7 +130,6 @@ translate_unix_perms(enum GNUNET_DISK_AccessPermissions perm)
131 130
132 return mode; 131 return mode;
133} 132}
134#endif
135 133
136 134
137/** 135/**
@@ -191,11 +189,7 @@ getSizeRec(void *cls, const char *fn)
191int 189int
192GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h) 190GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
193{ 191{
194#ifdef MINGW
195 return ((!h) || (h->h == INVALID_HANDLE_VALUE)) ? GNUNET_YES : GNUNET_NO;
196#else
197 return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO; 192 return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
198#endif
199} 193}
200 194
201/** 195/**
@@ -236,26 +230,9 @@ GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h,
236 return GNUNET_SYSERR; 230 return GNUNET_SYSERR;
237 } 231 }
238 232
239#ifdef MINGW
240 LARGE_INTEGER li;
241 LARGE_INTEGER new_pos;
242 BOOL b;
243
244 static DWORD t[] = { FILE_BEGIN, FILE_CURRENT, FILE_END };
245 li.QuadPart = offset;
246
247 b = SetFilePointerEx(h->h, li, &new_pos, t[whence]);
248 if (b == 0)
249 {
250 SetErrnoFromWinError(GetLastError());
251 return GNUNET_SYSERR;
252 }
253 return (off_t)new_pos.QuadPart;
254#else
255 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END }; 233 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
256 234
257 return lseek(h->fd, offset, t[whence]); 235 return lseek(h->fd, offset, t[whence]);
258#endif
259} 236}
260 237
261 238
@@ -1296,7 +1273,7 @@ GNUNET_DISK_file_open(const char *fn,
1296 expfn = GNUNET_STRINGS_filename_expand(fn); 1273 expfn = GNUNET_STRINGS_filename_expand(fn);
1297 if (NULL == expfn) 1274 if (NULL == expfn)
1298 return NULL; 1275 return NULL;
1299#ifndef MINGW 1276
1300 mode = 0; 1277 mode = 0;
1301 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE)) 1278 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
1302 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */ 1279 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
@@ -1342,69 +1319,6 @@ GNUNET_DISK_file_open(const char *fn,
1342 GNUNET_free(expfn); 1319 GNUNET_free(expfn);
1343 return NULL; 1320 return NULL;
1344 } 1321 }
1345#else
1346 access = 0;
1347 disp = OPEN_ALWAYS;
1348
1349 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
1350 access = FILE_READ_DATA | FILE_WRITE_DATA;
1351 else if (flags & GNUNET_DISK_OPEN_READ)
1352 access = FILE_READ_DATA;
1353 else if (flags & GNUNET_DISK_OPEN_WRITE)
1354 access = FILE_WRITE_DATA;
1355
1356 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1357 {
1358 disp = CREATE_NEW;
1359 }
1360 else if (flags & GNUNET_DISK_OPEN_CREATE)
1361 {
1362 (void)GNUNET_DISK_directory_create_for_file(expfn);
1363 if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1364 disp = CREATE_ALWAYS;
1365 else
1366 disp = OPEN_ALWAYS;
1367 }
1368 else if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1369 {
1370 disp = TRUNCATE_EXISTING;
1371 }
1372 else
1373 {
1374 disp = OPEN_EXISTING;
1375 }
1376
1377 if (ERROR_SUCCESS == plibc_conv_to_win_pathwconv(expfn, wexpfn))
1378 h = CreateFileW(wexpfn,
1379 access,
1380 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1381 NULL,
1382 disp,
1383 FILE_ATTRIBUTE_NORMAL,
1384 NULL);
1385 else
1386 h = INVALID_HANDLE_VALUE;
1387 if (h == INVALID_HANDLE_VALUE)
1388 {
1389 int err;
1390 SetErrnoFromWinError(GetLastError());
1391 err = errno;
1392 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_INFO, "open", expfn);
1393 GNUNET_free(expfn);
1394 errno = err;
1395 return NULL;
1396 }
1397
1398 if (flags & GNUNET_DISK_OPEN_APPEND)
1399 if (SetFilePointer(h, 0, 0, FILE_END) == INVALID_SET_FILE_POINTER)
1400 {
1401 SetErrnoFromWinError(GetLastError());
1402 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "SetFilePointer", expfn);
1403 CloseHandle(h);
1404 GNUNET_free(expfn);
1405 return NULL;
1406 }
1407#endif
1408 1322
1409 ret = GNUNET_new(struct GNUNET_DISK_FileHandle); 1323 ret = GNUNET_new(struct GNUNET_DISK_FileHandle);
1410 1324
diff --git a/src/util/dnsstub.c b/src/util/dnsstub.c
index ab7a08318..fef4b5f5d 100644
--- a/src/util/dnsstub.c
+++ b/src/util/dnsstub.c
@@ -291,16 +291,12 @@ do_dns_read(struct GNUNET_DNSSTUB_RequestSocket *rs,
291 ssize_t r; 291 ssize_t r;
292 int len; 292 int len;
293 293
294#ifndef MINGW
295 if (0 != ioctl(GNUNET_NETWORK_get_fd(dnsout), FIONREAD, &len)) 294 if (0 != ioctl(GNUNET_NETWORK_get_fd(dnsout), FIONREAD, &len))
296 { 295 {
297 /* conservative choice: */ 296 /* conservative choice: */
298 len = UINT16_MAX; 297 len = UINT16_MAX;
299 } 298 }
300#else 299
301 /* port the code above? */
302 len = UINT16_MAX;
303#endif
304 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len); 300 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len);
305 { 301 {
306 unsigned char buf[len] GNUNET_ALIGN; 302 unsigned char buf[len] GNUNET_ALIGN;
diff --git a/src/util/gnunet-timeout-w32.c b/src/util/gnunet-timeout-w32.c
deleted file mode 100644
index 3e579714c..000000000
--- a/src/util/gnunet-timeout-w32.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/util/gnunet-timeout-w32.c
23 * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period
24 * @author LRN
25 */
26
27#include <windows.h>
28#include <sys/types.h>
29#include <stdio.h>
30
31int
32main(int argc, char *argv[])
33{
34 int i;
35 DWORD wait_result;
36 wchar_t *commandline;
37 wchar_t **wargv;
38 wchar_t *arg;
39 unsigned int cmdlen;
40 STARTUPINFOW start;
41 PROCESS_INFORMATION proc;
42
43 wchar_t wpath[MAX_PATH + 1];
44
45 wchar_t *pathbuf;
46 DWORD pathbuf_len, alloc_len;
47 wchar_t *ptr;
48 wchar_t *non_const_filename;
49 wchar_t *wcmd;
50 int wargc;
51 int timeout = 0;
52 ssize_t wrote;
53
54 HANDLE job;
55
56 if (argc < 3)
57 {
58 printf
59 ("arg 1: timeout in sec., arg 2: executable, arg<n> arguments\n");
60 exit(1);
61 }
62
63 timeout = atoi(argv[1]);
64
65 if (timeout == 0)
66 timeout = 600;
67
68 commandline = GetCommandLineW();
69 if (commandline == NULL)
70 {
71 printf("Failed to get commandline: %lu\n", GetLastError());
72 exit(2);
73 }
74
75 wargv = CommandLineToArgvW(commandline, &wargc);
76 if (wargv == NULL || wargc <= 1)
77 {
78 printf("Failed to get parse commandline: %lu\n", GetLastError());
79 exit(3);
80 }
81
82 job = CreateJobObject(NULL, NULL);
83 if (job == NULL)
84 {
85 printf("Failed to create a job: %lu\n", GetLastError());
86 exit(4);
87 }
88
89 pathbuf_len = GetEnvironmentVariableW(L"PATH", (wchar_t *)&pathbuf, 0);
90
91 alloc_len = pathbuf_len + 1;
92
93 pathbuf = malloc(alloc_len * sizeof(wchar_t));
94
95 ptr = pathbuf;
96
97 alloc_len = GetEnvironmentVariableW(L"PATH", ptr, pathbuf_len);
98
99 cmdlen = wcslen(wargv[2]);
100 if (cmdlen < 5 || wcscmp(&wargv[2][cmdlen - 4], L".exe") != 0)
101 {
102 non_const_filename = malloc(sizeof(wchar_t) * (cmdlen + 5));
103 swprintf(non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]);
104 }
105 else
106 {
107 non_const_filename = wcsdup(wargv[2]);
108 }
109
110 /* Check that this is the full path. If it isn't, search. */
111 if (non_const_filename[1] == L':')
112 swprintf(wpath, sizeof(wpath) / sizeof(wchar_t), L"%S", non_const_filename);
113 else if (!SearchPathW
114 (pathbuf, non_const_filename, NULL, sizeof(wpath) / sizeof(wchar_t),
115 wpath, NULL))
116 {
117 printf("Failed to get find executable: %lu\n", GetLastError());
118 exit(5);
119 }
120 free(pathbuf);
121 free(non_const_filename);
122
123 cmdlen = wcslen(wpath) + 4;
124 i = 3;
125 while (NULL != (arg = wargv[i++]))
126 cmdlen += wcslen(arg) + 4;
127
128 wcmd = malloc(sizeof(wchar_t) * (cmdlen + 1));
129 wrote = 0;
130 i = 2;
131 while (NULL != (arg = wargv[i++]))
132 {
133 /* This is to escape trailing slash */
134 wchar_t arg_lastchar = arg[wcslen(arg) - 1];
135 if (wrote == 0)
136 {
137 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath,
138 arg_lastchar == L'\\' ? L"\\" : L"");
139 }
140 else
141 {
142 if (wcschr(arg, L' ') != NULL)
143 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg,
144 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
145 else
146 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg,
147 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
148 }
149 }
150
151 LocalFree(wargv);
152
153 memset(&start, 0, sizeof(start));
154 start.cb = sizeof(start);
155
156 if (!CreateProcessW(wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
157 NULL, NULL, &start, &proc))
158 {
159 wprintf(L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError());
160 exit(6);
161 }
162
163 AssignProcessToJobObject(job, proc.hProcess);
164
165 ResumeThread(proc.hThread);
166 CloseHandle(proc.hThread);
167
168 free(wcmd);
169
170 wait_result = WaitForSingleObject(proc.hProcess, timeout * 1000);
171 if (wait_result == WAIT_OBJECT_0)
172 {
173 DWORD status;
174 wait_result = GetExitCodeProcess(proc.hProcess, &status);
175 CloseHandle(proc.hProcess);
176 if (wait_result != 0)
177 {
178 printf("Test process exited with result %lu\n", status);
179 TerminateJobObject(job, status);
180 exit(status);
181 }
182 printf("Test process exited (failed to obtain exit status)\n");
183 TerminateJobObject(job, 0);
184 exit(0);
185 }
186 printf("Child processes were killed after timeout of %u seconds\n",
187 timeout);
188 TerminateJobObject(job, 1);
189 CloseHandle(proc.hProcess);
190 exit(1);
191}
192
193/* end of timeout_watchdog_w32.c */
diff --git a/src/util/network.c b/src/util/network.c
index ec76424eb..6f8a8ff5a 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -759,10 +759,6 @@ GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc,
759 flags, 759 flags,
760 src_addr, 760 src_addr,
761 addrlen); 761 addrlen);
762#ifdef MINGW
763 if (SOCKET_ERROR == ret)
764 SetErrnoFromWinsockError(WSAGetLastError());
765#endif
766 return ret; 762 return ret;
767} 763}
768 764
@@ -792,10 +788,6 @@ GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc,
792 buffer, 788 buffer,
793 length, 789 length,
794 flags); 790 flags);
795#ifdef MINGW
796 if (SOCKET_ERROR == ret)
797 SetErrnoFromWinsockError(WSAGetLastError());
798#endif
799 return ret; 791 return ret;
800} 792}
801 793
@@ -827,10 +819,6 @@ GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc,
827 buffer, 819 buffer,
828 length, 820 length,
829 flags); 821 flags);
830#ifdef MINGW
831 if (SOCKET_ERROR == ret)
832 SetErrnoFromWinsockError(WSAGetLastError());
833#endif
834 return ret; 822 return ret;
835} 823}
836 824
@@ -865,10 +853,6 @@ GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc,
865 flags |= MSG_NOSIGNAL; 853 flags |= MSG_NOSIGNAL;
866#endif 854#endif
867 ret = sendto(desc->fd, message, length, flags, dest_addr, dest_len); 855 ret = sendto(desc->fd, message, length, flags, dest_addr, dest_len);
868#ifdef MINGW
869 if (SOCKET_ERROR == ret)
870 SetErrnoFromWinsockError(WSAGetLastError());
871#endif
872 return ret; 856 return ret;
873} 857}
874 858
@@ -897,10 +881,7 @@ GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd,
897 option_name, 881 option_name,
898 option_value, 882 option_value,
899 option_len); 883 option_len);
900#ifdef MINGW 884
901 if (SOCKET_ERROR == ret)
902 SetErrnoFromWinsockError(WSAGetLastError());
903#endif
904 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; 885 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
905} 886}
906 887
@@ -950,10 +931,7 @@ GNUNET_NETWORK_socket_shutdown(struct GNUNET_NETWORK_Handle *desc,
950 int ret; 931 int ret;
951 932
952 ret = shutdown(desc->fd, how); 933 ret = shutdown(desc->fd, how);
953#ifdef MINGW 934
954 if (0 != ret)
955 SetErrnoFromWinsockError(WSAGetLastError());
956#endif
957 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR; 935 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR;
958} 936}
959 937
@@ -1054,7 +1032,6 @@ void
1054GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst, 1032GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst,
1055 const struct GNUNET_NETWORK_FDSet *src) 1033 const struct GNUNET_NETWORK_FDSet *src)
1056{ 1034{
1057#ifndef MINGW
1058 int nfds; 1035 int nfds;
1059 1036
1060 for (nfds = src->nsds; nfds >= 0; nfds--) 1037 for (nfds = src->nsds; nfds >= 0; nfds--)
@@ -1062,31 +1039,6 @@ GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst,
1062 FD_SET(nfds, &dst->sds); 1039 FD_SET(nfds, &dst->sds);
1063 dst->nsds = GNUNET_MAX(dst->nsds, 1040 dst->nsds = GNUNET_MAX(dst->nsds,
1064 src->nsds); 1041 src->nsds);
1065#else
1066 /* This is MinGW32-specific implementation that relies on the code that
1067 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1068 * that fd being added is not already in the set.
1069 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1070 *
1071 * NOTE: I don't understand why the UNIX-logic wouldn't work
1072 * for the first part here as well. -CG
1073 */
1074 unsigned int i;
1075
1076 for (i = 0; i < src->sds.fd_count; i++)
1077 FD_SET(src->sds.fd_array[i],
1078 &dst->sds);
1079 dst->nsds = GNUNET_MAX(src->nsds,
1080 dst->nsds);
1081
1082 /* also copy over `struct GNUNET_DISK_FileHandle` array */
1083 if (dst->handles_pos + src->handles_pos > dst->handles_size)
1084 GNUNET_array_grow(dst->handles,
1085 dst->handles_size,
1086 ((dst->handles_pos + src->handles_pos) << 1));
1087 for (i = 0; i < src->handles_pos; i++)
1088 dst->handles[dst->handles_pos++] = src->handles[i];
1089#endif
1090} 1042}
1091 1043
1092 1044
@@ -1103,16 +1055,6 @@ GNUNET_NETWORK_fdset_copy(struct GNUNET_NETWORK_FDSet *to,
1103 FD_COPY(&from->sds, 1055 FD_COPY(&from->sds,
1104 &to->sds); 1056 &to->sds);
1105 to->nsds = from->nsds; 1057 to->nsds = from->nsds;
1106#ifdef MINGW
1107 if (from->handles_pos > to->handles_size)
1108 GNUNET_array_grow(to->handles,
1109 to->handles_size,
1110 from->handles_pos * 2);
1111 GNUNET_memcpy(to->handles,
1112 from->handles,
1113 from->handles_pos * sizeof(struct GNUNET_NETWORK_Handle *));
1114 to->handles_pos = from->handles_pos;
1115#endif
1116} 1058}
1117 1059
1118 1060
@@ -1217,13 +1159,6 @@ void
1217GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, 1159GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds,
1218 const struct GNUNET_DISK_FileHandle *h) 1160 const struct GNUNET_DISK_FileHandle *h)
1219{ 1161{
1220#ifdef MINGW
1221 if (fds->handles_pos == fds->handles_size)
1222 GNUNET_array_grow(fds->handles,
1223 fds->handles_size,
1224 fds->handles_size * 2 + 2);
1225 fds->handles[fds->handles_pos++] = h;
1226#else
1227 int fd; 1162 int fd;
1228 1163
1229 GNUNET_assert(GNUNET_OK == 1164 GNUNET_assert(GNUNET_OK ==
@@ -1234,7 +1169,6 @@ GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds,
1234 &fds->sds); 1169 &fds->sds);
1235 fds->nsds = GNUNET_MAX(fd + 1, 1170 fds->nsds = GNUNET_MAX(fd + 1,
1236 fds->nsds); 1171 fds->nsds);
1237#endif
1238} 1172}
1239 1173
1240 1174
@@ -1247,22 +1181,7 @@ void
1247GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds, 1181GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds,
1248 const struct GNUNET_DISK_FileHandle *h) 1182 const struct GNUNET_DISK_FileHandle *h)
1249{ 1183{
1250#ifdef MINGW
1251 if (fds->handles_pos == fds->handles_size)
1252 GNUNET_array_grow(fds->handles,
1253 fds->handles_size,
1254 fds->handles_size * 2 + 2);
1255 fds->handles[fds->handles_pos] = h;
1256 if (fds->handles[0] != h)
1257 {
1258 const struct GNUNET_DISK_FileHandle *bak = fds->handles[0];
1259 fds->handles[0] = h;
1260 fds->handles[fds->handles_pos] = bak;
1261 }
1262 fds->handles_pos++;
1263#else
1264 GNUNET_NETWORK_fdset_handle_set(fds, h); 1184 GNUNET_NETWORK_fdset_handle_set(fds, h);
1265#endif
1266} 1185}
1267 1186
1268 1187
@@ -1277,42 +1196,11 @@ int
1277GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds, 1196GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds,
1278 const struct GNUNET_DISK_FileHandle *h) 1197 const struct GNUNET_DISK_FileHandle *h)
1279{ 1198{
1280#ifdef MINGW
1281 unsigned int i;
1282
1283 for (i = 0; i < fds->handles_pos; i++)
1284 if (fds->handles[i] == h)
1285 return GNUNET_YES;
1286 return GNUNET_NO;
1287#else
1288 return FD_ISSET(h->fd, 1199 return FD_ISSET(h->fd,
1289 &fds->sds); 1200 &fds->sds);
1290#endif
1291} 1201}
1292 1202
1293 1203
1294#ifdef MINGW
1295/**
1296 * Numerically compare pointers to sort them.
1297 * Used to test for overlap in the arrays.
1298 *
1299 * @param p1 a pointer
1300 * @param p2 a pointer
1301 * @return -1, 0 or 1, if the p1 < p2, p1==p2 or p1 > p2.
1302 */
1303static int
1304ptr_cmp(const void *p1,
1305 const void *p2)
1306{
1307 if (p1 == p2)
1308 return 0;
1309 if ((intptr_t)p1 < (intptr_t)p2)
1310 return -1;
1311 return 1;
1312}
1313#endif
1314
1315
1316/** 1204/**
1317 * Checks if two fd sets overlap 1205 * Checks if two fd sets overlap
1318 * 1206 *
@@ -1324,7 +1212,6 @@ int
1324GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1, 1212GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1,
1325 const struct GNUNET_NETWORK_FDSet *fds2) 1213 const struct GNUNET_NETWORK_FDSet *fds2)
1326{ 1214{
1327#ifndef MINGW
1328 int nfds; 1215 int nfds;
1329 1216
1330 nfds = GNUNET_MIN(fds1->nsds, 1217 nfds = GNUNET_MIN(fds1->nsds,
@@ -1339,53 +1226,6 @@ GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1,
1339 return GNUNET_YES; 1226 return GNUNET_YES;
1340 } 1227 }
1341 return GNUNET_NO; 1228 return GNUNET_NO;
1342#else
1343 unsigned int i;
1344 unsigned int j;
1345
1346 /* This code is somewhat hacky, we are not supposed to know what's
1347 * inside of fd_set; also the O(n^2) is really bad... */
1348 for (i = 0; i < fds1->sds.fd_count; i++)
1349 for (j = 0; j < fds2->sds.fd_count; j++)
1350 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1351 return GNUNET_YES;
1352
1353 /* take a short cut if possible */
1354 if ((0 == fds1->handles_pos) ||
1355 (0 == fds2->handles_pos))
1356 return GNUNET_NO;
1357
1358 /* Sort file handles array to avoid quadratic complexity when
1359 checking for overlap */
1360 qsort(fds1->handles,
1361 fds1->handles_pos,
1362 sizeof(void *),
1363 &ptr_cmp);
1364 qsort(fds2->handles,
1365 fds2->handles_pos,
1366 sizeof(void *),
1367 &ptr_cmp);
1368 i = 0;
1369 j = 0;
1370 while ((i < fds1->handles_pos) &&
1371 (j < fds2->handles_pos))
1372 {
1373 switch (ptr_cmp(fds1->handles[i],
1374 fds2->handles[j]))
1375 {
1376 case -1:
1377 i++;
1378 break;
1379
1380 case 0:
1381 return GNUNET_YES;
1382
1383 case 1:
1384 j++;
1385 }
1386 }
1387 return GNUNET_NO;
1388#endif
1389} 1229}
1390 1230
1391 1231
@@ -1413,192 +1253,10 @@ GNUNET_NETWORK_fdset_create()
1413void 1253void
1414GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds) 1254GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
1415{ 1255{
1416#ifdef MINGW
1417 GNUNET_array_grow(fds->handles,
1418 fds->handles_size,
1419 0);
1420#endif
1421 GNUNET_free(fds); 1256 GNUNET_free(fds);
1422} 1257}
1423 1258
1424 1259
1425#if MINGW
1426/**
1427 * FIXME.
1428 */
1429struct _select_params {
1430 /**
1431 * Read set.
1432 */
1433 fd_set *r;
1434
1435 /**
1436 * Write set.
1437 */
1438 fd_set *w;
1439
1440 /**
1441 * Except set.
1442 */
1443 fd_set *e;
1444
1445 /**
1446 * Timeout for select().
1447 */
1448 struct timeval *tv;
1449
1450 /**
1451 * FIXME.
1452 */
1453 HANDLE wakeup;
1454
1455 /**
1456 * FIXME.
1457 */
1458 HANDLE standby;
1459
1460 /**
1461 * FIXME.
1462 */
1463 _win_socket wakeup_socket;
1464
1465 /**
1466 * Set to return value from select.
1467 */
1468 int status;
1469};
1470
1471
1472/**
1473 * FIXME.
1474 */
1475static DWORD WINAPI
1476_selector(LPVOID p)
1477{
1478 struct _select_params *sp = p;
1479
1480 while (1)
1481 {
1482 WaitForSingleObject(sp->standby,
1483 INFINITE);
1484 ResetEvent(sp->standby);
1485 sp->status = select(1,
1486 sp->r,
1487 sp->w,
1488 sp->e,
1489 sp->tv);
1490 if (FD_ISSET(sp->wakeup_socket,
1491 sp->r))
1492 {
1493 FD_CLR(sp->wakeup_socket,
1494 sp->r);
1495 sp->status -= 1;
1496 }
1497 SetEvent(sp->wakeup);
1498 }
1499 return 0;
1500}
1501
1502
1503static HANDLE hEventPipeWrite;
1504
1505static HANDLE hEventReadReady;
1506
1507static struct _select_params sp;
1508
1509static HANDLE select_thread;
1510
1511static HANDLE select_finished_event;
1512
1513static HANDLE select_standby_event;
1514
1515static _win_socket select_wakeup_socket = -1;
1516
1517static _win_socket select_send_socket = -1;
1518
1519static struct timeval select_timeout;
1520
1521
1522/**
1523 * On W32, we actually use a thread to help with the
1524 * event loop due to W32-API limitations. This function
1525 * initializes that thread.
1526 */
1527static void
1528initialize_select_thread()
1529{
1530 _win_socket select_listening_socket = -1;
1531 struct sockaddr_in s_in;
1532 int alen;
1533 int res;
1534 unsigned long p;
1535
1536 select_standby_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1537 select_finished_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1538
1539 select_wakeup_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1540
1541 select_listening_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1542
1543 p = 1;
1544 res = ioctlsocket(select_wakeup_socket, FIONBIO, &p);
1545 LOG(GNUNET_ERROR_TYPE_DEBUG,
1546 "Select thread initialization: ioctlsocket() returns %d\n",
1547 res);
1548
1549 alen = sizeof(s_in);
1550 s_in.sin_family = AF_INET;
1551 s_in.sin_port = 0;
1552 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1553 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1554 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1555 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1556 res = bind(select_listening_socket,
1557 (const struct sockaddr *)&s_in,
1558 sizeof(s_in));
1559 LOG(GNUNET_ERROR_TYPE_DEBUG,
1560 "Select thread initialization: bind() returns %d\n",
1561 res);
1562
1563 res = getsockname(select_listening_socket,
1564 (struct sockaddr *)&s_in,
1565 &alen);
1566 LOG(GNUNET_ERROR_TYPE_DEBUG,
1567 "Select thread initialization: getsockname() returns %d\n",
1568 res);
1569
1570 res = listen(select_listening_socket,
1571 SOMAXCONN);
1572 LOG(GNUNET_ERROR_TYPE_DEBUG,
1573 "Select thread initialization: listen() returns %d\n",
1574 res);
1575 res = connect(select_wakeup_socket,
1576 (const struct sockaddr *)&s_in,
1577 sizeof(s_in));
1578 LOG(GNUNET_ERROR_TYPE_DEBUG,
1579 "Select thread initialization: connect() returns %d\n",
1580 res);
1581
1582 select_send_socket = accept(select_listening_socket,
1583 (struct sockaddr *)&s_in,
1584 &alen);
1585
1586 closesocket(select_listening_socket);
1587
1588 sp.wakeup = select_finished_event;
1589 sp.standby = select_standby_event;
1590 sp.wakeup_socket = select_wakeup_socket;
1591
1592 select_thread = CreateThread(NULL,
1593 0,
1594 _selector,
1595 &sp,
1596 0, NULL);
1597}
1598
1599
1600#endif
1601
1602/** 1260/**
1603 * Test if the given @a port is available. 1261 * Test if the given @a port is available.
1604 * 1262 *
@@ -1657,7 +1315,6 @@ GNUNET_NETWORK_test_port_free(int ipproto,
1657} 1315}
1658 1316
1659 1317
1660#ifndef MINGW
1661/** 1318/**
1662 * Check if sockets or pipes meet certain conditions 1319 * Check if sockets or pipes meet certain conditions
1663 * 1320 *
@@ -1714,523 +1371,4 @@ GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1714 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv); 1371 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1715} 1372}
1716 1373
1717
1718#else
1719/* MINGW */
1720
1721
1722/**
1723 * Non-blocking test if a pipe is ready for reading.
1724 *
1725 * @param fh pipe handle
1726 * @return #GNUNET_YES if the pipe is ready for reading
1727 */
1728static int
1729pipe_read_ready(const struct GNUNET_DISK_FileHandle *fh)
1730{
1731 DWORD error;
1732 BOOL bret;
1733 DWORD waitstatus = 0;
1734
1735 SetLastError(0);
1736 bret = PeekNamedPipe(fh->h, NULL, 0, NULL, &waitstatus, NULL);
1737 error = GetLastError();
1738 if (0 == bret)
1739 {
1740 /* TODO: either add more errors to this condition, or eliminate it
1741 * entirely (failed to peek -> pipe is in serious trouble, should
1742 * be selected as readable).
1743 */
1744 if ((error != ERROR_BROKEN_PIPE) &&
1745 (error != ERROR_INVALID_HANDLE))
1746 return GNUNET_NO;
1747 }
1748 else if (waitstatus <= 0)
1749 return GNUNET_NO;
1750 return GNUNET_YES;
1751}
1752
1753
1754/**
1755 * Non-blocking test if a pipe is having an IO exception.
1756 *
1757 * @param fh pipe handle
1758 * @return #GNUNET_YES if the pipe is having an IO exception.
1759 */
1760static int
1761pipe_except_ready(const struct GNUNET_DISK_FileHandle *fh)
1762{
1763 DWORD dwBytes;
1764
1765 if (PeekNamedPipe(fh->h, NULL, 0, NULL, &dwBytes, NULL))
1766 return GNUNET_NO;
1767 return GNUNET_YES;
1768}
1769
1770
1771/**
1772 * Iterate over handles in fds, destructively rewrite the
1773 * handles array contents of fds so that it starts with the
1774 * handles that are ready, and update handles_pos accordingly.
1775 *
1776 * @param fds set of handles (usually pipes) to be checked for readiness
1777 * @param except GNUNET_NO if fds should be checked for readiness to read,
1778 * GNUNET_YES if fds should be checked for exceptions
1779 * (there is no way to check for write-readiness - pipes are always write-ready)
1780 * @param set_for_sure a HANDLE that is known to be set already,
1781 * because WaitForMultipleObjects() returned its index.
1782 * @return number of ready handles
1783 */
1784static int
1785check_handles_status(struct GNUNET_NETWORK_FDSet *fds,
1786 int except,
1787 HANDLE set_for_sure)
1788{
1789 const struct GNUNET_DISK_FileHandle *fh;
1790 unsigned int roff;
1791 unsigned int woff;
1792
1793 for (woff = 0, roff = 0; roff < fds->handles_pos; roff++)
1794 {
1795 fh = fds->handles[roff];
1796 if (fh == set_for_sure)
1797 {
1798 fds->handles[woff++] = fh;
1799 }
1800 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1801 {
1802 if ((except && pipe_except_ready(fh)) ||
1803 (!except && pipe_read_ready(fh)))
1804 fds->handles[woff++] = fh;
1805 }
1806 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_FILE)
1807 {
1808 if (!except)
1809 fds->handles[woff++] = fh;
1810 }
1811 else
1812 {
1813 if (WAIT_OBJECT_0 == WaitForSingleObject(fh->h, 0))
1814 fds->handles[woff++] = fh;
1815 }
1816 }
1817 fds->handles_pos = woff;
1818 return woff;
1819}
1820
1821
1822/**
1823 * Check if sockets or pipes meet certain conditions, version for W32.
1824 *
1825 * @param rfds set of sockets or pipes to be checked for readability
1826 * @param wfds set of sockets or pipes to be checked for writability
1827 * @param efds set of sockets or pipes to be checked for exceptions
1828 * @param timeout relative value when to return
1829 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1830 */
1831int
1832GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1833 struct GNUNET_NETWORK_FDSet *wfds,
1834 struct GNUNET_NETWORK_FDSet *efds,
1835 const struct GNUNET_TIME_Relative timeout)
1836{
1837 const struct GNUNET_DISK_FileHandle *fh;
1838 int nfds;
1839 int handles;
1840 unsigned int i;
1841 int retcode;
1842 uint64_t mcs_total;
1843 DWORD ms_rounded;
1844 int nhandles = 0;
1845 int read_pipes_off;
1846 HANDLE handle_array[FD_SETSIZE + 2];
1847 int returncode;
1848 int returnedpos = 0;
1849 int selectret;
1850 fd_set aread;
1851 fd_set awrite;
1852 fd_set aexcept;
1853
1854 nfds = 0;
1855 handles = 0;
1856 if (NULL != rfds)
1857 {
1858 nfds = GNUNET_MAX(nfds, rfds->nsds);
1859 handles += rfds->handles_pos;
1860 }
1861 if (NULL != wfds)
1862 {
1863 nfds = GNUNET_MAX(nfds, wfds->nsds);
1864 handles += wfds->handles_pos;
1865 }
1866 if (NULL != efds)
1867 {
1868 nfds = GNUNET_MAX(nfds, efds->nsds);
1869 handles += efds->handles_pos;
1870 }
1871
1872 if ((0 == nfds) &&
1873 (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == timeout.rel_value_us) &&
1874 (0 == handles))
1875 {
1876 GNUNET_break(0);
1877 LOG(GNUNET_ERROR_TYPE_ERROR,
1878 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1879 "select");
1880 }
1881#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1882 /* calculate how long we need to wait in microseconds */
1883 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1884 {
1885 mcs_total = INFINITE;
1886 ms_rounded = INFINITE;
1887 }
1888 else
1889 {
1890 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1891 ms_rounded = (DWORD)(mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1892 if (mcs_total > 0 && ms_rounded == 0)
1893 ms_rounded = 1;
1894 }
1895 /* select() may be used as a portable way to sleep */
1896 if (!(rfds || wfds || efds))
1897 {
1898 Sleep(ms_rounded);
1899 return 0;
1900 }
1901
1902 if (NULL == select_thread)
1903 initialize_select_thread();
1904
1905 FD_ZERO(&aread);
1906 FD_ZERO(&awrite);
1907 FD_ZERO(&aexcept);
1908 if (rfds)
1909 FD_COPY(&rfds->sds, &aread);
1910 if (wfds)
1911 FD_COPY(&wfds->sds, &awrite);
1912 if (efds)
1913 FD_COPY(&efds->sds, &aexcept);
1914
1915 /* Start by doing a fast check on sockets and pipes (without
1916 waiting). It is cheap, and is sufficient most of the time. By
1917 profiling we detected that to be true in 90% of the cases.
1918 */
1919
1920 /* Do the select now */
1921 select_timeout.tv_sec = 0;
1922 select_timeout.tv_usec = 0;
1923
1924 /* Copy all the writes to the except, so we can detect connect() errors */
1925 for (i = 0; i < awrite.fd_count; i++)
1926 FD_SET(awrite.fd_array[i],
1927 &aexcept);
1928 if ((aread.fd_count > 0) ||
1929 (awrite.fd_count > 0) ||
1930 (aexcept.fd_count > 0))
1931 selectret = select(1,
1932 (NULL != rfds) ? &aread : NULL,
1933 (NULL != wfds) ? &awrite : NULL,
1934 &aexcept,
1935 &select_timeout);
1936 else
1937 selectret = 0;
1938 if (-1 == selectret)
1939 {
1940 /* Throw an error early on, while we still have the context. */
1941 LOG(GNUNET_ERROR_TYPE_ERROR,
1942 "W32 select(%d, %d, %d) failed: %lu\n",
1943 rfds ? aread.fd_count : 0,
1944 wfds ? awrite.fd_count : 0,
1945 aexcept.fd_count,
1946 GetLastError());
1947 GNUNET_assert(0);
1948 }
1949
1950 /* Check aexcept, if something is in there and we copied that
1951 FD before to detect connect() errors, add it back to the
1952 write set to report errors. */
1953 if (NULL != wfds)
1954 for (i = 0; i < aexcept.fd_count; i++)
1955 if (FD_ISSET(aexcept.fd_array[i],
1956 &wfds->sds))
1957 FD_SET(aexcept.fd_array[i],
1958 &awrite);
1959
1960
1961 /* If our select returned something or is a 0-timed request, then
1962 also check the pipes and get out of here! */
1963 /* Sadly, it means code duplication :( */
1964 if ((selectret > 0) || (0 == mcs_total))
1965 {
1966 retcode = 0;
1967
1968 /* Read Pipes */
1969 if (rfds && (rfds->handles_pos > 0))
1970 retcode += check_handles_status(rfds, GNUNET_NO, NULL);
1971
1972 /* wfds handles remain untouched, on W32
1973 we pretend our pipes are "always" write-ready */
1974
1975 /* except pipes */
1976 if (efds && (efds->handles_pos > 0))
1977 retcode += check_handles_status(efds, GNUNET_YES, NULL);
1978
1979 if (rfds)
1980 {
1981 GNUNET_NETWORK_fdset_zero(rfds);
1982 if (selectret != -1)
1983 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, selectret);
1984 }
1985 if (wfds)
1986 {
1987 GNUNET_NETWORK_fdset_zero(wfds);
1988 if (selectret != -1)
1989 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, selectret);
1990 }
1991 if (efds)
1992 {
1993 GNUNET_NETWORK_fdset_zero(efds);
1994 if (selectret != -1)
1995 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, selectret);
1996 }
1997 if (-1 == selectret)
1998 return -1;
1999 /* Add our select() FDs to the total return value */
2000 retcode += selectret;
2001 return retcode;
2002 }
2003
2004 /* If we got this far, use slower implementation that is able to do a waiting select
2005 on both sockets and pipes simultaneously */
2006
2007 /* Events for pipes */
2008 if (!hEventReadReady)
2009 hEventReadReady = CreateEvent(NULL, TRUE, TRUE, NULL);
2010 if (!hEventPipeWrite)
2011 hEventPipeWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
2012 retcode = 0;
2013
2014 FD_ZERO(&aread);
2015 FD_ZERO(&awrite);
2016 FD_ZERO(&aexcept);
2017 if (rfds)
2018 FD_COPY(&rfds->sds, &aread);
2019 if (wfds)
2020 FD_COPY(&wfds->sds, &awrite);
2021 if (efds)
2022 FD_COPY(&efds->sds, &aexcept);
2023 /* We will first Add the PIPES to the events */
2024 /* Track how far in `handle_array` the read pipes go,
2025 so we may by-pass them quickly if none of them
2026 are selected. */
2027 read_pipes_off = 0;
2028 if (rfds && (rfds->handles_pos > 0))
2029 {
2030 for (i = 0; i < rfds->handles_pos; i++)
2031 {
2032 fh = rfds->handles[i];
2033 if (fh->type == GNUNET_DISK_HANLDE_TYPE_EVENT)
2034 {
2035 handle_array[nhandles++] = fh->h;
2036 continue;
2037 }
2038 if (fh->type != GNUNET_DISK_HANLDE_TYPE_PIPE)
2039 continue;
2040 /* Read zero bytes to check the status of the pipe */
2041 if (!ReadFile(fh->h, NULL, 0, NULL, fh->oOverlapRead))
2042 {
2043 DWORD error_code = GetLastError();
2044
2045 if (error_code == ERROR_IO_PENDING)
2046 {
2047 /* add as unready */
2048 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
2049 read_pipes_off++;
2050 }
2051 else
2052 {
2053 /* add as ready */
2054 handle_array[nhandles++] = hEventReadReady;
2055 read_pipes_off++;
2056 }
2057 }
2058 else
2059 {
2060 /* error also counts as ready */
2061 handle_array[nhandles++] = hEventReadReady;
2062 read_pipes_off++;
2063 }
2064 }
2065 }
2066
2067 if (wfds && (wfds->handles_pos > 0))
2068 {
2069 LOG(GNUNET_ERROR_TYPE_DEBUG,
2070 "Adding the write ready event to the array as %d\n",
2071 nhandles);
2072 handle_array[nhandles++] = hEventPipeWrite;
2073 }
2074
2075 sp.status = 0;
2076 if (nfds > 0)
2077 {
2078 LOG(GNUNET_ERROR_TYPE_DEBUG,
2079 "Adding the socket event to the array as %d\n",
2080 nhandles);
2081 handle_array[nhandles++] = select_finished_event;
2082 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2083 {
2084 sp.tv = NULL;
2085 }
2086 else
2087 {
2088 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
2089 select_timeout.tv_usec = (timeout.rel_value_us -
2090 (select_timeout.tv_sec *
2091 GNUNET_TIME_UNIT_SECONDS.rel_value_us));
2092 sp.tv = &select_timeout;
2093 }
2094 FD_SET(select_wakeup_socket, &aread);
2095 do
2096 {
2097 i = recv(select_wakeup_socket,
2098 (char *)&returnedpos,
2099 1,
2100 0);
2101 }
2102 while (i == 1);
2103 sp.r = &aread;
2104 sp.w = &awrite;
2105 sp.e = &aexcept;
2106 /* Failed connections cause sockets to be set in errorfds on W32,
2107 * but on POSIX it should set them in writefds.
2108 * First copy all awrite sockets to aexcept, later we'll
2109 * check aexcept and set its contents in awrite as well
2110 * Sockets are also set in errorfds when OOB data is available,
2111 * but we don't use OOB data.
2112 */
2113 for (i = 0; i < awrite.fd_count; i++)
2114 FD_SET(awrite.fd_array[i],
2115 &aexcept);
2116 ResetEvent(select_finished_event);
2117 SetEvent(select_standby_event);
2118 }
2119
2120 /* NULL-terminate array */
2121 handle_array[nhandles] = NULL;
2122 LOG(GNUNET_ERROR_TYPE_DEBUG,
2123 "nfds: %d, handles: %d, will wait: %llu mcs\n",
2124 nfds,
2125 nhandles,
2126 mcs_total);
2127 if (nhandles)
2128 {
2129 returncode
2130 = WaitForMultipleObjects(nhandles,
2131 handle_array,
2132 FALSE,
2133 ms_rounded);
2134 LOG(GNUNET_ERROR_TYPE_DEBUG,
2135 "WaitForMultipleObjects Returned: %d\n",
2136 returncode);
2137 }
2138 else if (nfds > 0)
2139 {
2140 GNUNET_break(0); /* This branch shouldn't actually be executed...*/
2141 i = (int)WaitForSingleObject(select_finished_event,
2142 INFINITE);
2143 returncode = WAIT_TIMEOUT;
2144 }
2145 else
2146 {
2147 /* Shouldn't come this far. If it does - investigate. */
2148 GNUNET_assert(0);
2149 }
2150
2151 if (nfds > 0)
2152 {
2153 /* Don't wake up select-thread when delay is 0, it should return immediately
2154 * and wake up by itself.
2155 */
2156 if (0 != mcs_total)
2157 i = send(select_send_socket,
2158 (const char *)&returnedpos,
2159 1,
2160 0);
2161 i = (int)WaitForSingleObject(select_finished_event,
2162 INFINITE);
2163 LOG(GNUNET_ERROR_TYPE_DEBUG,
2164 "Finished waiting for the select thread: %d %d\n",
2165 i,
2166 sp.status);
2167 if (0 != mcs_total)
2168 {
2169 do
2170 {
2171 i = recv(select_wakeup_socket,
2172 (char *)&returnedpos,
2173 1, 0);
2174 }
2175 while (1 == i);
2176 }
2177 /* Check aexcept, add its contents to awrite */
2178 for (i = 0; i < aexcept.fd_count; i++)
2179 FD_SET(aexcept.fd_array[i], &awrite);
2180 }
2181
2182 returnedpos = returncode - WAIT_OBJECT_0;
2183 LOG(GNUNET_ERROR_TYPE_DEBUG,
2184 "return pos is: %d\n",
2185 returnedpos);
2186
2187 if (rfds)
2188 {
2189 /* We queued a zero-long read on each pipe to check
2190 * its state, now we must cancel these read operations.
2191 * This must be done while rfds->handles_pos is still
2192 * intact and matches the number of read handles that we
2193 * got from the caller.
2194 */
2195 for (i = 0; i < rfds->handles_pos; i++)
2196 {
2197 fh = rfds->handles[i];
2198 if (GNUNET_DISK_HANLDE_TYPE_PIPE == fh->type)
2199 CancelIo(fh->h);
2200 }
2201
2202 /* We may have some pipes ready for reading. */
2203 if (returnedpos < read_pipes_off)
2204 retcode += check_handles_status(rfds, GNUNET_NO, handle_array[returnedpos]);
2205 else
2206 rfds->handles_pos = 0;
2207
2208 if (-1 != sp.status)
2209 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, retcode);
2210 }
2211 if (wfds)
2212 {
2213 retcode += wfds->handles_pos;
2214 /* wfds handles remain untouched */
2215 if (-1 != sp.status)
2216 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, retcode);
2217 }
2218 if (efds)
2219 {
2220 retcode += check_handles_status(rfds,
2221 GNUNET_YES,
2222 returnedpos < nhandles ? handle_array[returnedpos] : NULL);
2223 if (-1 != sp.status)
2224 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, retcode);
2225 }
2226
2227 if (sp.status > 0)
2228 retcode += sp.status;
2229
2230 return retcode;
2231}
2232
2233/* MINGW */
2234#endif
2235
2236/* end of network.c */ 1374/* end of network.c */
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index 104a98da6..c8590c8fb 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -764,26 +764,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
764 char *p; 764 char *p;
765 char *pf; 765 char *pf;
766 766
767#ifdef MINGW
768 char *binaryexe;
769
770 GNUNET_asprintf(&binaryexe, "%s.exe", binary);
771 if ((GNUNET_YES ==
772 GNUNET_STRINGS_path_is_absolute(binaryexe, GNUNET_NO, NULL, NULL)) ||
773 (0 == strncmp(binary, "./", 2)))
774 p = GNUNET_strdup(binaryexe);
775 else
776 {
777 p = get_path_from_PATH(binaryexe);
778 if (NULL != p)
779 {
780 GNUNET_asprintf(&pf, "%s/%s", p, binaryexe);
781 GNUNET_free(p);
782 p = pf;
783 }
784 }
785 GNUNET_free(binaryexe);
786#else
787 if ((GNUNET_YES == 767 if ((GNUNET_YES ==
788 GNUNET_STRINGS_path_is_absolute(binary, GNUNET_NO, NULL, NULL)) || 768 GNUNET_STRINGS_path_is_absolute(binary, GNUNET_NO, NULL, NULL)) ||
789 (0 == strncmp(binary, "./", 2))) 769 (0 == strncmp(binary, "./", 2)))
@@ -800,7 +780,7 @@ GNUNET_OS_check_helper_binary(const char *binary,
800 p = pf; 780 p = pf;
801 } 781 }
802 } 782 }
803#endif 783
804 if (NULL == p) 784 if (NULL == p)
805 { 785 {
806 LOG(GNUNET_ERROR_TYPE_INFO, 786 LOG(GNUNET_ERROR_TYPE_INFO,
@@ -814,14 +794,14 @@ GNUNET_OS_check_helper_binary(const char *binary,
814 GNUNET_free(p); 794 GNUNET_free(p);
815 return GNUNET_SYSERR; 795 return GNUNET_SYSERR;
816 } 796 }
817#ifndef MINGW 797
818 if (0 == getuid()) 798 if (0 == getuid())
819 { 799 {
820 /* as we run as root, we don't insist on SUID */ 800 /* as we run as root, we don't insist on SUID */
821 GNUNET_free(p); 801 GNUNET_free(p);
822 return GNUNET_YES; 802 return GNUNET_YES;
823 } 803 }
824#endif 804
825 if (0 != stat(p, &statbuf)) 805 if (0 != stat(p, &statbuf))
826 { 806 {
827 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "stat", p); 807 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "stat", p);
@@ -830,7 +810,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
830 } 810 }
831 if (check_suid) 811 if (check_suid)
832 { 812 {
833#ifndef MINGW
834 (void)params; 813 (void)params;
835 if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) 814 if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid))
836 { 815 {
@@ -841,57 +820,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
841 _("Binary `%s' exists, but is not SUID\n"), 820 _("Binary `%s' exists, but is not SUID\n"),
842 p); 821 p);
843 /* binary exists, but not SUID */ 822 /* binary exists, but not SUID */
844#else
845 STARTUPINFO start;
846 char parameters[512];
847 PROCESS_INFORMATION proc;
848 DWORD exit_value;
849
850 GNUNET_snprintf(parameters, sizeof(parameters), "-d %s", params);
851 memset(&start, 0, sizeof(start));
852 start.cb = sizeof(start);
853 memset(&proc, 0, sizeof(proc));
854
855
856 // Start the child process.
857 if (!(CreateProcess(
858 p, // current windows (2k3 and up can handle / instead of \ in paths))
859 parameters, // execute dryrun/priviliege checking mode
860 NULL, // Process handle not inheritable
861 NULL, // Thread handle not inheritable
862 FALSE, // Set handle inheritance to FALSE
863 CREATE_DEFAULT_ERROR_MODE, // No creation flags
864 NULL, // Use parent's environment block
865 NULL, // Use parent's starting directory
866 &start, // Pointer to STARTUPINFO structure
867 &proc) // Pointer to PROCESS_INFORMATION structure
868 ))
869 {
870 LOG(GNUNET_ERROR_TYPE_ERROR,
871 _("CreateProcess failed for binary %s (%d).\n"),
872 p,
873 GetLastError());
874 return GNUNET_SYSERR;
875 }
876
877 // Wait until child process exits.
878 WaitForSingleObject(proc.hProcess, INFINITE);
879
880 if (!GetExitCodeProcess(proc.hProcess, &exit_value))
881 {
882 LOG(GNUNET_ERROR_TYPE_ERROR,
883 _("GetExitCodeProcess failed for binary %s (%d).\n"),
884 p,
885 GetLastError());
886 return GNUNET_SYSERR;
887 }
888 // Close process and thread handles.
889 CloseHandle(proc.hProcess);
890 CloseHandle(proc.hThread);
891
892 if (!exit_value)
893 return GNUNET_YES;
894#endif
895 } 823 }
896 GNUNET_free(p); 824 GNUNET_free(p);
897 return GNUNET_NO; 825 return GNUNET_NO;
diff --git a/src/util/os_network.c b/src/util/os_network.c
index 4df37b9e5..526678047 100644
--- a/src/util/os_network.c
+++ b/src/util/os_network.c
@@ -35,7 +35,7 @@
35#define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-os-network", syscall, filename) 35#define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-os-network", syscall, filename)
36 36
37 37
38#if !(HAVE_GETIFADDRS && HAVE_FREEIFADDRS) && !MINGW 38#if !(HAVE_GETIFADDRS && HAVE_FREEIFADDRS)
39/** 39/**
40 * Try to enumerate all network interfaces using 'ifconfig'. 40 * Try to enumerate all network interfaces using 'ifconfig'.
41 * 41 *
@@ -388,32 +388,7 @@ void
388GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, 388GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc,
389 void *proc_cls) 389 void *proc_cls)
390{ 390{
391#ifdef MINGW 391#if HAVE_GETIFADDRS && HAVE_FREEIFADDRS
392 int r;
393 int i;
394 struct EnumNICs3_results *results = NULL;
395 int results_count;
396
397 r = EnumNICs3(&results, &results_count);
398 if (r != GNUNET_OK)
399 return;
400
401 for (i = 0; i < results_count; i++)
402 {
403 if (GNUNET_OK !=
404 proc(proc_cls, results[i].pretty_name, results[i].is_default,
405 (const struct sockaddr *)&results[i].address,
406 results[i].
407 flags & ENUMNICS3_BCAST_OK ?
408 (const struct sockaddr *)&results[i].broadcast : NULL,
409 results[i].flags & ENUMNICS3_MASK_OK ?
410 (const struct sockaddr *)&results[i].mask : NULL,
411 results[i].addr_size))
412 break;
413 }
414 EnumNICs3_free(results);
415 return;
416#elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS
417 struct ifaddrs *ifa_first; 392 struct ifaddrs *ifa_first;
418 struct ifaddrs *ifa_ptr; 393 struct ifaddrs *ifa_ptr;
419 socklen_t alen; 394 socklen_t alen;
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index ebe469b3b..e25623af5 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -350,7 +350,6 @@ start_process(int pipe_control,
350 const char *filename, 350 const char *filename,
351 char *const argv[]) 351 char *const argv[])
352{ 352{
353#ifndef MINGW
354 pid_t ret; 353 pid_t ret;
355 char fds[16]; 354 char fds[16];
356 struct GNUNET_OS_Process *gnunet_proc; 355 struct GNUNET_OS_Process *gnunet_proc;
@@ -464,7 +463,7 @@ start_process(int pipe_control,
464 GNUNET_array_append(lscp, ls, -1); 463 GNUNET_array_append(lscp, ls, -1);
465 } 464 }
466#if DARWIN 465#if DARWIN
467 /* see https://gnunet.org/vfork */ 466 /* see https://web.archive.org/web/20150924082249/gnunet.org/vfork */
468 ret = vfork(); 467 ret = vfork();
469#else 468#else
470 ret = fork(); 469 ret = fork();
@@ -589,547 +588,6 @@ start_process(int pipe_control,
589 execvp(filename, argv); 588 execvp(filename, argv);
590 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename); 589 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
591 _exit(1); 590 _exit(1);
592#else
593 struct GNUNET_DISK_FileHandle *childpipe_read;
594 struct GNUNET_DISK_FileHandle *childpipe_write;
595 HANDLE childpipe_read_handle;
596 char **arg;
597 char **non_const_argv;
598 unsigned int cmdlen;
599 char *cmd;
600 char *idx;
601 STARTUPINFOW start;
602 PROCESS_INFORMATION proc;
603 int argcount = 0;
604 struct GNUNET_OS_Process *gnunet_proc;
605 char path[MAX_PATH + 1];
606 char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
607 char *env_block = NULL;
608 char *pathbuf;
609 DWORD pathbuf_len;
610 DWORD alloc_len;
611 char *self_prefix;
612 char *bindir;
613 char *libdir;
614 char *ptr;
615 char *non_const_filename;
616 char win_path[MAX_PATH + 1];
617 struct GNUNET_DISK_PipeHandle *lsocks_pipe;
618 const struct GNUNET_DISK_FileHandle *lsocks_write_fd;
619 HANDLE lsocks_read;
620 HANDLE lsocks_write;
621 wchar_t *wpath;
622 wchar_t *wcmd;
623 size_t wpath_len;
624 size_t wcmd_len;
625 int env_off;
626 int fail;
627 long lRet;
628 HANDLE stdin_handle;
629 HANDLE stdout_handle;
630 HANDLE stdih, stdoh, stdeh;
631 DWORD stdif, stdof, stdef;
632 BOOL bresult;
633 DWORD error_code;
634 DWORD create_no_window;
635
636 if (GNUNET_SYSERR ==
637 GNUNET_OS_check_helper_binary(filename, GNUNET_NO, NULL))
638 return NULL; /* not executable */
639
640 /* Search in prefix dir (hopefully - the directory from which
641 * the current module was loaded), bindir and libdir, then in PATH
642 */
643 self_prefix = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_SELF_PREFIX);
644 bindir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_BINDIR);
645 libdir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_LIBDIR);
646
647 pathbuf_len = GetEnvironmentVariableA("PATH", (char *)&pathbuf, 0);
648
649 alloc_len = pathbuf_len + 1 + strlen(self_prefix) + 1 + strlen(bindir) + 1 +
650 strlen(libdir);
651
652 pathbuf = GNUNET_malloc(alloc_len * sizeof(char));
653
654 ptr = pathbuf;
655 ptr += sprintf(pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
656 GNUNET_free(self_prefix);
657 GNUNET_free(bindir);
658 GNUNET_free(libdir);
659
660 alloc_len = GetEnvironmentVariableA("PATH", ptr, pathbuf_len);
661 if (alloc_len != pathbuf_len - 1)
662 {
663 GNUNET_free(pathbuf);
664 errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */
665 return NULL;
666 }
667
668 cmdlen = strlen(filename);
669 if ((cmdlen < 5) || (0 != strcmp(&filename[cmdlen - 4], ".exe")))
670 GNUNET_asprintf(&non_const_filename, "%s.exe", filename);
671 else
672 GNUNET_asprintf(&non_const_filename, "%s", filename);
673
674 /* It could be in POSIX form, convert it to a DOS path early on */
675 if (ERROR_SUCCESS !=
676 (lRet = plibc_conv_to_win_path(non_const_filename, win_path)))
677 {
678 SetErrnoFromWinError(lRet);
679 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR,
680 "plibc_conv_to_win_path",
681 non_const_filename);
682 GNUNET_free(non_const_filename);
683 GNUNET_free(pathbuf);
684 return NULL;
685 }
686 GNUNET_free(non_const_filename);
687 non_const_filename = GNUNET_strdup(win_path);
688 /* Check that this is the full path. If it isn't, search. */
689 /* FIXME: convert it to wchar_t and use SearchPathW?
690 * Remember: arguments to _start_process() are technically in UTF-8...
691 */
692 if (non_const_filename[1] == ':')
693 {
694 snprintf(path, sizeof(path) / sizeof(char), "%s", non_const_filename);
695 LOG(GNUNET_ERROR_TYPE_DEBUG,
696 "Using path `%s' as-is. PATH is %s\n",
697 path,
698 ptr);
699 }
700 else if (!SearchPathA(pathbuf,
701 non_const_filename,
702 NULL,
703 sizeof(path) / sizeof(char),
704 path,
705 NULL))
706 {
707 SetErrnoFromWinError(GetLastError());
708 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR,
709 "SearchPath",
710 non_const_filename);
711 GNUNET_free(non_const_filename);
712 GNUNET_free(pathbuf);
713 return NULL;
714 }
715 else
716 LOG(GNUNET_ERROR_TYPE_DEBUG, "Found `%s' in PATH `%s'\n", path, pathbuf);
717 GNUNET_free(pathbuf);
718 GNUNET_free(non_const_filename);
719
720 /* Count the number of arguments */
721 arg = (char **)argv;
722 while (*arg)
723 {
724 arg++;
725 argcount++;
726 }
727
728 /* Allocate a copy argv */
729 non_const_argv = GNUNET_malloc(sizeof(char *) * (argcount + 1));
730
731 /* Copy all argv strings */
732 argcount = 0;
733 arg = (char **)argv;
734 while (*arg)
735 {
736 if (arg == argv)
737 non_const_argv[argcount] = GNUNET_strdup(path);
738 else
739 non_const_argv[argcount] = GNUNET_strdup(*arg);
740 arg++;
741 argcount++;
742 }
743 non_const_argv[argcount] = NULL;
744
745 /* Count cmd len */
746 cmdlen = 1;
747 arg = non_const_argv;
748 while (*arg)
749 {
750 cmdlen = cmdlen + strlen(*arg) + 4;
751 arg++;
752 }
753
754 /* Allocate and create cmd */
755 cmd = idx = GNUNET_malloc(sizeof(char) * cmdlen);
756 arg = non_const_argv;
757 while (*arg)
758 {
759 char arg_last_char = (*arg)[strlen(*arg) - 1];
760 idx += sprintf(idx,
761 "\"%s%s\"%s",
762 *arg,
763 arg_last_char == '\\' ? "\\" : "",
764 *(arg + 1) ? " " : "");
765 arg++;
766 }
767
768 while (argcount > 0)
769 GNUNET_free(non_const_argv[--argcount]);
770 GNUNET_free(non_const_argv);
771
772 memset(&start, 0, sizeof(start));
773 start.cb = sizeof(start);
774 if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0))
775 start.dwFlags |= STARTF_USESTDHANDLES;
776
777 stdih = GetStdHandle(STD_INPUT_HANDLE);
778 GetHandleInformation(stdih, &stdif);
779 if (pipe_stdin != NULL)
780 {
781 GNUNET_DISK_internal_file_handle_(
782 GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ),
783 &stdin_handle,
784 sizeof(HANDLE));
785 start.hStdInput = stdin_handle;
786 }
787 else if (stdih)
788 {
789 if (std_inheritance & GNUNET_OS_INHERIT_STD_IN)
790 {
791 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 1);
792 if (pipe_stdin == NULL)
793 start.hStdInput = stdih;
794 }
795 else
796 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 0);
797 }
798
799
800 stdoh = GetStdHandle(STD_OUTPUT_HANDLE);
801 GetHandleInformation(stdoh, &stdof);
802 if (NULL != pipe_stdout)
803 {
804 GNUNET_DISK_internal_file_handle_(
805 GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE),
806 &stdout_handle,
807 sizeof(HANDLE));
808 start.hStdOutput = stdout_handle;
809 }
810 else if (stdoh)
811 {
812 if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT)
813 {
814 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 1);
815 if (pipe_stdout == NULL)
816 start.hStdOutput = stdoh;
817 }
818 else
819 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 0);
820 }
821
822 stdeh = GetStdHandle(STD_ERROR_HANDLE);
823 GetHandleInformation(stdeh, &stdef);
824 if (stdeh)
825 {
826 if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR)
827 {
828 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 1);
829 start.hStdError = stdeh;
830 }
831 else
832 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 0);
833 }
834
835 if (GNUNET_YES == pipe_control)
836 {
837 struct GNUNET_DISK_PipeHandle *childpipe;
838 childpipe = GNUNET_DISK_pipe(GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
839 if (NULL == childpipe)
840 return NULL;
841 childpipe_read =
842 GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_READ);
843 childpipe_write =
844 GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_WRITE);
845 GNUNET_DISK_pipe_close(childpipe);
846 if ((NULL == childpipe_read) || (NULL == childpipe_write) ||
847 (GNUNET_OK != GNUNET_DISK_internal_file_handle_(childpipe_read,
848 &childpipe_read_handle,
849 sizeof(HANDLE))))
850 {
851 if (childpipe_read)
852 GNUNET_DISK_file_close(childpipe_read);
853 if (childpipe_write)
854 GNUNET_DISK_file_close(childpipe_write);
855 GNUNET_free(cmd);
856 return NULL;
857 }
858 /* Unlike *nix variant, we don't dup the handle, so can't close
859 * filehandle right now.
860 */
861 SetHandleInformation(childpipe_read_handle, HANDLE_FLAG_INHERIT, 1);
862 }
863 else
864 {
865 childpipe_read = NULL;
866 childpipe_write = NULL;
867 }
868
869 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
870 {
871 lsocks_pipe =
872 GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
873
874 if (lsocks_pipe == NULL)
875 {
876 GNUNET_free(cmd);
877 GNUNET_DISK_pipe_close(lsocks_pipe);
878 if (GNUNET_YES == pipe_control)
879 {
880 GNUNET_DISK_file_close(childpipe_write);
881 GNUNET_DISK_file_close(childpipe_read);
882 }
883 return NULL;
884 }
885 lsocks_write_fd =
886 GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_WRITE);
887 GNUNET_DISK_internal_file_handle_(lsocks_write_fd,
888 &lsocks_write,
889 sizeof(HANDLE));
890 GNUNET_DISK_internal_file_handle_(
891 GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_READ),
892 &lsocks_read,
893 sizeof(HANDLE));
894 }
895 else
896 {
897 lsocks_pipe = NULL;
898 lsocks_write_fd = NULL;
899 }
900
901 env_off = 0;
902 if (GNUNET_YES == pipe_control)
903 {
904 GNUNET_asprintf(&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE);
905 GNUNET_asprintf(&our_env[env_off++], "%p", childpipe_read_handle);
906 }
907 if ((lsocks != NULL) && (lsocks[0] != INVALID_SOCKET))
908 {
909 /*This will tell the child that we're going to send lsocks over the pipe*/
910 GNUNET_asprintf(&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS");
911 GNUNET_asprintf(&our_env[env_off++], "%lu", lsocks_read);
912 }
913 our_env[env_off++] = NULL;
914 env_block = CreateCustomEnvTable(our_env);
915 while (0 > env_off)
916 GNUNET_free_non_null(our_env[--env_off]);
917
918 wpath_len = 0;
919 if (NULL ==
920 (wpath =
921 u8_to_u16((uint8_t *)path, 1 + strlen(path), NULL, &wpath_len)))
922 {
923 LOG(GNUNET_ERROR_TYPE_DEBUG,
924 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n",
925 path,
926 errno);
927 GNUNET_free(env_block);
928 GNUNET_free(cmd);
929 if (lsocks_pipe)
930 GNUNET_DISK_pipe_close(lsocks_pipe);
931 if (GNUNET_YES == pipe_control)
932 {
933 GNUNET_DISK_file_close(childpipe_write);
934 GNUNET_DISK_file_close(childpipe_read);
935 }
936 return NULL;
937 }
938
939 wcmd_len = 0;
940 if (NULL ==
941 (wcmd = u8_to_u16((uint8_t *)cmd, 1 + strlen(cmd), NULL, &wcmd_len)))
942 {
943 LOG(GNUNET_ERROR_TYPE_DEBUG,
944 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n",
945 cmd,
946 errno);
947 GNUNET_free(env_block);
948 GNUNET_free(cmd);
949 free(wpath);
950 if (lsocks_pipe)
951 GNUNET_DISK_pipe_close(lsocks_pipe);
952 if (GNUNET_YES == pipe_control)
953 {
954 GNUNET_DISK_file_close(childpipe_write);
955 GNUNET_DISK_file_close(childpipe_read);
956 }
957 return NULL;
958 }
959
960 create_no_window = 0;
961 {
962 HANDLE console_input = CreateFile("CONIN$",
963 GENERIC_READ,
964 FILE_SHARE_READ | FILE_SHARE_WRITE,
965 NULL,
966 OPEN_EXISTING,
967 0,
968 NULL);
969 if (INVALID_HANDLE_VALUE == console_input)
970 create_no_window = CREATE_NO_WINDOW;
971 else
972 CloseHandle(console_input);
973 }
974
975 bresult = CreateProcessW(wpath,
976 wcmd,
977 NULL,
978 NULL,
979 GNUNET_YES,
980 create_no_window | CREATE_SUSPENDED,
981 env_block,
982 NULL,
983 &start,
984 &proc);
985 error_code = GetLastError();
986
987 if ((NULL == pipe_stdin) && (stdih))
988 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, stdif);
989
990
991 if ((NULL == pipe_stdout) && (stdoh))
992 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, stdof);
993
994 if (stdeh)
995 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, stdef);
996
997 if (!bresult)
998 LOG(GNUNET_ERROR_TYPE_ERROR,
999 "CreateProcess(%s, %s) failed: %lu\n",
1000 path,
1001 cmd,
1002 error_code);
1003
1004 GNUNET_free(env_block);
1005 GNUNET_free(cmd);
1006 free(wpath);
1007 free(wcmd);
1008 if (GNUNET_YES == pipe_control)
1009 {
1010 GNUNET_DISK_file_close(childpipe_read);
1011 }
1012
1013 if (!bresult)
1014 {
1015 if (GNUNET_YES == pipe_control)
1016 {
1017 GNUNET_DISK_file_close(childpipe_write);
1018 }
1019 if (NULL != lsocks)
1020 GNUNET_DISK_pipe_close(lsocks_pipe);
1021 SetErrnoFromWinError(error_code);
1022 return NULL;
1023 }
1024
1025 gnunet_proc = GNUNET_new(struct GNUNET_OS_Process);
1026 gnunet_proc->pid = proc.dwProcessId;
1027 gnunet_proc->handle = proc.hProcess;
1028 gnunet_proc->control_pipe = childpipe_write;
1029
1030 CreateThread(NULL, 64000, &child_wait_thread, (void *)gnunet_proc, 0, NULL);
1031
1032 ResumeThread(proc.hThread);
1033 CloseHandle(proc.hThread);
1034
1035 if ((NULL == lsocks) || (INVALID_SOCKET == lsocks[0]))
1036 return gnunet_proc;
1037
1038 GNUNET_DISK_pipe_close_end(lsocks_pipe, GNUNET_DISK_PIPE_END_READ);
1039
1040 /* This is a replacement for "goto error" that doesn't use goto */
1041 fail = 1;
1042 do
1043 {
1044 ssize_t wrote;
1045 uint64_t size;
1046 uint64_t count;
1047 unsigned int i;
1048
1049 /* Tell the number of sockets */
1050 for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++)
1051 ;
1052
1053 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count));
1054 if (sizeof(count) != wrote)
1055 {
1056 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1057 "Failed to write %u count bytes to the child: %lu\n",
1058 sizeof(count),
1059 GetLastError());
1060 break;
1061 }
1062 for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++)
1063 {
1064 WSAPROTOCOL_INFOA pi;
1065 /* Get a socket duplication info */
1066 if (SOCKET_ERROR ==
1067 WSADuplicateSocketA(lsocks[i], gnunet_proc->pid, &pi))
1068 {
1069 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1070 "Failed to duplicate an socket[%u]: %lu\n",
1071 i,
1072 GetLastError());
1073 break;
1074 }
1075 /* Synchronous I/O is not nice, but we can't schedule this:
1076 * lsocks will be closed/freed by the caller soon, and until
1077 * the child creates a duplicate, closing a socket here will
1078 * close it for good.
1079 */
1080 /* Send the size of the structure
1081 * (the child might be built with different headers...)
1082 */
1083 size = sizeof(pi);
1084 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &size, sizeof(size));
1085 if (sizeof(size) != wrote)
1086 {
1087 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1088 "Failed to write %u size[%u] bytes to the child: %lu\n",
1089 sizeof(size),
1090 i,
1091 GetLastError());
1092 break;
1093 }
1094 /* Finally! Send the data */
1095 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &pi, sizeof(pi));
1096 if (sizeof(pi) != wrote)
1097 {
1098 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1099 "Failed to write %u socket[%u] bytes to the child: %lu\n",
1100 sizeof(pi),
1101 i,
1102 GetLastError());
1103 break;
1104 }
1105 }
1106 /* This will block us until the child makes a final read or closes
1107 * the pipe (hence no 'wrote' check), since we have to wait for it
1108 * to duplicate the last socket, before we return and start closing
1109 * our own copies)
1110 */
1111 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count));
1112 fail = 0;
1113 }
1114 while (fail);
1115
1116 GNUNET_DISK_file_sync(lsocks_write_fd);
1117 GNUNET_DISK_pipe_close(lsocks_pipe);
1118
1119 if (fail)
1120 {
1121 /* If we can't pass on the socket(s), the child will block forever,
1122 * better put it out of its misery.
1123 */
1124 SafeTerminateProcess(gnunet_proc->handle, 0, 0);
1125 CloseHandle(gnunet_proc->handle);
1126 if (NULL != gnunet_proc->control_pipe)
1127 GNUNET_DISK_file_close(gnunet_proc->control_pipe);
1128 GNUNET_free(gnunet_proc);
1129 return NULL;
1130 }
1131 return gnunet_proc;
1132#endif
1133} 591}
1134 592
1135 593
@@ -1439,7 +897,6 @@ process_status(struct GNUNET_OS_Process *proc,
1439 unsigned long *code, 897 unsigned long *code,
1440 int options) 898 int options)
1441{ 899{
1442#ifndef MINGW
1443 int status; 900 int status;
1444 int ret; 901 int ret;
1445 902
@@ -1488,53 +945,6 @@ process_status(struct GNUNET_OS_Process *proc,
1488 *type = GNUNET_OS_PROCESS_UNKNOWN; 945 *type = GNUNET_OS_PROCESS_UNKNOWN;
1489 *code = 0; 946 *code = 0;
1490 } 947 }
1491#else
1492#ifndef WNOHANG
1493#define WNOHANG 42 /* just a flag for W32, purely internal at this point */
1494#endif
1495
1496 HANDLE h;
1497 DWORD c, error_code, ret;
1498
1499 h = proc->handle;
1500 ret = proc->pid;
1501 if (h == NULL || ret == 0)
1502 {
1503 LOG(GNUNET_ERROR_TYPE_WARNING,
1504 "Invalid process information {%d, %08X}\n",
1505 ret,
1506 h);
1507 return GNUNET_SYSERR;
1508 }
1509 if (h == NULL)
1510 h = GetCurrentProcess();
1511
1512 if (WNOHANG != options)
1513 {
1514 if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE))
1515 {
1516 SetErrnoFromWinError(GetLastError());
1517 return GNUNET_SYSERR;
1518 }
1519 }
1520 SetLastError(0);
1521 ret = GetExitCodeProcess(h, &c);
1522 error_code = GetLastError();
1523 if (ret == 0 || error_code != NO_ERROR)
1524 {
1525 SetErrnoFromWinError(error_code);
1526 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetExitCodeProcess");
1527 return GNUNET_SYSERR;
1528 }
1529 if (STILL_ACTIVE == c)
1530 {
1531 *type = GNUNET_OS_PROCESS_RUNNING;
1532 *code = 0;
1533 return GNUNET_NO;
1534 }
1535 *type = GNUNET_OS_PROCESS_EXITED;
1536 *code = c;
1537#endif
1538 948
1539 return GNUNET_OK; 949 return GNUNET_OK;
1540} 950}
@@ -1589,7 +999,6 @@ GNUNET_OS_process_wait_status(struct GNUNET_OS_Process *proc,
1589int 999int
1590GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) 1000GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
1591{ 1001{
1592#ifndef MINGW
1593 pid_t pid = proc->pid; 1002 pid_t pid = proc->pid;
1594 pid_t ret; 1003 pid_t ret;
1595 1004
@@ -1601,28 +1010,6 @@ GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
1601 return GNUNET_SYSERR; 1010 return GNUNET_SYSERR;
1602 } 1011 }
1603 return GNUNET_OK; 1012 return GNUNET_OK;
1604#else
1605 HANDLE h;
1606
1607 h = proc->handle;
1608 if (NULL == h)
1609 {
1610 LOG(GNUNET_ERROR_TYPE_WARNING,
1611 "Invalid process information {%d, %08X}\n",
1612 proc->pid,
1613 h);
1614 return GNUNET_SYSERR;
1615 }
1616 if (NULL == h)
1617 h = GetCurrentProcess();
1618
1619 if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE))
1620 {
1621 SetErrnoFromWinError(GetLastError());
1622 return GNUNET_SYSERR;
1623 }
1624 return GNUNET_OK;
1625#endif
1626} 1013}
1627 1014
1628 1015
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 4bea5bd5d..f379bce42 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -108,7 +108,6 @@ struct GNUNET_SCHEDULER_Handle {
108 struct GNUNET_SIGNAL_Context *shc_gterm; 108 struct GNUNET_SIGNAL_Context *shc_gterm;
109#endif 109#endif
110 110
111#ifndef MINGW
112 /** 111 /**
113 * context of the SIGQUIT handler 112 * context of the SIGQUIT handler
114 */ 113 */
@@ -123,7 +122,6 @@ struct GNUNET_SCHEDULER_Handle {
123 * context of hte SIGPIPE handler 122 * context of hte SIGPIPE handler
124 */ 123 */
125 struct GNUNET_SIGNAL_Context *shc_pipe; 124 struct GNUNET_SIGNAL_Context *shc_pipe;
126#endif
127}; 125};
128 126
129 127
@@ -621,13 +619,11 @@ static pid_t my_pid;
621/** 619/**
622 * Signal handler called for SIGPIPE. 620 * Signal handler called for SIGPIPE.
623 */ 621 */
624#ifndef MINGW
625static void 622static void
626sighandler_pipe() 623sighandler_pipe()
627{ 624{
628 return; 625 return;
629} 626}
630#endif
631 627
632 628
633///** 629///**
@@ -1396,7 +1392,6 @@ check_fd(struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1396 * @return unique task identifier for the job 1392 * @return unique task identifier for the job
1397 * only valid until @a task is started! 1393 * only valid until @a task is started!
1398 */ 1394 */
1399#ifndef MINGW
1400static struct GNUNET_SCHEDULER_Task * 1395static struct GNUNET_SCHEDULER_Task *
1401add_without_sets(struct GNUNET_TIME_Relative delay, 1396add_without_sets(struct GNUNET_TIME_Relative delay,
1402 enum GNUNET_SCHEDULER_Priority priority, 1397 enum GNUNET_SCHEDULER_Priority priority,
@@ -1446,7 +1441,6 @@ add_without_sets(struct GNUNET_TIME_Relative delay,
1446 init_backtrace(t); 1441 init_backtrace(t);
1447 return t; 1442 return t;
1448} 1443}
1449#endif
1450 1444
1451 1445
1452/** 1446/**
@@ -1586,22 +1580,6 @@ GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay,
1586{ 1580{
1587 /* scheduler must be running */ 1581 /* scheduler must be running */
1588 GNUNET_assert(NULL != scheduler_driver); 1582 GNUNET_assert(NULL != scheduler_driver);
1589
1590#if MINGW
1591 struct GNUNET_NETWORK_FDSet *s;
1592 struct GNUNET_SCHEDULER_Task * ret;
1593
1594 GNUNET_assert(NULL != fd);
1595 s = GNUNET_NETWORK_fdset_create();
1596 GNUNET_NETWORK_fdset_set(s, fd);
1597 ret = GNUNET_SCHEDULER_add_select(
1598 priority, delay,
1599 on_read ? s : NULL,
1600 on_write ? s : NULL,
1601 task, task_cls);
1602 GNUNET_NETWORK_fdset_destroy(s);
1603 return ret;
1604#else
1605 GNUNET_assert(on_read || on_write); 1583 GNUNET_assert(on_read || on_write);
1606 GNUNET_assert(GNUNET_NETWORK_get_fd(fd) >= 0); 1584 GNUNET_assert(GNUNET_NETWORK_get_fd(fd) >= 0);
1607 return add_without_sets(delay, priority, 1585 return add_without_sets(delay, priority,
@@ -1610,7 +1588,6 @@ GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay,
1610 NULL, 1588 NULL,
1611 NULL, 1589 NULL,
1612 task, task_cls); 1590 task, task_cls);
1613#endif
1614} 1591}
1615 1592
1616 1593
@@ -1710,22 +1687,6 @@ GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay,
1710{ 1687{
1711 /* scheduler must be running */ 1688 /* scheduler must be running */
1712 GNUNET_assert(NULL != scheduler_driver); 1689 GNUNET_assert(NULL != scheduler_driver);
1713
1714#if MINGW
1715 struct GNUNET_NETWORK_FDSet *s;
1716 struct GNUNET_SCHEDULER_Task * ret;
1717
1718 GNUNET_assert(NULL != fd);
1719 s = GNUNET_NETWORK_fdset_create();
1720 GNUNET_NETWORK_fdset_handle_set(s, fd);
1721 ret = GNUNET_SCHEDULER_add_select(
1722 priority, delay,
1723 on_read ? s : NULL,
1724 on_write ? s : NULL,
1725 task, task_cls);
1726 GNUNET_NETWORK_fdset_destroy(s);
1727 return ret;
1728#else
1729 GNUNET_assert(on_read || on_write); 1690 GNUNET_assert(on_read || on_write);
1730 GNUNET_assert(fd->fd >= 0); 1691 GNUNET_assert(fd->fd >= 0);
1731 return add_without_sets(delay, priority, 1692 return add_without_sets(delay, priority,
@@ -1734,7 +1695,6 @@ GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay,
1734 on_read ? fd : NULL, 1695 on_read ? fd : NULL,
1735 on_write ? fd : NULL, 1696 on_write ? fd : NULL,
1736 task, task_cls); 1697 task, task_cls);
1737#endif
1738} 1698}
1739 1699
1740 1700
@@ -2218,14 +2178,12 @@ GNUNET_SCHEDULER_driver_init(const struct GNUNET_SCHEDULER_Driver *driver)
2218 sh->shc_gterm = GNUNET_SIGNAL_handler_install(GNUNET_TERM_SIG, 2178 sh->shc_gterm = GNUNET_SIGNAL_handler_install(GNUNET_TERM_SIG,
2219 &sighandler_shutdown); 2179 &sighandler_shutdown);
2220#endif 2180#endif
2221#ifndef MINGW
2222 sh->shc_pipe = GNUNET_SIGNAL_handler_install(SIGPIPE, 2181 sh->shc_pipe = GNUNET_SIGNAL_handler_install(SIGPIPE,
2223 &sighandler_pipe); 2182 &sighandler_pipe);
2224 sh->shc_quit = GNUNET_SIGNAL_handler_install(SIGQUIT, 2183 sh->shc_quit = GNUNET_SIGNAL_handler_install(SIGQUIT,
2225 &sighandler_shutdown); 2184 &sighandler_shutdown);
2226 sh->shc_hup = GNUNET_SIGNAL_handler_install(SIGHUP, 2185 sh->shc_hup = GNUNET_SIGNAL_handler_install(SIGHUP,
2227 &sighandler_shutdown); 2186 &sighandler_shutdown);
2228#endif
2229 2187
2230 /* Setup initial tasks */ 2188 /* Setup initial tasks */
2231 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; 2189 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
@@ -2282,11 +2240,9 @@ GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
2282#if (SIGTERM != GNUNET_TERM_SIG) 2240#if (SIGTERM != GNUNET_TERM_SIG)
2283 GNUNET_SIGNAL_handler_uninstall(sh->shc_gterm); 2241 GNUNET_SIGNAL_handler_uninstall(sh->shc_gterm);
2284#endif 2242#endif
2285#ifndef MINGW
2286 GNUNET_SIGNAL_handler_uninstall(sh->shc_pipe); 2243 GNUNET_SIGNAL_handler_uninstall(sh->shc_pipe);
2287 GNUNET_SIGNAL_handler_uninstall(sh->shc_quit); 2244 GNUNET_SIGNAL_handler_uninstall(sh->shc_quit);
2288 GNUNET_SIGNAL_handler_uninstall(sh->shc_hup); 2245 GNUNET_SIGNAL_handler_uninstall(sh->shc_hup);
2289#endif
2290 GNUNET_DISK_pipe_close(shutdown_pipe_handle); 2246 GNUNET_DISK_pipe_close(shutdown_pipe_handle);
2291 shutdown_pipe_handle = NULL; 2247 shutdown_pipe_handle = NULL;
2292 scheduler_driver = NULL; 2248 scheduler_driver = NULL;
@@ -2352,7 +2308,6 @@ select_loop(struct GNUNET_SCHEDULER_Handle *sh,
2352 2308
2353 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, 2309 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR,
2354 "select"); 2310 "select");
2355#ifndef MINGW
2356#if USE_LSOF 2311#if USE_LSOF
2357 char lsof[512]; 2312 char lsof[512];
2358 2313
@@ -2366,7 +2321,6 @@ select_loop(struct GNUNET_SCHEDULER_Handle *sh,
2366 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, 2321 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
2367 "system"); 2322 "system");
2368#endif 2323#endif
2369#endif
2370#if DEBUG_FDS 2324#if DEBUG_FDS
2371 for (struct Scheduled *s = context->scheduled_head; 2325 for (struct Scheduled *s = context->scheduled_head;
2372 NULL != s; 2326 NULL != s;
diff --git a/src/util/service.c b/src/util/service.c
index 880047a42..b0f4ea289 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1354,93 +1354,6 @@ get_server_addresses(const char *service_name,
1354} 1354}
1355 1355
1356 1356
1357#ifdef MINGW
1358/**
1359 * Read listen sockets from the parent process (ARM).
1360 *
1361 * @param sh service context to initialize
1362 * @return NULL-terminated array of sockets on success,
1363 * NULL if not ok (must bind yourself)
1364 */
1365static struct GNUNET_NETWORK_Handle **
1366receive_sockets_from_parent(struct GNUNET_SERVICE_Handle *sh)
1367{
1368 static struct GNUNET_NETWORK_Handle **lsocks;
1369 const char *env_buf;
1370 int fail;
1371 uint64_t count;
1372 uint64_t i;
1373 HANDLE lsocks_pipe;
1374
1375 env_buf = getenv("GNUNET_OS_READ_LSOCKS");
1376 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
1377 return NULL;
1378 /* Using W32 API directly here, because this pipe will
1379 * never be used outside of this function, and it's just too much of a bother
1380 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
1381 */
1382 lsocks_pipe = (HANDLE)strtoul(env_buf, NULL, 10);
1383 if ((0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
1384 return NULL;
1385 fail = 1;
1386 do
1387 {
1388 int ret;
1389 int fail2;
1390 DWORD rd;
1391
1392 ret = ReadFile(lsocks_pipe, &count, sizeof(count), &rd, NULL);
1393 if ((0 == ret) || (sizeof(count) != rd) || (0 == count))
1394 break;
1395 lsocks = GNUNET_new_array(count + 1, struct GNUNET_NETWORK_Handle *);
1396
1397 fail2 = 1;
1398 for (i = 0; i < count; i++)
1399 {
1400 WSAPROTOCOL_INFOA pi;
1401 uint64_t size;
1402 _win_socket s;
1403
1404 ret = ReadFile(lsocks_pipe, &size, sizeof(size), &rd, NULL);
1405 if ((0 == ret) || (sizeof(size) != rd) || (sizeof(pi) != size))
1406 break;
1407 ret = ReadFile(lsocks_pipe, &pi, sizeof(pi), &rd, NULL);
1408 if ((0 == ret) || (sizeof(pi) != rd))
1409 break;
1410 s = WSASocketA(pi.iAddressFamily,
1411 pi.iSocketType,
1412 pi.iProtocol,
1413 &pi,
1414 0,
1415 WSA_FLAG_OVERLAPPED);
1416 lsocks[i] = GNUNET_NETWORK_socket_box_native(s);
1417 if (NULL == lsocks[i])
1418 break;
1419 else if (i == count - 1)
1420 fail2 = 0;
1421 }
1422 if (fail2)
1423 break;
1424 lsocks[count] = NULL;
1425 fail = 0;
1426 }
1427 while (fail);
1428 CloseHandle(lsocks_pipe);
1429
1430 if (fail)
1431 {
1432 LOG(GNUNET_ERROR_TYPE_ERROR,
1433 _("Could not access a pre-bound socket, will try to bind myself\n"));
1434 for (i = 0; (i < count) && (NULL != lsocks[i]); i++)
1435 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(lsocks[i]));
1436 GNUNET_free(lsocks);
1437 return NULL;
1438 }
1439 return lsocks;
1440}
1441#endif
1442
1443
1444/** 1357/**
1445 * Create and initialize a listen socket for the server. 1358 * Create and initialize a listen socket for the server.
1446 * 1359 *
@@ -1557,13 +1470,10 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1557{ 1470{
1558 int tolerant; 1471 int tolerant;
1559 struct GNUNET_NETWORK_Handle **lsocks; 1472 struct GNUNET_NETWORK_Handle **lsocks;
1560
1561#ifndef MINGW
1562 const char *nfds; 1473 const char *nfds;
1563 unsigned int cnt; 1474 unsigned int cnt;
1564 int flags; 1475 int flags;
1565 char dummy[2]; 1476 char dummy[2];
1566#endif
1567 1477
1568 if (GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, "TOLERANT")) 1478 if (GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, "TOLERANT"))
1569 { 1479 {
@@ -1583,7 +1493,7 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1583 tolerant = GNUNET_NO; 1493 tolerant = GNUNET_NO;
1584 1494
1585 lsocks = NULL; 1495 lsocks = NULL;
1586#ifndef MINGW 1496
1587 errno = 0; 1497 errno = 0;
1588 if ((NULL != (nfds = getenv("LISTEN_FDS"))) && 1498 if ((NULL != (nfds = getenv("LISTEN_FDS"))) &&
1589 (1 == sscanf(nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) && 1499 (1 == sscanf(nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
@@ -1611,13 +1521,6 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1611 } 1521 }
1612 unsetenv("LISTEN_FDS"); 1522 unsetenv("LISTEN_FDS");
1613 } 1523 }
1614#else
1615 if (NULL != getenv("GNUNET_OS_READ_LSOCKS"))
1616 {
1617 lsocks = receive_sockets_from_parent(sh);
1618 putenv("GNUNET_OS_READ_LSOCKS=");
1619 }
1620#endif
1621 1524
1622 if (NULL != lsocks) 1525 if (NULL != lsocks)
1623 { 1526 {
@@ -1723,7 +1626,7 @@ set_user_id(struct GNUNET_SERVICE_Handle *sh)
1723 1626
1724 if (NULL == (user = get_user_name(sh))) 1627 if (NULL == (user = get_user_name(sh)))
1725 return GNUNET_OK; /* keep */ 1628 return GNUNET_OK; /* keep */
1726#ifndef MINGW 1629
1727 struct passwd *pws; 1630 struct passwd *pws;
1728 1631
1729 errno = 0; 1632 errno = 0;
@@ -1754,7 +1657,7 @@ set_user_id(struct GNUNET_SERVICE_Handle *sh)
1754 return GNUNET_SYSERR; 1657 return GNUNET_SYSERR;
1755 } 1658 }
1756 } 1659 }
1757#endif 1660
1758 GNUNET_free(user); 1661 GNUNET_free(user);
1759 return GNUNET_OK; 1662 return GNUNET_OK;
1760} 1663}
@@ -1808,7 +1711,6 @@ pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
1808static int 1711static int
1809detach_terminal(struct GNUNET_SERVICE_Handle *sh) 1712detach_terminal(struct GNUNET_SERVICE_Handle *sh)
1810{ 1713{
1811#ifndef MINGW
1812 pid_t pid; 1714 pid_t pid;
1813 int nullfd; 1715 int nullfd;
1814 int filedes[2]; 1716 int filedes[2];
@@ -1875,11 +1777,7 @@ detach_terminal(struct GNUNET_SERVICE_Handle *sh)
1875 if (-1 == pid) 1777 if (-1 == pid)
1876 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid"); 1778 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid");
1877 sh->ready_confirm_fd = filedes[1]; 1779 sh->ready_confirm_fd = filedes[1];
1878#else 1780
1879 /* FIXME: we probably need to do something else
1880 * elsewhere in order to fork the process itself... */
1881 FreeConsole();
1882#endif
1883 return GNUNET_OK; 1781 return GNUNET_OK;
1884} 1782}
1885 1783
diff --git a/src/util/strings.c b/src/util/strings.c
index dc46ad33a..25b09f8e2 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -602,20 +602,13 @@ char *
602GNUNET_STRINGS_filename_expand(const char *fil) 602GNUNET_STRINGS_filename_expand(const char *fil)
603{ 603{
604 char *buffer; 604 char *buffer;
605
606#ifndef MINGW
607 size_t len; 605 size_t len;
608 char *fm; 606 char *fm;
609 const char *fil_ptr; 607 const char *fil_ptr;
610#else
611 char *fn;
612 long lRet;
613#endif
614 608
615 if (fil == NULL) 609 if (fil == NULL)
616 return NULL; 610 return NULL;
617 611
618#ifndef MINGW
619 if (fil[0] == DIR_SEPARATOR) 612 if (fil[0] == DIR_SEPARATOR)
620 /* absolute path, just copy */ 613 /* absolute path, just copy */
621 return GNUNET_strdup(fil); 614 return GNUNET_strdup(fil);
@@ -677,34 +670,6 @@ GNUNET_STRINGS_filename_expand(const char *fil)
677 fil_ptr); 670 fil_ptr);
678 GNUNET_free(fm); 671 GNUNET_free(fm);
679 return buffer; 672 return buffer;
680#else
681 fn = GNUNET_malloc(MAX_PATH + 1);
682
683 if ((lRet = plibc_conv_to_win_path(fil, fn)) != ERROR_SUCCESS)
684 {
685 SetErrnoFromWinError(lRet);
686 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
687 return NULL;
688 }
689 /* is the path relative? */
690 if ((0 != strncmp(fn + 1, ":\\", 2)) && (0 != strncmp(fn, "\\\\", 2)))
691 {
692 char szCurDir[MAX_PATH + 1];
693
694 lRet = GetCurrentDirectory(MAX_PATH + 1, szCurDir);
695 if (lRet + strlen(fn) + 1 > (MAX_PATH + 1))
696 {
697 SetErrnoFromWinError(ERROR_BUFFER_OVERFLOW);
698 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
699 return NULL;
700 }
701 GNUNET_asprintf(&buffer, "%s\\%s", szCurDir, fn);
702 GNUNET_free(fn);
703 fn = buffer;
704 }
705
706 return fn;
707#endif
708} 673}
709 674
710 675
diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c
index 07e2327c9..4ba7b544c 100644
--- a/src/util/test_common_logging_runtime_loglevels.c
+++ b/src/util/test_common_logging_runtime_loglevels.c
@@ -401,11 +401,7 @@ runone()
401 401
402 proc = GNUNET_OS_start_process(GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, 402 proc = GNUNET_OS_start_process(GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
403 NULL, pipe_stdout, NULL, 403 NULL, pipe_stdout, NULL,
404#if MINGW
405 "test_common_logging_dummy",
406#else
407 "./test_common_logging_dummy", 404 "./test_common_logging_dummy",
408#endif
409 "test_common_logging_dummy", NULL); 405 "test_common_logging_dummy", NULL);
410 GNUNET_assert(NULL != proc); 406 GNUNET_assert(NULL != proc);
411 putenv("GNUNET_FORCE_LOG="); 407 putenv("GNUNET_FORCE_LOG=");
diff --git a/src/util/test_configuration.c b/src/util/test_configuration.c
index 71a1ae5bd..b5b1e238c 100644
--- a/src/util/test_configuration.c
+++ b/src/util/test_configuration.c
@@ -323,12 +323,8 @@ testConfig()
323 GNUNET_break(0); 323 GNUNET_break(0);
324 return 8; 324 return 8;
325 } 325 }
326#ifndef MINGW 326
327 if (0 != strcmp(c, "/hello/world")) 327 if (0 != strcmp(c, "/hello/world"))
328#else
329#define HI "\\hello\\world"
330 if (strstr(c, HI) != c + strlen(c) - strlen(HI))
331#endif
332 { 328 {
333 GNUNET_break(0); 329 GNUNET_break(0);
334 GNUNET_free(c); 330 GNUNET_free(c);
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c
index 620605f96..77b8c8b2f 100644
--- a/src/util/test_getopt.c
+++ b/src/util/test_getopt.c
@@ -163,9 +163,9 @@ main(int argc, char *argv[])
163 163
164 GNUNET_log_setup("test_getopt", "WARNING", NULL); 164 GNUNET_log_setup("test_getopt", "WARNING", NULL);
165 /* suppress output from -h, -v options */ 165 /* suppress output from -h, -v options */
166#ifndef MINGW 166
167 GNUNET_break(0 == close(1)); 167 GNUNET_break(0 == close(1));
168#endif 168
169 if (0 != testMinimal()) 169 if (0 != testMinimal())
170 errCnt++; 170 errCnt++;
171 if (0 != testVerbose()) 171 if (0 != testVerbose())
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index ea26c4ee6..0b27a2eff 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -307,11 +307,8 @@ run(void *cls, char *const *args, const char *cfgfile,
307#if HAVE_SOCKADDR_IN_SIN_LEN 307#if HAVE_SOCKADDR_IN_SIN_LEN
308 sa.sin_len = (u_char)sizeof(sa); 308 sa.sin_len = (u_char)sizeof(sa);
309#endif 309#endif
310#ifndef MINGW
311 inet_aton(ROOTSERVER_IP, &sa.sin_addr); 310 inet_aton(ROOTSERVER_IP, &sa.sin_addr);
312#else 311
313 sa.sin_addr.S_un.S_addr = inet_addr(ROOTSERVER_IP);
314#endif
315 GNUNET_RESOLVER_hostname_get((const struct sockaddr *)&sa, 312 GNUNET_RESOLVER_hostname_get((const struct sockaddr *)&sa,
316 sizeof(struct sockaddr), GNUNET_YES, timeout, 313 sizeof(struct sockaddr), GNUNET_YES, timeout,
317 &check_rootserver_name, cls); 314 &check_rootserver_name, cls);
diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c
index 236bb4e76..8952225c2 100644
--- a/src/util/test_scheduler.c
+++ b/src/util/test_scheduler.c
@@ -211,7 +211,6 @@ checkShutdown()
211} 211}
212 212
213 213
214#ifndef MINGW
215static void 214static void
216taskSig(void *cls) 215taskSig(void *cls)
217{ 216{
@@ -244,7 +243,6 @@ checkSignal()
244 GNUNET_SCHEDULER_run(&taskSig, &ok); 243 GNUNET_SCHEDULER_run(&taskSig, &ok);
245 return ok; 244 return ok;
246} 245}
247#endif
248 246
249 247
250static void 248static void
@@ -283,9 +281,7 @@ main(int argc, char *argv[])
283 GNUNET_log_setup("test_scheduler", "WARNING", NULL); 281 GNUNET_log_setup("test_scheduler", "WARNING", NULL);
284 ret += check(); 282 ret += check();
285 ret += checkCancel(); 283 ret += checkCancel();
286#ifndef MINGW
287 ret += checkSignal(); 284 ret += checkSignal();
288#endif
289 ret += checkShutdown(); 285 ret += checkShutdown();
290 GNUNET_DISK_pipe_close(p); 286 GNUNET_DISK_pipe_close(p);
291 287
diff --git a/src/util/test_service.c b/src/util/test_service.c
index c0b02872f..4edc38a0d 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -206,11 +206,10 @@ main(int argc,
206 NULL); 206 NULL);
207 ret += check("test_service"); 207 ret += check("test_service");
208 ret += check("test_service"); 208 ret += check("test_service");
209#ifndef MINGW
210 s = GNUNET_NETWORK_socket_create(PF_INET6, 209 s = GNUNET_NETWORK_socket_create(PF_INET6,
211 SOCK_STREAM, 210 SOCK_STREAM,
212 0); 211 0);
213#endif 212
214 if (NULL == s) 213 if (NULL == s)
215 { 214 {
216 if ((errno == ENOBUFS) || 215 if ((errno == ENOBUFS) ||
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index a4e548e31..60887c587 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -67,11 +67,9 @@ main(int argc, char *argv[])
67 (GNUNET_TIME_UNIT_MILLISECONDS, 67 (GNUNET_TIME_UNIT_MILLISECONDS,
68 7 * 60 * 60 * 1000), GNUNET_YES); 68 7 * 60 * 60 * 1000), GNUNET_YES);
69 WANTNF(buf, bc); 69 WANTNF(buf, bc);
70#ifndef MINGW 70
71 hdir = getenv("HOME"); 71 hdir = getenv("HOME");
72#else 72
73 hdir = getenv("USERPROFILE");
74#endif
75 GNUNET_snprintf(buf, sizeof(buf), "%s%s", hdir, DIR_SEPARATOR_STR); 73 GNUNET_snprintf(buf, sizeof(buf), "%s%s", hdir, DIR_SEPARATOR_STR);
76 b = GNUNET_STRINGS_filename_expand("~"); 74 b = GNUNET_STRINGS_filename_expand("~");
77 GNUNET_assert(b != NULL); 75 GNUNET_assert(b != NULL);
diff --git a/src/util/w32cat.c b/src/util/w32cat.c
deleted file mode 100644
index fa7637d38..000000000
--- a/src/util/w32cat.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 W32 version of 'cat' program
3 Copyright (C) 2012 LRN
4
5 cat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 cat is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with cat; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20 SPDX-License-Identifier: AGPL3.0-or-later
21 */
22
23#include <stdio.h>
24#include <windows.h>
25#include <stdint.h>
26#include <signal.h>
27
28DWORD WINAPI
29parent_control_thread(LPVOID lpParameter)
30{
31 HANDLE h = (HANDLE)lpParameter;
32
33 while (TRUE)
34 {
35 DWORD dw;
36 BOOL b;
37 unsigned char c;
38 b = ReadFile(h, &c, 1, &dw, NULL);
39 if (!b)
40 {
41 ExitProcess(0);
42 }
43 raise((int)c);
44 }
45}
46
47void
48install_parent_control_handler()
49{
50 const char *env_buf;
51 char *env_buf_end;
52 uint64_t pipe_fd;
53 HANDLE pipe_handle;
54
55 env_buf = getenv("GNUNET_OS_CONTROL_PIPE");
56 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
57 return;
58 errno = 0;
59 pipe_fd = strtoull(env_buf, &env_buf_end, 16);
60 if ((0 != errno) || (env_buf == env_buf_end))
61 return;
62 /* Gcc will issue a warning here. What to do with it? */
63 pipe_handle = (HANDLE)(uintptr_t)pipe_fd;
64 CreateThread(NULL, 0, parent_control_thread, (LPVOID)pipe_handle, 0, NULL);
65}
66
67int
68main(int argc, char **argv)
69{
70 HANDLE stdi, stdo;
71 BOOL b;
72 wchar_t *commandlinew, **argvw;
73 int argcw;
74 int i;
75
76 stdo = GetStdHandle(STD_OUTPUT_HANDLE);
77 if (stdo == INVALID_HANDLE_VALUE || stdo == NULL)
78 return 1;
79
80 commandlinew = GetCommandLineW();
81 argvw = CommandLineToArgvW(commandlinew, &argcw);
82 if (argvw == NULL)
83 return 1;
84
85 install_parent_control_handler();
86
87 for (i = 1; i < argcw || argcw == 1; i++)
88 {
89 DWORD r, w;
90 int is_dash = wcscmp(NULL == argvw[i] ? L"-" : argvw[i], L"-") == 0;
91 if (argcw == 1 || is_dash)
92 {
93 stdi = GetStdHandle(STD_INPUT_HANDLE);
94 if (stdi == INVALID_HANDLE_VALUE)
95 {
96 fprintf(stderr, "cat: Failed to obtain stdin handle.\n");
97 return 4;
98 }
99 if (stdi == NULL)
100 {
101 fprintf(stderr, "cat: Have no stdin.\n");
102 return 5;
103 }
104 }
105 else
106 {
107 stdi = CreateFileW(argvw[i], GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
108 if (stdi == INVALID_HANDLE_VALUE)
109 {
110 wchar_t *msgbuf;
111 DWORD le = GetLastError();
112 if (0 < FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *)&msgbuf, 0, NULL))
113 {
114 fprintf(stderr, "cat: Failed to open file `%S'. Error %lu.\n", argvw[i], le);
115 return 3;
116 }
117 fprintf(stderr, "cat: Failed to open file `%S'. Error %lu: %S\n", argvw[i], le, msgbuf);
118 if (msgbuf != NULL)
119 LocalFree(msgbuf);
120 return 2;
121 }
122 }
123 do
124 {
125 unsigned char c;
126 b = ReadFile(stdi, &c, 1, &r, NULL);
127 if (b && r > 0)
128 {
129 b = WriteFile(stdo, &c, 1, &w, NULL);
130 if (b == 0)
131 {
132 wchar_t *msgbuf;
133 DWORD le = GetLastError();
134 if (0 < FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *)&msgbuf, 0, NULL))
135 {
136 fprintf(stderr, "cat: Failed to write into stdout. Error %lu.\n", le);
137 return 3;
138 }
139 fprintf(stderr, "cat: Failed to write into stdout. Error %lu: %S\n", le, msgbuf);
140 if (msgbuf != NULL)
141 LocalFree(msgbuf);
142 return 6;
143 }
144 }
145 }
146 while (b && r > 0);
147 if (argcw == 1)
148 break;
149 if (!is_dash)
150 CloseHandle(stdi);
151 }
152 LocalFree(argvw);
153 return 0;
154}
diff --git a/src/util/win.c b/src/util/win.c
deleted file mode 100644
index a2b0d08da..000000000
--- a/src/util/win.c
+++ /dev/null
@@ -1,1365 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/win.c
23 * @brief Helper functions for MS Windows in C++
24 * @author Nils Durner
25 */
26
27#ifndef _WIN_C
28#define _WIN_C
29
30#include "winproc.h"
31#include "platform.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_common.h"
34#include "gnunet_connection_lib.h"
35
36#include <ntdef.h>
37#ifndef INHERITED_ACE
38#define INHERITED_ACE 0x10
39#endif
40
41int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
42
43#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
44 union { \
45 struct { \
46 ULONG Length; \
47 DWORD Flags; \
48 }; \
49 };
50
51#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
52 SOCKET_ADDRESS Address; \
53 IP_PREFIX_ORIGIN PrefixOrigin; \
54 IP_SUFFIX_ORIGIN SuffixOrigin; \
55 IP_DAD_STATE DadState; \
56 ULONG ValidLifetime; \
57 ULONG PreferredLifetime; \
58 ULONG LeaseLifetime;
59
60#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
61 UINT8 OnLinkPrefixLength;
62
63
64#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix, addition) \
65 typedef struct _IP_ADAPTER_UNICAST_ADDRESS ## suffix { \
66 _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
67 struct _IP_ADAPTER_UNICAST_ADDRESS ## suffix *Next; \
68 _IP_ADAPTER_UNICAST_ADDRESS_BASE \
69 addition \
70 } IP_ADAPTER_UNICAST_ADDRESS ## suffix, *PIP_ADAPTER_UNICAST_ADDRESS ## suffix;
71
72/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
73_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA, _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
74
75
76#ifndef __MINGW64_VERSION_MAJOR
77typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
78 union {
79 ULONGLONG Alignment;
80 struct {
81 ULONG Length;
82 DWORD Reserved;
83 };
84 };
85 struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;
86 SOCKET_ADDRESS Address;
87} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
88
89typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
90 union {
91 ULONGLONG Alignment;
92 struct {
93 ULONG Length;
94 DWORD Reserved;
95 };
96 };
97 struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;
98 SOCKET_ADDRESS Address;
99} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;
100#endif
101
102typedef UINT32 NET_IF_COMPARTMENT_ID;
103typedef GUID NET_IF_NETWORK_GUID;
104
105#ifndef __MINGW64_VERSION_MAJOR
106typedef enum _NET_IF_CONNECTION_TYPE {
107 NET_IF_CONNECTION_DEDICATED = 1,
108 NET_IF_CONNECTION_PASSIVE,
109 NET_IF_CONNECTION_DEMAND,
110 NET_IF_CONNECTION_MAXIMUM
111} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
112
113typedef enum {
114 TUNNEL_TYPE_NONE = 0,
115 TUNNEL_TYPE_OTHER,
116 TUNNEL_TYPE_DIRECT,
117 TUNNEL_TYPE_6TO4,
118 TUNNEL_TYPE_ISATAP,
119 TUNNEL_TYPE_TEREDO,
120 TUNNEL_TYPE_IPHTTPS
121} TUNNEL_TYPE, *PTUNNEL_TYPE;
122#endif
123
124/*
125 A DUID consists of a two-octet type code represented in network byte
126 order, followed by a variable number of octets that make up the
127 actual identifier. A DUID can be no more than 128 octets long (not
128 including the type code).
129 */
130#define MAX_DHCPV6_DUID_LENGTH 130
131
132#ifndef __MINGW64_VERSION_MAJOR
133typedef union _NET_LUID {
134 ULONG64 Value;
135 struct {
136 ULONG64 Reserved : 24;
137 ULONG64 NetLuidIndex : 24;
138 ULONG64 IfType : 16;
139 } Info;
140} NET_LUID, *PNET_LUID, IF_LUID;
141
142#define MAX_DNS_SUFFIX_STRING_LENGTH 246
143
144typedef struct _IP_ADAPTER_DNS_SUFFIX {
145 struct _IP_ADAPTER_DNS_SUFFIX *Next;
146 WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];
147} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
148#endif
149
150
151
152#define _IP_ADAPTER_ADDRESSES_HEAD \
153 union { \
154 ULONGLONG Alignment; \
155 struct { \
156 ULONG Length; \
157 DWORD IfIndex; \
158 }; \
159 };
160
161#define _IP_ADAPTER_ADDRESSES_BASE \
162 PCHAR AdapterName; \
163 PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \
164 PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \
165 PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \
166 PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \
167 PWCHAR DnsSuffix; \
168 PWCHAR Description; \
169 PWCHAR FriendlyName; \
170 BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \
171 DWORD PhysicalAddressLength; \
172 DWORD Flags; \
173 DWORD Mtu; \
174 DWORD IfType; \
175 IF_OPER_STATUS OperStatus;
176
177#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
178 DWORD Ipv6IfIndex; \
179 DWORD ZoneIndices[16]; \
180 PIP_ADAPTER_PREFIX FirstPrefix; \
181
182
183#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
184 _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
185 ULONG64 TransmitLinkSpeed; \
186 ULONG64 ReceiveLinkSpeed; \
187 PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
188 PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \
189 ULONG Ipv4Metric; \
190 ULONG Ipv6Metric; \
191 IF_LUID Luid; \
192 SOCKET_ADDRESS Dhcpv4Server; \
193 NET_IF_COMPARTMENT_ID CompartmentId; \
194 NET_IF_NETWORK_GUID NetworkGuid; \
195 NET_IF_CONNECTION_TYPE ConnectionType; \
196 TUNNEL_TYPE TunnelType; \
197 SOCKET_ADDRESS Dhcpv6Server; \
198 BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \
199 ULONG Dhcpv6ClientDuidLength; \
200 ULONG Dhcpv6Iaid;
201
202#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
203 _IP_ADAPTER_ADDRESSES_ADD_VISTA \
204 PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
205
206#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix, addition) \
207 typedef struct _IP_ADAPTER_ADDRESSES ## suffix { \
208 _IP_ADAPTER_ADDRESSES_HEAD \
209 struct _IP_ADAPTER_ADDRESSES ## suffix *Next; \
210 _IP_ADAPTER_ADDRESSES_BASE \
211 addition \
212 } IP_ADAPTER_ADDRESSES ## suffix, *PIP_ADAPTER_ADDRESSES ## suffix;
213
214
215/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
216_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1, _IP_ADAPTER_ADDRESSES_ADD_XPSP1)
217_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA, _IP_ADAPTER_ADDRESSES_ADD_VISTA)
218_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1, _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
219
220static int
221EnumNICs_IPv6_get_ifs_count(_win_socket s)
222{
223 DWORD dwret = 0, err;
224 int iret;
225
226 iret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
227 &dwret, NULL, NULL);
228 err = GetLastError();
229 if (iret == SOCKET_ERROR && err == WSAEFAULT)
230 return dwret;
231 else if (iret == 0)
232 return 0;
233 return GNUNET_SYSERR;
234}
235
236static int
237EnumNICs_IPv6_get_ifs(_win_socket s, SOCKET_ADDRESS_LIST *inf, int size)
238{
239 int iret;
240 DWORD dwret = 0;
241
242 iret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
243 &dwret, NULL, NULL);
244
245 if (iret != 0 || dwret != size)
246 {
247 /* It's supposed to succeed! And size should be the same */
248 return GNUNET_SYSERR;
249 }
250 return GNUNET_OK;
251}
252
253#undef GNUNET_malloc
254#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | \
255 HEAP_GENERATE_EXCEPTIONS, a)
256
257#undef GNUNET_free
258#define GNUNET_free(a) HeapFree(GetProcessHeap(), 0, a)
259
260#undef GNUNET_free_non_null
261#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free (a); } while (0)
262
263static int
264EnumNICs_IPv4_get_ifs(SOCKET s, INTERFACE_INFO **inf, int *size)
265{
266 int iret;
267 DWORD dwret = 0;
268 DWORD error;
269 INTERFACE_INFO *ii = NULL;
270 DWORD ii_size = sizeof(INTERFACE_INFO) * 15;
271
272 while (TRUE)
273 {
274 if (ii_size >= sizeof(INTERFACE_INFO) * 1000)
275 return GNUNET_SYSERR;
276 ii = (INTERFACE_INFO *)GNUNET_malloc(ii_size);
277 dwret = 0;
278 iret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
279 &dwret, NULL, NULL);
280 error = GetLastError();
281 if (iret == SOCKET_ERROR)
282 {
283 if (error == WSAEFAULT)
284 {
285 GNUNET_free(ii);
286 ii_size *= 2;
287 continue;
288 }
289 GNUNET_free(ii);
290 return GNUNET_SYSERR;
291 }
292 else
293 {
294 *inf = ii;
295 *size = dwret;
296 return GNUNET_OK;
297 }
298 }
299 return GNUNET_SYSERR;
300}
301
302int
303EnumNICs2(INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
304{
305 int result = 0;
306 _win_socket s4;
307 _win_socket s6;
308 int ifs4len = 0;
309 int ifs6len = 0;
310 INTERFACE_INFO *interfaces4 = NULL;
311 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
312
313 SetLastError(0);
314 s4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
315 (void)GetLastError();
316 SetLastError(0);
317 s6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
318 (void)GetLastError();
319 if (s6 != INVALID_SOCKET)
320 {
321 ifs6len = EnumNICs_IPv6_get_ifs_count(s6);
322 if (ifs6len > 0)
323 {
324 interfaces6 = (SOCKET_ADDRESS_LIST *)GNUNET_malloc(ifs6len);
325 result = EnumNICs_IPv6_get_ifs(s6, interfaces6, ifs6len) || result;
326 }
327 closesocket(s6);
328 s6 = INVALID_SOCKET;
329 }
330
331 if (s4 != INVALID_SOCKET)
332 {
333 result = EnumNICs_IPv4_get_ifs(s4, &interfaces4, &ifs4len) || result;
334 closesocket(s4);
335 s4 = INVALID_SOCKET;
336 }
337 if (ifs6len + ifs4len == 0)
338 goto error;
339
340 if (!result)
341 {
342 *ifs4 = interfaces4;
343 *ifs4_len = ifs4len;
344 *ifs6 = interfaces6;
345 return GNUNET_OK;
346 }
347error:
348 if (interfaces4 != NULL)
349 GNUNET_free(interfaces4);
350 if (interfaces6 != NULL)
351 GNUNET_free(interfaces6);
352 if (s4 != INVALID_SOCKET)
353 closesocket(s4);
354 if (s6 != INVALID_SOCKET)
355 closesocket(s6);
356 return GNUNET_SYSERR;
357}
358
359
360/**
361 * @returns #GNUNET_OK on success, #GNUNET_SYSERR on error
362 */
363int
364EnumNICs3(struct EnumNICs3_results **results, int *results_count)
365{
366 DWORD dwRetVal = 0;
367 int count = 0;
368 ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
369 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
370 struct sockaddr_in6 examplecom6;
371 IPAddr examplecom;
372 DWORD best_interface = 0;
373 DWORD best_interface6 = 0;
374
375 int use_enum2 = 0;
376 INTERFACE_INFO *interfaces4 = NULL;
377 int interfaces4_len = 0;
378 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
379
380 unsigned long outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
381 IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
382 IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *)GNUNET_malloc(outBufLen);
383
384 if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
385 == ERROR_BUFFER_OVERFLOW)
386 {
387 GNUNET_free(pAddresses);
388 pAddresses = (IP_ADAPTER_ADDRESSES *)GNUNET_malloc(outBufLen);
389 }
390
391 dwRetVal = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
392
393 if (dwRetVal != NO_ERROR)
394 {
395 GNUNET_free(pAddresses);
396 return GNUNET_SYSERR;
397 }
398
399 if (pAddresses->Length < sizeof(IP_ADAPTER_ADDRESSES_VISTA))
400 {
401 use_enum2 = 1;
402
403 /* Enumerate NICs using WSAIoctl() */
404 if (GNUNET_OK != EnumNICs2(&interfaces4, &interfaces4_len, &interfaces6))
405 {
406 GNUNET_free(pAddresses);
407 return GNUNET_SYSERR;
408 }
409 }
410
411 examplecom = inet_addr("192.0.34.166"); /* www.example.com */
412 if (GetBestInterface(examplecom, &best_interface) != NO_ERROR)
413 best_interface = 0;
414
415 if (GNGetBestInterfaceEx != NULL)
416 {
417 examplecom6.sin6_family = AF_INET6;
418 examplecom6.sin6_port = 0;
419 examplecom6.sin6_flowinfo = 0;
420 examplecom6.sin6_scope_id = 0;
421 inet_pton(AF_INET6, "2001:500:88:200:0:0:0:10",
422 (struct sockaddr *)&examplecom6.sin6_addr);
423 dwRetVal = GNGetBestInterfaceEx((struct sockaddr *)&examplecom6,
424 &best_interface6);
425 if (dwRetVal != NO_ERROR)
426 best_interface6 = 0;
427 }
428
429 /* Give IPv6 a priority */
430 if (best_interface6 != 0)
431 best_interface = best_interface6;
432
433 count = 0;
434 for (pCurrentAddress = pAddresses;
435 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
436 {
437 if (pCurrentAddress->OperStatus == IfOperStatusUp)
438 {
439 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
440 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
441 unicast = unicast->Next)
442 {
443 if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
444 unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
445 (unicast->DadState == IpDadStateDeprecated ||
446 unicast->DadState == IpDadStatePreferred))
447 count += 1;
448 }
449 }
450 }
451
452 if (count == 0)
453 {
454 *results = NULL;
455 *results_count = 0;
456 GNUNET_free(pAddresses);
457 GNUNET_free_non_null(interfaces4);
458 GNUNET_free_non_null(interfaces6);
459 return GNUNET_OK;
460 }
461
462 *results = (struct EnumNICs3_results *)GNUNET_malloc(
463 sizeof(struct EnumNICs3_results) * count);
464 *results_count = count;
465
466 count = 0;
467 for (pCurrentAddress = pAddresses;
468 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
469 {
470 struct EnumNICs3_results *r;
471 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
472 if (pCurrentAddress->OperStatus != IfOperStatusUp)
473 continue;
474 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
475 unicast = unicast->Next)
476 {
477 int i, j;
478 int mask_length = -1;
479 char dst[INET6_ADDRSTRLEN + 1];
480
481 if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
482 unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
483 (unicast->DadState != IpDadStateDeprecated &&
484 unicast->DadState != IpDadStatePreferred))
485 continue;
486
487 r = &(*results)[count];
488 r->flags = 0;
489 if (pCurrentAddress->IfIndex > 0 &&
490 pCurrentAddress->IfIndex == best_interface &&
491 unicast->Address.lpSockaddr->sa_family == AF_INET)
492 r->is_default = 1;
493 else if (pCurrentAddress->Ipv6IfIndex > 0 &&
494 pCurrentAddress->Ipv6IfIndex == best_interface6 &&
495 unicast->Address.lpSockaddr->sa_family == AF_INET6)
496 r->is_default = 1;
497 else
498 r->is_default = 0;
499
500 /* Don't choose default interface twice */
501 if (r->is_default)
502 best_interface = best_interface6 = 0;
503
504 if (!use_enum2)
505 {
506 GNUNET_memcpy(&r->address, unicast->Address.lpSockaddr,
507 unicast->Address.iSockaddrLength);
508 memset(&r->mask, 0, sizeof(struct sockaddr));
509 mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *)unicast)->
510 OnLinkPrefixLength;
511 /* OnLinkPrefixLength is the number of leading 1s in the mask.
512 * OnLinkPrefixLength is available on Vista and later (hence use_enum2).
513 */
514 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
515 {
516 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
517 for (i = 0; i < mask_length; i++)
518 ((unsigned char *)&m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
519 }
520 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
521 {
522 struct sockaddr_in6 *m = (struct sockaddr_in6 *)&r->mask;
523 struct sockaddr_in6 *b = (struct sockaddr_in6 *)&r->broadcast;
524 for (i = 0; i < mask_length; i++)
525 ((unsigned char *)&m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
526 GNUNET_memcpy(&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
527 for (i = mask_length; i < 128; i++)
528 ((unsigned char *)&b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
529 }
530 r->flags |= ENUMNICS3_MASK_OK;
531 }
532 else
533 {
534 int found = 0;
535 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
536 {
537 for (i = 0; !found && i < interfaces4_len / sizeof(INTERFACE_INFO); i++)
538 {
539 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
540 GNUNET_memcpy(&interfaces4[i].iiAddress.Address,
541 unicast->Address.lpSockaddr,
542 unicast->Address.iSockaddrLength);
543 found = 1;
544 GNUNET_memcpy(&r->address, &interfaces4[i].iiAddress.Address,
545 sizeof(struct sockaddr_in));
546 GNUNET_memcpy(&r->mask, &interfaces4[i].iiNetmask.Address,
547 sizeof(struct sockaddr_in));
548 for (mask_length = 0;
549 ((unsigned char *)&m->sin_addr)[mask_length / 8] &
550 0x80 >> (mask_length % 8); mask_length++)
551 {
552 }
553 r->flags |= ENUMNICS3_MASK_OK;
554 }
555 }
556 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
557 {
558 for (i = 0;
559 interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
560 i++)
561 {
562 GNUNET_memcpy(interfaces6->Address[i].lpSockaddr,
563 unicast->Address.lpSockaddr,
564 unicast->Address.iSockaddrLength);
565 found = 1;
566 GNUNET_memcpy(&r->address, interfaces6->Address[i].lpSockaddr,
567 sizeof(struct sockaddr_in6));
568 /* TODO: Find a way to reliably get network mask for IPv6 on XP */
569 memset(&r->mask, 0, sizeof(struct sockaddr));
570 r->flags &= ~ENUMNICS3_MASK_OK;
571 }
572 }
573 if (!found)
574 {
575 DebugBreak();
576 }
577 }
578 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
579 {
580 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
581 struct sockaddr_in *a = (struct sockaddr_in *)&r->address;
582 /* copy address to broadcast, then flip all the trailing bits not
583 * falling under netmask to 1,
584 * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
585 */
586 GNUNET_memcpy(&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
587 for (i = mask_length; i < 32; i++)
588 ((unsigned char *)&m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
589 r->flags |= ENUMNICS3_BCAST_OK;
590 r->addr_size = sizeof(struct sockaddr_in);
591 inet_ntop(AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
592 }
593 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
594 {
595 struct sockaddr_in6 *a = (struct sockaddr_in6 *)&r->address;
596 /* for IPv6 broadcast is not defined, zero it down */
597 memset(&r->broadcast, 0, sizeof(struct sockaddr));
598 r->flags &= ~ENUMNICS3_BCAST_OK;
599 r->addr_size = sizeof(struct sockaddr_in6);
600 inet_ntop(AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
601 }
602
603 i = 0;
604 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
605 "%S (%s", pCurrentAddress->FriendlyName, dst);
606 for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
607 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
608 "%s%02X", j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
609 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
610 r->pretty_name[1000] = '\0';
611 count += 1;
612 }
613 }
614
615 if (use_enum2)
616 {
617 GNUNET_free_non_null(interfaces4);
618 GNUNET_free_non_null(interfaces6);
619 }
620
621 GNUNET_free(pAddresses);
622 return GNUNET_OK;
623}
624
625void
626EnumNICs3_free(struct EnumNICs3_results *r)
627{
628 GNUNET_free_non_null(r);
629}
630
631
632/**
633 * Lists all network interfaces in a combo box
634 * Used by the basic GTK configurator
635 *
636 * @param callback function to call for each NIC
637 * @param callback_cls closure for callback
638 */
639int
640ListNICs(void (*callback)(void *, const char *, int), void * callback_cls)
641{
642 int r;
643 int i;
644 struct EnumNICs3_results *results = NULL;
645 int results_count;
646
647 r = EnumNICs3(&results, &results_count);
648 if (r != GNUNET_OK)
649 return GNUNET_NO;
650
651 for (i = 0; i < results_count; i++)
652 callback(callback_cls, results[i].pretty_name, results[i].is_default);
653 GNUNET_free_non_null(results);
654 return GNUNET_YES;
655}
656
657/**
658 * @brief Installs the Windows service
659 * @param servicename name of the service as diplayed by the SCM
660 * @param application path to the application binary
661 * @param username the name of the service's user account
662 * @returns 0 on success
663 * 1 if the Windows version doesn't support services
664 * 2 if the SCM could not be opened
665 * 3 if the service could not be created
666 */
667int InstallAsService(char *servicename, char *application, char *username)
668{
669 SC_HANDLE hManager, hService;
670 char szEXE[_MAX_PATH + 17] = "\"";
671 char *user = NULL;
672
673 if (!GNOpenSCManager)
674 return 1;
675
676 plibc_conv_to_win_path(application, szEXE + 1);
677 strcat(szEXE, "\" --win-service");
678 hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
679 if (!hManager)
680 return 2;
681
682 if (username)
683 {
684 user = (char *)malloc(strlen(username) + 3);
685 sprintf(user, ".\\%s", username);
686 }
687
688 hService = GNCreateService(hManager, (LPCTSTR)servicename, (LPCTSTR)servicename, 0,
689 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR)szEXE,
690 NULL, NULL, NULL, (LPCTSTR)user, (LPCTSTR)username);
691
692 if (user)
693 free(user);
694
695 if (!hService)
696 return 3;
697
698 GNCloseServiceHandle(hService);
699
700 return 0;
701}
702
703
704/**
705 * @brief Uninstall Windows service
706 * @param servicename name of the service to delete
707 * @returns 0 on success
708 * 1 if the Windows version doesn't support services
709 * 2 if the SCM could not be openend
710 * 3 if the service cannot be accessed
711 * 4 if the service cannot be deleted
712 */
713int
714UninstallService(char *servicename)
715{
716 SC_HANDLE hManager, hService;
717
718 if (!GNOpenSCManager)
719 return 1;
720
721 hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
722 if (!hManager)
723 return 2;
724
725 if (!(hService = GNOpenService(hManager, (LPCTSTR)servicename, DELETE)))
726 {
727 if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
728 return 3;
729 else
730 goto closeSCM;
731 }
732
733 if (!GNDeleteService(hService))
734 if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
735 return 4;
736
737closeSCM:
738 GNCloseServiceHandle(hService);
739
740 return 0;
741}
742
743/**
744 * @author Scott Field, Microsoft
745 * @see http://support.microsoft.com/?scid=kb;en-us;132958
746 * @date 12-Jul-95
747 */
748void
749_InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
750{
751 DWORD StringLength;
752
753 if (String == NULL)
754 {
755 LsaString->Buffer = NULL;
756 LsaString->Length = 0;
757 LsaString->MaximumLength = 0;
758 return;
759 }
760
761 StringLength = wcslen(String);
762 LsaString->Buffer = String;
763 LsaString->Length = (USHORT)StringLength * sizeof(WCHAR);
764 LsaString->MaximumLength = (USHORT)(StringLength + 1) * sizeof(WCHAR);
765}
766
767
768/**
769 * @author Scott Field, Microsoft
770 * @see http://support.microsoft.com/?scid=kb;en-us;132958
771 * @date 12-Jul-95
772 */
773NTSTATUS
774_OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
775{
776 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
777 LSA_UNICODE_STRING ServerString;
778 PLSA_UNICODE_STRING Server = NULL;
779
780 /* Always initialize the object attributes to all zeroes. */
781 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
782
783 if (ServerName != NULL)
784 {
785 /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */
786 _InitLsaString(&ServerString, ServerName);
787 Server = &ServerString;
788 }
789
790 /* Attempt to open the policy. */
791 return GNLsaOpenPolicy(Server,
792 &ObjectAttributes, DesiredAccess, PolicyHandle);
793}
794
795/**
796 * @brief Obtain a SID representing the supplied account on the supplied system
797 * @return TRUE on success, FALSE on failure
798 * @author Scott Field, Microsoft
799 * @date 12-Jul-95
800 * @remarks A buffer is allocated which contains the SID representing the
801 * supplied account. This buffer should be freed when it is no longer
802 * needed by calling\n
803 * HeapFree(GetProcessHeap(), 0, buffer)
804 * @remarks Call GetLastError() to obtain extended error information.
805 * @see http://support.microsoft.com/?scid=kb;en-us;132958
806 */
807BOOL
808_GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)
809{
810 LPTSTR ReferencedDomain = NULL;
811 DWORD cbSid = 128; /* initial allocation attempt */
812 DWORD cchReferencedDomain = 16; /* initial allocation size */
813 SID_NAME_USE peUse;
814 BOOL bSuccess = FALSE; /* assume this function will fail */
815
816 /* initial memory allocations */
817 if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
818 return FALSE;
819
820 if ((ReferencedDomain = (LPTSTR)HeapAlloc(GetProcessHeap(),
821 0,
822 cchReferencedDomain *
823 sizeof(TCHAR))) == NULL)
824 return FALSE;
825
826 /* Obtain the SID of the specified account on the specified system. */
827 while (!GNLookupAccountName(SystemName, /* machine to lookup account on */
828 AccountName, /* account to lookup */
829 *Sid, /* SID of interest */
830 &cbSid, /* size of SID */
831 ReferencedDomain, /* domain account was found on */
832 &cchReferencedDomain, &peUse))
833 {
834 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
835 {
836 /* reallocate memory */
837 if ((*Sid = HeapReAlloc(GetProcessHeap(), 0, *Sid, cbSid)) == NULL)
838 return FALSE;
839
840 if ((ReferencedDomain = (LPTSTR)HeapReAlloc(GetProcessHeap(),
841 0,
842 ReferencedDomain,
843 cchReferencedDomain
844 * sizeof(TCHAR))) == NULL)
845 return FALSE;
846 }
847 else
848 goto end;
849 }
850
851 /* Indicate success. */
852 bSuccess = TRUE;
853
854end:
855 /* Cleanup and indicate failure, if appropriate. */
856 HeapFree(GetProcessHeap(), 0, ReferencedDomain);
857
858 if (!bSuccess)
859 {
860 if (*Sid != NULL)
861 {
862 HeapFree(GetProcessHeap(), 0, *Sid);
863 *Sid = NULL;
864 }
865 }
866
867 return bSuccess;
868}
869
870/**
871 * @author Scott Field, Microsoft
872 * @see http://support.microsoft.com/?scid=kb;en-us;132958
873 * @date 12-Jul-95
874 */
875NTSTATUS
876_SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */
877 PSID AccountSid, /* SID to grant privilege to */
878 LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
879 BOOL bEnable /* enable or disable */
880 )
881{
882 LSA_UNICODE_STRING PrivilegeString;
883
884 /* Create a LSA_UNICODE_STRING for the privilege name. */
885 _InitLsaString(&PrivilegeString, PrivilegeName);
886
887 /* grant or revoke the privilege, accordingly */
888 if (bEnable)
889 {
890 NTSTATUS i;
891
892 i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */
893 AccountSid, /* target SID */
894 &PrivilegeString, /* privileges */
895 1 /* privilege count */
896 );
897 return i;
898 }
899 else
900 {
901 return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */
902 AccountSid, /* target SID */
903 FALSE, /* do not disable all rights */
904 &PrivilegeString, /* privileges */
905 1 /* privilege count */
906 );
907 }
908}
909
910/**
911 * @brief Create a Windows service account
912 * @return 0 on success, > 0 otherwise
913 * @param pszName the name of the account
914 * @param pszDesc description of the account
915 */
916int
917CreateServiceAccount(const char *pszName,
918 const char *pszDesc)
919{
920 USER_INFO_1 ui;
921 USER_INFO_1008 ui2;
922 NET_API_STATUS nStatus;
923 wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH];
924 LSA_HANDLE hPolicy;
925 PSID pSID;
926
927 if (!GNNetUserAdd)
928 return 1;
929 mbstowcs(wszName, pszName, strlen(pszName) + 1);
930 mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1);
931
932 memset(&ui, 0, sizeof(ui));
933 ui.usri1_name = wszName;
934 ui.usri1_password = wszName; /* account is locked anyway */
935 ui.usri1_priv = USER_PRIV_USER;
936 ui.usri1_comment = wszDesc;
937 ui.usri1_flags = UF_SCRIPT;
938
939 nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);
940
941 if (nStatus != NERR_Success && nStatus != NERR_UserExists)
942 return 2;
943
944 ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
945 GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL);
946
947 if (!NT_SUCCESS(_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy)))
948 return 3;
949
950 _GetAccountSid(NULL, (LPCTSTR)pszName, &pSID);
951
952 if (!NT_SUCCESS(_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeServiceLogonRight", TRUE)))
953 return 4;
954
955 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyInteractiveLogonRight", TRUE);
956 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyBatchLogonRight", TRUE);
957 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyNetworkLogonRight", TRUE);
958
959 GNLsaClose(hPolicy);
960
961 return 0;
962}
963
964/**
965 * @brief Grant permission to a file
966 * @param lpszFileName the name of the file or directory
967 * @param lpszAccountName the user account
968 * @param dwAccessMask the desired access (e.g. GENERIC_ALL)
969 * @return TRUE on success
970 * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&
971 */
972BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,
973 DWORD dwAccessMask)
974{
975 /* SID variables. */
976 SID_NAME_USE snuType;
977 TCHAR * szDomain = NULL;
978 DWORD cbDomain = 0;
979 LPVOID pUserSID = NULL;
980 DWORD cbUserSID = 0;
981
982 /* File SD variables. */
983 PSECURITY_DESCRIPTOR pFileSD = NULL;
984 DWORD cbFileSD = 0;
985
986 /* New SD variables. */
987 SECURITY_DESCRIPTOR newSD;
988
989 /* ACL variables. */
990 PACL pACL = NULL;
991 BOOL fDaclPresent;
992 BOOL fDaclDefaulted;
993 ACL_SIZE_INFORMATION AclInfo;
994
995 /* New ACL variables. */
996 PACL pNewACL = NULL;
997 DWORD cbNewACL = 0;
998
999 /* Temporary ACE. */
1000 LPVOID pTempAce = NULL;
1001 UINT CurrentAceIndex = 0;
1002
1003 UINT newAceIndex = 0;
1004
1005 /* Assume function will fail. */
1006 BOOL fResult = FALSE;
1007 BOOL fAPISuccess;
1008
1009 SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
1010
1011 /**
1012 * STEP 1: Get SID of the account name specified.
1013 */
1014 fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR)lpszAccountName,
1015 pUserSID, &cbUserSID, (LPTSTR)szDomain, &cbDomain, &snuType);
1016
1017 /* API should have failed with insufficient buffer. */
1018 if (fAPISuccess)
1019 goto end;
1020 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1021 {
1022 goto end;
1023 }
1024
1025 pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID);
1026 if (!pUserSID)
1027 {
1028 goto end;
1029 }
1030
1031 szDomain = (TCHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR));
1032 if (!szDomain)
1033 {
1034 goto end;
1035 }
1036
1037 fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR)lpszAccountName,
1038 pUserSID, &cbUserSID, (LPTSTR)szDomain, &cbDomain, &snuType);
1039 if (!fAPISuccess)
1040 {
1041 goto end;
1042 }
1043
1044 /**
1045 * STEP 2: Get security descriptor (SD) of the file specified.
1046 */
1047 fAPISuccess = GNGetFileSecurity((LPCTSTR)lpszFileName,
1048 secInfo, pFileSD, 0, &cbFileSD);
1049
1050 /* API should have failed with insufficient buffer. */
1051 if (fAPISuccess)
1052 goto end;
1053 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1054 {
1055 goto end;
1056 }
1057
1058 pFileSD = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1059 cbFileSD);
1060 if (!pFileSD)
1061 {
1062 goto end;
1063 }
1064
1065 fAPISuccess = GNGetFileSecurity((LPCTSTR)lpszFileName,
1066 secInfo, pFileSD, cbFileSD, &cbFileSD);
1067 if (!fAPISuccess)
1068 {
1069 goto end;
1070 }
1071
1072 /**
1073 * STEP 3: Initialize new SD.
1074 */
1075 if (!GNInitializeSecurityDescriptor(&newSD,
1076 SECURITY_DESCRIPTOR_REVISION))
1077 {
1078 goto end;
1079 }
1080
1081 /**
1082 * STEP 4: Get DACL from the old SD.
1083 */
1084 if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
1085 &fDaclDefaulted))
1086 {
1087 goto end;
1088 }
1089
1090 /**
1091 * STEP 5: Get size information for DACL.
1092 */
1093 AclInfo.AceCount = 0; // Assume NULL DACL.
1094 AclInfo.AclBytesFree = 0;
1095 AclInfo.AclBytesInUse = sizeof(ACL);
1096
1097 if (pACL == NULL)
1098 fDaclPresent = FALSE;
1099
1100 /* If not NULL DACL, gather size information from DACL. */
1101 if (fDaclPresent)
1102 {
1103 if (!GNGetAclInformation(pACL, &AclInfo,
1104 sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1105 {
1106 goto end;
1107 }
1108 }
1109
1110 /**
1111 * STEP 6: Compute size needed for the new ACL.
1112 */
1113 cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
1114 + GetLengthSid(pUserSID) - sizeof(DWORD);
1115
1116 /**
1117 * STEP 7: Allocate memory for new ACL.
1118 */
1119 pNewACL = (PACL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);
1120 if (!pNewACL)
1121 {
1122 goto end;
1123 }
1124
1125 /**
1126 * STEP 8: Initialize the new ACL.
1127 */
1128 if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
1129 {
1130 goto end;
1131 }
1132
1133 /**
1134 * STEP 9 If DACL is present, copy all the ACEs from the old DACL
1135 * to the new DACL.
1136 *
1137 * The following code assumes that the old DACL is
1138 * already in Windows 2000 preferred order. To conform
1139 * to the new Windows 2000 preferred order, first we will
1140 * copy all non-inherited ACEs from the old DACL to the
1141 * new DACL, irrespective of the ACE type.
1142 */
1143
1144 newAceIndex = 0;
1145
1146 if (fDaclPresent && AclInfo.AceCount)
1147 {
1148 for (CurrentAceIndex = 0;
1149 CurrentAceIndex < AclInfo.AceCount;
1150 CurrentAceIndex++)
1151 {
1152 /**
1153 * TEP 10: Get an ACE.
1154 */
1155 if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce))
1156 {
1157 goto end;
1158 }
1159
1160 /**
1161 * STEP 11: Check if it is a non-inherited ACE.
1162 * If it is an inherited ACE, break from the loop so
1163 * that the new access allowed non-inherited ACE can
1164 * be added in the correct position, immediately after
1165 * all non-inherited ACEs.
1166 */
1167 if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
1168 & INHERITED_ACE)
1169 break;
1170
1171 /**
1172 * STEP 12: Skip adding the ACE, if the SID matches
1173 * with the account specified, as we are going to
1174 * add an access allowed ACE with a different access
1175 * mask.
1176 */
1177 if (GNEqualSid(pUserSID,
1178 &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
1179 continue;
1180
1181 /**
1182 * STEP 13: Add the ACE to the new ACL.
1183 */
1184 if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
1185 ((PACE_HEADER)pTempAce)->AceSize))
1186 {
1187 goto end;
1188 }
1189
1190 newAceIndex++;
1191 }
1192 }
1193
1194 /**
1195 * STEP 14: Add the access-allowed ACE to the new DACL.
1196 * The new ACE added here will be in the correct position,
1197 * immediately after all existing non-inherited ACEs.
1198 */
1199 if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
1200 pUserSID))
1201 {
1202 goto end;
1203 }
1204
1205 /**
1206 * STEP 14.5: Make new ACE inheritable
1207 */
1208 if (!GetAce(pNewACL, newAceIndex, &pTempAce))
1209 goto end;
1210 ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |=
1211 (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
1212
1213 /**
1214 * STEP 15: To conform to the new Windows 2000 preferred order,
1215 * we will now copy the rest of inherited ACEs from the
1216 * old DACL to the new DACL.
1217 */
1218 if (fDaclPresent && AclInfo.AceCount)
1219 {
1220 for (;
1221 CurrentAceIndex < AclInfo.AceCount;
1222 CurrentAceIndex++)
1223 {
1224 /**
1225 * STEP 16: Get an ACE.
1226 */
1227 if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce))
1228 {
1229 goto end;
1230 }
1231
1232 /**
1233 * STEP 17: Add the ACE to the new ACL.
1234 */
1235 if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
1236 ((PACE_HEADER)pTempAce)->AceSize))
1237 {
1238 goto end;
1239 }
1240 }
1241 }
1242
1243 /**
1244 * STEP 18: Set permissions
1245 */
1246 if (GNSetNamedSecurityInfo((LPTSTR)lpszFileName, SE_FILE_OBJECT,
1247 DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS)
1248 {
1249 goto end;
1250 }
1251
1252 fResult = TRUE;
1253
1254end:
1255
1256 /**
1257 * STEP 19: Free allocated memory
1258 */
1259 if (pUserSID)
1260 HeapFree(GetProcessHeap(), 0, pUserSID);
1261
1262 if (szDomain)
1263 HeapFree(GetProcessHeap(), 0, szDomain);
1264
1265 if (pFileSD)
1266 HeapFree(GetProcessHeap(), 0, pFileSD);
1267
1268 if (pNewACL)
1269 HeapFree(GetProcessHeap(), 0, pNewACL);
1270
1271 return fResult;
1272}
1273
1274char *winErrorStr(const char *prefix, int dwErr)
1275{
1276 char *err, *ret;
1277 int mem;
1278
1279 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1280 NULL, (DWORD)dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&err,
1281 0, NULL))
1282 {
1283 err = (char *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, 1);
1284 }
1285
1286 mem = strlen(err) + strlen(prefix) + 20;
1287 ret = (char *)malloc(mem);
1288
1289 snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
1290
1291 LocalFree(err);
1292
1293 return ret;
1294}
1295
1296/**
1297 * Terminate a process by creating a remote thread within it,
1298 * which proceeds to call ExitProcess() inside that process.
1299 * Safer than TerminateProcess ().
1300 *
1301 * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/
1302 *
1303 * @param hProcess handle of a process to terminate
1304 * @param uExitCode exit code to use for ExitProcess()
1305 * @param dwTimeout number of ms to wait for the process to terminate
1306 * @return TRUE on success, FALSE on failure (check last error for the code)
1307 */
1308BOOL
1309SafeTerminateProcess(HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
1310{
1311 DWORD dwTID, dwCode, dwErr = 0;
1312 HANDLE hProcessDup = INVALID_HANDLE_VALUE;
1313 HANDLE hRT = NULL;
1314 HINSTANCE hKernel = GetModuleHandle("Kernel32");
1315 BOOL bSuccess = FALSE;
1316
1317 BOOL bDup = DuplicateHandle(GetCurrentProcess(), hProcess,
1318 GetCurrentProcess(), &hProcessDup, PROCESS_ALL_ACCESS,
1319 FALSE, 0);
1320
1321 /* Detect the special case where the process is
1322 * already dead...
1323 */
1324 if (GetExitCodeProcess(bDup ? hProcessDup : hProcess, &dwCode) &&
1325 (STILL_ACTIVE == dwCode))
1326 {
1327 FARPROC pfnExitProc;
1328
1329 pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
1330
1331 hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
1332 (LPTHREAD_START_ROUTINE)pfnExitProc, (PVOID)uExitCode, 0, &dwTID);
1333
1334 dwErr = GetLastError();
1335 }
1336 else
1337 {
1338 dwErr = ERROR_PROCESS_ABORTED;
1339 }
1340
1341 if (hRT)
1342 {
1343 /* Must wait process to terminate to
1344 * guarantee that it has exited...
1345 */
1346 DWORD dwWaitResult = WaitForSingleObject((bDup) ? hProcessDup : hProcess,
1347 dwTimeout);
1348 if (dwWaitResult == WAIT_TIMEOUT)
1349 dwErr = WAIT_TIMEOUT;
1350 else
1351 dwErr = GetLastError();
1352
1353 CloseHandle(hRT);
1354 bSuccess = dwErr == NO_ERROR;
1355 }
1356
1357 if (bDup)
1358 CloseHandle(hProcessDup);
1359
1360 SetLastError(dwErr);
1361
1362 return bSuccess;
1363}
1364
1365#endif
diff --git a/src/util/winproc.c b/src/util/winproc.c
deleted file mode 100644
index f2e4de4df..000000000
--- a/src/util/winproc.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/winproc.c
23 * @brief Functions for MS Windows
24 * @author Nils Durner
25 */
26
27#include "platform.h"
28#include "gnunet_crypto_lib.h"
29#include "gnunet_common.h"
30
31
32#ifdef MINGW
33
34static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
35#ifdef W32_VEH
36static void *GNWinVEH_handle = NULL;
37#endif
38
39TNtQuerySystemInformation GNNtQuerySystemInformation;
40TGetIfEntry GNGetIfEntry;
41TGetIpAddrTable GNGetIpAddrTable;
42TGetIfTable GNGetIfTable;
43TOpenSCManager GNOpenSCManager;
44TCreateService GNCreateService;
45TCloseServiceHandle GNCloseServiceHandle;
46TDeleteService GNDeleteService;
47TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler;
48TSetServiceStatus GNSetServiceStatus;
49TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
50TControlService GNControlService;
51TOpenService GNOpenService;
52TGetBestInterfaceEx GNGetBestInterfaceEx;
53TGetAdaptersInfo GNGetAdaptersInfo;
54TNetUserAdd GNNetUserAdd;
55TNetUserSetInfo GNNetUserSetInfo;
56TLsaOpenPolicy GNLsaOpenPolicy;
57TLsaAddAccountRights GNLsaAddAccountRights;
58TLsaRemoveAccountRights GNLsaRemoveAccountRights;
59TLsaClose GNLsaClose;
60TLookupAccountName GNLookupAccountName;
61TGetFileSecurity GNGetFileSecurity;
62TInitializeSecurityDescriptor GNInitializeSecurityDescriptor;
63TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl;
64TGetAclInformation GNGetAclInformation;
65TInitializeAcl GNInitializeAcl;
66TGetAce GNGetAce;
67TEqualSid GNEqualSid;
68TAddAce GNAddAce;
69TAddAccessAllowedAce GNAddAccessAllowedAce;
70TSetNamedSecurityInfo GNSetNamedSecurityInfo;
71
72#define LOG(kind, ...) GNUNET_log_from(kind, "util-winproc", __VA_ARGS__)
73/**
74 * Log (panic) messages from PlibC
75 */
76void
77plibc_panic(int err, char *msg)
78{
79 LOG(((err == INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
80 "%s", msg);
81}
82
83#ifdef W32_VEH
84/**
85 * Handles exceptions (useful for debugging).
86 * Issues a DebugBreak() call if the process is being debugged (not really
87 * useful - if the process is being debugged, this handler won't be invoked
88 * anyway). If it is not, runs a debugger from GNUNET_DEBUGGER env var,
89 * substituting first %u in it for PID, and the second one for the event,
90 * that should be set once the debugger attaches itself (otherwise the
91 * only way out of WaitForSingleObject() is to time out after 1 minute).
92 */
93LONG __stdcall
94GNWinVEH(PEXCEPTION_POINTERS ExceptionInfo)
95{
96 char debugger[MAX_PATH + 1];
97 char *debugger_env = NULL;
98
99 if (IsDebuggerPresent())
100 {
101 DebugBreak();
102 return EXCEPTION_CONTINUE_EXECUTION;
103 }
104 debugger_env = getenv("GNUNET_DEBUGGER");
105 if (debugger_env != NULL)
106 {
107 STARTUPINFO si;
108 PROCESS_INFORMATION pi;
109 HANDLE event;
110 SECURITY_ATTRIBUTES sa;
111 memset(&si, 0, sizeof(si));
112 si.cb = sizeof(si);
113 memset(&pi, 0, sizeof(pi));
114 memset(&sa, 0, sizeof(sa));
115 sa.nLength = sizeof(sa);
116 sa.bInheritHandle = TRUE;
117 event = CreateEvent(&sa, FALSE, FALSE, NULL);
118 snprintf(debugger, MAX_PATH + 1, debugger_env, GetCurrentProcessId(), (uintptr_t)event);
119 debugger[MAX_PATH] = '\0';
120 if (0 != CreateProcessA(NULL, debugger, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
121 {
122 CloseHandle(pi.hProcess);
123 CloseHandle(pi.hThread);
124 WaitForSingleObject(event, 60000);
125 CloseHandle(event);
126 if (IsDebuggerPresent())
127 {
128 return EXCEPTION_CONTINUE_EXECUTION;
129 }
130 }
131 else
132 CloseHandle(event);
133 }
134 return EXCEPTION_CONTINUE_SEARCH;
135}
136#endif
137
138/**
139 * @brief Initialize PlibC and set up Windows environment
140 * @param logging context, NULL means stderr
141 * @return Error code from winerror.h, ERROR_SUCCESS on success
142 */
143int
144GNInitWinEnv()
145{
146 int ret;
147
148 plibc_initialized();
149 plibc_set_panic_proc(plibc_panic);
150 ret = plibc_init_utf8("GNU", PACKAGE, 1);
151 plibc_set_stat_size_size(sizeof(((struct stat *)0)->st_size));
152 plibc_set_stat_time_size(sizeof(((struct stat *)0)->st_mtime));
153 /* don't load other DLLs twice */
154 if (hNTDLL)
155 return ret;
156
157#ifdef W32_VEH
158 if (GNWinVEH_handle == NULL)
159 {
160 GNWinVEH_handle = AddVectoredExceptionHandler(1, &GNWinVEH);
161 if (GNWinVEH_handle == NULL)
162 {
163 /* This is bad, but what can we do? */
164 printf("Failed to set up an exception handler!\n");
165 }
166 }
167#endif
168
169 hNTDLL = LoadLibrary("ntdll.dll");
170
171 /* Function to get CPU usage under Win NT */
172 if (hNTDLL)
173 {
174 GNNtQuerySystemInformation =
175 (TNtQuerySystemInformation)GetProcAddress(hNTDLL,
176 "NtQuerySystemInformation");
177 }
178 else
179 {
180 GNNtQuerySystemInformation = NULL;
181 }
182
183 /* Functions to get information about a network adapter */
184 hIphlpapi = LoadLibrary("iphlpapi.dll");
185 if (hIphlpapi)
186 {
187 GNGetIfEntry = (TGetIfEntry)GetProcAddress(hIphlpapi, "GetIfEntry");
188 GNGetIpAddrTable =
189 (TGetIpAddrTable)GetProcAddress(hIphlpapi, "GetIpAddrTable");
190 GNGetIfTable = (TGetIfTable)GetProcAddress(hIphlpapi, "GetIfTable");
191 GNGetBestInterfaceEx =
192 (TGetBestInterfaceEx)GetProcAddress(hIphlpapi, "GetBestInterfaceEx");
193 GNGetAdaptersInfo =
194 (TGetAdaptersInfo)GetProcAddress(hIphlpapi, "GetAdaptersInfo");
195 }
196 else
197 {
198 GNGetIfEntry = NULL;
199 GNGetIpAddrTable = NULL;
200 GNGetIfTable = NULL;
201 GNGetBestInterfaceEx = NULL;
202 GNGetAdaptersInfo = NULL;
203 }
204
205 /* Service & Account functions */
206 hAdvapi = LoadLibrary("advapi32.dll");
207 if (hAdvapi)
208 {
209 GNOpenSCManager =
210 (TOpenSCManager)GetProcAddress(hAdvapi, "OpenSCManagerA");
211 GNCreateService =
212 (TCreateService)GetProcAddress(hAdvapi, "CreateServiceA");
213 GNCloseServiceHandle =
214 (TCloseServiceHandle)GetProcAddress(hAdvapi, "CloseServiceHandle");
215 GNDeleteService =
216 (TDeleteService)GetProcAddress(hAdvapi, "DeleteService");
217 GNRegisterServiceCtrlHandler =
218 (TRegisterServiceCtrlHandler)GetProcAddress(hAdvapi,
219 "RegisterServiceCtrlHandlerA");
220 GNSetServiceStatus =
221 (TSetServiceStatus)GetProcAddress(hAdvapi, "SetServiceStatus");
222 GNStartServiceCtrlDispatcher =
223 (TStartServiceCtrlDispatcher)GetProcAddress(hAdvapi,
224 "StartServiceCtrlDispatcherA");
225 GNControlService =
226 (TControlService)GetProcAddress(hAdvapi, "ControlService");
227 GNOpenService = (TOpenService)GetProcAddress(hAdvapi, "OpenServiceA");
228
229 GNLsaOpenPolicy =
230 (TLsaOpenPolicy)GetProcAddress(hAdvapi, "LsaOpenPolicy");
231 GNLsaAddAccountRights =
232 (TLsaAddAccountRights)GetProcAddress(hAdvapi, "LsaAddAccountRights");
233 GNLsaRemoveAccountRights =
234 (TLsaRemoveAccountRights)GetProcAddress(hAdvapi,
235 "LsaRemoveAccountRights");
236 GNLsaClose = (TLsaClose)GetProcAddress(hAdvapi, "LsaClose");
237 GNLookupAccountName =
238 (TLookupAccountName)GetProcAddress(hAdvapi, "LookupAccountNameA");
239
240 GNGetFileSecurity =
241 (TGetFileSecurity)GetProcAddress(hAdvapi, "GetFileSecurityA");
242 GNInitializeSecurityDescriptor =
243 (TInitializeSecurityDescriptor)GetProcAddress(hAdvapi,
244 "InitializeSecurityDescriptor");
245 GNGetSecurityDescriptorDacl =
246 (TGetSecurityDescriptorDacl)GetProcAddress(hAdvapi,
247 "GetSecurityDescriptorDacl");
248 GNGetAclInformation =
249 (TGetAclInformation)GetProcAddress(hAdvapi, "GetAclInformation");
250 GNInitializeAcl =
251 (TInitializeAcl)GetProcAddress(hAdvapi, "InitializeAcl");
252 GNGetAce = (TGetAce)GetProcAddress(hAdvapi, "GetAce");
253 GNEqualSid = (TEqualSid)GetProcAddress(hAdvapi, "EqualSid");
254 GNAddAce = (TAddAce)GetProcAddress(hAdvapi, "AddAce");
255 GNAddAccessAllowedAce =
256 (TAddAccessAllowedAce)GetProcAddress(hAdvapi, "AddAccessAllowedAce");
257 GNSetNamedSecurityInfo =
258 (TSetNamedSecurityInfo)GetProcAddress(hAdvapi,
259 "SetNamedSecurityInfoA");
260 }
261 else
262 {
263 GNOpenSCManager = NULL;
264 GNCreateService = NULL;
265 GNCloseServiceHandle = NULL;
266 GNDeleteService = NULL;
267 GNRegisterServiceCtrlHandler = NULL;
268 GNSetServiceStatus = NULL;
269 GNStartServiceCtrlDispatcher = NULL;
270 GNControlService = NULL;
271 GNOpenService = NULL;
272
273 GNLsaOpenPolicy = NULL;
274 GNLsaAddAccountRights = NULL;
275 GNLsaRemoveAccountRights = NULL;
276 GNLsaClose = NULL;
277 GNLookupAccountName = NULL;
278
279 GNGetFileSecurity = NULL;
280 GNInitializeSecurityDescriptor = NULL;
281 GNGetSecurityDescriptorDacl = NULL;
282 GNGetAclInformation = NULL;
283 GNInitializeAcl = NULL;
284 GNGetAce = NULL;
285 GNEqualSid = NULL;
286 GNAddAce = NULL;
287 GNAddAccessAllowedAce = NULL;
288 GNSetNamedSecurityInfo = NULL;
289 }
290
291 /* Account function */
292 hNetapi = LoadLibrary("netapi32.dll");
293 if (hNetapi)
294 {
295 GNNetUserAdd = (TNetUserAdd)GetProcAddress(hNetapi, "NetUserAdd");
296 GNNetUserSetInfo =
297 (TNetUserSetInfo)GetProcAddress(hNetapi, "NetUserSetInfo");
298 }
299 else
300 {
301 GNNetUserAdd = NULL;
302 GNNetUserSetInfo = NULL;
303 }
304
305 return ret;
306}
307
308/**
309 * Clean up Windows environment
310 */
311void
312GNShutdownWinEnv()
313{
314 plibc_shutdown();
315
316#ifdef W32_VEH
317 if (GNWinVEH_handle != NULL)
318 {
319 RemoveVectoredExceptionHandler(GNWinVEH_handle);
320 GNWinVEH_handle = NULL;
321 }
322#endif
323
324 FreeLibrary(hNTDLL);
325 FreeLibrary(hIphlpapi);
326 FreeLibrary(hAdvapi);
327 FreeLibrary(hNetapi);
328
329 CoUninitialize();
330}
331
332#endif /* MINGW */
333
334#if !HAVE_ATOLL
335long long
336atoll(const char *nptr)
337{
338 return atol(nptr);
339}
340#endif
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index d1f74d35b..3ad9b1a54 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -1,11 +1,6 @@
1# This Makefile.am is in the public domain 1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include 2AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
3 3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined,--export-all-symbols
6 VPNBIN = gnunet-helper-vpn
7endif
8
9if USE_COVERAGE 4if USE_COVERAGE
10 AM_CFLAGS = --coverage -O0 5 AM_CFLAGS = --coverage -O0
11endif 6endif
@@ -39,20 +34,9 @@ libexec_PROGRAMS = \
39bin_PROGRAMS = \ 34bin_PROGRAMS = \
40 gnunet-vpn 35 gnunet-vpn
41 36
42if MINGW 37gnunet_helper_vpn_SOURCES = \
43 gnunet_helper_vpn_LDFLAGS = \ 38gnunet-helper-vpn.c
44 -no-undefined -Wl,--export-all-symbols
45
46 gnunet_helper_vpn_LDADD = \
47 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \
48 -lcomdlg32 -lgdi32 -liphlpapi
49 39
50 gnunet_helper_vpn_SOURCES = \
51 gnunet-helper-vpn-windows.c
52else
53 gnunet_helper_vpn_SOURCES = \
54 gnunet-helper-vpn.c
55endif
56gnunet_service_vpn_SOURCES = \ 40gnunet_service_vpn_SOURCES = \
57 gnunet-service-vpn.c 41 gnunet-service-vpn.c
58gnunet_service_vpn_LDADD = \ 42gnunet_service_vpn_LDADD = \
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c
deleted file mode 100644
index afa4fa139..000000000
--- a/src/vpn/gnunet-helper-vpn-windows.c
+++ /dev/null
@@ -1,1610 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010, 2012 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file vpn/gnunet-helper-vpn-windows.c
22 * @brief the helper for the VPN service in win32 builds.
23 * Opens a virtual network-interface, sends data received on the if to stdout,
24 * sends data received on stdin to the interface
25 * @author Christian M. Fuchs
26 *
27 * The following list of people have reviewed this code and considered
28 * it safe since the last modification (if you reviewed it, please
29 * have your name added to the list):
30 *
31 */
32
33#include <stdio.h>
34#include <Winsock2.h>
35#include <windows.h>
36#include <setupapi.h>
37#ifndef __MINGW64_VERSION_MAJOR
38#include <ddk/cfgmgr32.h>
39#include <ddk/newdev.h>
40#else
41#include <cfgmgr32.h>
42#include <newdev.h>
43#endif
44#include <time.h>
45#include "platform.h"
46#include "tap-windows.h"
47/**
48 * Need 'struct GNUNET_HashCode' and 'struct GNUNET_PeerIdentity'.
49 */
50#include "gnunet_crypto_lib.h"
51/**
52 * Need 'struct GNUNET_MessageHeader'.
53 */
54#include "gnunet_common.h"
55
56/**
57 * Need VPN message types.
58 */
59#include "gnunet_protocols.h"
60
61/**
62 * Should we print (interesting|debug) messages that can happen during
63 * normal operation?
64 */
65#define DEBUG GNUNET_NO
66
67#if DEBUG
68/* FIXME: define with varargs... */
69#define LOG_DEBUG(msg) fprintf(stderr, "%s", msg);
70#else
71#define LOG_DEBUG(msg) do {} while (0)
72#endif
73
74/**
75 * Will this binary be run in permissions testing mode?
76 */
77static boolean privilege_testing = FALSE;
78
79/**
80 * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
81 */
82#define MAX_SIZE 65536
83
84/**
85 * Name or Path+Name of our win32 driver.
86 * The .sys and .cat files HAVE to be in the same location as this file!
87 */
88#define INF_FILE "share/gnunet/openvpn-tap32/tapw32/OemWin2k.inf"
89
90/**
91 * Name or Path+Name of our win64 driver.
92 * The .sys and .cat files HAVE to be in the same location as this file!
93 */
94#define INF_FILE64 "share/gnunet/openvpn-tap32/tapw64/OemWin2k.inf"
95
96/**
97 * Hardware ID used in the inf-file.
98 * This might change over time, as openvpn advances their driver
99 */
100#define HARDWARE_ID "tap0901"
101
102/**
103 * Minimum major-id of the driver version we can work with
104 */
105#define TAP_WIN_MIN_MAJOR 9
106
107/**
108 * Minimum minor-id of the driver version we can work with.
109 * v <= 7 has buggy IPv6.
110 * v == 8 is broken for small IPv4 Packets
111 */
112#define TAP_WIN_MIN_MINOR 9
113
114/**
115 * Time in seconds to wait for our virtual device to go up after telling it to do so.
116 *
117 * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt
118 * (in fact, 4 was chosen by a fair dice roll...)
119 */
120#define TAP32_POSTUP_WAITTIME 4
121
122/**
123 * Location of the network interface list resides in registry.
124 */
125#define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
126
127/**
128 * Our local process' PID. Used for creating a sufficiently unique additional
129 * hardware ID for our device.
130 */
131static char secondary_hwid[LINE_LEN / 2];
132
133/**
134 * Device's visible Name, used to identify a network device in netsh.
135 * eg: "Local Area Connection 9"
136 */
137static char device_visible_name[256];
138
139/**
140 * This is our own local instance of a virtual network interface
141 * It is (somewhat) equivalent to using tun/tap in unixoid systems
142 *
143 * Upon initialization, we create such an device node.
144 * Upon termination, we remove it again.
145 *
146 * If we crash this device might stay around.
147 */
148static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE;
149
150/**
151 * Registry Key we hand over to windows to spawn a new virtual interface
152 */
153static SP_DEVINFO_DATA DeviceNode;
154
155/**
156 * GUID of our virtual device in the form of
157 * {12345678-1234-1234-1234-123456789abc} - in hex
158 */
159static char device_guid[256];
160
161
162/**
163 * Possible states of an IO facility.
164 */
165enum IO_State {
166 /**
167 * overlapped I/O is ready for work
168 */
169 IOSTATE_READY = 0,
170
171 /**
172 * overlapped I/O has been queued
173 */
174 IOSTATE_QUEUED,
175
176 /**
177 * overlapped I/O has finished, but is waiting for it's write-partner
178 */
179 IOSTATE_WAITING,
180
181 /**
182 * there is a full buffer waiting
183 */
184 IOSTATE_RESUME,
185
186 /**
187 * Operlapped IO states for facility objects
188 * overlapped I/O has failed, stop processing
189 */
190 IOSTATE_FAILED
191};
192
193
194/**
195 * A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling
196 */
197struct io_facility {
198 /**
199 * The mode the state machine associated with this object is in.
200 */
201 enum IO_State facility_state;
202
203 /**
204 * If the path is open or blocked in general (used for quickly checking)
205 */
206 BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)!
207
208 /**
209 * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT)
210 */
211 HANDLE handle;
212
213 /**
214 * Overlaped IO structure used for asynchronous IO in windows.
215 */
216 OVERLAPPED overlapped;
217
218 /**
219 * Buffer for reading things to and writing from...
220 */
221 unsigned char buffer[MAX_SIZE];
222
223 /**
224 * How much of this buffer was used when reading or how much data can be written
225 */
226 DWORD buffer_size;
227
228 /**
229 * Amount of data actually written or read by readfile/writefile.
230 */
231 DWORD buffer_size_processed;
232
233 /**
234 * How much of this buffer we have writte in total
235 */
236 DWORD buffer_size_written;
237};
238
239/**
240 * ReOpenFile is only available as of XP SP2 and 2003 SP1
241 */
242WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE, DWORD, DWORD, DWORD);
243
244/**
245 * IsWow64Process definition for our is_win64, as this is a kernel function
246 */
247typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
248
249
250/**
251 * Like strlcpy but portable. The given string @a src is copied until its null
252 * byte or until @a n - 1 bytes have been read. The destination buffer is
253 * guaranteed to be null-terminated.
254 *
255 * @param dst destination of the copy (must be @a n bytes long)
256 * @param src source of the copy (at most @a n - 1 bytes will be read)
257 * @param n the length of the string to copy, including its terminating null
258 * byte
259 * @return the length of the string that was copied, excluding the terminating
260 * null byte
261 */
262size_t
263GNUNET_strlcpy(char *dst, const char *src, size_t n)
264{
265 size_t ret;
266 size_t slen;
267
268 GNUNET_assert(0 != n);
269 slen = strnlen(src, n - 1);
270 memcpy(dst, src, slen);
271 dst[slen] = '\0';
272 return slen;
273}
274
275
276/**
277 * Determines if the host OS is win32 or win64
278 *
279 * @return true if
280 */
281BOOL
282is_win64()
283{
284#if defined(_WIN64)
285 //this is a win64 binary,
286 return TRUE;
287#elif defined(_WIN32)
288 //this is a 32bit binary, and we need to check if we are running in WOW64
289 BOOL success = FALSE;
290 BOOL on_wow64 = FALSE;
291 LPFN_ISWOW64PROCESS IsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
292
293 if (NULL != IsWow64Process)
294 success = IsWow64Process(GetCurrentProcess(), &on_wow64);
295
296 return success && on_wow64;
297#endif
298}
299/**
300 * Wrapper for executing a shellcommand in windows.
301 *
302 * @param command - the command + parameters to execute
303 * @return * exitcode of the program executed,
304 * * EINVAL (cmd/file not found)
305 * * EPIPE (could not read STDOUT)
306 */
307static int
308execute_shellcommand(const char *command)
309{
310 FILE *pipe;
311
312 if ((NULL == command) ||
313 (NULL == (pipe = _popen(command, "rt"))))
314 return EINVAL;
315
316#if DEBUG
317 fprintf(stderr, "DEBUG: Command output: \n");
318 char output[LINE_LEN];
319 while (NULL != fgets(output, sizeof(output), pipe))
320 fprintf(stderr, "%s", output);
321#endif
322
323 return _pclose(pipe);
324}
325
326
327/**
328 * @brief Sets the IPv6-Address given in address on the interface dev
329 *
330 * @param address the IPv6-Address
331 * @param prefix_len the length of the network-prefix
332 */
333static int
334set_address6(const char *address, unsigned long prefix_len)
335{
336 int ret = EINVAL;
337 char command[LINE_LEN];
338 struct sockaddr_in6 sa6;
339
340 /*
341 * parse the new address
342 */
343 memset(&sa6, 0, sizeof(struct sockaddr_in6));
344 sa6.sin6_family = AF_INET6;
345 if (1 != inet_pton(AF_INET6, address, &sa6.sin6_addr.s6_addr))
346 {
347 fprintf(stderr, "ERROR: Failed to parse address `%s': %s\n", address,
348 strerror(errno));
349 return -1;
350 }
351
352 /*
353 * prepare the command
354 */
355 snprintf(command, LINE_LEN,
356 "netsh interface ipv6 add address \"%s\" %s/%d store=active",
357 device_visible_name, address, prefix_len);
358 /*
359 * Set the address
360 */
361 ret = execute_shellcommand(command);
362
363 /* Did it work?*/
364 if (0 != ret)
365 fprintf(stderr, "FATAL: Setting IPv6 address failed: %s\n", strerror(ret));
366 return ret;
367}
368
369
370/**
371 * @brief Removes the IPv6-Address given in address from the interface dev
372 *
373 * @param address the IPv4-Address
374 */
375static void
376remove_address6(const char *address)
377{
378 char command[LINE_LEN];
379 int ret = EINVAL;
380
381 // sanity checking was already done in set_address6
382 /*
383 * prepare the command
384 */
385 snprintf(command, LINE_LEN,
386 "netsh interface ipv6 delete address \"%s\" store=persistent",
387 device_visible_name);
388 /*
389 * Set the address
390 */
391 ret = execute_shellcommand(command);
392
393 /* Did it work?*/
394 if (0 != ret)
395 fprintf(stderr,
396 "FATAL: removing IPv6 address failed: %s\n",
397 strerror(ret));
398}
399
400
401/**
402 * @brief Sets the IPv4-Address given in address on the interface dev
403 *
404 * @param address the IPv4-Address
405 * @param mask the netmask
406 */
407static int
408set_address4(const char *address, const char *mask)
409{
410 int ret = EINVAL;
411 char command[LINE_LEN];
412
413 struct sockaddr_in addr;
414
415 addr.sin_family = AF_INET;
416
417 /*
418 * Parse the address
419 */
420 if (1 != inet_pton(AF_INET, address, &addr.sin_addr.s_addr))
421 {
422 fprintf(stderr, "ERROR: Failed to parse address `%s': %s\n", address,
423 strerror(errno));
424 return -1;
425 }
426 // Set Device to Subnet-Mode? do we really need openvpn/tun.c:2925 ?
427
428 /*
429 * prepare the command
430 */
431 snprintf(command, LINE_LEN,
432 "netsh interface ipv4 add address \"%s\" %s %s store=active",
433 device_visible_name, address, mask);
434 /*
435 * Set the address
436 */
437 ret = execute_shellcommand(command);
438
439 /* Did it work?*/
440 if (0 != ret)
441 fprintf(stderr,
442 "FATAL: Setting IPv4 address failed: %s\n",
443 strerror(ret));
444 return ret;
445}
446
447
448/**
449 * @brief Removes the IPv4-Address given in address from the interface dev
450 *
451 * @param address the IPv4-Address
452 */
453static void
454remove_address4(const char *address)
455{
456 char command[LINE_LEN];
457 int ret = EINVAL;
458
459 // sanity checking was already done in set_address4
460
461 /*
462 * prepare the command
463 */
464 snprintf(command, LINE_LEN,
465 "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent",
466 device_visible_name);
467 /*
468 * Set the address
469 */
470 ret = execute_shellcommand(command);
471
472 /* Did it work?*/
473 if (0 != ret)
474 fprintf(stderr, "FATAL: removing IPv4 address failed: %s\n", strerror(ret));
475}
476
477
478/**
479 * Setup a new virtual interface to use for tunneling.
480 *
481 * @return: TRUE if setup was successful, else FALSE
482 */
483static BOOL
484setup_interface()
485{
486 /*
487 * where to find our inf-file. (+ the "full" path, after windows found")
488 *
489 * We do not directly input all the props here, because openvpn will update
490 * these details over time.
491 */
492 char inf_file_path[MAX_PATH];
493 char * temp_inf_filename;
494 char hwidlist[LINE_LEN + 4];
495 char class_name[128];
496 GUID class_guid;
497 int str_length = 0;
498
499 /**
500 * Set the device's hardware ID and add it to a list.
501 * This information will later on identify this device in registry.
502 */
503 str_len = GNUNET_strlcpy(hwidlist,
504 HARDWARE_ID,
505 sizeof(hwidList)) + 1;
506 /**
507 * this is kind of over-complicated, but allows keeps things independent of
508 * how the openvpn-hwid is actually stored.
509 *
510 * A HWID list is double-\0 terminated and \0 separated
511 */
512 str_len += GNUNET_strlcpy(&hwidlist[str_length],
513 secondary_hwid,
514 sizeof(hwidlist) - str_len) + 1;
515 GNUNET_assert(str_len < sizeof(hwidlist));
516 hwidlist[str_len] = '\0';
517 ++str_len;
518
519 /**
520 * Locate the inf-file, we need to store it somewhere where the system can
521 * find it. We need to pick the correct driver for win32/win64.
522 */
523 if (is_win64())
524 GetFullPathNameA(INF_FILE64, MAX_PATH, inf_file_path, &temp_inf_filename);
525 else
526 GetFullPathNameA(INF_FILE, MAX_PATH, inf_file_path, &temp_inf_filename);
527
528 fprintf(stderr, "INFO: Located our driver's .inf file at %s\n", inf_file_path);
529 /**
530 * Bootstrap our device info using the drivers inf-file
531 */
532 if (!SetupDiGetINFClassA(inf_file_path,
533 &class_guid,
534 class_name, sizeof(class_name) / sizeof(char),
535 NULL))
536 return FALSE;
537
538 /**
539 * Collect all the other needed information...
540 * let the system fill our this form
541 */
542 DeviceInfo = SetupDiCreateDeviceInfoList(&class_guid, NULL);
543 if (DeviceInfo == INVALID_HANDLE_VALUE)
544 return FALSE;
545
546 DeviceNode.cbSize = sizeof(SP_DEVINFO_DATA);
547 if (!SetupDiCreateDeviceInfoA(DeviceInfo,
548 class_name,
549 &class_guid,
550 NULL,
551 0,
552 DICD_GENERATE_ID,
553 &DeviceNode))
554 return FALSE;
555
556 /* Deploy all the information collected into the registry */
557 if (!SetupDiSetDeviceRegistryPropertyA(DeviceInfo,
558 &DeviceNode,
559 SPDRP_HARDWAREID,
560 (LPBYTE)hwidlist,
561 str_length * sizeof(char)))
562 return FALSE;
563
564 /* Install our new class(=device) into the system */
565 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
566 DeviceInfo,
567 &DeviceNode))
568 return FALSE;
569
570 /* This system call tends to take a while (several seconds!) on
571 "modern" Windoze systems */
572 if (!UpdateDriverForPlugAndPlayDevicesA(NULL,
573 secondary_hwid,
574 inf_file_path,
575 INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE,
576 NULL)) //reboot required? NEVER!
577 return FALSE;
578
579 fprintf(stderr, "DEBUG: successfully created a network device\n");
580 return TRUE;
581}
582
583
584/**
585 * Remove our new virtual interface to use for tunneling.
586 * This function must be called AFTER setup_interface!
587 *
588 * @return: TRUE if destruction was successful, else FALSE
589 */
590static BOOL
591remove_interface()
592{
593 SP_REMOVEDEVICE_PARAMS remove;
594
595 if (INVALID_HANDLE_VALUE == DeviceInfo)
596 return FALSE;
597
598 remove.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
599 remove.HwProfile = 0;
600 remove.Scope = DI_REMOVEDEVICE_GLOBAL;
601 remove.ClassInstallHeader.InstallFunction = DIF_REMOVE;
602 /*
603 * 1. Prepare our existing device information set, and place the
604 * uninstall related information into the structure
605 */
606 if (!SetupDiSetClassInstallParamsA(DeviceInfo,
607 (PSP_DEVINFO_DATA)&DeviceNode,
608 &remove.ClassInstallHeader,
609 sizeof(remove)))
610 return FALSE;
611 /*
612 * 2. Uninstall the virtual interface using the class installer
613 */
614 if (!SetupDiCallClassInstaller(DIF_REMOVE,
615 DeviceInfo,
616 (PSP_DEVINFO_DATA)&DeviceNode))
617 return FALSE;
618
619 SetupDiDestroyDeviceInfoList(DeviceInfo);
620
621 fprintf(stderr, "DEBUG: removed interface successfully\n");
622
623 return TRUE;
624}
625
626
627/**
628 * Do all the lookup necessary to retrieve the inteface's actual name
629 * off the registry.
630 *
631 * @return: TRUE if we were able to lookup the interface's name, else FALSE
632 */
633static BOOL
634resolve_interface_name()
635{
636 SP_DEVINFO_LIST_DETAIL_DATA device_details;
637 char pnp_instance_id [MAX_DEVICE_ID_LEN];
638 HKEY adapter_key_handle;
639 LONG status;
640 DWORD len;
641 int i = 0;
642 int retrys;
643 BOOL retval = FALSE;
644 char adapter[] = INTERFACE_REGISTRY_LOCATION;
645
646 /* We can obtain the PNP instance ID from our setupapi handle */
647 device_details.cbSize = sizeof(device_details);
648 if (CR_SUCCESS != CM_Get_Device_ID_ExA(DeviceNode.DevInst,
649 (PCHAR)pnp_instance_id,
650 MAX_DEVICE_ID_LEN,
651 0, //must be 0
652 NULL)) //hMachine, we are local
653 return FALSE;
654
655 fprintf(stderr, "DEBUG: Resolving interface name for network device %s\n", pnp_instance_id);
656
657 /* Registry is incredibly slow, retry for up to 30 seconds to allow registry to refresh */
658 for (retrys = 0; retrys < 120 && !retval; retrys++)
659 {
660 /* sleep for 250ms*/
661 Sleep(250);
662
663 /* Now we can use this ID to locate the correct networks interface in registry */
664 if (ERROR_SUCCESS != RegOpenKeyExA(
665 HKEY_LOCAL_MACHINE,
666 adapter,
667 0,
668 KEY_READ,
669 &adapter_key_handle))
670 return FALSE;
671
672 /* Of course there is a multitude of entries here, with arbitrary names,
673 * thus we need to iterate through there.
674 */
675 while (!retval)
676 {
677 char instance_key[256];
678 char query_key [256];
679 HKEY instance_key_handle;
680 char pnpinstanceid_name[] = "PnpInstanceID";
681 char pnpinstanceid_value[256];
682 char adaptername_name[] = "Name";
683 DWORD data_type;
684
685 len = 256 * sizeof(char);
686 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */
687 status = RegEnumKeyExA(
688 adapter_key_handle,
689 i,
690 instance_key,
691 &len,
692 NULL,
693 NULL,
694 NULL,
695 NULL);
696
697 /* this may fail due to one of two reasons:
698 * we are at the end of the list*/
699 if (ERROR_NO_MORE_ITEMS == status)
700 break;
701 // * we found a broken registry key, continue with the next key.
702 if (ERROR_SUCCESS != status)
703 goto cleanup;
704
705 /* prepare our new query string: */
706 snprintf(query_key, 256, "%s\\%s\\Connection",
707 adapter,
708 instance_key);
709
710 /* look inside instance_key\\Connection */
711 if (ERROR_SUCCESS != RegOpenKeyExA(
712 HKEY_LOCAL_MACHINE,
713 query_key,
714 0,
715 KEY_READ,
716 &instance_key_handle))
717 goto cleanup;
718
719 /* now, read our PnpInstanceID */
720 len = sizeof(pnpinstanceid_value);
721 status = RegQueryValueExA(instance_key_handle,
722 pnpinstanceid_name,
723 NULL, //reserved, always NULL according to MSDN
724 &data_type,
725 (LPBYTE)pnpinstanceid_value,
726 &len);
727
728 if (status != ERROR_SUCCESS || data_type != REG_SZ)
729 goto cleanup;
730
731 /* compare the value we got to our devices PNPInstanceID*/
732 if (0 != strncmp(pnpinstanceid_value, pnp_instance_id,
733 sizeof(pnpinstanceid_value) / sizeof(char)))
734 goto cleanup;
735
736 len = sizeof(device_visible_name);
737 status = RegQueryValueExA(
738 instance_key_handle,
739 adaptername_name,
740 NULL, //reserved, always NULL according to MSDN
741 &data_type,
742 (LPBYTE)device_visible_name,
743 &len);
744
745 if (status != ERROR_SUCCESS || data_type != REG_SZ)
746 goto cleanup;
747
748 /*
749 * we have successfully found OUR instance,
750 * save the device GUID before exiting
751 */
752 GNUNET_strlcpy(device_guid, instance_key, sizeof(device_guid));
753 retval = TRUE;
754 fprintf(stderr, "DEBUG: Interface Name lookup succeeded on retry %d, got \"%s\" %s\n", retrys, device_visible_name, device_guid);
755
756cleanup:
757 RegCloseKey(instance_key_handle);
758
759 ++i;
760 }
761
762 RegCloseKey(adapter_key_handle);
763 }
764 return retval;
765}
766
767
768/**
769 * Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET
770 *
771 * @param handle the handle to our tap device
772 * @return TRUE if the version is sufficient, else FALSE
773 */
774static BOOL
775check_tapw32_version(HANDLE handle)
776{
777 ULONG version[3];
778 DWORD len;
779
780 memset(&(version), 0, sizeof(version));
781
782 if (DeviceIoControl(handle, TAP_WIN_IOCTL_GET_VERSION,
783 &version, sizeof(version),
784 &version, sizeof(version), &len, NULL))
785 fprintf(stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n",
786 (int)version[0],
787 (int)version[1],
788 (version[2] ? "(DEBUG)" : ""));
789
790 if ((version[0] != TAP_WIN_MIN_MAJOR) ||
791 (version[1] < TAP_WIN_MIN_MINOR))
792 {
793 fprintf(stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d\n",
794 TAP_WIN_MIN_MAJOR,
795 TAP_WIN_MIN_MINOR);
796 return FALSE;
797 }
798
799 return TRUE;
800}
801
802
803/**
804 * Creates a tun-interface called dev;
805 *
806 * @return the fd to the tun or -1 on error
807 */
808static HANDLE
809init_tun()
810{
811 char device_path[256];
812 HANDLE handle;
813
814 if (!setup_interface())
815 {
816 errno = ENODEV;
817 return INVALID_HANDLE_VALUE;
818 }
819
820 if (!resolve_interface_name())
821 {
822 errno = ENODEV;
823 return INVALID_HANDLE_VALUE;
824 }
825
826 /* Open Windows TAP-Windows adapter */
827 snprintf(device_path, sizeof(device_path), "%s%s%s",
828 USERMODEDEVICEDIR,
829 device_guid,
830 TAP_WIN_SUFFIX);
831
832 handle = CreateFile(
833 device_path,
834 GENERIC_READ | GENERIC_WRITE,
835 0, /* was: FILE_SHARE_READ */
836 0,
837 OPEN_EXISTING,
838 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
839 0
840 );
841
842 if (INVALID_HANDLE_VALUE == handle)
843 {
844 fprintf(stderr, "FATAL: CreateFile failed on TAP device: %s\n", device_path);
845 return handle;
846 }
847
848 /* get driver version info */
849 if (!check_tapw32_version(handle))
850 {
851 CloseHandle(handle);
852 return INVALID_HANDLE_VALUE;
853 }
854
855 /* TODO (opt?): get MTU-Size */
856
857 fprintf(stderr, "DEBUG: successfully opened TAP device\n");
858 return handle;
859}
860
861
862/**
863 * Brings a TAP device up and sets it to connected state.
864 *
865 * @param handle the handle to our TAP device
866 * @return True if the operation succeeded, else false
867 */
868static BOOL
869tun_up(HANDLE handle)
870{
871 ULONG status = TRUE;
872 DWORD len;
873
874 if (!DeviceIoControl(handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
875 &status, sizeof(status),
876 &status, sizeof(status), &len, NULL))
877 {
878 fprintf(stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)\n");
879 return FALSE;
880 }
881
882 /* Wait for the device to go UP, might take some time. */
883 Sleep(TAP32_POSTUP_WAITTIME * 1000);
884 fprintf(stderr, "DEBUG: successfully set TAP device to UP\n");
885
886 return TRUE;
887}
888
889
890/**
891 * Attempts to read off an input facility (tap or named pipe) in overlapped mode.
892 *
893 * 1.
894 * If the input facility is in IOSTATE_READY, it will issue a new read operation to the
895 * input handle. Then it goes into IOSTATE_QUEUED state.
896 * In case the read succeeded instantly the input facility enters 3.
897 *
898 * 2.
899 * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already.
900 * If it has finished, go to state 3.
901 * If it has failed, set IOSTATE_FAILED
902 *
903 * 3.
904 * If the output facility is in state IOSTATE_READY, the read-buffer is copied to the output buffer.
905 * The input facility enters state IOSTATE_READY
906 * The output facility enters state IOSTATE_READY
907 * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING
908 *
909 * IOSTATE_WAITING is reset by the output facility, once it has completed.
910 *
911 * @param input_facility input named pipe or file to work with.
912 * @param output_facility output pipe or file to hand over data to.
913 * @return false if an event reset was impossible (OS error), else true
914 */
915static BOOL
916attempt_read_tap(struct io_facility * input_facility,
917 struct io_facility * output_facility)
918{
919 struct GNUNET_MessageHeader * hdr;
920 unsigned short size;
921
922 switch (input_facility->facility_state)
923 {
924 case IOSTATE_READY:
925 {
926 if (!ResetEvent(input_facility->overlapped.hEvent))
927 {
928 return FALSE;
929 }
930
931 input_facility->buffer_size = 0;
932
933 /* Check how the task is handled */
934 if (ReadFile(input_facility->handle,
935 input_facility->buffer,
936 sizeof(input_facility->buffer) - sizeof(struct GNUNET_MessageHeader),
937 &input_facility->buffer_size,
938 &input_facility->overlapped))
939 { /* async event processed immediately*/
940 /* reset event manually*/
941 if (!SetEvent(input_facility->overlapped.hEvent))
942 return FALSE;
943
944 fprintf(stderr, "DEBUG: tap read succeeded immediately\n");
945
946 /* we successfully read something from the TAP and now need to
947 * send it our via STDOUT. Is that possible at the moment? */
948 if ((IOSTATE_READY == output_facility->facility_state ||
949 IOSTATE_WAITING == output_facility->facility_state)
950 && (0 < input_facility->buffer_size))
951 { /* hand over this buffers content and apply message header for gnunet */
952 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
953 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
954
955 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
956 input_facility->buffer,
957 input_facility->buffer_size);
958
959 output_facility->buffer_size = size;
960 hdr->size = htons(size);
961 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
962 output_facility->facility_state = IOSTATE_READY;
963 }
964 else if (0 < input_facility->buffer_size)
965 /* If we have have read our buffer, wait for our write-partner*/
966 input_facility->facility_state = IOSTATE_WAITING;
967 }
968 else /* operation was either queued or failed*/
969 {
970 int err = GetLastError();
971 if (ERROR_IO_PENDING == err)
972 { /* operation queued */
973 input_facility->facility_state = IOSTATE_QUEUED;
974 }
975 else
976 { /* error occurred, let the rest of the elements finish */
977 input_facility->path_open = FALSE;
978 input_facility->facility_state = IOSTATE_FAILED;
979 if (IOSTATE_WAITING == output_facility->facility_state)
980 output_facility->path_open = FALSE;
981
982 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
983 }
984 }
985 }
986 return TRUE;
987
988 // We are queued and should check if the read has finished
989 case IOSTATE_QUEUED:
990 {
991 // there was an operation going on already, check if that has completed now.
992
993 if (GetOverlappedResult(input_facility->handle,
994 &input_facility->overlapped,
995 &input_facility->buffer_size,
996 FALSE))
997 { /* successful return for a queued operation */
998 if (!ResetEvent(input_facility->overlapped.hEvent))
999 return FALSE;
1000
1001 fprintf(stderr, "DEBUG: tap read succeeded delayed\n");
1002
1003 /* we successfully read something from the TAP and now need to
1004 * send it our via STDOUT. Is that possible at the moment? */
1005 if ((IOSTATE_READY == output_facility->facility_state ||
1006 IOSTATE_WAITING == output_facility->facility_state)
1007 && 0 < input_facility->buffer_size)
1008 { /* hand over this buffers content and apply message header for gnunet */
1009 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
1010 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
1011
1012 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1013 input_facility->buffer,
1014 input_facility->buffer_size);
1015
1016 output_facility->buffer_size = size;
1017 hdr->size = htons(size);
1018 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1019 output_facility->facility_state = IOSTATE_READY;
1020 input_facility->facility_state = IOSTATE_READY;
1021 }
1022 else if (0 < input_facility->buffer_size)
1023 { /* If we have have read our buffer, wait for our write-partner*/
1024 input_facility->facility_state = IOSTATE_WAITING;
1025 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
1026 }
1027 }
1028 else
1029 { /* operation still pending/queued or failed? */
1030 int err = GetLastError();
1031 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1032 { /* error occurred, let the rest of the elements finish */
1033 input_facility->path_open = FALSE;
1034 input_facility->facility_state = IOSTATE_FAILED;
1035 if (IOSTATE_WAITING == output_facility->facility_state)
1036 output_facility->path_open = FALSE;
1037 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1038 }
1039 }
1040 }
1041 return TRUE;
1042
1043 case IOSTATE_RESUME:
1044 hdr = (struct GNUNET_MessageHeader *)output_facility->buffer;
1045 size = input_facility->buffer_size + sizeof(struct GNUNET_MessageHeader);
1046
1047 GNUNET_memcpy(output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1048 input_facility->buffer,
1049 input_facility->buffer_size);
1050
1051 output_facility->buffer_size = size;
1052 hdr->size = htons(size);
1053 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1054 output_facility->facility_state = IOSTATE_READY;
1055 input_facility->facility_state = IOSTATE_READY;
1056 return TRUE;
1057
1058 default:
1059 return TRUE;
1060 }
1061}
1062
1063
1064/**
1065 * Attempts to read off an input facility (tap or named pipe) in overlapped mode.
1066 *
1067 * 1.
1068 * If the input facility is in IOSTATE_READY, it will issue a new read operation to the
1069 * input handle. Then it goes into IOSTATE_QUEUED state.
1070 * In case the read succeeded instantly the input facility enters 3.
1071 *
1072 * 2.
1073 * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already.
1074 * If it has finished, go to state 3.
1075 * If it has failed, set IOSTATE_FAILED
1076 *
1077 * 3.
1078 * If the facility is finished with ready
1079 * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader.
1080 * The input facility enters state IOSTATE_READY
1081 * The output facility enters state IOSTATE_READY
1082 * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING
1083 *
1084 * IOSTATE_WAITING is reset by the output facility, once it has completed.
1085 *
1086 * @param input_facility input named pipe or file to work with.
1087 * @param output_facility output pipe or file to hand over data to.
1088 * @return false if an event reset was impossible (OS error), else true
1089 */
1090static BOOL
1091attempt_read_stdin(struct io_facility * input_facility,
1092 struct io_facility * output_facility)
1093{
1094 struct GNUNET_MessageHeader * hdr;
1095
1096 switch (input_facility->facility_state)
1097 {
1098 case IOSTATE_READY:
1099 {
1100 input_facility->buffer_size = 0;
1101
1102partial_read_iostate_ready:
1103 if (!ResetEvent(input_facility->overlapped.hEvent))
1104 return FALSE;
1105
1106 /* Check how the task is handled */
1107 if (ReadFile(input_facility->handle,
1108 input_facility->buffer + input_facility->buffer_size,
1109 sizeof(input_facility->buffer) - input_facility->buffer_size,
1110 &input_facility->buffer_size_processed,
1111 &input_facility->overlapped))
1112 { /* async event processed immediately*/
1113 hdr = (struct GNUNET_MessageHeader *)input_facility->buffer;
1114
1115 /* reset event manually*/
1116 if (!SetEvent(input_facility->overlapped.hEvent))
1117 return FALSE;
1118
1119 fprintf(stderr, "DEBUG: stdin read succeeded immediately\n");
1120 input_facility->buffer_size += input_facility->buffer_size_processed;
1121
1122 if (ntohs(hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER ||
1123 ntohs(hdr->size) > sizeof(input_facility->buffer))
1124 {
1125 fprintf(stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->type), ntohs(hdr->size));
1126 input_facility->facility_state = IOSTATE_READY;
1127 return TRUE;
1128 }
1129 /* we got the a part of a packet */
1130 if (ntohs(hdr->size) > input_facility->buffer_size)
1131 goto partial_read_iostate_ready;
1132
1133 /* have we read more than 0 bytes of payload? (sizeread > header)*/
1134 if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader) &&
1135 ((IOSTATE_READY == output_facility->facility_state) ||
1136 (IOSTATE_WAITING == output_facility->facility_state)))
1137 { /* we successfully read something from the TAP and now need to
1138 * send it our via STDOUT. Is that possible at the moment? */
1139 /* hand over this buffers content and strip gnunet message header */
1140 GNUNET_memcpy(output_facility->buffer,
1141 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1142 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1143 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1144 output_facility->facility_state = IOSTATE_READY;
1145 input_facility->facility_state = IOSTATE_READY;
1146 }
1147 else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1148 /* If we have have read our buffer, wait for our write-partner*/
1149 input_facility->facility_state = IOSTATE_WAITING;
1150 else /* we read nothing */
1151 input_facility->facility_state = IOSTATE_READY;
1152 }
1153 else /* operation was either queued or failed*/
1154 {
1155 int err = GetLastError();
1156 if (ERROR_IO_PENDING == err) /* operation queued */
1157 input_facility->facility_state = IOSTATE_QUEUED;
1158 else
1159 { /* error occurred, let the rest of the elements finish */
1160 input_facility->path_open = FALSE;
1161 input_facility->facility_state = IOSTATE_FAILED;
1162 if (IOSTATE_WAITING == output_facility->facility_state)
1163 output_facility->path_open = FALSE;
1164
1165 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1166 }
1167 }
1168 }
1169 return TRUE;
1170
1171 // We are queued and should check if the read has finished
1172 case IOSTATE_QUEUED:
1173 {
1174 // there was an operation going on already, check if that has completed now.
1175 if (GetOverlappedResult(input_facility->handle,
1176 &input_facility->overlapped,
1177 &input_facility->buffer_size_processed,
1178 FALSE))
1179 { /* successful return for a queued operation */
1180 hdr = (struct GNUNET_MessageHeader *)input_facility->buffer;
1181
1182 if (!ResetEvent(input_facility->overlapped.hEvent))
1183 return FALSE;
1184
1185 fprintf(stderr, "DEBUG: stdin read succeeded delayed\n");
1186 input_facility->buffer_size += input_facility->buffer_size_processed;
1187
1188 if ((ntohs(hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1189 (ntohs(hdr->size) > sizeof(input_facility->buffer)))
1190 {
1191 fprintf(stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->type), ntohs(hdr->size));
1192 input_facility->facility_state = IOSTATE_READY;
1193 return TRUE;
1194 }
1195 /* we got the a part of a packet */
1196 if (ntohs(hdr->size) > input_facility->buffer_size)
1197 ;
1198 goto partial_read_iostate_ready;
1199
1200 /* we successfully read something from the TAP and now need to
1201 * send it our via STDOUT. Is that possible at the moment? */
1202 if ((IOSTATE_READY == output_facility->facility_state ||
1203 IOSTATE_WAITING == output_facility->facility_state)
1204 && input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1205 { /* hand over this buffers content and strip gnunet message header */
1206 GNUNET_memcpy(output_facility->buffer,
1207 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1208 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1209 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1210 output_facility->facility_state = IOSTATE_READY;
1211 input_facility->facility_state = IOSTATE_READY;
1212 }
1213 else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader))
1214 input_facility->facility_state = IOSTATE_WAITING;
1215 else
1216 input_facility->facility_state = IOSTATE_READY;
1217 }
1218 else
1219 { /* operation still pending/queued or failed? */
1220 int err = GetLastError();
1221 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1222 { /* error occurred, let the rest of the elements finish */
1223 input_facility->path_open = FALSE;
1224 input_facility->facility_state = IOSTATE_FAILED;
1225 if (IOSTATE_WAITING == output_facility->facility_state)
1226 output_facility->path_open = FALSE;
1227 fprintf(stderr, "FATAL: Read from handle failed, allowing write to finish\n");
1228 }
1229 }
1230 }
1231 return TRUE;
1232
1233 case IOSTATE_RESUME: /* Our buffer was filled already but our write facility was busy. */
1234 GNUNET_memcpy(output_facility->buffer,
1235 input_facility->buffer + sizeof(struct GNUNET_MessageHeader),
1236 input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
1237 output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
1238 output_facility->facility_state = IOSTATE_READY;
1239 input_facility->facility_state = IOSTATE_READY;
1240 return TRUE;
1241
1242 default:
1243 return TRUE;
1244 }
1245}
1246
1247
1248/**
1249 * Attempts to write to an output facility (tap or named pipe) in overlapped mode.
1250 *
1251 * TODO: high level description
1252 *
1253 * @param output_facility output pipe or file to hand over data to.
1254 * @param input_facility input named pipe or file to work with.
1255 * @return false if an event reset was impossible (OS error), else true
1256 */
1257static BOOL
1258attempt_write(struct io_facility * output_facility,
1259 struct io_facility * input_facility)
1260{
1261 switch (output_facility->facility_state)
1262 {
1263 case IOSTATE_READY:
1264 output_facility->buffer_size_written = 0;
1265
1266continue_partial_write:
1267 if (!ResetEvent(output_facility->overlapped.hEvent))
1268 return FALSE;
1269
1270 /* Check how the task was handled */
1271 if (WriteFile(output_facility->handle,
1272 output_facility->buffer + output_facility->buffer_size_written,
1273 output_facility->buffer_size - output_facility->buffer_size_written,
1274 &output_facility->buffer_size_processed,
1275 &output_facility->overlapped))
1276 {/* async event processed immediately*/
1277 fprintf(stderr, "DEBUG: write succeeded immediately\n");
1278 output_facility->buffer_size_written += output_facility->buffer_size_processed;
1279
1280 /* reset event manually*/
1281 if (!SetEvent(output_facility->overlapped.hEvent))
1282 return FALSE;
1283
1284 /* partial write */
1285 if (output_facility->buffer_size_written < output_facility->buffer_size)
1286 goto continue_partial_write;
1287
1288 /* we are now waiting for our buffer to be filled*/
1289 output_facility->facility_state = IOSTATE_WAITING;
1290
1291 /* we successfully wrote something and now need to reset our reader */
1292 if (IOSTATE_WAITING == input_facility->facility_state)
1293 input_facility->facility_state = IOSTATE_RESUME;
1294 else if (IOSTATE_FAILED == input_facility->facility_state)
1295 output_facility->path_open = FALSE;
1296 }
1297 else /* operation was either queued or failed*/
1298 {
1299 int err = GetLastError();
1300 if (ERROR_IO_PENDING == err)
1301 { /* operation queued */
1302 output_facility->facility_state = IOSTATE_QUEUED;
1303 }
1304 else
1305 { /* error occurred, close this path */
1306 output_facility->path_open = FALSE;
1307 output_facility->facility_state = IOSTATE_FAILED;
1308 fprintf(stderr, "FATAL: Write to handle failed, exiting\n");
1309 }
1310 }
1311 return TRUE;
1312
1313 case IOSTATE_QUEUED:
1314 // there was an operation going on already, check if that has completed now.
1315
1316 if (GetOverlappedResult(output_facility->handle,
1317 &output_facility->overlapped,
1318 &output_facility->buffer_size_processed,
1319 FALSE))
1320 {/* successful return for a queued operation */
1321 if (!ResetEvent(output_facility->overlapped.hEvent))
1322 return FALSE;
1323
1324 fprintf(stderr, "DEBUG: write succeeded delayed\n");
1325 output_facility->buffer_size_written += output_facility->buffer_size_processed;
1326
1327 /* partial write */
1328 if (output_facility->buffer_size_written < output_facility->buffer_size)
1329 goto continue_partial_write;
1330
1331 /* we are now waiting for our buffer to be filled*/
1332 output_facility->facility_state = IOSTATE_WAITING;
1333
1334 /* we successfully wrote something and now need to reset our reader */
1335 if (IOSTATE_WAITING == input_facility->facility_state)
1336 input_facility->facility_state = IOSTATE_RESUME;
1337 else if (IOSTATE_FAILED == input_facility->facility_state)
1338 output_facility->path_open = FALSE;
1339 }
1340 else
1341 { /* operation still pending/queued or failed? */
1342 int err = GetLastError();
1343 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1344 { /* error occurred, close this path */
1345 output_facility->path_open = FALSE;
1346 output_facility->facility_state = IOSTATE_FAILED;
1347 fprintf(stderr, "FATAL: Write to handle failed, exiting\n");
1348 }
1349 }
1350
1351 default:
1352 return TRUE;
1353 }
1354}
1355
1356
1357/**
1358 * Initialize a overlapped structure
1359 *
1360 * @param elem the element to initilize
1361 * @param initial_state the initial state for this instance
1362 * @param signaled if the hEvent created should default to signaled or not
1363 * @return true on success, else false
1364 */
1365static BOOL
1366initialize_io_facility(struct io_facility * elem,
1367 int initial_state,
1368 BOOL signaled)
1369{
1370 elem->path_open = TRUE;
1371 elem->handle = INVALID_HANDLE_VALUE;
1372 elem->facility_state = initial_state;
1373 elem->buffer_size = 0;
1374 elem->overlapped.hEvent = CreateEvent(NULL, TRUE, signaled, NULL);
1375 if (NULL == elem->overlapped.hEvent)
1376 return FALSE;
1377
1378 return TRUE;
1379}
1380
1381
1382/**
1383 * Start forwarding to and from the tunnel.
1384 *
1385 * @param tap_handle device handle for interacting with the Virtual interface
1386 */
1387static void
1388run(HANDLE tap_handle)
1389{
1390 /* IO-Facility for reading from our virtual interface */
1391 struct io_facility tap_read;
1392 /* IO-Facility for writing to our virtual interface */
1393 struct io_facility tap_write;
1394 /* IO-Facility for reading from stdin */
1395 struct io_facility std_in;
1396 /* IO-Facility for writing to stdout */
1397 struct io_facility std_out;
1398
1399 HANDLE parent_std_in_handle = GetStdHandle(STD_INPUT_HANDLE);
1400 HANDLE parent_std_out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
1401
1402 /* tun up: */
1403 /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn
1404 * to remove the need to flush the arp cache, handle DHCP and wrong IPs.
1405 *
1406 * DHCP and such are all features we will never use in gnunet afaik.
1407 * But for openvpn those are essential.
1408 */
1409 if ((privilege_testing) || (!tun_up(tap_handle)))
1410 goto teardown_final;
1411
1412 /* Initialize our overlapped IO structures*/
1413 if (!(initialize_io_facility(&tap_read, IOSTATE_READY, FALSE)
1414 && initialize_io_facility(&tap_write, IOSTATE_WAITING, TRUE)
1415 && initialize_io_facility(&std_in, IOSTATE_READY, FALSE)
1416 && initialize_io_facility(&std_out, IOSTATE_WAITING, TRUE)))
1417 goto teardown_final;
1418
1419 /* Handles for STDIN and STDOUT */
1420 tap_read.handle = tap_handle;
1421 tap_write.handle = tap_handle;
1422
1423#ifdef DEBUG_TO_CONSOLE
1424 /* Debug output to console STDIN/STDOUT*/
1425 std_in.handle = parent_std_in_handle;
1426 std_out.handle = parent_std_out_handle;
1427#else
1428 fprintf(stderr, "DEBUG: reopening stdin/out for overlapped IO\n");
1429 /*
1430 * Find out the types of our handles.
1431 * This part is a problem, because in windows we need to handle files,
1432 * pipes and the console differently.
1433 */
1434 if ((FILE_TYPE_PIPE != GetFileType(parent_std_in_handle)) ||
1435 (FILE_TYPE_PIPE != GetFileType(parent_std_out_handle)))
1436 {
1437 fprintf(stderr, "ERROR: stdin/stdout must be named pipes\n");
1438 goto teardown;
1439 }
1440
1441 std_in.handle = ReOpenFile(parent_std_in_handle,
1442 GENERIC_READ,
1443 FILE_SHARE_WRITE | FILE_SHARE_READ,
1444 FILE_FLAG_OVERLAPPED);
1445
1446 if (INVALID_HANDLE_VALUE == std_in.handle)
1447 {
1448 fprintf(stderr, "FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe\n");
1449 goto teardown;
1450 }
1451
1452 std_out.handle = ReOpenFile(parent_std_out_handle,
1453 GENERIC_WRITE,
1454 FILE_SHARE_READ,
1455 FILE_FLAG_OVERLAPPED);
1456
1457 if (INVALID_HANDLE_VALUE == std_out.handle)
1458 {
1459 fprintf(stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe\n");
1460 goto teardown;
1461 }
1462#endif
1463
1464 fprintf(stderr, "DEBUG: mainloop has begun\n");
1465
1466 while (std_out.path_open || tap_write.path_open)
1467 {
1468 /* perform READ from stdin if possible */
1469 if (std_in.path_open && (!attempt_read_stdin(&std_in, &tap_write)))
1470 break;
1471
1472 /* perform READ from tap if possible */
1473 if (tap_read.path_open && (!attempt_read_tap(&tap_read, &std_out)))
1474 break;
1475
1476 /* perform WRITE to tap if possible */
1477 if (tap_write.path_open && (!attempt_write(&tap_write, &std_in)))
1478 break;
1479
1480 /* perform WRITE to STDOUT if possible */
1481 if (std_out.path_open && (!attempt_write(&std_out, &tap_read)))
1482 break;
1483 }
1484
1485 fprintf(stderr, "DEBUG: teardown initiated\n");
1486teardown:
1487 CancelIo(tap_handle);
1488 CancelIo(std_in.handle);
1489 CancelIo(std_out.handle);
1490teardown_final:
1491 CloseHandle(tap_handle);
1492}
1493
1494
1495/**
1496 * Open VPN tunnel interface.
1497 *
1498 * @param argc must be 6
1499 * @param argv 0: binary name (gnunet-helper-vpn)
1500 * [1: dryrun/testrun (does not execute mainloop)]
1501 * 2: tunnel interface prefix (gnunet-vpn)
1502 * 3: IPv6 address (::1), "-" to disable
1503 * 4: IPv6 netmask length in bits (64), ignored if #2 is "-"
1504 * 5: IPv4 address (1.2.3.4), "-" to disable
1505 * 6: IPv4 netmask (255.255.0.0), ignored if #4 is "-"
1506 */
1507int
1508main(int argc, char **argv)
1509{
1510 char hwid[LINE_LEN];
1511 HANDLE handle;
1512 int global_ret = 0;
1513 BOOL have_ip4 = FALSE;
1514 BOOL have_ip6 = FALSE;
1515
1516 if (argc > 1 && 0 == strcmp(argv[1], "-d"))
1517 {
1518 privilege_testing = TRUE;
1519 fprintf(stderr,
1520 "%s",
1521 "DEBUG: Running binary in privilege testing mode.");
1522 argv++;
1523 argc--;
1524 }
1525
1526 if (6 != argc)
1527 {
1528 fprintf(stderr,
1529 "%s",
1530 "FATAL: must supply 5 arguments\nUsage:\ngnunet-helper-vpn [-d] <if name prefix> <address6 or \"-\"> <netbits6> <address4 or \"-\"> <netmask4>\n");
1531 return 1;
1532 }
1533
1534 GNUNET_strlcpy(hwid, argv[1], sizeof(hwid));
1535
1536 /*
1537 * We use our PID for finding/resolving the control-panel name of our virtual
1538 * device. PIDs are (of course) unique at runtime, thus we can safely use it
1539 * as additional hardware-id for our device.
1540 */
1541 snprintf(secondary_hwid, LINE_LEN / 2, "%s-%d",
1542 hwid,
1543 _getpid());
1544
1545 if (INVALID_HANDLE_VALUE == (handle = init_tun()))
1546 {
1547 fprintf(stderr, "FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n",
1548 hwid,
1549 argv[2],
1550 argv[3],
1551 argv[4],
1552 argv[5]);
1553 global_ret = -1;
1554 goto cleanup;
1555 }
1556
1557 fprintf(stderr, "DEBUG: Setting IPs, if needed\n");
1558 if (0 != strcmp(argv[2], "-"))
1559 {
1560 const char *address = argv[2];
1561 long prefix_len = atol(argv[3]);
1562
1563 if ((prefix_len < 1) || (prefix_len > 127))
1564 {
1565 fprintf(stderr, "FATAL: ipv6 prefix_len out of range\n");
1566 global_ret = -1;
1567 goto cleanup;
1568 }
1569
1570 fprintf(stderr, "DEBUG: Setting IP6 address: %s/%d\n", address, prefix_len);
1571 if (0 != (global_ret = set_address6(address, prefix_len)))
1572 goto cleanup;
1573
1574 have_ip6 = TRUE;
1575 }
1576
1577 if (0 != strcmp(argv[4], "-"))
1578 {
1579 const char *address = argv[4];
1580 const char *mask = argv[5];
1581
1582 fprintf(stderr, "DEBUG: Setting IP4 address: %s/%s\n", address, mask);
1583 if (0 != (global_ret = set_address4(address, mask)))
1584 goto cleanup;
1585
1586 have_ip4 = TRUE;
1587 }
1588
1589 run(handle);
1590cleanup:
1591
1592 if (have_ip4)
1593 {
1594 const char *address = argv[4];
1595 fprintf(stderr, "DEBUG: Removing IP4 address\n");
1596 remove_address4(address);
1597 }
1598 if (have_ip6)
1599 {
1600 const char *address = argv[2];
1601 fprintf(stderr, "DEBUG: Removing IP6 address\n");
1602 remove_address6(address);
1603 }
1604
1605 fprintf(stderr, "DEBUG: removing interface\n");
1606 remove_interface();
1607 fprintf(stderr, "DEBUG: graceful exit completed\n");
1608
1609 return global_ret;
1610}
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
index b655b9ef3..3d248efd8 100644
--- a/src/zonemaster/Makefile.am
+++ b/src/zonemaster/Makefile.am
@@ -10,10 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 zonemaster.conf 11 zonemaster.conf
12 12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE 13if USE_COVERAGE
18 AM_CFLAGS = --coverage -O0 14 AM_CFLAGS = --coverage -O0
19 XLIBS = -lgcov 15 XLIBS = -lgcov