"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