aboutsummaryrefslogtreecommitdiff
path: root/contrib/libpcap/rpcapd/rpcapd.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/rpcapd/rpcapd.c')
-rw-r--r--contrib/libpcap/rpcapd/rpcapd.c172
1 files changed, 119 insertions, 53 deletions
diff --git a/contrib/libpcap/rpcapd/rpcapd.c b/contrib/libpcap/rpcapd/rpcapd.c
index 430acdc88e86..4c1b74549a45 100644
--- a/contrib/libpcap/rpcapd/rpcapd.c
+++ b/contrib/libpcap/rpcapd/rpcapd.c
@@ -35,10 +35,12 @@
#endif
#include "ftmacros.h"
+#include "diag-control.h"
#include <errno.h> // for the errno variable
#include <string.h> // for strtok, etc
#include <stdlib.h> // for malloc(), free(), ...
+#include <stdio.h> // for fprintf(), stderr, FILE etc
#include <pcap.h> // for PCAP_ERRBUF_SIZE
#include <signal.h> // for signal()
@@ -53,6 +55,10 @@
#include "daemon.h" // the true main() method of this daemon
#include "log.h"
+#ifdef HAVE_OPENSSL
+#include "sslutils.h"
+#endif
+
#ifdef _WIN32
#include <process.h> // for thread stuff
#include "win32-svc.h" // for Win32 service stuff
@@ -86,6 +92,7 @@ static HANDLE state_change_event; //!< event to signal that a state change shou
#endif
static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down
static volatile sig_atomic_t reread_config; //!< '1' if the server is to re-read its configuration
+static int uses_ssl; //!< '1' to use TLS over the data socket
extern char *optarg; // for getopt()
@@ -112,7 +119,7 @@ static unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
/*!
\brief Prints the usage screen if it is launched in console mode.
*/
-static void printusage(void)
+static void printusage(FILE * f)
{
const char *usagetext =
"USAGE:"
@@ -145,14 +152,23 @@ static void printusage(void)
" -i run in inetd mode (UNIX only)\n\n"
#endif
" -D log debugging messages\n\n"
+#ifdef HAVE_OPENSSL
+ " -S encrypt all communication with SSL (implements rpcaps://)\n"
+ " -C enable compression\n"
+ " -K <pem_file> uses the SSL private key in this file (default: key.pem)\n"
+ " -X <pem_file> uses the certificate from this file (default: cert.pem)\n"
+#endif
" -s <config_file> save the current configuration to file\n\n"
" -f <config_file> load the current configuration from file; all switches\n"
" specified from the command line are ignored\n\n"
" -h print this help screen\n\n";
- (void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
- "Compiled with %s\n\n", pcap_lib_version());
- printf("%s", usagetext);
+ (void)fprintf(f, "RPCAPD, a remote packet capture daemon.\n"
+ "Compiled with %s\n", pcap_lib_version());
+#if defined(HAVE_OPENSSL) && defined(SSLEAY_VERSION)
+ (void)fprintf(f, "Compiled with %s\n", SSLeay_version(SSLEAY_VERSION));
+#endif
+ (void)fprintf(f, "\n%s", usagetext);
}
@@ -172,6 +188,9 @@ int main(int argc, char *argv[])
#ifndef _WIN32
struct sigaction action;
#endif
+#ifdef HAVE_OPENSSL
+ int enable_compression = 0;
+#endif
savefile[0] = 0;
loadfile[0] = 0;
@@ -180,8 +199,8 @@ int main(int argc, char *argv[])
// Initialize errbuf
memset(errbuf, 0, sizeof(errbuf));
- strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
- strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
+ pcap_strlcpy(address, RPCAP_DEFAULT_NETADDR, sizeof (address));
+ pcap_strlcpy(port, RPCAP_DEFAULT_NETPORT, sizeof (port));
// Prepare to open a new server socket
memset(&mainhints, 0, sizeof(struct addrinfo));
@@ -191,7 +210,15 @@ int main(int argc, char *argv[])
mainhints.ai_socktype = SOCK_STREAM;
// Getting the proper command line options
- while ((retval = getopt(argc, argv, "b:dDhip:4l:na:s:f:v")) != -1)
+# ifdef HAVE_OPENSSL
+# define SSL_CLOPTS "SK:X:C"
+# else
+# define SSL_CLOPTS ""
+# endif
+
+# define CLOPTS "b:dDhip:4l:na:s:f:v" SSL_CLOPTS
+
+ while ((retval = getopt(argc, argv, CLOPTS)) != -1)
{
switch (retval)
{
@@ -200,10 +227,10 @@ int main(int argc, char *argv[])
rpcapd_log_set(log_to_systemlog, log_debug_messages);
break;
case 'b':
- strncpy(address, optarg, MAX_LINE);
+ pcap_strlcpy(address, optarg, sizeof (address));
break;
case 'p':
- strncpy(port, optarg, MAX_LINE);
+ pcap_strlcpy(port, optarg, sizeof (port));
break;
case '4':
mainhints.ai_family = PF_INET; // IPv4 server only
@@ -215,7 +242,7 @@ int main(int argc, char *argv[])
break;
case 'i':
#ifdef _WIN32
- printusage();
+ printusage(stderr);
exit(1);
#else
isrunbyinetd = 1;
@@ -231,7 +258,7 @@ int main(int argc, char *argv[])
break;
case 'l':
{
- strncpy(hostlist, optarg, sizeof(hostlist));
+ pcap_strlcpy(hostlist, optarg, sizeof(hostlist));
break;
}
case 'a':
@@ -246,12 +273,12 @@ int main(int argc, char *argv[])
{
tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
- pcap_strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
+ pcap_strlcpy(activelist[i].address, tmpaddress, sizeof (activelist[i].address));
if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
- pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+ pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, sizeof (activelist[i].port));
else
- pcap_strlcpy(activelist[i].port, tmpport, MAX_LINE);
+ pcap_strlcpy(activelist[i].port, tmpport, sizeof (activelist[i].port));
tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
@@ -266,13 +293,27 @@ int main(int argc, char *argv[])
break;
}
case 'f':
- pcap_strlcpy(loadfile, optarg, MAX_LINE);
+ pcap_strlcpy(loadfile, optarg, sizeof (loadfile));
break;
case 's':
- pcap_strlcpy(savefile, optarg, MAX_LINE);
+ pcap_strlcpy(savefile, optarg, sizeof (savefile));
break;
+#ifdef HAVE_OPENSSL
+ case 'S':
+ uses_ssl = 1;
+ break;
+ case 'C':
+ enable_compression = 1;
+ break;
+ case 'K':
+ ssl_set_keyfile(optarg);
+ break;
+ case 'X':
+ ssl_set_certfile(optarg);
+ break;
+#endif
case 'h':
- printusage();
+ printusage(stdout);
exit(0);
/*NOTREACHED*/
default:
@@ -289,6 +330,16 @@ int main(int argc, char *argv[])
}
#endif
+ //
+ // We want UTF-8 error messages.
+ //
+ if (pcap_init(PCAP_CHAR_ENC_UTF_8, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(-1);
+ }
+ pcap_fmt_set_encoding(PCAP_CHAR_ENC_UTF_8);
+
if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
{
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
@@ -302,7 +353,7 @@ int main(int argc, char *argv[])
if (loadfile[0])
fileconf_read();
-#ifdef WIN32
+#ifdef _WIN32
//
// Create a handle to signal the main loop to tell it to do
// something.
@@ -310,8 +361,8 @@ int main(int argc, char *argv[])
state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (state_change_event == NULL)
{
- sock_geterror("Can't create state change event", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "Can't create state change event");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -321,8 +372,8 @@ int main(int argc, char *argv[])
//
if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
{
- sock_geterror("Can't set control handler", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "Can't set control handler");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -342,6 +393,17 @@ int main(int argc, char *argv[])
signal(SIGPIPE, SIG_IGN);
#endif
+# ifdef HAVE_OPENSSL
+ if (uses_ssl) {
+ if (ssl_init_once(1, enable_compression, errbuf, PCAP_ERRBUF_SIZE) < 0)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Can't initialize SSL: %s",
+ errbuf);
+ exit(2);
+ }
+ }
+# endif
+
#ifndef _WIN32
if (isrunbyinetd)
{
@@ -365,8 +427,8 @@ int main(int argc, char *argv[])
sockctrl = dup(0);
if (sockctrl == -1)
{
- sock_geterror("Can't dup standard input", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "Can't dup standard input");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -399,7 +461,7 @@ int main(int argc, char *argv[])
exit(0);
}
(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
- nullAuthAllowed);
+ nullAuthAllowed, uses_ssl);
//
// Nothing more to do.
@@ -442,7 +504,7 @@ int main(int argc, char *argv[])
// LINUX WARNING: the current linux implementation of pthreads requires a management thread
// to handle some hidden stuff. So, as soon as you create the first thread, two threads are
- // created. Fom this point on, the number of threads active are always one more compared
+ // created. From this point on, the number of threads active are always one more compared
// to the number you're expecting
// Second child continues
@@ -454,7 +516,7 @@ int main(int argc, char *argv[])
//
// If this call succeeds, it is blocking on Win32
//
- if (svc_start() != 1)
+ if (!svc_start())
rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service");
// When the previous call returns, the entire application has to be stopped.
@@ -561,7 +623,7 @@ void main_startup(void)
SOCKET sock;
struct listen_sock *sock_info;
- if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ if ((sock = sock_open(NULL, tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
{
switch (tempaddrinfo->ai_family)
{
@@ -674,8 +736,8 @@ send_state_change_event(void)
if (!SetEvent(state_change_event))
{
- sock_geterror("SetEvent on shutdown event failed", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "SetEvent on shutdown event failed");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
}
}
@@ -842,15 +904,15 @@ accept_connections(void)
event = WSACreateEvent();
if (event == WSA_INVALID_EVENT)
{
- sock_geterror("Can't create socket event", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "Can't create socket event");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
{
- sock_geterror("Can't setup socket event", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "Can't setup socket event");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -868,8 +930,8 @@ accept_connections(void)
WSA_INFINITE, FALSE);
if (ret == WSA_WAIT_FAILED)
{
- sock_geterror("WSAWaitForMultipleEvents failed", errbuf,
- PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "WSAWaitForMultipleEvents failed");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -908,8 +970,8 @@ accept_connections(void)
if (WSAEnumNetworkEvents(sock_info->sock,
events[i], &network_events) == SOCKET_ERROR)
{
- sock_geterror("WSAEnumNetworkEvents failed",
- errbuf, PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "WSAEnumNetworkEvents failed");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
exit(2);
}
@@ -918,15 +980,15 @@ accept_connections(void)
//
// Did an error occur?
//
- if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
- {
+ if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
+ {
//
// Yes - report it and keep going.
//
- sock_fmterror("Socket error",
+ sock_fmterrmsg(errbuf,
+ PCAP_ERRBUF_SIZE,
network_events.iErrorCode[FD_ACCEPT_BIT],
- errbuf,
- PCAP_ERRBUF_SIZE);
+ "Socket error");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
continue;
}
@@ -1100,7 +1162,7 @@ accept_connection(SOCKET listen_sock)
break;
}
- // The accept() call can return this error when a signal is catched
+ // The accept() call can return this error when a signal is caught
// In this case, we have simply to ignore this error code
// Stevens, pg 124
#ifdef _WIN32
@@ -1112,7 +1174,7 @@ accept_connection(SOCKET listen_sock)
// Don't check for errors here, since the error can be due to the fact that the thread
// has been killed
- sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE, "accept() failed");
rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
errbuf);
return;
@@ -1136,14 +1198,16 @@ accept_connection(SOCKET listen_sock)
//
if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
{
- sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "WSAEventSelect() failed");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
sock_close(sockctrl, NULL, 0);
return;
}
if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
{
- sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE);
+ sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
+ "ioctlsocket(FIONBIO) failed");
rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
sock_close(sockctrl, NULL, 0);
return;
@@ -1236,7 +1300,7 @@ accept_connection(SOCKET listen_sock)
exit(0);
}
(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
- nullAuthAllowed);
+ nullAuthAllowed, uses_ssl);
exit(0);
}
@@ -1296,13 +1360,15 @@ main_active(void *ptr)
{
int activeclose;
- if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ if ((sockctrl = sock_open(activepars->address, addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
{
rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
+ DIAG_OFF_FORMAT_TRUNCATION
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
(hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
+ DIAG_ON_FORMAT_TRUNCATION
rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
@@ -1324,10 +1390,10 @@ main_active(void *ptr)
// daemon_serviceloop() will free the copy.
//
activeclose = daemon_serviceloop(sockctrl, 1,
- hostlist_copy, nullAuthAllowed);
+ hostlist_copy, nullAuthAllowed, uses_ssl);
}
- // If the connection is closed by the user explicitely, don't try to connect to it again
+ // If the connection is closed by the user explicitly, don't try to connect to it again
// just exit the program
if (activeclose == 1)
break;
@@ -1352,7 +1418,7 @@ unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
// told by the client to close.
//
(void)daemon_serviceloop(params.sockctrl, 0, params.hostlist,
- nullAuthAllowed);
+ nullAuthAllowed, uses_ssl);
return 0;
}