6c0dca7689f98ebceb353e21c1cca7bb02c8cb06
[openafs.git] / src / export / export.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 /*
11  * export -     EXPORT kernel extension
12  */
13
14 /* Unsafe: conflicts with _KERNEL inclusion of headers below */
15 /* #include <afs/param.h> */
16 /* #include <afsconfig.h> */
17 /* RCSID("$Header$"); */
18
19 #define _KERNEL
20 #include "sys/types.h"
21 #include "sys/user.h"
22 #include "sys/conf.h"
23 #include "sys/errno.h"
24 #include "sys/device.h"
25 #include "sys/uio.h"
26 #include "sys/pri.h"
27 #include "sys/malloc.h"
28 #include "sym.h"
29 #include "export.h"
30
31 #undef RELOC
32
33 sym_t  *toc_syms;               /* symbol table                 */
34 int     toc_nsyms;              /* # of symbols                 */
35 caddr_t toc_strs;               /* string table                 */
36 int     toc_size;               /* size of toc_syms             */
37
38 /*
39  * export       -       entry point to EXPORT kernel extension
40  *
41  * Input:
42  *      cmd     -       add/delete command
43  *      uiop    -       uio vector describing any config params
44  */
45 export(cmd, uiop)
46 struct uio *uiop; {
47         int     err, monster;
48         static once;
49
50         err     = 0;
51         monster = lockl(&kernel_lock, LOCK_SHORT);
52
53         switch (cmd) {
54             case CFG_INIT:                      /* add EXPORT           */
55                 if (err = config(uiop))
56                         export_cleanup();
57                 break;
58
59             case CFG_TERM:                      /* remove EXPORT        */
60                 if (err = export_cleanup())
61                         break;
62                 break;
63
64             default:
65                 err = EINVAL;
66                 break;
67         }
68
69         if (monster != LOCK_NEST)
70                 unlockl(&kernel_lock);
71
72         return err;
73 }
74 \f
75 /*
76  * config -     process configuration data
77  */
78 config(uiop)
79 register struct uio *uiop; {
80         struct k_conf conf;
81         register struct export_nl *np;
82         register sym_t *sym;
83         register err;
84
85         if (err = uiomove((char *)&conf, sizeof (conf), UIO_WRITE, uiop))
86                 return err;
87
88         toc_nsyms = conf.nsyms;
89         toc_size  = conf.symt_sz + conf.str_sz;
90
91         if (toc_nsyms * sizeof (sym_t) != conf.symt_sz
92             || toc_size > (1024 * 1024))
93 #ifdef AFS_AIX51_ENV
94                 return EFBIG;
95 #else
96                 return EINVAL;
97 #endif
98
99         toc_syms = (sym_t *) xmalloc(toc_size, 2, kernel_heap);
100
101         if (!toc_syms)
102                 return ENOMEM;
103
104         toc_strs = (char *) &toc_syms[toc_nsyms];
105
106         /*
107          * copy in the symbol table and the string table
108          */
109         if (err = copyin(conf.symtab, toc_syms, conf.symt_sz)
110             || (err = copyin(conf.strtab, toc_strs, conf.str_sz))) {
111                 xmfree(toc_syms, kernel_heap);
112                 toc_syms = 0;
113                 return err;
114         }
115
116         /*
117          * `TOC' format in kernel has offsets relocated to point directly
118          * into the string table.
119          */
120         for (sym = toc_syms; sym < &toc_syms[toc_nsyms]; ++sym)
121 #ifndef __XCOFF64__
122                 if (sym->n_zeroes == 0)
123 #endif
124                         sym->n_nptr = sym->n_offset + toc_strs;
125
126         return 0;
127 }
128
129 /*
130  * export_cleanup -     cleanup EXPORT prior to removing kernel extension
131  */
132 export_cleanup() {
133
134         /*
135          * get rid of the symbol table
136          */
137         if (toc_syms) {
138                 xmfree(toc_syms, kernel_heap);
139                 toc_syms = 0;
140                 toc_size = 0;
141                 toc_strs = 0;
142         }
143
144         return 0;
145 }
146
147 /*
148  * import_kfunc -       import a kernel function that was mistakenly left
149  *                      off the exports list
150  *
151  * NOTE:
152  *      We are assuming that the functions we are importing from the
153  *      kernel really are within the kernel.  If they are actually
154  *      exported from some other kernel extension (but referenced in
155  *      the /unix symbol table) we are in trouble.
156  */
157 #ifdef __XCOFF64__
158         u_int64 *myg_toc;
159 #else
160         u_int32 *myg_toc;
161 #endif
162
163 import_kfunc(struct k_func *kfp) {
164         register sym_t *sym;
165         register i, pri;
166 #if 0
167         static caddr_t *g_toc;
168 #endif
169
170         if (!myg_toc) {
171                 sym = sym_lookup("g_toc", 0);
172                 if (!sym) {
173                         printf("\nimport: can't ascertain kernel's TOC\n");
174                         return EINVAL;
175                 }
176                 myg_toc = sym->n_value;
177         }
178
179         sym = sym_lookup(kfp->name, 0);
180         if (!sym) {
181                 printf("\nimport: function `%s' not found\n", kfp->name);
182                 return EINVAL;
183         }
184
185         kfp->fdesc[0] = sym->n_value;
186         kfp->fdesc[1] = myg_toc;
187         kfp->fdesc[2] = 0;
188
189 #ifdef __XCOFF64__
190         *(u_int64**) kfp->fpp = kfp->fdesc;
191 #else
192         *(u_int **) kfp->fpp = kfp->fdesc;
193 #endif
194
195         return 0;
196 }
197
198 /*
199  * import_kvar -        import a kernel variable that was mistakenly left
200  *                      off the exports list
201  */
202 import_kvar(struct k_var *kvp, caddr_t *toc) {
203         register sym_t *sym;
204         register i, pri;
205         label_t jmpbuf;
206
207         switch (setjmpx(&jmpbuf)) {
208             case 0:
209                 break;
210
211             default:
212                 return EINVAL;
213         }
214
215         sym = sym_lookup(kvp->name, 0);
216         if (!sym) {
217                 printf("\nimport: variable `%s' not found\n", kvp->name);
218                 longjmpx(EINVAL);
219         }
220
221         /*
222          * look through the caller's TOC for the reference to his surrogate
223          * variable.
224          */
225         while (*toc != kvp->varp)
226                 ++toc;
227
228         printf("import(%s): replacing my TOC at 0x%x: 0x%8x with 0x%8x\n"
229                , kvp->name, toc, *toc, sym->n_value);
230
231         /*
232          * replace reference to surrogate with reference real
233          */
234         pri = i_disable(INTMAX);
235         *toc = (caddr_t) sym->n_value;
236         i_enable(pri);
237
238         clrjmpx(&jmpbuf);
239
240         return 0;
241 }
242
243
244 /*
245  * Call vanilla syscalls
246  */
247 #ifndef AFS_AIX51_ENV
248 osetgroups(ngroups, gidset)
249     int ngroups;
250     gid_t *gidset;
251 {
252     int error;
253
254     error = setgroups(ngroups, gidset);
255     return (error);
256 }
257 #endif
258
259 #ifdef AFS_AIX51_ENV
260 #ifdef AFS_64BIT_KERNEL
261 okioctl(fdes, cmd, arg, ext, arg2, arg3)
262 #else /* AFS_64BIT_KERNEL */
263 okioctl32(fdes, cmd, arg, ext, arg2, arg3)
264 #endif /* AFS_64BIT_KERNEL */
265     int fdes, cmd;
266     caddr_t ext, arg, arg2, arg3;
267 #else
268 okioctl(fdes, cmd, arg, ext)
269     int fdes, cmd, arg;
270     caddr_t ext;
271 #endif
272 {
273     int error;
274     
275 #ifdef AFS_AIX51_ENV
276 #ifdef AFS_64BIT_KERNEL
277     error = kioctl(fdes, cmd, arg, ext, arg2, arg3);
278 #else /* AFS_64BIT_KERNEL */
279     error = kioctl32(fdes, cmd, arg, ext, arg2, arg3);
280 #endif /* AFS_64BIT_KERNEL */
281 #else
282     error = kioctl(fdes, cmd, arg, ext);
283 #endif
284     return (error);
285 }
286
287 #ifdef  notdef
288 ocore(signo, sigctx)
289     char signo;
290     struct sigcontext *sigctx;
291 {
292     int error;
293 #include <sys/user.h>
294     u.u_sigflags[signo] |= SA_FULLDUMP;         /* XXX */
295     error = core(signo, sigctx);
296     return (error);
297 }
298 #endif
299