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