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