Move parsing getattrinfo() result out of dns_resolver module
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
#define DNS_RESOLVER_H
|
||||
|
||||
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <module.h>
|
||||
|
||||
|
||||
@@ -16,10 +19,36 @@
|
||||
|
||||
|
||||
struct dns_resolver_module {
|
||||
module_info module;
|
||||
status_t (*dns_resolve)(const char* host, uint32* addr);
|
||||
module_info module;
|
||||
status_t (*getaddrinfo)(const char* node, const char* service,
|
||||
const struct addrinfo* hints, struct addrinfo** res);
|
||||
};
|
||||
|
||||
|
||||
static inline int
|
||||
getaddrinfo(const char* node, const char* service, const struct addrinfo* hints,
|
||||
struct addrinfo** res)
|
||||
{
|
||||
dns_resolver_module* dns;
|
||||
status_t result = get_module(DNS_RESOLVER_MODULE_NAME,
|
||||
reinterpret_cast<module_info**>(&dns));
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
result = dns->getaddrinfo(node, service, hints, res);
|
||||
|
||||
put_module(DNS_RESOLVER_MODULE_NAME);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
freeaddrinfo(struct addrinfo* res)
|
||||
{
|
||||
free(res);
|
||||
}
|
||||
|
||||
|
||||
#endif // DNS_RESOLVER_H
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
|
||||
#include "Connection.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
#include <net/dns_resolver.h>
|
||||
|
||||
|
||||
#define LAST_FRAGMENT 0x80000000
|
||||
@@ -48,6 +50,42 @@ ServerAddress::operator=(const ServerAddress& x)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerAddress::ResolveName(const char* name, ServerAddress* addr)
|
||||
{
|
||||
addr->fPort = 2049;
|
||||
addr->fProtocol = ProtocolUDP;
|
||||
|
||||
struct in_addr iaddr;
|
||||
if (inet_aton(name, &iaddr) != 0) {
|
||||
addr->fAddress = ntohl(iaddr.s_addr);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
addrinfo* ai;
|
||||
status_t result = getaddrinfo(name, NULL, NULL, &ai);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
addrinfo* current = ai;
|
||||
while (current != NULL) {
|
||||
if (current->ai_family == AF_INET) {
|
||||
sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(current->ai_addr);
|
||||
|
||||
addr->fAddress = ntohl(sin->sin_addr.s_addr);
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
current = current->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const sockaddr_in& addr, Transport proto)
|
||||
:
|
||||
fSock(-1),
|
||||
|
||||
@@ -29,6 +29,9 @@ struct ServerAddress {
|
||||
bool operator<(const ServerAddress& x);
|
||||
|
||||
ServerAddress& operator=(const ServerAddress& x);
|
||||
|
||||
static status_t ResolveName(const char* name,
|
||||
ServerAddress* addr);
|
||||
};
|
||||
|
||||
class Connection {
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
|
||||
#include "Filesystem.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <lock.h>
|
||||
#include <net/dns_resolver.h>
|
||||
|
||||
#include "Request.h"
|
||||
#include "RootInode.h"
|
||||
@@ -216,37 +214,25 @@ Filesystem::Migrate(const RPC::Server* serv)
|
||||
FSLocations* locs =
|
||||
reinterpret_cast<FSLocations*>(values[0].fData.fLocations);
|
||||
|
||||
dns_resolver_module* dns;
|
||||
result = get_module(DNS_RESOLVER_MODULE_NAME,
|
||||
reinterpret_cast<module_info**>(&dns));
|
||||
if (result != B_OK) {
|
||||
delete[] values;
|
||||
return result;
|
||||
}
|
||||
|
||||
RPC::Server* server = fServer;
|
||||
for (uint32 i = 0; i < locs->fCount; i++) {
|
||||
for (uint32 j = 0; j < locs->fLocations[i].fCount; j++) {
|
||||
uint32 ip;
|
||||
struct in_addr addr;
|
||||
if (inet_aton(locs->fLocations[i].fLocations[j], &addr) == 0) {
|
||||
result = dns->dns_resolve(locs->fLocations[i].fLocations[j],
|
||||
&ip);
|
||||
if (result != B_OK)
|
||||
continue;
|
||||
} else
|
||||
ip = addr.s_addr;
|
||||
ServerAddress addr;
|
||||
|
||||
if (gRPCServerManager->Acquire(&fServer, ip, 2049,
|
||||
ProtocolUDP, CreateNFS4Server) == B_OK) {
|
||||
if (ServerAddress::ResolveName(locs->fLocations[i].fLocations[j],
|
||||
&addr) != B_OK)
|
||||
continue;
|
||||
|
||||
if (gRPCServerManager->Acquire(&fServer, addr.fAddress, addr.fPort,
|
||||
addr.fProtocol, CreateNFS4Server) == B_OK) {
|
||||
|
||||
free(const_cast<char*>(fPath));
|
||||
fPath = strdup(locs->fLocations[j].fRootPath);
|
||||
fPath = strdup(locs->fLocations[i].fRootPath);
|
||||
|
||||
if (fPath == NULL) {
|
||||
gRPCServerManager->Release(fServer);
|
||||
fServer = server;
|
||||
put_module(DNS_RESOLVER_MODULE_NAME);
|
||||
|
||||
delete[] values;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
@@ -256,7 +242,6 @@ Filesystem::Migrate(const RPC::Server* serv)
|
||||
}
|
||||
}
|
||||
|
||||
put_module(DNS_RESOLVER_MODULE_NAME);
|
||||
delete[] values;
|
||||
|
||||
if (server == fServer) {
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/dns_resolver.h>
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include "Connection.h"
|
||||
@@ -42,7 +40,7 @@ CreateNFS4Server(RPC::Server* serv)
|
||||
|
||||
|
||||
static status_t
|
||||
sParseArguments(const char* _args, uint32* _ip, char* _path)
|
||||
ParseArguments(const char* _args, uint32* _ip, char* _path)
|
||||
{
|
||||
if (_args == NULL)
|
||||
return B_BAD_VALUE;
|
||||
@@ -55,26 +53,12 @@ sParseArguments(const char* _args, uint32* _ip, char* _path)
|
||||
}
|
||||
*path++ = '\0';
|
||||
|
||||
status_t result;
|
||||
struct in_addr addr;
|
||||
if (inet_aton(args, &addr) == 0) {
|
||||
dns_resolver_module* dns;
|
||||
result = get_module(DNS_RESOLVER_MODULE_NAME,
|
||||
reinterpret_cast<module_info**>(&dns));
|
||||
if (result != B_OK) {
|
||||
free(args);
|
||||
return result;
|
||||
}
|
||||
ServerAddress addr;
|
||||
status_t result = ServerAddress::ResolveName(args, &addr);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
result = dns->dns_resolve(args, _ip);
|
||||
put_module(DNS_RESOLVER_MODULE_NAME);
|
||||
if (result != B_OK) {
|
||||
free(args);
|
||||
return result;
|
||||
}
|
||||
} else
|
||||
*_ip = addr.s_addr;
|
||||
*_ip = ntohl(*_ip);
|
||||
*_ip = addr.fAddress;
|
||||
|
||||
_path[255] = '\0';
|
||||
strncpy(_path, path, 255);
|
||||
@@ -92,7 +76,7 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
|
||||
uint32 ip;
|
||||
char path[256];
|
||||
result = sParseArguments(args, &ip, path);
|
||||
result = ParseArguments(args, &ip, path);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ const char* kPortNameReq = "dns_resolver_req";
|
||||
const char* kPortNameRpl = "dns_resolver_rpl";
|
||||
|
||||
enum MsgCodes {
|
||||
MsgResolveRequest = 1,
|
||||
MsgResolveReply = 2,
|
||||
MsgResolveError = 3
|
||||
MsgReply,
|
||||
MsgError,
|
||||
MsgGetAddrInfo,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
#include <net/dns_resolver.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <lock.h>
|
||||
#include <port.h>
|
||||
#include <team.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include "Definitions.h"
|
||||
|
||||
@@ -91,40 +93,120 @@ dns_resolver_uninit()
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
dns_resolve(const char* host, uint32* addr)
|
||||
static void
|
||||
RelocateEntries(struct addrinfo *addr)
|
||||
{
|
||||
mutex_lock(&gPortLock);
|
||||
char* generalOffset = reinterpret_cast<char*>(addr);
|
||||
|
||||
struct addrinfo* current = addr;
|
||||
while (current != NULL) {
|
||||
uint64 addrOffset = reinterpret_cast<uint64>(current->ai_addr);
|
||||
uint64 nameOffset = reinterpret_cast<uint64>(current->ai_canonname);
|
||||
uint64 nextOffset = reinterpret_cast<uint64>(current->ai_next);
|
||||
|
||||
if (current->ai_addr != NULL) {
|
||||
current->ai_addr =
|
||||
reinterpret_cast<sockaddr*>(generalOffset + addrOffset);
|
||||
}
|
||||
|
||||
if (current->ai_canonname != NULL)
|
||||
current->ai_canonname = generalOffset + nameOffset;
|
||||
|
||||
if (current->ai_next != NULL) {
|
||||
current->ai_next =
|
||||
reinterpret_cast<addrinfo*>(generalOffset + nextOffset);
|
||||
}
|
||||
|
||||
current = current->ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
GetAddrInfo(const char* node, const char* service,
|
||||
const struct addrinfo* hints, struct addrinfo** res)
|
||||
{
|
||||
dprintf("SENDING GETADDRINFO %s\n", node);
|
||||
|
||||
uint32 nodeSize = node != NULL ? strlen(node) + 1 : 1;
|
||||
uint32 serviceSize = service != NULL ? strlen(service) + 1 : 1;
|
||||
uint32 size = nodeSize + serviceSize + sizeof(*hints);
|
||||
char* buffer = reinterpret_cast<char*>(malloc(size));
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter _(buffer);
|
||||
|
||||
off_t off = 0;
|
||||
if (node != NULL)
|
||||
strcpy(buffer + off, node);
|
||||
else
|
||||
buffer[off] = '\0';
|
||||
off += nodeSize;
|
||||
|
||||
if (service != NULL)
|
||||
strcpy(buffer + off, service);
|
||||
else
|
||||
buffer[off] = '\0';
|
||||
off += serviceSize;
|
||||
|
||||
if (hints != NULL)
|
||||
memcpy(buffer + off, hints, sizeof(*hints));
|
||||
else {
|
||||
struct addrinfo *nullHints =
|
||||
reinterpret_cast<struct addrinfo*>(buffer + off);
|
||||
memset(nullHints, 0, sizeof(*nullHints));
|
||||
nullHints->ai_family = AF_UNSPEC;
|
||||
}
|
||||
dprintf("SENDING BUFFER %s %d\n", buffer, (int)size);
|
||||
MutexLocker locker(gPortLock);
|
||||
do {
|
||||
status_t result = write_port(gPortRequest, MsgResolveRequest, host,
|
||||
strlen(host) + 1);
|
||||
status_t result = write_port(gPortRequest, MsgGetAddrInfo, buffer,
|
||||
size);
|
||||
if (result != B_OK) {
|
||||
result = dns_resolver_repair();
|
||||
if (result != B_OK) {
|
||||
mutex_unlock(&gPortLock);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ssize_t replySize = port_buffer_size(gPortReply);
|
||||
if (replySize < B_OK) {
|
||||
result = dns_resolver_repair();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
continue;
|
||||
}
|
||||
|
||||
void* reply = malloc(replySize);
|
||||
if (reply == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
int32 code;
|
||||
result = read_port(gPortReply, &code, addr, sizeof(*addr));
|
||||
if (result < B_OK) {
|
||||
replySize = read_port(gPortReply, &code, reply, replySize);
|
||||
if (replySize < B_OK) {
|
||||
result = dns_resolver_repair();
|
||||
if (result != B_OK) {
|
||||
mutex_unlock(&gPortLock);
|
||||
free(reply);
|
||||
return result;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
mutex_unlock(&gPortLock);
|
||||
|
||||
if (code == MsgResolveReply)
|
||||
return B_OK;
|
||||
else
|
||||
return *addr;
|
||||
struct addrinfo *addr;
|
||||
switch (code) {
|
||||
case MsgReply:
|
||||
addr = reinterpret_cast<struct addrinfo*>(reply);
|
||||
RelocateEntries(addr);
|
||||
*res = addr;
|
||||
return B_OK;
|
||||
case MsgError:
|
||||
result = *reinterpret_cast<status_t*>(reply);
|
||||
free(reply);
|
||||
return result;
|
||||
default:
|
||||
free(reply);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
} while (true);
|
||||
}
|
||||
@@ -150,7 +232,7 @@ static dns_resolver_module sDNSResolverModule = {
|
||||
dns_resolver_std_ops,
|
||||
},
|
||||
|
||||
dns_resolve,
|
||||
GetAddrInfo,
|
||||
};
|
||||
|
||||
module_info* modules[] = {
|
||||
|
||||
@@ -8,81 +8,133 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <port.h>
|
||||
#include <AutoDeleter.h>
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "Definitions.h"
|
||||
|
||||
|
||||
port_id gRequestPort;
|
||||
port_id gReplyPort;
|
||||
|
||||
|
||||
status_t
|
||||
resolve_dns(const char* host, uint32* addr)
|
||||
GetAddrInfo(const char* buffer)
|
||||
{
|
||||
addrinfo* ai;
|
||||
addrinfo* current;
|
||||
status_t result = getaddrinfo(host, NULL, NULL, &ai);
|
||||
const char* node = buffer[0] == '\0' ? NULL : buffer;
|
||||
uint32 nodeSize = node != NULL ? strlen(node) + 1 : 1;
|
||||
|
||||
const char* service = buffer[nodeSize] == '\0' ? NULL : buffer + nodeSize;
|
||||
uint32 serviceSize = service != NULL ? strlen(service) + 1 : 1;
|
||||
|
||||
const struct addrinfo* hints =
|
||||
reinterpret_cast<const addrinfo*>(buffer + nodeSize + serviceSize);
|
||||
|
||||
struct addrinfo* ai;
|
||||
status_t result = getaddrinfo(node, service, hints, &ai);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
return write_port(gReplyPort, MsgError, &result, sizeof(result));
|
||||
|
||||
current = ai;
|
||||
uint32 addrsSize = ai == NULL ? 0 : sizeof(addrinfo);
|
||||
uint32 namesSize = 0;
|
||||
uint32 socksSize = 0;
|
||||
|
||||
addrinfo* current = ai;
|
||||
while (current != NULL) {
|
||||
if (current->ai_family == AF_INET) {
|
||||
sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(current->ai_addr);
|
||||
*addr = sin->sin_addr.s_addr;
|
||||
freeaddrinfo(ai);
|
||||
return B_OK;
|
||||
if (current->ai_canonname != NULL)
|
||||
namesSize += strlen(current->ai_canonname) + 1;
|
||||
if (current->ai_addr != NULL) {
|
||||
if (current->ai_family == AF_INET)
|
||||
socksSize += sizeof(sockaddr_in);
|
||||
else
|
||||
socksSize += sizeof(sockaddr_in6);
|
||||
}
|
||||
|
||||
if (current->ai_next != NULL)
|
||||
addrsSize += sizeof(addrinfo);
|
||||
current = current->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return B_NAME_NOT_FOUND;
|
||||
uint32 totalSize = addrsSize + namesSize + socksSize;
|
||||
char* reply = reinterpret_cast<char*>(malloc(totalSize));
|
||||
if (reply == NULL) {
|
||||
free(reply);
|
||||
|
||||
result = B_NO_MEMORY;
|
||||
return write_port(gReplyPort, MsgError, &result, sizeof(result));
|
||||
}
|
||||
|
||||
uint32 addrPos = 0;
|
||||
uint32 namePos = addrsSize;
|
||||
uint32 sockPos = addrsSize + namesSize;
|
||||
|
||||
current = ai;
|
||||
while (current != NULL) {
|
||||
if (current->ai_canonname != NULL) {
|
||||
strcpy(reply + namePos, current->ai_canonname);
|
||||
uint32 nSize = strlen(current->ai_canonname) + 1;
|
||||
current->ai_canonname = reinterpret_cast<char*>(namePos);
|
||||
namePos += nSize;
|
||||
}
|
||||
if (current->ai_addr != NULL) {
|
||||
if (current->ai_family == AF_INET) {
|
||||
memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in));
|
||||
current->ai_addr = reinterpret_cast<sockaddr*>(sockPos);
|
||||
sockPos += sizeof(sockaddr_in);
|
||||
} else {
|
||||
memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in6));
|
||||
current->ai_addr = reinterpret_cast<sockaddr*>(sockPos);
|
||||
sockPos += sizeof(sockaddr_in6);
|
||||
}
|
||||
}
|
||||
|
||||
addrinfo* next = current->ai_next;
|
||||
current->ai_next = reinterpret_cast<addrinfo*>(addrPos) + 1;
|
||||
memcpy(reply + addrPos, current, sizeof(addrinfo));
|
||||
addrPos += sizeof(addrinfo);
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
return write_port(gReplyPort, MsgReply, reply, totalSize);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
main_loop(port_id portReq, port_id portRpl)
|
||||
MainLoop()
|
||||
{
|
||||
do {
|
||||
ssize_t size = port_buffer_size(portReq);
|
||||
ssize_t size = port_buffer_size(gRequestPort);
|
||||
if (size < B_OK)
|
||||
return 0;
|
||||
|
||||
void* buffer = malloc(size);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter _(buffer);
|
||||
|
||||
int32 code;
|
||||
status_t result = read_port(portReq, &code, buffer, size);
|
||||
if (size < B_OK) {
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (code != MsgResolveRequest) {
|
||||
free(buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 addr;
|
||||
result = resolve_dns(reinterpret_cast<char*>(buffer), &addr);
|
||||
free(buffer);
|
||||
|
||||
if (result == B_OK)
|
||||
result = write_port(portRpl, MsgResolveReply, &addr, sizeof(addr));
|
||||
else {
|
||||
result = write_port(portRpl, MsgResolveError, &result,
|
||||
sizeof(result));
|
||||
}
|
||||
|
||||
if (result == B_BAD_PORT_ID)
|
||||
size = read_port(gRequestPort, &code, buffer, size);
|
||||
if (size < B_OK)
|
||||
return 0;
|
||||
|
||||
status_t result;
|
||||
switch (code) {
|
||||
case MsgGetAddrInfo:
|
||||
result = GetAddrInfo(reinterpret_cast<char*>(buffer));
|
||||
default:
|
||||
result = B_BAD_VALUE;
|
||||
write_port(gReplyPort, MsgError, &result, sizeof(result));
|
||||
result = B_OK;
|
||||
}
|
||||
|
||||
if (result != B_OK)
|
||||
return 0;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
@@ -90,18 +142,18 @@ main_loop(port_id portReq, port_id portRpl)
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
port_id portReq = find_port(kPortNameReq);
|
||||
if (portReq == B_NAME_NOT_FOUND) {
|
||||
fprintf(stderr, "%s\n", strerror(portReq));
|
||||
return portReq;
|
||||
gRequestPort = find_port(kPortNameReq);
|
||||
if (gRequestPort < B_OK) {
|
||||
fprintf(stderr, "%s\n", strerror(gRequestPort));
|
||||
return gRequestPort;
|
||||
}
|
||||
|
||||
port_id portRpl = find_port(kPortNameRpl);
|
||||
if (portRpl == B_NAME_NOT_FOUND) {
|
||||
fprintf(stderr, "%s\n", strerror(portRpl));
|
||||
return portRpl;
|
||||
gReplyPort = find_port(kPortNameRpl);
|
||||
if (gReplyPort < B_OK) {
|
||||
fprintf(stderr, "%s\n", strerror(gReplyPort));
|
||||
return gReplyPort;
|
||||
}
|
||||
|
||||
return main_loop(portReq, portRpl);
|
||||
return MainLoop();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user