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