xref: /haiku/src/add-ons/kernel/network/dns_resolver/server/main.cpp (revision 97f11716bfaa0f385eb0e28a52bf56a5023b9e99)
121769ef6SPawel Dziepak /*
221769ef6SPawel Dziepak  * Copyright 2012 Haiku, Inc. All rights reserved.
321769ef6SPawel Dziepak  * Distributed under the terms of the MIT License.
421769ef6SPawel Dziepak  *
521769ef6SPawel Dziepak  * Authors:
621769ef6SPawel Dziepak  *		Paweł Dziepak, pdziepak@quarnos.org
721769ef6SPawel Dziepak  */
821769ef6SPawel Dziepak 
921769ef6SPawel Dziepak 
101a3518cfSAugustin Cavalier #include <stdio.h>
1121769ef6SPawel Dziepak #include <stdlib.h>
129054c96cSPawel Dziepak #include <string.h>
1321769ef6SPawel Dziepak 
1421769ef6SPawel Dziepak #include <sys/socket.h>
1521769ef6SPawel Dziepak #include <netdb.h>
1621769ef6SPawel Dziepak 
179054c96cSPawel Dziepak #include <AutoDeleter.h>
189054c96cSPawel Dziepak #include <OS.h>
1921769ef6SPawel Dziepak #include <SupportDefs.h>
2021769ef6SPawel Dziepak 
2121769ef6SPawel Dziepak #include "Definitions.h"
2221769ef6SPawel Dziepak 
2321769ef6SPawel Dziepak 
249054c96cSPawel Dziepak port_id		gRequestPort;
259054c96cSPawel Dziepak port_id		gReplyPort;
269054c96cSPawel Dziepak 
279054c96cSPawel Dziepak 
2821769ef6SPawel Dziepak status_t
Serialize(char ** _reply,uint32 * _totalSize,const struct addrinfo * ai)29a4cdd6beSPawel Dziepak Serialize(char** _reply, uint32* _totalSize, const struct addrinfo* ai)
3021769ef6SPawel Dziepak {
319054c96cSPawel Dziepak 	uint32 addrsSize = ai == NULL ? 0 : sizeof(addrinfo);
329054c96cSPawel Dziepak 	uint32 namesSize = 0;
339054c96cSPawel Dziepak 	uint32 socksSize = 0;
3421769ef6SPawel Dziepak 
35a4cdd6beSPawel Dziepak 	const struct addrinfo* current = ai;
3621769ef6SPawel Dziepak 	while (current != NULL) {
379054c96cSPawel Dziepak 		if (current->ai_canonname != NULL)
389054c96cSPawel Dziepak 			namesSize += strlen(current->ai_canonname) + 1;
399054c96cSPawel Dziepak 		if (current->ai_addr != NULL) {
409054c96cSPawel Dziepak 			if (current->ai_family == AF_INET)
419054c96cSPawel Dziepak 				socksSize += sizeof(sockaddr_in);
429054c96cSPawel Dziepak 			else
439054c96cSPawel Dziepak 				socksSize += sizeof(sockaddr_in6);
4421769ef6SPawel Dziepak 		}
459054c96cSPawel Dziepak 		if (current->ai_next != NULL)
469054c96cSPawel Dziepak 			addrsSize += sizeof(addrinfo);
4721769ef6SPawel Dziepak 		current = current->ai_next;
4821769ef6SPawel Dziepak 	}
4921769ef6SPawel Dziepak 
509054c96cSPawel Dziepak 	uint32 totalSize = addrsSize + namesSize + socksSize;
519054c96cSPawel Dziepak 	char* reply = reinterpret_cast<char*>(malloc(totalSize));
52a4cdd6beSPawel Dziepak 	if (reply == NULL)
53a4cdd6beSPawel Dziepak 		return B_NO_MEMORY;
549054c96cSPawel Dziepak 
559054c96cSPawel Dziepak 	uint32 addrPos = 0;
569054c96cSPawel Dziepak 	uint32 namePos = addrsSize;
579054c96cSPawel Dziepak 	uint32 sockPos = addrsSize + namesSize;
589054c96cSPawel Dziepak 
59a4cdd6beSPawel Dziepak 	struct addrinfo temp;
60a4cdd6beSPawel Dziepak 
619054c96cSPawel Dziepak 	current = ai;
629054c96cSPawel Dziepak 	while (current != NULL) {
63a4cdd6beSPawel Dziepak 		memcpy(&temp, current, sizeof(addrinfo));
64a4cdd6beSPawel Dziepak 
659054c96cSPawel Dziepak 		if (current->ai_canonname != NULL) {
669054c96cSPawel Dziepak 			strcpy(reply + namePos, current->ai_canonname);
679054c96cSPawel Dziepak 			uint32 nSize = strlen(current->ai_canonname) + 1;
68a4cdd6beSPawel Dziepak 			temp.ai_canonname = reinterpret_cast<char*>(namePos);
699054c96cSPawel Dziepak 			namePos += nSize;
709054c96cSPawel Dziepak 		}
719054c96cSPawel Dziepak 		if (current->ai_addr != NULL) {
729054c96cSPawel Dziepak 			if (current->ai_family == AF_INET) {
739054c96cSPawel Dziepak 				memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in));
74a4cdd6beSPawel Dziepak 				temp.ai_addr = reinterpret_cast<sockaddr*>(sockPos);
759054c96cSPawel Dziepak 				sockPos += sizeof(sockaddr_in);
769054c96cSPawel Dziepak 			} else {
779054c96cSPawel Dziepak 				memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in6));
78a4cdd6beSPawel Dziepak 				temp.ai_addr = reinterpret_cast<sockaddr*>(sockPos);
799054c96cSPawel Dziepak 				sockPos += sizeof(sockaddr_in6);
809054c96cSPawel Dziepak 			}
819054c96cSPawel Dziepak 		}
829054c96cSPawel Dziepak 
839054c96cSPawel Dziepak 		addrinfo* next = current->ai_next;
84cd2c1203SPawel Dziepak 		if (next != NULL)
85a4cdd6beSPawel Dziepak 			temp.ai_next = reinterpret_cast<addrinfo*>(addrPos) + 1;
86a4cdd6beSPawel Dziepak 		else
87a4cdd6beSPawel Dziepak 			temp.ai_next = NULL;
88a4cdd6beSPawel Dziepak 
89a4cdd6beSPawel Dziepak 		memcpy(reply + addrPos, &temp, sizeof(addrinfo));
909054c96cSPawel Dziepak 		addrPos += sizeof(addrinfo);
919054c96cSPawel Dziepak 
929054c96cSPawel Dziepak 		current = next;
939054c96cSPawel Dziepak 	}
949054c96cSPawel Dziepak 
95a4cdd6beSPawel Dziepak 	*_reply = reply;
96a4cdd6beSPawel Dziepak 	*_totalSize = totalSize;
97a4cdd6beSPawel Dziepak 	return B_OK;
98a4cdd6beSPawel Dziepak }
99a4cdd6beSPawel Dziepak 
100a4cdd6beSPawel Dziepak 
101a4cdd6beSPawel Dziepak status_t
GetAddrInfo(const char * buffer)102a4cdd6beSPawel Dziepak GetAddrInfo(const char* buffer)
103a4cdd6beSPawel Dziepak {
104a4cdd6beSPawel Dziepak 	const char* node = buffer[0] == '\0' ? NULL : buffer;
105a4cdd6beSPawel Dziepak 	uint32 nodeSize = node != NULL ? strlen(node) + 1 : 1;
106a4cdd6beSPawel Dziepak 
107a4cdd6beSPawel Dziepak 	const char* service = buffer[nodeSize] == '\0' ? NULL : buffer + nodeSize;
108a4cdd6beSPawel Dziepak 	uint32 serviceSize = service != NULL ? strlen(service) + 1 : 1;
109a4cdd6beSPawel Dziepak 
110a4cdd6beSPawel Dziepak 	const struct addrinfo* hints
111a4cdd6beSPawel Dziepak 		= reinterpret_cast<const addrinfo*>(buffer + nodeSize + serviceSize);
112a4cdd6beSPawel Dziepak 
113a4cdd6beSPawel Dziepak 	struct addrinfo* ai;
114a4cdd6beSPawel Dziepak 	status_t result = getaddrinfo(node, service, hints, &ai);
115a4cdd6beSPawel Dziepak 	if (result != B_OK)
116a4cdd6beSPawel Dziepak 		return write_port(gReplyPort, MsgError, &result, sizeof(result));
117a4cdd6beSPawel Dziepak 
118a4cdd6beSPawel Dziepak 	uint32 totalSize;
119a4cdd6beSPawel Dziepak 	char* reply;
120a4cdd6beSPawel Dziepak 	result = Serialize(&reply, &totalSize, ai);
121a4cdd6beSPawel Dziepak 	freeaddrinfo(ai);
122a4cdd6beSPawel Dziepak 	if (result != B_OK)
123a4cdd6beSPawel Dziepak 		return write_port(gReplyPort, MsgError, &result, sizeof(result));
124*ee96bcfeSMurai Takashi 	result = write_port(gReplyPort, MsgReply, reply, totalSize);
125*ee96bcfeSMurai Takashi 	free(reply);
126*ee96bcfeSMurai Takashi 	return result;
12721769ef6SPawel Dziepak }
12821769ef6SPawel Dziepak 
12921769ef6SPawel Dziepak 
13021769ef6SPawel Dziepak status_t
MainLoop()1319054c96cSPawel Dziepak MainLoop()
13221769ef6SPawel Dziepak {
13321769ef6SPawel Dziepak 	do {
1349054c96cSPawel Dziepak 		ssize_t size = port_buffer_size(gRequestPort);
13521769ef6SPawel Dziepak 		if (size < B_OK)
13621769ef6SPawel Dziepak 			return 0;
13721769ef6SPawel Dziepak 
13821769ef6SPawel Dziepak 		void* buffer = malloc(size);
13921769ef6SPawel Dziepak 		if (buffer == NULL)
14021769ef6SPawel Dziepak 			return B_NO_MEMORY;
1419054c96cSPawel Dziepak 		MemoryDeleter _(buffer);
14221769ef6SPawel Dziepak 
14321769ef6SPawel Dziepak 		int32 code;
1449054c96cSPawel Dziepak 		size = read_port(gRequestPort, &code, buffer, size);
1459054c96cSPawel Dziepak 		if (size < B_OK)
14621769ef6SPawel Dziepak 			return 0;
14721769ef6SPawel Dziepak 
1489054c96cSPawel Dziepak 		status_t result;
1499054c96cSPawel Dziepak 		switch (code) {
1509054c96cSPawel Dziepak 			case MsgGetAddrInfo:
1519054c96cSPawel Dziepak 				result = GetAddrInfo(reinterpret_cast<char*>(buffer));
1524a35186aSAugustin Cavalier 				break;
1534a35186aSAugustin Cavalier 
1549054c96cSPawel Dziepak 			default:
1559054c96cSPawel Dziepak 				result = B_BAD_VALUE;
1569054c96cSPawel Dziepak 				write_port(gReplyPort, MsgError, &result, sizeof(result));
1579054c96cSPawel Dziepak 				result = B_OK;
1589054c96cSPawel Dziepak 		}
1599054c96cSPawel Dziepak 
1609054c96cSPawel Dziepak 		if (result != B_OK)
1619054c96cSPawel Dziepak 			return 0;
16221769ef6SPawel Dziepak 	} while (true);
16321769ef6SPawel Dziepak }
16421769ef6SPawel Dziepak 
16521769ef6SPawel Dziepak 
16621769ef6SPawel Dziepak int
main(int argc,char ** argv)16721769ef6SPawel Dziepak main(int argc, char** argv)
16821769ef6SPawel Dziepak {
1699054c96cSPawel Dziepak 	gRequestPort = find_port(kPortNameReq);
1709054c96cSPawel Dziepak 	if (gRequestPort < B_OK) {
1719054c96cSPawel Dziepak 		fprintf(stderr, "%s\n", strerror(gRequestPort));
1729054c96cSPawel Dziepak 		return gRequestPort;
17321769ef6SPawel Dziepak 	}
17421769ef6SPawel Dziepak 
1759054c96cSPawel Dziepak 	gReplyPort = find_port(kPortNameRpl);
1769054c96cSPawel Dziepak 	if (gReplyPort < B_OK) {
1779054c96cSPawel Dziepak 		fprintf(stderr, "%s\n", strerror(gReplyPort));
1789054c96cSPawel Dziepak 		return gReplyPort;
17921769ef6SPawel Dziepak 	}
18021769ef6SPawel Dziepak 
1819054c96cSPawel Dziepak 	return MainLoop();
18221769ef6SPawel Dziepak }
18321769ef6SPawel Dziepak 
184