fixed typo
[strongswan.git] / src / libstrongswan / utils / host.c
1 /**
2 * @file host.c
3 *
4 * @brief Implementation of host_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006-2007 Tobias Brunner
10 * Copyright (C) 2006 Daniel Roethlisberger
11 * Copyright (C) 2005-2006 Martin Willi
12 * Copyright (C) 2005 Jan Hutter
13 * Hochschule fuer Technik Rapperswil
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
24 */
25
26 #include <string.h>
27 #include <printf.h>
28
29 #include "host.h"
30
31
32 typedef struct private_host_t private_host_t;
33
34 /**
35 * @brief Private Data of a host object.
36 */
37 struct private_host_t {
38 /**
39 * Public data
40 */
41 host_t public;
42
43 /**
44 * low-lewel structure, wich stores the address
45 */
46 union {
47 /** generic type */
48 struct sockaddr address;
49 /** maximum sockaddr size */
50 struct sockaddr_storage address_max;
51 /** IPv4 address */
52 struct sockaddr_in address4;
53 /** IPv6 address */
54 struct sockaddr_in6 address6;
55 };
56 /**
57 * length of address structure
58 */
59 socklen_t socklen;
60 };
61
62
63 /**
64 * implements host_t.get_sockaddr
65 */
66 static sockaddr_t *get_sockaddr(private_host_t *this)
67 {
68 return &(this->address);
69 }
70
71 /**
72 * implements host_t.get_sockaddr_len
73 */
74 static socklen_t *get_sockaddr_len(private_host_t *this)
75 {
76 return &(this->socklen);
77 }
78
79 /**
80 * Implementation of host_t.is_anyaddr.
81 */
82 static bool is_anyaddr(private_host_t *this)
83 {
84 switch (this->address.sa_family)
85 {
86 case AF_INET:
87 {
88 u_int8_t default_route[4];
89 memset(default_route, 0, sizeof(default_route));
90 return memeq(default_route, &(this->address4.sin_addr.s_addr),
91 sizeof(default_route));
92 }
93 case AF_INET6:
94 {
95 u_int8_t default_route[16];
96 memset(default_route, 0, sizeof(default_route));
97 return memeq(default_route, &(this->address6.sin6_addr.s6_addr),
98 sizeof(default_route));
99 }
100 default:
101 {
102 return FALSE;
103 }
104 }
105 }
106
107 /**
108 * output handler in printf()
109 */
110 static int print(FILE *stream, const struct printf_info *info,
111 const void *const *args)
112 {
113 private_host_t *this = *((private_host_t**)(args[0]));
114 char buffer[INET6_ADDRSTRLEN];
115 void *address;
116 u_int16_t port;
117
118 if (this == NULL)
119 {
120 return fprintf(stream, "(null)");
121 }
122
123 if (is_anyaddr(this))
124 {
125 return fprintf(stream, "%%any");
126 }
127
128 switch (this->address.sa_family)
129 {
130 case AF_INET:
131 address = &this->address4.sin_addr;
132 port = this->address4.sin_port;
133 break;
134 case AF_INET6:
135 address = &this->address6.sin6_addr;
136 port = this->address6.sin6_port;
137 break;
138 default:
139 return fprintf(stream, "(family not supported)");
140 }
141
142 if (inet_ntop(this->address.sa_family, address,
143 buffer, sizeof(buffer)) == NULL)
144 {
145 return fprintf(stream, "(address conversion failed)");
146 }
147
148 if (info->alt)
149 {
150 return fprintf(stream, "%s[%d]", buffer, ntohs(port));
151 }
152 else
153 {
154 return fprintf(stream, "%s", buffer);
155 }
156 }
157
158 /**
159 * register printf() handlers
160 */
161 static void __attribute__ ((constructor))print_register()
162 {
163 register_printf_function(PRINTF_HOST, print, arginfo_ptr);
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 = 4;
179 return address;
180 }
181 case AF_INET6:
182 {
183 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
184 address.len = 16;
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 are equal */
268 if (is_anyaddr(this) && is_anyaddr(other))
269 {
270 return TRUE;
271 }
272
273 return FALSE;
274 }
275
276 switch (this->address.sa_family)
277 {
278 case AF_INET:
279 {
280 if (memeq(&this->address4.sin_addr, &other->address4.sin_addr,
281 sizeof(this->address4.sin_addr)))
282 {
283 return TRUE;
284 }
285 break;
286 }
287 case AF_INET6:
288 {
289 if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
290 sizeof(this->address6.sin6_addr)))
291 {
292 return TRUE;
293 }
294 }
295 default:
296 break;
297 }
298 return FALSE;
299 }
300
301 /**
302 * Implements host_t.get_differences
303 */
304 static host_diff_t get_differences(host_t *this, host_t *other)
305 {
306 host_diff_t ret = HOST_DIFF_NONE;
307
308 if (!this->ip_equals(this, other))
309 {
310 ret |= HOST_DIFF_ADDR;
311 }
312
313 if (this->get_port(this) != other->get_port(other))
314 {
315 ret |= HOST_DIFF_PORT;
316 }
317
318 return ret;
319 }
320
321 /**
322 * Impelements host_t.equals
323 */
324 static bool equals(private_host_t *this, private_host_t *other)
325 {
326 if (!ip_equals(this, other))
327 {
328 return FAILED;
329 }
330
331 switch (this->address.sa_family)
332 {
333 case AF_INET:
334 {
335 if (this->address4.sin_port == other->address4.sin_port)
336 {
337 return TRUE;
338 }
339 break;
340 }
341 case AF_INET6:
342 {
343 if (this->address6.sin6_port == other->address6.sin6_port)
344 {
345 return TRUE;
346 }
347 break;
348 }
349 default:
350 break;
351 }
352 return FALSE;
353 }
354
355 /**
356 * Implements host_t.destroy
357 */
358 static void destroy(private_host_t *this)
359 {
360 free(this);
361 }
362
363 /**
364 * Creates an empty host_t object
365 */
366 static private_host_t *host_create_empty(void)
367 {
368 private_host_t *this = malloc_thing(private_host_t);
369
370 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
371 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
372 this->public.clone = (host_t* (*) (host_t*))clone_;
373 this->public.get_family = (int (*) (host_t*))get_family;
374 this->public.get_address = (chunk_t (*) (host_t *)) get_address;
375 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
376 this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
377 this->public.get_differences = get_differences;
378 this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
379 this->public.equals = (bool (*) (host_t *,host_t *)) equals;
380 this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
381 this->public.destroy = (void (*) (host_t*))destroy;
382
383 return this;
384 }
385
386 /*
387 * Described in header.
388 */
389 host_t *host_create_from_string(char *string, u_int16_t port)
390 {
391 private_host_t *this = host_create_empty();
392
393 if (strchr(string, '.'))
394 {
395 this->address.sa_family = AF_INET;
396 }
397 else
398 {
399 this->address.sa_family = AF_INET6;
400 }
401
402 switch (this->address.sa_family)
403 {
404 case AF_INET:
405 {
406 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
407 {
408 break;
409 }
410 this->address4.sin_port = htons(port);
411 this->socklen = sizeof(struct sockaddr_in);
412 return &this->public;
413 }
414 case AF_INET6:
415 {
416 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
417 {
418 break;
419 }
420 this->address6.sin6_port = htons(port);
421 this->socklen = sizeof(struct sockaddr_in6);
422 return &this->public;
423 }
424 default:
425 {
426 break;
427 }
428 }
429 free(this);
430 return NULL;
431 }
432
433 /*
434 * Described in header.
435 */
436 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
437 {
438 private_host_t *this = host_create_empty();
439
440 this->address.sa_family = family;
441 switch (family)
442 {
443 case AF_INET:
444 {
445 if (address.len != 4)
446 {
447 break;
448 }
449 memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4);
450 this->address4.sin_port = htons(port);
451 this->socklen = sizeof(struct sockaddr_in);
452 return &(this->public);
453 }
454 case AF_INET6:
455 {
456 if (address.len != 16)
457 {
458 break;
459 }
460 memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16);
461 this->address6.sin6_port = htons(port);
462 this->socklen = sizeof(struct sockaddr_in6);
463 return &this->public;
464 }
465 default:
466 break;
467 }
468 free(this);
469 return NULL;
470 }
471
472 /*
473 * Described in header.
474 */
475 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
476 {
477 private_host_t *this = host_create_empty();
478
479 switch (sockaddr->sa_family)
480 {
481 case AF_INET:
482 {
483 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
484 this->socklen = sizeof(struct sockaddr_in);
485 return &this->public;
486 }
487 case AF_INET6:
488 {
489 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
490 this->socklen = sizeof(struct sockaddr_in6);
491 return &this->public;
492 }
493 default:
494 break;
495 }
496 free(this);
497 return NULL;
498 }
499
500 /*
501 * Described in header.
502 */
503 host_t *host_create_any(int family)
504 {
505 private_host_t *this = host_create_empty();
506
507 memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
508 this->address.sa_family = family;
509
510 switch (family)
511 {
512 case AF_INET:
513 {
514 this->socklen = sizeof(struct sockaddr_in);
515 return &(this->public);
516 }
517 case AF_INET6:
518 {
519 this->socklen = sizeof(struct sockaddr_in6);
520 return &this->public;
521 }
522 default:
523 break;
524 }
525 return NULL;
526 }