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