【问题标题】:C reading mac address - undefined behaviorC读取mac地址 - 未定义的行为
【发布时间】:2016-06-25 01:11:22
【问题描述】:

我想读取目标的 MAC 地址。所以我使用下面的代码

TS32 get_mac_address(TU8 ** aps8Mac)
{
    TS32 fd;
    struct ifreq ifr;
    CHAR *iface = "eth0";
    TU8 *mac;

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);

    ioctl(fd, SIOCGIFHWADDR, &ifr);

    close(fd);

    mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
    *aps8Mac = mac;

    return 0;
}

int main(int argc, char **argv)
{
    TU8   *s8Mac = NULL;
    get_mac_address(&s8Mac);
    fprintf(stdout, "MAC address : %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n" , s8Mac[0], s8Mac[1], s8Mac[2], s8Mac[3], s8Mac[4], s8Mac[5]); 
    fprintf(stdout, "MAC address : %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n" , s8Mac[0], s8Mac[1], s8Mac[2], s8Mac[3], s8Mac[4], s8Mac[5]);
    return 0;
}

一旦在我得到的目标上执行:

MAC 地址:00:01:02:03:00:76
MAC地址:FE:76:9C:8C:AB:7E

为什么我不读书

MAC 地址:00:01:02:03:00:76
MAC地址:00:01:02:03:00:76

编辑 1: get_mac_address 根据作为答案给出的建议修改

TS32 get_mac_address(TU8 ** aps8Mac)
{
    TS32 fd;
    struct ifreq ifr;
    CHAR *iface = "eth0";

    TU8 *mac = malloc(sizeof(TU8) * 17);

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);

  ioctl(fd, SIOCGIFHWADDR, &ifr);

    close(fd);

    mac = (TU8 *)ifr.ifr_hwaddr.sa_data;
    *aps8Mac = mac;
    return 0;
}

【问题讨论】:

  • 你在哪里分配空间来保存 MAC 地址?
  • @DavidSchwartz 我已经修改了主题以包含修改后的功能。但是,我仍然获得相同的行为
  • 您丢弃了从malloc 获得的值,但仍然返回指向临时对象的指针。 mac = (TU8 *)ifr.ifr_hwaddr.sa_data; *aps8Mac = mac; 只是设置*aps8Mac 等于ifr.ifr_hwaddr.sa_data 的一种迂回方式。

标签: c linux sockets ethernet mac-address


【解决方案1】:

您正在返回一个指向本地堆栈变量的指针。这是非法的——一旦函数返回,你就不再被允许访问它的局部变量。正确的做法是在调用者中分配内存,让被调用者将结果复制到那里。

打印一次正确结果的原因是从 C 函数返回不会将其堆栈空间归零。这些值碰巧在堆栈上仍然完好无损,因此它们被传递给fprintf。然后fprintf 调用使用堆栈来完成它的工作,将不同的数据放在指向的位置。

【讨论】:

  • 我已经修改了问题,以便按照您的建议在调用者中分配内存,但行为仍然相同。我想我理解错了。
【解决方案2】:

编辑后,您为 mac 地址分配了 17 个字节。
(我不确定您为什么想要 17 个字节...典型的 MAC 地址只有 6 个字节长!)

但是,您没有正确填写该数据。

您尝试在线填写:

mac = (TU8 *)ifr.ifr_hwaddr.sa_data;

但所做的只是为mac 指针提供与sa_data 相同的指针,同时泄漏您之前分配的内存。

我相信您想将数据从一个结构复制到另一个结构:

// Copy 17 bytes from the sa_data to the allocated, reserved space for mac-address
// After this, ifr-->sa_data can be overwritten or destroyed; we don't care
// We have our own copy of the data in mac.
memcpy(mac, (TU8 *)ifr.ifr_hwaddr.sa_data, 17*sizeof(TU8) );

我会尝试像这样重写它:

TS32 get_mac_address(TU8 ** aps8Mac)
{
    TS32 fd;
    struct ifreq ifr;
    CHAR *iface = "eth0";
    const int MAC_SIZE = 6; // MAC addresses are 6-bytes.

    *aps8Mac = malloc(sizeof(TU8) * MAC_SIZE);

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);

    ioctl(fd, SIOCGIFHWADDR, &ifr);
    close(fd);

    // Copy the 6-byte address to the output.
    memcpy(*aps8Mac, ifr.ifr_hwaddr.sa_data, MAC_SIZE);

    return 0;
}

【讨论】:

  • 感谢您的回复,我现在明白了。在你的函数中,需要指定 MAC_SIZE 的类型,不是吗?
猜你喜欢
  • 2020-02-27
  • 2023-01-03
  • 2018-02-12
  • 2019-05-30
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多