core: enable wildcard matching on interface names for whitelist/blacklist
Change-Id: Iabf5084028d7e8c4a26ec5289c331f4a779c0bf7
Refs: #4009
diff --git a/core/network-interface-predicate.cpp b/core/network-interface-predicate.cpp
index 9c1bb11..81f199b 100644
--- a/core/network-interface-predicate.cpp
+++ b/core/network-interface-predicate.cpp
@@ -29,6 +29,8 @@
#include "network-interface.hpp"
#include "network.hpp"
+#include <fnmatch.h>
+
namespace nfd {
NetworkInterfacePredicate::NetworkInterfacePredicate()
@@ -95,6 +97,14 @@
}
static bool
+doesMatchPattern(const std::string& ifname, const std::string& pattern)
+{
+ // use fnmatch(3) to provide unix glob-style matching for interface names
+ // fnmatch returns 0 if there is a match
+ return ::fnmatch(pattern.data(), ifname.data(), 0) == 0;
+}
+
+static bool
doesMatchRule(const NetworkInterfaceInfo& netif, const std::string& rule)
{
// if '/' is in rule, this is a subnet, check if IP in subnet
@@ -108,7 +118,7 @@
}
return rule == "*" ||
- netif.name == rule ||
+ doesMatchPattern(netif.name, rule) ||
netif.etherAddress.toString() == rule;
}
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 819e038..fe3efef 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -44,7 +44,6 @@
; The tables section configures the CS, PIT, FIB, Strategy Choice, and Measurements
tables
{
-
; ContentStore size limit in number of packets
; default is 65536, about 500MB with 8KB packet size
cs_max_packets 65536
@@ -118,7 +117,7 @@
keep_alive_interval 25; interval (seconds) between keep-alive refreshes
; UDP multicast settings
- ; NFD creates one UDP multicast face per NIC
+ ; By default, NFD creates one UDP multicast face per NIC
;
; In multi-homed Linux machines these settings will NOT work without
; root or settings the appropriate permissions:
@@ -130,11 +129,10 @@
mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
; Whitelist and blacklist can contain, in no particular order:
- ; interface names (e.g., ifname eth0),
- ; mac addresses (e.g., ether 85:3b:4d:d3:5f:c2),
- ; subnets (e.g., subnet 192.0.2.0/24, note that only IPv4 is supported here),
- ; or a wildcard (*) that matches all interfaces.
-
+ ; interface names, including wildcard patterns (e.g., 'ifname eth0', 'ifname en*', 'ifname wlp?s0'),
+ ; mac addresses (e.g., 'ether 85:3b:4d:d3:5f:c2'),
+ ; subnets (e.g., 'subnet 192.0.2.0/24', note that only IPv4 is supported here),
+ ; or a single asterisk ('*') that matches all interfaces.
whitelist
{
*
@@ -170,17 +168,16 @@
@IF_HAVE_LIBPCAP@ether
@IF_HAVE_LIBPCAP@{
@IF_HAVE_LIBPCAP@ ; Ethernet multicast settings
- @IF_HAVE_LIBPCAP@ ; NFD creates one Ethernet multicast face per NIC
+ @IF_HAVE_LIBPCAP@ ; By default, NFD creates one Ethernet multicast face per NIC
@IF_HAVE_LIBPCAP@
@IF_HAVE_LIBPCAP@ mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
@IF_HAVE_LIBPCAP@ mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
@IF_HAVE_LIBPCAP@
@IF_HAVE_LIBPCAP@ ; Whitelist and blacklist can contain, in no particular order:
- @IF_HAVE_LIBPCAP@ ; interface names (e.g., ifname eth0),
- @IF_HAVE_LIBPCAP@ ; mac addresses (e.g., ether 85:3b:4d:d3:5f:c2),
- @IF_HAVE_LIBPCAP@ ; subnets (e.g., subnet 192.0.2.0/24, note that only IPv4 is supported here),
- @IF_HAVE_LIBPCAP@ ; or a wildcard (*) that matches all interfaces.
- @IF_HAVE_LIBPCAP@
+ @IF_HAVE_LIBPCAP@ ; interface names, including wildcard patterns (e.g., 'ifname eth0', 'ifname en*', 'ifname wlp?s0'),
+ @IF_HAVE_LIBPCAP@ ; mac addresses (e.g., 'ether 85:3b:4d:d3:5f:c2'),
+ @IF_HAVE_LIBPCAP@ ; subnets (e.g., 'subnet 192.0.2.0/24', note that only IPv4 is supported here),
+ @IF_HAVE_LIBPCAP@ ; or a single asterisk ('*') that matches all interfaces.
@IF_HAVE_LIBPCAP@ whitelist
@IF_HAVE_LIBPCAP@ {
@IF_HAVE_LIBPCAP@ *
diff --git a/tests/core/network-interface-predicate.t.cpp b/tests/core/network-interface-predicate.t.cpp
index 75beb81..4b6a375 100644
--- a/tests/core/network-interface-predicate.t.cpp
+++ b/tests/core/network-interface-predicate.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -61,6 +61,14 @@
{address_v6::from_string("2001:db8::1")},
address_v4::from_string("198.51.100.255"),
IFF_MULTICAST | IFF_BROADCAST | IFF_UP});
+ interfaces.push_back(
+ NetworkInterfaceInfo{3, "enp68s0f1",
+ ethernet::Address::fromString("3e:15:c2:8b:65:03"),
+ {address_v4::from_string("192.168.2.3")},
+ {},
+ address_v4::from_string("192.168.2.255"),
+ IFF_UP});
+
}
void
@@ -94,6 +102,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
}
BOOST_AUTO_TEST_CASE(EmptyWhitelist)
@@ -105,6 +114,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(WildcardBlacklist)
@@ -117,6 +127,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(IfnameWhitelist)
@@ -130,6 +141,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(IfnameBlacklist)
@@ -143,6 +155,72 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
+}
+
+BOOST_AUTO_TEST_CASE(IfnameWildcardStart)
+{
+ parseConfig("whitelist\n"
+ "{\n"
+ " ifname enp*\n"
+ "}");
+
+ BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
+}
+
+BOOST_AUTO_TEST_CASE(IfnameWildcardMiddle)
+{
+ parseConfig("whitelist\n"
+ "{\n"
+ " ifname *th*\n"
+ "}");
+
+ BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
+}
+
+BOOST_AUTO_TEST_CASE(IfnameWildcardDouble)
+{
+ parseConfig("whitelist\n"
+ "{\n"
+ " ifname eth**\n"
+ "}");
+
+ BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
+}
+
+BOOST_AUTO_TEST_CASE(IfnameWildcardOnly)
+{
+ parseConfig("whitelist\n"
+ "{\n"
+ " ifname *\n"
+ "}");
+
+ BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
+}
+
+BOOST_AUTO_TEST_CASE(IfnameQuestionMark)
+{
+ parseConfig("whitelist\n"
+ "{\n"
+ " ifname eth?\n"
+ "}");
+
+ BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(IfnameMalformed)
@@ -166,6 +244,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(EtherBlacklist)
@@ -179,6 +258,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
}
BOOST_AUTO_TEST_CASE(EtherMalformed)
@@ -201,6 +281,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), false);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), true);
}
BOOST_AUTO_TEST_CASE(SubnetBlacklist)
@@ -213,6 +294,7 @@
BOOST_CHECK_EQUAL(predicate(interfaces[0]), true);
BOOST_CHECK_EQUAL(predicate(interfaces[1]), false);
BOOST_CHECK_EQUAL(predicate(interfaces[2]), true);
+ BOOST_CHECK_EQUAL(predicate(interfaces[3]), false);
}
BOOST_AUTO_TEST_CASE(SubnetMalformed)