blob: abb00293f363492321a359f1c31bed94301220a3 [file] [log] [blame]
susmit91e1d7c2016-10-03 16:16:57 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2016, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "network-interface-predicate.hpp"
27
28#include "config-file.hpp"
29#include "network-interface.hpp"
30#include "network.hpp"
31
32namespace nfd {
33
34NetworkInterfacePredicate::NetworkInterfacePredicate()
35{
36 this->clear();
37}
38
39void
40NetworkInterfacePredicate::clear()
41{
42 m_whitelist = std::set<std::string>{"*"};
43 m_blacklist.clear();
44}
45
46static void
47parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section)
48{
49 set.clear();
50
51 for (const auto& item : list) {
52 if (item.first == "*") {
53 // insert wildcard
54 set.insert(item.first);
55 }
56 else if (item.first == "ifname") {
57 // very basic sanity check for interface names
58 auto name = item.second.get_value<std::string>();
59 if (name.empty()) {
60 BOOST_THROW_EXCEPTION(ConfigFile::Error("Empty interface name in \"" + section + "\" section"));
61 }
62 set.insert(name);
63 }
64 else if (item.first == "ether") {
65 // validate ethernet address
66 auto addr = item.second.get_value<std::string>();
67 if (ethernet::Address::fromString(addr).isNull()) {
68 BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed ether address \"" + addr +
69 "\" in \"" + section + "\" section"));
70 }
71 set.insert(addr);
72 }
73 else if (item.first == "subnet") {
74 // example subnet: 10.0.0.0/8
75 auto cidr = item.second.get_value<std::string>();
76 if (!Network::isValidCidr(cidr)) {
77 BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed subnet declaration \"" + cidr +
78 "\" in \"" + section + "\" section"));
79 }
80 set.insert(cidr);
81 }
82 }
83}
84
85void
86NetworkInterfacePredicate::parseWhitelist(const boost::property_tree::ptree& list)
87{
88 parseList(m_whitelist, list, "whitelist");
89}
90
91void
92NetworkInterfacePredicate::parseBlacklist(const boost::property_tree::ptree& list)
93{
94 parseList(m_blacklist, list, "blacklist");
95}
96
97static bool
98doesMatchRule(const NetworkInterfaceInfo& nic, const std::string& rule)
99{
100 // if / is in rule, this is a subnet, check if IP in subnet
101
102 if (boost::contains(rule, "/")) {
103 Network n = boost::lexical_cast<Network>(rule);
104 for (const auto& addr : nic.ipv4Addresses) {
105 if (n.doesContain(addr)) {
106 return true;
107 }
108 }
109 }
110
111 return rule == "*" ||
112 nic.name == rule ||
113 nic.etherAddress.toString() == rule;
114}
115
116bool
117NetworkInterfacePredicate::operator()(const NetworkInterfaceInfo& nic) const
118{
119 return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesMatchRule, nic, _1)) &&
120 std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesMatchRule, nic, _1));
121}
122
123} // namespace nfd