1

我正在编写一个内核模块,并且需要对于给定的 IP 来验证内核的 ARP 缓存中是否有针对该 IP 的 ARP 条目。如果它存在,我需要从这个 ARP 条目中获取 MAC 地址。

我在这一点上试图理解这个arp_find功能,usr/src/linux-version/net/ipv4/arp.c但我不太明白......有人可以发布一个例子来说明我如何完成这项任务或指导我做一些可以帮助我的事情吗?我将不胜感激!

编辑:我的 IP 地址存储为struct in_addr

编辑#2:我找到了答案——对于那些有这个问题的人,请neigh_lookup检查net/core/neighbour.c. 该pkey参数只是指向您的 IPv4 地址 ( struct in_addr) 的指针。

4

2 回答 2

0

我认为在Linux内核中,ARP缓存只存储邻居的mac地址。您可以使用 arp_ioctl() 或遵循 arp_ioctl() 方法来实现您的任务。arp_ioctl() 做了两个主要的事情: (1) 找到 net_device;(2)arp查找;

于 2013-03-05T02:23:10.370 回答
0

我有同样的问题。

我需要获取与特定 IP 关联的邻居的 MAC 地址。此外,在我的情况下,可能 IP<->MAC 映射没有出现在 ARP 缓存中。所以在这种情况下,我需要先发送 ARP 请求。

这是我目前得到的一个肮脏的解决方案:

struct mac_addr {
    uint8_t addr[ETH_ALEN];
};

static int resolve_neighbour(__be32 const src_ip, __be32 const dst_ip, struct mac_addr* const mac) {
    int rc = 0;
    struct neighbour *neigh;
    struct rtable* const rt = ip_route_output(&init_net, dst_ip, src_ip, 0, 0);

    if (IS_ERR(rt)) {
        LOG(KERN_ERR, "Failed to find ip route"); // TODO: add dst and src ip
        return PTR_ERR(rt);
    }

    rcu_read_lock();
    neigh = dst_neigh_lookup(&rt->dst, &dst_ip);
    if (neigh) {
        if (neigh->nud_state & NUD_VALID) {
            neigh_ha_snapshot(mac->addr, neigh, rt->dst.dev);
        } else {
            PDEBUG("neigh is not valid. Sending ARP");
            if ((rc = neigh_resolve_output(neigh, NULL))) {
                LOG(KERN_ERR, "Failed to resolve neighbour");
            } else {
                rc = -EAGAIN;
            }
        }
        neigh_release(neigh);
    } else {
        LOG(KERN_ERR, "Failed to get neighbour"); // TODO: add dst ip
        rc = -ENONET;
    }
    rcu_read_unlock();
    return rc;
}

static int foobar(void) {
    int rc = 0;
    __be32 const dst_ip = 0x0a01000a; // FIXME: TODO: get it from register or from tre user
    __be32 const src_ip = htonl(0); // FIXME: TODO: get it from register or from the user
    struct mac_addr mac;
    size_t i;
    enum {RESOLVE_TRIES = 3, RESOLVE_TIMEOUT_MS = 100};

    for (i = 0; i < RESOLVE_TRIES; ++i) {
        if ((rc = resolve_neighbour(src_ip, dst_ip, &mac)) == -EAGAIN) {
            msleep(RESOLVE_TIMEOUT_MS);
        } else {
            break;
        }
    }

    if (rc) {
        LOG(KERN_ERR, "Failed to get neighbour MAC address");
        return rc;
    }

    PDEBUG("DST MAC %02X:%02X:%02X:%02X:%02X:%02X",
            mac.addr[0], mac.addr[1], mac.addr[2],
            mac.addr[3], mac.addr[4], mac.addr[5]);

    return rc;
}

于 2021-09-10T15:06:27.643 回答