]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/amd/hlfsd/stubs.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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       memset((char *) &uid, 0, sizeof(int));
168       uid = *(u_int *) argp->fh_data;
169       if (plt_search(uid) != (uid2home_t *) NULL) {
170         res.ns_status = NFS_OK;
171         un_fattr.na_fileid = uid;
172         res.ns_u.ns_attr_u = un_fattr;
173         dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
174              (long) uid, (long) gid);
175       } else {                  /* not found */
176         res.ns_status = NFSERR_STALE;
177       }
178     }
179   }
180   return &res;
181 }
182
183
184 nfsattrstat *
185 nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
186 {
187   static nfsattrstat res = {NFSERR_ROFS};
188
189   return &res;
190 }
191
192
193 voidp
194 nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
195 {
196   static char res;
197
198   return (voidp) &res;
199 }
200
201
202 nfsdiropres *
203 nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
204 {
205   static nfsdiropres res;
206   int idx;
207   uid_t uid = (uid_t) INVALIDID;
208   gid_t gid = (gid_t) INVALIDID;
209
210   if (!started) {
211     started++;
212     rootfattr.na_ctime = startup;
213     rootfattr.na_mtime = startup;
214     slinkfattr.na_ctime = startup;
215     slinkfattr.na_mtime = startup;
216     un_fattr.na_ctime = startup;
217     un_fattr.na_mtime = startup;
218   }
219
220   if (eq_fh(&argp->da_fhandle, &slink)) {
221     res.dr_status = NFSERR_NOTDIR;
222     return &res;
223   }
224
225   if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
226     res.dr_status = NFSERR_NOENT;
227     return &res;
228   }
229   if (eq_fh(&argp->da_fhandle, &root)) {
230     if (argp->da_name[0] == '.' &&
231         (argp->da_name[1] == '\0' ||
232          (argp->da_name[1] == '.' &&
233           argp->da_name[2] == '\0'))) {
234 #if 0
235     /*
236      * XXX: increment mtime of parent directory, causes NFS clients to
237      * invalidate their cache for that directory.
238      * Some NFS clients may need this code.
239      */
240       if (uid != rootfattr.na_uid) {
241         clocktime(&rootfattr.na_mtime);
242         rootfattr.na_uid = uid;
243       }
244 #endif
245       res.dr_u.dr_drok_u.drok_fhandle = root;
246       res.dr_u.dr_drok_u.drok_attributes = rootfattr;
247       res.dr_status = NFS_OK;
248       return &res;
249     }
250
251     if (STREQ(argp->da_name, slinkname)) {
252 #ifndef MNT2_NFS_OPT_SYMTTL
253       /*
254        * This code is needed to defeat Solaris 2.4's (and newer) symlink
255        * values cache.  It forces the last-modified time of the symlink to be
256        * current.  It is not needed if the O/S has an nfs flag to turn off the
257        * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
258        *
259        * Additionally, Linux currently ignores the nt_useconds field,
260        * so we must update the nt_seconds field every time.
261        */
262       if (uid != slinkfattr.na_uid) {
263         clocktime(&slinkfattr.na_mtime);
264         slinkfattr.na_uid = uid;
265       }
266 #endif /* not MNT2_NFS_OPT_SYMTTL */
267       res.dr_u.dr_drok_u.drok_fhandle = slink;
268       res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
269       res.dr_status = NFS_OK;
270       return &res;
271     }
272
273     if (gid != hlfs_gid) {
274       res.dr_status = NFSERR_NOENT;
275       return &res;
276     }
277
278     /* if gets here, gid == hlfs_gid */
279     if ((idx = untab_index(argp->da_name)) < 0) {
280       res.dr_status = NFSERR_NOENT;
281       return &res;
282     } else {                    /* entry found and gid is permitted */
283       un_fattr.na_fileid = untab[idx].uid;
284       res.dr_u.dr_drok_u.drok_attributes = un_fattr;
285       memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh));
286       *(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid;
287       xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
288                untab[idx].username,
289                sizeof(am_nfs_fh) - sizeof(int));
290       res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
291       res.dr_status = NFS_OK;
292       dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
293            (long) uid, (long) gid, untab[idx].username);
294       return &res;
295     }
296   } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
297
298   res.dr_status = NFSERR_STALE;
299   return &res;
300 }
301
302
303 nfsreadlinkres *
304 nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
305 {
306   static nfsreadlinkres res;
307   uid_t userid = (uid_t) INVALIDID;
308   gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */
309   int retval = 0;
310   char *path_val = (char *) NULL;
311   char *username;
312   static uid_t last_uid = (uid_t) INVALIDID;
313
314   if (eq_fh(argp, &root)) {
315     res.rlr_status = NFSERR_ISDIR;
316   } else if (eq_fh(argp, &slink)) {
317     if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
318       return (nfsreadlinkres *) NULL;
319
320     clocktime(&slinkfattr.na_atime);
321
322     res.rlr_status = NFS_OK;
323     if (groupid == hlfs_gid) {
324       res.rlr_u.rlr_data_u = DOTSTRING;
325     } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
326       /*
327        * parent process (fork in homedir()) continues
328        * processing, by getting a NULL returned as a
329        * "special".  Child returns result.
330        */
331       return (nfsreadlinkres *) NULL;
332     }
333
334   } else {                      /* check if asked for user mailbox */
335
336     if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
337       return (nfsreadlinkres *) NULL;
338     }
339
340     if (groupid == hlfs_gid) {
341       memset((char *) &userid, 0, sizeof(int));
342       userid = *(u_int *) argp->fh_data;
343       username = (char *) &argp->fh_data[sizeof(int)];
344       if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
345         return (nfsreadlinkres *) NULL;
346     } else {
347       res.rlr_status = NFSERR_STALE;
348     }
349   }
350
351   /* print info, but try to avoid repetitions */
352   if (userid != last_uid) {
353     plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
354          (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
355     last_uid = userid;
356   }
357
358   /* I don't think it will pass this if -D fork */
359   if (serverpid == getpid())
360     return &res;
361
362   if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
363     svcerr_systemerr(nfsxprt);
364
365   /*
366    * Child exists here.   We need to determine which
367    * exist status to return.  The exit status
368    * is gathered using wait() and determines
369    * if we returned $HOME/.hlfsspool or $ALTDIR.  The parent
370    * needs this info so it can update the lookup table.
371    */
372   if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
373     retval = 1;         /* could not get real home dir (or uid 0 user) */
374   else
375     retval = 0;
376
377   /*
378    * If asked for -D fork, then must return the value,
379    * NOT exit, or else the main hlfsd server exits.
380    * Bug: where is that status information being collected?
381    */
382   if (amuDebug(D_FORK))
383     return &res;
384
385   exit(retval);
386 }
387
388
389 nfsreadres *
390 nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
391 {
392   static nfsreadres res = {NFSERR_ACCES};
393
394   return &res;
395 }
396
397
398 voidp
399 nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
400 {
401   static char res;
402
403   return (voidp) &res;
404 }
405
406
407 nfsattrstat *
408 nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
409 {
410   static nfsattrstat res = {NFSERR_ROFS};
411
412   return &res;
413 }
414
415
416 nfsdiropres *
417 nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
418 {
419   static nfsdiropres res = {NFSERR_ROFS};
420
421   return &res;
422 }
423
424
425 nfsstat *
426 nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
427 {
428   static nfsstat res = {NFSERR_ROFS};
429
430   return &res;
431 }
432
433
434 nfsstat *
435 nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
436 {
437   static nfsstat res = {NFSERR_ROFS};
438
439   return &res;
440 }
441
442
443 nfsstat *
444 nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
445 {
446   static nfsstat res = {NFSERR_ROFS};
447
448   return &res;
449 }
450
451
452 nfsstat *
453 nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
454 {
455   static nfsstat res = {NFSERR_ROFS};
456
457   return &res;
458 }
459
460
461 nfsdiropres *
462 nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
463 {
464   static nfsdiropres res = {NFSERR_ROFS};
465
466   return &res;
467 }
468
469
470 nfsstat *
471 nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
472 {
473   static nfsstat res = {NFSERR_ROFS};
474
475   return &res;
476 }
477
478
479 nfsreaddirres *
480 nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
481 {
482   static nfsreaddirres res;
483   static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
484   static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
485   static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
486
487   slinkent.ne_name = slinkname;
488
489   if (eq_fh(&argp->rda_fhandle, &slink)) {
490     res.rdr_status = NFSERR_NOTDIR;
491   } else if (eq_fh(&argp->rda_fhandle, &root)) {
492     clocktime(&rootfattr.na_atime);
493
494     res.rdr_status = NFS_OK;
495     switch (argp->rda_cookie[0]) {
496     case 0:
497       res.rdr_u.rdr_reply_u.dl_entries = &dotent;
498       break;
499     case DOTCOOKIE:
500       res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
501       break;
502     case DOTDOTCOOKIE:
503       res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
504       break;
505     case SLINKCOOKIE:
506       res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
507       break;
508     }
509     res.rdr_u.rdr_reply_u.dl_eof = TRUE;
510   } else {
511     res.rdr_status = NFSERR_STALE;
512   }
513   return &res;
514 }
515
516
517 nfsstatfsres *
518 nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
519 {
520   static nfsstatfsres res = {NFS_OK};
521
522   res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
523   res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
524
525   /*
526    * Some "df" programs automatically assume that file systems
527    * with zero blocks are meta-filesystems served by automounters.
528    */
529   res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
530   res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
531   res.sfr_u.sfr_reply_u.sfrok_bavail = 0;
532
533   return &res;
534 }