1 /***************************************************************************
2     begin       : Tue Oct 02 2002
3     copyright   : (C) 2019 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include "inetaddr_p.h"
31 #include <gwenhywfar/misc.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <netdb.h>
35 #include <string.h>
36 #include <sys/un.h>
37 #include <arpa/inet.h>
38 
39 #include "gwenhywfar/debug.h"
40 
41 /* #define MEMTRACE */
42 
43 /* needed for Solaris */
44 #ifndef SUN_LEN
45 # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
46   + strlen ((ptr)->sun_path))
47 #endif
48 
49 
50 #ifdef MEMTRACE
51 static int GWEN_INETADDR__Counter=0;
52 #endif
53 
54 
55 
56 /* ------------------------------------------------------------------------------------------------
57  * forward declarations
58  * ------------------------------------------------------------------------------------------------
59  */
60 
61 static int GWEN_InetAddr_TranslateHError(int herr);
62 
63 
64 
65 /* ------------------------------------------------------------------------------------------------
66  * implementations
67  * ------------------------------------------------------------------------------------------------
68  */
69 
70 
71 
GWEN_InetAddr_GetCapabilities(void)72 uint32_t GWEN_InetAddr_GetCapabilities(void)
73 {
74   return
75     GWEN_INETADDR_CAPS_AF_TCP |
76     GWEN_INETADDR_CAPS_AF_UNIX;
77 }
78 
79 
80 
GWEN_InetAddr_ModuleInit(void)81 int GWEN_InetAddr_ModuleInit(void)
82 {
83   return 0;
84 }
85 
86 
87 
GWEN_InetAddr_ModuleFini(void)88 int GWEN_InetAddr_ModuleFini(void)
89 {
90   return 0;
91 }
92 
93 
94 
GWEN_InetAddr_new(GWEN_AddressFamily af)95 GWEN_INETADDRESS *GWEN_InetAddr_new(GWEN_AddressFamily af)
96 {
97   GWEN_INETADDRESS *ia;
98 
99   GWEN_NEW_OBJECT(GWEN_INETADDRESS, ia);
100 
101   ia->af=af;
102   switch (ia->af) {
103   case GWEN_AddressFamilyIP: {
104     struct sockaddr_in *aptr;
105 
106     ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr_in));
107     assert(ia->address);
108     aptr=(struct sockaddr_in *)(ia->address);
109     ia->size=sizeof(struct sockaddr_in);
110     memset(ia->address, 0, ia->size);
111 #ifdef PF_INET
112     aptr->sin_family=PF_INET;
113 #else
114     aptr->sin_family=AF_INET;
115 #endif
116     break;
117   }
118 
119   case GWEN_AddressFamilyUnix: {
120     struct sockaddr_un *aptr;
121 
122     ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr_un));
123     assert(ia->address);
124     aptr=(struct sockaddr_un *)(ia->address);
125 #if defined(PF_UNIX)
126     aptr->sun_family=PF_UNIX;
127 #elif defined (AF_UNIX)
128     aptr->sun_family=AF_UNIX;
129 #else
130     DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
131     GWEN_InetAddr_free(ia);
132     return 0;
133 #endif
134     aptr->sun_path[0]=0;
135     ia->size=sizeof(struct sockaddr_un);
136     memset(ia->address, 0, ia->size);
137     break;
138   }
139 
140   default:
141     DBG_INFO(GWEN_LOGDOMAIN, "Unknown address family (%d)", af);
142     assert(0);
143   } /* switch */
144 #ifdef MEMTRACE
145   GWEN_INETADDR__Counter++;
146   DBG_INFO(GWEN_LOGDOMAIN, "InetAddr created, now %d", GWEN_INETADDR__Counter);
147 #endif
148   return ia;
149 }
150 
151 
152 
GWEN_InetAddr_dup(const GWEN_INETADDRESS * oa)153 GWEN_INETADDRESS *GWEN_InetAddr_dup(const GWEN_INETADDRESS *oa)
154 {
155   GWEN_INETADDRESS *ia;
156 
157   GWEN_NEW_OBJECT(GWEN_INETADDRESS, ia);
158   ia->af=oa->af;
159   ia->size=oa->size;
160   //ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr));
161   if (oa->size) {
162     ia->address=(struct sockaddr *)malloc(oa->size);
163     assert(ia->address);
164     memmove(ia->address, oa->address, oa->size);
165   }
166   return ia;
167 }
168 
169 
170 
GWEN_InetAddr_free(GWEN_INETADDRESS * ia)171 void GWEN_InetAddr_free(GWEN_INETADDRESS *ia)
172 {
173   if (ia) {
174 #ifdef MEMTRACE
175     GWEN_INETADDR__Counter--;
176     DBG_INFO(GWEN_LOGDOMAIN, "Free InetAddr, makes %d", GWEN_INETADDR__Counter);
177 #endif
178     free(ia->address);
179     GWEN_FREE_OBJECT(ia);
180   }
181 }
182 
183 
184 
GWEN_InetAddr_SetAddress(GWEN_INETADDRESS * ia,const char * addr)185 int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia,
186                              const char *addr)
187 {
188   assert(ia);
189 
190   switch (ia->af) {
191   case GWEN_AddressFamilyIP: {
192     struct sockaddr_in *aptr;
193 
194     aptr=(struct sockaddr_in *)(ia->address);
195     /* reset */
196 #ifdef PF_INET
197     aptr->sin_family=PF_INET;
198 #elif defined (AF_INET)
199     aptr->sun_family=AF_INET;
200 #else
201     DBG_ERROR(GWEN_LOGDOMAIN, "No TCP sockets available for this system");
202     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
203 #endif
204     aptr->sin_addr.s_addr=0;
205 
206     if (addr) {
207       /* ok, address to be set */
208       if (!inet_aton(addr, &aptr->sin_addr))
209         /* bad address, so maybe it rather is a name */
210         return GWEN_ERROR_BAD_ADDRESS;
211     }
212     break;
213   }
214 
215   case GWEN_AddressFamilyUnix: {
216     struct sockaddr_un *aptr;
217 
218     aptr=(struct sockaddr_un *)(ia->address);
219 #ifdef PF_UNIX
220     aptr->sun_family=PF_UNIX;
221 #elif defined (AF_UNIX)
222     aptr->sun_family=AF_UNIX;
223 #else
224     DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
225     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
226 #endif
227     memset(aptr->sun_path, 0, sizeof(aptr->sun_path));
228     if (addr) {
229       /* ok, address to be set */
230       if ((strlen(addr)+1)>sizeof(aptr->sun_path)) {
231         /* bad address */
232         DBG_INFO(GWEN_LOGDOMAIN, "Path too long (%d>%d)",
233                  (int)(strlen(addr)+1), (int)(sizeof(aptr->sun_path)));
234         return GWEN_ERROR_BAD_ADDRESS;
235       }
236       strcpy(aptr->sun_path, addr);
237       ia->size=SUN_LEN(aptr);
238     }
239     break;
240   }
241   default:
242     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
243   } /* switch */
244 
245   return 0;
246 }
247 
248 
249 
250 /* internal function */
GWEN_InetAddr_TranslateHError(int herr)251 int GWEN_InetAddr_TranslateHError(int herr)
252 {
253   int rv;
254 
255   switch (herr) {
256   case HOST_NOT_FOUND:
257     rv=GWEN_ERROR_HOST_NOT_FOUND;
258     break;
259 #ifdef NO_ADDRESS
260   case NO_ADDRESS:
261     rv=GWEN_ERROR_NO_ADDRESS;
262     break;
263 #endif
264   case NO_RECOVERY:
265     rv=GWEN_ERROR_NO_RECOVERY;
266     break;
267   case TRY_AGAIN:
268     rv=GWEN_ERROR_TRY_AGAIN;
269     break;
270   default:
271     rv=GWEN_ERROR_UNKNOWN_DNS_ERROR;
272     break;
273   } /* switch */
274   return rv;
275 }
276 
277 
278 
GWEN_InetAddr_SetName(GWEN_INETADDRESS * ia,const char * name)279 int GWEN_InetAddr_SetName(GWEN_INETADDRESS *ia, const char *name)
280 {
281   struct hostent *he;
282 
283   assert(ia);
284 
285   switch (ia->af) {
286   case GWEN_AddressFamilyIP: {
287     struct sockaddr_in *aptr;
288 
289     aptr=(struct sockaddr_in *)(ia->address);
290     /* try to resolve name */
291     he=gethostbyname(name);
292     if (!he)
293       return GWEN_InetAddr_TranslateHError(h_errno);
294     /* name resolved, store address */
295     memcpy(&(aptr->sin_addr),
296            he->h_addr_list[0],
297            sizeof(struct in_addr));
298     break;
299   }
300 
301   case GWEN_AddressFamilyUnix: {
302     struct sockaddr_un *aptr;
303 
304     aptr=(struct sockaddr_un *)(ia->address);
305 #ifdef PF_UNIX
306     aptr->sun_family=PF_UNIX;
307 #elif defined (AF_UNIX)
308     aptr->sun_family=AF_UNIX;
309 #else
310     DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
311     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
312 #endif
313     aptr->sun_path[0]=0;
314 
315     if (name) {
316       /* ok, address to be set */
317       if ((strlen(name)+1)>sizeof(aptr->sun_path)) {
318         /* bad address */
319         DBG_INFO(GWEN_LOGDOMAIN, "Path too long (%d>%d)",
320                  (int)(strlen(name)+1), (int)(sizeof(aptr->sun_path)));
321         return GWEN_ERROR_BAD_ADDRESS;
322       }
323       strcpy(aptr->sun_path, name);
324       ia->size=SUN_LEN(aptr);
325     }
326     break;
327   }
328 
329   default:
330     return GWEN_INETADDR_ERROR_BAD_ADDRESS_FAMILY;
331   } /* switch */
332   return 0;
333 }
334 
335 
336 
GWEN_InetAddr_GetAddress(const GWEN_INETADDRESS * ia,char * buffer,unsigned int bsize)337 int GWEN_InetAddr_GetAddress(const GWEN_INETADDRESS *ia,
338                              char *buffer, unsigned int bsize)
339 {
340   const char *s;
341 
342   assert(ia);
343   assert(buffer);
344 
345   switch (ia->af) {
346   case GWEN_AddressFamilyIP: {
347     struct sockaddr_in *aptr;
348     unsigned int sNameLen;
349 
350     aptr=(struct sockaddr_in *)(ia->address);
351     s=inet_ntoa(aptr->sin_addr);
352     assert(s);
353     sNameLen=strlen(s);
354     if (sNameLen+1>bsize) {
355       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%u > %u)", (int) sNameLen+1, bsize);
356       return GWEN_ERROR_BUFFER_OVERFLOW;
357     }
358     strcpy(buffer, s);
359     break;
360   }
361 
362   case GWEN_AddressFamilyUnix: {
363     struct sockaddr_un *aptr;
364     int i;
365 
366     aptr=(struct sockaddr_un *)(ia->address);
367     s=aptr->sun_path;
368     i=ia->size;
369     i-=sizeof(aptr->sun_family);
370     if (i+1>(int)bsize) {
371       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%u > %u)", (int) i+1, bsize);
372       return GWEN_ERROR_BUFFER_OVERFLOW;
373     }
374     memmove(buffer, s, i);
375     buffer[i]=0;
376     break;
377   }
378 
379   default:
380     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
381   } /* switch */
382   return 0;
383 }
384 
385 
386 
GWEN_InetAddr_GetName(const GWEN_INETADDRESS * ia,char * buffer,unsigned int bsize)387 int GWEN_InetAddr_GetName(const GWEN_INETADDRESS *ia,
388                           char *buffer, unsigned int bsize)
389 {
390   struct hostent *he;
391   struct in_addr lia;
392 
393   assert(ia);
394   assert(buffer);
395 
396   switch (ia->af) {
397   case GWEN_AddressFamilyIP: {
398     struct sockaddr_in *aptr;
399 
400     aptr=(struct sockaddr_in *)(ia->address);
401     /* resolve name from address */
402     lia=aptr->sin_addr;
403 #ifdef PF_INET
404     he=gethostbyaddr((char *)&lia, sizeof(lia), PF_INET);
405 #else
406     he=gethostbyaddr((char *)&lia, sizeof(lia), AF_INET);
407 #endif
408     if (!he)
409       return GWEN_InetAddr_TranslateHError(h_errno);
410 
411     /* copy name into given buffer */
412     assert(he->h_name);
413     if (strlen(he->h_name)+1>bsize)
414       return GWEN_ERROR_BUFFER_OVERFLOW;
415     /* copy the name into the buffer */
416     strcpy(buffer, he->h_name);
417     break;
418   }
419 
420   case GWEN_AddressFamilyUnix: {
421     struct sockaddr_un *aptr;
422 
423     aptr=(struct sockaddr_un *)(ia->address);
424     /* simply copy path */
425     if (strlen(aptr->sun_path)+1>bsize)
426       return GWEN_ERROR_BUFFER_OVERFLOW;
427     strcpy(buffer, aptr->sun_path);
428     break;
429   }
430 
431   default:
432     return GWEN_INETADDR_ERROR_BAD_ADDRESS_FAMILY;
433 
434   } /* switch */
435 
436   /* finished */
437   return 0;
438 }
439 
440 
441 
GWEN_InetAddr_GetPort(const GWEN_INETADDRESS * ia)442 int GWEN_InetAddr_GetPort(const GWEN_INETADDRESS *ia)
443 {
444   int i;
445 
446   assert(ia);
447 
448   switch (ia->af) {
449   case GWEN_AddressFamilyIP: {
450     struct sockaddr_in *aptr;
451 
452     aptr=(struct sockaddr_in *)(ia->address);
453     i=ntohs(aptr->sin_port);
454     break;
455   }
456 
457   default:
458     DBG_INFO(GWEN_LOGDOMAIN, "not an IP address");
459     i=0;
460   } /* switch */
461 
462   return i;
463 }
464 
465 
466 
GWEN_InetAddr_SetPort(GWEN_INETADDRESS * ia,int port)467 int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)
468 {
469   assert(ia);
470 
471   switch (ia->af) {
472   case GWEN_AddressFamilyIP: {
473     struct sockaddr_in *aptr;
474 
475     aptr=(struct sockaddr_in *)(ia->address);
476     aptr->sin_port=htons(port);
477     break;
478   }
479 
480   default:
481     return GWEN_ERROR_BAD_ADDRESS_FAMILY;
482   } /* switch */
483   return 0;
484 }
485 
486 
487 
488 
489 
490 
491