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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 30c5d13 was 30c5d13, checked in by Martin Decky <martin@…>, 12 years ago

restore accidentally removed iaf_addr lookup functionality

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file Internet address parsing and formatting.
33 */
34
35#include <errno.h>
36#include <unistd.h>
37#include <net/socket_codes.h>
38#include <inet/addr.h>
39#include <net/inet.h>
40#include <stdio.h>
41#include <malloc.h>
42#include <bitops.h>
43
44#define INET_PREFIXSTRSIZE 5
45
46#if !(defined(__BE__) ^ defined(__LE__))
47 #error The architecture must be either big-endian or little-endian.
48#endif
49
50const addr48_t addr48_broadcast = {
51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
52};
53
54static const inet_addr_t inet_addr_any_addr = {
55 .family = AF_INET,
56 .addr = 0
57};
58
59static const inet_addr_t inet_addr_any_addr6 = {
60 .family = AF_INET6,
61 .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
62};
63
64void addr48(const addr48_t src, addr48_t dst)
65{
66 memcpy(dst, src, 6);
67}
68
69void addr128(const addr128_t src, addr128_t dst)
70{
71 memcpy(dst, src, 16);
72}
73
74int addr128_compare(const addr128_t a, const addr128_t b)
75{
76 return memcmp(a, b, 16);
77}
78
79void host2addr128_t_be(const addr128_t host, addr128_t be)
80{
81#ifdef __BE__
82 memcpy(be, host, 16);
83#else
84 be[0] = host[15];
85 be[1] = host[14];
86 be[2] = host[13];
87 be[3] = host[12];
88 be[4] = host[11];
89 be[5] = host[10];
90 be[6] = host[9];
91 be[7] = host[8];
92 be[8] = host[7];
93 be[9] = host[6];
94 be[10] = host[5];
95 be[11] = host[4];
96 be[12] = host[3];
97 be[13] = host[2];
98 be[14] = host[1];
99 be[15] = host[0];
100#endif
101}
102
103void addr128_t_be2host(const addr128_t be, addr128_t host)
104{
105#ifdef __BE__
106 memcpy(host, be, 16);
107#else
108 host[0] = be[15];
109 host[1] = be[14];
110 host[2] = be[13];
111 host[3] = be[12];
112 host[4] = be[11];
113 host[5] = be[10];
114 host[6] = be[9];
115 host[7] = be[8];
116 host[8] = be[7];
117 host[9] = be[6];
118 host[10] = be[5];
119 host[11] = be[4];
120 host[12] = be[3];
121 host[13] = be[2];
122 host[14] = be[1];
123 host[15] = be[0];
124#endif
125}
126
127void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
128{
129 addr->family = AF_INET;
130 addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
131 ((addr32_t) c << 8) | ((addr32_t) d);
132}
133
134void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
135 uint8_t prefix)
136{
137 naddr->family = AF_INET;
138 naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
139 ((addr32_t) c << 8) | ((addr32_t) d);
140 naddr->prefix = prefix;
141}
142
143void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
144 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
145{
146 addr->family = AF_INET6;
147 addr->addr6[0] = (a >> 8) & 0xff;
148 addr->addr6[1] = a & 0xff;
149 addr->addr6[2] = (b >> 8) & 0xff;
150 addr->addr6[3] = b & 0xff;
151 addr->addr6[4] = (c >> 8) & 0xff;
152 addr->addr6[5] = c & 0xff;
153 addr->addr6[6] = (d >> 8) & 0xff;
154 addr->addr6[7] = d & 0xff;
155 addr->addr6[8] = (e >> 8) & 0xff;
156 addr->addr6[9] = e & 0xff;
157 addr->addr6[10] = (f >> 8) & 0xff;
158 addr->addr6[11] = f & 0xff;
159 addr->addr6[12] = (g >> 8) & 0xff;
160 addr->addr6[13] = g & 0xff;
161 addr->addr6[14] = (h >> 8) & 0xff;
162 addr->addr6[15] = h & 0xff;
163}
164
165void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
166 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
167{
168 naddr->family = AF_INET6;
169 naddr->addr6[0] = (a >> 8) & 0xff;
170 naddr->addr6[1] = a & 0xff;
171 naddr->addr6[2] = (b >> 8) & 0xff;
172 naddr->addr6[3] = b & 0xff;
173 naddr->addr6[4] = (c >> 8) & 0xff;
174 naddr->addr6[5] = c & 0xff;
175 naddr->addr6[6] = (d >> 8) & 0xff;
176 naddr->addr6[7] = d & 0xff;
177 naddr->addr6[8] = (e >> 8) & 0xff;
178 naddr->addr6[9] = e & 0xff;
179 naddr->addr6[10] = (f >> 8) & 0xff;
180 naddr->addr6[11] = f & 0xff;
181 naddr->addr6[12] = (g >> 8) & 0xff;
182 naddr->addr6[13] = g & 0xff;
183 naddr->addr6[14] = (h >> 8) & 0xff;
184 naddr->addr6[15] = h & 0xff;
185 naddr->prefix = prefix;
186}
187
188/** Parse network address family.
189 *
190 * @param text Network address in common notation.
191 * @param af Place to store network address family.
192 *
193 * @return EOK on success, EINVAL if input is not in valid format.
194 *
195 */
196int inet_addr_family(const char *text, uint16_t *af)
197{
198 char *dot = str_chr(text, '.');
199 if (dot != NULL) {
200 *af = AF_INET;
201 return EOK;
202 }
203
204 char *collon = str_chr(text, ':');
205 if (collon != NULL) {
206 *af = AF_INET6;
207 return EOK;
208 }
209
210 return EINVAL;
211}
212
213void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
214{
215 addr->family = naddr->family;
216 memcpy(addr->addr6, naddr->addr6, 16);
217}
218
219void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix,
220 inet_naddr_t *naddr)
221{
222 naddr->family = addr->family;
223 memcpy(naddr->addr6, addr->addr6, 16);
224 naddr->prefix = prefix;
225}
226
227void inet_addr_any(inet_addr_t *addr)
228{
229 addr->family = AF_NONE;
230 memset(addr->addr6, 0, 16);
231}
232
233void inet_naddr_any(inet_naddr_t *naddr)
234{
235 naddr->family = AF_NONE;
236 memset(naddr->addr6, 0, 16);
237 naddr->prefix = 0;
238}
239
240int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
241{
242 if (a->family != b->family)
243 return 0;
244
245 switch (a->family) {
246 case AF_INET:
247 return (a->addr == b->addr);
248 case AF_INET6:
249 return addr128_compare(a->addr6, b->addr6);
250 default:
251 return 0;
252 }
253}
254
255int inet_addr_is_any(const inet_addr_t *addr)
256{
257 return ((addr->family == 0) ||
258 (inet_addr_compare(addr, &inet_addr_any_addr)) ||
259 (inet_addr_compare(addr, &inet_addr_any_addr6)));
260}
261
262int inet_naddr_compare(const inet_naddr_t *naddr, const inet_addr_t *addr)
263{
264 if (naddr->family != addr->family)
265 return 0;
266
267 switch (naddr->family) {
268 case AF_INET:
269 return (naddr->addr == addr->addr);
270 case AF_INET6:
271 return addr128_compare(naddr->addr6, addr->addr6);
272 default:
273 return 0;
274 }
275}
276
277int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
278{
279 if (naddr->family != addr->family)
280 return 0;
281
282 switch (naddr->family) {
283 case AF_INET:
284 if (naddr->prefix > 32)
285 return 0;
286
287 addr32_t mask =
288 BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
289 return ((naddr->addr & mask) == (addr->addr & mask));
290 case AF_INET6:
291 if (naddr->prefix > 128)
292 return 0;
293
294 size_t pos = 0;
295 for (size_t i = 0; i < 16; i++) {
296 /* Further bits do not matter */
297 if (naddr->prefix < pos)
298 break;
299
300 if (naddr->prefix - pos > 8) {
301 /* Comparison without masking */
302 if (naddr->addr6[i] != addr->addr6[i])
303 return 0;
304 } else {
305 /* Comparison with masking */
306 uint8_t mask =
307 BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
308 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
309 return 0;
310 }
311
312 pos += 8;
313 }
314
315 return 1;
316 default:
317 return 0;
318 }
319}
320
321/** Parse node address.
322 *
323 * @param text Network address in common notation.
324 * @param addr Place to store node address.
325 *
326 * @return EOK on success, EINVAL if input is not in valid format.
327 *
328 */
329int inet_addr_parse(const char *text, inet_addr_t *addr)
330{
331 int rc = inet_addr_family(text, &addr->family);
332 if (rc != EOK)
333 return rc;
334
335 uint8_t buf[16];
336 rc = inet_pton(addr->family, text, buf);
337 if (rc != EOK)
338 return rc;
339
340 switch (addr->family) {
341 case AF_INET:
342 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
343 buf[3];
344 break;
345 case AF_INET6:
346 memcpy(addr->addr6, buf, 16);
347 break;
348 default:
349 return EINVAL;
350 }
351
352 return EOK;
353}
354
355/** Parse network address.
356 *
357 * @param text Network address in common notation.
358 * @param naddr Place to store network address.
359 *
360 * @return EOK on success, EINVAL if input is not in valid format.
361 *
362 */
363int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
364{
365 char *slash = str_chr(text, '/');
366 if (slash == NULL)
367 return EINVAL;
368
369 *slash = 0;
370
371 int rc = inet_addr_family(text, &naddr->family);
372 if (rc != EOK)
373 return rc;
374
375 uint8_t buf[16];
376 rc = inet_pton(naddr->family, text, buf);
377 *slash = '/';
378
379 if (rc != EOK)
380 return rc;
381
382 slash++;
383 uint8_t prefix;
384
385 switch (naddr->family) {
386 case AF_INET:
387 prefix = strtoul(slash, &slash, 10);
388 if (prefix > 32)
389 return EINVAL;
390
391 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
392 buf[3];
393 naddr->prefix = prefix;
394
395 break;
396 case AF_INET6:
397 prefix = strtoul(slash, &slash, 10);
398 if (prefix > 128)
399 return EINVAL;
400
401 memcpy(naddr->addr6, buf, 16);
402 naddr->prefix = prefix;
403
404 break;
405 default:
406 return ENOTSUP;
407 }
408
409 return EOK;
410}
411
412/** Format node address.
413 *
414 * @param addr Node address.
415 * @param bufp Place to store pointer to formatted string.
416 *
417 * @return EOK on success.
418 * @return ENOMEM if out of memory.
419 * @return ENOTSUP on unsupported address family.
420 *
421 */
422int inet_addr_format(const inet_addr_t *addr, char **bufp)
423{
424 int rc = 0;
425
426 switch (addr->family) {
427 case AF_NONE:
428 rc = asprintf(bufp, "none");
429 break;
430 case AF_INET:
431 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
432 (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
433 addr->addr & 0xff);
434 break;
435 case AF_INET6:
436 *bufp = (char *) malloc(INET6_ADDRSTRLEN);
437 if (*bufp == NULL)
438 return ENOMEM;
439
440 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
441 default:
442 return ENOTSUP;
443 }
444
445 if (rc < 0)
446 return ENOMEM;
447
448 return EOK;
449}
450
451/** Format network address.
452 *
453 * @param naddr Network address.
454 * @param bufp Place to store pointer to formatted string.
455 *
456 * @return EOK on success.
457 * @return ENOMEM if out of memory.
458 * @return ENOTSUP on unsupported address family.
459 *
460 */
461int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
462{
463 int rc = 0;
464 char prefix[INET_PREFIXSTRSIZE];
465
466 switch (naddr->family) {
467 case AF_NONE:
468 rc = asprintf(bufp, "none");
469 break;
470 case AF_INET:
471 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
472 "/%" PRIu8, (naddr->addr >> 24) & 0xff,
473 (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
474 naddr->addr & 0xff, naddr->prefix);
475 break;
476 case AF_INET6:
477 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
478 if (*bufp == NULL)
479 return ENOMEM;
480
481 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
482 INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
483 if (rc != EOK) {
484 free(*bufp);
485 return rc;
486 }
487
488 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
489 naddr->prefix);
490 if (rc < 0) {
491 free(*bufp);
492 return ENOMEM;
493 }
494
495 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
496
497 break;
498 default:
499 return ENOTSUP;
500 }
501
502 if (rc < 0)
503 return ENOMEM;
504
505 return EOK;
506}
507
508uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
509{
510 switch (addr->family) {
511 case AF_INET:
512 if (v4 != NULL)
513 *v4 = addr->addr;
514
515 break;
516 case AF_INET6:
517 if (v6 != NULL)
518 memcpy(*v6, addr->addr6, 16);
519
520 break;
521 }
522
523 return addr->family;
524}
525
526uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
527 uint8_t *prefix)
528{
529 switch (naddr->family) {
530 case AF_INET:
531 if (v4 != NULL)
532 *v4 = naddr->addr;
533
534 if (prefix != NULL)
535 *prefix = naddr->prefix;
536
537 break;
538 case AF_INET6:
539 if (v6 != NULL)
540 memcpy(*v6, naddr->addr6, 16);
541
542 if (prefix != NULL)
543 *prefix = naddr->prefix;
544
545 break;
546 }
547
548 return naddr->family;
549}
550
551void inet_addr_set(addr32_t v4, inet_addr_t *addr)
552{
553 addr->family = AF_INET;
554 addr->addr = v4;
555}
556
557void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
558{
559 naddr->family = AF_INET;
560 naddr->addr = v4;
561 naddr->prefix = prefix;
562}
563
564void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
565{
566 addr->family = AF_INET;
567 addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
568}
569
570void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
571{
572 addr->family = AF_INET6;
573 memcpy(addr->addr6, v6, 16);
574}
575
576void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
577{
578 naddr->family = AF_INET6;
579 memcpy(naddr->addr6, v6, 16);
580 naddr->prefix = prefix;
581}
582
583void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
584 inet_addr_t *addr)
585{
586 addr->family = AF_INET6;
587 addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
588}
589
590uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
591 sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
592{
593 switch (addr->family) {
594 case AF_INET:
595 if (sockaddr_in != NULL) {
596 sockaddr_in->sin_family = AF_INET;
597 sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
598 }
599
600 break;
601 case AF_INET6:
602 if (sockaddr_in6 != NULL) {
603 sockaddr_in6->sin6_family = AF_INET6;
604 host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
605 }
606
607 break;
608 }
609
610 return addr->family;
611}
612
613/** @}
614 */
Note: See TracBrowser for help on using the repository browser.