blob: 36c9190da70b06e6c004f7d7244af85419488b05 [file] [log] [blame]
Davide Pesavento9a8bae52016-02-24 20:33:08 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "ndn-cxx-config.hpp"
23
24#ifdef NDN_CXX_HAVE_RTNETLINK
25
26#include "network-monitor-impl-rtnl.hpp"
27
28#include <netinet/in.h>
29#include <linux/netlink.h>
30#include <linux/rtnetlink.h>
31#include <net/if.h>
32
33#include <cerrno>
34#include <cstring>
35
36namespace ndn {
37namespace util {
38
39NetworkMonitor::Impl::Impl(NetworkMonitor& nm, boost::asio::io_service& io)
40 : m_nm(nm)
41 , m_socket(io)
42{
43 int fd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
44 if (fd < 0)
45 BOOST_THROW_EXCEPTION(Error(std::string("Cannot create netlink socket (") +
46 std::strerror(errno) + ")"));
47
48 sockaddr_nl addr{};
49 addr.nl_family = AF_NETLINK;
50 addr.nl_groups = RTMGRP_LINK |
51 RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
52 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
53
54 if (::bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
55 BOOST_THROW_EXCEPTION(Error(std::string("Cannot bind on netlink socket (") +
56 std::strerror(errno) + ")"));
57 }
58
59 m_socket.assign(fd);
60
61 m_socket.async_read_some(boost::asio::buffer(m_buffer, NETLINK_BUFFER_SIZE),
62 bind(&Impl::onReceiveRtNetlink, this, _1, _2));
63}
64
65void
66NetworkMonitor::Impl::onReceiveRtNetlink(const boost::system::error_code& error, size_t nBytesReceived)
67{
68 if (error) {
69 return;
70 }
71
72 const nlmsghdr* nlh = reinterpret_cast<const nlmsghdr*>(m_buffer);
73 while ((NLMSG_OK(nlh, nBytesReceived)) && (nlh->nlmsg_type != NLMSG_DONE)) {
74 if (nlh->nlmsg_type == RTM_NEWADDR || nlh->nlmsg_type == RTM_DELADDR ||
75 nlh->nlmsg_type == RTM_NEWLINK || nlh->nlmsg_type == RTM_DELLINK ||
76 nlh->nlmsg_type == RTM_NEWROUTE || nlh->nlmsg_type == RTM_DELROUTE) {
77 m_nm.onNetworkStateChanged();
78 break;
79 }
80 nlh = NLMSG_NEXT(nlh, nBytesReceived);
81 }
82
83 m_socket.async_read_some(boost::asio::buffer(m_buffer, NETLINK_BUFFER_SIZE),
84 bind(&Impl::onReceiveRtNetlink, this, _1, _2));
85}
86
87} // namespace util
88} // namespace ndn
89
90#endif // NDN_CXX_HAVE_RTNETLINK