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