void MonNetworkSnifferGatherData(void) { int i; char vbuff[CF_BUFSIZE]; const char* const statedir = GetStateDir(); for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save incoming '%s'", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_incoming.%s", statedir, FILE_SEPARATOR, TCPNAMES[i]); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(NETIN_DIST[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state %s is smaller, retaining old for 40 mins longer", TCPNAMES[i]); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETIN_DIST[i], i, "in"); entropy = MonEntropyCalculate(NETIN_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "in", entropy); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; } for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save outgoing '%s'", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_outgoing.%s", statedir, FILE_SEPARATOR, TCPNAMES[i]); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(NETOUT_DIST[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", TCPNAMES[i]); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETOUT_DIST[i], i, "out"); entropy = MonEntropyCalculate(NETOUT_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "out", entropy); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; } }
void MonNetworkGatherData(double *cf_this) { FILE *pp; char local[CF_BUFSIZE], remote[CF_BUFSIZE], comm[CF_BUFSIZE]; Item *in[ATTR], *out[ATTR]; char *sp; int i; enum cf_netstat_type { cfn_new, cfn_old } type = cfn_new; enum cf_packet_type { cfn_udp4, cfn_udp6, cfn_tcp4, cfn_tcp6} packet = cfn_tcp4; for (i = 0; i < ATTR; i++) { in[i] = out[i] = NULL; } DeleteItemList(ALL_INCOMING); ALL_INCOMING = NULL; sscanf(VNETSTAT[VSYSTEMHARDCLASS], "%s", comm); strcat(comm, " -an"); if ((pp = cf_popen(comm, "r", true)) == NULL) { /* FIXME: no logging */ return; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); for (;;) { memset(local, 0, CF_BUFSIZE); memset(remote, 0, CF_BUFSIZE); size_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: no logging */ cf_pclose(pp); free(vbuff); return; } else { break; } } if (strstr(vbuff, "UNIX")) { break; } if (!((strstr(vbuff, ":")) || (strstr(vbuff, ".")))) { continue; } /* Different formats here ... ugh.. pick a model */ // If this is old style, we look for chapter headings, e.g. "TCP: IPv4" if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_udp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_tcp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_udp4; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_tcp4; type = cfn_old; continue; } // Line by line state in modern/linux output if (strncmp(vbuff,"udp6",4) == 0) { packet = cfn_udp6; type = cfn_new; } else if (strncmp(vbuff,"tcp6",4) == 0) { packet = cfn_tcp6; type = cfn_new; } else if (strncmp(vbuff,"udp",3) == 0) { packet = cfn_udp4; type = cfn_new; } else if (strncmp(vbuff,"tcp",3) == 0) { packet = cfn_tcp4; type = cfn_new; } // End extract type switch (type) { case cfn_new: sscanf(vbuff, "%*s %*s %*s %s %s", local, remote); /* linux-like */ break; case cfn_old: sscanf(vbuff, "%s %s", local, remote); break; } if (strlen(local) == 0) { continue; } // Extract the port number from the end of the string for (sp = local + strlen(local); (*sp != '.') && (*sp != ':') && (sp > local); sp--) { } *sp = '\0'; // Separate address from port number sp++; char *localport = sp; if (strstr(vbuff, "LISTEN")) { // General bucket IdempPrependItem(&ALL_INCOMING, sp, NULL); // Categories the incoming ports by packet types switch (packet) { case cfn_udp4: IdempPrependItem(&MON_UDP4, sp, local); break; case cfn_udp6: IdempPrependItem(&MON_UDP6, sp, local); break; case cfn_tcp4: IdempPrependItem(&MON_TCP4, localport, local); break; case cfn_tcp6: IdempPrependItem(&MON_TCP6, localport, local); break; default: break; } } // Now look at outgoing for (sp = remote + strlen(remote) - 1; (sp >= remote) && (isdigit((int) *sp)); sp--) { } sp++; char *remoteport = sp; // Now look for the specific vital signs to count frequencies for (i = 0; i < ATTR; i++) { if (strcmp(localport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].in]++; AppendItem(&in[i], vbuff, ""); } if (strcmp(remoteport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].out]++; AppendItem(&out[i], vbuff, ""); } } } cf_pclose(pp); /* Now save the state for ShowState() the state is not smaller than the last or at least 40 minutes older. This mirrors the persistence of the maxima classes */ for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save incoming '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(in[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(in[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "in", in[i]); RawSaveItemList(in[i], vbuff); DeleteItemList(in[i]); Log(LOG_LEVEL_DEBUG, "Saved in netstat data in '%s'", vbuff); } for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save outgoing '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(out[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(out[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "out", out[i]); RawSaveItemList(out[i], vbuff); Log(LOG_LEVEL_DEBUG, "Saved out netstat data in '%s'", vbuff); DeleteItemList(out[i]); } free(vbuff); }