【问题标题】:Getting MAC address for a given IP from ARP entry (Linux kernel)从 ARP 条目(Linux 内核)获取给定 IP 的 MAC 地址
【发布时间】:2013-03-04 18:47:10
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您好,请问您的目标实现了吗?我正在编写内核模块,它以一种特殊的方式处理 TCP 数据包,然后假设将它们发送到目的地。但似乎我无法获得下一跳的 MAC 地址。我已经有了它的 IP 地址,但是任何涉及到 mac 地址的 rtable 结构的请求都会导致内核崩溃......
  • @AlexKey:你试过我在“编辑#2”中描述的吗?

标签: c linux linux-device-driver


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。

    我需要获取与特定 IP 关联的邻居的 MAC 地址。此外,在我的情况下,可能 IPMAC 映射没有出现在 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;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2012-04-10
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多