我需要在程序中使用Berkeley数据包过滤器,为此我了解到必须使用PF_PACKET类型的套接字。我能够按预期通过过滤器接收数据包。填充用于发送数据包的套接字地址时,我遇到了障碍。
我按如下方式创建了套接字:
my_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
....
memset(&socket_address, 0, sizeof (socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_ifindex = if_nametoindex("eth0");
socket_address.sll_protocol = htons(ETH_P_IP);
bind(ptr_simsw->gre_fd_pkt, (struct sockaddr *)&socket_address, sizeof(socket_address);
...
if (setsockopt (my_fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0)
...
我之所以选择SOCK_DGRAM而不是SOCK_RAW,是因为我的应用程序并不需要控制L2,因为目标IP反复更改,所以我不想在程序中构造以太网头。这是我的发送例程:
struct sockaddr_ll socket_address;
memset(&socket_address, 0, sizeof (socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_ifindex = if_nametoindex("eth0");
socket_address.sll_protocol = htons(ETH_P_IP);
if ((rval = sendto(my_fd, pkt_buf, IP_TOT_LEN, 0, (struct sockaddr *)&socket_address, sizeof(socket_address))) < 0)
...
由此引起的问题是以太网报头中的目标地址仍然为0,我的猜测是因为我没有在socket_address中指定它。在不需要提供以太网目标的情况下,在PF_PACKET类型的套接字上发送数据包的正确方法是什么?我的理解是,SOCK_DGRAM是实现此目标的方法。是否有套接字选项等,内核可以通过该选项来填充MAC?