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