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

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

Need better interfaces for handling internet host and host:port specifications.

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