3a16138a48986cfdd64e9bfa614be30568aed058
[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, which 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 METHOD(host_t, get_sockaddr, sockaddr_t*,
63 private_host_t *this)
64 {
65 return &(this->address);
66 }
67
68 METHOD(host_t, get_sockaddr_len, socklen_t*,
69 private_host_t *this)
70 {
71 return &(this->socklen);
72 }
73
74 METHOD(host_t, is_anyaddr, bool,
75 private_host_t *this)
76 {
77 switch (this->address.sa_family)
78 {
79 case AF_INET:
80 {
81 u_int8_t zeroes[IPV4_LEN];
82
83 memset(zeroes, 0, IPV4_LEN);
84 return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
85 }
86 case AF_INET6:
87 {
88 u_int8_t zeroes[IPV6_LEN];
89
90 memset(zeroes, 0, IPV6_LEN);
91 return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
92 }
93 default:
94 {
95 return FALSE;
96 }
97 }
98 }
99
100 /**
101 * Described in header.
102 */
103 int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
104 const void *const *args)
105 {
106 private_host_t *this = *((private_host_t**)(args[0]));
107 char buffer[INET6_ADDRSTRLEN + 16];
108
109 if (this == NULL)
110 {
111 snprintf(buffer, sizeof(buffer), "(null)");
112 }
113 else if (is_anyaddr(this) && !spec->plus)
114 {
115 snprintf(buffer, sizeof(buffer), "%%any%s",
116 this->address.sa_family == AF_INET6 ? "6" : "");
117 }
118 else
119 {
120 void *address;
121 u_int16_t port;
122 int len;
123
124 address = &this->address6.sin6_addr;
125 port = this->address6.sin6_port;
126
127 switch (this->address.sa_family)
128 {
129 case AF_INET:
130 address = &this->address4.sin_addr;
131 port = this->address4.sin_port;
132 /* fall */
133 case AF_INET6:
134
135 if (inet_ntop(this->address.sa_family, address,
136 buffer, sizeof(buffer)) == NULL)
137 {
138 snprintf(buffer, sizeof(buffer),
139 "(address conversion failed)");
140 }
141 else if (spec->hash)
142 {
143 len = strlen(buffer);
144 snprintf(buffer + len, sizeof(buffer) - len,
145 "[%d]", ntohs(port));
146 }
147 break;
148 default:
149 snprintf(buffer, sizeof(buffer), "(family not supported)");
150 break;
151 }
152 }
153 if (spec->minus)
154 {
155 return print_in_hook(data, "%-*s", spec->width, buffer);
156 }
157 return print_in_hook(data, "%*s", spec->width, buffer);
158 }
159
160 METHOD(host_t, get_address, chunk_t,
161 private_host_t *this)
162 {
163 chunk_t address = chunk_empty;
164
165 switch (this->address.sa_family)
166 {
167 case AF_INET:
168 {
169 address.ptr = (char*)&(this->address4.sin_addr.s_addr);
170 address.len = IPV4_LEN;
171 return address;
172 }
173 case AF_INET6:
174 {
175 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
176 address.len = IPV6_LEN;
177 return address;
178 }
179 default:
180 {
181 /* return empty chunk */
182 return address;
183 }
184 }
185 }
186
187 METHOD(host_t, get_family, int,
188 private_host_t *this)
189 {
190 return this->address.sa_family;
191 }
192
193 METHOD(host_t, get_port, u_int16_t,
194 private_host_t *this)
195 {
196 switch (this->address.sa_family)
197 {
198 case AF_INET:
199 {
200 return ntohs(this->address4.sin_port);
201 }
202 case AF_INET6:
203 {
204 return ntohs(this->address6.sin6_port);
205 }
206 default:
207 {
208 return 0;
209 }
210 }
211 }
212
213 METHOD(host_t, set_port, void,
214 private_host_t *this, u_int16_t port)
215 {
216 switch (this->address.sa_family)
217 {
218 case AF_INET:
219 {
220 this->address4.sin_port = htons(port);
221 break;
222 }
223 case AF_INET6:
224 {
225 this->address6.sin6_port = htons(port);
226 break;
227 }
228 default:
229 {
230 break;
231 }
232 }
233 }
234
235 METHOD(host_t, clone_, host_t*,
236 private_host_t *this)
237 {
238 private_host_t *new;
239
240 new = malloc_thing(private_host_t);
241 memcpy(new, this, sizeof(private_host_t));
242
243 return &new->public;
244 }
245
246 /**
247 * Implements host_t.ip_equals
248 */
249 static bool ip_equals(private_host_t *this, private_host_t *other)
250 {
251 if (this->address.sa_family != other->address.sa_family)
252 {
253 /* 0.0.0.0 and 0::0 are equal */
254 return (is_anyaddr(this) && is_anyaddr(other));
255 }
256
257 switch (this->address.sa_family)
258 {
259 case AF_INET:
260 {
261 return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
262 sizeof(this->address4.sin_addr));
263 }
264 case AF_INET6:
265 {
266 return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
267 sizeof(this->address6.sin6_addr));
268 }
269 default:
270 break;
271 }
272 return FALSE;
273 }
274
275 /**
276 * Implements host_t.get_differences
277 */
278 static host_diff_t get_differences(host_t *this, host_t *other)
279 {
280 host_diff_t ret = HOST_DIFF_NONE;
281
282 if (!this->ip_equals(this, other))
283 {
284 ret |= HOST_DIFF_ADDR;
285 }
286
287 if (this->get_port(this) != other->get_port(other))
288 {
289 ret |= HOST_DIFF_PORT;
290 }
291
292 return ret;
293 }
294
295 /**
296 * Implements host_t.equals
297 */
298 static bool equals(private_host_t *this, private_host_t *other)
299 {
300 if (!ip_equals(this, other))
301 {
302 return FALSE;
303 }
304
305 switch (this->address.sa_family)
306 {
307 case AF_INET:
308 {
309 return (this->address4.sin_port == other->address4.sin_port);
310 }
311 case AF_INET6:
312 {
313 return (this->address6.sin6_port == other->address6.sin6_port);
314 }
315 default:
316 break;
317 }
318 return FALSE;
319 }
320
321 METHOD(host_t, destroy, void,
322 private_host_t *this)
323 {
324 free(this);
325 }
326
327 /**
328 * Creates an empty host_t object
329 */
330 static private_host_t *host_create_empty(void)
331 {
332 private_host_t *this;
333
334 INIT(this,
335 .public = {
336 .get_sockaddr = _get_sockaddr,
337 .get_sockaddr_len = _get_sockaddr_len,
338 .clone = _clone_,
339 .get_family = _get_family,
340 .get_address = _get_address,
341 .get_port = _get_port,
342 .set_port = _set_port,
343 .get_differences = get_differences,
344 .ip_equals = (bool (*)(host_t *,host_t *))ip_equals,
345 .equals = (bool (*)(host_t *,host_t *)) equals,
346 .is_anyaddr = _is_anyaddr,
347 .destroy = _destroy,
348 },
349 );
350
351 return this;
352 }
353
354 /*
355 * Create a %any host with port
356 */
357 static host_t *host_create_any_port(int family, u_int16_t port)
358 {
359 host_t *this;
360
361 this = host_create_any(family);
362 this->set_port(this, port);
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_port(AF_INET, port);
376 }
377 if (streq(string, "%any6"))
378 {
379 return host_create_any_port(AF_INET6, port);
380 }
381
382 this = host_create_empty();
383 if (strchr(string, '.'))
384 {
385 this->address.sa_family = AF_INET;
386 }
387 else
388 {
389 this->address.sa_family = AF_INET6;
390 }
391 switch (this->address.sa_family)
392 {
393 case AF_INET:
394 {
395 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
396 {
397 break;
398 }
399 this->address4.sin_port = htons(port);
400 this->socklen = sizeof(struct sockaddr_in);
401 return &this->public;
402 }
403 case AF_INET6:
404 {
405 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
406 {
407 break;
408 }
409 this->address6.sin6_port = htons(port);
410 this->socklen = sizeof(struct sockaddr_in6);
411 return &this->public;
412 }
413 default:
414 {
415 break;
416 }
417 }
418 free(this);
419 return NULL;
420 }
421
422 /*
423 * Described in header.
424 */
425 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
426 {
427 private_host_t *this = host_create_empty();
428
429 switch (sockaddr->sa_family)
430 {
431 case AF_INET:
432 {
433 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
434 this->socklen = sizeof(struct sockaddr_in);
435 return &this->public;
436 }
437 case AF_INET6:
438 {
439 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
440 this->socklen = sizeof(struct sockaddr_in6);
441 return &this->public;
442 }
443 default:
444 break;
445 }
446 free(this);
447 return NULL;
448 }
449
450 /*
451 * Described in header.
452 */
453 host_t *host_create_from_dns(char *string, int af, u_int16_t port)
454 {
455 private_host_t *this;
456 struct addrinfo hints, *result;
457 int error;
458
459 if (streq(string, "%any"))
460 {
461 return host_create_any_port(af ? af : AF_INET, port);
462 }
463 if (streq(string, "%any6"))
464 {
465 return host_create_any_port(af ? af : AF_INET6, port);
466 }
467 if (af == AF_INET && strchr(string, ':'))
468 { /* do not try to convert v6 addresses for v4 family */
469 return NULL;
470 }
471
472 memset(&hints, 0, sizeof(hints));
473 hints.ai_family = af;
474 error = getaddrinfo(string, NULL, &hints, &result);
475 if (error != 0)
476 {
477 DBG1(DBG_LIB, "resolving '%s' failed: %s", string, gai_strerror(error));
478 return NULL;
479 }
480 /* result is a linked list, but we use only the first address */
481 this = (private_host_t*)host_create_from_sockaddr(result->ai_addr);
482 freeaddrinfo(result);
483 if (this)
484 {
485 switch (this->address.sa_family)
486 {
487 case AF_INET:
488 this->address4.sin_port = htons(port);
489 break;
490 case AF_INET6:
491 this->address6.sin6_port = htons(port);
492 break;
493 }
494 return &this->public;
495 }
496 return NULL;
497 }
498
499 /*
500 * Described in header.
501 */
502 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
503 {
504 private_host_t *this;
505
506 switch (family)
507 {
508 case AF_INET:
509 if (address.len < IPV4_LEN)
510 {
511 return NULL;
512 }
513 address.len = IPV4_LEN;
514 break;
515 case AF_INET6:
516 if (address.len < IPV6_LEN)
517 {
518 return NULL;
519 }
520 address.len = IPV6_LEN;
521 break;
522 case AF_UNSPEC:
523 switch (address.len)
524 {
525 case IPV4_LEN:
526 family = AF_INET;
527 break;
528 case IPV6_LEN:
529 family = AF_INET6;
530 break;
531 default:
532 return NULL;
533 }
534 break;
535 default:
536 return NULL;
537 }
538 this = host_create_empty();
539 this->address.sa_family = family;
540 switch (family)
541 {
542 case AF_INET:
543 memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
544 this->address4.sin_port = htons(port);
545 this->socklen = sizeof(struct sockaddr_in);
546 break;
547 case AF_INET6:
548 memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
549 this->address6.sin6_port = htons(port);
550 this->socklen = sizeof(struct sockaddr_in6);
551 break;
552 }
553 return &this->public;
554 }
555
556 /*
557 * Described in header.
558 */
559 host_t *host_create_from_subnet(char *string, int *bits)
560 {
561 char *pos, buf[64];
562 host_t *net;
563
564 pos = strchr(string, '/');
565 if (pos)
566 {
567 if (pos - string >= sizeof(buf))
568 {
569 return NULL;
570 }
571 strncpy(buf, string, pos - string);
572 buf[pos - string] = '\0';
573 *bits = atoi(pos + 1);
574 return host_create_from_string(buf, 0);
575 }
576 net = host_create_from_string(string, 0);
577 if (net)
578 {
579 if (net->get_family(net) == AF_INET)
580 {
581 *bits = 32;
582 }
583 else
584 {
585 *bits = 128;
586 }
587 }
588 return net;
589 }
590
591 /*
592 * Described in header.
593 */
594 host_t *host_create_any(int family)
595 {
596 private_host_t *this = host_create_empty();
597
598 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
599 this->address.sa_family = family;
600
601 switch (family)
602 {
603 case AF_INET:
604 {
605 this->socklen = sizeof(struct sockaddr_in);
606 return &(this->public);
607 }
608 case AF_INET6:
609 {
610 this->socklen = sizeof(struct sockaddr_in6);
611 return &this->public;
612 }
613 default:
614 break;
615 }
616 free(this);
617 return NULL;
618 }