Reputation: 454
I'm writing a program in C and it needs to look up the IP & MAC address of an interface. I'm using IOCTL calls. Until recently I was still using custom data structure to store theses addresses, and everything was working perfectly. Then I moved to using standards struct like
struct in_addr
struct ether_addr
.
On my OS (Archlinux), it is still working properly,so that's good. But usually I run my program into a virtualized environment (Slitaz linux) in VirtualBox.I do this so I can run a virtualized network with GNS3. Since these modifications, impossible to get the IOCTL call working properly in Slitaz. When I call
printf("%s\n",strerror(errno));
I just get
No Such Device
If it wasn't working properly on both architecture, I would search more in-depth, but here i'm completely lost, it works fine on Arch but not on Slitaz. it WORKED in Slitaz BEFORE these change, I can still use the older version ( 2 branches in git, one for the old version and one for the current).
Thank you for your help.
Nikko
Here are the relevant part of code (I show for MAC oinyl since IP problem is the same):
/*
* 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;
}
And in the main.c, where I call this function :
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);
}
SOLUTION
Thanks to the anser I changed my get_ifreq method to :
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;
}
Upvotes: 1
Views: 340
Reputation: 12347
It seems likely that there is additional garbage in the ifreq structure that you're not clearing out here:
struct ifreq ifr;
if_len = strlen(interface);
strncpy(ifr.ifr_name,interface,if_len);
You declare the struct ifreq on the stack but don't initialize it so the bytes in that structure are potentially random garbage. You then copy exactly if_len bytes into it, but what about the bytes immediately following that. Assuming if_len is less than IFNAMSIZ, how will the kernel know to stop at if_len in interpreting the interface name?
I would clear the structure prior to the strncpy.
Upvotes: 2