first cut at UDP server mode

This commit is contained in:
Michael Rash 2014-09-28 11:49:04 -04:00
parent c07afac883
commit 1fd0e7e960
11 changed files with 451 additions and 7 deletions

View File

@ -166,6 +166,20 @@ 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 listener mode (no libpcap dependency)
dnl
want_udp_listener=no
AC_ARG_ENABLE([udp-listener],
[AS_HELP_STRING([--enable-udp-listener],
[Enable UDP listener mode (no libpcap dependency) @<:@default is to disable@:>@])],
[want_udp_listener=$enableval],
[])
AM_CONDITIONAL([UDP_LISTENER], [test "$want_udp_listener" = yes])
#if test "$want_udp_listener" = yes; then
# AC_DEFINE([UDP_LISTENER], [1], [Define for UDP listener mode])
#fi
dnl Decide whether or not to enable all warnings with -Wall
dnl
use_wall=yes
@ -430,12 +444,18 @@ 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], [
use_libpcap=no
AS_IF([test "$want_udp_listener" = no], [
# Looking for libpcap
#
AC_CHECK_LIB([pcap],[pcap_open_live],
[ AC_DEFINE([HAVE_LIBPCAP], [1], [Define if you have libpcap]) ],
[ AC_MSG_ERROR([fwknopd needs libpcap])]
)
use_libpcap=yes
])
AM_CONDITIONAL([USE_LIBPCAP], [test x$use_libpcap = xyes])
AS_IF([test "$want_digest_cache" = yes], [
use_ndbm=no
@ -674,6 +694,10 @@ if [test "$want_server" = "yes" ]; then
firewall type: $FIREWALL_TYPE
firewall program path: $FIREWALL_EXE
"
if [test "$want_udp_listener" = "yes" ]; then
echo " UDP listener mode enabled, no libpcap dependency
"
fi
if [test "$want_digest_cache" = "no" ]; then
echo " *WARNING*

View File

@ -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 USE_LIBPCAP
fwknopd_LDADD += -lpcap
endif
if !CONFIG_FILE_CACHE
if USE_NDBM
fwknopd_LDADD += -lndbm
else

View File

@ -57,6 +57,8 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
"ENABLE_SPA_OVER_HTTP",
"ENABLE_TCP_SERVER",
"TCPSERV_PORT",
"ENABLE_UDP_SERVER",
"UDPSERV_PORT",
"LOCALE",
"SYSLOG_IDENTITY",
"SYSLOG_FACILITY",
@ -186,6 +188,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}

View File

@ -151,6 +151,8 @@ 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);
#if FIREWALL_IPFW
range_check(opts, "IPFW_START_RULE_NUM", opts->config[CONF_IPFW_START_RULE_NUM],
@ -808,6 +810,16 @@ 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)
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);
/* Syslog identity.
*/
if(opts->config[CONF_SYSLOG_IDENTITY] == NULL)
@ -1113,6 +1125,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++;

View File

@ -31,7 +31,6 @@
#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"
@ -39,6 +38,7 @@
#include "sig_handler.h"
#include "replay_cache.h"
#include "tcp_server.h"
#include "udp_server.h"
/* Prototypes
*/
@ -178,7 +178,20 @@ 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(1 || 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);
}
}
/* 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 +202,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

View File

@ -101,6 +101,8 @@
#define DEF_ENABLE_SPA_OVER_HTTP "N"
#define DEF_ENABLE_TCP_SERVER "N"
#define DEF_TCPSERV_PORT "62201"
#define DEF_ENABLE_UDP_SERVER "N"
#define DEF_UDPSERV_PORT "62201"
#define DEF_SYSLOG_IDENTITY MY_NAME
#define DEF_SYSLOG_FACILITY "LOG_DAEMON"
@ -112,6 +114,7 @@
#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_PCAP_DISPATCH_COUNT (2 << 22)
#define RCHK_MAX_FW_TIMEOUT (2 << 22)
@ -225,6 +228,8 @@ enum {
CONF_ENABLE_SPA_OVER_HTTP,
CONF_ENABLE_TCP_SERVER,
CONF_TCPSERV_PORT,
CONF_ENABLE_UDP_SERVER,
CONF_UDPSERV_PORT,
CONF_LOCALE,
CONF_SYSLOG_IDENTITY,
CONF_SYSLOG_FACILITY,
@ -565,6 +570,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 */

