gethostbyname_r is not supported on Mac OS X (but gethostbyname uses thread-local...
[strongswan.git] / src / libstrongswan / utils / host.c
1 /*
2 * Copyright (C) 2006-2009 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
19 #define _GNU_SOURCE
20 #include <netdb.h>
21 #include <string.h>
22
23 #include "host.h"
24
25 #include <debug.h>
26
27 #define IPV4_LEN 4
28 #define IPV6_LEN 16
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 zeroes[IPV4_LEN];
87
88 memset(zeroes, 0, IPV4_LEN);
89 return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
90 }
91 case AF_INET6:
92 {
93 u_int8_t zeroes[IPV6_LEN];
94
95 memset(zeroes, 0, IPV6_LEN);
96 return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
97 }
98 default:
99 {
100 return FALSE;
101 }
102 }
103 }
104
105 /**
106 * Described in header.
107 */
108 int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
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%s",
121 this->address.sa_family == AF_INET6 ? "6" : "");
122 }
123 else
124 {
125 void *address;
126 u_int16_t port;
127 int len;
128
129 address = &this->address6.sin6_addr;
130 port = this->address6.sin6_port;
131
132 switch (this->address.sa_family)
133 {
134 case AF_INET:
135 address = &this->address4.sin_addr;
136 port = this->address4.sin_port;
137 /* fall */
138 case AF_INET6:
139
140 if (inet_ntop(this->address.sa_family, address,
141 buffer, sizeof(buffer)) == NULL)
142 {
143 snprintf(buffer, sizeof(buffer),
144 "(address conversion failed)");
145 }
146 else if (spec->hash)
147 {
148 len = strlen(buffer);
149 snprintf(buffer + len, sizeof(buffer) - len,
150 "[%d]", ntohs(port));
151 }
152 break;
153 default:
154 snprintf(buffer, sizeof(buffer), "(family not supported)");
155 break;
156 }
157 }
158 if (spec->minus)
159 {
160 return print_in_hook(dst, dstlen, "%-*s", spec->width, buffer);
161 }
162 return print_in_hook(dst, dstlen, "%*s", spec->width, buffer);
163 }
164
165 /**
166 * Implementation of host_t.get_address.
167 */
168 static chunk_t get_address(private_host_t *this)
169 {
170 chunk_t address = chunk_empty;
171
172 switch (this->address.sa_family)
173 {
174 case AF_INET:
175 {
176 address.ptr = (char*)&(this->address4.sin_addr.s_addr);
177 address.len = IPV4_LEN;
178 return address;
179 }
180 case AF_INET6:
181 {
182 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
183 address.len = IPV6_LEN;
184 return address;
185 }
186 default:
187 {
188 /* return empty chunk */
189 return address;
190 }
191 }
192 }
193
194 /**
195 * implements host_t.get_family
196 */
197 static int get_family(private_host_t *this)
198 {
199 return this->address.sa_family;
200 }
201
202 /**
203 * implements host_t.get_port
204 */
205 static u_int16_t get_port(private_host_t *this)
206 {
207 switch (this->address.sa_family)
208 {
209 case AF_INET:
210 {
211 return ntohs(this->address4.sin_port);
212 }
213 case AF_INET6:
214 {
215 return ntohs(this->address6.sin6_port);
216 }
217 default:
218 {
219 return 0;
220 }
221 }
222 }
223
224 /**
225 * implements host_t.set_port
226 */
227 static void set_port(private_host_t *this, u_int16_t port)
228 {
229 switch (this->address.sa_family)
230 {
231 case AF_INET:
232 {
233 this->address4.sin_port = htons(port);
234 break;
235 }
236 case AF_INET6:
237 {
238 this->address6.sin6_port = htons(port);
239 break;
240 }
241 default:
242 {
243 break;
244 }
245 }
246 }
247
248 /**
249 * Implements host_t.clone.
250 */
251 static private_host_t *clone_(private_host_t *this)
252 {
253 private_host_t *new = malloc_thing(private_host_t);
254
255 memcpy(new, this, sizeof(private_host_t));
256 return new;
257 }
258
259 /**
260 * Impelements host_t.ip_equals
261 */
262 static bool ip_equals(private_host_t *this, private_host_t *other)
263 {
264 if (this->address.sa_family != other->address.sa_family)
265 {
266 /* 0.0.0.0 and 0::0 are equal */
267 return (is_anyaddr(this) && is_anyaddr(other));
268 }
269
270 switch (this->address.sa_family)
271 {
272 case AF_INET:
273 {
274 return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
275 sizeof(this->address4.sin_addr));
276 }
277 case AF_INET6:
278 {
279 return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
280 sizeof(this->address6.sin6_addr));
281 }
282 default:
283 break;
284 }
285 return FALSE;
286 }
287
288 /**
289 * Implements host_t.get_differences
290 */
291 static host_diff_t get_differences(host_t *this, host_t *other)
292 {
293 host_diff_t ret = HOST_DIFF_NONE;
294
295 if (!this->ip_equals(this, other))
296 {
297 ret |= HOST_DIFF_ADDR;
298 }
299
300 if (this->get_port(this) != other->get_port(other))
301 {
302 ret |= HOST_DIFF_PORT;
303 }
304
305 return ret;
306 }
307
308 /**
309 * Implements host_t.equals
310 */
311 static bool equals(private_host_t *this, private_host_t *other)
312 {
313 if (!ip_equals(this, other))
314 {
315 return FALSE;
316 }
317
318 switch (this->address.sa_family)
319 {
320 case AF_INET:
321 {
322 return (this->address4.sin_port == other->address4.sin_port);
323 }
324 case AF_INET6:
325 {
326 return (this->address6.sin6_port == other->address6.sin6_port);
327 }
328 default:
329 break;
330 }
331 return FALSE;
332 }
333
334 /**
335 * Implements host_t.destroy
336 */
337 static void destroy(private_host_t *this)
338 {
339 free(this);
340 }
341
342 /**
343 * Creates an empty host_t object
344 */
345 static private_host_t *host_create_empty(void)
346 {
347 private_host_t *this = malloc_thing(private_host_t);
348
349 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
350 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
351 this->public.clone = (host_t* (*) (host_t*))clone_;
352 this->public.get_family = (int (*) (host_t*))get_family;
353 this->public.get_address = (chunk_t (*) (host_t *)) get_address;
354 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
355 this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
356 this->public.get_differences = get_differences;
357 this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
358 this->public.equals = (bool (*) (host_t *,host_t *)) equals;
359 this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
360 this->public.destroy = (void (*) (host_t*))destroy;
361
362 return this;
363 }
364
365 /*
366 * Create a %any host with port
367 */
368 static host_t *host_create_any_port(int family, u_int16_t port)
369 {
370 host_t *this;
371
372 this = host_create_any(family);
373 this->set_port(this, port);
374 return this;
375 }
376
377 /*
378 * Described in header.
379 */
380 host_t *host_create_from_string(char *string, u_int16_t port)
381 {
382 private_host_t *this;
383
384 if (streq(string, "%any"))
385 {
386 return host_create_any_port(AF_INET, port);
387 }
388 if (streq(string, "%any6"))
389 {
390 return host_create_any_port(AF_INET6, port);
391 }
392
393 this = host_create_empty();
394 if (strchr(string, '.'))
395 {
396 this->address.sa_family = AF_INET;
397 }
398 else
399 {
400 this->address.sa_family = AF_INET6;
401 }
402 switch (this->address.sa_family)
403 {
404 case AF_INET:
405 {
406 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
407 {
408 break;
409 }
410 this->address4.sin_port = htons(port);
411 this->socklen = sizeof(struct sockaddr_in);
412 return &this->public;
413 }
414 case AF_INET6:
415 {
416 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
417 {
418 break;
419 }
420 this->address6.sin6_port = htons(port);
421 this->socklen = sizeof(struct sockaddr_in6);
422 return &this->public;
423 }
424 default:
425 {
426 break;
427 }
428 }
429 free(this);
430 return NULL;
431 }
432
433 /*
434 * Described in header.
435 */
436 host_t *host_create_from_dns(char *string, int af, u_int16_t port)
437 {
438 private_host_t *this;
439 struct hostent *ptr;
440 int ret = 0, err;
441 #ifdef HAVE_GETHOSTBYNAME_R
442 struct hostent host;
443 char buf[512];
444 #endif
445
446 if (streq(string, "%any"))
447 {
448 return host_create_any_port(af ? af : AF_INET, port);
449 }
450 if (streq(string, "%any6"))
451 {
452 return host_create_any_port(af ? af : AF_INET6, port);
453 }
454 else if (strchr(string, ':'))
455 {
456 /* gethostbyname does not like IPv6 addresses - fallback */
457 return host_create_from_string(string, port);
458 }
459
460 #ifdef HAVE_GETHOSTBYNAME_R
461 if (af)
462 {
463 ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err);
464 }
465 else
466 {
467 ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err);
468 }
469 #else
470 /* Some systems (e.g. Mac OS X) do not support gethostbyname_r */
471 if (af)
472 {
473 ptr = gethostbyname2(string, af);
474 }
475 else
476 {
477 ptr = gethostbyname(string);
478 }
479 if (ptr == NULL)
480 {
481 err = h_errno;
482 }
483 #endif
484 if (ret != 0 || ptr == NULL)
485 {
486 DBG1("resolving '%s' failed: %s", string, hstrerror(err));
487 return NULL;
488 }
489 this = host_create_empty();
490 this->address.sa_family = ptr->h_addrtype;
491 switch (this->address.sa_family)
492 {
493 case AF_INET:
494 memcpy(&this->address4.sin_addr.s_addr,
495 ptr->h_addr_list[0], ptr->h_length);
496 this->address4.sin_port = htons(port);
497 this->socklen = sizeof(struct sockaddr_in);
498 break;
499 case AF_INET6:
500 memcpy(&this->address6.sin6_addr.s6_addr,
501 ptr->h_addr_list[0], ptr->h_length);
502 this->address6.sin6_port = htons(port);
503 this->socklen = sizeof(struct sockaddr_in6);
504 break;
505 default:
506 free(this);
507 return NULL;
508 }
509 return &this->public;
510 }
511
512 /*
513 * Described in header.
514 */
515 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
516 {
517 private_host_t *this;
518
519 switch (family)
520 {
521 case AF_INET:
522 if (address.len < IPV4_LEN)
523 {
524 return NULL;
525 }
526 address.len = IPV4_LEN;
527 break;
528 case AF_INET6:
529 if (address.len < IPV6_LEN)
530 {
531 return NULL;
532 }
533 address.len = IPV6_LEN;
534 break;
535 case AF_UNSPEC:
536 switch (address.len)
537 {
538 case IPV4_LEN:
539 family = AF_INET;
540 break;
541 case IPV6_LEN:
542 family = AF_INET6;
543 break;
544 default:
545 return NULL;
546 }
547 break;
548 default:
549 return NULL;
550 }
551 this = host_create_empty();
552 this->address.sa_family = family;
553 switch (family)
554 {
555 case AF_INET:
556 memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
557 this->address4.sin_port = htons(port);
558 this->socklen = sizeof(struct sockaddr_in);
559 break;
560 case AF_INET6:
561 memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
562 this->address6.sin6_port = htons(port);
563 this->socklen = sizeof(struct sockaddr_in6);
564 break;
565 }
566 return &this->public;
567 }
568
569 /*
570 * Described in header.
571 */
572 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
573 {
574 private_host_t *this = host_create_empty();
575
576 switch (sockaddr->sa_family)
577 {
578 case AF_INET:
579 {
580 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
581 this->socklen = sizeof(struct sockaddr_in);
582 return &this->public;
583 }
584 case AF_INET6:
585 {
586 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
587 this->socklen = sizeof(struct sockaddr_in6);
588 return &this->public;
589 }
590 default:
591 break;
592 }
593 free(this);
594 return NULL;
595 }
596
597 /*
598 * Described in header.
599 */
600 host_t *host_create_any(int family)
601 {
602 private_host_t *this = host_create_empty();
603
604 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
605 this->address.sa_family = family;
606
607 switch (family)
608 {
609 case AF_INET:
610 {
611 this->socklen = sizeof(struct sockaddr_in);
612 return &(this->public);
613 }
614 case AF_INET6:
615 {
616 this->socklen = sizeof(struct sockaddr_in6);
617 return &this->public;
618 }
619 default:
620 break;
621 }
622 return NULL;
623 }