mirror of
https://github.com/facebook/sapling.git
synced 2024-12-26 06:21:48 +03:00
nfs: add a portmap client
Summary: The portmap protocol allows for service discovery and registration against the per-host rpcbind daemon. An NFS server will need to register against it to be mountable. The portmap_util binary is here for testing purposes and will not be used in EdenFS. This code was written by wez. Reviewed By: kmancini Differential Revision: D25986694 fbshipit-source-id: 1eee7238fdf70c8c4937e685da91ad08d46befe4
This commit is contained in:
parent
7c7f50ef9d
commit
1b0d345774
74
eden/fs/nfs/portmap/PortmapClient.cpp
Normal file
74
eden/fs/nfs/portmap/PortmapClient.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include "eden/fs/nfs/portmap/PortmapClient.h"
|
||||
#include <common/network/NetworkUtil.h>
|
||||
#include <folly/Exception.h>
|
||||
#include <folly/SocketAddress.h>
|
||||
#include <folly/String.h>
|
||||
#include <folly/logging/xlog.h>
|
||||
|
||||
using folly::IOBuf;
|
||||
using folly::IOBufQueue;
|
||||
using folly::SocketAddress;
|
||||
|
||||
namespace facebook::eden {
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t kPortmapPortNumber = 111;
|
||||
constexpr uint32_t kPortmapProgNumber = 100000;
|
||||
/*
|
||||
* Ideally we should use version 3 and 4, as that appears to have better
|
||||
* support for ipv6. For now, and since the goal is to only support a loopback
|
||||
* NFS, let's use version 2 and ipv4.
|
||||
*/
|
||||
constexpr uint32_t kPortmapVersionNumber = 2;
|
||||
constexpr uint32_t kPortmapSet = 1;
|
||||
constexpr uint32_t kPortmapUnSet = 2;
|
||||
constexpr uint32_t kPortmapGetPort = 3;
|
||||
} // namespace
|
||||
|
||||
EDEN_XDR_SERDE_IMPL(PortmapMapping, prog, vers, prot, port);
|
||||
|
||||
PortmapClient::PortmapClient()
|
||||
: client_(SocketAddress(
|
||||
network::NetworkUtil::getLocalIPv4(),
|
||||
kPortmapPortNumber)) {
|
||||
#ifdef __APPLE__
|
||||
{
|
||||
// Connect to the portmap "tickler" socket.
|
||||
// This causes launchd to spawn `rpcbind` and bring up the portmap service.
|
||||
auto addr = SocketAddress::makeFromPath("/var/run/portmap.socket");
|
||||
sockaddr_storage stg;
|
||||
auto len = addr.getAddress(&stg);
|
||||
tickler_ = folly::netops::socket(addr.getFamily(), SOCK_STREAM, 0);
|
||||
folly::checkUnixError(
|
||||
folly::netops::connect(tickler_, (sockaddr*)&stg, len),
|
||||
"connect to ",
|
||||
addr.getPath());
|
||||
}
|
||||
#endif
|
||||
|
||||
client_.connect();
|
||||
}
|
||||
|
||||
bool PortmapClient::unsetMapping(PortmapMapping map) {
|
||||
return client_.call<bool, PortmapMapping>(
|
||||
kPortmapProgNumber, kPortmapVersionNumber, kPortmapUnSet, map);
|
||||
}
|
||||
|
||||
bool PortmapClient::setMapping(PortmapMapping map) {
|
||||
return client_.call<bool, PortmapMapping>(
|
||||
kPortmapProgNumber, kPortmapVersionNumber, kPortmapSet, map);
|
||||
}
|
||||
|
||||
uint32_t PortmapClient::getPort(PortmapMapping map) {
|
||||
return client_.call<uint32_t, PortmapMapping>(
|
||||
kPortmapProgNumber, kPortmapVersionNumber, kPortmapGetPort, map);
|
||||
}
|
||||
|
||||
} // namespace facebook::eden
|
43
eden/fs/nfs/portmap/PortmapClient.h
Normal file
43
eden/fs/nfs/portmap/PortmapClient.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <folly/net/NetworkSocket.h>
|
||||
#include "eden/fs/nfs/rpc/Rpc.h"
|
||||
#include "eden/fs/nfs/rpc/StreamClient.h"
|
||||
|
||||
namespace facebook::eden {
|
||||
|
||||
struct PortmapMapping {
|
||||
uint32_t prog;
|
||||
uint32_t vers;
|
||||
uint32_t prot;
|
||||
uint32_t port;
|
||||
|
||||
static constexpr uint32_t kProtoTcp = 6;
|
||||
static constexpr uint32_t kProtoUdp = 17;
|
||||
|
||||
bool operator==(const PortmapMapping&) const;
|
||||
};
|
||||
EDEN_XDR_SERDE_DECL(PortmapMapping);
|
||||
|
||||
class PortmapClient {
|
||||
public:
|
||||
bool setMapping(PortmapMapping map);
|
||||
bool unsetMapping(PortmapMapping map);
|
||||
uint32_t getPort(PortmapMapping map);
|
||||
|
||||
PortmapClient();
|
||||
|
||||
private:
|
||||
#ifdef __APPLE__
|
||||
folly::NetworkSocket tickler_;
|
||||
#endif
|
||||
StreamClient client_;
|
||||
};
|
||||
|
||||
} // namespace facebook::eden
|
41
eden/fs/nfs/portmap/PortmapUtil.cpp
Normal file
41
eden/fs/nfs/portmap/PortmapUtil.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <folly/SocketAddress.h>
|
||||
#include <folly/init/Init.h>
|
||||
#include <folly/logging/Init.h>
|
||||
#include <folly/logging/xlog.h>
|
||||
#include "eden/fs/nfs/portmap/PortmapClient.h"
|
||||
|
||||
using namespace facebook::eden;
|
||||
|
||||
FOLLY_INIT_LOGGING_CONFIG("eden=INFO");
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
folly::init(&argc, &argv);
|
||||
|
||||
PortmapClient client;
|
||||
|
||||
auto port =
|
||||
client.getPort(PortmapMapping{100003, 3, PortmapMapping::kProtoTcp, 0});
|
||||
|
||||
XLOG(INFO) << "Got port: " << port;
|
||||
|
||||
// Try to set a bogus port for NFS.
|
||||
// This will fail if there is already an NFS daemon running
|
||||
XLOG(INFO) << "Set mapping: "
|
||||
<< client.setMapping(
|
||||
PortmapMapping{100003, 3, PortmapMapping::kProtoTcp, 123});
|
||||
|
||||
// Read back the current port
|
||||
auto newPort =
|
||||
client.getPort(PortmapMapping{100003, 3, PortmapMapping::kProtoTcp, 0});
|
||||
|
||||
XLOG(INFO) << "Got new port: " << newPort;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user