4 * @brief Implementation of host_t.
9 * Copyright (C) 2006-2007 Tobias Brunner
10 * Copyright (C) 2006 Daniel Roethlisberger
11 * Copyright (C) 2005-2006 Martin Willi
12 * Copyright (C) 2005 Jan Hutter
13 * Hochschule fuer Technik Rapperswil
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32 typedef struct private_host_t private_host_t
;
35 * @brief Private Data of a host object.
37 struct private_host_t
{
44 * low-lewel structure, wich stores the address
48 struct sockaddr address
;
49 /** maximum sockaddr size */
50 struct sockaddr_storage address_max
;
52 struct sockaddr_in address4
;
54 struct sockaddr_in6 address6
;
57 * length of address structure
64 * implements host_t.get_sockaddr
66 static sockaddr_t
*get_sockaddr(private_host_t
*this)
68 return &(this->address
);
72 * implements host_t.get_sockaddr_len
74 static socklen_t
*get_sockaddr_len(private_host_t
*this)
76 return &(this->socklen
);
80 * Implementation of host_t.is_anyaddr.
82 static bool is_anyaddr(private_host_t
*this)
84 switch (this->address
.sa_family
)
88 u_int8_t default_route
[4];
89 memset(default_route
, 0, sizeof(default_route
));
90 return memeq(default_route
, &(this->address4
.sin_addr
.s_addr
),
91 sizeof(default_route
));
95 u_int8_t default_route
[16];
96 memset(default_route
, 0, sizeof(default_route
));
97 return memeq(default_route
, &(this->address6
.sin6_addr
.s6_addr
),
98 sizeof(default_route
));
108 * output handler in printf()
110 static int print(FILE *stream
, const struct printf_info
*info
,
111 const void *const *args
)
113 private_host_t
*this = *((private_host_t
**)(args
[0]));
114 char buffer
[INET6_ADDRSTRLEN
];
120 return fprintf(stream
, "(null)");
123 if (is_anyaddr(this))
125 return fprintf(stream
, "%%any");
128 switch (this->address
.sa_family
)
131 address
= &this->address4
.sin_addr
;
132 port
= this->address4
.sin_port
;
135 address
= &this->address6
.sin6_addr
;
136 port
= this->address6
.sin6_port
;
139 return fprintf(stream
, "(family not supported)");
142 if (inet_ntop(this->address
.sa_family
, address
,
143 buffer
, sizeof(buffer
)) == NULL
)
145 return fprintf(stream
, "(address conversion failed)");
150 return fprintf(stream
, "%s[%d]", buffer
, ntohs(port
));
154 return fprintf(stream
, "%s", buffer
);
159 * register printf() handlers
161 static void __attribute__ ((constructor
))print_register()
163 register_printf_function(PRINTF_HOST
, print
, arginfo_ptr
);
167 * Implementation of host_t.get_address.
169 static chunk_t
get_address(private_host_t
*this)
171 chunk_t address
= chunk_empty
;
173 switch (this->address
.sa_family
)
177 address
.ptr
= (char*)&(this->address4
.sin_addr
.s_addr
);
183 address
.ptr
= (char*)&(this->address6
.sin6_addr
.s6_addr
);
189 /* return empty chunk */
196 * implements host_t.get_family
198 static int get_family(private_host_t
*this)
200 return this->address
.sa_family
;
204 * implements host_t.get_port
206 static u_int16_t
get_port(private_host_t
*this)
208 switch (this->address
.sa_family
)
212 return ntohs(this->address4
.sin_port
);
216 return ntohs(this->address6
.sin6_port
);
226 * implements host_t.set_port
228 static void set_port(private_host_t
*this, u_int16_t port
)
230 switch (this->address
.sa_family
)
234 this->address4
.sin_port
= htons(port
);
239 this->address6
.sin6_port
= htons(port
);
250 * Implements host_t.clone.
252 static private_host_t
*clone_(private_host_t
*this)
254 private_host_t
*new = malloc_thing(private_host_t
);
256 memcpy(new, this, sizeof(private_host_t
));
261 * Impelements host_t.ip_equals
263 static bool ip_equals(private_host_t
*this, private_host_t
*other
)
265 if (this->address
.sa_family
!= other
->address
.sa_family
)
267 /* 0.0.0.0 and ::0 are equal */
268 if (is_anyaddr(this) && is_anyaddr(other
))
276 switch (this->address
.sa_family
)
280 if (memeq(&this->address4
.sin_addr
, &other
->address4
.sin_addr
,
281 sizeof(this->address4
.sin_addr
)))
289 if (memeq(&this->address6
.sin6_addr
, &other
->address6
.sin6_addr
,
290 sizeof(this->address6
.sin6_addr
)))
302 * Implements host_t.get_differences
304 static host_diff_t
get_differences(host_t
*this, host_t
*other
)
306 host_diff_t ret
= HOST_DIFF_NONE
;
308 if (!this->ip_equals(this, other
))
310 ret
|= HOST_DIFF_ADDR
;
313 if (this->get_port(this) != other
->get_port(other
))
315 ret
|= HOST_DIFF_PORT
;
322 * Impelements host_t.equals
324 static bool equals(private_host_t
*this, private_host_t
*other
)
326 if (!ip_equals(this, other
))
331 switch (this->address
.sa_family
)
335 if (this->address4
.sin_port
== other
->address4
.sin_port
)
343 if (this->address6
.sin6_port
== other
->address6
.sin6_port
)
356 * Implements host_t.destroy
358 static void destroy(private_host_t
*this)
364 * Creates an empty host_t object
366 static private_host_t
*host_create_empty(void)
368 private_host_t
*this = malloc_thing(private_host_t
);
370 this->public.get_sockaddr
= (sockaddr_t
* (*) (host_t
*))get_sockaddr
;
371 this->public.get_sockaddr_len
= (socklen_t
*(*) (host_t
*))get_sockaddr_len
;
372 this->public.clone
= (host_t
* (*) (host_t
*))clone_
;
373 this->public.get_family
= (int (*) (host_t
*))get_family
;
374 this->public.get_address
= (chunk_t (*) (host_t
*)) get_address
;
375 this->public.get_port
= (u_int16_t (*) (host_t
*))get_port
;
376 this->public.set_port
= (void (*) (host_t
*,u_int16_t
))set_port
;
377 this->public.get_differences
= get_differences
;
378 this->public.ip_equals
= (bool (*) (host_t
*,host_t
*)) ip_equals
;
379 this->public.equals
= (bool (*) (host_t
*,host_t
*)) equals
;
380 this->public.is_anyaddr
= (bool (*) (host_t
*)) is_anyaddr
;
381 this->public.destroy
= (void (*) (host_t
*))destroy
;
387 * Described in header.
389 host_t
*host_create_from_string(char *string
, u_int16_t port
)
391 private_host_t
*this = host_create_empty();
393 if (strchr(string
, '.'))
395 this->address
.sa_family
= AF_INET
;
399 this->address
.sa_family
= AF_INET6
;
402 switch (this->address
.sa_family
)
406 if (inet_pton(AF_INET
, string
, &this->address4
.sin_addr
) <=0)
410 this->address4
.sin_port
= htons(port
);
411 this->socklen
= sizeof(struct sockaddr_in
);
412 return &this->public;
416 if (inet_pton(AF_INET6
, string
, &this->address6
.sin6_addr
) <=0)
420 this->address6
.sin6_port
= htons(port
);
421 this->socklen
= sizeof(struct sockaddr_in6
);
422 return &this->public;
434 * Described in header.
436 host_t
*host_create_from_chunk(int family
, chunk_t address
, u_int16_t port
)
438 private_host_t
*this = host_create_empty();
440 this->address
.sa_family
= family
;
445 if (address
.len
!= 4)
449 memcpy(&(this->address4
.sin_addr
.s_addr
), address
.ptr
,4);
450 this->address4
.sin_port
= htons(port
);
451 this->socklen
= sizeof(struct sockaddr_in
);
452 return &(this->public);
456 if (address
.len
!= 16)
460 memcpy(&(this->address6
.sin6_addr
.s6_addr
), address
.ptr
, 16);
461 this->address6
.sin6_port
= htons(port
);
462 this->socklen
= sizeof(struct sockaddr_in6
);
463 return &this->public;
473 * Described in header.
475 host_t
*host_create_from_sockaddr(sockaddr_t
*sockaddr
)
477 private_host_t
*this = host_create_empty();
479 switch (sockaddr
->sa_family
)
483 memcpy(&this->address4
, sockaddr
, sizeof(struct sockaddr_in
));
484 this->socklen
= sizeof(struct sockaddr_in
);
485 return &this->public;
489 memcpy(&this->address6
, sockaddr
, sizeof(struct sockaddr_in6
));
490 this->socklen
= sizeof(struct sockaddr_in6
);
491 return &this->public;
501 * Described in header.
503 host_t
*host_create_any(int family
)
505 private_host_t
*this = host_create_empty();
507 memset(&this->address_max
, 0, sizeof(struct sockaddr_storage
));
508 this->address
.sa_family
= family
;
514 this->socklen
= sizeof(struct sockaddr_in
);
515 return &(this->public);
519 this->socklen
= sizeof(struct sockaddr_in6
);
520 return &this->public;