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