5c21c06ea555621970653f23049a3e832a75a6c9
[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 <stdlib.h>     // strtol
14 #include <acess/sys.h>
15
16 static const struct {
17         const char *Name;
18          int    SockType;
19          int    Protocol;
20          int    Port;
21 } caLocalServices[] = {
22         {"telnet", SOCK_STREAM, 0, 23},
23         {"http", SOCK_STREAM, 0, 80},
24 };
25 static const int ciNumLocalServices = sizeof(caLocalServices)/sizeof(caLocalServices[0]);
26
27 // === CODE ===
28 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
29 {
30         static const struct addrinfo    defhints = {
31                 .ai_family = AF_UNSPEC,
32                 .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG
33                 };
34         struct addrinfo *ret = NULL;
35
36         _SysDebug("getaddrinfo('%s','%s',%p,%p)", node, service, hints, res);
37
38         // Error checks
39         if( !node && !service ) return EAI_NONAME;
40         
41         if( !hints )
42                 hints = &defhints;
43
44         if( !node )
45         {
46                 if( !(hints->ai_flags & AI_PASSIVE) )
47                         ;       // Use localhost
48                 else
49                         ;       // Use wildcard
50         }
51         else
52         {
53                 // 1. Check if the node is an IP address
54                 {
55                          int    type;
56                         char    addrdata[16];
57                         type = Net_ParseAddress(node, addrdata);
58                         switch(type)
59                         {
60                         case 0:
61                                 break;
62                         case 4: // IPv4
63                                 ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
64                                 ret->ai_family = AF_INET;
65                                 ret->ai_socktype = 0;
66                                 ret->ai_protocol = 0;
67                                 ret->ai_addrlen = sizeof(struct in_addr);
68                                 ret->ai_addr = (void*)( ret + 1 );
69                                 ret->ai_canonname = 0;
70                                 ret->ai_next = 0;
71                                 ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
72                                 ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
73                                 memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
74                                 break;
75                         default:
76                                 _SysDebug("getaddrinfo: Unknown address family %i", type);
77                                 return 1;
78                         }
79                 }
80                 
81                 // 2. Check for a DNS name
82                 // - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
83                 if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
84                 {
85                         _SysDebug("getaddrinfo: TODO DNS Lookups");
86                         // TODO: DNS Lookups
87                         // ? /Acess/Conf/Nameservers
88                         // ? /Acess/Conf/Hosts
89                         //count = Net_LookupDNS(node, service, NULL);
90                         //
91                 }
92                 
93                 // 3. No Match, chuck sad
94                 if( !ret )
95                 {
96                         return EAI_NONAME;
97                 }
98         }
99
100         int default_socktype = hints->ai_socktype;
101         int default_protocol = hints->ai_protocol;
102         int default_port = 0;
103         
104         #if 0
105         if( default_protocol == 0 )
106         {
107                 switch(default_socktype)
108                 {
109                 case SOCK_DGRAM:
110                         default_protocol = 
111                 }
112         }
113         #endif
114         
115         // Convert `node` into types
116         if( service )
117         {
118                 const char *end;
119                 
120                 default_port = strtol(service, (char**)&end, 0);
121                 if( *end != '\0' && (hints->ai_flags & AI_NUMERICSERV) )
122                 {
123                         return EAI_NONAME;
124                 }
125                 
126                 if( *end != '\0' )
127                 {
128                         // TODO: Read something like /Acess/Conf/services
129                         for( int i = 0; i < ciNumLocalServices; i ++ )
130                         {
131                                 if( strcmp(service, caLocalServices[i].Name) == 0 ) {
132                                         end = service + strlen(service);
133                                         default_socktype = caLocalServices[i].SockType;
134                                         default_protocol = caLocalServices[i].Protocol;
135                                         default_port = caLocalServices[i].Port;
136                                         break;
137                                 }
138                         }
139                 }
140                 
141                 if( *end != '\0' )
142                 {
143                         _SysDebug("getaddrinfo: TODO Service translation");
144                 }
145         }
146
147         for( struct addrinfo *ai = ret; ai; ai = ai->ai_next)
148         {
149                 struct sockaddr_in      *in = (void*)ai->ai_addr;
150                 struct sockaddr_in6     *in6 = (void*)ai->ai_addr;
151                 
152                 // Check ai_socktype/ai_protocol
153                 // TODO: Do both of these need to be zero for defaults to apply?
154                 if( ai->ai_socktype == 0 )
155                         ai->ai_socktype = default_socktype;
156                 if( ai->ai_protocol == 0 )
157                         ai->ai_protocol = default_protocol;
158                 
159                 switch(ai->ai_family)
160                 {
161                 case AF_INET:
162                         if( in->sin_port == 0 )
163                                 in->sin_port = default_port;
164                         _SysDebug("%p: IPv4 [%s]:%i %i,%i",
165                                 ai, Net_PrintAddress(4, &in->sin_addr),
166                                 in->sin_port, ai->ai_socktype, ai->ai_protocol);
167                         break;
168                 case AF_INET6:
169                         if( in6->sin6_port == 0 )
170                                 in6->sin6_port = default_port;
171                         _SysDebug("%p: IPv6 [%s]:%i %i,%i",
172                                 ai, Net_PrintAddress(6, &in6->sin6_addr),
173                                 in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
174                         break;
175                 default:
176                         _SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
177                         return 1;
178                 }
179         }
180
181         *res = ret;
182         return 0;
183 }
184
185 void freeaddrinfo(struct addrinfo *res)
186 {
187         
188 }
189
190 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
191 {
192         // Determine hostname
193         if( host )
194         {
195                 if( hostlen == 0 )
196                         return EAI_OVERFLOW;
197                 host[0] = '\0';
198                 if( !(flags & NI_NUMERICHOST) )
199                 {
200                         // Handle NI_NOFQDN
201                 }
202                 // Numeric hostname or the hostname was unresolvable
203                 if( host[0] == '\0' )
204                 {
205                         if( (flags & NI_NAMEREQD) )
206                                 return EAI_NONAME;
207                 }
208         }
209         
210         // Determine service name
211         if( serv )
212         {
213                 if( servlen == 0 )
214                         return EAI_OVERFLOW;
215                 serv[0] = '\0';
216                 if( !(flags & NI_NUMERICSERV) )
217                 {
218                         // Handle NI_DGRAM
219                 }
220                 if( serv[0] == '\0' )
221                 {
222                         
223                 }
224         }
225         return EAI_SUCCESS;
226 }
227
228
229 const char *gai_strerror(int errnum)
230 {
231         switch(errnum)
232         {
233         case EAI_SUCCESS:       return "No error";
234         case EAI_FAIL:          return "Permanent resolution failure";
235         default:        return "UNKNOWN";
236         }
237 }
238
239 struct hostent *gethostbyname(const char *name)
240 {
241         return NULL;
242 }
243

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