1*e985b929SDavid van Moolenbroek /* $NetBSD: regress_util.c,v 1.2 2013/04/11 16:56:42 christos Exp $ */
2*e985b929SDavid van Moolenbroek /*
3*e985b929SDavid van Moolenbroek * Copyright (c) 2009-2012 Nick Mathewson and Niels Provos
4*e985b929SDavid van Moolenbroek *
5*e985b929SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*e985b929SDavid van Moolenbroek * modification, are permitted provided that the following conditions
7*e985b929SDavid van Moolenbroek * are met:
8*e985b929SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
9*e985b929SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
10*e985b929SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
11*e985b929SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
12*e985b929SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
13*e985b929SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
14*e985b929SDavid van Moolenbroek * derived from this software without specific prior written permission.
15*e985b929SDavid van Moolenbroek *
16*e985b929SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*e985b929SDavid van Moolenbroek * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*e985b929SDavid van Moolenbroek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*e985b929SDavid van Moolenbroek * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*e985b929SDavid van Moolenbroek * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*e985b929SDavid van Moolenbroek * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*e985b929SDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*e985b929SDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*e985b929SDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*e985b929SDavid van Moolenbroek * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*e985b929SDavid van Moolenbroek */
27*e985b929SDavid van Moolenbroek #ifdef WIN32
28*e985b929SDavid van Moolenbroek #include <winsock2.h>
29*e985b929SDavid van Moolenbroek #include <windows.h>
30*e985b929SDavid van Moolenbroek #include <ws2tcpip.h>
31*e985b929SDavid van Moolenbroek #endif
32*e985b929SDavid van Moolenbroek
33*e985b929SDavid van Moolenbroek #include "event2/event-config.h"
34*e985b929SDavid van Moolenbroek #include <sys/cdefs.h>
35*e985b929SDavid van Moolenbroek __RCSID("$NetBSD: regress_util.c,v 1.2 2013/04/11 16:56:42 christos Exp $");
36*e985b929SDavid van Moolenbroek
37*e985b929SDavid van Moolenbroek #include <sys/types.h>
38*e985b929SDavid van Moolenbroek
39*e985b929SDavid van Moolenbroek #ifndef WIN32
40*e985b929SDavid van Moolenbroek #include <sys/socket.h>
41*e985b929SDavid van Moolenbroek #include <netinet/in.h>
42*e985b929SDavid van Moolenbroek #include <arpa/inet.h>
43*e985b929SDavid van Moolenbroek #include <unistd.h>
44*e985b929SDavid van Moolenbroek #endif
45*e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_NETINET_IN6_H
46*e985b929SDavid van Moolenbroek #include <netinet/in6.h>
47*e985b929SDavid van Moolenbroek #endif
48*e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_SYS_WAIT_H
49*e985b929SDavid van Moolenbroek #include <sys/wait.h>
50*e985b929SDavid van Moolenbroek #endif
51*e985b929SDavid van Moolenbroek #include <signal.h>
52*e985b929SDavid van Moolenbroek #include <stdio.h>
53*e985b929SDavid van Moolenbroek #include <stdlib.h>
54*e985b929SDavid van Moolenbroek #include <string.h>
55*e985b929SDavid van Moolenbroek #include <limits.h>
56*e985b929SDavid van Moolenbroek
57*e985b929SDavid van Moolenbroek #include "event2/event.h"
58*e985b929SDavid van Moolenbroek #include "event2/util.h"
59*e985b929SDavid van Moolenbroek #include "../ipv6-internal.h"
60*e985b929SDavid van Moolenbroek #include "../util-internal.h"
61*e985b929SDavid van Moolenbroek #include "../log-internal.h"
62*e985b929SDavid van Moolenbroek #include "../strlcpy-internal.h"
63*e985b929SDavid van Moolenbroek
64*e985b929SDavid van Moolenbroek #include "regress.h"
65*e985b929SDavid van Moolenbroek
66*e985b929SDavid van Moolenbroek enum entry_status { NORMAL, CANONICAL, BAD };
67*e985b929SDavid van Moolenbroek
68*e985b929SDavid van Moolenbroek /* This is a big table of results we expect from generating and parsing */
69*e985b929SDavid van Moolenbroek static struct ipv4_entry {
70*e985b929SDavid van Moolenbroek const char *addr;
71*e985b929SDavid van Moolenbroek ev_uint32_t res;
72*e985b929SDavid van Moolenbroek enum entry_status status;
73*e985b929SDavid van Moolenbroek } ipv4_entries[] = {
74*e985b929SDavid van Moolenbroek { "1.2.3.4", 0x01020304u, CANONICAL },
75*e985b929SDavid van Moolenbroek { "255.255.255.255", 0xffffffffu, CANONICAL },
76*e985b929SDavid van Moolenbroek { "256.0.0.0", 0, BAD },
77*e985b929SDavid van Moolenbroek { "ABC", 0, BAD },
78*e985b929SDavid van Moolenbroek { "1.2.3.4.5", 0, BAD },
79*e985b929SDavid van Moolenbroek { "176.192.208.244", 0xb0c0d0f4, CANONICAL },
80*e985b929SDavid van Moolenbroek { NULL, 0, BAD },
81*e985b929SDavid van Moolenbroek };
82*e985b929SDavid van Moolenbroek
83*e985b929SDavid van Moolenbroek static struct ipv6_entry {
84*e985b929SDavid van Moolenbroek const char *addr;
85*e985b929SDavid van Moolenbroek ev_uint32_t res[4];
86*e985b929SDavid van Moolenbroek enum entry_status status;
87*e985b929SDavid van Moolenbroek } ipv6_entries[] = {
88*e985b929SDavid van Moolenbroek { "::", { 0, 0, 0, 0, }, CANONICAL },
89*e985b929SDavid van Moolenbroek { "0:0:0:0:0:0:0:0", { 0, 0, 0, 0, }, NORMAL },
90*e985b929SDavid van Moolenbroek { "::1", { 0, 0, 0, 1, }, CANONICAL },
91*e985b929SDavid van Moolenbroek { "::1.2.3.4", { 0, 0, 0, 0x01020304, }, CANONICAL },
92*e985b929SDavid van Moolenbroek { "ffff:1::", { 0xffff0001u, 0, 0, 0, }, CANONICAL },
93*e985b929SDavid van Moolenbroek { "ffff:0000::", { 0xffff0000u, 0, 0, 0, }, NORMAL },
94*e985b929SDavid van Moolenbroek { "ffff::1234", { 0xffff0000u, 0, 0, 0x1234, }, CANONICAL },
95*e985b929SDavid van Moolenbroek { "0102::1.2.3.4", {0x01020000u, 0, 0, 0x01020304u }, NORMAL },
96*e985b929SDavid van Moolenbroek { "::9:c0a8:1:1", { 0, 0, 0x0009c0a8u, 0x00010001u }, CANONICAL },
97*e985b929SDavid van Moolenbroek { "::ffff:1.2.3.4", { 0, 0, 0x000ffffu, 0x01020304u }, CANONICAL },
98*e985b929SDavid van Moolenbroek { "FFFF::", { 0xffff0000u, 0, 0, 0 }, NORMAL },
99*e985b929SDavid van Moolenbroek { "foobar.", { 0, 0, 0, 0 }, BAD },
100*e985b929SDavid van Moolenbroek { "foobar", { 0, 0, 0, 0 }, BAD },
101*e985b929SDavid van Moolenbroek { "fo:obar", { 0, 0, 0, 0 }, BAD },
102*e985b929SDavid van Moolenbroek { "ffff", { 0, 0, 0, 0 }, BAD },
103*e985b929SDavid van Moolenbroek { "fffff::", { 0, 0, 0, 0 }, BAD },
104*e985b929SDavid van Moolenbroek { "fffff::", { 0, 0, 0, 0 }, BAD },
105*e985b929SDavid van Moolenbroek { "::1.0.1.1000", { 0, 0, 0, 0 }, BAD },
106*e985b929SDavid van Moolenbroek { "1:2:33333:4::", { 0, 0, 0, 0 }, BAD },
107*e985b929SDavid van Moolenbroek { "1:2:3:4:5:6:7:8:9", { 0, 0, 0, 0 }, BAD },
108*e985b929SDavid van Moolenbroek { "1::2::3", { 0, 0, 0, 0 }, BAD },
109*e985b929SDavid van Moolenbroek { ":::1", { 0, 0, 0, 0 }, BAD },
110*e985b929SDavid van Moolenbroek { NULL, { 0, 0, 0, 0, }, BAD },
111*e985b929SDavid van Moolenbroek };
112*e985b929SDavid van Moolenbroek
113*e985b929SDavid van Moolenbroek static void
regress_ipv4_parse(void * ptr)114*e985b929SDavid van Moolenbroek regress_ipv4_parse(void *ptr)
115*e985b929SDavid van Moolenbroek {
116*e985b929SDavid van Moolenbroek int i;
117*e985b929SDavid van Moolenbroek for (i = 0; ipv4_entries[i].addr; ++i) {
118*e985b929SDavid van Moolenbroek char written[128];
119*e985b929SDavid van Moolenbroek struct ipv4_entry *ent = &ipv4_entries[i];
120*e985b929SDavid van Moolenbroek struct in_addr in;
121*e985b929SDavid van Moolenbroek int r;
122*e985b929SDavid van Moolenbroek r = evutil_inet_pton(AF_INET, ent->addr, &in);
123*e985b929SDavid van Moolenbroek if (r == 0) {
124*e985b929SDavid van Moolenbroek if (ent->status != BAD) {
125*e985b929SDavid van Moolenbroek TT_FAIL(("%s did not parse, but it's a good address!",
126*e985b929SDavid van Moolenbroek ent->addr));
127*e985b929SDavid van Moolenbroek }
128*e985b929SDavid van Moolenbroek continue;
129*e985b929SDavid van Moolenbroek }
130*e985b929SDavid van Moolenbroek if (ent->status == BAD) {
131*e985b929SDavid van Moolenbroek TT_FAIL(("%s parsed, but we expected an error", ent->addr));
132*e985b929SDavid van Moolenbroek continue;
133*e985b929SDavid van Moolenbroek }
134*e985b929SDavid van Moolenbroek if (ntohl(in.s_addr) != ent->res) {
135*e985b929SDavid van Moolenbroek TT_FAIL(("%s parsed to %lx, but we expected %lx", ent->addr,
136*e985b929SDavid van Moolenbroek (unsigned long)ntohl(in.s_addr),
137*e985b929SDavid van Moolenbroek (unsigned long)ent->res));
138*e985b929SDavid van Moolenbroek continue;
139*e985b929SDavid van Moolenbroek }
140*e985b929SDavid van Moolenbroek if (ent->status == CANONICAL) {
141*e985b929SDavid van Moolenbroek const char *w = evutil_inet_ntop(AF_INET, &in, written,
142*e985b929SDavid van Moolenbroek sizeof(written));
143*e985b929SDavid van Moolenbroek if (!w) {
144*e985b929SDavid van Moolenbroek TT_FAIL(("Tried to write out %s; got NULL.", ent->addr));
145*e985b929SDavid van Moolenbroek continue;
146*e985b929SDavid van Moolenbroek }
147*e985b929SDavid van Moolenbroek if (strcmp(written, ent->addr)) {
148*e985b929SDavid van Moolenbroek TT_FAIL(("Tried to write out %s; got %s",
149*e985b929SDavid van Moolenbroek ent->addr, written));
150*e985b929SDavid van Moolenbroek continue;
151*e985b929SDavid van Moolenbroek }
152*e985b929SDavid van Moolenbroek }
153*e985b929SDavid van Moolenbroek
154*e985b929SDavid van Moolenbroek }
155*e985b929SDavid van Moolenbroek
156*e985b929SDavid van Moolenbroek }
157*e985b929SDavid van Moolenbroek
158*e985b929SDavid van Moolenbroek static void
regress_ipv6_parse(void * ptr)159*e985b929SDavid van Moolenbroek regress_ipv6_parse(void *ptr)
160*e985b929SDavid van Moolenbroek {
161*e985b929SDavid van Moolenbroek #ifdef AF_INET6
162*e985b929SDavid van Moolenbroek int i, j;
163*e985b929SDavid van Moolenbroek
164*e985b929SDavid van Moolenbroek for (i = 0; ipv6_entries[i].addr; ++i) {
165*e985b929SDavid van Moolenbroek char written[128];
166*e985b929SDavid van Moolenbroek struct ipv6_entry *ent = &ipv6_entries[i];
167*e985b929SDavid van Moolenbroek struct in6_addr in6;
168*e985b929SDavid van Moolenbroek int r;
169*e985b929SDavid van Moolenbroek r = evutil_inet_pton(AF_INET6, ent->addr, &in6);
170*e985b929SDavid van Moolenbroek if (r == 0) {
171*e985b929SDavid van Moolenbroek if (ent->status != BAD)
172*e985b929SDavid van Moolenbroek TT_FAIL(("%s did not parse, but it's a good address!",
173*e985b929SDavid van Moolenbroek ent->addr));
174*e985b929SDavid van Moolenbroek continue;
175*e985b929SDavid van Moolenbroek }
176*e985b929SDavid van Moolenbroek if (ent->status == BAD) {
177*e985b929SDavid van Moolenbroek TT_FAIL(("%s parsed, but we expected an error", ent->addr));
178*e985b929SDavid van Moolenbroek continue;
179*e985b929SDavid van Moolenbroek }
180*e985b929SDavid van Moolenbroek for (j = 0; j < 4; ++j) {
181*e985b929SDavid van Moolenbroek /* Can't use s6_addr32 here; some don't have it. */
182*e985b929SDavid van Moolenbroek ev_uint32_t u =
183*e985b929SDavid van Moolenbroek (in6.s6_addr[j*4 ] << 24) |
184*e985b929SDavid van Moolenbroek (in6.s6_addr[j*4+1] << 16) |
185*e985b929SDavid van Moolenbroek (in6.s6_addr[j*4+2] << 8) |
186*e985b929SDavid van Moolenbroek (in6.s6_addr[j*4+3]);
187*e985b929SDavid van Moolenbroek if (u != ent->res[j]) {
188*e985b929SDavid van Moolenbroek TT_FAIL(("%s did not parse as expected.", ent->addr));
189*e985b929SDavid van Moolenbroek continue;
190*e985b929SDavid van Moolenbroek }
191*e985b929SDavid van Moolenbroek }
192*e985b929SDavid van Moolenbroek if (ent->status == CANONICAL) {
193*e985b929SDavid van Moolenbroek const char *w = evutil_inet_ntop(AF_INET6, &in6, written,
194*e985b929SDavid van Moolenbroek sizeof(written));
195*e985b929SDavid van Moolenbroek if (!w) {
196*e985b929SDavid van Moolenbroek TT_FAIL(("Tried to write out %s; got NULL.", ent->addr));
197*e985b929SDavid van Moolenbroek continue;
198*e985b929SDavid van Moolenbroek }
199*e985b929SDavid van Moolenbroek if (strcmp(written, ent->addr)) {
200*e985b929SDavid van Moolenbroek TT_FAIL(("Tried to write out %s; got %s", ent->addr, written));
201*e985b929SDavid van Moolenbroek continue;
202*e985b929SDavid van Moolenbroek }
203*e985b929SDavid van Moolenbroek }
204*e985b929SDavid van Moolenbroek
205*e985b929SDavid van Moolenbroek }
206*e985b929SDavid van Moolenbroek #else
207*e985b929SDavid van Moolenbroek TT_BLATHER(("Skipping IPv6 address parsing."));
208*e985b929SDavid van Moolenbroek #endif
209*e985b929SDavid van Moolenbroek }
210*e985b929SDavid van Moolenbroek
211*e985b929SDavid van Moolenbroek static struct sa_port_ent {
212*e985b929SDavid van Moolenbroek const char *parse;
213*e985b929SDavid van Moolenbroek int safamily;
214*e985b929SDavid van Moolenbroek const char *addr;
215*e985b929SDavid van Moolenbroek int port;
216*e985b929SDavid van Moolenbroek } sa_port_ents[] = {
217*e985b929SDavid van Moolenbroek { "[ffff::1]:1000", AF_INET6, "ffff::1", 1000 },
218*e985b929SDavid van Moolenbroek { "[ffff::1]", AF_INET6, "ffff::1", 0 },
219*e985b929SDavid van Moolenbroek { "[ffff::1", 0, NULL, 0 },
220*e985b929SDavid van Moolenbroek { "[ffff::1]:65599", 0, NULL, 0 },
221*e985b929SDavid van Moolenbroek { "[ffff::1]:0", 0, NULL, 0 },
222*e985b929SDavid van Moolenbroek { "[ffff::1]:-1", 0, NULL, 0 },
223*e985b929SDavid van Moolenbroek { "::1", AF_INET6, "::1", 0 },
224*e985b929SDavid van Moolenbroek { "1:2::1", AF_INET6, "1:2::1", 0 },
225*e985b929SDavid van Moolenbroek { "192.168.0.1:50", AF_INET, "192.168.0.1", 50 },
226*e985b929SDavid van Moolenbroek { "1.2.3.4", AF_INET, "1.2.3.4", 0 },
227*e985b929SDavid van Moolenbroek { NULL, 0, NULL, 0 },
228*e985b929SDavid van Moolenbroek };
229*e985b929SDavid van Moolenbroek
230*e985b929SDavid van Moolenbroek static void
regress_sockaddr_port_parse(void * ptr)231*e985b929SDavid van Moolenbroek regress_sockaddr_port_parse(void *ptr)
232*e985b929SDavid van Moolenbroek {
233*e985b929SDavid van Moolenbroek struct sockaddr_storage ss;
234*e985b929SDavid van Moolenbroek int i, r;
235*e985b929SDavid van Moolenbroek
236*e985b929SDavid van Moolenbroek for (i = 0; sa_port_ents[i].parse; ++i) {
237*e985b929SDavid van Moolenbroek struct sa_port_ent *ent = &sa_port_ents[i];
238*e985b929SDavid van Moolenbroek int len = sizeof(ss);
239*e985b929SDavid van Moolenbroek memset(&ss, 0, sizeof(ss));
240*e985b929SDavid van Moolenbroek r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len);
241*e985b929SDavid van Moolenbroek if (r < 0) {
242*e985b929SDavid van Moolenbroek if (ent->safamily)
243*e985b929SDavid van Moolenbroek TT_FAIL(("Couldn't parse %s!", ent->parse));
244*e985b929SDavid van Moolenbroek continue;
245*e985b929SDavid van Moolenbroek } else if (! ent->safamily) {
246*e985b929SDavid van Moolenbroek TT_FAIL(("Shouldn't have been able to parse %s!", ent->parse));
247*e985b929SDavid van Moolenbroek continue;
248*e985b929SDavid van Moolenbroek }
249*e985b929SDavid van Moolenbroek if (ent->safamily == AF_INET) {
250*e985b929SDavid van Moolenbroek struct sockaddr_in sin;
251*e985b929SDavid van Moolenbroek memset(&sin, 0, sizeof(sin));
252*e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
253*e985b929SDavid van Moolenbroek sin.sin_len = sizeof(sin);
254*e985b929SDavid van Moolenbroek #endif
255*e985b929SDavid van Moolenbroek sin.sin_family = AF_INET;
256*e985b929SDavid van Moolenbroek sin.sin_port = htons(ent->port);
257*e985b929SDavid van Moolenbroek r = evutil_inet_pton(AF_INET, ent->addr, &sin.sin_addr);
258*e985b929SDavid van Moolenbroek if (1 != r) {
259*e985b929SDavid van Moolenbroek TT_FAIL(("Couldn't parse ipv4 target %s.", ent->addr));
260*e985b929SDavid van Moolenbroek } else if (memcmp(&sin, &ss, sizeof(sin))) {
261*e985b929SDavid van Moolenbroek TT_FAIL(("Parse for %s was not as expected.", ent->parse));
262*e985b929SDavid van Moolenbroek } else if (len != sizeof(sin)) {
263*e985b929SDavid van Moolenbroek TT_FAIL(("Length for %s not as expected.",ent->parse));
264*e985b929SDavid van Moolenbroek }
265*e985b929SDavid van Moolenbroek } else {
266*e985b929SDavid van Moolenbroek struct sockaddr_in6 sin6;
267*e985b929SDavid van Moolenbroek memset(&sin6, 0, sizeof(sin6));
268*e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
269*e985b929SDavid van Moolenbroek sin6.sin6_len = sizeof(sin6);
270*e985b929SDavid van Moolenbroek #endif
271*e985b929SDavid van Moolenbroek sin6.sin6_family = AF_INET6;
272*e985b929SDavid van Moolenbroek sin6.sin6_port = htons(ent->port);
273*e985b929SDavid van Moolenbroek r = evutil_inet_pton(AF_INET6, ent->addr, &sin6.sin6_addr);
274*e985b929SDavid van Moolenbroek if (1 != r) {
275*e985b929SDavid van Moolenbroek TT_FAIL(("Couldn't parse ipv6 target %s.", ent->addr));
276*e985b929SDavid van Moolenbroek } else if (memcmp(&sin6, &ss, sizeof(sin6))) {
277*e985b929SDavid van Moolenbroek TT_FAIL(("Parse for %s was not as expected.", ent->parse));
278*e985b929SDavid van Moolenbroek } else if (len != sizeof(sin6)) {
279*e985b929SDavid van Moolenbroek TT_FAIL(("Length for %s not as expected.",ent->parse));
280*e985b929SDavid van Moolenbroek }
281*e985b929SDavid van Moolenbroek }
282*e985b929SDavid van Moolenbroek }
283*e985b929SDavid van Moolenbroek }
284*e985b929SDavid van Moolenbroek
285*e985b929SDavid van Moolenbroek
286*e985b929SDavid van Moolenbroek static void
regress_sockaddr_port_format(void * ptr)287*e985b929SDavid van Moolenbroek regress_sockaddr_port_format(void *ptr)
288*e985b929SDavid van Moolenbroek {
289*e985b929SDavid van Moolenbroek struct sockaddr_storage ss;
290*e985b929SDavid van Moolenbroek int len;
291*e985b929SDavid van Moolenbroek const char *cp;
292*e985b929SDavid van Moolenbroek char cbuf[128];
293*e985b929SDavid van Moolenbroek int r;
294*e985b929SDavid van Moolenbroek
295*e985b929SDavid van Moolenbroek len = sizeof(ss);
296*e985b929SDavid van Moolenbroek r = evutil_parse_sockaddr_port("192.168.1.1:80",
297*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, &len);
298*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
299*e985b929SDavid van Moolenbroek cp = evutil_format_sockaddr_port(
300*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, cbuf, sizeof(cbuf));
301*e985b929SDavid van Moolenbroek tt_ptr_op(cp,==,cbuf);
302*e985b929SDavid van Moolenbroek tt_str_op(cp,==,"192.168.1.1:80");
303*e985b929SDavid van Moolenbroek
304*e985b929SDavid van Moolenbroek len = sizeof(ss);
305*e985b929SDavid van Moolenbroek r = evutil_parse_sockaddr_port("[ff00::8010]:999",
306*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, &len);
307*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
308*e985b929SDavid van Moolenbroek cp = evutil_format_sockaddr_port(
309*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, cbuf, sizeof(cbuf));
310*e985b929SDavid van Moolenbroek tt_ptr_op(cp,==,cbuf);
311*e985b929SDavid van Moolenbroek tt_str_op(cp,==,"[ff00::8010]:999");
312*e985b929SDavid van Moolenbroek
313*e985b929SDavid van Moolenbroek ss.ss_family=99;
314*e985b929SDavid van Moolenbroek cp = evutil_format_sockaddr_port(
315*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, cbuf, sizeof(cbuf));
316*e985b929SDavid van Moolenbroek tt_ptr_op(cp,==,cbuf);
317*e985b929SDavid van Moolenbroek tt_str_op(cp,==,"<addr with socktype 99>");
318*e985b929SDavid van Moolenbroek end:
319*e985b929SDavid van Moolenbroek ;
320*e985b929SDavid van Moolenbroek }
321*e985b929SDavid van Moolenbroek
322*e985b929SDavid van Moolenbroek static struct sa_pred_ent {
323*e985b929SDavid van Moolenbroek const char *parse;
324*e985b929SDavid van Moolenbroek
325*e985b929SDavid van Moolenbroek int is_loopback;
326*e985b929SDavid van Moolenbroek } sa_pred_entries[] = {
327*e985b929SDavid van Moolenbroek { "127.0.0.1", 1 },
328*e985b929SDavid van Moolenbroek { "127.0.3.2", 1 },
329*e985b929SDavid van Moolenbroek { "128.1.2.3", 0 },
330*e985b929SDavid van Moolenbroek { "18.0.0.1", 0 },
331*e985b929SDavid van Moolenbroek { "129.168.1.1", 0 },
332*e985b929SDavid van Moolenbroek
333*e985b929SDavid van Moolenbroek { "::1", 1 },
334*e985b929SDavid van Moolenbroek { "::0", 0 },
335*e985b929SDavid van Moolenbroek { "f::1", 0 },
336*e985b929SDavid van Moolenbroek { "::501", 0 },
337*e985b929SDavid van Moolenbroek { NULL, 0 },
338*e985b929SDavid van Moolenbroek
339*e985b929SDavid van Moolenbroek };
340*e985b929SDavid van Moolenbroek
341*e985b929SDavid van Moolenbroek static void
test_evutil_sockaddr_predicates(void * ptr)342*e985b929SDavid van Moolenbroek test_evutil_sockaddr_predicates(void *ptr)
343*e985b929SDavid van Moolenbroek {
344*e985b929SDavid van Moolenbroek struct sockaddr_storage ss;
345*e985b929SDavid van Moolenbroek int r, i;
346*e985b929SDavid van Moolenbroek
347*e985b929SDavid van Moolenbroek for (i=0; sa_pred_entries[i].parse; ++i) {
348*e985b929SDavid van Moolenbroek struct sa_pred_ent *ent = &sa_pred_entries[i];
349*e985b929SDavid van Moolenbroek int len = sizeof(ss);
350*e985b929SDavid van Moolenbroek
351*e985b929SDavid van Moolenbroek r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len);
352*e985b929SDavid van Moolenbroek
353*e985b929SDavid van Moolenbroek if (r<0) {
354*e985b929SDavid van Moolenbroek TT_FAIL(("Couldn't parse %s!", ent->parse));
355*e985b929SDavid van Moolenbroek continue;
356*e985b929SDavid van Moolenbroek }
357*e985b929SDavid van Moolenbroek
358*e985b929SDavid van Moolenbroek /* sockaddr_is_loopback */
359*e985b929SDavid van Moolenbroek if (ent->is_loopback != evutil_sockaddr_is_loopback((struct sockaddr*)&ss)) {
360*e985b929SDavid van Moolenbroek TT_FAIL(("evutil_sockaddr_loopback(%s) not as expected",
361*e985b929SDavid van Moolenbroek ent->parse));
362*e985b929SDavid van Moolenbroek }
363*e985b929SDavid van Moolenbroek }
364*e985b929SDavid van Moolenbroek }
365*e985b929SDavid van Moolenbroek
366*e985b929SDavid van Moolenbroek static void
test_evutil_strtoll(void * ptr)367*e985b929SDavid van Moolenbroek test_evutil_strtoll(void *ptr)
368*e985b929SDavid van Moolenbroek {
369*e985b929SDavid van Moolenbroek const char *s;
370*e985b929SDavid van Moolenbroek char *endptr;
371*e985b929SDavid van Moolenbroek
372*e985b929SDavid van Moolenbroek tt_want(evutil_strtoll("5000000000", NULL, 10) ==
373*e985b929SDavid van Moolenbroek ((ev_int64_t)5000000)*1000);
374*e985b929SDavid van Moolenbroek tt_want(evutil_strtoll("-5000000000", NULL, 10) ==
375*e985b929SDavid van Moolenbroek ((ev_int64_t)5000000)*-1000);
376*e985b929SDavid van Moolenbroek s = " 99999stuff";
377*e985b929SDavid van Moolenbroek tt_want(evutil_strtoll(s, &endptr, 10) == (ev_int64_t)99999);
378*e985b929SDavid van Moolenbroek tt_want(endptr == s+6);
379*e985b929SDavid van Moolenbroek tt_want(evutil_strtoll("foo", NULL, 10) == 0);
380*e985b929SDavid van Moolenbroek }
381*e985b929SDavid van Moolenbroek
382*e985b929SDavid van Moolenbroek static void
test_evutil_snprintf(void * ptr)383*e985b929SDavid van Moolenbroek test_evutil_snprintf(void *ptr)
384*e985b929SDavid van Moolenbroek {
385*e985b929SDavid van Moolenbroek char buf[16];
386*e985b929SDavid van Moolenbroek int r;
387*e985b929SDavid van Moolenbroek ev_uint64_t u64 = ((ev_uint64_t)1000000000)*200;
388*e985b929SDavid van Moolenbroek ev_int64_t i64 = -1 * (ev_int64_t) u64;
389*e985b929SDavid van Moolenbroek size_t size = 8000;
390*e985b929SDavid van Moolenbroek ev_ssize_t ssize = -9000;
391*e985b929SDavid van Moolenbroek
392*e985b929SDavid van Moolenbroek r = evutil_snprintf(buf, sizeof(buf), "%d %d", 50, 100);
393*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "50 100");
394*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 6);
395*e985b929SDavid van Moolenbroek
396*e985b929SDavid van Moolenbroek r = evutil_snprintf(buf, sizeof(buf), "longish %d", 1234567890);
397*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "longish 1234567");
398*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 18);
399*e985b929SDavid van Moolenbroek
400*e985b929SDavid van Moolenbroek r = evutil_snprintf(buf, sizeof(buf), EV_U64_FMT, EV_U64_ARG(u64));
401*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "200000000000");
402*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 12);
403*e985b929SDavid van Moolenbroek
404*e985b929SDavid van Moolenbroek r = evutil_snprintf(buf, sizeof(buf), EV_I64_FMT, EV_I64_ARG(i64));
405*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "-200000000000");
406*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 13);
407*e985b929SDavid van Moolenbroek
408*e985b929SDavid van Moolenbroek r = evutil_snprintf(buf, sizeof(buf), EV_SIZE_FMT" "EV_SSIZE_FMT,
409*e985b929SDavid van Moolenbroek EV_SIZE_ARG(size), EV_SSIZE_ARG(ssize));
410*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "8000 -9000");
411*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 10);
412*e985b929SDavid van Moolenbroek
413*e985b929SDavid van Moolenbroek end:
414*e985b929SDavid van Moolenbroek ;
415*e985b929SDavid van Moolenbroek }
416*e985b929SDavid van Moolenbroek
417*e985b929SDavid van Moolenbroek static void
test_evutil_casecmp(void * ptr)418*e985b929SDavid van Moolenbroek test_evutil_casecmp(void *ptr)
419*e985b929SDavid van Moolenbroek {
420*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strcasecmp("ABC", "ABC"), ==, 0);
421*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strcasecmp("ABC", "abc"), ==, 0);
422*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strcasecmp("ABC", "abcd"), <, 0);
423*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strcasecmp("ABC", "abb"), >, 0);
424*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strcasecmp("ABCd", "abc"), >, 0);
425*e985b929SDavid van Moolenbroek
426*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 100), ==, 0);
427*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 4), ==, 0);
428*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEXXXX", 4), ==, 0);
429*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibE", 4), ==, 0);
430*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Libe", "LibEvEnT", 4), ==, 0);
431*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Lib", "LibEvEnT", 4), <, 0);
432*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("abc", "def", 99), <, 0);
433*e985b929SDavid van Moolenbroek tt_int_op(evutil_ascii_strncasecmp("Z", "qrst", 1), >, 0);
434*e985b929SDavid van Moolenbroek end:
435*e985b929SDavid van Moolenbroek ;
436*e985b929SDavid van Moolenbroek }
437*e985b929SDavid van Moolenbroek
438*e985b929SDavid van Moolenbroek static int logsev = 0;
439*e985b929SDavid van Moolenbroek static char *logmsg = NULL;
440*e985b929SDavid van Moolenbroek
441*e985b929SDavid van Moolenbroek static void
logfn(int severity,const char * msg)442*e985b929SDavid van Moolenbroek logfn(int severity, const char *msg)
443*e985b929SDavid van Moolenbroek {
444*e985b929SDavid van Moolenbroek logsev = severity;
445*e985b929SDavid van Moolenbroek tt_want(msg);
446*e985b929SDavid van Moolenbroek if (msg) {
447*e985b929SDavid van Moolenbroek if (logmsg)
448*e985b929SDavid van Moolenbroek free(logmsg);
449*e985b929SDavid van Moolenbroek logmsg = strdup(msg);
450*e985b929SDavid van Moolenbroek }
451*e985b929SDavid van Moolenbroek }
452*e985b929SDavid van Moolenbroek
453*e985b929SDavid van Moolenbroek static int fatal_want_severity = 0;
454*e985b929SDavid van Moolenbroek static const char *fatal_want_message = NULL;
455*e985b929SDavid van Moolenbroek static void
fatalfn(int exitcode)456*e985b929SDavid van Moolenbroek fatalfn(int exitcode)
457*e985b929SDavid van Moolenbroek {
458*e985b929SDavid van Moolenbroek if (logsev != fatal_want_severity ||
459*e985b929SDavid van Moolenbroek !logmsg ||
460*e985b929SDavid van Moolenbroek strcmp(logmsg, fatal_want_message))
461*e985b929SDavid van Moolenbroek exit(0);
462*e985b929SDavid van Moolenbroek else
463*e985b929SDavid van Moolenbroek exit(exitcode);
464*e985b929SDavid van Moolenbroek }
465*e985b929SDavid van Moolenbroek
466*e985b929SDavid van Moolenbroek #ifndef WIN32
467*e985b929SDavid van Moolenbroek #define CAN_CHECK_ERR
468*e985b929SDavid van Moolenbroek static void
check_error_logging(void (* fn)(void),int wantexitcode,int wantseverity,const char * wantmsg)469*e985b929SDavid van Moolenbroek check_error_logging(void (*fn)(void), int wantexitcode,
470*e985b929SDavid van Moolenbroek int wantseverity, const char *wantmsg)
471*e985b929SDavid van Moolenbroek {
472*e985b929SDavid van Moolenbroek pid_t pid;
473*e985b929SDavid van Moolenbroek int status = 0, exitcode;
474*e985b929SDavid van Moolenbroek fatal_want_severity = wantseverity;
475*e985b929SDavid van Moolenbroek fatal_want_message = wantmsg;
476*e985b929SDavid van Moolenbroek if ((pid = regress_fork()) == 0) {
477*e985b929SDavid van Moolenbroek /* child process */
478*e985b929SDavid van Moolenbroek fn();
479*e985b929SDavid van Moolenbroek exit(0); /* should be unreachable. */
480*e985b929SDavid van Moolenbroek } else {
481*e985b929SDavid van Moolenbroek wait(&status);
482*e985b929SDavid van Moolenbroek exitcode = WEXITSTATUS(status);
483*e985b929SDavid van Moolenbroek tt_int_op(wantexitcode, ==, exitcode);
484*e985b929SDavid van Moolenbroek }
485*e985b929SDavid van Moolenbroek end:
486*e985b929SDavid van Moolenbroek ;
487*e985b929SDavid van Moolenbroek }
488*e985b929SDavid van Moolenbroek
489*e985b929SDavid van Moolenbroek static void
errx_fn(void)490*e985b929SDavid van Moolenbroek errx_fn(void)
491*e985b929SDavid van Moolenbroek {
492*e985b929SDavid van Moolenbroek event_errx(2, "Fatal error; too many kumquats (%d)", 5);
493*e985b929SDavid van Moolenbroek }
494*e985b929SDavid van Moolenbroek
495*e985b929SDavid van Moolenbroek static void
err_fn(void)496*e985b929SDavid van Moolenbroek err_fn(void)
497*e985b929SDavid van Moolenbroek {
498*e985b929SDavid van Moolenbroek errno = ENOENT;
499*e985b929SDavid van Moolenbroek event_err(5,"Couldn't open %s", "/very/bad/file");
500*e985b929SDavid van Moolenbroek }
501*e985b929SDavid van Moolenbroek
502*e985b929SDavid van Moolenbroek static void
sock_err_fn(void)503*e985b929SDavid van Moolenbroek sock_err_fn(void)
504*e985b929SDavid van Moolenbroek {
505*e985b929SDavid van Moolenbroek evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0);
506*e985b929SDavid van Moolenbroek #ifdef WIN32
507*e985b929SDavid van Moolenbroek EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK);
508*e985b929SDavid van Moolenbroek #else
509*e985b929SDavid van Moolenbroek errno = EAGAIN;
510*e985b929SDavid van Moolenbroek #endif
511*e985b929SDavid van Moolenbroek event_sock_err(20, fd, "Unhappy socket");
512*e985b929SDavid van Moolenbroek }
513*e985b929SDavid van Moolenbroek #endif
514*e985b929SDavid van Moolenbroek
515*e985b929SDavid van Moolenbroek static void
test_evutil_log(void * ptr)516*e985b929SDavid van Moolenbroek test_evutil_log(void *ptr)
517*e985b929SDavid van Moolenbroek {
518*e985b929SDavid van Moolenbroek evutil_socket_t fd = -1;
519*e985b929SDavid van Moolenbroek char buf[128];
520*e985b929SDavid van Moolenbroek
521*e985b929SDavid van Moolenbroek event_set_log_callback(logfn);
522*e985b929SDavid van Moolenbroek event_set_fatal_callback(fatalfn);
523*e985b929SDavid van Moolenbroek #define RESET() do { \
524*e985b929SDavid van Moolenbroek logsev = 0; \
525*e985b929SDavid van Moolenbroek if (logmsg) free(logmsg); \
526*e985b929SDavid van Moolenbroek logmsg = NULL; \
527*e985b929SDavid van Moolenbroek } while (/*CONSTCOND*/0)
528*e985b929SDavid van Moolenbroek #define LOGEQ(sev,msg) do { \
529*e985b929SDavid van Moolenbroek tt_int_op(logsev,==,sev); \
530*e985b929SDavid van Moolenbroek tt_assert(logmsg != NULL); \
531*e985b929SDavid van Moolenbroek tt_str_op(logmsg,==,msg); \
532*e985b929SDavid van Moolenbroek } while (/*CONSTCOND*/0)
533*e985b929SDavid van Moolenbroek
534*e985b929SDavid van Moolenbroek #ifdef CAN_CHECK_ERR
535*e985b929SDavid van Moolenbroek /* We need to disable these tests for now. Previously, the logging
536*e985b929SDavid van Moolenbroek * module didn't enforce the requirement that a fatal callback
537*e985b929SDavid van Moolenbroek * actually exit. Now, it exits no matter what, so if we wan to
538*e985b929SDavid van Moolenbroek * reinstate these tests, we'll need to fork for each one. */
539*e985b929SDavid van Moolenbroek check_error_logging(errx_fn, 2, _EVENT_LOG_ERR,
540*e985b929SDavid van Moolenbroek "Fatal error; too many kumquats (5)");
541*e985b929SDavid van Moolenbroek RESET();
542*e985b929SDavid van Moolenbroek #endif
543*e985b929SDavid van Moolenbroek
544*e985b929SDavid van Moolenbroek event_warnx("Far too many %s (%d)", "wombats", 99);
545*e985b929SDavid van Moolenbroek LOGEQ(_EVENT_LOG_WARN, "Far too many wombats (99)");
546*e985b929SDavid van Moolenbroek RESET();
547*e985b929SDavid van Moolenbroek
548*e985b929SDavid van Moolenbroek event_msgx("Connecting lime to coconut");
549*e985b929SDavid van Moolenbroek LOGEQ(_EVENT_LOG_MSG, "Connecting lime to coconut");
550*e985b929SDavid van Moolenbroek RESET();
551*e985b929SDavid van Moolenbroek
552*e985b929SDavid van Moolenbroek event_debug(("A millisecond passed! We should log that!"));
553*e985b929SDavid van Moolenbroek #ifdef USE_DEBUG
554*e985b929SDavid van Moolenbroek LOGEQ(_EVENT_LOG_DEBUG, "A millisecond passed! We should log that!");
555*e985b929SDavid van Moolenbroek #else
556*e985b929SDavid van Moolenbroek tt_int_op(logsev,==,0);
557*e985b929SDavid van Moolenbroek tt_ptr_op(logmsg,==,NULL);
558*e985b929SDavid van Moolenbroek #endif
559*e985b929SDavid van Moolenbroek RESET();
560*e985b929SDavid van Moolenbroek
561*e985b929SDavid van Moolenbroek /* Try with an errno. */
562*e985b929SDavid van Moolenbroek errno = ENOENT;
563*e985b929SDavid van Moolenbroek event_warn("Couldn't open %s", "/bad/file");
564*e985b929SDavid van Moolenbroek evutil_snprintf(buf, sizeof(buf),
565*e985b929SDavid van Moolenbroek "Couldn't open /bad/file: %s",strerror(ENOENT));
566*e985b929SDavid van Moolenbroek LOGEQ(_EVENT_LOG_WARN,buf);
567*e985b929SDavid van Moolenbroek RESET();
568*e985b929SDavid van Moolenbroek
569*e985b929SDavid van Moolenbroek #ifdef CAN_CHECK_ERR
570*e985b929SDavid van Moolenbroek evutil_snprintf(buf, sizeof(buf),
571*e985b929SDavid van Moolenbroek "Couldn't open /very/bad/file: %s",strerror(ENOENT));
572*e985b929SDavid van Moolenbroek check_error_logging(err_fn, 5, _EVENT_LOG_ERR, buf);
573*e985b929SDavid van Moolenbroek RESET();
574*e985b929SDavid van Moolenbroek #endif
575*e985b929SDavid van Moolenbroek
576*e985b929SDavid van Moolenbroek /* Try with a socket errno. */
577*e985b929SDavid van Moolenbroek fd = socket(AF_INET, SOCK_STREAM, 0);
578*e985b929SDavid van Moolenbroek #ifdef WIN32
579*e985b929SDavid van Moolenbroek evutil_snprintf(buf, sizeof(buf),
580*e985b929SDavid van Moolenbroek "Unhappy socket: %s",
581*e985b929SDavid van Moolenbroek evutil_socket_error_to_string(WSAEWOULDBLOCK));
582*e985b929SDavid van Moolenbroek EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK);
583*e985b929SDavid van Moolenbroek #else
584*e985b929SDavid van Moolenbroek evutil_snprintf(buf, sizeof(buf),
585*e985b929SDavid van Moolenbroek "Unhappy socket: %s", strerror(EAGAIN));
586*e985b929SDavid van Moolenbroek errno = EAGAIN;
587*e985b929SDavid van Moolenbroek #endif
588*e985b929SDavid van Moolenbroek event_sock_warn(fd, "Unhappy socket");
589*e985b929SDavid van Moolenbroek LOGEQ(_EVENT_LOG_WARN, buf);
590*e985b929SDavid van Moolenbroek RESET();
591*e985b929SDavid van Moolenbroek
592*e985b929SDavid van Moolenbroek #ifdef CAN_CHECK_ERR
593*e985b929SDavid van Moolenbroek check_error_logging(sock_err_fn, 20, _EVENT_LOG_ERR, buf);
594*e985b929SDavid van Moolenbroek RESET();
595*e985b929SDavid van Moolenbroek #endif
596*e985b929SDavid van Moolenbroek
597*e985b929SDavid van Moolenbroek #undef RESET
598*e985b929SDavid van Moolenbroek #undef LOGEQ
599*e985b929SDavid van Moolenbroek end:
600*e985b929SDavid van Moolenbroek if (logmsg)
601*e985b929SDavid van Moolenbroek free(logmsg);
602*e985b929SDavid van Moolenbroek if (fd >= 0)
603*e985b929SDavid van Moolenbroek evutil_closesocket(fd);
604*e985b929SDavid van Moolenbroek }
605*e985b929SDavid van Moolenbroek
606*e985b929SDavid van Moolenbroek static void
test_evutil_strlcpy(void * arg)607*e985b929SDavid van Moolenbroek test_evutil_strlcpy(void *arg)
608*e985b929SDavid van Moolenbroek {
609*e985b929SDavid van Moolenbroek char buf[8];
610*e985b929SDavid van Moolenbroek
611*e985b929SDavid van Moolenbroek /* Successful case. */
612*e985b929SDavid van Moolenbroek tt_int_op(5, ==, strlcpy(buf, "Hello", sizeof(buf)));
613*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "Hello");
614*e985b929SDavid van Moolenbroek
615*e985b929SDavid van Moolenbroek /* Overflow by a lot. */
616*e985b929SDavid van Moolenbroek tt_int_op(13, ==, strlcpy(buf, "pentasyllabic", sizeof(buf)));
617*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "pentasy");
618*e985b929SDavid van Moolenbroek
619*e985b929SDavid van Moolenbroek /* Overflow by exactly one. */
620*e985b929SDavid van Moolenbroek tt_int_op(8, ==, strlcpy(buf, "overlong", sizeof(buf)));
621*e985b929SDavid van Moolenbroek tt_str_op(buf, ==, "overlon");
622*e985b929SDavid van Moolenbroek end:
623*e985b929SDavid van Moolenbroek ;
624*e985b929SDavid van Moolenbroek }
625*e985b929SDavid van Moolenbroek
626*e985b929SDavid van Moolenbroek struct example_struct {
627*e985b929SDavid van Moolenbroek const char *a;
628*e985b929SDavid van Moolenbroek const char *b;
629*e985b929SDavid van Moolenbroek long c;
630*e985b929SDavid van Moolenbroek };
631*e985b929SDavid van Moolenbroek
632*e985b929SDavid van Moolenbroek static void
test_evutil_upcast(void * arg)633*e985b929SDavid van Moolenbroek test_evutil_upcast(void *arg)
634*e985b929SDavid van Moolenbroek {
635*e985b929SDavid van Moolenbroek struct example_struct es1;
636*e985b929SDavid van Moolenbroek const char **cp;
637*e985b929SDavid van Moolenbroek es1.a = "World";
638*e985b929SDavid van Moolenbroek es1.b = "Hello";
639*e985b929SDavid van Moolenbroek es1.c = -99;
640*e985b929SDavid van Moolenbroek
641*e985b929SDavid van Moolenbroek tt_int_op(evutil_offsetof(struct example_struct, b), ==, sizeof(char*));
642*e985b929SDavid van Moolenbroek
643*e985b929SDavid van Moolenbroek cp = &es1.b;
644*e985b929SDavid van Moolenbroek tt_ptr_op(EVUTIL_UPCAST(cp, struct example_struct, b), ==, &es1);
645*e985b929SDavid van Moolenbroek
646*e985b929SDavid van Moolenbroek end:
647*e985b929SDavid van Moolenbroek ;
648*e985b929SDavid van Moolenbroek }
649*e985b929SDavid van Moolenbroek
650*e985b929SDavid van Moolenbroek static void
test_evutil_integers(void * arg)651*e985b929SDavid van Moolenbroek test_evutil_integers(void *arg)
652*e985b929SDavid van Moolenbroek {
653*e985b929SDavid van Moolenbroek ev_int64_t i64;
654*e985b929SDavid van Moolenbroek ev_uint64_t u64;
655*e985b929SDavid van Moolenbroek ev_int32_t i32;
656*e985b929SDavid van Moolenbroek ev_uint32_t u32;
657*e985b929SDavid van Moolenbroek ev_int16_t i16;
658*e985b929SDavid van Moolenbroek ev_uint16_t u16;
659*e985b929SDavid van Moolenbroek ev_int8_t i8;
660*e985b929SDavid van Moolenbroek ev_uint8_t u8;
661*e985b929SDavid van Moolenbroek
662*e985b929SDavid van Moolenbroek void *ptr;
663*e985b929SDavid van Moolenbroek ev_intptr_t iptr;
664*e985b929SDavid van Moolenbroek ev_uintptr_t uptr;
665*e985b929SDavid van Moolenbroek
666*e985b929SDavid van Moolenbroek ev_ssize_t ssize;
667*e985b929SDavid van Moolenbroek
668*e985b929SDavid van Moolenbroek tt_int_op(sizeof(u64), ==, 8);
669*e985b929SDavid van Moolenbroek tt_int_op(sizeof(i64), ==, 8);
670*e985b929SDavid van Moolenbroek tt_int_op(sizeof(u32), ==, 4);
671*e985b929SDavid van Moolenbroek tt_int_op(sizeof(i32), ==, 4);
672*e985b929SDavid van Moolenbroek tt_int_op(sizeof(u16), ==, 2);
673*e985b929SDavid van Moolenbroek tt_int_op(sizeof(i16), ==, 2);
674*e985b929SDavid van Moolenbroek tt_int_op(sizeof(u8), ==, 1);
675*e985b929SDavid van Moolenbroek tt_int_op(sizeof(i8), ==, 1);
676*e985b929SDavid van Moolenbroek
677*e985b929SDavid van Moolenbroek tt_int_op(sizeof(ev_ssize_t), ==, sizeof(size_t));
678*e985b929SDavid van Moolenbroek tt_int_op(sizeof(ev_intptr_t), >=, sizeof(void *));
679*e985b929SDavid van Moolenbroek tt_int_op(sizeof(ev_uintptr_t), ==, sizeof(intptr_t));
680*e985b929SDavid van Moolenbroek
681*e985b929SDavid van Moolenbroek u64 = 1000000000;
682*e985b929SDavid van Moolenbroek u64 *= 1000000000;
683*e985b929SDavid van Moolenbroek tt_assert(u64 / 1000000000 == 1000000000);
684*e985b929SDavid van Moolenbroek i64 = -1000000000;
685*e985b929SDavid van Moolenbroek i64 *= 1000000000;
686*e985b929SDavid van Moolenbroek tt_assert(i64 / 1000000000 == -1000000000);
687*e985b929SDavid van Moolenbroek
688*e985b929SDavid van Moolenbroek u64 = EV_UINT64_MAX;
689*e985b929SDavid van Moolenbroek i64 = EV_INT64_MAX;
690*e985b929SDavid van Moolenbroek tt_assert(u64 > 0);
691*e985b929SDavid van Moolenbroek tt_assert(i64 > 0);
692*e985b929SDavid van Moolenbroek u64++;
693*e985b929SDavid van Moolenbroek i64++;
694*e985b929SDavid van Moolenbroek tt_assert(u64 == 0);
695*e985b929SDavid van Moolenbroek tt_assert(i64 == EV_INT64_MIN);
696*e985b929SDavid van Moolenbroek tt_assert(i64 < 0);
697*e985b929SDavid van Moolenbroek
698*e985b929SDavid van Moolenbroek u32 = EV_UINT32_MAX;
699*e985b929SDavid van Moolenbroek i32 = EV_INT32_MAX;
700*e985b929SDavid van Moolenbroek tt_assert(u32 > 0);
701*e985b929SDavid van Moolenbroek tt_assert(i32 > 0);
702*e985b929SDavid van Moolenbroek u32++;
703*e985b929SDavid van Moolenbroek i32++;
704*e985b929SDavid van Moolenbroek tt_assert(u32 == 0);
705*e985b929SDavid van Moolenbroek tt_assert(i32 == EV_INT32_MIN);
706*e985b929SDavid van Moolenbroek tt_assert(i32 < 0);
707*e985b929SDavid van Moolenbroek
708*e985b929SDavid van Moolenbroek u16 = EV_UINT16_MAX;
709*e985b929SDavid van Moolenbroek i16 = EV_INT16_MAX;
710*e985b929SDavid van Moolenbroek tt_assert(u16 > 0);
711*e985b929SDavid van Moolenbroek tt_assert(i16 > 0);
712*e985b929SDavid van Moolenbroek u16++;
713*e985b929SDavid van Moolenbroek i16++;
714*e985b929SDavid van Moolenbroek tt_assert(u16 == 0);
715*e985b929SDavid van Moolenbroek tt_assert(i16 == EV_INT16_MIN);
716*e985b929SDavid van Moolenbroek tt_assert(i16 < 0);
717*e985b929SDavid van Moolenbroek
718*e985b929SDavid van Moolenbroek u8 = EV_UINT8_MAX;
719*e985b929SDavid van Moolenbroek i8 = EV_INT8_MAX;
720*e985b929SDavid van Moolenbroek tt_assert(u8 > 0);
721*e985b929SDavid van Moolenbroek tt_assert(i8 > 0);
722*e985b929SDavid van Moolenbroek u8++;
723*e985b929SDavid van Moolenbroek i8++;
724*e985b929SDavid van Moolenbroek tt_assert(u8 == 0);
725*e985b929SDavid van Moolenbroek tt_assert(i8 == EV_INT8_MIN);
726*e985b929SDavid van Moolenbroek tt_assert(i8 < 0);
727*e985b929SDavid van Moolenbroek
728*e985b929SDavid van Moolenbroek ssize = EV_SSIZE_MAX;
729*e985b929SDavid van Moolenbroek tt_assert(ssize > 0);
730*e985b929SDavid van Moolenbroek ssize++;
731*e985b929SDavid van Moolenbroek tt_assert(ssize < 0);
732*e985b929SDavid van Moolenbroek tt_assert(ssize == EV_SSIZE_MIN);
733*e985b929SDavid van Moolenbroek
734*e985b929SDavid van Moolenbroek ptr = &ssize;
735*e985b929SDavid van Moolenbroek iptr = (ev_intptr_t)ptr;
736*e985b929SDavid van Moolenbroek uptr = (ev_uintptr_t)ptr;
737*e985b929SDavid van Moolenbroek ptr = (void *)iptr;
738*e985b929SDavid van Moolenbroek tt_assert(ptr == &ssize);
739*e985b929SDavid van Moolenbroek ptr = (void *)uptr;
740*e985b929SDavid van Moolenbroek tt_assert(ptr == &ssize);
741*e985b929SDavid van Moolenbroek
742*e985b929SDavid van Moolenbroek iptr = -1;
743*e985b929SDavid van Moolenbroek tt_assert(iptr < 0);
744*e985b929SDavid van Moolenbroek end:
745*e985b929SDavid van Moolenbroek ;
746*e985b929SDavid van Moolenbroek }
747*e985b929SDavid van Moolenbroek
748*e985b929SDavid van Moolenbroek struct evutil_addrinfo *
ai_find_by_family(struct evutil_addrinfo * ai,int family)749*e985b929SDavid van Moolenbroek ai_find_by_family(struct evutil_addrinfo *ai, int family)
750*e985b929SDavid van Moolenbroek {
751*e985b929SDavid van Moolenbroek while (ai) {
752*e985b929SDavid van Moolenbroek if (ai->ai_family == family)
753*e985b929SDavid van Moolenbroek return ai;
754*e985b929SDavid van Moolenbroek ai = ai->ai_next;
755*e985b929SDavid van Moolenbroek }
756*e985b929SDavid van Moolenbroek return NULL;
757*e985b929SDavid van Moolenbroek }
758*e985b929SDavid van Moolenbroek
759*e985b929SDavid van Moolenbroek struct evutil_addrinfo *
ai_find_by_protocol(struct evutil_addrinfo * ai,int protocol)760*e985b929SDavid van Moolenbroek ai_find_by_protocol(struct evutil_addrinfo *ai, int protocol)
761*e985b929SDavid van Moolenbroek {
762*e985b929SDavid van Moolenbroek while (ai) {
763*e985b929SDavid van Moolenbroek if (ai->ai_protocol == protocol)
764*e985b929SDavid van Moolenbroek return ai;
765*e985b929SDavid van Moolenbroek ai = ai->ai_next;
766*e985b929SDavid van Moolenbroek }
767*e985b929SDavid van Moolenbroek return NULL;
768*e985b929SDavid van Moolenbroek }
769*e985b929SDavid van Moolenbroek
770*e985b929SDavid van Moolenbroek
771*e985b929SDavid van Moolenbroek int
_test_ai_eq(const struct evutil_addrinfo * ai,const char * sockaddr_port,int socktype,int protocol,int line)772*e985b929SDavid van Moolenbroek _test_ai_eq(const struct evutil_addrinfo *ai, const char *sockaddr_port,
773*e985b929SDavid van Moolenbroek int socktype, int protocol, int line)
774*e985b929SDavid van Moolenbroek {
775*e985b929SDavid van Moolenbroek struct sockaddr_storage ss;
776*e985b929SDavid van Moolenbroek int slen = sizeof(ss);
777*e985b929SDavid van Moolenbroek int gotport;
778*e985b929SDavid van Moolenbroek char buf[128];
779*e985b929SDavid van Moolenbroek memset(&ss, 0, sizeof(ss));
780*e985b929SDavid van Moolenbroek if (socktype > 0)
781*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_socktype, ==, socktype);
782*e985b929SDavid van Moolenbroek if (protocol > 0)
783*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_protocol, ==, protocol);
784*e985b929SDavid van Moolenbroek
785*e985b929SDavid van Moolenbroek if (evutil_parse_sockaddr_port(
786*e985b929SDavid van Moolenbroek sockaddr_port, (struct sockaddr*)&ss, &slen)<0) {
787*e985b929SDavid van Moolenbroek TT_FAIL(("Couldn't parse expected address %s on line %d",
788*e985b929SDavid van Moolenbroek sockaddr_port, line));
789*e985b929SDavid van Moolenbroek return -1;
790*e985b929SDavid van Moolenbroek }
791*e985b929SDavid van Moolenbroek if (ai->ai_family != ss.ss_family) {
792*e985b929SDavid van Moolenbroek TT_FAIL(("Address family %d did not match %d on line %d",
793*e985b929SDavid van Moolenbroek ai->ai_family, ss.ss_family, line));
794*e985b929SDavid van Moolenbroek return -1;
795*e985b929SDavid van Moolenbroek }
796*e985b929SDavid van Moolenbroek if (ai->ai_addr->sa_family == AF_INET) {
797*e985b929SDavid van Moolenbroek struct sockaddr_in *sin = (struct sockaddr_in*)ai->ai_addr;
798*e985b929SDavid van Moolenbroek evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
799*e985b929SDavid van Moolenbroek gotport = ntohs(sin->sin_port);
800*e985b929SDavid van Moolenbroek if (ai->ai_addrlen != sizeof(struct sockaddr_in)) {
801*e985b929SDavid van Moolenbroek TT_FAIL(("Addr size mismatch on line %d", line));
802*e985b929SDavid van Moolenbroek return -1;
803*e985b929SDavid van Moolenbroek }
804*e985b929SDavid van Moolenbroek } else {
805*e985b929SDavid van Moolenbroek struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ai->ai_addr;
806*e985b929SDavid van Moolenbroek evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf));
807*e985b929SDavid van Moolenbroek gotport = ntohs(sin6->sin6_port);
808*e985b929SDavid van Moolenbroek if (ai->ai_addrlen != sizeof(struct sockaddr_in6)) {
809*e985b929SDavid van Moolenbroek TT_FAIL(("Addr size mismatch on line %d", line));
810*e985b929SDavid van Moolenbroek return -1;
811*e985b929SDavid van Moolenbroek }
812*e985b929SDavid van Moolenbroek }
813*e985b929SDavid van Moolenbroek if (evutil_sockaddr_cmp(ai->ai_addr, (struct sockaddr*)&ss, 1)) {
814*e985b929SDavid van Moolenbroek TT_FAIL(("Wanted %s, got %s:%d on line %d", sockaddr_port,
815*e985b929SDavid van Moolenbroek buf, gotport, line));
816*e985b929SDavid van Moolenbroek return -1;
817*e985b929SDavid van Moolenbroek } else {
818*e985b929SDavid van Moolenbroek TT_BLATHER(("Wanted %s, got %s:%d on line %d", sockaddr_port,
819*e985b929SDavid van Moolenbroek buf, gotport, line));
820*e985b929SDavid van Moolenbroek }
821*e985b929SDavid van Moolenbroek return 0;
822*e985b929SDavid van Moolenbroek end:
823*e985b929SDavid van Moolenbroek TT_FAIL(("Test failed on line %d", line));
824*e985b929SDavid van Moolenbroek return -1;
825*e985b929SDavid van Moolenbroek }
826*e985b929SDavid van Moolenbroek
827*e985b929SDavid van Moolenbroek static void
test_evutil_rand(void * arg)828*e985b929SDavid van Moolenbroek test_evutil_rand(void *arg)
829*e985b929SDavid van Moolenbroek {
830*e985b929SDavid van Moolenbroek char buf1[32];
831*e985b929SDavid van Moolenbroek char buf2[32];
832*e985b929SDavid van Moolenbroek int counts[256];
833*e985b929SDavid van Moolenbroek int i, j, k, n=0;
834*e985b929SDavid van Moolenbroek
835*e985b929SDavid van Moolenbroek memset(buf2, 0, sizeof(buf2));
836*e985b929SDavid van Moolenbroek memset(counts, 0, sizeof(counts));
837*e985b929SDavid van Moolenbroek
838*e985b929SDavid van Moolenbroek for (k=0;k<32;++k) {
839*e985b929SDavid van Moolenbroek /* Try a few different start and end points; try to catch
840*e985b929SDavid van Moolenbroek * the various misaligned cases of arc4random_buf */
841*e985b929SDavid van Moolenbroek int startpoint = _evutil_weakrand() % 4;
842*e985b929SDavid van Moolenbroek int endpoint = 32 - (_evutil_weakrand() % 4);
843*e985b929SDavid van Moolenbroek
844*e985b929SDavid van Moolenbroek memset(buf2, 0, sizeof(buf2));
845*e985b929SDavid van Moolenbroek
846*e985b929SDavid van Moolenbroek /* Do 6 runs over buf1, or-ing the result into buf2 each
847*e985b929SDavid van Moolenbroek * time, to make sure we're setting each byte that we mean
848*e985b929SDavid van Moolenbroek * to set. */
849*e985b929SDavid van Moolenbroek for (i=0;i<8;++i) {
850*e985b929SDavid van Moolenbroek memset(buf1, 0, sizeof(buf1));
851*e985b929SDavid van Moolenbroek evutil_secure_rng_get_bytes(buf1 + startpoint,
852*e985b929SDavid van Moolenbroek endpoint-startpoint);
853*e985b929SDavid van Moolenbroek n += endpoint - startpoint;
854*e985b929SDavid van Moolenbroek for (j=0; j<32; ++j) {
855*e985b929SDavid van Moolenbroek if (j >= startpoint && j < endpoint) {
856*e985b929SDavid van Moolenbroek buf2[j] |= buf1[j];
857*e985b929SDavid van Moolenbroek ++counts[(unsigned char)buf1[j]];
858*e985b929SDavid van Moolenbroek } else {
859*e985b929SDavid van Moolenbroek tt_assert(buf1[j] == 0);
860*e985b929SDavid van Moolenbroek tt_int_op(buf1[j], ==, 0);
861*e985b929SDavid van Moolenbroek
862*e985b929SDavid van Moolenbroek }
863*e985b929SDavid van Moolenbroek }
864*e985b929SDavid van Moolenbroek }
865*e985b929SDavid van Moolenbroek
866*e985b929SDavid van Moolenbroek /* This will give a false positive with P=(256**8)==(2**64)
867*e985b929SDavid van Moolenbroek * for each character. */
868*e985b929SDavid van Moolenbroek for (j=startpoint;j<endpoint;++j) {
869*e985b929SDavid van Moolenbroek tt_int_op(buf2[j], !=, 0);
870*e985b929SDavid van Moolenbroek }
871*e985b929SDavid van Moolenbroek }
872*e985b929SDavid van Moolenbroek
873*e985b929SDavid van Moolenbroek /* for (i=0;i<256;++i) { printf("%3d %2d\n", i, counts[i]); } */
874*e985b929SDavid van Moolenbroek end:
875*e985b929SDavid van Moolenbroek ;
876*e985b929SDavid van Moolenbroek }
877*e985b929SDavid van Moolenbroek
878*e985b929SDavid van Moolenbroek static void
test_evutil_getaddrinfo(void * arg)879*e985b929SDavid van Moolenbroek test_evutil_getaddrinfo(void *arg)
880*e985b929SDavid van Moolenbroek {
881*e985b929SDavid van Moolenbroek struct evutil_addrinfo *ai = NULL, *a;
882*e985b929SDavid van Moolenbroek struct evutil_addrinfo hints;
883*e985b929SDavid van Moolenbroek
884*e985b929SDavid van Moolenbroek struct sockaddr_in6 *sin6;
885*e985b929SDavid van Moolenbroek struct sockaddr_in *sin;
886*e985b929SDavid van Moolenbroek char buf[128];
887*e985b929SDavid van Moolenbroek const char *cp;
888*e985b929SDavid van Moolenbroek int r;
889*e985b929SDavid van Moolenbroek
890*e985b929SDavid van Moolenbroek /* Try using it as a pton. */
891*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
892*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
893*e985b929SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
894*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("1.2.3.4", "8080", &hints, &ai);
895*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 0);
896*e985b929SDavid van Moolenbroek tt_assert(ai);
897*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */
898*e985b929SDavid van Moolenbroek test_ai_eq(ai, "1.2.3.4:8080", SOCK_STREAM, IPPROTO_TCP);
899*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
900*e985b929SDavid van Moolenbroek ai = NULL;
901*e985b929SDavid van Moolenbroek
902*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
903*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
904*e985b929SDavid van Moolenbroek hints.ai_protocol = IPPROTO_UDP;
905*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("1001:b0b::f00f", "4321", &hints, &ai);
906*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 0);
907*e985b929SDavid van Moolenbroek tt_assert(ai);
908*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */
909*e985b929SDavid van Moolenbroek test_ai_eq(ai, "[1001:b0b::f00f]:4321", SOCK_DGRAM, IPPROTO_UDP);
910*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
911*e985b929SDavid van Moolenbroek ai = NULL;
912*e985b929SDavid van Moolenbroek
913*e985b929SDavid van Moolenbroek /* Try out the behavior of nodename=NULL */
914*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
915*e985b929SDavid van Moolenbroek hints.ai_family = PF_INET;
916*e985b929SDavid van Moolenbroek hints.ai_protocol = IPPROTO_TCP;
917*e985b929SDavid van Moolenbroek hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind */
918*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo(NULL, "9999", &hints, &ai);
919*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
920*e985b929SDavid van Moolenbroek tt_assert(ai);
921*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL);
922*e985b929SDavid van Moolenbroek test_ai_eq(ai, "0.0.0.0:9999", SOCK_STREAM, IPPROTO_TCP);
923*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
924*e985b929SDavid van Moolenbroek ai = NULL;
925*e985b929SDavid van Moolenbroek hints.ai_flags = 0; /* as if for connect */
926*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo(NULL, "9998", &hints, &ai);
927*e985b929SDavid van Moolenbroek tt_assert(ai);
928*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
929*e985b929SDavid van Moolenbroek test_ai_eq(ai, "127.0.0.1:9998", SOCK_STREAM, IPPROTO_TCP);
930*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL);
931*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
932*e985b929SDavid van Moolenbroek ai = NULL;
933*e985b929SDavid van Moolenbroek
934*e985b929SDavid van Moolenbroek hints.ai_flags = 0; /* as if for connect */
935*e985b929SDavid van Moolenbroek hints.ai_family = PF_INET6;
936*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo(NULL, "9997", &hints, &ai);
937*e985b929SDavid van Moolenbroek tt_assert(ai);
938*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
939*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL);
940*e985b929SDavid van Moolenbroek test_ai_eq(ai, "[::1]:9997", SOCK_STREAM, IPPROTO_TCP);
941*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
942*e985b929SDavid van Moolenbroek ai = NULL;
943*e985b929SDavid van Moolenbroek
944*e985b929SDavid van Moolenbroek hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind. */
945*e985b929SDavid van Moolenbroek hints.ai_family = PF_INET6;
946*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo(NULL, "9996", &hints, &ai);
947*e985b929SDavid van Moolenbroek tt_assert(ai);
948*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
949*e985b929SDavid van Moolenbroek tt_ptr_op(ai->ai_next, ==, NULL);
950*e985b929SDavid van Moolenbroek test_ai_eq(ai, "[::]:9996", SOCK_STREAM, IPPROTO_TCP);
951*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
952*e985b929SDavid van Moolenbroek ai = NULL;
953*e985b929SDavid van Moolenbroek
954*e985b929SDavid van Moolenbroek /* Now try an unspec one. We should get a v6 and a v4. */
955*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
956*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo(NULL, "9996", &hints, &ai);
957*e985b929SDavid van Moolenbroek tt_assert(ai);
958*e985b929SDavid van Moolenbroek tt_int_op(r,==,0);
959*e985b929SDavid van Moolenbroek a = ai_find_by_family(ai, PF_INET6);
960*e985b929SDavid van Moolenbroek tt_assert(a);
961*e985b929SDavid van Moolenbroek test_ai_eq(a, "[::]:9996", SOCK_STREAM, IPPROTO_TCP);
962*e985b929SDavid van Moolenbroek a = ai_find_by_family(ai, PF_INET);
963*e985b929SDavid van Moolenbroek tt_assert(a);
964*e985b929SDavid van Moolenbroek test_ai_eq(a, "0.0.0.0:9996", SOCK_STREAM, IPPROTO_TCP);
965*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
966*e985b929SDavid van Moolenbroek ai = NULL;
967*e985b929SDavid van Moolenbroek
968*e985b929SDavid van Moolenbroek /* Try out AI_NUMERICHOST: successful case. Also try
969*e985b929SDavid van Moolenbroek * multiprotocol. */
970*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
971*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
972*e985b929SDavid van Moolenbroek hints.ai_flags = EVUTIL_AI_NUMERICHOST;
973*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("1.2.3.4", NULL, &hints, &ai);
974*e985b929SDavid van Moolenbroek tt_int_op(r, ==, 0);
975*e985b929SDavid van Moolenbroek a = ai_find_by_protocol(ai, IPPROTO_TCP);
976*e985b929SDavid van Moolenbroek tt_assert(a);
977*e985b929SDavid van Moolenbroek test_ai_eq(a, "1.2.3.4", SOCK_STREAM, IPPROTO_TCP);
978*e985b929SDavid van Moolenbroek a = ai_find_by_protocol(ai, IPPROTO_UDP);
979*e985b929SDavid van Moolenbroek tt_assert(a);
980*e985b929SDavid van Moolenbroek test_ai_eq(a, "1.2.3.4", SOCK_DGRAM, IPPROTO_UDP);
981*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
982*e985b929SDavid van Moolenbroek ai = NULL;
983*e985b929SDavid van Moolenbroek
984*e985b929SDavid van Moolenbroek /* Try the failing case of AI_NUMERICHOST */
985*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
986*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
987*e985b929SDavid van Moolenbroek hints.ai_flags = EVUTIL_AI_NUMERICHOST;
988*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai);
989*e985b929SDavid van Moolenbroek tt_int_op(r, ==, EVUTIL_EAI_NONAME);
990*e985b929SDavid van Moolenbroek tt_ptr_op(ai, ==, NULL);
991*e985b929SDavid van Moolenbroek
992*e985b929SDavid van Moolenbroek /* Try symbolic service names wit AI_NUMERICSERV */
993*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
994*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
995*e985b929SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
996*e985b929SDavid van Moolenbroek hints.ai_flags = EVUTIL_AI_NUMERICSERV;
997*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai);
998*e985b929SDavid van Moolenbroek tt_int_op(r,==,EVUTIL_EAI_NONAME);
999*e985b929SDavid van Moolenbroek
1000*e985b929SDavid van Moolenbroek /* Try symbolic service names */
1001*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
1002*e985b929SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
1003*e985b929SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
1004*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai);
1005*e985b929SDavid van Moolenbroek if (r!=0) {
1006*e985b929SDavid van Moolenbroek TT_DECLARE("SKIP", ("Symbolic service names seem broken."));
1007*e985b929SDavid van Moolenbroek } else {
1008*e985b929SDavid van Moolenbroek tt_assert(ai);
1009*e985b929SDavid van Moolenbroek test_ai_eq(ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP);
1010*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
1011*e985b929SDavid van Moolenbroek ai = NULL;
1012*e985b929SDavid van Moolenbroek }
1013*e985b929SDavid van Moolenbroek
1014*e985b929SDavid van Moolenbroek /* Now do some actual lookups. */
1015*e985b929SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
1016*e985b929SDavid van Moolenbroek hints.ai_family = PF_INET;
1017*e985b929SDavid van Moolenbroek hints.ai_protocol = IPPROTO_TCP;
1018*e985b929SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
1019*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai);
1020*e985b929SDavid van Moolenbroek if (r != 0) {
1021*e985b929SDavid van Moolenbroek TT_DECLARE("SKIP", ("Couldn't resolve www.google.com"));
1022*e985b929SDavid van Moolenbroek } else {
1023*e985b929SDavid van Moolenbroek tt_assert(ai);
1024*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_family, ==, PF_INET);
1025*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_protocol, ==, IPPROTO_TCP);
1026*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_socktype, ==, SOCK_STREAM);
1027*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in));
1028*e985b929SDavid van Moolenbroek sin = (struct sockaddr_in*)ai->ai_addr;
1029*e985b929SDavid van Moolenbroek tt_int_op(sin->sin_family, ==, AF_INET);
1030*e985b929SDavid van Moolenbroek tt_int_op(sin->sin_port, ==, htons(80));
1031*e985b929SDavid van Moolenbroek tt_int_op(sin->sin_addr.s_addr, !=, 0xffffffff);
1032*e985b929SDavid van Moolenbroek
1033*e985b929SDavid van Moolenbroek cp = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
1034*e985b929SDavid van Moolenbroek TT_BLATHER(("www.google.com resolved to %s",
1035*e985b929SDavid van Moolenbroek cp?cp:"<unwriteable>"));
1036*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
1037*e985b929SDavid van Moolenbroek ai = NULL;
1038*e985b929SDavid van Moolenbroek }
1039*e985b929SDavid van Moolenbroek
1040*e985b929SDavid van Moolenbroek hints.ai_family = PF_INET6;
1041*e985b929SDavid van Moolenbroek r = evutil_getaddrinfo("ipv6.google.com", "80", &hints, &ai);
1042*e985b929SDavid van Moolenbroek if (r != 0) {
1043*e985b929SDavid van Moolenbroek TT_BLATHER(("Couldn't do an ipv6 lookup for ipv6.google.com"));
1044*e985b929SDavid van Moolenbroek } else {
1045*e985b929SDavid van Moolenbroek tt_assert(ai);
1046*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_family, ==, PF_INET6);
1047*e985b929SDavid van Moolenbroek tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in6));
1048*e985b929SDavid van Moolenbroek sin6 = (struct sockaddr_in6*)ai->ai_addr;
1049*e985b929SDavid van Moolenbroek tt_int_op(sin6->sin6_port, ==, htons(80));
1050*e985b929SDavid van Moolenbroek
1051*e985b929SDavid van Moolenbroek cp = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
1052*e985b929SDavid van Moolenbroek sizeof(buf));
1053*e985b929SDavid van Moolenbroek TT_BLATHER(("ipv6.google.com resolved to %s",
1054*e985b929SDavid van Moolenbroek cp?cp:"<unwriteable>"));
1055*e985b929SDavid van Moolenbroek }
1056*e985b929SDavid van Moolenbroek
1057*e985b929SDavid van Moolenbroek end:
1058*e985b929SDavid van Moolenbroek if (ai)
1059*e985b929SDavid van Moolenbroek evutil_freeaddrinfo(ai);
1060*e985b929SDavid van Moolenbroek }
1061*e985b929SDavid van Moolenbroek
1062*e985b929SDavid van Moolenbroek #ifdef WIN32
1063*e985b929SDavid van Moolenbroek static void
test_evutil_loadsyslib(void * arg)1064*e985b929SDavid van Moolenbroek test_evutil_loadsyslib(void *arg)
1065*e985b929SDavid van Moolenbroek {
1066*e985b929SDavid van Moolenbroek HANDLE h=NULL;
1067*e985b929SDavid van Moolenbroek
1068*e985b929SDavid van Moolenbroek h = evutil_load_windows_system_library(TEXT("kernel32.dll"));
1069*e985b929SDavid van Moolenbroek tt_assert(h);
1070*e985b929SDavid van Moolenbroek
1071*e985b929SDavid van Moolenbroek end:
1072*e985b929SDavid van Moolenbroek if (h)
1073*e985b929SDavid van Moolenbroek CloseHandle(h);
1074*e985b929SDavid van Moolenbroek
1075*e985b929SDavid van Moolenbroek }
1076*e985b929SDavid van Moolenbroek #endif
1077*e985b929SDavid van Moolenbroek
1078*e985b929SDavid van Moolenbroek struct testcase_t util_testcases[] = {
1079*e985b929SDavid van Moolenbroek { "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
1080*e985b929SDavid van Moolenbroek { "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
1081*e985b929SDavid van Moolenbroek { "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
1082*e985b929SDavid van Moolenbroek { "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL },
1083*e985b929SDavid van Moolenbroek { "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
1084*e985b929SDavid van Moolenbroek { "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL },
1085*e985b929SDavid van Moolenbroek { "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL },
1086*e985b929SDavid van Moolenbroek { "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL },
1087*e985b929SDavid van Moolenbroek { "strlcpy", test_evutil_strlcpy, 0, NULL, NULL },
1088*e985b929SDavid van Moolenbroek { "log", test_evutil_log, TT_FORK, NULL, NULL },
1089*e985b929SDavid van Moolenbroek { "upcast", test_evutil_upcast, 0, NULL, NULL },
1090*e985b929SDavid van Moolenbroek { "integers", test_evutil_integers, 0, NULL, NULL },
1091*e985b929SDavid van Moolenbroek { "rand", test_evutil_rand, TT_FORK, NULL, NULL },
1092*e985b929SDavid van Moolenbroek { "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
1093*e985b929SDavid van Moolenbroek #ifdef WIN32
1094*e985b929SDavid van Moolenbroek { "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
1095*e985b929SDavid van Moolenbroek #endif
1096*e985b929SDavid van Moolenbroek END_OF_TESTCASES,
1097*e985b929SDavid van Moolenbroek };
1098*e985b929SDavid van Moolenbroek
1099