diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 194 |
1 files changed, 139 insertions, 55 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 207311610988..560677d187f1 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 |
| @@ -92,7 +94,6 @@ struct ip_map { | |||
| 92 | struct unix_domain *m_client; | 94 | struct unix_domain *m_client; |
| 93 | int m_add_change; | 95 | int m_add_change; |
| 94 | }; | 96 | }; |
| 95 | static struct cache_head *ip_table[IP_HASHMAX]; | ||
| 96 | 97 | ||
| 97 | static void ip_map_put(struct kref *kref) | 98 | static void ip_map_put(struct kref *kref) |
| 98 | { | 99 | { |
| @@ -178,8 +179,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); | 179 | return sunrpc_cache_pipe_upcall(cd, h, ip_map_request); |
| 179 | } | 180 | } |
| 180 | 181 | ||
| 181 | static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr); | 182 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr); |
| 182 | static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry); | 183 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry); |
| 183 | 184 | ||
| 184 | static int ip_map_parse(struct cache_detail *cd, | 185 | static int ip_map_parse(struct cache_detail *cd, |
| 185 | char *mesg, int mlen) | 186 | char *mesg, int mlen) |
| @@ -219,10 +220,9 @@ static int ip_map_parse(struct cache_detail *cd, | |||
| 219 | switch (address.sa.sa_family) { | 220 | switch (address.sa.sa_family) { |
| 220 | case AF_INET: | 221 | case AF_INET: |
| 221 | /* Form a mapped IPv4 address in sin6 */ | 222 | /* Form a mapped IPv4 address in sin6 */ |
| 222 | memset(&sin6, 0, sizeof(sin6)); | ||
| 223 | sin6.sin6_family = AF_INET6; | 223 | sin6.sin6_family = AF_INET6; |
| 224 | sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); | 224 | ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, |
| 225 | sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr; | 225 | &sin6.sin6_addr); |
| 226 | break; | 226 | break; |
| 227 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 227 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 228 | case AF_INET6: | 228 | case AF_INET6: |
| @@ -249,9 +249,9 @@ static int ip_map_parse(struct cache_detail *cd, | |||
| 249 | dom = NULL; | 249 | dom = NULL; |
| 250 | 250 | ||
| 251 | /* IPv6 scope IDs are ignored for now */ | 251 | /* IPv6 scope IDs are ignored for now */ |
| 252 | ipmp = ip_map_lookup(class, &sin6.sin6_addr); | 252 | ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr); |
| 253 | if (ipmp) { | 253 | if (ipmp) { |
| 254 | err = ip_map_update(ipmp, | 254 | err = __ip_map_update(cd, ipmp, |
| 255 | container_of(dom, struct unix_domain, h), | 255 | container_of(dom, struct unix_domain, h), |
| 256 | expiry); | 256 | expiry); |
| 257 | } else | 257 | } else |
| @@ -294,29 +294,15 @@ static int ip_map_show(struct seq_file *m, | |||
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | 296 | ||
| 297 | struct cache_detail ip_map_cache = { | 297 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, |
| 298 | .owner = THIS_MODULE, | 298 | 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 | |||
| 312 | static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr) | ||
| 313 | { | 299 | { |
| 314 | struct ip_map ip; | 300 | struct ip_map ip; |
| 315 | struct cache_head *ch; | 301 | struct cache_head *ch; |
| 316 | 302 | ||
| 317 | strcpy(ip.m_class, class); | 303 | strcpy(ip.m_class, class); |
| 318 | ipv6_addr_copy(&ip.m_addr, addr); | 304 | ipv6_addr_copy(&ip.m_addr, addr); |
| 319 | ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, | 305 | ch = sunrpc_cache_lookup(cd, &ip.h, |
| 320 | hash_str(class, IP_HASHBITS) ^ | 306 | hash_str(class, IP_HASHBITS) ^ |
| 321 | hash_ip6(*addr)); | 307 | hash_ip6(*addr)); |
| 322 | 308 | ||
| @@ -326,7 +312,17 @@ static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr) | |||
| 326 | return NULL; | 312 | return NULL; |
| 327 | } | 313 | } |
| 328 | 314 | ||
| 329 | static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry) | 315 | static inline struct ip_map *ip_map_lookup(struct net *net, char *class, |
| 316 | struct in6_addr *addr) | ||
| 317 | { | ||
| 318 | struct sunrpc_net *sn; | ||
| 319 | |||
| 320 | sn = net_generic(net, sunrpc_net_id); | ||
| 321 | return __ip_map_lookup(sn->ip_map_cache, class, addr); | ||
| 322 | } | ||
| 323 | |||
| 324 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, | ||
| 325 | struct unix_domain *udom, time_t expiry) | ||
| 330 | { | 326 | { |
| 331 | struct ip_map ip; | 327 | struct ip_map ip; |
| 332 | struct cache_head *ch; | 328 | struct cache_head *ch; |
| @@ -344,17 +340,25 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex | |||
| 344 | ip.m_add_change++; | 340 | ip.m_add_change++; |
| 345 | } | 341 | } |
| 346 | ip.h.expiry_time = expiry; | 342 | ip.h.expiry_time = expiry; |
| 347 | ch = sunrpc_cache_update(&ip_map_cache, | 343 | ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, |
| 348 | &ip.h, &ipm->h, | ||
| 349 | hash_str(ipm->m_class, IP_HASHBITS) ^ | 344 | hash_str(ipm->m_class, IP_HASHBITS) ^ |
| 350 | hash_ip6(ipm->m_addr)); | 345 | hash_ip6(ipm->m_addr)); |
| 351 | if (!ch) | 346 | if (!ch) |
| 352 | return -ENOMEM; | 347 | return -ENOMEM; |
| 353 | cache_put(ch, &ip_map_cache); | 348 | cache_put(ch, cd); |
| 354 | return 0; | 349 | return 0; |
| 355 | } | 350 | } |
| 356 | 351 | ||
| 357 | int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom) | 352 | static inline int ip_map_update(struct net *net, struct ip_map *ipm, |
| 353 | struct unix_domain *udom, time_t expiry) | ||
| 354 | { | ||
| 355 | struct sunrpc_net *sn; | ||
| 356 | |||
| 357 | sn = net_generic(net, sunrpc_net_id); | ||
| 358 | return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); | ||
| 359 | } | ||
| 360 | |||
| 361 | int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) | ||
| 358 | { | 362 | { |
| 359 | struct unix_domain *udom; | 363 | struct unix_domain *udom; |
| 360 | struct ip_map *ipmp; | 364 | struct ip_map *ipmp; |
| @@ -362,10 +366,10 @@ int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom) | |||
| 362 | if (dom->flavour != &svcauth_unix) | 366 | if (dom->flavour != &svcauth_unix) |
| 363 | return -EINVAL; | 367 | return -EINVAL; |
| 364 | udom = container_of(dom, struct unix_domain, h); | 368 | udom = container_of(dom, struct unix_domain, h); |
| 365 | ipmp = ip_map_lookup("nfsd", addr); | 369 | ipmp = ip_map_lookup(net, "nfsd", addr); |
| 366 | 370 | ||
| 367 | if (ipmp) | 371 | if (ipmp) |
| 368 | return ip_map_update(ipmp, udom, NEVER); | 372 | return ip_map_update(net, ipmp, udom, NEVER); |
| 369 | else | 373 | else |
| 370 | return -ENOMEM; | 374 | return -ENOMEM; |
| 371 | } | 375 | } |
| @@ -383,16 +387,18 @@ int auth_unix_forget_old(struct auth_domain *dom) | |||
| 383 | } | 387 | } |
| 384 | EXPORT_SYMBOL_GPL(auth_unix_forget_old); | 388 | EXPORT_SYMBOL_GPL(auth_unix_forget_old); |
| 385 | 389 | ||
| 386 | struct auth_domain *auth_unix_lookup(struct in6_addr *addr) | 390 | struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr) |
| 387 | { | 391 | { |
| 388 | struct ip_map *ipm; | 392 | struct ip_map *ipm; |
| 389 | struct auth_domain *rv; | 393 | struct auth_domain *rv; |
| 394 | struct sunrpc_net *sn; | ||
| 390 | 395 | ||
| 391 | ipm = ip_map_lookup("nfsd", addr); | 396 | sn = net_generic(net, sunrpc_net_id); |
| 397 | ipm = ip_map_lookup(net, "nfsd", addr); | ||
| 392 | 398 | ||
| 393 | if (!ipm) | 399 | if (!ipm) |
| 394 | return NULL; | 400 | return NULL; |
| 395 | if (cache_check(&ip_map_cache, &ipm->h, NULL)) | 401 | if (cache_check(sn->ip_map_cache, &ipm->h, NULL)) |
| 396 | return NULL; | 402 | return NULL; |
| 397 | 403 | ||
| 398 | if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { | 404 | if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { |
| @@ -403,22 +409,29 @@ struct auth_domain *auth_unix_lookup(struct in6_addr *addr) | |||
| 403 | rv = &ipm->m_client->h; | 409 | rv = &ipm->m_client->h; |
| 404 | kref_get(&rv->ref); | 410 | kref_get(&rv->ref); |
| 405 | } | 411 | } |
| 406 | cache_put(&ipm->h, &ip_map_cache); | 412 | cache_put(&ipm->h, sn->ip_map_cache); |
| 407 | return rv; | 413 | return rv; |
| 408 | } | 414 | } |
| 409 | EXPORT_SYMBOL_GPL(auth_unix_lookup); | 415 | EXPORT_SYMBOL_GPL(auth_unix_lookup); |
| 410 | 416 | ||
| 411 | void svcauth_unix_purge(void) | 417 | void svcauth_unix_purge(void) |
| 412 | { | 418 | { |
| 413 | cache_purge(&ip_map_cache); | 419 | struct net *net; |
| 420 | |||
| 421 | for_each_net(net) { | ||
| 422 | struct sunrpc_net *sn; | ||
| 423 | |||
| 424 | sn = net_generic(net, sunrpc_net_id); | ||
| 425 | cache_purge(sn->ip_map_cache); | ||
| 426 | } | ||
| 414 | } | 427 | } |
| 415 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); | 428 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); |
| 416 | 429 | ||
| 417 | static inline struct ip_map * | 430 | static inline struct ip_map * |
| 418 | ip_map_cached_get(struct svc_rqst *rqstp) | 431 | ip_map_cached_get(struct svc_xprt *xprt) |
| 419 | { | 432 | { |
| 420 | struct ip_map *ipm = NULL; | 433 | struct ip_map *ipm = NULL; |
| 421 | struct svc_xprt *xprt = rqstp->rq_xprt; | 434 | struct sunrpc_net *sn; |
| 422 | 435 | ||
| 423 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { | 436 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { |
| 424 | spin_lock(&xprt->xpt_lock); | 437 | spin_lock(&xprt->xpt_lock); |
| @@ -430,9 +443,10 @@ ip_map_cached_get(struct svc_rqst *rqstp) | |||
| 430 | * remembered, e.g. by a second mount from the | 443 | * remembered, e.g. by a second mount from the |
| 431 | * same IP address. | 444 | * same IP address. |
| 432 | */ | 445 | */ |
| 446 | sn = net_generic(xprt->xpt_net, sunrpc_net_id); | ||
| 433 | xprt->xpt_auth_cache = NULL; | 447 | xprt->xpt_auth_cache = NULL; |
| 434 | spin_unlock(&xprt->xpt_lock); | 448 | spin_unlock(&xprt->xpt_lock); |
| 435 | cache_put(&ipm->h, &ip_map_cache); | 449 | cache_put(&ipm->h, sn->ip_map_cache); |
| 436 | return NULL; | 450 | return NULL; |
| 437 | } | 451 | } |
| 438 | cache_get(&ipm->h); | 452 | cache_get(&ipm->h); |
| @@ -443,10 +457,8 @@ ip_map_cached_get(struct svc_rqst *rqstp) | |||
| 443 | } | 457 | } |
| 444 | 458 | ||
| 445 | static inline void | 459 | static inline void |
| 446 | ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | 460 | ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm) |
| 447 | { | 461 | { |
| 448 | struct svc_xprt *xprt = rqstp->rq_xprt; | ||
| 449 | |||
| 450 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { | 462 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { |
| 451 | spin_lock(&xprt->xpt_lock); | 463 | spin_lock(&xprt->xpt_lock); |
| 452 | if (xprt->xpt_auth_cache == NULL) { | 464 | if (xprt->xpt_auth_cache == NULL) { |
| @@ -456,15 +468,26 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | |||
| 456 | } | 468 | } |
| 457 | spin_unlock(&xprt->xpt_lock); | 469 | spin_unlock(&xprt->xpt_lock); |
| 458 | } | 470 | } |
| 459 | if (ipm) | 471 | if (ipm) { |
| 460 | cache_put(&ipm->h, &ip_map_cache); | 472 | struct sunrpc_net *sn; |
| 473 | |||
| 474 | sn = net_generic(xprt->xpt_net, sunrpc_net_id); | ||
| 475 | cache_put(&ipm->h, sn->ip_map_cache); | ||
| 476 | } | ||
| 461 | } | 477 | } |
| 462 | 478 | ||
| 463 | void | 479 | void |
| 464 | svcauth_unix_info_release(void *info) | 480 | svcauth_unix_info_release(struct svc_xprt *xpt) |
| 465 | { | 481 | { |
| 466 | struct ip_map *ipm = info; | 482 | struct ip_map *ipm; |
| 467 | cache_put(&ipm->h, &ip_map_cache); | 483 | |
| 484 | ipm = xpt->xpt_auth_cache; | ||
| 485 | if (ipm != NULL) { | ||
| 486 | struct sunrpc_net *sn; | ||
| 487 | |||
| 488 | sn = net_generic(xpt->xpt_net, sunrpc_net_id); | ||
| 489 | cache_put(&ipm->h, sn->ip_map_cache); | ||
| 490 | } | ||
| 468 | } | 491 | } |
| 469 | 492 | ||
| 470 | /**************************************************************************** | 493 | /**************************************************************************** |
| @@ -674,6 +697,8 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
| 674 | switch (ret) { | 697 | switch (ret) { |
| 675 | case -ENOENT: | 698 | case -ENOENT: |
| 676 | return ERR_PTR(-ENOENT); | 699 | return ERR_PTR(-ENOENT); |
| 700 | case -ETIMEDOUT: | ||
| 701 | return ERR_PTR(-ESHUTDOWN); | ||
| 677 | case 0: | 702 | case 0: |
| 678 | gi = get_group_info(ug->gi); | 703 | gi = get_group_info(ug->gi); |
| 679 | cache_put(&ug->h, &unix_gid_cache); | 704 | cache_put(&ug->h, &unix_gid_cache); |
| @@ -691,6 +716,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
| 691 | struct ip_map *ipm; | 716 | struct ip_map *ipm; |
| 692 | struct group_info *gi; | 717 | struct group_info *gi; |
| 693 | struct svc_cred *cred = &rqstp->rq_cred; | 718 | struct svc_cred *cred = &rqstp->rq_cred; |
| 719 | struct svc_xprt *xprt = rqstp->rq_xprt; | ||
| 720 | struct net *net = xprt->xpt_net; | ||
| 721 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
| 694 | 722 | ||
| 695 | switch (rqstp->rq_addr.ss_family) { | 723 | switch (rqstp->rq_addr.ss_family) { |
| 696 | case AF_INET: | 724 | case AF_INET: |
| @@ -709,26 +737,27 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
| 709 | if (rqstp->rq_proc == 0) | 737 | if (rqstp->rq_proc == 0) |
| 710 | return SVC_OK; | 738 | return SVC_OK; |
| 711 | 739 | ||
| 712 | ipm = ip_map_cached_get(rqstp); | 740 | ipm = ip_map_cached_get(xprt); |
| 713 | if (ipm == NULL) | 741 | if (ipm == NULL) |
| 714 | ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, | 742 | ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class, |
| 715 | &sin6->sin6_addr); | 743 | &sin6->sin6_addr); |
| 716 | 744 | ||
| 717 | if (ipm == NULL) | 745 | if (ipm == NULL) |
| 718 | return SVC_DENIED; | 746 | return SVC_DENIED; |
| 719 | 747 | ||
| 720 | switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { | 748 | switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { |
| 721 | default: | 749 | default: |
| 722 | BUG(); | 750 | BUG(); |
| 723 | case -EAGAIN: | ||
| 724 | case -ETIMEDOUT: | 751 | case -ETIMEDOUT: |
| 752 | return SVC_CLOSE; | ||
| 753 | case -EAGAIN: | ||
| 725 | return SVC_DROP; | 754 | return SVC_DROP; |
| 726 | case -ENOENT: | 755 | case -ENOENT: |
| 727 | return SVC_DENIED; | 756 | return SVC_DENIED; |
| 728 | case 0: | 757 | case 0: |
| 729 | rqstp->rq_client = &ipm->m_client->h; | 758 | rqstp->rq_client = &ipm->m_client->h; |
| 730 | kref_get(&rqstp->rq_client->ref); | 759 | kref_get(&rqstp->rq_client->ref); |
| 731 | ip_map_cached_put(rqstp, ipm); | 760 | ip_map_cached_put(xprt, ipm); |
| 732 | break; | 761 | break; |
| 733 | } | 762 | } |
| 734 | 763 | ||
| @@ -736,6 +765,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
| 736 | switch (PTR_ERR(gi)) { | 765 | switch (PTR_ERR(gi)) { |
| 737 | case -EAGAIN: | 766 | case -EAGAIN: |
| 738 | return SVC_DROP; | 767 | return SVC_DROP; |
| 768 | case -ESHUTDOWN: | ||
| 769 | return SVC_CLOSE; | ||
| 739 | case -ENOENT: | 770 | case -ENOENT: |
| 740 | break; | 771 | break; |
| 741 | default: | 772 | default: |
| @@ -776,7 +807,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 776 | cred->cr_gid = (gid_t) -1; | 807 | cred->cr_gid = (gid_t) -1; |
| 777 | cred->cr_group_info = groups_alloc(0); | 808 | cred->cr_group_info = groups_alloc(0); |
| 778 | if (cred->cr_group_info == NULL) | 809 | if (cred->cr_group_info == NULL) |
| 779 | return SVC_DROP; /* kmalloc failure - client must retry */ | 810 | return SVC_CLOSE; /* kmalloc failure - client must retry */ |
| 780 | 811 | ||
| 781 | /* Put NULL verifier */ | 812 | /* Put NULL verifier */ |
| 782 | svc_putnl(resv, RPC_AUTH_NULL); | 813 | svc_putnl(resv, RPC_AUTH_NULL); |
| @@ -840,7 +871,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 840 | goto badcred; | 871 | goto badcred; |
| 841 | cred->cr_group_info = groups_alloc(slen); | 872 | cred->cr_group_info = groups_alloc(slen); |
| 842 | if (cred->cr_group_info == NULL) | 873 | if (cred->cr_group_info == NULL) |
| 843 | return SVC_DROP; | 874 | return SVC_CLOSE; |
| 844 | for (i = 0; i < slen; i++) | 875 | for (i = 0; i < slen; i++) |
| 845 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); | 876 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); |
| 846 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 877 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
| @@ -886,3 +917,56 @@ struct auth_ops svcauth_unix = { | |||
| 886 | .set_client = svcauth_unix_set_client, | 917 | .set_client = svcauth_unix_set_client, |
| 887 | }; | 918 | }; |
| 888 | 919 | ||
| 920 | int ip_map_cache_create(struct net *net) | ||
| 921 | { | ||
| 922 | int err = -ENOMEM; | ||
| 923 | struct cache_detail *cd; | ||
| 924 | struct cache_head **tbl; | ||
| 925 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
| 926 | |||
| 927 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | ||
| 928 | if (cd == NULL) | ||
| 929 | goto err_cd; | ||
| 930 | |||
| 931 | tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); | ||
| 932 | if (tbl == NULL) | ||
| 933 | goto err_tbl; | ||
| 934 | |||
| 935 | cd->owner = THIS_MODULE, | ||
| 936 | cd->hash_size = IP_HASHMAX, | ||
| 937 | cd->hash_table = tbl, | ||
| 938 | cd->name = "auth.unix.ip", | ||
| 939 | cd->cache_put = ip_map_put, | ||
| 940 | cd->cache_upcall = ip_map_upcall, | ||
| 941 | cd->cache_parse = ip_map_parse, | ||
| 942 | cd->cache_show = ip_map_show, | ||
| 943 | cd->match = ip_map_match, | ||
| 944 | cd->init = ip_map_init, | ||
| 945 | cd->update = update, | ||
| 946 | cd->alloc = ip_map_alloc, | ||
| 947 | |||
| 948 | err = cache_register_net(cd, net); | ||
| 949 | if (err) | ||
| 950 | goto err_reg; | ||
| 951 | |||
| 952 | sn->ip_map_cache = cd; | ||
| 953 | return 0; | ||
| 954 | |||
| 955 | err_reg: | ||
| 956 | kfree(tbl); | ||
| 957 | err_tbl: | ||
| 958 | kfree(cd); | ||
| 959 | err_cd: | ||
| 960 | return err; | ||
| 961 | } | ||
| 962 | |||
| 963 | void ip_map_cache_destroy(struct net *net) | ||
| 964 | { | ||
| 965 | struct sunrpc_net *sn; | ||
| 966 | |||
| 967 | sn = net_generic(net, sunrpc_net_id); | ||
| 968 | cache_purge(sn->ip_map_cache); | ||
| 969 | cache_unregister_net(sn->ip_map_cache, net); | ||
| 970 | kfree(sn->ip_map_cache->hash_table); | ||
| 971 | kfree(sn->ip_map_cache); | ||
| 972 | } | ||
