]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/amd/hlfsd/stubs.c
MFV r277870
[FreeBSD/FreeBSD.git] / contrib / amd / hlfsd / stubs.c
1 /*
2  * Copyright (c) 1997-2006 Erez Zadok
3  * Copyright (c) 1989 Jan-Simon Pendry
4  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5  * Copyright (c) 1989 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry at Imperial College, London.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgment:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *
40  * File: am-utils/hlfsd/stubs.c
41  *
42  * HLFSD was written at Columbia University Computer Science Department, by
43  * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
44  * It is being distributed under the same terms and conditions as amd does.
45  */
46
47 #ifdef HAVE_CONFIG_H
48 # include <config.h>
49 #endif /* HAVE_CONFIG_H */
50 #include <am_defs.h>
51 #include <hlfsd.h>
52
53 /*
54  * STATIC VARIABLES:
55  */
56 static nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0,
57                              1, 0, ROOTID};
58 static nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
59                               (NFS_MAXPATHLEN + 1) / 512, 0, SLINKID};
60                                 /* user name file attributes */
61 static nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
62                             (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID};
63 static int started;
64 static am_nfs_fh slink;
65 static am_nfs_fh un_fhandle;
66
67 /*
68  * GLOBALS:
69  */
70 am_nfs_fh root;
71 am_nfs_fh *root_fhp =           &root;
72
73
74 /* initialize NFS file handles for hlfsd */
75 void
76 hlfsd_init_filehandles(void)
77 {
78   u_int ui;
79
80   ui = ROOTID;
81   memcpy(root.fh_data, &ui, sizeof(ui));
82
83   ui = SLINKID;
84   memcpy(slink.fh_data, &ui, sizeof(ui));
85
86   ui = INVALIDID;
87   memcpy(un_fhandle.fh_data, &ui, sizeof(ui));
88 }
89
90
91 voidp
92 nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
93 {
94   static char res;
95
96   return (voidp) &res;
97 }
98
99
100 /* compare if two filehandles are equal */
101 static int
102 eq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2)
103 {
104   return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh)));
105 }
106
107
108 nfsattrstat *
109 nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
110 {
111   static nfsattrstat res;
112   uid_t uid = (uid_t) INVALIDID;
113   gid_t gid = (gid_t) INVALIDID;
114
115   if (!started) {
116     started++;
117     rootfattr.na_ctime = startup;
118     rootfattr.na_mtime = startup;
119     slinkfattr.na_ctime = startup;
120     slinkfattr.na_mtime = startup;
121     un_fattr.na_ctime = startup;
122     un_fattr.na_mtime = startup;
123   }
124
125   if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
126     res.ns_status = NFSERR_STALE;
127     return &res;
128   }
129   if (eq_fh(argp, &root)) {
130 #if 0
131     /*
132      * XXX: increment mtime of parent directory, causes NFS clients to
133      * invalidate their cache for that directory.
134      * Some NFS clients may need this code.
135      */
136     if (uid != rootfattr.na_uid) {
137       clocktime(&rootfattr.na_mtime);
138       rootfattr.na_uid = uid;
139     }
140 #endif
141     res.ns_status = NFS_OK;
142     res.ns_u.ns_attr_u = rootfattr;
143   } else if (eq_fh(argp, &slink)) {
144
145 #ifndef MNT2_NFS_OPT_SYMTTL
146     /*
147      * This code is needed to defeat Solaris 2.4's (and newer) symlink
148      * values cache.  It forces the last-modified time of the symlink to be
149      * current.  It is not needed if the O/S has an nfs flag to turn off the
150      * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
151      *
152      * Additionally, Linux currently ignores the nt_useconds field,
153      * so we must update the nt_seconds field every time.
154      */
155     if (uid != slinkfattr.na_uid) {
156       clocktime(&slinkfattr.na_mtime);
157       slinkfattr.na_uid = uid;
158     }
159 #endif /* not MNT2_NFS_OPT_SYMTTL */
160
161     res.ns_status = NFS_OK;
162     res.ns_u.ns_attr_u = slinkfattr;
163   } else {
164     if (gid != hlfs_gid) {
165       res.ns_status = NFSERR_STALE;
166     } else {
167       (void)memcpy(&uid, argp->fh_data, sizeof(uid));
168       if (plt_search(uid) != (uid2home_t *) NULL) {
169         res.ns_status = NFS_OK;
170         un_fattr.na_fileid = uid;
171         res.ns_u.ns_attr_u = un_fattr;
172         dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
173              (long) uid, (long) gid);
174       } else {                  /* not found */
175         res.ns_status = NFSERR_STALE;
176       }
177     }
178   }
179   return &res;
180 }
181
182
183 nfsattrstat *
184 nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
185 {
186   static nfsattrstat res = {NFSERR_ROFS};
187
188   return &res;
189 }
190
191
192 voidp
193 nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
194 {
195   static char res;
196
197   return (voidp) &res;
198 }
199
200
201 nfsdiropres *
202 nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
203 {
204   static nfsdiropres res;
205   int idx;
206   uid_t uid = (uid_t) INVALIDID;
207   gid_t gid = (gid_t) INVALIDID;
208
209   if (!started) {
210     started++;
211     rootfattr.na_ctime = startup;
212     rootfattr.na_mtime = startup;
213     slinkfattr.na_ctime = startup;
214     slinkfattr.na_mtime = startup;
215     un_fattr.na_ctime = startup;
216     un_fattr.na_mtime = startup;
217   }
218
219   if (eq_fh(&argp->da_fhandle, &slink)) {
220     res.dr_status = NFSERR_NOTDIR;
221     return &res;
222   }
223
224   if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
225     res.dr_status = NFSERR_NOENT;
226     return &res;
227   }
228   if (eq_fh(&argp->da_fhandle, &root)) {
229     if (argp->da_name[0] == '.' &&
230         (argp->da_name[1] == '\0' ||
231          (argp->da_name[1] == '.' &&
232           argp->da_name[2] == '\0'))) {
233 #if 0
234     /*
235      * XXX: increment mtime of parent directory, causes NFS clients to
236      * invalidate their cache for that directory.
237      * Some NFS clients may need this code.
238      */
239       if (uid != rootfattr.na_uid) {
240         clocktime(&rootfattr.na_mtime);
241         rootfattr.na_uid = uid;
242       }
243 #endif
244       res.dr_u.dr_drok_u.drok_fhandle = root;
245       res.dr_u.dr_drok_u.drok_attributes = rootfattr;
246       res.dr_status = NFS_OK;
247       return &res;
248     }
249
250     if (STREQ(argp->da_name, slinkname)) {
251 #ifndef MNT2_NFS_OPT_SYMTTL
252       /*
253        * This code is needed to defeat Solaris 2.4's (and newer) symlink
254        * values cache.  It forces the last-modified time of the symlink to be
255        * current.  It is not needed if the O/S has an nfs flag to turn off the
256        * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
257        *
258        * Additionally, Linux currently ignores the nt_useconds field,
259        * so we must update the nt_seconds field every time.
260        */
261       if (uid != slinkfattr.na_uid) {
262         clocktime(&slinkfattr.na_mtime);
263         slinkfattr.na_uid = uid;
264       }
265 #endif /* not MNT2_NFS_OPT_SYMTTL */
266       res.dr_u.dr_drok_u.drok_fhandle = slink;
267       res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
268       res.dr_status = NFS_OK;
269       return &res;
270     }
271
272     if (gid != hlfs_gid) {
273       res.dr_status = NFSERR_NOENT;
274       return &res;
275     }
276
277     /* if gets here, gid == hlfs_gid */
278     if ((idx = untab_index(argp->da_name)) < 0) {
279       res.dr_status = NFSERR_NOENT;
280       return &res;
281     } else {                    /* entry found and gid is permitted */
282       un_fattr.na_fileid = untab[idx].uid;
283       res.dr_u.dr_drok_u.drok_attributes = un_fattr;
284       memset(&un_fhandle, 0, sizeof(un_fhandle));
285       memcpy(un_fhandle.fh_data, &untab[idx].uid, sizeof(untab[idx].uid));
286       xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
287                untab[idx].username,
288                sizeof(am_nfs_fh) - sizeof(int));
289       res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
290       res.dr_status = NFS_OK;
291       dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
292            (long) uid, (long) gid, untab[idx].username);
293       return &res;
294     }
295   } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
296
297   res.dr_status = NFSERR_STALE;
298   return &res;
299 }
300
301
302 nfsreadlinkres *
303 nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
304 {
305   static nfsreadlinkres res;
306   uid_t userid = (uid_t) INVALIDID;
307   gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */
308   int retval = 0;
309   char *path_val = (char *) NULL;
310   char *username;
311   static uid_t last_uid = (uid_t) INVALIDID;
312
313   if (eq_fh(argp, &root)) {
314     res.rlr_status = NFSERR_ISDIR;
315   } else if (eq_fh(argp, &slink)) {
316     if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
317       return (nfsreadlinkres *) NULL;
318
319     clocktime(&slinkfattr.na_atime);
320
321     res.rlr_status = NFS_OK;
322     if (groupid == hlfs_gid) {
323       res.rlr_u.rlr_data_u = DOTSTRING;
324     } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
325       /*
326        * parent process (fork in homedir()) continues
327        * processing, by getting a NULL returned as a
328        * "special".  Child returns result.
329        */
330       return (nfsreadlinkres *) NULL;
331     }
332
333   } else {                      /* check if asked for user mailbox */
334
335     if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
336       return (nfsreadlinkres *) NULL;
337     }
338
339     if (groupid == hlfs_gid) {
340       memcpy(&userid, argp->fh_data, sizeof(userid));
341       username = (char *) &argp->fh_data[sizeof(int)];
342       if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
343         return (nfsreadlinkres *) NULL;
344     } else {
345       res.rlr_status = NFSERR_STALE;
346     }
347   }
348
349   /* print info, but try to avoid repetitions */
350   if (userid != last_uid) {
351     plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
352          (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
353     last_uid = userid;
354   }
355
356   /* I don't think it will pass this if -D fork */
357   if (serverpid == getpid())
358     return &res;
359
360   if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
361     svcerr_systemerr(nfsxprt);
362
363   /*
364    * Child exists here.   We need to determine which
365    * exist status to return.  The exit status
366    * is gathered using wait() and determines
367    * if we returned $HOME/.hlfsspool or $ALTDIR.  The parent
368    * needs this info so it can update the lookup table.
369    */
370   if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
371     retval = 1;         /* could not get real home dir (or uid 0 user) */
372   else
373     retval = 0;
374
375   /*
376    * If asked for -D fork, then must return the value,
377    * NOT exit, or else the main hlfsd server exits.
378    * Bug: where is that status information being collected?
379    */
380   if (amuDebug(D_FORK))
381     return &res;
382
383   exit(retval);
384 }
385
386
387 nfsreadres *
388 nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
389 {
390   static nfsreadres res = {NFSERR_ACCES};
391
392   return &res;
393 }
394
395
396 voidp
397 nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
398 {
399   static char res;
400
401   return (voidp) &res;
402 }
403
404
405 nfsattrstat *
406 nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
407 {
408   static nfsattrstat res = {NFSERR_ROFS};
409
410   return &res;
411 }
412
413
414 nfsdiropres *
415 nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
416 {
417   static nfsdiropres res = {NFSERR_ROFS};
418
419   return &res;
420 }
421
422
423 nfsstat *
424 nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
425 {
426   static nfsstat res = {NFSERR_ROFS};
427
428   return &res;
429 }
430
431
432 nfsstat *
433 nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
434 {
435   static nfsstat res = {NFSERR_ROFS};
436
437   return &res;
438 }
439
440
441 nfsstat *
442 nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
443 {
444   static nfsstat res = {NFSERR_ROFS};
445
446   return &res;
447 }
448
449
450 nfsstat *
451 nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
452 {
453   static nfsstat res = {NFSERR_ROFS};
454
455   return &res;
456 }
457
458
459 nfsdiropres *
460 nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
461 {
462   static nfsdiropres res = {NFSERR_ROFS};
463
464   return &res;
465 }
466
467
468 nfsstat *
469 nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
470 {
471   static nfsstat res = {NFSERR_ROFS};
472
473   return &res;
474 }
475
476
477 nfsreaddirres *
478 nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
479 {
480   static nfsreaddirres res;
481   static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
482   static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
483   static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
484
485   slinkent.ne_name = slinkname;
486
487   if (eq_fh(&argp->rda_fhandle, &slink)) {
488     res.rdr_status = NFSERR_NOTDIR;
489   } else if (eq_fh(&argp->rda_fhandle, &root)) {
490     clocktime(&rootfattr.na_atime);
491
492     res.rdr_status = NFS_OK;
493     switch (argp->rda_cookie[0]) {
494     case 0:
495       res.rdr_u.rdr_reply_u.dl_entries = &dotent;
496       break;
497     case DOTCOOKIE:
498       res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
499       break;
500     case DOTDOTCOOKIE:
501       res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
502       break;
503     case SLINKCOOKIE:
504       res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
505       break;
506     }
507     res.rdr_u.rdr_reply_u.dl_eof = TRUE;
508   } else {
509     res.rdr_status = NFSERR_STALE;
510   }
511   return &res;
512 }
513
514
515 nfsstatfsres *
516 nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
517 {
518   static nfsstatfsres res = {NFS_OK};
519
520   res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
521   res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
522
523   /*
524    * Some "df" programs automatically assume that file systems
525    * with zero blocks are meta-filesystems served by automounters.
526    */
527   res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
528   res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
529   res.sfr_u.sfr_reply_u.sfrok_bavail = 0;
530
531   return &res;
532 }