From 21769ef60394a854df725a2ad2ca995c4daa2042 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 19 Jun 2012 03:20:39 +0200 Subject: [PATCH] Add dns_resolver module dns_resolver module provides a means for all kernel mode code to resolve DNS hostnames. --- build/jam/BuildSetup | 1 + build/jam/HaikuImage | 2 + headers/private/net/dns_resolver.h | 25 +++ src/add-ons/kernel/network/Jamfile | 1 + .../kernel/network/dns_resolver/Definitions.h | 23 +++ .../kernel/network/dns_resolver/Jamfile | 4 + .../dns_resolver/kernel_add_on/Jamfile | 9 + .../kernel_add_on/dns_resolver.cpp | 160 ++++++++++++++++++ .../network/dns_resolver/server/Jamfile | 16 ++ .../server/dns_resolver_server.rdef | 20 +++ .../network/dns_resolver/server/main.cpp | 107 ++++++++++++ 11 files changed, 368 insertions(+) create mode 100644 headers/private/net/dns_resolver.h create mode 100644 src/add-ons/kernel/network/dns_resolver/Definitions.h create mode 100644 src/add-ons/kernel/network/dns_resolver/Jamfile create mode 100644 src/add-ons/kernel/network/dns_resolver/kernel_add_on/Jamfile create mode 100644 src/add-ons/kernel/network/dns_resolver/kernel_add_on/dns_resolver.cpp create mode 100644 src/add-ons/kernel/network/dns_resolver/server/Jamfile create mode 100644 src/add-ons/kernel/network/dns_resolver/server/dns_resolver_server.rdef create mode 100644 src/add-ons/kernel/network/dns_resolver/server/main.cpp diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index b6fbcc1c5b..9136f0ddb7 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -1297,6 +1297,7 @@ if $(HAIKU_NO_WERROR) != 1 { EnableWerror src add-ons kernel generic ; # EnableWerror src add-ons kernel network datalink_protocols ; EnableWerror src add-ons kernel network devices ; + EnableWerror src add-ons kernel network dns_resolver ; EnableWerror src add-ons kernel network notifications ; EnableWerror src add-ons kernel network ppp ; EnableWerror src add-ons kernel network protocols ; diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 0f44294dcd..0d2714b10b 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -106,6 +106,7 @@ PRIVATE_SYSTEM_LIBS = SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon media_addon_server media_server midi_server mount_server net_server notification_server power_daemon print_server print_addon_server registrar syslog_daemon + dns_resolver_server ; SYSTEM_NETWORK_DEVICES = ethernet loopback ; @@ -651,6 +652,7 @@ AddFilesToHaikuImage system add-ons input_server filters : screen_saver shortcut_catcher ; AddFilesToHaikuImage system add-ons kernel network : notifications stack ; +AddFilesToHaikuImage system add-ons kernel network : dns_resolver ; AddFilesToHaikuImage system add-ons kernel network devices : $(SYSTEM_NETWORK_DEVICES) ; AddFilesToHaikuImage system add-ons kernel network datalink_protocols diff --git a/headers/private/net/dns_resolver.h b/headers/private/net/dns_resolver.h new file mode 100644 index 0000000000..179e9c2fe2 --- /dev/null +++ b/headers/private/net/dns_resolver.h @@ -0,0 +1,25 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef DNS_RESOLVER_H +#define DNS_RESOLVER_H + + +#include + + +#define DNS_RESOLVER_MODULE_NAME "network/dns_resolver/v1" + + +struct dns_resolver_module { + module_info module; + status_t (*dns_resolve)(const char* host, uint32* addr); +}; + + +#endif // DNS_RESOLVER_H + diff --git a/src/add-ons/kernel/network/Jamfile b/src/add-ons/kernel/network/Jamfile index 66d4448e41..7667873344 100644 --- a/src/add-ons/kernel/network/Jamfile +++ b/src/add-ons/kernel/network/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel network ; SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ; SubInclude HAIKU_TOP src add-ons kernel network devices ; +SubInclude HAIKU_TOP src add-ons kernel network dns_resolver ; SubInclude HAIKU_TOP src add-ons kernel network notifications ; SubInclude HAIKU_TOP src add-ons kernel network protocols ; SubInclude HAIKU_TOP src add-ons kernel network stack ; diff --git a/src/add-ons/kernel/network/dns_resolver/Definitions.h b/src/add-ons/kernel/network/dns_resolver/Definitions.h new file mode 100644 index 0000000000..407b2a436c --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/Definitions.h @@ -0,0 +1,23 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + + +const char* kPortNameReq = "dns_resolver_req"; +const char* kPortNameRpl = "dns_resolver_rpl"; + +enum MsgCodes { + MsgResolveRequest = 1, + MsgResolveReply = 2, + MsgResolveError = 3 +}; + + +#endif // DEFINITIONS_H + diff --git a/src/add-ons/kernel/network/dns_resolver/Jamfile b/src/add-ons/kernel/network/dns_resolver/Jamfile new file mode 100644 index 0000000000..8dcbbeb2ea --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/Jamfile @@ -0,0 +1,4 @@ +SubDir HAIKU_TOP src add-ons kernel network dns_resolver ; + +SubInclude HAIKU_TOP src add-ons kernel network dns_resolver kernel_add_on ; +SubInclude HAIKU_TOP src add-ons kernel network dns_resolver server ; diff --git a/src/add-ons/kernel/network/dns_resolver/kernel_add_on/Jamfile b/src/add-ons/kernel/network/dns_resolver/kernel_add_on/Jamfile new file mode 100644 index 0000000000..30bc8c5a89 --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/kernel_add_on/Jamfile @@ -0,0 +1,9 @@ +SubDir HAIKU_TOP src add-ons kernel network dns_resolver kernel_add_on ; + +UsePrivateKernelHeaders ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; + +KernelAddon dns_resolver : + dns_resolver.cpp +; diff --git a/src/add-ons/kernel/network/dns_resolver/kernel_add_on/dns_resolver.cpp b/src/add-ons/kernel/network/dns_resolver/kernel_add_on/dns_resolver.cpp new file mode 100644 index 0000000000..121c08c6c7 --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/kernel_add_on/dns_resolver.cpp @@ -0,0 +1,160 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include + +#include +#include +#include +#include + +#include "Definitions.h" + + +static mutex gPortLock; +static port_id gPortRequest = -1; +static port_id gPortReply = -1; + +static const int32 kQueueLength = 1; + + +static status_t +dns_resolver_repair() +{ + status_t result = B_OK; + + gPortRequest = create_port(kQueueLength, kPortNameReq); + if (gPortRequest < B_OK) + return gPortRequest; + + gPortReply = create_port(kQueueLength, kPortNameRpl); + if (gPortReply < B_OK) { + delete_port(gPortRequest); + return gPortReply; + } + + char path[256]; + if (find_directory(B_SYSTEM_SERVERS_DIRECTORY, static_cast(-1), + false, path, sizeof(path)) != B_OK) { + delete_port(gPortReply); + delete_port(gPortRequest); + return B_NAME_NOT_FOUND; + } + strlcat(path, "/dns_resolver_server", sizeof(path)); + + const char* args[] = { path, NULL }; + thread_id thread = load_image_etc(1, args, NULL, B_NORMAL_PRIORITY, + B_SYSTEM_TEAM, 0); + if (thread < B_OK) { + delete_port(gPortReply); + delete_port(gPortRequest); + return thread; + } + + set_port_owner(gPortRequest, thread); + set_port_owner(gPortReply, thread); + + result = resume_thread(thread); + if (result != B_OK) { + kill_thread(thread); + delete_port(gPortReply); + delete_port(gPortRequest); + return result; + } + + return B_OK; +} + + +static status_t +dns_resolver_init() +{ + mutex_init(&gPortLock, NULL); + return dns_resolver_repair(); +} + + +static status_t +dns_resolver_uninit() +{ + delete_port(gPortRequest); + delete_port(gPortReply); + mutex_destroy(&gPortLock); + + return B_OK; +} + + +static status_t +dns_resolve(const char* host, uint32* addr) +{ + mutex_lock(&gPortLock); + do { + status_t result = write_port(gPortRequest, MsgResolveRequest, host, + strlen(host) + 1); + if (result != B_OK) { + result = dns_resolver_repair(); + if (result != B_OK) { + mutex_unlock(&gPortLock); + return result; + } + + continue; + } + + int32 code; + result = read_port(gPortReply, &code, addr, sizeof(*addr)); + if (result < B_OK) { + result = dns_resolver_repair(); + if (result != B_OK) { + mutex_unlock(&gPortLock); + return result; + } + + continue; + } + mutex_unlock(&gPortLock); + + if (code == MsgResolveReply) + return B_OK; + else + return *addr; + + } while (true); +} + + +static status_t +dns_resolver_std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + return dns_resolver_init(); + case B_MODULE_UNINIT: + return dns_resolver_uninit(); + default: + return B_ERROR; + } +} + +static dns_resolver_module sDNSResolverModule = { + { + DNS_RESOLVER_MODULE_NAME, + 0, + dns_resolver_std_ops, + }, + + dns_resolve, +}; + +module_info* modules[] = { + (module_info*)&sDNSResolverModule, + NULL +}; + diff --git a/src/add-ons/kernel/network/dns_resolver/server/Jamfile b/src/add-ons/kernel/network/dns_resolver/server/Jamfile new file mode 100644 index 0000000000..e2fbbaad61 --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/server/Jamfile @@ -0,0 +1,16 @@ +SubDir HAIKU_TOP src add-ons kernel network dns_resolver server ; + +UsePrivateKernelHeaders ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; + +Application dns_resolver_server + : + main.cpp + + : + be $(TARGET_NETWORK_LIBS) + + : + dns_resolver_server.rdef +; diff --git a/src/add-ons/kernel/network/dns_resolver/server/dns_resolver_server.rdef b/src/add-ons/kernel/network/dns_resolver/server/dns_resolver_server.rdef new file mode 100644 index 0000000000..e0a0df5a41 --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/server/dns_resolver_server.rdef @@ -0,0 +1,20 @@ +/* + * dns_resolver_server.rdef + */ + +resource app_signature "application/x-vnd.Haiku-dns-resolver-server"; + +resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + variety = B_APPV_ALPHA, + internal = 0, + + short_info = "dns_resolver_server", + long_info = "dns_resolver_server ©2012 Haiku, Inc" +}; + diff --git a/src/add-ons/kernel/network/dns_resolver/server/main.cpp b/src/add-ons/kernel/network/dns_resolver/server/main.cpp new file mode 100644 index 0000000000..3b4a14ef19 --- /dev/null +++ b/src/add-ons/kernel/network/dns_resolver/server/main.cpp @@ -0,0 +1,107 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include + +#include +#include + +#include +#include + +#include "Definitions.h" + + +status_t +resolve_dns(const char* host, uint32* addr) +{ + addrinfo* ai; + addrinfo* current; + status_t result = getaddrinfo(host, NULL, NULL, &ai); + if (result != B_OK) + return result; + + current = ai; + + while (current != NULL) { + if (current->ai_family == AF_INET) { + sockaddr_in* sin = reinterpret_cast(current->ai_addr); + *addr = sin->sin_addr.s_addr; + freeaddrinfo(ai); + return B_OK; + } + + current = current->ai_next; + } + + freeaddrinfo(ai); + return B_NAME_NOT_FOUND; +} + + +status_t +main_loop(port_id portReq, port_id portRpl) +{ + do { + ssize_t size = port_buffer_size(portReq); + if (size < B_OK) + return 0; + + void* buffer = malloc(size); + if (buffer == NULL) + return B_NO_MEMORY; + + 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(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) + return 0; + + } while (true); +} + + +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; + } + + port_id portRpl = find_port(kPortNameRpl); + if (portRpl == B_NAME_NOT_FOUND) { + fprintf(stderr, "%s\n", strerror(portRpl)); + return portRpl; + } + + return main_loop(portReq, portRpl); +} +