View File

@ -28,6 +28,9 @@
*
*****************************************************************************
*/
#if HAVE_LIBPCAP
#include <pcap.h>
#include "fwknopd_common.h"
@ -347,4 +350,6 @@ pcap_capture(fko_srv_options_t *opts)
return(0);
}
#endif /* HAVE_LIBPCAP */
/***EOF***/

View File

@ -46,6 +46,8 @@
/* Prototypes
*/
#if HAVE_LIBPCAP
void process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header, const unsigned char *packet);
#endif
#endif /* PROCESS_PACKET_H */

211
server/udp_server.c Normal file
View File

@ -0,0 +1,211 @@
/*
*****************************************************************************
*
* 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 "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 reuse_addr = 1, is_err;
int is_err;
fd_set sfd_set;
struct sockaddr_in saddr, caddr;
struct timeval tv;
char sipbuf[MAX_IPV4_STR_LEN] = {0};
char msg[5000];
socklen_t clen;
unsigned short port;
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;
}
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;
}
/* So that we can re-bind to it without TIME_WAIT problems
if(setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) == -1)
{
log_msg(LOG_ERR, "run_udp_server: setsockopt error: %s",
strerror(errno));
close(s_sock);
return -1;
}
*/
/* Make our main socket non-blocking so we don't have to be stuck on
* listening for incoming connections.
*/
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, 0, 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;
}
/* Mark the socket so it will listen for incoming connections
* (but only one at a time)
if (listen(s_sock, 1) < 0)
{
log_msg(LOG_ERR, "run_udp_server: listen() failed: %s",
strerror(errno));
close(s_sock);
return -1;
}
*/
/* Now loop and receive SPA packets
*/
while(1)
{
/* Check for any expired firewall rules and deal with them.
*/
if(!opts->test)
check_firewall_rules(opts);
clen = sizeof(caddr);
/* Initialize and setup the socket for select.
*/
FD_ZERO(&sfd_set);
FD_SET(s_sock, &sfd_set);
/* Set our select timeout to 500 ms.
*/
tv.tv_sec = 0;
tv.tv_usec = 500000;
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;
pkt_len = recvfrom(s_sock, msg, 5000, 0, (struct sockaddr *)&caddr, &clen);
printf("-------------------------------------------------------\n");
msg[pkt_len] = 0;
printf("Received %d bytes:\n", pkt_len);
printf("%s",msg);
printf("\n-------------------------------------------------------\n");
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 connection from %s.", sipbuf);
}
/* Copy the packet for SPA processing
*/
strlcpy((char *)opts->spa_pkt.packet_data, 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);
usleep(1000000);
} /* infinite while loop */
return 1;
}
/***EOF***/

117
server/udp_server.c.orig Normal file
View File

@ -0,0 +1,117 @@
/*
*****************************************************************************
*
* 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 "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 is_err, pkt_len, sock_fd = 0;
char msg[5000];
struct sockaddr_in saddr, caddr;
char sipbuf[MAX_IPV4_STR_LEN] = {0};
unsigned short port;
socklen_t len;
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;
}
log_msg(LOG_INFO, "Kicking off UDP server to listen on port %i.", port);
/* Now, let's make a UDP server
*/
sock_fd = socket(AF_INET,SOCK_DGRAM,0);
bzero(&saddr,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
saddr.sin_port=htons(port);
bind(sock_fd,(struct sockaddr *)&saddr,sizeof(saddr));
while(1)
{
len = sizeof(caddr);
pkt_len = recvfrom(sock_fd,msg,5000,0,(struct sockaddr *)&caddr,&len);
//sendto(sock_fd,msg,pkt_len,0,(struct sockaddr *)&caddr,sizeof(caddr));
printf("-------------------------------------------------------\n");
msg[pkt_len] = 0;
printf("Received %d bytes:\n", pkt_len);
printf("%s",msg);
printf("\n-------------------------------------------------------\n");
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 from %s.", sipbuf);
/* Copy the packet for SPA processing
*/
strlcpy((char *)opts->spa_pkt.packet_data, 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);
/* Check for any expired firewall rules and deal with them.
*/
if(!opts->test)
check_firewall_rules(opts);
}
return 1;
}
/***EOF***/

40
server/udp_server.h Normal file
View File

@ -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***/