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(char *string
, u_int16_t port
)
363 private_host_t
*this;
365 if (streq(string
, "%any"))
367 return host_create_any_port(AF_INET
, port
);
369 if (streq(string
, "%any6"))
371 return host_create_any_port(AF_INET6
, port
);
374 this = host_create_empty();
375 if (strchr(string
, '.'))
377 this->address
.sa_family
= AF_INET
;
381 this->address
.sa_family
= AF_INET6
;
383 switch (this->address
.sa_family
)
387 if (inet_pton(AF_INET
, string
, &this->address4
.sin_addr
) <=0)
391 this->address4
.sin_port
= htons(port
);
392 this->socklen
= sizeof(struct sockaddr_in
);
393 return &this->public;
397 if (inet_pton(AF_INET6
, string
, &this->address6
.sin6_addr
) <=0)
401 this->address6
.sin6_port
= htons(port
);
402 this->socklen
= sizeof(struct sockaddr_in6
);
403 return &this->public;
415 * Described in header.
417 host_t
*host_create_from_sockaddr(sockaddr_t
*sockaddr
)
419 private_host_t
*this = host_create_empty();
421 switch (sockaddr
->sa_family
)
425 memcpy(&this->address4
, (struct sockaddr_in
*)sockaddr
,
426 sizeof(struct sockaddr_in
));
427 this->socklen
= sizeof(struct sockaddr_in
);
428 return &this->public;
432 memcpy(&this->address6
, (struct sockaddr_in6
*)sockaddr
,
433 sizeof(struct sockaddr_in6
));
434 this->socklen
= sizeof(struct sockaddr_in6
);
435 return &this->public;
445 * Described in header.
447 host_t
*host_create_from_dns(char *string
, int af
, u_int16_t port
)
451 this = lib
->hosts
->resolve(lib
->hosts
, string
, af
);
454 this->set_port(this, port
);
460 * Described in header.
462 host_t
*host_create_from_chunk(int family
, chunk_t address
, u_int16_t port
)
464 private_host_t
*this;
469 if (address
.len
< IPV4_LEN
)
473 address
.len
= IPV4_LEN
;
476 if (address
.len
< IPV6_LEN
)
480 address
.len
= IPV6_LEN
;
498 this = host_create_empty();
499 this->address
.sa_family
= family
;
503 memcpy(&this->address4
.sin_addr
.s_addr
, address
.ptr
, address
.len
);
504 this->address4
.sin_port
= htons(port
);
505 this->socklen
= sizeof(struct sockaddr_in
);
508 memcpy(&this->address6
.sin6_addr
.s6_addr
, address
.ptr
, address
.len
);
509 this->address6
.sin6_port
= htons(port
);
510 this->socklen
= sizeof(struct sockaddr_in6
);
513 return &this->public;
517 * Described in header.
519 host_t
*host_create_from_subnet(char *string
, int *bits
)
524 pos
= strchr(string
, '/');
527 if (pos
- string
>= sizeof(buf
))
531 strncpy(buf
, string
, pos
- string
);
532 buf
[pos
- string
] = '\0';
533 *bits
= atoi(pos
+ 1);
534 return host_create_from_string(buf
, 0);
536 net
= host_create_from_string(string
, 0);
539 if (net
->get_family(net
) == AF_INET
)
552 * Described in header.
554 host_t
*host_create_any(int family
)
556 private_host_t
*this = host_create_empty();
558 memset(&this->address_max
, 0, sizeof(struct sockaddr_storage
));
559 this->address
.sa_family
= family
;
565 this->socklen
= sizeof(struct sockaddr_in
);
566 return &(this->public);
570 this->socklen
= sizeof(struct sockaddr_in6
);
571 return &this->public;