« | September 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | | | | |
| 登录 |
| 联系我 email: binaryluo(at)gmail.com
Blog信息 |
blog名称:二进制-虚心使人进步,骄傲使人落后。 日志总数:42 评论数量:370 留言数量:88 访问次数:639394 建立时间:2005年2月19日 |

| |
[网络编程技术]Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo 发表于 2006/2/3 21:31:22 |
函数2:
int pcap_compile(pcap_t* p,
struct bpf_program* fp,
char* str,
int optimize,
bpf_u_int32 netmask)
编译一个数据包过滤器,将一个能被核心态(kernel-level)过滤器引擎解释的程序中的高层过滤表达式(filtering expression)进行转化。pcap_compile()被用来将字符串str编译进过滤器程序(fp),程序(fp)是一个指向bpf_program结构体并被pcap_compile()赋值的指针。optimize控制是否对目标代码(resulting code)的性能进行优化。Netmask表明IPv4掩码,它仅在检查过滤器程序中的IPv4广播地址的时候被使用。如果网络掩码对于程序是不可知的或者数据包是在Linux的”任何(any)”伪接口上被捕获的,则赋值0;IPv4广播地址的测试将不被正确进行,但过滤器程序中的其他所有的测试都不会有问题。返回-1表示发生了错误,此时,pcap_geterr()将被用来显示错误信息。
函数3:
int pcap_setfilter(pcap_t* p,
struct bpf_program* fp)
把一个过滤器同一次抓包关联起来。pcap_setfilter被用来指定一个过滤器程序。fp是一个指向bpf_program结构体的指针,通常是pcap_compile()执行的结果。当失败时返回-1,此时,pcap_geterr()被用来显示错误信息;返回0表示成功。
首先,首先我们设置过滤器为“ip and udp”。用这个方法我们可以确保packet_handler()仅接收IPv4上的UDP数据包:这就简化了解析过程并且提高了程序的效率。
我们还创建了IP和UDP两个结构体,这些结构体被packet_handler()用来定位不同的头域。
packet_handler()展现了像tcpdump/WinDump这些复杂的嗅探器(sniffer)如何解析网络数据包。因为我们不关心MAC头,所以我们跳过它。为了简便起见,抓包前我们用pcap_datalink()检查MAC层,以确保我们处理的是以太网。该方法可以确保MAC头是14字节。
IP头的定位在MAC头定位之后。我们从IP包头中取出源IP地址和目标IP地址。
展开UDP包头有点复杂,因为IP包头不是定长的。因此,我们使用IP包头的长度域来获得它的大小。一旦我们知道了UDP头的位置,我们可以取出源端口和目的端口。
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo发表评论于2006/3/20 21:53:09 |
以下引用everester(游客)在2006-3-20 11:08:10的评论:我把// ip_len = (ih->ver_ihl & 0xf) * 4 改为ip_len=(ih->flags_fo & 0x1fff); uh = (udp_header*)((u_char*)ih + ip_len);不知道这样可否得到预期的结果,(ih->flags_fo & 0x1fff)得到的是直接就是片偏移地址.请主人看看这样是否正确.原代码中的意思是在当前的这个IP分片数据包中找到该分片数据包的数据部分。而ih->flags_fo指的意思是这个IP分片在原始IP数据包中的偏移地址,所以(ih->flags_fo & 0x1fff)得到的是该分片数据包在原始IP数据包中的偏移地址。跟原来的语句不是一个意思。
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
everester(游客)发表评论于2006/3/20 11:08:10 |
我把// ip_len = (ih->ver_ihl & 0xf) * 4
改为ip_len=(ih->flags_fo & 0x1fff);
uh = (udp_header*)((u_char*)ih + ip_len);
不知道这样可否得到预期的结果,(ih->flags_fo & 0x1fff)得到的是直接就是片偏移地址.
请主人看看这样是否正确.
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
everester(游客)发表评论于2006/3/20 10:45:17 |
首部长度占四个字节,可表示的最大数值是15个单位(一个单位为四个字节,即31位),因为IP分组的首部长度必须为4个字节的整数倍,所以这个“单位”表示四个字节。
当IP分组的首部长度不时4个字节的整数倍时,必须利用最后一个填充字段来填充,这样做的目的也就是为了实现IP协议是较为方便而制定的规则。
用(ih->ver_ihl & 0xf) 所得的结果就是上面所说的“单位数”,再乘以四就变成了整个的IP包头所占用的以字节为单位的长度。
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo发表评论于2006/3/3 23:58:44 |
以下引用feiyu_lili在2006-3-3 14:48:11的评论:
不要意思,发了张图片变空白了。
再将该按位与的结果乘以4(该字段以4个字节为基本单位),就得到ip报头有多少个字节。
还是不太明白*4的道理
相当于说ip头的第二个字段有4bit,表示报头长度,这个字段的单位是字(也就是四个字节),4bit能表示的范围是0-15,但ip报头最短都有20字节,所以该字段的取值是5-15。
如果该字段是5,则表示报头长度是5个字,即20个字节;如果该字段是6,则表示报头长度是6个字,即24个字节,以此类推。(1个字=4个字节)
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
feiyu_lili发表评论于2006/3/3 14:48:11 |
不要意思,发了张图片变空白了。
再将该按位与的结果乘以4(该字段以4个字节为基本单位),就得到ip报头有多少个字节。
还是不太明白*4的道理
|
回复:Winpcap学习:第四天(20060203)【下】 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo发表评论于2006/3/3 12:14:19 |
以下引用feiyu_lili在2006-2-27 15:04:48的评论:你代码中计算长度有以下代码:
ih = (ip_header*)(pkt_data + 14);
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (udp_header*)((u_char*)ih + ip_len);
ih = (ip_header*)(pkt_data + 14); 这个我能明白,因为你在文中已经指出MAC头是14字节
但下面的2句
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (udp_header*)((u_char*)ih + ip_len);
你虽然也有解释:“IP头的定位在MAC头定位之后。我们从IP包头中取出源IP地址和目标IP地址。
展开UDP包头有点复杂,因为IP包头不是定长的。因此,我们使用IP包头的长度域来获得它的大小。”但是我还是不明白,为什么要这么做,你能不能解释的具体一点呢?有相关资料能不能发到我邮箱呢?
我的邮箱:feiyu_lili163.com
非常感谢~iph
->ver_ihl表示的是ip数据包头中的两个关键字段版本和报头长度。这两个字段每个都是4bit的,所以用一个字节来表示这两个字段:前四位
是版本字段,后四位是报头长度字段。而报头长度字段是以4个字节(32bit)为基本单位的,取值范围是5-15。
所以如果要取得ip报头长度(单位:字节)就是:
ip_len = (ih->ver_ihl & 0xf) * 4;
解释:ih->ver_ihl &
0xf就是ih->ver_ihl与00001111按位与,这样就能取得ih->ver_ihl的后四位的值,也就是ip报头中的“报头长
度”字段,再将该按位与的结果乘以4(该字段以4个字节为基本单位),就得到ip报头有多少个字节。
|
|