1570af302Sopenharmony_ci// inet_addr, inet_ntoa, inet_pton and inet_ntop tests with roundtrip check
2570af302Sopenharmony_ci#include <errno.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include <stdio.h>
5570af302Sopenharmony_ci#include <arpa/inet.h>
6570af302Sopenharmony_ci#include "test.h"
7570af302Sopenharmony_ci
8570af302Sopenharmony_cistatic int digit(int c)
9570af302Sopenharmony_ci{
10570af302Sopenharmony_ci	c-='0';
11570af302Sopenharmony_ci	if (c>9) c-='a'-'0'-10;
12570af302Sopenharmony_ci	return c;
13570af302Sopenharmony_ci}
14570af302Sopenharmony_ci
15570af302Sopenharmony_cistatic void tobin(void *d, char *s)
16570af302Sopenharmony_ci{
17570af302Sopenharmony_ci	int i;
18570af302Sopenharmony_ci	unsigned char *p = d;
19570af302Sopenharmony_ci	for (i=0; s[2*i]; i++) p[i] = digit(s[2*i])*16+digit(s[2*i+1]);
20570af302Sopenharmony_ci}
21570af302Sopenharmony_ci
22570af302Sopenharmony_cistatic void tohex(char *d, void *s, int n)
23570af302Sopenharmony_ci{
24570af302Sopenharmony_ci	int i;
25570af302Sopenharmony_ci	unsigned char *p = s;
26570af302Sopenharmony_ci	for (i=0; i<n; i++) sprintf(d+2*i, "%02x", p[i]);
27570af302Sopenharmony_ci}
28570af302Sopenharmony_ci
29570af302Sopenharmony_ci#define V6(src,ret,hex) do{\
30570af302Sopenharmony_ci	int r; \
31570af302Sopenharmony_ci	char binaddr[16]={0}; \
32570af302Sopenharmony_ci	char hexaddr[40]={0}; \
33570af302Sopenharmony_ci	char txtaddr[60]={0}; \
34570af302Sopenharmony_ci	\
35570af302Sopenharmony_ci	r=inet_pton(AF_INET6,src,binaddr); \
36570af302Sopenharmony_ci	if (r!=ret) \
37570af302Sopenharmony_ci		t_error("inet_pton(AF_INET6, "#src", addr) returned %d, want %d\n", r, ret); \
38570af302Sopenharmony_ci	if (ret!=1) break; \
39570af302Sopenharmony_ci	tohex(hexaddr,binaddr,16); \
40570af302Sopenharmony_ci	if (strcmp(hexaddr,hex)) \
41570af302Sopenharmony_ci		t_error("inet_pton(AF_INET6, "#src", addr) got addr %s, want %s\n", hexaddr, hex); \
42570af302Sopenharmony_ci	\
43570af302Sopenharmony_ci	tobin(binaddr,hex); \
44570af302Sopenharmony_ci	if (inet_ntop(AF_INET6,binaddr,txtaddr,sizeof txtaddr)!=txtaddr) \
45570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET6, <"#hex">, buf, size) did not return buf\n"); \
46570af302Sopenharmony_ci	if (inet_pton(AF_INET6,txtaddr,binaddr)!=1) \
47570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET6, <"#hex">, buf, size) got %s, it is rejected by inet_pton\n", txtaddr); \
48570af302Sopenharmony_ci	tohex(hexaddr,binaddr,16); \
49570af302Sopenharmony_ci	if (strcmp(hexaddr,hex)) \
50570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET6, <"#hex">, buf, size) got %s that is %s, want %s\n", txtaddr, hexaddr, hex); \
51570af302Sopenharmony_ci	if (strncmp(hex,"00000000000000000000ffff",24)==0 && !strchr(txtaddr,'.')) \
52570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET6, <"#hex">, buf, size) got %s, should be ipv4 mapped\n", txtaddr); \
53570af302Sopenharmony_ci}while(0);
54570af302Sopenharmony_ci
55570af302Sopenharmony_ci// ret and hex are the results of inet_pton and inet_addr respectively
56570af302Sopenharmony_ci#define V4(src,ret,hex) do{\
57570af302Sopenharmony_ci	int r; \
58570af302Sopenharmony_ci	uint32_t a; \
59570af302Sopenharmony_ci	struct in_addr in; \
60570af302Sopenharmony_ci	char buf[20]={0}; \
61570af302Sopenharmony_ci	char *p; \
62570af302Sopenharmony_ci	\
63570af302Sopenharmony_ci	a=inet_addr(src); \
64570af302Sopenharmony_ci	tohex(buf,&a,4); \
65570af302Sopenharmony_ci	if (strcmp(buf,hex)) \
66570af302Sopenharmony_ci		t_error("inet_addr("#src") returned %s, want %s\n", buf, hex); \
67570af302Sopenharmony_ci	\
68570af302Sopenharmony_ci	r=inet_pton(AF_INET,src,&a); \
69570af302Sopenharmony_ci	if (r!=ret) \
70570af302Sopenharmony_ci		t_error("inet_pton(AF_INET, "#src", addr) returned %d, want %d\n", r, ret); \
71570af302Sopenharmony_ci	\
72570af302Sopenharmony_ci	if (ret!=1) break; \
73570af302Sopenharmony_ci	\
74570af302Sopenharmony_ci	tohex(buf,&a,4); \
75570af302Sopenharmony_ci	if (strcmp(buf,hex)) \
76570af302Sopenharmony_ci		t_error("inet_pton(AF_INET, "#src", addr) got addr %s, want %s\n", buf, hex); \
77570af302Sopenharmony_ci	\
78570af302Sopenharmony_ci	tobin(&a,hex); \
79570af302Sopenharmony_ci	if (inet_ntop(AF_INET,&a,buf,sizeof buf)!=buf) \
80570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET, <"#hex">, buf, size) did not return buf\n"); \
81570af302Sopenharmony_ci	if (strcmp(buf,src)) \
82570af302Sopenharmony_ci		t_error("inet_ntop(AF_INET, <"#hex">, buf, size) got %s, want %s\n", buf, src); \
83570af302Sopenharmony_ci	\
84570af302Sopenharmony_ci	in.s_addr = a; \
85570af302Sopenharmony_ci	p=inet_ntoa(in); \
86570af302Sopenharmony_ci	if (strcmp(p,src)) \
87570af302Sopenharmony_ci		t_error("inet_ntoa(<"#hex">) returned %s, want %s\n", p, src); \
88570af302Sopenharmony_ci}while(0);
89570af302Sopenharmony_ci
90570af302Sopenharmony_ciint main(void)
91570af302Sopenharmony_ci{
92570af302Sopenharmony_ci
93570af302Sopenharmony_ci// errors
94570af302Sopenharmony_ciif (inet_pton(12345, "", 0) != -1 || errno != EAFNOSUPPORT)
95570af302Sopenharmony_ci	t_error("inet_pton(12345,,) should fail with EAFNOSUPPORT, got %s\n", strerror(errno));
96570af302Sopenharmony_cierrno=0;
97570af302Sopenharmony_ciif (inet_ntop(AF_INET,"xxxx","",0) != 0 || errno != ENOSPC)
98570af302Sopenharmony_ci	t_error("inet_ntop(,,0,0) should fail with ENOSPC, got %s\n", strerror(errno));
99570af302Sopenharmony_cierrno=0;
100570af302Sopenharmony_ci
101570af302Sopenharmony_ci// dotted-decimal notation
102570af302Sopenharmony_ciV4("0.0.0.0", 1, "00000000")
103570af302Sopenharmony_ciV4("127.0.0.1", 1, "7f000001")
104570af302Sopenharmony_ciV4("10.0.128.31", 1, "0a00801f")
105570af302Sopenharmony_ciV4("255.255.255.255", 1, "ffffffff")
106570af302Sopenharmony_ci
107570af302Sopenharmony_ci// numbers-and-dots notation, but not dotted-decimal
108570af302Sopenharmony_ciV4("1.2.03.4", 0, "01020304")
109570af302Sopenharmony_ciV4("1.2.0x33.4", 0, "01023304")
110570af302Sopenharmony_ciV4("1.2.0XAB.4", 0, "0102ab04")
111570af302Sopenharmony_ciV4("1.2.0xabcd", 0, "0102abcd")
112570af302Sopenharmony_ciV4("1.0xabcdef", 0, "01abcdef")
113570af302Sopenharmony_ciV4("00377.0x0ff.65534", 0, "fffffffe")
114570af302Sopenharmony_ci
115570af302Sopenharmony_ci// invalid
116570af302Sopenharmony_ciV4(".1.2.3", 0, "ffffffff")
117570af302Sopenharmony_ciV4("1..2.3", 0, "ffffffff")
118570af302Sopenharmony_ciV4("1.2.3.", 0, "ffffffff")
119570af302Sopenharmony_ciV4("1.2.3.4.5", 0, "ffffffff")
120570af302Sopenharmony_ciV4("1.2.3.a", 0, "ffffffff")
121570af302Sopenharmony_ciV4("1.256.2.3", 0, "ffffffff")
122570af302Sopenharmony_ciV4("1.2.4294967296.3", 0, "ffffffff")
123570af302Sopenharmony_ciV4("1.2.-4294967295.3", 0, "ffffffff")
124570af302Sopenharmony_ciV4("1.2. 3.4", 0, "ffffffff")
125570af302Sopenharmony_ci
126570af302Sopenharmony_ci// ipv6
127570af302Sopenharmony_ciV6(":", 0, "")
128570af302Sopenharmony_ciV6("::", 1, "00000000000000000000000000000000")
129570af302Sopenharmony_ciV6("::1", 1, "00000000000000000000000000000001")
130570af302Sopenharmony_ciV6(":::", 0, "")
131570af302Sopenharmony_ciV6("192.168.1.1", 0, "")
132570af302Sopenharmony_ciV6(":192.168.1.1", 0, "")
133570af302Sopenharmony_ciV6("::192.168.1.1", 1, "000000000000000000000000c0a80101")
134570af302Sopenharmony_ciV6("0:0:0:0:0:0:192.168.1.1", 1, "000000000000000000000000c0a80101")
135570af302Sopenharmony_ciV6("0:0::0:0:0:192.168.1.1", 1, "000000000000000000000000c0a80101")
136570af302Sopenharmony_ciV6("::012.34.56.78", 0, "")
137570af302Sopenharmony_ciV6(":ffff:192.168.1.1", 0, "")
138570af302Sopenharmony_ciV6("::ffff:192.168.1.1", 1, "00000000000000000000ffffc0a80101")
139570af302Sopenharmony_ciV6(".192.168.1.1", 0, "")
140570af302Sopenharmony_ciV6(":.192.168.1.1", 0, "")
141570af302Sopenharmony_ciV6("a:0b:00c:000d:E:F::", 1, "000a000b000c000d000e000f00000000")
142570af302Sopenharmony_ciV6("a:0b:00c:000d:0000e:f::", 0, "")
143570af302Sopenharmony_ciV6("1:2:3:4:5:6::", 1, "00010002000300040005000600000000")
144570af302Sopenharmony_ciV6("1:2:3:4:5:6:7::", 1, "00010002000300040005000600070000")
145570af302Sopenharmony_ciV6("1:2:3:4:5:6:7:8::", 0, "")
146570af302Sopenharmony_ciV6("1:2:3:4:5:6:7::9", 0, "")
147570af302Sopenharmony_ciV6("::1:2:3:4:5:6", 1, "00000000000100020003000400050006")
148570af302Sopenharmony_ciV6("::1:2:3:4:5:6:7", 1, "00000001000200030004000500060007")
149570af302Sopenharmony_ciV6("::1:2:3:4:5:6:7:8", 0, "")
150570af302Sopenharmony_ciV6("a:b::c:d:e:f", 1, "000a000b00000000000c000d000e000f")
151570af302Sopenharmony_ciV6("ffff:c0a8:5e4", 0, "")
152570af302Sopenharmony_ciV6(":ffff:c0a8:5e4", 0, "")
153570af302Sopenharmony_ciV6("0:0:0:0:0:ffff:c0a8:5e4", 1, "00000000000000000000ffffc0a805e4")
154570af302Sopenharmony_ciV6("0:0:0:0:ffff:c0a8:5e4", 0, "")
155570af302Sopenharmony_ciV6("0::ffff:c0a8:5e4", 1, "00000000000000000000ffffc0a805e4")
156570af302Sopenharmony_ciV6("::0::ffff:c0a8:5e4", 0, "")
157570af302Sopenharmony_ciV6("c0a8", 0, "")
158570af302Sopenharmony_ci
159570af302Sopenharmony_cireturn t_status;
160570af302Sopenharmony_ci}
161