926
934
/* ************************************ */
936
static AsStats* allocASStats(u_int16_t as_id) {
937
AsStats *asStats = (AsStats*)malloc(sizeof(AsStats));
939
if(0) traceEvent(CONST_TRACE_WARNING, "Allocating stats for AS %d", as_id);
941
if(asStats != NULL) {
942
memset(asStats, 0, sizeof(AsStats));
943
asStats->as_id = as_id;
944
resetTrafficCounter(&asStats->outBytes);
945
resetTrafficCounter(&asStats->outPkts);
946
resetTrafficCounter(&asStats->inBytes);
947
resetTrafficCounter(&asStats->inPkts);
948
resetTrafficCounter(&asStats->selfBytes);
949
resetTrafficCounter(&asStats->selfPkts);
955
/* ************************************ */
957
static void updateASTraffic(int actualDeviceId, u_int16_t src_as_id,
958
u_int16_t dst_as_id, u_int octets) {
959
AsStats *stats, *prev_stats = NULL;
960
u_char found_src = 0, found_dst = 0;
963
traceEvent(CONST_TRACE_INFO, "updateASTraffic(actualDeviceId=%d, src_as_id=%d, dst_as_id=%d, octets=%d)",
964
actualDeviceId, src_as_id, dst_as_id, octets);
966
if((src_as_id == 0) && (dst_as_id == 0))
969
accessMutex(&myGlobals.device[actualDeviceId].asMutex, "updateASTraffic");
971
stats = myGlobals.device[actualDeviceId].asStats;
974
if(stats->as_id == src_as_id) {
975
stats->lastUpdate = myGlobals.actTime;
976
incrementTrafficCounter(&stats->outBytes, octets), incrementTrafficCounter(&stats->outPkts, 1), stats->totPktsSinceLastRRDDump++;
977
if(src_as_id == dst_as_id) {
978
incrementTrafficCounter(&stats->selfBytes, octets), incrementTrafficCounter(&stats->selfPkts, 1);
979
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
984
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
989
} else if(stats->as_id == dst_as_id) {
990
stats->lastUpdate = myGlobals.actTime;
991
incrementTrafficCounter(&stats->inBytes, octets), incrementTrafficCounter(&stats->inPkts, 1), stats->totPktsSinceLastRRDDump++;
992
if(src_as_id == dst_as_id) {
993
incrementTrafficCounter(&stats->selfBytes, octets), incrementTrafficCounter(&stats->selfPkts, 1);
994
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
999
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
1005
if(found_src && found_dst) {
1006
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
1010
if((myGlobals.actTime-stats->lastUpdate) > PARM_AS_MAXIMUM_IDLE) {
1011
AsStats *next = stats->next;
1013
if(0) traceEvent(CONST_TRACE_INFO, "Purging stats about AS %d", stats->as_id);
1014
if(prev_stats == NULL)
1015
myGlobals.device[actualDeviceId].asStats = next;
1017
prev_stats->next = next;
1023
stats = stats->next;
1027
/* One (or both) ASs are missing */
1028
if((src_as_id != 0) && (!found_src)) {
1029
stats = allocASStats(src_as_id);
1030
stats->next = myGlobals.device[actualDeviceId].asStats;
1031
stats->lastUpdate = myGlobals.actTime;
1032
myGlobals.device[actualDeviceId].asStats = stats;
1035
if((dst_as_id != 0) && (dst_as_id != src_as_id) && (!found_dst)) {
1036
stats = allocASStats(dst_as_id);
1037
stats->next = myGlobals.device[actualDeviceId].asStats;
1038
stats->lastUpdate = myGlobals.actTime;
1039
myGlobals.device[actualDeviceId].asStats = stats;
1042
releaseMutex(&myGlobals.device[actualDeviceId].asMutex);
1044
updateASTraffic(actualDeviceId, src_as_id, dst_as_id, octets);
1047
/* ************************************ */
928
1049
static void processIpPkt(const u_char *bp,
929
1050
const struct pcap_pkthdr *h,
1354
1479
WIN = ntohs(tcp->th_win); /* TCP window size */
1356
if(tcp_data != tcp_opt) { /* there are some tcp_option to be parsed */
1357
u_char *opt_ptr = tcp_opt;
1481
if(tcp_data != tcp_opt) { /* there are some tcp_option to be parsed */
1482
u_char *opt_start = tcp_opt, *opt_end = tcp_data;
1483
u_short num_loops = 0;
1359
while(opt_ptr < tcp_data) {
1485
while(opt_start < opt_end) {
1486
switch(*opt_start) {
1361
1487
case TCPOPT_EOL: /* end option: exit */
1488
opt_start = opt_end;
1364
1490
case TCPOPT_NOP:
1368
1494
case TCPOPT_SACKOK:
1372
1498
case TCPOPT_MAXSEG:
1374
MSS = ntohs(ptohs(opt_ptr));
1500
MSS = ntohs(ptohs(opt_start));
1377
1503
case TCPOPT_WSCALE:
1382
1508
case TCPOPT_TIMESTAMP:
1385
opt_ptr += (*opt_ptr - 1);
1511
opt_start += (*opt_start - 1);
1390
opt_ptr += (*opt_ptr - 1);
1516
opt_start += (*opt_start - 1);
1521
if(num_loops > 16) {
1522
/* Suspicious packet: maybe the TCP options are wrong */
1396
if(WS == -1) { safe_snprintf(__FILE__, __LINE__, WSS, sizeof(WSS), "WS"); }
1397
else { safe_snprintf(__FILE__, __LINE__, WSS, sizeof(WSS), "%02d", WS); }
1529
safe_snprintf(__FILE__, __LINE__, WSS, sizeof(WSS), "WS");
1531
safe_snprintf(__FILE__, __LINE__, WSS, sizeof(WSS), "%02X", WS & 0xFFFF);
1399
if(MSS == -1) { safe_snprintf(__FILE__, __LINE__, _MSS, sizeof(_MSS), "_MSS"); }
1400
else { safe_snprintf(__FILE__, __LINE__, _MSS, sizeof(_MSS), "%04X", MSS); }
1534
safe_snprintf(__FILE__, __LINE__, _MSS, sizeof(_MSS), "_MSS");
1536
safe_snprintf(__FILE__, __LINE__, _MSS, sizeof(_MSS), "%04X", MSS & 0xFFFFFFFF);
1402
1538
safe_snprintf(__FILE__, __LINE__, fingerprint, sizeof(fingerprint),
1403
1539
"%04X:%s:%02X:%s:%d:%d:%d:%d:%c:%02X",
1457
1593
theSession = handleSession(h, fragmented, tp.th_win,
1458
1594
srcHost, sport, dstHost,
1459
dport, ntohs(ip6->ip6_plen), &tp,
1595
dport, ntohs(ip6->ip6_plen), &tp,
1461
theData, actualDeviceId, &newSession);
1597
theData, actualDeviceId, &newSession, 1);
1464
1600
theSession = handleSession(h, (off & 0x3fff), tp.th_win,
1465
1601
srcHost, sport, dstHost,
1468
theData, actualDeviceId, &newSession);
1604
theData, actualDeviceId, &newSession, 1);
1469
1605
if(theSession == NULL)
1470
1606
isPassiveSess = isVoipSess = 0;
1756
1892
dport, ntohs(ip6->ip6_plen), NULL,
1758
1894
(u_char*)(bp+hlen+sizeof(struct udphdr)),
1759
actualDeviceId, &newSession);
1895
actualDeviceId, &newSession, 1);
1762
1898
theSession = handleSession (h, (off & 0x3fff), 0,
1763
1899
srcHost, sport, dstHost,
1764
1900
dport, ip_len, NULL, udpDataLength,
1765
1901
(u_char*)(bp+hlen+sizeof(struct udphdr)),
1766
actualDeviceId, &newSession);
1902
actualDeviceId, &newSession, 1);
1769
1905
isPassiveSess = 0;
1771
1907
if(theSession == NULL)
1772
1908
isVoipSess = 0;
1774
isVoipSess = theSession->voipSession;
1910
isVoipSess = theSession->voipSession;
1776
1912
newSession = 1; /* Trick to account flows anyway */
1791
1927
if(dport < sport) {
1792
if(handleIP(dport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1928
if(handleIP(dport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1793
1929
0, actualDeviceId, newSession) == -1)
1794
handleIP(sport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1930
handleIP(sport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1795
1931
0, actualDeviceId, newSession);
1797
if(handleIP(sport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1933
if(handleIP(sport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1798
1934
0, actualDeviceId, newSession) == -1)
1799
handleIP(dport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1935
handleIP(dport, srcHost, dstHost, length, isPassiveSess, isVoipSess,
1800
1936
0, actualDeviceId, newSession);
2261
2399
if(myGlobals.ntopRunState > FLAG_NTOPSTATE_RUN) return;
2264
traceEvent(CONST_TRACE_INFO, "Got packet from %s (%d)", myGlobals.device[*_deviceId].name, *_deviceId);
2267
deviceId = (int)_deviceId;
2401
deviceId = (int)((long)_deviceId);
2268
2402
actDeviceId = getActualInterface(deviceId);
2269
2403
incrementTrafficCounter(&myGlobals.device[actDeviceId].receivedPkts, 1);
2271
if(myGlobals.device[actDeviceId].samplingRate > 1) {
2272
if(myGlobals.device[actDeviceId].droppedSamples < myGlobals.device[actDeviceId].samplingRate) {
2273
myGlobals.device[actDeviceId].droppedSamples++;
2274
return; /* Not enough samples received */
2276
myGlobals.device[actDeviceId].droppedSamples = 0;
2405
/* We assume that if there's a packet to queue for the sFlow interface
2406
then this has been queued by the sFlow plugins, while it was
2407
probably handling a queued packet */
2410
traceEvent(CONST_TRACE_INFO, "queuePacket: got packet from %s (%d)",
2411
myGlobals.device[deviceId].name, deviceId);
2414
/* We don't sample on sFlow sampled interfaces */
2415
if(myGlobals.device[deviceId].sflowGlobals == NULL) {
2416
if(myGlobals.device[actDeviceId].samplingRate > 1) {
2417
if(myGlobals.device[actDeviceId].droppedSamples < myGlobals.device[actDeviceId].samplingRate) {
2418
myGlobals.device[actDeviceId].droppedSamples++;
2419
return; /* Not enough samples received */
2421
myGlobals.device[actDeviceId].droppedSamples = 0;
2279
2425
if(myGlobals.runningPref.dontTrustMACaddr && (h->len <= 64)) {
2296
2442
if(len >= DEFAULT_SNAPLEN) len = DEFAULT_SNAPLEN-1;
2299
if(h->len >= MAX_PACKET_LEN) {
2300
traceEvent(CONST_TRACE_WARNING, "packet truncated (%d->%d)", h->len, MAX_PACKET_LEN);
2301
((struct pcap_pkthdr*)h)->len = MAX_PACKET_LEN-1;
2304
if(len >= MAX_PACKET_LEN) {
2305
bpf_u_int32 *caplen = (bpf_u_int32*)&(h->caplen);
2307
len = MAX_PACKET_LEN-1;
2309
Trick needed to avoid compilation errors
2310
as caplen is defined as 'const'
2445
if(h->caplen >= MAX_PACKET_LEN) {
2446
if(h->caplen > myGlobals.device[deviceId].mtuSize) {
2447
traceEvent(CONST_TRACE_WARNING, "packet truncated (%d->%d)",
2448
h->len, MAX_PACKET_LEN);
2451
((struct pcap_pkthdr*)h)->caplen = MAX_PACKET_LEN-1;
2315
2454
memcpy(p1, p, len);
2317
2456
processPacket(_deviceId, h, p1);
2318
releaseMutex(&myGlobals.packetProcessMutex);
2457
releaseMutex(&myGlobals.device[deviceId].packetProcessMutex);
2323
If we reach this point it means that somebody was already processing
2324
a packet so we need to queue it
2462
If we reach this point it means that somebody was already
2463
processing a packet so we need to queue it.
2326
if(myGlobals.packetQueueLen >= CONST_PACKET_QUEUE_LENGTH) {
2465
if(myGlobals.device[deviceId].packetQueueLen >= CONST_PACKET_QUEUE_LENGTH) {
2328
traceEvent(CONST_TRACE_INFO, "Dropping packet!!! [packet queue=%d/max=%d]",
2329
myGlobals.packetQueueLen, myGlobals.maxPacketQueueLen);
2467
traceEvent(CONST_TRACE_INFO, "Dropping packet [packet queue=%d/max=%d][id=%d]",
2468
myGlobals.device[deviceId].packetQueueLen, myGlobals.maxPacketQueueLen, deviceId);
2332
2471
myGlobals.receivedPacketsLostQ++;
2334
2472
incrementTrafficCounter(&myGlobals.device[getActualInterface(deviceId)].droppedPkts, 1);
2336
2473
ntop_conditional_sched_yield(); /* Allow other threads (dequeue) to run */
2340
2477
traceEvent(CONST_TRACE_INFO, "About to queue packet... ");
2342
accessMutex(&myGlobals.packetQueueMutex, "queuePacket");
2479
accessMutex(&myGlobals.device[deviceId].packetQueueMutex, "queuePacket");
2343
2480
myGlobals.receivedPacketsQueued++;
2344
memcpy(&myGlobals.packetQueue[myGlobals.packetQueueHead].h, h, sizeof(struct pcap_pkthdr));
2345
memset(myGlobals.packetQueue[myGlobals.packetQueueHead].p, 0,
2346
sizeof(myGlobals.packetQueue[myGlobals.packetQueueHead].p));
2481
memcpy(&myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].h,
2482
h, sizeof(struct pcap_pkthdr));
2483
memset(myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].p, 0,
2484
sizeof(myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].p));
2347
2485
/* Just to be safe */
2348
2486
len = h->caplen;
2349
if (myGlobals.runningPref.printIpOnly) {
2350
if(len >= DEFAULT_SNAPLEN) len = DEFAULT_SNAPLEN-1;
2351
memcpy(myGlobals.packetQueue[myGlobals.packetQueueHead].p, p, len);
2352
myGlobals.packetQueue[myGlobals.packetQueueHead].h.caplen = len;
2355
memcpy(myGlobals.packetQueue[myGlobals.packetQueueHead].p, p, len);
2356
myGlobals.packetQueue[myGlobals.packetQueueHead].h.caplen = len;
2487
if(myGlobals.runningPref.printIpOnly) {
2488
if(len >= DEFAULT_SNAPLEN) len = DEFAULT_SNAPLEN-1;
2489
memcpy(myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].p, p, len);
2490
myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].h.caplen = len;
2492
memcpy(myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].p, p, len);
2493
myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].h.caplen = len;
2359
myGlobals.packetQueue[myGlobals.packetQueueHead].deviceId = (int)((void*)_deviceId);
2360
myGlobals.packetQueueHead = (myGlobals.packetQueueHead+1) % CONST_PACKET_QUEUE_LENGTH;
2361
myGlobals.packetQueueLen++;
2362
if(myGlobals.packetQueueLen > myGlobals.maxPacketQueueLen)
2363
myGlobals.maxPacketQueueLen = myGlobals.packetQueueLen;
2364
releaseMutex(&myGlobals.packetQueueMutex);
2496
myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueHead].deviceId =
2497
(int)((long)((void*)_deviceId));
2498
myGlobals.device[deviceId].packetQueueHead = (myGlobals.device[deviceId].packetQueueHead+1)
2499
% CONST_PACKET_QUEUE_LENGTH;
2500
myGlobals.device[deviceId].packetQueueLen++;
2501
if(myGlobals.device[deviceId].packetQueueLen > myGlobals.device[deviceId].maxPacketQueueLen)
2502
myGlobals.device[deviceId].maxPacketQueueLen = myGlobals.device[deviceId].packetQueueLen;
2503
releaseMutex(&myGlobals.device[deviceId].packetQueueMutex);
2366
2505
traceEvent(CONST_TRACE_INFO, "Queued packet... [packet queue=%d/max=%d]",
2367
myGlobals.packetQueueLen, myGlobals.maxPacketQueueLen);
2506
myGlobals.device[deviceId].packetQueueLen, myGlobals.maxPacketQueueLen);
2370
2509
#ifdef DEBUG_THREADS
2371
2510
traceEvent(CONST_TRACE_INFO, "+ [packet queue=%d/max=%d]",
2372
myGlobals.packetQueueLen, myGlobals.maxPacketQueueLen);
2511
myGlobals.device[deviceId].packetQueueLen, myGlobals.maxPacketQueueLen);
2376
signalCondvar(&myGlobals.queueCondvar);
2515
signalCondvar(&myGlobals.device[deviceId].queueCondvar);
2378
2517
ntop_conditional_sched_yield(); /* Allow other threads (dequeue) to run */
2430
2569
&& (myGlobals.runningPref.enablePacketDecoding /* Courtesy of Ken Beaty <ken@ait.com> */))
2431
2570
traceEvent (CONST_TRACE_WARNING, "dequeuePacket: caplen %d != len %d\n", h.caplen, h.len);
2433
if (myGlobals.runningPref.printIpOnly) {
2434
memcpy(p, myGlobals.packetQueue[myGlobals.packetQueueTail].p, DEFAULT_SNAPLEN);
2436
memcpy(p, myGlobals.packetQueue[myGlobals.packetQueueTail].p, MAX_PACKET_LEN);
2572
if (myGlobals.runningPref.printIpOnly)
2573
memcpy(p, myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueTail].p, DEFAULT_SNAPLEN);
2575
memcpy(p, myGlobals.device[deviceId].packetQueue[myGlobals.device[deviceId].packetQueueTail].p, MAX_PACKET_LEN);
2439
2577
if(h.len > MAX_PACKET_LEN) {
2440
2578
traceEvent(CONST_TRACE_WARNING, "packet truncated (%d->%d)", h.len, MAX_PACKET_LEN);
2441
2579
h.len = MAX_PACKET_LEN;
2444
myGlobals.packetQueueTail = (myGlobals.packetQueueTail+1) % CONST_PACKET_QUEUE_LENGTH;
2445
myGlobals.packetQueueLen--;
2446
releaseMutex(&myGlobals.packetQueueMutex);
2582
myGlobals.device[deviceId].packetQueueTail = (myGlobals.device[deviceId].packetQueueTail+1) % CONST_PACKET_QUEUE_LENGTH;
2583
myGlobals.device[deviceId].packetQueueLen--;
2584
releaseMutex(&myGlobals.device[deviceId].packetQueueMutex);
2447
2585
#ifdef DEBUG_THREADS
2448
traceEvent(CONST_TRACE_INFO, "- [packet queue=%d/max=%d]", myGlobals.packetQueueLen, myGlobals.maxPacketQueueLen);
2586
traceEvent(CONST_TRACE_INFO, "- [packet queue=%d/max=%d]", myGlobals.device[deviceId].packetQueueLen, myGlobals.maxPacketQueueLen);
2452
traceEvent(CONST_TRACE_INFO, "Processing packet... [packet queue=%d/max=%d]",
2453
myGlobals.packetQueueLen, myGlobals.maxPacketQueueLen);
2590
traceEvent(CONST_TRACE_INFO, "Processing packet... [packet queue=%d/max=%d][id=%d]",
2591
myGlobals.device[deviceId].packetQueueLen, myGlobals.maxPacketQueueLen, deviceId);
2456
2594
myGlobals.actTime = time(NULL);
2457
accessMutex(&myGlobals.packetProcessMutex, "dequeuePacket");
2595
accessMutex(&myGlobals.device[deviceId].packetProcessMutex, "dequeuePacket");
2458
2596
processPacket((u_char*)((long)deviceId), &h, p);
2459
releaseMutex(&myGlobals.packetProcessMutex);
2597
releaseMutex(&myGlobals.device[deviceId].packetProcessMutex);
2462
myGlobals.dequeueThreadId = 0;
2600
myGlobals.device[deviceId].dequeuePacketThreadId = 0;
2464
2602
traceEvent(CONST_TRACE_INFO,
2465
"THREADMGMT[t%lu]: NPA: network packet analyzer (packet processor) thread terminated [p%d]",
2466
pthread_self(), getpid());
2603
"THREADMGMT[t%lu]: NPA: network packet analyzer (%s) thread terminated [p%d]",
2604
pthread_self(), myGlobals.device[deviceId].humanFriendlyName, getpid());
3530
3676
processIpPkt(p+hlen, h, length, ether_src, ether_dst, actualDeviceId, vlanId);
3678
} else if(eth_type == 0xDEAD) /* Agilent */ {
3680
u_int8_t version; /* Protocol Version */
3681
u_int8_t response_pdu; /* 0=Request, 1=Response */
3682
u_int8_t fragment_id; /* Fragment Id (Only for
3683
fragmented FORWARD responses) */
3684
u_int8_t pdu_type; /* See sgbic_pdu_type */
3685
u_int16_t pdu_id; /* Unique (serial) PDU identifier */
3686
u_int16_t pdu_len; /* length (bytes) of the PDU (not
3687
including this header) */
3688
u_char digest[16]; /* MD5 digest */
3691
sgbic_header_v1 *pdu;
3693
if(length > hlen+sizeof(sgbic_header_v1)) {
3694
pdu = (sgbic_header_v1*)(p+hlen);
3696
if((pdu->version == 1) && (pdu->pdu_type == 2 /* forward */)) {
3697
static u_short last_pdu_len, last_pdu_id;
3698
u_short size_shift = hlen+sizeof(sgbic_header_v1);
3700
if(pdu->fragment_id == 0) {
3701
struct pcap_pkthdr h1;
3703
h1.caplen = h->caplen-size_shift;
3704
h1.len = h->len-size_shift;
3705
h1.ts.tv_sec = h->ts.tv_sec;
3706
h1.ts.tv_usec = h->ts.tv_usec;
3709
if(last_pdu_id == pdu->pdu_id) {
3711
traceEvent(CONST_TRACE_ERROR, "[vers=%d][pdu_type=%d][pdu_id=%d][len=%d][fragment_id=%d]",
3712
pdu->version, pdu->pdu_type, pdu->pdu_id, ntohs(pdu->pdu_len), pdu->fragment_id);
3714
h1.len += last_pdu_len;
3716
traceEvent(CONST_TRACE_ERROR, "[caplen=%d][len=%d][last_pdu_len=%d]",
3717
h1.caplen, h1.len, last_pdu_len);
3720
processPacket(_deviceId, &h1, p+size_shift);
3722
last_pdu_len = h->len-size_shift, last_pdu_id = pdu->pdu_id;
3725
traceEvent(CONST_TRACE_ERROR, "[vers=%d][pdu_type=%d][pdu_id=%d][len=%d][fragment_id=%d]",
3726
pdu->version, pdu->pdu_type, pdu->pdu_id, ntohs(pdu->pdu_len), pdu->fragment_id);
3532
3732
} else if(eth_type == 0x8864) /* PPPOE */ {
3533
/* PPPoE - Courtesy of Andreas Pfaller Feb2003
3733
/* PPPoE - Courtesy of Andreas Pfaller Feb20032
3534
3734
* This strips the PPPoE encapsulation for traffic transiting the network.
3536
3736
struct pppoe_hdr *pppoe_hdr=(struct pppoe_hdr *) (p+hlen);