X-Git-Url: http://git.onelab.eu/?p=fprobe-ulog.git;a=blobdiff_plain;f=src%2Ffprobe-ulog.c;h=8c66067b2ba862ca5bcd5ef05fc51c1b3d075e12;hp=31d1e022600973f98f631adc3f58eb484f717ad8;hb=164b27f0c908f203af585fcd999033b62ba54a22;hpb=a2a10337384cfbcf977f7a8c0062a5c5a95ac5a5 diff --git a/src/fprobe-ulog.c b/src/fprobe-ulog.c index 31d1e02..8c66067 100644 --- a/src/fprobe-ulog.c +++ b/src/fprobe-ulog.c @@ -6,10 +6,13 @@ $Id: fprobe-ulog.c,v 1.1.2.4 2005/01/30 09:06:19 sla Exp $ - 7/11/2007 Sapan Bhatia + Sapan Bhatia - Added data collection (-f) functionality, xid support in the header and log file - rotation. + 7/11/2007 Added data collection (-f) functionality, xid support in the header and log file + rotation. + + 15/11/2007 Added check to make sure fprobe doesn't overflow the disk. Also added a test facility. + */ #include @@ -31,7 +34,7 @@ /* statfs() */ -#include +#include #include struct ipulog_handle { @@ -92,6 +95,9 @@ struct ipulog_handle { #include #include +#define PIDFILE "/var/log/fprobe-ulog.pid" +#define STD_NETFLOW_PDU + enum { aflag, Bflag, @@ -126,6 +132,7 @@ static struct getopt_parms parms[] = { {'b', MY_GETOPT_ARG_REQUIRED, 0, 0}, {'c', MY_GETOPT_ARG_REQUIRED, 0, 0}, {'d', MY_GETOPT_ARG_REQUIRED, 0, 0}, + {'D', MY_GETOPT_ARG_REQUIRED, 0, 0}, {'e', MY_GETOPT_ARG_REQUIRED, 0, 0}, {'E', MY_GETOPT_ARG_REQUIRED, 0, 0}, {'f', MY_GETOPT_ARG_REQUIRED, 0, 0}, @@ -378,6 +385,24 @@ inline void copy_flow(struct Flow *src, struct Flow *dst) dst->flags = src->flags; } +void get_cur_epoch() { + int fd; + fd = open("/tmp/fprobe_last_epoch",O_RDONLY); + if (fd != -1) { + char snum[7]; + ssize_t len; + len = read(fd, snum, sizeof(snum)-1); + if (len != -1) { + snum[len]='\0'; + sscanf(snum,"%d",&cur_epoch); + cur_epoch++; /* Let's not stone the last epoch */ + close(fd); + } + } + return; +} + + void update_cur_epoch_file(int n) { int fd, len; char snum[7]; @@ -391,7 +416,7 @@ void update_cur_epoch_file(int n) { close(fd); } -unsigned get_log_fd(char *fname, unsigned cur_fd) { +unsigned get_log_fd(char *fname, int cur_fd) { struct Time now; unsigned cur_uptime; /* We check if the amount of space left on the disk < some threshold and start reusing logs, or bail out if that @@ -402,28 +427,32 @@ unsigned get_log_fd(char *fname, unsigned cur_fd) { gettime(&now); cur_uptime = getuptime_minutes(&now); - if (fstatfs(cur_fd, &statfs) && cur_fd!=START_VALUE) { - my_log(LOG_ERR, "PANIC! Can't stat disk to calculate free blocks"); - } - else { - if (min_free && statfs.f_bfree < min_free) - switch(cur_epoch) { - case 0: /* Uh oh. Our first file filled up all of the free space. Just bail out. */ - my_log(LOG_ERR, "The first epoch filled up all the free space on disk. Bailing out."); - exit(1); - default: - my_log(LOG_INFO, "Disk almost full. I'm going to drop data. Max epochs = %d\n",cur_epoch); - cur_epoch = -1; - } + + if (cur_fd!=START_VALUE) { + if (fstatfs(cur_fd, &statfs) == -1) { + my_log(LOG_ERR, "PANIC! Can't stat disk to calculate free blocks"); + } + else { + if (min_free && (statfs.f_bavail < min_free)) + switch(cur_epoch) { + case 0: /* Uh oh. Our first file filled up all of the free space. Just bail out. */ + my_log(LOG_ERR, "The first epoch filled up all the free space on disk. Bailing out."); + exit(1); + default: + my_log(LOG_INFO, "Disk almost full (%u free blocks). I'm going to drop data. Max epochs = %d\n",statfs.f_bavail,cur_epoch); + cur_epoch = -1; + } + } } /* Epoch length in minutes */ - if ((cur_uptime - prev_uptime) > epoch_length || cur_fd<0 || cur_epoch==-1) { + if (((cur_uptime - prev_uptime) > epoch_length) || (cur_fd < 0) || (cur_epoch==-1)) { char nextname[MAX_PATH_LEN]; int write_fd; prev_uptime = cur_uptime; cur_epoch = (cur_epoch + 1) % log_epochs; - close(cur_fd); + if (cur_fd>0) + close(cur_fd); snprintf(nextname,MAX_PATH_LEN,"%s.%d",fname,cur_epoch); if ((write_fd = open(nextname, O_WRONLY|O_CREAT|O_TRUNC)) < 0) { my_log(LOG_ERR, "open(): %s (%s)\n", nextname, strerror(errno)); @@ -432,8 +461,9 @@ unsigned get_log_fd(char *fname, unsigned cur_fd) { update_cur_epoch_file(cur_epoch); ret_fd = write_fd; } - else + else { ret_fd = cur_fd; + } return(ret_fd); } @@ -789,7 +819,9 @@ void *emit_thread() p = fill(netflow->HeaderFields, netflow->HeaderFormat, 0, &emit_packet); size = netflow->HeaderSize + emit_count * netflow->FlowSize; /* Netflow PDUs need to be padded to 1464 bytes - Sapan */ +#ifdef STD_NETFLOW_PDU if (size < NETFLOW_PDU_SIZE) size = NETFLOW_PDU_SIZE; +#endif peer_rot_cur = 0; for (i = 0; i < npeers; i++) { if (peers[i].type == PEER_FILE) { @@ -1222,6 +1254,44 @@ void *cap_thread() return 0; } +/* Copied out of CoDemux */ + +static int init_daemon() { + pid_t pid; + FILE *pidfile; + + pidfile = fopen(PIDFILE, "w"); + if (pidfile == NULL) { + my_log(LOG_ERR, "%s creation failed\n", PIDFILE); + } + + if ((pid = fork()) < 0) { + fclose(pidfile); + my_log(LOG_ERR, "Could not fork!\n"); + return(-1); + } + else if (pid != 0) { + /* i'm the parent, writing down the child pid */ + fprintf(pidfile, "%u\n", pid); + fclose(pidfile); + exit(0); + } + + /* close the pid file */ + fclose(pidfile); + + /* routines for any daemon process + 1. create a new session + 2. change directory to the root + 3. change the file creation permission + */ + setsid(); + chdir("/usr/local/fprobe"); + umask(0); + + return(0); +} + int main(int argc, char **argv) { char errpbuf[512]; @@ -1447,6 +1517,8 @@ bad_collector: peers[npeers].write_fd = START_VALUE; peers[npeers].type = PEER_FILE; peers[npeers].seq = 0; + + get_cur_epoch(); npeers++; } else @@ -1468,6 +1540,9 @@ bad_collector: /* Daemonize (if log destination stdout-free) */ my_log_open(ident, verbosity, log_dest); + + init_daemon(); + if (!(log_dest & 2)) { /* Crash-proofing - Sapan*/ while (1) {