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