(no commit message)
[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 * arginfo handler in printf()
159 */
160 static int print_arginfo(const struct printf_info *info, size_t n, int *argtypes)
161 {
162 if (n > 0)
163 {
164 argtypes[0] = PA_POINTER;
165 }
166 return 1;
167 }
168
169 /**
170 * register printf() handlers
171 */
172 static void __attribute__ ((constructor))print_register()
173 {
174 register_printf_function(HOST_PRINTF_SPEC, print, print_arginfo);
175 }
176
177 /**
178 * Implementation of host_t.get_address.
179 */
180 static chunk_t get_address(private_host_t *this)
181 {
182 chunk_t address = CHUNK_INITIALIZER;
183
184 switch (this->address.sa_family)
185 {
186 case AF_INET:
187 {
188 address.ptr = (char*)&(this->address4.sin_addr.s_addr);
189 address.len = 4;
190 return address;
191 }
192 case AF_INET6:
193 {
194 address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
195 address.len = 16;
196 return address;
197 }
198 default:
199 {
200 /* return empty chunk */
201 return address;
202 }
203 }
204 }
205
206 /**
207 * implements host_t.get_family
208 */
209 static int get_family(private_host_t *this)
210 {
211 return this->address.sa_family;
212 }
213
214 /**
215 * implements host_t.get_port
216 */
217 static u_int16_t get_port(private_host_t *this)
218 {
219 switch (this->address.sa_family)
220 {
221 case AF_INET:
222 {
223 return ntohs(this->address4.sin_port);
224 }
225 case AF_INET6:
226 {
227 return ntohs(this->address6.sin6_port);
228 }
229 default:
230 {
231 return 0;
232 }
233 }
234 }
235
236 /**
237 * implements host_t.set_port
238 */
239 static void set_port(private_host_t *this, u_int16_t port)
240 {
241 switch (this->address.sa_family)
242 {
243 case AF_INET:
244 {
245 this->address4.sin_port = htons(port);
246 break;
247 }
248 case AF_INET6:
249 {
250 this->address6.sin6_port = htons(port);
251 break;
252 }
253 default:
254 {
255 break;
256 }
257 }
258 }
259
260 /**
261 * Implements host_t.clone.
262 */
263 static private_host_t *clone(private_host_t *this)
264 {
265 private_host_t *new = malloc_thing(private_host_t);
266
267 memcpy(new, this, sizeof(private_host_t));
268 return new;
269 }
270
271 /**
272 * Impelements host_t.ip_equals
273 */
274 static bool ip_equals(private_host_t *this, private_host_t *other)
275 {
276 if (this->address.sa_family != other->address.sa_family)
277 {
278 /* 0.0.0.0 and ::0 are equal */
279 if (is_anyaddr(this) && is_anyaddr(other))
280 {
281 return TRUE;
282 }
283
284 return FALSE;
285 }
286
287 switch (this->address.sa_family)
288 {
289 case AF_INET:
290 {
291 if (memeq(&this->address4.sin_addr, &other->address4.sin_addr,
292 sizeof(this->address4.sin_addr)))
293 {
294 return TRUE;
295 }
296 break;
297 }
298 case AF_INET6:
299 {
300 if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
301 sizeof(this->address6.sin6_addr)))
302 {
303 return TRUE;
304 }
305 }
306 default:
307 break;
308 }
309 return FALSE;
310 }
311
312 /**
313 * Implements host_t.get_differences
314 */
315 static host_diff_t get_differences(host_t *this, host_t *other)
316 {
317 host_diff_t ret = HOST_DIFF_NONE;
318
319 if (!this->ip_equals(this, other))
320 {
321 ret |= HOST_DIFF_ADDR;
322 }
323
324 if (this->get_port(this) != other->get_port(other))
325 {
326 ret |= HOST_DIFF_PORT;
327 }
328
329 return ret;
330 }
331
332 /**
333 * Impelements host_t.equals
334 */
335 static bool equals(private_host_t *this, private_host_t *other)
336 {
337 if (!ip_equals(this, other))
338 {
339 return FAILED;
340 }
341
342 switch (this->address.sa_family)
343 {
344 case AF_INET:
345 {
346 if (this->address4.sin_port == other->address4.sin_port)
347 {
348 return TRUE;
349 }
350 break;
351 }
352 case AF_INET6:
353 {
354 if (this->address6.sin6_port == other->address6.sin6_port)
355 {
356 return TRUE;
357 }
358 break;
359 }
360 default:
361 break;
362 }
363 return FALSE;
364 }
365
366 /**
367 * Implements host_t.destroy
368 */
369 static void destroy(private_host_t *this)
370 {
371 free(this);
372 }
373
374 /**
375 * Creates an empty host_t object
376 */
377 static private_host_t *host_create_empty(void)
378 {
379 private_host_t *this = malloc_thing(private_host_t);
380
381 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
382 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
383 this->public.clone = (host_t* (*) (host_t*))clone;
384 this->public.get_family = (int (*) (host_t*))get_family;
385 this->public.get_address = (chunk_t (*) (host_t *)) get_address;
386 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
387 this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
388 this->public.get_differences = get_differences;
389 this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
390 this->public.equals = (bool (*) (host_t *,host_t *)) equals;
391 this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
392 this->public.destroy = (void (*) (host_t*))destroy;
393
394 return this;
395 }
396
397 /*
398 * Described in header.
399 */
400 host_t *host_create_from_string(char *string, u_int16_t port)
401 {
402 private_host_t *this = host_create_empty();
403
404 if (strchr(string, '.'))
405 {
406 this->address.sa_family = AF_INET;
407 }
408 else
409 {
410 this->address.sa_family = AF_INET6;
411 }
412
413 switch (this->address.sa_family)
414 {
415 case AF_INET:
416 {
417 if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
418 {
419 break;
420 }
421 this->address4.sin_port = htons(port);
422 this->socklen = sizeof(struct sockaddr_in);
423 return &this->public;
424 }
425 case AF_INET6:
426 {
427 if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
428 {
429 break;
430 }
431 this->address6.sin6_port = htons(port);
432 this->socklen = sizeof(struct sockaddr_in6);
433 return &this->public;
434 }
435 default:
436 {
437 break;
438 }
439 }
440 free(this);
441 return NULL;
442 }
443
444 /*
445 * Described in header.
446 */
447 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
448 {
449 private_host_t *this = host_create_empty();
450
451 this->address.sa_family = family;
452 switch (family)
453 {
454 case AF_INET:
455 {
456 if (address.len != 4)
457 {
458 break;
459 }
460 memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4);
461 this->address4.sin_port = htons(port);
462 this->socklen = sizeof(struct sockaddr_in);
463 return &(this->public);
464 }
465 case AF_INET6:
466 {
467 if (address.len != 16)
468 {
469 break;
470 }
471 memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16);
472 this->address6.sin6_port = htons(port);
473 this->socklen = sizeof(struct sockaddr_in6);
474 return &this->public;
475 }
476 default:
477 break;
478 }
479 free(this);
480 return NULL;
481 }
482
483 /*
484 * Described in header.
485 */
486 host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
487 {
488 private_host_t *this = host_create_empty();
489
490 switch (sockaddr->sa_family)
491 {
492 case AF_INET:
493 {
494 memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
495 this->socklen = sizeof(struct sockaddr_in);
496 return &this->public;
497 }
498 case AF_INET6:
499 {
500 memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
501 this->socklen = sizeof(struct sockaddr_in6);
502 return &this->public;
503 }
504 default:
505 break;
506 }
507 free(this);
508 return NULL;
509 }