Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / afs / afs_pag_call.c
bloba20e3e6276a2e5eaec9c2a0794e16b93b160eceb
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
10 #include <afsconfig.h>
11 #include "afs/param.h"
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h"
17 #include "rx/rx_globals.h"
18 #include "rx/rxstat.h"
19 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
20 #include "net/if.h"
21 #include "netinet/in_var.h"
22 #endif /* !defined(UKERNEL) */
23 #include "rmtsys.h"
24 #include "pagcb.h"
27 afs_int32 afs_termState = 0;
28 afs_int32 afs_gcpags = AFS_GCPAGS;
29 enum afs_shutdown_state afs_shuttingdown = AFS_RUNNING;
30 int afs_cold_shutdown = 0;
31 int afs_resourceinit_flag = 0;
32 afs_int32 afs_nfs_server_addr;
33 struct interfaceAddr afs_cb_interface;
34 struct afs_osi_WaitHandle AFS_WaitHandler;
35 static struct rx_securityClass *srv_secobj;
36 static struct rx_securityClass *clt_secobj;
37 static struct rx_service *stats_svc;
38 static struct rx_service *pagcb_svc;
39 static struct rx_connection *rmtsys_conn;
40 char *afs_sysname = 0;
41 char *afs_sysnamelist[MAXNUMSYSNAMES];
42 int afs_sysnamecount = 0;
43 int afs_sysnamegen = 0;
44 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
47 void
48 afs_Daemon(void)
50 afs_int32 now, last10MinCheck, last60MinCheck;
52 last10MinCheck = 0;
53 last60MinCheck = 0;
54 while (1) {
55 rx_CheckPackets();
56 now = osi_Time();
58 if (last10MinCheck + 600 < now) {
59 afs_GCUserData();
62 if (last60MinCheck + 3600 < now) {
63 afs_int32 didany;
64 afs_GCPAGs(&didany);
67 now = 20000 - (osi_Time() - now);
68 afs_osi_Wait(now, &AFS_WaitHandler, 0);
70 if (afs_termState == AFSOP_STOP_AFS) {
71 #if defined(RXK_LISTENER_ENV)
72 afs_termState = AFSOP_STOP_RXEVENT;
73 #else
74 afs_termState = AFSOP_STOP_COMPLETE;
75 #endif
76 afs_osi_Wakeup(&afs_termState);
77 return;
83 void
84 afspag_Init(afs_int32 nfs_server_addr)
86 struct clientcred ccred;
87 struct rmtbulk idata, odata;
88 afs_int32 code, err, addr, obuf;
89 int i;
91 afs_uuid_create(&afs_cb_interface.uuid);
93 AFS_GLOCK();
95 afs_InitStats();
96 rx_Init(htons(7001));
98 AFS_STATCNT(afs_ResourceInit);
99 AFS_RWLOCK_INIT(&afs_xuser, "afs_xuser");
100 AFS_RWLOCK_INIT(&afs_xpagcell, "afs_xpagcell");
101 AFS_RWLOCK_INIT(&afs_xpagsys, "afs_xpagsys");
102 AFS_RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
104 afs_resourceinit_flag = 1;
105 afs_nfs_server_addr = nfs_server_addr;
106 for (i = 0; i < MAXNUMSYSNAMES; i++) {
107 afs_sysnamelist[i] = afs_osi_Alloc(MAXSYSNAME);
108 osi_Assert(afs_sysnamelist[i] != NULL);
110 afs_sysname = afs_sysnamelist[0];
111 strcpy(afs_sysname, SYS_NAME);
112 afs_sysnamecount = 1;
113 afs_sysnamegen++;
115 srv_secobj = rxnull_NewServerSecurityObject();
116 stats_svc = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", &srv_secobj,
117 1, RXSTATS_ExecuteRequest);
118 pagcb_svc = rx_NewService(0, PAGCB_SERVICEID, "pagcb", &srv_secobj,
119 1, PAGCB_ExecuteRequest);
120 rx_StartServer(0);
122 clt_secobj = rxnull_NewClientSecurityObject();
123 rmtsys_conn = rx_NewConnection(nfs_server_addr, htons(7009),
124 RMTSYS_SERVICEID, clt_secobj, 0);
126 #ifdef RXK_LISTENER_ENV
127 afs_start_thread(rxk_Listener, "Rx Listener");
128 #endif
129 afs_start_thread((void *)(void *)rx_ServerProc, "Rx Server Thread");
130 afs_start_thread(afs_rxevent_daemon, "Rx Event Daemon");
131 afs_start_thread(afs_Daemon, "AFS PAG Daemon");
133 afs_icl_InitLogs();
135 AFS_GUNLOCK();
137 /* If it's reachable, tell the translator to nuke our creds.
138 * We should be more agressive about making sure this gets done,
139 * even if the translator is unreachable when we boot.
141 addr = obuf = err = 0;
142 idata.rmtbulk_len = sizeof(addr);
143 idata.rmtbulk_val = (char *)&addr;
144 odata.rmtbulk_len = sizeof(obuf);
145 odata.rmtbulk_val = (char *)&obuf;
146 memset(&ccred, 0, sizeof(ccred));
147 code = RMTSYS_Pioctl(rmtsys_conn, &ccred, NIL_PATHP, 0x4F01, 0,
148 &idata, &odata, &err);
149 } /*afs_ResourceInit */
152 /* called with the GLOCK held */
153 void
154 afspag_Shutdown(void)
156 if (afs_shuttingdown != AFS_RUNNING)
157 return;
158 afs_shuttingdown = AFS_SHUTDOWN;
159 afs_termState = AFSOP_STOP_RXCALLBACK;
160 rx_WakeupServerProcs();
161 while (afs_termState == AFSOP_STOP_RXCALLBACK)
162 afs_osi_Sleep(&afs_termState);
163 /* rx_ServerProc sets AFS_STOP_AFS */
165 while (afs_termState == AFSOP_STOP_AFS) {
166 afs_osi_CancelWait(&AFS_WaitHandler);
167 afs_osi_Sleep(&afs_termState);
169 /* afs_Daemon sets AFS_STOP_RXEVENT */
171 #if defined(RXK_LISTENER_ENV)
172 while (afs_termState == AFSOP_STOP_RXEVENT)
173 afs_osi_Sleep(&afs_termState);
174 /* afs_rxevent_daemon sets AFSOP_STOP_RXK_LISTENER */
176 afs_osi_UnmaskRxkSignals();
177 osi_StopListener();
178 while (afs_termState == AFSOP_STOP_RXK_LISTENER)
179 afs_osi_Sleep(&afs_termState);
180 /* rxk_Listener sets AFSOP_STOP_COMPLETE */
181 #endif
184 static void
185 token_conversion(char *buffer, int buf_size, int in)
187 struct ClearToken *ticket;
188 afs_int32 *lptr, n;
190 /* secret ticket */
191 if (buf_size < 4) return;
192 lptr = (afs_int32 *)buffer;
193 buffer += 4; buf_size -= 4;
194 if (in) {
195 *lptr = ntohl(*lptr);
196 n = *lptr;
197 } else {
198 n = *lptr;
199 *lptr = htonl(*lptr);
201 if (n < 0 || buf_size < n) return;
202 buffer += n; buf_size -= n;
204 /* clear token */
205 if (buf_size < 4) return;
206 lptr = (afs_int32 *)buffer;
207 buffer += 4; buf_size -= 4;
208 if (in) {
209 *lptr = ntohl(*lptr);
210 n = *lptr;
211 } else {
212 n = *lptr;
213 *lptr = htonl(*lptr);
215 if (n < 0 || buf_size < n) return;
216 if (n >= sizeof(struct ClearToken)) {
217 ticket = (struct ClearToken *)buffer;
218 if (in) {
219 ticket->AuthHandle = ntohl(ticket->AuthHandle);
220 ticket->ViceId = ntohl(ticket->ViceId);
221 ticket->BeginTimestamp = ntohl(ticket->BeginTimestamp);
222 ticket->EndTimestamp = ntohl(ticket->EndTimestamp);
223 } else {
224 ticket->AuthHandle = htonl(ticket->AuthHandle);
225 ticket->ViceId = htonl(ticket->ViceId);
226 ticket->BeginTimestamp = htonl(ticket->BeginTimestamp);
227 ticket->EndTimestamp = htonl(ticket->EndTimestamp);
230 buffer += n; buf_size -= n;
232 /* primary flag */
233 if (buf_size < 4) return;
234 lptr = (afs_int32 *)buffer;
235 if (in) {
236 *lptr = ntohl(*lptr);
237 } else {
238 *lptr = htonl((*lptr) & ~0x8000);
240 return;
243 static void
244 FetchVolumeStatus_conversion(char *buffer, int buf_size, int in)
246 AFSFetchVolumeStatus *status = (AFSFetchVolumeStatus *)buffer;
248 if (buf_size < sizeof(AFSFetchVolumeStatus))
249 return;
250 if (in) {
251 status->Vid = ntohl(status->Vid);
252 status->ParentId = ntohl(status->ParentId);
253 status->Type = ntohl(status->Type);
254 status->MinQuota = ntohl(status->MinQuota);
255 status->MaxQuota = ntohl(status->MaxQuota);
256 status->BlocksInUse = ntohl(status->BlocksInUse);
257 status->PartBlocksAvail = ntohl(status->PartBlocksAvail);
258 status->PartMaxBlocks = ntohl(status->PartMaxBlocks);
259 } else {
260 status->Vid = htonl(status->Vid);
261 status->ParentId = htonl(status->ParentId);
262 status->Type = htonl(status->Type);
263 status->MinQuota = htonl(status->MinQuota);
264 status->MaxQuota = htonl(status->MaxQuota);
265 status->BlocksInUse = htonl(status->BlocksInUse);
266 status->PartBlocksAvail = htonl(status->PartBlocksAvail);
267 status->PartMaxBlocks = htonl(status->PartMaxBlocks);
271 static void
272 inparam_conversion(int cmd, char *buffer, int buf_size, int in)
274 afs_int32 *lptr = (afs_int32 *)buffer;
276 switch (cmd & 0xffff) {
277 case (0x5600 | 3): /* VIOCSETTOK */
278 token_conversion(buffer, buf_size, in);
279 return;
281 case (0x5600 | 5): /* VIOCSETVOLSTAT */
282 FetchVolumeStatus_conversion(buffer, buf_size, in);
283 return;
285 case (0x5600 | 8): /* VIOCGETTOK */
286 case (0x5600 | 10): /* VIOCCKSERV */
287 case (0x5600 | 20): /* VIOCACCESS */
288 case (0x5600 | 24): /* VIOCSETCACHESIZE */
289 case (0x5600 | 27): /* VIOCGETCELL */
290 case (0x5600 | 32): /* VIOC_AFS_MARINER_HOST */
291 case (0x5600 | 34): /* VIOC_VENUSLOG */
292 case (0x5600 | 38): /* VIOC_AFS_SYSNAME */
293 case (0x5600 | 39): /* VIOC_EXPORTAFS */
294 /* one 32-bit integer */
295 if (buf_size >= 4) {
296 if (in) lptr[0] = ntohl(lptr[0]);
297 else lptr[0] = htonl(lptr[0]);
299 return;
301 case (0x5600 | 36): /* VIOCSETCELLSTATUS */
302 /* two 32-bit integers */
303 if (buf_size >= 4) {
304 if (in) lptr[0] = ntohl(lptr[0]);
305 else lptr[0] = htonl(lptr[0]);
307 if (buf_size >= 8) {
308 if (in) lptr[1] = ntohl(lptr[1]);
309 else lptr[1] = htonl(lptr[1]);
311 return;
315 static void
316 outparam_conversion(int cmd, char *buffer, int buf_size, int in)
318 afs_int32 *lptr = (afs_int32 *)buffer;
319 int i;
321 switch (cmd & 0xffff) {
322 case (0x5600 | 4): /* VIOCGETVOLSTAT */
323 case (0x5600 | 5): /* VIOCSETVOLSTAT */
324 FetchVolumeStatus_conversion(buffer, buf_size, in);
325 return;
327 case (0x5600 | 8): /* VIOCGETTOK */
328 token_conversion(buffer, buf_size, in);
329 return;
331 case (0x5600 | 12): /* VIOCCKCONN */
332 case (0x5600 | 32): /* VIOC_AFS_MARINER_HOST */
333 case (0x5600 | 34): /* VIOC_VENUSLOG */
334 case (0x5600 | 35): /* VIOC_GETCELLSTATUS */
335 case (0x5600 | 38): /* VIOC_AFS_SYSNAME */
336 case (0x5600 | 39): /* VIOC_EXPORTAFS */
337 /* one 32-bit integer */
338 if (buf_size >= 4) {
339 if (in) lptr[0] = ntohl(lptr[0]);
340 else lptr[0] = htonl(lptr[0]);
342 return;
344 case (0x5600 | 40): /* VIOCGETCACHEPARMS */
345 /* sixteen 32-bit integers */
346 for (i = 0; i < 16 && buf_size >= 4; i++) {
347 if (in) lptr[i] = ntohl(lptr[i]);
348 else lptr[i] = htonl(lptr[i]);
349 buf_size -= 4;
351 return;
356 /* called with the GLOCK held */
358 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
360 cred_t *credp = crref(); /* don't free until done! */
361 struct afs_ioctl data;
362 struct clientcred ccred;
363 struct rmtbulk idata, odata;
364 short in_size, out_size;
365 afs_int32 code = 0, pag, err;
366 gid_t g0, g1;
367 char *abspath, *pathbuf = 0;
369 AFS_STATCNT(afs_syscall_pioctl);
370 if (follow)
371 follow = 1; /* compat. with old venus */
372 code = copyin_afs_ioctl(cmarg, &data);
373 if (code) goto out;
375 if ((com & 0xff) == 90) {
376 /* PSetClientContext, in any space */
377 code = EINVAL;
378 goto out;
381 /* Special handling for a few pioctls */
382 switch (com & 0xffff) {
383 case (0x5600 | 3): /* VIOCSETTOK */
384 code = afspag_PSetTokens(data.in, data.in_size, &credp);
385 if (code) goto out;
386 break;
388 case (0x5600 | 9): /* VIOCUNLOG */
389 case (0x5600 | 21): /* VIOCUNPAG */
390 code = afspag_PUnlog(data.in, data.in_size, &credp);
391 if (code) goto out;
392 break;
394 case (0x5600 | 38): /* VIOC_AFS_SYSNAME */
395 code = afspag_PSetSysName(data.in, data.in_size, &credp);
396 if (code) goto out;
397 break;
400 /* Set up credentials */
401 memset(&ccred, 0, sizeof(ccred));
402 pag = PagInCred(credp);
403 ccred.uid = afs_cr_uid(credp);
404 if (pag != NOPAG) {
405 afs_get_groups_from_pag(pag, &g0, &g1);
406 ccred.group0 = g0;
407 ccred.group1 = g1;
411 * Copy the path and convert to absolute, if one was given.
412 * NB: We can only use osI_AllocLargeSpace here as long as
413 * RMTSYS_MAXPATHLEN is less than AFS_LRALLOCSIZ.
415 if (path) {
416 pathbuf = osi_AllocLargeSpace(RMTSYS_MAXPATHLEN);
417 if (!pathbuf) {
418 code = ENOMEM;
419 goto out;
421 code = osi_abspath(path, pathbuf, RMTSYS_MAXPATHLEN, 0, &abspath);
422 if (code)
423 goto out_path;
424 } else {
425 abspath = NIL_PATHP;
428 /* Allocate, copy, and convert incoming data */
429 idata.rmtbulk_len = in_size = data.in_size;
430 if (in_size < 0 || in_size > MAXBUFFERLEN) {
431 code = EINVAL;
432 goto out_path;
434 if (in_size > AFS_LRALLOCSIZ)
435 idata.rmtbulk_val = osi_Alloc(in_size);
436 else
437 idata.rmtbulk_val = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
438 if (!idata.rmtbulk_val) {
439 code = ENOMEM;
440 goto out_path;
442 if (in_size) {
443 AFS_COPYIN(data.in, idata.rmtbulk_val, in_size, code);
444 if (code)
445 goto out_idata;
446 inparam_conversion(com, idata.rmtbulk_val, in_size, 0);
449 /* Allocate space for outgoing data */
450 odata.rmtbulk_len = out_size = data.out_size;
451 if (out_size < 0 || out_size > MAXBUFFERLEN) {
452 code = EINVAL;
453 goto out_idata;
455 if (out_size > AFS_LRALLOCSIZ)
456 odata.rmtbulk_val = osi_Alloc(out_size);
457 else
458 odata.rmtbulk_val = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
459 if (!odata.rmtbulk_val) {
460 code = ENOMEM;
461 goto out_idata;
464 AFS_GUNLOCK();
465 code = RMTSYS_Pioctl(rmtsys_conn, &ccred, abspath, com, follow,
466 &idata, &odata, &err);
467 AFS_GLOCK();
468 if (code)
469 goto out_odata;
471 /* Convert and copy out the result */
472 if (odata.rmtbulk_len > out_size) {
473 code = E2BIG;
474 goto out_odata;
476 if (odata.rmtbulk_len) {
477 outparam_conversion(com, odata.rmtbulk_val, odata.rmtbulk_len, 1);
478 AFS_COPYOUT(odata.rmtbulk_val, data.out, odata.rmtbulk_len, code);
480 if (!code)
481 code = err;
483 out_odata:
484 if (out_size > AFS_LRALLOCSIZ)
485 osi_Free(odata.rmtbulk_val, out_size);
486 else
487 osi_FreeLargeSpace(odata.rmtbulk_val);
489 out_idata:
490 if (in_size > AFS_LRALLOCSIZ)
491 osi_Free(idata.rmtbulk_val, in_size);
492 else
493 osi_FreeLargeSpace(idata.rmtbulk_val);
495 out_path:
496 if (path)
497 osi_FreeLargeSpace(pathbuf);
499 out:
500 crfree(credp);
501 #if defined(KERNEL_HAVE_UERROR)
502 if (!getuerror())
503 setuerror(code);
504 return (getuerror());
505 #else
506 return (code);
507 #endif
512 afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
513 long parm, parm2, parm3, parm4, parm5, parm6;
515 /* Superusers may shut us down, such as with afsd -shutdown. */
516 if (parm == AFSOP_SHUTDOWN && afs_suser(NULL))
518 AFS_GLOCK();
519 afspag_Shutdown();
520 AFS_GUNLOCK();
521 return 0;
524 /* otherwise, we don't support afs_syscall_call, period */
525 #if defined(KERNEL_HAVE_UERROR)
526 setuerror(EPERM);
527 #endif
528 return EPERM;