2011-05-09 16:57:15 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
2013-01-05 21:42:40 +04:00
This file is part of systemd .
2011-05-09 16:57:15 +04:00
Copyright 2008 - 2011 Lennart Poettering
2014-04-14 14:46:09 +04:00
Copyright 2014 Tom Gundersen
2011-05-09 16:57:15 +04:00
2013-01-05 21:42:40 +04:00
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
( at your option ) any later version .
2011-05-09 16:57:15 +04:00
2013-01-05 21:42:40 +04:00
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
2011-05-09 16:57:15 +04:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
2013-01-05 21:42:40 +04:00
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
2011-05-09 16:57:15 +04:00
* * */
2014-04-14 14:46:09 +04:00
# include "sd-rtnl.h"
# include "rtnl-util.h"
# include "macro.h"
2011-05-09 16:57:15 +04:00
2011-06-15 18:49:24 +04:00
# include "ifconf.h"
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
int ifconf_acquire_addresses ( struct address * * _list , unsigned * _n_list ) {
_cleanup_rtnl_unref_ sd_rtnl * rtnl = NULL ;
_cleanup_rtnl_message_unref_ sd_rtnl_message * req = NULL , * reply = NULL ;
sd_rtnl_message * m ;
_cleanup_free_ struct address * list = NULL ;
struct address * new_list = NULL ;
unsigned n_list = 0 ;
int r ;
2013-03-30 18:46:04 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_open ( & rtnl , 0 ) ;
if ( r < 0 )
return r ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_message_new_addr ( rtnl , & req , RTM_GETADDR , 0 , AF_UNSPEC ) ;
if ( r < 0 )
return r ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_call ( rtnl , req , 0 , & reply ) ;
if ( r < 0 )
return r ;
m = reply ;
do {
uint16_t type ;
unsigned char scope ;
unsigned char flags ;
unsigned char family ;
int ifindex ;
union {
struct in_addr in ;
struct in6_addr in6 ;
} address ;
r = sd_rtnl_message_get_errno ( m ) ;
if ( r < 0 )
return r ;
r = sd_rtnl_message_get_type ( m , & type ) ;
if ( r < 0 )
return r ;
if ( type ! = RTM_NEWADDR )
2011-05-09 16:57:15 +04:00
continue ;
2014-04-14 14:46:09 +04:00
r = sd_rtnl_message_addr_get_scope ( m , & scope ) ;
if ( r < 0 )
return r ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
if ( scope = = RT_SCOPE_HOST | | scope = = RT_SCOPE_NOWHERE )
2013-03-30 18:46:04 +04:00
continue ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_message_addr_get_flags ( m , & flags ) ;
if ( r < 0 )
return r ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
if ( flags & IFA_F_DEPRECATED )
2013-03-30 18:46:04 +04:00
continue ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_message_addr_get_family ( m , & family ) ;
if ( r < 0 )
return r ;
switch ( family ) {
case AF_INET :
r = sd_rtnl_message_read_in_addr ( m , IFA_LOCAL , & address . in ) ;
if ( r < 0 ) {
r = sd_rtnl_message_read_in_addr ( m , IFA_ADDRESS , & address . in ) ;
if ( r < 0 )
continue ;
}
break ;
case AF_INET6 :
r = sd_rtnl_message_read_in6_addr ( m , IFA_LOCAL , & address . in6 ) ;
if ( r < 0 ) {
r = sd_rtnl_message_read_in6_addr ( m , IFA_ADDRESS , & address . in6 ) ;
if ( r < 0 )
continue ;
}
break ;
default :
2013-03-30 18:46:04 +04:00
continue ;
}
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
r = sd_rtnl_message_addr_get_ifindex ( m , & ifindex ) ;
if ( r < 0 )
return r ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
new_list = realloc ( list , ( n_list + 1 ) * sizeof ( struct address ) ) ;
if ( ! new_list )
return - ENOMEM ;
else
list = new_list ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
assert_cc ( sizeof ( address ) < = 16 ) ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
list [ n_list ] . family = family ;
list [ n_list ] . scope = scope ;
memcpy ( list [ n_list ] . address , & address , sizeof ( address ) ) ;
list [ n_list ] . ifindex = ifindex ;
2011-05-09 16:57:15 +04:00
2014-04-14 14:46:09 +04:00
n_list + + ;
2013-04-02 21:52:51 +04:00
2014-04-14 14:46:09 +04:00
} while ( ( m = sd_rtnl_message_next ( m ) ) ) ;
2011-05-09 16:57:15 +04:00
2013-10-12 03:33:13 +04:00
if ( n_list )
qsort ( list , n_list , sizeof ( struct address ) , address_compare ) ;
2013-03-30 18:46:04 +04:00
* _n_list = n_list ;
2014-04-14 14:46:09 +04:00
* _list = list ;
list = NULL ;
2013-03-30 18:46:04 +04:00
return 0 ;
2011-05-09 16:57:15 +04:00
}