2 * Copyright (C) 2006-2014 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
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>.
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
21 #include <utils/debug.h>
27 typedef struct private_host_t private_host_t
;
30 * Private Data of a host object.
32 struct private_host_t
{
39 * low-lewel structure, which stores the address
43 struct sockaddr address
;
44 /** maximum sockaddr size */
45 struct sockaddr_storage address_max
;
47 struct sockaddr_in address4
;
49 struct sockaddr_in6 address6
;
52 * length of address structure
58 * Update the sockaddr internal sa_len option, if available
60 static inline void update_sa_len(private_host_t
*this)
62 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
63 this->address
.sa_len
= this->socklen
;
64 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
67 METHOD(host_t
, get_sockaddr
, sockaddr_t
*,
70 return &(this->address
);
73 METHOD(host_t
, get_sockaddr_len
, socklen_t
*,
76 return &(this->socklen
);
79 METHOD(host_t
, is_anyaddr
, bool,
82 static const u_int8_t zeroes
[IPV6_LEN
];
84 switch (this->address
.sa_family
)
88 return memeq(zeroes
, &(this->address4
.sin_addr
.s_addr
), IPV4_LEN
);
92 return memeq(zeroes
, &(this->address6
.sin6_addr
.s6_addr
), IPV6_LEN
);
102 * Described in header.
104 int host_printf_hook(printf_hook_data_t
*data
, printf_hook_spec_t
*spec
,
105 const void *const *args
)
107 private_host_t
*this = *((private_host_t
**)(args
[0]));
108 char buffer
[INET6_ADDRSTRLEN
+ 16];
112 snprintf(buffer
, sizeof(buffer
), "(null)");
114 else if (is_anyaddr(this) && !spec
->plus
&& !spec
->hash
)
116 snprintf(buffer
, sizeof(buffer
), "%%any%s",
117 this->address
.sa_family
== AF_INET6 ?
"6" : "");
125 address
= &this->address6
.sin6_addr
;
126 port
= this->address6
.sin6_port
;
128 switch (this->address
.sa_family
)
131 address
= &this->address4
.sin_addr
;
132 port
= this->address4
.sin_port
;
136 if (inet_ntop(this->address
.sa_family
, address
,
137 buffer
, sizeof(buffer
)) == NULL
)
139 snprintf(buffer
, sizeof(buffer
),
140 "(address conversion failed)");
144 len
= strlen(buffer
);
145 snprintf(buffer
+ len
, sizeof(buffer
) - len
,
146 "[%d]", ntohs(port
));
150 snprintf(buffer
, sizeof(buffer
), "(family not supported)");
156 return print_in_hook(data
, "%-*s", spec
->width
, buffer
);
158 return print_in_hook(data
, "%*s", spec
->width
, buffer
);
161 METHOD(host_t
, get_address
, chunk_t
,
162 private_host_t
*this)
164 chunk_t address
= chunk_empty
;
166 switch (this->address
.sa_family
)
170 address
.ptr
= (char*)&(this->address4
.sin_addr
.s_addr
);
171 address
.len
= IPV4_LEN
;
176 address
.ptr
= (char*)&(this->address6
.sin6_addr
.s6_addr
);
177 address
.len
= IPV6_LEN
;
182 /* return empty chunk */
188 METHOD(host_t
, get_family
, int,
189 private_host_t
*this)
191 return this->address
.sa_family
;
194 METHOD(host_t
, get_port
, u_int16_t
,
195 private_host_t
*this)
197 switch (this->address
.sa_family
)
201 return ntohs(this->address4
.sin_port
);
205 return ntohs(this->address6
.sin6_port
);
214 METHOD(host_t
, set_port
, void,
215 private_host_t
*this, u_int16_t port
)
217 switch (this->address
.sa_family
)
221 this->address4
.sin_port
= htons(port
);
226 this->address6
.sin6_port
= htons(port
);
236 METHOD(host_t
, clone_
, host_t
*,
237 private_host_t
*this)
241 new = malloc_thing(private_host_t
);
242 memcpy(new, this, sizeof(private_host_t
));
248 * Implements host_t.ip_equals
250 static bool ip_equals(private_host_t
*this, private_host_t
*other
)
252 if (this->address
.sa_family
!= other
->address
.sa_family
)
254 /* 0.0.0.0 and 0::0 are equal */
255 return (is_anyaddr(this) && is_anyaddr(other
));
258 switch (this->address
.sa_family
)
262 return memeq(&this->address4
.sin_addr
, &other
->address4
.sin_addr
,
263 sizeof(this->address4
.sin_addr
));
267 return memeq(&this->address6
.sin6_addr
, &other
->address6
.sin6_addr
,
268 sizeof(this->address6
.sin6_addr
));
277 * Implements host_t.equals
279 static bool equals(private_host_t
*this, private_host_t
*other
)
281 if (!ip_equals(this, other
))
286 switch (this->address
.sa_family
)
290 return (this->address4
.sin_port
== other
->address4
.sin_port
);
294 return (this->address6
.sin6_port
== other
->address6
.sin6_port
);
302 METHOD(host_t
, destroy
, void,
303 private_host_t
*this)
309 * Creates an empty host_t object
311 static private_host_t
*host_create_empty(void)
313 private_host_t
*this;
317 .get_sockaddr
= _get_sockaddr
,
318 .get_sockaddr_len
= _get_sockaddr_len
,
320 .get_family
= _get_family
,
321 .get_address
= _get_address
,
322 .get_port
= _get_port
,
323 .set_port
= _set_port
,
324 .ip_equals
= (bool (*)(host_t
*,host_t
*))ip_equals
,
325 .equals
= (bool (*)(host_t
*,host_t
*)) equals
,
326 .is_anyaddr
= _is_anyaddr
,
335 * Create a %any host with port
337 static host_t
*host_create_any_port(int family
, u_int16_t port
)
341 this = host_create_any(family
);
342 this->set_port(this, port
);
347 * Described in header.
349 host_t
*host_create_from_string_and_family(char *string
, int family
,
353 struct sockaddr_in v4
;
354 struct sockaddr_in6 v6
;
361 if (streq(string
, "%any"))
363 return host_create_any_port(family ? family
: AF_INET
, port
);
365 if (family
== AF_UNSPEC
|| family
== AF_INET
)
367 if (streq(string
, "%any4") || streq(string
, "0.0.0.0"))
369 return host_create_any_port(AF_INET
, port
);
372 if (family
== AF_UNSPEC
|| family
== AF_INET6
)
374 if (streq(string
, "%any6") || streq(string
, "::"))
376 return host_create_any_port(AF_INET6
, port
);
382 if (strchr(string
, '.'))
388 memset(&addr
.v6
, 0, sizeof(addr
.v6
));
389 if (inet_pton(AF_INET6
, string
, &addr
.v6
.sin6_addr
) != 1)
393 addr
.v6
.sin6_port
= htons(port
);
394 addr
.v6
.sin6_family
= AF_INET6
;
395 return host_create_from_sockaddr((sockaddr_t
*)&addr
);
397 if (strchr(string
, ':'))
398 { /* do not try to convert v6 addresses for v4 family */
402 memset(&addr
.v4
, 0, sizeof(addr
.v4
));
403 if (inet_pton(AF_INET
, string
, &addr
.v4
.sin_addr
) != 1)
407 addr
.v4
.sin_port
= htons(port
);
408 addr
.v4
.sin_family
= AF_INET
;
409 return host_create_from_sockaddr((sockaddr_t
*)&addr
);
416 * Described in header.
418 host_t
*host_create_from_string(char *string
, u_int16_t port
)
420 return host_create_from_string_and_family(string
, AF_UNSPEC
, port
);
424 * Described in header.
426 host_t
*host_create_from_sockaddr(sockaddr_t
*sockaddr
)
428 private_host_t
*this = host_create_empty();
430 switch (sockaddr
->sa_family
)
434 memcpy(&this->address4
, (struct sockaddr_in
*)sockaddr
,
435 sizeof(struct sockaddr_in
));
436 this->socklen
= sizeof(struct sockaddr_in
);
438 return &this->public;
442 memcpy(&this->address6
, (struct sockaddr_in6
*)sockaddr
,
443 sizeof(struct sockaddr_in6
));
444 this->socklen
= sizeof(struct sockaddr_in6
);
446 return &this->public;
456 * Described in header.
458 host_t
*host_create_from_dns(char *string
, int af
, u_int16_t port
)
462 this = host_create_from_string_and_family(string
, af
, port
);
465 this = lib
->hosts
->resolve(lib
->hosts
, string
, af
);
469 this->set_port(this, port
);
475 * Described in header.
477 host_t
*host_create_from_chunk(int family
, chunk_t address
, u_int16_t port
)
479 private_host_t
*this;
484 if (address
.len
< IPV4_LEN
)
488 address
.len
= IPV4_LEN
;
491 if (address
.len
< IPV6_LEN
)
495 address
.len
= IPV6_LEN
;
513 this = host_create_empty();
514 this->address
.sa_family
= family
;
518 memcpy(&this->address4
.sin_addr
.s_addr
, address
.ptr
, address
.len
);
519 this->address4
.sin_port
= htons(port
);
520 this->socklen
= sizeof(struct sockaddr_in
);
523 memcpy(&this->address6
.sin6_addr
.s6_addr
, address
.ptr
, address
.len
);
524 this->address6
.sin6_port
= htons(port
);
525 this->socklen
= sizeof(struct sockaddr_in6
);
529 return &this->public;
533 * Described in header.
535 bool host_create_from_range(char *string
, host_t
**from
, host_t
**to
)
539 sep
= strchr(string
, '-');
544 for (pos
= sep
+1; *pos
&& *pos
== ' '; pos
++)
546 /* trim spaces before to address*/
548 *to
= host_create_from_string(pos
, 0);
553 for (pos
= sep
-1; pos
> string
&& *pos
== ' '; pos
--)
555 /* trim spaces behind from address */
557 pos
= strndup(string
, pos
- string
+ 1);
558 *from
= host_create_from_string_and_family(pos
, (*to
)->get_family(*to
), 0);
569 * Described in header.
571 host_t
*host_create_from_subnet(char *string
, int *bits
)
576 pos
= strchr(string
, '/');
579 if (pos
- string
>= sizeof(buf
))
583 strncpy(buf
, string
, pos
- string
);
584 buf
[pos
- string
] = '\0';
585 *bits
= atoi(pos
+ 1);
586 return host_create_from_string(buf
, 0);
588 net
= host_create_from_string(string
, 0);
591 if (net
->get_family(net
) == AF_INET
)
606 host_t
*host_create_netmask(int family
, int netbits
)
608 private_host_t
*this;
609 int bits
, bytes
, len
= 0;
615 if (netbits
< 0 || netbits
> 32)
619 this = host_create_empty();
620 this->socklen
= sizeof(struct sockaddr_in
);
621 target
= (char*)&this->address4
.sin_addr
;
625 if (netbits
< 0 || netbits
> 128)
629 this = host_create_empty();
630 this->socklen
= sizeof(struct sockaddr_in6
);
631 target
= (char*)&this->address6
.sin6_addr
;
638 memset(&this->address_max
, 0, sizeof(struct sockaddr_storage
));
639 this->address
.sa_family
= family
;
643 bits
= 8 - (netbits
& 0x07);
645 memset(target
, 0xff, bytes
);
648 memset(target
+ bytes
, 0x00, len
- bytes
);
649 target
[bytes
] = (u_int8_t
)(0xff << bits
);
651 return &this->public;
655 * Described in header.
657 host_t
*host_create_any(int family
)
659 private_host_t
*this = host_create_empty();
661 memset(&this->address_max
, 0, sizeof(struct sockaddr_storage
));
662 this->address
.sa_family
= family
;
668 this->socklen
= sizeof(struct sockaddr_in
);
670 return &(this->public);
674 this->socklen
= sizeof(struct sockaddr_in6
);
676 return &this->public;