2 * Copyright (C) 2006-2012 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 METHOD(host_t
, get_sockaddr
, sockaddr_t
*,
61 return &(this->address
);
64 METHOD(host_t
, get_sockaddr_len
, socklen_t
*,
67 return &(this->socklen
);
70 METHOD(host_t
, is_anyaddr
, bool,
73 static const u_int8_t zeroes
[IPV6_LEN
];
75 switch (this->address
.sa_family
)
79 return memeq(zeroes
, &(this->address4
.sin_addr
.s_addr
), IPV4_LEN
);
83 return memeq(zeroes
, &(this->address6
.sin6_addr
.s6_addr
), IPV6_LEN
);
93 * Described in header.
95 int host_printf_hook(printf_hook_data_t
*data
, printf_hook_spec_t
*spec
,
96 const void *const *args
)
98 private_host_t
*this = *((private_host_t
**)(args
[0]));
99 char buffer
[INET6_ADDRSTRLEN
+ 16];
103 snprintf(buffer
, sizeof(buffer
), "(null)");
105 else if (is_anyaddr(this) && !spec
->plus
)
107 snprintf(buffer
, sizeof(buffer
), "%%any%s",
108 this->address
.sa_family
== AF_INET6 ?
"6" : "");
116 address
= &this->address6
.sin6_addr
;
117 port
= this->address6
.sin6_port
;
119 switch (this->address
.sa_family
)
122 address
= &this->address4
.sin_addr
;
123 port
= this->address4
.sin_port
;
127 if (inet_ntop(this->address
.sa_family
, address
,
128 buffer
, sizeof(buffer
)) == NULL
)
130 snprintf(buffer
, sizeof(buffer
),
131 "(address conversion failed)");
135 len
= strlen(buffer
);
136 snprintf(buffer
+ len
, sizeof(buffer
) - len
,
137 "[%d]", ntohs(port
));
141 snprintf(buffer
, sizeof(buffer
), "(family not supported)");
147 return print_in_hook(data
, "%-*s", spec
->width
, buffer
);
149 return print_in_hook(data
, "%*s", spec
->width
, buffer
);
152 METHOD(host_t
, get_address
, chunk_t
,
153 private_host_t
*this)
155 chunk_t address
= chunk_empty
;
157 switch (this->address
.sa_family
)
161 address
.ptr
= (char*)&(this->address4
.sin_addr
.s_addr
);
162 address
.len
= IPV4_LEN
;
167 address
.ptr
= (char*)&(this->address6
.sin6_addr
.s6_addr
);
168 address
.len
= IPV6_LEN
;
173 /* return empty chunk */
179 METHOD(host_t
, get_family
, int,
180 private_host_t
*this)
182 return this->address
.sa_family
;
185 METHOD(host_t
, get_port
, u_int16_t
,
186 private_host_t
*this)
188 switch (this->address
.sa_family
)
192 return ntohs(this->address4
.sin_port
);
196 return ntohs(this->address6
.sin6_port
);
205 METHOD(host_t
, set_port
, void,
206 private_host_t
*this, u_int16_t port
)
208 switch (this->address
.sa_family
)
212 this->address4
.sin_port
= htons(port
);
217 this->address6
.sin6_port
= htons(port
);
227 METHOD(host_t
, clone_
, host_t
*,
228 private_host_t
*this)
232 new = malloc_thing(private_host_t
);
233 memcpy(new, this, sizeof(private_host_t
));
239 * Implements host_t.ip_equals
241 static bool ip_equals(private_host_t
*this, private_host_t
*other
)
243 if (this->address
.sa_family
!= other
->address
.sa_family
)
245 /* 0.0.0.0 and 0::0 are equal */
246 return (is_anyaddr(this) && is_anyaddr(other
));
249 switch (this->address
.sa_family
)
253 return memeq(&this->address4
.sin_addr
, &other
->address4
.sin_addr
,
254 sizeof(this->address4
.sin_addr
));
258 return memeq(&this->address6
.sin6_addr
, &other
->address6
.sin6_addr
,
259 sizeof(this->address6
.sin6_addr
));
268 * Implements host_t.get_differences
270 static host_diff_t
get_differences(host_t
*this, host_t
*other
)
272 host_diff_t ret
= HOST_DIFF_NONE
;
274 if (!this->ip_equals(this, other
))
276 ret
|= HOST_DIFF_ADDR
;
279 if (this->get_port(this) != other
->get_port(other
))
281 ret
|= HOST_DIFF_PORT
;
288 * Implements host_t.equals
290 static bool equals(private_host_t
*this, private_host_t
*other
)
292 if (!ip_equals(this, other
))
297 switch (this->address
.sa_family
)
301 return (this->address4
.sin_port
== other
->address4
.sin_port
);
305 return (this->address6
.sin6_port
== other
->address6
.sin6_port
);
313 METHOD(host_t
, destroy
, void,
314 private_host_t
*this)
320 * Creates an empty host_t object
322 static private_host_t
*host_create_empty(void)
324 private_host_t
*this;
328 .get_sockaddr
= _get_sockaddr
,
329 .get_sockaddr_len
= _get_sockaddr_len
,
331 .get_family
= _get_family
,
332 .get_address
= _get_address
,
333 .get_port
= _get_port
,
334 .set_port
= _set_port
,
335 .get_differences
= get_differences
,
336 .ip_equals
= (bool (*)(host_t
*,host_t
*))ip_equals
,
337 .equals
= (bool (*)(host_t
*,host_t
*)) equals
,
338 .is_anyaddr
= _is_anyaddr
,
347 * Create a %any host with port
349 static host_t
*host_create_any_port(int family
, u_int16_t port
)
353 this = host_create_any(family
);
354 this->set_port(this, port
);
359 * Described in header.
361 host_t
*host_create_from_string_and_family(char *string
, int family
,
366 struct sockaddr_in v4
;
367 struct sockaddr_in6 v6
;
370 if (streq(string
, "%any"))
372 return host_create_any_port(family ? family
: AF_INET
, port
);
374 if (family
== AF_UNSPEC
|| family
== AF_INET
)
376 if (streq(string
, "%any4") || streq(string
, "0.0.0.0"))
378 return host_create_any_port(AF_INET
, port
);
381 if (family
== AF_UNSPEC
|| family
== AF_INET6
)
383 if (streq(string
, "%any6") || streq(string
, "::"))
385 return host_create_any_port(AF_INET6
, port
);
391 if (strchr(string
, '.'))
397 if (inet_pton(AF_INET6
, string
, &addr
.v6
.sin6_addr
) != 1)
401 addr
.v6
.sin6_port
= htons(port
);
402 addr
.sockaddr
.sa_family
= AF_INET6
;
403 return host_create_from_sockaddr(&addr
.sockaddr
);
405 if (strchr(string
, ':'))
406 { /* do not try to convert v6 addresses for v4 family */
410 if (inet_pton(AF_INET
, string
, &addr
.v4
.sin_addr
) != 1)
414 addr
.v4
.sin_port
= htons(port
);
415 addr
.sockaddr
.sa_family
= AF_INET
;
416 return host_create_from_sockaddr(&addr
.sockaddr
);
423 * Described in header.
425 host_t
*host_create_from_string(char *string
, u_int16_t port
)
427 return host_create_from_string_and_family(string
, AF_UNSPEC
, port
);
431 * Described in header.
433 host_t
*host_create_from_sockaddr(sockaddr_t
*sockaddr
)
435 private_host_t
*this = host_create_empty();
437 switch (sockaddr
->sa_family
)
441 memcpy(&this->address4
, (struct sockaddr_in
*)sockaddr
,
442 sizeof(struct sockaddr_in
));
443 this->socklen
= sizeof(struct sockaddr_in
);
444 return &this->public;
448 memcpy(&this->address6
, (struct sockaddr_in6
*)sockaddr
,
449 sizeof(struct sockaddr_in6
));
450 this->socklen
= sizeof(struct sockaddr_in6
);
451 return &this->public;
461 * Described in header.
463 host_t
*host_create_from_dns(char *string
, int af
, u_int16_t port
)
467 this = host_create_from_string_and_family(string
, af
, port
);
470 this = lib
->hosts
->resolve(lib
->hosts
, string
, af
);
474 this->set_port(this, port
);
480 * Described in header.
482 host_t
*host_create_from_chunk(int family
, chunk_t address
, u_int16_t port
)
484 private_host_t
*this;
489 if (address
.len
< IPV4_LEN
)
493 address
.len
= IPV4_LEN
;
496 if (address
.len
< IPV6_LEN
)
500 address
.len
= IPV6_LEN
;
518 this = host_create_empty();
519 this->address
.sa_family
= family
;
523 memcpy(&this->address4
.sin_addr
.s_addr
, address
.ptr
, address
.len
);
524 this->address4
.sin_port
= htons(port
);
525 this->socklen
= sizeof(struct sockaddr_in
);
528 memcpy(&this->address6
.sin6_addr
.s6_addr
, address
.ptr
, address
.len
);
529 this->address6
.sin6_port
= htons(port
);
530 this->socklen
= sizeof(struct sockaddr_in6
);
533 return &this->public;
537 * Described in header.
539 host_t
*host_create_from_subnet(char *string
, int *bits
)
544 pos
= strchr(string
, '/');
547 if (pos
- string
>= sizeof(buf
))
551 strncpy(buf
, string
, pos
- string
);
552 buf
[pos
- string
] = '\0';
553 *bits
= atoi(pos
+ 1);
554 return host_create_from_string(buf
, 0);
556 net
= host_create_from_string(string
, 0);
559 if (net
->get_family(net
) == AF_INET
)
572 * Described in header.
574 host_t
*host_create_any(int family
)
576 private_host_t
*this = host_create_empty();
578 memset(&this->address_max
, 0, sizeof(struct sockaddr_storage
));
579 this->address
.sa_family
= family
;
585 this->socklen
= sizeof(struct sockaddr_in
);
586 return &(this->public);
590 this->socklen
= sizeof(struct sockaddr_in6
);
591 return &this->public;