主要情况
我正在使用原始套接字尝试接收OSPF数据包。虽然我已经通过Wireshark成功地抓取了数据包,但我无法通过函数recv()接收任何内容,线程只是卡住了。
相关线程函数如下:
#define IPPROTO_OSPF (89)
// myconfigs::nic_name is "ens33", I'm sure it's correct (using it)
void* threadRecvPackets(void *intf) {
Interface *interface = (Interface*) intf;
int socket_fd;
if ((socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_OSPF)) < 0) {
perror("[Thread]RecvPacket: socket_fd init");
}
/* Bind sockets to certain Network Interface */
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, myconfigs::nic_name);
if (setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) {
perror("[Thread]RecvPacket: setsockopt - bind to device");
}
/* Add to OSPF multicast */
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_interface.s_addr = htonl(interface->ip);
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.5");
if (setsockopt(socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
perror("[Thread]RecvPacket: setsockopt - multicast ip add membership");
}
/* Set Source Address - useless */
// struct sockaddr_in src_addr;
// memset(&src_addr, 0, sizeof(src_addr));
// src_addr.sin_family = AF_INET;
// src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#ifdef DEBUG
printf("[Thread]RecvPacket init\n");
#endif
#define RECV_LEN 1024
char* packet_rcv = (char*)malloc(RECV_LEN);
while (true) {
memset(packet_rcv, 0, RECV_LEN);
#ifdef DEBUG
printf("[Thread]RecvPacket: start to recv\n");
#endif
recv(socket_fd, packet_rcv, RECV_LEN, 0); // stuck here!!
// socklen_t src_addr_len = sizeof(src_addr);
// recvfrom(socket_fd, packet_rcv, RECV_LEN, 0, (struct sockaddr*)&src_addr, &src_addr_len);
in_addr_t src_ip = ntohl(*(uint32_t*)(packet_rcv + IPHDR_SRCIP));
#ifdef DEBUG
printf("[Thread]RecvPacket: recv one\n");
#endif
if (src_ip == interface->ip) {
continue; // from self, finish packet process
}
/* ... dealing with the packet recvd, treated as 5 type of OSPF packet */
}
}
结果如下(线程SendHelloPacket正在使用sendto()并且成功)
我的用法有什么问题吗?(我是socket编程新手)
其他详情
环境:ubuntu 20.04在VMWare中
使用ensp模拟配备OSPF的路由器,并将OSPF数据包发送到我的虚拟机
中的ubuntu在我的ubuntu 20.04中,Wireshark捕获的数据包如下:
NIC信息如下(“promisc”模式没有用)
1条答案
按热度按时间qjp7pelc1#
我想是因为我的无知。
原因可能在于:
socket(AF_INET, SOCK_RAW, IPPROTO_OSPF)
.未实现类似recv()
的套接字函数中的处理方法。只有IPPROTO_TCP
、IPPROTO_UDP
、IPPROTO_ICMP
等可以工作。所以我改为使用
AF_PACKET
(与PF_PACKET
相同)和htons(ETH_P_IP)
,然后无需任何其他配置,我就可以接收数据链路层上的所有帧。其余的事情将是手动过滤接收的数据包。下面是新函数:
但我也想知道是否有更合适的方式来做这件事。(过滤不需要的数据包在某处的linux内核不是这里)