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

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