c5c457ed869d2520e66b0bb817e68c15554490c8
[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 #define VFS 1
14
15 #include <afs/cmd.h>
16
17 #include "afsd.h"
18
19 #include <assert.h>
20 #include <potpourri.h>
21 #include <afs/afsutil.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/file.h>
31 #include <errno.h>
32 #include <sys/time.h>
33 #include <dirent.h>
34 #include <sys/wait.h>
35
36
37 #ifdef HAVE_SYS_PARAM_H
38 #include <sys/param.h>
39 #endif
40
41 #ifdef HAVE_SYS_FS_TYPES_H
42 #include <sys/fs_types.h>
43 #endif
44
45 #ifdef HAVE_SYS_MOUNT_H
46 #include <sys/mount.h>
47 #endif
48
49 #ifdef HAVE_SYS_FCNTL_H
50 #include <sys/fcntl.h>
51 #endif
52
53 #ifdef HAVE_SYS_MNTTAB_H
54 #include <sys/mnttab.h>
55 #endif
56
57 #ifdef HAVE_SYS_MNTENT_H
58 #include <sys/mntent.h>
59 #endif
60
61 #ifdef HAVE_MNTENT_H
62 #include <mntent.h>
63 #endif
64
65 #ifdef HAVE_SYS_MOUNT_H
66 #include <sys/mount.h>
67 #endif
68
69 #ifdef HAVE_SYS_VFS_H
70 #include <sys/vfs.h>
71 #endif
72
73 #ifdef HAVE_SYS_FSTYP_H
74 #include <sys/fstyp.h>
75 #endif
76
77 #ifdef HAVE_UNISTD_H
78 #include <unistd.h>
79 #endif
80
81 #ifdef HAVE_FCNTL_H
82 #include <fcntl.h>
83 #endif
84
85 #include <netinet/in.h>
86 #include <afs/afs_args.h>
87 #include <afs/cellconfig.h>
88 #include <ctype.h>
89 #include <afs/afssyscalls.h>
90 #include <afs/afsutil.h>
91
92 #ifdef AFS_DARWIN_ENV
93 #ifdef AFS_DARWIN80_ENV
94 #include <sys/ioctl.h>
95 #include <sys/xattr.h>
96 #endif
97 #include <mach/mach.h>
98 #ifndef AFS_DARWIN100_ENV
99 /* Symbols from the DiskArbitration framework */
100 kern_return_t DiskArbStart(mach_port_t *);
101 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
102                                                          char *);
103 #define DISK_ARB_NETWORK_DISK_FLAG 8
104 #endif
105 #include <mach/mach_port.h>
106 #include <mach/mach_interface.h>
107 #include <mach/mach_init.h>
108 #endif /* AFS_DARWIN_ENV */
109
110 #ifndef MOUNT_AFS
111 #define MOUNT_AFS AFS_MOUNT_AFS
112 #endif /* MOUNT_AFS */
113
114 #ifdef AFS_SGI65_ENV
115 # include <sched.h>
116 # define SET_RTPRI(P) {  \
117     struct sched_param sp; \
118     sp.sched_priority = P; \
119     if (sched_setscheduler(0, SCHED_RR, &sp)<0) { \
120         perror("sched_setscheduler"); \
121     } \
122 }
123 # define SET_AFSD_RTPRI() SET_RTPRI(68)
124 # define SET_RX_RTPRI()   SET_RTPRI(199)
125 #else
126 # ifdef AFS_LINUX20_ENV
127 #  define SET_AFSD_RTPRI()
128 #  define SET_RX_RTPRI() do { \
129     if (setpriority(PRIO_PROCESS, 0, -10) < 0) \
130         perror("setting rx priority"); \
131 } while (0)
132 # else
133 #  define SET_AFSD_RTPRI()
134 #  define SET_RX_RTPRI()
135 # endif
136 #endif
137
138 void
139 afsd_set_rx_rtpri(void)
140 {
141     SET_RX_RTPRI();
142 }
143
144 void
145 afsd_set_afsd_rtpri(void)
146 {
147     SET_AFSD_RTPRI();
148 }
149
150 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
151
152 int
153 afsd_call_syscall(long param1, long param2, long param3, long param4, long param5,
154              long param6, long  param7)
155 {
156     int error;
157 # ifdef AFS_LINUX20_ENV
158     long eparm[4];
159     struct afsprocdata syscall_data;
160     int fd = open(PROC_SYSCALL_FNAME, O_RDWR);
161     if (fd < 0)
162         fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
163     eparm[0] = param4;
164     eparm[1] = param5;
165     eparm[2] = param6;
166     eparm[3] = param7;
167
168     param4 = (long)eparm;
169
170     syscall_data.syscall = AFSCALL_CALL;
171     syscall_data.param1 = param1;
172     syscall_data.param2 = param2;
173     syscall_data.param3 = param3;
174     syscall_data.param4 = param4;
175     if (fd > 0) {
176         error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
177         close(fd);
178     } else
179 # endif /* AFS_LINUX20_ENV */
180 # ifdef AFS_DARWIN80_ENV
181     struct afssysargs syscall_data;
182     void *ioctldata;
183     int fd = open(SYSCALL_DEV_FNAME,O_RDWR);
184     int syscallnum;
185 #ifdef AFS_DARWIN100_ENV
186     int is64 = 0;
187     struct afssysargs64 syscall64_data;
188     if (sizeof(param1) == 8) {
189         syscallnum = VIOC_SYSCALL64;
190         is64 = 1;
191         ioctldata = &syscall64_data;
192         syscall64_data.syscall = (int)AFSCALL_CALL;
193         syscall64_data.param1 = param1;
194         syscall64_data.param2 = param2;
195         syscall64_data.param3 = param3;
196         syscall64_data.param4 = param4;
197         syscall64_data.param5 = param5;
198         syscall64_data.param6 = param6;
199     } else {
200 #endif
201         syscallnum = VIOC_SYSCALL;
202         ioctldata = &syscall_data;
203         syscall_data.syscall = AFSCALL_CALL;
204         syscall_data.param1 = param1;
205         syscall_data.param2 = param2;
206         syscall_data.param3 = param3;
207         syscall_data.param4 = param4;
208         syscall_data.param5 = param5;
209         syscall_data.param6 = param6;
210 #ifdef AFS_DARWIN100_ENV
211     }
212 #endif
213     if(fd >= 0) {
214         error = ioctl(fd, syscallnum, ioctldata);
215         close(fd);
216     } else {
217         error = -1;
218     }
219     if (!error) {
220 #ifdef AFS_DARWIN100_ENV
221         if (is64)
222             error=syscall64_data.retval;
223         else
224 #endif
225             error=syscall_data.retval;
226     }
227 # else /* AFS_DARWIN80_ENV */
228     error =
229         syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4,
230                 param5, param6, param7);
231 # endif /* !AFS_DARWIN80_ENV */
232
233     if (afsd_debug) {
234 #ifdef AFS_NBSD40_ENV
235         char *s = strerror(errno);
236         printf("SScall(%d, %d, %d)=%d (%d, %s)\n", AFS_SYSCALL, AFSCALL_CALL,
237                 param1, error, errno, s);
238 #else
239         printf("SScall(%d, %d, %ld)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1,
240                error);
241 #endif
242     }
243
244     return (error);
245 }
246 #else /* !AFS_SGI_ENV && !AFS_AIX32_ENV */
247 # if defined(AFS_SGI_ENV)
248 int
249 afsd_call_syscall(call, parm0, parm1, parm2, parm3, parm4)
250 {
251
252     int error;
253
254     error = afs_syscall(call, parm0, parm1, parm2, parm3, parm4);
255     if (afsd_verbose)
256         printf("SScall(%d, %d)=%d ", call, parm0, error);
257
258     return error;
259 }
260 # else /* AFS_SGI_ENV */
261 int
262 afsd_call_syscall(call, parm0, parm1, parm2, parm3, parm4, parm5, parm6)
263 {
264
265     return syscall(AFSCALL_CALL, call, parm0, parm1, parm2, parm3, parm4,
266                    parm5, parm6);
267 }
268 # endif /* !AFS_SGI_ENV */
269 #endif /* AFS_SGI_ENV || AFS_AIX32_ENV */
270
271
272 #ifdef  AFS_AIX_ENV
273 /* Special handling for AIX's afs mount operation since they require much more
274  * miscl. information before making the vmount(2) syscall */
275 #include <sys/vfs.h>
276
277 #define ROUNDUP(x)  (((x) + 3) & ~3)
278
279 aix_vmount()
280 {
281     struct vmount *vmountp;
282     int size, error;
283
284     size = sizeof(struct vmount) + ROUNDUP(strlen(cacheMountDir) + 1) + 5 * 4;
285     /* Malloc the vmount structure */
286     if ((vmountp = (struct vmount *)malloc(size)) == (struct vmount *)NULL) {
287         printf("Can't allocate space for the vmount structure (AIX)\n");
288         exit(1);
289     }
290
291     /* zero out the vmount structure */
292     memset(vmountp, '\0', size);
293
294     /* transfer info into the vmount structure */
295     vmountp->vmt_revision = VMT_REVISION;
296     vmountp->vmt_length = size;
297     vmountp->vmt_fsid.fsid_dev = 0;
298     vmountp->vmt_fsid.fsid_type = AFS_MOUNT_AFS;
299     vmountp->vmt_vfsnumber = 0;
300     vmountp->vmt_time = 0;      /* We'll put the time soon! */
301     vmountp->vmt_flags = VFS_DEVMOUNT;  /* read/write permission */
302     vmountp->vmt_gfstype = AFS_MOUNT_AFS;
303     vmountdata(vmountp, "AFS", cacheMountDir, "", "", "", "rw");
304
305     /* Do the actual mount system call */
306     error = vmount(vmountp, size);
307     free(vmountp);
308     return (error);
309 }
310
311 vmountdata(struct vmount * vmtp, char *obj, char *stub, char *host,
312            char *hostsname, char *info, char *args)
313 {
314     struct data {
315         short vmt_off;
316         short vmt_size;
317     } *vdp, *vdprev;
318     int size;
319
320     vdp = (struct data *)vmtp->vmt_data;
321     vdp->vmt_off = sizeof(struct vmount);
322     size = ROUNDUP(strlen(obj) + 1);
323     vdp->vmt_size = size;
324     strcpy(vmt2dataptr(vmtp, VMT_OBJECT), obj);
325
326     vdprev = vdp;
327     vdp++;
328     vdp->vmt_off = vdprev->vmt_off + size;
329     size = ROUNDUP(strlen(stub) + 1);
330     vdp->vmt_size = size;
331     strcpy(vmt2dataptr(vmtp, VMT_STUB), stub);
332
333     vdprev = vdp;
334     vdp++;
335     vdp->vmt_off = vdprev->vmt_off + size;
336     size = ROUNDUP(strlen(host) + 1);
337     vdp->vmt_size = size;
338     strcpy(vmt2dataptr(vmtp, VMT_HOST), host);
339
340     vdprev = vdp;
341     vdp++;
342     vdp->vmt_off = vdprev->vmt_off + size;
343     size = ROUNDUP(strlen(hostsname) + 1);
344     vdp->vmt_size = size;
345     strcpy(vmt2dataptr(vmtp, VMT_HOSTNAME), hostsname);
346
347
348     vdprev = vdp;
349     vdp++;
350     vdp->vmt_off = vdprev->vmt_off + size;
351     size = ROUNDUP(strlen(info) + 1);
352     vdp->vmt_size = size;
353     strcpy(vmt2dataptr(vmtp, VMT_INFO), info);
354
355     vdprev = vdp;
356     vdp++;
357     vdp->vmt_off = vdprev->vmt_off + size;
358     size = ROUNDUP(strlen(args) + 1);
359     vdp->vmt_size = size;
360     strcpy(vmt2dataptr(vmtp, VMT_ARGS), args);
361 }
362 #endif /* AFS_AIX_ENV */
363
364 #ifdef  AFS_HPUX_ENV
365 #define MOUNTED_TABLE   MNT_MNTTAB
366 #else
367 #ifdef  AFS_SUN5_ENV
368 #define MOUNTED_TABLE   MNTTAB
369 #else
370 #define MOUNTED_TABLE   MOUNTED
371 #endif
372 #endif
373
374 static int
375 HandleMTab(char *cacheMountDir)
376 {
377 #if (defined (AFS_SUN_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)) && !defined(AFS_SUN58_ENV)
378     FILE *tfilep;
379 #ifdef  AFS_SUN5_ENV
380     char tbuf[16];
381     struct mnttab tmntent;
382
383     memset(&tmntent, '\0', sizeof(struct mnttab));
384     if (!(tfilep = fopen(MOUNTED_TABLE, "a+"))) {
385         printf("Can't open %s\n", MOUNTED_TABLE);
386         perror(MNTTAB);
387         exit(-1);
388     }
389     tmntent.mnt_special = "AFS";
390     tmntent.mnt_mountp = cacheMountDir;
391     tmntent.mnt_fstype = "xx";
392     tmntent.mnt_mntopts = "rw";
393     sprintf(tbuf, "%ld", (long)time((time_t *) 0));
394     tmntent.mnt_time = tbuf;
395     putmntent(tfilep, &tmntent);
396     fclose(tfilep);
397 #else
398 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
399     struct mntent tmntent;
400
401     tfilep = setmntent("/etc/mtab", "a+");
402     tmntent.mnt_fsname = "AFS";
403     tmntent.mnt_dir = cacheMountDir;
404     tmntent.mnt_type = "afs";
405     tmntent.mnt_opts = "rw";
406     tmntent.mnt_freq = 1;
407     tmntent.mnt_passno = 3;
408     addmntent(tfilep, &tmntent);
409     endmntent(tfilep);
410 #else
411     struct mntent tmntent;
412
413     memset(&tmntent, '\0', sizeof(struct mntent));
414     tfilep = setmntent(MOUNTED_TABLE, "a+");
415     if (!tfilep) {
416         printf("Can't open %s for write; Not adding afs entry to it\n",
417                MOUNTED_TABLE);
418         return 1;
419     }
420     tmntent.mnt_fsname = "AFS";
421     tmntent.mnt_dir = cacheMountDir;
422     tmntent.mnt_type = "xx";
423     tmntent.mnt_opts = "rw";
424     tmntent.mnt_freq = 1;
425     tmntent.mnt_passno = 3;
426 #ifdef  AFS_HPUX_ENV
427     tmntent.mnt_type = "afs";
428     tmntent.mnt_time = time(0);
429     tmntent.mnt_cnode = 0;
430 #endif
431     addmntent(tfilep, &tmntent);
432     endmntent(tfilep);
433 #endif /* AFS_SGI_ENV */
434 #endif /* AFS_SUN5_ENV */
435 #endif /* unreasonable systems */
436 #ifdef AFS_DARWIN_ENV
437 #ifndef AFS_DARWIN100_ENV
438     mach_port_t diskarb_port;
439     kern_return_t status;
440
441     status = DiskArbStart(&diskarb_port);
442     if (status == KERN_SUCCESS) {
443         status =
444             DiskArbDiskAppearedWithMountpointPing_auto("AFS",
445                                                        DISK_ARB_NETWORK_DISK_FLAG,
446                                                        cacheMountDir);
447     }
448
449     return status;
450 #endif
451 #endif /* AFS_DARWIN_ENV */
452     return 0;
453 }
454
455 void
456 afsd_mount_afs(const char *rn, const char *cacheMountDir)
457 {
458     int mountFlags;             /*Flags passed to mount() */
459     char *mountDir; /* For HandleMTab() */
460
461     mountFlags = 0;             /* Read/write file system, can do setuid() */
462 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
463 #ifdef  AFS_SUN5_ENV
464     mountFlags |= MS_DATA;
465 #else
466     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... */
467 #endif
468 #endif
469
470 #if defined(AFS_HPUX100_ENV)
471     mountFlags |= MS_DATA;
472 #endif
473
474     if (afsd_verbose)
475         printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn,
476             cacheMountDir, mountFlags);
477 #if defined(AFS_FBSD60_ENV)
478     /* data must be non-NULL but is otherwise ignored */
479     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, rn)) < 0) {
480 #elif defined(AFS_FBSD_ENV)
481     if ((mount("AFS", cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
482 #elif defined(AFS_AIX_ENV)
483     if (aix_vmount()) {
484 #elif defined(AFS_HPUX100_ENV)
485     if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
486 #elif defined(AFS_SUN5_ENV)
487     if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
488 #elif defined(AFS_SGI_ENV)
489     mountFlags = MS_FSS;
490     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS))
491         < 0) {
492 #elif defined(AFS_LINUX20_ENV)
493     if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) {
494 #elif defined(AFS_NBSD50_ENV)
495     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, NULL, 0)) < 0) {
496 #else
497     /* This is the standard mount used by the suns and rts */
498     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
499 #endif
500         printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir,
501                 errno);
502         exit(1);
503     }
504
505     mountDir = strdup(cacheMountDir);
506     HandleMTab(mountDir);
507     free(mountDir);
508 }
509
510 int
511 afsd_fork(int wait, afsd_callback_func cb, void *rock)
512 {
513     int code;
514     code = fork();
515     if (code == 0) {
516         (*cb) (rock);
517         exit(1);
518     } else {
519         assert(code > 0);
520         if (wait) {
521             assert(waitpid(code, NULL, 0) != -1);
522         }
523     }
524     return 0;
525 }
526
527 int
528 afsd_daemon(int nochdir, int noclose)
529 {
530     return daemon(nochdir, noclose);
531 }
532
533 int
534 main(int argc, char **argv)
535 {
536     int code;
537
538     afsd_init();
539
540     code = afsd_parse(argc, argv);
541     if (code) {
542         return -1;
543     }
544
545     return afsd_run();
546 }