Linux下的Packet Socket的使用

Linux下的Packet Socket的使用

Hanse
2009-4-3

Linux支持PF_PACKET类型的套接字,用于实现用户层的网络协议。通过该SOCK_RAW类型的Packet socket,应用程序可以直接接收带完整二层数据帧,处理完毕后再使用该socket发出二层数据帧。因此可以实现更底层的网络协议。也可以通过该类型的Socket实现网络抓包,当然,如果要抓取不是自己的网络报文,还需要把网卡设置为混杂模式。

1、创建Packet Socket

       #include
       #include
       #include /* the L2 protocols */

       packet_socket = socket(PF_PACKET, int socket_type, int protocol);

其中socket_type可以是SOCK_DGRAM,SOCK_RAW。设置为SOCK_RAW则接收到的报文中包含二层协议头,否则只有二层数据帧内容。

 例如:
 int skfd;

        skfd = socket(PF_PACKET, SOCK_RAW, htons(protocol));

2、绑定到网络接口
这一步是可选的。如果不绑定,则所有接口上的二层数据帧都会收到。
 struct sockaddr_ll ll;
 struct ifreq ifr;

 strncpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
 memset(l2, 0, sizeof(*l2));
 strncpy(l2->ifname, ifname, sizeof(l2->ifname));

 memset(&ll, 0, sizeof(ll));
 ll.sll_family = PF_PACKET;
 ll.sll_ifindex = ifr.ifr_ifindex;
 ll.sll_protocol = htons(protocol);
 if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  perror("bind[PF_PACKET]");
  close(l2->fd);
  free(l2);
  return NULL;
 }

protocol是需要监听的协议类型,如果为ETH_P_ALL,则接收所有数据帧。

注意:
桥中接收不到转发的非自己的报文

ssize_t recvfrom(int s, void *buf, size_t len, int flags,
                        struct sockaddr *from, socklen_t *fromlen);
如果传入fromlen为0则不会填充from参数。


参考文档:

1、Linux Man: packet(7)

你可能感兴趣的:(Linux下的Packet Socket的使用)