"Fossies" - the Fresh Open Source Software Archive 
Member "nss_ldap-265/doc/lookup_nssldap.c" (6 Nov 2009, 9611 Bytes) of package /linux/privat/old/nss_ldap-265.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 #ident "$Id: lookup_nssldap.c,v 1.4 2006/08/09 13:42:50 lukeh Exp $"
2 /* ----------------------------------------------------------------------- *
3 *
4 * lookup_nss.c - module for Linux automountd to access a NSS
5 * automount map
6 *
7 * Copyright 1997 Transmeta Corporation - All Rights Reserved
8 * Copyright 2001-2003 Ian Kent <raven@themaw.net>
9 * Copyright 2005-2006 PADL Software Pty Ltd - All Rights Reserved
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
14 * USA; either version 2 of the License, or (at your option) any later
15 * version; incorporated herein by reference.
16 *
17 * ----------------------------------------------------------------------- */
18
19 #define _GNU_SOURCE
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <signal.h>
29 #include <netinet/in.h>
30 #include <arpa/nameser.h>
31 #include <resolv.h>
32 #include <dlfcn.h>
33 #include <nss.h>
34
35 #define MODULE_LOOKUP
36 #include "automount.h"
37
38 #define MAPFMT_DEFAULT "sun"
39
40 #define NAMESERVICE "ldap"
41
42 #define MODPREFIX "lookup(nss" NAMESERVICE "): "
43
44 struct lookup_context {
45 char *nsname;
46 char *mapname;
47 struct parse_mod *parse;
48 void *dlhandle;
49 enum nss_status (*setautomntent)(const char *, void **);
50 enum nss_status (*getautomntent_r)(void *, const char **, const char **,
51 char *, size_t, int *);
52 enum nss_status (*endautomntent)(void **);
53 enum nss_status (*getautomntbyname_r)(void *, const char *,
54 const char **, const char **,
55 char *, size_t, int *);
56 };
57
58 int lookup_version = AUTOFS_LOOKUP_VERSION;
59
60 int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context_p)
61 {
62 struct lookup_context *context;
63 char buf[1024];
64
65 context = (struct lookup_context *)malloc(sizeof(*context));
66 if (context == NULL) {
67 crit(MODPREFIX "malloc: %m");
68 return 1;
69 }
70 memset(context, 0, sizeof(*context));
71
72 context->nsname = NULL;
73 context->parse = NULL;
74 context->dlhandle = NULL;
75 context->setautomntent = NULL;
76 context->getautomntent_r = NULL;
77 context->endautomntent = NULL;
78
79 if (mapfmt == NULL) {
80 mapfmt = MAPFMT_DEFAULT;
81 }
82
83 if (argc < 1) {
84 crit(MODPREFIX "invalid number of arguments");
85 return 1;
86 }
87
88 asprintf(&context->nsname, "nss%s", NAMESERVICE);
89 if (context->nsname == NULL) {
90 crit(MODPREFIX "strdup: %m");
91 return 1;
92 }
93
94 snprintf(buf, sizeof(buf), "libnss_%s.so.2", NAMESERVICE);
95
96 context->dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
97 if (context->dlhandle == NULL) {
98 crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
99 return 1;
100 }
101
102 snprintf(buf, sizeof(buf), "_nss_%s_setautomntent", NAMESERVICE);
103 context->setautomntent = dlsym(context->dlhandle, buf);
104 if (context->setautomntent == NULL) {
105 crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
106 return 1;
107 }
108
109 snprintf(buf, sizeof(buf), "_nss_%s_getautomntent_r", NAMESERVICE);
110 context->getautomntent_r = dlsym(context->dlhandle, buf);
111 if (context->getautomntent_r == NULL) {
112 crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
113 return 1;
114 }
115
116 snprintf(buf, sizeof(buf), "_nss_%s_endautomntent", NAMESERVICE);
117 context->endautomntent = dlsym(context->dlhandle, buf);
118 if (context->endautomntent == NULL) {
119 crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
120 return 1;
121 }
122
123 snprintf(buf, sizeof(buf), "_nss_%s_getautomntbyname_r", NAMESERVICE);
124 context->getautomntbyname_r = dlsym(context->dlhandle, buf);
125 if (context->getautomntbyname_r == NULL) {
126 crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
127 return 1;
128 }
129
130 context->mapname = strdup(argv[0]);
131 if (context->mapname == NULL) {
132 crit(MODPREFIX "strdup: %m");
133 return 1;
134 }
135
136 context->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
137 if (context->parse == NULL) {
138 free(context);
139 return 1;
140 }
141
142 *context_p = context;
143 return 0;
144 }
145
146 static const char *nsserr_string(enum nss_status status)
147 {
148 switch (status) {
149 case NSS_STATUS_TRYAGAIN:
150 return "Insufficient buffer space";
151 break;
152 case NSS_STATUS_UNAVAIL:
153 return "Name service unavailable";
154 break;
155 case NSS_STATUS_NOTFOUND:
156 return "Not found";
157 break;
158 case NSS_STATUS_SUCCESS:
159 return "Success";
160 break;
161 default:
162 break;
163 }
164
165 return "Unknown error";
166 }
167
168 static int read_map(const char *root, time_t age, struct lookup_context *context)
169 {
170 enum nss_status status;
171 void *private = NULL;
172 const char *key, *mapent;
173 int nss_errno;
174 char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
175
176 status = (*context->setautomntent)(context->mapname, &private);
177 if (status != NSS_STATUS_SUCCESS) {
178 warn(MODPREFIX "lookup_ghost for map %s failed: %s",
179 context->mapname, nsserr_string(status));
180 return 0;
181 }
182
183 for (;;) {
184 status = (*context->getautomntent_r)(private, &key, &mapent,
185 buffer, sizeof(buffer),
186 &nss_errno);
187 if (status != NSS_STATUS_SUCCESS)
188 break;
189
190 cache_add(root, key, mapent, age);
191 }
192
193 (*context->endautomntent)(&private);
194
195 if (status != NSS_STATUS_SUCCESS && status != NSS_STATUS_NOTFOUND) {
196 warn(MODPREFIX "lookup_ghost for map %s failed: %s",
197 context->mapname, nsserr_string(status));
198 return 0;
199 }
200
201 /* Clean stale entries from the cache */
202 cache_clean(root, age);
203
204 return 1;
205 }
206
207 int lookup_ghost(const char *root, int ghost, time_t now, void *context)
208 {
209 struct lookup_context *ctxt = (struct lookup_context *)context;
210 time_t age = now ? now : time(NULL);
211 struct mapent_cache *me;
212 int status = 1;
213
214 if (!read_map(root, age, ctxt))
215 return LKP_FAIL;
216
217 status = cache_ghost(root, ghost, ctxt->mapname, ctxt->nsname, ctxt->parse);
218
219 me = cache_lookup_first();
220 /* me NULL => empty map */
221 if (me == NULL)
222 return LKP_FAIL;
223
224 if (*me->key == '/' && *(root + 1) != '-') {
225 me = cache_partial_match(root);
226 /* me NULL => no entries for this direct mount root or indirect map */
227 if (me == NULL)
228 return LKP_FAIL | LKP_INDIRECT;
229 }
230
231 return status;
232 }
233
234 int lookup_one(const char *root, const char *key, time_t age, struct lookup_context *ctxt)
235 {
236 enum nss_status status;
237 void *private = NULL;
238 int nss_errno;
239 char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
240 const char *canon_key, *mapent;
241
242 status = (*ctxt->setautomntent)(ctxt->mapname, &private);
243 if (status != NSS_STATUS_SUCCESS) {
244 warn(MODPREFIX "failed to lookup map %s: %s", ctxt->mapname, nsserr_string(status));
245 return CHE_FAIL;
246 }
247
248 status = (*ctxt->getautomntbyname_r)(private, key,
249 &canon_key, &mapent,
250 buffer, sizeof(buffer),
251 &nss_errno);
252
253 (*ctxt->endautomntent)(&private);
254
255 if (status == NSS_STATUS_NOTFOUND) {
256 warn(MODPREFIX "key %s not found in map %s", key, ctxt->mapname);
257 return CHE_MISSING;
258 } else if (status != NSS_STATUS_SUCCESS) {
259 warn(MODPREFIX "failed to read map %s: %s", ctxt->mapname, nsserr_string(status));
260 return CHE_FAIL;
261 }
262
263 /* XXX should we be using canon_key or key */
264 return cache_update(root, canon_key, mapent, age);
265 }
266
267 int lookup_wild(const char *root, time_t age, struct lookup_context *ctxt)
268 {
269 return lookup_one(root, "*", age, ctxt);
270 }
271
272 int lookup_mount(const char *root, const char *name, int name_len, void *context)
273 {
274 struct lookup_context *ctxt = (struct lookup_context *)context;
275 char key[KEY_MAX_LEN + 1];
276 size_t key_len;
277 char mapent[MAPENT_MAX_LEN + 1];
278 struct mapent_cache *me = NULL;
279 int ret;
280 time_t now = time(NULL);
281 time_t t_last_read;
282 int rmdir_if_mount_fails = 0;
283
284 debug(MODPREFIX "looking up %s", name);
285
286 if (ap.type == LKP_DIRECT)
287 key_len = snprintf(key, KEY_MAX_LEN, "%s/%s", root, name);
288 else
289 key_len = snprintf(key, KEY_MAX_LEN, "%s", name);
290
291 if (key_len > KEY_MAX_LEN)
292 return 1;
293
294 /* check map and if change is detected re-read map */
295 ret = lookup_one(root, key, now, ctxt);
296 if (ret == CHE_FAIL)
297 return 1;
298
299 me = cache_lookup_first();
300 t_last_read = (me != NULL) ? now - me->age : ap.exp_runfreq + 1;
301
302 if (ret == CHE_UPDATED) {
303 /* Have parent update its map */
304 if (t_last_read > ap.exp_runfreq)
305 kill(getppid(), SIGHUP);
306 } else if (ret == CHE_MISSING) {
307 if (!cache_delete(root, key, 0)) {
308 rmdir_if_mount_fails = 1;
309 }
310
311 /* Maybe update wild card map entry */
312 if (ap.type == LKP_INDIRECT)
313 ret = lookup_wild(root, now, ctxt);
314
315 /* Have parent update its map */
316 if (t_last_read > ap.exp_runfreq)
317 kill(getppid(), SIGHUP);
318 }
319
320 me = cache_lookup(key);
321 if (me != NULL) {
322 snprintf(mapent, sizeof(mapent), "%s", me->mapent);
323 } else {
324 /* path component, do submount */
325 me = cache_partial_match(key);
326 if (me != NULL) {
327 snprintf(mapent, sizeof(mapent), "-fstype=autofs %s:%s",
328 ctxt->nsname, ctxt->mapname);
329 }
330 }
331
332 if (me == NULL)
333 return 1;
334
335 debug(MODPREFIX "%s -> %s", name, mapent);
336
337 ret = ctxt->parse->parse_mount(root, name, name_len, mapent, ctxt->parse->context);
338
339 if (ret && rmdir_if_mount_fails)
340 rmdir_path(key);
341
342 return ret;
343 }
344
345 int lookup_done(void *context)
346 {
347 struct lookup_context *ctxt = (struct lookup_context *)context;
348 int ret;
349
350 if (ctxt->nsname != NULL) {
351 free(ctxt->nsname);
352 ctxt->nsname = NULL;
353 }
354
355 if (ctxt->mapname != NULL) {
356 free(ctxt->mapname);
357 ctxt->mapname = NULL;
358 }
359
360 ret = close_parse(ctxt->parse);
361
362 if (ctxt->dlhandle != NULL) {
363 dlclose(ctxt->dlhandle);
364 ctxt->dlhandle = NULL;
365 }
366
367 memset(ctxt, 0, sizeof(*ctxt));
368 free(ctxt);
369
370 return ret;
371 }
372