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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d5c1051 was d5c1051, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

"Obviously harmless" error handling tweaks.

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