diff options
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | org.tcpdump.rpcapd.plist | 30 | ||||
-rw-r--r-- | rpcapd/config_params.h | 56 | ||||
-rwxr-xr-x | rpcapd/daemon.c | 292 | ||||
-rwxr-xr-x | rpcapd/daemon.h | 22 | ||||
-rwxr-xr-x | rpcapd/fileconf.c | 1 | ||||
-rwxr-xr-x | rpcapd/rpcapd.c | 244 | ||||
-rwxr-xr-x | rpcapd/rpcapd.h | 16 |
8 files changed, 419 insertions, 244 deletions
diff --git a/Makefile.in b/Makefile.in index 0659a584..84f70530 100644 --- a/Makefile.in +++ b/Makefile.in @@ -303,6 +303,7 @@ EXTRA_DIST = \ msdos/readme.dos \ nomkdep \ org.tcpdump.chmod_bpf.plist \ + org.tcpdump.rpcapd.plist \ pcap-bpf.c \ pcap-bt-linux.c \ pcap-bt-linux.h \ @@ -351,6 +352,7 @@ EXTRA_DIST = \ rpcap-protocol.c \ rpcapd/CMakeLists.txt \ rpcapd/Makefile.in \ + rpcapd/config_params.h \ rpcapd/daemon.h \ rpcapd/daemon.c \ rpcapd/fileconf.c \ diff --git a/org.tcpdump.rpcapd.plist b/org.tcpdump.rpcapd.plist new file mode 100644 index 00000000..db3223a7 --- /dev/null +++ b/org.tcpdump.rpcapd.plist @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Disabled</key> + <false/> + <key>Label</key> + <string>com.tcpdump.rpcapd</string> + <key>Program</key> + <string>/usr/local/libexec/rpcapd</string> + <key>ProgramArguments</key> + <array> + <string>/usr/local/libexec/rpcapd</string> + <string>-i</string> + </array> + <key>Sockets</key> + <dict> + <key>Listeners</key> + <dict> + <key>SockServiceName</key> + <string>2002</string> + </dict> + </dict> + <key>inetdCompatibility</key> + <dict> + <key>Wait</key> + <false/> + </dict> +</dict> +</plist> diff --git a/rpcapd/config_params.h b/rpcapd/config_params.h new file mode 100644 index 00000000..c219ce16 --- /dev/null +++ b/rpcapd/config_params.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002 - 2003 + * NetGroup, Politecnico di Torino (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __CONFIG_PARAMS_H__ +#define __CONFIG_PARAMS_H__ + +// +// Parameters set from the configuration file. +// + +#define MAX_LINE 2048 /* Maximum chars allowed for the host list (in passive mode) */ +#define MAX_HOST_LIST 64000 +#define MAX_ACTIVE_LIST 10 + +struct active_pars +{ + char address[MAX_LINE + 1]; // keeps the network address (either numeric or literal) to of the active client + char port[MAX_LINE + 1]; // keeps the network port to bind to + int ai_family; // address faimly to use +}; + +extern char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server +extern struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode) +extern int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise +extern char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration + +#endif diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c index bbe4dd1a..a0acd4af 100755 --- a/rpcapd/daemon.c +++ b/rpcapd/daemon.c @@ -66,11 +66,21 @@ #define RPCAP_TIMEOUT_RUNTIME 180 /* Run-time timeout for RPCAP connections (default: 3 min) */ #define RPCAP_SUSPEND_WRONGAUTH 1 /* If the authentication is wrong, stops 1 sec before accepting a new auth message */ +// Parameters for the service loop. +struct daemon_slpars +{ + SOCKET sockctrl_in; //!< SOCKET ID of the input side of the control connection + SOCKET sockctrl_out; //!< SOCKET ID of the output side of the control connection + uint8 protocol_version; //!< negotiated protocol version + int isactive; //!< Not null if the daemon has to run in active mode + int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise +}; + /* * Data for a session managed by a thread. */ struct session { - SOCKET sockctrl; + SOCKET sockctrl_out; SOCKET sockdata; uint8 protocol_version; pcap_t *fp; @@ -78,8 +88,8 @@ struct session { }; // Locally defined functions -static int daemon_msg_err(SOCKET sockctrl, uint32 plen); -static int daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed); +static int daemon_msg_err(SOCKET sockctrl_in, uint32 plen); +static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen); static int daemon_AuthUserPwd(char *username, char *password, char *errbuf); static int daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen); @@ -94,7 +104,7 @@ static int daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *ses #endif static int daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen); -static int daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errbuf); +static int daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errbuf); static int daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt); @@ -111,24 +121,10 @@ static int rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp); static int rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf); static int rpcapd_discard(SOCKET sock, uint32 len); -/*! - \brief Main serving function - This function is the one which does the job. It is the main() of the child - thread, which is created as soon as a new connection is accepted. - - \param ptr: a void pointer that keeps the reference of the 'pthread_chain' - value corresponding to this thread. This variable is casted into a 'pthread_chain' - value in order to retrieve the socket we're currently using, the thread ID, and - some pointers to the previous and next elements into this struct. - - \return None. -*/ -#ifdef _WIN32 -unsigned __stdcall daemon_serviceloop(void *ptr) -#else -void *daemon_serviceloop(void *ptr) -#endif +int +daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nullAuthAllowed) { + struct daemon_slpars pars; // service loop parameters char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed char errmsgbuf[PCAP_ERRBUF_SIZE + 1]; // buffer for errors to send to the client int nrecv; @@ -138,8 +134,8 @@ void *daemon_serviceloop(void *ptr) char source[PCAP_BUF_SIZE+1]; // keeps the string that contains the interface to open int got_source = 0; // 1 if we've gotten the source from an open request struct session *session = NULL; // struct session main variable - struct daemon_slpars *pars; // parameters related to the present daemon loop const char *msg_type_string; // string for message type + int client_told_us_to_close = 0; // 1 if the client told us to close the capture int have_thread = 0; // 1 if threaddata refers to a thread we've created #ifdef _WIN32 @@ -159,22 +155,15 @@ void *daemon_serviceloop(void *ptr) struct timeval tv; // maximum time the select() can block waiting for data int retval; // select() return value - pars = (struct daemon_slpars *) ptr; + // Set parameters structure + pars.sockctrl_in = sockctrl_in; + pars.sockctrl_out = sockctrl_out; + pars.protocol_version = 0; // not yet known + pars.isactive = isactive; // active mode + pars.nullAuthAllowed = nullAuthAllowed; *errbuf = 0; // Initialize errbuf -#ifndef _WIN32 - // If we're in active mode, this is not a separate thread - if (! pars->isactive) - { - // Modify thread params so that it can be killed at any time - if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) - goto end; - if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) - goto end; - } -#endif - // // The client must first authenticate; loop until they send us a // message with a version we support and credentials we accept, @@ -189,20 +178,20 @@ void *daemon_serviceloop(void *ptr) // // XXX - do this on *every* trip through the loop? // - if (!pars->isactive) + if (!pars.isactive) { FD_ZERO(&rfds); // We do not have to block here tv.tv_sec = RPCAP_TIMEOUT_INIT; tv.tv_usec = 0; - FD_SET(pars->sockctrl, &rfds); + FD_SET(pars.sockctrl_in, &rfds); - retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv); + retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE); - if (rpcap_senderror(pars->sockctrl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1) + if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1) rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } @@ -211,7 +200,7 @@ void *daemon_serviceloop(void *ptr) // So, this was a fake connection. Drop it down if (retval == 0) { - if (rpcap_senderror(pars->sockctrl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1) + if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1) rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } @@ -220,7 +209,7 @@ void *daemon_serviceloop(void *ptr) // // Read the message header from the client. // - nrecv = rpcapd_recv_msg_header(pars->sockctrl, &header); + nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header); if (nrecv == -1) { // Fatal error. @@ -276,7 +265,7 @@ void *daemon_serviceloop(void *ptr) // reply_version = RPCAP_MAX_VERSION; } - if (rpcap_senderror(pars->sockctrl, reply_version, + if (rpcap_senderror(pars.sockctrl_out, reply_version, PCAP_ERR_WRONGVER, "RPCAP version number mismatch", errbuf) == -1) { @@ -286,7 +275,7 @@ void *daemon_serviceloop(void *ptr) } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Network error. goto end; @@ -299,12 +288,12 @@ void *daemon_serviceloop(void *ptr) // // OK, we use the version the client specified. // - pars->protocol_version = header.ver; + pars.protocol_version = header.ver; switch (header.type) { case RPCAP_MSG_AUTH_REQ: - retval = daemon_msg_auth_req(pars->sockctrl, pars->protocol_version, plen, pars->nullAuthAllowed); + retval = daemon_msg_auth_req(&pars, plen); if (retval == -1) { // Fatal error; a message has @@ -330,7 +319,7 @@ void *daemon_serviceloop(void *ptr) // Discard the rest of the message, if // there is anything more. // - (void)rpcapd_discard(pars->sockctrl, plen); + (void)rpcapd_discard(pars.sockctrl_in, plen); // We're done with this client. goto end; @@ -342,7 +331,7 @@ void *daemon_serviceloop(void *ptr) // an error message rather than a "let // me log in" message, indicating that // we're not allowed to connect to them? - (void)daemon_msg_err(pars->sockctrl, plen); + (void)daemon_msg_err(pars.sockctrl_in, plen); goto end; case RPCAP_MSG_FINDALLIF_REQ: @@ -365,15 +354,15 @@ void *daemon_serviceloop(void *ptr) { pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type); } - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_WRONGMSG, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Network error. goto end; @@ -401,15 +390,15 @@ void *daemon_serviceloop(void *ptr) { pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type); } - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_WRONGMSG, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Fatal error. goto end; @@ -421,15 +410,15 @@ void *daemon_serviceloop(void *ptr) // Unknown message type. // pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type); - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_WRONGMSG, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Fatal error. goto end; @@ -467,7 +456,7 @@ void *daemon_serviceloop(void *ptr) // // Be carefully: the capture can have been started, but an error occurred (so session != NULL, but // sockdata is 0 - if ((!pars->isactive) && ((session == NULL) || ((session != NULL) && (session->sockdata == 0)))) + if ((!pars.isactive) && ((session == NULL) || ((session != NULL) && (session->sockdata == 0)))) { // Check for the initial timeout FD_ZERO(&rfds); @@ -475,14 +464,14 @@ void *daemon_serviceloop(void *ptr) tv.tv_sec = RPCAP_TIMEOUT_RUNTIME; tv.tv_usec = 0; - FD_SET(pars->sockctrl, &rfds); + FD_SET(pars.sockctrl_in, &rfds); - retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv); + retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE); - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_NETW, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1) rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; @@ -492,8 +481,8 @@ void *daemon_serviceloop(void *ptr) // So, this was a fake connection. Drop it down if (retval == 0) { - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1) @@ -505,7 +494,7 @@ void *daemon_serviceloop(void *ptr) // // Read the message header from the client. // - nrecv = rpcapd_recv_msg_header(pars->sockctrl, &header); + nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header); if (nrecv == -1) { // Fatal error. @@ -524,7 +513,7 @@ void *daemon_serviceloop(void *ptr) // // For now, there's only one version. // - if (header.ver != pars->protocol_version) + if (header.ver != pars.protocol_version) { // // Tell them it's not the negotiated version. @@ -532,7 +521,7 @@ void *daemon_serviceloop(void *ptr) // so they don't reject it as having the wrong // version. // - if (rpcap_senderror(pars->sockctrl, + if (rpcap_senderror(pars.sockctrl_out, header.ver, PCAP_ERR_WRONGVER, "RPCAP version in message isn't the negotiated version", errbuf) == -1) @@ -543,7 +532,7 @@ void *daemon_serviceloop(void *ptr) } // Discard the rest of the message. - (void)rpcapd_discard(pars->sockctrl, plen); + (void)rpcapd_discard(pars.sockctrl_in, plen); // Give up on them. goto end; } @@ -552,7 +541,7 @@ void *daemon_serviceloop(void *ptr) { case RPCAP_MSG_ERROR: // The other endpoint reported an error { - (void)daemon_msg_err(pars->sockctrl, plen); + (void)daemon_msg_err(pars.sockctrl_in, plen); // Do nothing; just exit; the error code is already into the errbuf // XXX - actually exit.... break; @@ -560,7 +549,7 @@ void *daemon_serviceloop(void *ptr) case RPCAP_MSG_FINDALLIF_REQ: { - if (daemon_msg_findallif_req(pars, plen) == -1) + if (daemon_msg_findallif_req(&pars, plen) == -1) { // Fatal error; a message has // been logged, so just give up. @@ -580,7 +569,7 @@ void *daemon_serviceloop(void *ptr) // us multiple open requests, the last // one wins. // - retval = daemon_msg_open_req(pars, plen, source, sizeof(source)); + retval = daemon_msg_open_req(&pars, plen, source, sizeof(source)); if (retval == -1) { // Fatal error; a message has @@ -597,8 +586,8 @@ void *daemon_serviceloop(void *ptr) { // They never told us what device // to capture on! - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_STARTCAPTURE, "No capture device was specified", errbuf) == -1) @@ -608,14 +597,14 @@ void *daemon_serviceloop(void *ptr) rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { goto end; } break; } - if (daemon_msg_startcap_req(pars, plen, &have_thread, &threaddata, source, &session, &samp_param) == -1) + if (daemon_msg_startcap_req(&pars, plen, &have_thread, &threaddata, source, &session, &samp_param) == -1) { // Fatal error; a message has // been logged, so just give up. @@ -628,7 +617,7 @@ void *daemon_serviceloop(void *ptr) { if (session) { - if (daemon_msg_updatefilter_req(pars, session, plen) == -1) + if (daemon_msg_updatefilter_req(&pars, session, plen) == -1) { // Fatal error; a message has // been logged, so just give up. @@ -637,8 +626,8 @@ void *daemon_serviceloop(void *ptr) } else { - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_UPDATEFILTER, "Device not opened. Cannot update filter", errbuf) == -1) @@ -653,16 +642,19 @@ void *daemon_serviceloop(void *ptr) case RPCAP_MSG_CLOSE: // The other endpoint close the pcap session { - // signal to the main that the user closed the control connection - // This is used only in case of active mode - pars->activeclose = 1; + // + // Indicate to our caller that the client + // closed the control connection. + // This is used only in case of active mode. + // + client_told_us_to_close = 1; SOCK_MESSAGE("The other end system asked to close the connection."); goto end; } case RPCAP_MSG_STATS_REQ: { - if (daemon_msg_stats_req(pars, session, plen, &stats, svrcapt) == -1) + if (daemon_msg_stats_req(&pars, session, plen, &stats, svrcapt) == -1) { // Fatal error; a message has // been logged, so just give up. @@ -688,7 +680,7 @@ void *daemon_serviceloop(void *ptr) svrcapt = 0; } - if (daemon_msg_endcap_req(pars, session, &have_thread, threaddata) == -1) + if (daemon_msg_endcap_req(&pars, session, &have_thread, threaddata) == -1) { free(session); session = NULL; @@ -701,8 +693,8 @@ void *daemon_serviceloop(void *ptr) } else { - rpcap_senderror(pars->sockctrl, - pars->protocol_version, + rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_ENDCAPTURE, "Device not opened. Cannot close the capture", errbuf); @@ -712,7 +704,7 @@ void *daemon_serviceloop(void *ptr) case RPCAP_MSG_SETSAMPLING_REQ: { - if (daemon_msg_setsampling_req(pars, plen, &samp_param) == -1) + if (daemon_msg_setsampling_req(&pars, plen, &samp_param) == -1) { // Fatal error; a message has // been logged, so just give up. @@ -728,8 +720,8 @@ void *daemon_serviceloop(void *ptr) // get to reauthenticate. // rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed"); - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, "RPCAP_MSG_AUTH_REQ request sent after authentication was completed", errbuf) == -1) @@ -738,7 +730,7 @@ void *daemon_serviceloop(void *ptr) goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Fatal error. goto end; @@ -768,15 +760,15 @@ void *daemon_serviceloop(void *ptr) rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type); pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type); } - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_WRONGMSG, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Fatal error. goto end; @@ -789,15 +781,15 @@ void *daemon_serviceloop(void *ptr) // rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type); pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type); - if (rpcap_senderror(pars->sockctrl, - pars->protocol_version, PCAP_ERR_WRONGMSG, + if (rpcap_senderror(pars.sockctrl_out, + pars.protocol_version, PCAP_ERR_WRONGMSG, errbuf, errmsgbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); goto end; } // Discard the rest of the message. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars.sockctrl_in, plen) == -1) { // Fatal error. goto end; @@ -857,25 +849,18 @@ end: session = NULL; } - // Print message and exit + // Print message and return SOCK_MESSAGE("I'm exiting from the child loop"); SOCK_MESSAGE(errbuf); - if (!pars->isactive) - { - if (pars->sockctrl) - sock_close(pars->sockctrl, NULL, 0); - - free(pars); - } - return 0; + return client_told_us_to_close; } /* * This handles the RPCAP_MSG_ERR message. */ static int -daemon_msg_err(SOCKET sockctrl, uint32 plen) +daemon_msg_err(SOCKET sockctrl_in, uint32 plen) { char errbuf[PCAP_ERRBUF_SIZE]; char remote_errbuf[PCAP_ERRBUF_SIZE]; @@ -886,7 +871,7 @@ daemon_msg_err(SOCKET sockctrl, uint32 plen) * Message is too long; just read as much of it as we * can into the buffer provided, and discard the rest. */ - if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1, + if (sock_recv(sockctrl_in, remote_errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE) == -1) { @@ -894,7 +879,7 @@ daemon_msg_err(SOCKET sockctrl, uint32 plen) rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf); return -1; } - if (rpcapd_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1) + if (rpcapd_discard(sockctrl_in, plen - (PCAP_ERRBUF_SIZE - 1)) == -1) { // Network error. return -1; @@ -912,7 +897,7 @@ daemon_msg_err(SOCKET sockctrl, uint32 plen) } else { - if (sock_recv(sockctrl, remote_errbuf, plen, + if (sock_recv(sockctrl_in, remote_errbuf, plen, SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE) == -1) { @@ -954,7 +939,7 @@ daemon_msg_err(SOCKET sockctrl, uint32 plen) * unrecoverable error or for the authentication failure. */ static int -daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed) +daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen) { char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client @@ -962,7 +947,7 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed int status; struct rpcap_auth auth; // RPCAP authentication header - status = rpcapd_recv(sockctrl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf); + status = rpcapd_recv(pars->sockctrl_in, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf); if (status == -1) { return -1; @@ -976,7 +961,7 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed { case RPCAP_RMTAUTH_NULL: { - if (!nullAuthAllowed) + if (!pars->nullAuthAllowed) { // Send the client an error reply. pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Authentication failed; NULL authentication not permitted."); @@ -998,7 +983,7 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed PCAP_ERRBUF_SIZE, errno, "malloc() failed"); goto error; } - status = rpcapd_recv(sockctrl, username, usernamelen, &plen, errmsgbuf); + status = rpcapd_recv(pars->sockctrl_in, username, usernamelen, &plen, errmsgbuf); if (status == -1) { free(username); @@ -1020,7 +1005,7 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed free(username); goto error; } - status = rpcapd_recv(sockctrl, passwd, passwdlen, &plen, errmsgbuf); + status = rpcapd_recv(pars->sockctrl_in, passwd, passwdlen, &plen, errmsgbuf); if (status == -1) { free(username); @@ -1043,7 +1028,8 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed // free(username); free(passwd); - if (rpcap_senderror(sockctrl, ver, + if (rpcap_senderror(pars->sockctrl_out, + pars->protocol_version, PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1) { // That failed; log a message and give up. @@ -1076,10 +1062,10 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed } // The authentication succeeded; let the client know. - rpcap_createhdr(&header, ver, RPCAP_MSG_AUTH_REPLY, 0, 0); + rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_AUTH_REPLY, 0, 0); // Send the ok message back - if (sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) { // That failed; log a messsage and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -1087,7 +1073,7 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed } // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } @@ -1095,8 +1081,8 @@ daemon_msg_auth_req(SOCKET sockctrl, uint8 ver, uint32 plen, int nullAuthAllowed return 0; error: - if (rpcap_senderror(sockctrl, ver, PCAP_ERR_AUTH, errmsgbuf, - errbuf) == -1) + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, + PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1) { // That failed; log a message and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -1105,7 +1091,7 @@ error: error_noreply: // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } @@ -1250,7 +1236,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen) uint16 nif = 0; // counts the number of interface listed // Discard the rest of the message; there shouldn't be any payload. - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { // Network error. return -1; @@ -1262,7 +1248,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen) if (alldevs == NULL) { - if (rpcap_senderror(pars->sockctrl, pars->protocol_version, + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_NOREMOTEIF, "No interfaces found! Make sure libpcap/WinPcap is properly installed" " and you have the right to access to the remote device.", @@ -1416,7 +1402,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen) pcap_freealldevs(alldevs); // Send a final command that says "now send it!" - if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); return -1; @@ -1428,7 +1414,7 @@ error: if (alldevs) pcap_freealldevs(alldevs); - if (rpcap_senderror(pars->sockctrl, pars->protocol_version, + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -1458,7 +1444,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_ goto error; } - nread = sock_recv(pars->sockctrl, source, plen, + nread = sock_recv(pars->sockctrl_in, source, plen, SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE); if (nread == -1) { @@ -1502,7 +1488,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_ pcap_close(fp); // Send the reply. - if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); return -1; @@ -1510,7 +1496,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_ return 0; error: - if (rpcap_senderror(pars->sockctrl, pars->protocol_version, + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_OPEN, errmsgbuf, errbuf) == -1) { // That failed; log a message and give up. @@ -1519,7 +1505,7 @@ error: } // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } @@ -1566,7 +1552,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, int *have_threa addrinfo = NULL; - status = rpcapd_recv(pars->sockctrl, (char *) &startcapreq, + status = rpcapd_recv(pars->sockctrl_in, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), &plen, errmsgbuf); if (status == -1) { @@ -1618,7 +1604,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, int *have_threa we want to connect to */ saddrlen = sizeof(struct sockaddr_storage); - if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) + if (getpeername(pars->sockctrl_in, (struct sockaddr *) &saddr, &saddrlen) == -1) { sock_geterror("getpeername(): ", errmsgbuf, PCAP_ERRBUF_SIZE); goto error; @@ -1680,11 +1666,11 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, int *have_threa addrinfo = NULL; // Needed to send an error on the ctrl connection - session->sockctrl = pars->sockctrl; + session->sockctrl_out = pars->sockctrl_out; session->protocol_version = pars->protocol_version; // Now I can set the filter - ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf); + ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf); if (ret == -1) { // Fatal error. A message has been logged; just give up. @@ -1719,7 +1705,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, int *have_threa startcapreply->portdata = htons(port); } - if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) { // That failed; log a message and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -1778,7 +1764,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, int *have_threa *have_thread = 1; // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) goto fatal_error; *sessionp = session; @@ -1819,7 +1805,7 @@ error: free(session); } - if (rpcap_senderror(pars->sockctrl, pars->protocol_version, + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1) { // That failed; log a message and give up. @@ -1828,7 +1814,7 @@ error: } // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { // Network error. return -1; @@ -1949,7 +1935,7 @@ daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, int * rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_ENDCAP_REPLY, 0, 0); - if (sock_send(pars->sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) { // That failed; log a message and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -1960,7 +1946,7 @@ daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, int * } static int -daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errmsgbuf) +daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errmsgbuf) { int status; struct rpcap_filter filter; @@ -1969,7 +1955,7 @@ daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp struct bpf_program bf_prog; unsigned int i; - status = rpcapd_recv(sockctrl, (char *) &filter, + status = rpcapd_recv(sockctrl_in, (char *) &filter, sizeof(struct rpcap_filter), plenp, errmsgbuf); if (status == -1) { @@ -2000,7 +1986,7 @@ daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp for (i = 0; i < bf_prog.bf_len; i++) { - status = rpcapd_recv(sockctrl, (char *) &insn, + status = rpcapd_recv(sockctrl_in, (char *) &insn, sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf); if (status == -1) { @@ -2042,7 +2028,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, int ret; // status of daemon_unpackapplyfilter() struct rpcap_header header; // keeps the answer to the updatefilter command - ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf); + ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf); if (ret == -1) { // Fatal error. A message has been logged; just give up. @@ -2055,7 +2041,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, } // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { // Network error. return -1; @@ -2065,7 +2051,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0); - if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE)) + if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE)) { // That failed; log a messsage and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -2075,11 +2061,11 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, return 0; error: - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } - rpcap_senderror(pars->sockctrl, pars->protocol_version, + rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_UPDATEFILTER, errmsgbuf, NULL); return 0; @@ -2097,7 +2083,7 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap struct rpcap_sampling rpcap_samp; int status; - status = rpcapd_recv(pars->sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf); + status = rpcapd_recv(pars->sockctrl_in, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf); if (status == -1) { return -1; @@ -2115,14 +2101,14 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0); - if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) { // That failed; log a messsage and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); return -1; } - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } @@ -2130,7 +2116,7 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap return 0; error: - if (rpcap_senderror(pars->sockctrl, pars->protocol_version, + if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1) { // That failed; log a message and give up. @@ -2139,7 +2125,7 @@ error: } // Check if all the data has been read; if not, discard the data in excess - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { return -1; } @@ -2157,7 +2143,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 struct rpcap_stats *netstats; // statistics sent on the network // Checks that the header does not contain other data; if so, discard it - if (rpcapd_discard(pars->sockctrl, plen) == -1) + if (rpcapd_discard(pars->sockctrl_in, plen) == -1) { // Network error. return -1; @@ -2201,7 +2187,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 } // Send the packet - if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) + if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) { rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); return -1; @@ -2210,7 +2196,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 return 0; error: - rpcap_senderror(pars->sockctrl, pars->protocol_version, + rpcap_senderror(pars->sockctrl_out, pars->protocol_version, PCAP_ERR_GETSTATS, errmsgbuf, NULL); return 0; } @@ -2356,7 +2342,7 @@ daemon_thrdatamain(void *ptr) if (retval == -1) { pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp)); - rpcap_senderror(session->sockctrl, session->protocol_version, + rpcap_senderror(session->sockctrl_out, session->protocol_version, PCAP_ERR_READEX, errbuf, NULL); goto error; } diff --git a/rpcapd/daemon.h b/rpcapd/daemon.h index ffbd2bce..bd240b80 100755 --- a/rpcapd/daemon.h +++ b/rpcapd/daemon.h @@ -33,22 +33,12 @@ #ifndef __DAEMON_H__ #define __DAEMON_H__ -//! Structure that keeps the parameters needed by the daemon_serviceloop() -// function -struct daemon_slpars -{ - SOCKET sockctrl; //!< SOCKET ID of the control connection - uint8 protocol_version; //!< negotiated protocol version - int isactive; //!< Not null if the daemon has to run in active mode - int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise - int activeclose; //!< '1' if the client closed the control connection explicitely; used in active mode only -}; - -#ifdef _WIN32 -unsigned __stdcall daemon_serviceloop(void *ptr); -#else -void *daemon_serviceloop(void *ptr); -#endif +// +// Returns 1 if the client closed the control connection explicitly, 0 +// otherwise; used in active mode only. +// +int daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, + int nullAuthAllowed); void sleep_secs(int secs); diff --git a/rpcapd/fileconf.c b/rpcapd/fileconf.c index 46b6dceb..099cdf37 100755 --- a/rpcapd/fileconf.c +++ b/rpcapd/fileconf.c @@ -45,6 +45,7 @@ #include "sockutils.h" // for SOCK_MESSAGE #include "portability.h" #include "rpcapd.h" +#include "config_params.h" // configuration file parameters #include "fileconf.h" #include "rpcap-protocol.h" diff --git a/rpcapd/rpcapd.c b/rpcapd/rpcapd.c index 2a148c4a..7ea0ba90 100755 --- a/rpcapd/rpcapd.c +++ b/rpcapd/rpcapd.c @@ -46,6 +46,7 @@ #include "sockutils.h" // for socket calls #include "portability.h" #include "rpcapd.h" +#include "config_params.h" // configuration file parameters #include "fileconf.h" // for the configuration file management #include "rpcap-protocol.h" #include "daemon.h" // the true main() method of this daemon @@ -56,6 +57,7 @@ #include "win32-svc.h" // for Win32 service stuff #include "getopt.h" // for getopt()-for-Windows #else + #include <fcntl.h> // for open() #include <unistd.h> // for exit() #include <sys/wait.h> // waitpid() #endif @@ -100,6 +102,9 @@ static void accept_connection(SOCKET listen_sock); #ifndef _WIN32 static void main_reap_children(int sign); #endif +#ifdef _WIN32 +static unsigned __stdcall main_passive_serviceloop_thread(void *ptr); +#endif #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */ @@ -111,7 +116,11 @@ static void printusage(void) char *usagetext = "USAGE:" " " PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n" - " [-n] [-v] [-d] [-s <file>] [-f <file>]\n\n" + " [-n] [-v] [-d] " +#ifndef _WIN32 + "[-i] " +#endif + "[-s <file>] [-f <file>]\n\n" " -b <address> the address to bind to (either numeric or literal).\n" " Default: binds to all local IPv4 and IPv6 addresses\n\n" " -p <port> the port to bind to.\n" @@ -119,17 +128,21 @@ static void printusage(void) " -4 use only IPv4.\n" " Default: use both IPv4 and IPv6 waiting sockets\n\n" " -l <host_list> a file that contains a list of hosts that are allowed\n" - " to connect to this server (if more than one, list them one per line).\n" - " We suggest to use literal names (instead of numeric ones) in\n" - " order to avoid problems with different address families.\n\n" + " to connect to this server (if more than one, list them one\n" + " per line).\n" + " We suggest to use literal names (instead of numeric ones)\n" + " in order to avoid problems with different address families.\n\n" " -n permit NULL authentication (usually used with '-l')\n\n" " -a <host,port> run in active mode when connecting to 'host' on port 'port'\n" " In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n" - " -v run in active mode only (default: if '-a' is specified, it accepts\n" - " passive connections as well\n\n" + " -v run in active mode only (default: if '-a' is specified, it\n" + " accepts passive connections as well)\n\n" " -d run in daemon mode (UNIX only) or as a service (Win32 only)\n" - " Warning (Win32): this switch is provided automatically when the service\n" - " is started from the control panel\n\n" + " Warning (Win32): this switch is provided automatically when\n" + " the service is started from the control panel\n\n" +#ifndef _WIN32 + " -i run in inetd mode (UNIX only)\n\n" +#endif " -s <file> save the current configuration to file\n\n" " -f <file> load the current configuration from file; all switches\n" " specified from the command line are ignored\n\n" @@ -146,7 +159,10 @@ static void printusage(void) int main(int argc, char *argv[]) { char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration - int isdaemon = 0; // Not null if the user wants to run this program as a daemon + int isdaemon = 0; // Non-zero if the user wants to run this program as a daemon +#ifndef _WIN32 + int isrunbyinetd = 0; // Non-zero if this is being run by inetd or something inetd-like +#endif int retval; // keeps the returning value from several functions char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed #ifndef _WIN32 @@ -177,7 +193,7 @@ int main(int argc, char *argv[]) mainhints.ai_socktype = SOCK_STREAM; // Getting the proper command line options - while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1) + while ((retval = getopt(argc, argv, "b:dhip:4l:na:s:f:v")) != -1) { switch (retval) { @@ -193,6 +209,14 @@ int main(int argc, char *argv[]) case 'd': isdaemon = 1; break; + case 'i': +#ifdef _WIN32 + printusage(); + exit(1); +#else + isrunbyinetd = 1; +#endif + break; case 'n': nullAuthAllowed = 1; break; @@ -244,13 +268,23 @@ int main(int argc, char *argv[]) case 'h': printusage(); exit(0); + break; default: + exit(1); break; } } +#ifndef _WIN32 + if (isdaemon && isrunbyinetd) + { + fprintf(stderr, "rpcapd: -d and -i can't be used together\n"); + exit(1); + } +#endif + if (savefile[0] && fileconf_save(savefile)) - SOCK_MESSAGE("Error when saving the configuration to file"); + SOCK_MESSAGE("Error when saving the configuration to file"); // If the file does not exist, it keeps the settings provided by the command line if (loadfile[0]) @@ -296,13 +330,86 @@ int main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); #endif - // forking a daemon, if it is needed +#ifndef _WIN32 + if (isrunbyinetd) + { + // + // -i was specified, indicating that this is being run + // by inetd or something that can run network daemons + // as if it were inetd (xinetd, launchd, systemd, etc.). + // + // Our standard input is the input side of a connection, + // and our standard output is the output side of a + // connection. + // + int sockctrl_in, sockctrl_out; + int devnull_fd; + + // + // Duplicate the standard input and output, making them + // the input and output side of the control connection. + // + sockctrl_in = dup(0); + if (sockctrl_in == -1) + { + sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE); + rpcapd_log(LOGPRIO_ERROR, "Can't dup standard input: %s", + errbuf); + exit(2); + } + sockctrl_out = dup(1); + if (sockctrl_out == -1) + { + sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE); + rpcapd_log(LOGPRIO_ERROR, "Can't dup standard output: %s", + errbuf); + exit(2); + } + + // + // Try to set the standard input and output to /dev/null. + // + devnull_fd = open("/dev/null", O_RDWR); + if (devnull_fd != -1) + { + // + // If this fails, just drive on. + // + (void)dup2(devnull_fd, 0); + (void)dup2(devnull_fd, 1); + close(devnull_fd); + } + + // + // Handle this client. + // This is passive mode, so we don't care whether we were + // told by the client to close. + // + (void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0, + nullAuthAllowed); + + // + // Nothing more to do. + // + exit(0); + } +#endif + if (isdaemon) { + // + // This is being run as a daemon. + // On UN*X, it might be manually run, or run from an + // rc file. + // #ifndef _WIN32 int pid; + // + // Daemonize ourselves. + // // Unix Network Programming, pg 336 + // if ((pid = fork()) != 0) exit(0); // Parent terminates @@ -329,7 +436,11 @@ int main(int argc, char *argv[]) // umask(0); // chdir("/"); #else + // + // This is being run as a service on Windows. + // // If this call succeeds, it is blocking on Win32 + // if (svc_start() != 1) SOCK_MESSAGE("Unable to start the service"); @@ -896,10 +1007,10 @@ accept_connection(SOCKET listen_sock) #ifdef _WIN32 HANDLE threadId; // handle for the subthread u_long off = 0; + SOCKET *sockctrl_temp; #else pid_t pid; #endif - struct daemon_slpars *pars; // parameters needed by the daemon_serviceloop() // Initialize errbuf memset(errbuf, 0, sizeof(errbuf)); @@ -971,9 +1082,15 @@ accept_connection(SOCKET listen_sock) return; } - // in case of passive mode, this variable is deallocated by the daemon_serviceloop() - pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars)); - if (pars == NULL) + // + // Allocate a location to hold the value of sockctrl. + // It will be freed in the newly-created thread once it's + // finished with it. + // I guess we *could* just cast sockctrl to a void *, but that's + // a bit ugly. + // + sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET)); + if (sockctrl_temp == NULL) { pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "malloc() failed"); @@ -981,19 +1098,16 @@ accept_connection(SOCKET listen_sock) sock_close(sockctrl, NULL, 0); return; } + *sockctrl_temp = sockctrl; - pars->sockctrl = sockctrl; - pars->activeclose = 0; // useless in passive mode - pars->isactive = 0; - pars->nullAuthAllowed = nullAuthAllowed; - - threadId = (HANDLE)_beginthreadex(NULL, 0, daemon_serviceloop, - (void *) pars, 0, NULL); + threadId = (HANDLE)_beginthreadex(NULL, 0, + main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL); if (threadId == 0) { pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread"); rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL); sock_close(sockctrl, NULL, 0); + free(sockctrl_temp); return; } CloseHandle(threadId); @@ -1010,33 +1124,36 @@ accept_connection(SOCKET listen_sock) { // // Child process. - // This is passive mode, so this variable is deallocated - // by the daemon_serviceloop(). - // - pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars)); - if (pars == NULL) - { - pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Can't allocate memory for the child process"); - rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL); - sock_close(sockctrl, NULL, 0); - return; - } - - pars->sockctrl = sockctrl; - pars->activeclose = 0; // useless in passive mode - pars->isactive = 0; - pars->nullAuthAllowed = nullAuthAllowed; - // // Close the socket on which we're listening (must // be open only in the parent). // closesocket(listen_sock); +#if 0 + // + // Modify thread params so that it can be killed at any time + // XXX - is this necessary? This is the main and, currently, + // only thread in the child process, and nobody tries to + // cancel us, although *we* may cancel the thread that's + // handling the capture loop. + // + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) + goto end; + if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) + goto end; +#endif + // // Run the service loop. + // This is passive mode, so we don't care whether we were + // told by the client to close. // - daemon_serviceloop((void *) pars); + (void)daemon_serviceloop(sockctrl, sockctrl, 0, + nullAuthAllowed); + + close(sockctrl); + exit(0); } @@ -1067,7 +1184,6 @@ main_active(void *ptr) struct addrinfo hints; // temporary struct to keep settings needed to open the new socket struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket struct active_pars *activepars; - struct daemon_slpars *pars; // parameters needed by the daemon_serviceloop() activepars = (struct active_pars *) ptr; @@ -1112,24 +1228,10 @@ main_active(void *ptr) continue; } - pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars)); - if (pars == NULL) - { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, - errno, "malloc() failed"); - continue; - } - - pars->sockctrl = sockctrl; - pars->activeclose = 0; - pars->isactive = 1; - pars->nullAuthAllowed = nullAuthAllowed; - - daemon_serviceloop((void *) pars); - - activeclose = pars->activeclose; + activeclose = daemon_serviceloop(sockctrl, sockctrl, 1, + nullAuthAllowed); - free(pars); + sock_close(sockctrl, NULL, 0); // If the connection is closed by the user explicitely, don't try to connect to it again // just exit the program @@ -1140,3 +1242,27 @@ main_active(void *ptr) freeaddrinfo(addrinfo); return 0; } + +#ifdef _WIN32 +// +// Main routine of a passive-mode service thread. +// +unsigned __stdcall main_passive_serviceloop_thread(void *ptr) +{ + SOCKET sockctrl; + + sockctrl = *((SOCKET *)ptr); + free(ptr); + + // + // Handle this client. + // This is passive mode, so we don't care whether we were + // told by the client to close. + // + (void)daemon_serviceloop(sockctrl, sockctrl, 0, nullAuthAllowed); + + sock_close(sockctrl, NULL, 0); + + return 0; +} +#endif diff --git a/rpcapd/rpcapd.h b/rpcapd/rpcapd.h index 4ef9c7e9..90ba7ffa 100755 --- a/rpcapd/rpcapd.h +++ b/rpcapd/rpcapd.h @@ -34,23 +34,7 @@ #define __RPCAPD_H__ #define PROGRAM_NAME "rpcapd" -#define MAX_LINE 2048 /* Maximum chars allowed for the host list (in passive mode) */ #define SOCKET_MAXCONN 10 /* Maximum number of connections queued into the accept() */ -#define MAX_HOST_LIST 64000 -#define MAX_ACTIVE_LIST 10 - -struct active_pars -{ - char address[MAX_LINE + 1]; // keeps the network address (either numeric or literal) to of the active client - char port[MAX_LINE + 1]; // keeps the network port to bind to - int ai_family; // address faimly to use -}; - -extern char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server -extern struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode) -extern int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise -extern char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration - #ifdef _WIN32 void send_shutdown_notification(void); // Send notification to shut down the daemon void send_reread_configuration_notification(void); // Send notification to re-read the configuration file |