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)