lkml.org 
[lkml]   [1998]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: Confusing ifreq behavior: guru needed
From
Date
bryan@terran.org (B. James Phillippe) writes:

> Hello,
>
> I'll be concise: I am writing some user-space code that needs to
> obtain the IPv4 protocol address and hardware address from an interface
> (arbitrary). I am using the ioctl() method with SIOCGIFHWADDR and
> SIOCGIFADDR, operating on struct ifreq (contains struct sockaddr). The
> hardware address part works like I expect. But the IP address doesn't;
> it's stored in sa_data, offset two bytes. I don't understand why. Here is
> a code pseudo-fragment:

First: This is linux-kernel for kernel development, not
linux-random-programming-question. Unless you're pretty sure that you found
a bug you should send such help requests to other forums like comp.os.linux.programming.apps or in this case just the generic comp.unix.programmer newsgroup.
The problem with sending too many messages to linux-kernel is that it may
lead in the loss of valuable bug reports in all the other noise, which may
lead to a lower-quality Linux, which you don't want, do you?

>
> Obtaining hardware address (works as I expected):
>
> int s = socket( AF_INET, SOCK_DGRAM, 0 );
> struct ifreq req;
>
> strcpy( req.ifr_name, "some-device" );
> ioctl( s, SIOCGIFHWADDR, &req );
>
> close( s );
> memcpy( "place-to-store-hwaddr", req.ifr_hwaddr.sa_data, 6 );
> /* the "6" is for an ethernet address */
>
> Obtaining the protocol address (it is offset?):
>
> int s = socket( AF_INET, SOCK_DGRAM, 0 );
> struct ifreq req;
>
> strcpy( req.ifr_name, "same-device" );
> ioctl( s, SIOCGIFADDR, &req );
>
> close( s );
> 32-bit-holder = *((u_int32_t*)(req.ifr_addr.sa_data+2));
>
> Note the "+2". I found this by trial and error. If anyone can explain
> this to me (or if I'm doing something wrong) I would be very greatful.

The correct portable way to use these ioctls is with the macros defined
in linux/if.h (or the equivalent file in glibc). See if.h for a list,
for SIOCGIFADDR it is ifr_addr (in the generic sockaddr, you have to use
pointer casts to get an sockaddr_in) or ifr.hwaddr for SIOCGIFHWADDR.

Also note that SIOCGIFADDR is not a good idea to use, because it only returns
one address but in 2.1 one interface may carry many addresses. It is better
to use SIOCGIFCONF to get all addresses and match for the device there
(it gets a struct ifconf instead of a struct ifreq, call it first with
ifconf.ifc_buf set to NULL to get the required buffer length, then allocate
this buffer based on the returned ifc_len value and set ifc_req to it and
call the ioctl again. Then you can iterate over ifreq structures describing
all interface addresses in your buffer.

To get the 32bit address correctly in your second example:

struct sin_addr address;

address = ((struct sockaddr_in *) &req.ifr_addr)->sin_addr;

I agree that it is an problem in Linux that these ioctls are not documented
currently, this is being worked on.

-Andi


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:45    [W:0.053 / U:0.368 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site