/** * Callback for UDP data called by LibNIDS * @param addr Address data (2x IP:port) * @param buf UDP payload * @param len Length of UDP payload * @param iph IP header */ void net_udp(struct tuple4 *addr, char *buf, int len, struct ip *iph) { log_write(net_time(), "U", *addr, buf, len); }
/** * Callback for TCP data assembled by LibNIDS * @param tcp Pointer to stream struct * @param param Additional parameter associated with TCP stream */ void net_tcp(struct tcp_stream *tcp, void **param) { struct half_stream *hlf = NULL; struct tuple4 addr; /* Local copy of address */ memcpy(&addr, &tcp->addr, sizeof(struct tuple4)); /* TCP connection established */ if (tcp->nids_state == NIDS_JUST_EST) { /* Enable monitoring of data */ tcp->client.collect++; tcp->server.collect++; if (!merge_tcp_payloads) log_write(net_time(), "T+", addr, "", 0); return; } /* Disable monitoring if stream too long */ if (max_tcp_bytes && tcp->client.count + tcp->server.count > max_tcp_bytes) { /* Disable monitoring */ tcp->client.collect = 0; tcp->server.collect = 0; } /* New data is available */ if (tcp->nids_state == NIDS_DATA) { /* Skip if payloads should be merged */ if (merge_tcp_payloads) { nids_discard(tcp, 0); return; } /* Check which end has sent data */ if (tcp->client.count_new) { hlf = &tcp->client; swap_addr(&addr); } else { hlf = &tcp->server; } log_write(net_time(), "T", addr, hlf->data, hlf->count_new); return; } /* TCP connection closed */ if (tcp->nids_state == NIDS_CLOSE || tcp->nids_state == NIDS_RESET || tcp->nids_state == NIDS_TIMED_OUT) { /* Skip if payloads should not be merged */ if (!merge_tcp_payloads) { log_write(net_time(), "T-", addr, "", 0); return; } /* Log merged payloads */ if (tcp->server.count) log_write(net_time(), "T", addr, tcp->server.data, tcp->server.count); swap_addr(&addr); if (tcp->client.count) log_write(net_time(), "T", addr, tcp->client.data, tcp->client.count); return; } }
void * log_main_loop(void * context) { log_serverio_init(); log_fileio_init(); log_cnc_init(); bzero(zero_state, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); while (1) { sleep(1); if (nbsf::flags[nbsf::STATS]) { /* We're sending this over the network to a (presumably) java program. So if the compiler puts padding in, it will screw up our parsing. __packed__ *should* prevent the compiler from putting padding/alignment stuff in. But a thought-out size check after is still a good idea. */ struct __attribute__((__packed__)) { uint64_t fio_upstart; uint64_t sio_upstart; uint64_t cio_upstart; uint64_t cnc_upstart; uint64_t main_upstart; nbsf::io_state_t fio_start[NUM_LOG_BUFFERS]; nbsf::io_state_t cio_start[NUM_LOG_BUFFERS]; nbsf::io_state_t total[NUM_LOG_BUFFERS]; nbsf::buf_state_t state[NUM_LOG_BUFFERS]; uint32_t ratio[NUM_LOG_BUFFERS]; uint32_t size[NUM_LOG_BUFFERS]; uint32_t cores; uint8_t flags[nbsf::num_flags]; } contig; // 40 + (3 * n * 40) + (n * 12) + (2 * n * 4) + 4 + (nbsf::num_flags) int packed_size = 40 + (3 * NUM_LOG_BUFFERS * 40) + (NUM_LOG_BUFFERS * 12) + (2 * NUM_LOG_BUFFERS * 4) + 4 + (nbsf::num_flags); NBLassert(sizeof(contig) == packed_size); LOGDEBUG(7, "stat struct size: %i\n", packed_size); const time_t CURRENT = time(NULL); //Copy volatile items as close to simultaneously as possible to minimize drift contig.fio_upstart = nbsf::fio_upstart; contig.sio_upstart = nbsf::sio_upstart; contig.cio_upstart = nbsf::cio_upstart; contig.cnc_upstart = nbsf::cnc_upstart; contig.main_upstart = nbsf::main_upstart; memcpy(contig.fio_start, nbsf::fio_start, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); memcpy(contig.cio_start, nbsf::cio_start, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); memcpy(contig.total, nbsf::total, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { //memcpy(contig.state + i, log_main->buffers[i], sizeof(nbsf::buf_state_t)); log_buffer_t * buf = log_main->buffers[i]; contig.state[i].filenr = buf->fileio_nextr; contig.state[i].servnr = buf->servio_nextr; contig.state[i].nextw = buf->next_write; contig.ratio[i] = LOG_RATIO[i]; contig.size[i] = LOG_BUFFER_SIZES[i]; } memcpy( contig.flags, (uint8_t *) nbsf::flags, nbsf::num_flags); //Set non-volatile items, convert everything to network order. contig.cores = htonl(nbsf::NUM_CORES); if (contig.flags[nbsf::fileio]) { neterize(contig.fio_start, contig.fio_start, contig.total); contig.fio_upstart = net_time(contig.fio_upstart, CURRENT); } else { bzero(contig.fio_start, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); contig.fio_upstart = 0; } if (contig.flags[nbsf::serv_connected]) { neterize(contig.cio_start, contig.cio_start, contig.total); contig.cio_upstart = net_time(contig.cio_upstart, CURRENT); } else { bzero(contig.cio_start, sizeof(nbsf::io_state_t) * NUM_LOG_BUFFERS); contig.cio_upstart = 0; } neterize(contig.total, zero_state, contig.total); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { LOGDEBUG(6, "\t\tstat(%i): filenr=%i servnr=%i nextw=%i\n", i, contig.state[i].filenr, contig.state[i].servnr, contig.state[i].nextw); contig.state[i].filenr = htonl(contig.state[i].filenr); contig.state[i].servnr = htonl(contig.state[i].servnr); contig.state[i].nextw = htonl(contig.state[i].nextw); contig.size[i] = htonl(contig.size[i]); contig.ratio[i] = htonl(contig.ratio[i]); } contig.sio_upstart = (contig.flags[nbsf::servio]) ? net_time(contig.sio_upstart, CURRENT) : 0; contig.cnc_upstart = (contig.flags[nbsf::cnc_connected]) ? net_time(contig.cnc_upstart, CURRENT) : 0; contig.main_upstart = net_time(contig.main_upstart, CURRENT); char cbuf[100]; snprintf(cbuf, 100, "stats nbuffers=%i", NUM_LOG_BUFFERS); NBlog(NBL_SMALL_BUFFER, 0, clock(), cbuf, packed_size, (uint8_t *) &contig); } }