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