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