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