f33385e67f52490d8b7261d32a26d91f08bd2445
[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 host, *ptr;
440 char buf[512];
441 int err, ret;
442
443 if (streq(string, "%any"))
444 {
445 return host_create_any_port(af ? af : AF_INET, port);
446 }
447 if (streq(string, "%any6"))
448 {
449 return host_create_any_port(af ? af : AF_INET6, port);
450 }
451 else if (strchr(string, ':'))
452 {
453 /* gethostbyname does not like IPv6 addresses - fallback */
454 return host_create_from_string(string, port);
455 }
456
457 if (af)
458 {
459 ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err);
460 }
461 else
462 {
463 ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err);
464 }
465 if (ret != 0)
466 {
467 DBG1("resolving '%s' failed: %s", string, hstrerror(err));
468 return NULL;
469 }
470 if (ptr == NULL)
471 {
472 DBG1("resolving '%s' failed", string);
473 }
474 this = host_create_empty();
475 this->address.sa_family = host.h_addrtype;
476 switch (this->address.sa_family)
477 {
478 case AF_INET:
479 memcpy(&this->address4.sin_addr.s_addr,
480 host.h_addr_list[0], host.h_length);
481 this->address4.sin_port = htons(port);
482 this->socklen = sizeof(struct sockaddr_in);
483 break;
484 case AF_INET6:
485 memcpy(&this->address6.sin6_addr.s6_addr,
486 host.h_addr_list[0], host.h_length);
487 this->address6.sin6_port = htons(port);
488 this->socklen = sizeof(struct sockaddr_in6);
489 break;
490 default:
491 free(this);
492 return NULL;
493 }
494 return &this->public;
495 }
496
497 /*
498 * Described in header.
499 */
500 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
501 {
502 private_host_t *this;
503
504 switch (family)
505 {
506 case AF_INET:
507 if (address.len < IPV4_LEN)
508 {
509 return NULL;
510 }
511 address.len = IPV4_LEN;
512 break;
513 case AF_INET6:
514 if (address.len < IPV6_LEN)
515 {
516 return NULL;
517 }
518 address.len = IPV6_LEN;
519 break;
520 case AF_UNSPEC:
521 switch (address.len)
522 {
523 case IPV4_LEN:
524 family = AF_INET;
525 break;
526 case IPV6_LEN:
527 family = AF_INET6;
528 break;
529 default:
530 return NULL;
531 }
532 break;
533 default:
534 return NULL;
535 }
536 this = host_create_empty();
537 this->address.sa_family = family;
538 switch (family)
539 {
540 case AF_INET:
541 memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
542 this->address4.sin_port = htons(port);
543 this->socklen = sizeof(struct sockaddr_in);
544 break;
545 case AF_INET6:
546 memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
547 this->address6.sin6_port = htons(port);
548 this->socklen = sizeof(struct sockaddr_in6);
549 break;
550 }
551 return &this->public;
552 }
553
554 /*
555 * Described in header.
556 */
557 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
558 {
559 private_host_t *this = host_create_empty();
560
561 switch (sockaddr->sa_family)
562 {
563 case AF_INET:
564 {
565 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
566 this->socklen = sizeof(struct sockaddr_in);
567 return &this->public;
568 }
569 case AF_INET6:
570 {
571 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
572 this->socklen = sizeof(struct sockaddr_in6);
573 return &this->public;
574 }
575 default:
576 break;
577 }
578 free(this);
579 return NULL;
580 }
581
582 /*
583 * Described in header.
584 */
585 host_t *host_create_any(int family)
586 {
587 private_host_t *this = host_create_empty();
588
589 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
590 this->address.sa_family = family;
591
592 switch (family)
593 {
594 case AF_INET:
595 {
596 this->socklen = sizeof(struct sockaddr_in);
597 return &(this->public);
598 }
599 case AF_INET6:
600 {
601 this->socklen = sizeof(struct sockaddr_in6);
602 return &this->public;
603 }
604 default:
605 break;
606 }
607 return NULL;
608 }