@ -38,8 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct NetlinkList
{
struct NetlinkList * m_next ;
struct nlmsghdr * m_data ;
struct NetlinkList * m_next ;
struct nlmsghdr * m_data ;
unsigned int m_size ;
} NetlinkList ;
@ -47,7 +47,7 @@ static int
netlink_socket ( void )
{
int l_socket = socket ( PF_NETLINK , SOCK_RAW , NETLINK_ROUTE ) ;
if ( l_socket < 0 )
if ( l_socket < 0 )
{
return - 1 ;
}
@ -55,7 +55,7 @@ netlink_socket(void)
struct sockaddr_nl l_addr ;
memset ( & l_addr , 0 , sizeof ( l_addr ) ) ;
l_addr . nl_family = AF_NETLINK ;
if ( bind ( l_socket , ( struct sockaddr * ) & l_addr , sizeof ( l_addr ) ) < 0 )
if ( bind ( l_socket , ( struct sockaddr * ) & l_addr , sizeof ( l_addr ) ) < 0 )
{
close ( l_socket ) ;
return - 1 ;
@ -75,48 +75,53 @@ netlink_send(int p_socket, int p_request)
memset ( & l_data , 0 , sizeof ( l_data ) ) ;
l_data . m_hdr . nlmsg_len = NLMSG_LENGTH ( sizeof ( struct rtgenmsg ) ) ;
l_data . m_hdr . nlmsg_type = p_request ;
l_data . m_hdr . nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST ;
l_data . m_hdr . nlmsg_pid = 0 ;
l_data . m_hdr . nlmsg_seq = p_socket ;
l_data . m_hdr . nlmsg_len = NLMSG_LENGTH ( sizeof ( struct rtgenmsg ) ) ;
l_data . m_hdr . nlmsg_type = p_request ;
l_data . m_hdr . nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST ;
l_data . m_hdr . nlmsg_pid = 0 ;
l_data . m_hdr . nlmsg_seq = p_socket ;
l_data . m_msg . rtgen_family = AF_UNSPEC ;
struct sockaddr_nl l_addr ;
memset ( & l_addr , 0 , sizeof ( l_addr ) ) ;
l_addr . nl_family = AF_NETLINK ;
return ( sendto ( p_socket , & l_data . m_hdr , l_data . m_hdr . nlmsg_len , 0 ,
( struct sockaddr * ) & l_addr , sizeof ( l_addr ) ) ) ;
return ( sendto (
p_socket ,
& l_data . m_hdr ,
l_data . m_hdr . nlmsg_len ,
0 ,
( struct sockaddr * ) & l_addr ,
sizeof ( l_addr ) ) ) ;
}
static int
netlink_recv ( int p_socket , void * p_buffer , size_t p_len )
netlink_recv ( int p_socket , void * p_buffer , size_t p_len )
{
struct msghdr l_msg ;
struct iovec l_iov = { p_buffer , p_len } ;
struct sockaddr_nl l_addr ;
for ( ; ; )
for ( ; ; )
{
l_msg . msg_name = ( void * ) & l_addr ;
l_msg . msg_namelen = sizeof ( l_addr ) ;
l_msg . msg_iov = & l_iov ;
l_msg . msg_iovlen = 1 ;
l_msg . msg_control = NULL ;
l_msg . msg_name = ( void * ) & l_addr ;
l_msg . msg_namelen = sizeof ( l_addr ) ;
l_msg . msg_iov = & l_iov ;
l_msg . msg_iovlen = 1 ;
l_msg . msg_control = NULL ;
l_msg . msg_controllen = 0 ;
l_msg . msg_flags = 0 ;
int l_result = recvmsg ( p_socket , & l_msg , 0 ) ;
l_msg . msg_flags = 0 ;
int l_result = recvmsg ( p_socket , & l_msg , 0 ) ;
if ( l_result < 0 )
if ( l_result < 0 )
{
if ( errno = = EINTR )
if ( errno = = EINTR )
{
continue ;
}
return - 2 ;
}
if ( l_msg . msg_flags & MSG_TRUNC )
if ( l_msg . msg_flags & MSG_TRUNC )
{ // buffer was too small
return - 1 ;
}
@ -124,49 +129,47 @@ netlink_recv(int p_socket, void *p_buffer, size_t p_len)
}
}
static struct nlmsghdr *
getNetlinkResponse ( int p_socket , int * p_size , int * p_done )
static struct nlmsghdr *
getNetlinkResponse ( int p_socket , int * p_size , int * p_done )
{
size_t l_size = 4096 ;
void * l_buffer = NULL ;
size_t l_size = 4096 ;
void * l_buffer = NULL ;
for ( ; ; )
for ( ; ; )
{
free ( l_buffer ) ;
l_buffer = malloc ( l_size ) ;
if ( l_buffer = = NULL )
if ( l_buffer = = NULL )
{
return NULL ;
}
int l_read = netlink_recv ( p_socket , l_buffer , l_size ) ;
* p_size = l_read ;
if ( l_read = = - 2 )
* p_size = l_read ;
if ( l_read = = - 2 )
{
free ( l_buffer ) ;
return NULL ;
}
if ( l_read > = 0 )
if ( l_read > = 0 )
{
pid_t l_pid = getpid ( ) ;
struct nlmsghdr * l_hdr ;
for ( l_hdr = ( struct nlmsghdr * ) l_buffer ;
NLMSG_OK ( l_hdr , ( unsigned int ) l_read ) ;
l_hdr = ( struct nlmsghdr * ) NLMSG_NEXT ( l_hdr , l_read ) )
struct nlmsghdr * l_hdr ;
for ( l_hdr = ( struct nlmsghdr * ) l_buffer ; NLMSG_OK ( l_hdr , ( unsigned int ) l_read ) ;
l_hdr = ( struct nlmsghdr * ) NLMSG_NEXT ( l_hdr , l_read ) )
{
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid
| | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid | | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
{
continue ;
}
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
{
* p_done = 1 ;
break ;
}
if ( l_hdr - > nlmsg_type = = NLMSG_ERROR )
if ( l_hdr - > nlmsg_type = = NLMSG_ERROR )
{
free ( l_buffer ) ;
return NULL ;
@ -179,11 +182,11 @@ getNetlinkResponse(int p_socket, int *p_size, int *p_done)
}
}
static NetlinkList *
newListItem ( struct nlmsghdr * p_data , unsigned int p_size )
static NetlinkList *
newListItem ( struct nlmsghdr * p_data , unsigned int p_size )
{
NetlinkList * l_item = malloc ( sizeof ( NetlinkList ) ) ;
if ( l_item = = NULL )
NetlinkList * l_item = malloc ( sizeof ( NetlinkList ) ) ;
if ( l_item = = NULL )
{
return NULL ;
}
@ -195,46 +198,46 @@ newListItem(struct nlmsghdr *p_data, unsigned int p_size)
}
static void
freeResultList ( NetlinkList * p_list )
freeResultList ( NetlinkList * p_list )
{
NetlinkList * l_cur ;
while ( p_list )
NetlinkList * l_cur ;
while ( p_list )
{
l_cur = p_list ;
l_cur = p_list ;
p_list = p_list - > m_next ;
free ( l_cur - > m_data ) ;
free ( l_cur ) ;
}
}
static NetlinkList *
static NetlinkList *
getResultList ( int p_socket , int p_request )
{
if ( netlink_send ( p_socket , p_request ) < 0 )
if ( netlink_send ( p_socket , p_request ) < 0 )
{
return NULL ;
}
NetlinkList * l_list = NULL ;
NetlinkList * l_end = NULL ;
NetlinkList * l_list = NULL ;
NetlinkList * l_end = NULL ;
int l_size ;
int l_done = 0 ;
while ( ! l_done )
while ( ! l_done )
{
struct nlmsghdr * l_hdr = getNetlinkResponse ( p_socket , & l_size , & l_done ) ;
if ( ! l_hdr )
struct nlmsghdr * l_hdr = getNetlinkResponse ( p_socket , & l_size , & l_done ) ;
if ( ! l_hdr )
{ // error
freeResultList ( l_list ) ;
return NULL ;
}
NetlinkList * l_item = newListItem ( l_hdr , l_size ) ;
if ( ! l_item )
NetlinkList * l_item = newListItem ( l_hdr , l_size ) ;
if ( ! l_item )
{
freeResultList ( l_list ) ;
return NULL ;
}
if ( ! l_list )
if ( ! l_list )
{
l_list = l_item ;
}
@ -256,36 +259,34 @@ maxSize(size_t a, size_t b)
static size_t
calcAddrLen ( sa_family_t p_family , int p_dataSize )
{
switch ( p_family )
switch ( p_family )
{
case AF_INET :
return sizeof ( struct sockaddr_in ) ;
case AF_INET6 :
return sizeof ( struct sockaddr_in6 ) ;
case AF_PACKET :
return maxSize ( sizeof ( struct sockaddr_ll ) ,
offsetof ( struct sockaddr_ll , sll_addr ) + p_dataSize ) ;
return maxSize (
sizeof ( struct sockaddr_ll ) , offsetof ( struct sockaddr_ll , sll_addr ) + p_dataSize ) ;
default :
return maxSize ( sizeof ( struct sockaddr ) ,
offsetof ( struct sockaddr , sa_data ) + p_dataSize ) ;
return maxSize ( sizeof ( struct sockaddr ) , offsetof ( struct sockaddr , sa_data ) + p_dataSize ) ;
}
}
static void
makeSockaddr ( sa_family_t p_family , struct sockaddr * p_dest , void * p_data ,
size_t p_size )
makeSockaddr ( sa_family_t p_family , struct sockaddr * p_dest , void * p_data , size_t p_size )
{
switch ( p_family )
switch ( p_family )
{
case AF_INET :
memcpy ( & ( ( struct sockaddr_in * ) p_dest ) - > sin_addr , p_data , p_size ) ;
memcpy ( & ( ( struct sockaddr_in * ) p_dest ) - > sin_addr , p_data , p_size ) ;
break ;
case AF_INET6 :
memcpy ( & ( ( struct sockaddr_in6 * ) p_dest ) - > sin6_addr , p_data , p_size ) ;
memcpy ( & ( ( struct sockaddr_in6 * ) p_dest ) - > sin6_addr , p_data , p_size ) ;
break ;
case AF_PACKET :
memcpy ( ( ( struct sockaddr_ll * ) p_dest ) - > sll_addr , p_data , p_size ) ;
( ( struct sockaddr_ll * ) p_dest ) - > sll_halen = p_size ;
memcpy ( ( ( struct sockaddr_ll * ) p_dest ) - > sll_addr , p_data , p_size ) ;
( ( struct sockaddr_ll * ) p_dest ) - > sll_halen = p_size ;
break ;
default :
memcpy ( p_dest - > sa_data , p_data , p_size ) ;
@ -295,16 +296,16 @@ makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data,
}
static void
addToEnd ( struct ifaddrs * * p_resultList , struct ifaddrs * p_entry )
addToEnd ( struct ifaddrs * * p_resultList , struct ifaddrs * p_entry )
{
if ( ! * p_resultList )
if ( ! * p_resultList )
{
* p_resultList = p_entry ;
}
else
{
struct ifaddrs * l_cur = * p_resultList ;
while ( l_cur - > ifa_next )
struct ifaddrs * l_cur = * p_resultList ;
while ( l_cur - > ifa_next )
{
l_cur = l_cur - > ifa_next ;
}
@ -313,23 +314,22 @@ addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
}
static int
interpretLink ( struct nlmsghdr * p_hdr , struct ifaddrs * * p_resultList )
interpretLink ( struct nlmsghdr * p_hdr , struct ifaddrs * * p_resultList )
{
struct ifinfomsg * l_info = ( struct ifinfomsg * ) NLMSG_DATA ( p_hdr ) ;
struct ifinfomsg * l_info = ( struct ifinfomsg * ) NLMSG_DATA ( p_hdr ) ;
size_t l_nameSize = 0 ;
size_t l_addrSize = 0 ;
size_t l_dataSize = 0 ;
size_t l_rtaSize = NLMSG_PAYLOAD ( p_hdr , sizeof ( struct ifinfomsg ) ) ;
struct rtattr * l_rta ;
for ( l_rta = IFLA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ;
l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
struct rtattr * l_rta ;
for ( l_rta = IFLA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ; l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
{
void * l_rtaData = RTA_DATA ( l_rta ) ;
void * l_rtaData = RTA_DATA ( l_rta ) ;
( void ) l_rtaData ;
size_t l_rtaDataSize = RTA_PAYLOAD ( l_rta ) ;
switch ( l_rta - > rta_type )
switch ( l_rta - > rta_type )
{
case IFLA_ADDRESS :
case IFLA_BROADCAST :
@ -346,19 +346,19 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
}
}
struct ifaddrs * l_entry = malloc ( sizeof ( struct ifaddrs ) + sizeof ( int )
+ l_nameSize + l_addrSize + l_dataSize ) ;
if ( l_entry = = NULL )
struct ifaddrs * l_entry =
malloc ( sizeof ( struct ifaddrs ) + sizeof ( int ) + l_nameSize + l_addrSize + l_dataSize ) ;
if ( l_entry = = NULL )
{
return - 1 ;
}
memset ( l_entry , 0 , sizeof ( struct ifaddrs ) ) ;
l_entry - > ifa_name = " " ;
char * l_index = ( ( char * ) l_entry ) + sizeof ( struct ifaddrs ) ;
char * l_name = l_index + sizeof ( int ) ;
char * l_addr = l_name + l_nameSize ;
char * l_data = l_addr + l_addrSize ;
char * l_index = ( ( char * ) l_entry ) + sizeof ( struct ifaddrs ) ;
char * l_name = l_index + sizeof ( int ) ;
char * l_addr = l_name + l_nameSize ;
char * l_data = l_addr + l_addrSize ;
// save the interface index so we can look it up when handling the addresses.
memcpy ( l_index , & l_info - > ifi_index , sizeof ( int ) ) ;
@ -366,28 +366,26 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
l_entry - > ifa_flags = l_info - > ifi_flags ;
l_rtaSize = NLMSG_PAYLOAD ( p_hdr , sizeof ( struct ifinfomsg ) ) ;
for ( l_rta = IFLA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ;
l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
for ( l_rta = IFLA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ; l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
{
void * l_rtaData = RTA_DATA ( l_rta ) ;
void * l_rtaData = RTA_DATA ( l_rta ) ;
size_t l_rtaDataSize = RTA_PAYLOAD ( l_rta ) ;
switch ( l_rta - > rta_type )
switch ( l_rta - > rta_type )
{
case IFLA_ADDRESS :
case IFLA_BROADCAST :
{
size_t l_addrLen = calcAddrLen ( AF_PACKET , l_rtaDataSize ) ;
makeSockaddr ( AF_PACKET , ( struct sockaddr * ) l_addr , l_rtaData ,
l_rtaDataSize ) ;
( ( struct sockaddr_ll * ) l_addr ) - > sll_ifindex = l_info - > ifi_index ;
( ( struct sockaddr_ll * ) l_addr ) - > sll_hatype = l_info - > ifi_type ;
if ( l_rta - > rta_type = = IFLA_ADDRESS )
makeSockaddr ( AF_PACKET , ( struct sockaddr * ) l_addr , l_rtaData , l_rtaDataSize ) ;
( ( struct sockaddr_ll * ) l_addr ) - > sll_ifindex = l_info - > ifi_index ;
( ( struct sockaddr_ll * ) l_addr ) - > sll_hatype = l_info - > ifi_type ;
if ( l_rta - > rta_type = = IFLA_ADDRESS )
{
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
}
else
{
l_entry - > ifa_broadaddr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_broadaddr = ( struct sockaddr * ) l_addr ;
}
l_addr + = NLMSG_ALIGN ( l_addrLen ) ;
break ;
@ -395,7 +393,7 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
case IFLA_IFNAME :
strncpy ( l_name , l_rtaData , l_rtaDataSize ) ;
l_name [ l_rtaDataSize ] = ' \0 ' ;
l_entry - > ifa_name = l_name ;
l_entry - > ifa_name = l_name ;
break ;
case IFLA_STATS :
memcpy ( l_data , l_rtaData , l_rtaDataSize ) ;
@ -410,17 +408,17 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
return 0 ;
}
static struct ifaddrs *
findInterface ( int p_index , struct ifaddrs * * p_links , int p_numLinks )
static struct ifaddrs *
findInterface ( int p_index , struct ifaddrs * * p_links , int p_numLinks )
{
int l_num = 0 ;
struct ifaddrs * l_cur = * p_links ;
while ( l_cur & & l_num < p_numLinks )
int l_num = 0 ;
struct ifaddrs * l_cur = * p_links ;
while ( l_cur & & l_num < p_numLinks )
{
char * l_indexPtr = ( ( char * ) l_cur ) + sizeof ( struct ifaddrs ) ;
char * l_indexPtr = ( ( char * ) l_cur ) + sizeof ( struct ifaddrs ) ;
int l_index ;
memcpy ( & l_index , l_indexPtr , sizeof ( int ) ) ;
if ( l_index = = p_index )
if ( l_index = = p_index )
{
return l_cur ;
}
@ -432,14 +430,12 @@ findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
}
static int
interpretAddr ( struct nlmsghdr * p_hdr , struct ifaddrs * * p_resultList ,
int p_numLinks )
interpretAddr ( struct nlmsghdr * p_hdr , struct ifaddrs * * p_resultList , int p_numLinks )
{
struct ifaddrmsg * l_info = ( struct ifaddrmsg * ) NLMSG_DATA ( p_hdr ) ;
struct ifaddrs * l_interface =
findInterface ( l_info - > ifa_index , p_resultList , p_numLinks ) ;
struct ifaddrmsg * l_info = ( struct ifaddrmsg * ) NLMSG_DATA ( p_hdr ) ;
struct ifaddrs * l_interface = findInterface ( l_info - > ifa_index , p_resultList , p_numLinks ) ;
if ( l_info - > ifa_family = = AF_PACKET )
if ( l_info - > ifa_family = = AF_PACKET )
{
return 0 ;
}
@ -450,28 +446,24 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
int l_addedNetmask = 0 ;
size_t l_rtaSize = NLMSG_PAYLOAD ( p_hdr , sizeof ( struct ifaddrmsg ) ) ;
struct rtattr * l_rta ;
for ( l_rta = IFA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ;
l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
struct rtattr * l_rta ;
for ( l_rta = IFA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ; l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
{
void * l_rtaData = RTA_DATA ( l_rta ) ;
void * l_rtaData = RTA_DATA ( l_rta ) ;
( void ) l_rtaData ;
size_t l_rtaDataSize = RTA_PAYLOAD ( l_rta ) ;
switch ( l_rta - > rta_type )
switch ( l_rta - > rta_type )
{
case IFA_ADDRESS :
case IFA_LOCAL :
if ( ( l_info - > ifa_family = = AF_INET | | l_info - > ifa_family = = AF_INET6 )
& & ! l_addedNetmask )
if ( ( l_info - > ifa_family = = AF_INET | | l_info - > ifa_family = = AF_INET6 ) & & ! l_addedNetmask )
{ // make room for netmask
l_addrSize + =
NLMSG_ALIGN ( calcAddrLen ( l_info - > ifa_family , l_rtaDataSize ) ) ;
l_addrSize + = NLMSG_ALIGN ( calcAddrLen ( l_info - > ifa_family , l_rtaDataSize ) ) ;
l_addedNetmask = 1 ;
}
case IFA_BROADCAST :
l_addrSize + =
NLMSG_ALIGN ( calcAddrLen ( l_info - > ifa_family , l_rtaDataSize ) ) ;
l_addrSize + = NLMSG_ALIGN ( calcAddrLen ( l_info - > ifa_family , l_rtaDataSize ) ) ;
break ;
case IFA_LABEL :
l_nameSize + = NLMSG_ALIGN ( l_rtaSize + 1 ) ;
@ -481,71 +473,68 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
}
}
struct ifaddrs * l_entry =
malloc ( sizeof ( struct ifaddrs ) + l_nameSize + l_addrSize ) ;
if ( l_entry = = NULL )
struct ifaddrs * l_entry = malloc ( sizeof ( struct ifaddrs ) + l_nameSize + l_addrSize ) ;
if ( l_entry = = NULL )
{
return - 1 ;
}
memset ( l_entry , 0 , sizeof ( struct ifaddrs ) ) ;
l_entry - > ifa_name = ( l_interface ? l_interface - > ifa_name : " " ) ;
char * l_name = ( ( char * ) l_entry ) + sizeof ( struct ifaddrs ) ;
char * l_addr = l_name + l_nameSize ;
char * l_name = ( ( char * ) l_entry ) + sizeof ( struct ifaddrs ) ;
char * l_addr = l_name + l_nameSize ;
l_entry - > ifa_flags = l_info - > ifa_flags ;
if ( l_interface )
if ( l_interface )
{
l_entry - > ifa_flags | = l_interface - > ifa_flags ;
}
l_rtaSize = NLMSG_PAYLOAD ( p_hdr , sizeof ( struct ifaddrmsg ) ) ;
for ( l_rta = IFA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ;
l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
for ( l_rta = IFA_RTA ( l_info ) ; RTA_OK ( l_rta , l_rtaSize ) ; l_rta = RTA_NEXT ( l_rta , l_rtaSize ) )
{
void * l_rtaData = RTA_DATA ( l_rta ) ;
void * l_rtaData = RTA_DATA ( l_rta ) ;
size_t l_rtaDataSize = RTA_PAYLOAD ( l_rta ) ;
switch ( l_rta - > rta_type )
switch ( l_rta - > rta_type )
{
case IFA_ADDRESS :
case IFA_BROADCAST :
case IFA_LOCAL :
{
size_t l_addrLen = calcAddrLen ( l_info - > ifa_family , l_rtaDataSize ) ;
makeSockaddr ( l_info - > ifa_family , ( struct sockaddr * ) l_addr , l_rtaData ,
l_rtaDataSize ) ;
if ( l_info - > ifa_family = = AF_INET6 )
makeSockaddr ( l_info - > ifa_family , ( struct sockaddr * ) l_addr , l_rtaData , l_rtaDataSize ) ;
if ( l_info - > ifa_family = = AF_INET6 )
{
if ( IN6_IS_ADDR_LINKLOCAL ( ( struct in6_addr * ) l_rtaData )
| | IN6_IS_ADDR_MC_LINKLOCAL ( ( struct in6_addr * ) l_rtaData ) )
if ( IN6_IS_ADDR_LINKLOCAL ( ( struct in6_addr * ) l_rtaData )
| | IN6_IS_ADDR_MC_LINKLOCAL ( ( struct in6_addr * ) l_rtaData ) )
{
( ( struct sockaddr_in6 * ) l_addr ) - > sin6_scope_id = l_info - > ifa_index ;
( ( struct sockaddr_in6 * ) l_addr ) - > sin6_scope_id = l_info - > ifa_index ;
}
}
if ( l_rta - > rta_type = = IFA_ADDRESS )
if ( l_rta - > rta_type = = IFA_ADDRESS )
{ // apparently in a point-to-point network IFA_ADDRESS contains the
// dest address and IFA_LOCAL contains the local address
if ( l_entry - > ifa_addr )
if ( l_entry - > ifa_addr )
{
l_entry - > ifa_dstaddr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_dstaddr = ( struct sockaddr * ) l_addr ;
}
else
{
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
}
}
else if ( l_rta - > rta_type = = IFA_LOCAL )
else if ( l_rta - > rta_type = = IFA_LOCAL )
{
if ( l_entry - > ifa_addr )
if ( l_entry - > ifa_addr )
{
l_entry - > ifa_dstaddr = l_entry - > ifa_addr ;
}
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_addr = ( struct sockaddr * ) l_addr ;
}
else
{
l_entry - > ifa_broadaddr = ( struct sockaddr * ) l_addr ;
l_entry - > ifa_broadaddr = ( struct sockaddr * ) l_addr ;
}
l_addr + = NLMSG_ALIGN ( l_addrLen ) ;
break ;
@ -553,35 +542,31 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
case IFA_LABEL :
strncpy ( l_name , l_rtaData , l_rtaDataSize ) ;
l_name [ l_rtaDataSize ] = ' \0 ' ;
l_entry - > ifa_name = l_name ;
l_entry - > ifa_name = l_name ;
break ;
default :
break ;
}
}
if ( l_entry - > ifa_addr
& & ( l_entry - > ifa_addr - > sa_family = = AF_INET
| | l_entry - > ifa_addr - > sa_family = = AF_INET6 ) )
if ( l_entry - > ifa_addr
& & ( l_entry - > ifa_addr - > sa_family = = AF_INET | | l_entry - > ifa_addr - > sa_family = = AF_INET6 ) )
{
unsigned l_maxPrefix = ( l_entry - > ifa_addr - > sa_family = = AF_INET ? 32 : 128 ) ;
unsigned l_prefix =
( l_info - > ifa_prefixlen > l_maxPrefix ? l_maxPrefix
: l_info - > ifa_prefixlen ) ;
unsigned l_prefix = ( l_info - > ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info - > ifa_prefixlen ) ;
char l_mask [ 16 ] = { 0 } ;
unsigned i ;
for ( i = 0 ; i < ( l_prefix / 8 ) ; + + i )
for ( i = 0 ; i < ( l_prefix / 8 ) ; + + i )
{
l_mask [ i ] = 0xff ;
}
if ( l_prefix % 8 )
if ( l_prefix % 8 )
{
l_mask [ i ] = 0xff < < ( 8 - ( l_prefix % 8 ) ) ;
}
makeSockaddr ( l_entry - > ifa_addr - > sa_family , ( struct sockaddr * ) l_addr ,
l_mask , l_maxPrefix / 8 ) ;
l_entry - > ifa_netmask = ( struct sockaddr * ) l_addr ;
makeSockaddr ( l_entry - > ifa_addr - > sa_family , ( struct sockaddr * ) l_addr , l_mask , l_maxPrefix / 8 ) ;
l_entry - > ifa_netmask = ( struct sockaddr * ) l_addr ;
}
addToEnd ( p_resultList , l_entry ) ;
@ -589,31 +574,30 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
}
static int
interpretLinks ( int p_socket , NetlinkList * p_netlinkList ,
struct ifaddrs * * p_resultList )
interpretLinks ( int p_socket , NetlinkList * p_netlinkList , struct ifaddrs * * p_resultList )
{
int l_numLinks = 0 ;
pid_t l_pid = getpid ( ) ;
for ( ; p_netlinkList ; p_netlinkList = p_netlinkList - > m_next )
pid_t l_pid = getpid ( ) ;
for ( ; p_netlinkList ; p_netlinkList = p_netlinkList - > m_next )
{
unsigned int l_nlsize = p_netlinkList - > m_size ;
struct nlmsghdr * l_hdr ;
for ( l_hdr = p_netlinkList - > m_data ; NLMSG_OK ( l_hdr , l_nlsize ) ;
l_hdr = NLMSG_NEXT ( l_hdr , l_nlsize ) )
struct nlmsghdr * l_hdr ;
for ( l_hdr = p_netlinkList - > m_data ; NLMSG_OK ( l_hdr , l_nlsize ) ;
l_hdr = NLMSG_NEXT ( l_hdr , l_nlsize ) )
{
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid | | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid | | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
{
continue ;
}
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
{
break ;
}
if ( l_hdr - > nlmsg_type = = RTM_NEWLINK )
if ( l_hdr - > nlmsg_type = = RTM_NEWLINK )
{
if ( interpretLink ( l_hdr , p_resultList ) = = - 1 )
if ( interpretLink ( l_hdr , p_resultList ) = = - 1 )
{
return - 1 ;
}
@ -625,30 +609,30 @@ interpretLinks(int p_socket, NetlinkList *p_netlinkList,
}
static int
interpretAddrs ( int p_socket , NetlinkList * p_netlinkList ,
struct ifaddrs * * p_resultList , int p_numLinks )
interpretAddrs (
int p_socket , NetlinkList * p_netlinkList , struct ifaddrs * * p_resultList , int p_numLinks )
{
pid_t l_pid = getpid ( ) ;
for ( ; p_netlinkList ; p_netlinkList = p_netlinkList - > m_next )
for ( ; p_netlinkList ; p_netlinkList = p_netlinkList - > m_next )
{
unsigned int l_nlsize = p_netlinkList - > m_size ;
struct nlmsghdr * l_hdr ;
for ( l_hdr = p_netlinkList - > m_data ; NLMSG_OK ( l_hdr , l_nlsize ) ;
l_hdr = NLMSG_NEXT ( l_hdr , l_nlsize ) )
struct nlmsghdr * l_hdr ;
for ( l_hdr = p_netlinkList - > m_data ; NLMSG_OK ( l_hdr , l_nlsize ) ;
l_hdr = NLMSG_NEXT ( l_hdr , l_nlsize ) )
{
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid | | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
if ( ( pid_t ) l_hdr - > nlmsg_pid ! = l_pid | | ( int ) l_hdr - > nlmsg_seq ! = p_socket )
{
continue ;
}
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
if ( l_hdr - > nlmsg_type = = NLMSG_DONE )
{
break ;
}
if ( l_hdr - > nlmsg_type = = RTM_NEWADDR )
if ( l_hdr - > nlmsg_type = = RTM_NEWADDR )
{
if ( interpretAddr ( l_hdr , p_resultList , p_numLinks ) = = - 1 )
if ( interpretAddr ( l_hdr , p_resultList , p_numLinks ) = = - 1 )
{
return - 1 ;
}
@ -659,39 +643,38 @@ interpretAddrs(int p_socket, NetlinkList *p_netlinkList,
}
int
getifaddrs ( struct ifaddrs * * ifap )
getifaddrs ( struct ifaddrs * * ifap )
{
if ( ! ifap )
if ( ! ifap )
{
return - 1 ;
}
* ifap = NULL ;
int l_socket = netlink_socket ( ) ;
if ( l_socket < 0 )
if ( l_socket < 0 )
{
return - 1 ;
}
NetlinkList * l_linkResults = getResultList ( l_socket , RTM_GETLINK ) ;
if ( ! l_linkResults )
NetlinkList * l_linkResults = getResultList ( l_socket , RTM_GETLINK ) ;
if ( ! l_linkResults )
{
close ( l_socket ) ;
return - 1 ;
}
NetlinkList * l_addrResults = getResultList ( l_socket , RTM_GETADDR ) ;
if ( ! l_addrResults )
NetlinkList * l_addrResults = getResultList ( l_socket , RTM_GETADDR ) ;
if ( ! l_addrResults )
{
close ( l_socket ) ;
freeResultList ( l_linkResults ) ;
return - 1 ;
}
int l_result = 0 ;
int l_result = 0 ;
int l_numLinks = interpretLinks ( l_socket , l_linkResults , ifap ) ;
if ( l_numLinks = = - 1
| | interpretAddrs ( l_socket , l_addrResults , ifap , l_numLinks ) = = - 1 )
if ( l_numLinks = = - 1 | | interpretAddrs ( l_socket , l_addrResults , ifap , l_numLinks ) = = - 1 )
{
l_result = - 1 ;
}
@ -703,13 +686,13 @@ getifaddrs(struct ifaddrs **ifap)
}
void
freeifaddrs ( struct ifaddrs * ifa )
freeifaddrs ( struct ifaddrs * ifa )
{
struct ifaddrs * l_cur ;
while ( ifa )
struct ifaddrs * l_cur ;
while ( ifa )
{
l_cur = ifa ;
ifa = ifa - > ifa_next ;
ifa = ifa - > ifa_next ;
free ( l_cur ) ;
}
}