1168754Sbushman/*-
2168754Sbushman * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3251867Seadler * All rights reserved.
4168754Sbushman *
5168754Sbushman * Redistribution and use in source and binary forms, with or without
6168754Sbushman * modification, are permitted provided that the following conditions
7168754Sbushman * are met:
8168754Sbushman * 1. Redistributions of source code must retain the above copyright
9168754Sbushman *    notice, this list of conditions and the following disclaimer.
10168754Sbushman * 2. Redistributions in binary form must reproduce the above copyright
11168754Sbushman *    notice, this list of conditions and the following disclaimer in the
12168754Sbushman *    documentation and/or other materials provided with the distribution.
13168754Sbushman *
14168754Sbushman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15168754Sbushman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16168754Sbushman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17168754Sbushman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18168754Sbushman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19168754Sbushman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20168754Sbushman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21168754Sbushman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22168754Sbushman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23168754Sbushman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24168754Sbushman * SUCH DAMAGE.
25168754Sbushman *
26168754Sbushman */
27168754Sbushman
28168754Sbushman#include <sys/cdefs.h>
29168754Sbushman__FBSDID("$FreeBSD$");
30168754Sbushman
31168754Sbushman#include <arpa/inet.h>
32168754Sbushman#include <sys/socket.h>
33168754Sbushman#include <sys/types.h>
34168754Sbushman#include <netinet/in.h>
35168754Sbushman#include <assert.h>
36168754Sbushman#include <errno.h>
37168754Sbushman#include <netdb.h>
38168754Sbushman#include <resolv.h>
39168754Sbushman#include <stdio.h>
40168754Sbushman#include <stdlib.h>
41168754Sbushman#include <string.h>
42168754Sbushman#include <stringlist.h>
43168754Sbushman#include <unistd.h>
44168754Sbushman#include "testutil.h"
45168754Sbushman
46168754Sbushman#ifndef min
47168754Sbushman#define min(a,b) (((a)<(b))?(a):(b))
48168754Sbushman#endif
49168754Sbushman
50168754Sbushmanenum test_methods {
51168754Sbushman	TEST_GETHOSTBYNAME2,
52168754Sbushman	TEST_GETHOSTBYADDR,
53168754Sbushman	TEST_GETHOSTBYNAME2_GETADDRINFO,
54168754Sbushman	TEST_GETHOSTBYADDR_GETNAMEINFO,
55168754Sbushman	TEST_BUILD_SNAPSHOT,
56168754Sbushman	TEST_BUILD_ADDR_SNAPSHOT
57168754Sbushman};
58168754Sbushman
59168754Sbushmanstatic int use_ipnode_functions = 0;
60168754Sbushmanstatic int use_ipv6_mapping = 0;
61171016Sbushmanstatic int ipnode_flags = 0;
62168754Sbushmanstatic int debug = 0;
63168754Sbushmanstatic int af_type = AF_INET;
64168754Sbushmanstatic enum test_methods method = TEST_BUILD_SNAPSHOT;
65168754Sbushman
66168754SbushmanDECLARE_TEST_DATA(hostent)
67168754SbushmanDECLARE_TEST_FILE_SNAPSHOT(hostent)
68168754SbushmanDECLARE_1PASS_TEST(hostent)
69168754SbushmanDECLARE_2PASS_TEST(hostent)
70168754Sbushman
71168754Sbushman/* These stubs will use gethostby***() or getipnodeby***() functions,
72168754Sbushman * depending on the use_ipnode_functions global variable value */
73168754Sbushmanstatic struct hostent *__gethostbyname2(const char *, int);
74168754Sbushmanstatic struct hostent *__gethostbyaddr(const void *, socklen_t, int);
75168754Sbushmanstatic void __freehostent(struct hostent *);
76168754Sbushman
77168754Sbushmanstatic void clone_hostent(struct hostent *, struct hostent const *);
78168754Sbushmanstatic int compare_hostent(struct hostent *, struct hostent *, void *);
79168754Sbushmanstatic void dump_hostent(struct hostent *);
80168754Sbushmanstatic void free_hostent(struct hostent *);
81168754Sbushman
82168754Sbushmanstatic int is_hostent_equal(struct hostent *, struct addrinfo *);
83168754Sbushman
84168754Sbushmanstatic void sdump_hostent(struct hostent *, char *, size_t);
85168754Sbushmanstatic int hostent_read_hostlist_func(struct hostent *, char *);
86168754Sbushmanstatic int hostent_read_snapshot_addr(char *, unsigned char *, size_t);
87168754Sbushmanstatic int hostent_read_snapshot_func(struct hostent *, char *);
88168754Sbushman
89168754Sbushmanstatic int hostent_test_correctness(struct hostent *, void *);
90168754Sbushmanstatic int hostent_test_gethostbyaddr(struct hostent *, void *);
91168754Sbushmanstatic int hostent_test_getaddrinfo_eq(struct hostent *, void *);
92168754Sbushmanstatic int hostent_test_getnameinfo_eq(struct hostent *, void *);
93168754Sbushman
94168754Sbushmanstatic void usage(void)  __attribute__((__noreturn__));
95168754Sbushman
96168754SbushmanIMPLEMENT_TEST_DATA(hostent)
97168754SbushmanIMPLEMENT_TEST_FILE_SNAPSHOT(hostent)
98168754SbushmanIMPLEMENT_1PASS_TEST(hostent)
99168754SbushmanIMPLEMENT_2PASS_TEST(hostent)
100168754Sbushman
101168754Sbushmanstatic struct hostent *
102168754Sbushman__gethostbyname2(const char *name, int af)
103168754Sbushman{
104168754Sbushman	struct hostent *he;
105168754Sbushman	int error;
106168754Sbushman
107171016Sbushman	if (use_ipnode_functions == 0)
108168754Sbushman		he = gethostbyname2(name, af);
109171016Sbushman	else {
110168754Sbushman		error = 0;
111171016Sbushman		he = getipnodebyname(name, af, ipnode_flags, &error);
112168754Sbushman		if (he == NULL);
113168754Sbushman			errno = error;
114168754Sbushman	}
115168754Sbushman
116168754Sbushman	return (he);
117168754Sbushman}
118168754Sbushman
119168754Sbushmanstatic struct hostent *
120168754Sbushman__gethostbyaddr(const void *addr, socklen_t len, int af)
121168754Sbushman{
122168754Sbushman	struct hostent *he;
123168754Sbushman	int error;
124168754Sbushman
125171016Sbushman	if (use_ipnode_functions == 0)
126168754Sbushman		he = gethostbyaddr(addr, len, af);
127171016Sbushman	else {
128168754Sbushman		error = 0;
129171016Sbushman		he = getipnodebyaddr(addr, len, af, &error);
130168754Sbushman		if (he == NULL)
131168754Sbushman			errno = error;
132168754Sbushman	}
133168754Sbushman
134168754Sbushman	return (he);
135168754Sbushman}
136168754Sbushman
137168754Sbushmanstatic void
138168754Sbushman__freehostent(struct hostent *he)
139168754Sbushman{
140168754Sbushman	/* NOTE: checking for he != NULL - just in case */
141168754Sbushman	if ((use_ipnode_functions != 0) && (he != NULL))
142168754Sbushman		freehostent(he);
143168754Sbushman}
144168754Sbushman
145168754Sbushmanstatic void
146168754Sbushmanclone_hostent(struct hostent *dest, struct hostent const *src)
147168754Sbushman{
148168754Sbushman	assert(dest != NULL);
149168754Sbushman	assert(src != NULL);
150168754Sbushman
151168754Sbushman	char **cp;
152168754Sbushman	int aliases_num;
153168754Sbushman	int addrs_num;
154168754Sbushman	size_t offset;
155168754Sbushman
156168754Sbushman	memset(dest, 0, sizeof(struct hostent));
157168754Sbushman
158168754Sbushman	if (src->h_name != NULL) {
159168754Sbushman		dest->h_name = strdup(src->h_name);
160168754Sbushman		assert(dest->h_name != NULL);
161168754Sbushman	}
162168754Sbushman
163168754Sbushman	dest->h_addrtype = src->h_addrtype;
164168754Sbushman	dest->h_length = src->h_length;
165168754Sbushman
166168754Sbushman	if (src->h_aliases != NULL) {
167168754Sbushman		aliases_num = 0;
168168754Sbushman		for (cp = src->h_aliases; *cp; ++cp)
169168754Sbushman			++aliases_num;
170168754Sbushman
171168754Sbushman		dest->h_aliases = (char **)malloc((aliases_num + 1) *
172168754Sbushman			(sizeof(char *)));
173168754Sbushman		assert(dest->h_aliases != NULL);
174168754Sbushman		memset(dest->h_aliases, 0, (aliases_num + 1) *
175168754Sbushman			(sizeof(char *)));
176168754Sbushman
177168754Sbushman		for (cp = src->h_aliases; *cp; ++cp) {
178168754Sbushman			dest->h_aliases[cp - src->h_aliases] = strdup(*cp);
179168754Sbushman			assert(dest->h_aliases[cp - src->h_aliases] != NULL);
180168754Sbushman		}
181168754Sbushman	}
182168754Sbushman
183168754Sbushman	if (src->h_addr_list != NULL) {
184168754Sbushman		addrs_num = 0;
185168754Sbushman		for (cp = src->h_addr_list; *cp; ++cp)
186168754Sbushman			++addrs_num;
187168754Sbushman
188168754Sbushman		dest->h_addr_list = (char **)malloc((addrs_num + 1) *
189168754Sbushman			(sizeof(char *)));
190168754Sbushman		assert(dest->h_addr_list != NULL);
191168754Sbushman		memset(dest->h_addr_list, 0, (addrs_num + 1) *
192168754Sbushman			(sizeof(char *)));
193168754Sbushman
194168754Sbushman		for (cp = src->h_addr_list; *cp; ++cp) {
195168754Sbushman			offset = cp - src->h_addr_list;
196168754Sbushman			dest->h_addr_list[offset] =
197168754Sbushman				(char *)malloc(src->h_length);
198168754Sbushman			assert(dest->h_addr_list[offset] != NULL);
199168754Sbushman			memcpy(dest->h_addr_list[offset],
200168754Sbushman				src->h_addr_list[offset], src->h_length);
201168754Sbushman		}
202168754Sbushman	}
203168754Sbushman}
204168754Sbushman
205168754Sbushmanstatic void
206168754Sbushmanfree_hostent(struct hostent *ht)
207168754Sbushman{
208168754Sbushman	char **cp;
209168754Sbushman
210168754Sbushman	assert(ht != NULL);
211168754Sbushman
212168754Sbushman	free(ht->h_name);
213168754Sbushman
214168754Sbushman	if (ht->h_aliases != NULL) {
215168754Sbushman		for (cp = ht->h_aliases; *cp; ++cp)
216168754Sbushman			free(*cp);
217168754Sbushman		free(ht->h_aliases);
218168754Sbushman	}
219168754Sbushman
220168754Sbushman	if  (ht->h_addr_list != NULL) {
221168754Sbushman		for (cp = ht->h_addr_list; *cp; ++cp)
222168754Sbushman			free(*cp);
223168754Sbushman		free(ht->h_addr_list);
224168754Sbushman	}
225168754Sbushman}
226168754Sbushman
227168754Sbushmanstatic  int
228168754Sbushmancompare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata)
229168754Sbushman{
230171016Sbushman	char **c1, **c2, **ct, **cb;
231171016Sbushman	int b;
232168754Sbushman
233168754Sbushman	if (ht1 == ht2)
234168754Sbushman		return 0;
235168754Sbushman
236168754Sbushman	if ((ht1 == NULL) || (ht2 == NULL))
237168754Sbushman		goto errfin;
238168754Sbushman
239168754Sbushman	if ((ht1->h_name == NULL) || (ht2->h_name == NULL))
240168754Sbushman		goto errfin;
241168754Sbushman
242168754Sbushman	if ((ht1->h_addrtype != ht2->h_addrtype) ||
243168754Sbushman		(ht1->h_length != ht2->h_length) ||
244168754Sbushman		(strcmp(ht1->h_name, ht2->h_name) != 0))
245168754Sbushman			goto errfin;
246168754Sbushman
247168754Sbushman	c1 = ht1->h_aliases;
248168754Sbushman	c2 = ht2->h_aliases;
249168754Sbushman
250168754Sbushman	if (((ht1->h_aliases == NULL) || (ht2->h_aliases == NULL)) &&
251168754Sbushman		(ht1->h_aliases != ht2->h_aliases))
252168754Sbushman		goto errfin;
253168754Sbushman
254168754Sbushman	if ((c1 != NULL) && (c2 != NULL)) {
255171016Sbushman		cb = c1;
256171016Sbushman		for (;*c1; ++c1) {
257171016Sbushman			b = 0;
258171016Sbushman			for (ct = c2; *ct; ++ct) {
259171016Sbushman				if (strcmp(*c1, *ct) == 0) {
260171016Sbushman					b = 1;
261171016Sbushman					break;
262171016Sbushman				}
263171016Sbushman			}
264171016Sbushman			if (b == 0) {
265171016Sbushman				if (debug)
266171016Sbushman					printf("h1 aliases item can't be "\
267171016Sbushman					    "found in h2 aliases\n");
268168754Sbushman				goto errfin;
269171016Sbushman			}
270171016Sbushman		}
271171016Sbushman
272171016Sbushman		c1 = cb;
273171016Sbushman		for (;*c2; ++c2) {
274171016Sbushman			b = 0;
275171016Sbushman			for (ct = c1; *ct; ++ct) {
276171016Sbushman				if (strcmp(*c2, *ct) == 0) {
277171016Sbushman					b = 1;
278171016Sbushman					break;
279171016Sbushman				}
280171016Sbushman			}
281171016Sbushman			if (b == 0) {
282171016Sbushman				if (debug)
283171016Sbushman					printf("h2 aliases item can't be "\
284171016Sbushman					    " found in h1 aliases\n");
285171016Sbushman				goto errfin;
286171016Sbushman			}
287171016Sbushman		}
288168754Sbushman	}
289168754Sbushman
290168754Sbushman	c1 = ht1->h_addr_list;
291168754Sbushman	c2 = ht2->h_addr_list;
292168754Sbushman
293168754Sbushman	if (((ht1->h_addr_list == NULL) || (ht2->h_addr_list== NULL)) &&
294168754Sbushman		(ht1->h_addr_list != ht2->h_addr_list))
295168754Sbushman		goto errfin;
296168754Sbushman
297168754Sbushman	if ((c1 != NULL) && (c2 != NULL)) {
298171016Sbushman		cb = c1;
299171016Sbushman		for (;*c1; ++c1) {
300171016Sbushman			b = 0;
301171016Sbushman			for (ct = c2; *ct; ++ct) {
302171016Sbushman				if (memcmp(*c1, *ct, ht1->h_length) == 0) {
303171016Sbushman					b = 1;
304171016Sbushman					break;
305171016Sbushman				}
306171016Sbushman			}
307171016Sbushman			if (b == 0) {
308171016Sbushman				if (debug)
309171016Sbushman					printf("h1 addresses item can't be "\
310171016Sbushman					    "found in h2 addresses\n");
311168754Sbushman				goto errfin;
312171016Sbushman			}
313171016Sbushman		}
314171016Sbushman
315171016Sbushman		c1 = cb;
316171016Sbushman		for (;*c2; ++c2) {
317171016Sbushman			b = 0;
318171016Sbushman			for (ct = c1; *ct; ++ct) {
319171016Sbushman				if (memcmp(*c2, *ct, ht1->h_length) == 0) {
320171016Sbushman					b = 1;
321171016Sbushman					break;
322171016Sbushman				}
323171016Sbushman			}
324171016Sbushman			if (b == 0) {
325171016Sbushman				if (debug)
326171016Sbushman					printf("h2 addresses item can't be "\
327171016Sbushman					    "found in h1 addresses\n");
328171016Sbushman				goto errfin;
329171016Sbushman			}
330171016Sbushman		}
331168754Sbushman	}
332168754Sbushman
333168754Sbushman	return 0;
334168754Sbushman
335168754Sbushmanerrfin:
336168754Sbushman	if ((debug) && (mdata == NULL)) {
337168754Sbushman		printf("following structures are not equal:\n");
338168754Sbushman		dump_hostent(ht1);
339168754Sbushman		dump_hostent(ht2);
340168754Sbushman	}
341168754Sbushman
342168754Sbushman	return (-1);
343168754Sbushman}
344168754Sbushman
345168754Sbushmanstatic int
346168754Sbushmancheck_addrinfo_for_name(struct addrinfo *ai, char const *name)
347168754Sbushman{
348168754Sbushman	struct addrinfo *ai2;
349168754Sbushman
350168754Sbushman	for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
351168754Sbushman		if (strcmp(ai2->ai_canonname, name) == 0)
352168754Sbushman			return (0);
353168754Sbushman	}
354168754Sbushman
355168754Sbushman	return (-1);
356168754Sbushman}
357168754Sbushman
358168754Sbushmanstatic int
359168754Sbushmancheck_addrinfo_for_addr(struct addrinfo *ai, char const *addr,
360168754Sbushman	socklen_t addrlen, int af)
361168754Sbushman{
362168754Sbushman	struct addrinfo *ai2;
363168754Sbushman
364168754Sbushman	for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
365168754Sbushman		if (af != ai2->ai_family)
366168754Sbushman			continue;
367168754Sbushman
368168754Sbushman		switch (af) {
369168754Sbushman			case AF_INET:
370168754Sbushman				if (memcmp(addr,
371168754Sbushman				    (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr,
372168754Sbushman				    min(addrlen, ai2->ai_addrlen)) == 0)
373168754Sbushman				    return (0);
374168754Sbushman			break;
375168754Sbushman			case AF_INET6:
376168754Sbushman				if (memcmp(addr,
377168754Sbushman				    (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr,
378168754Sbushman				    min(addrlen, ai2->ai_addrlen)) == 0)
379168754Sbushman				    return (0);
380168754Sbushman			break;
381168754Sbushman			default:
382168754Sbushman			break;
383168754Sbushman		}
384168754Sbushman	}
385168754Sbushman
386168754Sbushman	return (-1);
387168754Sbushman}
388168754Sbushman
389168754Sbushmanstatic int
390168754Sbushmanis_hostent_equal(struct hostent *he, struct addrinfo *ai)
391168754Sbushman{
392168754Sbushman	char **cp;
393168754Sbushman	int rv;
394168754Sbushman
395168754Sbushman	if (debug)
396168754Sbushman		printf("checking equality of he and ai\n");
397168754Sbushman
398168754Sbushman	rv = check_addrinfo_for_name(ai, he->h_name);
399168754Sbushman	if (rv != 0) {
400168754Sbushman		if (debug)
401168754Sbushman			printf("not equal - he->h_name couldn't be found\n");
402168754Sbushman
403168754Sbushman		return (rv);
404168754Sbushman	}
405168754Sbushman
406168754Sbushman	for (cp = he->h_addr_list; *cp; ++cp) {
407168754Sbushman		rv = check_addrinfo_for_addr(ai, *cp, he->h_length,
408168754Sbushman			he->h_addrtype);
409168754Sbushman		if (rv != 0) {
410168754Sbushman			if (debug)
411168754Sbushman				printf("not equal - one of he->h_addr_list couldn't be found\n");
412168754Sbushman
413168754Sbushman			return (rv);
414168754Sbushman		}
415168754Sbushman	}
416168754Sbushman
417168754Sbushman	if (debug)
418168754Sbushman		printf("equal\n");
419168754Sbushman
420168754Sbushman	return (0);
421168754Sbushman}
422168754Sbushman
423168754Sbushmanstatic void
424168754Sbushmansdump_hostent(struct hostent *ht, char *buffer, size_t buflen)
425168754Sbushman{
426168754Sbushman	char **cp;
427168754Sbushman	size_t i;
428168754Sbushman	int written;
429168754Sbushman
430168754Sbushman	written = snprintf(buffer, buflen, "%s %d %d",
431168754Sbushman		ht->h_name, ht->h_addrtype, ht->h_length);
432168754Sbushman	buffer += written;
433168754Sbushman	if (written > buflen)
434168754Sbushman		return;
435168754Sbushman	buflen -= written;
436168754Sbushman
437168754Sbushman	if (ht->h_aliases != NULL) {
438168754Sbushman		if (*(ht->h_aliases) != NULL) {
439168754Sbushman			for (cp = ht->h_aliases; *cp; ++cp) {
440168754Sbushman				written = snprintf(buffer, buflen, " %s",*cp);
441168754Sbushman				buffer += written;
442168754Sbushman				if (written > buflen)
443168754Sbushman					return;
444168754Sbushman				buflen -= written;
445168754Sbushman
446168754Sbushman				if (buflen == 0)
447168754Sbushman					return;
448168754Sbushman			}
449168754Sbushman		} else {
450168754Sbushman			written = snprintf(buffer, buflen, " noaliases");
451168754Sbushman			buffer += written;
452168754Sbushman			if (written > buflen)
453168754Sbushman				return;
454168754Sbushman			buflen -= written;
455168754Sbushman		}
456168754Sbushman	} else {
457168754Sbushman		written = snprintf(buffer, buflen, " (null)");
458168754Sbushman		buffer += written;
459168754Sbushman		if (written > buflen)
460168754Sbushman			return;
461168754Sbushman		buflen -= written;
462168754Sbushman	}
463168754Sbushman
464168754Sbushman	written = snprintf(buffer, buflen, " : ");
465168754Sbushman	buffer += written;
466168754Sbushman	if (written > buflen)
467168754Sbushman		return;
468168754Sbushman	buflen -= written;
469168754Sbushman
470168754Sbushman	if (ht->h_addr_list != NULL) {
471168754Sbushman		if (*(ht->h_addr_list) != NULL) {
472168754Sbushman			for (cp = ht->h_addr_list; *cp; ++cp) {
473168754Sbushman			    for (i = 0; i < ht->h_length; ++i ) {
474168754Sbushman				written = snprintf(buffer, buflen,
475168754Sbushman				    	i + 1 != ht->h_length ? "%d." : "%d",
476168754Sbushman				    	(unsigned char)(*cp)[i]);
477168754Sbushman				buffer += written;
478168754Sbushman				if (written > buflen)
479168754Sbushman					return;
480168754Sbushman				buflen -= written;
481168754Sbushman
482168754Sbushman				if (buflen == 0)
483168754Sbushman					return;
484168754Sbushman			    }
485168754Sbushman
486168754Sbushman			    if (*(cp + 1) ) {
487168754Sbushman				written = snprintf(buffer, buflen, " ");
488168754Sbushman				buffer += written;
489168754Sbushman				if (written > buflen)
490168754Sbushman				    return;
491168754Sbushman				buflen -= written;
492168754Sbushman			    }
493168754Sbushman			}
494168754Sbushman		} else {
495168754Sbushman			written = snprintf(buffer, buflen, " noaddrs");
496168754Sbushman			buffer += written;
497168754Sbushman			if (written > buflen)
498168754Sbushman				return;
499168754Sbushman			buflen -= written;
500168754Sbushman		}
501168754Sbushman	} else {
502168754Sbushman		written = snprintf(buffer, buflen, " (null)");
503168754Sbushman		buffer += written;
504168754Sbushman		if (written > buflen)
505168754Sbushman			return;
506168754Sbushman		buflen -= written;
507168754Sbushman	}
508168754Sbushman}
509168754Sbushman
510168754Sbushmanstatic int
511168754Sbushmanhostent_read_hostlist_func(struct hostent *he, char *line)
512168754Sbushman{
513168754Sbushman	struct hostent *result;
514168754Sbushman	int rv;
515168754Sbushman
516168754Sbushman	if (debug)
517168754Sbushman		printf("resolving %s: ", line);
518168754Sbushman	result = __gethostbyname2(line, af_type);
519168754Sbushman	if (result != NULL) {
520168754Sbushman		if (debug)
521168754Sbushman			printf("found\n");
522168754Sbushman
523168754Sbushman		rv = hostent_test_correctness(result, NULL);
524168754Sbushman		if (rv != 0) {
525168754Sbushman			__freehostent(result);
526168754Sbushman			return (rv);
527168754Sbushman		}
528168754Sbushman
529168754Sbushman		clone_hostent(he, result);
530168754Sbushman		__freehostent(result);
531168754Sbushman	} else {
532168754Sbushman		if (debug)
533168754Sbushman			printf("not found\n");
534168754Sbushman
535168754Sbushman 		memset(he, 0, sizeof(struct hostent));
536168754Sbushman		he->h_name = strdup(line);
537168754Sbushman		assert(he->h_name != NULL);
538168754Sbushman	}
539168754Sbushman	return (0);
540168754Sbushman}
541168754Sbushman
542168754Sbushmanstatic int
543168754Sbushmanhostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
544168754Sbushman{
545168754Sbushman	char *s, *ps, *ts;
546168754Sbushman
547168754Sbushman	ps = addr;
548168754Sbushman	while ( (s = strsep(&ps, ".")) != NULL) {
549168754Sbushman		if (len == 0)
550168754Sbushman			return (-1);
551168754Sbushman
552168754Sbushman		*result = (unsigned char)strtol(s, &ts, 10);
553168754Sbushman		++result;
554168754Sbushman		if (*ts != '\0')
555168754Sbushman			return (-1);
556168754Sbushman
557168754Sbushman		--len;
558168754Sbushman	}
559168754Sbushman	if (len != 0)
560168754Sbushman		return (-1);
561168754Sbushman	else
562168754Sbushman		return (0);
563168754Sbushman}
564168754Sbushman
565168754Sbushmanstatic int
566168754Sbushmanhostent_read_snapshot_func(struct hostent *ht, char *line)
567168754Sbushman{
568241844Seadler	StringList *sl1, *sl2;
569168754Sbushman	char *s, *ps, *ts;
570168754Sbushman	int i, rv;
571168754Sbushman
572168754Sbushman	if (debug)
573168754Sbushman		printf("1 line read from snapshot:\n%s\n", line);
574168754Sbushman
575168754Sbushman	rv = 0;
576168754Sbushman	i = 0;
577168754Sbushman	sl1 = sl2 = NULL;
578168754Sbushman	ps = line;
579168754Sbushman	memset(ht, 0, sizeof(struct hostent));
580168754Sbushman	while ( (s = strsep(&ps, " ")) != NULL) {
581168754Sbushman		switch (i) {
582168754Sbushman			case 0:
583168754Sbushman				ht->h_name = strdup(s);
584168754Sbushman				assert(ht->h_name != NULL);
585168754Sbushman			break;
586168754Sbushman
587168754Sbushman			case 1:
588168754Sbushman				ht->h_addrtype = (int)strtol(s, &ts, 10);
589168754Sbushman				if (*ts != '\0')
590168754Sbushman					goto fin;
591168754Sbushman			break;
592168754Sbushman
593168754Sbushman			case 2:
594168754Sbushman				ht->h_length = (int)strtol(s, &ts, 10);
595168754Sbushman				if (*ts != '\0')
596168754Sbushman					goto fin;
597168754Sbushman			break;
598168754Sbushman
599168754Sbushman			case 3:
600168754Sbushman				if (sl1 == NULL) {
601168754Sbushman					if (strcmp(s, "(null)") == 0)
602168754Sbushman						return (0);
603168754Sbushman
604168754Sbushman					sl1 = sl_init();
605168754Sbushman					assert(sl1 != NULL);
606168754Sbushman
607168754Sbushman					if (strcmp(s, "noaliases") != 0) {
608168754Sbushman						ts = strdup(s);
609168754Sbushman						assert(ts != NULL);
610168754Sbushman						sl_add(sl1, ts);
611168754Sbushman					}
612168754Sbushman				} else {
613168754Sbushman					if (strcmp(s, ":") == 0)
614168754Sbushman						++i;
615168754Sbushman					else {
616168754Sbushman						ts = strdup(s);
617168754Sbushman						assert(ts != NULL);
618168754Sbushman						sl_add(sl1, ts);
619168754Sbushman					}
620168754Sbushman				}
621168754Sbushman			break;
622168754Sbushman
623168754Sbushman			case 4:
624168754Sbushman				if (sl2 == NULL) {
625168754Sbushman					if (strcmp(s, "(null)") == 0)
626168754Sbushman						return (0);
627168754Sbushman
628168754Sbushman					sl2 = sl_init();
629168754Sbushman					assert(sl2 != NULL);
630168754Sbushman
631168754Sbushman					if (strcmp(s, "noaddrs") != 0) {
632168754Sbushman					    ts = (char *)malloc(ht->h_length);
633168754Sbushman					    assert(ts != NULL);
634168754Sbushman					    memset(ts, 0, ht->h_length);
635171016Sbushman					    rv = hostent_read_snapshot_addr(s,\
636171016Sbushman						 (unsigned char *)ts, ht->h_length);
637168754Sbushman					    sl_add(sl2, ts);
638168754Sbushman					    if (rv != 0)
639168754Sbushman						    goto fin;
640168754Sbushman					}
641168754Sbushman				} else {
642168754Sbushman				    ts = (char *)malloc(ht->h_length);
643168754Sbushman				    assert(ts != NULL);
644168754Sbushman				    memset(ts, 0, ht->h_length);
645171016Sbushman				    rv = hostent_read_snapshot_addr(s,\
646171016Sbushman					(unsigned char *)ts, ht->h_length);
647168754Sbushman				    sl_add(sl2, ts);
648168754Sbushman				    if (rv != 0)
649168754Sbushman					    goto fin;
650168754Sbushman				}
651168754Sbushman			break;
652168754Sbushman			default:
653168754Sbushman			break;
654168754Sbushman		};
655168754Sbushman
656168754Sbushman		if ((i != 3) && (i != 4))
657168754Sbushman			++i;
658168754Sbushman	}
659168754Sbushman
660168754Sbushmanfin:
661168754Sbushman	if (sl1 != NULL) {
662168754Sbushman		sl_add(sl1, NULL);
663168754Sbushman		ht->h_aliases = sl1->sl_str;
664168754Sbushman	}
665168754Sbushman	if (sl2 != NULL) {
666168754Sbushman		sl_add(sl2, NULL);
667168754Sbushman		ht->h_addr_list = sl2->sl_str;
668168754Sbushman	}
669168754Sbushman
670168754Sbushman	if ((i != 4) || (rv != 0)) {
671168754Sbushman		free_hostent(ht);
672168754Sbushman		memset(ht, 0, sizeof(struct hostent));
673168754Sbushman		return (-1);
674168754Sbushman	}
675168754Sbushman
676168754Sbushman	/* NOTE: is it a dirty hack or not? */
677168754Sbushman	free(sl1);
678168754Sbushman	free(sl2);
679168754Sbushman	return (0);
680168754Sbushman}
681168754Sbushman
682168754Sbushmanstatic void
683168754Sbushmandump_hostent(struct hostent *result)
684168754Sbushman{
685168754Sbushman	if (result != NULL) {
686168754Sbushman		char buffer[1024];
687168754Sbushman		sdump_hostent(result, buffer, sizeof(buffer));
688168754Sbushman		printf("%s\n", buffer);
689168754Sbushman	} else
690168754Sbushman		printf("(null)\n");
691168754Sbushman}
692168754Sbushman
693168754Sbushmanstatic int
694168754Sbushmanhostent_test_correctness(struct hostent *ht, void *mdata)
695168754Sbushman{
696168754Sbushman	if (debug) {
697168754Sbushman		printf("testing correctness with the following data:\n");
698168754Sbushman		dump_hostent(ht);
699168754Sbushman	}
700168754Sbushman
701168754Sbushman	if (ht == NULL)
702168754Sbushman		goto errfin;
703168754Sbushman
704168754Sbushman	if (ht->h_name == NULL)
705168754Sbushman		goto errfin;
706168754Sbushman
707168754Sbushman	if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX)))
708168754Sbushman		goto errfin;
709168754Sbushman
710168754Sbushman	if ((ht->h_length != sizeof(struct in_addr)) &&
711168754Sbushman		(ht->h_length != sizeof(struct in6_addr)))
712168754Sbushman		goto errfin;
713168754Sbushman
714168754Sbushman	if (ht->h_aliases == NULL)
715168754Sbushman		goto errfin;
716168754Sbushman
717168754Sbushman	if (ht->h_addr_list == NULL)
718168754Sbushman		goto errfin;
719168754Sbushman
720168754Sbushman	if (debug)
721168754Sbushman		printf("correct\n");
722168754Sbushman
723168754Sbushman	return (0);
724168754Sbushmanerrfin:
725168754Sbushman	if (debug)
726168754Sbushman		printf("incorrect\n");
727168754Sbushman
728168754Sbushman	return (-1);
729168754Sbushman}
730168754Sbushman
731168754Sbushmanstatic int
732168754Sbushmanhostent_test_gethostbyaddr(struct hostent *he, void *mdata)
733168754Sbushman{
734168754Sbushman	struct hostent *result;
735168754Sbushman	struct hostent_test_data *addr_test_data;
736168754Sbushman	int rv;
737168754Sbushman
738168754Sbushman	addr_test_data = (struct hostent_test_data *)mdata;
739168754Sbushman
740168754Sbushman	/* We should omit unresolved hostents */
741168754Sbushman	if (he->h_addr_list != NULL) {
742168754Sbushman		char **cp;
743168754Sbushman		for (cp = he->h_addr_list; *cp; ++cp) {
744168754Sbushman			if (debug)
745168754Sbushman			    printf("doing reverse lookup for %s\n", he->h_name);
746168754Sbushman
747168754Sbushman			result = __gethostbyaddr(*cp, he->h_length,
748168754Sbushman			    he->h_addrtype);
749168754Sbushman			if (result == NULL) {
750168754Sbushman				if (debug)
751168754Sbushman				    printf("warning: reverse lookup failed\n");
752168754Sbushman
753168754Sbushman				continue;
754168754Sbushman			}
755168754Sbushman			rv = hostent_test_correctness(result, NULL);
756168754Sbushman			if (rv != 0) {
757168754Sbushman			    __freehostent(result);
758168754Sbushman			    return (rv);
759168754Sbushman			}
760168754Sbushman
761168754Sbushman			if (addr_test_data != NULL)
762168754Sbushman			    TEST_DATA_APPEND(hostent, addr_test_data, result);
763168754Sbushman
764168754Sbushman			__freehostent(result);
765168754Sbushman		}
766168754Sbushman	}
767168754Sbushman
768168754Sbushman	return (0);
769168754Sbushman}
770168754Sbushman
771168754Sbushmanstatic int
772168754Sbushmanhostent_test_getaddrinfo_eq(struct hostent *he, void *mdata)
773168754Sbushman{
774168754Sbushman	struct addrinfo *ai, hints;
775168754Sbushman	int rv;
776168754Sbushman
777168754Sbushman	ai = NULL;
778168754Sbushman	memset(&hints, 0, sizeof(struct addrinfo));
779168754Sbushman	hints.ai_family = af_type;
780168754Sbushman	hints.ai_flags = AI_CANONNAME;
781168754Sbushman
782168754Sbushman	if (debug)
783168754Sbushman		printf("using getaddrinfo() to resolve %s\n", he->h_name);
784168754Sbushman
785168754Sbushman	/* struct hostent *he was not resolved */
786168754Sbushman	if (he->h_addr_list == NULL) {
787168754Sbushman		/* We can be sure that he->h_name is not NULL */
788168754Sbushman		rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
789168754Sbushman		if (rv == 0) {
790168754Sbushman			if (debug)
791168754Sbushman			    printf("not ok - shouldn't have been resolved\n");
792168754Sbushman			return (-1);
793168754Sbushman		}
794168754Sbushman	} else {
795168754Sbushman		rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
796168754Sbushman		if (rv != 0) {
797168754Sbushman			if (debug)
798168754Sbushman			    printf("not ok - should have beed resolved\n");
799168754Sbushman			return (-1);
800168754Sbushman		}
801168754Sbushman
802168754Sbushman		rv = is_hostent_equal(he, ai);
803168754Sbushman		if (rv != 0) {
804168754Sbushman			if (debug)
805168754Sbushman			    printf("not ok - addrinfo and hostent are not equal\n");
806168754Sbushman			return (-1);
807168754Sbushman		}
808168754Sbushman
809168754Sbushman	}
810168754Sbushman
811168754Sbushman	return (0);
812168754Sbushman}
813168754Sbushman
814168754Sbushmanstatic int
815168754Sbushmanhostent_test_getnameinfo_eq(struct hostent *he, void *mdata)
816168754Sbushman{
817168754Sbushman	char buffer[NI_MAXHOST];
818168754Sbushman	struct sockaddr_in sin;
819168754Sbushman	struct sockaddr_in6 sin6;
820168754Sbushman	struct sockaddr *saddr;
821168754Sbushman	struct hostent *result;
822168754Sbushman	int rv;
823168754Sbushman
824168754Sbushman	if (he->h_addr_list != NULL) {
825168754Sbushman		char **cp;
826168754Sbushman		for (cp = he->h_addr_list; *cp; ++cp) {
827168754Sbushman			if (debug)
828168754Sbushman			    printf("doing reverse lookup for %s\n", he->h_name);
829168754Sbushman
830168754Sbushman			result = __gethostbyaddr(*cp, he->h_length,
831168754Sbushman			    he->h_addrtype);
832168754Sbushman			if (result != NULL) {
833168754Sbushman				rv = hostent_test_correctness(result, NULL);
834168754Sbushman				if (rv != 0) {
835168754Sbushman				    __freehostent(result);
836168754Sbushman				    return (rv);
837168754Sbushman				}
838168754Sbushman			} else {
839168754Sbushman				if (debug)
840168754Sbushman				    printf("reverse lookup failed\n");
841168754Sbushman			}
842168754Sbushman
843168754Sbushman			switch (he->h_addrtype) {
844168754Sbushman			case AF_INET:
845168754Sbushman				memset(&sin, 0, sizeof(struct sockaddr_in));
846168754Sbushman				sin.sin_len = sizeof(struct sockaddr_in);
847168754Sbushman				sin.sin_family = AF_INET;
848168754Sbushman				memcpy(&sin.sin_addr, *cp, he->h_length);
849168754Sbushman
850168754Sbushman				saddr = (struct sockaddr *)&sin;
851168754Sbushman				break;
852168754Sbushman			case AF_INET6:
853168754Sbushman				memset(&sin6, 0, sizeof(struct sockaddr_in6));
854168754Sbushman				sin6.sin6_len = sizeof(struct sockaddr_in6);
855168754Sbushman				sin6.sin6_family = AF_INET6;
856168754Sbushman				memcpy(&sin6.sin6_addr, *cp, he->h_length);
857168754Sbushman
858168754Sbushman				saddr = (struct sockaddr *)&sin6;
859168754Sbushman				break;
860168754Sbushman			default:
861168754Sbushman				if (debug)
862168754Sbushman					printf("warning: %d family is unsupported\n",
863168754Sbushman						he->h_addrtype);
864168754Sbushman				continue;
865168754Sbushman			}
866168754Sbushman
867168754Sbushman			assert(saddr != NULL);
868168754Sbushman			rv = getnameinfo(saddr, saddr->sa_len, buffer,
869168754Sbushman				sizeof(buffer), NULL, 0, NI_NAMEREQD);
870168754Sbushman
871168754Sbushman			if ((rv != 0) && (result != NULL)) {
872168754Sbushman				if (debug)
873168754Sbushman					printf("not ok - getnameinfo() didn't make the reverse lookup, when it should have (%s)\n",
874168754Sbushman						gai_strerror(rv));
875168754Sbushman				return (rv);
876168754Sbushman			}
877168754Sbushman
878168754Sbushman			if ((rv == 0) && (result == NULL)) {
879168754Sbushman				if (debug)
880168754Sbushman					printf("not ok - getnameinfo() made the reverse lookup, when it shouldn't have\n");
881168754Sbushman				return (rv);
882168754Sbushman			}
883168754Sbushman
884168754Sbushman			if ((rv != 0) && (result == NULL)) {
885168754Sbushman				if (debug)
886168754Sbushman					printf("ok - both getnameinfo() and ***byaddr() failed\n");
887168754Sbushman
888168754Sbushman				continue;
889168754Sbushman			}
890168754Sbushman
891168754Sbushman			if (debug)
892168754Sbushman				printf("comparing %s with %s\n", result->h_name,
893168754Sbushman					buffer);
894168754Sbushman
895168754Sbushman			rv = strcmp(result->h_name, buffer);
896168754Sbushman			__freehostent(result);
897168754Sbushman
898168754Sbushman			if (rv != 0) {
899168754Sbushman				if (debug)
900168754Sbushman					printf("not ok - getnameinfo() and ***byaddr() results are not equal\n");
901168754Sbushman				return (rv);
902168754Sbushman			} else {
903168754Sbushman				if (debug)
904168754Sbushman					printf("ok - getnameinfo() and ***byaddr() results are equal\n");
905168754Sbushman			}
906168754Sbushman		}
907168754Sbushman	}
908168754Sbushman
909168754Sbushman	return (0);
910168754Sbushman}
911168754Sbushman
912168754Sbushmanstatic void
913168754Sbushmanusage(void)
914168754Sbushman{
915168754Sbushman	(void)fprintf(stderr,
916171016Sbushman	    "Usage: %s -na2i [-o] [-d] [-46] [-mAcM] [-C] [-s <file>] -f <file>\n",
917168754Sbushman	    getprogname());
918168754Sbushman	exit(1);
919168754Sbushman}
920168754Sbushman
921168754Sbushmanint
922168754Sbushmanmain(int argc, char **argv)
923168754Sbushman{
924168754Sbushman	struct hostent_test_data td, td_addr, td_snap;
925168754Sbushman	char *snapshot_file, *hostlist_file;
926168754Sbushman	res_state statp;
927168754Sbushman	int rv;
928168754Sbushman	int c;
929168754Sbushman
930168754Sbushman	if (argc < 2)
931168754Sbushman		usage();
932168754Sbushman
933168754Sbushman	snapshot_file = NULL;
934168754Sbushman	hostlist_file = NULL;
935171016Sbushman	while ((c = getopt(argc, argv, "nad2iod46mAcMs:f:")) != -1)
936168754Sbushman		switch (c) {
937168754Sbushman		case '4':
938171016Sbushman			af_type = AF_INET;
939171016Sbushman			break;
940168754Sbushman		case '6':
941171016Sbushman			af_type = AF_INET6;
942171016Sbushman			break;
943171016Sbushman		case 'M':
944171016Sbushman			af_type = AF_INET6;
945171016Sbushman			use_ipv6_mapping = 1;
946171016Sbushman			ipnode_flags |= AI_V4MAPPED_CFG;
947171016Sbushman			break;
948168754Sbushman		case 'm':
949171016Sbushman			af_type = AF_INET6;
950171016Sbushman			use_ipv6_mapping = 1;
951171016Sbushman			ipnode_flags |= AI_V4MAPPED;
952168754Sbushman			break;
953171016Sbushman		case 'c':
954171016Sbushman			ipnode_flags |= AI_ADDRCONFIG;
955171016Sbushman			break;
956171016Sbushman		case 'A':
957171016Sbushman			ipnode_flags |= AI_ALL;
958171016Sbushman			break;
959168754Sbushman		case 'o':
960168754Sbushman			use_ipnode_functions = 1;
961168754Sbushman			break;
962168754Sbushman		case 'd':
963168754Sbushman			debug = 1;
964168754Sbushman			break;
965168754Sbushman		case 'n':
966168754Sbushman			method = TEST_GETHOSTBYNAME2;
967168754Sbushman			break;
968168754Sbushman		case 'a':
969168754Sbushman			method = TEST_GETHOSTBYADDR;
970168754Sbushman			break;
971168754Sbushman		case '2':
972168754Sbushman			method = TEST_GETHOSTBYNAME2_GETADDRINFO;
973168754Sbushman			break;
974168754Sbushman		case 'i':
975168754Sbushman			method = TEST_GETHOSTBYADDR_GETNAMEINFO;
976168754Sbushman			break;
977168754Sbushman		case 's':
978168754Sbushman			snapshot_file = strdup(optarg);
979168754Sbushman			break;
980168754Sbushman		case 'f':
981168754Sbushman			hostlist_file = strdup(optarg);
982168754Sbushman			break;
983168754Sbushman		default:
984168754Sbushman			usage();
985168754Sbushman		}
986171016Sbushman
987171016Sbushman	if (use_ipnode_functions == 0) {
988171016Sbushman		statp = __res_state();
989171016Sbushman		if ((statp == NULL) || ((statp->options & RES_INIT) == 0 &&
990171016Sbushman			res_ninit(statp) == -1)) {
991171016Sbushman			if (debug)
992171016Sbushman			    printf("error: can't init res_state\n");
993171016Sbushman
994171016Sbushman			free(snapshot_file);
995171016Sbushman			free(hostlist_file);
996171016Sbushman			return (-1);
997171016Sbushman		}
998168754Sbushman
999171016Sbushman		if (use_ipv6_mapping == 0)
1000171016Sbushman			statp->options &= ~RES_USE_INET6;
1001171016Sbushman		else
1002171016Sbushman			statp->options |= RES_USE_INET6;
1003171016Sbushman	}
1004171016Sbushman
1005168754Sbushman	TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent);
1006168754Sbushman	TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent);
1007168754Sbushman	TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent);
1008168754Sbushman
1009168754Sbushman	if (hostlist_file == NULL)
1010168754Sbushman		usage();
1011168754Sbushman
1012168754Sbushman	if (access(hostlist_file, R_OK) != 0) {
1013168754Sbushman		if (debug)
1014168754Sbushman			printf("can't access the hostlist file %s\n",
1015168754Sbushman				hostlist_file);
1016168754Sbushman
1017168754Sbushman		usage();
1018168754Sbushman	}
1019168754Sbushman
1020168754Sbushman	if (debug)
1021168754Sbushman		printf("building host lists from %s\n", hostlist_file);
1022168754Sbushman
1023168754Sbushman	rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td,
1024168754Sbushman		hostent_read_hostlist_func);
1025168754Sbushman	if (rv != 0)
1026168754Sbushman		goto fin;
1027168754Sbushman
1028168754Sbushman	if (snapshot_file != NULL) {
1029168754Sbushman		if (access(snapshot_file, W_OK | R_OK) != 0) {
1030168754Sbushman			if (errno == ENOENT) {
1031168754Sbushman				if (method != TEST_GETHOSTBYADDR)
1032168754Sbushman					method = TEST_BUILD_SNAPSHOT;
1033168754Sbushman				else
1034168754Sbushman					method = TEST_BUILD_ADDR_SNAPSHOT;
1035168754Sbushman			} else {
1036168754Sbushman				if (debug)
1037168754Sbushman				    printf("can't access the snapshot file %s\n",
1038168754Sbushman				    snapshot_file);
1039168754Sbushman
1040168754Sbushman				rv = -1;
1041168754Sbushman				goto fin;
1042168754Sbushman			}
1043168754Sbushman		} else {
1044168754Sbushman			rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file,
1045168754Sbushman				&td_snap, hostent_read_snapshot_func);
1046168754Sbushman			if (rv != 0) {
1047168754Sbushman				if (debug)
1048168754Sbushman					printf("error reading snapshot file\n");
1049168754Sbushman				goto fin;
1050168754Sbushman			}
1051168754Sbushman		}
1052168754Sbushman	}
1053168754Sbushman
1054168754Sbushman	switch (method) {
1055168754Sbushman	case TEST_GETHOSTBYNAME2:
1056168754Sbushman		if (snapshot_file != NULL)
1057168754Sbushman			rv = DO_2PASS_TEST(hostent, &td, &td_snap,
1058168754Sbushman				compare_hostent, NULL);
1059168754Sbushman		break;
1060168754Sbushman	case TEST_GETHOSTBYADDR:
1061168754Sbushman		rv = DO_1PASS_TEST(hostent, &td,
1062168754Sbushman			hostent_test_gethostbyaddr, (void *)&td_addr);
1063168754Sbushman
1064168754Sbushman		if (snapshot_file != NULL)
1065168754Sbushman			rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap,
1066168754Sbushman				compare_hostent, NULL);
1067168754Sbushman		break;
1068168754Sbushman	case TEST_GETHOSTBYNAME2_GETADDRINFO:
1069168754Sbushman		rv = DO_1PASS_TEST(hostent, &td,
1070168754Sbushman			hostent_test_getaddrinfo_eq, NULL);
1071168754Sbushman		break;
1072168754Sbushman	case TEST_GETHOSTBYADDR_GETNAMEINFO:
1073168754Sbushman		rv = DO_1PASS_TEST(hostent, &td,
1074168754Sbushman			hostent_test_getnameinfo_eq, NULL);
1075168754Sbushman		break;
1076168754Sbushman	case TEST_BUILD_SNAPSHOT:
1077168754Sbushman		if (snapshot_file != NULL) {
1078168754Sbushman		    rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td,
1079168754Sbushman			sdump_hostent);
1080168754Sbushman		}
1081168754Sbushman		break;
1082168754Sbushman	case TEST_BUILD_ADDR_SNAPSHOT:
1083168754Sbushman		if (snapshot_file != NULL) {
1084168754Sbushman			rv = DO_1PASS_TEST(hostent, &td,
1085168754Sbushman				hostent_test_gethostbyaddr, (void *)&td_addr);
1086168754Sbushman
1087168754Sbushman		    rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
1088168754Sbushman			&td_addr, sdump_hostent);
1089168754Sbushman		}
1090168754Sbushman		break;
1091168754Sbushman	default:
1092168754Sbushman		rv = 0;
1093168754Sbushman		break;
1094168754Sbushman	};
1095168754Sbushman
1096168754Sbushmanfin:
1097168754Sbushman	TEST_DATA_DESTROY(hostent, &td_snap);
1098168754Sbushman	TEST_DATA_DESTROY(hostent, &td_addr);
1099168754Sbushman	TEST_DATA_DESTROY(hostent, &td);
1100168754Sbushman	free(hostlist_file);
1101168754Sbushman	free(snapshot_file);
1102171016Sbushman
1103168754Sbushman	return (rv);
1104168754Sbushman}
1105171016Sbushman
1106