source: mainline/uspace/lib/inet/src/addr.c@ d5ed54b

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

Use assignment operator to copy Ethernet addresses

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