]>
jfr.im git - irc/quakenet/snircd.git/blob - ircd/test/ircd_in_addr_t.c
1 /* ircd_in_addr_t.c - Test file for IP address manipulation */
4 #include "ircd_string.h"
9 #include <netinet/in.h>
11 /** Structure to describe a test for IP address parsing and unparsing. */
13 const char *text
; /**< Textual address to parse. */
14 const char *canonical
; /**< Canonical form of address. */
15 struct irc_in_addr expected
; /**< Parsed address. */
16 const char *base64_v4
; /**< v4-only compatible base64 encoding. */
17 const char *base64_v6
; /**< v6-compatible base64 encoding. */
18 unsigned int is_valid
: 1; /**< is address valid? */
19 unsigned int is_ipv4
: 1; /**< is address ipv4? */
20 unsigned int is_loopback
: 1; /**< is address loopback? */
23 /** Array of addresses to test with. */
24 static struct address_test test_addrs
[] = {
26 {{ 0, 0, 0, 0, 0, 0, 0, 0 }},
27 "AAAAAA", "_", 0, 0, 0 },
29 {{ 0, 0, 0, 0, 0, 0, 0, 1 }},
30 "AAAAAA", "_AAB", 1, 0, 1 },
31 { "127.0.0.1", "127.0.0.1",
32 {{ 0, 0, 0, 0, 0, 0, 0x7f00, 1 }},
33 "B]AAAB", "B]AAAB", 1, 1, 1 },
34 { "::ffff:127.0.0.3", "127.0.0.3",
35 {{ 0, 0, 0, 0, 0, 0xffff, 0x7f00, 3 }},
36 "B]AAAD", "B]AAAD", 1, 1, 1 },
37 { "::127.0.0.1", "127.0.0.1",
38 {{ 0, 0, 0, 0, 0, 0, 0x7f00, 1 }},
39 "B]AAAB", "B]AAAB", 1, 1, 1 },
40 { "2002:7f00:3::1", "2002:7f00:3::1",
41 {{ 0x2002, 0x7f00, 3, 0, 0, 0, 0, 1 }},
42 "B]AAAD", "CACH8AAAD_AAB", 1, 0, 0 },
43 { "8352:0344:0:0:0:0:2001:1204", "8352:344::2001:1204",
44 {{ 0x8352, 0x344, 0, 0, 0, 0, 0x2001, 0x1204 }},
45 "AAAAAA", "INSANE_CABBIE", 1, 0, 0 },
46 { "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8",
47 {{ 1, 2, 3, 4, 5, 6, 7, 8 }},
48 "AAAAAA", "AABAACAADAAEAAFAAGAAHAAI", 1, 0, 0 },
52 /** Perform tests for a single IP address.
53 * @param[in] addr Address test structure.
56 test_address(struct address_test
*addr
)
58 struct irc_in_addr parsed
;
59 unsigned int ii
, len
, val
;
60 char unparsed
[64], base64_v4
[64], base64_v6
[64];
62 /* Convert expected address to network order. */
63 for (ii
= 0; ii
< 8; ++ii
)
64 addr
->expected
.in6_16
[ii
] = htons(addr
->expected
.in6_16
[ii
]);
65 /* Make sure the text form is parsed as expected. */
66 len
= ircd_aton(&parsed
, addr
->text
);
67 assert(len
== strlen(addr
->text
));
68 assert(!irc_in_addr_cmp(&parsed
, &addr
->expected
));
69 /* Make sure it converts back to ASCII. */
70 ircd_ntoa_r(unparsed
, &parsed
);
71 assert(!strcmp(unparsed
, addr
->canonical
));
72 /* Check IP-to-base64 conversion. */
73 iptobase64(base64_v4
, &parsed
, sizeof(base64_v4
), 0);
74 iptobase64(base64_v6
, &parsed
, sizeof(base64_v6
), 1);
76 assert(!strcmp(base64_v4
, addr
->base64_v4
));
78 assert(!strcmp(base64_v6
, addr
->base64_v6
));
79 /* Check testable attributes. */
80 val
= irc_in_addr_valid(&parsed
);
81 assert(!!val
== addr
->is_valid
);
82 val
= irc_in_addr_is_ipv4(&parsed
);
83 assert(!!val
== addr
->is_ipv4
);
84 val
= irc_in_addr_is_loopback(&parsed
);
85 assert(!!val
== addr
->is_loopback
);
86 /* Check base64-to-IP conversion. */
88 base64toip(addr
->base64_v4
, &parsed
);
89 assert(!memcmp(parsed
.in6_16
+6, addr
->expected
.in6_16
+6, 4));
91 base64toip(addr
->base64_v6
, &parsed
);
92 assert(!memcmp(&parsed
, &addr
->expected
, sizeof(parsed
)));
94 /* Tests completed. */
95 printf("Passed: %s (%s/%s)\n", addr
->text
, base64_v4
, base64_v6
);
98 /** Structure to describe a test for IP mask parsing. */
100 const char *text
; /**< Textual IP mask to parse. */
101 struct irc_in_addr expected
; /**< Canonical form of address. */
102 unsigned int is_ipmask
: 1; /**< Parse as an ipmask? */
103 unsigned int is_parseable
: 1; /**< Is address parseable? */
104 unsigned int exp_bits
: 8; /**< Number of bits expected in netmask */
107 /** Array of ipmasks to test with. */
108 static struct ipmask_test test_masks
[] = {
109 { "::", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 128 },
110 { "::/0", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 0 },
111 { "::10.0.0.0", {{ 0, 0, 0, 0, 0, 0, 0xa00, 0 }}, 1, 1, 128 },
112 { "192.168/16", {{ 0, 0, 0, 0, 0, 0xffff, 0xc0a8, 0 }}, 1, 1, 112 },
113 { "192.*", {{ 0, 0, 0, 0, 0, 0xffff, 0xc000, 0 }}, 1, 1, 104 },
114 { "192.*.*.*", {{ 0, 0, 0, 0, 0, 0xffff, 0xc000, 0 }}, 1, 1, 104 },
115 { "192.*/8", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
116 { "192*", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
117 { "192.168.0.0/16", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0, 0, 0 },
118 { "ab.*", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
119 { "a*", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
120 { "*", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 0 },
121 { "a:b", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
122 { "a::*", {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 1, 0, 0 },
123 { "a:*", {{ 0xa, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 16 },
124 { "a:*:*", {{ 0xa, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 16 },
125 { "a:/16", {{ 0xa, 0, 0, 0, 0, 0, 0, 0 }}, 1, 1, 16 },
129 /** Perform tests for a single IP mask.
130 * @param[in] mask IP mask test structure.
133 test_ipmask(struct ipmask_test
*mask
)
135 struct irc_in_addr parsed
;
136 unsigned int len
, ii
;
137 unsigned char bits
= 0;
139 /* Convert expected address to network order. */
140 for (ii
= 0; ii
< 8; ++ii
)
141 mask
->expected
.in6_16
[ii
] = htons(mask
->expected
.in6_16
[ii
]);
142 /* Try to parse; make sure its parseability and netmask length are
144 len
= ipmask_parse(mask
->text
, &parsed
, mask
->is_ipmask
? &bits
: 0);
145 assert(!!len
== mask
->is_parseable
);
147 printf("X-Fail: %s\n", mask
->text
);
151 assert(bits
== mask
->exp_bits
);
152 assert(!memcmp(&parsed
, &mask
->expected
, sizeof(parsed
)));
153 printf("Passed: %s (%s/%u)\n", mask
->text
, ircd_ntoa(&parsed
), bits
);
157 main(int argc
, char *argv
[])
161 printf("Testing address parsing..\n");
162 for (ii
= 0; test_addrs
[ii
].text
; ++ii
)
163 test_address(&test_addrs
[ii
]);
165 printf("\nTesting ipmask parsing..\n");
166 for (ii
= 0; test_masks
[ii
].text
; ++ii
)
167 test_ipmask(&test_masks
[ii
]);