【发布时间】:2016-05-21 09:27:52
【问题描述】:
在开发小型 DHCP 客户端时,我设法通过绑定到 IFADDR_ANY 并设置 SO_BROADCAST 和 SO_BINDTODEVICE 在特定接口上发送广播,我可以看到来自 DHCP 服务器的回复。
不幸的是,除非该接口配置了地址,否则我的应用程序不会收到任何数据包。这使得编写 DHCP 客户端变得毫无意义。
问题:如何在未分配地址的接口上接收 IPv4 UDP 广播?
我知道 RAW 套接字,但我想避免使用它们。 如果发送是不可能的,我会接受除非配置了地址,否则没有 UDP 是可能的,但是由于发送工作正常而只是接收不能,我想知道我是否遗漏了什么。
这是最少的代码:
#define _DEFAULT_SOURCE
#include <sys/types.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc < 2) {
return 0;
}
struct sockaddr_in src = { .sin_family=AF_INET, .sin_addr.s_addr=INADDR_ANY, .sin_port=htons(68) };
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
const int on=1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
struct ifreq ifr;
memset(&ifr, '\0', sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), argv[1]);
ioctl(fd, SIOCGIFINDEX, &ifr);
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
bind(fd, (struct sockaddr *)&src, sizeof(src));
char buf[512];
ssize_t res = recvfrom(fd, buf, sizeof(buf), 0, NULL, 0);
printf("res=%zi\n", res);
return 0;
}
我通过“sudo strace”运行它,它永远停止在 recvmsg() 中,即使我可以在wireshark 的端口 68 上观看广播 UDP。
【问题讨论】:
-
是的,你错过了tour和阅读How to Ask。
-
为了让我们调试问题,1) 发布代码 2) 发布来自 DHCP 服务器的实际输入(DHCP 是服务器,而不是客户端) 3) 将实际输出发布到DHCP 服务器。 4)发布代码。 (1 和 4 是重复的,因为这非常关键。
-
看了这么多问题,然后我第一次问自己就错了——对不起。 :)
标签: c linux sockets udp broadcast