为什么要在libpcap程序中重新声明TCP和IP头?

时间:2015-10-04 19:28:23

标签: c struct libpcap

libpcap 的教程中,我看到以下结构:

/* IP header */
struct sniff_ip {
    u_char  ip_vhl;                 
    u_char  ip_tos;                 
    u_short ip_len;                 
    u_short ip_id;                  
    u_short ip_off;                 
    #define IP_RF 0x8000            
    #define IP_DF 0x4000            
    #define IP_MF 0x2000            
    #define IP_OFFMASK 0x1fff       
    u_char  ip_ttl;                 
    u_char  ip_p;                   
    u_short ip_sum;                 
    struct  in_addr ip_src,ip_dst;  
};
#define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip)                (((ip)->ip_vhl) >> 4)

/* TCP header */
typedef u_int tcp_seq;

struct sniff_tcp {
    u_short th_sport;               
    u_short th_dport;               
    tcp_seq th_seq;                 
    tcp_seq th_ack;                 
    u_char  th_offx2;               
    #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
    u_char  th_flags;
    #define TH_FIN  0x01
    #define TH_SYN  0x02
    #define TH_RST  0x04
    #define TH_PUSH 0x08
    #define TH_ACK  0x10
    #define TH_URG  0x20
    #define TH_ECE  0x40
    #define TH_CWR  0x80
    #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
    u_short th_win;                 
    u_short th_sum;                 
    u_short th_urp;                 
};

为什么上面标题的结构已被重新声明,并且netinet/tcp.hnetinet/ip.h中的TCP和IP结构未被使用? 使用这个自定义结构有一些优势吗?

1 个答案:

答案 0 :(得分:1)

简短回答:这只是一个例子。

正如本教程作者对本文的评论中所指出的那样,存在可移植性问题,因为并非所有操作系统都提供这样的网络结构,另一方面格式由RFC明确定义,因此自己的结构可以是使用

教程演变

原始文件于2005年修改(有一条说明“由Guy Harris进一步编辑和开发”)。原始文档可以在cvs中找到1.1版:

  

首先,我们必须先确定实际结构   对他们进行类型转换。以下是我的结构定义   用于描述以太网上的TCP / IP数据包。所有三个定义   我使用的是直接从POSIX库中获取的。通常我   只会简单地使用这些库中的定义,但它   我的经验是,图书馆与平台略有不同   平台,使其快速实施变得复杂。因此对于   演示目的我们将避免这种混乱,只需复制   相关结构。顺便提一下,所有这些都可以在   本地Unix系统上的include/features.h。以下是结构:

有linux结构的原始副本(现在它们在示例中被修改)。解释:

  

注意:在我的Slackware Linux 8盒子(库存内核2.2.19)上,我找到了   使用上述结构的代码无法编译。问题,因为它   原来,在_BSD_SOURCE,实现了POSIX   接口,除非定义了#define _BSD_SOURCE 1。如果它没有定义,那么   我不得不为TCP标头使用不同的结构定义。该   更通用的解决方案,不会阻止代码工作   在FreeBSD或OpenBSD上(以前工作正常),简单来说就是这样   做以下事项:
  {{1}}
在包含任何标头文件之前。这将确保使用BSD样式的API。再说一遍,如果你   不希望这样做,那么你可以简单地使用替代TCP   标题结构,我已经链接到这里,以及一些快速   关于使用它的注意事项。

因此,在文档版本之后,在v1.2中修改了结构,并在v1.6中使用以下提交注释更改了文本:

  

不要谈论来自POSIX的任何内容(它没有),也不要   请注意,他们可能在UN * X系统上可用(不要拿你的   来自OS的数据包布局;它可能没有它们,或者它们可能没有它们   拥有你想要的所有协议功能。