int receive_fd(int sock) { #if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; struct iovec vec; ssize_t n; char ch; int fd; #ifndef HAVE_ACCRIGHTS_IN_MSGHDR char tmp[CMSG_SPACE(sizeof(int))]; struct cmsghdr *cmsg; #endif memset(&msg, 0, sizeof(msg)); vec.iov_base = &ch; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; #ifdef HAVE_ACCRIGHTS_IN_MSGHDR msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #else msg.msg_control = tmp; msg.msg_controllen = sizeof(tmp); #endif if ((n = recvmsg(sock, &msg, 0)) == -1) logerr("%s: recvmsg", __func__); if (n != 1) logerrx("%s: recvmsg: expected received 1 got %ld", __func__, (long)n); #ifdef HAVE_ACCRIGHTS_IN_MSGHDR if (msg.msg_accrightslen != sizeof(fd)) logerrx("%s: no fd", __func__); #else cmsg = CMSG_FIRSTHDR(&msg); if (cmsg == NULL) logerrx("%s: no message header", __func__); #ifndef BROKEN_CMSG_TYPE if (cmsg->cmsg_type != SCM_RIGHTS) logerrx("%s: expected type %d got %d", __func__, SCM_RIGHTS, cmsg->cmsg_type); #endif fd = (*(int *)CMSG_DATA(cmsg)); #endif return (fd); #else # error No supported FD passing primitives found #endif }
static int start_socket(int monitor_fd) { int fd; if ((fd = client_open_socket(monitor_fd)) == -1) logerrx("Logsock open failed, exiting"); return (fd); }
static int start_log(int monitor_fd) { int fd; off_t r; char ebuf[512]; if ((fd = client_open_log(monitor_fd)) == -1) logerrx("Logfile open failed, exiting"); /* Don't try to write a v.3 log on the end of a v.2 one */ r = lseek(fd, 0, SEEK_END); /* * If there isn't a full legacy header in the file or an error occurs * (r == -1, e.g. on a FIFO) then don't bother checking for an old * log header. */ if (r < sizeof(struct store_v2_header)) return (fd); if ((r = lseek(fd, 0, SEEK_SET)) == -1) logerr("%s: lseek", __func__); switch (store_v2_check_header(fd, ebuf, sizeof(ebuf))) { case STORE_ERR_OK: /* Uh oh - an old flow log is in the way, don't try to write */ logerrx("Error: Cannot append to legacy (version 2) flow log, " "please move it out of the way and restart flowd"); case STORE_ERR_BAD_MAGIC: case STORE_ERR_UNSUP_VERSION: /* Good - the existing flow log is a probably a new one */ if ((r = lseek(fd, 0, SEEK_END)) == -1) logerr("%s: lseek", __func__); return (fd); default: logerrx("%s: %s", __func__, ebuf); } /* NOTREACHED */ return (-1); }
/* Enqueue a flow for output, return 0 on success, -1 on queue full */ static int output_flow_enqueue(u_int8_t *f, size_t len, int verbose) { /* Force flush on overflow */ if (output_queue_offset + len > OUTPUT_MAX_QLEN) { logit(LOG_DEBUG, "%s: output queue full", __func__); return (-1); } if (output_queue == NULL) { output_queue_alloc = OUTPUT_INITIAL_QLEN; if ((output_queue = malloc(output_queue_alloc)) == NULL) { logerrx("Output queue allocation (%u bytes) failed", output_queue_alloc); } if (verbose) { logit(LOG_DEBUG, "%s: initial allocation %u", __func__, output_queue_alloc); } } while (output_queue_offset + len > output_queue_alloc) { u_int8_t *tmp_q; size_t tmp_len = output_queue_alloc << 1; /* This should never happen if max = initial * 2^x */ if (tmp_len > OUTPUT_MAX_QLEN) { logit(LOG_DEBUG, "%s: oops, tmp_len (%u) > " "OUTPUT_MAX_QLEN (%u)", __func__, tmp_len, OUTPUT_MAX_QLEN); return (-1); } if ((tmp_q = realloc(output_queue, tmp_len)) == NULL) { logit(LOG_DEBUG, "%s: realloc of %u fail", __func__, tmp_len); return (-1); } if (verbose) { logit(LOG_DEBUG, "%s: increased output queue " "from %uKB to %uKB", __func__, output_queue_alloc >> 10, tmp_len >> 10); } output_queue = tmp_q; output_queue_alloc = tmp_len; } memcpy(output_queue + output_queue_offset, f, len); output_queue_offset += len; if (verbose) { logit(LOG_DEBUG, "%s: offset %u alloc %u", __func__, output_queue_offset, output_queue_alloc); } return (0); }
int send_fd(int sock, int fd) { #if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; struct iovec vec; char ch = '\0'; ssize_t n; #ifndef HAVE_ACCRIGHTS_IN_MSGHDR char tmp[CMSG_SPACE(sizeof(int))]; struct cmsghdr *cmsg; #endif memset(&msg, 0, sizeof(msg)); #ifdef HAVE_ACCRIGHTS_IN_MSGHDR msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #else msg.msg_control = (caddr_t)tmp; msg.msg_controllen = CMSG_LEN(sizeof(int)); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsg) = fd; #endif vec.iov_base = &ch; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; if ((n = sendmsg(sock, &msg, 0)) == -1) logerr("%s: sendmsg(%d)", __func__, fd); if (n != 1) logerrx("%s: sendmsg: expected sent 1 got %ld", __func__, (long)n); return (0); #else # error No supported FD passing primitives found #endif }
static void output_flow_flush(int log_fd, int verbose) { char ebuf[512]; if (log_fd == -1) return; if (verbose) { logit(LOG_DEBUG, "%s: flushing output queue len %u", __func__, output_queue_offset); } if (output_queue_offset == 0) return; if (store_put_buf(log_fd, output_queue, output_queue_offset, ebuf, sizeof(ebuf)) != STORE_ERR_OK) logerrx("%s: exiting on %s", __func__, ebuf); output_queue_offset = 0; }
static void process_flow(struct store_flow_complete *flow, struct flowd_config *conf, int log_fd, int log_socket) { char ebuf[512], fbuf[1024]; int flen; u_int filtres; /* Another sanity check */ if (flow->src_addr.af != flow->dst_addr.af) { logit(LOG_WARNING, "%s: flow src(%d)/dst(%d) AF mismatch", __func__, flow->src_addr.af, flow->dst_addr.af); return; } /* Prepare for writing */ flow->hdr.fields = htonl(flow->hdr.fields); flow->recv_time.recv_sec = htonl(flow->recv_time.recv_sec); flow->recv_time.recv_usec = htonl(flow->recv_time.recv_usec); filtres = filter_flow(flow, &conf->filter_list); if (conf->opts & FLOWD_OPT_VERBOSE) { char fmtbuf[1024]; u_int64_t pp = 0; struct flot_node fl; store_format_flow(flow, &fl, fmtbuf, sizeof(fmtbuf), 0, STORE_DISPLAY_ALL, 0); logit(LOG_DEBUG, "%s: %s flow %s", __func__, filtres == FF_ACTION_DISCARD ? "DISCARD" : "ACCEPT", fmtbuf); /////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// IMED sem_wait (&semFlows); Add_flow(&fl); //logit(LOG_WARNING, "Remplissage de|||||||| flot_flow_packets ######### %llu ###################################", flot.flow_packets); //logit(LOG_WARNING, "Remplissage de|||||||| l'adresse source ######### %s ########estimation_flow_list ########################", flot.src_addr); /*logit(LOG_WARNING, "packets ###### %llu ####### \n", estimation_flow_list->flow_packets); logit(LOG_WARNING, "SRC_ADDR #### %s #### \n", estimation_flow_list->src_addr); logit(LOG_WARNING, "DST_ADDR #### %s ##### \n", estimation_flow_list->dst_addr); logit(LOG_WARNING, "GATEWAY ##### %s ##### \n", estimation_flow_list->gateway_addr); logit(LOG_WARNING, "SRC_PORT #### %d ###### \n", estimation_flow_list->src_port); logit(LOG_WARNING, "DST_PORT #### %d ####### \n", estimation_flow_list->dst_port); logit(LOG_WARNING, "OCKTETS ##### %llu ###### \n", estimation_flow_list->flow_octets);*/ sem_post (&semFlows); // sleep(1); ///////////////////////////////////////////////////////////////////////////////////////////////////// } if (filtres == FF_ACTION_DISCARD) return; if (store_flow_serialise_masked(flow, conf->store_mask, fbuf, sizeof(fbuf), &flen, ebuf, sizeof(ebuf)) != STORE_ERR_OK) logerrx("%s: exiting on %s", __func__, ebuf); if (log_fd != -1 && output_flow_enqueue(fbuf, flen, conf->opts & FLOWD_OPT_VERBOSE) == -1) { output_flow_flush(log_fd, conf->opts & FLOWD_OPT_VERBOSE); /* Must not fail after flush */ if (output_flow_enqueue(fbuf, flen, conf->opts & FLOWD_OPT_VERBOSE) == -1) logerrx("%s: enqueue failed after flush", __func__); } /* Track failures to send on log socket so we can reopen it */ if (log_socket != -1 && send(log_socket, fbuf, flen, 0) == -1) { if (logsock_num_errors > 0 && (logsock_num_errors % 10) == 0) { logit(LOG_WARNING, "log socket send: %s " "(num errors %d)", strerror(errno), logsock_num_errors); } if (errno != ENOBUFS) { if (logsock_first_error == 0) logsock_first_error = time(NULL); logsock_num_errors++; } } else { /* Start to disregard errors after success */ if (logsock_num_errors > 0) logsock_num_errors--; if (logsock_num_errors == 0) logsock_first_error = 0; } /* XXX reopen log file on one failure, exit on multiple */ }
int main(int argc, char **argv) { int ch, i, fd, utc, r, verbose, debug, csv; extern char *optarg; extern int optind; struct store_flow_complete flow; struct store_v2_flow_complete flow_v2; char buf[2048], ebuf[512]; const char *ffile, *ofile; FILE *ffilef; int ofd, read_legacy, head, nflows; u_int32_t disp_mask; struct flowd_config filter_config; struct store_v2_header hdr_v2; utc = verbose = debug = read_legacy = csv = 0; ofile = ffile = NULL; ofd = -1; ffilef = NULL; head = 0; bzero(&filter_config, sizeof(filter_config)); while ((ch = getopt(argc, argv, "H:LUdf:ho:qvc")) != -1) { switch (ch) { case 'h': usage(); return (0); case 'H': if ((head = atoi(optarg)) <= 0) { fprintf(stderr, "Invalid -H value.\n"); usage(); exit(1); } break; case 'L': read_legacy = 1; break; case 'U': utc = 1; break; case 'd': debug = 1; filter_config.opts |= FLOWD_OPT_VERBOSE; break; case 'f': ffile = optarg; break; case 'o': ofile = optarg; break; case 'q': verbose = -1; break; case 'v': verbose = 1; break; case 'c': csv = 1; break; default: usage(); exit(1); } } loginit(PROGNAME, 1, debug); if (argc - optind < 1) { fprintf(stderr, "No logfile specified\n"); usage(); exit(1); } if (ffile != NULL) { if ((ffilef = fopen(ffile, "r")) == NULL) logerr("fopen(%s)", ffile); if (parse_config(ffile, ffilef, &filter_config, 1) != 0) exit(1); fclose(ffilef); } if (ofile != NULL) { if (strcmp(ofile, "-") == 0) { if (!debug) verbose = -1; ofile = NULL; if (isatty(STDOUT_FILENO)) logerrx("Refusing to write binary flow data to " "standard output."); } ofd = open_start_log(ofile, debug); } if (filter_config.store_mask == 0) filter_config.store_mask = STORE_FIELD_ALL; disp_mask = (verbose > 0) ? STORE_DISPLAY_ALL: STORE_DISPLAY_BRIEF; disp_mask &= filter_config.store_mask; for (i = optind; i < argc; i++) { if (strcmp(argv[i], "-") == 0) fd = STDIN_FILENO; else if ((fd = open(argv[i], O_RDONLY)) == -1) logerr("open(%s)", argv[i]); if (read_legacy && store_v2_get_header(fd, &hdr_v2, ebuf, sizeof(ebuf)) != STORE_ERR_OK) logerrx("%s", ebuf); if (verbose >= 1) { printf("LOGFILE %s", argv[i]); if (read_legacy) printf(" started at %s", iso_time(ntohl(hdr_v2.start_time), utc)); printf("\n"); fflush(stdout); } if (csv == 1) { csv++; printf("#:unix_secs,unix_nsecs,sysuptime,exaddr," "dpkts,doctets,first,last,engine_type,engine_id," "srcaddr,dstaddr,nexthop,input,output,srcport," "dstport,prot,tos,tcp_flags,src_mask,dst_mask," "src_as,dst_as\n"); } for (nflows = 0; head == 0 || nflows < head; nflows++) { bzero(&flow, sizeof(flow)); if (read_legacy) r = store_v2_get_flow(fd, &flow_v2, ebuf, sizeof(ebuf)); else r = store_get_flow(fd, &flow, ebuf, sizeof(ebuf)); if (r == STORE_ERR_EOF) break; else if (r != STORE_ERR_OK) logerrx("%s", ebuf); if (read_legacy && store_v2_flow_convert(&flow_v2, &flow) == -1) logerrx("legacy flow conversion failed"); if (ffile != NULL && filter_flow(&flow, &filter_config.filter_list) == FF_ACTION_DISCARD) continue; if (csv) { store_format_flow_flowtools_csv(&flow, buf, sizeof(buf), utc, disp_mask, 0); printf("%s\n", buf); } else if (verbose >= 0) { store_format_flow(&flow, buf, sizeof(buf), utc, disp_mask, 0); printf("%s\n", buf); fflush(stdout); } if (ofd != -1 && store_put_flow(ofd, &flow, filter_config.store_mask, ebuf, sizeof(ebuf)) == -1) logerrx("%s", ebuf); } if (fd != STDIN_FILENO) close(fd); } if (ofd != -1) close(ofd); if (ffile != NULL && debug) dump_config(&filter_config, "final", 1); return (0); }