Netexpert FAQ 网络分析专家学习建议入口 @netexpert成员申请指南
网络分析时代 netexpert积分规则的说明 Netis招贤纳士(2008年11月22日更新)
发新话题
打印

tcpdump的时间戳的计算

tcpdump的时间戳的计算

详细见二楼

最近需要用程序读入tcpdump的输出*.cap,但网上根本没有其存储格式的资料,劳烦知道的共享一下,以解燃眉之急。

我知道ethereal可以读取,但我必须将数据读入到自己的程序,所以还是得分析cap的格式。网上说winpcap的帮助中有,但是我找了(4.0的),却没看到类似的东西...
现在有病乱投医,无论是直接分析cap文件,还是通过winpcap(或libpcap)的函数实现都行!先谢过了。


[ 本帖最后由 grsgrs 于 2008-3-13 19:57 编辑 ]
对不起,因为你的签名过于华丽而被系统屏蔽!
请更换更加朴素的再试。

TOP

现在大致弄懂了点,只是不知道时间戳的表示方式:
(下面红色部分就是记录时间的一串,就是不知道怎么算出时间戳:16:08:28.440861000 01/12/2007 的)
00000000   D4 C3 B2 A1 02 00 04 00  00 00 00 00 00 00 00 00
00000010   60 00 00 00 01 00 00 00  FC 41 A7 45 1D BA 06 00
00000020   3E 00 00 00 3E 00 00 00  00 0D 29 87 59 28 00 14
00000030   78 86 7A D6 08 00 45 00  00 30 ...

用tcpdump导出的*.cap文件,格式如上面所示。现在知道了之前的24字节是文件头可以不管,红色部分因该就是时间戳,之后是包的内容。
tcpdump -n -r a.cap 显示该时间戳为 16:08:28.440861000 01/12/2007,这个是怎么算出来的啊?有人知道吗?



算了,最后还是自己弄的,00000010   60 00 00 00 01 00 00 00  FC 41 A7 45 1D BA 06 00
FC 41 A7 45 是以秒为单位的时间日期,后面的4位是微妙

00000020   3E 00 00 00 3E 00 00 00
这两个是包长,一个代表实际文件中存储的长度,一个是原始长度。
end.

[ 本帖最后由 grsgrs 于 2008-3-13 20:00 编辑 ]
对不起,因为你的签名过于华丽而被系统屏蔽!
请更换更加朴素的再试。

TOP

弱弱问一句
      那时间是怎么转换的啊?
   FC 41 A7 45 1D BA 06 00==16:08:28

TOP

其实我也不是很懂,前面是记录的秒数,后面是微秒:
FC 41 A7 45 读入后是 0x45A741FC,是一个从某时刻到现在的秒数,不出意外的话,从1980-1-1 0:00:00开始
这里是 01/12/2007 16:08:28

1D BA 06 00 是 0x0006BA1D 即 440861,看到了,那个 .440861000 就是这么来的。

ps: 要是你研究出了秒数的计算方法,也请告诉我

[ 本帖最后由 grsgrs 于 2008-3-17 16:49 编辑 ]
对不起,因为你的签名过于华丽而被系统屏蔽!
请更换更加朴素的再试。

TOP

