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