rpcapd.c revision 1.1.1.1.4.2 1 1.1.1.1.4.2 christos /*
2 1.1.1.1.4.2 christos * Copyright (c) 2002 - 2003
3 1.1.1.1.4.2 christos * NetGroup, Politecnico di Torino (Italy)
4 1.1.1.1.4.2 christos * All rights reserved.
5 1.1.1.1.4.2 christos *
6 1.1.1.1.4.2 christos * Redistribution and use in source and binary forms, with or without
7 1.1.1.1.4.2 christos * modification, are permitted provided that the following conditions
8 1.1.1.1.4.2 christos * are met:
9 1.1.1.1.4.2 christos *
10 1.1.1.1.4.2 christos * 1. Redistributions of source code must retain the above copyright
11 1.1.1.1.4.2 christos * notice, this list of conditions and the following disclaimer.
12 1.1.1.1.4.2 christos * 2. Redistributions in binary form must reproduce the above copyright
13 1.1.1.1.4.2 christos * notice, this list of conditions and the following disclaimer in the
14 1.1.1.1.4.2 christos * documentation and/or other materials provided with the distribution.
15 1.1.1.1.4.2 christos * 3. Neither the name of the Politecnico di Torino nor the names of its
16 1.1.1.1.4.2 christos * contributors may be used to endorse or promote products derived from
17 1.1.1.1.4.2 christos * this software without specific prior written permission.
18 1.1.1.1.4.2 christos *
19 1.1.1.1.4.2 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 1.1.1.1.4.2 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 1.1.1.1.4.2 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 1.1.1.1.4.2 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 1.1.1.1.4.2 christos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 1.1.1.1.4.2 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 1.1.1.1.4.2 christos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 1.1.1.1.4.2 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 1.1.1.1.4.2 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 1.1.1.1.4.2 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 1.1.1.1.4.2 christos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 1.1.1.1.4.2 christos *
31 1.1.1.1.4.2 christos */
32 1.1.1.1.4.2 christos
33 1.1.1.1.4.2 christos #ifdef HAVE_CONFIG_H
34 1.1.1.1.4.2 christos #include <config.h>
35 1.1.1.1.4.2 christos #endif
36 1.1.1.1.4.2 christos
37 1.1.1.1.4.2 christos #include "ftmacros.h"
38 1.1.1.1.4.2 christos
39 1.1.1.1.4.2 christos #include <errno.h> // for the errno variable
40 1.1.1.1.4.2 christos #include <string.h> // for strtok, etc
41 1.1.1.1.4.2 christos #include <stdlib.h> // for malloc(), free(), ...
42 1.1.1.1.4.2 christos #include <pcap.h> // for PCAP_ERRBUF_SIZE
43 1.1.1.1.4.2 christos #include <signal.h> // for signal()
44 1.1.1.1.4.2 christos
45 1.1.1.1.4.2 christos #include "fmtutils.h"
46 1.1.1.1.4.2 christos #include "sockutils.h" // for socket calls
47 1.1.1.1.4.2 christos #include "varattrs.h" // for _U_
48 1.1.1.1.4.2 christos #include "portability.h"
49 1.1.1.1.4.2 christos #include "rpcapd.h"
50 1.1.1.1.4.2 christos #include "config_params.h" // configuration file parameters
51 1.1.1.1.4.2 christos #include "fileconf.h" // for the configuration file management
52 1.1.1.1.4.2 christos #include "rpcap-protocol.h"
53 1.1.1.1.4.2 christos #include "daemon.h" // the true main() method of this daemon
54 1.1.1.1.4.2 christos #include "log.h"
55 1.1.1.1.4.2 christos
56 1.1.1.1.4.2 christos #ifdef _WIN32
57 1.1.1.1.4.2 christos #include <process.h> // for thread stuff
58 1.1.1.1.4.2 christos #include "win32-svc.h" // for Win32 service stuff
59 1.1.1.1.4.2 christos #include "getopt.h" // for getopt()-for-Windows
60 1.1.1.1.4.2 christos #else
61 1.1.1.1.4.2 christos #include <fcntl.h> // for open()
62 1.1.1.1.4.2 christos #include <unistd.h> // for exit()
63 1.1.1.1.4.2 christos #include <sys/wait.h> // waitpid()
64 1.1.1.1.4.2 christos #endif
65 1.1.1.1.4.2 christos
66 1.1.1.1.4.2 christos //
67 1.1.1.1.4.2 christos // Element in list of sockets on which we're listening for connections.
68 1.1.1.1.4.2 christos //
69 1.1.1.1.4.2 christos struct listen_sock {
70 1.1.1.1.4.2 christos struct listen_sock *next;
71 1.1.1.1.4.2 christos SOCKET sock;
72 1.1.1.1.4.2 christos };
73 1.1.1.1.4.2 christos
74 1.1.1.1.4.2 christos // Global variables
75 1.1.1.1.4.2 christos char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server
76 1.1.1.1.4.2 christos struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
77 1.1.1.1.4.2 christos int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise
78 1.1.1.1.4.2 christos static struct listen_sock *listen_socks; //!< sockets on which we listen
79 1.1.1.1.4.2 christos char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration
80 1.1.1.1.4.2 christos static int passivemode = 1; //!< '1' if we want to run in passive mode as well
81 1.1.1.1.4.2 christos static struct addrinfo mainhints; //!< temporary struct to keep settings needed to open the new socket
82 1.1.1.1.4.2 christos static char address[MAX_LINE + 1]; //!< keeps the network address (either numeric or literal) to bind to
83 1.1.1.1.4.2 christos static char port[MAX_LINE + 1]; //!< keeps the network port to bind to
84 1.1.1.1.4.2 christos #ifdef _WIN32
85 1.1.1.1.4.2 christos static HANDLE state_change_event; //!< event to signal that a state change should take place
86 1.1.1.1.4.2 christos #endif
87 1.1.1.1.4.2 christos static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down
88 1.1.1.1.4.2 christos static volatile sig_atomic_t reread_config; //!< '1' if the server is to re-read its configuration
89 1.1.1.1.4.2 christos
90 1.1.1.1.4.2 christos extern char *optarg; // for getopt()
91 1.1.1.1.4.2 christos
92 1.1.1.1.4.2 christos // Function definition
93 1.1.1.1.4.2 christos #ifdef _WIN32
94 1.1.1.1.4.2 christos static unsigned __stdcall main_active(void *ptr);
95 1.1.1.1.4.2 christos static BOOL WINAPI main_ctrl_event(DWORD);
96 1.1.1.1.4.2 christos #else
97 1.1.1.1.4.2 christos static void *main_active(void *ptr);
98 1.1.1.1.4.2 christos static void main_terminate(int sign);
99 1.1.1.1.4.2 christos static void main_reread_config(int sign);
100 1.1.1.1.4.2 christos #endif
101 1.1.1.1.4.2 christos static void accept_connections(void);
102 1.1.1.1.4.2 christos static void accept_connection(SOCKET listen_sock);
103 1.1.1.1.4.2 christos #ifndef _WIN32
104 1.1.1.1.4.2 christos static void main_reap_children(int sign);
105 1.1.1.1.4.2 christos #endif
106 1.1.1.1.4.2 christos #ifdef _WIN32
107 1.1.1.1.4.2 christos static unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
108 1.1.1.1.4.2 christos #endif
109 1.1.1.1.4.2 christos
110 1.1.1.1.4.2 christos #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
111 1.1.1.1.4.2 christos
112 1.1.1.1.4.2 christos /*!
113 1.1.1.1.4.2 christos \brief Prints the usage screen if it is launched in console mode.
114 1.1.1.1.4.2 christos */
115 1.1.1.1.4.2 christos static void printusage(void)
116 1.1.1.1.4.2 christos {
117 1.1.1.1.4.2 christos const char *usagetext =
118 1.1.1.1.4.2 christos "USAGE:"
119 1.1.1.1.4.2 christos " " PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
120 1.1.1.1.4.2 christos " [-n] [-v] [-d] "
121 1.1.1.1.4.2 christos #ifndef _WIN32
122 1.1.1.1.4.2 christos "[-i] "
123 1.1.1.1.4.2 christos #endif
124 1.1.1.1.4.2 christos "[-s <config_file>] [-f <config_file>]\n\n"
125 1.1.1.1.4.2 christos " -b <address> the address to bind to (either numeric or literal).\n"
126 1.1.1.1.4.2 christos " Default: binds to all local IPv4 and IPv6 addresses\n\n"
127 1.1.1.1.4.2 christos " -p <port> the port to bind to.\n"
128 1.1.1.1.4.2 christos " Default: binds to port " RPCAP_DEFAULT_NETPORT "\n\n"
129 1.1.1.1.4.2 christos " -4 use only IPv4.\n"
130 1.1.1.1.4.2 christos " Default: use both IPv4 and IPv6 waiting sockets\n\n"
131 1.1.1.1.4.2 christos " -l <host_list> a file that contains a list of hosts that are allowed\n"
132 1.1.1.1.4.2 christos " to connect to this server (if more than one, list them one\n"
133 1.1.1.1.4.2 christos " per line).\n"
134 1.1.1.1.4.2 christos " We suggest to use literal names (instead of numeric ones)\n"
135 1.1.1.1.4.2 christos " in order to avoid problems with different address families.\n\n"
136 1.1.1.1.4.2 christos " -n permit NULL authentication (usually used with '-l')\n\n"
137 1.1.1.1.4.2 christos " -a <host,port> run in active mode when connecting to 'host' on port 'port'\n"
138 1.1.1.1.4.2 christos " In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n"
139 1.1.1.1.4.2 christos " -v run in active mode only (default: if '-a' is specified, it\n"
140 1.1.1.1.4.2 christos " accepts passive connections as well)\n\n"
141 1.1.1.1.4.2 christos " -d run in daemon mode (UNIX only) or as a service (Win32 only)\n"
142 1.1.1.1.4.2 christos " Warning (Win32): this switch is provided automatically when\n"
143 1.1.1.1.4.2 christos " the service is started from the control panel\n\n"
144 1.1.1.1.4.2 christos #ifndef _WIN32
145 1.1.1.1.4.2 christos " -i run in inetd mode (UNIX only)\n\n"
146 1.1.1.1.4.2 christos #endif
147 1.1.1.1.4.2 christos " -s <config_file> save the current configuration to file\n\n"
148 1.1.1.1.4.2 christos " -f <config_file> load the current configuration from file; all switches\n"
149 1.1.1.1.4.2 christos " specified from the command line are ignored\n\n"
150 1.1.1.1.4.2 christos " -h print this help screen\n\n";
151 1.1.1.1.4.2 christos
152 1.1.1.1.4.2 christos (void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
153 1.1.1.1.4.2 christos "Compiled with %s\n\n", pcap_lib_version());
154 1.1.1.1.4.2 christos printf("%s", usagetext);
155 1.1.1.1.4.2 christos }
156 1.1.1.1.4.2 christos
157 1.1.1.1.4.2 christos
158 1.1.1.1.4.2 christos
159 1.1.1.1.4.2 christos //! Program main
160 1.1.1.1.4.2 christos int main(int argc, char *argv[])
161 1.1.1.1.4.2 christos {
162 1.1.1.1.4.2 christos char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration
163 1.1.1.1.4.2 christos int isdaemon = 0; // Non-zero if the user wants to run this program as a daemon
164 1.1.1.1.4.2 christos #ifndef _WIN32
165 1.1.1.1.4.2 christos int isrunbyinetd = 0; // Non-zero if this is being run by inetd or something inetd-like
166 1.1.1.1.4.2 christos #endif
167 1.1.1.1.4.2 christos int retval; // keeps the returning value from several functions
168 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
169 1.1.1.1.4.2 christos #ifndef _WIN32
170 1.1.1.1.4.2 christos struct sigaction action;
171 1.1.1.1.4.2 christos #endif
172 1.1.1.1.4.2 christos
173 1.1.1.1.4.2 christos savefile[0] = 0;
174 1.1.1.1.4.2 christos loadfile[0] = 0;
175 1.1.1.1.4.2 christos hostlist[0] = 0;
176 1.1.1.1.4.2 christos
177 1.1.1.1.4.2 christos // Initialize errbuf
178 1.1.1.1.4.2 christos memset(errbuf, 0, sizeof(errbuf));
179 1.1.1.1.4.2 christos
180 1.1.1.1.4.2 christos if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
181 1.1.1.1.4.2 christos {
182 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
183 1.1.1.1.4.2 christos exit(-1);
184 1.1.1.1.4.2 christos }
185 1.1.1.1.4.2 christos
186 1.1.1.1.4.2 christos strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
187 1.1.1.1.4.2 christos strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
188 1.1.1.1.4.2 christos
189 1.1.1.1.4.2 christos // Prepare to open a new server socket
190 1.1.1.1.4.2 christos memset(&mainhints, 0, sizeof(struct addrinfo));
191 1.1.1.1.4.2 christos
192 1.1.1.1.4.2 christos mainhints.ai_family = PF_UNSPEC;
193 1.1.1.1.4.2 christos mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket
194 1.1.1.1.4.2 christos mainhints.ai_socktype = SOCK_STREAM;
195 1.1.1.1.4.2 christos
196 1.1.1.1.4.2 christos // Getting the proper command line options
197 1.1.1.1.4.2 christos while ((retval = getopt(argc, argv, "b:dhip:4l:na:s:f:v")) != -1)
198 1.1.1.1.4.2 christos {
199 1.1.1.1.4.2 christos switch (retval)
200 1.1.1.1.4.2 christos {
201 1.1.1.1.4.2 christos case 'b':
202 1.1.1.1.4.2 christos strncpy(address, optarg, MAX_LINE);
203 1.1.1.1.4.2 christos break;
204 1.1.1.1.4.2 christos case 'p':
205 1.1.1.1.4.2 christos strncpy(port, optarg, MAX_LINE);
206 1.1.1.1.4.2 christos break;
207 1.1.1.1.4.2 christos case '4':
208 1.1.1.1.4.2 christos mainhints.ai_family = PF_INET; // IPv4 server only
209 1.1.1.1.4.2 christos break;
210 1.1.1.1.4.2 christos case 'd':
211 1.1.1.1.4.2 christos isdaemon = 1;
212 1.1.1.1.4.2 christos break;
213 1.1.1.1.4.2 christos case 'i':
214 1.1.1.1.4.2 christos #ifdef _WIN32
215 1.1.1.1.4.2 christos printusage();
216 1.1.1.1.4.2 christos exit(1);
217 1.1.1.1.4.2 christos #else
218 1.1.1.1.4.2 christos isrunbyinetd = 1;
219 1.1.1.1.4.2 christos #endif
220 1.1.1.1.4.2 christos break;
221 1.1.1.1.4.2 christos case 'n':
222 1.1.1.1.4.2 christos nullAuthAllowed = 1;
223 1.1.1.1.4.2 christos break;
224 1.1.1.1.4.2 christos case 'v':
225 1.1.1.1.4.2 christos passivemode = 0;
226 1.1.1.1.4.2 christos break;
227 1.1.1.1.4.2 christos case 'l':
228 1.1.1.1.4.2 christos {
229 1.1.1.1.4.2 christos strncpy(hostlist, optarg, sizeof(hostlist));
230 1.1.1.1.4.2 christos break;
231 1.1.1.1.4.2 christos }
232 1.1.1.1.4.2 christos case 'a':
233 1.1.1.1.4.2 christos {
234 1.1.1.1.4.2 christos char *tmpaddress, *tmpport;
235 1.1.1.1.4.2 christos char *lasts;
236 1.1.1.1.4.2 christos int i = 0;
237 1.1.1.1.4.2 christos
238 1.1.1.1.4.2 christos tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);
239 1.1.1.1.4.2 christos
240 1.1.1.1.4.2 christos while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
241 1.1.1.1.4.2 christos {
242 1.1.1.1.4.2 christos tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
243 1.1.1.1.4.2 christos
244 1.1.1.1.4.2 christos strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
245 1.1.1.1.4.2 christos
246 1.1.1.1.4.2 christos if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
247 1.1.1.1.4.2 christos strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
248 1.1.1.1.4.2 christos else
249 1.1.1.1.4.2 christos strlcpy(activelist[i].port, tmpport, MAX_LINE);
250 1.1.1.1.4.2 christos
251 1.1.1.1.4.2 christos tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
252 1.1.1.1.4.2 christos
253 1.1.1.1.4.2 christos i++;
254 1.1.1.1.4.2 christos }
255 1.1.1.1.4.2 christos
256 1.1.1.1.4.2 christos if (i > MAX_ACTIVE_LIST)
257 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
258 1.1.1.1.4.2 christos
259 1.1.1.1.4.2 christos // I don't initialize the remaining part of the structure, since
260 1.1.1.1.4.2 christos // it is already zeroed (it is a global var)
261 1.1.1.1.4.2 christos break;
262 1.1.1.1.4.2 christos }
263 1.1.1.1.4.2 christos case 'f':
264 1.1.1.1.4.2 christos strlcpy(loadfile, optarg, MAX_LINE);
265 1.1.1.1.4.2 christos break;
266 1.1.1.1.4.2 christos case 's':
267 1.1.1.1.4.2 christos strlcpy(savefile, optarg, MAX_LINE);
268 1.1.1.1.4.2 christos break;
269 1.1.1.1.4.2 christos case 'h':
270 1.1.1.1.4.2 christos printusage();
271 1.1.1.1.4.2 christos exit(0);
272 1.1.1.1.4.2 christos break;
273 1.1.1.1.4.2 christos default:
274 1.1.1.1.4.2 christos exit(1);
275 1.1.1.1.4.2 christos break;
276 1.1.1.1.4.2 christos }
277 1.1.1.1.4.2 christos }
278 1.1.1.1.4.2 christos
279 1.1.1.1.4.2 christos #ifndef _WIN32
280 1.1.1.1.4.2 christos if (isdaemon && isrunbyinetd)
281 1.1.1.1.4.2 christos {
282 1.1.1.1.4.2 christos fprintf(stderr, "rpcapd: -d and -i can't be used together\n");
283 1.1.1.1.4.2 christos exit(1);
284 1.1.1.1.4.2 christos }
285 1.1.1.1.4.2 christos #endif
286 1.1.1.1.4.2 christos
287 1.1.1.1.4.2 christos if (savefile[0] && fileconf_save(savefile))
288 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE("Error when saving the configuration to file");
289 1.1.1.1.4.2 christos
290 1.1.1.1.4.2 christos // If the file does not exist, it keeps the settings provided by the command line
291 1.1.1.1.4.2 christos if (loadfile[0])
292 1.1.1.1.4.2 christos fileconf_read();
293 1.1.1.1.4.2 christos
294 1.1.1.1.4.2 christos #ifdef WIN32
295 1.1.1.1.4.2 christos //
296 1.1.1.1.4.2 christos // Create a handle to signal the main loop to tell it to do
297 1.1.1.1.4.2 christos // something.
298 1.1.1.1.4.2 christos //
299 1.1.1.1.4.2 christos state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
300 1.1.1.1.4.2 christos if (state_change_event == NULL)
301 1.1.1.1.4.2 christos {
302 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
303 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't create state change event: %s",
304 1.1.1.1.4.2 christos errbuf);
305 1.1.1.1.4.2 christos exit(2);
306 1.1.1.1.4.2 christos }
307 1.1.1.1.4.2 christos
308 1.1.1.1.4.2 christos //
309 1.1.1.1.4.2 christos // Catch control signals.
310 1.1.1.1.4.2 christos //
311 1.1.1.1.4.2 christos if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
312 1.1.1.1.4.2 christos {
313 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
314 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't set control handler: %s",
315 1.1.1.1.4.2 christos errbuf);
316 1.1.1.1.4.2 christos exit(2);
317 1.1.1.1.4.2 christos }
318 1.1.1.1.4.2 christos #else
319 1.1.1.1.4.2 christos memset(&action, 0, sizeof (action));
320 1.1.1.1.4.2 christos action.sa_handler = main_terminate;
321 1.1.1.1.4.2 christos action.sa_flags = 0;
322 1.1.1.1.4.2 christos sigemptyset(&action.sa_mask);
323 1.1.1.1.4.2 christos sigaction(SIGTERM, &action, NULL);
324 1.1.1.1.4.2 christos memset(&action, 0, sizeof (action));
325 1.1.1.1.4.2 christos action.sa_handler = main_reap_children;
326 1.1.1.1.4.2 christos action.sa_flags = 0;
327 1.1.1.1.4.2 christos sigemptyset(&action.sa_mask);
328 1.1.1.1.4.2 christos sigaction(SIGCHLD, &action, NULL);
329 1.1.1.1.4.2 christos // Ignore SIGPIPE - we'll get EPIPE when trying to write to a closed
330 1.1.1.1.4.2 christos // connection, we don't want to get killed by a signal in that case
331 1.1.1.1.4.2 christos signal(SIGPIPE, SIG_IGN);
332 1.1.1.1.4.2 christos #endif
333 1.1.1.1.4.2 christos
334 1.1.1.1.4.2 christos #ifndef _WIN32
335 1.1.1.1.4.2 christos if (isrunbyinetd)
336 1.1.1.1.4.2 christos {
337 1.1.1.1.4.2 christos //
338 1.1.1.1.4.2 christos // -i was specified, indicating that this is being run
339 1.1.1.1.4.2 christos // by inetd or something that can run network daemons
340 1.1.1.1.4.2 christos // as if it were inetd (xinetd, launchd, systemd, etc.).
341 1.1.1.1.4.2 christos //
342 1.1.1.1.4.2 christos // Our standard input is the input side of a connection,
343 1.1.1.1.4.2 christos // and our standard output is the output side of a
344 1.1.1.1.4.2 christos // connection.
345 1.1.1.1.4.2 christos //
346 1.1.1.1.4.2 christos int sockctrl_in, sockctrl_out;
347 1.1.1.1.4.2 christos int devnull_fd;
348 1.1.1.1.4.2 christos
349 1.1.1.1.4.2 christos //
350 1.1.1.1.4.2 christos // Duplicate the standard input and output, making them
351 1.1.1.1.4.2 christos // the input and output side of the control connection.
352 1.1.1.1.4.2 christos //
353 1.1.1.1.4.2 christos sockctrl_in = dup(0);
354 1.1.1.1.4.2 christos if (sockctrl_in == -1)
355 1.1.1.1.4.2 christos {
356 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
357 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't dup standard input: %s",
358 1.1.1.1.4.2 christos errbuf);
359 1.1.1.1.4.2 christos exit(2);
360 1.1.1.1.4.2 christos }
361 1.1.1.1.4.2 christos sockctrl_out = dup(1);
362 1.1.1.1.4.2 christos if (sockctrl_out == -1)
363 1.1.1.1.4.2 christos {
364 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
365 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't dup standard output: %s",
366 1.1.1.1.4.2 christos errbuf);
367 1.1.1.1.4.2 christos exit(2);
368 1.1.1.1.4.2 christos }
369 1.1.1.1.4.2 christos
370 1.1.1.1.4.2 christos //
371 1.1.1.1.4.2 christos // Try to set the standard input and output to /dev/null.
372 1.1.1.1.4.2 christos //
373 1.1.1.1.4.2 christos devnull_fd = open("/dev/null", O_RDWR);
374 1.1.1.1.4.2 christos if (devnull_fd != -1)
375 1.1.1.1.4.2 christos {
376 1.1.1.1.4.2 christos //
377 1.1.1.1.4.2 christos // If this fails, just drive on.
378 1.1.1.1.4.2 christos //
379 1.1.1.1.4.2 christos (void)dup2(devnull_fd, 0);
380 1.1.1.1.4.2 christos (void)dup2(devnull_fd, 1);
381 1.1.1.1.4.2 christos close(devnull_fd);
382 1.1.1.1.4.2 christos }
383 1.1.1.1.4.2 christos
384 1.1.1.1.4.2 christos //
385 1.1.1.1.4.2 christos // Handle this client.
386 1.1.1.1.4.2 christos // This is passive mode, so we don't care whether we were
387 1.1.1.1.4.2 christos // told by the client to close.
388 1.1.1.1.4.2 christos //
389 1.1.1.1.4.2 christos (void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0,
390 1.1.1.1.4.2 christos nullAuthAllowed);
391 1.1.1.1.4.2 christos
392 1.1.1.1.4.2 christos //
393 1.1.1.1.4.2 christos // Nothing more to do.
394 1.1.1.1.4.2 christos //
395 1.1.1.1.4.2 christos exit(0);
396 1.1.1.1.4.2 christos }
397 1.1.1.1.4.2 christos #endif
398 1.1.1.1.4.2 christos
399 1.1.1.1.4.2 christos if (isdaemon)
400 1.1.1.1.4.2 christos {
401 1.1.1.1.4.2 christos //
402 1.1.1.1.4.2 christos // This is being run as a daemon.
403 1.1.1.1.4.2 christos // On UN*X, it might be manually run, or run from an
404 1.1.1.1.4.2 christos // rc file.
405 1.1.1.1.4.2 christos //
406 1.1.1.1.4.2 christos #ifndef _WIN32
407 1.1.1.1.4.2 christos int pid;
408 1.1.1.1.4.2 christos
409 1.1.1.1.4.2 christos //
410 1.1.1.1.4.2 christos // Daemonize ourselves.
411 1.1.1.1.4.2 christos //
412 1.1.1.1.4.2 christos // Unix Network Programming, pg 336
413 1.1.1.1.4.2 christos //
414 1.1.1.1.4.2 christos if ((pid = fork()) != 0)
415 1.1.1.1.4.2 christos exit(0); // Parent terminates
416 1.1.1.1.4.2 christos
417 1.1.1.1.4.2 christos // First child continues
418 1.1.1.1.4.2 christos // Set daemon mode
419 1.1.1.1.4.2 christos setsid();
420 1.1.1.1.4.2 christos
421 1.1.1.1.4.2 christos // generated under unix with 'kill -HUP', needed to reload the configuration
422 1.1.1.1.4.2 christos memset(&action, 0, sizeof (action));
423 1.1.1.1.4.2 christos action.sa_handler = main_reread_config;
424 1.1.1.1.4.2 christos action.sa_flags = 0;
425 1.1.1.1.4.2 christos sigemptyset(&action.sa_mask);
426 1.1.1.1.4.2 christos sigaction(SIGHUP, &action, NULL);
427 1.1.1.1.4.2 christos
428 1.1.1.1.4.2 christos if ((pid = fork()) != 0)
429 1.1.1.1.4.2 christos exit(0); // First child terminates
430 1.1.1.1.4.2 christos
431 1.1.1.1.4.2 christos // LINUX WARNING: the current linux implementation of pthreads requires a management thread
432 1.1.1.1.4.2 christos // to handle some hidden stuff. So, as soon as you create the first thread, two threads are
433 1.1.1.1.4.2 christos // created. Fom this point on, the number of threads active are always one more compared
434 1.1.1.1.4.2 christos // to the number you're expecting
435 1.1.1.1.4.2 christos
436 1.1.1.1.4.2 christos // Second child continues
437 1.1.1.1.4.2 christos // umask(0);
438 1.1.1.1.4.2 christos // chdir("/");
439 1.1.1.1.4.2 christos #else
440 1.1.1.1.4.2 christos //
441 1.1.1.1.4.2 christos // This is being run as a service on Windows.
442 1.1.1.1.4.2 christos //
443 1.1.1.1.4.2 christos // If this call succeeds, it is blocking on Win32
444 1.1.1.1.4.2 christos //
445 1.1.1.1.4.2 christos if (svc_start() != 1)
446 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE("Unable to start the service");
447 1.1.1.1.4.2 christos
448 1.1.1.1.4.2 christos // When the previous call returns, the entire application has to be stopped.
449 1.1.1.1.4.2 christos exit(0);
450 1.1.1.1.4.2 christos #endif
451 1.1.1.1.4.2 christos }
452 1.1.1.1.4.2 christos else // Console mode
453 1.1.1.1.4.2 christos {
454 1.1.1.1.4.2 christos #ifndef _WIN32
455 1.1.1.1.4.2 christos // Enable the catching of Ctrl+C
456 1.1.1.1.4.2 christos memset(&action, 0, sizeof (action));
457 1.1.1.1.4.2 christos action.sa_handler = main_terminate;
458 1.1.1.1.4.2 christos action.sa_flags = 0;
459 1.1.1.1.4.2 christos sigemptyset(&action.sa_mask);
460 1.1.1.1.4.2 christos sigaction(SIGINT, &action, NULL);
461 1.1.1.1.4.2 christos
462 1.1.1.1.4.2 christos // generated under unix with 'kill -HUP', needed to reload the configuration
463 1.1.1.1.4.2 christos // We do not have this kind of signal in Win32
464 1.1.1.1.4.2 christos memset(&action, 0, sizeof (action));
465 1.1.1.1.4.2 christos action.sa_handler = main_reread_config;
466 1.1.1.1.4.2 christos action.sa_flags = 0;
467 1.1.1.1.4.2 christos sigemptyset(&action.sa_mask);
468 1.1.1.1.4.2 christos sigaction(SIGHUP, &action, NULL);
469 1.1.1.1.4.2 christos #endif
470 1.1.1.1.4.2 christos
471 1.1.1.1.4.2 christos printf("Press CTRL + C to stop the server...\n");
472 1.1.1.1.4.2 christos }
473 1.1.1.1.4.2 christos
474 1.1.1.1.4.2 christos // If we're a Win32 service, we have already called this function in the service_main
475 1.1.1.1.4.2 christos main_startup();
476 1.1.1.1.4.2 christos
477 1.1.1.1.4.2 christos // The code should never arrive here (since the main_startup is blocking)
478 1.1.1.1.4.2 christos // however this avoids a compiler warning
479 1.1.1.1.4.2 christos exit(0);
480 1.1.1.1.4.2 christos }
481 1.1.1.1.4.2 christos
482 1.1.1.1.4.2 christos void main_startup(void)
483 1.1.1.1.4.2 christos {
484 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
485 1.1.1.1.4.2 christos struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
486 1.1.1.1.4.2 christos int i;
487 1.1.1.1.4.2 christos #ifdef _WIN32
488 1.1.1.1.4.2 christos HANDLE threadId; // handle for the subthread
489 1.1.1.1.4.2 christos #else
490 1.1.1.1.4.2 christos pid_t pid;
491 1.1.1.1.4.2 christos #endif
492 1.1.1.1.4.2 christos
493 1.1.1.1.4.2 christos i = 0;
494 1.1.1.1.4.2 christos addrinfo = NULL;
495 1.1.1.1.4.2 christos memset(errbuf, 0, sizeof(errbuf));
496 1.1.1.1.4.2 christos
497 1.1.1.1.4.2 christos // Starts all the active threads
498 1.1.1.1.4.2 christos while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
499 1.1.1.1.4.2 christos {
500 1.1.1.1.4.2 christos activelist[i].ai_family = mainhints.ai_family;
501 1.1.1.1.4.2 christos
502 1.1.1.1.4.2 christos #ifdef _WIN32
503 1.1.1.1.4.2 christos threadId = (HANDLE)_beginthreadex(NULL, 0, main_active,
504 1.1.1.1.4.2 christos (void *)&activelist[i], 0, NULL);
505 1.1.1.1.4.2 christos if (threadId == 0)
506 1.1.1.1.4.2 christos {
507 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE("Error creating the active child threads");
508 1.1.1.1.4.2 christos continue;
509 1.1.1.1.4.2 christos }
510 1.1.1.1.4.2 christos CloseHandle(threadId);
511 1.1.1.1.4.2 christos #else
512 1.1.1.1.4.2 christos if ((pid = fork()) == 0) // I am the child
513 1.1.1.1.4.2 christos {
514 1.1.1.1.4.2 christos main_active((void *) &activelist[i]);
515 1.1.1.1.4.2 christos exit(0);
516 1.1.1.1.4.2 christos }
517 1.1.1.1.4.2 christos #endif
518 1.1.1.1.4.2 christos i++;
519 1.1.1.1.4.2 christos }
520 1.1.1.1.4.2 christos
521 1.1.1.1.4.2 christos /*
522 1.1.1.1.4.2 christos * The code that manages the active connections is not blocking;
523 1.1.1.1.4.2 christos * the code that manages the passive connection is blocking.
524 1.1.1.1.4.2 christos * So, if the user does not want to run in passive mode, we have
525 1.1.1.1.4.2 christos * to block the main thread here, otherwise the program ends and
526 1.1.1.1.4.2 christos * all threads are stopped.
527 1.1.1.1.4.2 christos *
528 1.1.1.1.4.2 christos * WARNING: this means that in case we have only active mode,
529 1.1.1.1.4.2 christos * the program does not terminate even if all the child thread
530 1.1.1.1.4.2 christos * terminates. The user has always to press Ctrl+C (or send a
531 1.1.1.1.4.2 christos * SIGTERM) to terminate the program.
532 1.1.1.1.4.2 christos */
533 1.1.1.1.4.2 christos if (passivemode)
534 1.1.1.1.4.2 christos {
535 1.1.1.1.4.2 christos struct addrinfo *tempaddrinfo;
536 1.1.1.1.4.2 christos
537 1.1.1.1.4.2 christos //
538 1.1.1.1.4.2 christos // Get a list of sockets on which to listen.
539 1.1.1.1.4.2 christos //
540 1.1.1.1.4.2 christos if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
541 1.1.1.1.4.2 christos {
542 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
543 1.1.1.1.4.2 christos return;
544 1.1.1.1.4.2 christos }
545 1.1.1.1.4.2 christos
546 1.1.1.1.4.2 christos for (tempaddrinfo = addrinfo; tempaddrinfo;
547 1.1.1.1.4.2 christos tempaddrinfo = tempaddrinfo->ai_next)
548 1.1.1.1.4.2 christos {
549 1.1.1.1.4.2 christos SOCKET sock;
550 1.1.1.1.4.2 christos struct listen_sock *sock_info;
551 1.1.1.1.4.2 christos
552 1.1.1.1.4.2 christos if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
553 1.1.1.1.4.2 christos {
554 1.1.1.1.4.2 christos switch (tempaddrinfo->ai_family)
555 1.1.1.1.4.2 christos {
556 1.1.1.1.4.2 christos case AF_INET:
557 1.1.1.1.4.2 christos {
558 1.1.1.1.4.2 christos struct sockaddr_in *in;
559 1.1.1.1.4.2 christos char addrbuf[INET_ADDRSTRLEN];
560 1.1.1.1.4.2 christos
561 1.1.1.1.4.2 christos in = (struct sockaddr_in *)tempaddrinfo->ai_addr;
562 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
563 1.1.1.1.4.2 christos inet_ntop(AF_INET, &in->sin_addr,
564 1.1.1.1.4.2 christos addrbuf, sizeof (addrbuf)),
565 1.1.1.1.4.2 christos ntohs(in->sin_port),
566 1.1.1.1.4.2 christos errbuf);
567 1.1.1.1.4.2 christos break;
568 1.1.1.1.4.2 christos }
569 1.1.1.1.4.2 christos
570 1.1.1.1.4.2 christos case AF_INET6:
571 1.1.1.1.4.2 christos {
572 1.1.1.1.4.2 christos struct sockaddr_in6 *in6;
573 1.1.1.1.4.2 christos char addrbuf[INET6_ADDRSTRLEN];
574 1.1.1.1.4.2 christos
575 1.1.1.1.4.2 christos in6 = (struct sockaddr_in6 *)tempaddrinfo->ai_addr;
576 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
577 1.1.1.1.4.2 christos inet_ntop(AF_INET6, &in6->sin6_addr,
578 1.1.1.1.4.2 christos addrbuf, sizeof (addrbuf)),
579 1.1.1.1.4.2 christos ntohs(in6->sin6_port),
580 1.1.1.1.4.2 christos errbuf);
581 1.1.1.1.4.2 christos break;
582 1.1.1.1.4.2 christos }
583 1.1.1.1.4.2 christos
584 1.1.1.1.4.2 christos default:
585 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for address family %u: %s",
586 1.1.1.1.4.2 christos tempaddrinfo->ai_family,
587 1.1.1.1.4.2 christos errbuf);
588 1.1.1.1.4.2 christos break;
589 1.1.1.1.4.2 christos }
590 1.1.1.1.4.2 christos continue;
591 1.1.1.1.4.2 christos }
592 1.1.1.1.4.2 christos
593 1.1.1.1.4.2 christos sock_info = (struct listen_sock *) malloc(sizeof (struct listen_sock));
594 1.1.1.1.4.2 christos if (sock_info == NULL)
595 1.1.1.1.4.2 christos {
596 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't allocate structure for listen socket");
597 1.1.1.1.4.2 christos exit(2);
598 1.1.1.1.4.2 christos }
599 1.1.1.1.4.2 christos sock_info->sock = sock;
600 1.1.1.1.4.2 christos sock_info->next = listen_socks;
601 1.1.1.1.4.2 christos listen_socks = sock_info;
602 1.1.1.1.4.2 christos }
603 1.1.1.1.4.2 christos
604 1.1.1.1.4.2 christos freeaddrinfo(addrinfo);
605 1.1.1.1.4.2 christos
606 1.1.1.1.4.2 christos if (listen_socks == NULL)
607 1.1.1.1.4.2 christos {
608 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't listen on any address");
609 1.1.1.1.4.2 christos exit(2);
610 1.1.1.1.4.2 christos }
611 1.1.1.1.4.2 christos
612 1.1.1.1.4.2 christos //
613 1.1.1.1.4.2 christos // Now listen on all of them, waiting for connections.
614 1.1.1.1.4.2 christos //
615 1.1.1.1.4.2 christos accept_connections();
616 1.1.1.1.4.2 christos }
617 1.1.1.1.4.2 christos
618 1.1.1.1.4.2 christos //
619 1.1.1.1.4.2 christos // We're done; exit.
620 1.1.1.1.4.2 christos //
621 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(PROGRAM_NAME " is closing.\n");
622 1.1.1.1.4.2 christos
623 1.1.1.1.4.2 christos #ifndef _WIN32
624 1.1.1.1.4.2 christos //
625 1.1.1.1.4.2 christos // Sends a KILL signal to all the processes in this process's
626 1.1.1.1.4.2 christos // process group; i.e., it kills all the child processes
627 1.1.1.1.4.2 christos // we've created.
628 1.1.1.1.4.2 christos //
629 1.1.1.1.4.2 christos // XXX - that also includes us, so we will be killed as well;
630 1.1.1.1.4.2 christos // that may cause a message to be printed or logged.
631 1.1.1.1.4.2 christos //
632 1.1.1.1.4.2 christos kill(0, SIGKILL);
633 1.1.1.1.4.2 christos #endif
634 1.1.1.1.4.2 christos
635 1.1.1.1.4.2 christos //
636 1.1.1.1.4.2 christos // Just leave. We shouldn't need to clean up sockets or
637 1.1.1.1.4.2 christos // anything else, and if we try to do so, we'll could end
638 1.1.1.1.4.2 christos // up closing sockets, or shutting Winsock down, out from
639 1.1.1.1.4.2 christos // under service loops, causing all sorts of noisy error
640 1.1.1.1.4.2 christos // messages.
641 1.1.1.1.4.2 christos //
642 1.1.1.1.4.2 christos // We shouldn't need to worry about cleaning up any resources
643 1.1.1.1.4.2 christos // such as handles, sockets, threads, etc. - exit() should
644 1.1.1.1.4.2 christos // terminate the process, causing all those resources to be
645 1.1.1.1.4.2 christos // cleaned up (including the threads; Microsoft claims in the
646 1.1.1.1.4.2 christos // ExitProcess() documentation that, if ExitProcess() is called,
647 1.1.1.1.4.2 christos // "If a thread is waiting on a kernel object, it will not be
648 1.1.1.1.4.2 christos // terminated until the wait has completed.", but claims in the
649 1.1.1.1.4.2 christos // _beginthread()/_beginthreadex() documentation that "All threads
650 1.1.1.1.4.2 christos // are terminated if any thread calls abort, exit, _exit, or
651 1.1.1.1.4.2 christos // ExitProcess." - the latter appears to be the case, even for
652 1.1.1.1.4.2 christos // threads waiting on the event for a pcap_t).
653 1.1.1.1.4.2 christos //
654 1.1.1.1.4.2 christos exit(0);
655 1.1.1.1.4.2 christos }
656 1.1.1.1.4.2 christos
657 1.1.1.1.4.2 christos #ifdef _WIN32
658 1.1.1.1.4.2 christos static void
659 1.1.1.1.4.2 christos send_state_change_event(void)
660 1.1.1.1.4.2 christos {
661 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
662 1.1.1.1.4.2 christos
663 1.1.1.1.4.2 christos if (!SetEvent(state_change_event))
664 1.1.1.1.4.2 christos {
665 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
666 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "SetEvent on shutdown event failed: %s", errbuf);
667 1.1.1.1.4.2 christos }
668 1.1.1.1.4.2 christos }
669 1.1.1.1.4.2 christos
670 1.1.1.1.4.2 christos void
671 1.1.1.1.4.2 christos send_shutdown_notification(void)
672 1.1.1.1.4.2 christos {
673 1.1.1.1.4.2 christos //
674 1.1.1.1.4.2 christos // Indicate that the server should shut down.
675 1.1.1.1.4.2 christos //
676 1.1.1.1.4.2 christos shutdown_server = 1;
677 1.1.1.1.4.2 christos
678 1.1.1.1.4.2 christos //
679 1.1.1.1.4.2 christos // Send a state change event, to wake up WSAWaitForMultipleEvents().
680 1.1.1.1.4.2 christos //
681 1.1.1.1.4.2 christos send_state_change_event();
682 1.1.1.1.4.2 christos }
683 1.1.1.1.4.2 christos
684 1.1.1.1.4.2 christos void
685 1.1.1.1.4.2 christos send_reread_configuration_notification(void)
686 1.1.1.1.4.2 christos {
687 1.1.1.1.4.2 christos //
688 1.1.1.1.4.2 christos // Indicate that the server should re-read its configuration file.
689 1.1.1.1.4.2 christos //
690 1.1.1.1.4.2 christos reread_config = 1;
691 1.1.1.1.4.2 christos
692 1.1.1.1.4.2 christos //
693 1.1.1.1.4.2 christos // Send a state change event, to wake up WSAWaitForMultipleEvents().
694 1.1.1.1.4.2 christos //
695 1.1.1.1.4.2 christos send_state_change_event();
696 1.1.1.1.4.2 christos }
697 1.1.1.1.4.2 christos
698 1.1.1.1.4.2 christos static BOOL WINAPI main_ctrl_event(DWORD ctrltype)
699 1.1.1.1.4.2 christos {
700 1.1.1.1.4.2 christos //
701 1.1.1.1.4.2 christos // ctrltype is one of:
702 1.1.1.1.4.2 christos //
703 1.1.1.1.4.2 christos // CTRL_C_EVENT - we got a ^C; this is like SIGINT
704 1.1.1.1.4.2 christos // CTRL_BREAK_EVENT - we got Ctrl+Break
705 1.1.1.1.4.2 christos // CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP
706 1.1.1.1.4.2 christos // CTRL_LOGOFF_EVENT - a user is logging off; this is received
707 1.1.1.1.4.2 christos // only by services
708 1.1.1.1.4.2 christos // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
709 1.1.1.1.4.2 christos // received only by services
710 1.1.1.1.4.2 christos //
711 1.1.1.1.4.2 christos // For now, we treat all but CTRL_LOGOFF_EVENT as indications
712 1.1.1.1.4.2 christos // that we should shut down.
713 1.1.1.1.4.2 christos //
714 1.1.1.1.4.2 christos switch (ctrltype)
715 1.1.1.1.4.2 christos {
716 1.1.1.1.4.2 christos case CTRL_C_EVENT:
717 1.1.1.1.4.2 christos case CTRL_BREAK_EVENT:
718 1.1.1.1.4.2 christos case CTRL_CLOSE_EVENT:
719 1.1.1.1.4.2 christos case CTRL_SHUTDOWN_EVENT:
720 1.1.1.1.4.2 christos //
721 1.1.1.1.4.2 christos // Set a shutdown notification.
722 1.1.1.1.4.2 christos //
723 1.1.1.1.4.2 christos send_shutdown_notification();
724 1.1.1.1.4.2 christos break;
725 1.1.1.1.4.2 christos
726 1.1.1.1.4.2 christos default:
727 1.1.1.1.4.2 christos break;
728 1.1.1.1.4.2 christos }
729 1.1.1.1.4.2 christos
730 1.1.1.1.4.2 christos //
731 1.1.1.1.4.2 christos // We handled this.
732 1.1.1.1.4.2 christos //
733 1.1.1.1.4.2 christos return TRUE;
734 1.1.1.1.4.2 christos }
735 1.1.1.1.4.2 christos #else
736 1.1.1.1.4.2 christos static void main_terminate(int sign _U_)
737 1.1.1.1.4.2 christos {
738 1.1.1.1.4.2 christos //
739 1.1.1.1.4.2 christos // Note that the server should shut down.
740 1.1.1.1.4.2 christos // select() should get an EINTR error when we return,
741 1.1.1.1.4.2 christos // so it will wake up and know it needs to check the flag.
742 1.1.1.1.4.2 christos //
743 1.1.1.1.4.2 christos shutdown_server = 1;
744 1.1.1.1.4.2 christos }
745 1.1.1.1.4.2 christos
746 1.1.1.1.4.2 christos static void main_reread_config(int sign _U_)
747 1.1.1.1.4.2 christos {
748 1.1.1.1.4.2 christos //
749 1.1.1.1.4.2 christos // Note that the server should re-read its configuration file.
750 1.1.1.1.4.2 christos // select() should get an EINTR error when we return,
751 1.1.1.1.4.2 christos // so it will wake up and know it needs to check the flag.
752 1.1.1.1.4.2 christos //
753 1.1.1.1.4.2 christos reread_config = 1;
754 1.1.1.1.4.2 christos }
755 1.1.1.1.4.2 christos
756 1.1.1.1.4.2 christos static void main_reap_children(int sign _U_)
757 1.1.1.1.4.2 christos {
758 1.1.1.1.4.2 christos pid_t pid;
759 1.1.1.1.4.2 christos int exitstat;
760 1.1.1.1.4.2 christos
761 1.1.1.1.4.2 christos // Reap all child processes that have exited.
762 1.1.1.1.4.2 christos // For reference, Stevens, pg 128
763 1.1.1.1.4.2 christos
764 1.1.1.1.4.2 christos while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
765 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE("Child terminated");
766 1.1.1.1.4.2 christos
767 1.1.1.1.4.2 christos return;
768 1.1.1.1.4.2 christos }
769 1.1.1.1.4.2 christos #endif
770 1.1.1.1.4.2 christos
771 1.1.1.1.4.2 christos //
772 1.1.1.1.4.2 christos // Loop waiting for incoming connections and accepting them.
773 1.1.1.1.4.2 christos //
774 1.1.1.1.4.2 christos static void
775 1.1.1.1.4.2 christos accept_connections(void)
776 1.1.1.1.4.2 christos {
777 1.1.1.1.4.2 christos #ifdef _WIN32
778 1.1.1.1.4.2 christos struct listen_sock *sock_info;
779 1.1.1.1.4.2 christos DWORD num_events;
780 1.1.1.1.4.2 christos WSAEVENT *events;
781 1.1.1.1.4.2 christos int i;
782 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
783 1.1.1.1.4.2 christos
784 1.1.1.1.4.2 christos //
785 1.1.1.1.4.2 christos // How big does the set of events need to be?
786 1.1.1.1.4.2 christos // One for the shutdown event, plus one for every socket on which
787 1.1.1.1.4.2 christos // we'll be listening.
788 1.1.1.1.4.2 christos //
789 1.1.1.1.4.2 christos num_events = 1; // shutdown event
790 1.1.1.1.4.2 christos for (sock_info = listen_socks; sock_info;
791 1.1.1.1.4.2 christos sock_info = sock_info->next)
792 1.1.1.1.4.2 christos {
793 1.1.1.1.4.2 christos if (num_events == WSA_MAXIMUM_WAIT_EVENTS)
794 1.1.1.1.4.2 christos {
795 1.1.1.1.4.2 christos //
796 1.1.1.1.4.2 christos // WSAWaitForMultipleEvents() doesn't support
797 1.1.1.1.4.2 christos // more than WSA_MAXIMUM_WAIT_EVENTS events
798 1.1.1.1.4.2 christos // on which to wait.
799 1.1.1.1.4.2 christos //
800 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Too many sockets on which to listen");
801 1.1.1.1.4.2 christos exit(2);
802 1.1.1.1.4.2 christos }
803 1.1.1.1.4.2 christos num_events++;
804 1.1.1.1.4.2 christos }
805 1.1.1.1.4.2 christos
806 1.1.1.1.4.2 christos //
807 1.1.1.1.4.2 christos // Allocate the array of events.
808 1.1.1.1.4.2 christos //
809 1.1.1.1.4.2 christos events = (WSAEVENT *) malloc(num_events * sizeof (WSAEVENT));
810 1.1.1.1.4.2 christos if (events == NULL)
811 1.1.1.1.4.2 christos {
812 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't allocate array of events which to listen");
813 1.1.1.1.4.2 christos exit(2);
814 1.1.1.1.4.2 christos }
815 1.1.1.1.4.2 christos
816 1.1.1.1.4.2 christos //
817 1.1.1.1.4.2 christos // Fill it in.
818 1.1.1.1.4.2 christos //
819 1.1.1.1.4.2 christos events[0] = state_change_event; // state change event first
820 1.1.1.1.4.2 christos for (sock_info = listen_socks, i = 1; sock_info;
821 1.1.1.1.4.2 christos sock_info = sock_info->next, i++)
822 1.1.1.1.4.2 christos {
823 1.1.1.1.4.2 christos WSAEVENT event;
824 1.1.1.1.4.2 christos
825 1.1.1.1.4.2 christos //
826 1.1.1.1.4.2 christos // Create an event that is signaled if there's a connection
827 1.1.1.1.4.2 christos // to accept on the socket in question.
828 1.1.1.1.4.2 christos //
829 1.1.1.1.4.2 christos event = WSACreateEvent();
830 1.1.1.1.4.2 christos if (event == WSA_INVALID_EVENT)
831 1.1.1.1.4.2 christos {
832 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
833 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't create socket event: %s", errbuf);
834 1.1.1.1.4.2 christos exit(2);
835 1.1.1.1.4.2 christos }
836 1.1.1.1.4.2 christos if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
837 1.1.1.1.4.2 christos {
838 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
839 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Can't setup socket event: %s", errbuf);
840 1.1.1.1.4.2 christos exit(2);
841 1.1.1.1.4.2 christos }
842 1.1.1.1.4.2 christos events[i] = event;
843 1.1.1.1.4.2 christos }
844 1.1.1.1.4.2 christos
845 1.1.1.1.4.2 christos for (;;)
846 1.1.1.1.4.2 christos {
847 1.1.1.1.4.2 christos //
848 1.1.1.1.4.2 christos // Wait for incoming connections.
849 1.1.1.1.4.2 christos //
850 1.1.1.1.4.2 christos DWORD ret;
851 1.1.1.1.4.2 christos
852 1.1.1.1.4.2 christos ret = WSAWaitForMultipleEvents(num_events, events, FALSE,
853 1.1.1.1.4.2 christos WSA_INFINITE, FALSE);
854 1.1.1.1.4.2 christos if (ret == WSA_WAIT_FAILED)
855 1.1.1.1.4.2 christos {
856 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
857 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "WSAWaitForMultipleEvents failed: %s", errbuf);
858 1.1.1.1.4.2 christos exit(2);
859 1.1.1.1.4.2 christos }
860 1.1.1.1.4.2 christos
861 1.1.1.1.4.2 christos if (ret == WSA_WAIT_EVENT_0)
862 1.1.1.1.4.2 christos {
863 1.1.1.1.4.2 christos //
864 1.1.1.1.4.2 christos // The state change event was set.
865 1.1.1.1.4.2 christos //
866 1.1.1.1.4.2 christos if (shutdown_server)
867 1.1.1.1.4.2 christos {
868 1.1.1.1.4.2 christos //
869 1.1.1.1.4.2 christos // Time to quit. Exit the loop.
870 1.1.1.1.4.2 christos //
871 1.1.1.1.4.2 christos break;
872 1.1.1.1.4.2 christos }
873 1.1.1.1.4.2 christos if (reread_config)
874 1.1.1.1.4.2 christos {
875 1.1.1.1.4.2 christos //
876 1.1.1.1.4.2 christos // We should re-read the configuration
877 1.1.1.1.4.2 christos // file.
878 1.1.1.1.4.2 christos //
879 1.1.1.1.4.2 christos reread_config = 0; // clear the indicator
880 1.1.1.1.4.2 christos fileconf_read();
881 1.1.1.1.4.2 christos }
882 1.1.1.1.4.2 christos }
883 1.1.1.1.4.2 christos
884 1.1.1.1.4.2 christos //
885 1.1.1.1.4.2 christos // Check each socket.
886 1.1.1.1.4.2 christos //
887 1.1.1.1.4.2 christos for (sock_info = listen_socks, i = 1; sock_info;
888 1.1.1.1.4.2 christos sock_info = sock_info->next, i++)
889 1.1.1.1.4.2 christos {
890 1.1.1.1.4.2 christos WSANETWORKEVENTS network_events;
891 1.1.1.1.4.2 christos
892 1.1.1.1.4.2 christos if (WSAEnumNetworkEvents(sock_info->sock,
893 1.1.1.1.4.2 christos events[i], &network_events) == SOCKET_ERROR)
894 1.1.1.1.4.2 christos {
895 1.1.1.1.4.2 christos sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
896 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "WSAEnumNetworkEvents failed: %s", errbuf);
897 1.1.1.1.4.2 christos exit(2);
898 1.1.1.1.4.2 christos }
899 1.1.1.1.4.2 christos if (network_events.lNetworkEvents & FD_ACCEPT)
900 1.1.1.1.4.2 christos {
901 1.1.1.1.4.2 christos //
902 1.1.1.1.4.2 christos // Did an error occur?
903 1.1.1.1.4.2 christos //
904 1.1.1.1.4.2 christos if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
905 1.1.1.1.4.2 christos {
906 1.1.1.1.4.2 christos //
907 1.1.1.1.4.2 christos // Yes - report it and keep going.
908 1.1.1.1.4.2 christos //
909 1.1.1.1.4.2 christos sock_fmterror(NULL,
910 1.1.1.1.4.2 christos network_events.iErrorCode[FD_ACCEPT_BIT],
911 1.1.1.1.4.2 christos errbuf,
912 1.1.1.1.4.2 christos PCAP_ERRBUF_SIZE);
913 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Socket error: %s", errbuf);
914 1.1.1.1.4.2 christos continue;
915 1.1.1.1.4.2 christos }
916 1.1.1.1.4.2 christos
917 1.1.1.1.4.2 christos //
918 1.1.1.1.4.2 christos // Accept the connection.
919 1.1.1.1.4.2 christos //
920 1.1.1.1.4.2 christos accept_connection(sock_info->sock);
921 1.1.1.1.4.2 christos }
922 1.1.1.1.4.2 christos }
923 1.1.1.1.4.2 christos }
924 1.1.1.1.4.2 christos #else
925 1.1.1.1.4.2 christos struct listen_sock *sock_info;
926 1.1.1.1.4.2 christos int num_sock_fds;
927 1.1.1.1.4.2 christos
928 1.1.1.1.4.2 christos //
929 1.1.1.1.4.2 christos // How big does the bitset of sockets on which to select() have
930 1.1.1.1.4.2 christos // to be?
931 1.1.1.1.4.2 christos //
932 1.1.1.1.4.2 christos num_sock_fds = 0;
933 1.1.1.1.4.2 christos for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
934 1.1.1.1.4.2 christos {
935 1.1.1.1.4.2 christos if (sock_info->sock + 1 > num_sock_fds)
936 1.1.1.1.4.2 christos {
937 1.1.1.1.4.2 christos if ((unsigned int)(sock_info->sock + 1) >
938 1.1.1.1.4.2 christos (unsigned int)FD_SETSIZE)
939 1.1.1.1.4.2 christos {
940 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Socket FD is too bit for an fd_set");
941 1.1.1.1.4.2 christos exit(2);
942 1.1.1.1.4.2 christos }
943 1.1.1.1.4.2 christos num_sock_fds = sock_info->sock + 1;
944 1.1.1.1.4.2 christos }
945 1.1.1.1.4.2 christos }
946 1.1.1.1.4.2 christos
947 1.1.1.1.4.2 christos for (;;)
948 1.1.1.1.4.2 christos {
949 1.1.1.1.4.2 christos fd_set sock_fds;
950 1.1.1.1.4.2 christos int ret;
951 1.1.1.1.4.2 christos
952 1.1.1.1.4.2 christos //
953 1.1.1.1.4.2 christos // Set up an fd_set for all the sockets on which we're
954 1.1.1.1.4.2 christos // listening.
955 1.1.1.1.4.2 christos //
956 1.1.1.1.4.2 christos // This set is modified by select(), so we have to
957 1.1.1.1.4.2 christos // construct it anew each time.
958 1.1.1.1.4.2 christos //
959 1.1.1.1.4.2 christos FD_ZERO(&sock_fds);
960 1.1.1.1.4.2 christos for (sock_info = listen_socks; sock_info;
961 1.1.1.1.4.2 christos sock_info = sock_info->next)
962 1.1.1.1.4.2 christos {
963 1.1.1.1.4.2 christos FD_SET(sock_info->sock, &sock_fds);
964 1.1.1.1.4.2 christos }
965 1.1.1.1.4.2 christos
966 1.1.1.1.4.2 christos //
967 1.1.1.1.4.2 christos // Wait for incoming connections.
968 1.1.1.1.4.2 christos //
969 1.1.1.1.4.2 christos ret = select(num_sock_fds, &sock_fds, NULL, NULL, NULL);
970 1.1.1.1.4.2 christos if (ret == -1)
971 1.1.1.1.4.2 christos {
972 1.1.1.1.4.2 christos if (errno == EINTR)
973 1.1.1.1.4.2 christos {
974 1.1.1.1.4.2 christos //
975 1.1.1.1.4.2 christos // If this is a "terminate the
976 1.1.1.1.4.2 christos // server" signal, exit the loop,
977 1.1.1.1.4.2 christos // otherwise just keep trying.
978 1.1.1.1.4.2 christos //
979 1.1.1.1.4.2 christos if (shutdown_server)
980 1.1.1.1.4.2 christos {
981 1.1.1.1.4.2 christos //
982 1.1.1.1.4.2 christos // Time to quit. Exit the loop.
983 1.1.1.1.4.2 christos //
984 1.1.1.1.4.2 christos break;
985 1.1.1.1.4.2 christos }
986 1.1.1.1.4.2 christos if (reread_config)
987 1.1.1.1.4.2 christos {
988 1.1.1.1.4.2 christos //
989 1.1.1.1.4.2 christos // We should re-read the configuration
990 1.1.1.1.4.2 christos // file.
991 1.1.1.1.4.2 christos //
992 1.1.1.1.4.2 christos reread_config = 0; // clear the indicator
993 1.1.1.1.4.2 christos fileconf_read();
994 1.1.1.1.4.2 christos }
995 1.1.1.1.4.2 christos
996 1.1.1.1.4.2 christos //
997 1.1.1.1.4.2 christos // Go back and wait again.
998 1.1.1.1.4.2 christos //
999 1.1.1.1.4.2 christos continue;
1000 1.1.1.1.4.2 christos }
1001 1.1.1.1.4.2 christos else
1002 1.1.1.1.4.2 christos {
1003 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "select failed: %s",
1004 1.1.1.1.4.2 christos strerror(errno));
1005 1.1.1.1.4.2 christos exit(2);
1006 1.1.1.1.4.2 christos }
1007 1.1.1.1.4.2 christos }
1008 1.1.1.1.4.2 christos
1009 1.1.1.1.4.2 christos //
1010 1.1.1.1.4.2 christos // Check each socket.
1011 1.1.1.1.4.2 christos //
1012 1.1.1.1.4.2 christos for (sock_info = listen_socks; sock_info;
1013 1.1.1.1.4.2 christos sock_info = sock_info->next)
1014 1.1.1.1.4.2 christos {
1015 1.1.1.1.4.2 christos if (FD_ISSET(sock_info->sock, &sock_fds))
1016 1.1.1.1.4.2 christos {
1017 1.1.1.1.4.2 christos //
1018 1.1.1.1.4.2 christos // Accept the connection.
1019 1.1.1.1.4.2 christos //
1020 1.1.1.1.4.2 christos accept_connection(sock_info->sock);
1021 1.1.1.1.4.2 christos }
1022 1.1.1.1.4.2 christos }
1023 1.1.1.1.4.2 christos }
1024 1.1.1.1.4.2 christos #endif
1025 1.1.1.1.4.2 christos
1026 1.1.1.1.4.2 christos //
1027 1.1.1.1.4.2 christos // Close all the listen sockets.
1028 1.1.1.1.4.2 christos //
1029 1.1.1.1.4.2 christos for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
1030 1.1.1.1.4.2 christos {
1031 1.1.1.1.4.2 christos closesocket(sock_info->sock);
1032 1.1.1.1.4.2 christos }
1033 1.1.1.1.4.2 christos sock_cleanup();
1034 1.1.1.1.4.2 christos }
1035 1.1.1.1.4.2 christos
1036 1.1.1.1.4.2 christos //
1037 1.1.1.1.4.2 christos // Accept a connection and start a worker thread, on Windows, or a
1038 1.1.1.1.4.2 christos // worker process, on UN*X, to handle the connection.
1039 1.1.1.1.4.2 christos //
1040 1.1.1.1.4.2 christos static void
1041 1.1.1.1.4.2 christos accept_connection(SOCKET listen_sock)
1042 1.1.1.1.4.2 christos {
1043 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
1044 1.1.1.1.4.2 christos SOCKET sockctrl; // keeps the socket ID for this control connection
1045 1.1.1.1.4.2 christos struct sockaddr_storage from; // generic sockaddr_storage variable
1046 1.1.1.1.4.2 christos socklen_t fromlen; // keeps the length of the sockaddr_storage variable
1047 1.1.1.1.4.2 christos
1048 1.1.1.1.4.2 christos #ifdef _WIN32
1049 1.1.1.1.4.2 christos HANDLE threadId; // handle for the subthread
1050 1.1.1.1.4.2 christos u_long off = 0;
1051 1.1.1.1.4.2 christos SOCKET *sockctrl_temp;
1052 1.1.1.1.4.2 christos #else
1053 1.1.1.1.4.2 christos pid_t pid;
1054 1.1.1.1.4.2 christos #endif
1055 1.1.1.1.4.2 christos
1056 1.1.1.1.4.2 christos // Initialize errbuf
1057 1.1.1.1.4.2 christos memset(errbuf, 0, sizeof(errbuf));
1058 1.1.1.1.4.2 christos
1059 1.1.1.1.4.2 christos for (;;)
1060 1.1.1.1.4.2 christos {
1061 1.1.1.1.4.2 christos // Accept the connection
1062 1.1.1.1.4.2 christos fromlen = sizeof(struct sockaddr_storage);
1063 1.1.1.1.4.2 christos
1064 1.1.1.1.4.2 christos sockctrl = accept(listen_sock, (struct sockaddr *) &from, &fromlen);
1065 1.1.1.1.4.2 christos
1066 1.1.1.1.4.2 christos if (sockctrl != INVALID_SOCKET)
1067 1.1.1.1.4.2 christos {
1068 1.1.1.1.4.2 christos // Success.
1069 1.1.1.1.4.2 christos break;
1070 1.1.1.1.4.2 christos }
1071 1.1.1.1.4.2 christos
1072 1.1.1.1.4.2 christos // The accept() call can return this error when a signal is catched
1073 1.1.1.1.4.2 christos // In this case, we have simply to ignore this error code
1074 1.1.1.1.4.2 christos // Stevens, pg 124
1075 1.1.1.1.4.2 christos #ifdef _WIN32
1076 1.1.1.1.4.2 christos if (WSAGetLastError() == WSAEINTR)
1077 1.1.1.1.4.2 christos #else
1078 1.1.1.1.4.2 christos if (errno == EINTR)
1079 1.1.1.1.4.2 christos #endif
1080 1.1.1.1.4.2 christos continue;
1081 1.1.1.1.4.2 christos
1082 1.1.1.1.4.2 christos // Don't check for errors here, since the error can be due to the fact that the thread
1083 1.1.1.1.4.2 christos // has been killed
1084 1.1.1.1.4.2 christos sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
1085 1.1.1.1.4.2 christos rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
1086 1.1.1.1.4.2 christos errbuf);
1087 1.1.1.1.4.2 christos return;
1088 1.1.1.1.4.2 christos }
1089 1.1.1.1.4.2 christos
1090 1.1.1.1.4.2 christos //
1091 1.1.1.1.4.2 christos // We have a connection.
1092 1.1.1.1.4.2 christos // Check whether the connecting host is among the ones allowed.
1093 1.1.1.1.4.2 christos //
1094 1.1.1.1.4.2 christos if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
1095 1.1.1.1.4.2 christos {
1096 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
1097 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1098 1.1.1.1.4.2 christos return;
1099 1.1.1.1.4.2 christos }
1100 1.1.1.1.4.2 christos
1101 1.1.1.1.4.2 christos #ifdef _WIN32
1102 1.1.1.1.4.2 christos //
1103 1.1.1.1.4.2 christos // Put the socket back into blocking mode; doing WSAEventSelect()
1104 1.1.1.1.4.2 christos // on the listen socket makes that socket non-blocking, and it
1105 1.1.1.1.4.2 christos // appears that sockets returned from an accept() on that socket
1106 1.1.1.1.4.2 christos // are also non-blocking.
1107 1.1.1.1.4.2 christos //
1108 1.1.1.1.4.2 christos // First, we have to un-WSAEventSelect() this socket, and then
1109 1.1.1.1.4.2 christos // we can turn non-blocking mode off.
1110 1.1.1.1.4.2 christos //
1111 1.1.1.1.4.2 christos if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
1112 1.1.1.1.4.2 christos {
1113 1.1.1.1.4.2 christos sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
1114 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
1115 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1116 1.1.1.1.4.2 christos return;
1117 1.1.1.1.4.2 christos }
1118 1.1.1.1.4.2 christos if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
1119 1.1.1.1.4.2 christos {
1120 1.1.1.1.4.2 christos sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
1121 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
1122 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1123 1.1.1.1.4.2 christos return;
1124 1.1.1.1.4.2 christos }
1125 1.1.1.1.4.2 christos
1126 1.1.1.1.4.2 christos //
1127 1.1.1.1.4.2 christos // Allocate a location to hold the value of sockctrl.
1128 1.1.1.1.4.2 christos // It will be freed in the newly-created thread once it's
1129 1.1.1.1.4.2 christos // finished with it.
1130 1.1.1.1.4.2 christos // I guess we *could* just cast sockctrl to a void *, but that's
1131 1.1.1.1.4.2 christos // a bit ugly.
1132 1.1.1.1.4.2 christos //
1133 1.1.1.1.4.2 christos sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET));
1134 1.1.1.1.4.2 christos if (sockctrl_temp == NULL)
1135 1.1.1.1.4.2 christos {
1136 1.1.1.1.4.2 christos pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1137 1.1.1.1.4.2 christos errno, "malloc() failed");
1138 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
1139 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1140 1.1.1.1.4.2 christos return;
1141 1.1.1.1.4.2 christos }
1142 1.1.1.1.4.2 christos *sockctrl_temp = sockctrl;
1143 1.1.1.1.4.2 christos
1144 1.1.1.1.4.2 christos threadId = (HANDLE)_beginthreadex(NULL, 0,
1145 1.1.1.1.4.2 christos main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL);
1146 1.1.1.1.4.2 christos if (threadId == 0)
1147 1.1.1.1.4.2 christos {
1148 1.1.1.1.4.2 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread");
1149 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
1150 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1151 1.1.1.1.4.2 christos free(sockctrl_temp);
1152 1.1.1.1.4.2 christos return;
1153 1.1.1.1.4.2 christos }
1154 1.1.1.1.4.2 christos CloseHandle(threadId);
1155 1.1.1.1.4.2 christos #else
1156 1.1.1.1.4.2 christos pid = fork();
1157 1.1.1.1.4.2 christos if (pid == -1)
1158 1.1.1.1.4.2 christos {
1159 1.1.1.1.4.2 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child process");
1160 1.1.1.1.4.2 christos rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
1161 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1162 1.1.1.1.4.2 christos return;
1163 1.1.1.1.4.2 christos }
1164 1.1.1.1.4.2 christos if (pid == 0)
1165 1.1.1.1.4.2 christos {
1166 1.1.1.1.4.2 christos //
1167 1.1.1.1.4.2 christos // Child process.
1168 1.1.1.1.4.2 christos //
1169 1.1.1.1.4.2 christos // Close the socket on which we're listening (must
1170 1.1.1.1.4.2 christos // be open only in the parent).
1171 1.1.1.1.4.2 christos //
1172 1.1.1.1.4.2 christos closesocket(listen_sock);
1173 1.1.1.1.4.2 christos
1174 1.1.1.1.4.2 christos #if 0
1175 1.1.1.1.4.2 christos //
1176 1.1.1.1.4.2 christos // Modify thread params so that it can be killed at any time
1177 1.1.1.1.4.2 christos // XXX - is this necessary? This is the main and, currently,
1178 1.1.1.1.4.2 christos // only thread in the child process, and nobody tries to
1179 1.1.1.1.4.2 christos // cancel us, although *we* may cancel the thread that's
1180 1.1.1.1.4.2 christos // handling the capture loop.
1181 1.1.1.1.4.2 christos //
1182 1.1.1.1.4.2 christos if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
1183 1.1.1.1.4.2 christos goto end;
1184 1.1.1.1.4.2 christos if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
1185 1.1.1.1.4.2 christos goto end;
1186 1.1.1.1.4.2 christos #endif
1187 1.1.1.1.4.2 christos
1188 1.1.1.1.4.2 christos //
1189 1.1.1.1.4.2 christos // Run the service loop.
1190 1.1.1.1.4.2 christos // This is passive mode, so we don't care whether we were
1191 1.1.1.1.4.2 christos // told by the client to close.
1192 1.1.1.1.4.2 christos //
1193 1.1.1.1.4.2 christos (void)daemon_serviceloop(sockctrl, sockctrl, 0,
1194 1.1.1.1.4.2 christos nullAuthAllowed);
1195 1.1.1.1.4.2 christos
1196 1.1.1.1.4.2 christos close(sockctrl);
1197 1.1.1.1.4.2 christos
1198 1.1.1.1.4.2 christos exit(0);
1199 1.1.1.1.4.2 christos }
1200 1.1.1.1.4.2 christos
1201 1.1.1.1.4.2 christos // I am the parent
1202 1.1.1.1.4.2 christos // Close the socket for this session (must be open only in the child)
1203 1.1.1.1.4.2 christos closesocket(sockctrl);
1204 1.1.1.1.4.2 christos #endif
1205 1.1.1.1.4.2 christos }
1206 1.1.1.1.4.2 christos
1207 1.1.1.1.4.2 christos /*!
1208 1.1.1.1.4.2 christos \brief 'true' main of the program in case the active mode is turned on.
1209 1.1.1.1.4.2 christos
1210 1.1.1.1.4.2 christos This function loops forever trying to connect to the remote host, until the
1211 1.1.1.1.4.2 christos daemon is turned down.
1212 1.1.1.1.4.2 christos
1213 1.1.1.1.4.2 christos \param ptr: it keeps the 'activepars' parameters. It is a 'void *'
1214 1.1.1.1.4.2 christos just because the thread APIs want this format.
1215 1.1.1.1.4.2 christos */
1216 1.1.1.1.4.2 christos #ifdef _WIN32
1217 1.1.1.1.4.2 christos static unsigned __stdcall
1218 1.1.1.1.4.2 christos #else
1219 1.1.1.1.4.2 christos static void *
1220 1.1.1.1.4.2 christos #endif
1221 1.1.1.1.4.2 christos main_active(void *ptr)
1222 1.1.1.1.4.2 christos {
1223 1.1.1.1.4.2 christos char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
1224 1.1.1.1.4.2 christos SOCKET sockctrl; // keeps the socket ID for this control connection
1225 1.1.1.1.4.2 christos struct addrinfo hints; // temporary struct to keep settings needed to open the new socket
1226 1.1.1.1.4.2 christos struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
1227 1.1.1.1.4.2 christos struct active_pars *activepars;
1228 1.1.1.1.4.2 christos
1229 1.1.1.1.4.2 christos activepars = (struct active_pars *) ptr;
1230 1.1.1.1.4.2 christos
1231 1.1.1.1.4.2 christos // Prepare to open a new server socket
1232 1.1.1.1.4.2 christos memset(&hints, 0, sizeof(struct addrinfo));
1233 1.1.1.1.4.2 christos // WARNING Currently it supports only ONE socket family among IPv4 and IPv6
1234 1.1.1.1.4.2 christos hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server
1235 1.1.1.1.4.2 christos hints.ai_socktype = SOCK_STREAM;
1236 1.1.1.1.4.2 christos hints.ai_family = activepars->ai_family;
1237 1.1.1.1.4.2 christos
1238 1.1.1.1.4.2 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
1239 1.1.1.1.4.2 christos activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
1240 1.1.1.1.4.2 christos (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
1241 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
1242 1.1.1.1.4.2 christos
1243 1.1.1.1.4.2 christos // Initialize errbuf
1244 1.1.1.1.4.2 christos memset(errbuf, 0, sizeof(errbuf));
1245 1.1.1.1.4.2 christos
1246 1.1.1.1.4.2 christos // Do the work
1247 1.1.1.1.4.2 christos if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
1248 1.1.1.1.4.2 christos {
1249 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
1250 1.1.1.1.4.2 christos return 0;
1251 1.1.1.1.4.2 christos }
1252 1.1.1.1.4.2 christos
1253 1.1.1.1.4.2 christos for (;;)
1254 1.1.1.1.4.2 christos {
1255 1.1.1.1.4.2 christos int activeclose;
1256 1.1.1.1.4.2 christos
1257 1.1.1.1.4.2 christos if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
1258 1.1.1.1.4.2 christos {
1259 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
1260 1.1.1.1.4.2 christos
1261 1.1.1.1.4.2 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
1262 1.1.1.1.4.2 christos activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
1263 1.1.1.1.4.2 christos (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
1264 1.1.1.1.4.2 christos
1265 1.1.1.1.4.2 christos SOCK_DEBUG_MESSAGE(errbuf);
1266 1.1.1.1.4.2 christos
1267 1.1.1.1.4.2 christos sleep_secs(RPCAP_ACTIVE_WAIT);
1268 1.1.1.1.4.2 christos
1269 1.1.1.1.4.2 christos continue;
1270 1.1.1.1.4.2 christos }
1271 1.1.1.1.4.2 christos
1272 1.1.1.1.4.2 christos activeclose = daemon_serviceloop(sockctrl, sockctrl, 1,
1273 1.1.1.1.4.2 christos nullAuthAllowed);
1274 1.1.1.1.4.2 christos
1275 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1276 1.1.1.1.4.2 christos
1277 1.1.1.1.4.2 christos // If the connection is closed by the user explicitely, don't try to connect to it again
1278 1.1.1.1.4.2 christos // just exit the program
1279 1.1.1.1.4.2 christos if (activeclose == 1)
1280 1.1.1.1.4.2 christos break;
1281 1.1.1.1.4.2 christos }
1282 1.1.1.1.4.2 christos
1283 1.1.1.1.4.2 christos freeaddrinfo(addrinfo);
1284 1.1.1.1.4.2 christos return 0;
1285 1.1.1.1.4.2 christos }
1286 1.1.1.1.4.2 christos
1287 1.1.1.1.4.2 christos #ifdef _WIN32
1288 1.1.1.1.4.2 christos //
1289 1.1.1.1.4.2 christos // Main routine of a passive-mode service thread.
1290 1.1.1.1.4.2 christos //
1291 1.1.1.1.4.2 christos unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
1292 1.1.1.1.4.2 christos {
1293 1.1.1.1.4.2 christos SOCKET sockctrl;
1294 1.1.1.1.4.2 christos
1295 1.1.1.1.4.2 christos sockctrl = *((SOCKET *)ptr);
1296 1.1.1.1.4.2 christos free(ptr);
1297 1.1.1.1.4.2 christos
1298 1.1.1.1.4.2 christos //
1299 1.1.1.1.4.2 christos // Handle this client.
1300 1.1.1.1.4.2 christos // This is passive mode, so we don't care whether we were
1301 1.1.1.1.4.2 christos // told by the client to close.
1302 1.1.1.1.4.2 christos //
1303 1.1.1.1.4.2 christos (void)daemon_serviceloop(sockctrl, sockctrl, 0, nullAuthAllowed);
1304 1.1.1.1.4.2 christos
1305 1.1.1.1.4.2 christos sock_close(sockctrl, NULL, 0);
1306 1.1.1.1.4.2 christos
1307 1.1.1.1.4.2 christos return 0;
1308 1.1.1.1.4.2 christos }
1309 1.1.1.1.4.2 christos #endif
1310