/src/strongswan/src/libstrongswan/networking/host.c
Line | Count | Source |
1 | | /* |
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 | | * |
7 | | * Copyright (C) secunet Security Networks AG |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU General Public License as published by the |
11 | | * Free Software Foundation; either version 2 of the License, or (at your |
12 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, but |
15 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
17 | | * for more details. |
18 | | */ |
19 | | |
20 | | #include "host.h" |
21 | | |
22 | | #include <utils/debug.h> |
23 | | #include <library.h> |
24 | | |
25 | 0 | #define IPV4_LEN 4 |
26 | 0 | #define IPV6_LEN 16 |
27 | | |
28 | | typedef struct private_host_t private_host_t; |
29 | | |
30 | | /** |
31 | | * Private Data of a host object. |
32 | | */ |
33 | | struct private_host_t { |
34 | | /** |
35 | | * Public data |
36 | | */ |
37 | | host_t public; |
38 | | |
39 | | /** |
40 | | * low-lewel structure, which stores the address |
41 | | */ |
42 | | union { |
43 | | /** generic type */ |
44 | | struct sockaddr address; |
45 | | /** maximum sockaddr size */ |
46 | | struct sockaddr_storage address_max; |
47 | | /** IPv4 address */ |
48 | | struct sockaddr_in address4; |
49 | | /** IPv6 address */ |
50 | | struct sockaddr_in6 address6; |
51 | | }; |
52 | | /** |
53 | | * length of address structure |
54 | | */ |
55 | | socklen_t socklen; |
56 | | }; |
57 | | |
58 | | /** |
59 | | * Update the sockaddr internal sa_len option, if available |
60 | | */ |
61 | | static inline void update_sa_len(private_host_t *this) |
62 | 5.72k | { |
63 | | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
64 | | this->address.sa_len = this->socklen; |
65 | | #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ |
66 | 5.72k | } |
67 | | |
68 | | METHOD(host_t, get_sockaddr, sockaddr_t*, |
69 | | private_host_t *this) |
70 | 0 | { |
71 | 0 | return &(this->address); |
72 | 0 | } |
73 | | |
74 | | METHOD(host_t, get_sockaddr_len, socklen_t*, |
75 | | private_host_t *this) |
76 | 0 | { |
77 | 0 | return &(this->socklen); |
78 | 0 | } |
79 | | |
80 | | METHOD(host_t, is_anyaddr, bool, |
81 | | private_host_t *this) |
82 | 0 | { |
83 | 0 | static const uint8_t zeroes[IPV6_LEN]; |
84 | |
|
85 | 0 | switch (this->address.sa_family) |
86 | 0 | { |
87 | 0 | case AF_INET: |
88 | 0 | { |
89 | 0 | return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN); |
90 | 0 | } |
91 | 0 | case AF_INET6: |
92 | 0 | { |
93 | 0 | return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN); |
94 | 0 | } |
95 | 0 | default: |
96 | 0 | { |
97 | 0 | return FALSE; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * Described in header. |
104 | | */ |
105 | | int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, |
106 | | const void *const *args) |
107 | 0 | { |
108 | 0 | private_host_t *this = *((private_host_t**)(args[0])); |
109 | 0 | char buffer[INET6_ADDRSTRLEN + 16]; |
110 | |
|
111 | 0 | if (this == NULL) |
112 | 0 | { |
113 | 0 | snprintf(buffer, sizeof(buffer), "(null)"); |
114 | 0 | } |
115 | 0 | else if (is_anyaddr(this) && !spec->plus && !spec->hash) |
116 | 0 | { |
117 | 0 | snprintf(buffer, sizeof(buffer), "%%any%s", |
118 | 0 | this->address.sa_family == AF_INET6 ? "6" : ""); |
119 | 0 | } |
120 | 0 | else |
121 | 0 | { |
122 | 0 | void *address; |
123 | 0 | uint16_t port; |
124 | 0 | int len; |
125 | |
|
126 | 0 | address = &this->address6.sin6_addr; |
127 | 0 | port = this->address6.sin6_port; |
128 | |
|
129 | 0 | switch (this->address.sa_family) |
130 | 0 | { |
131 | 0 | case AF_INET: |
132 | 0 | address = &this->address4.sin_addr; |
133 | 0 | port = this->address4.sin_port; |
134 | | /* fall */ |
135 | 0 | case AF_INET6: |
136 | |
|
137 | 0 | if (inet_ntop(this->address.sa_family, address, |
138 | 0 | buffer, sizeof(buffer)) == NULL) |
139 | 0 | { |
140 | 0 | snprintf(buffer, sizeof(buffer), |
141 | 0 | "(address conversion failed)"); |
142 | 0 | } |
143 | 0 | else if (spec->hash && port) |
144 | 0 | { |
145 | 0 | len = strlen(buffer); |
146 | 0 | snprintf(buffer + len, sizeof(buffer) - len, |
147 | 0 | "[%d]", ntohs(port)); |
148 | 0 | } |
149 | 0 | break; |
150 | 0 | default: |
151 | 0 | snprintf(buffer, sizeof(buffer), "(family not supported)"); |
152 | 0 | break; |
153 | 0 | } |
154 | 0 | } |
155 | 0 | if (spec->minus) |
156 | 0 | { |
157 | 0 | return print_in_hook(data, "%-*s", spec->width, buffer); |
158 | 0 | } |
159 | 0 | return print_in_hook(data, "%*s", spec->width, buffer); |
160 | 0 | } |
161 | | |
162 | | METHOD(host_t, get_address, chunk_t, |
163 | | private_host_t *this) |
164 | 0 | { |
165 | 0 | chunk_t address = chunk_empty; |
166 | |
|
167 | 0 | switch (this->address.sa_family) |
168 | 0 | { |
169 | 0 | case AF_INET: |
170 | 0 | { |
171 | 0 | address.ptr = (char*)&(this->address4.sin_addr.s_addr); |
172 | 0 | address.len = IPV4_LEN; |
173 | 0 | return address; |
174 | 0 | } |
175 | 0 | case AF_INET6: |
176 | 0 | { |
177 | 0 | address.ptr = (char*)&(this->address6.sin6_addr.s6_addr); |
178 | 0 | address.len = IPV6_LEN; |
179 | 0 | return address; |
180 | 0 | } |
181 | 0 | default: |
182 | 0 | { |
183 | | /* return empty chunk */ |
184 | 0 | return address; |
185 | 0 | } |
186 | 0 | } |
187 | 0 | } |
188 | | |
189 | | METHOD(host_t, get_family, int, |
190 | | private_host_t *this) |
191 | 0 | { |
192 | 0 | return this->address.sa_family; |
193 | 0 | } |
194 | | |
195 | | METHOD(host_t, get_port, uint16_t, |
196 | | private_host_t *this) |
197 | 0 | { |
198 | 0 | switch (this->address.sa_family) |
199 | 0 | { |
200 | 0 | case AF_INET: |
201 | 0 | { |
202 | 0 | return ntohs(this->address4.sin_port); |
203 | 0 | } |
204 | 0 | case AF_INET6: |
205 | 0 | { |
206 | 0 | return ntohs(this->address6.sin6_port); |
207 | 0 | } |
208 | 0 | default: |
209 | 0 | { |
210 | 0 | return 0; |
211 | 0 | } |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | METHOD(host_t, set_port, void, |
216 | | private_host_t *this, uint16_t port) |
217 | 0 | { |
218 | 0 | switch (this->address.sa_family) |
219 | 0 | { |
220 | 0 | case AF_INET: |
221 | 0 | { |
222 | 0 | this->address4.sin_port = htons(port); |
223 | 0 | break; |
224 | 0 | } |
225 | 0 | case AF_INET6: |
226 | 0 | { |
227 | 0 | this->address6.sin6_port = htons(port); |
228 | 0 | break; |
229 | 0 | } |
230 | 0 | default: |
231 | 0 | { |
232 | 0 | break; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | } |
236 | | |
237 | | METHOD(host_t, clone_, host_t*, |
238 | | private_host_t *this) |
239 | 0 | { |
240 | 0 | private_host_t *new; |
241 | |
|
242 | 0 | new = malloc_thing(private_host_t); |
243 | 0 | memcpy(new, this, sizeof(private_host_t)); |
244 | |
|
245 | 0 | return &new->public; |
246 | 0 | } |
247 | | |
248 | | /** |
249 | | * Implements host_t.ip_equals |
250 | | */ |
251 | | static bool ip_equals(private_host_t *this, private_host_t *other) |
252 | 0 | { |
253 | 0 | if (this->address.sa_family != other->address.sa_family) |
254 | 0 | { |
255 | | /* 0.0.0.0 and 0::0 are equal */ |
256 | 0 | return (is_anyaddr(this) && is_anyaddr(other)); |
257 | 0 | } |
258 | | |
259 | 0 | switch (this->address.sa_family) |
260 | 0 | { |
261 | 0 | case AF_INET: |
262 | 0 | { |
263 | 0 | return memeq(&this->address4.sin_addr, &other->address4.sin_addr, |
264 | 0 | sizeof(this->address4.sin_addr)); |
265 | 0 | } |
266 | 0 | case AF_INET6: |
267 | 0 | { |
268 | 0 | return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr, |
269 | 0 | sizeof(this->address6.sin6_addr)); |
270 | 0 | } |
271 | 0 | default: |
272 | 0 | break; |
273 | 0 | } |
274 | 0 | return FALSE; |
275 | 0 | } |
276 | | |
277 | | /** |
278 | | * Implements host_t.equals |
279 | | */ |
280 | | static bool equals(private_host_t *this, private_host_t *other) |
281 | 0 | { |
282 | 0 | if (!ip_equals(this, other)) |
283 | 0 | { |
284 | 0 | return FALSE; |
285 | 0 | } |
286 | | |
287 | 0 | switch (this->address.sa_family) |
288 | 0 | { |
289 | 0 | case AF_INET: |
290 | 0 | { |
291 | 0 | return (this->address4.sin_port == other->address4.sin_port); |
292 | 0 | } |
293 | 0 | case AF_INET6: |
294 | 0 | { |
295 | 0 | return (this->address6.sin6_port == other->address6.sin6_port); |
296 | 0 | } |
297 | 0 | default: |
298 | 0 | break; |
299 | 0 | } |
300 | 0 | return FALSE; |
301 | 0 | } |
302 | | |
303 | | METHOD(host_t, destroy, void, |
304 | | private_host_t *this) |
305 | 5.72k | { |
306 | 5.72k | free(this); |
307 | 5.72k | } |
308 | | |
309 | | /** |
310 | | * Creates an empty host_t object |
311 | | */ |
312 | | static private_host_t *host_create_empty(void) |
313 | 5.72k | { |
314 | 5.72k | private_host_t *this; |
315 | | |
316 | 5.72k | INIT(this, |
317 | 5.72k | .public = { |
318 | 5.72k | .get_sockaddr = _get_sockaddr, |
319 | 5.72k | .get_sockaddr_len = _get_sockaddr_len, |
320 | 5.72k | .clone = _clone_, |
321 | 5.72k | .get_family = _get_family, |
322 | 5.72k | .get_address = _get_address, |
323 | 5.72k | .get_port = _get_port, |
324 | 5.72k | .set_port = _set_port, |
325 | 5.72k | .ip_equals = (bool (*)(host_t *,host_t *))ip_equals, |
326 | 5.72k | .equals = (bool (*)(host_t *,host_t *)) equals, |
327 | 5.72k | .is_anyaddr = _is_anyaddr, |
328 | 5.72k | .destroy = _destroy, |
329 | 5.72k | }, |
330 | 5.72k | ); |
331 | | |
332 | 5.72k | return this; |
333 | 5.72k | } |
334 | | |
335 | | /* |
336 | | * Create a %any host with port |
337 | | */ |
338 | | static host_t *host_create_any_port(int family, uint16_t port) |
339 | 0 | { |
340 | 0 | host_t *this; |
341 | |
|
342 | 0 | this = host_create_any(family); |
343 | 0 | this->set_port(this, port); |
344 | 0 | return this; |
345 | 0 | } |
346 | | |
347 | | /* |
348 | | * Described in header. |
349 | | */ |
350 | | host_t *host_create_from_string_and_family(char *string, int family, |
351 | | uint16_t port) |
352 | 5.72k | { |
353 | 5.72k | union { |
354 | 5.72k | struct sockaddr_in v4; |
355 | 5.72k | struct sockaddr_in6 v6; |
356 | 5.72k | } addr; |
357 | | |
358 | 5.72k | if (!string) |
359 | 0 | { |
360 | 0 | return NULL; |
361 | 0 | } |
362 | 5.72k | if (streq(string, "%any")) |
363 | 0 | { |
364 | 0 | return host_create_any_port(family ? family : AF_INET, port); |
365 | 0 | } |
366 | 5.72k | if (family == AF_UNSPEC || family == AF_INET) |
367 | 5.72k | { |
368 | 5.72k | if (streq(string, "%any4") || streq(string, "0.0.0.0")) |
369 | 0 | { |
370 | 0 | return host_create_any_port(AF_INET, port); |
371 | 0 | } |
372 | 5.72k | } |
373 | 5.72k | if (family == AF_UNSPEC || family == AF_INET6) |
374 | 5.72k | { |
375 | 5.72k | if (streq(string, "%any6") || streq(string, "::")) |
376 | 0 | { |
377 | 0 | return host_create_any_port(AF_INET6, port); |
378 | 0 | } |
379 | 5.72k | } |
380 | 5.72k | switch (family) |
381 | 5.72k | { |
382 | 5.72k | case AF_UNSPEC: |
383 | 5.72k | if (strchr(string, '.')) |
384 | 5.72k | { |
385 | 5.72k | goto af_inet; |
386 | 5.72k | } |
387 | | /* FALL */ |
388 | 0 | case AF_INET6: |
389 | 0 | memset(&addr.v6, 0, sizeof(addr.v6)); |
390 | 0 | if (inet_pton(AF_INET6, string, &addr.v6.sin6_addr) != 1) |
391 | 0 | { |
392 | 0 | return NULL; |
393 | 0 | } |
394 | 0 | addr.v6.sin6_port = htons(port); |
395 | 0 | addr.v6.sin6_family = AF_INET6; |
396 | 0 | return host_create_from_sockaddr((sockaddr_t*)&addr); |
397 | 0 | case AF_INET: |
398 | 0 | if (strchr(string, ':')) |
399 | 0 | { /* do not try to convert v6 addresses for v4 family */ |
400 | 0 | return NULL; |
401 | 0 | } |
402 | 5.72k | af_inet: |
403 | 5.72k | memset(&addr.v4, 0, sizeof(addr.v4)); |
404 | 5.72k | if (inet_pton(AF_INET, string, &addr.v4.sin_addr) != 1) |
405 | 0 | { |
406 | 0 | return NULL; |
407 | 0 | } |
408 | 5.72k | addr.v4.sin_port = htons(port); |
409 | 5.72k | addr.v4.sin_family = AF_INET; |
410 | 5.72k | return host_create_from_sockaddr((sockaddr_t*)&addr); |
411 | 0 | default: |
412 | 0 | return NULL; |
413 | 5.72k | } |
414 | 5.72k | } |
415 | | |
416 | | /* |
417 | | * Described in header. |
418 | | */ |
419 | | host_t *host_create_from_string(char *string, uint16_t port) |
420 | 5.72k | { |
421 | 5.72k | return host_create_from_string_and_family(string, AF_UNSPEC, port); |
422 | 5.72k | } |
423 | | |
424 | | /* |
425 | | * Described in header. |
426 | | */ |
427 | | host_t *host_create_from_sockaddr(sockaddr_t *sockaddr) |
428 | 5.72k | { |
429 | 5.72k | private_host_t *this = host_create_empty(); |
430 | | |
431 | 5.72k | switch (sockaddr->sa_family) |
432 | 5.72k | { |
433 | 5.72k | case AF_INET: |
434 | 5.72k | { |
435 | 5.72k | memcpy(&this->address4, (struct sockaddr_in*)sockaddr, |
436 | 5.72k | sizeof(struct sockaddr_in)); |
437 | 5.72k | this->socklen = sizeof(struct sockaddr_in); |
438 | 5.72k | update_sa_len(this); |
439 | 5.72k | return &this->public; |
440 | 0 | } |
441 | 0 | case AF_INET6: |
442 | 0 | { |
443 | 0 | memcpy(&this->address6, (struct sockaddr_in6*)sockaddr, |
444 | 0 | sizeof(struct sockaddr_in6)); |
445 | 0 | this->socklen = sizeof(struct sockaddr_in6); |
446 | 0 | update_sa_len(this); |
447 | 0 | return &this->public; |
448 | 0 | } |
449 | 0 | default: |
450 | 0 | break; |
451 | 5.72k | } |
452 | 0 | free(this); |
453 | 0 | return NULL; |
454 | 5.72k | } |
455 | | |
456 | | /* |
457 | | * Described in header. |
458 | | */ |
459 | | host_t *host_create_from_dns(char *string, int af, uint16_t port) |
460 | 0 | { |
461 | 0 | host_t *this; |
462 | |
|
463 | 0 | this = host_create_from_string_and_family(string, af, port); |
464 | 0 | if (!this && string && string[0] != '%') |
465 | 0 | { |
466 | 0 | this = lib->hosts->resolve(lib->hosts, string, af); |
467 | 0 | } |
468 | 0 | if (this) |
469 | 0 | { |
470 | 0 | this->set_port(this, port); |
471 | 0 | } |
472 | 0 | return this; |
473 | 0 | } |
474 | | |
475 | | /* |
476 | | * Described in header. |
477 | | */ |
478 | | host_t *host_create_from_chunk(int family, chunk_t address, uint16_t port) |
479 | 0 | { |
480 | 0 | private_host_t *this; |
481 | |
|
482 | 0 | switch (family) |
483 | 0 | { |
484 | 0 | case AF_INET: |
485 | 0 | if (address.len < IPV4_LEN) |
486 | 0 | { |
487 | 0 | return NULL; |
488 | 0 | } |
489 | 0 | address.len = IPV4_LEN; |
490 | 0 | break; |
491 | 0 | case AF_INET6: |
492 | 0 | if (address.len < IPV6_LEN) |
493 | 0 | { |
494 | 0 | return NULL; |
495 | 0 | } |
496 | 0 | address.len = IPV6_LEN; |
497 | 0 | break; |
498 | 0 | case AF_UNSPEC: |
499 | 0 | switch (address.len) |
500 | 0 | { |
501 | 0 | case IPV4_LEN: |
502 | 0 | family = AF_INET; |
503 | 0 | break; |
504 | 0 | case IPV6_LEN: |
505 | 0 | family = AF_INET6; |
506 | 0 | break; |
507 | 0 | default: |
508 | 0 | return NULL; |
509 | 0 | } |
510 | 0 | break; |
511 | 0 | default: |
512 | 0 | return NULL; |
513 | 0 | } |
514 | 0 | this = host_create_empty(); |
515 | 0 | this->address.sa_family = family; |
516 | 0 | switch (family) |
517 | 0 | { |
518 | 0 | case AF_INET: |
519 | 0 | memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len); |
520 | 0 | this->address4.sin_port = htons(port); |
521 | 0 | this->socklen = sizeof(struct sockaddr_in); |
522 | 0 | break; |
523 | 0 | case AF_INET6: |
524 | 0 | memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len); |
525 | 0 | this->address6.sin6_port = htons(port); |
526 | 0 | this->socklen = sizeof(struct sockaddr_in6); |
527 | 0 | break; |
528 | 0 | } |
529 | 0 | update_sa_len(this); |
530 | 0 | return &this->public; |
531 | 0 | } |
532 | | |
533 | | /* |
534 | | * Described in header. |
535 | | */ |
536 | | bool host_create_from_range(char *string, host_t **from, host_t **to) |
537 | 0 | { |
538 | 0 | char *sep, *pos; |
539 | |
|
540 | 0 | sep = strchr(string, '-'); |
541 | 0 | if (!sep) |
542 | 0 | { |
543 | 0 | return FALSE; |
544 | 0 | } |
545 | 0 | for (pos = sep+1; *pos && *pos == ' '; pos++) |
546 | 0 | { |
547 | | /* trim spaces before to address*/ |
548 | 0 | } |
549 | 0 | *to = host_create_from_string(pos, 0); |
550 | 0 | if (!*to) |
551 | 0 | { |
552 | 0 | return FALSE; |
553 | 0 | } |
554 | 0 | for (pos = sep-1; pos > string && *pos == ' '; pos--) |
555 | 0 | { |
556 | | /* trim spaces behind from address */ |
557 | 0 | } |
558 | 0 | pos = strndup(string, pos - string + 1); |
559 | 0 | *from = host_create_from_string_and_family(pos, (*to)->get_family(*to), 0); |
560 | 0 | free(pos); |
561 | 0 | if (!*from) |
562 | 0 | { |
563 | 0 | (*to)->destroy(*to); |
564 | 0 | return FALSE; |
565 | 0 | } |
566 | 0 | return TRUE; |
567 | 0 | } |
568 | | |
569 | | /* |
570 | | * Described in header. |
571 | | */ |
572 | | host_t *host_create_from_subnet(char *string, int *bits) |
573 | 0 | { |
574 | 0 | char *pos, buf[64]; |
575 | 0 | host_t *net; |
576 | |
|
577 | 0 | pos = strchr(string, '/'); |
578 | 0 | if (pos) |
579 | 0 | { |
580 | 0 | if (pos - string >= sizeof(buf)) |
581 | 0 | { |
582 | 0 | return NULL; |
583 | 0 | } |
584 | 0 | strncpy(buf, string, pos - string); |
585 | 0 | buf[pos - string] = '\0'; |
586 | 0 | *bits = atoi(pos + 1); |
587 | 0 | return host_create_from_string(buf, 0); |
588 | 0 | } |
589 | 0 | net = host_create_from_string(string, 0); |
590 | 0 | if (net) |
591 | 0 | { |
592 | 0 | if (net->get_family(net) == AF_INET) |
593 | 0 | { |
594 | 0 | *bits = 32; |
595 | 0 | } |
596 | 0 | else |
597 | 0 | { |
598 | 0 | *bits = 128; |
599 | 0 | } |
600 | 0 | } |
601 | 0 | return net; |
602 | 0 | } |
603 | | |
604 | | /* |
605 | | * See header. |
606 | | */ |
607 | | host_t *host_create_netmask(int family, int netbits) |
608 | 0 | { |
609 | 0 | private_host_t *this; |
610 | 0 | int bits, bytes, len = 0; |
611 | 0 | char *target; |
612 | |
|
613 | 0 | switch (family) |
614 | 0 | { |
615 | 0 | case AF_INET: |
616 | 0 | if (netbits < 0 || netbits > 32) |
617 | 0 | { |
618 | 0 | return NULL; |
619 | 0 | } |
620 | 0 | this = host_create_empty(); |
621 | 0 | this->socklen = sizeof(struct sockaddr_in); |
622 | 0 | target = (char*)&this->address4.sin_addr; |
623 | 0 | len = 4; |
624 | 0 | break; |
625 | 0 | case AF_INET6: |
626 | 0 | if (netbits < 0 || netbits > 128) |
627 | 0 | { |
628 | 0 | return NULL; |
629 | 0 | } |
630 | 0 | this = host_create_empty(); |
631 | 0 | this->socklen = sizeof(struct sockaddr_in6); |
632 | 0 | target = (char*)&this->address6.sin6_addr; |
633 | 0 | len = 16; |
634 | 0 | break; |
635 | 0 | default: |
636 | 0 | return NULL; |
637 | 0 | } |
638 | | |
639 | 0 | memset(&this->address_max, 0, sizeof(struct sockaddr_storage)); |
640 | 0 | this->address.sa_family = family; |
641 | 0 | update_sa_len(this); |
642 | |
|
643 | 0 | bytes = netbits / 8; |
644 | 0 | bits = 8 - (netbits & 0x07); |
645 | |
|
646 | 0 | memset(target, 0xff, bytes); |
647 | 0 | if (bytes < len) |
648 | 0 | { |
649 | 0 | memset(target + bytes, 0x00, len - bytes); |
650 | 0 | target[bytes] = (uint8_t)(0xff << bits); |
651 | 0 | } |
652 | 0 | return &this->public; |
653 | 0 | } |
654 | | |
655 | | /* |
656 | | * Described in header. |
657 | | */ |
658 | | host_t *host_create_any(int family) |
659 | 0 | { |
660 | 0 | private_host_t *this = host_create_empty(); |
661 | |
|
662 | 0 | memset(&this->address_max, 0, sizeof(struct sockaddr_storage)); |
663 | 0 | this->address.sa_family = family; |
664 | |
|
665 | 0 | switch (family) |
666 | 0 | { |
667 | 0 | case AF_INET: |
668 | 0 | { |
669 | 0 | this->socklen = sizeof(struct sockaddr_in); |
670 | 0 | update_sa_len(this); |
671 | 0 | return &(this->public); |
672 | 0 | } |
673 | 0 | case AF_INET6: |
674 | 0 | { |
675 | 0 | this->socklen = sizeof(struct sockaddr_in6); |
676 | 0 | update_sa_len(this); |
677 | 0 | return &this->public; |
678 | 0 | } |
679 | 0 | default: |
680 | 0 | break; |
681 | 0 | } |
682 | 0 | free(this); |
683 | | return NULL; |
684 | 0 | } |