📄 bandwidthd.c
字号:
IP_Offset = 22; break; } if (ForkBackground) { fclose(stdin); fclose(stdout); fclose(stderr); } signal(SIGHUP, signal_handler); signal(SIGTERM, signal_handler); if (IPDataStore) // If there is data in the datastore draw some initial graphs { syslog(LOG_INFO, "Drawing initial graphs"); WriteOutWebpages(IntervalStart+config.interval); } if (pcap_loop(pd, -1, PacketCallback, pcap_userdata) < 0) { syslog(LOG_ERR, "Bandwidthd: pcap_loop: %s", pcap_geterr(pd)); exit(1); } pcap_close(pd); exit(0); } void PacketCallback(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { unsigned int counter; u_int caplen = h->caplen; const struct ip *ip; uint32_t srcip; uint32_t dstip; struct IPData *ptrIPData; if (h->ts.tv_sec > IntervalStart + config.interval) // Then write out this intervals data and possibly kick off the grapher { GraphIntervalCount++; CommitData(IntervalStart+config.interval); IpCount = 0; IntervalStart=h->ts.tv_sec; } caplen -= IP_Offset; // We're only measuring ip size, so pull off the ethernet header p += IP_Offset; // Move the pointer past the datalink header ip = (const struct ip *)p; // Point ip at the ip header if (ip->ip_v != 4) // then not an ip packet so skip it return; srcip = ntohl(*(uint32_t *) (&ip->ip_src)); dstip = ntohl(*(uint32_t *) (&ip->ip_dst)); for (counter = 0; counter < SubnetCount; counter++) { // Packets from a monitored subnet to a monitored subnet will be // credited to both ip's if (SubnetTable[counter].ip == (srcip & SubnetTable[counter].mask)) { ptrIPData = FindIp(srcip); // Return or create this ip's data structure if (ptrIPData) Credit(&(ptrIPData->Send), ip); ptrIPData = FindIp(0); // Totals if (ptrIPData) Credit(&(ptrIPData->Send), ip); } if (SubnetTable[counter].ip == (dstip & SubnetTable[counter].mask)) { ptrIPData = FindIp(dstip); if (ptrIPData) Credit(&(ptrIPData->Receive), ip); ptrIPData = FindIp(0); if (ptrIPData) Credit(&(ptrIPData->Receive), ip); } } }inline void Credit(struct Statistics *Stats, const struct ip *ip) { unsigned long size; const struct tcphdr *tcp; uint16_t sport, dport; size = ntohs(ip->ip_len); Stats->total += size; switch(ip->ip_p) { case 6: // TCP tcp = (struct tcphdr *)(ip+1); tcp = (struct tcphdr *) ( ((char *)tcp) + ((ip->ip_hl-5)*4) ); // Compensate for IP Options Stats->tcp += size; sport = ntohs(tcp->TCPHDR_SPORT); dport = ntohs(tcp->TCPHDR_DPORT); if (sport == 80 || dport == 80 || sport == 443 || dport == 443) Stats->http += size; if (sport == 20 || dport == 20 || sport == 21 || dport == 21) Stats->ftp += size; if (sport == 1044|| dport == 1044|| // Direct File Express sport == 1045|| dport == 1045|| // '' <- Dito Marks sport == 1214|| dport == 1214|| // Grokster, Kaza, Morpheus sport == 4661|| dport == 4661|| // EDonkey 2000 sport == 4662|| dport == 4662|| // '' sport == 4665|| dport == 4665|| // '' sport == 5190|| dport == 5190|| // Song Spy sport == 5500|| dport == 5500|| // Hotline Connect sport == 5501|| dport == 5501|| // '' sport == 5502|| dport == 5502|| // '' sport == 5503|| dport == 5503|| // '' sport == 6346|| dport == 6346|| // Gnutella Engine sport == 6347|| dport == 6347|| // '' sport == 6666|| dport == 6666|| // Yoink sport == 6667|| dport == 6667|| // '' sport == 7788|| dport == 7788|| // Budy Share sport == 8888|| dport == 8888|| // AudioGnome, OpenNap, Swaptor sport == 8889|| dport == 8889|| // AudioGnome, OpenNap sport == 28864|| dport == 28864|| // hotComm sport == 28865|| dport == 28865) // hotComm Stats->p2p += size; break; case 17: Stats->udp += size; break; case 1: Stats->icmp += size; break; } }// TODO: Throw away old data!void DropOldData(long int timestamp) // Go through the ram datastore and dump old data { struct IPDataStore *DataStore; struct IPDataStore *PrevDataStore; struct DataStoreBlock *DeletedBlock; PrevDataStore = NULL; DataStore = IPDataStore; // Progress through the linked list until we reach the end while(DataStore) // we have data { // If the First block is out of date, purge it, if it is the only block // purge the node while(DataStore->FirstBlock->LatestTimestamp < timestamp - config.range) { if ((!DataStore->FirstBlock->Next) && PrevDataStore) // There is no valid block of data for this ip, so unlink the whole ip { // Don't bother unlinking the ip if it's the first one, that's to much // Trouble PrevDataStore->Next = DataStore->Next; // Unlink the node free(DataStore->FirstBlock->Data); // Free the memory free(DataStore->FirstBlock); free(DataStore); DataStore = PrevDataStore->Next; // Go to the next node if (!DataStore) return; // We're done } else if (!DataStore->FirstBlock->Next) { // There is no valid block of data for this ip, and we are // the first ip, so do nothing break; // break out of this loop so the outside loop increments us } else // Just unlink this block { DeletedBlock = DataStore->FirstBlock; DataStore->FirstBlock = DataStore->FirstBlock->Next; // Unlink the block free(DeletedBlock->Data); free(DeletedBlock); } } PrevDataStore = DataStore; DataStore = DataStore->Next; } }void StoreIPDataInPostgresql(struct IPData IncData[]) {#ifdef HAVE_LIBPQ struct IPData *IPData; unsigned int counter; struct Statistics *Stats; PGresult *res; static PGconn *conn = NULL; static char sensor_id[50]; const char *paramValues[10]; char *sql1; char *sql2; char Values[10][50]; if (!config.output_database == DB_PGSQL) return; paramValues[0] = Values[0]; paramValues[1] = Values[1]; paramValues[2] = Values[2]; paramValues[3] = Values[3]; paramValues[4] = Values[4]; paramValues[5] = Values[5]; paramValues[6] = Values[6]; paramValues[7] = Values[7]; paramValues[8] = Values[8]; paramValues[9] = Values[9]; // ************ Inititialize the db if it's not already if (!conn) { /* Connect to the database */ conn = PQconnectdb(config.db_connect_string); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { syslog(LOG_ERR, "Connection to database '%s' failed: %s", config.db_connect_string, PQerrorMessage(conn)); PQfinish(conn); conn = NULL; return; } strncpy(Values[0], config.sensor_id, 50); res = PQexecParams(conn, "select sensor_id from sensors where sensor_name = $1;", 1, /* one param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } if (PQntuples(res)) { strncpy(sensor_id, PQgetvalue(res, 0, 0), 50); PQclear(res); } else { // Insert new sensor id PQclear(res); res = PQexecParams(conn, "insert into sensors (sensor_name, last_connection) VALUES ($1, now());", 1, /* one param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } PQclear(res); res = PQexecParams(conn, "select sensor_id from sensors where sensor_name = $1;", 1, /* one param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } strncpy(sensor_id, PQgetvalue(res, 0, 0), 50); PQclear(res); } } // Begin transaction // **** Perform inserts res = PQexecParams(conn, "BEGIN;", 0, /* zero param */ NULL, /* let the backend deduce param type */ NULL, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql BEGIN failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } PQclear(res); strncpy(Values[0], sensor_id, 50); res = PQexecParams(conn, "update sensors set last_connection = now() where sensor_id = $1;", 1, /* one param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql UPDATE failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } PQclear(res); Values[0][49] = '\0'; snprintf(Values[1], 50, "%llu", config.interval); for (counter=0; counter < IpCount; counter++) { IPData = &IncData[counter]; if (IPData->ip == 0) { // This optimization allows us to quickly draw totals graphs for a sensor sql1 = "INSERT INTO bd_tx_total_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"; sql2 = "INSERT INTO bd_rx_total_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"; } else { sql1 = "INSERT INTO bd_tx_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"; sql2 = "INSERT INTO bd_rx_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"; } HostIp2CharIp(IPData->ip, Values[2]); Stats = &(IPData->Send); if (Stats->total > 512) // Don't log empty sets { // Log data in kilobytes snprintf(Values[3], 50, "%llu", (long long unsigned int)((((double)Stats->total)/1024.0) + 0.5)); snprintf(Values[4], 50, "%llu", (long long unsigned int)((((double)Stats->icmp)/1024.0) + 0.5)); snprintf(Values[5], 50, "%llu", (long long unsigned int)((((double)Stats->udp)/1024.0) + 0.5)); snprintf(Values[6], 50, "%llu", (long long unsigned int)((((double)Stats->tcp)/1024.0) + 0.5)); snprintf(Values[7], 50, "%llu", (long long unsigned int)((((double)Stats->ftp)/1024.0) + 0.5)); snprintf(Values[8], 50, "%llu", (long long unsigned int)((((double)Stats->http)/1024.0) + 0.5)); snprintf(Values[9], 50, "%llu", (long long unsigned int)((((double)Stats->p2p)/1024.0) + 0.5)); res = PQexecParams(conn, sql1, 10, /* nine param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } PQclear(res); } Stats = &(IPData->Receive); if (Stats->total > 512) // Don't log empty sets { snprintf(Values[3], 50, "%llu", (long long unsigned int)((((double)Stats->total)/1024.0) + 0.5)); snprintf(Values[4], 50, "%llu", (long long unsigned int)((((double)Stats->icmp)/1024.0) + 0.5)); snprintf(Values[5], 50, "%llu", (long long unsigned int)((((double)Stats->udp)/1024.0) + 0.5)); snprintf(Values[6], 50, "%llu", (long long unsigned int)((((double)Stats->tcp)/1024.0) + 0.5)); snprintf(Values[7], 50, "%llu", (long long unsigned int)((((double)Stats->ftp)/1024.0) + 0.5)); snprintf(Values[8], 50, "%llu", (long long unsigned int)((((double)Stats->http)/1024.0) + 0.5)); snprintf(Values[9], 50, "%llu", (long long unsigned int)((((double)Stats->p2p)/1024.0) + 0.5)); res = PQexecParams(conn, sql2, 10, /* seven param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; return; } PQclear(res); } } // Commit transaction res = PQexecParams(conn, "COMMIT;", 0, /* zero param */ NULL, /* let the backend deduce param type */ NULL, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -