xref: /illumos-gate/usr/src/lib/nsswitch/dns/common/dns_common.c (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	dns_common.c
24  *
25  * Copyright (c) 1993,1998 by Sun Microsystems, Inc.
26  * All rights reserved.
27  */
28 
29 #pragma	ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include "dns_common.h"
32 
33 #define	DNS_ALIASES	0
34 #define	DNS_ADDRLIST	1
35 #define	DNS_MAPDLIST	2
36 
37 static int
38 dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type)
39 	char	**from_list, **to_list,	**aliaspp;
40 	int	type, *count, af_type;
41 {
42 	char		*fstr;
43 	int		cnt = 0;
44 	size_t		len;
45 
46 	*count = 0;
47 	if ((char *)to_list >= *aliaspp)
48 		return (NSS_STR_PARSE_ERANGE);
49 
50 	for (fstr = from_list[cnt]; fstr != NULL; fstr = from_list[cnt]) {
51 		if (type == DNS_ALIASES)
52 			len = strlen(fstr) + 1;
53 		else
54 			len = (af_type == AF_INET) ? sizeof (struct in_addr)
55 						: sizeof (struct in6_addr);
56 		*aliaspp -= len;
57 		to_list[cnt] = *aliaspp;
58 		if (*aliaspp <= (char *)&to_list[cnt+1])
59 			return (NSS_STR_PARSE_ERANGE);
60 		if (type == DNS_MAPDLIST) {
61 			struct in6_addr *addr6p = (struct in6_addr *) *aliaspp;
62 
63 			(void) memset(addr6p, '\0', sizeof (struct in6_addr));
64 			(void) memcpy(&addr6p->s6_addr[12], fstr,
65 					sizeof (struct in_addr));
66 			addr6p->s6_addr[10] = 0xffU;
67 			addr6p->s6_addr[11] = 0xffU;
68 			++cnt;
69 		} else {
70 			(void) memcpy (*aliaspp, fstr, len);
71 			++cnt;
72 		}
73 	}
74 	to_list[cnt] = NULL;
75 
76 	*count = cnt;
77 	if (cnt == 0)
78 		return (NSS_STR_PARSE_PARSE);
79 
80 	return (NSS_STR_PARSE_SUCCESS);
81 }
82 
83 
84 int
85 ent2result(he, argp, af_type)
86 	struct hostent		*he;
87 	nss_XbyY_args_t		*argp;
88 	int			af_type;
89 {
90 	char		*buffer, *limit;
91 	int		buflen = argp->buf.buflen;
92 	int		ret, count;
93 	size_t len;
94 	struct hostent 	*host;
95 	struct in_addr	*addrp;
96 	struct in6_addr	*addrp6;
97 
98 	limit = argp->buf.buffer + buflen;
99 	host = (struct hostent *) argp->buf.result;
100 	buffer = argp->buf.buffer;
101 
102 	/* h_addrtype and h_length */
103 	host->h_addrtype = af_type;
104 	host->h_length = (af_type == AF_INET) ? sizeof (struct in_addr)
105 					: sizeof (struct in6_addr);
106 
107 	/* h_name */
108 	len = strlen(he->h_name) + 1;
109 	host->h_name = buffer;
110 	if (host->h_name + len >= limit)
111 		return (NSS_STR_PARSE_ERANGE);
112 	(void) memcpy(host->h_name, he->h_name, len);
113 	buffer += len;
114 
115 	/* h_addr_list */
116 	if (af_type == AF_INET) {
117 		addrp = (struct in_addr *) ROUND_DOWN(limit, sizeof (*addrp));
118 		host->h_addr_list = (char **)
119 				ROUND_UP(buffer, sizeof (char **));
120 		ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list,
121 			(char **)&addrp, DNS_ADDRLIST, &count, af_type);
122 		if (ret != NSS_STR_PARSE_SUCCESS)
123 			return (ret);
124 		/* h_aliases */
125 		host->h_aliases = host->h_addr_list + count + 1;
126 		ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
127 			(char **)&addrp, DNS_ALIASES, &count, af_type);
128 	} else {
129 		addrp6 = (struct in6_addr *)
130 			ROUND_DOWN(limit, sizeof (*addrp6));
131 		host->h_addr_list = (char **)
132 			ROUND_UP(buffer, sizeof (char **));
133 		if (he->h_addrtype == AF_INET && af_type == AF_INET6) {
134 			ret = dns_netdb_aliases(he->h_addr_list,
135 				host->h_addr_list, (char **)&addrp6,
136 				DNS_MAPDLIST, &count, af_type);
137 		} else {
138 			ret = dns_netdb_aliases(he->h_addr_list,
139 				host->h_addr_list, (char **)&addrp6,
140 				DNS_ADDRLIST, &count, af_type);
141 		}
142 		if (ret != NSS_STR_PARSE_SUCCESS)
143 			return (ret);
144 		/* h_aliases */
145 		host->h_aliases = host->h_addr_list + count + 1;
146 		ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
147 			(char **)&addrp6, DNS_ALIASES, &count, af_type);
148 	}
149 	if (ret == NSS_STR_PARSE_PARSE)
150 		ret = NSS_STR_PARSE_SUCCESS;
151 
152 	return (ret);
153 }
154 
155 
156 nss_backend_t *
157 _nss_dns_constr(dns_backend_op_t ops[], int n_ops)
158 {
159 	dns_backend_ptr_t	be;
160 
161 	if ((be = (dns_backend_ptr_t) malloc(sizeof (*be))) == 0)
162 		return (0);
163 
164 	be->ops = ops;
165 	be->n_ops = n_ops;
166 	return ((nss_backend_t *) be);
167 }
168