[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

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

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /* $FreeBSD: src/sys/nfs4client/nfs4_idmap.c,v 1.8 2008/10/23 15:53:51 des Exp $ */
  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/lock.h>
 36 #include <sys/lockmgr.h>
 37 #include <sys/fnv_hash.h>
 38 #include <sys/proc.h>
 39 #include <sys/syscall.h>
 40 #include <sys/sysent.h>
 41 #include <sys/libkern.h>
 42 
 43 #include <rpc/rpcclnt.h>
 44 
 45 #include <nfs4client/nfs4_dev.h>
 46 #include <nfs4client/nfs4_idmap.h>
 47 
 48 
 49 #ifdef IDMAPVERBOSE
 50 #define IDMAP_DEBUG(...) printf(__VA_ARGS__);
 51 #else
 52 #define IDMAP_DEBUG(...)
 53 #endif
 54 
 55 #define IDMAP_HASH_SIZE 37
 56 
 57 MALLOC_DEFINE(M_IDMAP, "idmap", "idmap");
 58 
 59 #define idmap_entry_get(ID) (ID) = malloc(sizeof(struct idmap_entry), M_IDMAP, M_WAITOK | M_ZERO)
 60 #define idmap_entry_put(ID) free((ID), M_IDMAP)
 61 
 62 
 63 
 64 struct idmap_entry {
 65         struct idmap_msg id_info;
 66 
 67         TAILQ_ENTRY(idmap_entry) id_entry_id;
 68         TAILQ_ENTRY(idmap_entry) id_entry_name;
 69 };
 70 
 71 struct idmap_hash {
 72         TAILQ_HEAD(, idmap_entry) hash_name[IDMAP_HASH_SIZE];
 73         TAILQ_HEAD(, idmap_entry) hash_id[IDMAP_HASH_SIZE];
 74 
 75         struct lock hash_lock;
 76 };
 77 
 78 #define IDMAP_RLOCK(lock) lockmgr(lock, LK_SHARED, NULL)
 79 #define IDMAP_WLOCK(lock) lockmgr(lock, LK_EXCLUSIVE, NULL)
 80 #define IDMAP_UNLOCK(lock) lockmgr(lock, LK_RELEASE, NULL)
 81 
 82 
 83 static struct idmap_hash idmap_uid_hash;
 84 static struct idmap_hash idmap_gid_hash;
 85 
 86 static struct idmap_entry * idmap_name_lookup(uint32_t, char *);
 87 static struct idmap_entry * idmap_id_lookup(uint32_t, ident_t);
 88 static int idmap_upcall_name(uint32_t, char *, struct idmap_entry **);
 89 static int idmap_upcall_id(uint32_t , ident_t, struct idmap_entry ** );
 90 static int idmap_add(struct idmap_entry *);
 91 
 92 static int
 93 idmap_upcall_name(uint32_t type, char * name, struct idmap_entry ** found)
 94 {
 95         int error;
 96         struct idmap_entry * e;
 97         size_t len, siz;
 98 
 99         if (type > IDMAP_MAX_TYPE || type == 0) {
100                 IDMAP_DEBUG("bad type %d\n", type);
101                 return EINVAL; /* XXX */
102         }
103 
104         if (name == NULL || (len = strlen(name)) == 0 || len > IDMAP_MAXNAMELEN) {
105                 IDMAP_DEBUG("idmap_upcall_name: bad name\n");
106                 return EFAULT;  /* XXX */
107         }
108 
109         e = malloc(sizeof(struct idmap_entry), M_IDMAP,
110             M_WAITOK | M_ZERO);
111 
112         e->id_info.id_type = type;
113         bcopy(name, e->id_info.id_name, len);
114         e->id_info.id_namelen = len;
115 
116 
117         siz = sizeof(struct idmap_msg);
118         error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz,
119             (caddr_t)&e->id_info, &siz);
120 
121         if (error) {
122                 IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error);
123                 *found = NULL;
124                 return error;
125         }
126 
127         if (siz != sizeof(struct idmap_msg)) {
128                 IDMAP_DEBUG("bad size of returned message\n");
129                 *found = NULL;
130                 return EFAULT;
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         e = malloc(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 void
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 }
195 
196 static int
197 idmap_add(struct idmap_entry * e)
198 {
199         struct idmap_hash * hash;
200         uint32_t hval_id, hval_name;
201 
202         if (e->id_info.id_namelen == 0) {
203                 printf("idmap_add: name of len 0\n");
204                 return EINVAL;
205         }
206 
207         switch (e->id_info.id_type) {
208         case IDMAP_TYPE_UID:
209                 hash = &idmap_uid_hash;
210                 break;
211         case IDMAP_TYPE_GID:
212                 hash = &idmap_gid_hash;
213                 break;
214         default:
215                 /* XXX yikes */
216                 panic("idmap add: bad type!");
217                 break;
218         }
219 
220         idmap_hashf(e, &hval_id, &hval_name);
221 
222         IDMAP_WLOCK(&hash->hash_lock);
223 
224         TAILQ_INSERT_TAIL(&hash->hash_id[hval_id], e, id_entry_id);
225         TAILQ_INSERT_TAIL(&hash->hash_name[hval_name], e, id_entry_name);
226 
227         IDMAP_UNLOCK(&hash->hash_lock);
228 
229         return 0;
230 }
231 
232 static struct idmap_entry *
233 idmap_id_lookup(uint32_t type, ident_t id)
234 {
235         struct idmap_hash * hash;
236         uint32_t hval;
237         struct idmap_entry * e;
238 
239         switch (type) {
240         case IDMAP_TYPE_UID:
241                 hash = &idmap_uid_hash;
242                 hval = id.uid % IDMAP_HASH_SIZE;
243                 break;
244         case IDMAP_TYPE_GID:
245                 hash = &idmap_gid_hash;
246                 hval = id.gid % IDMAP_HASH_SIZE;
247                 break;
248         default:
249                 /* XXX yikes */
250                 panic("lookup: bad type!");
251                 break;
252         }
253 
254 
255         IDMAP_RLOCK(&hash->hash_lock);
256 
257         TAILQ_FOREACH(e, &hash->hash_id[hval], id_entry_name) {
258                 if ((type == IDMAP_TYPE_UID && e->id_info.id_id.uid == id.uid)||
259                     (type == IDMAP_TYPE_GID  && e->id_info.id_id.gid == id.gid)) {
260                         IDMAP_UNLOCK(&hash->hash_lock);
261                         return e;
262                 }
263         }
264 
265         IDMAP_UNLOCK(&hash->hash_lock);
266         return NULL;
267 }
268 
269 static struct idmap_entry *
270 idmap_name_lookup(uint32_t type, char * name)
271 {
272         struct idmap_hash * hash;
273         uint32_t hval;
274         struct idmap_entry * e;
275         size_t len;
276 
277         switch (type) {
278         case IDMAP_TYPE_UID:
279                 hash = &idmap_uid_hash;
280                 break;
281         case IDMAP_TYPE_GID:
282                 hash = &idmap_gid_hash;
283                 break;
284         default:
285                 /* XXX yikes */
286                 panic("lookup: bad type!");
287                 break;
288         }
289 
290         len = strlen(name);
291 
292         if (len == 0 || len > IDMAP_MAXNAMELEN) {
293                 IDMAP_DEBUG("bad name length %d\n", len);
294                 return NULL;
295         }
296 
297         hval = fnv_32_str(name, FNV1_32_INIT) % IDMAP_HASH_SIZE;
298 
299         IDMAP_RLOCK(&hash->hash_lock);
300 
301         TAILQ_FOREACH(e, &hash->hash_name[hval], id_entry_name) {
302                 if ((strlen(e->id_info.id_name) == strlen(name)) && strncmp(e->id_info.id_name, name, strlen(name)) == 0) {
303                         IDMAP_UNLOCK(&hash->hash_lock);
304                         return e;
305                 }
306         }
307 
308         IDMAP_UNLOCK(&hash->hash_lock);
309         return NULL;
310 }
311 
312 void
313 idmap_init(void)
314 {
315         unsigned int i;
316 
317         for (i=0; i<IDMAP_HASH_SIZE; i++) {
318                 TAILQ_INIT(&idmap_uid_hash.hash_name[i]);
319                 TAILQ_INIT(&idmap_uid_hash.hash_id[i]);
320 
321                 TAILQ_INIT(&idmap_gid_hash.hash_name[i]);
322                 TAILQ_INIT(&idmap_gid_hash.hash_id[i]);
323         }
324 
325         lockinit(&idmap_uid_hash.hash_lock, PLOCK, "idmap uid hash table", 0,0);
326         lockinit(&idmap_gid_hash.hash_lock, PLOCK, "idmap gid hash table", 0,0);
327 
328 }
329 
330 void idmap_uninit(void)
331 {
332         struct idmap_entry * e;
333         int i;
334 
335         lockdestroy(&idmap_uid_hash.hash_lock);
336         lockdestroy(&idmap_gid_hash.hash_lock);
337 
338         for (i=0; i<IDMAP_HASH_SIZE; i++) {
339                 while(!TAILQ_EMPTY(&idmap_uid_hash.hash_name[i])) {
340                         e = TAILQ_FIRST(&idmap_uid_hash.hash_name[i]);
341                         TAILQ_REMOVE(&idmap_uid_hash.hash_name[i], e, id_entry_name);
342                         TAILQ_REMOVE(&idmap_uid_hash.hash_id[i], e, id_entry_id);
343                         free(e, M_IDMAP);
344                 }
345 
346                 while(!TAILQ_EMPTY(&idmap_gid_hash.hash_name[i])) {
347                         e = TAILQ_FIRST(&idmap_gid_hash.hash_name[i]);
348                         TAILQ_REMOVE(&idmap_gid_hash.hash_name[i], e, id_entry_name);
349                         TAILQ_REMOVE(&idmap_gid_hash.hash_id[i], e, id_entry_id);
350                         free(e, M_IDMAP);
351                 }
352 
353         }
354 }
355 
356 int
357 idmap_uid_to_name(uid_t uid, char ** name, size_t * len)
358 {
359         struct idmap_entry * e;
360         int error = 0;
361         ident_t id;
362 
363         id.uid = uid;
364 
365 
366         if ((e = idmap_id_lookup(IDMAP_TYPE_UID, id)) == NULL) {
367                 if ((error = idmap_upcall_id(IDMAP_TYPE_UID, id, &e)) != 0) {
368                         IDMAP_DEBUG("error in upcall\n");
369                         return error;
370                 }
371 
372                 if (e == NULL) {
373                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
374                         return EFAULT;
375                 }
376 
377                 if (idmap_add(e) != 0) {
378                         IDMAP_DEBUG("idmap_add failed\n");
379                         free(e, M_IDMAP);
380                         return EFAULT;
381                 }
382         }
383 
384         *name = e->id_info.id_name;
385         *len = e->id_info.id_namelen;
386         return 0;
387 }
388 
389 int
390 idmap_gid_to_name(gid_t gid, char ** name, size_t * len)
391 {
392         struct idmap_entry * e;
393         int error = 0;
394         ident_t id;
395 
396         id.gid = gid;
397 
398 
399         if ((e = idmap_id_lookup(IDMAP_TYPE_GID, id)) == NULL) {
400                 if ((error = idmap_upcall_id(IDMAP_TYPE_GID, id, &e))) {
401                         IDMAP_DEBUG("error in upcall\n");
402                         return error;
403                 }
404 
405                 if (e == NULL) {
406                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
407                         return EFAULT;
408                 }
409 
410                 if (idmap_add(e) != 0) {
411                         IDMAP_DEBUG("idmap_add failed\n");
412                         free(e, M_IDMAP);
413                 }
414         }
415 
416         *name = e->id_info.id_name;
417         *len  = e->id_info.id_namelen;
418         return 0;
419 }
420 
421 int
422 idmap_name_to_uid(char * name, size_t len, uid_t * id)
423 {
424         struct idmap_entry * e;
425         int error = 0;
426         char * namestr;
427 
428         if (name == NULL )
429                 return EFAULT;
430 
431         if (len == 0 || len > IDMAP_MAXNAMELEN) {
432                 IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
433                 return EINVAL;
434         }
435 
436         /* XXX hack */
437         namestr = malloc(len + 1, M_TEMP, M_WAITOK);
438         bcopy(name, namestr, len);
439         namestr[len] = '\0';
440 
441 
442         if ((e = idmap_name_lookup(IDMAP_TYPE_UID, namestr)) == NULL) {
443                 if ((error = idmap_upcall_name(IDMAP_TYPE_UID, namestr, &e))) {
444                         free(namestr, M_TEMP);
445                         return error;
446                 }
447 
448                 if (e == NULL) {
449                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
450                         free(namestr, M_TEMP);
451                         return EFAULT;
452                 }
453 
454                 if (idmap_add(e) != 0) {
455                         IDMAP_DEBUG("idmap_add failed\n");
456                         free(e, M_IDMAP);
457                 }
458         }
459 
460         *id = e->id_info.id_id.uid;
461         free(namestr, M_TEMP);
462         return 0;
463 }
464 
465 int
466 idmap_name_to_gid(char * name, size_t len, gid_t * id)
467 {
468         struct idmap_entry * e;
469         int error = 0;
470 
471         char * namestr;
472 
473         if (name == NULL )
474                 return EFAULT;
475 
476         if (len == 0 || len > IDMAP_MAXNAMELEN) {
477                 IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
478                 return EINVAL;
479         }
480 
481         /* XXX hack */
482         namestr = malloc(len + 1, M_TEMP, M_WAITOK);
483         bcopy(name, namestr, len);
484         namestr[len] = '\0';
485 
486 
487         if ((e = idmap_name_lookup(IDMAP_TYPE_GID, namestr)) == NULL) {
488                 if ((error = idmap_upcall_name(IDMAP_TYPE_GID, namestr, &e)) != 0) {
489                         IDMAP_DEBUG("error in upcall\n");
490                         free(namestr, M_TEMP);
491                         return error;
492                 }
493 
494                 if (e == NULL) {
495                         IDMAP_DEBUG("no error from upcall, but no data returned\n");
496                         free(namestr, M_TEMP);
497                         return EFAULT;
498                 }
499 
500                 if (idmap_add(e) != 0) {
501                         IDMAP_DEBUG("idmap_add failed\n");
502                         free(e, M_IDMAP);
503                 }
504         }
505 
506         *id = e->id_info.id_id.gid;
507         free(namestr, M_TEMP);
508         return 0;
509 }
510 

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


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