]> Pileus Git - ~andy/linux/blob - net/sunrpc/svcauth_unix.c
net: sunrpc: kill unused macros
[~andy/linux] / net / sunrpc / svcauth_unix.c
1 #include <linux/types.h>
2 #include <linux/sched.h>
3 #include <linux/module.h>
4 #include <linux/sunrpc/types.h>
5 #include <linux/sunrpc/xdr.h>
6 #include <linux/sunrpc/svcsock.h>
7 #include <linux/sunrpc/svcauth.h>
8 #include <linux/sunrpc/gss_api.h>
9 #include <linux/err.h>
10 #include <linux/seq_file.h>
11 #include <linux/hash.h>
12 #include <linux/string.h>
13 #include <linux/slab.h>
14 #include <net/sock.h>
15 #include <net/ipv6.h>
16 #include <linux/kernel.h>
17 #define RPCDBG_FACILITY RPCDBG_AUTH
18
19 #include <linux/sunrpc/clnt.h>
20
21 #include "netns.h"
22
23 /*
24  * AUTHUNIX and AUTHNULL credentials are both handled here.
25  * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
26  * are always nobody (-2).  i.e. we do the same IP address checks for
27  * AUTHNULL as for AUTHUNIX, and that is done here.
28  */
29
30
31 struct unix_domain {
32         struct auth_domain      h;
33         int     addr_changes;
34         /* other stuff later */
35 };
36
37 extern struct auth_ops svcauth_unix;
38
39 struct auth_domain *unix_domain_find(char *name)
40 {
41         struct auth_domain *rv;
42         struct unix_domain *new = NULL;
43
44         rv = auth_domain_lookup(name, NULL);
45         while(1) {
46                 if (rv) {
47                         if (new && rv != &new->h)
48                                 auth_domain_put(&new->h);
49
50                         if (rv->flavour != &svcauth_unix) {
51                                 auth_domain_put(rv);
52                                 return NULL;
53                         }
54                         return rv;
55                 }
56
57                 new = kmalloc(sizeof(*new), GFP_KERNEL);
58                 if (new == NULL)
59                         return NULL;
60                 kref_init(&new->h.ref);
61                 new->h.name = kstrdup(name, GFP_KERNEL);
62                 if (new->h.name == NULL) {
63                         kfree(new);
64                         return NULL;
65                 }
66                 new->h.flavour = &svcauth_unix;
67                 new->addr_changes = 0;
68                 rv = auth_domain_lookup(name, &new->h);
69         }
70 }
71 EXPORT_SYMBOL_GPL(unix_domain_find);
72
73 static void svcauth_unix_domain_release(struct auth_domain *dom)
74 {
75         struct unix_domain *ud = container_of(dom, struct unix_domain, h);
76
77         kfree(dom->name);
78         kfree(ud);
79 }
80
81
82 /**************************************************
83  * cache for IP address to unix_domain
84  * as needed by AUTH_UNIX
85  */
86 #define IP_HASHBITS     8
87 #define IP_HASHMAX      (1<<IP_HASHBITS)
88
89 struct ip_map {
90         struct cache_head       h;
91         char                    m_class[8]; /* e.g. "nfsd" */
92         struct in6_addr         m_addr;
93         struct unix_domain      *m_client;
94         int                     m_add_change;
95 };
96
97 static void ip_map_put(struct kref *kref)
98 {
99         struct cache_head *item = container_of(kref, struct cache_head, ref);
100         struct ip_map *im = container_of(item, struct ip_map,h);
101
102         if (test_bit(CACHE_VALID, &item->flags) &&
103             !test_bit(CACHE_NEGATIVE, &item->flags))
104                 auth_domain_put(&im->m_client->h);
105         kfree(im);
106 }
107
108 #if IP_HASHBITS == 8
109 /* hash_long on a 64 bit machine is currently REALLY BAD for
110  * IP addresses in reverse-endian (i.e. on a little-endian machine).
111  * So use a trivial but reliable hash instead
112  */
113 static inline int hash_ip(__be32 ip)
114 {
115         int hash = (__force u32)ip ^ ((__force u32)ip>>16);
116         return (hash ^ (hash>>8)) & 0xff;
117 }
118 #endif
119 static inline int hash_ip6(struct in6_addr ip)
120 {
121         return (hash_ip(ip.s6_addr32[0]) ^
122                 hash_ip(ip.s6_addr32[1]) ^
123                 hash_ip(ip.s6_addr32[2]) ^
124                 hash_ip(ip.s6_addr32[3]));
125 }
126 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
127 {
128         struct ip_map *orig = container_of(corig, struct ip_map, h);
129         struct ip_map *new = container_of(cnew, struct ip_map, h);
130         return strcmp(orig->m_class, new->m_class) == 0 &&
131                ipv6_addr_equal(&orig->m_addr, &new->m_addr);
132 }
133 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
134 {
135         struct ip_map *new = container_of(cnew, struct ip_map, h);
136         struct ip_map *item = container_of(citem, struct ip_map, h);
137
138         strcpy(new->m_class, item->m_class);
139         ipv6_addr_copy(&new->m_addr, &item->m_addr);
140 }
141 static void update(struct cache_head *cnew, struct cache_head *citem)
142 {
143         struct ip_map *new = container_of(cnew, struct ip_map, h);
144         struct ip_map *item = container_of(citem, struct ip_map, h);
145
146         kref_get(&item->m_client->h.ref);
147         new->m_client = item->m_client;
148         new->m_add_change = item->m_add_change;
149 }
150 static struct cache_head *ip_map_alloc(void)
151 {
152         struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
153         if (i)
154                 return &i->h;
155         else
156                 return NULL;
157 }
158
159 static void ip_map_request(struct cache_detail *cd,
160                                   struct cache_head *h,
161                                   char **bpp, int *blen)
162 {
163         char text_addr[40];
164         struct ip_map *im = container_of(h, struct ip_map, h);
165
166         if (ipv6_addr_v4mapped(&(im->m_addr))) {
167                 snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
168         } else {
169                 snprintf(text_addr, 40, "%pI6", &im->m_addr);
170         }
171         qword_add(bpp, blen, im->m_class);
172         qword_add(bpp, blen, text_addr);
173         (*bpp)[-1] = '\n';
174 }
175
176 static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
177 {
178         return sunrpc_cache_pipe_upcall(cd, h, ip_map_request);
179 }
180
181 static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
182 static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
183
184 static int ip_map_parse(struct cache_detail *cd,
185                           char *mesg, int mlen)
186 {
187         /* class ipaddress [domainname] */
188         /* should be safe just to use the start of the input buffer
189          * for scratch: */
190         char *buf = mesg;
191         int len;
192         char class[8];
193         union {
194                 struct sockaddr         sa;
195                 struct sockaddr_in      s4;
196                 struct sockaddr_in6     s6;
197         } address;
198         struct sockaddr_in6 sin6;
199         int err;
200
201         struct ip_map *ipmp;
202         struct auth_domain *dom;
203         time_t expiry;
204
205         if (mesg[mlen-1] != '\n')
206                 return -EINVAL;
207         mesg[mlen-1] = 0;
208
209         /* class */
210         len = qword_get(&mesg, class, sizeof(class));
211         if (len <= 0) return -EINVAL;
212
213         /* ip address */
214         len = qword_get(&mesg, buf, mlen);
215         if (len <= 0) return -EINVAL;
216
217         if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0)
218                 return -EINVAL;
219         switch (address.sa.sa_family) {
220         case AF_INET:
221                 /* Form a mapped IPv4 address in sin6 */
222                 sin6.sin6_family = AF_INET6;
223                 ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
224                                 &sin6.sin6_addr);
225                 break;
226 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
227         case AF_INET6:
228                 memcpy(&sin6, &address.s6, sizeof(sin6));
229                 break;
230 #endif
231         default:
232                 return -EINVAL;
233         }
234
235         expiry = get_expiry(&mesg);
236         if (expiry ==0)
237                 return -EINVAL;
238
239         /* domainname, or empty for NEGATIVE */
240         len = qword_get(&mesg, buf, mlen);
241         if (len < 0) return -EINVAL;
242
243         if (len) {
244                 dom = unix_domain_find(buf);
245                 if (dom == NULL)
246                         return -ENOENT;
247         } else
248                 dom = NULL;
249
250         /* IPv6 scope IDs are ignored for now */
251         ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
252         if (ipmp) {
253                 err = __ip_map_update(cd, ipmp,
254                              container_of(dom, struct unix_domain, h),
255                              expiry);
256         } else
257                 err = -ENOMEM;
258
259         if (dom)
260                 auth_domain_put(dom);
261
262         cache_flush();
263         return err;
264 }
265
266 static int ip_map_show(struct seq_file *m,
267                        struct cache_detail *cd,
268                        struct cache_head *h)
269 {
270         struct ip_map *im;
271         struct in6_addr addr;
272         char *dom = "-no-domain-";
273
274         if (h == NULL) {
275                 seq_puts(m, "#class IP domain\n");
276                 return 0;
277         }
278         im = container_of(h, struct ip_map, h);
279         /* class addr domain */
280         ipv6_addr_copy(&addr, &im->m_addr);
281
282         if (test_bit(CACHE_VALID, &h->flags) &&
283             !test_bit(CACHE_NEGATIVE, &h->flags))
284                 dom = im->m_client->h.name;
285
286         if (ipv6_addr_v4mapped(&addr)) {
287                 seq_printf(m, "%s %pI4 %s\n",
288                         im->m_class, &addr.s6_addr32[3], dom);
289         } else {
290                 seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
291         }
292         return 0;
293 }
294
295
296 static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
297                 struct in6_addr *addr)
298 {
299         struct ip_map ip;
300         struct cache_head *ch;
301
302         strcpy(ip.m_class, class);
303         ipv6_addr_copy(&ip.m_addr, addr);
304         ch = sunrpc_cache_lookup(cd, &ip.h,
305                                  hash_str(class, IP_HASHBITS) ^
306                                  hash_ip6(*addr));
307
308         if (ch)
309                 return container_of(ch, struct ip_map, h);
310         else
311                 return NULL;
312 }
313
314 static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
315                 struct in6_addr *addr)
316 {
317         struct sunrpc_net *sn;
318
319         sn = net_generic(net, sunrpc_net_id);
320         return __ip_map_lookup(sn->ip_map_cache, class, addr);
321 }
322
323 static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
324                 struct unix_domain *udom, time_t expiry)
325 {
326         struct ip_map ip;
327         struct cache_head *ch;
328
329         ip.m_client = udom;
330         ip.h.flags = 0;
331         if (!udom)
332                 set_bit(CACHE_NEGATIVE, &ip.h.flags);
333         else {
334                 ip.m_add_change = udom->addr_changes;
335                 /* if this is from the legacy set_client system call,
336                  * we need m_add_change to be one higher
337                  */
338                 if (expiry == NEVER)
339                         ip.m_add_change++;
340         }
341         ip.h.expiry_time = expiry;
342         ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
343                                  hash_str(ipm->m_class, IP_HASHBITS) ^
344                                  hash_ip6(ipm->m_addr));
345         if (!ch)
346                 return -ENOMEM;
347         cache_put(ch, cd);
348         return 0;
349 }
350
351 static inline int ip_map_update(struct net *net, struct ip_map *ipm,
352                 struct unix_domain *udom, time_t expiry)
353 {
354         struct sunrpc_net *sn;
355
356         sn = net_generic(net, sunrpc_net_id);
357         return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
358 }
359
360 int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
361 {
362         struct unix_domain *udom;
363         struct ip_map *ipmp;
364
365         if (dom->flavour != &svcauth_unix)
366                 return -EINVAL;
367         udom = container_of(dom, struct unix_domain, h);
368         ipmp = ip_map_lookup(net, "nfsd", addr);
369
370         if (ipmp)
371                 return ip_map_update(net, ipmp, udom, NEVER);
372         else
373                 return -ENOMEM;
374 }
375 EXPORT_SYMBOL_GPL(auth_unix_add_addr);
376
377 int auth_unix_forget_old(struct auth_domain *dom)
378 {
379         struct unix_domain *udom;
380
381         if (dom->flavour != &svcauth_unix)
382                 return -EINVAL;
383         udom = container_of(dom, struct unix_domain, h);
384         udom->addr_changes++;
385         return 0;
386 }
387 EXPORT_SYMBOL_GPL(auth_unix_forget_old);
388
389 struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
390 {
391         struct ip_map *ipm;
392         struct auth_domain *rv;
393         struct sunrpc_net *sn;
394
395         sn = net_generic(net, sunrpc_net_id);
396         ipm = ip_map_lookup(net, "nfsd", addr);
397
398         if (!ipm)
399                 return NULL;
400         if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
401                 return NULL;
402
403         if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
404                 if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
405                         auth_domain_put(&ipm->m_client->h);
406                 rv = NULL;
407         } else {
408                 rv = &ipm->m_client->h;
409                 kref_get(&rv->ref);
410         }
411         cache_put(&ipm->h, sn->ip_map_cache);
412         return rv;
413 }
414 EXPORT_SYMBOL_GPL(auth_unix_lookup);
415
416 void svcauth_unix_purge(void)
417 {
418         struct net *net;
419
420         for_each_net(net) {
421                 struct sunrpc_net *sn;
422
423                 sn = net_generic(net, sunrpc_net_id);
424                 cache_purge(sn->ip_map_cache);
425         }
426 }
427 EXPORT_SYMBOL_GPL(svcauth_unix_purge);
428
429 static inline struct ip_map *
430 ip_map_cached_get(struct svc_xprt *xprt)
431 {
432         struct ip_map *ipm = NULL;
433         struct sunrpc_net *sn;
434
435         if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
436                 spin_lock(&xprt->xpt_lock);
437                 ipm = xprt->xpt_auth_cache;
438                 if (ipm != NULL) {
439                         if (!cache_valid(&ipm->h)) {
440                                 /*
441                                  * The entry has been invalidated since it was
442                                  * remembered, e.g. by a second mount from the
443                                  * same IP address.
444                                  */
445                                 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
446                                 xprt->xpt_auth_cache = NULL;
447                                 spin_unlock(&xprt->xpt_lock);
448                                 cache_put(&ipm->h, sn->ip_map_cache);
449                                 return NULL;
450                         }
451                         cache_get(&ipm->h);
452                 }
453                 spin_unlock(&xprt->xpt_lock);
454         }
455         return ipm;
456 }
457
458 static inline void
459 ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
460 {
461         if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
462                 spin_lock(&xprt->xpt_lock);
463                 if (xprt->xpt_auth_cache == NULL) {
464                         /* newly cached, keep the reference */
465                         xprt->xpt_auth_cache = ipm;
466                         ipm = NULL;
467                 }
468                 spin_unlock(&xprt->xpt_lock);
469         }
470         if (ipm) {
471                 struct sunrpc_net *sn;
472
473                 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
474                 cache_put(&ipm->h, sn->ip_map_cache);
475         }
476 }
477
478 void
479 svcauth_unix_info_release(struct svc_xprt *xpt)
480 {
481         struct ip_map *ipm;
482
483         ipm = xpt->xpt_auth_cache;
484         if (ipm != NULL) {
485                 struct sunrpc_net *sn;
486
487                 sn = net_generic(xpt->xpt_net, sunrpc_net_id);
488                 cache_put(&ipm->h, sn->ip_map_cache);
489         }
490 }
491
492 /****************************************************************************
493  * auth.unix.gid cache
494  * simple cache to map a UID to a list of GIDs
495  * because AUTH_UNIX aka AUTH_SYS has a max of 16
496  */
497 #define GID_HASHBITS    8
498 #define GID_HASHMAX     (1<<GID_HASHBITS)
499
500 struct unix_gid {
501         struct cache_head       h;
502         uid_t                   uid;
503         struct group_info       *gi;
504 };
505 static struct cache_head        *gid_table[GID_HASHMAX];
506
507 static void unix_gid_put(struct kref *kref)
508 {
509         struct cache_head *item = container_of(kref, struct cache_head, ref);
510         struct unix_gid *ug = container_of(item, struct unix_gid, h);
511         if (test_bit(CACHE_VALID, &item->flags) &&
512             !test_bit(CACHE_NEGATIVE, &item->flags))
513                 put_group_info(ug->gi);
514         kfree(ug);
515 }
516
517 static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
518 {
519         struct unix_gid *orig = container_of(corig, struct unix_gid, h);
520         struct unix_gid *new = container_of(cnew, struct unix_gid, h);
521         return orig->uid == new->uid;
522 }
523 static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
524 {
525         struct unix_gid *new = container_of(cnew, struct unix_gid, h);
526         struct unix_gid *item = container_of(citem, struct unix_gid, h);
527         new->uid = item->uid;
528 }
529 static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
530 {
531         struct unix_gid *new = container_of(cnew, struct unix_gid, h);
532         struct unix_gid *item = container_of(citem, struct unix_gid, h);
533
534         get_group_info(item->gi);
535         new->gi = item->gi;
536 }
537 static struct cache_head *unix_gid_alloc(void)
538 {
539         struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
540         if (g)
541                 return &g->h;
542         else
543                 return NULL;
544 }
545
546 static void unix_gid_request(struct cache_detail *cd,
547                              struct cache_head *h,
548                              char **bpp, int *blen)
549 {
550         char tuid[20];
551         struct unix_gid *ug = container_of(h, struct unix_gid, h);
552
553         snprintf(tuid, 20, "%u", ug->uid);
554         qword_add(bpp, blen, tuid);
555         (*bpp)[-1] = '\n';
556 }
557
558 static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
559 {
560         return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request);
561 }
562
563 static struct unix_gid *unix_gid_lookup(uid_t uid);
564 extern struct cache_detail unix_gid_cache;
565
566 static int unix_gid_parse(struct cache_detail *cd,
567                         char *mesg, int mlen)
568 {
569         /* uid expiry Ngid gid0 gid1 ... gidN-1 */
570         int uid;
571         int gids;
572         int rv;
573         int i;
574         int err;
575         time_t expiry;
576         struct unix_gid ug, *ugp;
577
578         if (mlen <= 0 || mesg[mlen-1] != '\n')
579                 return -EINVAL;
580         mesg[mlen-1] = 0;
581
582         rv = get_int(&mesg, &uid);
583         if (rv)
584                 return -EINVAL;
585         ug.uid = uid;
586
587         expiry = get_expiry(&mesg);
588         if (expiry == 0)
589                 return -EINVAL;
590
591         rv = get_int(&mesg, &gids);
592         if (rv || gids < 0 || gids > 8192)
593                 return -EINVAL;
594
595         ug.gi = groups_alloc(gids);
596         if (!ug.gi)
597                 return -ENOMEM;
598
599         for (i = 0 ; i < gids ; i++) {
600                 int gid;
601                 rv = get_int(&mesg, &gid);
602                 err = -EINVAL;
603                 if (rv)
604                         goto out;
605                 GROUP_AT(ug.gi, i) = gid;
606         }
607
608         ugp = unix_gid_lookup(uid);
609         if (ugp) {
610                 struct cache_head *ch;
611                 ug.h.flags = 0;
612                 ug.h.expiry_time = expiry;
613                 ch = sunrpc_cache_update(&unix_gid_cache,
614                                          &ug.h, &ugp->h,
615                                          hash_long(uid, GID_HASHBITS));
616                 if (!ch)
617                         err = -ENOMEM;
618                 else {
619                         err = 0;
620                         cache_put(ch, &unix_gid_cache);
621                 }
622         } else
623                 err = -ENOMEM;
624  out:
625         if (ug.gi)
626                 put_group_info(ug.gi);
627         return err;
628 }
629
630 static int unix_gid_show(struct seq_file *m,
631                          struct cache_detail *cd,
632                          struct cache_head *h)
633 {
634         struct unix_gid *ug;
635         int i;
636         int glen;
637
638         if (h == NULL) {
639                 seq_puts(m, "#uid cnt: gids...\n");
640                 return 0;
641         }
642         ug = container_of(h, struct unix_gid, h);
643         if (test_bit(CACHE_VALID, &h->flags) &&
644             !test_bit(CACHE_NEGATIVE, &h->flags))
645                 glen = ug->gi->ngroups;
646         else
647                 glen = 0;
648
649         seq_printf(m, "%u %d:", ug->uid, glen);
650         for (i = 0; i < glen; i++)
651                 seq_printf(m, " %d", GROUP_AT(ug->gi, i));
652         seq_printf(m, "\n");
653         return 0;
654 }
655
656 struct cache_detail unix_gid_cache = {
657         .owner          = THIS_MODULE,
658         .hash_size      = GID_HASHMAX,
659         .hash_table     = gid_table,
660         .name           = "auth.unix.gid",
661         .cache_put      = unix_gid_put,
662         .cache_upcall   = unix_gid_upcall,
663         .cache_parse    = unix_gid_parse,
664         .cache_show     = unix_gid_show,
665         .match          = unix_gid_match,
666         .init           = unix_gid_init,
667         .update         = unix_gid_update,
668         .alloc          = unix_gid_alloc,
669 };
670
671 static struct unix_gid *unix_gid_lookup(uid_t uid)
672 {
673         struct unix_gid ug;
674         struct cache_head *ch;
675
676         ug.uid = uid;
677         ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h,
678                                  hash_long(uid, GID_HASHBITS));
679         if (ch)
680                 return container_of(ch, struct unix_gid, h);
681         else
682                 return NULL;
683 }
684
685 static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
686 {
687         struct unix_gid *ug;
688         struct group_info *gi;
689         int ret;
690
691         ug = unix_gid_lookup(uid);
692         if (!ug)
693                 return ERR_PTR(-EAGAIN);
694         ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
695         switch (ret) {
696         case -ENOENT:
697                 return ERR_PTR(-ENOENT);
698         case -ETIMEDOUT:
699                 return ERR_PTR(-ESHUTDOWN);
700         case 0:
701                 gi = get_group_info(ug->gi);
702                 cache_put(&ug->h, &unix_gid_cache);
703                 return gi;
704         default:
705                 return ERR_PTR(-EAGAIN);
706         }
707 }
708
709 int
710 svcauth_unix_set_client(struct svc_rqst *rqstp)
711 {
712         struct sockaddr_in *sin;
713         struct sockaddr_in6 *sin6, sin6_storage;
714         struct ip_map *ipm;
715         struct group_info *gi;
716         struct svc_cred *cred = &rqstp->rq_cred;
717         struct svc_xprt *xprt = rqstp->rq_xprt;
718         struct net *net = xprt->xpt_net;
719         struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
720
721         switch (rqstp->rq_addr.ss_family) {
722         case AF_INET:
723                 sin = svc_addr_in(rqstp);
724                 sin6 = &sin6_storage;
725                 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
726                 break;
727         case AF_INET6:
728                 sin6 = svc_addr_in6(rqstp);
729                 break;
730         default:
731                 BUG();
732         }
733
734         rqstp->rq_client = NULL;
735         if (rqstp->rq_proc == 0)
736                 return SVC_OK;
737
738         ipm = ip_map_cached_get(xprt);
739         if (ipm == NULL)
740                 ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
741                                     &sin6->sin6_addr);
742
743         if (ipm == NULL)
744                 return SVC_DENIED;
745
746         switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
747                 default:
748                         BUG();
749                 case -ETIMEDOUT:
750                         return SVC_CLOSE;
751                 case -EAGAIN:
752                         return SVC_DROP;
753                 case -ENOENT:
754                         return SVC_DENIED;
755                 case 0:
756                         rqstp->rq_client = &ipm->m_client->h;
757                         kref_get(&rqstp->rq_client->ref);
758                         ip_map_cached_put(xprt, ipm);
759                         break;
760         }
761
762         gi = unix_gid_find(cred->cr_uid, rqstp);
763         switch (PTR_ERR(gi)) {
764         case -EAGAIN:
765                 return SVC_DROP;
766         case -ESHUTDOWN:
767                 return SVC_CLOSE;
768         case -ENOENT:
769                 break;
770         default:
771                 put_group_info(cred->cr_group_info);
772                 cred->cr_group_info = gi;
773         }
774         return SVC_OK;
775 }
776
777 EXPORT_SYMBOL_GPL(svcauth_unix_set_client);
778
779 static int
780 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
781 {
782         struct kvec     *argv = &rqstp->rq_arg.head[0];
783         struct kvec     *resv = &rqstp->rq_res.head[0];
784         struct svc_cred *cred = &rqstp->rq_cred;
785
786         cred->cr_group_info = NULL;
787         rqstp->rq_client = NULL;
788
789         if (argv->iov_len < 3*4)
790                 return SVC_GARBAGE;
791
792         if (svc_getu32(argv) != 0) {
793                 dprintk("svc: bad null cred\n");
794                 *authp = rpc_autherr_badcred;
795                 return SVC_DENIED;
796         }
797         if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
798                 dprintk("svc: bad null verf\n");
799                 *authp = rpc_autherr_badverf;
800                 return SVC_DENIED;
801         }
802
803         /* Signal that mapping to nobody uid/gid is required */
804         cred->cr_uid = (uid_t) -1;
805         cred->cr_gid = (gid_t) -1;
806         cred->cr_group_info = groups_alloc(0);
807         if (cred->cr_group_info == NULL)
808                 return SVC_CLOSE; /* kmalloc failure - client must retry */
809
810         /* Put NULL verifier */
811         svc_putnl(resv, RPC_AUTH_NULL);
812         svc_putnl(resv, 0);
813
814         rqstp->rq_flavor = RPC_AUTH_NULL;
815         return SVC_OK;
816 }
817
818 static int
819 svcauth_null_release(struct svc_rqst *rqstp)
820 {
821         if (rqstp->rq_client)
822                 auth_domain_put(rqstp->rq_client);
823         rqstp->rq_client = NULL;
824         if (rqstp->rq_cred.cr_group_info)
825                 put_group_info(rqstp->rq_cred.cr_group_info);
826         rqstp->rq_cred.cr_group_info = NULL;
827
828         return 0; /* don't drop */
829 }
830
831
832 struct auth_ops svcauth_null = {
833         .name           = "null",
834         .owner          = THIS_MODULE,
835         .flavour        = RPC_AUTH_NULL,
836         .accept         = svcauth_null_accept,
837         .release        = svcauth_null_release,
838         .set_client     = svcauth_unix_set_client,
839 };
840
841
842 static int
843 svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
844 {
845         struct kvec     *argv = &rqstp->rq_arg.head[0];
846         struct kvec     *resv = &rqstp->rq_res.head[0];
847         struct svc_cred *cred = &rqstp->rq_cred;
848         u32             slen, i;
849         int             len   = argv->iov_len;
850
851         cred->cr_group_info = NULL;
852         rqstp->rq_client = NULL;
853
854         if ((len -= 3*4) < 0)
855                 return SVC_GARBAGE;
856
857         svc_getu32(argv);                       /* length */
858         svc_getu32(argv);                       /* time stamp */
859         slen = XDR_QUADLEN(svc_getnl(argv));    /* machname length */
860         if (slen > 64 || (len -= (slen + 3)*4) < 0)
861                 goto badcred;
862         argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
863         argv->iov_len -= slen*4;
864
865         cred->cr_uid = svc_getnl(argv);         /* uid */
866         cred->cr_gid = svc_getnl(argv);         /* gid */
867         slen = svc_getnl(argv);                 /* gids length */
868         if (slen > 16 || (len -= (slen + 2)*4) < 0)
869                 goto badcred;
870         cred->cr_group_info = groups_alloc(slen);
871         if (cred->cr_group_info == NULL)
872                 return SVC_CLOSE;
873         for (i = 0; i < slen; i++)
874                 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
875         if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
876                 *authp = rpc_autherr_badverf;
877                 return SVC_DENIED;
878         }
879
880         /* Put NULL verifier */
881         svc_putnl(resv, RPC_AUTH_NULL);
882         svc_putnl(resv, 0);
883
884         rqstp->rq_flavor = RPC_AUTH_UNIX;
885         return SVC_OK;
886
887 badcred:
888         *authp = rpc_autherr_badcred;
889         return SVC_DENIED;
890 }
891
892 static int
893 svcauth_unix_release(struct svc_rqst *rqstp)
894 {
895         /* Verifier (such as it is) is already in place.
896          */
897         if (rqstp->rq_client)
898                 auth_domain_put(rqstp->rq_client);
899         rqstp->rq_client = NULL;
900         if (rqstp->rq_cred.cr_group_info)
901                 put_group_info(rqstp->rq_cred.cr_group_info);
902         rqstp->rq_cred.cr_group_info = NULL;
903
904         return 0;
905 }
906
907
908 struct auth_ops svcauth_unix = {
909         .name           = "unix",
910         .owner          = THIS_MODULE,
911         .flavour        = RPC_AUTH_UNIX,
912         .accept         = svcauth_unix_accept,
913         .release        = svcauth_unix_release,
914         .domain_release = svcauth_unix_domain_release,
915         .set_client     = svcauth_unix_set_client,
916 };
917
918 int ip_map_cache_create(struct net *net)
919 {
920         int err = -ENOMEM;
921         struct cache_detail *cd;
922         struct cache_head **tbl;
923         struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
924
925         cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
926         if (cd == NULL)
927                 goto err_cd;
928
929         tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
930         if (tbl == NULL)
931                 goto err_tbl;
932
933         cd->owner = THIS_MODULE,
934         cd->hash_size = IP_HASHMAX,
935         cd->hash_table = tbl,
936         cd->name = "auth.unix.ip",
937         cd->cache_put = ip_map_put,
938         cd->cache_upcall = ip_map_upcall,
939         cd->cache_parse = ip_map_parse,
940         cd->cache_show = ip_map_show,
941         cd->match = ip_map_match,
942         cd->init = ip_map_init,
943         cd->update = update,
944         cd->alloc = ip_map_alloc,
945
946         err = cache_register_net(cd, net);
947         if (err)
948                 goto err_reg;
949
950         sn->ip_map_cache = cd;
951         return 0;
952
953 err_reg:
954         kfree(tbl);
955 err_tbl:
956         kfree(cd);
957 err_cd:
958         return err;
959 }
960
961 void ip_map_cache_destroy(struct net *net)
962 {
963         struct sunrpc_net *sn;
964
965         sn = net_generic(net, sunrpc_net_id);
966         cache_purge(sn->ip_map_cache);
967         cache_unregister_net(sn->ip_map_cache, net);
968         kfree(sn->ip_map_cache->hash_table);
969         kfree(sn->ip_map_cache);
970 }