Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
5ec569cd
Commit
5ec569cd
authored
Dec 16, 2011
by
Tomek Mrugalski
🛰
Browse files
[1237] OS-detection cleanup, Linux-specific IfaceMgr cleanup.
parent
aaea8925
Changes
4
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
5ec569cd
...
...
@@ -373,7 +373,7 @@ AC_MSG_CHECKING(OS family)
system=`uname -s`
case $system in
Linux)
OS_TYPE="L
INUX
"
OS_TYPE="L
inux
"
CPPFLAGS="$CPPFLAGS -DOS_LINUX"
;;
Darwin | FreeBSD | NetBSD | OpenBSD)
...
...
@@ -390,10 +390,13 @@ case $system in
;;
esac
AC_MSG_RESULT($OS_TYPE)
AM_CONDITIONAL(OS_LINUX, test $OS_TYPE = LINUX)
AM_CONDITIONAL(OS_LINUX, test $OS_TYPE = Linux)
AM_COND_IF([OS_LINUX], [AC_DEFINE([OS_LINUX], [1], [Running on Linux?])])
AM_CONDITIONAL(OS_BSD, test $OS_TYPE = BSD)
AM_COND_IF([OS_BSD], [AC_DEFINE([OS_BSD], [1], [Running on BSD?])])
AM_CONDITIONAL(OS_SOLARIS, test $OS_TYPE = Solaris)
AM_COND_IF([OS_SOLARIS], [AC_DEFINE([OS_SOLARIS], [1], [Running on Solaris?])])
AC_MSG_CHECKING(for sa_len in struct sockaddr)
AC_TRY_COMPILE([
...
...
src/lib/dhcp/Makefile.am
View file @
5ec569cd
...
...
@@ -18,14 +18,8 @@ libdhcp_la_SOURCES += option6_addrlst.cc option6_addrlst.h
libdhcp_la_SOURCES
+=
dhcp6.h dhcp4.h
libdhcp_la_SOURCES
+=
pkt6.cc pkt6.h
libdhcp_la_SOURCES
+=
pkt4.cc pkt4.h
if
OS_LINUX
libdhcp_la_SOURCES
+=
iface_mgr_linux.cc
endif
if
OS_BSD
libdhcp_la_SOURCES
+=
iface_mgr_bsd.cc
endif
EXTRA_DIST
=
README
...
...
src/lib/dhcp/iface_mgr_bsd.cc
View file @
5ec569cd
...
...
@@ -12,6 +12,10 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#if defined(OS_BSD)
#include <dhcp/iface_mgr.h>
#include <exceptions/exceptions.h>
...
...
@@ -20,17 +24,6 @@ using namespace isc;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
dhcp
;
#if !defined(OS_BSD)
/// There are several detectIfaces() implementations for specific
/// Operating Systems. This one is specific to BSD. It works on
/// BSD only, so it does not make sense to try to compile it somewhere
/// else. In particular, Makefile.am includes only one iface_mgr_{OS_TYPE}.cc
/// file.
#error "Attempt to compile iface_mgr_bsd.cc on non-BSD system!"
#endif
namespace
isc
{
void
...
...
@@ -41,3 +34,5 @@ IfaceMgr::detectIfaces() {
}
}
#endif
src/lib/dhcp/iface_mgr_linux.cc
View file @
5ec569cd
...
...
@@ -12,6 +12,11 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#if defined(OS_LINUX)
#include <dhcp/iface_mgr.h>
#include <exceptions/exceptions.h>
...
...
@@ -24,29 +29,20 @@ using namespace isc;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
dhcp
;
#if !defined(OS_LINUX)
/// There are several detectIfaces() implementations for specific
/// Operating Systems. This one is specific to Linux. It works on
/// Linux only, so it does not make sense to try to compile it somewhere
/// else. In particular, Makefile.am includes only one iface_mgr_{OS_TYPE}.cc
/// file.
#error "Attempt to compile iface_mgr_linux.cc on non-Linux system!"
#endif
/// This is a structure that defines context for netlink connection.
struct
rtnl_handle
{
int
fd
;
struct
sockaddr_nl
local
;
struct
sockaddr_nl
peer
;
__u32
seq
;
__u32
dump
;
int
fd
;
struct
sockaddr_nl
local
;
struct
sockaddr_nl
peer
;
__u32
seq
;
__u32
dump
;
};
struct
nlmsg_list
{
struct
nlmsg_list
*
next
;
struct
nlmsghdr
h
;
struct
nlmsg_list
*
next
;
struct
nlmsghdr
h
;
};
const
int
sndbuf
=
32768
;
...
...
@@ -55,53 +51,61 @@ const int rcvbuf = 32768;
namespace
isc
{
/// @brief Opens netlink socket and initializes handle structure.
///
/// @exception Unexpected Thrown if socket configuration fails.
///
/// @param handle Context will be stored in this structure.
void
rtnl_open_socket
(
struct
rtnl_handle
&
handle
)
{
// equivalent of rtnl_open
handle
.
fd
=
socket
(
AF_NETLINK
,
SOCK_RAW
,
NETLINK_ROUTE
);
if
(
handle
.
fd
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to create NETLINK socket."
);
isc_throw
(
Unexpected
,
"Failed to create NETLINK socket."
);
}
if
(
setsockopt
(
handle
.
fd
,
SOL_SOCKET
,
SO_SNDBUF
,
&
sndbuf
,
sizeof
(
sndbuf
))
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to set send buffer in NETLINK socket."
);
isc_throw
(
Unexpected
,
"Failed to set send buffer in NETLINK socket."
);
}
if
(
setsockopt
(
handle
.
fd
,
SOL_SOCKET
,
SO_RCVBUF
,
&
sndbuf
,
sizeof
(
rcvbuf
))
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to set receive buffer in NETLINK socket."
);
isc_throw
(
Unexpected
,
"Failed to set receive buffer in NETLINK socket."
);
}
memset
(
&
handle
.
local
,
0
,
sizeof
(
handle
.
local
));
handle
.
local
.
nl_family
=
AF_NETLINK
;
handle
.
local
.
nl_groups
=
0
;
if
(
bind
(
handle
.
fd
,
(
struct
sockaddr
*
)
&
handle
.
local
,
sizeof
(
handle
.
local
))
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to bind netlink socket."
);
isc_throw
(
Unexpected
,
"Failed to bind netlink socket."
);
}
socklen_t
addr_len
=
sizeof
(
handle
.
local
);
if
(
getsockname
(
handle
.
fd
,
(
struct
sockaddr
*
)
&
handle
.
local
,
&
addr_len
)
<
0
)
{
isc_throw
(
Unexpected
,
"Getsockname for netlink socket failed."
);
isc_throw
(
Unexpected
,
"Getsockname for netlink socket failed."
);
}
// just 2 sanity checks and we are done
if
(
(
addr_len
!=
sizeof
(
handle
.
local
))
||
(
handle
.
local
.
nl_family
!=
AF_NETLINK
)
)
{
isc_throw
(
Unexpected
,
"getsockname() returned unexpected data for netlink socket."
);
(
handle
.
local
.
nl_family
!=
AF_NETLINK
)
)
{
isc_throw
(
Unexpected
,
"getsockname() returned unexpected data for netlink socket."
);
}
}
// sends request over NETLINK socket
void
rtnl_send_request
(
struct
rtnl_handle
&
handle
,
int
family
,
int
type
)
{
/// @brief Sends request over NETLINK socket.
///
/// @param handle context structure
/// @param family requested information family
/// @param type request type (RTM_GETLINK or RTM_GETADDR)
void
rtnl_send_request
(
struct
rtnl_handle
&
handle
,
int
family
,
int
type
)
{
struct
{
struct
nlmsghdr
nlh
;
struct
rtgenmsg
g
;
struct
nlmsghdr
nlh
;
struct
rtgenmsg
g
;
}
req
;
struct
sockaddr_nl
nladdr
;
memset
(
&
nladdr
,
0
,
sizeof
(
nladdr
));
nladdr
.
nl_family
=
AF_NETLINK
;
memset
(
&
req
,
0
,
sizeof
(
req
));
req
.
nlh
.
nlmsg_len
=
sizeof
(
req
);
req
.
nlh
.
nlmsg_type
=
type
;
...
...
@@ -109,98 +113,95 @@ void rtnl_send_request(struct rtnl_handle& handle,
req
.
nlh
.
nlmsg_pid
=
0
;
req
.
nlh
.
nlmsg_seq
=
handle
.
dump
=
++
handle
.
seq
;
req
.
g
.
rtgen_family
=
family
;
int
status
=
sendto
(
handle
.
fd
,
(
void
*
)
&
req
,
sizeof
(
req
),
0
,
(
struct
sockaddr
*
)
&
nladdr
,
sizeof
(
nladdr
));
(
struct
sockaddr
*
)
&
nladdr
,
sizeof
(
nladdr
));
if
(
status
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to send "
<<
sizeof
(
nladdr
)
<<
" bytes over netlink socket."
);
isc_throw
(
Unexpected
,
"Failed to send "
<<
sizeof
(
nladdr
)
<<
" bytes over netlink socket."
);
}
}
void
rtnl_store_reply
(
/*const struct sockaddr_nl *who,*/
struct
nlmsghdr
*
n
,
struct
nlmsg_list
**
linfo
)
/// @brief Appends nlmsg to a list
///
/// @param n a message to be added
/// @param link_info a list
void
rtnl_store_reply
(
struct
nlmsghdr
*
n
,
struct
nlmsg_list
**
link_info
)
{
struct
nlmsg_list
*
h
;
struct
nlmsg_list
**
lp
;
h
=
(
nlmsg_list
*
)
malloc
(
n
->
nlmsg_len
+
sizeof
(
void
*
));
if
(
h
==
NULL
)
{
isc_throw
(
Unexpected
,
"Failed to allocate "
<<
n
->
nlmsg_len
+
sizeof
(
void
*
)
<<
" bytes."
);
isc_throw
(
Unexpected
,
"Failed to allocate "
<<
n
->
nlmsg_len
+
sizeof
(
void
*
)
<<
" bytes."
);
}
memcpy
(
&
h
->
h
,
n
,
n
->
nlmsg_len
);
h
->
next
=
NULL
;
for
(
lp
=
linfo
;
*
lp
;
lp
=
&
(
*
lp
)
->
next
)
/* NOTHING */
;
for
(
lp
=
l
ink_
info
;
*
lp
;
lp
=
&
(
*
lp
)
->
next
)
/* NOTHING */
;
*
lp
=
h
;
// ll_remember_index(who, n, NULL);
// return 0;
}
void
parse_rtattr
(
struct
rtattr
*
tb
[],
int
max
,
struct
rtattr
*
rta
,
int
len
)
{
memset
(
tb
,
0
,
sizeof
(
struct
rtattr
*
)
*
(
max
+
1
));
while
(
RTA_OK
(
rta
,
len
))
{
if
(
rta
->
rta_type
<=
max
)
tb
[
rta
->
rta_type
]
=
rta
;
rta
=
RTA_NEXT
(
rta
,
len
);
if
(
rta
->
rta_type
<=
max
)
tb
[
rta
->
rta_type
]
=
rta
;
rta
=
RTA_NEXT
(
rta
,
len
);
}
if
(
len
)
{
isc_throw
(
Unexpected
,
"Failed to parse RTATTR in netlink message."
);
isc_throw
(
Unexpected
,
"Failed to parse RTATTR in netlink message."
);
}
}
void
ipaddrs_get
(
IfaceMgr
::
Iface
&
iface
,
struct
nlmsg_list
*
ainfo
)
{
void
ipaddrs_get
(
IfaceMgr
::
Iface
&
iface
,
struct
nlmsg_list
*
addr_info
)
{
uint8_t
addr
[
16
];
struct
rtattr
*
rta_tb
[
IFA_MAX
+
1
];
for
(
;
ainfo
;
ainfo
=
ainfo
->
next
)
{
struct
nlmsghdr
*
n
=
&
ainfo
->
h
;
struct
ifaddrmsg
*
ifa
=
(
ifaddrmsg
*
)
NLMSG_DATA
(
n
);
// these are not the addresses you are looking for
if
(
ifa
->
ifa_index
!=
iface
.
ifindex_
)
{
continue
;
}
if
(
ifa
->
ifa_family
==
AF_INET6
)
{
memset
(
rta_tb
,
0
,
sizeof
(
rta_tb
));
parse_rtattr
(
rta_tb
,
IFA_MAX
,
IFA_RTA
(
ifa
),
n
->
nlmsg_len
-
NLMSG_LENGTH
(
sizeof
(
*
ifa
)));
if
(
!
rta_tb
[
IFA_LOCAL
])
rta_tb
[
IFA_LOCAL
]
=
rta_tb
[
IFA_ADDRESS
];
if
(
!
rta_tb
[
IFA_ADDRESS
])
rta_tb
[
IFA_ADDRESS
]
=
rta_tb
[
IFA_LOCAL
];
memcpy
(
addr
,(
char
*
)
RTA_DATA
(
rta_tb
[
IFLA_ADDRESS
]),
16
);
IOAddress
a
=
IOAddress
::
from_bytes
(
AF_INET6
,
addr
);
iface
.
addrs_
.
push_back
(
a
);
/// TODO: Read lifetimes of configured addresses
}
if
(
ifa
->
ifa_family
==
AF_INET
)
{
memset
(
rta_tb
,
0
,
sizeof
(
rta_tb
));
parse_rtattr
(
rta_tb
,
IFA_MAX
,
IFA_RTA
(
ifa
),
n
->
nlmsg_len
-
NLMSG_LENGTH
(
sizeof
(
*
ifa
)));
if
(
!
rta_tb
[
IFA_LOCAL
])
rta_tb
[
IFA_LOCAL
]
=
rta_tb
[
IFA_ADDRESS
];
if
(
!
rta_tb
[
IFA_ADDRESS
])
rta_tb
[
IFA_ADDRESS
]
=
rta_tb
[
IFA_LOCAL
];
memcpy
(
addr
,(
char
*
)
RTA_DATA
(
rta_tb
[
IFLA_ADDRESS
]),
4
);
IOAddress
a
=
IOAddress
::
from_bytes
(
AF_INET
,
addr
);
iface
.
addrs_
.
push_back
(
a
);
}
for
(
;
addr_info
;
addr_info
=
addr_info
->
next
)
{
struct
nlmsghdr
*
n
=
&
addr_info
->
h
;
struct
ifaddrmsg
*
ifa
=
(
ifaddrmsg
*
)
NLMSG_DATA
(
n
);
// these are not the addresses you are looking for
if
(
ifa
->
ifa_index
!=
iface
.
ifindex_
)
{
continue
;
}
if
(
ifa
->
ifa_family
==
AF_INET6
)
{
memset
(
rta_tb
,
0
,
sizeof
(
rta_tb
));
parse_rtattr
(
rta_tb
,
IFA_MAX
,
IFA_RTA
(
ifa
),
n
->
nlmsg_len
-
NLMSG_LENGTH
(
sizeof
(
*
ifa
)));
if
(
!
rta_tb
[
IFA_LOCAL
])
rta_tb
[
IFA_LOCAL
]
=
rta_tb
[
IFA_ADDRESS
];
if
(
!
rta_tb
[
IFA_ADDRESS
])
rta_tb
[
IFA_ADDRESS
]
=
rta_tb
[
IFA_LOCAL
];
memcpy
(
addr
,(
char
*
)
RTA_DATA
(
rta_tb
[
IFLA_ADDRESS
]),
16
);
IOAddress
a
=
IOAddress
::
from_bytes
(
AF_INET6
,
addr
);
iface
.
addrs_
.
push_back
(
a
);
/// TODO: Read lifetimes of configured addresses
}
if
(
ifa
->
ifa_family
==
AF_INET
)
{
memset
(
rta_tb
,
0
,
sizeof
(
rta_tb
));
parse_rtattr
(
rta_tb
,
IFA_MAX
,
IFA_RTA
(
ifa
),
n
->
nlmsg_len
-
NLMSG_LENGTH
(
sizeof
(
*
ifa
)));
if
(
!
rta_tb
[
IFA_LOCAL
])
rta_tb
[
IFA_LOCAL
]
=
rta_tb
[
IFA_ADDRESS
];
if
(
!
rta_tb
[
IFA_ADDRESS
])
rta_tb
[
IFA_ADDRESS
]
=
rta_tb
[
IFA_LOCAL
];
memcpy
(
addr
,(
char
*
)
RTA_DATA
(
rta_tb
[
IFLA_ADDRESS
]),
4
);
IOAddress
a
=
IOAddress
::
from_bytes
(
AF_INET
,
addr
);
iface
.
addrs_
.
push_back
(
a
);
}
}
}
void
rtnl_process_reply
(
struct
rtnl_handle
&
rth
,
struct
nlmsg_list
*&
info
)
{
void
rtnl_process_reply
(
struct
rtnl_handle
&
rth
,
struct
nlmsg_list
*&
info
)
{
struct
sockaddr_nl
nladdr
;
struct
iovec
iov
;
...
...
@@ -212,91 +213,91 @@ void rtnl_process_reply(struct rtnl_handle &rth,
msg
.
msg_iovlen
=
1
;
char
buf
[
rcvbuf
];
iov
.
iov_base
=
buf
;
while
(
1
)
{
int
status
;
struct
nlmsghdr
*
h
;
iov
.
iov_len
=
sizeof
(
buf
);
status
=
recvmsg
(
rth
.
fd
,
&
msg
,
0
);
if
(
status
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
isc_throw
(
Unexpected
,
"Overrun while processing reply from netlink socket."
);
}
if
(
status
==
0
)
{
isc_throw
(
Unexpected
,
"EOF while reading netlink socket."
);
}
h
=
(
struct
nlmsghdr
*
)
buf
;
while
(
NLMSG_OK
(
h
,
status
))
{
// why we received this anyway?
if
(
nladdr
.
nl_pid
!=
0
||
h
->
nlmsg_pid
!=
rth
.
local
.
nl_pid
||
h
->
nlmsg_seq
!=
rth
.
dump
)
{
h
=
NLMSG_NEXT
(
h
,
status
);
continue
;
}
if
(
h
->
nlmsg_type
==
NLMSG_DONE
)
{
// end of message
return
;
}
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
struct
nlmsgerr
*
err
=
(
struct
nlmsgerr
*
)
NLMSG_DATA
(
h
);
if
(
h
->
nlmsg_len
<
NLMSG_LENGTH
(
sizeof
(
struct
nlmsgerr
)))
{
// we are really out of luck here. We can't even say what is
// wrong as error message is truncated. D'oh.
isc_throw
(
Unexpected
,
"Netlink reply read failed."
);
}
else
{
isc_throw
(
Unexpected
,
"Netlink reply read error "
<<
-
err
->
error
);
}
// never happens we throw before we reach here
return
;
}
// store the data
rtnl_store_reply
(
/*&nladdr,*/
h
,
&
info
);
h
=
NLMSG_NEXT
(
h
,
status
);
}
if
(
msg
.
msg_flags
&
MSG_TRUNC
)
{
isc_throw
(
Unexpected
,
"Message received over netlink truncated."
);
}
if
(
status
)
{
isc_throw
(
Unexpected
,
"Trailing garbage of "
<<
status
<<
" bytes received over netlink."
);
}
int
status
;
struct
nlmsghdr
*
h
;
iov
.
iov_len
=
sizeof
(
buf
);
status
=
recvmsg
(
rth
.
fd
,
&
msg
,
0
);
if
(
status
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
isc_throw
(
Unexpected
,
"Overrun while processing reply from netlink socket."
);
}
if
(
status
==
0
)
{
isc_throw
(
Unexpected
,
"EOF while reading netlink socket."
);
}
h
=
(
struct
nlmsghdr
*
)
buf
;
while
(
NLMSG_OK
(
h
,
status
))
{
// why we received this anyway?
if
(
nladdr
.
nl_pid
!=
0
||
h
->
nlmsg_pid
!=
rth
.
local
.
nl_pid
||
h
->
nlmsg_seq
!=
rth
.
dump
)
{
h
=
NLMSG_NEXT
(
h
,
status
);
continue
;
}
if
(
h
->
nlmsg_type
==
NLMSG_DONE
)
{
// end of message
return
;
}
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
struct
nlmsgerr
*
err
=
(
struct
nlmsgerr
*
)
NLMSG_DATA
(
h
);
if
(
h
->
nlmsg_len
<
NLMSG_LENGTH
(
sizeof
(
struct
nlmsgerr
)))
{
// we are really out of luck here. We can't even say what is
// wrong as error message is truncated. D'oh.
isc_throw
(
Unexpected
,
"Netlink reply read failed."
);
}
else
{
isc_throw
(
Unexpected
,
"Netlink reply read error "
<<
-
err
->
error
);
}
// never happens we throw before we reach here
return
;
}
// store the data
rtnl_store_reply
(
h
,
&
info
);
h
=
NLMSG_NEXT
(
h
,
status
);
}
if
(
msg
.
msg_flags
&
MSG_TRUNC
)
{
isc_throw
(
Unexpected
,
"Message received over netlink truncated."
);
}
if
(
status
)
{
isc_throw
(
Unexpected
,
"Trailing garbage of "
<<
status
<<
" bytes received over netlink."
);
}
}
}
void
release_list
(
struct
nlmsg_list
*
n
)
{
/// @brief releases nlmsg list
///
/// @param head first element of the list to be released
void
release_list
(
struct
nlmsg_list
*
head
)
{
struct
nlmsg_list
*
tmp
;
while
(
n
)
{
tmp
=
n
->
next
;
free
(
n
);
n
=
tmp
;
while
(
head
)
{
tmp
=
head
->
next
;
free
(
head
);
head
=
tmp
;
}
}
void
IfaceMgr
::
detectIfaces
()
{
void
IfaceMgr
::
detectIfaces
()
{
cout
<<
"Linux: detecting interfaces."
<<
endl
;
struct
nlmsg_list
*
l
info
=
NULL
;
struct
nlmsg_list
*
a
info
=
NULL
;
struct
nlmsg_list
*
l
=
NULL
;
struct
nlmsg_list
*
link_
info
=
NULL
;
// link info list
struct
nlmsg_list
*
addr_
info
=
NULL
;
// address info list
struct
nlmsg_list
*
l
=
NULL
;
struct
rtnl_handle
rth
;
/
*
required to display information about interface
*/
struct
ifinfomsg
*
ifi
=
NULL
;
struct
rtattr
*
tb
[
IFLA_MAX
+
1
];
/
/
required to display information about interface
struct
ifinfomsg
*
ifi
=
NULL
;
struct
rtattr
*
tb
[
IFLA_MAX
+
1
];
int
len
=
0
;
memset
(
tb
,
0
,
sizeof
(
tb
));
memset
(
&
rth
,
0
,
sizeof
(
rth
));
...
...
@@ -305,60 +306,66 @@ IfaceMgr::detectIfaces() {
rtnl_open_socket
(
rth
);
// now we have open functional socket, let's use it!
// ask for list of interface...
rtnl_send_request
(
rth
,
AF_PACKET
,
RTM_GETLINK
);
// process reply
rtnl_process_reply
(
rth
,
linfo
);
//rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL);
/* 2nd attribute: AF_UNSPEC, AF_INET, AF_INET6 */
// Get reply and store it in link_info list.
rtnl_process_reply
(
rth
,
link_info
);
// Now ask for list of addresses (AF_UNSPEC = of any family)
rtnl_send_request
(
rth
,
AF_UNSPEC
,
RTM_GETADDR
);
rtnl_process_reply
(
rth
,
ainfo
);
/* build list with interface names */
for
(
l
=
linfo
;
l
;
l
=
l
->
next
)
{
ifi
=
(
ifinfomsg
*
)
NLMSG_DATA
(
&
l
->
h
);
len
=
(
&
l
->
h
)
->
nlmsg_len
;
len
-=
NLMSG_LENGTH
(
sizeof
(
*
ifi
));
parse_rtattr
(
tb
,
IFLA_MAX
,
IFLA_RTA
(
ifi
),
len
);
Iface
*
iface
=
new
Iface
(
string
(
(
char
*
)
RTA_DATA
(
tb
[
IFLA_IFNAME
])),
ifi
->
ifi_index
);
iface
->
hardware_type_
=
ifi
->
ifi_type
;
iface
->
setFlags
(
ifi
->
ifi_flags
);
iface
->
mac_len_
=
0
;
memset
(
iface
->
mac_
,
0
,
IfaceMgr
::
MAX_MAC_LEN
);
/* Does inetface has LL_ADDR? */
if
(
tb
[
IFLA_ADDRESS
])
{
iface
->
mac_len_
=
RTA_PAYLOAD
(
tb
[
IFLA_ADDRESS
]);
if
(
iface
->
mac_len_
>
IfaceMgr
::
MAX_MAC_LEN
)
{
iface
->
mac_len_
=
0
;
isc_throw
(
Unexpected
,
"Interface "
<<
iface
->
getFullName
()
<<
" was detected to have link address of length "
<<
RTA_PAYLOAD
(
tb
[
IFLA_ADDRESS
])
<<
", but maximum supported length is "
<<
IfaceMgr
::
MAX_MAC_LEN
);
}
memcpy
(
iface
->
mac_
,
RTA_DATA
(
tb
[
IFLA_ADDRESS
]),
iface
->
mac_len_
);
}
else
{
/* Tunnels can have no LL_ADDR. RTA_PAYLOAD doesn't check it and try to
* dereference it in this manner
* #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
*/
iface
->
mac_len_
=
0
;
}
ipaddrs_get
(
*
iface
,
ainfo
);
ifaces_
.
push_back
(
*
iface
);
}
// Get reply and store it in addr_info list.
rtnl_process_reply
(
rth
,
addr_info
);
// Now build list with interface names
for
(
l
=
link_info
;
l
;
l
=
l
->
next
)
{
ifi
=
(
ifinfomsg
*
)
NLMSG_DATA
(
&
l
->
h
);
len
=
(
&
l
->
h
)
->
nlmsg_len
;
len
-=
NLMSG_LENGTH
(
sizeof
(
*
ifi
));
parse_rtattr
(
tb
,
IFLA_MAX
,
IFLA_RTA
(
ifi
),
len
);
Iface
*
iface
=
new
Iface
(
string
(
(
char
*
)
RTA_DATA
(
tb
[
IFLA_IFNAME
])),
ifi
->
ifi_index
);
iface
->
hardware_type_
=
ifi
->
ifi_type
;
iface
->
setFlags
(
ifi
->
ifi_flags
);
iface
->
mac_len_
=
0
;
memset
(
iface
->
mac_
,
0
,
IfaceMgr
::
MAX_MAC_LEN
);
// Does inetface has LL_ADDR?
if
(
tb
[
IFLA_ADDRESS
])
{
iface
->
mac_len_
=
RTA_PAYLOAD
(
tb
[
IFLA_ADDRESS
]);
if
(
iface
->
mac_len_
>
IfaceMgr
::
MAX_MAC_LEN
)
{
iface
->
mac_len_
=
0
;
isc_throw
(
Unexpected
,
"Interface "
<<
iface
->
getFullName
()
<<
" was detected to have link address of length "
<<
RTA_PAYLOAD
(
tb
[
IFLA_ADDRESS
])
<<
", but maximum supported length is "
<<
IfaceMgr
::
MAX_MAC_LEN
);
}
memcpy
(
iface
->
mac_
,
RTA_DATA
(
tb
[
IFLA_ADDRESS
]),
iface
->
mac_len_
);
}
else
{
// Tunnels can have no LL_ADDR. RTA_PAYLOAD doesn't check it and try to
// dereference it in this manner