made backtrace() calls optional to support uClibc
[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 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <string.h>
26 #include <printf.h>
27
28 #include "host.h"
29
30
31 typedef struct private_host_t private_host_t;
32
33 /**
34 * @brief 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 /** maximux 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 default_route[4];
88 memset(default_route, 0, sizeof(default_route));
89 return memeq(default_route, &(this->address4.sin_addr.s_addr),
90 sizeof(default_route));
91 }
92 case AF_INET6:
93 {
94 u_int8_t default_route[16];
95 memset(default_route, 0, sizeof(default_route));
96 return memeq(default_route, &(this->address6.sin6_addr.s6_addr),
97 sizeof(default_route));
98 }
99 default:
100 {
101 return FALSE;
102 }
103 }
104 }
105
106 /**
107 * output handler in printf()
108 */
109 static int print(FILE *stream, const struct printf_info *info,
110 const void *const *args)
111 {
112 private_host_t *this = *((private_host_t**)(args[0]));
113 char buffer[INET6_ADDRSTRLEN];
114 void *address;
115 u_int16_t port;
116
117 if (this == NULL)
118 {
119 return fprintf(stream, "(null)");
120 }
121
122 if (is_anyaddr(this))
123 {
124 return fprintf(stream, "%%any");
125 }
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 break;
133 case AF_INET6:
134 address = &this->address6.sin6_addr;
135 port = this->address6.sin6_port;
136 break;
137 default:
138 return fprintf(stream, "(family not supported)");
139 }
140
141 if (inet_ntop(this->address.sa_family, address,
142 buffer, sizeof(buffer)) == NULL)
143 {
144 return fprintf(stream, "(address conversion failed)");
145 }
146
147 if (info->alt)
148 {
149 return fprintf(stream, "%s[%d]", buffer, ntohs(port));
150 }
151 else
152 {
153 return fprintf(stream, "%s", buffer);
154 }
155 }
156
157 /**
158 * register printf() handlers
159 */
160 static void __attribute__ ((constructor))print_register()
161 {
162 register_printf_function(PRINTF_HOST, print, arginfo_ptr);
163 }
164
165 /**
166 * Implementation of host_t.get_address.
167 */
168 static chunk_t get_address(private_host_t *this)
169 {
170 chunk_t address = chunk_empty;
171
172 switch (this->address.sa_family)
173 {
174 case AF_INET:
175 {
176 address.ptr = (char*)&(this->address4.sin_addr.s_addr);
177 address.len = 4;
178 return address;
179 }
180 case AF_INET6:
181 {
182 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
183 address.len = 16;
184 return address;
185 }
186 default:
187 {
188 /* return empty chunk */
189 return address;
190 }
191 }
192 }
193
194 /**
195 * implements host_t.get_family
196 */
197 static int get_family(private_host_t *this)
198 {
199 return this->address.sa_family;
200 }
201
202 /**
203 * implements host_t.get_port
204 */
205 static u_int16_t get_port(private_host_t *this)
206 {
207 switch (this->address.sa_family)
208 {
209 case AF_INET:
210 {
211 return ntohs(this->address4.sin_port);
212 }
213 case AF_INET6:
214 {
215 return ntohs(this->address6.sin6_port);
216 }
217 default:
218 {
219 return 0;
220 }
221 }
222 }
223
224 /**
225 * implements host_t.set_port
226 */
227 static void set_port(private_host_t *this, u_int16_t port)
228 {
229 switch (this->address.sa_family)
230 {
231 case AF_INET:
232 {
233 this->address4.sin_port = htons(port);
234 break;
235 }
236 case AF_INET6:
237 {
238 this->address6.sin6_port = htons(port);
239 break;
240 }
241 default:
242 {
243 break;
244 }
245 }
246 }
247
248 /**
249 * Implements host_t.clone.
250 */
251 static private_host_t *clone(private_host_t *this)
252 {
253 private_host_t *new = malloc_thing(private_host_t);
254
255 memcpy(new, this, sizeof(private_host_t));
256 return new;
257 }
258
259 /**
260 * Impelements host_t.ip_equals
261 */
262 static bool ip_equals(private_host_t *this, private_host_t *other)
263 {
264 if (this->address.sa_family != other->address.sa_family)
265 {
266 /* 0.0.0.0 and ::0 are equal */
267 if (is_anyaddr(this) && is_anyaddr(other))
268 {
269 return TRUE;
270 }
271
272 return FALSE;
273 }
274
275 switch (this->address.sa_family)
276 {
277 case AF_INET:
278 {
279 if (memeq(&this->address4.sin_addr, &other->address4.sin_addr,
280 sizeof(this->address4.sin_addr)))
281 {
282 return TRUE;
283 }
284 break;
285 }
286 case AF_INET6:
287 {
288 if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
289 sizeof(this->address6.sin6_addr)))
290 {
291 return TRUE;
292 }
293 }
294 default:
295 break;
296 }
297 return FALSE;
298 }
299
300 /**
301 * Implements host_t.get_differences
302 */
303 static host_diff_t get_differences(host_t *this, host_t *other)
304 {
305 host_diff_t ret = HOST_DIFF_NONE;
306
307 if (!this->ip_equals(this, other))
308 {
309 ret |= HOST_DIFF_ADDR;
310 }
311
312 if (this->get_port(this) != other->get_port(other))
313 {
314 ret |= HOST_DIFF_PORT;
315 }
316
317 return ret;
318 }
319
320 /**
321 * Impelements host_t.equals
322 */
323 static bool equals(private_host_t *this, private_host_t *other)
324 {
325 if (!ip_equals(this, other))
326 {
327 return FAILED;
328 }
329
330 switch (this->address.sa_family)
331 {
332 case AF_INET:
333 {
334 if (this->address4.sin_port == other->address4.sin_port)
335 {
336 return TRUE;
337 }
338 break;
339 }
340 case AF_INET6:
341 {
342 if (this->address6.sin6_port == other->address6.sin6_port)
343 {
344 return TRUE;
345 }
346 break;
347 }
348 default:
349 break;
350 }
351 return FALSE;
352 }
353
354 /**
355 * Implements host_t.destroy
356 */
357 static void destroy(private_host_t *this)
358 {
359 free(this);
360 }
361
362 /**
363 * Creates an empty host_t object
364 */
365 static private_host_t *host_create_empty(void)
366 {
367 private_host_t *this = malloc_thing(private_host_t);
368
369 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
370 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
371 this->public.clone = (host_t* (*) (host_t*))clone;
372 this->public.get_family = (int (*) (host_t*))get_family;
373 this->public.get_address = (chunk_t (*) (host_t *)) get_address;
374 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
375 this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
376 this->public.get_differences = get_differences;
377 this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
378 this->public.equals = (bool (*) (host_t *,host_t *)) equals;
379 this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
380 this->public.destroy = (void (*) (host_t*))destroy;
381
382 return this;
383 }
384
385 /*
386 * Described in header.
387 */
388 host_t *host_create_from_string(char *string, u_int16_t port)
389 {
390 private_host_t *this = host_create_empty();
391
392 if (strchr(string, '.'))
393 {
394 this->address.sa_family = AF_INET;
395 }
396 else
397 {
398 this->address.sa_family = AF_INET6;
399 }
400
401 switch (this->address.sa_family)
402 {
403 case AF_INET:
404 {
405 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
406 {
407 break;
408 }
409 this->address4.sin_port = htons(port);
410 this->socklen = sizeof(struct sockaddr_in);
411 return &this->public;
412 }
413 case AF_INET6:
414 {
415 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
416 {
417 break;
418 }
419 this->address6.sin6_port = htons(port);
420 this->socklen = sizeof(struct sockaddr_in6);
421 return &this->public;
422 }
423 default:
424 {
425 break;
426 }
427 }
428 free(this);
429 return NULL;
430 }
431
432 /*
433 * Described in header.
434 */
435 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
436 {
437 private_host_t *this = host_create_empty();
438
439 this->address.sa_family = family;
440 switch (family)
441 {
442 case AF_INET:
443 {
444 if (address.len != 4)
445 {
446 break;
447 }
448 memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4);
449 this->address4.sin_port = htons(port);
450 this->socklen = sizeof(struct sockaddr_in);
451 return &(this->public);
452 }
453 case AF_INET6:
454 {
455 if (address.len != 16)
456 {
457 break;
458 }
459 memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16);
460 this->address6.sin6_port = htons(port);
461 this->socklen = sizeof(struct sockaddr_in6);
462 return &this->public;
463 }
464 default:
465 break;
466 }
467 free(this);
468 return NULL;
469 }
470
471 /*
472 * Described in header.
473 */
474 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
475 {
476 private_host_t *this = host_create_empty();
477
478 switch (sockaddr->sa_family)
479 {
480 case AF_INET:
481 {
482 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
483 this->socklen = sizeof(struct sockaddr_in);
484 return &this->public;
485 }
486 case AF_INET6:
487 {
488 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
489 this->socklen = sizeof(struct sockaddr_in6);
490 return &this->public;
491 }
492 default:
493 break;
494 }
495 free(this);
496 return NULL;
497 }