1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <netdb.h>
30*0Sstevel@tonic-gate #include <arpa/inet.h>
31*0Sstevel@tonic-gate #include <netinet/in.h>
32*0Sstevel@tonic-gate #include <sys/socket.h>
33*0Sstevel@tonic-gate #include <syslog.h>
34*0Sstevel@tonic-gate #include <sys/systeminfo.h>
35*0Sstevel@tonic-gate #include "ns_internal.h"
36*0Sstevel@tonic-gate #include "ldap_common.h"
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /* host attributes filters */
39*0Sstevel@tonic-gate #define	_H_DN			"dn"
40*0Sstevel@tonic-gate #define	_H_NAME			"cn"
41*0Sstevel@tonic-gate #define	_H_ADDR			"iphostnumber"
42*0Sstevel@tonic-gate #define	_F_GETHOSTBYNAME	"(&(objectClass=ipHost)(cn=%s))"
43*0Sstevel@tonic-gate #define	_F_GETHOSTBYNAME_SSD	"(&(%%s)(cn=%s))"
44*0Sstevel@tonic-gate #define	_F_GETHOSTDOTTEDBYNAME	"(&(objectClass=ipHost)(|(cn=%s)(cn=%s)))"
45*0Sstevel@tonic-gate #define	_F_GETHOSTDOTTEDBYNAME_SSD "(&(%%s)(|(cn=%s)(cn=%s)))"
46*0Sstevel@tonic-gate #define	_F_GETHOSTBYADDR	"(&(objectClass=ipHost)(ipHostNumber=%s))"
47*0Sstevel@tonic-gate #define	_F_GETHOSTBYADDR_SSD	"(&(%%s)(ipHostNumber=%s))"
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate static const char *hosts_attrs[] = {
50*0Sstevel@tonic-gate 	_H_NAME,
51*0Sstevel@tonic-gate 	_H_ADDR,
52*0Sstevel@tonic-gate 	(char *)NULL
53*0Sstevel@tonic-gate };
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate /*
57*0Sstevel@tonic-gate  * _nss_ldap_hosts2ent is the data marshaling method for the hosts getXbyY
58*0Sstevel@tonic-gate  * system call gethostbyname() and gethostbyaddr. The format of this call
59*0Sstevel@tonic-gate  * is a cononical name and alias (alias is cononical name too) and one or
60*0Sstevel@tonic-gate  * more IP addresses in support of multihomed hosts. This method is called
61*0Sstevel@tonic-gate  * after a successful synchronous search has been performed. This method
62*0Sstevel@tonic-gate  * will parse the search results into struct hostent = argp->buf.buffer
63*0Sstevel@tonic-gate  * which gets returned to the frontend process. One of three error
64*0Sstevel@tonic-gate  * conditions is also returned to nsswitch.
65*0Sstevel@tonic-gate  */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static int
68*0Sstevel@tonic-gate _nss_ldap_hosts2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
69*0Sstevel@tonic-gate {
70*0Sstevel@tonic-gate 	int			i, j;
71*0Sstevel@tonic-gate 	int			nss_result;
72*0Sstevel@tonic-gate 	int			buflen = (int)0;
73*0Sstevel@tonic-gate 	int			firstimename = (int)1;
74*0Sstevel@tonic-gate 	int			firstimedn   = (int)1;
75*0Sstevel@tonic-gate 	int			firstimeaddr = (int)1;
76*0Sstevel@tonic-gate 	unsigned long		len = 0L;
77*0Sstevel@tonic-gate 	char			**hn, **ha, **dp;
78*0Sstevel@tonic-gate 	char			*cname = (char *)NULL;
79*0Sstevel@tonic-gate 	char			*buffer = (char *)NULL;
80*0Sstevel@tonic-gate 	char			*ceiling = (char *)NULL;
81*0Sstevel@tonic-gate 	struct hostent		*host = (struct hostent *)NULL;
82*0Sstevel@tonic-gate 	in_addr_t		addr;
83*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
84*0Sstevel@tonic-gate 	ns_ldap_attr_t		*attrptr;
85*0Sstevel@tonic-gate 	in_addr_t		inet_addr(const char *cp);
86*0Sstevel@tonic-gate 	int			namecount = 0;
87*0Sstevel@tonic-gate 	int			addrcount = 0;
88*0Sstevel@tonic-gate 	int			aliascount = 0;
89*0Sstevel@tonic-gate 	int			validaddress = 0;
90*0Sstevel@tonic-gate 	int			gluelen = 0;
91*0Sstevel@tonic-gate 	ns_ldap_entry_t		*entry;
92*0Sstevel@tonic-gate 	ns_ldap_attr_t		*attr;
93*0Sstevel@tonic-gate #ifdef DEBUG
94*0Sstevel@tonic-gate 	struct in_addr		in;
95*0Sstevel@tonic-gate #endif /* DEBUG */
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	buffer = argp->buf.buffer;
98*0Sstevel@tonic-gate 	buflen = (size_t)argp->buf.buflen;
99*0Sstevel@tonic-gate 	if (!argp->buf.result) {
100*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_ERANGE;
101*0Sstevel@tonic-gate 		goto result_hosts2ent;
102*0Sstevel@tonic-gate 	}
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	host = (struct hostent *)argp->buf.result;
105*0Sstevel@tonic-gate 	ceiling = buffer + buflen;
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
108*0Sstevel@tonic-gate 	(void) memset(argp->buf.buffer, 0, buflen);
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 	attrptr = getattr(result, 0);
111*0Sstevel@tonic-gate 	if (attrptr == NULL) {
112*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
113*0Sstevel@tonic-gate 		goto result_hosts2ent;
114*0Sstevel@tonic-gate 	}
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	namecount = 0;
117*0Sstevel@tonic-gate 	addrcount = 0;
118*0Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
119*0Sstevel@tonic-gate 		for (i = 0, attr = entry->attr_pair[i];
120*0Sstevel@tonic-gate 			i < entry->attr_count; i++) {
121*0Sstevel@tonic-gate 			attr = entry->attr_pair[i];
122*0Sstevel@tonic-gate 			if (strcasecmp(attr->attrname, _H_NAME) == 0)
123*0Sstevel@tonic-gate 				namecount += attr->value_count;
124*0Sstevel@tonic-gate 			if (strcasecmp(attr->attrname, _H_ADDR) == 0)
125*0Sstevel@tonic-gate 				addrcount += attr->value_count;
126*0Sstevel@tonic-gate 		}
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
129*0Sstevel@tonic-gate 	    for (i = 0; i < entry->attr_count; i++) {
130*0Sstevel@tonic-gate 		attrptr = entry->attr_pair[i];
131*0Sstevel@tonic-gate 		if (attrptr == NULL) {
132*0Sstevel@tonic-gate 			nss_result = (int)NSS_STR_PARSE_PARSE;
133*0Sstevel@tonic-gate 			goto result_hosts2ent;
134*0Sstevel@tonic-gate 		}
135*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _H_DN) == 0) {
136*0Sstevel@tonic-gate 		    for (j = 0; j < attrptr->value_count; j++) {
137*0Sstevel@tonic-gate 			if (firstimedn) {
138*0Sstevel@tonic-gate 			    /* get domain name associated with this dn */
139*0Sstevel@tonic-gate 			    be->toglue = _get_domain_name(
140*0Sstevel@tonic-gate 					attrptr->attrvalue[j]);
141*0Sstevel@tonic-gate 			    firstimedn = (int)0;
142*0Sstevel@tonic-gate 			}
143*0Sstevel@tonic-gate 		    }
144*0Sstevel@tonic-gate 		}
145*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _H_NAME) == 0) {
146*0Sstevel@tonic-gate 		    for (j = 0; j < attrptr->value_count; j++) {
147*0Sstevel@tonic-gate 			if (firstimename) {
148*0Sstevel@tonic-gate 			    /* canonical name */
149*0Sstevel@tonic-gate 			    cname = __s_api_get_canonical_name(result->entry,
150*0Sstevel@tonic-gate 				attrptr, 1);
151*0Sstevel@tonic-gate 			    if (cname == NULL ||
152*0Sstevel@tonic-gate 				    (len = strlen(cname)) < 1) {
153*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_PARSE;
154*0Sstevel@tonic-gate 				goto result_hosts2ent;
155*0Sstevel@tonic-gate 			    }
156*0Sstevel@tonic-gate 			    if (be->toglue != NULL &&
157*0Sstevel@tonic-gate 				!DOTTEDSUBDOMAIN(cname))
158*0Sstevel@tonic-gate 				gluelen = strlen(be->toglue) + 1;
159*0Sstevel@tonic-gate 			    else
160*0Sstevel@tonic-gate 				gluelen = 0;
161*0Sstevel@tonic-gate 			    host->h_name = buffer;
162*0Sstevel@tonic-gate 			    buffer += len + gluelen + 1;
163*0Sstevel@tonic-gate 			    if (buffer >= ceiling) {
164*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_ERANGE;
165*0Sstevel@tonic-gate 				goto result_hosts2ent;
166*0Sstevel@tonic-gate 			    }
167*0Sstevel@tonic-gate 			    (void) strcpy(host->h_name, cname);
168*0Sstevel@tonic-gate 			    if (gluelen > 0) {
169*0Sstevel@tonic-gate 				(void) strcat(host->h_name, ".");
170*0Sstevel@tonic-gate 				(void) strcat(host->h_name, be->toglue);
171*0Sstevel@tonic-gate 			    }
172*0Sstevel@tonic-gate 			    /* alias name */
173*0Sstevel@tonic-gate 			    aliascount = (namecount >= 1 ? (namecount - 1) : 0);
174*0Sstevel@tonic-gate 			    hn = host->h_aliases = (char **)ROUND_UP(buffer,
175*0Sstevel@tonic-gate 				sizeof (char **));
176*0Sstevel@tonic-gate 			    buffer = (char *)host->h_aliases +
177*0Sstevel@tonic-gate 				(sizeof (char *) * (aliascount + 1));
178*0Sstevel@tonic-gate 			    buffer = (char *)ROUND_UP(buffer,
179*0Sstevel@tonic-gate 				sizeof (char **));
180*0Sstevel@tonic-gate 			    if (buffer >= ceiling) {
181*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_ERANGE;
182*0Sstevel@tonic-gate 				goto result_hosts2ent;
183*0Sstevel@tonic-gate 			    }
184*0Sstevel@tonic-gate 			    firstimename = (int)0;
185*0Sstevel@tonic-gate 			}
186*0Sstevel@tonic-gate 			/* alias list */
187*0Sstevel@tonic-gate 			if (aliascount > 0) {
188*0Sstevel@tonic-gate 				if ((attrptr->attrvalue[j] == NULL) ||
189*0Sstevel@tonic-gate 				    (len = strlen(attrptr->attrvalue[j])) < 1) {
190*0Sstevel@tonic-gate 				    nss_result = (int)NSS_STR_PARSE_PARSE;
191*0Sstevel@tonic-gate 				    goto result_hosts2ent;
192*0Sstevel@tonic-gate 				}
193*0Sstevel@tonic-gate 				/* skip canonical name */
194*0Sstevel@tonic-gate 				if (strcmp(cname, attrptr->attrvalue[j]) == 0)
195*0Sstevel@tonic-gate 					continue;
196*0Sstevel@tonic-gate 				/* check for duplicates */
197*0Sstevel@tonic-gate 				for (dp = host->h_aliases; *dp != NULL; dp++) {
198*0Sstevel@tonic-gate 				    if (strcmp(*dp, attrptr->attrvalue[j]) == 0)
199*0Sstevel@tonic-gate 					goto next_alias;
200*0Sstevel@tonic-gate 				}
201*0Sstevel@tonic-gate 				if (be->toglue != NULL &&
202*0Sstevel@tonic-gate 					!DOTTEDSUBDOMAIN(attrptr->attrvalue[j]))
203*0Sstevel@tonic-gate 					gluelen = strlen(be->toglue) + 1;
204*0Sstevel@tonic-gate 				else
205*0Sstevel@tonic-gate 					gluelen = 0;
206*0Sstevel@tonic-gate 				*hn = buffer;
207*0Sstevel@tonic-gate 				buffer += len + gluelen + 1;
208*0Sstevel@tonic-gate 				if (buffer >= ceiling) {
209*0Sstevel@tonic-gate 				    nss_result = (int)NSS_STR_PARSE_ERANGE;
210*0Sstevel@tonic-gate 				    goto result_hosts2ent;
211*0Sstevel@tonic-gate 				}
212*0Sstevel@tonic-gate 				(void) strcpy(*hn, attrptr->attrvalue[j]);
213*0Sstevel@tonic-gate 				if (gluelen > 0) {
214*0Sstevel@tonic-gate 				    (void) strcat(*hn, ".");
215*0Sstevel@tonic-gate 				    (void) strcat(*hn, be->toglue);
216*0Sstevel@tonic-gate 				}
217*0Sstevel@tonic-gate 				hn++;
218*0Sstevel@tonic-gate 			}
219*0Sstevel@tonic-gate next_alias:
220*0Sstevel@tonic-gate 			continue;
221*0Sstevel@tonic-gate 		    }
222*0Sstevel@tonic-gate 		}
223*0Sstevel@tonic-gate 	    }
224*0Sstevel@tonic-gate 	}
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
227*0Sstevel@tonic-gate 	    for (i = 0; i < entry->attr_count; i++) {
228*0Sstevel@tonic-gate 		attrptr = entry->attr_pair[i];
229*0Sstevel@tonic-gate 		if (attrptr == NULL) {
230*0Sstevel@tonic-gate 		    nss_result = (int)NSS_STR_PARSE_PARSE;
231*0Sstevel@tonic-gate 		    goto result_hosts2ent;
232*0Sstevel@tonic-gate 		}
233*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _H_ADDR) == 0) {
234*0Sstevel@tonic-gate 		    for (j = 0; j < attrptr->value_count; j++) {
235*0Sstevel@tonic-gate 			if (firstimeaddr) {
236*0Sstevel@tonic-gate 			    /* allocate 1 address per entry */
237*0Sstevel@tonic-gate 			    ha = host->h_addr_list =
238*0Sstevel@tonic-gate 				(char **)ROUND_UP(buffer,
239*0Sstevel@tonic-gate 				sizeof (char **));
240*0Sstevel@tonic-gate 			    buffer = (char *)host->h_addr_list +
241*0Sstevel@tonic-gate 				sizeof (char *) *
242*0Sstevel@tonic-gate 				(addrcount + 1);
243*0Sstevel@tonic-gate 			    buffer = (char *)ROUND_UP(buffer,
244*0Sstevel@tonic-gate 				sizeof (char **));
245*0Sstevel@tonic-gate 			    if (buffer >= ceiling) {
246*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_ERANGE;
247*0Sstevel@tonic-gate 				goto result_hosts2ent;
248*0Sstevel@tonic-gate 			    }
249*0Sstevel@tonic-gate 			    firstimeaddr = (int)0;
250*0Sstevel@tonic-gate 			}
251*0Sstevel@tonic-gate 			/* filter out IPV6 addresses */
252*0Sstevel@tonic-gate 			addr = inet_addr(_strip_quotes(attrptr->attrvalue[j]));
253*0Sstevel@tonic-gate 			if (addr == (in_addr_t)-1) {
254*0Sstevel@tonic-gate 			    goto next_addr;
255*0Sstevel@tonic-gate 			}
256*0Sstevel@tonic-gate 			validaddress++;
257*0Sstevel@tonic-gate 			/* check for duplicates */
258*0Sstevel@tonic-gate 			for (dp = host->h_addr_list; *dp != NULL; dp++) {
259*0Sstevel@tonic-gate 			if (memcmp(*dp, &addr, (size_t)sizeof (in_addr_t)) == 0)
260*0Sstevel@tonic-gate 			    goto next_addr;
261*0Sstevel@tonic-gate 			}
262*0Sstevel@tonic-gate 			*ha = buffer;
263*0Sstevel@tonic-gate 			len = (unsigned long)sizeof (in_addr_t);
264*0Sstevel@tonic-gate 			buffer += len;
265*0Sstevel@tonic-gate 			if (buffer >= ceiling) {
266*0Sstevel@tonic-gate 			    nss_result = (int)NSS_STR_PARSE_ERANGE;
267*0Sstevel@tonic-gate 			    goto result_hosts2ent;
268*0Sstevel@tonic-gate 			}
269*0Sstevel@tonic-gate 			(void) memcpy(*ha++, (char *)&addr, (size_t)len);
270*0Sstevel@tonic-gate next_addr:
271*0Sstevel@tonic-gate 			continue;
272*0Sstevel@tonic-gate 		    }
273*0Sstevel@tonic-gate 		}
274*0Sstevel@tonic-gate 	    }
275*0Sstevel@tonic-gate 	}
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	if (validaddress == 0) {
278*0Sstevel@tonic-gate 	    nss_result = (int)NSS_STR_PARSE_NO_ADDR;
279*0Sstevel@tonic-gate 	    goto result_hosts2ent;
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	host->h_addrtype = AF_INET;
283*0Sstevel@tonic-gate 	host->h_length = sizeof (uint_t);
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate #ifdef DEBUG
286*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts2ent]\n");
287*0Sstevel@tonic-gate 	(void) fprintf(stdout, "        h_name: [%s]\n", host->h_name);
288*0Sstevel@tonic-gate 	if (host->h_aliases != NULL) {
289*0Sstevel@tonic-gate 		for (hn = host->h_aliases; *hn != NULL; hn++)
290*0Sstevel@tonic-gate 			(void) fprintf(stdout, "     h_aliases: [%s]\n", *hn);
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 	(void) fprintf(stdout, "    h_addrtype: [%d]\n", host->h_addrtype);
293*0Sstevel@tonic-gate 	(void) fprintf(stdout, "      h_length: [%d]\n", host->h_length);
294*0Sstevel@tonic-gate 	for (ha = host->h_addr_list; *ha != NULL; ha++) {
295*0Sstevel@tonic-gate 		(void) memcpy(&in.s_addr, *ha, sizeof (in.s_addr));
296*0Sstevel@tonic-gate 		if (inet_ntoa(in) != NULL)
297*0Sstevel@tonic-gate 			(void) fprintf(stdout, "   h_addr_list: [%s]\n",
298*0Sstevel@tonic-gate 				inet_ntoa(in));
299*0Sstevel@tonic-gate 		else
300*0Sstevel@tonic-gate 			(void) fprintf(stdout, "   h_addr_list: <NULL>\n");
301*0Sstevel@tonic-gate 	}
302*0Sstevel@tonic-gate #endif /* DEBUG */
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate result_hosts2ent:
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
307*0Sstevel@tonic-gate 	return ((int)nss_result);
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate /*
312*0Sstevel@tonic-gate  * getbyname gets a struct hostent by hostname. This function constructs
313*0Sstevel@tonic-gate  * an ldap search filter using the name invocation parameter and the
314*0Sstevel@tonic-gate  * gethostbyname search filter defined. Once the filter is constructed,
315*0Sstevel@tonic-gate  * we search for a matching entry and marshal the data results into
316*0Sstevel@tonic-gate  * struct hostent for the frontend process.  Host name searches will be
317*0Sstevel@tonic-gate  * on fully qualified host names (foo.bar.sun.com)
318*0Sstevel@tonic-gate  */
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate static nss_status_t
321*0Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
322*0Sstevel@tonic-gate {
323*0Sstevel@tonic-gate 	char		hostname[3 * MAXHOSTNAMELEN];
324*0Sstevel@tonic-gate 	char		realdomain[BUFSIZ];
325*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
326*0Sstevel@tonic-gate 	nss_status_t	lstat;
327*0Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
328*0Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
329*0Sstevel@tonic-gate 	int		rc;
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 	if (_ldap_filter_name(hostname, argp->key.name, sizeof (hostname)) != 0)
332*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	rc = snprintf(searchfilter, sizeof (searchfilter), _F_GETHOSTBYNAME,
335*0Sstevel@tonic-gate 	    hostname);
336*0Sstevel@tonic-gate 	if (rc >= sizeof (searchfilter) || rc < 0)
337*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 	rc = snprintf(userdata, sizeof (userdata), _F_GETHOSTBYNAME_SSD,
340*0Sstevel@tonic-gate 	    hostname);
341*0Sstevel@tonic-gate 	if (rc >= sizeof (userdata) || rc < 0)
342*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	/* get the domain we are in */
345*0Sstevel@tonic-gate 	rc = sysinfo(SI_SRPC_DOMAIN, realdomain, BUFSIZ);
346*0Sstevel@tonic-gate 	if (rc <= 0)
347*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	/* Is this a request for a host.domain */
350*0Sstevel@tonic-gate 	if (DOTTEDSUBDOMAIN(hostname)) {
351*0Sstevel@tonic-gate 		char	host[MAXHOSTNAMELEN];
352*0Sstevel@tonic-gate 		char	domain[MAXHOSTNAMELEN];
353*0Sstevel@tonic-gate 		char	hname[3 * MAXHOSTNAMELEN];
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 		/* separate host and domain.  this function */
356*0Sstevel@tonic-gate 		/* will munge hname, so use argp->keyname */
357*0Sstevel@tonic-gate 		/* from here on for original string */
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 		(void) strcpy(hname, hostname);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 		if (chophostdomain(hname, host, domain) == -1) {
362*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
363*0Sstevel@tonic-gate 		}
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 		/* if domain is a proper subset of realdomain */
366*0Sstevel@tonic-gate 		/* ie. domain = "eng" and realdomain */
367*0Sstevel@tonic-gate 		/* = "eng.wiz.com", we try to lookup both" */
368*0Sstevel@tonic-gate 		/* host.domain and host */
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 		if (propersubdomain(realdomain, domain) == 1) {
371*0Sstevel@tonic-gate 			/* yes, it is a proper domain */
372*0Sstevel@tonic-gate 			rc = snprintf(searchfilter, sizeof (searchfilter),
373*0Sstevel@tonic-gate 			    _F_GETHOSTDOTTEDBYNAME, hostname, host);
374*0Sstevel@tonic-gate 			if (rc >= sizeof (searchfilter) || rc < 0)
375*0Sstevel@tonic-gate 				return ((nss_status_t)NSS_NOTFOUND);
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 			rc = snprintf(userdata, sizeof (userdata),
378*0Sstevel@tonic-gate 			    _F_GETHOSTDOTTEDBYNAME_SSD, hostname, host);
379*0Sstevel@tonic-gate 			if (rc >= sizeof (userdata) || rc < 0)
380*0Sstevel@tonic-gate 				return ((nss_status_t)NSS_NOTFOUND);
381*0Sstevel@tonic-gate 		} else {
382*0Sstevel@tonic-gate 			/* it is not a proper domain, so only try to look up */
383*0Sstevel@tonic-gate 			/* host.domain */
384*0Sstevel@tonic-gate 			rc = snprintf(searchfilter, sizeof (searchfilter),
385*0Sstevel@tonic-gate 			    _F_GETHOSTBYNAME, hostname);
386*0Sstevel@tonic-gate 			if (rc >= sizeof (searchfilter) || rc < 0)
387*0Sstevel@tonic-gate 				return ((nss_status_t)NSS_NOTFOUND);
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 			rc = snprintf(userdata, sizeof (userdata),
390*0Sstevel@tonic-gate 			    _F_GETHOSTBYNAME_SSD, hostname);
391*0Sstevel@tonic-gate 			if (rc >= sizeof (userdata) || rc < 0)
392*0Sstevel@tonic-gate 				return ((nss_status_t)NSS_NOTFOUND);
393*0Sstevel@tonic-gate 		}
394*0Sstevel@tonic-gate 	} else {
395*0Sstevel@tonic-gate 		rc = snprintf(searchfilter, sizeof (searchfilter),
396*0Sstevel@tonic-gate 		    _F_GETHOSTBYNAME, hostname);
397*0Sstevel@tonic-gate 		if (rc >= sizeof (searchfilter) || rc < 0)
398*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 		rc = snprintf(userdata, sizeof (userdata),
401*0Sstevel@tonic-gate 		    _F_GETHOSTBYNAME_SSD, hostname);
402*0Sstevel@tonic-gate 		if (rc >= sizeof (userdata) || rc < 0)
403*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
404*0Sstevel@tonic-gate 	}
405*0Sstevel@tonic-gate 	lstat = (nss_status_t)_nss_ldap_lookup(be, argp, _HOSTS,
406*0Sstevel@tonic-gate 		searchfilter, NULL, _merge_SSD_filter,
407*0Sstevel@tonic-gate 		userdata);
408*0Sstevel@tonic-gate 	if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
409*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate 	argp->h_errno = __nss2herrno(lstat);
412*0Sstevel@tonic-gate 	return ((nss_status_t)lstat);
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate /*
417*0Sstevel@tonic-gate  * getbyaddr gets a struct hostent by host address. This function
418*0Sstevel@tonic-gate  * constructs an ldap search filter using the host address invocation
419*0Sstevel@tonic-gate  * parameter and the gethostbyaddr search filter defined. Once the
420*0Sstevel@tonic-gate  * filter is constructed, we search for a matching entry and marshal
421*0Sstevel@tonic-gate  * the data results into struct hostent for the frontend process.
422*0Sstevel@tonic-gate  *
423*0Sstevel@tonic-gate  * extern char *inet_ntoa_r() not an advertised function from libnsl.
424*0Sstevel@tonic-gate  * There is no man page and no prototype.
425*0Sstevel@tonic-gate  */
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate static nss_status_t
428*0Sstevel@tonic-gate getbyaddr(ldap_backend_ptr be, void *a)
429*0Sstevel@tonic-gate {
430*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
431*0Sstevel@tonic-gate 	struct in_addr	addr;
432*0Sstevel@tonic-gate 	char		buf[18];
433*0Sstevel@tonic-gate 	nss_status_t	lstat;
434*0Sstevel@tonic-gate 	extern char	*inet_ntoa_r();
435*0Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
436*0Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
437*0Sstevel@tonic-gate 	int		ret;
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	argp->h_errno = 0;
440*0Sstevel@tonic-gate 	if ((argp->key.hostaddr.type != AF_INET) ||
441*0Sstevel@tonic-gate 	    (argp->key.hostaddr.len != sizeof (addr)))
442*0Sstevel@tonic-gate 		return (NSS_NOTFOUND);
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	(void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
445*0Sstevel@tonic-gate 	(void) inet_ntoa_r(addr, buf);
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETHOSTBYADDR,
448*0Sstevel@tonic-gate 	    buf);
449*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
450*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETHOSTBYADDR_SSD, buf);
453*0Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
454*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate 	lstat = (nss_status_t)_nss_ldap_lookup(be, argp,
457*0Sstevel@tonic-gate 		_HOSTS, searchfilter, NULL, _merge_SSD_filter, userdata);
458*0Sstevel@tonic-gate 	if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
459*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	argp->h_errno = __nss2herrno(lstat);
462*0Sstevel@tonic-gate 	return ((nss_status_t)lstat);
463*0Sstevel@tonic-gate }
464*0Sstevel@tonic-gate 
465*0Sstevel@tonic-gate static ldap_backend_op_t hosts_ops[] = {
466*0Sstevel@tonic-gate 	_nss_ldap_destr,
467*0Sstevel@tonic-gate 	_nss_ldap_endent,
468*0Sstevel@tonic-gate 	_nss_ldap_setent,
469*0Sstevel@tonic-gate 	_nss_ldap_getent,
470*0Sstevel@tonic-gate 	getbyname,
471*0Sstevel@tonic-gate 	getbyaddr
472*0Sstevel@tonic-gate };
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate /*
476*0Sstevel@tonic-gate  * _nss_ldap_hosts_constr is where life begins. This function calls the generic
477*0Sstevel@tonic-gate  * ldap constructor function to define and build the abstract data types
478*0Sstevel@tonic-gate  * required to support ldap operations.
479*0Sstevel@tonic-gate  */
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate /*ARGSUSED0*/
482*0Sstevel@tonic-gate nss_backend_t *
483*0Sstevel@tonic-gate _nss_ldap_hosts_constr(const char *dummy1, const char *dummy2,
484*0Sstevel@tonic-gate 			const char *dummy3)
485*0Sstevel@tonic-gate {
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate #ifdef	DEBUG
488*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts_constr]\n");
489*0Sstevel@tonic-gate #endif	/* DEBUG */
490*0Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(hosts_ops,
491*0Sstevel@tonic-gate 		sizeof (hosts_ops)/sizeof (hosts_ops[0]), _HOSTS,
492*0Sstevel@tonic-gate 		hosts_attrs, _nss_ldap_hosts2ent));
493*0Sstevel@tonic-gate }
494