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