diff options
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 |