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