Merge branch 'udp_listener' into execvpe
This commit is contained in:
+18
-1
@@ -166,6 +166,16 @@ if test "x$want_fuzzing_interfaces" = "xyes"; then
|
||||
AC_DEFINE([FUZZING_INTERFACES], [1], [Define for fuzzing interfaces support])
|
||||
fi
|
||||
|
||||
dnl Decide whether or not to enable UDP server mode (no libpcap dependency)
|
||||
dnl
|
||||
want_udp_server=no
|
||||
AC_ARG_ENABLE([udp-server],
|
||||
[AS_HELP_STRING([--enable-udp-server],
|
||||
[Enable UDP server mode for no libpcap dependency @<:@default is to disable@:>@])],
|
||||
[want_udp_server=$enableval],
|
||||
[])
|
||||
AM_CONDITIONAL([UDP_SERVER], [test "$want_udp_server" = yes])
|
||||
|
||||
dnl Decide whether or not to enable all warnings with -Wall
|
||||
dnl
|
||||
use_wall=yes
|
||||
@@ -443,12 +453,15 @@ AS_IF([test "x$WGET_EXE" != x],
|
||||
dnl Check for libpcap, gdbm (or ndbm) if we are building the server component
|
||||
dnl
|
||||
AS_IF([test "$want_server" = yes], [
|
||||
|
||||
AS_IF([test "$want_udp_server" = no], [
|
||||
# Looking for libpcap
|
||||
#
|
||||
AC_CHECK_LIB([pcap],[pcap_open_live],
|
||||
[ AC_DEFINE([HAVE_LIBPCAP], [1], [Define if you have libpcap]) ],
|
||||
[ AC_DEFINE([USE_LIBPCAP], [1], [Define if you have libpcap]) ],
|
||||
[ AC_MSG_ERROR([fwknopd needs libpcap])]
|
||||
)
|
||||
])
|
||||
|
||||
AS_IF([test "$want_digest_cache" = yes], [
|
||||
use_ndbm=no
|
||||
@@ -687,6 +700,10 @@ if [test "$want_server" = "yes" ]; then
|
||||
firewall type: $FIREWALL_TYPE
|
||||
firewall program path: $FIREWALL_EXE
|
||||
"
|
||||
if [test "$want_udp_server" = "yes" ]; then
|
||||
echo " UDP server mode enabled, no libpcap dependency
|
||||
"
|
||||
fi
|
||||
|
||||
if [test "$want_digest_cache" = "no" ]; then
|
||||
echo " *WARNING*
|
||||
|
||||
@@ -308,14 +308,14 @@ See the '@sysconfdir@/fwknop/fwknopd.conf'' file for the full list and correspon
|
||||
|
||||
*ENABLE_TCP_SERVER* '<Y/N>'::
|
||||
Enable the fwknopd TCP server. This is a "dummy" TCP server that will
|
||||
accept TCP connection requests on the specified TCPSERV_PORT.
|
||||
If set to "Y", fwknopd will fork off a child process to listen for, and
|
||||
accept incoming TCP request. This server only accepts the
|
||||
request. It does not otherwise communicate. This is only to allow the
|
||||
incoming SPA over TCP packet which is detected via PCAP. The connection
|
||||
is closed after 1 second regardless.
|
||||
Note that fwknopd still only gets its data via pcap, so the filter
|
||||
defined by PCAP_FILTER needs to be updated to include this TCP port.
|
||||
accept TCP connection requests on the specified TCPSERV_PORT.
|
||||
If set to "Y", fwknopd will fork off a child process to listen for, and
|
||||
accept incoming TCP request. This server only accepts the
|
||||
request. It does not otherwise communicate. This is only to allow the
|
||||
incoming SPA over TCP packet which is detected via PCAP. The connection
|
||||
is closed after 1 second regardless.
|
||||
Note that fwknopd still only gets its data via pcap, so the filter
|
||||
defined by PCAP_FILTER needs to be updated to include this TCP port.
|
||||
|
||||
*PCAP_DISPATCH_COUNT* '<count>'::
|
||||
Sets the number of packets that are processed when the *pcap_dispatch()*
|
||||
@@ -346,6 +346,19 @@ See the '@sysconfdir@/fwknop/fwknopd.conf'' file for the full list and correspon
|
||||
Set the port number that the ``dummy'' TCP server listens on. This server
|
||||
is only spawned when ``ENABLE_TCP_SERVER'' is set to ``Y''.
|
||||
|
||||
*ENABLE_UDP_SERVER* '<Y/N>'::
|
||||
Enable the *fwknopd* UDP server. This enables *fwknopd* to acquire SPA
|
||||
packets via a UDP socket directly without having to use libpcap. When this
|
||||
mode is enabled, *fwknop* should be compiled with *--enable-udp-server*
|
||||
(passed to the *configure* script) so that libpcap can be removed as a
|
||||
dependency. As one would expect, when the UDP server is used, no incoming
|
||||
packets are ever acknowledged by *fwknopd* and therefore collecting SPA
|
||||
packets in this mode is a good alternative to sniffing the wire directly.
|
||||
|
||||
*UDPSERV_PORT* '<port>'::
|
||||
Set the port number that the UDP server listens on. This server
|
||||
is only spawned when ``ENABLE_UDP_SERVER'' is set to ``Y''.
|
||||
|
||||
*SYSLOG_IDENTITY* '<identity>'::
|
||||
Override syslog identity on message logged by *fwknopd*. The defaults
|
||||
are usually ok.
|
||||
|
||||
+9
-4
@@ -6,16 +6,21 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
|
||||
process_packet.h log_msg.c log_msg.h utils.c utils.h \
|
||||
sig_handler.c sig_handler.h replay_cache.c replay_cache.h \
|
||||
access.c access.h fwknopd_errors.c fwknopd_errors.h \
|
||||
tcp_server.c tcp_server.h extcmd.c extcmd.h \
|
||||
tcp_server.c tcp_server.h udp_server.c udp_server.h \
|
||||
fw_util.c fw_util.h fw_util_ipf.c fw_util_ipf.h \
|
||||
fw_util_firewalld.c fw_util_firewalld.h \
|
||||
fw_util_iptables.c fw_util_iptables.h \
|
||||
fw_util_ipfw.c fw_util_ipfw.h \
|
||||
fw_util_pf.c fw_util_pf.h cmd_opts.h
|
||||
fw_util_pf.c fw_util_pf.h cmd_opts.h \
|
||||
extcmd.c extcmd.h
|
||||
|
||||
fwknopd_LDADD = $(top_builddir)/lib/libfko.la $(top_builddir)/common/libfko_util.a -lpcap
|
||||
fwknopd_LDADD = $(top_builddir)/lib/libfko.la $(top_builddir)/common/libfko_util.a
|
||||
|
||||
if ! CONFIG_FILE_CACHE
|
||||
if !UDP_SERVER
|
||||
fwknopd_LDADD += -lpcap
|
||||
endif
|
||||
|
||||
if !CONFIG_FILE_CACHE
|
||||
if USE_NDBM
|
||||
fwknopd_LDADD += -lndbm
|
||||
else
|
||||
|
||||
@@ -57,6 +57,9 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
|
||||
"ENABLE_SPA_OVER_HTTP",
|
||||
"ENABLE_TCP_SERVER",
|
||||
"TCPSERV_PORT",
|
||||
"ENABLE_UDP_SERVER",
|
||||
"UDPSERV_PORT",
|
||||
"UDPSERV_SELECT_TIMEOUT",
|
||||
"LOCALE",
|
||||
"SYSLOG_IDENTITY",
|
||||
"SYSLOG_FACILITY",
|
||||
@@ -186,6 +189,7 @@ static struct option cmd_opts[] =
|
||||
{"restart", 0, NULL, 'R'},
|
||||
{"status", 0, NULL, 'S'},
|
||||
{"test", 0, NULL, 't'},
|
||||
{"udp-server", 0, NULL, 'U'},
|
||||
{"verbose", 0, NULL, 'v'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
{0, 0, 0, 0}
|
||||
|
||||
@@ -151,6 +151,10 @@ validate_int_var_ranges(fko_srv_options_t *opts)
|
||||
1, RCHK_MAX_SNIFF_BYTES);
|
||||
range_check(opts, "TCPSERV_PORT", opts->config[CONF_TCPSERV_PORT],
|
||||
1, RCHK_MAX_TCPSERV_PORT);
|
||||
range_check(opts, "UDPSERV_PORT", opts->config[CONF_UDPSERV_PORT],
|
||||
1, RCHK_MAX_UDPSERV_PORT);
|
||||
range_check(opts, "UDPSERV_PORT", opts->config[CONF_UDPSERV_SELECT_TIMEOUT],
|
||||
1, RCHK_MAX_UDPSERV_SELECT_TIMEOUT);
|
||||
|
||||
#if FIREWALL_IPFW
|
||||
range_check(opts, "IPFW_START_RULE_NUM", opts->config[CONF_IPFW_START_RULE_NUM],
|
||||
@@ -808,6 +812,30 @@ validate_options(fko_srv_options_t *opts)
|
||||
if(opts->config[CONF_TCPSERV_PORT] == NULL)
|
||||
set_config_entry(opts, CONF_TCPSERV_PORT, DEF_TCPSERV_PORT);
|
||||
|
||||
/* Enable UDP server.
|
||||
*/
|
||||
if(opts->config[CONF_ENABLE_UDP_SERVER] == NULL)
|
||||
{
|
||||
if((strncasecmp(DEF_ENABLE_UDP_SERVER, "Y", 1) == 0) &&
|
||||
!opts->enable_udp_server)
|
||||
{
|
||||
log_msg(LOG_ERR, "pcap capture not enabled, forcing UDP server mode");
|
||||
opts->enable_udp_server = 1;
|
||||
}
|
||||
set_config_entry(opts, CONF_ENABLE_UDP_SERVER, DEF_ENABLE_UDP_SERVER);
|
||||
}
|
||||
|
||||
/* UDP Server port.
|
||||
*/
|
||||
if(opts->config[CONF_UDPSERV_PORT] == NULL)
|
||||
set_config_entry(opts, CONF_UDPSERV_PORT, DEF_UDPSERV_PORT);
|
||||
|
||||
/* UDP server select() timeout in microseconds
|
||||
*/
|
||||
if(opts->config[CONF_UDPSERV_SELECT_TIMEOUT] == NULL)
|
||||
set_config_entry(opts, CONF_UDPSERV_SELECT_TIMEOUT,
|
||||
DEF_UDPSERV_SELECT_TIMEOUT);
|
||||
|
||||
/* Syslog identity.
|
||||
*/
|
||||
if(opts->config[CONF_SYSLOG_IDENTITY] == NULL)
|
||||
@@ -1113,6 +1141,9 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
|
||||
case 't':
|
||||
opts->test = 1;
|
||||
break;
|
||||
case 'U':
|
||||
opts->enable_udp_server = 1;
|
||||
break;
|
||||
/* Verbosity level */
|
||||
case 'v':
|
||||
opts->verbose++;
|
||||
|
||||
+33
-9
@@ -31,14 +31,17 @@
|
||||
#include "fwknopd.h"
|
||||
#include "access.h"
|
||||
#include "config_init.h"
|
||||
#include "process_packet.h"
|
||||
#include "pcap_capture.h"
|
||||
#include "log_msg.h"
|
||||
#include "utils.h"
|
||||
#include "fw_util.h"
|
||||
#include "sig_handler.h"
|
||||
#include "replay_cache.h"
|
||||
#include "tcp_server.h"
|
||||
#include "udp_server.h"
|
||||
|
||||
#if USE_LIBPCAP
|
||||
#include "pcap_capture.h"
|
||||
#endif
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
@@ -178,7 +181,25 @@ main(int argc, char **argv)
|
||||
if(!opts.test && (fw_initialize(&opts) != 1))
|
||||
clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
|
||||
/* If the TCP server option was set, fire it up here.
|
||||
/* If we are to acquire SPA data via a UDP socket, start it up here.
|
||||
*/
|
||||
if(opts.enable_udp_server ||
|
||||
strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "Y", 1) == 0)
|
||||
{
|
||||
if(run_udp_server(&opts) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "Fatal run_udp_server() error");
|
||||
clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the TCP server option was set, fire it up here. Note that in
|
||||
* this mode, fwknopd still acquires SPA packets via libpcap. If you
|
||||
* want to use UDP only without the libpcap dependency, see the FIXME...
|
||||
*/
|
||||
if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0)
|
||||
{
|
||||
@@ -189,9 +210,12 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_LIBPCAP
|
||||
/* Intiate pcap capture mode...
|
||||
*/
|
||||
pcap_capture(&opts);
|
||||
if(strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "N", 1) == 0)
|
||||
pcap_capture(&opts);
|
||||
#endif
|
||||
|
||||
/* Deal with any signals that we've received and break out
|
||||
* of the loop for any terminating signals
|
||||
@@ -379,7 +403,7 @@ static int handle_signals(fko_srv_options_t *opts)
|
||||
|
||||
if(got_sighup)
|
||||
{
|
||||
log_msg(LOG_WARNING, "Got SIGHUP. Re-reading configs.");
|
||||
log_msg(LOG_WARNING, "Got SIGHUP. Re-reading configs.");
|
||||
free_configs(opts);
|
||||
kill(opts->tcp_server_pid, SIGTERM);
|
||||
usleep(1000000);
|
||||
@@ -388,12 +412,12 @@ static int handle_signals(fko_srv_options_t *opts)
|
||||
}
|
||||
else if(got_sigint)
|
||||
{
|
||||
log_msg(LOG_WARNING, "Got SIGINT. Exiting...");
|
||||
log_msg(LOG_WARNING, "Got SIGINT. Exiting...");
|
||||
got_sigint = 0;
|
||||
}
|
||||
else if(got_sigterm)
|
||||
{
|
||||
log_msg(LOG_WARNING, "Got SIGTERM. Exiting...");
|
||||
log_msg(LOG_WARNING, "Got SIGTERM. Exiting...");
|
||||
got_sigterm = 0;
|
||||
}
|
||||
else
|
||||
@@ -406,13 +430,13 @@ static int handle_signals(fko_srv_options_t *opts)
|
||||
&& opts->packet_ctr >= opts->packet_ctr_limit)
|
||||
{
|
||||
log_msg(LOG_INFO,
|
||||
"Packet count limit (%d) reached. Exiting...",
|
||||
"Packet count limit (%d) reached. Exiting...",
|
||||
opts->packet_ctr_limit);
|
||||
}
|
||||
else /* got_signal was not set (should be if we are here) */
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"Capture ended without signal. Exiting...");
|
||||
"Capture ended without signal. Exiting...");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
+14
-1
@@ -41,7 +41,7 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBPCAP
|
||||
#if USE_LIBPCAP
|
||||
#include <pcap.h>
|
||||
#endif
|
||||
|
||||
@@ -101,6 +101,13 @@
|
||||
#define DEF_ENABLE_SPA_OVER_HTTP "N"
|
||||
#define DEF_ENABLE_TCP_SERVER "N"
|
||||
#define DEF_TCPSERV_PORT "62201"
|
||||
#if USE_LIBPCAP
|
||||
#define DEF_ENABLE_UDP_SERVER "N"
|
||||
#else
|
||||
#define DEF_ENABLE_UDP_SERVER "Y"
|
||||
#endif
|
||||
#define DEF_UDPSERV_PORT "62201"
|
||||
#define DEF_UDPSERV_SELECT_TIMEOUT "500000" /* half a second (in microseconds) */
|
||||
#define DEF_SYSLOG_IDENTITY MY_NAME
|
||||
#define DEF_SYSLOG_FACILITY "LOG_DAEMON"
|
||||
|
||||
@@ -112,6 +119,8 @@
|
||||
#define RCHK_MAX_SPA_PACKET_AGE 100000 /* seconds, can disable */
|
||||
#define RCHK_MAX_SNIFF_BYTES (2 << 14)
|
||||
#define RCHK_MAX_TCPSERV_PORT ((2 << 16) - 1)
|
||||
#define RCHK_MAX_UDPSERV_PORT ((2 << 16) - 1)
|
||||
#define RCHK_MAX_UDPSERV_SELECT_TIMEOUT (2 << 22)
|
||||
#define RCHK_MAX_PCAP_DISPATCH_COUNT (2 << 22)
|
||||
#define RCHK_MAX_FW_TIMEOUT (2 << 22)
|
||||
|
||||
@@ -225,6 +234,9 @@ enum {
|
||||
CONF_ENABLE_SPA_OVER_HTTP,
|
||||
CONF_ENABLE_TCP_SERVER,
|
||||
CONF_TCPSERV_PORT,
|
||||
CONF_ENABLE_UDP_SERVER,
|
||||
CONF_UDPSERV_PORT,
|
||||
CONF_UDPSERV_SELECT_TIMEOUT,
|
||||
CONF_LOCALE,
|
||||
CONF_SYSLOG_IDENTITY,
|
||||
CONF_SYSLOG_FACILITY,
|
||||
@@ -567,6 +579,7 @@ typedef struct fko_srv_options
|
||||
unsigned char test; /* Test mode flag */
|
||||
unsigned char verbose; /* Verbose mode flag */
|
||||
unsigned char exit_after_parse_config; /* Parse config and exit */
|
||||
unsigned char enable_udp_server; /* Enable UDP server mode */
|
||||
|
||||
unsigned char firewd_disable_check_support; /* Don't use firewall-cmd ... -C */
|
||||
unsigned char ipt_disable_check_support; /* Don't use iptables -C */
|
||||
|
||||
+9
-18
@@ -28,12 +28,13 @@
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <pcap.h>
|
||||
|
||||
#include "fwknopd_common.h"
|
||||
#include "pcap_capture.h"
|
||||
#include "process_packet.h"
|
||||
#include "sig_handler.h"
|
||||
#include "fw_util.h"
|
||||
#include "log_msg.h"
|
||||
#include "fwknopd_errors.h"
|
||||
@@ -44,6 +45,8 @@
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#if USE_LIBPCAP
|
||||
|
||||
/* The pcap capture routine.
|
||||
*/
|
||||
int
|
||||
@@ -247,24 +250,10 @@ pcap_capture(fko_srv_options_t *opts)
|
||||
got_sigchld = 0;
|
||||
}
|
||||
|
||||
/* Any signal except USR1, USR2, and SIGCHLD mean break the loop.
|
||||
*/
|
||||
if(got_signal != 0)
|
||||
if(sig_do_stop())
|
||||
{
|
||||
if(got_sigint || got_sigterm || got_sighup)
|
||||
{
|
||||
pcap_breakloop(pcap);
|
||||
pending_break = 1;
|
||||
}
|
||||
else if(got_sigusr1 || got_sigusr2)
|
||||
{
|
||||
/* Not doing anything with these yet.
|
||||
*/
|
||||
got_sigusr1 = got_sigusr2 = 0;
|
||||
got_signal = 0;
|
||||
}
|
||||
else
|
||||
got_signal = 0;
|
||||
pcap_breakloop(pcap);
|
||||
pending_break = 1;
|
||||
}
|
||||
|
||||
res = pcap_dispatch(pcap, pcap_dispatch_count,
|
||||
@@ -347,4 +336,6 @@ pcap_capture(fko_srv_options_t *opts)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* USE_LIBPCAP */
|
||||
|
||||
/***EOF***/
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
#if USE_LIBPCAP
|
||||
void process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, const unsigned char *packet);
|
||||
#endif
|
||||
|
||||
#endif /* PROCESS_PACKET_H */
|
||||
|
||||
@@ -148,4 +148,28 @@ set_sig_handlers(void)
|
||||
return(err);
|
||||
}
|
||||
|
||||
int
|
||||
sig_do_stop(void)
|
||||
{
|
||||
/* Any signal except USR1, USR2, and SIGCHLD mean break the loop.
|
||||
*/
|
||||
if(got_signal != 0)
|
||||
{
|
||||
if(got_sigint || got_sigterm || got_sighup)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if(got_sigusr1 || got_sigusr2)
|
||||
{
|
||||
/* Not doing anything with these yet.
|
||||
*/
|
||||
got_sigusr1 = got_sigusr2 = 0;
|
||||
got_signal = 0;
|
||||
}
|
||||
else
|
||||
got_signal = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***EOF***/
|
||||
|
||||
@@ -44,6 +44,7 @@ extern sig_atomic_t got_sigchld;
|
||||
|
||||
void sig_handler(int sig);
|
||||
int set_sig_handlers(void);
|
||||
int sig_do_stop(void);
|
||||
|
||||
#endif /* SIG_HANDLER_H */
|
||||
|
||||
|
||||
+2
-2
@@ -169,13 +169,13 @@ run_tcp_server(fko_srv_options_t *opts)
|
||||
return -1;
|
||||
}
|
||||
|
||||
clen = sizeof(caddr);
|
||||
|
||||
/* Now loop and accept and drop connections after the first packet or a
|
||||
* short timeout.
|
||||
*/
|
||||
while(1)
|
||||
{
|
||||
clen = sizeof(caddr);
|
||||
|
||||
/* Initialize and setup the socket for select.
|
||||
*/
|
||||
FD_ZERO(&sfd_set);
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: udp_server.c
|
||||
*
|
||||
* Purpose: Collect SPA packets via a UDP server.
|
||||
*
|
||||
* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
|
||||
* Copyright (C) 2009-2014 fwknop developers and contributors. For a full
|
||||
* list of contributors, see the file 'CREDITS'.
|
||||
*
|
||||
* License (GNU General Public License):
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fwknopd_common.h"
|
||||
#include "sig_handler.h"
|
||||
#include "incoming_spa.h"
|
||||
#include "log_msg.h"
|
||||
#include "fw_util.h"
|
||||
#include "utils.h"
|
||||
#include <errno.h>
|
||||
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#if HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#if HAVE_NETDB
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
int
|
||||
run_udp_server(fko_srv_options_t *opts)
|
||||
{
|
||||
int s_sock, sfd_flags, selval, pkt_len;
|
||||
int is_err, s_timeout;
|
||||
fd_set sfd_set;
|
||||
struct sockaddr_in saddr, caddr;
|
||||
struct timeval tv;
|
||||
char sipbuf[MAX_IPV4_STR_LEN] = {0};
|
||||
char dgram_msg[MAX_SPA_PACKET_LEN+1] = {0};
|
||||
unsigned short port;
|
||||
socklen_t clen;
|
||||
|
||||
port = strtol_wrapper(opts->config[CONF_UDPSERV_PORT],
|
||||
1, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
|
||||
if(is_err != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_ERR, "[*] Invalid max UDPSERV_PORT value.");
|
||||
return -1;
|
||||
}
|
||||
s_timeout = strtol_wrapper(opts->config[CONF_UDPSERV_SELECT_TIMEOUT],
|
||||
1, RCHK_MAX_UDPSERV_SELECT_TIMEOUT, NO_EXIT_UPON_ERR, &is_err);
|
||||
if(is_err != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_ERR, "[*] Invalid max UDPSERV_SELECT_TIMEOUT value.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_msg(LOG_INFO, "Kicking off UDP server to listen on port %i.", port);
|
||||
|
||||
/* Now, let's make a UDP server
|
||||
*/
|
||||
if ((s_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "run_udp_server: socket() failed: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make our main socket non-blocking so we don't have to be stuck on
|
||||
* listening for incoming datagrams.
|
||||
*/
|
||||
if((sfd_flags = fcntl(s_sock, F_GETFL, 0)) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "run_udp_server: fcntl F_GETFL error: %s",
|
||||
strerror(errno));
|
||||
close(s_sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sfd_flags |= O_NONBLOCK;
|
||||
|
||||
if(fcntl(s_sock, F_SETFL, sfd_flags) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "run_udp_server: fcntl F_SETFL error setting O_NONBLOCK: %s",
|
||||
strerror(errno));
|
||||
close(s_sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Construct local address structure */
|
||||
memset(&saddr, 0x0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET; /* Internet address family */
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
|
||||
saddr.sin_port = htons(port); /* Local port */
|
||||
|
||||
/* Bind to the local address */
|
||||
if (bind(s_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "run_udp_server: bind() failed: %s",
|
||||
strerror(errno));
|
||||
close(s_sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize our signal handlers. You can check the return value for
|
||||
* the number of signals that were *not* set. Those that were not set
|
||||
* will be listed in the log/stderr output.
|
||||
*/
|
||||
if(set_sig_handlers() > 0)
|
||||
log_msg(LOG_ERR, "Errors encountered when setting signal handlers.");
|
||||
|
||||
/* Now loop and receive SPA packets
|
||||
*/
|
||||
while(1)
|
||||
{
|
||||
if(sig_do_stop())
|
||||
{
|
||||
close(s_sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check for any expired firewall rules and deal with them.
|
||||
*/
|
||||
if(!opts->test)
|
||||
check_firewall_rules(opts);
|
||||
|
||||
/* Initialize and setup the socket for select.
|
||||
*/
|
||||
FD_ZERO(&sfd_set);
|
||||
FD_SET(s_sock, &sfd_set);
|
||||
|
||||
/* Set our select timeout to (500ms by default).
|
||||
*/
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = s_timeout;
|
||||
|
||||
selval = select(s_sock+1, &sfd_set, NULL, NULL, &tv);
|
||||
|
||||
if(selval == -1)
|
||||
{
|
||||
/* Select error so bail
|
||||
*/
|
||||
log_msg(LOG_ERR, "run_udp_server: select error socket: %s",
|
||||
strerror(errno));
|
||||
close(s_sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(selval == 0)
|
||||
continue;
|
||||
|
||||
/* If we make it here then there is a datagram to process
|
||||
*/
|
||||
clen = sizeof(caddr);
|
||||
|
||||
pkt_len = recvfrom(s_sock, dgram_msg, MAX_SPA_PACKET_LEN,
|
||||
0, (struct sockaddr *)&caddr, &clen);
|
||||
|
||||
dgram_msg[pkt_len] = 0x0;
|
||||
|
||||
if(opts->verbose)
|
||||
{
|
||||
memset(sipbuf, 0x0, MAX_IPV4_STR_LEN);
|
||||
inet_ntop(AF_INET, &(caddr.sin_addr.s_addr), sipbuf, MAX_IPV4_STR_LEN);
|
||||
log_msg(LOG_INFO, "udp_server: Got UDP datagram (%d bytes) from: %s",
|
||||
pkt_len, sipbuf);
|
||||
}
|
||||
|
||||
/* Expect the data to not be too large
|
||||
*/
|
||||
if(pkt_len <= MAX_SPA_PACKET_LEN)
|
||||
{
|
||||
/* Copy the packet for SPA processing
|
||||
*/
|
||||
strlcpy((char *)opts->spa_pkt.packet_data, dgram_msg, pkt_len+1);
|
||||
opts->spa_pkt.packet_data_len = pkt_len;
|
||||
opts->spa_pkt.packet_proto = IPPROTO_UDP;
|
||||
opts->spa_pkt.packet_src_ip = caddr.sin_addr.s_addr;
|
||||
opts->spa_pkt.packet_dst_ip = saddr.sin_addr.s_addr;
|
||||
opts->spa_pkt.packet_src_port = ntohs(caddr.sin_port);
|
||||
opts->spa_pkt.packet_dst_port = ntohs(saddr.sin_port);
|
||||
|
||||
incoming_spa(opts);
|
||||
}
|
||||
|
||||
memset(dgram_msg, 0x0, sizeof(dgram_msg));
|
||||
|
||||
opts->packet_ctr += 1;
|
||||
if(opts->foreground == 1 && opts->verbose > 2)
|
||||
log_msg(LOG_DEBUG, "run_udp_server() processed: %d packets",
|
||||
opts->packet_ctr);
|
||||
|
||||
/* Count the set of processed packets (pcap_dispatch() return
|
||||
* value) - we use this as a comparison for --packet-limit regardless
|
||||
* of SPA packet validity at this point.
|
||||
*/
|
||||
if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"* Incoming packet count limit of %i reached",
|
||||
opts->packet_ctr_limit
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} /* infinite while loop */
|
||||
|
||||
close(s_sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***EOF***/
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: udp_server.h
|
||||
*
|
||||
* Purpose: Header file for udp_server.c.
|
||||
*
|
||||
* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
|
||||
* Copyright (C) 2009-2014 fwknop developers and contributors. For a full
|
||||
* list of contributors, see the file 'CREDITS'.
|
||||
*
|
||||
* License (GNU General Public License):
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef UDP_SERVER_H
|
||||
#define UDP_SERVER_H
|
||||
|
||||
/* Function prototypes
|
||||
*/
|
||||
int run_udp_server(fko_srv_options_t *opts);
|
||||
|
||||
#endif /* UDP_SERVER_H */
|
||||
|
||||
/***EOF***/
|
||||
@@ -0,0 +1,2 @@
|
||||
ENABLE_UDP_SERVER Y;
|
||||
UDPSERV_PORT 62201;
|
||||
@@ -126,6 +126,7 @@ our %cf = (
|
||||
'gpg_no_sig_verify_access' => "$conf_dir/gpg_no_sig_verify_access.conf",
|
||||
'gpg_invalid_sig_id_access' => "$conf_dir/gpg_invalid_sig_id_access.conf",
|
||||
'tcp_server' => "$conf_dir/tcp_server_fwknopd.conf",
|
||||
'udp_server' => "$conf_dir/udp_server_fwknopd.conf",
|
||||
'spa_over_http' => "$conf_dir/spa_over_http_fwknopd.conf",
|
||||
'tcp_pcap_filter' => "$conf_dir/tcp_pcap_filter_fwknopd.conf",
|
||||
'icmp_pcap_filter' => "$conf_dir/icmp_pcap_filter_fwknopd.conf",
|
||||
|
||||
@@ -2494,6 +2494,14 @@
|
||||
'function' => \&server_packet_limit,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
|
||||
},
|
||||
{
|
||||
'category' => 'basic operations',
|
||||
'subcategory' => 'server',
|
||||
'detail' => 'UDP server --packet-limit 1 exit',
|
||||
'function' => \&server_packet_limit,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd $default_server_conf_args --udp-server --packet-limit 1 $intf_str",
|
||||
},
|
||||
|
||||
{
|
||||
'category' => 'basic operations',
|
||||
'subcategory' => 'server',
|
||||
@@ -2586,6 +2594,38 @@
|
||||
],
|
||||
'positive_output_matches' => [qr/invalid\sPCAP_DISPATCH_COUNT/],
|
||||
},
|
||||
{
|
||||
'category' => 'basic operations',
|
||||
'subcategory' => 'server',
|
||||
'detail' => 'invalid tcp server port',
|
||||
'function' => \&server_conf_files,
|
||||
'fwknopd_cmdline' => $server_rewrite_conf_files,
|
||||
'exec_err' => $YES,
|
||||
'server_access_file' => [
|
||||
'SOURCE any',
|
||||
'KEY testtest',
|
||||
],
|
||||
'server_conf_file' => [
|
||||
'TCPSERV_PORT 9999999999'
|
||||
],
|
||||
'positive_output_matches' => [qr/not in the range/],
|
||||
},
|
||||
{
|
||||
'category' => 'basic operations',
|
||||
'subcategory' => 'server',
|
||||
'detail' => 'invalid udp server port',
|
||||
'function' => \&server_conf_files,
|
||||
'fwknopd_cmdline' => $server_rewrite_conf_files,
|
||||
'exec_err' => $YES,
|
||||
'server_access_file' => [
|
||||
'SOURCE any',
|
||||
'KEY testtest',
|
||||
],
|
||||
'server_conf_file' => [
|
||||
'UDPSERV_PORT 9999999999'
|
||||
],
|
||||
'positive_output_matches' => [qr/not in the range/],
|
||||
},
|
||||
|
||||
{
|
||||
'category' => 'basic operations',
|
||||
|
||||
@@ -621,6 +621,27 @@
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "UDP server --udp-server / tcp/22",
|
||||
'function' => \&spa_cycle,
|
||||
'cmdline' => $default_client_args,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd $default_server_conf_args $intf_str --udp-server",
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "UDP server conf / tcp/22",
|
||||
'function' => \&spa_cycle,
|
||||
'cmdline' => $default_client_args,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'udp_server'} -a $cf{'def_access'} " .
|
||||
"-d $default_digest_file -p $default_pid_file $intf_str",
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
},
|
||||
|
||||
{
|
||||
'category' => 'Rijndael',
|
||||
|
||||
@@ -970,6 +970,30 @@
|
||||
'key_file' => $cf{'rc_hmac_sha512_short_key'},
|
||||
},
|
||||
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "UDP server --udp-server / tcp/22",
|
||||
'function' => \&spa_cycle,
|
||||
'cmdline' => $default_client_hmac_args,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
|
||||
"-d $default_digest_file -p $default_pid_file $intf_str --udp-server",
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "UDP server conf / tcp/22",
|
||||
'function' => \&spa_cycle,
|
||||
'cmdline' => $default_client_hmac_args,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'udp_server'} -a $cf{'hmac_access'} " .
|
||||
"-d $default_digest_file -p $default_pid_file $intf_str",
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client',
|
||||
|
||||
@@ -29,4 +29,13 @@
|
||||
'fwknopd_cmdline' => "$fwknopdCmd $default_server_conf_args $intf_str",
|
||||
'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => 'UDP server replay detection',
|
||||
'function' => \&replay_detection,
|
||||
'cmdline' => $default_client_args,
|
||||
'fwknopd_cmdline' => "$fwknopdCmd $default_server_conf_args $intf_str --udp-server",
|
||||
'server_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user