fixed resolving numerical addresses in host_create_from_dns()
[strongswan.git] / src / libstrongswan / utils / host.c
1 /*
2 * Copyright (C) 2006-2007 Tobias Brunner
3 * Copyright (C) 2006 Daniel Roethlisberger
4 * Copyright (C) 2005-2006 Martin Willi
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * $Id$
19 */
20
21 #define _GNU_SOURCE
22 #include <netdb.h>
23 #include <string.h>
24 #include <printf.h>
25
26 #include "host.h"
27
28 #include <debug.h>
29
30 typedef struct private_host_t private_host_t;
31
32 /**
33 * Private Data of a host object.
34 */
35 struct private_host_t {
36 /**
37 * Public data
38 */
39 host_t public;
40
41 /**
42 * low-lewel structure, wich stores the address
43 */
44 union {
45 /** generic type */
46 struct sockaddr address;
47 /** maximum sockaddr size */
48 struct sockaddr_storage address_max;
49 /** IPv4 address */
50 struct sockaddr_in address4;
51 /** IPv6 address */
52 struct sockaddr_in6 address6;
53 };
54 /**
55 * length of address structure
56 */
57 socklen_t socklen;
58 };
59
60
61 /**
62 * implements host_t.get_sockaddr
63 */
64 static sockaddr_t *get_sockaddr(private_host_t *this)
65 {
66 return &(this->address);
67 }
68
69 /**
70 * implements host_t.get_sockaddr_len
71 */
72 static socklen_t *get_sockaddr_len(private_host_t *this)
73 {
74 return &(this->socklen);
75 }
76
77 /**
78 * Implementation of host_t.is_anyaddr.
79 */
80 static bool is_anyaddr(private_host_t *this)
81 {
82 switch (this->address.sa_family)
83 {
84 case AF_INET:
85 {
86 u_int8_t default_route[4];
87 memset(default_route, 0, sizeof(default_route));
88 return memeq(default_route, &(this->address4.sin_addr.s_addr),
89 sizeof(default_route));
90 }
91 case AF_INET6:
92 {
93 u_int8_t default_route[16];
94 memset(default_route, 0, sizeof(default_route));
95 return memeq(default_route, &(this->address6.sin6_addr.s6_addr),
96 sizeof(default_route));
97 }
98 default:
99 {
100 return FALSE;
101 }
102 }
103 }
104
105 /**
106 * output handler in printf()
107 */
108 static int print(FILE *stream, const struct printf_info *info,
109 const void *const *args)
110 {
111 private_host_t *this = *((private_host_t**)(args[0]));
112 char buffer[INET6_ADDRSTRLEN + 16];
113
114 if (this == NULL)
115 {
116 snprintf(buffer, sizeof(buffer), "(null)");
117 }
118 else if (is_anyaddr(this))
119 {
120 snprintf(buffer, sizeof(buffer), "%%any");
121 }
122 else
123 {
124 void *address;
125 u_int16_t port;
126 int len;
127
128 address = &this->address6.sin6_addr;
129 port = this->address6.sin6_port;
130
131 switch (this->address.sa_family)
132 {
133 case AF_INET:
134 address = &this->address4.sin_addr;
135 port = this->address4.sin_port;
136 /* fall */
137 case AF_INET6:
138
139 if (inet_ntop(this->address.sa_family, address,
140 buffer, sizeof(buffer)) == NULL)
141 {
142 snprintf(buffer, sizeof(buffer),
143 "(address conversion failed)");
144 }
145 else if (info->alt)
146 {
147 len = strlen(buffer);
148 snprintf(buffer + len, sizeof(buffer) - len,
149 "[%d]", ntohs(port));
150 }
151 break;
152 default:
153 snprintf(buffer, sizeof(buffer), "(family not supported)");
154 break;
155 }
156 }
157 if (info->left)
158 {
159 return fprintf(stream, "%-*s", info->width, buffer);
160 }
161 return fprintf(stream, "%*s", info->width, buffer);
162 }
163
164
165 /**
166 * arginfo handler for printf() hosts
167 */
168 int arginfo(const struct printf_info *info, size_t n, int *argtypes)
169 {
170 if (n > 0)
171 {
172 argtypes[0] = PA_POINTER;
173 }
174 return 1;
175 }
176
177 /**
178 * return printf hook functions for a host
179 */
180 printf_hook_functions_t host_get_printf_hooks()
181 {
182 printf_hook_functions_t hooks = {print, arginfo};
183
184 return hooks;
185 }
186
187 /**
188 * Implementation of host_t.get_address.
189 */
190 static chunk_t get_address(private_host_t *this)
191 {
192 chunk_t address = chunk_empty;
193
194 switch (this->address.sa_family)
195 {
196 case AF_INET:
197 {
198 address.ptr = (char*)&(this->address4.sin_addr.s_addr);
199 address.len = 4;
200 return address;
201 }
202 case AF_INET6:
203 {
204 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
205 address.len = 16;
206 return address;
207 }
208 default:
209 {
210 /* return empty chunk */
211 return address;
212 }
213 }
214 }
215
216 /**
217 * implements host_t.get_family
218 */
219 static int get_family(private_host_t *this)
220 {
221 return this->address.sa_family;
222 }
223
224 /**
225 * implements host_t.get_port
226 */
227 static u_int16_t get_port(private_host_t *this)
228 {
229 switch (this->address.sa_family)
230 {
231 case AF_INET:
232 {
233 return ntohs(this->address4.sin_port);
234 }
235 case AF_INET6:
236 {
237 return ntohs(this->address6.sin6_port);
238 }
239 default:
240 {
241 return 0;
242 }
243 }
244 }
245
246 /**
247 * implements host_t.set_port
248 */
249 static void set_port(private_host_t *this, u_int16_t port)
250 {
251 switch (this->address.sa_family)
252 {
253 case AF_INET:
254 {
255 this->address4.sin_port = htons(port);
256 break;
257 }
258 case AF_INET6:
259 {
260 this->address6.sin6_port = htons(port);
261 break;
262 }
263 default:
264 {
265 break;
266 }
267 }
268 }
269
270 /**
271 * Implements host_t.clone.
272 */
273 static private_host_t *clone_(private_host_t *this)
274 {
275 private_host_t *new = malloc_thing(private_host_t);
276
277 memcpy(new, this, sizeof(private_host_t));
278 return new;
279 }
280
281 /**
282 * Impelements host_t.ip_equals
283 */
284 static bool ip_equals(private_host_t *this, private_host_t *other)
285 {
286 if (this->address.sa_family != other->address.sa_family)
287 {
288 /* 0.0.0.0 and ::0 are equal */
289 if (is_anyaddr(this) && is_anyaddr(other))
290 {
291 return TRUE;
292 }
293
294 return FALSE;
295 }
296
297 switch (this->address.sa_family)
298 {
299 case AF_INET:
300 {
301 if (memeq(&this->address4.sin_addr, &other->address4.sin_addr,
302 sizeof(this->address4.sin_addr)))
303 {
304 return TRUE;
305 }
306 break;
307 }
308 case AF_INET6:
309 {
310 if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
311 sizeof(this->address6.sin6_addr)))
312 {
313 return TRUE;
314 }
315 }
316 default:
317 break;
318 }
319 return FALSE;
320 }
321
322 /**
323 * Implements host_t.get_differences
324 */
325 static host_diff_t get_differences(host_t *this, host_t *other)
326 {
327 host_diff_t ret = HOST_DIFF_NONE;
328
329 if (!this->ip_equals(this, other))
330 {
331 ret |= HOST_DIFF_ADDR;
332 }
333
334 if (this->get_port(this) != other->get_port(other))
335 {
336 ret |= HOST_DIFF_PORT;
337 }
338
339 return ret;
340 }
341
342 /**
343 * Impelements host_t.equals
344 */
345 static bool equals(private_host_t *this, private_host_t *other)
346 {
347 if (!ip_equals(this, other))
348 {
349 return FALSE;
350 }
351
352 switch (this->address.sa_family)
353 {
354 case AF_INET:
355 {
356 if (this->address4.sin_port == other->address4.sin_port)
357 {
358 return TRUE;
359 }
360 break;
361 }
362 case AF_INET6:
363 {
364 if (this->address6.sin6_port == other->address6.sin6_port)
365 {
366 return TRUE;
367 }
368 break;
369 }
370 default:
371 break;
372 }
373 return FALSE;
374 }
375
376 /**
377 * Implements host_t.destroy
378 */
379 static void destroy(private_host_t *this)
380 {
381 free(this);
382 }
383
384 /**
385 * Creates an empty host_t object
386 */
387 static private_host_t *host_create_empty(void)
388 {
389 private_host_t *this = malloc_thing(private_host_t);
390
391 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
392 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
393 this->public.clone = (host_t* (*) (host_t*))clone_;
394 this->public.get_family = (int (*) (host_t*))get_family;
395 this->public.get_address = (chunk_t (*) (host_t *)) get_address;
396 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
397 this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
398 this->public.get_differences = get_differences;
399 this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
400 this->public.equals = (bool (*) (host_t *,host_t *)) equals;
401 this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
402 this->public.destroy = (void (*) (host_t*))destroy;
403
404 return this;
405 }
406
407 /*
408 * Described in header.
409 */
410 host_t *host_create_from_string(char *string, u_int16_t port)
411 {
412 private_host_t *this = host_create_empty();
413
414 if (strchr(string, '.'))
415 {
416 this->address.sa_family = AF_INET;
417 }
418 else
419 {
420 this->address.sa_family = AF_INET6;
421 }
422
423 switch (this->address.sa_family)
424 {
425 case AF_INET:
426 {
427 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
428 {
429 break;
430 }
431 this->address4.sin_port = htons(port);
432 this->socklen = sizeof(struct sockaddr_in);
433 return &this->public;
434 }
435 case AF_INET6:
436 {
437 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
438 {
439 break;
440 }
441 this->address6.sin6_port = htons(port);
442 this->socklen = sizeof(struct sockaddr_in6);
443 return &this->public;
444 }
445 default:
446 {
447 break;
448 }
449 }
450 free(this);
451 return NULL;
452 }
453
454 /*
455 * Described in header.
456 */
457 host_t *host_create_from_dns(char *string, int af, u_int16_t port)
458 {
459 private_host_t *this;
460 struct hostent host, *ptr;
461 char buf[512];
462 int err, ret;
463
464 if (af)
465 {
466 ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err);
467 }
468 else
469 {
470 ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err);
471 }
472 if (ret != 0)
473 {
474 DBG1("resolving '%s' failed: %s", string, hstrerror(err));
475 return NULL;
476 }
477 if (ptr == NULL)
478 {
479 DBG1("resolving '%s' failed", string);
480 }
481 this = host_create_empty();
482 this->address.sa_family = host.h_addrtype;
483 switch (this->address.sa_family)
484 {
485 case AF_INET:
486 memcpy(&this->address4.sin_addr.s_addr,
487 host.h_addr_list[0], host.h_length);
488 this->address4.sin_port = htons(port);
489 this->socklen = sizeof(struct sockaddr_in);
490 break;
491 case AF_INET6:
492 memcpy(&this->address6.sin6_addr.s6_addr,
493 host.h_addr_list[0], host.h_length);
494 this->address6.sin6_port = htons(port);
495 this->socklen = sizeof(struct sockaddr_in6);
496 break;
497 default:
498 free(this);
499 return NULL;
500 }
501 return &this->public;
502 }
503
504 /*
505 * Described in header.
506 */
507 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
508 {
509 private_host_t *this = host_create_empty();
510
511 this->address.sa_family = family;
512 switch (family)
513 {
514 case AF_INET:
515 {
516 if (address.len != 4)
517 {
518 break;
519 }
520 memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4);
521 this->address4.sin_port = htons(port);
522 this->socklen = sizeof(struct sockaddr_in);
523 return &(this->public);
524 }
525 case AF_INET6:
526 {
527 if (address.len != 16)
528 {
529 break;
530 }
531 memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16);
532 this->address6.sin6_port = htons(port);
533 this->socklen = sizeof(struct sockaddr_in6);
534 return &this->public;
535 }
536 default:
537 break;
538 }
539 free(this);
540 return NULL;
541 }
542
543 /*
544 * Described in header.
545 */
546 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
547 {
548 private_host_t *this = host_create_empty();
549
550 switch (sockaddr->sa_family)
551 {
552 case AF_INET:
553 {
554 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
555 this->socklen = sizeof(struct sockaddr_in);
556 return &this->public;
557 }
558 case AF_INET6:
559 {
560 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
561 this->socklen = sizeof(struct sockaddr_in6);
562 return &this->public;
563 }
564 default:
565 break;
566 }
567 free(this);
568 return NULL;
569 }
570
571 /*
572 * Described in header.
573 */
574 host_t *host_create_any(int family)
575 {
576 private_host_t *this = host_create_empty();
577
578 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
579 this->address.sa_family = family;
580
581 switch (family)
582 {
583 case AF_INET:
584 {
585 this->socklen = sizeof(struct sockaddr_in);
586 return &(this->public);
587 }
588 case AF_INET6:
589 {
590 this->socklen = sizeof(struct sockaddr_in6);
591 return &this->public;
592 }
593 default:
594 break;
595 }
596 return NULL;
597 }