added 2 changesets to branch 'refs/remotes/pdziepak-github/nfs4' old head: a0d5a922d6440c2d4df51536fab9ef5057e021f5 new head: 266b99b7e921a71c22ac5d444a107abb282bbf36 overview: https://github.com/pdziepak/Haiku/compare/a0d5a92...266b99b ---------------------------------------------------------------------------- 07b3bd5: nfs4: Correctly parse paths with '.' or '..' 266b99b: nfs4: Support callbacks over IPv6 [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 9 files changed, 179 insertions(+), 63 deletions(-) .../kernel/file_systems/nfs4/Connection.cpp | 62 ++++++++++++-------- .../kernel/file_systems/nfs4/Connection.h | 16 ++++- .../kernel/file_systems/nfs4/FileInfo.cpp | 11 ++-- .../kernel/file_systems/nfs4/RPCCallback.h | 19 ++++++ .../file_systems/nfs4/RPCCallbackServer.cpp | 55 +++++++++++++++-- .../kernel/file_systems/nfs4/RPCCallbackServer.h | 21 ++++--- .../kernel/file_systems/nfs4/RPCServer.cpp | 17 +++++- .../kernel/file_systems/nfs4/RequestBuilder.cpp | 30 ++++++---- .../file_systems/nfs4/kernel_interface.cpp | 11 +--- ############################################################################ Commit: 07b3bd59abde6a349ecca01a5042e7be828893b4 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Feb 12 22:05:32 2013 UTC nfs4: Correctly parse paths with '.' or '..' ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp index 6a208c1..5b7a57d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp @@ -13,8 +13,6 @@ #include "Request.h" -// TODO: This function probably needs more strict checking against incorrect -// paths. Correct handling of '..' and '.' also may be useful. status_t FileInfo::ParsePath(RequestBuilder& req, uint32& count, const char* _path) { @@ -33,8 +31,13 @@ FileInfo::ParsePath(RequestBuilder& req, uint32& count, const char* _path) *pathEnd = '\0'; if (pathEnd != pathStart) { - req.LookUp(pathStart); - count++; + if (!strcmp(pathStart, "..")) { + req.LookUpUp(); + count++; + } else if (strcmp(pathStart, ".")) { + req.LookUp(pathStart); + count++; + } } if (pathEnd != NULL && pathEnd[1] != '\0') ############################################################################ Commit: 266b99b7e921a71c22ac5d444a107abb282bbf36 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Feb 13 00:14:45 2013 UTC nfs4: Support callbacks over IPv6 ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index e9f8678..adc21d9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012 Haiku, Inc. All rights reserved. + * Copyright 2012-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -61,6 +61,26 @@ PeerAddress::PeerAddress() } +PeerAddress::PeerAddress(int networkFamily) + : + fProtocol(0) +{ + ASSERT(networkFamily == AF_INET || networkFamily == AF_INET6); + + memset(&fAddress, 0, sizeof(fAddress)); + + fAddress.ss_family = networkFamily; + switch (networkFamily) { + case AF_INET: + fAddress.ss_len = sizeof(sockaddr_in); + break; + case AF_INET6: + fAddress.ss_len = sizeof(sockaddr_in6); + break; + } +} + + const char* PeerAddress::ProtocolString() const { @@ -94,13 +114,11 @@ PeerAddress::SetProtocol(const char* protocol) char* PeerAddress::UniversalAddress() const { - const sockaddr* address = reinterpret_cast<const sockaddr*>(&fAddress); - char* uAddr = reinterpret_cast<char*>(malloc(INET6_ADDRSTRLEN + 16)); if (uAddr == NULL) return NULL; - if (inet_ntop(address->sa_family, InAddr(), uAddr, AddressSize()) == NULL) + if (inet_ntop(fAddress.ss_family, InAddr(), uAddr, AddressSize()) == NULL) return NULL; char port[16]; @@ -114,7 +132,7 @@ PeerAddress::UniversalAddress() const socklen_t PeerAddress::AddressSize() const { - switch (reinterpret_cast<const sockaddr*>(&fAddress)->sa_family) { + switch (Family()) { case AF_INET: return sizeof(sockaddr_in); case AF_INET6: @@ -130,7 +148,7 @@ PeerAddress::Port() const { uint16 port; - switch (reinterpret_cast<const sockaddr*>(&fAddress)->sa_family) { + switch (Family()) { case AF_INET: port = reinterpret_cast<const sockaddr_in*>(&fAddress)->sin_port; break; @@ -150,7 +168,7 @@ PeerAddress::SetPort(uint16 port) { port = htons(port); - switch (reinterpret_cast<sockaddr*>(&fAddress)->sa_family) { + switch (Family()) { case AF_INET: reinterpret_cast<sockaddr_in*>(&fAddress)->sin_port = port; break; @@ -160,11 +178,10 @@ PeerAddress::SetPort(uint16 port) } } - const void* PeerAddress::InAddr() const { - switch (reinterpret_cast<const sockaddr*>(&fAddress)->sa_family) { + switch (Family()) { case AF_INET: return &reinterpret_cast<const sockaddr_in*>(&fAddress)->sin_addr; case AF_INET6: @@ -178,7 +195,7 @@ PeerAddress::InAddr() const size_t PeerAddress::InAddrSize() const { - switch (reinterpret_cast<const sockaddr*>(&fAddress)->sa_family) { + switch (Family()) { case AF_INET: return sizeof(in_addr); case AF_INET6: @@ -723,21 +740,23 @@ ConnectionBase::Disconnect() status_t -ConnectionListener::Listen(ConnectionListener** listener, uint16 port) +ConnectionListener::Listen(ConnectionListener** listener, int networkFamily, + uint16 port) { ASSERT(listener != NULL); + ASSERT(networkFamily == AF_INET || networkFamily == AF_INET6); - int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + int sock = socket(networkFamily, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) return errno; - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_len = sizeof(addr); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != B_OK) { + PeerAddress address(networkFamily); + address.SetPort(port); + address.fProtocol = IPPROTO_TCP; + + status_t result = bind(sock, (sockaddr*)&address.fAddress, + address.AddressSize()); + if (result != B_OK) { close(sock); return errno; } @@ -747,17 +766,12 @@ ConnectionListener::Listen(ConnectionListener** listener, uint16 port) return errno; } - PeerAddress address; - address.fProtocol = IPPROTO_TCP; - memset(&address.fAddress, 0, sizeof(address.fAddress)); - *listener = new(std::nothrow) ConnectionListener(address); if (*listener == NULL) { close(sock); return B_NO_MEMORY; } - status_t result; if ((*listener)->fWaitCancel < B_OK) { result = (*listener)->fWaitCancel; close(sock); diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.h b/src/add-ons/kernel/file_systems/nfs4/Connection.h index 16f8062..3c01daa 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.h +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Haiku, Inc. All rights reserved. + * Copyright 2012-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -25,6 +25,9 @@ struct PeerAddress { PeerAddress& operator=(const PeerAddress& address); PeerAddress(); + PeerAddress(int networkFamily); + + inline int Family() const; const char* ProtocolString() const; void SetProtocol(const char* protocol); @@ -40,6 +43,14 @@ struct PeerAddress { size_t InAddrSize() const; }; + +inline int +PeerAddress::Family() const +{ + return fAddress.ss_family; +} + + struct addrinfo; class AddressResolver { @@ -122,7 +133,8 @@ public: class ConnectionListener : public ConnectionBase { public: - static status_t Listen(ConnectionListener** listener, uint16 port = 0); + static status_t Listen(ConnectionListener** listener, int networkFamily, + uint16 port = 0); status_t AcceptConnection(Connection** connection); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h index b729156..9f579be 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h @@ -14,6 +14,7 @@ namespace RPC { +class CallbackServer; class CallbackRequest; class Server; @@ -24,10 +25,14 @@ public: inline void SetID(int32 id); inline int32 ID(); + inline void SetCBServer(CallbackServer* server); + inline CallbackServer* CBServer(); + status_t EnqueueRequest(CallbackRequest* request, Connection* connection); private: + CallbackServer* fCBServer; Server* fServer; int32 fID; }; @@ -47,6 +52,20 @@ Callback::ID() } +inline void +Callback::SetCBServer(CallbackServer* server) +{ + fCBServer = server; +} + + +inline CallbackServer* +Callback::CBServer() +{ + return fCBServer; +} + + } // namespace RPC diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp index f02a53c..c296289 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012 Haiku, Inc. All rights reserved. + * Copyright 2012-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -13,22 +13,25 @@ #include "RPCCallback.h" #include "RPCCallbackReply.h" #include "RPCCallbackRequest.h" +#include "RPCServer.h" using namespace RPC; CallbackServer* gRPCCallbackServer = NULL; +CallbackServer* gRPCCallbackServer6 = NULL; -CallbackServer::CallbackServer() +CallbackServer::CallbackServer(int networkFamily) : fConnectionList(NULL), fListener(NULL), fThreadRunning(false), fCallbackArray(NULL), fArraySize(0), - fFreeSlot(-1) + fFreeSlot(-1), + fNetworkFamily(networkFamily) { mutex_init(&fConnectionLock, NULL); mutex_init(&fThreadLock, NULL); @@ -47,6 +50,47 @@ CallbackServer::~CallbackServer() } +CallbackServer* +CallbackServer::Get(Server* server) +{ + ASSERT(server != NULL); + + int family = server->ID().Family(); + ASSERT(family == AF_INET || family == AF_INET6); + + int idx; + switch (family) { + case AF_INET: + idx = 0; + break; + case AF_INET6: + idx = 1; + break; + default: + return NULL; + } + + MutexLocker _(fServerCreationLock); + if (fServers[idx] == NULL) + fServers[idx] = new CallbackServer(family); + return fServers[idx]; +} + + +void +CallbackServer::ShutdownAll() +{ + MutexLocker _(fServerCreationLock); + for (unsigned int i = 0; i < sizeof(fServers) / sizeof(fServers[0]); i++) + delete fServers[i]; + memset(&fServers, 0, sizeof(fServers)); +} + + +mutex CallbackServer::fServerCreationLock = MUTEX_INITIALIZER(NULL); +CallbackServer* CallbackServer::fServers[2] = { NULL, NULL }; + + status_t CallbackServer::RegisterCallback(Callback* callback) { @@ -82,6 +126,7 @@ CallbackServer::RegisterCallback(Callback* callback) fCallbackArray[id].fCallback = callback; callback->SetID(id); + callback->SetCBServer(this); return B_OK; } @@ -91,6 +136,7 @@ status_t CallbackServer::UnregisterCallback(Callback* callback) { ASSERT(callback != NULL); + ASSERT(callback->CBServer() == this); int32 id = callback->ID(); @@ -98,6 +144,7 @@ CallbackServer::UnregisterCallback(Callback* callback) fCallbackArray[id].fNext = fFreeSlot; fFreeSlot = id; + callback->SetCBServer(NULL); return B_OK; } @@ -109,7 +156,7 @@ CallbackServer::StartServer() if (fThreadRunning) return B_OK; - status_t result = ConnectionListener::Listen(&fListener); + status_t result = ConnectionListener::Listen(&fListener, fNetworkFamily); if (result != B_OK) return result; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.h b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.h index 8a5f67b..fce7354 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Haiku, Inc. All rights reserved. + * Copyright 2012-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -17,6 +17,7 @@ namespace RPC { class Callback; +class Server; struct ConnectionEntry { Connection* fConnection; @@ -33,13 +34,16 @@ union CallbackSlot { class CallbackServer { public: - CallbackServer(); + CallbackServer(int networkFamily); ~CallbackServer(); + static CallbackServer* Get(Server* server); + static void ShutdownAll(); + status_t RegisterCallback(Callback* callback); status_t UnregisterCallback(Callback* callback); - inline PeerAddress LocalID(); + inline PeerAddress LocalID(); protected: status_t StartServer(); @@ -57,6 +61,9 @@ protected: inline Callback* GetCallback(int32 id); private: + static mutex fServerCreationLock; + static CallbackServer* fServers[2]; + mutex fConnectionLock; ConnectionEntry* fConnectionList; ConnectionListener* fListener; @@ -69,6 +76,8 @@ private: CallbackSlot* fCallbackArray; uint32 fArraySize; int32 fFreeSlot; + + int fNetworkFamily; }; @@ -76,6 +85,8 @@ inline PeerAddress CallbackServer::LocalID() { PeerAddress address; + + ASSERT(fListener != NULL); fListener->GetLocalAddress(&address); return address; } @@ -93,9 +104,5 @@ CallbackServer::GetCallback(int32 id) } // namespace RPC - -extern RPC::CallbackServer* gRPCCallbackServer; - - #endif // RPCCALLBACKSERVER_H diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index 13f6a5f..9506af6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -97,7 +97,7 @@ Server::Server(Connection* connection, PeerAddress* address) Server::~Server() { if (fCallback != NULL) - gRPCCallbackServer->UnregisterCallback(fCallback); + fCallback->CBServer()->UnregisterCallback(fCallback); delete fCallback; mutex_destroy(&fCallbackLock); mutex_destroy(&fRepairLock); @@ -235,9 +235,22 @@ Callback* Server::GetCallback() { MutexLocker _(fCallbackLock); + if (fCallback == NULL) { fCallback = new(std::nothrow) Callback(this); - gRPCCallbackServer->RegisterCallback(fCallback); + if (fCallback == NULL) + return NULL; + + CallbackServer* server = CallbackServer::Get(this); + if (server == NULL) { + delete fCallback; + return NULL; + } + + if (server->RegisterCallback(fCallback) != B_OK) { + delete fCallback; + return NULL; + } } return fCallback; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 02951f2..83ff3b4 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -671,21 +671,29 @@ RequestBuilder::SetClientID(RPC::Server* server) fRequest->Stream().AddUInt(0x40000000); - uint32 id = server->GetCallback()->ID(); + if (server->GetCallback() != NULL) { + ASSERT(server->GetCallback()->CBServer() != NULL); - PeerAddress local = gRPCCallbackServer->LocalID(); - PeerAddress servAddr = server->LocalID(); - servAddr.SetPort(local.Port()); + uint32 id = server->GetCallback()->ID(); - fRequest->Stream().AddString(local.ProtocolString()); + PeerAddress local = server->GetCallback()->CBServer()->LocalID(); + PeerAddress servAddr = server->LocalID(); + servAddr.SetPort(local.Port()); - char* uAddr = servAddr.UniversalAddress(); - if (uAddr == NULL) - return B_NO_MEMORY; - fRequest->Stream().AddString(uAddr); - free(uAddr); + fRequest->Stream().AddString(local.ProtocolString()); + + char* uAddr = servAddr.UniversalAddress(); + if (uAddr == NULL) + return B_NO_MEMORY; + fRequest->Stream().AddString(uAddr); + free(uAddr); - fRequest->Stream().AddUInt(id); + fRequest->Stream().AddUInt(id); + } else { + fRequest->Stream().AddString(""); + fRequest->Stream().AddString(""); + fRequest->Stream().AddUInt(0); + } fOpCount++; diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index 630e1e9..5a93ea5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -1367,14 +1367,6 @@ nfs4_init() return B_NO_MEMORY; } - gRPCCallbackServer = new(std::nothrow) RPC::CallbackServer; - if (gRPCCallbackServer == NULL) { - mutex_destroy(&gIdMapperLock); - delete gWorkQueue; - delete gRPCServerManager; - return B_NO_MEMORY; - } - return B_OK; } @@ -1382,7 +1374,8 @@ nfs4_init() status_t nfs4_uninit() { - delete gRPCCallbackServer; + RPC::CallbackServer::ShutdownAll(); + delete gIdMapper; delete gWorkQueue; delete gRPCServerManager;