xref: /illumos-gate/usr/src/cmd/fs.d/autofs/ns_generic.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2005 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 int
187 loaddirect_map(mapname, localmap, defopts, stack, stkptr)
188 	char *mapname, *localmap, *defopts;
189 	char **stack, ***stkptr;
190 {
191 	struct __nsw_lookup *curr_ns = NULL;
192 	int ns_err = __NSW_SUCCESS;
193 	struct ns_info *nsp;
194 
195 	if (*mapname == '/')		/* must be a file */
196 		return (loaddirect_files(mapname, localmap, defopts,
197 				stack, stkptr));
198 
199 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
200 		ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack,
201 					stkptr);
202 		if (ns_err == __NSW_SUCCESS)
203 			return (__NSW_SUCCESS);
204 	}
205 
206 	return (__NSW_UNAVAIL);
207 }
208 
209 int
210 gethostkeys(mapname, list, error, cache_time)
211 	char *mapname;
212 	struct dir_entry **list;
213 	int *error;
214 	int *cache_time;
215 {
216 	char *buffer, **p;
217 	int bufferlen = 1000;
218 	struct dir_entry *last = NULL;
219 	struct hostent ent;
220 
221 #ifdef lint
222 	mapname = mapname;
223 #endif
224 
225 	*cache_time = RDDIR_CACHE_TIME * 2;
226 	*error = 0;
227 	if (trace  > 1)
228 		trace_prt(1, "gethostkeys called\n");
229 
230 	if (sethostent(1)) {
231 		syslog(LOG_ERR, "gethostkeys: sethostent failed");
232 		*error = EIO;
233 		return (__NSW_UNAVAIL);
234 	}
235 
236 	buffer = (char *)malloc(bufferlen);
237 	if (buffer == NULL) {
238 		syslog(LOG_ERR, "gethostkeys: malloc of buffer failed");
239 		*error = ENOMEM;
240 		return (__NSW_UNAVAIL);
241 	}
242 
243 	while (gethostent_r(&ent, buffer, bufferlen, error)) {
244 		/*
245 		 * add canonical name
246 		 */
247 		if (add_dir_entry(ent.h_name, list, &last)) {
248 			*error = ENOMEM;
249 			goto done;
250 		}
251 		if (ent.h_aliases == NULL)
252 			goto done;	/* no aliases */
253 		for (p = ent.h_aliases; *p != 0; p++) {
254 			if (strcmp(*p, ent.h_name) != 0) {
255 				/*
256 				 * add alias only if different
257 				 * from canonical name
258 				 */
259 				if (add_dir_entry(*p, list, &last)) {
260 					*error = ENOMEM;
261 					goto done;
262 				}
263 			}
264 		}
265 		assert(last != NULL);
266 	}
267 done:	if (*list != NULL) {
268 		/*
269 		 * list of entries found
270 		 */
271 		*error = 0;
272 	}
273 	endhostent();
274 
275 	return (__NSW_SUCCESS);
276 }
277 
278 /*
279  * enumerate all entries in the map in the various name services.
280  */
281 int
282 getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid)
283 	char *mapname;
284 	struct dir_entry **list;
285 	int *error;
286 	int *cache_time;
287 	char **stack, ***stkptr;
288 	uid_t uid;
289 
290 {
291 	struct __nsw_lookup *curr_ns = NULL;
292 	int ns_err = __NSW_SUCCESS;
293 	int success = 0;
294 	struct ns_info *nsp;
295 
296 	if (*mapname == '/') 		/* must be a file */
297 		return (getmapkeys_files(mapname, list, error, cache_time,
298 				stack, stkptr));
299 	if (strcmp(mapname, "-hosts") == 0) {
300 		return (gethostkeys(mapname, list, error, cache_time));
301 	}
302 
303 	while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
304 		ns_err = nsp->ns_getmapkeys(mapname, list, error,
305 				cache_time, stack, stkptr);
306 		if (*error == 0) {
307 			/*
308 			 * return success if listing was successful
309 			 * for at least one name service
310 			 */
311 			success++;
312 		}
313 
314 		/*
315 		 * XXX force next name service
316 		 */
317 		if (ns_err != __NSW_UNAVAIL)
318 			ns_err = __NSW_NOTFOUND;
319 	}
320 	if (success) {
321 		/*
322 		 * if succeeded at least once, return error=0
323 		 */
324 		*error = 0;
325 	};
326 
327 	return (success ? __NSW_SUCCESS : __NSW_NOTFOUND);
328 }
329