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