blob: c212ecde738616232294c295ce3b260649b35e15 [file] [log] [blame]
susmit91e1d7c2016-10-03 16:16:57 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2760adc2017-07-06 05:44:52 +00002/*
Junxiao Shi7003c602017-01-10 13:35:28 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
susmit91e1d7c2016-10-03 16:16:57 -06004 * 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"
susmit91e1d7c2016-10-03 16:16:57 -060029#include "network.hpp"
30
susmit21f22e62017-03-25 15:44:45 -050031#include <fnmatch.h>
32
susmit91e1d7c2016-10-03 16:16:57 -060033namespace nfd {
34
35NetworkInterfacePredicate::NetworkInterfacePredicate()
36{
37 this->clear();
38}
39
40void
41NetworkInterfacePredicate::clear()
42{
43 m_whitelist = std::set<std::string>{"*"};
44 m_blacklist.clear();
45}
46
47static void
48parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section)
49{
50 set.clear();
51
52 for (const auto& item : list) {
53 if (item.first == "*") {
54 // insert wildcard
55 set.insert(item.first);
56 }
57 else if (item.first == "ifname") {
58 // very basic sanity check for interface names
59 auto name = item.second.get_value<std::string>();
60 if (name.empty()) {
61 BOOST_THROW_EXCEPTION(ConfigFile::Error("Empty interface name in \"" + section + "\" section"));
62 }
63 set.insert(name);
64 }
65 else if (item.first == "ether") {
66 // validate ethernet address
67 auto addr = item.second.get_value<std::string>();
Junxiao Shia5765d62017-08-09 04:07:46 +000068 if (ndn::ethernet::Address::fromString(addr).isNull()) {
susmit91e1d7c2016-10-03 16:16:57 -060069 BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed ether address \"" + addr +
70 "\" in \"" + section + "\" section"));
71 }
72 set.insert(addr);
73 }
74 else if (item.first == "subnet") {
75 // example subnet: 10.0.0.0/8
76 auto cidr = item.second.get_value<std::string>();
77 if (!Network::isValidCidr(cidr)) {
78 BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed subnet declaration \"" + cidr +
79 "\" in \"" + section + "\" section"));
80 }
81 set.insert(cidr);
82 }
83 }
84}
85
86void
87NetworkInterfacePredicate::parseWhitelist(const boost::property_tree::ptree& list)
88{
89 parseList(m_whitelist, list, "whitelist");
90}
91
92void
93NetworkInterfacePredicate::parseBlacklist(const boost::property_tree::ptree& list)
94{
95 parseList(m_blacklist, list, "blacklist");
96}
97
98static bool
susmit21f22e62017-03-25 15:44:45 -050099doesMatchPattern(const std::string& ifname, const std::string& pattern)
100{
101 // use fnmatch(3) to provide unix glob-style matching for interface names
102 // fnmatch returns 0 if there is a match
103 return ::fnmatch(pattern.data(), ifname.data(), 0) == 0;
104}
105
106static bool
Junxiao Shia5765d62017-08-09 04:07:46 +0000107doesMatchRule(const ndn::net::NetworkInterface& netif, const std::string& rule)
Junxiao Shi2760adc2017-07-06 05:44:52 +0000108{
109 // if '/' is in rule, this is a subnet, check if IP in subnet
110 if (rule.find('/') != std::string::npos) {
111 Network n = boost::lexical_cast<Network>(rule);
112 for (const auto& addr : netif.getNetworkAddresses()) {
113 if (n.doesContain(addr.getIp())) {
114 return true;
115 }
116 }
117 }
118
119 return rule == "*" ||
120 doesMatchPattern(netif.getName(), rule) ||
121 netif.getEthernetAddress().toString() == rule;
122}
123
susmit91e1d7c2016-10-03 16:16:57 -0600124bool
Junxiao Shi2760adc2017-07-06 05:44:52 +0000125NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
126{
Junxiao Shia5765d62017-08-09 04:07:46 +0000127 return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesMatchRule, cref(netif), _1)) &&
128 std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesMatchRule, cref(netif), _1));
Junxiao Shi2760adc2017-07-06 05:44:52 +0000129}
130
131bool
Junxiao Shi7003c602017-01-10 13:35:28 +0000132NetworkInterfacePredicate::operator==(const NetworkInterfacePredicate& other) const
133{
134 return this->m_whitelist == other.m_whitelist &&
135 this->m_blacklist == other.m_blacklist;
susmit91e1d7c2016-10-03 16:16:57 -0600136}
137
138} // namespace nfd