Linux下的packet socket使用总结

来源:互联网 发布:梦幻手游宝宝评分算法 编辑:程序博客网 时间:2024/06/07 23:28

协议栈分析过程中遇到的知识点记录。

转自:http://blog.csdn.net/sprintwind/article/details/44204761,此处只用于个人收藏总结、学习


pcap的实现即基于此接口,在实际项目中因为经常因为开源软件被审计,自己使用此接口实现了二层报文的收发。

接口使用如下:

上节讲到的RAW socket虽然已经能处理IP层的数据了,但是在实际的应用中可能需要获取更加底层的报文信息。这就需要用到另一种更加强大的socket创建方式——packet socket,创建之后直接可以操作包括以太层在内的报文数据。

packet socket的创建方式如下:

socket(AF_PACKET, int socket_type, int protocol);
  • 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结构定义如下:

struct sockaddr_ll {               unsigned short sll_family;   /* Always AF_PACKET */               unsigned short sll_protocol; /* Physical layer protocol */               int            sll_ifindex;  /* Interface number */               unsigned short sll_hatype;   /* Header type */               unsigned char  sll_pkttype;  /* Packet type */               unsigned char  sll_halen;    /* Length of address */               unsigned char  sll_addr[8];  /* Physical layer address */           };
  • 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会被用到。


原创粉丝点击