10 #include "ace/config.h" 14 #ifdef OPENDDS_LINUX_NETWORK_CONFIG_MONITOR 21 #include <linux/rtnetlink.h> 29 const size_t MAX_NETLINK_MESSAGE_SIZE = 4096;
32 : interceptor_(interceptor)
34 reactor(interceptor->reactor());
37 bool LinuxNetworkConfigMonitor::open()
44 RcHandle<OpenHandler> oh = make_rch<OpenHandler>(
rchandle_from(
this));
49 bool LinuxNetworkConfigMonitor::OpenHandler::wait()
const 58 void LinuxNetworkConfigMonitor::OpenHandler::execute()
60 RcHandle<LinuxNetworkConfigMonitor> lncm = lncm_.lock();
65 retval_ = lncm->open_i();
67 condition_.notify_all();
70 bool LinuxNetworkConfigMonitor::open_i()
76 ACE_Netlink_Addr addr;
77 addr.set(pid, RTMGRP_NOTIFY | RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR);
78 if (socket_.open(addr, AF_NETLINK, NETLINK_ROUTE) != 0) {
81 ACE_ERROR((LM_WARNING,
"(%P|%t) WARNING: LinuxNetworkConfigMonitor::open_i: could not open socket" 82 " this is expected for API30+\n"));
86 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::open_i: could not open socket: %m\n"));
92 if (socket_.enable(ACE_NONBLOCK) != 0) {
94 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::open_i: could not set non-blocking: %m\n"));
103 memset(&request, 0,
sizeof(request));
106 request.header.nlmsg_len = NLMSG_LENGTH(
sizeof(request.msg));
107 request.header.nlmsg_type = RTM_GETLINK;
108 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
109 request.header.nlmsg_pid = pid;
112 if (socket_.send(&request, request.header.nlmsg_len, 0) !=
static_cast<ssize_t>(request.header.nlmsg_len)) {
114 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::open_i: could not send request for links: %m\n"));
122 request.header.nlmsg_len = NLMSG_LENGTH(
sizeof(request.msg));
123 request.header.nlmsg_type = RTM_GETADDR;
124 request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
125 request.header.nlmsg_pid = pid;
128 if (socket_.send(&request, request.header.nlmsg_len, 0) !=
static_cast<ssize_t>(request.header.nlmsg_len)) {
130 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::open_i: could not send request for addresses: %m\n"));
137 if (reactor()->register_handler(
this, READ_MASK) != 0) {
138 ACE_ERROR((LM_ERROR,
ACE_TEXT(
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::open_i: could not register for input: %m\n")));
144 bool LinuxNetworkConfigMonitor::close()
151 RcHandle<CloseHandler> ch = make_rch<CloseHandler>(
rchandle_from(
this));
156 bool LinuxNetworkConfigMonitor::CloseHandler::wait()
const 165 void LinuxNetworkConfigMonitor::CloseHandler::execute()
167 RcHandle<LinuxNetworkConfigMonitor> lncm = lncm_.lock();
172 retval_ = lncm->close_i();
174 condition_.notify_all();
177 bool LinuxNetworkConfigMonitor::close_i()
180 reactor()->remove_handler(
this, READ_MASK);
182 if (socket_.close() != 0) {
184 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::close_i: could not close socket: %m\n"));
193 ACE_HANDLE LinuxNetworkConfigMonitor::get_handle()
const 195 return socket_.get_handle();
198 int LinuxNetworkConfigMonitor::handle_input(ACE_HANDLE)
207 void LinuxNetworkConfigMonitor::read_messages()
209 char buffer[MAX_NETLINK_MESSAGE_SIZE];
214 if (socket_.get_handle() == -1) {
217 buffer_length = socket_.recv(buffer, 4096, 0);
219 if (buffer_length < 0) {
220 if (errno == EAGAIN || errno == EWOULDBLOCK) {
224 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::read_messages: could not recv: %m\n"));
227 }
else if (buffer_length == 0) {
231 for (
const nlmsghdr*
header = reinterpret_cast<const nlmsghdr*>(buffer);
232 buffer_length >= 0 && NLMSG_OK(
header, static_cast<size_t>(buffer_length));
239 void LinuxNetworkConfigMonitor::process_message(
const nlmsghdr*
header)
241 switch (header->nlmsg_type) {
244 const nlmsgerr* msg =
reinterpret_cast<nlmsgerr*
>(NLMSG_DATA(header));
246 ACE_ERROR((LM_ERROR,
"(%P|%t) ERROR: LinuxNetworkConfigMonitor::process_message: NETLINK error: %C\n",
strerror(-msg->error)));
252 const ifaddrmsg* msg =
reinterpret_cast<ifaddrmsg*
>(NLMSG_DATA(header));
253 size_t address_length = 0;
254 switch (msg->ifa_family) {
264 int rta_length = IFA_PAYLOAD(header);
265 for (
const rtattr* attr = reinterpret_cast<const rtattr*>(IFA_RTA(msg));
266 RTA_OK(attr, rta_length);
267 attr = RTA_NEXT(attr, rta_length)) {
268 if (attr->rta_type == IFA_ADDRESS) {
269 if (RTA_PAYLOAD(attr) != address_length) {
271 ACE_ERROR((LM_WARNING,
"(%P|%t) WARNING: LinuxNetworkConfigMonitor::process_message: incorrect address byte count\n"));
276 addr.
set_address(reinterpret_cast<const char*>(RTA_DATA(attr)), address_length, 0);
277 NetworkInterfaceMap::const_iterator pos = network_interface_map_.find(msg->ifa_index);
278 if (pos != network_interface_map_.end()) {
279 set(NetworkInterfaceAddress(pos->second.name, pos->second.can_multicast, NetworkAddress(addr)));
280 }
else if (
log_level >= LogLevel::Warning) {
281 ACE_ERROR((LM_WARNING,
"(%P|%t) WARNING: LinuxNetworkConfigMonitor::process_message: cannot find interface for address\n"));
289 const ifaddrmsg* msg =
reinterpret_cast<ifaddrmsg*
>(NLMSG_DATA(header));
290 size_t address_length = 0;
291 switch (msg->ifa_family) {
301 int rta_length = IFA_PAYLOAD(header);
302 for (
const rtattr* attr = reinterpret_cast<const rtattr*>(IFA_RTA(msg));
303 RTA_OK(attr, rta_length);
304 attr = RTA_NEXT(attr, rta_length)) {
305 if (attr->rta_type == IFA_ADDRESS) {
306 if (RTA_PAYLOAD(attr) != address_length) {
308 ACE_ERROR((LM_WARNING,
"(%P|%t) WARNING: LinuxNetworkConfigMonitor::process_message: incorrect address byte count\n"));
313 NetworkInterfaceMap::iterator pos = network_interface_map_.find(msg->ifa_index);
314 if (pos != network_interface_map_.end()) {
316 addr.
set_address(reinterpret_cast<const char*>(RTA_DATA(attr)), address_length, 0);
317 remove_address(pos->second.name, NetworkAddress(addr));
326 const ifinfomsg* msg =
reinterpret_cast<ifinfomsg*
>(NLMSG_DATA(header));
327 int rta_length = IFLA_PAYLOAD(header);
328 for (
const rtattr* attr = reinterpret_cast<const rtattr*>(IFLA_RTA(msg));
329 RTA_OK(attr, rta_length);
330 attr = RTA_NEXT(attr, rta_length)) {
331 if (attr->rta_type == IFLA_IFNAME) {
332 name =
reinterpret_cast<const char*
>(RTA_DATA(attr));
337 NetworkInterfaceMap::iterator pos = network_interface_map_.find(msg->ifi_index);
338 if (pos != network_interface_map_.end()) {
339 remove_interface(pos->second.name);
340 network_interface_map_.erase(pos);
342 network_interface_map_[msg->ifi_index] = NetworkInterface(name, msg->ifi_flags & (IFF_MULTICAST | IFF_LOOPBACK));
347 const ifinfomsg* msg =
reinterpret_cast<ifinfomsg*
>(NLMSG_DATA(header));
348 NetworkInterfaceMap::iterator pos = network_interface_map_.find(msg->ifi_index);
349 if (pos != network_interface_map_.end()) {
350 remove_interface(pos->second.name);
351 network_interface_map_.erase(pos);
363 #endif // OPENDDS_LINUX_NETWORK_CONFIG_MONITOR RcHandle< T > rchandle_from(T *pointer)
#define ACE_GUARD(MUTEX, OBJ, LOCK)
char * strerror(int errnum)
CommandPtr execute_or_enqueue(CommandPtr command)
Christopher Diggins *renamed files *fixing compilation errors *adding Visual C project file *removed make Max Lybbert *removed references to missing and unused header
#define ACE_GUARD_RETURN(MUTEX, OBJ, LOCK, RETURN)
int set_address(const char *ip_addr, int len, int encode=1, int map=0)
OpenDDS_Dcps_Export LogLevel log_level
RcHandle< ReactorInterceptor > ReactorInterceptor_rch
void * memset(void *s, int c, size_t len)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
#define TheServiceParticipant
The Internal API and Implementation of OpenDDS.