source: mainline/uspace/lib/c/generic/inet/addr.c@ 5e801dc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5e801dc was ae7d03c, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Selected ccheck-proposed comment fixes.

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