face: change default Unix socket path
Refs: #5304
Change-Id: I5c7415874131b156e54a655960d9de47c1eae91d
diff --git a/daemon/face/unix-stream-channel.cpp b/daemon/face/unix-stream-channel.cpp
index 906d23e..150fad4 100644
--- a/daemon/face/unix-stream-channel.cpp
+++ b/daemon/face/unix-stream-channel.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2023, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -49,11 +49,10 @@
UnixStreamChannel::~UnixStreamChannel()
{
if (isListening()) {
- // use the non-throwing variants during destruction
- // and ignore any errors
+ // use the non-throwing variants during destruction and ignore any errors
boost::system::error_code error;
m_acceptor.close(error);
- NFD_LOG_CHAN_DEBUG("Removing socket file");
+ NFD_LOG_CHAN_TRACE("Removing socket file");
boost::filesystem::remove(m_endpoint.path(), error);
}
}
@@ -70,7 +69,7 @@
namespace fs = boost::filesystem;
- fs::path socketPath(m_endpoint.path());
+ fs::path socketPath = m_endpoint.path();
fs::file_type type = fs::symlink_status(socketPath).type();
if (type == fs::socket_file) {
@@ -80,7 +79,7 @@
NFD_LOG_CHAN_TRACE("connect() on existing socket file returned: " << error.message());
if (!error) {
// someone answered, leave the socket alone
- NDN_THROW(Error("Socket file at " + m_endpoint.path() + " belongs to another NFD process"));
+ NDN_THROW(Error("Socket file at " + m_endpoint.path() + " belongs to another process"));
}
else if (error == boost::asio::error::connection_refused ||
error == boost::asio::error::timed_out) {
@@ -94,6 +93,12 @@
NDN_THROW(Error(m_endpoint.path() + " already exists and is not a socket file"));
}
+ // ensure parent directory exists before creating socket
+ fs::path parent = socketPath.parent_path();
+ if (!parent.empty() && fs::create_directories(parent)) {
+ NFD_LOG_CHAN_TRACE("Created directory " << parent);
+ }
+
m_acceptor.open();
m_acceptor.bind(m_endpoint);
m_acceptor.listen(backlog);
diff --git a/daemon/face/unix-stream-factory.cpp b/daemon/face/unix-stream-factory.cpp
index a275fde..27719eb 100644
--- a/daemon/face/unix-stream-factory.cpp
+++ b/daemon/face/unix-stream-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2022, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -45,8 +45,8 @@
{
// unix
// {
- // path /run/nfd.sock ; on Linux
- // path /var/run/nfd.sock ; on other platforms
+ // path /run/nfd/nfd.sock ; on Linux
+ // path /var/run/nfd/nfd.sock ; on other platforms
// }
m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
@@ -59,15 +59,12 @@
}
#ifdef __linux__
- std::string path = "/run/nfd.sock";
+ std::string path = "/run/nfd/nfd.sock";
#else
- std::string path = "/var/run/nfd.sock";
+ std::string path = "/var/run/nfd/nfd.sock";
#endif // __linux__
- for (const auto& pair : *configSection) {
- const std::string& key = pair.first;
- const ConfigSection& value = pair.second;
-
+ for (const auto& [key, value] : *configSection) {
if (key == "path") {
path = value.get_value<std::string>();
}
@@ -87,11 +84,10 @@
}
shared_ptr<UnixStreamChannel>
-UnixStreamFactory::createChannel(const std::string& unixSocketPath)
+UnixStreamFactory::createChannel(const std::string& socketPath)
{
- boost::filesystem::path p(unixSocketPath);
- p = boost::filesystem::canonical(p.parent_path()) / p.filename();
- unix_stream::Endpoint endpoint(p.string());
+ auto normalizedPath = boost::filesystem::weakly_canonical(boost::filesystem::absolute(socketPath));
+ unix_stream::Endpoint endpoint(normalizedPath.string());
auto it = m_channels.find(endpoint);
if (it != m_channels.end())
diff --git a/daemon/face/unix-stream-factory.hpp b/daemon/face/unix-stream-factory.hpp
index 76bbfc9..51bc51d 100644
--- a/daemon/face/unix-stream-factory.hpp
+++ b/daemon/face/unix-stream-factory.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2023, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -53,7 +53,7 @@
* an exception will be thrown if the channel cannot be created.
*/
shared_ptr<UnixStreamChannel>
- createChannel(const std::string& unixSocketPath);
+ createChannel(const std::string& socketPath);
private:
void
diff --git a/daemon/rib/service.cpp b/daemon/rib/service.cpp
index 1634ef9..814feb0 100644
--- a/daemon/rib/service.cpp
+++ b/daemon/rib/service.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2022, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -68,9 +68,9 @@
if (config.get_child_optional("face_system.unix")) {
// default socket path should be the same as in UnixStreamFactory::processConfig
#ifdef __linux__
- auto path = config.get<std::string>("face_system.unix.path", "/run/nfd.sock");
+ auto path = config.get<std::string>("face_system.unix.path", "/run/nfd/nfd.sock");
#else
- auto path = config.get<std::string>("face_system.unix.path", "/var/run/nfd.sock");
+ auto path = config.get<std::string>("face_system.unix.path", "/var/run/nfd/nfd.sock");
#endif // __linux__
return make_shared<ndn::UnixTransport>(path);
}
diff --git a/docs/conf.py b/docs/conf.py
index 4ab82aa..83b4c52 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -10,7 +10,7 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'Named Data Networking Forwarding Daemon (NFD)'
-copyright = 'Copyright © 2014-2023 Named Data Networking Project.'
+copyright = 'Copyright © 2014-2024 Named Data Networking Project.'
author = 'Named Data Networking Project'
# The short X.Y version.
diff --git a/docs/manpages/nfdc-face.rst b/docs/manpages/nfdc-face.rst
index c09191b..410b814 100644
--- a/docs/manpages/nfdc-face.rst
+++ b/docs/manpages/nfdc-face.rst
@@ -66,7 +66,7 @@
- tcp4://192.0.2.1:6363
- tcp6://[2001:db8::1]:6363
- tcp://example.net
- - unix:///var/run/nfd.sock
+ - unix:///run/nfd/nfd.sock
- fd://6
- ether://[08:00:27:01:01:01]
- dev://eth0
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 660beb2..bf7d9ea 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -101,10 +101,9 @@
; Unix stream faces and channels.
unix
{
- ; The default transport is unix:///run/nfd.sock (on Linux) or unix:///var/run/nfd.sock (on
- ; other platforms). This should match the "transport" field in client.conf for ndn-cxx. If you
- ; wish to use TCP instead of Unix sockets with ndn-cxx, change "transport" to an appropriate
- ; TCP FaceUri.
+ ; The default transport is 'unix:///run/nfd/nfd.sock' (on Linux) or 'unix:///var/run/nfd/nfd.sock' (on
+ ; other platforms). This should match the 'transport' field in client.conf for ndn-cxx. If you wish
+ ; to use TCP instead of Unix sockets with ndn-cxx, change 'transport' to an appropriate TCP FaceUri.
path @UNIX_SOCKET_PATH@ ; Unix stream listener path
}
@@ -303,12 +302,12 @@
; sudo mkdir -p @SYSCONFDIR@/ndn/keys
; sudo mv default.ndncert @SYSCONFDIR@/ndn/keys/default.ndncert
;
- ; The "certfile" field below specifies the default key directory for
+ ; The 'certfile' field below specifies the default key directory for
; your machine. You may move your newly created key to the location it
; specifies or path.
; certfile keys/default.ndncert ; NDN identity certificate file
- certfile any ; "any" authorizes command interests signed under any certificate,
+ certfile any ; 'any' authorizes command interests signed under any certificate,
; i.e., no actual validation.
privileges ; set of privileges granted to this identity
{
diff --git a/tests/daemon/face/unix-stream-channel.t.cpp b/tests/daemon/face/unix-stream-channel.t.cpp
index e4ce0cf..d583625 100644
--- a/tests/daemon/face/unix-stream-channel.t.cpp
+++ b/tests/daemon/face/unix-stream-channel.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2022, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -41,7 +41,8 @@
protected:
UnixStreamChannelFixture()
{
- listenerEp = unix_stream::Endpoint("nfd-test-unix-stream-channel.sock");
+ listenerEp = unix_stream::Endpoint(socketPath.string());
+ fs::remove_all(socketPath.parent_path());
}
shared_ptr<UnixStreamChannel>
@@ -68,11 +69,14 @@
clientConnect(local::stream_protocol::socket& client)
{
client.async_connect(listenerEp,
- [this] (const boost::system::error_code& error) {
+ [this] (const auto& error) {
BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
limitedIo.afterOp();
});
}
+
+protected:
+ fs::path socketPath = fs::path(UNIT_TESTS_TMPDIR) / "unix-stream-channel" / "test" / "foo.sock";
};
BOOST_AUTO_TEST_SUITE(Face)
@@ -128,9 +132,6 @@
BOOST_AUTO_TEST_CASE(SocketFile)
{
- fs::path socketPath(listenerEp.path());
- fs::remove(socketPath);
-
auto channel = makeChannel();
BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::file_not_found);
@@ -144,32 +145,33 @@
BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::file_not_found);
}
-BOOST_AUTO_TEST_CASE(ExistingStaleSocketFile)
+BOOST_AUTO_TEST_CASE(ExistingSocketFile)
{
- fs::path socketPath(listenerEp.path());
- fs::remove(socketPath);
-
+ fs::create_directories(socketPath.parent_path());
local::stream_protocol::acceptor acceptor(g_io, listenerEp);
- acceptor.close();
BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::socket_file);
auto channel = makeChannel();
+ BOOST_CHECK_THROW(channel->listen(nullptr, nullptr), UnixStreamChannel::Error);
+
+ acceptor.close();
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::socket_file);
+
BOOST_CHECK_NO_THROW(channel->listen(nullptr, nullptr));
BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::socket_file);
}
BOOST_AUTO_TEST_CASE(ExistingRegularFile)
{
- fs::path socketPath(listenerEp.path());
- fs::remove(socketPath);
+ auto guard = ndn::make_scope_exit([=] { fs::remove(socketPath); });
- std::ofstream f(listenerEp.path());
+ fs::create_directories(socketPath.parent_path());
+ std::ofstream f(socketPath.string());
f.close();
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::regular_file);
auto channel = makeChannel();
BOOST_CHECK_THROW(channel->listen(nullptr, nullptr), UnixStreamChannel::Error);
-
- fs::remove(socketPath);
}
BOOST_AUTO_TEST_SUITE_END() // TestUnixStreamChannel
diff --git a/tests/daemon/face/unix-stream-factory.t.cpp b/tests/daemon/face/unix-stream-factory.t.cpp
index 53a8687..1f0a62f 100644
--- a/tests/daemon/face/unix-stream-factory.t.cpp
+++ b/tests/daemon/face/unix-stream-factory.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2023, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,21 +28,18 @@
#include "face-system-fixture.hpp"
#include "factory-test-common.hpp"
+#include <boost/filesystem.hpp>
+
namespace nfd::tests {
-using face::UnixStreamFactory;
-
-using UnixStreamFactoryFixture = FaceSystemFactoryFixture<UnixStreamFactory>;
+using UnixStreamFactoryFixture = FaceSystemFactoryFixture<face::UnixStreamFactory>;
BOOST_AUTO_TEST_SUITE(Face)
BOOST_FIXTURE_TEST_SUITE(TestUnixStreamFactory, UnixStreamFactoryFixture)
-const std::string CHANNEL_PATH1("unix-stream-test.1.sock");
-const std::string CHANNEL_PATH2("unix-stream-test.2.sock");
-
BOOST_AUTO_TEST_SUITE(ProcessConfig)
-BOOST_AUTO_TEST_CASE(Normal)
+BOOST_AUTO_TEST_CASE(AbsolutePath)
{
const std::string CONFIG = R"CONFIG(
face_system
@@ -58,9 +55,40 @@
parseConfig(CONFIG, false);
BOOST_REQUIRE_EQUAL(factory.getChannels().size(), 1);
+ BOOST_TEST(factory.getChannels().front()->isListening());
+
const auto& uri = factory.getChannels().front()->getUri();
- BOOST_CHECK_EQUAL(uri.getScheme(), "unix");
- BOOST_CHECK_NE(uri.getPath().find("nfd-test.sock"), std::string::npos);
+ BOOST_TEST(uri.getScheme() == "unix");
+ boost::filesystem::path path(uri.getPath());
+ BOOST_TEST(path.filename() == "nfd-test.sock");
+ BOOST_TEST(boost::filesystem::canonical(path) == path); // path should already be in canonical form
+ BOOST_TEST(boost::filesystem::equivalent(path, "/tmp/nfd-test.sock"));
+}
+
+BOOST_AUTO_TEST_CASE(RelativePath)
+{
+ const std::string CONFIG = R"CONFIG(
+ face_system
+ {
+ unix
+ {
+ path nfd-test.sock
+ }
+ }
+ )CONFIG";
+
+ parseConfig(CONFIG, true);
+ parseConfig(CONFIG, false);
+
+ BOOST_REQUIRE_EQUAL(factory.getChannels().size(), 1);
+ BOOST_TEST(factory.getChannels().front()->isListening());
+
+ const auto& uri = factory.getChannels().front()->getUri();
+ BOOST_TEST(uri.getScheme() == "unix");
+ boost::filesystem::path path(uri.getPath());
+ BOOST_TEST(path.filename() == "nfd-test.sock");
+ BOOST_TEST(boost::filesystem::canonical(path) == path); // path should already be in canonical form
+ BOOST_TEST(boost::filesystem::equivalent(path, "nfd-test.sock"));
}
BOOST_AUTO_TEST_CASE(Omitted)
@@ -95,6 +123,9 @@
BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
+const std::string CHANNEL_PATH1("unix-stream-test.1.sock");
+const std::string CHANNEL_PATH2("unix-stream-test.2.sock");
+
BOOST_AUTO_TEST_CASE(GetChannels)
{
BOOST_CHECK_EQUAL(factory.getChannels().empty(), true);
@@ -107,16 +138,24 @@
BOOST_AUTO_TEST_CASE(CreateChannel)
{
- auto channel1 = factory.createChannel(CHANNEL_PATH1);
+ auto channel1 = factory.createChannel("./" + CHANNEL_PATH1); // test path normalization
auto channel1a = factory.createChannel(CHANNEL_PATH1);
+ auto channel1b = factory.createChannel(boost::filesystem::absolute(CHANNEL_PATH1).string());
+ auto channel1c = factory.createChannel("foo//../" + CHANNEL_PATH1);
BOOST_CHECK_EQUAL(channel1, channel1a);
+ BOOST_CHECK_EQUAL(channel1, channel1b);
+ BOOST_CHECK_EQUAL(channel1, channel1c);
BOOST_CHECK_EQUAL(factory.getChannels().size(), 1);
const auto& uri = channel1->getUri();
+ BOOST_TEST_INFO_SCOPE(uri);
BOOST_CHECK_EQUAL(uri.getScheme(), "unix");
BOOST_CHECK_EQUAL(uri.getHost(), "");
BOOST_CHECK_EQUAL(uri.getPort(), "");
- BOOST_CHECK_EQUAL(uri.getPath().rfind(CHANNEL_PATH1), uri.getPath().size() - CHANNEL_PATH1.size());
+ boost::filesystem::path path1(uri.getPath());
+ BOOST_TEST(path1.filename() == CHANNEL_PATH1);
+ BOOST_TEST(path1.is_absolute()); // path should always be absolute
+ BOOST_TEST(path1.lexically_normal() == path1); // path should be in normal form
auto channel2 = factory.createChannel(CHANNEL_PATH2);
BOOST_CHECK_NE(channel1, channel2);
diff --git a/wscript b/wscript
index 11a1353..63b8a8a 100644
--- a/wscript
+++ b/wscript
@@ -1,6 +1,6 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
"""
-Copyright (c) 2014-2023, Regents of the University of California,
+Copyright (c) 2014-2024, Regents of the University of California,
Arizona Board of Regents,
Colorado State University,
University Pierre & Marie Curie, Sorbonne University,
@@ -209,7 +209,7 @@
install_path='${SYSCONFDIR}/ndn',
IF_HAVE_LIBPCAP='' if bld.env.HAVE_LIBPCAP else '; ',
IF_HAVE_WEBSOCKET='' if bld.env.HAVE_WEBSOCKET else '; ',
- UNIX_SOCKET_PATH='/run/nfd.sock' if Utils.unversioned_sys_platform() == 'linux' else '/var/run/nfd.sock')
+ UNIX_SOCKET_PATH='/run/nfd/nfd.sock' if Utils.unversioned_sys_platform() == 'linux' else '/var/run/nfd/nfd.sock')
bld.install_files('${SYSCONFDIR}/ndn', 'autoconfig.conf.sample')
if bld.env.HAVE_SYSTEMD: