在接收以太网帧的示例代码中添加MAC地址过滤功能,可以通过在接收到每个以太网帧后,检查其源或目的MAC地址是否匹配预定义的地址。如果匹配,则处理该帧;如果不匹配,则忽略。
以下是修改后的代码,增加了对源MAC地址的过滤:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
bool isMacAddressFiltered(const struct ethhdr *ethHeader, const char *filterMac) {
// 将目标MAC地址字符串转换为二进制格式
struct ether_addr *filterAddr = ether_aton(filterMac);
return (memcmp(ethHeader->h_source, filterAddr, ETH_ALEN) == 0); // 比较源MAC地址
}
void receiveEthernetFrame() {
int sockfd;
unsigned char buffer[1514]; // 1514 字节为最大 Ethernet 帧长度
// 创建原始套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("Socket creation failed");
return;
}
const char* filterMac = "00:11:22:33:44:55"; // 设置要过滤的 MAC 地址
while (true) {
ssize_t bytesReceived = recv(sockfd, buffer, sizeof(buffer), 0);
if (bytesReceived < 0) {
perror("Receive error");
break;
}
struct ethhdr *ethHeader = (struct ethhdr *)buffer;
// 检查源 MAC 地址是否符合过滤条件
if (!isMacAddressFiltered(ethHeader, filterMac)) {
continue; // 不符合条件则跳过此帧
}
// 打印源和目标 MAC 地址
std::cout << "Source MAC: " << ether_ntoa((struct ether_addr*)ethHeader->h_source) << std::endl;
std::cout << "Destination MAC: " << ether_ntoa((struct ether_addr*)ethHeader->h_dest) << std::endl;
// 打印有效载荷内容(假设这里只处理前46个字节)
std::cout << "Payload: ";
for (int i = 0; i < bytesReceived - ETH_HLEN; ++i) {
std::cout << buffer[ETH_HLEN + i]; // 有效载荷从ETH_HLEN开始
}
std::cout << std::endl;
}
close(sockfd); //关闭套接字
}
int main() {
receiveEthernetFrame();
return 0;
}
注意事项:
- MAC地址格式:确保
filterMac
使用正确的格式,如"00:11:22:33:44:55"
。 - 性能问题:进行筛选时,应注意处理速度,以免错过其他重要的数据包。
- 多重过滤:如果需要基于多个不同的MAC地址进行过滤,可以将这些地址存储在一个数组中,并在接收数据时遍历这个数组进行比较。
这个示例代码将在接收到的数据包中只处理与给定源MAC地址相匹配的帧,其他数据包会被忽略。
内容由零声教学AI助手提供,问题来源于学员提问