2 * Copyright 2000, International Business Machines Corporation and others.
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
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)
21 #include "netinet/in_var.h"
22 #endif /* !defined(UKERNEL) */
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 */
50 afs_int32 now
, last10MinCheck
, last60MinCheck
;
58 if (last10MinCheck
+ 600 < now
) {
62 if (last60MinCheck
+ 3600 < now
) {
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
;
74 afs_termState
= AFSOP_STOP_COMPLETE
;
76 afs_osi_Wakeup(&afs_termState
);
84 afspag_Init(afs_int32 nfs_server_addr
)
86 struct clientcred ccred
;
87 struct rmtbulk idata
, odata
;
88 afs_int32 code
, err
, addr
, obuf
;
91 afs_uuid_create(&afs_cb_interface
.uuid
);
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;
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
);
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");
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");
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 */
154 afspag_Shutdown(void)
156 if (afs_shuttingdown
!= AFS_RUNNING
)
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();
178 while (afs_termState
== AFSOP_STOP_RXK_LISTENER
)
179 afs_osi_Sleep(&afs_termState
);
180 /* rxk_Listener sets AFSOP_STOP_COMPLETE */
185 token_conversion(char *buffer
, int buf_size
, int in
)
187 struct ClearToken
*ticket
;
191 if (buf_size
< 4) return;
192 lptr
= (afs_int32
*)buffer
;
193 buffer
+= 4; buf_size
-= 4;
195 *lptr
= ntohl(*lptr
);
199 *lptr
= htonl(*lptr
);
201 if (n
< 0 || buf_size
< n
) return;
202 buffer
+= n
; buf_size
-= n
;
205 if (buf_size
< 4) return;
206 lptr
= (afs_int32
*)buffer
;
207 buffer
+= 4; buf_size
-= 4;
209 *lptr
= ntohl(*lptr
);
213 *lptr
= htonl(*lptr
);
215 if (n
< 0 || buf_size
< n
) return;
216 if (n
>= sizeof(struct ClearToken
)) {
217 ticket
= (struct ClearToken
*)buffer
;
219 ticket
->AuthHandle
= ntohl(ticket
->AuthHandle
);
220 ticket
->ViceId
= ntohl(ticket
->ViceId
);
221 ticket
->BeginTimestamp
= ntohl(ticket
->BeginTimestamp
);
222 ticket
->EndTimestamp
= ntohl(ticket
->EndTimestamp
);
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
;
233 if (buf_size
< 4) return;
234 lptr
= (afs_int32
*)buffer
;
236 *lptr
= ntohl(*lptr
);
238 *lptr
= htonl((*lptr
) & ~0x8000);
244 FetchVolumeStatus_conversion(char *buffer
, int buf_size
, int in
)
246 AFSFetchVolumeStatus
*status
= (AFSFetchVolumeStatus
*)buffer
;
248 if (buf_size
< sizeof(AFSFetchVolumeStatus
))
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
);
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
);
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
);
281 case (0x5600 | 5): /* VIOCSETVOLSTAT */
282 FetchVolumeStatus_conversion(buffer
, buf_size
, in
);
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 */
296 if (in
) lptr
[0] = ntohl(lptr
[0]);
297 else lptr
[0] = htonl(lptr
[0]);
301 case (0x5600 | 36): /* VIOCSETCELLSTATUS */
302 /* two 32-bit integers */
304 if (in
) lptr
[0] = ntohl(lptr
[0]);
305 else lptr
[0] = htonl(lptr
[0]);
308 if (in
) lptr
[1] = ntohl(lptr
[1]);
309 else lptr
[1] = htonl(lptr
[1]);
316 outparam_conversion(int cmd
, char *buffer
, int buf_size
, int in
)
318 afs_int32
*lptr
= (afs_int32
*)buffer
;
321 switch (cmd
& 0xffff) {
322 case (0x5600 | 4): /* VIOCGETVOLSTAT */
323 case (0x5600 | 5): /* VIOCSETVOLSTAT */
324 FetchVolumeStatus_conversion(buffer
, buf_size
, in
);
327 case (0x5600 | 8): /* VIOCGETTOK */
328 token_conversion(buffer
, buf_size
, in
);
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 */
339 if (in
) lptr
[0] = ntohl(lptr
[0]);
340 else lptr
[0] = htonl(lptr
[0]);
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
]);
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
;
367 char *abspath
, *pathbuf
= 0;
369 AFS_STATCNT(afs_syscall_pioctl
);
371 follow
= 1; /* compat. with old venus */
372 code
= copyin_afs_ioctl(cmarg
, &data
);
375 if ((com
& 0xff) == 90) {
376 /* PSetClientContext, in any space */
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
);
388 case (0x5600 | 9): /* VIOCUNLOG */
389 case (0x5600 | 21): /* VIOCUNPAG */
390 code
= afspag_PUnlog(data
.in
, data
.in_size
, &credp
);
394 case (0x5600 | 38): /* VIOC_AFS_SYSNAME */
395 code
= afspag_PSetSysName(data
.in
, data
.in_size
, &credp
);
400 /* Set up credentials */
401 memset(&ccred
, 0, sizeof(ccred
));
402 pag
= PagInCred(credp
);
403 ccred
.uid
= afs_cr_uid(credp
);
405 afs_get_groups_from_pag(pag
, &g0
, &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.
416 pathbuf
= osi_AllocLargeSpace(RMTSYS_MAXPATHLEN
);
421 code
= osi_abspath(path
, pathbuf
, RMTSYS_MAXPATHLEN
, 0, &abspath
);
428 /* Allocate, copy, and convert incoming data */
429 idata
.rmtbulk_len
= in_size
= data
.in_size
;
430 if (in_size
< 0 || in_size
> MAXBUFFERLEN
) {
434 if (in_size
> AFS_LRALLOCSIZ
)
435 idata
.rmtbulk_val
= osi_Alloc(in_size
);
437 idata
.rmtbulk_val
= osi_AllocLargeSpace(AFS_LRALLOCSIZ
);
438 if (!idata
.rmtbulk_val
) {
443 AFS_COPYIN(data
.in
, idata
.rmtbulk_val
, in_size
, code
);
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
) {
455 if (out_size
> AFS_LRALLOCSIZ
)
456 odata
.rmtbulk_val
= osi_Alloc(out_size
);
458 odata
.rmtbulk_val
= osi_AllocLargeSpace(AFS_LRALLOCSIZ
);
459 if (!odata
.rmtbulk_val
) {
465 code
= RMTSYS_Pioctl(rmtsys_conn
, &ccred
, abspath
, com
, follow
,
466 &idata
, &odata
, &err
);
471 /* Convert and copy out the result */
472 if (odata
.rmtbulk_len
> out_size
) {
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
);
484 if (out_size
> AFS_LRALLOCSIZ
)
485 osi_Free(odata
.rmtbulk_val
, out_size
);
487 osi_FreeLargeSpace(odata
.rmtbulk_val
);
490 if (in_size
> AFS_LRALLOCSIZ
)
491 osi_Free(idata
.rmtbulk_val
, in_size
);
493 osi_FreeLargeSpace(idata
.rmtbulk_val
);
497 osi_FreeLargeSpace(pathbuf
);
501 #if defined(KERNEL_HAVE_UERROR)
504 return (getuerror());
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
))
524 /* otherwise, we don't support afs_syscall_call, period */
525 #if defined(KERNEL_HAVE_UERROR)