Retire AFS_MOUNT_AFS
[openafs.git] / src / afsd / afsd_kernel.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #ifdef IGNORE_SOME_GCC_WARNINGS
16 # ifdef __clang__
17 #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
18 # else
19 #  pragma GCC diagnostic warning "-Wdeprecated-declarations"
20 # endif
21 #endif
22
23 #define VFS 1
24
25 #include <afs/cmd.h>
26
27 #include "afsd.h"
28
29 #include <assert.h>
30 #include <afs/afsutil.h>
31 #include <sys/file.h>
32 #include <sys/wait.h>
33
34 #if defined(AFS_LINUX20_ENV)
35 #include <sys/resource.h>
36 #endif
37
38 #ifdef HAVE_SYS_FS_TYPES_H
39 #include <sys/fs_types.h>
40 #endif
41
42 #ifdef HAVE_SYS_MOUNT_H
43 #include <sys/mount.h>
44 #endif
45
46 #ifdef HAVE_SYS_FCNTL_H
47 #include <sys/fcntl.h>
48 #endif
49
50 #ifdef HAVE_SYS_MNTTAB_H
51 #include <sys/mnttab.h>
52 #endif
53
54 #ifdef HAVE_SYS_MNTENT_H
55 #include <sys/mntent.h>
56 #endif
57
58 #ifdef HAVE_MNTENT_H
59 #include <mntent.h>
60 #endif
61
62 #ifdef HAVE_SYS_MOUNT_H
63 #include <sys/mount.h>
64 #endif
65
66 #ifdef HAVE_SYS_VFS_H
67 #include <sys/vfs.h>
68 #endif
69
70 #ifdef HAVE_SYS_FSTYP_H
71 #include <sys/fstyp.h>
72 #endif
73
74 #include <ctype.h>
75
76 #include <afs/opr.h>
77 #include <afs/afs_args.h>
78 #include <afs/cellconfig.h>
79 #include <afs/afssyscalls.h>
80 #include <afs/afsutil.h>
81
82 #ifdef AFS_DARWIN_ENV
83 #ifdef AFS_DARWIN80_ENV
84 #include <sys/xattr.h>
85 #endif
86 #include <mach/mach.h>
87 #ifndef AFS_DARWIN100_ENV
88 /* Symbols from the DiskArbitration framework */
89 kern_return_t DiskArbStart(mach_port_t *);
90 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
91                                                          char *);
92 #define DISK_ARB_NETWORK_DISK_FLAG 8
93 #endif
94 #include <mach/mach_port.h>
95 #include <mach/mach_interface.h>
96 #include <mach/mach_init.h>
97 #endif /* AFS_DARWIN_ENV */
98
99 #define AFS_MOUNT_STR "afs"
100 #ifndef MOUNT_AFS
101 #define MOUNT_AFS AFS_MOUNT_STR
102 #endif /* MOUNT_AFS */
103
104 #ifdef AFS_SGI65_ENV
105 # include <sched.h>
106 # define SET_RTPRI(P) {  \
107     struct sched_param sp; \
108     sp.sched_priority = P; \
109     if (sched_setscheduler(0, SCHED_RR, &sp)<0) { \
110         perror("sched_setscheduler"); \
111     } \
112 }
113 # define SET_AFSD_RTPRI() SET_RTPRI(68)
114 # define SET_RX_RTPRI()   SET_RTPRI(199)
115 #else
116 # ifdef AFS_LINUX20_ENV
117 #  define SET_AFSD_RTPRI()
118 #  define SET_RX_RTPRI() do { \
119     if (setpriority(PRIO_PROCESS, 0, -10) < 0) \
120         perror("setting rx priority"); \
121 } while (0)
122 # else
123 #  define SET_AFSD_RTPRI()
124 #  define SET_RX_RTPRI()
125 # endif
126 #endif
127
128 static char *afsd_syscalls[AFSOP_MAX_OPCODE + 1]; /* For syscall tracing. */
129
130 static void
131 afsd_init_syscall_opcodes(void)
132 {
133 #define add_opcode(x) afsd_syscalls[x] = #x
134     add_opcode(AFSOP_START_RXCALLBACK);
135     add_opcode(AFSOP_START_AFS);
136     add_opcode(AFSOP_START_BKG);
137     add_opcode(AFSOP_START_TRUNCDAEMON);
138     add_opcode(AFSOP_START_CS);
139     add_opcode(AFSOP_ADDCELL);
140     add_opcode(AFSOP_CACHEINIT);
141     add_opcode(AFSOP_CACHEINFO);
142     add_opcode(AFSOP_VOLUMEINFO);
143     add_opcode(AFSOP_CACHEFILE);
144     add_opcode(AFSOP_CACHEINODE);
145     add_opcode(AFSOP_AFSLOG);
146     add_opcode(AFSOP_ROOTVOLUME);
147     add_opcode(AFSOP_STARTLOG);
148     add_opcode(AFSOP_ENDLOG);
149     add_opcode(AFSOP_AFS_VFSMOUNT);
150     add_opcode(AFSOP_ADVISEADDR);
151     add_opcode(AFSOP_CLOSEWAIT);
152     add_opcode(AFSOP_RXEVENT_DAEMON);
153     add_opcode(AFSOP_GETMTU);
154     add_opcode(AFSOP_GETIFADDRS);
155     add_opcode(AFSOP_ADDCELL2);
156     add_opcode(AFSOP_AFSDB_HANDLER);
157     add_opcode(AFSOP_SET_DYNROOT);
158     add_opcode(AFSOP_ADDCELLALIAS);
159     add_opcode(AFSOP_SET_FAKESTAT);
160     add_opcode(AFSOP_CELLINFO);
161     add_opcode(AFSOP_SET_THISCELL);
162     add_opcode(AFSOP_BASIC_INIT);
163     add_opcode(AFSOP_SET_BACKUPTREE);
164     add_opcode(AFSOP_SET_RXPCK);
165     add_opcode(AFSOP_BUCKETPCT);
166     add_opcode(AFSOP_SET_RXMAXMTU);
167     add_opcode(AFSOP_BKG_HANDLER);
168     add_opcode(AFSOP_GETMASK);
169     add_opcode(AFSOP_SET_RXMAXFRAGS);
170     add_opcode(AFSOP_SET_RMTSYS_FLAG);
171     add_opcode(AFSOP_SEED_ENTROPY);
172     add_opcode(AFSOP_SET_INUMCALC);
173     add_opcode(AFSOP_RXLISTENER_DAEMON);
174     add_opcode(AFSOP_CACHEBASEDIR);
175     add_opcode(AFSOP_CACHEDIRS);
176     add_opcode(AFSOP_CACHEFILES);
177     add_opcode(AFSOP_SETINT);
178     add_opcode(AFSOP_GO);
179     add_opcode(AFSOP_CHECKLOCKS);
180     add_opcode(AFSOP_SHUTDOWN);
181     add_opcode(AFSOP_STOP_RXCALLBACK);
182     add_opcode(AFSOP_STOP_AFS);
183     add_opcode(AFSOP_STOP_BKG);
184     add_opcode(AFSOP_STOP_TRUNCDAEMON);
185     /* AFSOP_STOP_RXEVENT -- not a syscall opcode */
186     /* AFSOP_STOP_COMPLETE -- not a syscall opcode */
187     add_opcode(AFSOP_STOP_CS);
188     /* AFSOP_STOP_RXK_LISTENER -- not a syscall opcode */
189     add_opcode(AFSOP_STOP_AFSDB);
190     add_opcode(AFSOP_STOP_NETIF);
191 #undef add_opcode
192 }
193
194 void
195 afsd_set_rx_rtpri(void)
196 {
197     SET_RX_RTPRI();
198 }
199
200 void
201 afsd_set_afsd_rtpri(void)
202 {
203     SET_AFSD_RTPRI();
204 }
205
206 #if defined(AFS_LINUX20_ENV)
207 int
208 os_syscall(struct afsd_syscall_args *args)
209 {
210     int error;
211     struct afsprocdata syscall_data;
212
213     int fd = open(PROC_SYSCALL_FNAME, O_RDWR);
214     if (fd < 0)
215         fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
216
217     if (fd < 0)
218         return -1;
219
220     syscall_data.syscall = AFSCALL_CALL;
221     syscall_data.param1 = args->syscall;
222     syscall_data.param2 = args->params[0];
223     syscall_data.param3 = args->params[1];
224     syscall_data.param4 = (long) &args->params[2];
225
226     error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
227     close(fd);
228
229     return error;
230 }
231 #elif defined(AFS_DARWIN80_ENV)
232
233 # if defined(AFS_DARWIN100_ENV)
234 static int
235 os_syscall64(struct afsd_syscall_args *args)
236 {
237     int error;
238     struct afssysargs64 syscall64_data;
239     int fd = open(SYSCALL_DEV_FNAME, O_RDWR);
240
241     if (fd < 0)
242         return -1;
243
244     syscall64_data.syscall = (int)AFSCALL_CALL;
245     syscall64_data.param1 = args->syscall;
246     syscall64_data.param2 = args->params[0];
247     syscall64_data.param3 = args->params[1];
248     syscall64_data.param4 = args->params[2];
249     syscall64_data.param5 = args->params[3];
250     syscall64_data.param6 = args->params[4];
251
252     error = ioctl(fd, VIOC_SYSCALL64, &syscall64_data);
253     close(fd);
254
255     if (error)
256         return error;
257
258     return syscall64_data.retval;
259 }
260 # endif
261
262 static int
263 os_syscall(struct afsd_syscall_args *args)
264 {
265     int error;
266     struct afssysargs syscall_data;
267     int fd;
268
269 # ifdef AFS_DARWIN100_ENV
270     if (sizeof(long) == 8)
271         return os_syscall64(args);
272 # endif
273
274     fd = open(SYSCALL_DEV_FNAME, O_RDWR);
275     if (fd < 0)
276         return -1;
277
278     syscall_data.syscall = AFSCALL_CALL;
279     syscall_data.param1 = (unsigned int)(uintptr_t)args->syscall;
280     syscall_data.param2 = (unsigned int)(uintptr_t)args->params[0];
281     syscall_data.param3 = (unsigned int)(uintptr_t)args->params[1];
282     syscall_data.param4 = (unsigned int)(uintptr_t)args->params[2];
283     syscall_data.param5 = (unsigned int)(uintptr_t)args->params[3];
284     syscall_data.param6 = (unsigned int)(uintptr_t)args->params[4];
285
286     error = ioctl(fd, VIOC_SYSCALL, syscall_data);
287     close(fd);
288
289     if (error)
290         return error;
291
292     return syscall_data.retval;
293 }
294
295 #elif defined(AFS_SUN511_ENV)
296 static int
297 os_syscall(struct afsd_syscall_args *args)
298 {
299     int retval, error;
300
301     error = ioctl_sun_afs_syscall(AFSCALL_CALL, args->syscall,
302                                  args->params[0], args->params[1],
303                                  args->params[2], args->params[3],
304                                  args->params[4], &retval);
305     if (error)
306         return error;
307
308     return retval;
309 }
310 #elif defined(AFS_SGI_ENV)
311 static int
312 os_syscall(struct afsd_syscall_args *args)
313 {
314     return afs_syscall(args->syscall, args->params[0], args->params[1],
315                        args->params[2], args->params[3], args->params[4]);
316 }
317 #elif defined(AFS_AIX32_ENV)
318 static int
319 os_syscall(struct afsd_syscall_args *args)
320 {
321     return syscall(AFSCALL_CALL, args->syscall,
322                    args->params[0], args->params[1], args->params[2],
323                    args->params[3], args->params[4], args->params[5],
324                    args->params[6]);
325 }
326 #else
327 static int
328 os_syscall(struct afsd_syscall_args *args)
329 {
330     return syscall(AFS_SYSCALL, AFSCALL_CALL, args->syscall,
331                    args->params[0], args->params[1], args->params[2],
332                    args->params[3], args->params[4], args->params[5]);
333 }
334 #endif
335
336 int
337 afsd_call_syscall(struct afsd_syscall_args *args)
338 {
339     int error;
340
341     error = os_syscall(args);
342
343     if (afsd_debug) {
344         char *opcode;
345         char buffer[32];
346         const char *syscall_str;
347
348 #if defined(AFS_SYSCALL)
349         syscall_str = AFS_STRINGIZE(AFS_SYSCALL);
350 #else
351         syscall_str = "[AFS_SYSCALL]";
352 #endif
353
354         if ((args->syscall < 0) ||
355             (args->syscall >= (sizeof(afsd_syscalls) / sizeof(*afsd_syscalls))))
356             opcode = NULL;
357         else
358             opcode = afsd_syscalls[args->syscall];
359
360         if (opcode == NULL) {
361             snprintf(buffer, sizeof(buffer), "unknown (%d)", args->syscall);
362             opcode = buffer;
363         }
364
365         if (error == -1) {
366             char *s = strerror(errno);
367             printf("os_syscall(%s, %d, %s, 0x%lx)=%d (%d, %s)\n",
368                     syscall_str, AFSCALL_CALL, opcode,
369                    (long)args->params[0], error, errno, s);
370         } else {
371             printf("os_syscall(%s %d %s, 0x%lx)=%d\n",
372                     syscall_str, AFSCALL_CALL, opcode,
373                    (long)args->params[0], error);
374         }
375     }
376
377     return error;
378 }
379
380 #ifdef  AFS_AIX_ENV
381 /* Special handling for AIX's afs mount operation since they require much more
382  * miscl. information before making the vmount(2) syscall */
383 #include <sys/vfs.h>
384
385 #define ROUNDUP(x)  (((x) + 3) & ~3)
386
387 aix_vmount(const char *cacheMountDir)
388 {
389     struct vmount *vmountp;
390     int size, error;
391
392     size = sizeof(struct vmount) + ROUNDUP(strlen(cacheMountDir) + 1) + 5 * 4;
393     /* Malloc and zero the vmount structure */
394     if ((vmountp = calloc(1, size)) == NULL) {
395         printf("Can't allocate space for the vmount structure (AIX)\n");
396         exit(1);
397     }
398
399     /* transfer info into the vmount structure */
400     vmountp->vmt_revision = VMT_REVISION;
401     vmountp->vmt_length = size;
402     vmountp->vmt_fsid.fsid_dev = 0;
403     vmountp->vmt_fsid.fsid_type = AFS_FSNO;
404     vmountp->vmt_vfsnumber = 0;
405     vmountp->vmt_time = 0;      /* We'll put the time soon! */
406     vmountp->vmt_flags = VFS_DEVMOUNT;  /* read/write permission */
407     vmountp->vmt_gfstype = AFS_FSNO;
408     vmountdata(vmountp, "AFS", cacheMountDir, "", "", "", "rw");
409
410     /* Do the actual mount system call */
411     error = vmount(vmountp, size);
412     free(vmountp);
413     return (error);
414 }
415
416 vmountdata(struct vmount * vmtp, char *obj, char *stub, char *host,
417            char *hostsname, char *info, char *args)
418 {
419     struct data {
420         short vmt_off;
421         short vmt_size;
422     } *vdp, *vdprev;
423     int size;
424
425     vdp = (struct data *)vmtp->vmt_data;
426     vdp->vmt_off = sizeof(struct vmount);
427     size = ROUNDUP(strlen(obj) + 1);
428     vdp->vmt_size = size;
429     strcpy(vmt2dataptr(vmtp, VMT_OBJECT), obj);
430
431     vdprev = vdp;
432     vdp++;
433     vdp->vmt_off = vdprev->vmt_off + size;
434     size = ROUNDUP(strlen(stub) + 1);
435     vdp->vmt_size = size;
436     strcpy(vmt2dataptr(vmtp, VMT_STUB), stub);
437
438     vdprev = vdp;
439     vdp++;
440     vdp->vmt_off = vdprev->vmt_off + size;
441     size = ROUNDUP(strlen(host) + 1);
442     vdp->vmt_size = size;
443     strcpy(vmt2dataptr(vmtp, VMT_HOST), host);
444
445     vdprev = vdp;
446     vdp++;
447     vdp->vmt_off = vdprev->vmt_off + size;
448     size = ROUNDUP(strlen(hostsname) + 1);
449     vdp->vmt_size = size;
450     strcpy(vmt2dataptr(vmtp, VMT_HOSTNAME), hostsname);
451
452
453     vdprev = vdp;
454     vdp++;
455     vdp->vmt_off = vdprev->vmt_off + size;
456     size = ROUNDUP(strlen(info) + 1);
457     vdp->vmt_size = size;
458     strcpy(vmt2dataptr(vmtp, VMT_INFO), info);
459
460     vdprev = vdp;
461     vdp++;
462     vdp->vmt_off = vdprev->vmt_off + size;
463     size = ROUNDUP(strlen(args) + 1);
464     vdp->vmt_size = size;
465     strcpy(vmt2dataptr(vmtp, VMT_ARGS), args);
466 }
467 #endif /* AFS_AIX_ENV */
468
469 #ifdef  AFS_HPUX_ENV
470 #define MOUNTED_TABLE   MNT_MNTTAB
471 #else
472 #define MOUNTED_TABLE   MOUNTED
473 #endif
474
475 static int
476 HandleMTab(char *cacheMountDir)
477 {
478 #if (defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV))
479     FILE *tfilep;
480 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
481     struct mntent tmntent;
482     char *dir;
483     int i;
484
485     tfilep = setmntent("/etc/mtab", "a+");
486     if (!tfilep) {
487         printf("Can't open /etc/mtab for writing (errno %d); not adding "
488                "an entry for AFS\n", errno);
489         return 1;
490     }
491
492     dir = strdup(cacheMountDir);
493
494     /* trim trailing slashes; don't look at dir[0] in case we are somehow
495      * just "/" */
496     for (i = strlen(dir)-1; i > 0; i--) {
497         if (dir[i] == '/') {
498             dir[i] = '\0';
499         } else {
500             break;
501         }
502     }
503
504     tmntent.mnt_fsname = "AFS";
505     tmntent.mnt_dir = dir;
506     tmntent.mnt_type = "afs";
507     tmntent.mnt_opts = "rw";
508     tmntent.mnt_freq = 1;
509     tmntent.mnt_passno = 3;
510     addmntent(tfilep, &tmntent);
511     endmntent(tfilep);
512
513     free(dir);
514     dir = NULL;
515 #else
516     struct mntent tmntent;
517
518     memset(&tmntent, '\0', sizeof(struct mntent));
519     tfilep = setmntent(MOUNTED_TABLE, "a+");
520     if (!tfilep) {
521         printf("Can't open %s for write; Not adding afs entry to it\n",
522                MOUNTED_TABLE);
523         return 1;
524     }
525     tmntent.mnt_fsname = "AFS";
526     tmntent.mnt_dir = cacheMountDir;
527     tmntent.mnt_type = "xx";
528     tmntent.mnt_opts = "rw";
529     tmntent.mnt_freq = 1;
530     tmntent.mnt_passno = 3;
531 #ifdef  AFS_HPUX_ENV
532     tmntent.mnt_type = "afs";
533     tmntent.mnt_time = time(0);
534     tmntent.mnt_cnode = 0;
535 #endif
536     addmntent(tfilep, &tmntent);
537     endmntent(tfilep);
538 #endif /* AFS_SGI_ENV */
539 #endif /* unreasonable systems */
540 #ifdef AFS_DARWIN_ENV
541 #ifndef AFS_DARWIN100_ENV
542     mach_port_t diskarb_port;
543     kern_return_t status;
544
545     status = DiskArbStart(&diskarb_port);
546     if (status == KERN_SUCCESS) {
547         status =
548             DiskArbDiskAppearedWithMountpointPing_auto("AFS",
549                                                        DISK_ARB_NETWORK_DISK_FLAG,
550                                                        cacheMountDir);
551     }
552
553     return status;
554 #endif
555 #endif /* AFS_DARWIN_ENV */
556     return 0;
557 }
558
559 void
560 afsd_mount_afs(const char *rn, const char *cacheMountDir)
561 {
562     int mountFlags;             /*Flags passed to mount() */
563     char *mountDir; /* For HandleMTab() */
564
565     mountFlags = 0;             /* Read/write file system, can do setuid() */
566 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
567 #ifdef  AFS_SUN5_ENV
568     mountFlags |= MS_DATA;
569 #else
570     mountFlags |= M_NEWTYPE;    /* This searches by name in vfs_conf.c so don't need to recompile vfs.c because MOUNT_MAXTYPE has changed; it seems that Sun fixed this at last... */
571 #endif
572 #endif
573
574 #if defined(AFS_HPUX100_ENV)
575     mountFlags |= MS_DATA;
576 #endif
577
578     if (afsd_verbose)
579         printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn,
580             cacheMountDir, mountFlags);
581 #if defined(AFS_FBSD_ENV)
582     /* data must be non-const non-NULL but is otherwise ignored */
583     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, &mountFlags)) < 0) {
584 #elif defined(AFS_AIX_ENV)
585     if (aix_vmount(cacheMountDir)) {
586 #elif defined(AFS_HPUX100_ENV)
587     if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
588 #elif defined(AFS_SUN5_ENV)
589     if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
590 #elif defined(AFS_SGI_ENV)
591     mountFlags = MS_FSS;
592     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS))
593         < 0) {
594 #elif defined(AFS_LINUX20_ENV)
595     if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) {
596 #elif defined(AFS_NBSD50_ENV)
597     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, NULL, 0)) < 0) {
598 #else
599     /* This is the standard mount used by the suns and rts */
600     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
601 #endif
602         printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir,
603                 errno);
604         exit(1);
605     }
606
607     mountDir = strdup(cacheMountDir);
608     HandleMTab(mountDir);
609     free(mountDir);
610 }
611
612 int
613 afsd_fork(int wait, afsd_callback_func cb, void *rock)
614 {
615     int code;
616     code = fork();
617     if (code == 0) {
618         (*cb) (rock);
619         exit(1);
620     } else {
621         assert(code > 0);
622         if (wait) {
623             opr_Verify(waitpid(code, NULL, 0) != -1);
624         }
625     }
626     return 0;
627 }
628
629 int
630 afsd_daemon(int nochdir, int noclose)
631 {
632     return daemon(nochdir, noclose);
633 }
634
635 int
636 afsd_check_mount(const char *rn, const char *mountdir)
637 {
638     struct stat statbuf;
639
640     if (stat(mountdir, &statbuf)) {
641         printf("%s: Mountpoint %s missing.\n", rn, mountdir);
642         return -1;
643     } else if (!S_ISDIR(statbuf.st_mode)) {
644         printf("%s: Mountpoint %s is not a directory.\n", rn, mountdir);
645         return -1;
646     } else if (mountdir[0] != '/') {
647         printf("%s: Mountpoint %s is not an absolute path.\n", rn, mountdir);
648         return -1;
649     }
650     return 0;
651 }
652
653 int
654 main(int argc, char **argv)
655 {
656     int code;
657
658     afsd_init_syscall_opcodes();
659     afsd_init();
660
661     code = afsd_parse(argc, argv);
662     if (code == CMD_HELP) {
663         return 0; /* Displaying help is not an error. */
664     }
665     if (code != 0) {
666         return -1;
667     }
668
669     return afsd_run();
670 }