source: mainline/uspace/lib/c/generic/inet/addr.c@ 4c14b88

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4c14b88 was 26de91a, checked in by Jiri Svoboda <jiri@…>, 12 years ago

IPv4 and v6 should not need separate handling by a simple client that is just connecting to a host/address. Add IPv6/DNS support in applications where missing.

  • Property mode set to 100644
File size: 14.8 KB
RevLine 
[3495654]1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file Internet address parsing and formatting.
33 */
34
[f023251]35#include <assert.h>
[3495654]36#include <errno.h>
[a2e3ee6]37#include <unistd.h>
38#include <net/socket_codes.h>
[3495654]39#include <inet/addr.h>
[a2e3ee6]40#include <net/inet.h>
[3495654]41#include <stdio.h>
[02a09ed]42#include <malloc.h>
43#include <bitops.h>
[3495654]44
[02a09ed]45#define INET_PREFIXSTRSIZE 5
46
47#if !(defined(__BE__) ^ defined(__LE__))
48 #error The architecture must be either big-endian or little-endian.
49#endif
50
[695b6ff]51const addr32_t addr32_broadcast_all_hosts = 0xffffffff;
52
[02a09ed]53const addr48_t addr48_broadcast = {
54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
55};
56
[83781a22]57static const addr48_t inet_addr48_solicited_node = {
58 0x33, 0x33, 0xff, 0, 0, 0
59};
60
[02a09ed]61static const inet_addr_t inet_addr_any_addr = {
[f023251]62 .version = ip_v4,
[02a09ed]63 .addr = 0
[a2e3ee6]64};
65
[02a09ed]66static const inet_addr_t inet_addr_any_addr6 = {
[f023251]67 .version = ip_v6,
[02a09ed]68 .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
[a2e3ee6]69};
70
[02a09ed]71void addr48(const addr48_t src, addr48_t dst)
72{
73 memcpy(dst, src, 6);
74}
75
76void addr128(const addr128_t src, addr128_t dst)
77{
78 memcpy(dst, src, 16);
79}
80
[e2839d7]81/** Compare addr48.
82 *
83 * @return Non-zero if equal, zero if not equal.
84 */
[83781a22]85int addr48_compare(const addr48_t a, const addr48_t b)
86{
[e2839d7]87 return memcmp(a, b, 6) == 0;
[83781a22]88}
89
[e2839d7]90/** Compare addr128.
91 *
92 * @return Non-zero if equal, zero if not equal.
93 */
[671b546]94int addr128_compare(const addr128_t a, const addr128_t b)
95{
[e2839d7]96 return memcmp(a, b, 16) == 0;
[671b546]97}
98
[83781a22]99/** Compute solicited node MAC multicast address from target IPv6 address
100 *
101 * @param ip Target IPv6 address
102 * @param mac Solicited MAC address to be assigned
103 *
104 */
105void addr48_solicited_node(const addr128_t ip, addr48_t mac)
106{
107 memcpy(mac, inet_addr48_solicited_node, 3);
108 memcpy(mac + 3, ip + 13, 3);
109}
110
[02a09ed]111void host2addr128_t_be(const addr128_t host, addr128_t be)
112{
113 memcpy(be, host, 16);
114}
115
116void addr128_t_be2host(const addr128_t be, addr128_t host)
117{
118 memcpy(host, be, 16);
119}
120
121void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
122{
[f023251]123 addr->version = ip_v4;
[02a09ed]124 addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
125 ((addr32_t) c << 8) | ((addr32_t) d);
126}
127
128void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
129 uint8_t prefix)
130{
[f023251]131 naddr->version = ip_v4;
[02a09ed]132 naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
133 ((addr32_t) c << 8) | ((addr32_t) d);
134 naddr->prefix = prefix;
135}
136
137void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
138 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
139{
[f023251]140 addr->version = ip_v6;
[02a09ed]141 addr->addr6[0] = (a >> 8) & 0xff;
142 addr->addr6[1] = a & 0xff;
143 addr->addr6[2] = (b >> 8) & 0xff;
144 addr->addr6[3] = b & 0xff;
145 addr->addr6[4] = (c >> 8) & 0xff;
146 addr->addr6[5] = c & 0xff;
147 addr->addr6[6] = (d >> 8) & 0xff;
148 addr->addr6[7] = d & 0xff;
149 addr->addr6[8] = (e >> 8) & 0xff;
150 addr->addr6[9] = e & 0xff;
151 addr->addr6[10] = (f >> 8) & 0xff;
152 addr->addr6[11] = f & 0xff;
153 addr->addr6[12] = (g >> 8) & 0xff;
154 addr->addr6[13] = g & 0xff;
155 addr->addr6[14] = (h >> 8) & 0xff;
156 addr->addr6[15] = h & 0xff;
157}
158
159void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
160 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
161{
[f023251]162 naddr->version = ip_v6;
[02a09ed]163 naddr->addr6[0] = (a >> 8) & 0xff;
164 naddr->addr6[1] = a & 0xff;
165 naddr->addr6[2] = (b >> 8) & 0xff;
166 naddr->addr6[3] = b & 0xff;
167 naddr->addr6[4] = (c >> 8) & 0xff;
168 naddr->addr6[5] = c & 0xff;
169 naddr->addr6[6] = (d >> 8) & 0xff;
170 naddr->addr6[7] = d & 0xff;
171 naddr->addr6[8] = (e >> 8) & 0xff;
172 naddr->addr6[9] = e & 0xff;
173 naddr->addr6[10] = (f >> 8) & 0xff;
174 naddr->addr6[11] = f & 0xff;
175 naddr->addr6[12] = (g >> 8) & 0xff;
176 naddr->addr6[13] = g & 0xff;
177 naddr->addr6[14] = (h >> 8) & 0xff;
178 naddr->addr6[15] = h & 0xff;
179 naddr->prefix = prefix;
180}
181
[f023251]182/** Determine address version.
[3495654]183 *
[f023251]184 * @param text Address in common notation.
185 * @param af Place to store address version.
[a2e3ee6]186 *
187 * @return EOK on success, EINVAL if input is not in valid format.
[3495654]188 *
189 */
[f023251]190static int inet_addr_version(const char *text, ip_ver_t *ver)
[3495654]191{
[a2e3ee6]192 char *dot = str_chr(text, '.');
193 if (dot != NULL) {
[f023251]194 *ver = ip_v4;
[a2e3ee6]195 return EOK;
[3495654]196 }
[f023251]197
[a2e3ee6]198 char *collon = str_chr(text, ':');
199 if (collon != NULL) {
[f023251]200 *ver = ip_v6;
[a2e3ee6]201 return EOK;
[3495654]202 }
[f023251]203
[a2e3ee6]204 return EINVAL;
[3495654]205}
206
[f023251]207static int ipver_af(ip_ver_t ver)
208{
209 switch (ver) {
210 case ip_any:
211 return AF_NONE;
212 case ip_v4:
213 return AF_INET;
214 case ip_v6:
215 return AF_INET6;
216 default:
217 assert(false);
218 return EINVAL;
[e948fde]219 }
220}
221
222ip_ver_t ipver_from_af(int af)
223{
224 switch (af) {
225 case AF_NONE:
226 return ip_any;
227 case AF_INET:
228 return ip_v4;
229 case AF_INET6:
230 return ip_v6;
231 default:
232 assert(false);
233 return EINVAL;
[f023251]234 }
235}
236
[02a09ed]237void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
238{
[f023251]239 addr->version = naddr->version;
[02a09ed]240 memcpy(addr->addr6, naddr->addr6, 16);
241}
242
[bb9b0c6]243void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix,
244 inet_naddr_t *naddr)
245{
[f023251]246 naddr->version = addr->version;
[bb9b0c6]247 memcpy(naddr->addr6, addr->addr6, 16);
248 naddr->prefix = prefix;
249}
250
[02a09ed]251void inet_addr_any(inet_addr_t *addr)
252{
[f023251]253 addr->version = ip_any;
[02a09ed]254 memset(addr->addr6, 0, 16);
255}
256
257void inet_naddr_any(inet_naddr_t *naddr)
258{
[f023251]259 naddr->version = ip_any;
[02a09ed]260 memset(naddr->addr6, 0, 16);
261 naddr->prefix = 0;
262}
263
264int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
265{
[f023251]266 if (a->version != b->version)
[02a09ed]267 return 0;
[f023251]268
269 switch (a->version) {
270 case ip_v4:
[02a09ed]271 return (a->addr == b->addr);
[f023251]272 case ip_v6:
[671b546]273 return addr128_compare(a->addr6, b->addr6);
[02a09ed]274 default:
275 return 0;
276 }
277}
278
279int inet_addr_is_any(const inet_addr_t *addr)
280{
[f023251]281 return ((addr->version == ip_any) ||
[02a09ed]282 (inet_addr_compare(addr, &inet_addr_any_addr)) ||
283 (inet_addr_compare(addr, &inet_addr_any_addr6)));
284}
285
[30c5d13]286int inet_naddr_compare(const inet_naddr_t *naddr, const inet_addr_t *addr)
287{
[f023251]288 if (naddr->version != addr->version)
[30c5d13]289 return 0;
290
[f023251]291 switch (naddr->version) {
292 case ip_v4:
[30c5d13]293 return (naddr->addr == addr->addr);
[f023251]294 case ip_v6:
[30c5d13]295 return addr128_compare(naddr->addr6, addr->addr6);
296 default:
297 return 0;
298 }
299}
300
[02a09ed]301int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
302{
[f023251]303 if (naddr->version != addr->version)
[02a09ed]304 return 0;
[f023251]305
306 switch (naddr->version) {
307 case ip_v4:
[02a09ed]308 if (naddr->prefix > 32)
309 return 0;
[f023251]310
[02a09ed]311 addr32_t mask =
312 BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
313 return ((naddr->addr & mask) == (addr->addr & mask));
[f023251]314 case ip_v6:
[02a09ed]315 if (naddr->prefix > 128)
316 return 0;
317
318 size_t pos = 0;
319 for (size_t i = 0; i < 16; i++) {
320 /* Further bits do not matter */
321 if (naddr->prefix < pos)
322 break;
323
324 if (naddr->prefix - pos > 8) {
325 /* Comparison without masking */
326 if (naddr->addr6[i] != addr->addr6[i])
327 return 0;
328 } else {
329 /* Comparison with masking */
330 uint8_t mask =
331 BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
332 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
333 return 0;
334 }
335
336 pos += 8;
337 }
338
339 return 1;
340 default:
341 return 0;
342 }
343}
344
[3495654]345/** Parse node address.
346 *
[a2e3ee6]347 * @param text Network address in common notation.
348 * @param addr Place to store node address.
349 *
350 * @return EOK on success, EINVAL if input is not in valid format.
[3495654]351 *
352 */
353int inet_addr_parse(const char *text, inet_addr_t *addr)
354{
[f023251]355 int rc = inet_addr_version(text, &addr->version);
[a2e3ee6]356 if (rc != EOK)
357 return rc;
358
[02a09ed]359 uint8_t buf[16];
[f023251]360 rc = inet_pton(ipver_af(addr->version), text, buf);
[a2e3ee6]361 if (rc != EOK)
362 return rc;
363
[f023251]364 switch (addr->version) {
365 case ip_v4:
[02a09ed]366 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
367 buf[3];
368 break;
[f023251]369 case ip_v6:
[02a09ed]370 memcpy(addr->addr6, buf, 16);
371 break;
372 default:
373 return EINVAL;
374 }
375
[a2e3ee6]376 return EOK;
377}
[3495654]378
[a2e3ee6]379/** Parse network address.
380 *
381 * @param text Network address in common notation.
382 * @param naddr Place to store network address.
383 *
384 * @return EOK on success, EINVAL if input is not in valid format.
385 *
386 */
387int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
388{
389 char *slash = str_chr(text, '/');
390 if (slash == NULL)
[3495654]391 return EINVAL;
[a2e3ee6]392
393 *slash = 0;
394
[f023251]395 int rc = inet_addr_version(text, &naddr->version);
[a2e3ee6]396 if (rc != EOK)
397 return rc;
398
[02a09ed]399 uint8_t buf[16];
[f023251]400 rc = inet_pton(ipver_af(naddr->version), text, buf);
[a2e3ee6]401 *slash = '/';
402
403 if (rc != EOK)
404 return rc;
405
406 slash++;
[02a09ed]407 uint8_t prefix;
[a2e3ee6]408
[f023251]409 switch (naddr->version) {
410 case ip_v4:
[02a09ed]411 prefix = strtoul(slash, &slash, 10);
412 if (prefix > 32)
[a2e3ee6]413 return EINVAL;
[02a09ed]414
415 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
416 buf[3];
417 naddr->prefix = prefix;
418
[a2e3ee6]419 break;
[f023251]420 case ip_v6:
[02a09ed]421 prefix = strtoul(slash, &slash, 10);
422 if (prefix > 128)
[3495654]423 return EINVAL;
[02a09ed]424
425 memcpy(naddr->addr6, buf, 16);
426 naddr->prefix = prefix;
427
[a2e3ee6]428 break;
429 default:
430 return ENOTSUP;
[3495654]431 }
[a2e3ee6]432
433 return EOK;
434}
[3495654]435
[a2e3ee6]436/** Format node address.
437 *
438 * @param addr Node address.
439 * @param bufp Place to store pointer to formatted string.
440 *
441 * @return EOK on success.
442 * @return ENOMEM if out of memory.
443 * @return ENOTSUP on unsupported address family.
444 *
445 */
[02a09ed]446int inet_addr_format(const inet_addr_t *addr, char **bufp)
[a2e3ee6]447{
[02a09ed]448 int rc = 0;
[a2e3ee6]449
[f023251]450 switch (addr->version) {
451 case ip_any:
[a2e3ee6]452 rc = asprintf(bufp, "none");
453 break;
[f023251]454 case ip_v4:
[02a09ed]455 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
456 (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
457 addr->addr & 0xff);
[a2e3ee6]458 break;
[f023251]459 case ip_v6:
[02a09ed]460 *bufp = (char *) malloc(INET6_ADDRSTRLEN);
461 if (*bufp == NULL)
462 return ENOMEM;
463
464 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
[a2e3ee6]465 default:
466 return ENOTSUP;
467 }
468
469 if (rc < 0)
470 return ENOMEM;
471
[3495654]472 return EOK;
473}
474
475/** Format network address.
476 *
[a2e3ee6]477 * @param naddr Network address.
478 * @param bufp Place to store pointer to formatted string.
479 *
480 * @return EOK on success.
481 * @return ENOMEM if out of memory.
482 * @return ENOTSUP on unsupported address family.
[3495654]483 *
484 */
[02a09ed]485int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
[3495654]486{
[02a09ed]487 int rc = 0;
488 char prefix[INET_PREFIXSTRSIZE];
[a2e3ee6]489
[f023251]490 switch (naddr->version) {
491 case ip_any:
[a2e3ee6]492 rc = asprintf(bufp, "none");
493 break;
[f023251]494 case ip_v4:
[02a09ed]495 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
496 "/%" PRIu8, (naddr->addr >> 24) & 0xff,
497 (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
498 naddr->addr & 0xff, naddr->prefix);
[a2e3ee6]499 break;
[f023251]500 case ip_v6:
[02a09ed]501 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
502 if (*bufp == NULL)
503 return ENOMEM;
504
505 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
506 INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
507 if (rc != EOK) {
508 free(*bufp);
509 return rc;
510 }
511
512 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
513 naddr->prefix);
514 if (rc < 0) {
515 free(*bufp);
516 return ENOMEM;
517 }
518
519 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
520
521 break;
[a2e3ee6]522 default:
523 return ENOTSUP;
524 }
525
[3495654]526 if (rc < 0)
527 return ENOMEM;
[a2e3ee6]528
529 return EOK;
530}
[3495654]531
[f023251]532ip_ver_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
[a2e3ee6]533{
[f023251]534 switch (addr->version) {
535 case ip_v4:
[02a09ed]536 if (v4 != NULL)
537 *v4 = addr->addr;
538 break;
[f023251]539 case ip_v6:
[02a09ed]540 if (v6 != NULL)
541 memcpy(*v6, addr->addr6, 16);
[f023251]542 break;
543 default:
544 assert(false);
[02a09ed]545 break;
546 }
[f023251]547
548 return addr->version;
[3495654]549}
550
[f023251]551ip_ver_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
[02a09ed]552 uint8_t *prefix)
[3495654]553{
[f023251]554 switch (naddr->version) {
555 case ip_v4:
[02a09ed]556 if (v4 != NULL)
557 *v4 = naddr->addr;
558 if (prefix != NULL)
559 *prefix = naddr->prefix;
560 break;
[f023251]561 case ip_v6:
[02a09ed]562 if (v6 != NULL)
563 memcpy(*v6, naddr->addr6, 16);
564 if (prefix != NULL)
565 *prefix = naddr->prefix;
[f023251]566 break;
567 default:
568 assert(false);
[02a09ed]569 break;
570 }
[f023251]571
572 return naddr->version;
[a2e3ee6]573}
[3495654]574
[02a09ed]575void inet_addr_set(addr32_t v4, inet_addr_t *addr)
[a2e3ee6]576{
[f023251]577 addr->version = ip_v4;
[02a09ed]578 addr->addr = v4;
[a2e3ee6]579}
[3495654]580
[02a09ed]581void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
[a2e3ee6]582{
[f023251]583 naddr->version = ip_v4;
[02a09ed]584 naddr->addr = v4;
[a2e3ee6]585 naddr->prefix = prefix;
586}
[3495654]587
[02a09ed]588void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
[a2e3ee6]589{
[f023251]590 addr->version = ip_v4;
[02a09ed]591 addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
[a2e3ee6]592}
593
[02a09ed]594void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
[a2e3ee6]595{
[f023251]596 addr->version = ip_v6;
[02a09ed]597 memcpy(addr->addr6, v6, 16);
[a2e3ee6]598}
599
[02a09ed]600void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
[a2e3ee6]601{
[f023251]602 naddr->version = ip_v6;
[02a09ed]603 memcpy(naddr->addr6, v6, 16);
604 naddr->prefix = prefix;
[a2e3ee6]605}
606
[02a09ed]607void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
608 inet_addr_t *addr)
[a2e3ee6]609{
[f023251]610 addr->version = ip_v6;
[02a09ed]611 addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
[a2e3ee6]612}
613
[02a09ed]614uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
615 sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
[a2e3ee6]616{
[f023251]617 switch (addr->version) {
618 case ip_v4:
[02a09ed]619 if (sockaddr_in != NULL) {
620 sockaddr_in->sin_family = AF_INET;
621 sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
622 }
623 break;
[f023251]624 case ip_v6:
[02a09ed]625 if (sockaddr_in6 != NULL) {
626 sockaddr_in6->sin6_family = AF_INET6;
627 host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
628 }
[f023251]629 break;
630 default:
631 assert(false);
[02a09ed]632 break;
[a2e3ee6]633 }
[f023251]634
635 return ipver_af(addr->version);
[a2e3ee6]636}
637
[26de91a]638int inet_addr_sockaddr(const inet_addr_t *addr, uint16_t port,
639 sockaddr_t **nsockaddr, socklen_t *naddrlen)
640{
641 sockaddr_in_t *sa4;
642 sockaddr_in6_t *sa6;
643
644 switch (addr->version) {
645 case ip_v4:
646 sa4 = calloc(1, sizeof(sockaddr_in_t));
647 if (sa4 == NULL)
648 return ENOMEM;
649
650 sa4->sin_family = AF_INET;
651 sa4->sin_port = host2uint16_t_be(port);
652 sa4->sin_addr.s_addr = host2uint32_t_be(addr->addr);
653 if (nsockaddr != NULL)
654 *nsockaddr = (sockaddr_t *)sa4;
655 if (naddrlen != NULL)
656 *naddrlen = sizeof(*sa4);
657 break;
658 case ip_v6:
659 sa6 = calloc(1, sizeof(sockaddr_in6_t));
660 if (sa6 == NULL)
661 return ENOMEM;
662
663 sa6->sin6_family = AF_INET6;
664 sa6->sin6_port = host2uint16_t_be(port);
665 host2addr128_t_be(addr->addr6, sa6->sin6_addr.s6_addr);
666 if (nsockaddr != NULL)
667 *nsockaddr = (sockaddr_t *)sa6;
668 if (naddrlen != NULL)
669 *naddrlen = sizeof(*sa6);
670 break;
671 default:
672 assert(false);
673 break;
674 }
675
676 return EOK;
677}
678
[3495654]679/** @}
680 */
Note: See TracBrowser for help on using the repository browser.