Menu

#35 1.6.1 - Incorrect calculation of first/last field

open
nobody
None
5
2010-06-28
2010-06-28
No

The same bug is reported for version < 1.6

The calculation of master_record_t->last/first field is incorrect in Process_v9_data function.

The below mentioned code reference is from nfdump1.5.7, but the similar issue exists in nfdump1.6.1.
----------------------------------------------------------------------------------------------------------------------------------------------------

How do nfcapd calculate exporter boot time ?

For every template/data flowset we calculate exporter router's boot time.
/* calculate boot time in msec */
v9_header->SysUptime = ntohl(v9_header->SysUptime);
v9_header->unix_secs = ntohl(v9_header->unix_secs);
exporter->boot_time = (uint64_t)1000 * (uint64_t)(v9_header->unix_secs) - (uint64_t)v9_header->SysUptime;

where
sys_uptime 4-7( 4Bytes field) Current time in milliseconds since the export device booted.
unix_secs 8-11(4 Bytes field) Time in seconds since 0000 UTC 1970, at which the Export Packet
leaves the Exporter.

sys_uptime is a 4 byte field, so it will overflow after 4294967296 msec ( ~ 50 days). So after every ~50 days, the exporter's boot_time will shift by ~50 days.

How do nfcapd calculate the time stamp ( since 0000 UTC 1970 ) for a netflow record ( we save this in master_record->last field) ?

First = data_record->first;
Last = data_record->last;

if ( First > Last )
/* Last in msec, in case of msec overflow, between start and end */
end_time = 0x100000000LL + Last + exporter->boot_time;
else
end_time = (uint64_t)Last + exporter->boot_time;

data_record->last = end_time/1000;

Here first, last field of data_record( master_record_t) are :

LAST_SWITCHED 21 4 Bytes field System uptime at which the last packet of this flow was switched
FIRST_SWITCHED 22 4 Bytes field System uptime at which the first packet of this flow was switched

These fields are 4 bytes fields, so they will overflow after ~50 days.

Consider these conditions for a netflow record.

Condition #1
sys_uptime/last_switched/first_switched have crossed the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
- first/last_switched:: after overflow the value in these fields will be like offset after 50 days.

In this condition the calculation of data_record->last field is correct.

Condition #2
sys_uptime has crossed the 50 days boundary. But first/last_switched did not cross the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
- first/last_switched:: they are the offset from the previous exporter_boot->time boundary.

In this condition the calculation for end_time is wrong ( end_time = (uint64_t)Last + exporter->boot_time; )

Condition #3
sys_uptime & last_switched have crossed the 50 days boundary. But first_switched did not cross the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
-last_switched:: after overflow the value in these fields will be like offset after 50 days.

In this situation First > Last condition will hold true. But the calculation for this case is again wrong ( end_time = 0x100000000LL + Last + exporter->boot_time; ).
Here we don't need to add the 0x100000000L value to Last.

Discussion