aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r--net/sunrpc/svcauth_unix.c229
1 files changed, 161 insertions, 68 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 207311610988..c8e10216c113 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -18,6 +18,8 @@
18 18
19#include <linux/sunrpc/clnt.h> 19#include <linux/sunrpc/clnt.h>
20 20
21#include "netns.h"
22
21/* 23/*
22 * AUTHUNIX and AUTHNULL credentials are both handled here. 24 * AUTHUNIX and AUTHNULL credentials are both handled here.
23 * AUTHNULL is treated just like AUTHUNIX except that the uid/gid 25 * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
@@ -28,12 +30,22 @@
28 30
29struct unix_domain { 31struct unix_domain {
30 struct auth_domain h; 32 struct auth_domain h;
33#ifdef CONFIG_NFSD_DEPRECATED
31 int addr_changes; 34 int addr_changes;
35#endif /* CONFIG_NFSD_DEPRECATED */
32 /* other stuff later */ 36 /* other stuff later */
33}; 37};
34 38
35extern struct auth_ops svcauth_unix; 39extern struct auth_ops svcauth_unix;
36 40
41static void svcauth_unix_domain_release(struct auth_domain *dom)
42{
43 struct unix_domain *ud = container_of(dom, struct unix_domain, h);
44
45 kfree(dom->name);
46 kfree(ud);
47}
48
37struct auth_domain *unix_domain_find(char *name) 49struct auth_domain *unix_domain_find(char *name)
38{ 50{
39 struct auth_domain *rv; 51 struct auth_domain *rv;
@@ -43,7 +55,7 @@ struct auth_domain *unix_domain_find(char *name)
43 while(1) { 55 while(1) {
44 if (rv) { 56 if (rv) {
45 if (new && rv != &new->h) 57 if (new && rv != &new->h)
46 auth_domain_put(&new->h); 58 svcauth_unix_domain_release(&new->h);
47 59
48 if (rv->flavour != &svcauth_unix) { 60 if (rv->flavour != &svcauth_unix) {
49 auth_domain_put(rv); 61 auth_domain_put(rv);
@@ -62,20 +74,14 @@ struct auth_domain *unix_domain_find(char *name)
62 return NULL; 74 return NULL;
63 } 75 }
64 new->h.flavour = &svcauth_unix; 76 new->h.flavour = &svcauth_unix;
77#ifdef CONFIG_NFSD_DEPRECATED
65 new->addr_changes = 0; 78 new->addr_changes = 0;
79#endif /* CONFIG_NFSD_DEPRECATED */
66 rv = auth_domain_lookup(name, &new->h); 80 rv = auth_domain_lookup(name, &new->h);
67 } 81 }
68} 82}
69EXPORT_SYMBOL_GPL(unix_domain_find); 83EXPORT_SYMBOL_GPL(unix_domain_find);
70 84
71static void svcauth_unix_domain_release(struct auth_domain *dom)
72{
73 struct unix_domain *ud = container_of(dom, struct unix_domain, h);
74
75 kfree(dom->name);
76 kfree(ud);
77}
78
79 85
80/************************************************** 86/**************************************************
81 * cache for IP address to unix_domain 87 * cache for IP address to unix_domain
@@ -83,16 +89,16 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
83 */ 89 */
84#define IP_HASHBITS 8 90#define IP_HASHBITS 8
85#define IP_HASHMAX (1<<IP_HASHBITS) 91#define IP_HASHMAX (1<<IP_HASHBITS)
86#define IP_HASHMASK (IP_HASHMAX-1)
87 92
88struct ip_map { 93struct ip_map {
89 struct cache_head h; 94 struct cache_head h;
90 char m_class[8]; /* e.g. "nfsd" */ 95 char m_class[8]; /* e.g. "nfsd" */
91 struct in6_addr m_addr; 96 struct in6_addr m_addr;
92 struct unix_domain *m_client; 97 struct unix_domain *m_client;
98#ifdef CONFIG_NFSD_DEPRECATED
93 int m_add_change; 99 int m_add_change;
100#endif /* CONFIG_NFSD_DEPRECATED */
94}; 101};
95static struct cache_head *ip_table[IP_HASHMAX];
96 102
97static void ip_map_put(struct kref *kref) 103static void ip_map_put(struct kref *kref)
98{ 104{
@@ -145,7 +151,9 @@ static void update(struct cache_head *cnew, struct cache_head *citem)
145 151
146 kref_get(&item->m_client->h.ref); 152 kref_get(&item->m_client->h.ref);
147 new->m_client = item->m_client; 153 new->m_client = item->m_client;
154#ifdef CONFIG_NFSD_DEPRECATED
148 new->m_add_change = item->m_add_change; 155 new->m_add_change = item->m_add_change;
156#endif /* CONFIG_NFSD_DEPRECATED */
149} 157}
150static struct cache_head *ip_map_alloc(void) 158static struct cache_head *ip_map_alloc(void)
151{ 159{
@@ -178,8 +186,8 @@ static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
178 return sunrpc_cache_pipe_upcall(cd, h, ip_map_request); 186 return sunrpc_cache_pipe_upcall(cd, h, ip_map_request);
179} 187}
180 188
181static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr); 189static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
182static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry); 190static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
183 191
184static int ip_map_parse(struct cache_detail *cd, 192static int ip_map_parse(struct cache_detail *cd,
185 char *mesg, int mlen) 193 char *mesg, int mlen)
@@ -219,10 +227,9 @@ static int ip_map_parse(struct cache_detail *cd,
219 switch (address.sa.sa_family) { 227 switch (address.sa.sa_family) {
220 case AF_INET: 228 case AF_INET:
221 /* Form a mapped IPv4 address in sin6 */ 229 /* Form a mapped IPv4 address in sin6 */
222 memset(&sin6, 0, sizeof(sin6));
223 sin6.sin6_family = AF_INET6; 230 sin6.sin6_family = AF_INET6;
224 sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); 231 ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
225 sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr; 232 &sin6.sin6_addr);
226 break; 233 break;
227#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 234#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
228 case AF_INET6: 235 case AF_INET6:
@@ -249,9 +256,9 @@ static int ip_map_parse(struct cache_detail *cd,
249 dom = NULL; 256 dom = NULL;
250 257
251 /* IPv6 scope IDs are ignored for now */ 258 /* IPv6 scope IDs are ignored for now */
252 ipmp = ip_map_lookup(class, &sin6.sin6_addr); 259 ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
253 if (ipmp) { 260 if (ipmp) {
254 err = ip_map_update(ipmp, 261 err = __ip_map_update(cd, ipmp,
255 container_of(dom, struct unix_domain, h), 262 container_of(dom, struct unix_domain, h),
256 expiry); 263 expiry);
257 } else 264 } else
@@ -294,29 +301,15 @@ static int ip_map_show(struct seq_file *m,
294} 301}
295 302
296 303
297struct cache_detail ip_map_cache = { 304static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
298 .owner = THIS_MODULE, 305 struct in6_addr *addr)
299 .hash_size = IP_HASHMAX,
300 .hash_table = ip_table,
301 .name = "auth.unix.ip",
302 .cache_put = ip_map_put,
303 .cache_upcall = ip_map_upcall,
304 .cache_parse = ip_map_parse,
305 .cache_show = ip_map_show,
306 .match = ip_map_match,
307 .init = ip_map_init,
308 .update = update,
309 .alloc = ip_map_alloc,
310};
311
312static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
313{ 306{
314 struct ip_map ip; 307 struct ip_map ip;
315 struct cache_head *ch; 308 struct cache_head *ch;
316 309
317 strcpy(ip.m_class, class); 310 strcpy(ip.m_class, class);
318 ipv6_addr_copy(&ip.m_addr, addr); 311 ipv6_addr_copy(&ip.m_addr, addr);
319 ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, 312 ch = sunrpc_cache_lookup(cd, &ip.h,
320 hash_str(class, IP_HASHBITS) ^ 313 hash_str(class, IP_HASHBITS) ^
321 hash_ip6(*addr)); 314 hash_ip6(*addr));
322 315
@@ -326,7 +319,17 @@ static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
326 return NULL; 319 return NULL;
327} 320}
328 321
329static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry) 322static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
323 struct in6_addr *addr)
324{
325 struct sunrpc_net *sn;
326
327 sn = net_generic(net, sunrpc_net_id);
328 return __ip_map_lookup(sn->ip_map_cache, class, addr);
329}
330
331static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
332 struct unix_domain *udom, time_t expiry)
330{ 333{
331 struct ip_map ip; 334 struct ip_map ip;
332 struct cache_head *ch; 335 struct cache_head *ch;
@@ -335,6 +338,7 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
335 ip.h.flags = 0; 338 ip.h.flags = 0;
336 if (!udom) 339 if (!udom)
337 set_bit(CACHE_NEGATIVE, &ip.h.flags); 340 set_bit(CACHE_NEGATIVE, &ip.h.flags);
341#ifdef CONFIG_NFSD_DEPRECATED
338 else { 342 else {
339 ip.m_add_change = udom->addr_changes; 343 ip.m_add_change = udom->addr_changes;
340 /* if this is from the legacy set_client system call, 344 /* if this is from the legacy set_client system call,
@@ -343,18 +347,28 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
343 if (expiry == NEVER) 347 if (expiry == NEVER)
344 ip.m_add_change++; 348 ip.m_add_change++;
345 } 349 }
350#endif /* CONFIG_NFSD_DEPRECATED */
346 ip.h.expiry_time = expiry; 351 ip.h.expiry_time = expiry;
347 ch = sunrpc_cache_update(&ip_map_cache, 352 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
348 &ip.h, &ipm->h,
349 hash_str(ipm->m_class, IP_HASHBITS) ^ 353 hash_str(ipm->m_class, IP_HASHBITS) ^
350 hash_ip6(ipm->m_addr)); 354 hash_ip6(ipm->m_addr));
351 if (!ch) 355 if (!ch)
352 return -ENOMEM; 356 return -ENOMEM;
353 cache_put(ch, &ip_map_cache); 357 cache_put(ch, cd);
354 return 0; 358 return 0;
355} 359}
356 360
357int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom) 361static inline int ip_map_update(struct net *net, struct ip_map *ipm,
362 struct unix_domain *udom, time_t expiry)
363{
364 struct sunrpc_net *sn;
365
366 sn = net_generic(net, sunrpc_net_id);
367 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
368}
369
370#ifdef CONFIG_NFSD_DEPRECATED
371int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
358{ 372{
359 struct unix_domain *udom; 373 struct unix_domain *udom;
360 struct ip_map *ipmp; 374 struct ip_map *ipmp;
@@ -362,10 +376,10 @@ int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
362 if (dom->flavour != &svcauth_unix) 376 if (dom->flavour != &svcauth_unix)
363 return -EINVAL; 377 return -EINVAL;
364 udom = container_of(dom, struct unix_domain, h); 378 udom = container_of(dom, struct unix_domain, h);
365 ipmp = ip_map_lookup("nfsd", addr); 379 ipmp = ip_map_lookup(net, "nfsd", addr);
366 380
367 if (ipmp) 381 if (ipmp)
368 return ip_map_update(ipmp, udom, NEVER); 382 return ip_map_update(net, ipmp, udom, NEVER);
369 else 383 else
370 return -ENOMEM; 384 return -ENOMEM;
371} 385}
@@ -383,42 +397,51 @@ int auth_unix_forget_old(struct auth_domain *dom)
383} 397}
384EXPORT_SYMBOL_GPL(auth_unix_forget_old); 398EXPORT_SYMBOL_GPL(auth_unix_forget_old);
385 399
386struct auth_domain *auth_unix_lookup(struct in6_addr *addr) 400struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
387{ 401{
388 struct ip_map *ipm; 402 struct ip_map *ipm;
389 struct auth_domain *rv; 403 struct auth_domain *rv;
404 struct sunrpc_net *sn;
390 405
391 ipm = ip_map_lookup("nfsd", addr); 406 sn = net_generic(net, sunrpc_net_id);
407 ipm = ip_map_lookup(net, "nfsd", addr);
392 408
393 if (!ipm) 409 if (!ipm)
394 return NULL; 410 return NULL;
395 if (cache_check(&ip_map_cache, &ipm->h, NULL)) 411 if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
396 return NULL; 412 return NULL;
397 413
398 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { 414 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
399 if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0) 415 sunrpc_invalidate(&ipm->h, sn->ip_map_cache);
400 auth_domain_put(&ipm->m_client->h);
401 rv = NULL; 416 rv = NULL;
402 } else { 417 } else {
403 rv = &ipm->m_client->h; 418 rv = &ipm->m_client->h;
404 kref_get(&rv->ref); 419 kref_get(&rv->ref);
405 } 420 }
406 cache_put(&ipm->h, &ip_map_cache); 421 cache_put(&ipm->h, sn->ip_map_cache);
407 return rv; 422 return rv;
408} 423}
409EXPORT_SYMBOL_GPL(auth_unix_lookup); 424EXPORT_SYMBOL_GPL(auth_unix_lookup);
425#endif /* CONFIG_NFSD_DEPRECATED */
410 426
411void svcauth_unix_purge(void) 427void svcauth_unix_purge(void)
412{ 428{
413 cache_purge(&ip_map_cache); 429 struct net *net;
430
431 for_each_net(net) {
432 struct sunrpc_net *sn;
433
434 sn = net_generic(net, sunrpc_net_id);
435 cache_purge(sn->ip_map_cache);
436 }
414} 437}
415EXPORT_SYMBOL_GPL(svcauth_unix_purge); 438EXPORT_SYMBOL_GPL(svcauth_unix_purge);
416 439
417static inline struct ip_map * 440static inline struct ip_map *
418ip_map_cached_get(struct svc_rqst *rqstp) 441ip_map_cached_get(struct svc_xprt *xprt)
419{ 442{
420 struct ip_map *ipm = NULL; 443 struct ip_map *ipm = NULL;
421 struct svc_xprt *xprt = rqstp->rq_xprt; 444 struct sunrpc_net *sn;
422 445
423 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { 446 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
424 spin_lock(&xprt->xpt_lock); 447 spin_lock(&xprt->xpt_lock);
@@ -430,9 +453,10 @@ ip_map_cached_get(struct svc_rqst *rqstp)
430 * remembered, e.g. by a second mount from the 453 * remembered, e.g. by a second mount from the
431 * same IP address. 454 * same IP address.
432 */ 455 */
456 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
433 xprt->xpt_auth_cache = NULL; 457 xprt->xpt_auth_cache = NULL;
434 spin_unlock(&xprt->xpt_lock); 458 spin_unlock(&xprt->xpt_lock);
435 cache_put(&ipm->h, &ip_map_cache); 459 cache_put(&ipm->h, sn->ip_map_cache);
436 return NULL; 460 return NULL;
437 } 461 }
438 cache_get(&ipm->h); 462 cache_get(&ipm->h);
@@ -443,10 +467,8 @@ ip_map_cached_get(struct svc_rqst *rqstp)
443} 467}
444 468
445static inline void 469static inline void
446ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) 470ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
447{ 471{
448 struct svc_xprt *xprt = rqstp->rq_xprt;
449
450 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { 472 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
451 spin_lock(&xprt->xpt_lock); 473 spin_lock(&xprt->xpt_lock);
452 if (xprt->xpt_auth_cache == NULL) { 474 if (xprt->xpt_auth_cache == NULL) {
@@ -456,15 +478,26 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
456 } 478 }
457 spin_unlock(&xprt->xpt_lock); 479 spin_unlock(&xprt->xpt_lock);
458 } 480 }
459 if (ipm) 481 if (ipm) {
460 cache_put(&ipm->h, &ip_map_cache); 482 struct sunrpc_net *sn;
483
484 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
485 cache_put(&ipm->h, sn->ip_map_cache);
486 }
461} 487}
462 488
463void 489void
464svcauth_unix_info_release(void *info) 490svcauth_unix_info_release(struct svc_xprt *xpt)
465{ 491{
466 struct ip_map *ipm = info; 492 struct ip_map *ipm;
467 cache_put(&ipm->h, &ip_map_cache); 493
494 ipm = xpt->xpt_auth_cache;
495 if (ipm != NULL) {
496 struct sunrpc_net *sn;
497
498 sn = net_generic(xpt->xpt_net, sunrpc_net_id);
499 cache_put(&ipm->h, sn->ip_map_cache);
500 }
468} 501}
469 502
470/**************************************************************************** 503/****************************************************************************
@@ -474,7 +507,6 @@ svcauth_unix_info_release(void *info)
474 */ 507 */
475#define GID_HASHBITS 8 508#define GID_HASHBITS 8
476#define GID_HASHMAX (1<<GID_HASHBITS) 509#define GID_HASHMAX (1<<GID_HASHBITS)
477#define GID_HASHMASK (GID_HASHMAX - 1)
478 510
479struct unix_gid { 511struct unix_gid {
480 struct cache_head h; 512 struct cache_head h;
@@ -674,6 +706,8 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
674 switch (ret) { 706 switch (ret) {
675 case -ENOENT: 707 case -ENOENT:
676 return ERR_PTR(-ENOENT); 708 return ERR_PTR(-ENOENT);
709 case -ETIMEDOUT:
710 return ERR_PTR(-ESHUTDOWN);
677 case 0: 711 case 0:
678 gi = get_group_info(ug->gi); 712 gi = get_group_info(ug->gi);
679 cache_put(&ug->h, &unix_gid_cache); 713 cache_put(&ug->h, &unix_gid_cache);
@@ -691,6 +725,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
691 struct ip_map *ipm; 725 struct ip_map *ipm;
692 struct group_info *gi; 726 struct group_info *gi;
693 struct svc_cred *cred = &rqstp->rq_cred; 727 struct svc_cred *cred = &rqstp->rq_cred;
728 struct svc_xprt *xprt = rqstp->rq_xprt;
729 struct net *net = xprt->xpt_net;
730 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
694 731
695 switch (rqstp->rq_addr.ss_family) { 732 switch (rqstp->rq_addr.ss_family) {
696 case AF_INET: 733 case AF_INET:
@@ -709,26 +746,27 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
709 if (rqstp->rq_proc == 0) 746 if (rqstp->rq_proc == 0)
710 return SVC_OK; 747 return SVC_OK;
711 748
712 ipm = ip_map_cached_get(rqstp); 749 ipm = ip_map_cached_get(xprt);
713 if (ipm == NULL) 750 if (ipm == NULL)
714 ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, 751 ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
715 &sin6->sin6_addr); 752 &sin6->sin6_addr);
716 753
717 if (ipm == NULL) 754 if (ipm == NULL)
718 return SVC_DENIED; 755 return SVC_DENIED;
719 756
720 switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { 757 switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
721 default: 758 default:
722 BUG(); 759 BUG();
723 case -EAGAIN:
724 case -ETIMEDOUT: 760 case -ETIMEDOUT:
761 return SVC_CLOSE;
762 case -EAGAIN:
725 return SVC_DROP; 763 return SVC_DROP;
726 case -ENOENT: 764 case -ENOENT:
727 return SVC_DENIED; 765 return SVC_DENIED;
728 case 0: 766 case 0:
729 rqstp->rq_client = &ipm->m_client->h; 767 rqstp->rq_client = &ipm->m_client->h;
730 kref_get(&rqstp->rq_client->ref); 768 kref_get(&rqstp->rq_client->ref);
731 ip_map_cached_put(rqstp, ipm); 769 ip_map_cached_put(xprt, ipm);
732 break; 770 break;
733 } 771 }
734 772
@@ -736,6 +774,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
736 switch (PTR_ERR(gi)) { 774 switch (PTR_ERR(gi)) {
737 case -EAGAIN: 775 case -EAGAIN:
738 return SVC_DROP; 776 return SVC_DROP;
777 case -ESHUTDOWN:
778 return SVC_CLOSE;
739 case -ENOENT: 779 case -ENOENT:
740 break; 780 break;
741 default: 781 default:
@@ -776,7 +816,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
776 cred->cr_gid = (gid_t) -1; 816 cred->cr_gid = (gid_t) -1;
777 cred->cr_group_info = groups_alloc(0); 817 cred->cr_group_info = groups_alloc(0);
778 if (cred->cr_group_info == NULL) 818 if (cred->cr_group_info == NULL)
779 return SVC_DROP; /* kmalloc failure - client must retry */ 819 return SVC_CLOSE; /* kmalloc failure - client must retry */
780 820
781 /* Put NULL verifier */ 821 /* Put NULL verifier */
782 svc_putnl(resv, RPC_AUTH_NULL); 822 svc_putnl(resv, RPC_AUTH_NULL);
@@ -840,7 +880,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
840 goto badcred; 880 goto badcred;
841 cred->cr_group_info = groups_alloc(slen); 881 cred->cr_group_info = groups_alloc(slen);
842 if (cred->cr_group_info == NULL) 882 if (cred->cr_group_info == NULL)
843 return SVC_DROP; 883 return SVC_CLOSE;
844 for (i = 0; i < slen; i++) 884 for (i = 0; i < slen; i++)
845 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); 885 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
846 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 886 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
@@ -886,3 +926,56 @@ struct auth_ops svcauth_unix = {
886 .set_client = svcauth_unix_set_client, 926 .set_client = svcauth_unix_set_client,
887}; 927};
888 928
929int ip_map_cache_create(struct net *net)
930{
931 int err = -ENOMEM;
932 struct cache_detail *cd;
933 struct cache_head **tbl;
934 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
935
936 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
937 if (cd == NULL)
938 goto err_cd;
939
940 tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
941 if (tbl == NULL)
942 goto err_tbl;
943
944 cd->owner = THIS_MODULE,
945 cd->hash_size = IP_HASHMAX,
946 cd->hash_table = tbl,
947 cd->name = "auth.unix.ip",
948 cd->cache_put = ip_map_put,
949 cd->cache_upcall = ip_map_upcall,
950 cd->cache_parse = ip_map_parse,
951 cd->cache_show = ip_map_show,
952 cd->match = ip_map_match,
953 cd->init = ip_map_init,
954 cd->update = update,
955 cd->alloc = ip_map_alloc,
956
957 err = cache_register_net(cd, net);
958 if (err)
959 goto err_reg;
960
961 sn->ip_map_cache = cd;
962 return 0;
963
964err_reg:
965 kfree(tbl);
966err_tbl:
967 kfree(cd);
968err_cd:
969 return err;
970}
971
972void ip_map_cache_destroy(struct net *net)
973{
974 struct sunrpc_net *sn;
975
976 sn = net_generic(net, sunrpc_net_id);
977 cache_purge(sn->ip_map_cache);
978 cache_unregister_net(sn->ip_map_cache, net);
979 kfree(sn->ip_map_cache->hash_table);
980 kfree(sn->ip_map_cache);
981}