From 9d187da615cf7481ab5efe896584be5b7be1c2fd Mon Sep 17 00:00:00 2001 From: Peter Haag Date: Sun, 24 Jun 2018 12:42:05 +0200 Subject: [PATCH] Add multiple packet repeaters to nfcapd/sfcapd --- ChangeLog | 1 + bin/nfcapd.c | 53 ++++++++++++++++++++++++++++++++++------------------ bin/nfnet.c | 27 +++++++++++++------------- bin/nfnet.h | 11 +++++++++++ bin/sfcapd.c | 53 +++++++++++++++++++++++++++++++++++----------------- man/nfcapd.1 | 2 +- man/sfcapd.1 | 2 +- 7 files changed, 98 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 152f584..12c2ad5 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2018-06-24 - Fix bookkeeper type - use key_t +- Add multiple packet repeaters to nfcapd/sfcapd. Up to 8 repeaters (-R) can be defined. 2018-05-06 - New bookkeeper hash broke NfSen. Fixed. ported back to release 1.6.17 diff --git a/bin/nfcapd.c b/bin/nfcapd.c index 61a5ca3..c670e6d 100644 --- a/bin/nfcapd.c +++ b/bin/nfcapd.c @@ -146,7 +146,7 @@ static void daemonize(void); static void SetPriv(char *userid, char *groupid ); -static void run(packet_function_t receive_packet, int socket, send_peer_t peer, +static void run(packet_function_t receive_packet, int socket, repeater_t *repeater, time_t twin, time_t t_begin, int report_seq, int use_subdirs, char *time_extension, int compress); /* Functions */ @@ -166,7 +166,7 @@ static void usage(char *name) { "-H Add port histogram data to flow file.(default 'no')\n" "-n Ident,IP,logdir\tAdd this flow source - multiple streams\n" "-P pidfile\tset the PID file\n" - "-R IP[/port]\tRepeat incoming packets to IP address/port\n" + "-R IP[/port]\tRepeat incoming packets to IP address/port. Max 8 repeaters.\n" "-s rate\tset default sampling rate (default 1)\n" "-x process\tlaunch process after a new file becomes available\n" "-z\t\tLZO compress flows in output file.\n" @@ -358,7 +358,7 @@ int err; #include "nffile_inline.c" #include "collector_inline.c" -static void run(packet_function_t receive_packet, int socket, send_peer_t peer, +static void run(packet_function_t receive_packet, int socket, repeater_t *repeater, time_t twin, time_t t_begin, int report_seq, int use_subdirs, char *time_extension, int compress) { common_flow_header_t *nf_header; FlowSource_t *fs; @@ -422,6 +422,7 @@ srecord_t *commbuff; */ while ( 1 ) { struct timeval tv; + int i; /* read next bunch of data into beginn of input buffer */ if ( !done) { @@ -443,12 +444,15 @@ srecord_t *commbuff; continue; } - if ( peer.hostname ) { + i = 0; + while ( repeater[i].hostname && (i < MAX_REPEATERS)) { ssize_t len; - len = sendto(peer.sockfd, in_buff, cnt, 0, (struct sockaddr *)&(peer.addr), peer.addrlen); + len = sendto(repeater[i].sockfd, in_buff, cnt, 0, + (struct sockaddr *)&(repeater[i].addr), repeater[i].addrlen); if ( len < 0 ) { LogError("ERROR: sendto(): %s", strerror(errno)); } + i++; } } @@ -745,14 +749,14 @@ char *userid, *groupid, *checkptr, *listenport, *mcastgroup, *extension_tags; char *Ident, *dynsrcdir, *time_extension, pidfile[MAXPATHLEN]; struct stat fstat; packet_function_t receive_packet; -send_peer_t peer; +repeater_t repeater[MAX_REPEATERS]; FlowSource_t *fs; struct sigaction act; int family, bufflen; time_t twin, t_start; int sock, synctime, do_daemonize, expire, spec_time_extension, report_sequence; int subdir_index, sampling_rate, compress; -int c; +int c, i; #ifdef PCAP char *pcap_file; @@ -780,8 +784,10 @@ char *pcap_file; expire = 0; sampling_rate = 1; compress = NOT_COMPRESSED; - memset((void *)&peer, 0, sizeof(send_peer_t)); - peer.family = AF_UNSPEC; + memset((void *)&repeater, 0, sizeof(repeater)); + for ( i = 0; i < MAX_REPEATERS; i++ ) { + repeater[i].family = AF_UNSPEC; + } Ident = "none"; FlowSource = NULL; extension_tags = DefaultExtensions; @@ -886,14 +892,23 @@ char *pcap_file; pidfile[MAXPATHLEN-1] = 0; break; case 'R': { + char *port, *hostname; char *p = strchr(optarg, '/'); + int i = 0; if ( p ) { *p++ = '\0'; - peer.port = strdup(p); + port = strdup(p); } else { - peer.port = DEFAULTCISCOPORT; + port = DEFAULTCISCOPORT; } - peer.hostname = strdup(optarg); + hostname = strdup(optarg); + while ( repeater[i].hostname && (i < MAX_REPEATERS) ) i++; + if ( i == MAX_REPEATERS ) { + fprintf(stderr, "Too many packet repeaters! Max: %i repeaters allowed.\n", MAX_REPEATERS); + exit(255); + } + repeater[i].hostname = hostname; + repeater[i].port = port; break; } case 'r': @@ -1040,12 +1055,14 @@ char *pcap_file; exit(255); } - if ( peer.hostname ) { - peer.sockfd = Unicast_send_socket (peer.hostname, peer.port, peer.family, bufflen, - &peer.addr, &peer.addrlen ); - if ( peer.sockfd <= 0 ) + i = 0; + while ( repeater[i].hostname && (i < MAX_REPEATERS) ) { + repeater[i].sockfd = Unicast_send_socket (repeater[i].hostname, repeater[i].port, repeater[i].family, bufflen, + &repeater[i].addr, &repeater[i].addrlen ); + if ( repeater[i].sockfd <= 0 ) exit(255); - LogInfo("Replay flows to host: %s port: %s", peer.hostname, peer.port); + LogInfo("Replay flows to host: %s port: %s", repeater[i].hostname, repeater[i].port); + i++; } if ( sampling_rate < 0 ) { @@ -1205,7 +1222,7 @@ char *pcap_file; sigaction(SIGCHLD, &act, NULL); LogInfo("Startup."); - run(receive_packet, sock, peer, twin, t_start, report_sequence, subdir_index, + run(receive_packet, sock, repeater, twin, t_start, report_sequence, subdir_index, time_extension, compress); close(sock); kill_launcher(launcher_pid); diff --git a/bin/nfnet.c b/bin/nfnet.c index 5cccd70..1aefc25 100644 --- a/bin/nfnet.c +++ b/bin/nfnet.c @@ -178,12 +178,11 @@ int error, p, sockfd; int Unicast_send_socket (const char *hostname, const char *sendport, int family, unsigned int wmem_size, struct sockaddr_storage *addr, int *addrlen) { struct addrinfo hints, *res, *ressave; -int n, sockfd; +int error, sockfd; unsigned int wmem_actual; socklen_t optlen; if ( !hostname || !sendport ) { - fprintf(stderr, "hostname and listen port required!\n"); LogError("hostname and listen port required!"); return -1; } @@ -194,10 +193,9 @@ socklen_t optlen; hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; - n = getaddrinfo(hostname, sendport, &hints, &res); - - if ( n < 0 ) { - fprintf(stderr, "getaddrinfo error: [%s]\n", strerror(errno)); + error = getaddrinfo(hostname, sendport, &hints, &res); + if ( error ) { + LogError("getaddrinfo() error: %s", gai_strerror(error)); return -1; } @@ -205,27 +203,28 @@ socklen_t optlen; sockfd = -1; while (res) { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - if ( !(sockfd < 0) ) { + if ( sockfd < 0 ) { + LogError("socket() error: could not open the requested socket: %s", strerror (errno)); + } else { // socket call was successsful - if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) { + if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) { + // unsuccessful connect :( + LogError("connect() error: could not open the requested socket: %s", strerror (errno)); + close(sockfd); + sockfd = -1; + } else { // connect successful - we are done close(sockfd); // ok - we need now an unconnected socket sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); break; } - // unsuccessful connect :( - close(sockfd); - sockfd = -1; } res=res->ai_next; } if (sockfd < 0) { freeaddrinfo(ressave); - fprintf(stderr, "Send socket error: could not open the requested socket: %s\n", strerror (errno)); - LogError("Send socket error: could not open the requested socket: %s", strerror (errno)); return -1; } diff --git a/bin/nfnet.h b/bin/nfnet.h index e95c5a8..c6737b9 100644 --- a/bin/nfnet.h +++ b/bin/nfnet.h @@ -57,6 +57,17 @@ typedef struct send_peer_s { void *endp; } send_peer_t; +typedef struct repeater_s { + char *hostname; + char *port; + struct sockaddr_storage addr; + int addrlen; + int family; + int sockfd; +} repeater_t; + +#define MAX_REPEATERS 8 + /* Function prototypes */ int Unicast_receive_socket(const char *bindhost, const char *listenport, int family, int sockbuflen ); diff --git a/bin/sfcapd.c b/bin/sfcapd.c index b2a7b74..5443786 100644 --- a/bin/sfcapd.c +++ b/bin/sfcapd.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018, Peter Haag * Copyright (c) 2017, Peter Haag * Copyright (c) 2016, Peter Haag * Copyright (c) 2014, Peter Haag @@ -124,7 +125,7 @@ static void daemonize(void); static void SetPriv(char *userid, char *groupid ); -static void run(packet_function_t receive_packet, int socket, send_peer_t peer, +static void run(packet_function_t receive_packet, int socket, repeater_t *repeater, time_t twin, time_t t_begin, int report_seq, int use_subdirs, char *time_extension, int compress); /* Functions */ @@ -144,7 +145,7 @@ static void usage(char *name) { "-H Add port histogram data to flow file.(default 'no')\n" "-n Ident,IP,logdir\tAdd this flow source - multiple streams\n" "-P pidfile\tset the PID file\n" - "-R IP[/port]\tRepeat incoming packets to IP address/port\n" + "-R IP[/port]\tRepeat incoming packets to IP address/port. Max 8 repeaters\n" "-x process\tlaunch process after a new file becomes available\n" "-z\t\tLZO compress flows in output file.\n" "-y\t\tLZ4 compress flows in output file.\n" @@ -332,7 +333,7 @@ int err; #include "nffile_inline.c" #include "collector_inline.c" -static void run(packet_function_t receive_packet, int socket, send_peer_t peer, +static void run(packet_function_t receive_packet, int socket, repeater_t *repeater, time_t twin, time_t t_begin, int report_seq, int use_subdirs, char *time_extension, int compress) { FlowSource_t *fs; struct sockaddr_storage sf_sender; @@ -393,6 +394,7 @@ srecord_t *commbuff; */ while ( 1 ) { struct timeval tv; + int i; /* read next bunch of data into beginn of input buffer */ if ( !done) { @@ -415,12 +417,15 @@ srecord_t *commbuff; continue; } - if ( peer.hostname ) { + i = 0; + while ( repeater[i].hostname && (i < MAX_REPEATERS)) { ssize_t len; - len = sendto(peer.sockfd, in_buff, cnt, 0, (struct sockaddr *)&(peer.addr), peer.addrlen); + len = sendto(repeater[i].sockfd, in_buff, cnt, 0, + (struct sockaddr *)&(repeater[i].addr), repeater[i].addrlen); if ( len < 0 ) { LogError("ERROR: sendto(): %s", strerror(errno)); } + i++; } } @@ -658,14 +663,14 @@ char *userid, *groupid, *checkptr, *listenport, *mcastgroup, *extension_tags; char *Ident, *pcap_file, *time_extension, pidfile[MAXPATHLEN]; struct stat fstat; packet_function_t receive_packet; -send_peer_t peer; +repeater_t repeater[MAX_REPEATERS]; FlowSource_t *fs; struct sigaction act; int family, bufflen; time_t twin, t_start; int sock, synctime, do_daemonize, expire, spec_time_extension, report_sequence; int subdir_index, compress; -int c; +int c, i; receive_packet = recvfrom; verbose = synctime = do_daemonize = 0; @@ -687,8 +692,10 @@ int c; expire = 0; spec_time_extension = 0; compress = NOT_COMPRESSED; - memset((void *)&peer, 0, sizeof(send_peer_t)); - peer.family = AF_UNSPEC; + memset((void *)&repeater, 0, sizeof(repeater)); + for ( i = 0; i < MAX_REPEATERS; i++ ) { + repeater[i].family = AF_UNSPEC; + } Ident = "none"; FlowSource = NULL; extension_tags = DefaultExtensions; @@ -794,14 +801,23 @@ int c; pidfile[MAXPATHLEN-1] = 0; break; case 'R': { + char *port, *hostname; char *p = strchr(optarg, '/'); + int i = 0; if ( p ) { *p++ = '\0'; - peer.port = strdup(p); + port = strdup(p); } else { - peer.port = DEFAULTSFLOWPORT; + port = DEFAULTSFLOWPORT; } - peer.hostname = strdup(optarg); + hostname = strdup(optarg); + while ( repeater[i].hostname && (i < MAX_REPEATERS) ) i++; + if ( i == MAX_REPEATERS ) { + fprintf(stderr, "Too many packet repeaters! Max: %i repeaters allowed.\n", MAX_REPEATERS); + exit(255); + } + repeater[i].hostname = hostname; + repeater[i].port = port; break; } case 'r': @@ -914,11 +930,14 @@ int c; exit(255); } - if ( peer.hostname ) { - peer.sockfd = Unicast_send_socket (peer.hostname, peer.port, peer.family, bufflen, - &peer.addr, &peer.addrlen ); - if ( peer.sockfd <= 0 ) + i = 0; + while ( repeater[i].hostname && (i < MAX_REPEATERS) ) { + repeater[i].sockfd = Unicast_send_socket (repeater[i].hostname, repeater[i].port, repeater[i].family, bufflen, + &repeater[i].addr, &repeater[i].addrlen ); + if ( repeater[i].sockfd <= 0 ) exit(255); + LogInfo("Replay flows to host: %s port: %s", repeater[i].hostname, repeater[i].port); + i++; } SetPriv(userid, groupid); @@ -1071,7 +1090,7 @@ int c; sigaction(SIGCHLD, &act, NULL); LogInfo("Startup."); - run(receive_packet, sock, peer, twin, t_start, report_sequence, subdir_index, + run(receive_packet, sock, repeater, twin, t_start, report_sequence, subdir_index, time_extension, compress); close(sock); kill_launcher(launcher_pid); diff --git a/man/nfcapd.1 b/man/nfcapd.1 index 5395fa1..71c6368 100755 --- a/man/nfcapd.1 +++ b/man/nfcapd.1 @@ -65,7 +65,7 @@ Join the specified IPv4 or IPv6 multicast group for listening. Enable packet repeater. Send all incoming packets to another \fIhost\fR and \fIport\fR. \fIhost\fR is either a valid IPv4/IPv6 address, or a valid symbolic hostname, which resolves to a IPv6 or IPv4 address. \fIport\fR may be omitted and defaults to port 9995. Note: Due to IPv4/IPv6 -accepted addresses the port separator is '/'. +accepted addresses the port separator is '/'. Up to 8 repeaters my be defined. .TP 3 .B -I \fIIdentString ( capital letter i ) Specifies an ident string, which describes the source e.g. the diff --git a/man/sfcapd.1 b/man/sfcapd.1 index 22a02e8..fe1769c 100755 --- a/man/sfcapd.1 +++ b/man/sfcapd.1 @@ -42,7 +42,7 @@ Join the specified IPv6 or IPv6 multicast group for listening. Enable packet repeater. Send all incoming packets to another \fIhost\fR and \fIport\fR. \fIhost\fR is either a valid IPv4/IPv6 address, or a valid simbolic hostname, which resolves to a IPv6 or IPv4 address. \fIport\fR may be omitted and defaults to port 6343. Note: Due to IPv4/IPv6 -accepted addresses the port separator is '/'. +accepted addresses the port separator is '/'. Up to 8 repeaters my be defined. .TP 3 .B -I \fIIdentString ( capital letter i ) Specifies an ident string, which describes the source e.g. the