总的来说,要自己想办法来实现,没有现成的函数可供调用,但是可以参考人家的处理思路,其实自己独立想出来的方法,往往更适合自己的代码。
从绝对的秒数转换成某年某月的形式,大概要考虑的问题有timezone,从1970年到现在之间经过的闰年的个数,有时候还有闰秒的问题(NTP时间戳处理有这个问题),其余的就是从秒数到年月日小时的转换了。
如果实在没有思路,就参考tcpdump的源代码,这是windump的时间戳处理的一小段
/*
* Print the timestamp
*/
void
ts_print(register const struct timeval *tvp)
{
        register int s;
        struct tm *tm;
        time_t Time;
        static unsigned b_sec;
        static unsigned b_usec;

        switch (tflag) {

        case 0: /* Default */
                s = (tvp->tv_sec + thiszone) % 86400;
                (void)printf("%02d:%02d:%02d.%06u ",
                             s / 3600, (s % 3600) / 60, s % 60,
                             (unsigned)tvp->tv_usec);
                break;

        case 1: /* No time stamp */
                break;

        case 2: /* Unix timeval style */
                (void)printf("%u.%06u ",
                             (unsigned)tvp->tv_sec,
                             (unsigned)tvp->tv_usec);
                break;

        case 3: /* Microseconds since previous packet */
                if (b_sec == 0) {
                        printf("000000 ");
                } else {
                        int d_usec = tvp->tv_usec - b_usec;
                        int d_sec = tvp->tv_sec - b_sec;

                        while (d_usec < 0) {
                                d_usec += 1000000;
                                d_sec--;
                        }
                        if (d_sec)
                                printf("%d. ", d_sec);
                        printf("%06d ", d_usec);
                }
                b_sec = tvp->tv_sec;
                b_usec = tvp->tv_usec;
                break;

        case 4: /* Default + Date*/
                s = (tvp->tv_sec + thiszone) % 86400;
                Time = (tvp->tv_sec + thiszone) - s;
                tm = gmtime (&Time);
                if (!tm)
                        printf("Date fail  ");
                else
                        printf("%04d-%02d-%02d ",
                                   tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
                printf("%02d:%02d:%02d.%06u ",
                           s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
                break;
        }
}

TOP

Libpcap File Format
The libpcap file format is the main capture file format used in TcpDump/WinDump, Wireshark/TShark, snort, and many other networking tools.

Overview
This file format is a very basic format to save captured network data. As the libpcap library became the "de facto" standard of network capturing on UN*X, it became the "common denominator" for network capture files in the open source world (there seems to be no such thing as a "common denominator" in the commercial network capture world at all).


Libpcap, and the Windows port of libpcap, WinPcap, use the same file format.


Although it's sometimes assumed that this file format is suitable for Ethernet networks only, it can serve many different network types.


The proposed file extension for libpcap based files is: .pcap


Wireshark handles all capture file I/O in the wiretap library. You'll find further details about the libpcap file format in the wiretap/libpcap.c and .h files



File Format
There are some variants of the format "in the wild", the following will only describe the commonly used format in its current version 2.4. This format version hasn't changed for quite a while (at least since libpcap 0.4 in 1998), so it's not expected to change except for the PCAPng file format mentioned below.


The file has a global header containing some global information followed by zero or more records for each captured packet, looking like this:

Global Header
Packet Header
Packet Data
Packet Header
Packet Data
Packet Header
Packet Data
...



A captured packet in a capture file does not necessarily contain all the data in the packet as it appeared on the network; the capture file might contain at most the first N bytes of each packet, for some value of N. The value of N, in such a capture, is called the "snapshot length" or "snaplen" of the capture. N might be a value larger than the largest possible packet, to ensure that no packet in the capture is "sliced" short; a value of 65535 will typically be used in this case.



Global Header
  • This header starts the libpcap file and will be followed by the first packet header:

    typedef struct pcap_hdr_s {
            guint32 magic_number;   /* magic number */
            guint16 version_major;  /* major version number */
            guint16 version_minor;  /* minor version number */
            gint32  thiszone;       /* GMT to local correction */
            guint32 sigfigs;        /* accuracy of timestamps */
            guint32 snaplen;        /* max length of captured packets, in octets */
            guint32 network;        /* data link type */
    } pcap_hdr_t;
    • magic_number: used to detect the file format itself and the byte ordering. The writing application writes 0xa1b2c3d4 with it's native byte ordering format into this field. The reading application will read either 0xa1b2c3d4 (identical) or 0xd4c3b2a1 (swapped). If the reading application reads the swapped 0xd4c3b2a1 value, it knows that all the following fields will have to be swapped too.
    • version_major, version_minor: the version number of this file format (current version is 2.4)
    • thiszone: the correction time in seconds between GMT (UTC) and the local timezone of the following packet header timestamps. Examples: If the timestamps are in GMT (UTC), thiszone is simply 0. If the timestamps are in Central European time (Amsterdam, Berlin, ...) which is GMT + 1:00, thiszone must be -3600. In practice, time stamps are always in GMT, so thiszone is always 0.
    • sigfigs: in theory, the accuracy of time stamps in the capture; in practice, all tools set it to 0
    • snaplen: the "snapshot length" for the capture (typically 65535 or even more, but might be limited by the user), see: incl_len vs. orig_len below
    • network: data link layer type (e.g. 1 for Ethernet, see wiretap/libpcap.c or libpcap's pcap-bpf.h for details), this can be various types like Token Ring, FDDI, etc.
    Note: if you need a new encapsulation type for libpcap files (the value for the network field), do NOT use ANY of the existing values! I.e., do NOT add a new encapsulation type by changing an existing entry; leave the existing entries alone. Instead, send mail to tcpdump-workers@tcpdump.org , asking for a new DLT_ value, and specifying the purpose of the new value.


Record (Packet) Header
  • Each captured packet starts with (any byte alignment possible):


    typedef struct pcaprec_hdr_s {
            guint32 ts_sec;         /* timestamp seconds */
            guint32 ts_usec;        /* timestamp microseconds */
            guint32 incl_len;       /* number of octets of packet saved in file */
            guint32 orig_len;       /* actual length of packet */
    } pcaprec_hdr_t;
    • ts_sec: the date and time when this packet was captured. This value is in seconds since January 1, 1970 00:00:00 GMT; this is also known as a UN*X time_t. You can use the ANSI C time() function from time.h to get this value, but you might use a more optimized way to get this timestamp value. If this timestamp isn't based on GMT (UTC), use thiszone from the global header for adjustments.
    • ts_usec: the microseconds when this packet was captured, as an offset to ts_sec. Beware: this value shouldn't reach 1 second (1 000 000), in this case ts_sec must be increased instead!
    • incl_len: the number of bytes of packet data actually captured and saved in the file. This value should never become larger than orig_len or the snaplen value of the global header.
    • orig_len: the length of the packet as it appeared on the network when it was captured. If incl_len and orig_len differ, the actually saved packet size was limited by snaplen.


* From Wireshark Wiki

TOP

呃,谢谢楼上的两位。实际已经算出来了,而且相当简单:
第一个四字节是秒数,这个是标准C++中的 CTime::time_t 类型,用 ctime() 输出时间。

Delphi里面也有人写过转化函数,如下:
// 将libpcap的 CTime::time_t 格式时间转化为 TDateTime
function time_t2DateTime(vTime_t: DWORD): TDateTime;
const
  cDeltaDate  : DWORD = 25569; // 1970/01/01
  cSecPerMint : DWORD = 60;
  cSecPerHour : DWORD = (60*60);
  cSecPerDay  : DWORD = (60*60*24);
var
  hh, mm, ss: Word;
  n: DWORD;
begin
  // GMT=+8,格林时间+8时区(北京)
  vtime_t := vtime_t + cSecPerHour*8 ;
  n := vtime_t mod cSecPerDay;
  hh := n div cSecPerHour;
  n := n mod cSecPerHour;
  mm := n div cSecPerMint;
  ss := n mod cSecPerMint;
  Result := (vtime_t div cSecPerDay) + cDeltaDate + EncodeTime(hh, mm, ss, 0);
end;



感谢楼上版主提供的结构,一直没把头部的24字节看懂:
typedef struct pcap_hdr_s {
        guint32 magic_number;   /* magic number */
        guint16 version_major;  /* major version number */
        guint16 version_minor;  /* minor version number */
        gint32  thiszone;       /* GMT to local correction */
        guint32 sigfigs;        /* accuracy of timestamps */
        guint32 snaplen;        /* max length of captured packets, in octets */
        guint32 network;        /* data link type */
} pcap_hdr_t;
有了这个说明真是恍然大悟!

[ 本帖最后由 grsgrs 于 2008-5-7 17:27 编辑 ]
对不起,因为你的签名过于华丽而被系统屏蔽!
请更换更加朴素的再试。

TOP

发新话题
版块跳转