📄 flow-capture.c
字号:
/* * Copyright (c) 2001 Mark Fullmer and The Ohio State University * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $Id: flow-capture.c,v 1.73 2003/04/02 18:03:01 maf Exp $ */#include "ftconfig.h"#include <ftlib.h>#include <sys/time.h>#include <sys/types.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/wait.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <syslog.h>#if HAVE_STRINGS_H #include <strings.h>#endif#if HAVE_STRING_H #include <string.h>#endif#include "ftbuild.h"#ifdef HAVE_LIBWRAP#include <tcpd.h>#endif /* HAVE_LIBWRAP */void fterr_exit_handler(int code);#define CAPTURE_PIDFILE "/var/run/flow-capture.pid"#define SELECT_TIMEOUT 1 /* 1 second */struct client_rec { int fd; struct sockaddr_in addr; int flags; time_t conn_time; struct ftio ftio; FT_LIST_ENTRY (client_rec) chain;};struct client { FT_LIST_HEAD(clienth, client_rec) list; struct sockaddr_in addr; int fd; int enabled; /* listen socket enabled? */ int max; /* max connections */ int active; /* active connections */#ifdef HAVE_LIBWRAP struct request_info tcpd;#endif /* HAVE_LIBWRAP */};struct rotate { double next; /* time of next rotation */ int cur; /* current rotation # */ int n; /* number per day */};struct file { int fd; /* file descriptor */ char name[MAXPATHLEN+1]; /* name */ char nname[MAXPATHLEN+1]; /* new name */ time_t time; struct ftver ftv; off_t nbytes; u_int32 hdr_nflows; u_int32 hdr_flows_corrupt; u_int32 hdr_flows_lost; u_int32 hdr_flows_reset;};int debug;int sig_pipe_flag, sig_quit_flag, sig_hup_flag, sig_chld_flag;int reload_flag;void sig_pipe(int);void sig_quit(int);void sig_hup(int);void sig_chld(int);pid_t pid;char *pidfile;struct ftnet ftnet;void usage(void);int calc_rotate (int next, double *trotate, int *cur);double doubletime(void);int main(argc, argv) int argc;char **argv;{#ifdef IP_ADD_MEMBERSHIP struct ip_mreq mr;#ifdef IP_ADD_SOURCE_MEMBERSHIP struct ip_mreq_source mrs;#endif#endif fd_set rfd; struct sockaddr_in tmp_addr; struct timeval tv; struct tm *tm; struct ftset ftset; struct ftfile_entries fte; struct client client; struct ftio ftio; struct ftpdu ftpdu; struct ftpeeri ftpi; struct ftver ftv; struct ftchash *ftch; struct ftchash_rec_exp ftch_recexp, *ftch_recexpp; struct rotate rot; struct file cap_file; struct ftipmask ftipmask; struct fttag fttag; struct ftfil ftfil; struct fttag_def *ftd; struct ftfil_def *ftfd; struct fts3rec_offsets fo; struct client_rec *client_rec, *client_rec2; pid_t child_pid; time_t tt_now, time_startup; double now; char work_dir[MAXPATHLEN+1], post_rotate_exec[MAXPATHLEN+1]; int i, n, tmp_len, enable_unlink, offset, detach, nest, one, max_fd; unsigned int v1, v2; u_int32 privacy_mask, hash; char fmt_src_ip[32], fmt_dst_ip[32], fmt_dst_port[32]; char xl_rec[FT_IO_MAXREC], *out_rec; char *tag_fname, *tag_active; char *filter_fname, *filter_active; int stat_interval, stat_next, child_status; int v_flag; time_startup = time((time_t)0L); bzero (&rot, sizeof rot); bzero (&cap_file, sizeof cap_file); bzero (&ftnet, sizeof ftnet); bzero (&tv, sizeof tv); bzero (&work_dir, sizeof work_dir); bzero (&post_rotate_exec, sizeof post_rotate_exec); bzero (&fte, sizeof fte); bzero (&client, sizeof client); bzero (&ftpdu, sizeof ftpdu); bzero (&ftv, sizeof ftv); bzero (&fttag, sizeof fttag); bzero (&ftfil, sizeof ftfil); FT_LIST_INIT(&client.list); stat_interval = 0; stat_next = -1; v_flag = 0; reload_flag = 1; tag_fname = FT_PATH_CFG_TAG; tag_active = (char*)0L; filter_fname = FT_PATH_CFG_FILTER; filter_active = (char*)0L; ftfd = (struct ftfil_def*)0L; ftd = (struct fttag_def*)0L; /* init fterr */ fterr_setid(argv[0]); fterr_setexit(fterr_exit_handler); /* defaults + default compression */ ftset_init(&ftset, Z_DEFAULT_COMPRESSION); /* by default do not mask any src/dst ip addr bits */ privacy_mask = 0xFFFFFFFF; /* default timeout waiting for an active fd */ tv.tv_sec = SELECT_TIMEOUT; /* listen for PDU's */ ftnet.loc_addr.sin_family = AF_INET; ftnet.loc_addr.sin_addr.s_addr = htonl(INADDR_ANY); ftnet.loc_addr.sin_port = htons(FT_PORT); /* listen for clients */ client.addr.sin_family = AF_INET; client.addr.sin_addr.s_addr = htonl(INADDR_ANY); client.addr.sin_port = htons(FT_PORT); /* default detach from parent */ detach = 1; /* default 95 rotations per day, or every 15 minutes */ rot.n = 95; /* no files initially open */ cap_file.fd = -1; /* year/month/day nesting */ nest = 3; /* pidfile */ pidfile = CAPTURE_PIDFILE; while ((i = getopt(argc, argv, "A:b:c:C:d:De:E:f:F:hm:n:N:p:S:t:T:V:w:z:R:")) != -1) switch (i) { case 'A': /* AS substitution */ ftset.as_sub = atoi(optarg); break; case 'b': /* output byte order */ if (!strcasecmp(optarg, "little")) ftset.byte_order = FT_HEADER_LITTLE_ENDIAN; else if (!strcasecmp(optarg, "big")) ftset.byte_order = FT_HEADER_BIG_ENDIAN; else fterr_errx(1, "expecting \"big\" or \"little\" at -b"); break; case 'c': /* client enable */ client.max = atoi(optarg); break; case 'C': /* comment field */ ftset.comments = optarg; break; case 'D': /* daemonize */ detach = 0; pidfile = (char*)0L; break; case 'e': /* expire */ fte.max_files = atoi(optarg); if (fte.max_files) fte.expiring = 1; break; case 'E': /* expire bytes */ if ((fte.max_bytes = scan_size(optarg)) == -1) fterr_errx(1, "scan_size(): failed"); if (fte.max_bytes) fte.expiring = 1; break; case 'f': /* filter fname */ filter_fname = optarg; break; case 'F': /* filter active */ filter_active = optarg; break; case 'd': /* debug */ debug = atoi(optarg); break; case 'h': /* help */ usage(); exit (0); break; case 'm': /* privacy mask */ privacy_mask = scan_ip(optarg); break; case 'n': /* # rotations / day */ rot.n = atoi(optarg); /* no more than 1 rotation per minute */ if (rot.n > (1440-1)) fterr_errx(1, "rotations limited to every 1 minute"); break; case 'N': /* nesting level */ nest = atoi(optarg); if ((nest < -3) || (nest > 3)) fterr_errx(1, "-3 <= nesting level <= 3"); break; case 'p': /* pidfile */ if ((optarg[0] == 0) || ((optarg[0] == '-') && (optarg[1] == 0))) pidfile = (char*)0L; else pidfile = optarg; break; case 'R': /* Post rotate exec */ if (strlen(optarg) > MAXPATHLEN) fterr_errx(1, "Post rotate argument too long"); strcpy(post_rotate_exec,optarg); break; case 'S': /* stat interval */ stat_interval = atoi(optarg); if ((stat_interval < 0) || (stat_interval > 60)) fterr_errx(1, "Stat interval must be between 0 and 60."); break; case 't': /* tag filename */ tag_fname = optarg; break; case 'T': /* active tags */ tag_active = optarg; /* required for fttag_eval() */ ftv.s_version = FT_IO_SVERSION; ftv.d_version = 1005; ftv.set = 1; break; case 'V': /* PDU version */ v_flag = 1; n = sscanf(optarg, "%u.%u", &v1, &v2); if (n == 1) { ftv.s_version = FT_IO_SVERSION; ftv.d_version = v1; ftv.set = 1; } else if (n == 2) { ftv.s_version = FT_IO_SVERSION; ftv.d_version = v1; ftv.agg_method = v2; ftv.agg_version = 2; ftv.set = 1; } else { fterr_errx(1, "Version scan failed"); } break; case 'w': /* working directory */ if (strlen(optarg) > (MAXPATHLEN)) fterr_errx(1, "Pathname too long"); strcpy(work_dir, optarg); break; case 'z': /* compress level */ ftset.z_level = atoi(optarg); if ((ftset.z_level < 0) || (ftset.z_level > 9)) fterr_errx(1, "Compression level must be between 0 and 9"); break; default: usage(); exit (1); break; } /* switch */ /* disable pidfile if not forking */ if (!detach) pidfile = (char*)0L; if ((argc - optind) != 1) fterr_errx(1, "Specify localip/remoteip/port."); /* tagging forces v1005 */ if (v_flag && tag_active && (ftv.d_version != 1005)) fterr_errx(1, "Must be v1005 with tagging."); if (!work_dir[0]) fterr_errx(1, "Specify workdir with -w."); ftpi = scan_peeri(argv[optind]); ftnet.rem_ip = ftpi.rem_ip; ftnet.loc_ip = ftpi.loc_ip; if (ftpi.dst_port) ftnet.dst_port = ftpi.dst_port; else ftnet.dst_port = FT_PORT; ftnet.loc_addr.sin_addr.s_addr = htonl(ftpi.loc_ip); ftnet.loc_addr.sin_port = htons(ftnet.dst_port); client.addr.sin_port = htons(ftnet.dst_port); /* if debugging is enabled do not unlink any files when aging */ if (debug) enable_unlink = 0; else enable_unlink = 1; /* setup for ftrec_mask_ip */ if (privacy_mask != 0xFFFFFFFF) ftrec_compute_mask(&ftipmask, privacy_mask, privacy_mask, ftset.byte_order); /* daemonize */ if (detach) { if ((pid = fork()) == -1) { fterr_err(1, "fork()"); } else if (pid) { if (pidfile) write_pidfile(pid, pidfile, ftnet.dst_port); exit (0); /* parent */ } umask(0022); setsid(); for (n = 0; n < 16; ++n) close (n); /* enable syslog */ fterr_setsyslog(1, LOG_PID|LOG_NDELAY, LOG_LOCAL6); /* disable stderr */ fterr_setfile(0, (void*)0L); } /* * configure signal handlers */ if (mysignal(SIGPIPE, sig_pipe) == SIG_ERR) fterr_err(1, "signal(SIGPIPE)"); if (mysignal(SIGHUP, sig_hup) == SIG_ERR) fterr_err(1, "signal(SIGHUP)"); if (mysignal(SIGQUIT, sig_quit) == SIG_ERR) fterr_err(1, "signal(SIGQUIT)"); if (mysignal(SIGCHLD, sig_chld) == SIG_ERR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -