现在的位置: 首页 > 综合 > 正文

Linux下的Packet Socket的使用

2013年02月01日 ⁄ 综合 ⁄ 共 1233字 ⁄ 字号 评论关闭

Linux下的Packet Socket的使用

Hanse <hansel@163.com>
2009-4-3

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

1、创建Packet Socket

<pre>

       #include <sys/socket.h>
       #include <netpacket/packet.h>
       #include <net/ethernet.h> /* the L2 protocols */

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

</pre>

其中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)

抱歉!评论已关闭.