c - 接收 UDP 广播,没有分配地址与 Linux/C/IPv4 接口(interface)

标签 c linux sockets udp broadcast

在开发小型 DHCP 客户端时,我设法通过绑定(bind)到 IFADDR_ANY 并设置 SO_BROADCAST 和 SO_BINDTODEVICE 在特定接口(interface)上发送广播,我可以看到来自 DHCP 服务器的回复。

不幸的是,除非该接口(interface)配置了地址,否则我的应用程序不会收到任何数据包。这使得编写 DHCP 客户端变得毫无意义。

问题:如何在未分配地址的接口(interface)上接收 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。

最佳答案

我解决了。 “反向路径过滤”被激活,导致所有采用不同返回路径(或没有路由)的 IPv4 数据包被丢弃。 如果没有为该接口(interface)配置地址,每个数据包都会被丢弃。

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

成功了。

关于c - 接收 UDP 广播,没有分配地址与 Linux/C/IPv4 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35325189/

相关文章:

c - 写入文件时排除终止符

c - scanf 接受多个字符输入

c - C 中预处理器语句的缩进

linux - 使用 kickstart 文件向 Red Hat ISO 附加 rpm

java - 如何使用匹配的 DER 私钥解密 PEM 公钥加密字节数组?

控制管道 StdIn 和 StdOut

linux - 除了 close() 之外,有没有办法通知进程的死亡?

Linux 在特定部分中搜索和替换

Linux 套接字/连接

python - 无法连接不同计算机上的 Python 套接字