为什么要在 libpcap 程序中重新声明 TCP 和 IP headers?
Why redeclare TCP and IP headers in a libpcap program?
在 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;
};
为什么上面headers的结构被重新声明了,而netinet/tcp.h
、netinet/ip.h
中的TCP和IP结构没有被使用?
使用这个自定义结构有什么好处吗?
简短的回答:这只是一个例子。
正如本教程的作者对此 post 的评论中指出的那样,存在可移植性问题,因为并非所有操作系统都提供此类网络结构,另一方面,格式由 RFC 明确定义, 所以可以使用自己的结构。
教程进化
原文档2005年修改(有注释"Further editing and development by Guy Harris")。可以在 cvs:
中找到原始文档 1.1 版
First, we must have the actual structures define before we can
typecast to them. The following is the structure definitions that I
use to describe a TCP/IP packet over Ethernet. All three definitions
that I use are taken directly out of the POSIX libraries. Normally I
would have simply just used the definitions in those libraries, but it
has been my experience that the libraries vary slightly from platform
to platform, making it complicated to implement them quickly. So for
demonstration purposes we will just avoid that mess and simply copy
the relevant structures. All of these, incidentally, can be found in
include/netinet
on your local Unix system. Here are the structures:
有 linux 结构的原始副本(现在在示例中进行了修改)。解释:
Note: On my Slackware Linux 8 box (stock kernel 2.2.19) I found that
code using the above structures would not compile. The problem, as it
turns out, was in include/features.h
, which implements a POSIX
interface unless _BSD_SOURCE
is defined. If it was not defined, then
I had to use a different structure definition for the TCP header. The
more universal solution, that does not prevent the code from working
on FreeBSD or OpenBSD (where it had previously worked fine), is simply
to do the following:
#define _BSD_SOURCE 1
prior to including any of your header files. This will ensure that a BSD style API is being used. Again, if you
don't wish to do this, then you can simply use the alternative TCP
header structure, which I've linked to here, along with some quick
notes about using it.
因此,在文档版本之后,在 v1.2 中修改了结构,在 v1.6 中更改了文本,并使用以下提交注释:
Don't talk about any of this coming from POSIX (it doesn't) and don't
note that they might be available on a UN*X system (don't take your
packet layouts from the OS; it might not have them, or they might not
have all the protocol features you want).
在 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;
};
为什么上面headers的结构被重新声明了,而netinet/tcp.h
、netinet/ip.h
中的TCP和IP结构没有被使用?
使用这个自定义结构有什么好处吗?
简短的回答:这只是一个例子。
正如本教程的作者对此 post 的评论中指出的那样,存在可移植性问题,因为并非所有操作系统都提供此类网络结构,另一方面,格式由 RFC 明确定义, 所以可以使用自己的结构。
教程进化
原文档2005年修改(有注释"Further editing and development by Guy Harris")。可以在 cvs:
中找到原始文档 1.1 版First, we must have the actual structures define before we can typecast to them. The following is the structure definitions that I use to describe a TCP/IP packet over Ethernet. All three definitions that I use are taken directly out of the POSIX libraries. Normally I would have simply just used the definitions in those libraries, but it has been my experience that the libraries vary slightly from platform to platform, making it complicated to implement them quickly. So for demonstration purposes we will just avoid that mess and simply copy the relevant structures. All of these, incidentally, can be found in
include/netinet
on your local Unix system. Here are the structures:
有 linux 结构的原始副本(现在在示例中进行了修改)。解释:
Note: On my Slackware Linux 8 box (stock kernel 2.2.19) I found that code using the above structures would not compile. The problem, as it turns out, was in
include/features.h
, which implements a POSIX interface unless_BSD_SOURCE
is defined. If it was not defined, then I had to use a different structure definition for the TCP header. The more universal solution, that does not prevent the code from working on FreeBSD or OpenBSD (where it had previously worked fine), is simply to do the following:
#define _BSD_SOURCE 1
prior to including any of your header files. This will ensure that a BSD style API is being used. Again, if you don't wish to do this, then you can simply use the alternative TCP header structure, which I've linked to here, along with some quick notes about using it.
因此,在文档版本之后,在 v1.2 中修改了结构,在 v1.6 中更改了文本,并使用以下提交注释:
Don't talk about any of this coming from POSIX (it doesn't) and don't note that they might be available on a UN*X system (don't take your packet layouts from the OS; it might not have them, or they might not have all the protocol features you want).