xref: /onnv-gate/usr/src/cmd/fs.d/autofs/ns_generic.c (revision 0:68f95e015346)
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  *	ns_generic.c
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26*0Sstevel@tonic-gate  * Use is subject to license terms.
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <syslog.h>
33*0Sstevel@tonic-gate #include <string.h>
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <nsswitch.h>
36*0Sstevel@tonic-gate #include <sys/param.h>
37*0Sstevel@tonic-gate #include <netdb.h>
38*0Sstevel@tonic-gate #include <errno.h>
39*0Sstevel@tonic-gate #include <assert.h>
40*0Sstevel@tonic-gate #include <rpc/rpc.h>
41*0Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h>
42*0Sstevel@tonic-gate #include "automount.h"
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate  * Each name service is represented by a ns_info structure.
46*0Sstevel@tonic-gate  */
47*0Sstevel@tonic-gate struct ns_info {
48*0Sstevel@tonic-gate 	char	*ns_name;		/* service name */
49*0Sstevel@tonic-gate 	void	(*ns_init)();		/* initialization routine */
50*0Sstevel@tonic-gate 	int	(*ns_getmapent)();	/* get map entry given key */
51*0Sstevel@tonic-gate 	int	(*ns_loadmaster)();	/* load master map */
52*0Sstevel@tonic-gate 	int	(*ns_loaddirect)();	/* load direct map */
53*0Sstevel@tonic-gate 	int	(*ns_getmapkeys)();	/* readdir */
54*0Sstevel@tonic-gate };
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate static struct ns_info ns_info[] = {
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 	"files",   init_files,  getmapent_files,
59*0Sstevel@tonic-gate 	loadmaster_files, loaddirect_files,
60*0Sstevel@tonic-gate 	getmapkeys_files,
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	"ldap",   init_ldap,  getmapent_ldap,
63*0Sstevel@tonic-gate 	loadmaster_ldap, loaddirect_ldap,
64*0Sstevel@tonic-gate 	getmapkeys_ldap,
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate 	"nisplus", init_nisplus, getmapent_nisplus,
67*0Sstevel@tonic-gate 	loadmaster_nisplus, loaddirect_nisplus,
68*0Sstevel@tonic-gate 	getmapkeys_nisplus,
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	"nis",	   init_nis,	getmapent_nis,
71*0Sstevel@tonic-gate 	loadmaster_nis,   loaddirect_nis,
72*0Sstevel@tonic-gate 	getmapkeys_nis,
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 	NULL, NULL, NULL, NULL, NULL, NULL, NULL
75*0Sstevel@tonic-gate };
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate static struct ns_info *get_next_ns(struct __nsw_lookup **, int);
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate void
80*0Sstevel@tonic-gate ns_setup(char **stack, char ***stkptr)
81*0Sstevel@tonic-gate {
82*0Sstevel@tonic-gate 	struct ns_info *nsp;
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	for (nsp = ns_info; nsp->ns_name; nsp++) {
85*0Sstevel@tonic-gate 		nsp->ns_init(stack, stkptr);
86*0Sstevel@tonic-gate 	}
87*0Sstevel@tonic-gate }
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate static struct ns_info *
90*0Sstevel@tonic-gate get_next_ns(curr_ns, curr_nserr)
91*0Sstevel@tonic-gate 	struct __nsw_lookup **curr_ns;
92*0Sstevel@tonic-gate 	int curr_nserr;
93*0Sstevel@tonic-gate {
94*0Sstevel@tonic-gate 	static struct __nsw_switchconfig *conf = NULL;
95*0Sstevel@tonic-gate 	enum __nsw_parse_err pserr;
96*0Sstevel@tonic-gate 	struct __nsw_lookup *lkp;
97*0Sstevel@tonic-gate 	struct ns_info *nsp;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	if (conf == NULL) {
100*0Sstevel@tonic-gate 		/* __nsw_getconfig() is protected by a lock */
101*0Sstevel@tonic-gate 		conf = __nsw_getconfig("automount", &pserr);
102*0Sstevel@tonic-gate 		if (conf == NULL) {
103*0Sstevel@tonic-gate 			return (NULL);
104*0Sstevel@tonic-gate 		}
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	if (*curr_ns == NULL)
108*0Sstevel@tonic-gate 		/* first time */
109*0Sstevel@tonic-gate 		lkp = conf->lookups;
110*0Sstevel@tonic-gate 	else {
111*0Sstevel@tonic-gate 		lkp = *curr_ns;
112*0Sstevel@tonic-gate 		/* __NSW_ACTION is MT-Safe */
113*0Sstevel@tonic-gate 		if (__NSW_ACTION(lkp, curr_nserr) == __NSW_RETURN)
114*0Sstevel@tonic-gate 			return (NULL);
115*0Sstevel@tonic-gate 		lkp = lkp->next;
116*0Sstevel@tonic-gate 	}
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	for (; lkp; lkp = lkp->next) {
119*0Sstevel@tonic-gate 		for (nsp = ns_info; nsp->ns_name; nsp++) {
120*0Sstevel@tonic-gate 			if (strcmp(lkp->service_name, nsp->ns_name) == 0) {
121*0Sstevel@tonic-gate 				*curr_ns = lkp;
122*0Sstevel@tonic-gate 				return (nsp);
123*0Sstevel@tonic-gate 			}
124*0Sstevel@tonic-gate 		}
125*0Sstevel@tonic-gate 		/*
126*0Sstevel@tonic-gate 		 * Note: if we get here then we've found
127*0Sstevel@tonic-gate 		 * an unsupported name service.
128*0Sstevel@tonic-gate 		 */
129*0Sstevel@tonic-gate 	}
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 	return (NULL);
132*0Sstevel@tonic-gate }
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate int
135*0Sstevel@tonic-gate getmapent(key, mapname, ml, stack, stkptr, iswildcard, isrestricted)
136*0Sstevel@tonic-gate 	char *key, *mapname;
137*0Sstevel@tonic-gate 	struct mapline *ml;
138*0Sstevel@tonic-gate 	char **stack, ***stkptr;
139*0Sstevel@tonic-gate 	bool_t *iswildcard;
140*0Sstevel@tonic-gate 	bool_t isrestricted;
141*0Sstevel@tonic-gate {
142*0Sstevel@tonic-gate 	struct __nsw_lookup *curr_ns = NULL;
143*0Sstevel@tonic-gate 	int ns_err = __NSW_SUCCESS;
144*0Sstevel@tonic-gate 	struct ns_info *nsp;
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	if (strcmp(mapname, "-hosts") == 0) {
147*0Sstevel@tonic-gate 		(void) strcpy(ml->linebuf, "-hosts");
148*0Sstevel@tonic-gate 		return (__NSW_SUCCESS);
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	if (*mapname == '/') 		/* must be a file */
152*0Sstevel@tonic-gate 		return (getmapent_files(key, mapname, ml, stack, stkptr,
153*0Sstevel@tonic-gate 					iswildcard, isrestricted));
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
156*0Sstevel@tonic-gate 		ns_err = nsp->ns_getmapent(key, mapname, ml, stack, stkptr,
157*0Sstevel@tonic-gate 						iswildcard, isrestricted);
158*0Sstevel@tonic-gate 		if (ns_err == __NSW_SUCCESS)
159*0Sstevel@tonic-gate 			return (__NSW_SUCCESS);
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	return (__NSW_UNAVAIL);
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate int
166*0Sstevel@tonic-gate loadmaster_map(mapname, defopts, stack, stkptr)
167*0Sstevel@tonic-gate 	char *mapname, *defopts;
168*0Sstevel@tonic-gate 	char **stack, ***stkptr;
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate 	struct __nsw_lookup *curr_ns = NULL;
171*0Sstevel@tonic-gate 	int ns_err = __NSW_SUCCESS;
172*0Sstevel@tonic-gate 	struct ns_info *nsp;
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	if (*mapname == '/')		/* must be a file */
175*0Sstevel@tonic-gate 		return (loadmaster_files(mapname, defopts, stack, stkptr));
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
178*0Sstevel@tonic-gate 		ns_err = nsp->ns_loadmaster(mapname, defopts, stack, stkptr);
179*0Sstevel@tonic-gate 		if (ns_err == __NSW_SUCCESS)
180*0Sstevel@tonic-gate 			return (__NSW_SUCCESS);
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	return (__NSW_UNAVAIL);
184*0Sstevel@tonic-gate }
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate loaddirect_map(mapname, localmap, defopts, stack, stkptr)
187*0Sstevel@tonic-gate 	char *mapname, *localmap, *defopts;
188*0Sstevel@tonic-gate 	char **stack, ***stkptr;
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	struct __nsw_lookup *curr_ns = NULL;
191*0Sstevel@tonic-gate 	int ns_err = __NSW_SUCCESS;
192*0Sstevel@tonic-gate 	struct ns_info *nsp;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	if (*mapname == '/')		/* must be a file */
195*0Sstevel@tonic-gate 		return (loaddirect_files(mapname, localmap, defopts,
196*0Sstevel@tonic-gate 				stack, stkptr));
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
199*0Sstevel@tonic-gate 		ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack,
200*0Sstevel@tonic-gate 					stkptr);
201*0Sstevel@tonic-gate 		if (ns_err == __NSW_SUCCESS)
202*0Sstevel@tonic-gate 			return (__NSW_SUCCESS);
203*0Sstevel@tonic-gate 	}
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	return (__NSW_UNAVAIL);
206*0Sstevel@tonic-gate }
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate int
209*0Sstevel@tonic-gate gethostkeys(mapname, list, error, cache_time)
210*0Sstevel@tonic-gate 	char *mapname;
211*0Sstevel@tonic-gate 	struct dir_entry **list;
212*0Sstevel@tonic-gate 	int *error;
213*0Sstevel@tonic-gate 	int *cache_time;
214*0Sstevel@tonic-gate {
215*0Sstevel@tonic-gate 	char *buffer, **p;
216*0Sstevel@tonic-gate 	int bufferlen = 1000;
217*0Sstevel@tonic-gate 	struct dir_entry *last = NULL;
218*0Sstevel@tonic-gate 	struct hostent ent;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate #ifdef lint
221*0Sstevel@tonic-gate 	mapname = mapname;
222*0Sstevel@tonic-gate #endif
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	*cache_time = RDDIR_CACHE_TIME * 2;
225*0Sstevel@tonic-gate 	*error = 0;
226*0Sstevel@tonic-gate 	if (trace  > 1)
227*0Sstevel@tonic-gate 		trace_prt(1, "gethostkeys called\n");
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	if (sethostent(1)) {
230*0Sstevel@tonic-gate 		syslog(LOG_ERR, "gethostkeys: sethostent failed");
231*0Sstevel@tonic-gate 		*error = EIO;
232*0Sstevel@tonic-gate 		return (__NSW_UNAVAIL);
233*0Sstevel@tonic-gate 	}
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	buffer = (char *)malloc(bufferlen);
236*0Sstevel@tonic-gate 	if (buffer == NULL) {
237*0Sstevel@tonic-gate 		syslog(LOG_ERR, "gethostkeys: malloc of buffer failed");
238*0Sstevel@tonic-gate 		*error = ENOMEM;
239*0Sstevel@tonic-gate 		return (__NSW_UNAVAIL);
240*0Sstevel@tonic-gate 	}
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	while (gethostent_r(&ent, buffer, bufferlen, error)) {
243*0Sstevel@tonic-gate 		/*
244*0Sstevel@tonic-gate 		 * add canonical name
245*0Sstevel@tonic-gate 		 */
246*0Sstevel@tonic-gate 		if (add_dir_entry(ent.h_name, list, &last)) {
247*0Sstevel@tonic-gate 			*error = ENOMEM;
248*0Sstevel@tonic-gate 			goto done;
249*0Sstevel@tonic-gate 		}
250*0Sstevel@tonic-gate 		if (ent.h_aliases == NULL)
251*0Sstevel@tonic-gate 			goto done;	/* no aliases */
252*0Sstevel@tonic-gate 		for (p = ent.h_aliases; *p != 0; p++) {
253*0Sstevel@tonic-gate 			if (strcmp(*p, ent.h_name) != 0) {
254*0Sstevel@tonic-gate 				/*
255*0Sstevel@tonic-gate 				 * add alias only if different
256*0Sstevel@tonic-gate 				 * from canonical name
257*0Sstevel@tonic-gate 				 */
258*0Sstevel@tonic-gate 				if (add_dir_entry(*p, list, &last)) {
259*0Sstevel@tonic-gate 					*error = ENOMEM;
260*0Sstevel@tonic-gate 					goto done;
261*0Sstevel@tonic-gate 				}
262*0Sstevel@tonic-gate 			}
263*0Sstevel@tonic-gate 		}
264*0Sstevel@tonic-gate 		assert(last != NULL);
265*0Sstevel@tonic-gate 	}
266*0Sstevel@tonic-gate done:	if (*list != NULL) {
267*0Sstevel@tonic-gate 		/*
268*0Sstevel@tonic-gate 		 * list of entries found
269*0Sstevel@tonic-gate 		 */
270*0Sstevel@tonic-gate 		*error = 0;
271*0Sstevel@tonic-gate 	}
272*0Sstevel@tonic-gate 	endhostent();
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	return (__NSW_SUCCESS);
275*0Sstevel@tonic-gate }
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate /*
278*0Sstevel@tonic-gate  * enumerate all entries in the map in the various name services.
279*0Sstevel@tonic-gate  */
280*0Sstevel@tonic-gate getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid)
281*0Sstevel@tonic-gate 	char *mapname;
282*0Sstevel@tonic-gate 	struct dir_entry **list;
283*0Sstevel@tonic-gate 	int *error;
284*0Sstevel@tonic-gate 	int *cache_time;
285*0Sstevel@tonic-gate 	char **stack, ***stkptr;
286*0Sstevel@tonic-gate 	uid_t uid;
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate {
289*0Sstevel@tonic-gate 	struct __nsw_lookup *curr_ns = NULL;
290*0Sstevel@tonic-gate 	int ns_err = __NSW_SUCCESS;
291*0Sstevel@tonic-gate 	int success = 0;
292*0Sstevel@tonic-gate 	struct ns_info *nsp;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	if (*mapname == '/') 		/* must be a file */
295*0Sstevel@tonic-gate 		return (getmapkeys_files(mapname, list, error, cache_time,
296*0Sstevel@tonic-gate 				stack, stkptr));
297*0Sstevel@tonic-gate 	if (strcmp(mapname, "-hosts") == 0) {
298*0Sstevel@tonic-gate 		return (gethostkeys(mapname, list, error, cache_time));
299*0Sstevel@tonic-gate 	}
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
302*0Sstevel@tonic-gate 		ns_err = nsp->ns_getmapkeys(mapname, list, error,
303*0Sstevel@tonic-gate 				cache_time, stack, stkptr);
304*0Sstevel@tonic-gate 		if (*error == 0) {
305*0Sstevel@tonic-gate 			/*
306*0Sstevel@tonic-gate 			 * return success if listing was successful
307*0Sstevel@tonic-gate 			 * for at least one name service
308*0Sstevel@tonic-gate 			 */
309*0Sstevel@tonic-gate 			success++;
310*0Sstevel@tonic-gate 		}
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 		/*
313*0Sstevel@tonic-gate 		 * XXX force next name service
314*0Sstevel@tonic-gate 		 */
315*0Sstevel@tonic-gate 		if (ns_err != __NSW_UNAVAIL)
316*0Sstevel@tonic-gate 			ns_err = __NSW_NOTFOUND;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 	if (success) {
319*0Sstevel@tonic-gate 		/*
320*0Sstevel@tonic-gate 		 * if succeeded at least once, return error=0
321*0Sstevel@tonic-gate 		 */
322*0Sstevel@tonic-gate 		*error = 0;
323*0Sstevel@tonic-gate 	};
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	return (success ? __NSW_SUCCESS : __NSW_NOTFOUND);
326*0Sstevel@tonic-gate }
327