Reputation: 3125
I am working with the following code:
struct sockaddr_in6 *sin;
struct ifreq ifr;
sin = (struct sockaddr_in6 *)&ifr.ifr_addr;
ifr_addr
is of type struct sockaddr
, which for convenience is reported here under:
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
How am I supposed to put an IPv6 address (via sin->sin6_addr.s6_addr
) in the ifr_addr
field given there are only 14 bytes available?
Where am I going wrong?
TIA, Chris
Upvotes: 2
Views: 3492
Reputation: 56038
Fortunately struct ifreq
is declared to contain the addresses in a union at the end of the structure:
struct ifreq
{
union
{
char ifrn_name[16];
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[16];
char ifru_newname[16];
__caddr_t ifru_data;
} ifr_ifru;
};
Note that the above was the result of gcc -E
and so all the preprocessor stuff has been expanded. Also note that ifr_addr
is #define
d to be ifr_ifru.ifru_addr
.
This means that technically, you can allocate bytes off the end of the structure to hold the address.
In my opinion, this is extremely sloppy. The union should be declared to hold a value of type sockaddr_storage
along with everything else. Then the structure size will be big enough to hold any address.
If you wanted to declare your own structure of the right size that you could use pretty easily, just do this:
union my_ifreq {
struct ifreq sys_ifreq;
struct {
char name_pad[IFNAMSIZ];
struct sockaddr_storage addr;
} padding;
};
Then you will have a structure that always has enough storage that you can stuff any valid address in sys_ifreq.ifr_addr
and have it work.
Upvotes: 3
Reputation: 12866
The platforms that use struct sockaddr
inside struct ifreq
also have an IPv6 friendly version struct lifreq
that uses struct sockaddr_storage
instead for example Solaris, other platforms such as Linux and AIX already use the longer structure.
Upvotes: 0