]>
Commit | Line | Data |
---|---|---|
6054c1eb | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
aba5acdf | 2 | #include <errno.h> |
9ec0e899 | 3 | #include <string.h> |
aba5acdf SH |
4 | #include <sys/types.h> |
5 | #include <netinet/in.h> | |
6 | ||
7 | #include "utils.h" | |
8 | ||
9 | static __inline__ u_int16_t dn_ntohs(u_int16_t addr) | |
10 | { | |
11 | union { | |
12 | u_int8_t byte[2]; | |
13 | u_int16_t word; | |
14 | } u; | |
15 | ||
16 | u.word = addr; | |
17 | return ((u_int16_t)u.byte[0]) | (((u_int16_t)u.byte[1]) << 8); | |
18 | } | |
19 | ||
20 | static __inline__ int do_digit(char *str, u_int16_t *addr, u_int16_t scale, size_t *pos, size_t len, int *started) | |
21 | { | |
22 | u_int16_t tmp = *addr / scale; | |
23 | ||
24 | if (*pos == len) | |
25 | return 1; | |
26 | ||
27 | if (((tmp) > 0) || *started || (scale == 1)) { | |
28 | *str = tmp + '0'; | |
29 | *started = 1; | |
30 | (*pos)++; | |
31 | *addr -= (tmp * scale); | |
32 | } | |
33 | ||
34 | return 0; | |
35 | } | |
36 | ||
37 | ||
38 | static const char *dnet_ntop1(const struct dn_naddr *dna, char *str, size_t len) | |
39 | { | |
9ec0e899 | 40 | u_int16_t addr, area; |
aba5acdf SH |
41 | size_t pos = 0; |
42 | int started = 0; | |
43 | ||
9ec0e899 MF |
44 | memcpy(&addr, dna->a_addr, sizeof(addr)); |
45 | addr = dn_ntohs(addr); | |
46 | area = addr >> 10; | |
47 | ||
aba5acdf SH |
48 | if (dna->a_len != 2) |
49 | return NULL; | |
50 | ||
51 | addr &= 0x03ff; | |
52 | ||
53 | if (len == 0) | |
54 | return str; | |
55 | ||
56 | if (do_digit(str + pos, &area, 10, &pos, len, &started)) | |
57 | return str; | |
58 | ||
59 | if (do_digit(str + pos, &area, 1, &pos, len, &started)) | |
60 | return str; | |
61 | ||
62 | if (pos == len) | |
63 | return str; | |
64 | ||
65 | *(str + pos) = '.'; | |
66 | pos++; | |
67 | started = 0; | |
68 | ||
69 | if (do_digit(str + pos, &addr, 1000, &pos, len, &started)) | |
70 | return str; | |
71 | ||
72 | if (do_digit(str + pos, &addr, 100, &pos, len, &started)) | |
73 | return str; | |
74 | ||
75 | if (do_digit(str + pos, &addr, 10, &pos, len, &started)) | |
76 | return str; | |
77 | ||
78 | if (do_digit(str + pos, &addr, 1, &pos, len, &started)) | |
79 | return str; | |
80 | ||
81 | if (pos == len) | |
82 | return str; | |
83 | ||
84 | *(str + pos) = 0; | |
85 | ||
86 | return str; | |
87 | } | |
88 | ||
89 | ||
90 | const char *dnet_ntop(int af, const void *addr, char *str, size_t len) | |
91 | { | |
92 | switch(af) { | |
93 | case AF_DECnet: | |
94 | errno = 0; | |
95 | return dnet_ntop1((struct dn_naddr *)addr, str, len); | |
96 | default: | |
97 | errno = EAFNOSUPPORT; | |
98 | } | |
99 | ||
100 | return NULL; | |
101 | } |