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) { ...@@ -102,6 +102,9 @@ TEST(AsyncIo, AddressParsing) {
#if !_WIN32 #if !_WIN32
EXPECT_EQ("unix:foo/bar/baz", tryParse(w, network, "unix:foo/bar/baz")); 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 #endif
// We can parse services by name... // We can parse services by name...
......
...@@ -449,8 +449,12 @@ public: ...@@ -449,8 +449,12 @@ public:
return str('[', buffer, "]:", ntohs(addr.inet6.sin6_port)); return str('[', buffer, "]:", ntohs(addr.inet6.sin6_port));
} }
case AF_UNIX: { case AF_UNIX: {
if (addr.unixDomain.sun_path[0] == '\0') {
return str("unix-abstract:", addr.unixDomain.sun_path + 1);
} else {
return str("unix:", addr.unixDomain.sun_path); return str("unix:", addr.unixDomain.sun_path);
} }
}
default: default:
return str("(unknown address family ", addr.generic.sa_family, ")"); return str("(unknown address family ", addr.generic.sa_family, ")");
} }
...@@ -470,12 +474,25 @@ public: ...@@ -470,12 +474,25 @@ public:
StringPtr path = str.slice(strlen("unix:")); StringPtr path = str.slice(strlen("unix:"));
KJ_REQUIRE(path.size() < sizeof(addr.unixDomain.sun_path), KJ_REQUIRE(path.size() < sizeof(addr.unixDomain.sun_path),
"Unix domain socket address is too long.", str); "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; result.addr.unixDomain.sun_family = AF_UNIX;
memcpy(result.addr.unixDomain.sun_path, path.cStr(), path.size() + 1); result.addr.unixDomain.sun_path[0] = '\0';
result.addrlen = offsetof(struct sockaddr_un, sun_path) + path.size(); memcpy(result.addr.unixDomain.sun_path + 1, path.cStr(), path.size());
// Linux-specific: abstract namespace for unix sockets result.addrlen = offsetof(struct sockaddr_un, sun_path) + path.size() + 1;
// According to unix(7), addrlen of an abstract socket should not include the NULL terminator
if (path[0] != '\0') result.addrlen++;
auto array = kj::heapArrayBuilder<SocketAddress>(1); auto array = kj::heapArrayBuilder<SocketAddress>(1);
array.add(result); array.add(result);
return array.finish(); return array.finish();
......
...@@ -390,7 +390,8 @@ int main(int argc, const char* argv[]) { ...@@ -390,7 +390,8 @@ int main(int argc, const char* argv[]) {
{% endhighlight %} {% endhighlight %}
Note that for the connect address, Cap'n Proto supports DNS host names as well as IPv4 and IPv6 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 For a more complete example, see the
[calculator client sample](https://github.com/sandstorm-io/capnproto/tree/master/c++/samples/calculator-client.c++). [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[]) { ...@@ -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 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 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 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 For a more complete example, see the
[calculator server sample](https://github.com/sandstorm-io/capnproto/tree/master/c++/samples/calculator-server.c++). [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