1*1c9681d1Schristos /*	$NetBSD: afssys.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2f59d82ffSelric 
3f59d82ffSelric /*
4f59d82ffSelric  * Copyright (c) 1995 - 2000, 2002, 2004, 2005 Kungliga Tekniska Högskolan
5f59d82ffSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6f59d82ffSelric  * All rights reserved.
7f59d82ffSelric  *
8f59d82ffSelric  * Redistribution and use in source and binary forms, with or without
9f59d82ffSelric  * modification, are permitted provided that the following conditions
10f59d82ffSelric  * are met:
11f59d82ffSelric  *
12f59d82ffSelric  * 1. Redistributions of source code must retain the above copyright
13f59d82ffSelric  *    notice, this list of conditions and the following disclaimer.
14f59d82ffSelric  *
15f59d82ffSelric  * 2. Redistributions in binary form must reproduce the above copyright
16f59d82ffSelric  *    notice, this list of conditions and the following disclaimer in the
17f59d82ffSelric  *    documentation and/or other materials provided with the distribution.
18f59d82ffSelric  *
19f59d82ffSelric  * 3. Neither the name of the Institute nor the names of its contributors
20f59d82ffSelric  *    may be used to endorse or promote products derived from this software
21f59d82ffSelric  *    without specific prior written permission.
22f59d82ffSelric  *
23f59d82ffSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24f59d82ffSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25f59d82ffSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26f59d82ffSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27f59d82ffSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28f59d82ffSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29f59d82ffSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30f59d82ffSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31f59d82ffSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32f59d82ffSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33f59d82ffSelric  * SUCH DAMAGE.
34f59d82ffSelric  */
35f59d82ffSelric 
36f59d82ffSelric #include "kafs_locl.h"
37f59d82ffSelric 
38f59d82ffSelric struct procdata {
39f59d82ffSelric     unsigned long param4;
40f59d82ffSelric     unsigned long param3;
41f59d82ffSelric     unsigned long param2;
42f59d82ffSelric     unsigned long param1;
43f59d82ffSelric     unsigned long syscall;
44f59d82ffSelric };
45e0895134Schristos #ifdef __GNU__
46e0895134Schristos #define _IOT_procdata _IOT(_IOTS(long), 5, 0, 0, 0, 0)
47e0895134Schristos #define VIOC_SYSCALL_PROC _IOW('C', 1, struct procdata)
48e0895134Schristos #else
49f59d82ffSelric #define VIOC_SYSCALL_PROC _IOW('C', 1, void *)
50e0895134Schristos #endif
51f59d82ffSelric 
52f59d82ffSelric struct devdata {
53f59d82ffSelric     unsigned long syscall;
54f59d82ffSelric     unsigned long param1;
55f59d82ffSelric     unsigned long param2;
56f59d82ffSelric     unsigned long param3;
57f59d82ffSelric     unsigned long param4;
58f59d82ffSelric     unsigned long param5;
59f59d82ffSelric     unsigned long param6;
60f59d82ffSelric     unsigned long retval;
61f59d82ffSelric };
62e0895134Schristos #ifdef __GNU__
63e0895134Schristos #define _IOT_devdata _IOT(_IOTS(long), 8, 0, 0, 0, 0)
64e0895134Schristos #endif
65f59d82ffSelric #ifdef _IOWR
66f59d82ffSelric #define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata)
67f59d82ffSelric #define VIOC_SYSCALL_DEV_OPENAFS _IOWR('C', 1, struct devdata)
68f59d82ffSelric #endif
69f59d82ffSelric 
70e0895134Schristos #ifdef _IOW
71e0895134Schristos #ifdef _ILP32
72e0895134Schristos struct sundevdata {
73e0895134Schristos     uint32_t param6;
74e0895134Schristos     uint32_t param5;
75e0895134Schristos     uint32_t param4;
76e0895134Schristos     uint32_t param3;
77e0895134Schristos     uint32_t param2;
78e0895134Schristos     uint32_t param1;
79e0895134Schristos     uint32_t syscall;
80e0895134Schristos };
81e0895134Schristos #define VIOC_SUN_SYSCALL_DEV _IOW('C', 2, struct sundevdata)
82e0895134Schristos #else
83e0895134Schristos struct sundevdata {
84e0895134Schristos     uint64_t param6;
85e0895134Schristos     uint64_t param5;
86e0895134Schristos     uint64_t param4;
87e0895134Schristos     uint64_t param3;
88e0895134Schristos     uint64_t param2;
89e0895134Schristos     uint64_t param1;
90e0895134Schristos     uint64_t syscall;
91e0895134Schristos };
92e0895134Schristos #define VIOC_SUN_SYSCALL_DEV _IOW('C', 1, struct sundevdata)
93e0895134Schristos #endif
94e0895134Schristos #endif /* _IOW */
95e0895134Schristos 
96f59d82ffSelric 
97f59d82ffSelric int _kafs_debug; /* this should be done in a better way */
98f59d82ffSelric 
99f59d82ffSelric #define UNKNOWN_ENTRY_POINT	(-1)
100f59d82ffSelric #define NO_ENTRY_POINT		0
101f59d82ffSelric #define SINGLE_ENTRY_POINT	1
102f59d82ffSelric #define MULTIPLE_ENTRY_POINT	2
103f59d82ffSelric #define SINGLE_ENTRY_POINT2	3
104f59d82ffSelric #define SINGLE_ENTRY_POINT3	4
105f59d82ffSelric #define LINUX_PROC_POINT	5
106f59d82ffSelric #define AIX_ENTRY_POINTS	6
107f59d82ffSelric #define MACOS_DEV_POINT		7
108e0895134Schristos #define SUN_PROC_POINT		8
109f59d82ffSelric 
110f59d82ffSelric static int afs_entry_point = UNKNOWN_ENTRY_POINT;
111f59d82ffSelric static int afs_syscalls[2];
112f59d82ffSelric static char *afs_ioctlpath;
113f59d82ffSelric static unsigned long afs_ioctlnum;
114f59d82ffSelric 
115f59d82ffSelric /* Magic to get AIX syscalls to work */
116f59d82ffSelric #ifdef _AIX
117f59d82ffSelric 
118f59d82ffSelric static int (*Pioctl)(char*, int, struct ViceIoctl*, int);
119f59d82ffSelric static int (*Setpag)(void);
120f59d82ffSelric 
121f59d82ffSelric #include "dlfcn.h"
122f59d82ffSelric 
123f59d82ffSelric /*
124f59d82ffSelric  *
125f59d82ffSelric  */
126f59d82ffSelric 
127f59d82ffSelric static int
try_aix(void)128f59d82ffSelric try_aix(void)
129f59d82ffSelric {
130f59d82ffSelric #ifdef STATIC_AFS_SYSCALLS
131f59d82ffSelric     Pioctl = aix_pioctl;
132f59d82ffSelric     Setpag = aix_setpag;
133f59d82ffSelric #else
134f59d82ffSelric     void *ptr;
135f59d82ffSelric     char path[MaxPathLen], *p;
136f59d82ffSelric     /*
137f59d82ffSelric      * If we are root or running setuid don't trust AFSLIBPATH!
138f59d82ffSelric      */
139f59d82ffSelric     if (getuid() != 0 && !issuid() && (p = getenv("AFSLIBPATH")) != NULL)
140f59d82ffSelric 	strlcpy(path, p, sizeof(path));
141f59d82ffSelric     else
142f59d82ffSelric 	snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR);
143f59d82ffSelric 
144f59d82ffSelric     ptr = dlopen(path, RTLD_NOW);
145f59d82ffSelric     if(ptr == NULL) {
146f59d82ffSelric 	if(_kafs_debug) {
147f59d82ffSelric 	    if(errno == ENOEXEC && (p = dlerror()) != NULL)
148f59d82ffSelric 		fprintf(stderr, "dlopen(%s): %s\n", path, p);
149f59d82ffSelric 	    else if (errno != ENOENT)
150f59d82ffSelric 		fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno));
151f59d82ffSelric 	}
152f59d82ffSelric 	return 1;
153f59d82ffSelric     }
154f59d82ffSelric     Setpag = (int (*)(void))dlsym(ptr, "aix_setpag");
155f59d82ffSelric     Pioctl = (int (*)(char*, int,
156f59d82ffSelric 		      struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl");
157f59d82ffSelric #endif
158f59d82ffSelric     afs_entry_point = AIX_ENTRY_POINTS;
159f59d82ffSelric     return 0;
160f59d82ffSelric }
161f59d82ffSelric #endif /* _AIX */
162f59d82ffSelric 
163f59d82ffSelric /*
164f59d82ffSelric  * This probably only works under Solaris and could get confused if
165f59d82ffSelric  * there's a /etc/name_to_sysnum file.
166f59d82ffSelric  */
167f59d82ffSelric 
168f59d82ffSelric #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
169f59d82ffSelric 
170f59d82ffSelric #define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum"
171f59d82ffSelric 
172f59d82ffSelric static int
map_syscall_name_to_number(const char * str,int * res)173f59d82ffSelric map_syscall_name_to_number (const char *str, int *res)
174f59d82ffSelric {
175f59d82ffSelric     FILE *f;
176f59d82ffSelric     char buf[256];
177f59d82ffSelric     size_t str_len = strlen (str);
178f59d82ffSelric 
179f59d82ffSelric     f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r");
180f59d82ffSelric     if (f == NULL)
181f59d82ffSelric 	return -1;
182f59d82ffSelric     while (fgets (buf, sizeof(buf), f) != NULL) {
183f59d82ffSelric 	if (buf[0] == '#')
184f59d82ffSelric 	    continue;
185f59d82ffSelric 
186f59d82ffSelric 	if (strncmp (str, buf, str_len) == 0) {
187f59d82ffSelric 	    char *begptr = buf + str_len;
188f59d82ffSelric 	    char *endptr;
189f59d82ffSelric 	    long val = strtol (begptr, &endptr, 0);
190f59d82ffSelric 
191f59d82ffSelric 	    if (val != 0 && endptr != begptr) {
192f59d82ffSelric 		fclose (f);
193f59d82ffSelric 		*res = val;
194f59d82ffSelric 		return 0;
195f59d82ffSelric 	    }
196f59d82ffSelric 	}
197f59d82ffSelric     }
198f59d82ffSelric     fclose (f);
199f59d82ffSelric     return -1;
200f59d82ffSelric }
201f59d82ffSelric #endif
202f59d82ffSelric 
203f59d82ffSelric static int
try_ioctlpath(const char * path,unsigned long ioctlnum,int entrypoint)204f59d82ffSelric try_ioctlpath(const char *path, unsigned long ioctlnum, int entrypoint)
205f59d82ffSelric {
206f59d82ffSelric     int fd, ret, saved_errno;
207f59d82ffSelric 
208f59d82ffSelric     fd = open(path, O_RDWR);
209f59d82ffSelric     if (fd < 0)
210f59d82ffSelric 	return 1;
211f59d82ffSelric     switch (entrypoint) {
212f59d82ffSelric     case LINUX_PROC_POINT: {
213f59d82ffSelric 	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
214f59d82ffSelric 	data.param2 = (unsigned long)VIOCGETTOK;
215f59d82ffSelric 	ret = ioctl(fd, ioctlnum, &data);
216f59d82ffSelric 	break;
217f59d82ffSelric     }
218f59d82ffSelric     case MACOS_DEV_POINT: {
219f59d82ffSelric 	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
220f59d82ffSelric 	data.param2 = (unsigned long)VIOCGETTOK;
221f59d82ffSelric 	ret = ioctl(fd, ioctlnum, &data);
222f59d82ffSelric 	break;
223f59d82ffSelric     }
224e0895134Schristos     case SUN_PROC_POINT: {
225e0895134Schristos 	struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_PIOCTL };
226e0895134Schristos 	data.param2 = (unsigned long)VIOCGETTOK;
227e0895134Schristos 	ret = ioctl(fd, ioctlnum, &data);
228e0895134Schristos 	break;
229e0895134Schristos     }
230f59d82ffSelric     default:
231f59d82ffSelric 	abort();
232f59d82ffSelric     }
233f59d82ffSelric     saved_errno = errno;
234f59d82ffSelric     close(fd);
235f59d82ffSelric     /*
236f59d82ffSelric      * Be quite liberal in what error are ok, the first is the one
237f59d82ffSelric      * that should trigger given that params is NULL.
238f59d82ffSelric      */
239f59d82ffSelric     if (ret &&
240f59d82ffSelric 	(saved_errno != EFAULT &&
241f59d82ffSelric 	 saved_errno != EDOM &&
242f59d82ffSelric 	 saved_errno != ENOTCONN))
243f59d82ffSelric 	return 1;
244f59d82ffSelric     afs_ioctlnum = ioctlnum;
245f59d82ffSelric     afs_ioctlpath = strdup(path);
246f59d82ffSelric     if (afs_ioctlpath == NULL)
247f59d82ffSelric 	return 1;
248f59d82ffSelric     afs_entry_point = entrypoint;
249f59d82ffSelric     return 0;
250f59d82ffSelric }
251f59d82ffSelric 
252f59d82ffSelric static int
do_ioctl(void * data)253f59d82ffSelric do_ioctl(void *data)
254f59d82ffSelric {
255f59d82ffSelric     int fd, ret, saved_errno;
256f59d82ffSelric     fd = open(afs_ioctlpath, O_RDWR);
257f59d82ffSelric     if (fd < 0) {
258f59d82ffSelric 	errno = EINVAL;
259f59d82ffSelric 	return -1;
260f59d82ffSelric     }
261f59d82ffSelric     ret = ioctl(fd, afs_ioctlnum, data);
262f59d82ffSelric     saved_errno = errno;
263f59d82ffSelric     close(fd);
264f59d82ffSelric     errno = saved_errno;
265f59d82ffSelric     return ret;
266f59d82ffSelric }
267f59d82ffSelric 
268f59d82ffSelric int
k_pioctl(char * a_path,int o_opcode,struct ViceIoctl * a_paramsP,int a_followSymlinks)269f59d82ffSelric k_pioctl(char *a_path,
270f59d82ffSelric 	 int o_opcode,
271f59d82ffSelric 	 struct ViceIoctl *a_paramsP,
272f59d82ffSelric 	 int a_followSymlinks)
273f59d82ffSelric {
274f59d82ffSelric #ifndef NO_AFS
275f59d82ffSelric     switch(afs_entry_point){
276f59d82ffSelric #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
277f59d82ffSelric     case SINGLE_ENTRY_POINT:
278f59d82ffSelric     case SINGLE_ENTRY_POINT2:
279f59d82ffSelric     case SINGLE_ENTRY_POINT3:
280f59d82ffSelric 	return syscall(afs_syscalls[0], AFSCALL_PIOCTL,
281f59d82ffSelric 		       a_path, o_opcode, a_paramsP, a_followSymlinks);
282f59d82ffSelric #endif
283f59d82ffSelric #if defined(AFS_PIOCTL)
284f59d82ffSelric     case MULTIPLE_ENTRY_POINT:
285f59d82ffSelric 	return syscall(afs_syscalls[0],
286f59d82ffSelric 		       a_path, o_opcode, a_paramsP, a_followSymlinks);
287f59d82ffSelric #endif
288f59d82ffSelric     case LINUX_PROC_POINT: {
289f59d82ffSelric 	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
290f59d82ffSelric 	data.param1 = (unsigned long)a_path;
291f59d82ffSelric 	data.param2 = (unsigned long)o_opcode;
292f59d82ffSelric 	data.param3 = (unsigned long)a_paramsP;
293f59d82ffSelric 	data.param4 = (unsigned long)a_followSymlinks;
294f59d82ffSelric 	return do_ioctl(&data);
295f59d82ffSelric     }
296f59d82ffSelric     case MACOS_DEV_POINT: {
297f59d82ffSelric 	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
298f59d82ffSelric 	int ret;
299f59d82ffSelric 
300f59d82ffSelric 	data.param1 = (unsigned long)a_path;
301f59d82ffSelric 	data.param2 = (unsigned long)o_opcode;
302f59d82ffSelric 	data.param3 = (unsigned long)a_paramsP;
303f59d82ffSelric 	data.param4 = (unsigned long)a_followSymlinks;
304f59d82ffSelric 
305f59d82ffSelric 	ret = do_ioctl(&data);
306f59d82ffSelric 	if (ret)
307f59d82ffSelric 	    return ret;
308f59d82ffSelric 
309f59d82ffSelric 	return data.retval;
310f59d82ffSelric     }
311e0895134Schristos     case SUN_PROC_POINT: {
312e0895134Schristos 	struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_PIOCTL };
313e0895134Schristos 	data.param1 = (unsigned long)a_path;
314e0895134Schristos 	data.param2 = (unsigned long)o_opcode;
315e0895134Schristos 	data.param3 = (unsigned long)a_paramsP;
316e0895134Schristos 	data.param4 = (unsigned long)a_followSymlinks;
317e0895134Schristos 	return do_ioctl(&data);
318e0895134Schristos     }
319f59d82ffSelric #ifdef _AIX
320f59d82ffSelric     case AIX_ENTRY_POINTS:
321f59d82ffSelric 	return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
322f59d82ffSelric #endif
323f59d82ffSelric     }
324f59d82ffSelric     errno = ENOSYS;
325f59d82ffSelric #ifdef SIGSYS
326f59d82ffSelric     kill(getpid(), SIGSYS);	/* You lose! */
327f59d82ffSelric #endif
328f59d82ffSelric #endif /* NO_AFS */
329f59d82ffSelric     return -1;
330f59d82ffSelric }
331f59d82ffSelric 
332f59d82ffSelric int
k_afs_cell_of_file(const char * path,char * cell,int len)333f59d82ffSelric k_afs_cell_of_file(const char *path, char *cell, int len)
334f59d82ffSelric {
335f59d82ffSelric     struct ViceIoctl parms;
336f59d82ffSelric     parms.in = NULL;
337f59d82ffSelric     parms.in_size = 0;
338f59d82ffSelric     parms.out = cell;
339f59d82ffSelric     parms.out_size = len;
340f59d82ffSelric     return k_pioctl(rk_UNCONST(path), VIOC_FILE_CELL_NAME, &parms, 1);
341f59d82ffSelric }
342f59d82ffSelric 
343f59d82ffSelric int
k_unlog(void)344f59d82ffSelric k_unlog(void)
345f59d82ffSelric {
346f59d82ffSelric     struct ViceIoctl parms;
347f59d82ffSelric     memset(&parms, 0, sizeof(parms));
348f59d82ffSelric     return k_pioctl(0, VIOCUNLOG, &parms, 0);
349f59d82ffSelric }
350f59d82ffSelric 
351f59d82ffSelric int
k_setpag(void)352f59d82ffSelric k_setpag(void)
353f59d82ffSelric {
354f59d82ffSelric #ifndef NO_AFS
355f59d82ffSelric     switch(afs_entry_point){
356f59d82ffSelric #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
357f59d82ffSelric     case SINGLE_ENTRY_POINT:
358f59d82ffSelric     case SINGLE_ENTRY_POINT2:
359f59d82ffSelric     case SINGLE_ENTRY_POINT3:
360f59d82ffSelric 	return syscall(afs_syscalls[0], AFSCALL_SETPAG);
361f59d82ffSelric #endif
362f59d82ffSelric #if defined(AFS_PIOCTL)
363f59d82ffSelric     case MULTIPLE_ENTRY_POINT:
364f59d82ffSelric 	return syscall(afs_syscalls[1]);
365f59d82ffSelric #endif
366f59d82ffSelric     case LINUX_PROC_POINT: {
367f59d82ffSelric 	struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG };
368f59d82ffSelric 	return do_ioctl(&data);
369f59d82ffSelric     }
370f59d82ffSelric     case MACOS_DEV_POINT: {
371f59d82ffSelric 	struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 };
372f59d82ffSelric 	int ret = do_ioctl(&data);
373f59d82ffSelric 	if (ret)
374f59d82ffSelric 	    return ret;
375f59d82ffSelric 	return data.retval;
376f59d82ffSelric      }
377e0895134Schristos     case SUN_PROC_POINT: {
378e0895134Schristos 	struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_SETPAG };
379e0895134Schristos 	return do_ioctl(&data);
380e0895134Schristos     }
381f59d82ffSelric #ifdef _AIX
382f59d82ffSelric     case AIX_ENTRY_POINTS:
383f59d82ffSelric 	return Setpag();
384f59d82ffSelric #endif
385f59d82ffSelric     }
386f59d82ffSelric 
387f59d82ffSelric     errno = ENOSYS;
388f59d82ffSelric #ifdef SIGSYS
389f59d82ffSelric     kill(getpid(), SIGSYS);	/* You lose! */
390f59d82ffSelric #endif
391f59d82ffSelric #endif /* NO_AFS */
392f59d82ffSelric     return -1;
393f59d82ffSelric }
394f59d82ffSelric 
395f59d82ffSelric static jmp_buf catch_SIGSYS;
396f59d82ffSelric 
397f59d82ffSelric #ifdef SIGSYS
398f59d82ffSelric 
399f59d82ffSelric static RETSIGTYPE
SIGSYS_handler(int sig)400f59d82ffSelric SIGSYS_handler(int sig)
401f59d82ffSelric {
402f59d82ffSelric     errno = 0;
403f59d82ffSelric     signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */
404f59d82ffSelric     longjmp(catch_SIGSYS, 1);
405f59d82ffSelric }
406f59d82ffSelric 
407f59d82ffSelric #endif
408f59d82ffSelric 
409f59d82ffSelric /*
410f59d82ffSelric  * Try to see if `syscall' is a pioctl.  Return 0 iff succesful.
411f59d82ffSelric  */
412f59d82ffSelric 
413f59d82ffSelric #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
414f59d82ffSelric static int
try_one(int syscall_num)415f59d82ffSelric try_one (int syscall_num)
416f59d82ffSelric {
417f59d82ffSelric     struct ViceIoctl parms;
418f59d82ffSelric     memset(&parms, 0, sizeof(parms));
419f59d82ffSelric 
420f59d82ffSelric     if (setjmp(catch_SIGSYS) == 0) {
421f59d82ffSelric 	syscall(syscall_num, AFSCALL_PIOCTL,
422f59d82ffSelric 		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
423f59d82ffSelric 	if (errno == EINVAL) {
424f59d82ffSelric 	    afs_entry_point = SINGLE_ENTRY_POINT;
425f59d82ffSelric 	    afs_syscalls[0] = syscall_num;
426f59d82ffSelric 	    return 0;
427f59d82ffSelric 	}
428f59d82ffSelric     }
429f59d82ffSelric     return 1;
430f59d82ffSelric }
431f59d82ffSelric #endif
432f59d82ffSelric 
433f59d82ffSelric /*
434f59d82ffSelric  * Try to see if `syscall_pioctl' is a pioctl syscall.  Return 0 iff
435f59d82ffSelric  * succesful.
436f59d82ffSelric  *
437f59d82ffSelric  */
438f59d82ffSelric 
439f59d82ffSelric #ifdef AFS_PIOCTL
440f59d82ffSelric static int
try_two(int syscall_pioctl,int syscall_setpag)441f59d82ffSelric try_two (int syscall_pioctl, int syscall_setpag)
442f59d82ffSelric {
443f59d82ffSelric     struct ViceIoctl parms;
444f59d82ffSelric     memset(&parms, 0, sizeof(parms));
445f59d82ffSelric 
446f59d82ffSelric     if (setjmp(catch_SIGSYS) == 0) {
447f59d82ffSelric 	syscall(syscall_pioctl,
448f59d82ffSelric 		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
449f59d82ffSelric 	if (errno == EINVAL) {
450f59d82ffSelric 	    afs_entry_point = MULTIPLE_ENTRY_POINT;
451f59d82ffSelric 	    afs_syscalls[0] = syscall_pioctl;
452f59d82ffSelric 	    afs_syscalls[1] = syscall_setpag;
453f59d82ffSelric 	    return 0;
454f59d82ffSelric 	}
455f59d82ffSelric     }
456f59d82ffSelric     return 1;
457f59d82ffSelric }
458f59d82ffSelric #endif
459f59d82ffSelric 
460f59d82ffSelric int
k_hasafs(void)461f59d82ffSelric k_hasafs(void)
462f59d82ffSelric {
463f59d82ffSelric #if !defined(NO_AFS) && defined(SIGSYS)
464f59d82ffSelric     RETSIGTYPE (*saved_func)(int);
465f59d82ffSelric #endif
466f59d82ffSelric     int saved_errno, ret;
467f59d82ffSelric     char *env = NULL;
468f59d82ffSelric 
469f59d82ffSelric     if (!issuid())
470f59d82ffSelric 	env = getenv ("AFS_SYSCALL");
471f59d82ffSelric 
472f59d82ffSelric     /*
473f59d82ffSelric      * Already checked presence of AFS syscalls?
474f59d82ffSelric      */
475f59d82ffSelric     if (afs_entry_point != UNKNOWN_ENTRY_POINT)
476f59d82ffSelric 	return afs_entry_point != NO_ENTRY_POINT;
477f59d82ffSelric 
478f59d82ffSelric     /*
479f59d82ffSelric      * Probe kernel for AFS specific syscalls,
480f59d82ffSelric      * they (currently) come in two flavors.
481f59d82ffSelric      * If the syscall is absent we recive a SIGSYS.
482f59d82ffSelric      */
483f59d82ffSelric     afs_entry_point = NO_ENTRY_POINT;
484f59d82ffSelric 
485f59d82ffSelric     saved_errno = errno;
486f59d82ffSelric #ifndef NO_AFS
487f59d82ffSelric #ifdef SIGSYS
488f59d82ffSelric     saved_func = signal(SIGSYS, SIGSYS_handler);
489f59d82ffSelric #endif
490f59d82ffSelric     if (env && strstr(env, "..") == NULL) {
491f59d82ffSelric 
492f59d82ffSelric 	if (strncmp("/proc/", env, 6) == 0) {
493f59d82ffSelric 	    if (try_ioctlpath(env, VIOC_SYSCALL_PROC, LINUX_PROC_POINT) == 0)
494f59d82ffSelric 		goto done;
495f59d82ffSelric 	}
496f59d82ffSelric 	if (strncmp("/dev/", env, 5) == 0) {
497f59d82ffSelric #ifdef VIOC_SYSCALL_DEV
498f59d82ffSelric 	    if (try_ioctlpath(env, VIOC_SYSCALL_DEV, MACOS_DEV_POINT) == 0)
499f59d82ffSelric 		goto done;
500f59d82ffSelric #endif
501f59d82ffSelric #ifdef VIOC_SYSCALL_DEV_OPENAFS
502f59d82ffSelric 	    if (try_ioctlpath(env,VIOC_SYSCALL_DEV_OPENAFS,MACOS_DEV_POINT) ==0)
503f59d82ffSelric 		goto done;
504f59d82ffSelric #endif
505f59d82ffSelric 	}
506f59d82ffSelric     }
507f59d82ffSelric 
508f59d82ffSelric     ret = try_ioctlpath("/proc/fs/openafs/afs_ioctl",
509f59d82ffSelric 			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
510f59d82ffSelric     if (ret == 0)
511f59d82ffSelric 	goto done;
512f59d82ffSelric     ret = try_ioctlpath("/proc/fs/nnpfs/afs_ioctl",
513f59d82ffSelric 			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
514f59d82ffSelric     if (ret == 0)
515f59d82ffSelric 	goto done;
516f59d82ffSelric 
517f59d82ffSelric #ifdef VIOC_SYSCALL_DEV_OPENAFS
518f59d82ffSelric     ret = try_ioctlpath("/dev/openafs_ioctl",
519f59d82ffSelric 			VIOC_SYSCALL_DEV_OPENAFS, MACOS_DEV_POINT);
520f59d82ffSelric     if (ret == 0)
521f59d82ffSelric 	goto done;
522f59d82ffSelric #endif
523f59d82ffSelric #ifdef VIOC_SYSCALL_DEV
524f59d82ffSelric     ret = try_ioctlpath("/dev/nnpfs_ioctl", VIOC_SYSCALL_DEV, MACOS_DEV_POINT);
525f59d82ffSelric     if (ret == 0)
526f59d82ffSelric 	goto done;
527f59d82ffSelric #endif
528e0895134Schristos #ifdef VIOC_SUN_SYSCALL_DEV
529e0895134Schristos     ret = try_ioctlpath("/dev/afs", VIOC_SUN_SYSCALL_DEV, SUN_PROC_POINT);
530e0895134Schristos     if (ret == 0)
531e0895134Schristos 	goto done;
532e0895134Schristos #endif
533e0895134Schristos 
534f59d82ffSelric 
535f59d82ffSelric #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
536f59d82ffSelric     {
537f59d82ffSelric 	int tmp;
538f59d82ffSelric 
539f59d82ffSelric 	if (env != NULL) {
540f59d82ffSelric 	    if (sscanf (env, "%d", &tmp) == 1) {
541f59d82ffSelric 		if (try_one (tmp) == 0)
542f59d82ffSelric 		    goto done;
543f59d82ffSelric 	    } else {
544f59d82ffSelric 		char *end = NULL;
545f59d82ffSelric 		char *p;
546f59d82ffSelric 		char *s = strdup (env);
547f59d82ffSelric 
548f59d82ffSelric 		if (s != NULL) {
549f59d82ffSelric 		    for (p = strtok_r (s, ",", &end);
550f59d82ffSelric 			 p != NULL;
551f59d82ffSelric 			 p = strtok_r (NULL, ",", &end)) {
552f59d82ffSelric 			if (map_syscall_name_to_number (p, &tmp) == 0)
553f59d82ffSelric 			    if (try_one (tmp) == 0) {
554f59d82ffSelric 				free (s);
555f59d82ffSelric 				goto done;
556f59d82ffSelric 			    }
557f59d82ffSelric 		    }
558f59d82ffSelric 		    free (s);
559f59d82ffSelric 		}
560f59d82ffSelric 	    }
561f59d82ffSelric 	}
562f59d82ffSelric     }
563f59d82ffSelric #endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */
564f59d82ffSelric 
565f59d82ffSelric #ifdef AFS_SYSCALL
566f59d82ffSelric     if (try_one (AFS_SYSCALL) == 0)
567f59d82ffSelric 	goto done;
568f59d82ffSelric #endif /* AFS_SYSCALL */
569f59d82ffSelric 
570f59d82ffSelric #ifdef AFS_PIOCTL
571f59d82ffSelric     {
572f59d82ffSelric 	int tmp[2];
573f59d82ffSelric 
574f59d82ffSelric 	if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2)
575f59d82ffSelric 	    if (try_two (tmp[0], tmp[1]) == 2)
576f59d82ffSelric 		goto done;
577f59d82ffSelric     }
578f59d82ffSelric #endif /* AFS_PIOCTL */
579f59d82ffSelric 
580f59d82ffSelric #ifdef AFS_PIOCTL
581f59d82ffSelric     if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0)
582f59d82ffSelric 	goto done;
583f59d82ffSelric #endif /* AFS_PIOCTL */
584f59d82ffSelric 
585f59d82ffSelric #ifdef AFS_SYSCALL2
586f59d82ffSelric     if (try_one (AFS_SYSCALL2) == 0)
587f59d82ffSelric 	goto done;
588f59d82ffSelric #endif /* AFS_SYSCALL2 */
589f59d82ffSelric 
590f59d82ffSelric #ifdef AFS_SYSCALL3
591f59d82ffSelric     if (try_one (AFS_SYSCALL3) == 0)
592f59d82ffSelric 	goto done;
593f59d82ffSelric #endif /* AFS_SYSCALL3 */
594f59d82ffSelric 
595f59d82ffSelric #ifdef _AIX
596f59d82ffSelric #if 0
597f59d82ffSelric     if (env != NULL) {
598f59d82ffSelric 	char *pos = NULL;
599f59d82ffSelric 	char *pioctl_name;
600f59d82ffSelric 	char *setpag_name;
601f59d82ffSelric 
602f59d82ffSelric 	pioctl_name = strtok_r (env, ", \t", &pos);
603f59d82ffSelric 	if (pioctl_name != NULL) {
604f59d82ffSelric 	    setpag_name = strtok_r (NULL, ", \t", &pos);
605f59d82ffSelric 	    if (setpag_name != NULL)
606f59d82ffSelric 		if (try_aix (pioctl_name, setpag_name) == 0)
607f59d82ffSelric 		    goto done;
608f59d82ffSelric 	}
609f59d82ffSelric     }
610f59d82ffSelric #endif
611f59d82ffSelric 
612f59d82ffSelric     if(try_aix() == 0)
613f59d82ffSelric 	goto done;
614f59d82ffSelric #endif
615f59d82ffSelric 
616f59d82ffSelric 
617f59d82ffSelric done:
618f59d82ffSelric #ifdef SIGSYS
619f59d82ffSelric     signal(SIGSYS, saved_func);
620f59d82ffSelric #endif
621f59d82ffSelric #endif /* NO_AFS */
622f59d82ffSelric     errno = saved_errno;
623f59d82ffSelric     return afs_entry_point != NO_ENTRY_POINT;
624f59d82ffSelric }
625f59d82ffSelric 
626f59d82ffSelric int
k_hasafs_recheck(void)627f59d82ffSelric k_hasafs_recheck(void)
628f59d82ffSelric {
629f59d82ffSelric     afs_entry_point = UNKNOWN_ENTRY_POINT;
630f59d82ffSelric     return k_hasafs();
631f59d82ffSelric }
632