ILD

packet socket 指定ARP协议的问题
作者:Yuan Jianpeng 邮箱:yuanjp@hust.edu.cn
发布时间:2018-5-9 站点:Inside Linux Development

packet socket指定接收ARP协议,当接口放入桥中时,接收不到ARP数据包。

1
2
3
4
5
6
7
8
9
10
11
struct sockaddr_ll sll;
int sock;
 
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
 
memset(&sll, 0, sizeof(sll));
sll.sll_family      = AF_PACKET;
sll.sll_ifindex     = ifindex;
sll.sll_protocol    = htons(ETH_P_ARP);
 
bind(sock, (struct sockaddr *) &sll, sizeof(sll));


解决办法是使用ETH_P_ALL,并添加内核filter。注意ETH_P_ALL也会接收TX的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct sockaddr_ll sll;
int sock;
 
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
memset(&sll, 0, sizeof(sll));
sll.sll_family      = AF_PACKET;
sll.sll_ifindex     = ifindex;
sll.sll_protocol    = htons(ETH_P_ARP);
 
bind(sock, (struct sockaddr *) &sll, sizeof(sll));
 
struct sock_filter arpfilter[] = {
    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),                 /* Skip 12 bytes */
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_P_ARP, 0, 1),     /* if eth type != ARP skip next instr. */
    BPF_STMT(BPF_RET+BPF_K, sizeof(struct arpMsg)),
    BPF_STMT(BPF_RET+BPF_K, 0),                             /* Return, either the ARP packet or nil */
};
 
struct sock_fprog fprog;
 
fprog.filter = arpfilter;
fprog.len = sizeof(arpfilter)/sizeof(struct sock_filter);
 
setsockopt(mysock, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));


可以使用filter来实现不接收tx数据,recvfrom返回的地址,也可判断是否为TX数据包:

1
2
3
4
5
6
7
8
struct sockaddr_ll addr;
struct arpMsg arp;
int addr_len = sizeof(addr);
 
int err = recvfrom(sock, &arp, sizeof(arp), MSG_TRUNC, &addr, &addr_len);
 
if (addr.sll_pkttype == PACKET_OUTGOING)
    printf("outgoing packet\n");


参考:

https://stackoverflow.com/questions/16543191/missing-arp-packets-in-sock-raw-socket


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.