Fixed host_create_from_subnet when no prefix is given.
[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 /**
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 if (af == AF_INET && strchr(string, ':'))
480 { /* do not try to convert v6 addresses for v4 family */
481 return NULL;
482 }
483
484 memset(&hints, 0, sizeof(hints));
485 hints.ai_family = af;
486 error = getaddrinfo(string, NULL, &hints, &result);
487 if (error != 0)
488 {
489 DBG1(DBG_LIB, "resolving '%s' failed: %s", string, gai_strerror(error));
490 return NULL;
491 }
492 /* result is a linked list, but we use only the first address */
493 this = (private_host_t*)host_create_from_sockaddr(result->ai_addr);
494 freeaddrinfo(result);
495 if (this)
496 {
497 switch (this->address.sa_family)
498 {
499 case AF_INET:
500 this->address4.sin_port = htons(port);
501 break;
502 case AF_INET6:
503 this->address6.sin6_port = htons(port);
504 break;
505 }
506 return &this->public;
507 }
508 return NULL;
509 }
510
511 /*
512 * Described in header.
513 */
514 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
515 {
516 private_host_t *this;
517
518 switch (family)
519 {
520 case AF_INET:
521 if (address.len < IPV4_LEN)
522 {
523 return NULL;
524 }
525 address.len = IPV4_LEN;
526 break;
527 case AF_INET6:
528 if (address.len < IPV6_LEN)
529 {
530 return NULL;
531 }
532 address.len = IPV6_LEN;
533 break;
534 case AF_UNSPEC:
535 switch (address.len)
536 {
537 case IPV4_LEN:
538 family = AF_INET;
539 break;
540 case IPV6_LEN:
541 family = AF_INET6;
542 break;
543 default:
544 return NULL;
545 }
546 break;
547 default:
548 return NULL;
549 }
550 this = host_create_empty();
551 this->address.sa_family = family;
552 switch (family)
553 {
554 case AF_INET:
555 memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
556 this->address4.sin_port = htons(port);
557 this->socklen = sizeof(struct sockaddr_in);
558 break;
559 case AF_INET6:
560 memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
561 this->address6.sin6_port = htons(port);
562 this->socklen = sizeof(struct sockaddr_in6);
563 break;
564 }
565 return &this->public;
566 }
567
568 /*
569 * Described in header.
570 */
571 host_t *host_create_from_subnet(char *string, int *bits)
572 {
573 char *pos, buf[64];
574 host_t *net;
575
576 pos = strchr(string, '/');
577 if (pos)
578 {
579 if (pos - string >= sizeof(buf))
580 {
581 return NULL;
582 }
583 strncpy(buf, string, pos - string);
584 buf[pos - string] = '\0';
585 *bits = atoi(pos + 1);
586 return host_create_from_string(buf, 0);
587 }
588 net = host_create_from_string(string, 0);
589 if (net)
590 {
591 if (net->get_family(net) == AF_INET)
592 {
593 *bits = 32;
594 }
595 else
596 {
597 *bits = 128;
598 }
599 }
600 return net;
601 }
602
603 /*
604 * Described in header.
605 */
606 host_t *host_create_any(int family)
607 {
608 private_host_t *this = host_create_empty();
609
610 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
611 this->address.sa_family = family;
612
613 switch (family)
614 {
615 case AF_INET:
616 {
617 this->socklen = sizeof(struct sockaddr_in);
618 return &(this->public);
619 }
620 case AF_INET6:
621 {
622 this->socklen = sizeof(struct sockaddr_in6);
623 return &this->public;
624 }
625 default:
626 break;
627 }
628 free(this);
629 return NULL;
630 }