协议栈分析过程中遇到的知识点记录。
转自:http://blog.csdn.net/sprintwind/article/details/44204761,此处只用于个人收藏总结、学习
pcap的实现即基于此接口,在实际项目中因为经常因为开源软件被审计,自己使用此接口实现了二层报文的收发。
接口使用如下:
上节讲到的RAW socket虽然已经能处理IP层的数据了,但是在实际的应用中可能需要获取更加底层的报文信息。这就需要用到另一种更加强大的socket创建方式——packet socket,创建之后直接可以操作包括以太层在内的报文数据。
packet socket的创建方式如下:
- 1
其中socket_type有SOCK_RAW 和 SOCK_DGRAM两种类型,它们的区别如下:
使用SOCK_RAW参数创建的packet socket收到的数据包含以太头及以太头以上的数据;
使用SOCK_DGRAM参数创建的packet socket收到的数据不包含以太头。
protocol参数常用的有ETH_P_IP,ETH_P_ARP和ETH_P_ALL三种,指定为ETH_P_IP后可以抓取ARP报文,指定ETH_P_ARP后可以抓取ARP报文,指定ETH_P_ALL后可以抓取所有报文。需要注意的是这个参数在指定时需要将协议类型转换为网络序传入,如htons(ETH_P_ALL),否则会导致无法抓取到预期的报文。更多的以太层协议类型可以在linux/if_ether.h头文件中找到。
创建了packet socket后,默认情况下所有网口的报文都能收到,如果只想收到指定网口的报文,需要使用bind接口传入struct sockaddr_ll结构来设置。struct sockaddr_ll结构定义如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
sll_protocol是标准的以太层协议,默认为创建socket时的指定的协议类型,具体定义见linux/if_ether.h;
sll_ifindex是网卡的接口索引,传入0将匹配所有接口,接口索引可以使用if_nametoindex接口获取;
sll_hatype是ARP的类型,具体定义见linux/if_arp.h;
sll_pkttype指定报文的类型,有效的类型有PACKET_HOST, PACKET_BROADCAST, PACKET_MULTICAST, PACKET_OTHERHOST,PACKET_OUTGOING五种,分别表示发往本地主机、以太层广播报文、以太层多播报文、发往其他主机的报文和本地主机的环回报文。这些类型只在接收报文时有效;
sll_halen和sll_addr分别用来表示报文的MAC地址长度和报文的MAC地址。
如果用packet socket来发送报文,sll_family,sll_addr, sll_halen和sll_ifindex这四个参数就够了,其他参数应该都赋值为0。在调用bind接口时只有sll_protocol和sll_ifindex会被用到。