diff options
author | ng0 <ng0@n0.is> | 2019-09-10 16:59:32 +0000 |
---|---|---|
committer | ng0 <ng0@n0.is> | 2019-09-10 16:59:32 +0000 |
commit | 04b6df21cd281e8cd540139f8d9ae85defc1961c (patch) | |
tree | 6357199445df8d5c0c631bc8f10aef838b1f9f1e /src | |
parent | 483b0139a218a5f8a8311bda3eb23bcd88f57688 (diff) | |
download | gnunet-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')
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/ | |||
8 | pkgcfg_DATA = \ | 8 | pkgcfg_DATA = \ |
9 | arm.conf | 9 | arm.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if 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 | ||
6 | libexecdir= $(pkglibdir)/libexec/ | 6 | libexecdir= $(pkglibdir)/libexec/ |
7 | 7 | ||
8 | if MINGW | ||
9 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
10 | endif | ||
11 | |||
12 | if USE_COVERAGE | 8 | if USE_COVERAGE |
13 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 9 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
14 | endif | 10 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 5 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
10 | endif | 6 | endif |
11 | 7 | ||
12 | bin_PROGRAMS = \ | 8 | bin_PROGRAMS = \ |
13 | gnunet-ats | 9 | gnunet-ats |
14 | 10 | ||
15 | gnunet_ats_SOURCES = \ | 11 | gnunet_ats_SOURCES = \ |
16 | gnunet-ats.c | 12 | gnunet-ats.c |
17 | gnunet_ats_LDADD = \ | 13 | gnunet_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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | ats.conf | 11 | ats.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if USE_COVERAGE |
18 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
19 | endif | 15 | endif |
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/ | |||
9 | pkgcfg_DATA = \ | 9 | pkgcfg_DATA = \ |
10 | auction.conf | 10 | auction.conf |
11 | 11 | ||
12 | if MINGW | ||
13 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
14 | endif | ||
15 | |||
16 | if USE_COVERAGE | 12 | if USE_COVERAGE |
17 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 13 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
18 | endif | 14 | endif |
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 | ||
4 | plugindir = $(libdir)/gnunet | 4 | plugindir = $(libdir)/gnunet |
5 | 5 | ||
6 | if MINGW | ||
7 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | if USE_COVERAGE | 6 | if USE_COVERAGE |
11 | AM_CFLAGS = --coverage | 7 | AM_CFLAGS = --coverage |
12 | endif | 8 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 |
42 | libgnunetcadet_la_LIBADD = \ | 38 | libgnunetcadet_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 | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | consensus.conf | 11 | consensus.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if USE_COVERAGE |
18 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
19 | endif | 15 | endif |
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 | ||
4 | plugindir = $(libdir)/gnunet | 4 | plugindir = $(libdir)/gnunet |
5 | 5 | ||
6 | if MINGW | ||
7 | WINFLAGS = -no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | AM_CPPFLAGS = \ | 6 | AM_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/ | |||
8 | pkgcfg_DATA = \ | 8 | pkgcfg_DATA = \ |
9 | core.conf | 9 | core.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if 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/ | |||
8 | dist_pkgcfg_DATA = \ | 8 | dist_pkgcfg_DATA = \ |
9 | datacache.conf | 9 | datacache.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if 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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | datastore.conf | 11 | datastore.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 | ||
5 | endif | ||
6 | 3 | ||
7 | plugindir = $(libdir)/gnunet | 4 | plugindir = $(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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage -O0 | 5 | AM_CFLAGS = --coverage -O0 |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined,--export-all-symbols | ||
6 | EXITBIN = gnunet-helper-exit | ||
7 | endif | ||
8 | |||
9 | if USE_COVERAGE | 4 | if USE_COVERAGE |
10 | AM_CFLAGS = --coverage -O0 | 5 | AM_CFLAGS = --coverage -O0 |
11 | endif | 6 | endif |
@@ -32,20 +27,10 @@ libexec_PROGRAMS = \ | |||
32 | gnunet-daemon-exit \ | 27 | gnunet-daemon-exit \ |
33 | $(EXITBIN) | 28 | $(EXITBIN) |
34 | 29 | ||
35 | if MINGW | ||
36 | gnunet_helper_exit_LDFLAGS = \ | ||
37 | -no-undefined -Wl,--export-all-symbols | ||
38 | 30 | ||
39 | gnunet_helper_exit_LDADD = \ | 31 | gnunet_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 | ||
45 | else | ||
46 | gnunet_helper_exit_SOURCES = \ | ||
47 | gnunet-helper-exit.c | ||
48 | endif | ||
49 | gnunet_daemon_exit_SOURCES = \ | 34 | gnunet_daemon_exit_SOURCES = \ |
50 | gnunet-daemon-exit.c exit.h | 35 | gnunet-daemon-exit.c exit.h |
51 | gnunet_daemon_exit_LDADD = \ | 36 | gnunet_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 | */ | ||
77 | static 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 | */ | ||
131 | static 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 | */ | ||
137 | static 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 | */ | ||
148 | static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE; | ||
149 | |||
150 | /** | ||
151 | * Registry Key we hand over to windows to spawn a new virtual interface | ||
152 | */ | ||
153 | static 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 | */ | ||
159 | static char device_guid[256]; | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Possible states of an IO facility. | ||
164 | */ | ||
165 | enum 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 | */ | ||
197 | struct 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 | */ | ||
242 | WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE, DWORD, DWORD, DWORD); | ||
243 | |||
244 | /** | ||
245 | * IsWow64Process definition for our is_win64, as this is a kernel function | ||
246 | */ | ||
247 | typedef 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 | */ | ||
262 | size_t | ||
263 | GNUNET_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 | */ | ||
281 | BOOL | ||
282 | is_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 | */ | ||
307 | static int | ||
308 | execute_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 | */ | ||
333 | static int | ||
334 | set_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 | */ | ||
375 | static void | ||
376 | remove_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 | */ | ||
405 | static int | ||
406 | set_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 | */ | ||
450 | static void | ||
451 | remove_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 | */ | ||
480 | static BOOL | ||
481 | setup_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 | */ | ||
588 | static BOOL | ||
589 | remove_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 | */ | ||
631 | static BOOL | ||
632 | resolve_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 | |||
754 | cleanup: | ||
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 | */ | ||
772 | static BOOL | ||
773 | check_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 | */ | ||
806 | static HANDLE | ||
807 | init_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 | */ | ||
866 | static BOOL | ||
867 | tun_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 | */ | ||
913 | static BOOL | ||
914 | attempt_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 | */ | ||
1088 | static BOOL | ||
1089 | attempt_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 | |||
1100 | partial_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 | */ | ||
1255 | static BOOL | ||
1256 | attempt_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 | |||
1264 | continue_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 | */ | ||
1363 | static BOOL | ||
1364 | initialize_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 | */ | ||
1385 | static void | ||
1386 | run(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 | |||
1484 | teardown: | ||
1485 | |||
1486 | CancelIo(tap_handle); | ||
1487 | CancelIo(std_in.handle); | ||
1488 | CancelIo(std_out.handle); | ||
1489 | |||
1490 | teardown_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 | */ | ||
1508 | int | ||
1509 | main(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); | ||
1667 | cleanup: | ||
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 | ||
28 | if 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 | ||
35 | endif | ||
36 | USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la | 27 | USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la |
37 | 28 | ||
38 | if USE_COVERAGE | 29 | if USE_COVERAGE |
@@ -46,11 +37,9 @@ libexecdir= $(pkglibdir)/libexec/ | |||
46 | plugindir = $(libdir)/gnunet | 37 | plugindir = $(libdir)/gnunet |
47 | 38 | ||
48 | pkgcfg_DATA = \ | 39 | pkgcfg_DATA = \ |
49 | gns.conf \ | 40 | gns.conf |
50 | $(DO_W32_HS_CONF) | ||
51 | 41 | ||
52 | lib_LTLIBRARIES = \ | 42 | lib_LTLIBRARIES = \ |
53 | $(DO_W32_NSP) \ | ||
54 | libgnunetgns.la | 43 | libgnunetgns.la |
55 | 44 | ||
56 | 45 | ||
@@ -73,12 +62,9 @@ endif | |||
73 | libexec_PROGRAMS = \ | 62 | libexec_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 | ||
79 | bin_PROGRAMS = \ | 67 | bin_PROGRAMS = \ |
80 | $(DO_W32_NSPTOOLS) \ | ||
81 | $(DO_NONPOSIX_GNSIMPORT) \ | ||
82 | gnunet-gns | 68 | gnunet-gns |
83 | 69 | ||
84 | noinst_PROGRAMS = \ | 70 | noinst_PROGRAMS = \ |
@@ -199,35 +185,15 @@ test_gns_proxy_LDADD = $(MHD_LIBS) $(LIB_GNURL) -lgnutls \ | |||
199 | $(GN_LIBINTL) | 185 | $(GN_LIBINTL) |
200 | test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | 186 | test_gns_proxy_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) |
201 | 187 | ||
202 | gnunet_gns_helper_service_w32_SOURCES = \ | 188 | #gnunet_gns_import_SOURCES = \ |
203 | gnunet-gns-helper-service-w32.c | 189 | # gnunet-gns-import.c |
204 | gnunet_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) | |
210 | gnunet_gns_import_SOURCES = \ | ||
211 | gnunet-gns-import.c | ||
212 | gnunet_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 | ||
220 | w32nsp_install_SOURCES = \ | ||
221 | w32nsp-install.c | ||
222 | w32nsp_install_LDADD = -lws2_32 | ||
223 | |||
224 | w32nsp_uninstall_SOURCES = \ | ||
225 | w32nsp-uninstall.c | ||
226 | w32nsp_uninstall_LDADD = -lws2_32 | ||
227 | |||
228 | w32nsp_resolve_SOURCES = \ | ||
229 | w32nsp-resolve.c | ||
230 | w32nsp_resolve_LDADD = -lws2_32 | ||
231 | 197 | ||
232 | gnunet_service_gns_SOURCES = \ | 198 | gnunet_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 | ||
250 | libw32nsp_la_SOURCES = \ | ||
251 | w32nsp.c | ||
252 | libw32nsp_la_LIBADD = \ | ||
253 | -lole32 -lws2_32 | ||
254 | libw32nsp_la_LDFLAGS = \ | ||
255 | -export-symbols $(top_srcdir)/src/gns/w32nsp.def \ | ||
256 | -no-undefined -static-libgcc | ||
257 | |||
258 | libgnunetgns_la_SOURCES = \ | 216 | libgnunetgns_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] | ||
2 | START_ON_DEMAND = YES | ||
3 | BINARY = gnunet-gns-helper-service-w32 | ||
4 | PORT = 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) | ||
39 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); | ||
40 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); | ||
41 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); | ||
42 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); | ||
43 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); | ||
44 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); | ||
45 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); | ||
46 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); | ||
47 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); | ||
48 | DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); | ||
49 | DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); | ||
50 | |||
51 | |||
52 | struct 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 | */ | ||
83 | static struct request *rq_head; | ||
84 | |||
85 | /** | ||
86 | * Tail of the doubly-linked list (for cleanup). | ||
87 | */ | ||
88 | static struct request *rq_tail; | ||
89 | |||
90 | /** | ||
91 | * Handle to GNS service. | ||
92 | */ | ||
93 | static struct GNUNET_GNS_Handle *gns; | ||
94 | |||
95 | /** | ||
96 | * Active operation on identity service. | ||
97 | */ | ||
98 | static struct GNUNET_IDENTITY_Operation *id_op; | ||
99 | |||
100 | /** | ||
101 | * Handle for identity service. | ||
102 | */ | ||
103 | static struct GNUNET_IDENTITY_Handle *identity; | ||
104 | |||
105 | /** | ||
106 | * Public key of the gns-master ego | ||
107 | */ | ||
108 | static struct GNUNET_CRYPTO_EcdsaPublicKey gns_master_pubkey; | ||
109 | |||
110 | /** | ||
111 | * Set to 1 once egos are obtained. | ||
112 | */ | ||
113 | static int got_egos; | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Task run on shutdown. Cleans up everything. | ||
118 | * | ||
119 | * @param cls unused | ||
120 | */ | ||
121 | static void | ||
122 | do_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 | |||
161 | void | ||
162 | MarshallWSAQUERYSETW(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 | |||
195 | static void | ||
196 | process_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 | |||
474 | static void | ||
475 | get_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 | */ | ||
594 | static int | ||
595 | check_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 | */ | ||
624 | static void | ||
625 | handle_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 | */ | ||
693 | static void | ||
694 | identity_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 | */ | ||
720 | static void | ||
721 | run(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 | */ | ||
761 | static void * | ||
762 | client_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 | */ | ||
777 | static void | ||
778 | client_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 | */ | ||
789 | GNUNET_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 | ||
21 | EXTRA_DIST = map-file | 21 | EXTRA_DIST = map-file |
22 | 22 | ||
23 | AM_LDFLAGS=-avoid-version -module -export-dynamic | 23 | AM_LDFLAGS=-avoid-version -module -export-dynamic |
24 | 24 | ||
25 | nssdir = $(libdir)/gnunet/nss | 25 | nssdir = $(libdir)/gnunet/nss |
26 | 26 | ||
27 | if !MINGW | ||
28 | nss_LTLIBRARIES = \ | 27 | nss_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 |
32 | endif | ||
33 | 31 | ||
34 | sources = nss_gns_query.h nss_gns_query.c | 32 | sources = nss_gns_query.h nss_gns_query.c |
35 | 33 | ||
@@ -45,4 +43,3 @@ libnss_gns4_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) | |||
45 | libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) | 43 | libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) |
46 | libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 | 44 | libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 |
47 | libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) | 45 | libnss_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 | |||
33 | int | ||
34 | main(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 | |||
37 | typedef int (WSPAPI *LPNSPSTARTUP)(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines); | ||
38 | |||
39 | GUID host = { 0x0002a800, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } }; | ||
40 | GUID ip4 = { 0x00090035, 0, 1, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } }; | ||
41 | GUID ip6 = { 0x00090035, 0, 0x001c, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } }; | ||
42 | |||
43 | DEFINE_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) | ||
46 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); | ||
47 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); | ||
48 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); | ||
49 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); | ||
50 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); | ||
51 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); | ||
52 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); | ||
53 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); | ||
54 | DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); | ||
55 | DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); | ||
56 | DEFINE_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 | |||
63 | VOID | ||
64 | FixList(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 | // | ||
84 | VOID | ||
85 | UnpackHostEnt(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 | |||
100 | static void | ||
101 | print_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 | |||
171 | int | ||
172 | main(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 = ≻ | ||
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 | |||
8 | int | ||
9 | main(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 | |||
81 | static CRITICAL_SECTION records_cs; | ||
82 | |||
83 | struct record { | ||
84 | _win_socket s; | ||
85 | DWORD flags; | ||
86 | uint8_t state; | ||
87 | char *buf; | ||
88 | wchar_t *name; | ||
89 | }; | ||
90 | |||
91 | static struct record *records = NULL; | ||
92 | static size_t records_len = 0; | ||
93 | static size_t records_size = 0; | ||
94 | |||
95 | static int | ||
96 | resize_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 | |||
114 | static int | ||
115 | add_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*/ | ||
149 | typedef INT (WSPAPI *LPNSPIOCTL)(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPWSACOMPLETION, LPWSATHREADID); | ||
150 | typedef 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 | |||
165 | static _win_socket | ||
166 | connect_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 | |||
195 | static int | ||
196 | send_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 | |||
261 | static int WSPAPI | ||
262 | NSPCleanup(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 | |||
273 | BOOL WINAPI | ||
274 | DllMain(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 | |||
301 | static int WSPAPI | ||
302 | GNUNET_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 | |||
360 | static void | ||
361 | UnmarshallWSAQUERYSETW(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 | |||
385 | static int WSAAPI | ||
386 | GNUNET_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 | |||
584 | static int WSPAPI | ||
585 | GNUNET_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 | |||
626 | static int WSAAPI | ||
627 | GNUNET_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 | |||
636 | static int WSAAPI | ||
637 | GNUNET_W32NSP_InstallServiceClass(LPGUID lpProviderId, | ||
638 | LPWSASERVICECLASSINFOW lpServiceClassInfo) | ||
639 | { | ||
640 | DEBUGLOG("GNUNET_W32NSP_InstallServiceClass\n"); | ||
641 | SetLastError(WSAEOPNOTSUPP); | ||
642 | return SOCKET_ERROR; | ||
643 | } | ||
644 | |||
645 | |||
646 | static int WSAAPI | ||
647 | GNUNET_W32NSP_RemoveServiceClass(LPGUID lpProviderId, LPGUID lpServiceClassId) | ||
648 | { | ||
649 | DEBUGLOG("GNUNET_W32NSP_RemoveServiceClass\n"); | ||
650 | SetLastError(WSAEOPNOTSUPP); | ||
651 | return SOCKET_ERROR; | ||
652 | } | ||
653 | |||
654 | static int WSAAPI | ||
655 | GNUNET_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 | |||
663 | static int WSAAPI | ||
664 | GNUNET_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 | */ | ||
679 | int WSAAPI | ||
680 | GNUNET_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 @@ | |||
1 | EXPORTS | ||
2 | NSPStartup=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 | ||
8 | libexecdir= $(pkglibdir)/libexec/ | 8 | libexecdir= $(pkglibdir)/libexec/ |
9 | 9 | ||
10 | if MINGW | ||
11 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
12 | endif | ||
13 | |||
14 | if USE_COVERAGE | 10 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 | ||
4 | plugindir = $(libdir)/gnunet | 4 | plugindir = $(libdir)/gnunet |
5 | 5 | ||
6 | if MINGW | ||
7 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | if USE_COVERAGE | 6 | if 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 | ||
4 | gnunetincludedir = $(includedir)/gnunet | 4 | gnunetincludedir = $(includedir)/gnunet |
5 | 5 | ||
6 | if MINGW | ||
7 | WINPROC = winproc.h | ||
8 | endif | ||
9 | |||
10 | EXTRA_DIST = \ | 6 | EXTRA_DIST = \ |
11 | gauger.h \ | 7 | gauger.h \ |
12 | block_fs.h \ | 8 | block_fs.h \ |
@@ -15,7 +11,7 @@ EXTRA_DIST = \ | |||
15 | 11 | ||
16 | if TALER_ONLY | 12 | if TALER_ONLY |
17 | gnunetinclude_HEADERS = \ | 13 | gnunetinclude_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 = \ | |||
25 | else | 21 | else |
26 | 22 | ||
27 | gnunetinclude_HEADERS = \ | 23 | gnunetinclude_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 | ||
55 | extern "C" | ||
56 | { | ||
57 | #endif | ||
58 | |||
59 | #ifndef MAX_NAME_LENGTH | ||
60 | #define MAX_NAME_LENGTH 25 | ||
61 | #endif | ||
62 | |||
63 | typedef DWORD WINAPI (*TNtQuerySystemInformation) (int, PVOID, ULONG, PULONG); | ||
64 | typedef DWORD WINAPI (*TGetIfEntry) (PMIB_IFROW pIfRow); | ||
65 | typedef DWORD WINAPI (*TGetIpAddrTable) (PMIB_IPADDRTABLE pIpAddrTable, | ||
66 | PULONG pdwSize, BOOL bOrder); | ||
67 | typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize, | ||
68 | BOOL bOrder); | ||
69 | typedef DWORD WINAPI (*TGetBestInterfaceEx) (struct sockaddr *, PDWORD); | ||
70 | /* TODO: Explicitly import -A variants (i.e. TCreateHardLinkA) or -W | ||
71 | * variants (TCreateHardLinkW), etc. | ||
72 | */ | ||
73 | typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName, | ||
74 | LPCTSTR lpExistingFileName, | ||
75 | LPSECURITY_ATTRIBUTES | ||
76 | lpSecurityAttributes); | ||
77 | typedef SC_HANDLE WINAPI (*TOpenSCManager) (LPCTSTR lpMachineName, | ||
78 | LPCTSTR lpDatabaseName, | ||
79 | DWORD dwDesiredAccess); | ||
80 | typedef 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); | ||
93 | typedef BOOL WINAPI (*TCloseServiceHandle) (SC_HANDLE hSCObject); | ||
94 | typedef BOOL WINAPI (*TDeleteService) (SC_HANDLE hService); | ||
95 | typedef SERVICE_STATUS_HANDLE WINAPI (*TRegisterServiceCtrlHandler) (LPCTSTR | ||
96 | lpServiceName, | ||
97 | LPHANDLER_FUNCTION | ||
98 | lpHandlerProc); | ||
99 | typedef BOOL WINAPI (*TSetServiceStatus) (SERVICE_STATUS_HANDLE | ||
100 | hServiceStatus, | ||
101 | LPSERVICE_STATUS lpServiceStatus); | ||
102 | typedef BOOL WINAPI (*TStartServiceCtrlDispatcher) (const | ||
103 | LPSERVICE_TABLE_ENTRY | ||
104 | lpServiceTable); | ||
105 | typedef BOOL WINAPI (*TControlService) (SC_HANDLE hService, DWORD dwControl, | ||
106 | LPSERVICE_STATUS lpServiceStatus); | ||
107 | typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager, | ||
108 | LPCTSTR lpServiceName, | ||
109 | DWORD dwDesiredAccess); | ||
110 | typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo, | ||
111 | PULONG pOutBufLen); | ||
112 | typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD); | ||
113 | typedef NET_API_STATUS WINAPI (*TNetUserSetInfo) (LPCWSTR servername, | ||
114 | LPCWSTR username, | ||
115 | DWORD level, LPBYTE buf, | ||
116 | LPDWORD param_err); | ||
117 | typedef NTSTATUS NTAPI (*TLsaOpenPolicy) (PLSA_UNICODE_STRING, | ||
118 | PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, | ||
119 | PLSA_HANDLE); | ||
120 | typedef NTSTATUS NTAPI (*TLsaAddAccountRights) (LSA_HANDLE, PSID, | ||
121 | PLSA_UNICODE_STRING, ULONG); | ||
122 | typedef NTSTATUS NTAPI (*TLsaRemoveAccountRights) (LSA_HANDLE, PSID, BOOLEAN, | ||
123 | PLSA_UNICODE_STRING, | ||
124 | ULONG); | ||
125 | typedef NTSTATUS NTAPI (*TLsaClose) (LSA_HANDLE); | ||
126 | typedef 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 | |||
133 | typedef BOOL WINAPI (*TGetFileSecurity) (LPCTSTR lpFileName, | ||
134 | SECURITY_INFORMATION | ||
135 | RequestedInformation, | ||
136 | PSECURITY_DESCRIPTOR | ||
137 | pSecurityDescriptor, DWORD nLength, | ||
138 | LPDWORD lpnLengthNeeded); | ||
139 | typedef BOOL WINAPI (*TInitializeSecurityDescriptor) (PSECURITY_DESCRIPTOR | ||
140 | pSecurityDescriptor, | ||
141 | DWORD dwRevision); | ||
142 | typedef BOOL WINAPI (*TGetSecurityDescriptorDacl) (PSECURITY_DESCRIPTOR | ||
143 | pSecurityDescriptor, | ||
144 | LPBOOL lpbDaclPresent, | ||
145 | PACL * pDacl, | ||
146 | LPBOOL lpbDaclDefaulted); | ||
147 | typedef BOOL WINAPI (*TGetAclInformation) (PACL pAcl, LPVOID pAclInformation, | ||
148 | DWORD nAclInformationLength, | ||
149 | ACL_INFORMATION_CLASS | ||
150 | dwAclInformationClass); | ||
151 | typedef BOOL WINAPI (*TInitializeAcl) (PACL pAcl, DWORD nAclLength, | ||
152 | DWORD dwAclRevision); | ||
153 | typedef BOOL WINAPI (*TGetAce) (PACL pAcl, DWORD dwAceIndex, LPVOID * pAce); | ||
154 | typedef BOOL WINAPI (*TEqualSid) (PSID pSid1, PSID pSid2); | ||
155 | typedef BOOL WINAPI (*TAddAce) (PACL pAcl, DWORD dwAceRevision, | ||
156 | DWORD dwStartingAceIndex, LPVOID pAceList, | ||
157 | DWORD nAceListLength); | ||
158 | typedef BOOL WINAPI (*TAddAccessAllowedAce) (PACL pAcl, DWORD dwAceRevision, | ||
159 | DWORD AccessMask, PSID pSid); | ||
160 | typedef 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 | |||
167 | extern TGetBestInterfaceEx GNGetBestInterfaceEx; | ||
168 | extern TNtQuerySystemInformation GNNtQuerySystemInformation; | ||
169 | extern TGetIfEntry GNGetIfEntry; | ||
170 | extern TGetIpAddrTable GNGetIpAddrTable; | ||
171 | extern TGetIfTable GNGetIfTable; | ||
172 | extern TCreateHardLink GNCreateHardLink; | ||
173 | extern TOpenSCManager GNOpenSCManager; | ||
174 | extern TCreateService GNCreateService; | ||
175 | extern TCloseServiceHandle GNCloseServiceHandle; | ||
176 | extern TDeleteService GNDeleteService; | ||
177 | extern TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler; | ||
178 | extern TSetServiceStatus GNSetServiceStatus; | ||
179 | extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; | ||
180 | extern TControlService GNControlService; | ||
181 | extern TOpenService GNOpenService; | ||
182 | extern TGetAdaptersInfo GNGetAdaptersInfo; | ||
183 | extern TNetUserAdd GNNetUserAdd; | ||
184 | extern TNetUserSetInfo GNNetUserSetInfo; | ||
185 | extern TLsaOpenPolicy GNLsaOpenPolicy; | ||
186 | extern TLsaAddAccountRights GNLsaAddAccountRights; | ||
187 | extern TLsaRemoveAccountRights GNLsaRemoveAccountRights; | ||
188 | extern TLsaClose GNLsaClose; | ||
189 | extern TLookupAccountName GNLookupAccountName; | ||
190 | extern TGetFileSecurity GNGetFileSecurity; | ||
191 | extern TInitializeSecurityDescriptor GNInitializeSecurityDescriptor; | ||
192 | extern TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl; | ||
193 | extern TGetAclInformation GNGetAclInformation; | ||
194 | extern TInitializeAcl GNInitializeAcl; | ||
195 | extern TGetAce GNGetAce; | ||
196 | extern TEqualSid GNEqualSid; | ||
197 | extern TAddAce GNAddAce; | ||
198 | extern TAddAccessAllowedAce GNAddAccessAllowedAce; | ||
199 | extern TSetNamedSecurityInfo GNSetNamedSecurityInfo; | ||
200 | |||
201 | |||
202 | BOOL CreateShortcut(const char *pszSrc, const char *pszDest); | ||
203 | BOOL DereferenceShortcut(char *pszShortcut); | ||
204 | long QueryRegistry(HKEY hMainKey, const char *pszKey, const char *pszSubKey, | ||
205 | char *pszBuffer, long *pdLength); | ||
206 | int ListNICs(void (*callback)(void *, const char *, int), void *cls); | ||
207 | BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName, | ||
208 | DWORD dwAccessMask); | ||
209 | char *winErrorStr(const char *prefix, int dwErr); | ||
210 | void EnumNICs(PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable); | ||
211 | |||
212 | #define ENUMNICS3_MASK_OK 0x01 | ||
213 | #define ENUMNICS3_BCAST_OK 0x02 | ||
214 | |||
215 | struct 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 | |||
225 | int EnumNICs3(struct EnumNICs3_results **, int *EnumNICs3_results_count); | ||
226 | void EnumNICs3_free(struct EnumNICs3_results *); | ||
227 | int GNInitWinEnv(); | ||
228 | void GNShutdownWinEnv(); | ||
229 | |||
230 | BOOL 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | namecache.conf | 11 | namecache.conf |
12 | 12 | ||
13 | |||
14 | if MINGW | ||
15 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
16 | endif | ||
17 | |||
18 | if USE_COVERAGE | 13 | if 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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | namestore.conf | 11 | namestore.conf |
12 | 12 | ||
13 | |||
14 | if MINGW | ||
15 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
16 | endif | ||
17 | |||
18 | if USE_COVERAGE | 13 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if 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 | ||
9 | endif | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | 4 | libexecdir= $(pkglibdir)/libexec/ |
12 | 5 | ||
13 | pkgcfgdir= $(pkgdatadir)/config.d/ | 6 | pkgcfgdir= $(pkgdatadir)/config.d/ |
@@ -45,7 +38,7 @@ gnunet_helper_nat_server_SOURCES = \ | |||
45 | $(NATSERVER) | 38 | $(NATSERVER) |
46 | 39 | ||
47 | gnunet_helper_nat_client_SOURCES = \ | 40 | gnunet_helper_nat_client_SOURCES = \ |
48 | $(NATCLIENT) | 41 | $(NATCLIENT) |
49 | 42 | ||
50 | 43 | ||
51 | gnunet_nat_SOURCES = \ | 44 | gnunet_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 | */ | ||
76 | struct 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 | */ | ||
132 | struct 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 | |||
144 | struct 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 | */ | ||
157 | struct 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 | */ | ||
170 | static boolean privilege_testing = FALSE; | ||
171 | |||
172 | /** | ||
173 | * Socket we use to send our ICMP packets. | ||
174 | */ | ||
175 | static _win_socket rawsock; | ||
176 | |||
177 | /** | ||
178 | * Target "dummy" address. | ||
179 | */ | ||
180 | static struct in_addr dummy; | ||
181 | |||
182 | /** | ||
183 | * Port we are listening on (communicated to the server). | ||
184 | */ | ||
185 | static 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 | */ | ||
197 | static int | ||
198 | inet_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 | */ | ||
217 | static uint16_t | ||
218 | calc_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 | */ | ||
238 | static void | ||
239 | send_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 | */ | ||
332 | static void | ||
333 | send_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 | */ | ||
429 | static _win_socket | ||
430 | make_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 | |||
461 | int | ||
462 | main(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 | */ | ||
97 | struct 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 | */ | ||
152 | struct 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 | |||
164 | struct 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 | */ | ||
177 | struct 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 | */ | ||
190 | static boolean privilege_testing = FALSE; | ||
191 | |||
192 | /** | ||
193 | * Socket we use to receive "fake" ICMP replies. | ||
194 | */ | ||
195 | static _win_socket icmpsock; | ||
196 | |||
197 | /** | ||
198 | * Socket we use to send our ICMP requests. | ||
199 | */ | ||
200 | static _win_socket rawsock; | ||
201 | |||
202 | /** | ||
203 | * Socket we use to send our UDP requests. | ||
204 | */ | ||
205 | static _win_socket udpsock; | ||
206 | |||
207 | /** | ||
208 | * Target "dummy" address. | ||
209 | */ | ||
210 | static 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 | */ | ||
220 | static uint16_t | ||
221 | calc_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 | */ | ||
243 | static int | ||
244 | inet_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 | */ | ||
261 | static void | ||
262 | send_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 | */ | ||
318 | static void | ||
319 | send_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 | */ | ||
345 | static void | ||
346 | process_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 | */ | ||
441 | static _win_socket | ||
442 | make_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 | */ | ||
461 | static _win_socket | ||
462 | make_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 | */ | ||
500 | static _win_socket | ||
501 | make_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 | |||
526 | int | ||
527 | main(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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | peerinfo.conf | 11 | peerinfo.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if 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/ | |||
10 | dist_pkgcfg_DATA = \ | 10 | dist_pkgcfg_DATA = \ |
11 | peerstore.conf | 11 | peerstore.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if USE_COVERAGE |
18 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
19 | endif | 15 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage -O0 | 5 | AM_CFLAGS = --coverage -O0 |
10 | endif | 6 | endif |
@@ -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 |
48 | endif | 44 | endif |
49 | if 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 | ||
55 | endif | ||
56 | else | 45 | else |
57 | if HAVE_LIBCURL | 46 | if HAVE_LIBCURL |
58 | LIB_GNURL=@LIBCURL@ | 47 | LIB_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 |
67 | endif | 56 | endif |
68 | if 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 | ||
74 | endif | ||
75 | endif | 57 | endif |
76 | endif | 58 | endif |
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 | ||
8 | libexecdir= $(pkglibdir)/libexec/ | 8 | libexecdir= $(pkglibdir)/libexec/ |
9 | 9 | ||
10 | if MINGW | ||
11 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
12 | endif | ||
13 | |||
14 | if USE_COVERAGE | 10 | if 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 | ||
6 | if MINGW | ||
7 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | if USE_COVERAGE | 6 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | rest.conf | 11 | rest.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if 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 | ||
4 | plugindir = $(libdir)/gnunet | 4 | plugindir = $(libdir)/gnunet |
5 | 5 | ||
6 | if MINGW | ||
7 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | if USE_COVERAGE | 6 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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/ | |||
8 | pkgcfg_DATA = \ | 8 | pkgcfg_DATA = \ |
9 | scalarproduct.conf | 9 | scalarproduct.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if USE_COVERAGE |
16 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 12 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
17 | endif | 13 | endif |
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/ | |||
8 | pkgcfg_DATA = \ | 8 | pkgcfg_DATA = \ |
9 | secretsharing.conf | 9 | secretsharing.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if USE_COVERAGE |
16 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 12 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
17 | endif | 13 | endif |
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 | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | set.conf | 11 | set.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if USE_COVERAGE |
18 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
19 | endif | 15 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if USE_COVERAGE |
9 | AM_CFLAGS = --coverage | 5 | AM_CFLAGS = --coverage |
10 | endif | 6 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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/ | |||
8 | dist_pkgcfg_DATA = \ | 8 | dist_pkgcfg_DATA = \ |
9 | template.conf | 9 | template.conf |
10 | 10 | ||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | 11 | if USE_COVERAGE |
16 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | 12 | AM_CFLAGS = -fprofile-arcs -ftest-coverage |
17 | endif | 13 | endif |
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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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)¤tCPULoad, &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) | |||
747 | void | 633 | void |
748 | GST_stats_destroy() | 634 | GST_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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | 4 | if 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 |
116 | endif | 116 | endif |
117 | else | ||
118 | if MINGW | ||
119 | BT_BIN = gnunet-helper-transport-bluetooth | ||
120 | BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la | ||
121 | endif | ||
122 | endif | 117 | endif |
123 | 118 | ||
124 | # end of HAVE_EXPERIMENTAL | 119 | # end of HAVE_EXPERIMENTAL |
125 | endif | 120 | endif |
126 | 121 | ||
127 | 122 | ||
128 | if !MINGW | ||
129 | UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la | 123 | UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la |
130 | UNIX_PLUGIN_TEST = test_transport_api_unix | 124 | UNIX_PLUGIN_TEST = test_transport_api_unix |
131 | UNIX_TEST = test_plugin_unix | 125 | UNIX_TEST = test_plugin_unix |
@@ -136,7 +130,7 @@ UNIX_QUOTA_TEST = test_quota_compliance_unix \ | |||
136 | if LINUX | 130 | if LINUX |
137 | UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract | 131 | UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract |
138 | endif | 132 | endif |
139 | endif | 133 | |
140 | 134 | ||
141 | noinst_PROGRAMS = \ | 135 | noinst_PROGRAMS = \ |
142 | gnunet-transport-profiler \ | 136 | gnunet-transport-profiler \ |
@@ -319,13 +313,9 @@ gnunet_transport_wlan_receiver_LDADD = \ | |||
319 | 313 | ||
320 | gnunet_helper_transport_bluetooth_SOURCES = \ | 314 | gnunet_helper_transport_bluetooth_SOURCES = \ |
321 | gnunet-helper-transport-bluetooth.c | 315 | gnunet-helper-transport-bluetooth.c |
322 | if MINGW | 316 | |
323 | gnunet_helper_transport_bluetooth_LDADD = \ | 317 | gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth |
324 | $(top_builddir)/src/util/libgnunetutil.la | 318 | |
325 | gnunet_helper_transport_bluetooth_LDFLAGS = -lws2_32 | ||
326 | else | ||
327 | gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth | ||
328 | endif | ||
329 | 319 | ||
330 | gnunet_transport_profiler_SOURCES = \ | 320 | gnunet_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 | */ | ||
80 | struct 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 | */ | ||
614 | static void | ||
615 | print_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 | */ | ||
629 | static void | ||
630 | initialize_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 | */ | ||
648 | static void | ||
649 | convert_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 | */ | ||
698 | static int | ||
699 | register_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 | */ | ||
862 | static int | ||
863 | get_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, | |||
1088 | static int | 815 | static int |
1089 | open_device(struct HardwareInfos *dev) | 816 | open_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 | ||
37 | typedef 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 | */ | ||
860 | static int | ||
861 | receive_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) | |||
1257 | static int | 1157 | static int |
1258 | detach_terminal(struct LEGACY_SERVICE_Context *sctx) | 1158 | detach_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 = \ | |||
13 | pkgcfg_DATA = \ | 13 | pkgcfg_DATA = \ |
14 | resolver.conf | 14 | resolver.conf |
15 | 15 | ||
16 | if MINGW | 16 | TEST_CLIENT_UNIX_NC = test_client_unix.nc |
17 | noinst_LTLIBRARIES = \ | ||
18 | libgnunetutilwin.la | ||
19 | libgnunetutilwin_la_SOURCES = \ | ||
20 | win.c \ | ||
21 | winproc.c | ||
22 | libgnunetutilwin_la_LDFLAGS = \ | ||
23 | -no-undefined -Wl,--export-all-symbols | ||
24 | libgnunetutilwin_la_LIBADD = \ | ||
25 | -lshell32 -liconv -lstdc++ \ | ||
26 | -lcomdlg32 -lgdi32 -liphlpapi | ||
27 | WINLIB = libgnunetutilwin.la | ||
28 | W32CAT = w32cat | ||
29 | W32CONSOLEHELPER = gnunet-helper-w32-console | ||
30 | endif | ||
31 | |||
32 | if !MINGW | ||
33 | TEST_CLIENT_UNIX_NC = test_client_unix.nc | ||
34 | else | ||
35 | TEST_CLIENT_UNIX_NC = | ||
36 | endif | ||
37 | 17 | ||
38 | if USE_COVERAGE | 18 | if 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 |
46 | endif | 26 | endif |
47 | 27 | ||
48 | w32cat_SOURCES = w32cat.c | ||
49 | |||
50 | gnunet_helper_w32_console_SOURCES = \ | ||
51 | gnunet-helper-w32-console.c \ | ||
52 | gnunet-helper-w32-console.h | ||
53 | gnunet_helper_w32_console_LDADD = \ | ||
54 | libgnunetutil.la | ||
55 | |||
56 | gnunet_config_diff_SOURCES = \ | 28 | gnunet_config_diff_SOURCES = \ |
57 | gnunet-config-diff.c | 29 | gnunet-config-diff.c |
58 | gnunet_config_diff_LDADD = \ | 30 | gnunet_config_diff_LDADD = \ |
@@ -202,8 +174,7 @@ lib_LTLIBRARIES = libgnunetutil.la | |||
202 | 174 | ||
203 | libexec_PROGRAMS = \ | 175 | libexec_PROGRAMS = \ |
204 | gnunet-service-resolver \ | 176 | gnunet-service-resolver \ |
205 | gnunet-timeout \ | 177 | gnunet-timeout |
206 | $(W32CONSOLEHELPER) | ||
207 | 178 | ||
208 | bin_PROGRAMS = \ | 179 | bin_PROGRAMS = \ |
209 | gnunet-resolver \ | 180 | gnunet-resolver \ |
@@ -217,7 +188,6 @@ endif | |||
217 | 188 | ||
218 | noinst_PROGRAMS = \ | 189 | noinst_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 | ||
229 | endif | 199 | endif |
230 | 200 | ||
231 | |||
232 | if !MINGW | ||
233 | gnunet_timeout_SOURCES = \ | 201 | gnunet_timeout_SOURCES = \ |
234 | gnunet-timeout.c | 202 | gnunet-timeout.c |
235 | else | ||
236 | gnunet_timeout_SOURCES = \ | ||
237 | gnunet-timeout-w32.c | ||
238 | endif | ||
239 | 203 | ||
240 | gnunet_service_resolver_SOURCES = \ | 204 | gnunet_service_resolver_SOURCES = \ |
241 | gnunet-service-resolver.c | 205 | gnunet-service-resolver.c |
@@ -393,8 +357,7 @@ test_os_start_process_SOURCES = \ | |||
393 | test_os_start_process_LDADD = \ | 357 | test_os_start_process_LDADD = \ |
394 | libgnunetutil.la | 358 | libgnunetutil.la |
395 | test_os_start_process_DEPENDENCIES = \ | 359 | test_os_start_process_DEPENDENCIES = \ |
396 | libgnunetutil.la \ | 360 | libgnunetutil.la |
397 | $(WINCAT) | ||
398 | 361 | ||
399 | test_client_nc_SOURCES = \ | 362 | test_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) | |||
191 | int | 189 | int |
192 | GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h) | 190 | GNUNET_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 | |||
31 | int | ||
32 | main(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 | |||
1054 | GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst, | 1032 | GNUNET_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 | |||
1217 | GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, | 1159 | GNUNET_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 | |||
1247 | GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds, | 1181 | GNUNET_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 | |||
1277 | GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds, | 1196 | GNUNET_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 | */ | ||
1303 | static int | ||
1304 | ptr_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 | |||
1324 | GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1, | 1212 | GNUNET_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() | |||
1413 | void | 1253 | void |
1414 | GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds) | 1254 | GNUNET_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 | */ | ||
1429 | struct _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 | */ | ||
1475 | static 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 | |||
1503 | static HANDLE hEventPipeWrite; | ||
1504 | |||
1505 | static HANDLE hEventReadReady; | ||
1506 | |||
1507 | static struct _select_params sp; | ||
1508 | |||
1509 | static HANDLE select_thread; | ||
1510 | |||
1511 | static HANDLE select_finished_event; | ||
1512 | |||
1513 | static HANDLE select_standby_event; | ||
1514 | |||
1515 | static _win_socket select_wakeup_socket = -1; | ||
1516 | |||
1517 | static _win_socket select_send_socket = -1; | ||
1518 | |||
1519 | static 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 | */ | ||
1527 | static void | ||
1528 | initialize_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 | */ | ||
1728 | static int | ||
1729 | pipe_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 | */ | ||
1760 | static int | ||
1761 | pipe_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 | */ | ||
1784 | static int | ||
1785 | check_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 | */ | ||
1831 | int | ||
1832 | GNUNET_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 | |||
388 | GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, | 388 | GNUNET_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, | |||
1589 | int | 999 | int |
1590 | GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) | 1000 | GNUNET_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 | ||
625 | static void | 622 | static void |
626 | sighandler_pipe() | 623 | sighandler_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 | ||
1400 | static struct GNUNET_SCHEDULER_Task * | 1395 | static struct GNUNET_SCHEDULER_Task * |
1401 | add_without_sets(struct GNUNET_TIME_Relative delay, | 1396 | add_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 | */ | ||
1365 | static struct GNUNET_NETWORK_Handle ** | ||
1366 | receive_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) | |||
1808 | static int | 1711 | static int |
1809 | detach_terminal(struct GNUNET_SERVICE_Handle *sh) | 1712 | detach_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 * | |||
602 | GNUNET_STRINGS_filename_expand(const char *fil) | 602 | GNUNET_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 | ||
215 | static void | 214 | static void |
216 | taskSig(void *cls) | 215 | taskSig(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 | ||
250 | static void | 248 | static 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 | |||
28 | DWORD WINAPI | ||
29 | parent_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 | |||
47 | void | ||
48 | install_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 | |||
67 | int | ||
68 | main(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 | |||
41 | int 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 | ||
77 | typedef 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 | |||
89 | typedef 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 | |||
102 | typedef UINT32 NET_IF_COMPARTMENT_ID; | ||
103 | typedef GUID NET_IF_NETWORK_GUID; | ||
104 | |||
105 | #ifndef __MINGW64_VERSION_MAJOR | ||
106 | typedef 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 | |||
113 | typedef 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 | ||
133 | typedef 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 | |||
144 | typedef 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 | |||
220 | static int | ||
221 | EnumNICs_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 | |||
236 | static int | ||
237 | EnumNICs_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 | |||
263 | static int | ||
264 | EnumNICs_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 | |||
302 | int | ||
303 | EnumNICs2(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 | } | ||
347 | error: | ||
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 | */ | ||
363 | int | ||
364 | EnumNICs3(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 | |||
625 | void | ||
626 | EnumNICs3_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 | */ | ||
639 | int | ||
640 | ListNICs(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 | */ | ||
667 | int 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 | */ | ||
713 | int | ||
714 | UninstallService(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 | |||
737 | closeSCM: | ||
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 | */ | ||
748 | void | ||
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 | */ | ||
773 | NTSTATUS | ||
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 | */ | ||
807 | BOOL | ||
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 | |||
854 | end: | ||
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 | */ | ||
875 | NTSTATUS | ||
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 | */ | ||
916 | int | ||
917 | CreateServiceAccount(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 | */ | ||
972 | BOOL 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 | |||
1254 | end: | ||
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 | |||
1274 | char *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 | */ | ||
1308 | BOOL | ||
1309 | SafeTerminateProcess(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 | |||
34 | static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi; | ||
35 | #ifdef W32_VEH | ||
36 | static void *GNWinVEH_handle = NULL; | ||
37 | #endif | ||
38 | |||
39 | TNtQuerySystemInformation GNNtQuerySystemInformation; | ||
40 | TGetIfEntry GNGetIfEntry; | ||
41 | TGetIpAddrTable GNGetIpAddrTable; | ||
42 | TGetIfTable GNGetIfTable; | ||
43 | TOpenSCManager GNOpenSCManager; | ||
44 | TCreateService GNCreateService; | ||
45 | TCloseServiceHandle GNCloseServiceHandle; | ||
46 | TDeleteService GNDeleteService; | ||
47 | TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler; | ||
48 | TSetServiceStatus GNSetServiceStatus; | ||
49 | TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; | ||
50 | TControlService GNControlService; | ||
51 | TOpenService GNOpenService; | ||
52 | TGetBestInterfaceEx GNGetBestInterfaceEx; | ||
53 | TGetAdaptersInfo GNGetAdaptersInfo; | ||
54 | TNetUserAdd GNNetUserAdd; | ||
55 | TNetUserSetInfo GNNetUserSetInfo; | ||
56 | TLsaOpenPolicy GNLsaOpenPolicy; | ||
57 | TLsaAddAccountRights GNLsaAddAccountRights; | ||
58 | TLsaRemoveAccountRights GNLsaRemoveAccountRights; | ||
59 | TLsaClose GNLsaClose; | ||
60 | TLookupAccountName GNLookupAccountName; | ||
61 | TGetFileSecurity GNGetFileSecurity; | ||
62 | TInitializeSecurityDescriptor GNInitializeSecurityDescriptor; | ||
63 | TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl; | ||
64 | TGetAclInformation GNGetAclInformation; | ||
65 | TInitializeAcl GNInitializeAcl; | ||
66 | TGetAce GNGetAce; | ||
67 | TEqualSid GNEqualSid; | ||
68 | TAddAce GNAddAce; | ||
69 | TAddAccessAllowedAce GNAddAccessAllowedAce; | ||
70 | TSetNamedSecurityInfo GNSetNamedSecurityInfo; | ||
71 | |||
72 | #define LOG(kind, ...) GNUNET_log_from(kind, "util-winproc", __VA_ARGS__) | ||
73 | /** | ||
74 | * Log (panic) messages from PlibC | ||
75 | */ | ||
76 | void | ||
77 | plibc_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 | */ | ||
93 | LONG __stdcall | ||
94 | GNWinVEH(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 | */ | ||
143 | int | ||
144 | GNInitWinEnv() | ||
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 | */ | ||
311 | void | ||
312 | GNShutdownWinEnv() | ||
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 | ||
335 | long long | ||
336 | atoll(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 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined,--export-all-symbols | ||
6 | VPNBIN = gnunet-helper-vpn | ||
7 | endif | ||
8 | |||
9 | if USE_COVERAGE | 4 | if USE_COVERAGE |
10 | AM_CFLAGS = --coverage -O0 | 5 | AM_CFLAGS = --coverage -O0 |
11 | endif | 6 | endif |
@@ -39,20 +34,9 @@ libexec_PROGRAMS = \ | |||
39 | bin_PROGRAMS = \ | 34 | bin_PROGRAMS = \ |
40 | gnunet-vpn | 35 | gnunet-vpn |
41 | 36 | ||
42 | if MINGW | 37 | gnunet_helper_vpn_SOURCES = \ |
43 | gnunet_helper_vpn_LDFLAGS = \ | 38 | gnunet-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 | ||
52 | else | ||
53 | gnunet_helper_vpn_SOURCES = \ | ||
54 | gnunet-helper-vpn.c | ||
55 | endif | ||
56 | gnunet_service_vpn_SOURCES = \ | 40 | gnunet_service_vpn_SOURCES = \ |
57 | gnunet-service-vpn.c | 41 | gnunet-service-vpn.c |
58 | gnunet_service_vpn_LDADD = \ | 42 | gnunet_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 | */ | ||
77 | static 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 | */ | ||
131 | static 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 | */ | ||
137 | static 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 | */ | ||
148 | static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE; | ||
149 | |||
150 | /** | ||
151 | * Registry Key we hand over to windows to spawn a new virtual interface | ||
152 | */ | ||
153 | static 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 | */ | ||
159 | static char device_guid[256]; | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Possible states of an IO facility. | ||
164 | */ | ||
165 | enum 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 | */ | ||
197 | struct 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 | */ | ||
242 | WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE, DWORD, DWORD, DWORD); | ||
243 | |||
244 | /** | ||
245 | * IsWow64Process definition for our is_win64, as this is a kernel function | ||
246 | */ | ||
247 | typedef 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 | */ | ||
262 | size_t | ||
263 | GNUNET_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 | */ | ||
281 | BOOL | ||
282 | is_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 | */ | ||
307 | static int | ||
308 | execute_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 | */ | ||
333 | static int | ||
334 | set_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 | */ | ||
375 | static void | ||
376 | remove_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 | */ | ||
407 | static int | ||
408 | set_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 | */ | ||
453 | static void | ||
454 | remove_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 | */ | ||
483 | static BOOL | ||
484 | setup_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 | */ | ||
590 | static BOOL | ||
591 | remove_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 | */ | ||
633 | static BOOL | ||
634 | resolve_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 | |||
756 | cleanup: | ||
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 | */ | ||
774 | static BOOL | ||
775 | check_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 | */ | ||
808 | static HANDLE | ||
809 | init_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 | */ | ||
868 | static BOOL | ||
869 | tun_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 | */ | ||
915 | static BOOL | ||
916 | attempt_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 | */ | ||
1090 | static BOOL | ||
1091 | attempt_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 | |||
1102 | partial_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 | */ | ||
1257 | static BOOL | ||
1258 | attempt_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 | |||
1266 | continue_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 | */ | ||
1365 | static BOOL | ||
1366 | initialize_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 | */ | ||
1387 | static void | ||
1388 | run(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"); | ||
1486 | teardown: | ||
1487 | CancelIo(tap_handle); | ||
1488 | CancelIo(std_in.handle); | ||
1489 | CancelIo(std_out.handle); | ||
1490 | teardown_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 | */ | ||
1507 | int | ||
1508 | main(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); | ||
1590 | cleanup: | ||
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/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | zonemaster.conf | 11 | zonemaster.conf |
12 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | 13 | if USE_COVERAGE |
18 | AM_CFLAGS = --coverage -O0 | 14 | AM_CFLAGS = --coverage -O0 |
19 | XLIBS = -lgcov | 15 | XLIBS = -lgcov |