The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/nfs4client/nfs4_idmap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD: releng/5.2/sys/nfs4client/nfs4_idmap.c 122698 2003-11-14 20:54:10Z alfred $ */
    2 /* $Id: nfs4_idmap.c,v 1.4 2003/11/05 14:58:59 rees Exp $ */
    3 
    4 /*
    5  * copyright (c) 2003
    6  * the regents of the university of michigan
    7  * all rights reserved
    8  * 
    9  * permission is granted to use, copy, create derivative works and redistribute
   10  * this software and such derivative works for any purpose, so long as the name
   11  * of the university of michigan is not used in any advertising or publicity
   12  * pertaining to the use or distribution of this software without specific,
   13  * written prior authorization.  if the above copyright notice or any other
   14  * identification of the university of michigan is included in any copy of any
   15  * portion of this software, then the disclaimer below must also be included.
   16  * 
   17  * this software is provided as is, without representation from the university
   18  * of michigan as to its fitness for any purpose, and without warranty by the
   19  * university of michigan of any kind, either express or implied, including
   20  * without limitation the implied warranties of merchantability and fitness for
   21  * a particular purpose. the regents of the university of michigan shall not be
   22  * liable for any damages, including special, indirect, incidental, or
   23  * consequential damages, with respect to any claim arising out of or in
   24  * connection with the use of the software, even if it has been or is hereafter
   25  * advised of the possibility of such damages.
   26  */
   27 
   28 /* TODO: 
   29  *  o validate ascii 
   30  * */
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/lockmgr.h>
   36 #include <sys/fnv_hash.h>
   37 #include <sys/proc.h>
   38 #include <sys/syscall.h>
   39 #include <sys/sysent.h>
   40 #include <sys/libkern.h>
   41 
   42 #include <rpc/rpcclnt.h>
   43 
   44 #include <nfs4client/nfs4_dev.h>
   45 #include <nfs4client/nfs4_idmap.h>
   46 
   47 
   48 #ifdef IDMAPVERBOSE
   49 #define IDMAP_DEBUG(X...) printf(X);
   50 #else
   51 #define IDMAP_DEBUG(X...)
   52 #endif
   53 
   54 #define IDMAP_HASH_SIZE 37
   55 
   56 MALLOC_DEFINE(M_IDMAP, "idmap", "idmap");
   57 
   58 #define idmap_entry_get(ID) MALLOC((ID), struct idmap_entry, sizeof(struct idmap_entry), M_IDMAP, M_WAITOK | M_ZERO)
   59 #define idmap_entry_put(ID) FREE((ID), M_IDMAP)
   60 
   61 
   62 
   63 struct idmap_entry {
   64         struct idmap_msg id_info;
   65 
   66         TAILQ_ENTRY(idmap_entry) id_entry_id;
   67         TAILQ_ENTRY(idmap_entry) id_entry_name;
   68 };
   69 
   70 struct idmap_hash {
   71         TAILQ_HEAD(, idmap_entry) hash_name[IDMAP_HASH_SIZE];
   72         TAILQ_HEAD(, idmap_entry) hash_id[IDMAP_HASH_SIZE];
   73 
   74         struct lock hash_lock;
   75 };
   76 
   77 #define IDMAP_RLOCK(lock) lockmgr(lock, LK_SHARED, NULL, curthread)
   78 #define IDMAP_WLOCK(lock) lockmgr(lock, LK_EXCLUSIVE, NULL, curthread)
   79 #define IDMAP_UNLOCK(lock) lockmgr(lock, LK_RELEASE, NULL, curthread)
   80 
   81 
   82 static struct idmap_hash idmap_uid_hash;
   83 static struct idmap_hash idmap_gid_hash;
   84 
   85 static struct idmap_entry * idmap_name_lookup(uint32_t, char *);
   86 static struct idmap_entry * idmap_id_lookup(uint32_t, ident_t);
   87 static int idmap_upcall_name(uint32_t, char *, struct idmap_entry **);
   88 static int idmap_upcall_id(uint32_t , ident_t, struct idmap_entry ** );
   89 static int idmap_add(struct idmap_entry *);
   90 
   91 static int
   92 idmap_upcall_name(uint32_t type, char * name, struct idmap_entry ** found)
   93 {
   94         int error;
   95         struct idmap_entry * e;
   96         size_t len, siz;
   97 
   98         if (type > IDMAP_MAX_TYPE || type == 0) {
   99                 IDMAP_DEBUG("bad type %d\n", type);
  100                 return EINVAL; /* XXX */ 
  101         }
  102 
  103         if (name == NULL || (len = strlen(name)) == 0 || len > IDMAP_MAXNAMELEN) {
  104                 IDMAP_DEBUG("idmap_upcall_name: bad name\n");
  105                 return EFAULT;  /* XXX */
  106         }
  107 
  108         MALLOC(e, struct idmap_entry *, sizeof(struct idmap_entry), M_IDMAP,
  109             M_WAITOK | M_ZERO);
  110 
  111         e->id_info.id_type = type;
  112         bcopy(name, e->id_info.id_name, len); 
  113         e->id_info.id_namelen = len;
  114 
  115 
  116         siz = sizeof(struct idmap_msg);
  117         error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz, 
  118             (caddr_t)&e->id_info, &siz);
  119 
  120         if (error) {
  121                 IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error);
  122                 *found = NULL;
  123                 return error;
  124         }
  125 
  126         if (siz != sizeof(struct idmap_msg)) {
  127                 IDMAP_DEBUG("bad size of returned message\n");
  128                 *found = NULL;
  129                 return EFAULT;
  130         }
  131 
  132                 
  133         *found = e;
  134         return 0;
  135 }
  136 
  137 static int
  138 idmap_upcall_id(uint32_t type, ident_t id, struct idmap_entry ** found)
  139 {
  140         int error;
  141         struct idmap_entry * e;
  142         size_t siz;
  143 
  144         if (type > IDMAP_MAX_TYPE)
  145                 panic("bad type"); /* XXX */ 
  146 
  147         MALLOC(e, struct idmap_entry *, sizeof(struct idmap_entry), M_IDMAP,
  148             M_WAITOK | M_ZERO);
  149 
  150         e->id_info.id_type = type;
  151         e->id_info.id_namelen = 0;      /* should already */
  152         e->id_info.id_id = id;
  153 
  154         siz = sizeof(struct idmap_msg);
  155         error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz, 
  156             (caddr_t)&e->id_info, &siz);
  157 
  158         if (error) {
  159                 IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error);
  160                 *found = NULL;
  161                 return error;
  162         }
  163 
  164         if (siz != sizeof(struct idmap_msg)) {
  165                 IDMAP_DEBUG("bad size of returned message\n");
  166                 *found = NULL;
  167                 return EFAULT;
  168         }
  169 
  170         *found = e;
  171         return 0;
  172 }
  173 
  174 static int 
  175 idmap_hashf(struct idmap_entry *e, uint32_t * hval_id, uint32_t * hval_name) 
  176 {
  177         switch (e->id_info.id_type) {
  178                 case IDMAP_TYPE_UID:
  179                         *hval_id = e->id_info.id_id.uid % IDMAP_HASH_SIZE;
  180                 break;
  181                 case IDMAP_TYPE_GID:
  182                         *hval_id = e->id_info.id_id.gid % IDMAP_HASH_SIZE;
  183                 break;
  184                 default:
  185                         /* XXX yikes! */
  186                         panic("hashf: bad type!");
  187                 break;
  188         }
  189 
  190         if (e->id_info.id_namelen == 0) 
  191                 /* XXX */ panic("hashf: bad name");
  192 
  193         *hval_name = fnv_32_str(e->id_info.id_name, FNV1_32_INIT) % IDMAP_HASH_SIZE;
  194         return 0;
  195 }
  196 
  197 static int
  198 idmap_add(struct idmap_entry * e)
  199 {
  200         struct idmap_hash * hash;
  201         uint32_t hval_id, hval_name;
  202 
  203         if (e == NULL)
  204           panic("idmap_add null");
  205 
  206         if (e->id_info.id_namelen == 0)
  207           panic("idmap_add name of len 0");
  208 
  209         switch (e->id_info.id_type) {
  210                 case IDMAP_TYPE_UID:
  211                         hash = &idmap_uid_hash;
  212                 break;
  213                 case IDMAP_TYPE_GID:
  214                         hash = &idmap_gid_hash;
  215                 break;
  216                 default:
  217                         /* XXX yikes */
  218                         panic("idmap add: bad type!");
  219                 break;
  220         }
  221 
  222         if (idmap_hashf(e, &hval_id, &hval_name) != 0) {
  223                 IDMAP_DEBUG("idmap_hashf fails!\n");
  224                 return -1;
  225         }
  226 
  227         IDMAP_WLOCK(&hash->hash_lock);
  228 
  229         TAILQ_INSERT_TAIL(&hash->hash_id[hval_id], e, id_entry_id);
  230         TAILQ_INSERT_TAIL(&hash->hash_name[hval_name], e, id_entry_name);
  231 
  232         IDMAP_UNLOCK(&hash->hash_lock);
  233 
  234         return 0;
  235 }
  236 
  237 static struct idmap_entry * 
  238 idmap_id_lookup(uint32_t type, ident_t id)
  239 {
  240         struct idmap_hash * hash;
  241         uint32_t hval;
  242         struct idmap_entry * e;
  243 
  244         switch (type) {
  245                 case IDMAP_TYPE_UID:
  246                         hash = &idmap_uid_hash; 
  247                         hval = id.uid % IDMAP_HASH_SIZE;
  248                 break;
  249                 case IDMAP_TYPE_GID:
  250                         hash = &idmap_gid_hash; 
  251                         hval = id.gid % IDMAP_HASH_SIZE;
  252                 break;
  253                 default:
  254                         /* XXX yikes */
  255                         panic("lookup: bad type!");     
  256                 break;
  257         }
  258         
  259 
  260         IDMAP_RLOCK(&hash->hash_lock);
  261 
  262         TAILQ_FOREACH(e, &hash->hash_id[hval], id_entry_name) {
  263                 if ((type == IDMAP_TYPE_UID && e->id_info.id_id.uid == id.uid)||
  264                     (type == IDMAP_TYPE_GID  && e->id_info.id_id.gid == id.gid)) {
  265                         IDMAP_UNLOCK(&hash->hash_lock);
  266                         return e;
  267                 }
  268         }
  269 
  270         IDMAP_UNLOCK(&hash->hash_lock);
  271         return NULL;
  272 }
  273 
  274 static struct idmap_entry * 
  275 idmap_name_lookup(uint32_t type, char * name)
  276 {
  277         struct idmap_hash * hash;
  278         uint32_t hval;
  279         struct idmap_entry * e;
  280         size_t len;
  281 
  282         switch (type) {
  283         case IDMAP_TYPE_UID:
  284                 hash = &idmap_uid_hash; 
  285         break;
  286         case IDMAP_TYPE_GID:
  287                 hash = &idmap_gid_hash; 
  288         break;
  289         default:
  290                 /* XXX yikes */
  291                 panic("lookup: bad type!");     
  292         break;
  293         }
  294         
  295         len = strlen(name);
  296 
  297         if (len == 0 || len > IDMAP_MAXNAMELEN) {
  298                 IDMAP_DEBUG("bad name length %d\n", len);
  299                 return NULL;
  300         }
  301 
  302         hval = fnv_32_str(name, FNV1_32_INIT) % IDMAP_HASH_SIZE;
  303 
  304         IDMAP_RLOCK(&hash->hash_lock);
  305 
  306         TAILQ_FOREACH(e, &hash->hash_name[hval], id_entry_name) {
  307                 if ((strlen(e->id_info.id_name) == strlen(name)) && strncmp(e->id_info.id_name, name, strlen(name)) == 0) {
  308                         IDMAP_UNLOCK(&hash->hash_lock);
  309                         return e;
  310                 }
  311         }
  312 
  313         IDMAP_UNLOCK(&hash->hash_lock);
  314         return NULL;
  315 }
  316 
  317 void 
  318 idmap_init(void)
  319 {
  320         unsigned int i;
  321 
  322         for (i=0; i<IDMAP_HASH_SIZE; i++) {
  323                 TAILQ_INIT(&idmap_uid_hash.hash_name[i]);
  324                 TAILQ_INIT(&idmap_uid_hash.hash_id[i]);
  325 
  326                 TAILQ_INIT(&idmap_gid_hash.hash_name[i]);
  327                 TAILQ_INIT(&idmap_gid_hash.hash_id[i]);
  328         }
  329 
  330         lockinit(&idmap_uid_hash.hash_lock, PLOCK, "idmap uid hash table", 0,0);
  331         lockinit(&idmap_gid_hash.hash_lock, PLOCK, "idmap gid hash table", 0,0);
  332 
  333 }
  334 
  335 void idmap_uninit(void)
  336 {
  337         struct idmap_entry * e;
  338         int i;
  339 
  340         lockdestroy(&idmap_uid_hash.hash_lock);
  341         lockdestroy(&idmap_gid_hash.hash_lock);
  342 
  343         for (i=0; i<IDMAP_HASH_SIZE; i++) {
  344                 while(!TAILQ_EMPTY(&idmap_uid_hash.hash_name[i])) {
  345                         e = TAILQ_FIRST(&idmap_uid_hash.hash_name[i]);
  346                         TAILQ_REMOVE(&idmap_uid_hash.hash_name[i], e, id_entry_name);
  347                         TAILQ_REMOVE(&idmap_uid_hash.hash_id[i], e, id_entry_id);
  348                         FREE(e, M_IDMAP);
  349                 }
  350 
  351                 while(!TAILQ_EMPTY(&idmap_gid_hash.hash_name[i])) {
  352                         e = TAILQ_FIRST(&idmap_gid_hash.hash_name[i]);
  353                         TAILQ_REMOVE(&idmap_gid_hash.hash_name[i], e, id_entry_name);
  354                         TAILQ_REMOVE(&idmap_gid_hash.hash_id[i], e, id_entry_id);
  355                         FREE(e, M_IDMAP);
  356                 }
  357 
  358         }
  359 }
  360 
  361 int 
  362 idmap_uid_to_name(uid_t uid, char ** name, size_t * len)
  363 {
  364         struct idmap_entry * e;
  365         int error = 0;
  366         ident_t id;
  367 
  368         id.uid = uid;
  369 
  370 
  371         if ((e = idmap_id_lookup(IDMAP_TYPE_UID, id)) == NULL) {
  372                 if ((error = idmap_upcall_id(IDMAP_TYPE_UID, id, &e)) != 0) {
  373                         IDMAP_DEBUG("error in upcall\n");
  374                         return error;
  375                 }
  376 
  377                 if (e == NULL) {
  378                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
  379                         return EFAULT;
  380                 }
  381 
  382                 if (idmap_add(e) != 0) {
  383                         IDMAP_DEBUG("idmap_add failed\n");
  384                         FREE(e, M_IDMAP);
  385                 }
  386         }
  387 
  388         *name = e->id_info.id_name;
  389         *len = e->id_info.id_namelen;
  390         return 0;
  391 }
  392 
  393 int 
  394 idmap_gid_to_name(gid_t gid, char ** name, size_t * len)
  395 {
  396         struct idmap_entry * e;
  397         int error = 0;
  398         ident_t id;
  399         
  400         id.gid = gid;
  401 
  402 
  403         if ((e = idmap_id_lookup(IDMAP_TYPE_GID, id)) == NULL) {
  404                 if ((error = idmap_upcall_id(IDMAP_TYPE_GID, (ident_t)id, &e))) {
  405                         IDMAP_DEBUG("error in upcall\n");
  406                         return error;
  407                 }
  408 
  409                 if (e == NULL) {
  410                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
  411                         return EFAULT;
  412                 }
  413 
  414                 if (idmap_add(e) != 0) {
  415                         IDMAP_DEBUG("idmap_add failed\n");
  416                         FREE(e, M_IDMAP);
  417                 }
  418         }
  419 
  420         *name = e->id_info.id_name;
  421         *len  = e->id_info.id_namelen;
  422         return 0;
  423 }
  424 
  425 int 
  426 idmap_name_to_uid(char * name, size_t len, uid_t * id)
  427 {
  428         struct idmap_entry * e;
  429         int error = 0;
  430         char * namestr;
  431 
  432         if (name == NULL )
  433                 return EFAULT;
  434 
  435         if (len == 0 || len > IDMAP_MAXNAMELEN) {
  436                 IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
  437                 return EINVAL;
  438         }
  439 
  440         /* XXX hack */
  441         MALLOC(namestr, char *, len + 1, M_TEMP, M_WAITOK);
  442         bcopy(name, namestr, len);
  443         namestr[len] = '\0';
  444 
  445 
  446         if ((e = idmap_name_lookup(IDMAP_TYPE_UID, namestr)) == NULL) {
  447                 if ((error = idmap_upcall_name(IDMAP_TYPE_UID, namestr, &e))) {
  448                         FREE(namestr, M_TEMP);
  449                         return error;
  450                 }
  451 
  452                 if (e == NULL) {
  453                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
  454                         FREE(namestr, M_TEMP);
  455                         return EFAULT;
  456                 }
  457 
  458                 if (idmap_add(e) != 0) {
  459                         IDMAP_DEBUG("idmap_add failed\n");
  460                         FREE(e, M_IDMAP);
  461                 }
  462         }
  463 
  464         *id = e->id_info.id_id.uid;
  465         FREE(namestr, M_TEMP);
  466         return 0;
  467 }
  468 
  469 int 
  470 idmap_name_to_gid(char * name, size_t len, gid_t * id)
  471 {
  472         struct idmap_entry * e;
  473         int error = 0;
  474 
  475         char * namestr;
  476 
  477         if (name == NULL )
  478                 return EFAULT;
  479 
  480         if (len == 0 || len > IDMAP_MAXNAMELEN) {
  481                 IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
  482                 return EINVAL;
  483         }
  484 
  485         /* XXX hack */
  486         MALLOC(namestr, char *, len + 1, M_TEMP, M_WAITOK);
  487         bcopy(name, namestr, len);
  488         namestr[len] = '\0';
  489 
  490 
  491         if ((e = idmap_name_lookup(IDMAP_TYPE_GID, namestr)) == NULL) {
  492                 if ((error = idmap_upcall_name(IDMAP_TYPE_GID, namestr, &e)) != 0) {
  493                         IDMAP_DEBUG("error in upcall\n");
  494                         FREE(namestr, M_TEMP);
  495                         return error;
  496                 }
  497 
  498                 if (e == NULL) {
  499                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
  500                         FREE(namestr, M_TEMP);
  501                         return EFAULT;
  502                 }
  503 
  504                 if (idmap_add(e) != 0) {
  505                         IDMAP_DEBUG("idmap_add failed\n");
  506                         FREE(e, M_IDMAP);
  507                 }
  508         }
  509 
  510         *id = e->id_info.id_id.gid;
  511         FREE(namestr, M_TEMP);
  512         return 0;
  513 }

Cache object: 815df1f888c4ee01f0307e102707e1f7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.