IOCTL 调用适用于某些架构
IOCTL call works on some architecture
我正在用 C 编写程序,它需要查找接口的 IP 和 MAC 地址。我正在使用 IOCTL 调用。直到最近我还在使用自定义数据结构来存储这些地址,一切都运行良好。
然后我开始使用像
这样的标准结构
struct in_addr
struct ether_addr
。
在我的 OS (Archlinux) 上,它仍然可以正常工作,这很好。但通常我 运行 我的程序进入虚拟化环境 (Slitaz linux) 在 VirtualBox.I 中这样做,所以我可以 运行 使用 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);
}
解决方案
感谢回答者,我将 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,内核如何知道在解释接口名称时停在 if_len?
我会在 strncpy 之前清除结构。
我正在用 C 编写程序,它需要查找接口的 IP 和 MAC 地址。我正在使用 IOCTL 调用。直到最近我还在使用自定义数据结构来存储这些地址,一切都运行良好。 然后我开始使用像
这样的标准结构struct in_addr
struct ether_addr
。
在我的 OS (Archlinux) 上,它仍然可以正常工作,这很好。但通常我 运行 我的程序进入虚拟化环境 (Slitaz linux) 在 VirtualBox.I 中这样做,所以我可以 运行 使用 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);
}
解决方案
感谢回答者,我将 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,内核如何知道在解释接口名称时停在 if_len?
我会在 strncpy 之前清除结构。