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