50e43d9926dccd25c393137ad23f6f6f1c9ff180
[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 <sys/socket.h>
21 #include <netdb.h>
22 #include <string.h>
23
24 #include "host.h"
25
26 #include <debug.h>
27
28 #define IPV4_LEN 4
29 #define IPV6_LEN 16
30
31 typedef struct private_host_t private_host_t;
32
33 /**
34 * Private Data of a host object.
35 */
36 struct private_host_t {
37 /**
38 * Public data
39 */
40 host_t public;
41
42 /**
43 * low-lewel structure, wich stores the address
44 */
45 union {
46 /** generic type */
47 struct sockaddr address;
48 /** maximum sockaddr size */
49 struct sockaddr_storage address_max;
50 /** IPv4 address */
51 struct sockaddr_in address4;
52 /** IPv6 address */
53 struct sockaddr_in6 address6;
54 };
55 /**
56 * length of address structure
57 */
58 socklen_t socklen;
59 };
60
61
62 /**
63 * implements host_t.get_sockaddr
64 */
65 static sockaddr_t *get_sockaddr(private_host_t *this)
66 {
67 return &(this->address);
68 }
69
70 /**
71 * implements host_t.get_sockaddr_len
72 */
73 static socklen_t *get_sockaddr_len(private_host_t *this)
74 {
75 return &(this->socklen);
76 }
77
78 /**
79 * Implementation of host_t.is_anyaddr.
80 */
81 static bool is_anyaddr(private_host_t *this)
82 {
83 switch (this->address.sa_family)
84 {
85 case AF_INET:
86 {
87 u_int8_t zeroes[IPV4_LEN];
88
89 memset(zeroes, 0, IPV4_LEN);
90 return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
91 }
92 case AF_INET6:
93 {
94 u_int8_t zeroes[IPV6_LEN];
95
96 memset(zeroes, 0, IPV6_LEN);
97 return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
98 }
99 default:
100 {
101 return FALSE;
102 }
103 }
104 }
105
106 /**
107 * Described in header.
108 */
109 int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
110 const void *const *args)
111 {
112 private_host_t *this = *((private_host_t**)(args[0]));
113 char buffer[INET6_ADDRSTRLEN + 16];
114
115 if (this == NULL)
116 {
117 snprintf(buffer, sizeof(buffer), "(null)");
118 }
119 else if (is_anyaddr(this))
120 {
121 snprintf(buffer, sizeof(buffer), "%%any%s",
122 this->address.sa_family == AF_INET6 ? "6" : "");
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 * Create a %any host with port
368 */
369 static host_t *host_create_any_port(int family, u_int16_t port)
370 {
371 host_t *this;
372
373 this = host_create_any(family);
374 this->set_port(this, port);
375 return this;
376 }
377
378 /*
379 * Described in header.
380 */
381 host_t *host_create_from_string(char *string, u_int16_t port)
382 {
383 private_host_t *this;
384
385 if (streq(string, "%any"))
386 {
387 return host_create_any_port(AF_INET, port);
388 }
389 if (streq(string, "%any6"))
390 {
391 return host_create_any_port(AF_INET6, port);
392 }
393
394 this = host_create_empty();
395 if (strchr(string, '.'))
396 {
397 this->address.sa_family = AF_INET;
398 }
399 else
400 {
401 this->address.sa_family = AF_INET6;
402 }
403 switch (this->address.sa_family)
404 {
405 case AF_INET:
406 {
407 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
408 {
409 break;
410 }
411 this->address4.sin_port = htons(port);
412 this->socklen = sizeof(struct sockaddr_in);
413 return &this->public;
414 }
415 case AF_INET6:
416 {
417 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
418 {
419 break;
420 }
421 this->address6.sin6_port = htons(port);
422 this->socklen = sizeof(struct sockaddr_in6);
423 return &this->public;
424 }
425 default:
426 {
427 break;
428 }
429 }
430 free(this);
431 return NULL;
432 }
433
434 /*
435 * Described in header.
436 */
437 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
438 {
439 private_host_t *this = host_create_empty();
440
441 switch (sockaddr->sa_family)
442 {
443 case AF_INET:
444 {
445 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
446 this->socklen = sizeof(struct sockaddr_in);
447 return &this->public;
448 }
449 case AF_INET6:
450 {
451 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
452 this->socklen = sizeof(struct sockaddr_in6);
453 return &this->public;
454 }
455 default:
456 break;
457 }
458 free(this);
459 return NULL;
460 }
461
462 /*
463 * Described in header.
464 */
465 host_t *host_create_from_dns(char *string, int af, u_int16_t port)
466 {
467 private_host_t *this;
468 struct addrinfo hints, *result;
469 int error;
470
471 if (streq(string, "%any"))
472 {
473 return host_create_any_port(af ? af : AF_INET, port);
474 }
475 if (streq(string, "%any6"))
476 {
477 return host_create_any_port(af ? af : AF_INET6, port);
478 }
479
480 memset(&hints, 0, sizeof(hints));
481 hints.ai_family = af;
482 error = getaddrinfo(string, NULL, &hints, &result);
483 if (error != 0)
484 {
485 DBG1(DBG_LIB, "resolving '%s' failed: %s", string, gai_strerror(error));
486 return NULL;
487 }
488 /* result is a linked list, but we use only the first address */
489 this = (private_host_t*)host_create_from_sockaddr(result->ai_addr);
490 freeaddrinfo(result);
491 if (this)
492 {
493 switch (this->address.sa_family)
494 {
495 case AF_INET:
496 this->address4.sin_port = htons(port);
497 break;
498 case AF_INET6:
499 this->address6.sin6_port = htons(port);
500 break;
501 }
502 return &this->public;
503 }
504 return NULL;
505 }
506
507 /*
508 * Described in header.
509 */
510 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
511 {
512 private_host_t *this;
513
514 switch (family)
515 {
516 case AF_INET:
517 if (address.len < IPV4_LEN)
518 {
519 return NULL;
520 }
521 address.len = IPV4_LEN;
522 break;
523 case AF_INET6:
524 if (address.len < IPV6_LEN)
525 {
526 return NULL;
527 }
528 address.len = IPV6_LEN;
529 break;
530 case AF_UNSPEC:
531 switch (address.len)
532 {
533 case IPV4_LEN:
534 family = AF_INET;
535 break;
536 case IPV6_LEN:
537 family = AF_INET6;
538 break;
539 default:
540 return NULL;
541 }
542 break;
543 default:
544 return NULL;
545 }
546 this = host_create_empty();
547 this->address.sa_family = family;
548 switch (family)
549 {
550 case AF_INET:
551 memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
552 this->address4.sin_port = htons(port);
553 this->socklen = sizeof(struct sockaddr_in);
554 break;
555 case AF_INET6:
556 memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
557 this->address6.sin6_port = htons(port);
558 this->socklen = sizeof(struct sockaddr_in6);
559 break;
560 }
561 return &this->public;
562 }
563
564 /*
565 * Described in header.
566 */
567 host_t *host_create_from_subnet(char *string, int *bits)
568 {
569 char *pos, buf[64];
570 host_t *net;
571
572 pos = strchr(string, '/');
573 if (pos)
574 {
575 if (pos - string >= sizeof(buf))
576 {
577 return NULL;
578 }
579 strncpy(buf, string, pos - string);
580 buf[pos - string] = '\0';
581 *bits = atoi(pos + 1);
582 return host_create_from_string(buf, 0);
583 }
584 net = host_create_from_string(buf, 0);
585 if (net)
586 {
587 if (net->get_family(net) == AF_INET)
588 {
589 *bits = 32;
590 }
591 else
592 {
593 *bits = 128;
594 }
595 }
596 return net;
597 }
598
599 /*
600 * Described in header.
601 */
602 host_t *host_create_any(int family)
603 {
604 private_host_t *this = host_create_empty();
605
606 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
607 this->address.sa_family = family;
608
609 switch (family)
610 {
611 case AF_INET:
612 {
613 this->socklen = sizeof(struct sockaddr_in);
614 return &(this->public);
615 }
616 case AF_INET6:
617 {
618 this->socklen = sizeof(struct sockaddr_in6);
619 return &this->public;
620 }
621 default:
622 break;
623 }
624 return NULL;
625 }