Commit 482e2d53 authored by Oliver Giles's avatar Oliver Giles

RPC: Introduce 'unix-abstract:' prefix for abstract Unix sockets

Abstract unix socket addresses can now be specified with the
'unix-abstract:' prefix, and the 'unix:' prefix now explicitly
rejects addresses which contain NULL bytes
parent f9e96d71
......@@ -102,6 +102,9 @@ TEST(AsyncIo, AddressParsing) {
#if !_WIN32
EXPECT_EQ("unix:foo/bar/baz", tryParse(w, network, "unix:foo/bar/baz"));
#if __linux__
EXPECT_EQ("unix-abstract:foo/bar/baz", tryParse(w, network, "unix-abstract:foo/bar/baz"));
#endif
#endif
// We can parse services by name...
......
......@@ -449,7 +449,11 @@ public:
return str('[', buffer, "]:", ntohs(addr.inet6.sin6_port));
}
case AF_UNIX: {
return str("unix:", addr.unixDomain.sun_path);
if (addr.unixDomain.sun_path[0] == '\0') {
return str("unix-abstract:", addr.unixDomain.sun_path + 1);
} else {
return str("unix:", addr.unixDomain.sun_path);
}
}
default:
return str("(unknown address family ", addr.generic.sa_family, ")");
......@@ -470,12 +474,25 @@ public:
StringPtr path = str.slice(strlen("unix:"));
KJ_REQUIRE(path.size() < sizeof(addr.unixDomain.sun_path),
"Unix domain socket address is too long.", str);
KJ_REQUIRE(path.size() == strlen(path.cStr()),
"Unix domain socket address contains NULL. Use"
" 'unix-abstract:' for the abstract namespace.");
result.addr.unixDomain.sun_family = AF_UNIX;
strcpy(result.addr.unixDomain.sun_path, path.cStr());
result.addrlen = offsetof(struct sockaddr_un, sun_path) + path.size() + 1;
auto array = kj::heapArrayBuilder<SocketAddress>(1);
array.add(result);
return array.finish();
}
if (str.startsWith("unix-abstract:")) {
StringPtr path = str.slice(strlen("unix-abstract:"));
KJ_REQUIRE(path.size() + 1 < sizeof(addr.unixDomain.sun_path),
"Unix domain socket address is too long.", str);
result.addr.unixDomain.sun_family = AF_UNIX;
memcpy(result.addr.unixDomain.sun_path, path.cStr(), path.size() + 1);
result.addrlen = offsetof(struct sockaddr_un, sun_path) + path.size();
// Linux-specific: abstract namespace for unix sockets
// According to unix(7), addrlen of an abstract socket should not include the NULL terminator
if (path[0] != '\0') result.addrlen++;
result.addr.unixDomain.sun_path[0] = '\0';
memcpy(result.addr.unixDomain.sun_path + 1, path.cStr(), path.size());
result.addrlen = offsetof(struct sockaddr_un, sun_path) + path.size() + 1;
auto array = kj::heapArrayBuilder<SocketAddress>(1);
array.add(result);
return array.finish();
......
......@@ -390,7 +390,8 @@ int main(int argc, const char* argv[]) {
{% endhighlight %}
Note that for the connect address, Cap'n Proto supports DNS host names as well as IPv4 and IPv6
addresses. Additionally, a Unix domain socket can be specified as `unix:` followed by a path name.
addresses. Additionally, a Unix domain socket can be specified as `unix:` followed by a path name,
and an abstract Unix domain socket can be specified as `unix-abstract:` followed by an identifier.
For a more complete example, see the
[calculator client sample](https://github.com/sandstorm-io/capnproto/tree/master/c++/samples/calculator-client.c++).
......@@ -429,7 +430,8 @@ int main(int argc, const char* argv[]) {
Note that for the bind address, Cap'n Proto supports DNS host names as well as IPv4 and IPv6
addresses. The special address `*` can be used to bind to the same port on all local IPv4 and
IPv6 interfaces. Additionally, a Unix domain socket can be specified as `unix:` followed by a
path name.
path name, and an abstract Unix domain socket can be specified as `unix-abstract:` followed by
an identifier.
For a more complete example, see the
[calculator server sample](https://github.com/sandstorm-io/capnproto/tree/master/c++/samples/calculator-server.c++).
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment