17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5cb5caa98Sdjl * Common Development and Distribution License (the "License").
6cb5caa98Sdjl * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217257d1b4Sraf
227c478bd9Sstevel@tonic-gate /*
23*23a1cceaSRoger A. Faulkner * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <netdb.h>
277c478bd9Sstevel@tonic-gate #include "files_common.h"
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <stddef.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/socket.h>
347c478bd9Sstevel@tonic-gate #include <netinet/in.h>
357c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
36cb5caa98Sdjl #include <arpa/inet.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate
39cb5caa98Sdjl static int check_name(nss_XbyY_args_t *, const char *, int,
40cb5caa98Sdjl int, const char **, int *, void *, int *);
417c478bd9Sstevel@tonic-gate static char *do_aliases();
427c478bd9Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname();
437c478bd9Sstevel@tonic-gate int __nss_files_2herrno();
44cb5caa98Sdjl static int __nss_files_get_addr(int, const char *, int,
45cb5caa98Sdjl void *, int, int *);
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate static int
check_name(nss_XbyY_args_t * argp,const char * line,int linelen,int type,const char ** namep,int * namelen,void * addrp,int * addrsize)48cb5caa98Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen,
49cb5caa98Sdjl int type, const char **namep, int *namelen,
50cb5caa98Sdjl void *addrp, int *addrsize)
517c478bd9Sstevel@tonic-gate {
52cb5caa98Sdjl const char *limit, *linep, *keyp, *addrstart;
53cb5caa98Sdjl int v6flag = 0, addrlen;
54cb5caa98Sdjl
55cb5caa98Sdjl linep = line;
56cb5caa98Sdjl limit = line + linelen;
57cb5caa98Sdjl
58cb5caa98Sdjl /* Address */
59cb5caa98Sdjl addrstart = linep;
60cb5caa98Sdjl while (linep < limit && !isspace(*linep)) {
61cb5caa98Sdjl if (*linep == ':')
62cb5caa98Sdjl v6flag++;
63cb5caa98Sdjl linep++;
647c478bd9Sstevel@tonic-gate }
65cb5caa98Sdjl addrlen = linep - addrstart;
66cb5caa98Sdjl
67cb5caa98Sdjl /* skip the delimiting spaces */
68cb5caa98Sdjl while (linep < limit && isspace(*linep))
69cb5caa98Sdjl linep++;
70cb5caa98Sdjl
71cb5caa98Sdjl /* Canonical name */
72cb5caa98Sdjl keyp = argp->key.name;
73cb5caa98Sdjl *namep = linep;
74cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) &&
757257d1b4Sraf tolower(*keyp) == tolower(*linep)) {
76cb5caa98Sdjl keyp++;
77cb5caa98Sdjl linep++;
78cb5caa98Sdjl }
79cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) {
80cb5caa98Sdjl if (__nss_files_get_addr(type, addrstart, addrlen,
817257d1b4Sraf addrp, v6flag, addrsize)) {
82cb5caa98Sdjl *namelen = linep - *namep;
837c478bd9Sstevel@tonic-gate return (1);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate }
86cb5caa98Sdjl while (linep < limit && !isspace(*linep))
87cb5caa98Sdjl linep++;
88cb5caa98Sdjl *namelen = linep - *namep;
89cb5caa98Sdjl
90cb5caa98Sdjl /* Aliases */
91cb5caa98Sdjl while (linep < limit) {
92cb5caa98Sdjl /* skip the delimiting spaces */
93cb5caa98Sdjl while (linep < limit && isspace(*linep))
94cb5caa98Sdjl linep++;
95cb5caa98Sdjl
96cb5caa98Sdjl /* compare name (case insensitive) */
97cb5caa98Sdjl keyp = argp->key.name;
98cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) &&
997257d1b4Sraf tolower(*keyp) == tolower(*linep)) {
100cb5caa98Sdjl keyp++;
101cb5caa98Sdjl linep++;
102cb5caa98Sdjl }
103cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep)))
104cb5caa98Sdjl return (__nss_files_get_addr(type, addrstart, addrlen,
1057257d1b4Sraf addrp, v6flag, addrsize));
106cb5caa98Sdjl
107cb5caa98Sdjl /* skip remainder of alias, if any */
108cb5caa98Sdjl while (linep < limit && !isspace(*linep))
109cb5caa98Sdjl linep++;
110cb5caa98Sdjl }
1117c478bd9Sstevel@tonic-gate return (0);
112cb5caa98Sdjl
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate static nss_status_t
getbyname(be,a)1167c478bd9Sstevel@tonic-gate getbyname(be, a)
1177c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
1187c478bd9Sstevel@tonic-gate void *a;
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
1217c478bd9Sstevel@tonic-gate nss_status_t res;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET);
1247c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS)
1257c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res);
1267c478bd9Sstevel@tonic-gate return (res);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
129cb5caa98Sdjl static int
__nss_files_get_addr(int af,const char * addrstart,int addrlen,void * addrp,int v6flag,int * h_length)130cb5caa98Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen,
131cb5caa98Sdjl void *addrp, int v6flag, int *h_length)
132cb5caa98Sdjl {
133cb5caa98Sdjl struct in_addr addr_ipv4;
134cb5caa98Sdjl struct in6_addr *addrpv6;
135cb5caa98Sdjl in_addr_t *addrpv4;
136cb5caa98Sdjl char addrbuf[INET6_ADDRSTRLEN + 1];
137cb5caa98Sdjl
138cb5caa98Sdjl if (addrlen >= sizeof (addrbuf))
139cb5caa98Sdjl return (0);
140cb5caa98Sdjl (void) memcpy(addrbuf, addrstart, addrlen);
141cb5caa98Sdjl addrbuf[addrlen] = '\0';
142cb5caa98Sdjl
143cb5caa98Sdjl if (af == AF_INET) {
144cb5caa98Sdjl addrpv4 = (in_addr_t *)addrp;
145cb5caa98Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU)
146cb5caa98Sdjl return (0);
147cb5caa98Sdjl *h_length = sizeof (in_addr_t);
148cb5caa98Sdjl } else if (af == AF_INET6) {
149cb5caa98Sdjl addrpv6 = (struct in6_addr *)addrp;
150cb5caa98Sdjl if (v6flag) {
151cb5caa98Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1)
152cb5caa98Sdjl return (0);
153cb5caa98Sdjl } else {
154cb5caa98Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) ==
1557257d1b4Sraf 0xffffffffU)
156cb5caa98Sdjl return (0);
157cb5caa98Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6);
158cb5caa98Sdjl }
159cb5caa98Sdjl *h_length = sizeof (struct in6_addr);
160cb5caa98Sdjl } else {
161cb5caa98Sdjl return (0);
162cb5caa98Sdjl }
163cb5caa98Sdjl return (1);
164cb5caa98Sdjl }
165cb5caa98Sdjl
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate int
__nss_files_check_addr(int af,nss_XbyY_args_t * argp,const char * line,int linelen)168cb5caa98Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line,
169cb5caa98Sdjl int linelen)
1707c478bd9Sstevel@tonic-gate {
171cb5caa98Sdjl const char *limit, *linep, *addrstart;
172cb5caa98Sdjl int v6flag = 0, addrlen, h_length;
173cb5caa98Sdjl in_addr_t addr_ipv4;
174cb5caa98Sdjl struct in6_addr addr_ipv6;
175cb5caa98Sdjl char *h_addrp;
176cb5caa98Sdjl
177cb5caa98Sdjl /* Compare the address type */
178cb5caa98Sdjl if (argp->key.hostaddr.type != af)
179cb5caa98Sdjl return (0);
1807c478bd9Sstevel@tonic-gate
181cb5caa98Sdjl /* Retrieve the address */
182cb5caa98Sdjl if (af == AF_INET)
183cb5caa98Sdjl h_addrp = (char *)&addr_ipv4;
184cb5caa98Sdjl else
185cb5caa98Sdjl h_addrp = (char *)&addr_ipv6;
186cb5caa98Sdjl linep = line;
187cb5caa98Sdjl limit = line + linelen;
188cb5caa98Sdjl addrstart = linep;
189cb5caa98Sdjl while (linep < limit && !isspace(*linep)) {
190cb5caa98Sdjl if (*linep == ':')
191cb5caa98Sdjl v6flag++;
192cb5caa98Sdjl linep++;
193cb5caa98Sdjl }
194cb5caa98Sdjl addrlen = linep - addrstart;
195cb5caa98Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp,
1967257d1b4Sraf v6flag, &h_length) == 0)
197cb5caa98Sdjl return (0);
198cb5caa98Sdjl
199cb5caa98Sdjl /* Compare the address */
200cb5caa98Sdjl return (h_length == argp->key.hostaddr.len &&
2017257d1b4Sraf memcmp(h_addrp, argp->key.hostaddr.addr,
2027257d1b4Sraf argp->key.hostaddr.len) == 0);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
205cb5caa98Sdjl static int
check_addr(nss_XbyY_args_t * argp,const char * line,int linelen)206cb5caa98Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
207cb5caa98Sdjl {
208cb5caa98Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen));
209cb5caa98Sdjl }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate static nss_status_t
getbyaddr(be,a)2127c478bd9Sstevel@tonic-gate getbyaddr(be, a)
2137c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
2147c478bd9Sstevel@tonic-gate void *a;
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2177c478bd9Sstevel@tonic-gate nss_status_t res;
2187c478bd9Sstevel@tonic-gate
219cb5caa98Sdjl res = _nss_files_XY_all(be, argp, 1, 0, check_addr);
2207c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS)
2217c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res);
2227c478bd9Sstevel@tonic-gate return (res);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
225c77e7dfdSchinlong /*
226c77e7dfdSchinlong * filter_ipv6
227c77e7dfdSchinlong *
228c77e7dfdSchinlong * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address
229c77e7dfdSchinlong * NSS_STR_PARSE_PARSE: An IPv6 address or other errors
230c77e7dfdSchinlong */
231c77e7dfdSchinlong static int
filter_ipv6(char * instr,int lenstr)232c77e7dfdSchinlong filter_ipv6(char *instr, int lenstr) {
233c77e7dfdSchinlong char *p, *addrstart, *limit, c;
234c77e7dfdSchinlong int rc;
235c77e7dfdSchinlong struct in_addr addr;
236c77e7dfdSchinlong
237c77e7dfdSchinlong p = instr;
238c77e7dfdSchinlong limit = p + lenstr;
239c77e7dfdSchinlong
240c77e7dfdSchinlong addrstart = p;
241c77e7dfdSchinlong
242c77e7dfdSchinlong /* parse IP address */
243c77e7dfdSchinlong while (p < limit && !isspace(*p)) {
244c77e7dfdSchinlong if (*p == ':')
245c77e7dfdSchinlong /* IPv6 */
246c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE);
247c77e7dfdSchinlong else
248c77e7dfdSchinlong p++;
249c77e7dfdSchinlong }
250c77e7dfdSchinlong
251c77e7dfdSchinlong if (p >= limit)
252c77e7dfdSchinlong /* invalid IP */
253c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE);
254c77e7dfdSchinlong
255c77e7dfdSchinlong /* extract IP address */
256c77e7dfdSchinlong c = *p;
257c77e7dfdSchinlong *p = '\0';
2587257d1b4Sraf rc = inet_aton(addrstart, &addr);
259c77e7dfdSchinlong *p = c;
260c77e7dfdSchinlong
261c77e7dfdSchinlong if (rc == 0)
262c77e7dfdSchinlong /* invalid IP */
263c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE);
264c77e7dfdSchinlong else
265c77e7dfdSchinlong /* IPv4 */
266c77e7dfdSchinlong return (NSS_STR_PARSE_SUCCESS);
267c77e7dfdSchinlong
268c77e7dfdSchinlong
269c77e7dfdSchinlong }
270c77e7dfdSchinlong static nss_status_t
getent_hosts(files_backend_ptr_t be,void * a)271c77e7dfdSchinlong getent_hosts(files_backend_ptr_t be, void *a)
272c77e7dfdSchinlong {
273c77e7dfdSchinlong nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
274c77e7dfdSchinlong nss_status_t rc = NSS_SUCCESS;
275c77e7dfdSchinlong
276c77e7dfdSchinlong if (args->buf.result != NULL) {
277c77e7dfdSchinlong return (_nss_files_XY_all(be, args, 1, 0, 0));
278c77e7dfdSchinlong } else {
279c77e7dfdSchinlong /*
280c77e7dfdSchinlong * Called by nscd
281c77e7dfdSchinlong */
282c77e7dfdSchinlong /*CONSTCOND*/
283c77e7dfdSchinlong while (1) {
284c77e7dfdSchinlong rc = _nss_files_XY_all(be, args, 1, 0, 0);
285c77e7dfdSchinlong /*
286c77e7dfdSchinlong * NSS_NOTFOUND, end of file or other errors.
287c77e7dfdSchinlong */
288c77e7dfdSchinlong if (rc != NSS_SUCCESS)
289c77e7dfdSchinlong break;
290c77e7dfdSchinlong /*
291c77e7dfdSchinlong * /etc/hosts and /etc/ipnodes are merged and
292c77e7dfdSchinlong * /etc/hosts can contain IPv6 addresses.
293c77e7dfdSchinlong * These addresses have to be filtered.
294c77e7dfdSchinlong */
295c77e7dfdSchinlong if (filter_ipv6(args->returnval, args->returnlen)
2967257d1b4Sraf == NSS_STR_PARSE_SUCCESS)
297c77e7dfdSchinlong break;
298c77e7dfdSchinlong /*
299c77e7dfdSchinlong * The entry is an IPv6 address or other errors.
300c77e7dfdSchinlong * Skip it and continue to find next one.
301c77e7dfdSchinlong */
302c77e7dfdSchinlong args->returnval = NULL;
303c77e7dfdSchinlong args->returnlen = 0;
304c77e7dfdSchinlong
305c77e7dfdSchinlong }
306c77e7dfdSchinlong return (rc);
307c77e7dfdSchinlong }
308c77e7dfdSchinlong
309c77e7dfdSchinlong }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate static files_backend_op_t host_ops[] = {
3127c478bd9Sstevel@tonic-gate _nss_files_destr,
3137c478bd9Sstevel@tonic-gate _nss_files_endent,
3147c478bd9Sstevel@tonic-gate _nss_files_setent,
315c77e7dfdSchinlong getent_hosts,
3167c478bd9Sstevel@tonic-gate getbyname,
3177c478bd9Sstevel@tonic-gate getbyaddr,
3187c478bd9Sstevel@tonic-gate };
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3217c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_files_hosts_constr(dummy1,dummy2,dummy3)3227c478bd9Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3)
3237c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3;
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate return (_nss_files_constr(host_ops,
3267c478bd9Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]),
3277c478bd9Sstevel@tonic-gate _PATH_HOSTS,
3287c478bd9Sstevel@tonic-gate NSS_LINELEN_HOSTS,
3297c478bd9Sstevel@tonic-gate NULL));
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep
3357c478bd9Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case.
3367c478bd9Sstevel@tonic-gate */
3377c478bd9Sstevel@tonic-gate nss_status_t
__nss_files_XY_hostbyname(be,args,filter,type)3387c478bd9Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type)
3397c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
3407c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args;
3417c478bd9Sstevel@tonic-gate const char *filter; /* hint for name string */
3427c478bd9Sstevel@tonic-gate int type;
3437c478bd9Sstevel@tonic-gate {
344cb5caa98Sdjl nss_status_t res;
345cb5caa98Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end;
346cb5caa98Sdjl char *first, *last, *buffer;
347cb5caa98Sdjl int parsestat, i, nhosts = 0, buflen;
348cb5caa98Sdjl const char *namep;
349cb5caa98Sdjl char *h_name;
350cb5caa98Sdjl int h_namelen, namelen;
351cb5caa98Sdjl struct hostent *hp;
352cb5caa98Sdjl in_addr_t *taddr = NULL;
353cb5caa98Sdjl struct in6_addr *taddr6 = NULL;
354cb5caa98Sdjl size_t ntaddr;
355cb5caa98Sdjl void *addrp;
356cb5caa98Sdjl char *alias_end = NULL;
357cb5caa98Sdjl
358cb5caa98Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) {
3597c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate if (be->f == 0) {
3637c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS)
3647c478bd9Sstevel@tonic-gate return (res);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate
367cb5caa98Sdjl ntaddr = MAXADDRS;
368cb5caa98Sdjl if (type == AF_INET) {
369cb5caa98Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr));
370cb5caa98Sdjl if (taddr == NULL)
371cb5caa98Sdjl return (NSS_UNAVAIL);
372cb5caa98Sdjl } else {
373cb5caa98Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6));
374cb5caa98Sdjl if (taddr6 == NULL)
375cb5caa98Sdjl return (NSS_UNAVAIL);
376cb5caa98Sdjl }
377cb5caa98Sdjl
3787c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND;
3797c478bd9Sstevel@tonic-gate args->returnval = (char *)0;
380cb5caa98Sdjl args->returnlen = 0;
381cb5caa98Sdjl hp = (struct hostent *)args->buf.result;
382cb5caa98Sdjl buffer = args->buf.buffer;
383cb5caa98Sdjl buflen = args->buf.buflen;
384cb5caa98Sdjl h_namelen = 0;
385cb5caa98Sdjl h_name = NULL;
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate for (;;) {
3887c478bd9Sstevel@tonic-gate char *instr = be->buf;
3897c478bd9Sstevel@tonic-gate int linelen;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f,
3927c478bd9Sstevel@tonic-gate instr, be->minbuf)) < 0) {
3937c478bd9Sstevel@tonic-gate break; /* EOF */
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate * This check avoids a malloc()/free() for the common
3987c478bd9Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an
3997c478bd9Sstevel@tonic-gate * already matched entry doesn't share a canonical name
4007c478bd9Sstevel@tonic-gate * with the current one, bail.
4017c478bd9Sstevel@tonic-gate */
4027c478bd9Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) {
4037c478bd9Sstevel@tonic-gate continue;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0)
4077c478bd9Sstevel@tonic-gate last = instr + linelen;
4087c478bd9Sstevel@tonic-gate *last-- = '\0';
4097c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++)
4107c478bd9Sstevel@tonic-gate ;
4117c478bd9Sstevel@tonic-gate /* Ignore blank and comment lines */
4127c478bd9Sstevel@tonic-gate if (*first == '\0')
4137c478bd9Sstevel@tonic-gate continue;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate while (isspace(*last))
4167c478bd9Sstevel@tonic-gate --last;
4177c478bd9Sstevel@tonic-gate linelen = last - first + 1;
4187c478bd9Sstevel@tonic-gate if (first != instr)
4197c478bd9Sstevel@tonic-gate instr = first;
4207c478bd9Sstevel@tonic-gate
421cb5caa98Sdjl /* Bail out if the canonical name does not match */
422cb5caa98Sdjl if (nhosts && strcasestr(instr, h_name) == 0) {
4237c478bd9Sstevel@tonic-gate continue;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint.
4287c478bd9Sstevel@tonic-gate */
429cb5caa98Sdjl addrp = (type == AF_INET)?
430cb5caa98Sdjl (void *)&taddr[nhosts]:
431cb5caa98Sdjl (void *)&taddr6[nhosts];
432cb5caa98Sdjl
433cb5caa98Sdjl if (check_name(args, instr, linelen,
434cb5caa98Sdjl type, &namep, &namelen,
435cb5caa98Sdjl addrp, &i)) {
4367c478bd9Sstevel@tonic-gate
437cb5caa98Sdjl /*
438cb5caa98Sdjl * If we've already matched once and have a possible
439cb5caa98Sdjl * match on this line, copy the aliases where they're
440cb5caa98Sdjl * safe from being overwritten when we look at the
441cb5caa98Sdjl * next entry. They're saved as a string of blank
442cb5caa98Sdjl * separated names for the alias parser. On errors,
443cb5caa98Sdjl * we return failure whether or not we have already
444cb5caa98Sdjl * obtained a valid address.
445cb5caa98Sdjl */
446cb5caa98Sdjl if (nhosts == 1 && hp) {
447cb5caa98Sdjl if (h_namelen + 1 > args->buf.buflen) {
448cb5caa98Sdjl args->erange = 1;
449cb5caa98Sdjl res = NSS_NOTFOUND;
450cb5caa98Sdjl break;
451cb5caa98Sdjl }
452cb5caa98Sdjl abuf = (char *)malloc(args->buf.buflen);
453cb5caa98Sdjl if (abuf == NULL) {
454cb5caa98Sdjl res = NSS_UNAVAIL;
455cb5caa98Sdjl break;
456cb5caa98Sdjl }
457cb5caa98Sdjl abuf_start = abuf;
458cb5caa98Sdjl abuf_end = abuf_start + args->buf.buflen;
459cb5caa98Sdjl (void) memcpy(abuf, h_name, h_namelen);
460cb5caa98Sdjl abuf += h_namelen;
461cb5caa98Sdjl *abuf = '\0';
462cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end);
463cb5caa98Sdjl if (abuf == NULL) {
464cb5caa98Sdjl args->erange = 1;
465cb5caa98Sdjl res = NSS_NOTFOUND;
466cb5caa98Sdjl break;
467cb5caa98Sdjl }
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate
470cb5caa98Sdjl if (hp != NULL) {
471cb5caa98Sdjl /* inside the application */
472cb5caa98Sdjl parsestat = (*args->str2ent)(instr, linelen,
473cb5caa98Sdjl hp, buffer, buflen);
474cb5caa98Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) {
475cb5caa98Sdjl if (parsestat == NSS_STR_PARSE_ERANGE)
476cb5caa98Sdjl args->erange = 1;
477cb5caa98Sdjl (void) memset(buffer, 0, buflen);
478cb5caa98Sdjl continue;
479cb5caa98Sdjl }
480cb5caa98Sdjl } else {
481cb5caa98Sdjl /* inside nscd */
482cb5caa98Sdjl int alen, cplen, erange = 0;
483cb5caa98Sdjl char *ap;
484cb5caa98Sdjl
485cb5caa98Sdjl /* Add alias to the first line if any */
486cb5caa98Sdjl if (nhosts > 0) {
487cb5caa98Sdjl
488cb5caa98Sdjl /* get to the start of alias */
489cb5caa98Sdjl ap = (char *)namep + namelen;
490cb5caa98Sdjl /* see if there's any alias */
491cb5caa98Sdjl if (ap == instr + linelen)
492cb5caa98Sdjl alen = 0;
493cb5caa98Sdjl else
494cb5caa98Sdjl alen = linelen - (ap - instr);
495cb5caa98Sdjl if (alen + 1 >= buflen)
496cb5caa98Sdjl erange = 1;
497cb5caa98Sdjl if (erange == 0 && alen != 0) {
498cb5caa98Sdjl /* make room for the alias */
499cb5caa98Sdjl if (alias_end != NULL)
500cb5caa98Sdjl (void) memmove(alias_end +
501cb5caa98Sdjl alen, alias_end, buffer -
502cb5caa98Sdjl alias_end);
503cb5caa98Sdjl /* copy in the alias */
504cb5caa98Sdjl (void) memmove(alias_end,
505cb5caa98Sdjl ap, alen);
506cb5caa98Sdjl buffer += alen;
507cb5caa98Sdjl buflen -= alen;
508c70a8a3bSmichen args->returnlen += alen;
509cb5caa98Sdjl alias_end += alen;
510cb5caa98Sdjl }
511cb5caa98Sdjl
512cb5caa98Sdjl /* Add delimiter to the buffer */
513cb5caa98Sdjl *buffer++ = '\n';
514cb5caa98Sdjl buflen--;
515cb5caa98Sdjl args->returnlen++;
516cb5caa98Sdjl }
517cb5caa98Sdjl
518cb5caa98Sdjl /* copy just the addr if not first one */
519cb5caa98Sdjl if (alias_end == NULL)
520cb5caa98Sdjl cplen = linelen;
521cb5caa98Sdjl else
522cb5caa98Sdjl cplen = namep - instr;
523cb5caa98Sdjl
524cb5caa98Sdjl if (cplen >= buflen || erange == 1) {
525cb5caa98Sdjl args->erange = 1;
526cb5caa98Sdjl if (nhosts > 0) {
527cb5caa98Sdjl *(--buffer) = '\0';
528cb5caa98Sdjl buflen++;
529cb5caa98Sdjl args->returnlen--;
530cb5caa98Sdjl }
531cb5caa98Sdjl continue;
532cb5caa98Sdjl }
533cb5caa98Sdjl
534cb5caa98Sdjl (void) memcpy(buffer, instr, cplen);
535cb5caa98Sdjl /* Adjust buffer */
536cb5caa98Sdjl buffer += cplen;
537cb5caa98Sdjl *buffer = '\0';
538cb5caa98Sdjl buflen -= cplen;
539c70a8a3bSmichen args->returnlen += cplen;
540cb5caa98Sdjl if (alias_end == NULL)
541cb5caa98Sdjl alias_end = buffer;
542cb5caa98Sdjl }
543cb5caa98Sdjl
544cb5caa98Sdjl /*
545cb5caa98Sdjl * If this is the first one, save the canonical
546cb5caa98Sdjl * name for future matches and continue.
547cb5caa98Sdjl */
548cb5caa98Sdjl if (++nhosts == 1) {
549cb5caa98Sdjl h_name = malloc(namelen + 1);
550cb5caa98Sdjl if (h_name == NULL) {
551cb5caa98Sdjl res = NSS_UNAVAIL;
552cb5caa98Sdjl break;
553cb5caa98Sdjl }
5547c478bd9Sstevel@tonic-gate res = NSS_SUCCESS;
555cb5caa98Sdjl (void) memcpy(h_name, namep, namelen);
556cb5caa98Sdjl h_name[namelen] = '\0';
557cb5caa98Sdjl h_namelen = namelen;
558cb5caa98Sdjl if (hp)
559cb5caa98Sdjl args->returnval = hp;
560cb5caa98Sdjl else
561cb5caa98Sdjl args->returnval = args->buf.buffer;
5627c478bd9Sstevel@tonic-gate continue;
5637c478bd9Sstevel@tonic-gate }
564cb5caa98Sdjl
565cb5caa98Sdjl
566cb5caa98Sdjl /* Extend the array */
567cb5caa98Sdjl if (nhosts >= ntaddr) {
568cb5caa98Sdjl ntaddr *= 2;
569cb5caa98Sdjl if (type == AF_INET) {
570cb5caa98Sdjl addrp = realloc(taddr,
571cb5caa98Sdjl sizeof (*taddr) * ntaddr);
572cb5caa98Sdjl if (addrp == NULL) {
573cb5caa98Sdjl res = NSS_UNAVAIL;
574cb5caa98Sdjl break;
575cb5caa98Sdjl }
576cb5caa98Sdjl taddr = (in_addr_t *)addrp;
577cb5caa98Sdjl } else {
578cb5caa98Sdjl addrp = realloc(taddr6,
579cb5caa98Sdjl sizeof (*taddr6) * ntaddr);
580cb5caa98Sdjl if (addrp == NULL) {
581cb5caa98Sdjl res = NSS_UNAVAIL;
582cb5caa98Sdjl break;
583cb5caa98Sdjl }
584cb5caa98Sdjl taddr6 = (struct in6_addr *)addrp;
585cb5caa98Sdjl }
586cb5caa98Sdjl }
587cb5caa98Sdjl
588cb5caa98Sdjl /*
589cb5caa98Sdjl * For non-nscd, save aliases in a temporary buffer
590cb5caa98Sdjl * Don't have to do this for nscd as 'buffer' already
591cb5caa98Sdjl * contains the required data in the appropriate
592cb5caa98Sdjl * format
593cb5caa98Sdjl */
594cb5caa98Sdjl if (hp) {
595cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end);
596cb5caa98Sdjl if (abuf == NULL) {
597cb5caa98Sdjl args->erange = 1;
598cb5caa98Sdjl res = NSS_NOTFOUND;
599cb5caa98Sdjl break;
600cb5caa98Sdjl }
6017c478bd9Sstevel@tonic-gate }
602cb5caa98Sdjl } else if (namep && h_namelen == namelen &&
603cb5caa98Sdjl strncasecmp(h_name, namep, namelen) == 0) {
6047c478bd9Sstevel@tonic-gate /*
6057c478bd9Sstevel@tonic-gate * This line didn't have the requested name but
6067c478bd9Sstevel@tonic-gate * is part of the same multihomed host (i.e. it
6077c478bd9Sstevel@tonic-gate * has the same canonical name as the previous
6087c478bd9Sstevel@tonic-gate * line), so march on...
6097c478bd9Sstevel@tonic-gate */
6107c478bd9Sstevel@tonic-gate continue;
6117c478bd9Sstevel@tonic-gate } else if (nhosts) {
612e37190e5Smichen continue;
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
616cb5caa98Sdjl if (abuf && res == NSS_SUCCESS) {
617cb5caa98Sdjl
618cb5caa98Sdjl /* abuf != NULL implies hp and abuf_start != NULL */
619cb5caa98Sdjl
6207c478bd9Sstevel@tonic-gate struct in_addr *addrp;
6217c478bd9Sstevel@tonic-gate struct in6_addr *addrp6;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate if (type == AF_INET) {
6247c478bd9Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer +
6257c478bd9Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp)));
6267c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp -
6277c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) +
6287c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *)));
6297c478bd9Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) {
6307c478bd9Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i];
6317c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp;
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate } else {
6347c478bd9Sstevel@tonic-gate addrp6 = (struct in6_addr *)
6357c478bd9Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen,
6367c478bd9Sstevel@tonic-gate sizeof (*addrp6)));
6377c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 -
6387c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) +
6397c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *)));
6407c478bd9Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) {
641cb5caa98Sdjl (void) memcpy(addrp6, &taddr6[i],
642cb5caa98Sdjl sizeof (struct in6_addr));
6437c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6;
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0;
6487c478bd9Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start,
6497c478bd9Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer,
6507c478bd9Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer);
6517c478bd9Sstevel@tonic-gate if (hp->h_aliases == 0) {
6527c478bd9Sstevel@tonic-gate args->erange = 1;
653cb5caa98Sdjl res = NSS_NOTFOUND;
6547c478bd9Sstevel@tonic-gate } else {
6557c478bd9Sstevel@tonic-gate hp->h_name = hp->h_aliases[0];
6567c478bd9Sstevel@tonic-gate hp->h_aliases++;
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate /*
6617c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened
6627c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1.
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate if (!args->stayopen)
6657c478bd9Sstevel@tonic-gate (void) _nss_files_endent(be, 0);
6667c478bd9Sstevel@tonic-gate
667cb5caa98Sdjl if (taddr)
668cb5caa98Sdjl free(taddr);
669cb5caa98Sdjl if (taddr6)
670cb5caa98Sdjl free(taddr6);
671cb5caa98Sdjl if (h_name)
672cb5caa98Sdjl free(h_name);
673cb5caa98Sdjl if (abuf_start)
674cb5caa98Sdjl free(abuf_start);
675cb5caa98Sdjl
6767c478bd9Sstevel@tonic-gate return (res);
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate static char *
do_aliases(struct hostent * hp,char * abuf,char * end)681cb5caa98Sdjl do_aliases(struct hostent *hp, char *abuf, char *end)
6827c478bd9Sstevel@tonic-gate {
683cb5caa98Sdjl char **cp;
684cb5caa98Sdjl size_t len;
6857c478bd9Sstevel@tonic-gate
686cb5caa98Sdjl if ((cp = hp->h_aliases) == NULL)
687cb5caa98Sdjl return (abuf);
6887c478bd9Sstevel@tonic-gate
689cb5caa98Sdjl for (; *cp; cp++) {
6907c478bd9Sstevel@tonic-gate len = strlen(*cp);
6917c478bd9Sstevel@tonic-gate if (abuf+len+1 >= end) {
692cb5caa98Sdjl return (NULL);
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate *abuf++ = ' ';
695cb5caa98Sdjl (void) memcpy(abuf, *cp, len);
696cb5caa98Sdjl abuf += len;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate *abuf = '\0';
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate return (abuf);
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate /*
7057c478bd9Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is
7067c478bd9Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines
7077c478bd9Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync.
7087c478bd9Sstevel@tonic-gate */
7097c478bd9Sstevel@tonic-gate int
__nss_files_2herrno(nsstat)7107c478bd9Sstevel@tonic-gate __nss_files_2herrno(nsstat)
7117c478bd9Sstevel@tonic-gate nss_status_t nsstat;
7127c478bd9Sstevel@tonic-gate {
7137c478bd9Sstevel@tonic-gate switch (nsstat) {
7147c478bd9Sstevel@tonic-gate case NSS_SUCCESS:
7157c478bd9Sstevel@tonic-gate /* no macro-defined success code for h_errno */
7167c478bd9Sstevel@tonic-gate return (0);
7177c478bd9Sstevel@tonic-gate case NSS_NOTFOUND:
7187c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND);
7197c478bd9Sstevel@tonic-gate case NSS_TRYAGAIN:
7207c478bd9Sstevel@tonic-gate return (TRY_AGAIN);
7217c478bd9Sstevel@tonic-gate case NSS_UNAVAIL:
7227c478bd9Sstevel@tonic-gate return (NO_RECOVERY);
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate /* anything else */
7257c478bd9Sstevel@tonic-gate return (NO_RECOVERY);
7267c478bd9Sstevel@tonic-gate }
727