Blame view

fs/nfsd/nfs4idmap.c 13.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   *  Mapping of UID/GIDs to name and vice versa.
   *
   *  Copyright (c) 2002, 2003 The Regents of the University of
   *  Michigan.  All rights reserved.
   *
   *  Marius Aamodt Eriksen <marius@umich.edu>
   *
   *  Redistribution and use in source and binary forms, with or without
   *  modification, are permitted provided that the following conditions
   *  are met:
   *
   *  1. Redistributions of source code must retain the above copyright
   *     notice, this list of conditions and the following disclaimer.
   *  2. Redistributions in binary form must reproduce the above copyright
   *     notice, this list of conditions and the following disclaimer in the
   *     documentation and/or other materials provided with the distribution.
   *  3. Neither the name of the University nor the names of its
   *     contributors may be used to endorse or promote products derived
   *     from this software without specific prior written permission.
   *
   *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <linux/seq_file.h>
341eb1844   Boaz Harrosh   nfsd: Source file...
36
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
37
  #include <linux/slab.h>
2ca72e17e   J. Bruce Fields   nfsd4: move idmap...
38
  #include "idmap.h"
3c7260234   J. Bruce Fields   nfsd4: return nfs...
39
  #include "nfsd.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  
  /*
   * Cache entry
   */
  
  /*
   * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on
   * that.
   */
  
  #define IDMAP_TYPE_USER  0
  #define IDMAP_TYPE_GROUP 1
  
  struct ent {
  	struct cache_head h;
  	int               type;		       /* User / Group */
  	uid_t             id;
  	char              name[IDMAP_NAMESZ];
  	char              authname[IDMAP_NAMESZ];
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
  /* Common entry handling */
  
  #define ENT_HASHBITS          8
  #define ENT_HASHMAX           (1 << ENT_HASHBITS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
65
66
  static void
  ent_init(struct cache_head *cnew, struct cache_head *citm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  {
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
68
69
  	struct ent *new = container_of(cnew, struct ent, h);
  	struct ent *itm = container_of(citm, struct ent, h);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
  	new->id = itm->id;
  	new->type = itm->type;
  
  	strlcpy(new->name, itm->name, sizeof(new->name));
  	strlcpy(new->authname, itm->authname, sizeof(new->name));
  }
fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
76
  static void
baab935ff   NeilBrown   [PATCH] knfsd: Co...
77
  ent_put(struct kref *ref)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
baab935ff   NeilBrown   [PATCH] knfsd: Co...
79
80
  	struct ent *map = container_of(ref, struct ent, h.ref);
  	kfree(map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
82
83
84
85
86
87
88
89
90
  static struct cache_head *
  ent_alloc(void)
  {
  	struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL);
  	if (e)
  		return &e->h;
  	else
  		return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  /*
   * ID -> Name cache
   */
  
  static struct cache_head *idtoname_table[ENT_HASHMAX];
  
  static uint32_t
  idtoname_hash(struct ent *ent)
  {
  	uint32_t hash;
  
  	hash = hash_str(ent->authname, ENT_HASHBITS);
  	hash = hash_long(hash ^ ent->id, ENT_HASHBITS);
  
  	/* Flip LSB for user/group */
  	if (ent->type == IDMAP_TYPE_GROUP)
  		hash ^= 1;
  
  	return hash;
  }
  
  static void
  idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
      int *blen)
  {
   	struct ent *ent = container_of(ch, struct ent, h);
  	char idstr[11];
  
  	qword_add(bpp, blen, ent->authname);
0a725fc4d   J. Bruce Fields   nfsd4: idmap upca...
120
  	snprintf(idstr, sizeof(idstr), "%u", ent->id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
  	qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
  	qword_add(bpp, blen, idstr);
  
  	(*bpp)[-1] = '
  ';
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
127
  static int
bc74b4f5e   Trond Myklebust   SUNRPC: Allow the...
128
129
130
131
132
133
  idtoname_upcall(struct cache_detail *cd, struct cache_head *ch)
  {
  	return sunrpc_cache_pipe_upcall(cd, ch, idtoname_request);
  }
  
  static int
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
134
  idtoname_match(struct cache_head *ca, struct cache_head *cb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  {
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
136
137
  	struct ent *a = container_of(ca, struct ent, h);
  	struct ent *b = container_of(cb, struct ent, h);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  	return (a->id == b->id && a->type == b->type &&
  	    strcmp(a->authname, b->authname) == 0);
  }
  
  static int
  idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
  {
  	struct ent *ent;
  
  	if (h == NULL) {
  		seq_puts(m, "#domain type id [name]
  ");
  		return 0;
  	}
  	ent = container_of(h, struct ent, h);
0a725fc4d   J. Bruce Fields   nfsd4: idmap upca...
153
  	seq_printf(m, "%s %s %u", ent->authname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
161
162
163
  			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
  			ent->id);
  	if (test_bit(CACHE_VALID, &h->flags))
  		seq_printf(m, " %s", ent->name);
  	seq_printf(m, "
  ");
  	return 0;
  }
  
  static void
2da8ca26c   Trond Myklebust   NFSD: Clean up th...
164
  warn_no_idmapd(struct cache_detail *detail, int has_died)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
  {
  	printk("nfsd: nfsv4 idmapping failing: has idmapd %s?
  ",
2da8ca26c   Trond Myklebust   NFSD: Clean up th...
168
  			has_died ? "died" : "not been started");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
  }
  
  
  static int         idtoname_parse(struct cache_detail *, char *, int);
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
173
174
  static struct ent *idtoname_lookup(struct ent *);
  static struct ent *idtoname_update(struct ent *, struct ent *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175

fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
176
  static struct cache_detail idtoname_cache = {
f35279d3f   Bruce Allan   [PATCH] sunrpc: c...
177
  	.owner		= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  	.hash_size	= ENT_HASHMAX,
  	.hash_table	= idtoname_table,
  	.name		= "nfs4.idtoname",
  	.cache_put	= ent_put,
bc74b4f5e   Trond Myklebust   SUNRPC: Allow the...
182
  	.cache_upcall	= idtoname_upcall,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
  	.cache_parse	= idtoname_parse,
  	.cache_show	= idtoname_show,
  	.warn_no_listener = warn_no_idmapd,
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
186
187
188
189
  	.match		= idtoname_match,
  	.init		= ent_init,
  	.update		= ent_init,
  	.alloc		= ent_alloc,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  };
a254b246e   Harvey Harrison   nfsd: fix sparse ...
191
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
  idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
  {
  	struct ent ent, *res;
  	char *buf1, *bp;
c9b6cbe56   J. Bruce Fields   knfsd: nfs4 name-...
196
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  	int error = -EINVAL;
  
  	if (buf[buflen - 1] != '
  ')
  		return (-EINVAL);
  	buf[buflen - 1]= '\0';
  
  	buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
  	if (buf1 == NULL)
  		return (-ENOMEM);
  
  	memset(&ent, 0, sizeof(ent));
  
  	/* Authentication name */
  	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
  		goto out;
  	memcpy(ent.authname, buf1, sizeof(ent.authname));
  
  	/* Type */
  	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
  		goto out;
  	ent.type = strcmp(buf1, "user") == 0 ?
  		IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
  
  	/* ID */
  	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
  		goto out;
  	ent.id = simple_strtoul(buf1, &bp, 10);
  	if (bp == buf1)
  		goto out;
  
  	/* expiry */
  	ent.h.expiry_time = get_expiry(&buf);
  	if (ent.h.expiry_time == 0)
  		goto out;
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
232
233
234
235
  	error = -ENOMEM;
  	res = idtoname_lookup(&ent);
  	if (!res)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	/* Name */
c9b6cbe56   J. Bruce Fields   knfsd: nfs4 name-...
237
238
239
  	error = -EINVAL;
  	len = qword_get(&buf, buf1, PAGE_SIZE);
  	if (len < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  		goto out;
c9b6cbe56   J. Bruce Fields   knfsd: nfs4 name-...
241
  	if (len == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  		set_bit(CACHE_NEGATIVE, &ent.h.flags);
d4395e03f   J. Bruce Fields   knfsd: fix broken...
243
244
245
  	else if (len >= IDMAP_NAMESZ)
  		goto out;
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  		memcpy(ent.name, buf1, sizeof(ent.name));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	error = -ENOMEM;
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
248
249
  	res = idtoname_update(&ent, res);
  	if (res == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  		goto out;
baab935ff   NeilBrown   [PATCH] knfsd: Co...
251
  	cache_put(&res->h, &idtoname_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
258
  
  	error = 0;
  out:
  	kfree(buf1);
  
  	return error;
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  
  static struct ent *
  idtoname_lookup(struct ent *item)
  {
  	struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache,
  						    &item->h,
  						    idtoname_hash(item));
  	if (ch)
  		return container_of(ch, struct ent, h);
  	else
  		return NULL;
  }
  
  static struct ent *
  idtoname_update(struct ent *new, struct ent *old)
  {
  	struct cache_head *ch = sunrpc_cache_update(&idtoname_cache,
  						    &new->h, &old->h,
  						    idtoname_hash(new));
  	if (ch)
  		return container_of(ch, struct ent, h);
  	else
  		return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
287
288
289
290
291
292
293
294
  
  /*
   * Name -> ID cache
   */
  
  static struct cache_head *nametoid_table[ENT_HASHMAX];
  
  static inline int
  nametoid_hash(struct ent *ent)
  {
  	return hash_str(ent->name, ENT_HASHBITS);
  }
fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
295
  static void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
302
303
304
305
306
307
  nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
      int *blen)
  {
   	struct ent *ent = container_of(ch, struct ent, h);
  
  	qword_add(bpp, blen, ent->authname);
  	qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
  	qword_add(bpp, blen, ent->name);
  
  	(*bpp)[-1] = '
  ';
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
308
  static int
bc74b4f5e   Trond Myklebust   SUNRPC: Allow the...
309
310
311
312
313
314
  nametoid_upcall(struct cache_detail *cd, struct cache_head *ch)
  {
  	return sunrpc_cache_pipe_upcall(cd, ch, nametoid_request);
  }
  
  static int
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
315
  nametoid_match(struct cache_head *ca, struct cache_head *cb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  {
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
317
318
  	struct ent *a = container_of(ca, struct ent, h);
  	struct ent *b = container_of(cb, struct ent, h);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  	return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
  	    strcmp(a->authname, b->authname) == 0);
  }
  
  static int
  nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
  {
  	struct ent *ent;
  
  	if (h == NULL) {
  		seq_puts(m, "#domain type name [id]
  ");
  		return 0;
  	}
  	ent = container_of(h, struct ent, h);
  	seq_printf(m, "%s %s %s", ent->authname,
  			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
  			ent->name);
  	if (test_bit(CACHE_VALID, &h->flags))
0a725fc4d   J. Bruce Fields   nfsd4: idmap upca...
338
  		seq_printf(m, " %u", ent->id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
  	seq_printf(m, "
  ");
  	return 0;
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
343
344
  static struct ent *nametoid_lookup(struct ent *);
  static struct ent *nametoid_update(struct ent *, struct ent *);
fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
345
  static int         nametoid_parse(struct cache_detail *, char *, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
347
  static struct cache_detail nametoid_cache = {
f35279d3f   Bruce Allan   [PATCH] sunrpc: c...
348
  	.owner		= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
  	.hash_size	= ENT_HASHMAX,
  	.hash_table	= nametoid_table,
  	.name		= "nfs4.nametoid",
  	.cache_put	= ent_put,
bc74b4f5e   Trond Myklebust   SUNRPC: Allow the...
353
  	.cache_upcall	= nametoid_upcall,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
  	.cache_parse	= nametoid_parse,
  	.cache_show	= nametoid_show,
  	.warn_no_listener = warn_no_idmapd,
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
357
358
359
360
  	.match		= nametoid_match,
  	.init		= ent_init,
  	.update		= ent_init,
  	.alloc		= ent_alloc,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  };
fd39ca9a8   NeilBrown   [PATCH] knfsd: nf...
362
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
  {
  	struct ent ent, *res;
  	char *buf1;
  	int error = -EINVAL;
  
  	if (buf[buflen - 1] != '
  ')
  		return (-EINVAL);
  	buf[buflen - 1]= '\0';
  
  	buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
  	if (buf1 == NULL)
  		return (-ENOMEM);
  
  	memset(&ent, 0, sizeof(ent));
  
  	/* Authentication name */
  	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
  		goto out;
  	memcpy(ent.authname, buf1, sizeof(ent.authname));
  
  	/* Type */
  	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
  		goto out;
  	ent.type = strcmp(buf1, "user") == 0 ?
  		IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
  
  	/* Name */
  	error = qword_get(&buf, buf1, PAGE_SIZE);
  	if (error <= 0 || error >= IDMAP_NAMESZ)
  		goto out;
  	memcpy(ent.name, buf1, sizeof(ent.name));
  
  	/* expiry */
  	ent.h.expiry_time = get_expiry(&buf);
  	if (ent.h.expiry_time == 0)
  		goto out;
  
  	/* ID */
  	error = get_int(&buf, &ent.id);
  	if (error == -EINVAL)
  		goto out;
  	if (error == -ENOENT)
  		set_bit(CACHE_NEGATIVE, &ent.h.flags);
  
  	error = -ENOMEM;
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
410
411
412
413
414
  	res = nametoid_lookup(&ent);
  	if (res == NULL)
  		goto out;
  	res = nametoid_update(&ent, res);
  	if (res == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  		goto out;
baab935ff   NeilBrown   [PATCH] knfsd: Co...
416
  	cache_put(&res->h, &nametoid_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
420
421
422
  	error = 0;
  out:
  	kfree(buf1);
  
  	return (error);
  }
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  
  static struct ent *
  nametoid_lookup(struct ent *item)
  {
  	struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache,
  						    &item->h,
  						    nametoid_hash(item));
  	if (ch)
  		return container_of(ch, struct ent, h);
  	else
  		return NULL;
  }
  
  static struct ent *
  nametoid_update(struct ent *new, struct ent *old)
  {
  	struct cache_head *ch = sunrpc_cache_update(&nametoid_cache,
  						    &new->h, &old->h,
  						    nametoid_hash(new));
  	if (ch)
  		return container_of(ch, struct ent, h);
  	else
  		return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
  
  /*
   * Exported API
   */
dbf847ecb   J. Bruce Fields   knfsd: allow cach...
451
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
  nfsd_idmap_init(void)
  {
dbf847ecb   J. Bruce Fields   knfsd: allow cach...
454
455
456
457
458
459
460
461
462
  	int rv;
  
  	rv = cache_register(&idtoname_cache);
  	if (rv)
  		return rv;
  	rv = cache_register(&nametoid_cache);
  	if (rv)
  		cache_unregister(&idtoname_cache);
  	return rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
  }
  
  void
  nfsd_idmap_shutdown(void)
  {
df95a9d4f   J. Bruce Fields   knfsd: cache unre...
468
469
  	cache_unregister(&idtoname_cache);
  	cache_unregister(&nametoid_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
  static int
  idmap_lookup(struct svc_rqst *rqstp,
f9ecc921b   NeilBrown   [PATCH] knfsd: Us...
473
  		struct ent *(*lookup_fn)(struct ent *), struct ent *key,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  		struct cache_detail *detail, struct ent **item)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  	int ret;
839049a87   NeilBrown   nfsd/idmap: drop ...
477
478
  	*item = lookup_fn(key);
  	if (!*item)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  		return -ENOMEM;
839049a87   NeilBrown   nfsd/idmap: drop ...
480
481
482
483
484
485
486
487
488
   retry:
  	ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle);
  
  	if (ret == -ETIMEDOUT) {
  		struct ent *prev_item = *item;
  		*item = lookup_fn(key);
  		if (*item != prev_item)
  			goto retry;
  		cache_put(&(*item)->h, detail);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  	return ret;
  }
3ab4d8b12   J. Bruce Fields   knfsd: nfsd: set ...
492
493
494
495
496
497
498
499
  static char *
  rqst_authname(struct svc_rqst *rqstp)
  {
  	struct auth_domain *clp;
  
  	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
  	return clp->name;
  }
3c7260234   J. Bruce Fields   nfsd4: return nfs...
500
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
506
507
508
509
  idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
  		uid_t *id)
  {
  	struct ent *item, key = {
  		.type = type,
  	};
  	int ret;
  
  	if (namelen + 1 > sizeof(key.name))
3c7260234   J. Bruce Fields   nfsd4: return nfs...
510
  		return nfserr_badowner;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
  	memcpy(key.name, name, namelen);
  	key.name[namelen] = '\0';
3ab4d8b12   J. Bruce Fields   knfsd: nfsd: set ...
513
  	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  	ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
  	if (ret == -ENOENT)
3c7260234   J. Bruce Fields   nfsd4: return nfs...
516
  		return nfserr_badowner;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  	if (ret)
3c7260234   J. Bruce Fields   nfsd4: return nfs...
518
  		return nfserrno(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  	*id = item->id;
baab935ff   NeilBrown   [PATCH] knfsd: Co...
520
  	cache_put(&item->h, &nametoid_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
527
528
529
530
531
  	return 0;
  }
  
  static int
  idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
  {
  	struct ent *item, key = {
  		.id = id,
  		.type = type,
  	};
  	int ret;
3ab4d8b12   J. Bruce Fields   knfsd: nfsd: set ...
532
  	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
536
537
538
539
540
  	ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
  	if (ret == -ENOENT)
  		return sprintf(name, "%u", id);
  	if (ret)
  		return ret;
  	ret = strlen(item->name);
  	BUG_ON(ret > IDMAP_NAMESZ);
  	memcpy(name, item->name, ret);
baab935ff   NeilBrown   [PATCH] knfsd: Co...
541
  	cache_put(&item->h, &idtoname_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
  	return ret;
  }
3c7260234   J. Bruce Fields   nfsd4: return nfs...
544
  __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
548
549
  nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
  		__u32 *id)
  {
  	return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
  }
3c7260234   J. Bruce Fields   nfsd4: return nfs...
550
  __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
  		__u32 *id)
  {
  	return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
  }
  
  int
  nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
  {
  	return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
  }
  
  int
  nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
  {
  	return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
  }