Merge branch 'master' of git://cadel.mutabah.net/acess2
[tpg/acess2.git] / Usermode / Libraries / libpsocket.so_src / getaddrinfo.c
1 /*
2  * Acess2 POSIX Sockets Library
3  * - By John Hodge (thePowersGang)
4  *
5  * getaddrinfo.c
6  * - getaddrinfo/freeaddrinfo/getnameinfo/gai_strerror
7  */
8 #include <netdb.h>
9 #include <netinet/in.h>
10 #include <net.h>        // Net_ParseAddress
11 #include <stdlib.h>     // malloc
12 #include <string.h>     // memcpy
13 #include <acess/sys.h>
14
15 // === CODE ===
16 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
17 {
18         static const struct addrinfo    defhints = {.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG};
19         struct addrinfo *ret = NULL;
20
21         // Error checks
22         if( !node && !service ) return EAI_NONAME;
23         
24         if( !hints )
25                 hints = &defhints;
26
27         if( !node )
28         {
29                 if( !(hints->ai_flags & AI_PASSIVE) )
30                         ;       // Use localhost
31                 else
32                         ;       // Use wildcard
33         }
34         else
35         {
36                 // 1. Check if the node is an IP address
37                 // TODO: Break this function out into inet_pton?
38                 {
39                          int    type;
40                         char    addrdata[16];
41                         type = Net_ParseAddress(node, addrdata);
42                         switch(type)
43                         {
44                         case 0:
45                                 break;
46                         case 4: // IPv4
47                                 ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
48                                 ret->ai_family = AF_INET;
49                                 ret->ai_socktype = 0;
50                                 ret->ai_protocol = 0;
51                                 ret->ai_addrlen = sizeof(struct in_addr);
52                                 ret->ai_addr = (void*)( ret + 1 );
53                                 ret->ai_canonname = 0;
54                                 ret->ai_next = 0;
55                                 ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
56                                 ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
57                                 memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
58                                 break;
59                         default:
60                                 _SysDebug("getaddrinfo: Unknown address family %i", type);
61                                 return 1;
62                         }
63                 }
64                 
65                 // 2. Check for a DNS name
66                 // - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
67                 if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
68                 {
69                         // TODO: DNS Lookups
70                         // ? /Acess/Conf/Nameservers
71                         // ? /Acess/Conf/Hosts
72                 }
73                 
74                 // 3. No Match, chuck sad
75                 if( !ret )
76                 {
77                         return EAI_NONAME;
78                 }
79         }
80
81         int default_socktype = 0;
82         int default_protocol = 0;
83         int default_port = 0;
84         
85         // Convert `node` into types
86         if( service )
87         {
88                 // TODO: Read something like /Acess/Conf/services
89         }
90
91         struct addrinfo *ai;
92         for( ai = ret; ai; ai = ai->ai_next)
93         {
94                 struct sockaddr_in      *in = (void*)ai->ai_addr;
95                 struct sockaddr_in6     *in6 = (void*)ai->ai_addr;
96                 
97                 // Check ai_socktype/ai_protocol
98                 // TODO: Do both of these need to be zero for defaults to apply?
99                 if( ai->ai_socktype == 0 )
100                         ai->ai_socktype = default_socktype;
101                 if( ai->ai_protocol == 0 )
102                         ai->ai_protocol = default_protocol;
103                 
104                 switch(ai->ai_family)
105                 {
106                 case AF_INET:
107                         if( in->sin_port == 0 )
108                                 in->sin_port = default_port;
109                         break;
110                 case AF_INET6:
111                         if( in6->sin6_port == 0 )
112                                 in6->sin6_port = default_port;
113                         break;
114                 default:
115                         _SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
116                         return 1;
117                 }
118         }
119
120         *res = ret;
121         return 0;
122 }
123
124 void freeaddrinfo(struct addrinfo *res)
125 {
126         
127 }
128
129 const char *gai_strerror(int errnum)
130 {
131         switch(errnum)
132         {
133         case EAI_SUCCESS:       return "No error";
134         case EAI_FAIL:          return "Permanent resolution failure";
135         default:        return "UNKNOWN";
136         }
137 }
138

UCC git Repository :: git.ucc.asn.au