gpt4 book ai didi

c - IOCTL 调用适用于某些架构

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:16:48 32 4
gpt4 key购买 nike

我正在用 C 编写程序,它需要查找接口(interface)的 IP 和 MAC 地址。我正在使用 IOCTL 调用。直到最近我还在使用自定义数据结构来存储这些地址,一切都运行良好。然后我转向使用标准结构,例如

结构 in_addr

结构 ether_addr

在我的操作系统 (Archlinux) 上,它仍然可以正常工作,这很好。但通常我会在 VirtualBox 中将我的程序运行到虚拟化环境 (Slitaz linux) 中。我这样做是为了可以使用 GNS3 运行虚拟化网络。由于这些修改,不可能让 IOCTL 调用在 Slitaz 中正常工作。当我打电话时

printf("%s\n",strerror(errno));

我刚刚明白

No Such Device

如果它在两种架构上都不能正常工作,我会进行更深入的搜索,但在这里我完全迷路了,它在 Arch 上工作正常但在 Slitaz 上却不行。在这些更改之前它在 Slitaz 中工作,我仍然可以使用旧版本(git 中的 2 个分支,一个用于旧版本,一个用于当前版本)。

感谢您的帮助。

日光


以下是代码的相关部分(我显示的是 MAC oinyl,因为 IP 问题是相同的):

/*
* Return a ifreq structure for this interface
* */
struct ifreq
get_ifreq ( const char * interface )
{

struct ifreq ifr;
size_t if_len;


if_len = strlen(interface);
if (if_len >= sizeof(ifr.ifr_name)){
fprintf(stderr,"Interface name too long to open descriptor.\nAbort.");
exit(EXIT_FAILURE);
}

strncpy(ifr.ifr_name,interface,if_len);

return ifr;
}

int
get_mac_address(const char * interface, struct ether_addr * ether) {
int fd ;
struct ifreq ifr = get_ifreq(interface);
if((fd = get_socketudp()) == -1) {
fprintf(stderr,"Unable to get mac address.\n");
return -1;
};

if(ioctl(fd,SIOCGIFHWADDR,&ifr) == -1) {
fprintf(stderr,"%s\n",strerror(fd));
fprintf(stderr,"Error while operating IOCTL (MAC resolving).\n");
close(fd);
return -1;
}
close(fd);
memcpy(ether,&ifr.ifr_hwaddr.sa_data,ETH_ALEN);
return 0;

}

在 main.c 中,我调用这个函数的地方:

char * interface = NULL;

/*----------------------------------------------------------------------
* Our OWN mac address & ip address
*-----------------------------------------------------------------------*/
struct ether_addr mac;
struct in_addr ip;

int
main ( int argc, char *argv[] )
{
char * operation = NULL;
char * hostA = NULL;
char * hostB = NULL;
int c = 0;

if (argc < 2) {
usage();
exit(EXIT_FAILURE);
}

while((c = getopt(argc,argv,"m:i:a:b:f:l:")) != -1){
switch(c){
case 'm':
operation = optarg;
if (strncmp(operation,"mitm",4) != 0 &&
strncmp(operation,"flood",5) != 0) {
fprintf(stderr,"Operation %s is unknown.Abort\n",operation);
abort();
}
break;
case 'i':
interface = optarg;
break;

case '?':
fprintf(stderr,"Option %c requires an argument",optopt);
abort();
}
}


/* Check options consistency */
if(operation == NULL) {
fprintf(stderr,"No Operations given. Abort.\n");
exit(EXIT_FAILURE);
} else if (interface == NULL) {
fprintf(stderr,"No interface given. Abort.\n");
exit(EXIT_FAILURE);
}



/* Store our own mac address */
if (get_mac_address(interface,mac) == -1) {
fprintf(stderr,"Abort.\n");
exit(EXIT_FAILURE);
}

解决方案

感谢 anser,我将 get_ifreq 方法更改为:

    struct ifreq
get_ifreq ( const char * interface )
{

struct ifreq ifr;
size_t if_len;

memset(ifr.ifr_name,0x00,IFNAMSIZ);
if_len = strlen(interface);
if (if_len >= IFNAMSIZ){
fprintf(stderr,"Interface name too long to open descriptor.\nAbort.");
exit(EXIT_FAILURE);
}

strncpy(ifr.ifr_name,interface,if_len);

return ifr;
}

最佳答案

似乎 ifreq 结构中还有您未在此处清除的额外垃圾:

struct ifreq ifr;
if_len = strlen(interface);
strncpy(ifr.ifr_name,interface,if_len);

您在堆栈上声明了 ifreq 结构但未对其进行初始化,因此该结构中的字节可能是随机垃圾。然后您将 if_len 字节精确地复制到其中,但是紧随其后的字节呢?假设 if_len 小于 IFNAMSIZ,内核如何知道在解释接口(interface)名称时在 if_len 处停止?

我会在 strncpy 之前清除结构。

关于c - IOCTL 调用适用于某些架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29141621/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com