Add dns_resolver module

dns_resolver module provides a means for all kernel mode code to resolve
DNS hostnames.
This commit is contained in:
Pawel Dziepak 2012-06-19 03:20:39 +02:00
parent 5fb2be8872
commit 21769ef603
11 changed files with 368 additions and 0 deletions

View File

@ -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 ;

View File

@ -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
: <net>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

View File

@ -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 <module.h>
#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

View File

@ -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 ;

View File

@ -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

View File

@ -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 ;

View File

@ -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
;

View File

@ -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 <net/dns_resolver.h>
#include <FindDirectory.h>
#include <lock.h>
#include <port.h>
#include <team.h>
#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<dev_t>(-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
};

View File

@ -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
;

View File

@ -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"
};

View File

@ -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 <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <port.h>
#include <SupportDefs.h>
#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<sockaddr_in*>(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<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)
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);
}