PDA

View Full Version : ioctl()???


caltiger
09-12-2006, 01:43 PM
hi,
i have been trying to retrieve the interface name of the machine i am on aloing with the ip address. i have gotten alot of sample codes online. but when i try to use those functions in another program written by me, the code does not return the correct response..

soo.. does anyone know how to use the ioctl() function to get the interface address?...
thanx.

RobSeace
09-12-2006, 06:45 PM
Well, which ioctl() are you trying to use, exactly? SIOCGIFCONF to obtain the full
list of interfaces? Or, just SIOCGIFADDR to obtain the IP for a single given interface?
The latter is fairly simple to use, while the former is much more complicated and
obscure... In fact, your system may possibly offer some other method of obtaining
the list of local interfaces which may be easier to use, such as if_nameindex() or
getifaddrs()... See this old thread (http://www.developerweb.net/forum/showthread.php?t=3322) for some example code using both if_nameindex() and
ioctl(SIOCGIFADDR)... (Note: some of the code is still mangled from the conversion
from the old forum, so you'll notice scattered HTML entities like "&", "<" and
such... But, some has been fixed... Specifically, this post's code (http://www.developerweb.net/forum/showpost.php?p=14025) should be ok...)

If you're still having problems, how about actually posting the code you're using
which isn't working correctly? And, preferably a description of exactly how it's
failing...

caltiger
09-13-2006, 04:04 AM
hi,
i was thinking of using SIOCGIFCONF to return the list of interfaces... at the same time, i was also trying to return the IP addresses at tht interface... so.. i know tht usinh SIOCGIFADDR is simple. i tried tht. it worked.. but S**IFCONF is not possible.
Also, i would like to know something else..
In my linux system, there are several users logged in. when i give "who" i can retireve the list of who all r logged in. i would like to know if there was some way to return the list of these users logged in along with their IPs as well...


thanx...

RobSeace
09-13-2006, 07:15 PM
but S**IFCONF is not possible.

Well, I wouldn't go that far... It's a royal pain in the ass to use, but it's not impossible
to use... ;-) Like I said in the thread I linked to: if you want an example of how to use
SIOCGIFCONF, you should grab the libpcap (http://www.tcpdump.org/) source and read that...
(Just grep for SIOCGIFCONF, and you'll find it...)

However, since you mention you're on Linux, then you should have if_nameindex()
available, and that's FAR easier to use... I'd definitely recommend using that instead
of trying to mess with SIOCGIFCONF, unless you have some other reason to need
to use it... (And, again, see my above linked post from the above linked thread for
some example code using both if_nameindex() and SIOCGIFADDR...)

As for your other question about "who"/"w" info, you can get that from utmp/wtmp...
See <utmp.h>, "man utmp", and "man getutent"...

caltiger
09-14-2006, 04:01 AM
hi,
i was wondering if there was any way to return the ip alaises using C programs???
i`ve created some aliases. now i`ve decided to try and retrieve them using programming.. any particualr command?

thanx.

mlampkin
09-14-2006, 10:26 AM
Hmmm...

Did you try using getifaddrs() ? Its on Linux, BSD and ( thanks to the BSD relation ) Mac OS...

If you iterate thru the returned list... cast the ifa_addr field(s) to a sockaddr... check if the address family is AF_INET... then cast those to a sockaddr_in and retrieve the address(es) you find...

You can also use it for retrieving your interface mac address(es)...

The primary downside is that its one of those funcs that uses a static / shared memory area... so running in multi-threaded / similar code you need to protect accesses...


Michael

mlampkin
09-16-2006, 01:34 AM
Since I'm bored... but don't like doing other folks coding... here is an example of retrieving the MAC address(es) using Python w/ C linkage and getifaddrs()...


from ctypes import *



class ifa_ifu_u( Union ):

_fields_ = [ ( "ifu_broadaddr", c_void_p ),
( "ifu_dstaddr", c_void_p ) ]


class ifaddrs( Structure ):

_fields_ = [ ( "ifa_next", c_void_p ),
( "ifa_name", c_char_p ),
( "ifa_flags", c_uint ),
( "ifa_addr", c_void_p ),
( "ifa_netmask", c_void_p ),
( "ifa_ifu", ifa_ifu_u ),
( "ifa_data", c_void_p ) ]



class AddrInfo( object ):
"""
"""


def __init__( self ):

import sys

if sys.platform.startswith( "darwin" ) or sys.platform.startswith( "freebsd" ):
self.getMacAddrs = self._getMacAddrs_BSD
elif sys.platform.startswith( "linux" ):
self.getMacAddrs = self._getMacAddrs_Linux
else:
pass


def _getMacAddrs_BSD( self ):

class sockaddr ( Structure ):
_fields_ = [ ( "sa_len", c_uint8 ),
( "sa_family", c_uint8 ),
( "sa_data", ( c_uint8 * 14 ) ) ]

class sockaddr_dl( Structure ):
_fields_ = [ ( "sdl_len", c_uint8 ),
( "sdl_family", c_uint8 ),
( "sdl_index", c_uint16 ),
( "sdl_type", c_uint8 ),
( "sdl_nlen", c_uint8 ),
( "sdl_alen", c_uint8 ),
( "sdl_slen", c_uint8 ),
( "sdl_data", ( c_uint8 * 46 ) ) ]

libc = CDLL("libc.so.6")

ptr = c_void_p( None )

result = libc.getifaddrs( pointer( ptr ) )

if result:
return None

ifa = ifaddrs.from_address( ptr.value )

result = []

while ( 1 ):

name = ""

for ch in ifa.ifa_name:
if ord( ch ):
name += ch
else:
break

if name.startswith( "em" ):
if sockaddr.from_address( ifa.ifa_addr ).sa_family == 18: # AF_LINK
addr = sockaddr_dl.from_address( ifa.ifa_addr )
result.append( ( name, addr.sdl_index, addr.sdl_data[ addr.sdl_nlen:addr.sdl_nlen + 6 ] ) )

if ifa.ifa_next:
ifa = ifaddrs.from_address( ifa.ifa_next )
else:
break

libc.freeifaddrs( ptr )

return result




def _getMacAddrs_Linux( self ):

class sockaddr ( Structure ):
_fields_ = [ ( "sa_family", c_uint16 ),
( "sa_data", ( c_uint8 * 14 ) ) ]

class sockaddr_ll( Structure ):
_fields_ = [ ( "sll_family", c_uint16 ),
( "sll_protocol", c_uint16 ),
( "sll_ifindex", c_uint32 ),
( "sll_hatype", c_uint16 ),
( "sll_pktype", c_uint8 ),
( "sll_halen", c_uint8 ),
( "sll_addr", ( c_uint8 * 8 ) ) ]

libc = CDLL("libc.so.6")

ptr = c_void_p( None )

result = libc.getifaddrs( pointer( ptr ) )

if result:
return None

ifa = ifaddrs.from_address( ptr.value )

result = []

while ( 1 ):

name = ""

for ch in ifa.ifa_name:
if ord( ch ):
name += ch
else:
break

if name.startswith( "eth" ):
if sockaddr.from_address( ifa.ifa_addr ).sa_family == 17: # AF_PACKET
addr = sockaddr_ll.from_address( ifa.ifa_addr )
result.append( ( name, addr.sll_ifindex, addr.sll_addr[ 0:addr.sll_halen ] ) )

if ifa.ifa_next:
ifa = ifaddrs.from_address( ifa.ifa_next )
else:
break

libc.freeifaddrs( ptr )

return result


a=AddrInfo()
print a.getMacAddrs()


It should work... seems to work on Linux... haven't tested on BSD or Darwin... and doesn't do Windows ( need a netbios or similar call there )...

Michael

caltiger
09-16-2006, 06:50 AM
hmmm.. thanks guys.. but i was able to use if_namindex.. just one rmoe skmall thing.. if_nameindex does not return the ip aliases.. just the actual interface and the Ip address of that interface.
Is there any way to modify if_nameindex to display the interface names of the aliased Ip addresses also?

thanks

mlampkin
09-16-2006, 08:48 AM
Huh?

What?

You used if_nameindex( * ) to retrieve network addresses?

It normally just returns basic names and indexes only... not even aliases... and never heard of the associated ip addrs ( there was actually a discussion of that during the specification of that function about WHY it could be a bad idea )...

Now I know if_nameindex allows additional vals in the return structure but... at the base level its the index number and name... so what platform are you using?


#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <errno.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>


int main( int argc, char ** argv )
{
struct ifaddrs * ifap = ( void * ) 0;
struct ifaddrs * ifnr = ( void * ) 0;

struct sockaddr * addr = ( void * ) 0;
struct sockaddr_in * addr_in = ( void * ) 0;

int res = getifaddrs( & ifap );

int a;
int b;
int c;
int d;

if ( 0 != res )
{
printf( "%s\n", strerror( errno ) );

exit( -1 );
}

ifnr = ifap;

while ( ( void * ) 0 != ifnr )
{
addr = ifnr->ifa_addr;

if ( AF_INET == addr->sa_family )
{
addr_in = ( struct sockaddr_in * ) ifnr->ifa_addr;

a = ( htonl( addr_in->sin_addr.s_addr ) >> 0x18 ) & 0xFF;
b = ( htonl( addr_in->sin_addr.s_addr ) >> 0x10 ) & 0xFF;
c = ( htonl( addr_in->sin_addr.s_addr ) >> 0x8 ) & 0xFF;
d = ( htonl( addr_in->sin_addr.s_addr ) & 0xFF );

printf( "%s : %u.%u.%u.%u\n", ifnr->ifa_name, a, b, c, d );
}

ifnr = ifnr->ifa_next;
}

freeifaddrs( ifap );

return 0;
}


All well... I was hoping the prior stuff ( python ) would give you the hints required... but since that appears to have failed... that is your fish for the day... lol


Michael

caltiger
09-16-2006, 11:02 AM
Huh?

What?

You used if_nameindex( * ) to retrieve network addresses?

It normally just returns basic names and indexes only... not even aliases... and never heard of the associated ip addrs ( there was actually a discussion of that during the specification of that function about WHY it could be a bad idea )...

Now I know if_nameindex allows additional vals in the return structure but... at the base level its the index number and name... so what platform are you using?


#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <errno.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>


int main( int argc, char ** argv )
{
struct ifaddrs * ifap = ( void * ) 0;
struct ifaddrs * ifnr = ( void * ) 0;

struct sockaddr * addr = ( void * ) 0;
struct sockaddr_in * addr_in = ( void * ) 0;

int res = getifaddrs( & ifap );

int a;
int b;
int c;
int d;

if ( 0 != res )
{
printf( "%s\n", strerror( errno ) );

exit( -1 );
}

ifnr = ifap;

while ( ( void * ) 0 != ifnr )
{
addr = ifnr->ifa_addr;

if ( AF_INET == addr->sa_family )
{
addr_in = ( struct sockaddr_in * ) ifnr->ifa_addr;

a = ( htonl( addr_in->sin_addr.s_addr ) >> 0x18 ) & 0xFF;
b = ( htonl( addr_in->sin_addr.s_addr ) >> 0x10 ) & 0xFF;
c = ( htonl( addr_in->sin_addr.s_addr ) >> 0x8 ) & 0xFF;
d = ( htonl( addr_in->sin_addr.s_addr ) & 0xFF );

printf( "%s : %u.%u.%u.%u\n", ifnr->ifa_name, a, b, c, d );
}

ifnr = ifnr->ifa_next;
}

freeifaddrs( ifap );

return 0;
}


All well... I was hoping the prior stuff ( python ) would give you the hints required... but since that appears to have failed... that is your fish for the day... lol


Michael
nooooooo..
i meantr i go the interface name from the if_nameindex. i got the ip addresses using SIOCGIFADDR.. sorry.. 4got to mention tht.. oh n btw.. i`m using red hat linux enterprise

caltiger
09-16-2006, 11:09 AM
Huh?


if ( AF_INET == addr->sa_family )
{
addr_in = ( struct sockaddr_in * ) ifnr->ifa_addr;

a = ( htonl( addr_in->sin_addr.s_addr ) >> 0x18 ) & 0xFF;
b = ( htonl( addr_in->sin_addr.s_addr ) >> 0x10 ) & 0xFF;
c = ( htonl( addr_in->sin_addr.s_addr ) >> 0x8 ) & 0xFF;
d = ( htonl( addr_in->sin_addr.s_addr ) & 0xFF );

printf( "%s : %u.%u.%u.%u\n", ifnr->ifa_name, a, b, c, d );
}


}
[/code]

Michael

wat does tht function do? i saw in another code tht the contents of sa_data were copied to an unsigned char *. then each of the elements of the hw address (in ur case a,b,c,d) are printed using
printf ("%2.2x.%2.2x.%2.2x.%2.2x.%2.2x.", u[0],u[1],u[2],u[3],u[4]).
here u is the unsigned char *.

isn`t the hardware address stored as such in sa_data or do we have to perform some function on tht?

thanx!!

mlampkin
09-16-2006, 12:13 PM
Um... you said you wanted to retrieve the alias addresses... which is an ip thing...

>>sigh<<

For each ifa_addr field returned... there is a family ( protocol ) associated with it... checking for AF_INET == means the record points to the IPv4 information... that is what I am showing... and so we cast to a sockaddr_in ( the IPv4 address structure ) and print out the internet addresses...

I simply did it step by step instead of cramming the entire operation of formatting into a single printf statement... :-/

If you were trying to get the ethernet address for an interface... then check for the AF_PACKET ( linux == 17 ) family like I did in the Python example... if you find that then cast to a sockaddr_dl and retrieve the six byte address from the sll_addr field...


Michael


P.S. Did you at least cut / paste and try to compile / run it first...?!