ioctl interface settings
Hey *myself* *chuckles*,
Well, as I promised, I bring you another post of nothing interesting, and this time, even I ain’t interested. But I thought that this experiment was necessary, to make sure that we are all comfortable with using ioctl for the interface.
But before that, another thing. You guys would be inspired to write codes like me (kudos), well don’t. Yeah, indent, and name ur vars properly, thats me, but ALWAYS error check, especially when calling library functions which might have a damn good chance of returning errors. I leave the error writing to your part, mainly cause I want to make my code concise, and filled with what I want. Never ever, however in reality, go without error checking!
A little personal (please skip):
Well, today, went to watch this movie, naqaab, and it sucked on ice, atleast, thats what I felt. Other than that, when I came back from movie, I was chatted 2 by 6 people simultaneously, whao is me! And lastly, some1 called anuda met me on orkut today, and I “guess” that she knows quite alot… for some1 who knows asm, I think C advanced is a pre-requisite. Plus, she’s a student, so not a network professional like susam or sudeep. Yeah, there’s vipul, he’s cool and all, but we engage in different styles of security. Lets see what frequency is anuda @.
Oh, and another thing, I am searching for some1 to help me write articles for my blog… just for the fun of it. Right now, I know, I am the only 1 who reads and writes it, but I hope that in future, when I get time to SEO, the blog will really come up, as it deals with a very rare subject.
Back to the code:
Well, this code is just a whole lot of ioctl’s all put together into one code, to get complete information about the interface. Its quite documented, and the principles and stuff are already explained in the previous entries.
//self_interfaceall.c - Get complete information about interfaces
//Yup, made by me, Gaurav aka Silver
#include "libnethead.h"
#define MAXADDR 10
//Just an array for max ip addresses
//For some reason, cannot make this allocate dynamically.... If we do, then we don't get any interfaces reported?
//Asked devsheds, lets see what happens.
int main(){
int fd;
int flags,i;
struct ifreq *ifr,*ifend;
struct ifreq ifmax[MAXADDR];
struct ifconf iflist;
struct sockaddr_in sin;
char buffer[25],devname[IFNAMSIZ];
struct ether_addr ea;
memset(&buffer,0,25);
fd=socket(AF_INET,SOCK_DGRAM,0);
//dummy socket, but created on IPv4 (note). Sock type isnt as important as the protocol family
//For this call, which gets the number of interfaces, ifc_req/ifc_buf MUST be 0
if(ioctl(fd,SIOCGIFCONF,(char*)&iflist)<0){ printf("ioctl failed for SIOCGIFCONF"); exit(0); }
//We know that my machine doesnt have sa_len , so skip that char buffer stuff
printf("Total number of interfaces: %d\n\n",(iflist.ifc_len)/sizeof(struct ifreq));
iflist.ifc_req=ifmax; //Put the interface list in a large enough location.
if(ioctl(fd,SIOCGIFCONF,(char*)&iflist)<0){ printf("ioctl failed for SIOCGIFCONF"); exit(0); }
ifr=iflist.ifc_req; //These lines for traversing the array
ifend=(struct ifreq *)(iflist.ifc_buf+iflist.ifc_len);
for(;ifrifr_name);
strncpy(devname,ifr->ifr_name,sizeof(ifr->ifr_name)); //Store it just for now
//Get the flags
printf("The device is: "); //Get the flags
if(ioctl(fd,SIOCGIFFLAGS,(char*)ifr)ifr_flags;
if(flags & IFF_UP){ printf("Up "); }
if(flags & IFF_LOOPBACK){ printf("Loopback "); }
if(flags & IFF_BROADCAST){ printf("Broadcast_supported "); }
if(flags & IFF_MULTICAST){ printf("Multicast_supported"); }
printf("\n"); if(flags & IFF_LOOPBACK) continue; //We cant get the hwaddr and stuff for loopback
//Get the ip address-
if(ioctl(fd,SIOCGIFADDR,(char*)ifr)ifr_addr));
inet_ntop(AF_INET,&(sin.sin_addr.s_addr),buffer,INET_ADDRSTRLEN);
printf("IP Address: %s\n",buffer);
if(flags & IFF_BROADCAST){ //find the broadcast address, if it exists
if(ioctl(fd,SIOCGIFBRDADDR,(char*)ifr)ifr_broadaddr));
inet_ntop(AF_INET,&(sin.sin_addr.s_addr),buffer,INET_ADDRSTRLEN);
printf("Broadcast Address: %s\n",buffer);
}
//Now get the hardware address
if(ioctl(fd,SIOCGIFHWADDR,(char*)ifr)ifr_hwaddr.sa_data),6);
printf("Hardware Address: ");
for(i=0;i<6;i++){ //This is the normal printing, I told in the last blog entry.
sprintf(buffer,"%x",ea.ether_addr_octet[i]);
if(strlen(buffer)<2){ printf("0"); }
printf("%s",buffer);
if(i!=5) printf(":");
}
printf("\n");
}
return 0;
}
Yeah, just compile that code, and run it… It should return the interfaces present, as well as their states… Feel free to add extra stuff if needed or applicable, such masters and slaves (for load balancers), and etc. That one code should be enough for a somewhat thorough understanding of using ioctl’s with the network interface devices.
Code 2:
Now we try and do something different. All this while, we just queried and found out about network devices, but now, we are going to set them…. In general, the steps for SIOC….. are-
1. To get devices, set ifr.ifr_name string to the device name, and all the other fields can contain any value, including blank. Then, call ioctl, with the appropriate request and (char*) pointer to the ifreq object (except in case of SIOCGIFCONF). In that call, ifreq object gets modified and the appropriate member of the union will have the corresponding data that is needed. All these requests begin with SIOCGIF___ , S for sumthing, IO probably interface, C, dunno…. G is probably for GET, and IF for interface.
2. To set device characteristics, set ifr.ifr_name string to the device name, but this time, set the appropriate union member in ifreq object to the new value which you want to set to…. Then call the ioctl command with the request and argument… if successful, ioctl wouldnt return -1, and that way, you know that the parameter has been changed successfully. All these requests begin with SIOCSIF___, that latter S probably standing for “set”
Note:
One more thing I found out, from mailing lists of tcpdump. In linux, there are something called flags and gflags associated with the device, which specify its operation. While setting device flags with ioctl, only the “gflags” field is set. Whereas, setting the flags using setsockopt() (yeah, you can set characteristics of the socket/interface with setsockopt as well, right), only the “flags” field is set, but not the “gflags”.
Now, there is one more difference. When we set a flag with socksetopt() , with socket SOL_PACKET, and request type as PACKET_ADD_MEMBERSHIP (dont worry, all this coming soon), and the binding to put in promiscious mode, PACKET_MR_PROMISC, we can put the device in promiscious mode as well. But in this case, the kernel associates this with the socket, and hence keeps track of which process put the device in promiscious mode. So, when the socket closes, the device is put back to the normal state (as stored in the gflags field), if there is not another socket thats using it.
What i mean is that, consider A process starts, puts the device in promiscious mode (using setsockopt). Now, B starts, and using setsockopt, decides to put the socket in promiscious mode as well (which it already is in). Now, A stops… In this case, the kernel keeps track of the request to set device in promiscious mode, and hence, since B is using that mode, it doesnt shut it off… However, if A put the device using flags IFF_PROMISC and ioctl, to first put, and then remove the promiscious mode, then even if B uses that mode, the mode will be shut off when A shuts off.
Hence, it is advisable to normally use setsockopt for promiscious mode setting, or flag setting. However, ioctl’s sometimes offer more flexibility.
The code (finally):
Again, I believe well commented, and explains the general method for doing these sortof things.
//self_interfacechange.c - Attempts to change characteristics of the interface ![]()
//Yup, guessed it right, its made by Silver, aka Gaurav ![]()
#include "libnethead.h"
#define device "eth0"
#define newip "172.16.38.53"
//Earlier IP address was .52
int main(){
int fd;
char flagset=0;
struct ifreq ifr;
struct sockaddr_in sin;
struct ether_addr ea={0x00,0x16,0x36,0x7b,0xa6,0x0a}; //Last change from 0b to 0a
strcpy(ifr.ifr_name,device); //The thing that gonna be the info source.
//First, lets change the mac address .
fd=socket(PF_INET,SOCK_DGRAM,0);
memcpy(&(ifr.ifr_hwaddr.sa_data),&ea,6); //Load the hard ware address.
ifr.ifr_hwaddr.sa_family=ARPHRD_ETHER; //Forgot this earlier.
if(ioctl(fd,SIOCSIFHWADDR,(char*)&ifr)<0){ printf("Error. Unable to change\n"); exit(0); }
printf("Changed ethernet address\n");
//Now change the IP address.
memset(&sin,0,sizeof(struct sockaddr_in));
sin.sin_family=AF_INET; if(inet_pton(AF_INET,newip,&sin.sin_addr)<0){ printf("error\n"); exit(0); }
//port should be zero
ifr.ifr_addr=*(struct sockaddr *)&sin;
if(ioctl(fd,SIOCSIFADDR,(char*)&ifr)<0){ printf("Error. Unable to change\n"); exit(0); }
printf("Changed ip address\n");
//Put off the device.
if(ioctl(fd,SIOCGIFFLAGS,(char*)&ifr)<0){ printf("Error. Unable to get flags\n"); exit(0); }
ifr.ifr_flags=ifr.ifr_flags&(~IFF_UP); //Disables device
//ifr.ifr_flags=ifr.ifr_flags | IFF_UP; //Enable device (heh, I knew I had to include this
)
if(ioctl(fd,SIOCSIFFLAGS,(char*)&ifr)<0){ printf("Error. Unable to set flags\n"); exit(0); }
printf("Flags set\n");
return 0;
}
As you can well see, there are 3 objectives of this code: 1. To change the Hardware address, 2. To change the IP address, 3. To put off/on the device.
You may change the code as you wish, all 3 parameters. Just run it, and if you’re lucky (or smart), the code will give 3 success messages! Yup, you are set. To test whether the script really was successful, just run the first code, self_interfaceall . W00T, your all set!
Post-face:
Well, what else would you it, ya? Well, the code I wrote was probably comprehensive enough for explaining all the concepts that were developed till now… From now on, we won’t lay any special importance to getting or setting interface name/characteristics. Just note, that to change the name of the device, simply fill in ifr.ifr_name with the new name, and ifr.ifr_ifindex with the previous index… see, this parts a bit different. And thats about the end of our special discussion of ioctl’s for getting interface details.
Whats next:
Well, I said that I’d be forming the ethernet packet… However, I’m in confusion, “maybe” I might post about ethernet packets, or perhaps, I might post a bit about broadcasting and multicasting concepts in general and specific.
If you’re not me, and your reading this blog, well, you’d be 1 of the rare ones
. This deals with quite a rare topic, so I hope that this blog comes up in search engines
.
About this entry
You’re currently reading “ioctl interface settings,” an entry on Crack in the River
- Published:
- July 16, 2007 / 1:00 pm
- Category:
- Libnet De-assembled
- Tags:
No comments yet
Jump to comment form | comments rss [?] | trackback uri [?]