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

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

Fix header guards and doxy groups of stuff moved out of libc

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