winnt-win2000-win98-afs-client-updates-20010623
[openafs.git] / src / WINNT / afsd / afsd_init.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 #include <afs/param.h>
11 #include <afs/stds.h>
12 #include <afs/afs_args.h>
13
14 #include <windows.h>
15 #include <string.h>
16 #include <nb30.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <winsock2.h>
20
21 #include <osi.h>
22 #include "afsd.h"
23 #include <rx\rx.h>
24 #include <rx\rx_null.h>
25
26 #include <WINNT/syscfg.h>
27
28 #include "smb.h"
29 #include "cm_rpc.h"
30
31 extern int RXAFSCB_ExecuteRequest();
32 extern int RXSTATS_ExecuteRequest();
33
34 extern afs_int32 cryptall;
35
36 char AFSConfigKeyName[] =
37         "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
38
39 osi_log_t *afsd_logp;
40
41 char cm_rootVolumeName[64];
42 DWORD cm_rootVolumeNameLen;
43 cm_volume_t *cm_rootVolumep = NULL;
44 cm_cell_t *cm_rootCellp = NULL;
45 cm_fid_t cm_rootFid;
46 cm_scache_t *cm_rootSCachep;
47 char cm_mountRoot[1024];
48 DWORD cm_mountRootLen;
49 int cm_logChunkSize;
50 int cm_chunkSize;
51
52 int smb_UseV3;
53
54 int LANadapter;
55
56 int numBkgD;
57 int numSvThreads;
58
59 int traceOnPanic = 0;
60
61 int logReady = 0;
62
63 char cm_HostName[200];
64 long cm_HostAddr;
65
66 char cm_CachePath[200];
67 DWORD cm_CachePathLen;
68
69 BOOL isGateway = FALSE;
70
71 BOOL reportSessionStartups = FALSE;
72
73 cm_initparams_v1 cm_initParams;
74
75 /*
76  * AFSD Initialization Log
77  *
78  * This is distinct from the regular debug logging facility.
79  * Log items go directly to a file, not to an array in memory, so that even
80  * if AFSD crashes, the log can be inspected.
81  */
82
83 HANDLE afsi_file;
84
85 void
86 afsi_start()
87 {
88         char wd[100];
89         char t[100], u[100];
90         int zilch;
91         int code;
92
93         afsi_file = INVALID_HANDLE_VALUE;
94         code = GetWindowsDirectory(wd, sizeof(wd));
95         if (code == 0) return;
96         strcat(wd, "\\afsd_init.log");
97         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
98         afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
99                                 CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
100         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));
101         strcat(t, ": Create log file\n");
102         strcat(u, ": Created log file\n");
103         WriteFile(afsi_file, t, strlen(t), &zilch, NULL);
104         WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
105 }
106
107 void
108 afsi_log(char *pattern, ...)
109 {
110         char s[100], t[100], u[100];
111         int zilch;
112         va_list ap;
113         va_start(ap, pattern);
114
115         vsprintf(s, pattern, ap);
116         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
117         sprintf(u, "%s: %s\n", t, s);
118         if (afsi_file != INVALID_HANDLE_VALUE)
119                 WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
120 }
121
122 /*
123  * Standard AFSD trace
124  */
125
126 void afsd_ForceTrace(BOOL flush)
127 {
128         HANDLE handle;
129         int len;
130         char buf[100];
131
132         if (!logReady) return;
133
134         len = GetTempPath(99, buf);
135         strcpy(&buf[len], "/afsd.log");
136         handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ,
137                             NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
138         if (handle == INVALID_HANDLE_VALUE) {
139                 logReady = 0;
140                 osi_panic("Cannot create log file", __FILE__, __LINE__);
141         }
142         osi_LogPrint(afsd_logp, handle);
143         if (flush)
144                 FlushFileBuffers(handle);
145         CloseHandle(handle);
146 }
147
148 /*
149  * AFSD Initialization
150  */
151
152 int afsd_InitCM(char **reasonP)
153 {
154         osi_uid_t debugID;
155         long cacheBlocks;
156         long cacheSize;
157         long logChunkSize;
158         long stats;
159         long traceBufSize;
160         long ltt, ltto;
161         char rootCellName[256];
162         struct rx_service *serverp;
163         static struct rx_securityClass *nullServerSecurityClassp;
164         struct hostent *thp;
165         char *msgBuf;
166         char buf[200];
167         HKEY parmKey;
168         DWORD dummyLen;
169         long code;
170         WSADATA WSAjunk;
171
172         WSAStartup(0x0101, &WSAjunk);
173
174         /* setup osidebug server at RPC slot 1000 */
175         osi_LongToUID(1000, &debugID);
176         code = osi_InitDebug(&debugID);
177         afsi_log("osi_InitDebug code %d", code);
178 //      osi_LockTypeSetDefault("stat"); /* comment this out for speed *
179         if (code != 0) {
180                 *reasonP = "unknown error";
181                 return -1;
182         }
183
184         /* who are we ? */
185         gethostname(cm_HostName, sizeof(cm_HostName));
186         afsi_log("gethostname %s", cm_HostName);
187         thp = gethostbyname(cm_HostName);
188         memcpy(&cm_HostAddr, thp->h_addr_list[0], 4);
189
190         /* seed random number generator */
191         srand(ntohl(cm_HostAddr));
192
193         /* Look up configuration parameters in Registry */
194
195         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
196                                 0, KEY_QUERY_VALUE, &parmKey);
197         if (code != ERROR_SUCCESS) {
198                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
199                                 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
200                               NULL, code, 0, (LPTSTR)&msgBuf, 0, NULL);
201                 sprintf(buf,
202                         "Failure in configuration while opening Registry: %s",
203                         msgBuf);
204                 osi_panic(buf, __FILE__, __LINE__);
205         }
206
207         dummyLen = sizeof(LANadapter);
208         code = RegQueryValueEx(parmKey, "LANadapter", NULL, NULL,
209                                 (BYTE *) &LANadapter, &dummyLen);
210         if (code == ERROR_SUCCESS)
211                 afsi_log("LAN adapter number %d", LANadapter);
212         else {
213                 LANadapter = -1;
214                 afsi_log("Default LAN adapter number");
215         }
216
217         dummyLen = sizeof(cacheSize);
218         code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
219                                 (BYTE *) &cacheSize, &dummyLen);
220         if (code == ERROR_SUCCESS)
221                 afsi_log("Cache size %d", cacheSize);
222         else {
223                 cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
224                 afsi_log("Default cache size %d", cacheSize);
225         }
226
227         dummyLen = sizeof(logChunkSize);
228         code = RegQueryValueEx(parmKey, "ChunkSize", NULL, NULL,
229                                 (BYTE *) &logChunkSize, &dummyLen);
230         if (code == ERROR_SUCCESS) {
231                 if (logChunkSize < 12 || logChunkSize > 30) {
232                         afsi_log("Invalid chunk size %d, using default",
233                                  logChunkSize);
234                         logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
235                 }
236                 afsi_log("Chunk size %d", logChunkSize);
237         } else {
238                 logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
239                 afsi_log("Default chunk size %d", logChunkSize);
240         }
241         cm_logChunkSize = logChunkSize;
242         cm_chunkSize = 1 << logChunkSize;
243
244         dummyLen = sizeof(numBkgD);
245         code = RegQueryValueEx(parmKey, "Daemons", NULL, NULL,
246                                 (BYTE *) &numBkgD, &dummyLen);
247         if (code == ERROR_SUCCESS)
248                 afsi_log("%d background daemons", numBkgD);
249         else {
250                 numBkgD = CM_CONFIGDEFAULT_DAEMONS;
251                 afsi_log("Defaulting to %d background daemons", numBkgD);
252         }
253
254         dummyLen = sizeof(numSvThreads);
255         code = RegQueryValueEx(parmKey, "ServerThreads", NULL, NULL,
256                                 (BYTE *) &numSvThreads, &dummyLen);
257         if (code == ERROR_SUCCESS)
258                 afsi_log("%d server threads", numSvThreads);
259         else {
260                 numSvThreads = CM_CONFIGDEFAULT_SVTHREADS;
261                 afsi_log("Defaulting to %d server threads", numSvThreads);
262         }
263
264         dummyLen = sizeof(stats);
265         code = RegQueryValueEx(parmKey, "Stats", NULL, NULL,
266                                 (BYTE *) &stats, &dummyLen);
267         if (code == ERROR_SUCCESS)
268                 afsi_log("Status cache size %d", stats);
269         else {
270                 stats = CM_CONFIGDEFAULT_STATS;
271                 afsi_log("Default status cache size %d", stats);
272         }
273
274         dummyLen = sizeof(ltt);
275         code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
276                                 (BYTE *) &ltt, &dummyLen);
277         if (code == ERROR_SUCCESS)
278                 afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
279         else {
280                 ltt = 1;
281                 afsi_log("Logoff token transfer on by default");
282         }
283         smb_LogoffTokenTransfer = ltt;
284
285         if (ltt) {
286                 dummyLen = sizeof(ltto);
287                 code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
288                                         NULL, NULL, (BYTE *) &ltto, &dummyLen);
289                 if (code == ERROR_SUCCESS)
290                         afsi_log("Logoff token tranfer timeout %d seconds",
291                                  ltto);
292                 else {
293                         ltto = 10;
294                         afsi_log("Default logoff token transfer timeout 10 seconds");
295                 }
296         }
297         smb_LogoffTransferTimeout = ltto;
298
299         dummyLen = sizeof(cm_rootVolumeName);
300         code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
301                                 cm_rootVolumeName, &dummyLen);
302         if (code == ERROR_SUCCESS)
303                 afsi_log("Root volume %s", cm_rootVolumeName);
304         else {
305                 strcpy(cm_rootVolumeName, "root.afs");
306                 afsi_log("Default root volume name root.afs");
307         }
308
309         cm_mountRootLen = sizeof(cm_mountRoot);
310         code = RegQueryValueEx(parmKey, "Mountroot", NULL, NULL,
311                                 cm_mountRoot, &cm_mountRootLen);
312         if (code == ERROR_SUCCESS)
313                 afsi_log("Mount root %s", cm_mountRoot);
314         else {
315                 strcpy(cm_mountRoot, "/afs");
316                 cm_mountRootLen = 4;
317                 /* Don't log */
318         }
319
320         dummyLen = sizeof(cm_CachePath);
321         code = RegQueryValueEx(parmKey, "CachePath", NULL, NULL,
322                                 cm_CachePath, &dummyLen);
323         if (code == ERROR_SUCCESS)
324                 afsi_log("Cache path %s", cm_CachePath);
325         else {
326                 GetWindowsDirectory(cm_CachePath, sizeof(cm_CachePath));
327                 cm_CachePath[2] = 0;    /* get drive letter only */
328                 strcat(cm_CachePath, "\\AFSCache");
329                 afsi_log("Default cache path %s", cm_CachePath);
330         }
331
332         dummyLen = sizeof(traceOnPanic);
333         code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
334                                 (BYTE *) &traceOnPanic, &dummyLen);
335         if (code == ERROR_SUCCESS)
336                 afsi_log("Set to %s on panic",
337                          traceOnPanic ? "trap" : "not trap");
338         else {
339                 traceOnPanic = 0;
340                 /* Don't log */
341         }
342
343         dummyLen = sizeof(isGateway);
344         code = RegQueryValueEx(parmKey, "IsGateway", NULL, NULL,
345                                 (BYTE *) &isGateway, &dummyLen);
346         if (code == ERROR_SUCCESS)
347                 afsi_log("Set for %s service",
348                          isGateway ? "gateway" : "stand-alone");
349         else {
350                 isGateway = 0;
351                 /* Don't log */
352         }
353
354         dummyLen = sizeof(reportSessionStartups);
355         code = RegQueryValueEx(parmKey, "ReportSessionStartups", NULL, NULL,
356                                 (BYTE *) &reportSessionStartups, &dummyLen);
357         if (code == ERROR_SUCCESS)
358                 afsi_log("Session startups %s be recorded in the Event Log",
359                          reportSessionStartups ? "will" : "will not");
360         else {
361                 reportSessionStartups = 0;
362                 /* Don't log */
363         }
364
365         dummyLen = sizeof(traceBufSize);
366         code = RegQueryValueEx(parmKey, "TraceBufferSize", NULL, NULL,
367                                 (BYTE *) &traceBufSize, &dummyLen);
368         if (code == ERROR_SUCCESS)
369                 afsi_log("Trace Buffer size %d", traceBufSize);
370         else {
371                 traceBufSize = CM_CONFIGDEFAULT_TRACEBUFSIZE;
372                 afsi_log("Default trace buffer size %d", traceBufSize);
373         }
374
375         dummyLen = sizeof(cm_sysName);
376         code = RegQueryValueEx(parmKey, "SysName", NULL, NULL,
377                                 cm_sysName, &dummyLen);
378         if (code == ERROR_SUCCESS)
379                 afsi_log("Sys name %s", cm_sysName);
380         else {
381                 strcat(cm_sysName, "i386_nt40");
382                 afsi_log("Default sys name %s", cm_sysName);
383         }
384
385         dummyLen = sizeof(cryptall);
386         code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
387                                 (BYTE *) &cryptall, &dummyLen);
388         if (code == ERROR_SUCCESS)
389                 afsi_log("SecurityLevel is %s", cryptall?"crypt":"clear");
390         else {
391                 cryptall = rxkad_clear;
392                 afsi_log("Default SecurityLevel is clear");
393         }
394
395         RegCloseKey (parmKey);
396
397         /* setup early variables */
398         /* These both used to be configurable. */
399         smb_UseV3 = 1;
400         buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
401
402         /* turn from 1024 byte units into memory blocks */
403         cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
404         
405         /* setup and enable debug log */
406         afsd_logp = osi_LogCreate("afsd", traceBufSize);
407         afsi_log("osi_LogCreate log addr %x", afsd_logp);
408         osi_LogEnable(afsd_logp);
409         logReady = 1;
410
411         /* get network related info */
412         cm_noIPAddr = CM_MAXINTERFACE_ADDR;
413         code = syscfg_GetIFInfo(&cm_noIPAddr,
414                                 cm_IPAddr, cm_SubnetMask,
415                                 cm_NetMtu, cm_NetFlags);
416
417         if ( (cm_noIPAddr <= 0) || (code <= 0 ) )
418             afsi_log("syscfg_GetIFInfo error code %d", code);
419         else
420             afsi_log("First Network address %x SubnetMask %x",
421                      cm_IPAddr[0], cm_SubnetMask[0]);
422
423         /*
424          * Save client configuration for GetCacheConfig requests
425          */
426         cm_initParams.nChunkFiles = 0;
427         cm_initParams.nStatCaches = stats;
428         cm_initParams.nDataCaches = 0;
429         cm_initParams.nVolumeCaches = 0;
430         cm_initParams.firstChunkSize = cm_chunkSize;
431         cm_initParams.otherChunkSize = cm_chunkSize;
432         cm_initParams.cacheSize = cacheSize;
433         cm_initParams.setTime = 0;
434         cm_initParams.memCache = 0;
435
436         /* initialize RX, and tell it to listen to port 7001, which is used for
437          * callback RPC messages.
438          */
439         code = rx_Init(htons(7001));
440         afsi_log("rx_Init code %x", code);
441         if (code != 0) {
442                 *reasonP = "afsd: failed to init rx client on port 7001";
443                 return -1;
444         }
445
446         /* Initialize the RPC server for session keys */
447         RpcInit();
448
449         /* create an unauthenticated service #1 for callbacks */
450         nullServerSecurityClassp = rxnull_NewServerSecurityObject();
451         serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
452                 RXAFSCB_ExecuteRequest);
453         afsi_log("rx_NewService addr %x", serverp);
454         if (serverp == NULL) {
455                 *reasonP = "unknown error";
456                 return -1;
457         }
458
459         nullServerSecurityClassp = rxnull_NewServerSecurityObject();
460         serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
461                 &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
462         afsi_log("rx_NewService addr %x", serverp);
463         if (serverp == NULL) {
464                 *reasonP = "unknown error";
465                 return -1;
466         }
467         
468         /* start server threads, *not* donating this one to the pool */
469         rx_StartServer(0);
470         afsi_log("rx_StartServer");
471
472         /* init user daemon, and other packages */
473         cm_InitUser();
474
475         cm_InitACLCache(2*stats);
476
477         cm_InitConn();
478
479         cm_InitCell();
480         
481         cm_InitServer();
482         
483         cm_InitVolume();
484         
485         cm_InitIoctl();
486         
487         smb_InitIoctl();
488         
489         cm_InitCallback();
490         
491         cm_InitSCache(stats);
492         
493         code = cm_InitDCache(0, cacheBlocks);
494         afsi_log("cm_InitDCache code %x", code);
495         if (code != 0) {
496                 *reasonP = "error initializing cache";
497                 return -1;
498         }
499
500         code = cm_GetRootCellName(rootCellName);
501         afsi_log("cm_GetRootCellName code %d rcn %s", code,
502                  (code ? "<none>" : rootCellName));
503         if (code != 0) {
504                 *reasonP = "can't find root cell name in afsd.ini";
505                 return -1;
506         }
507
508         cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
509         afsi_log("cm_GetCell addr %x", cm_rootCellp);
510         if (cm_rootCellp == NULL) {
511                 *reasonP = "can't find root cell in afsdcell.ini";
512                 return -1;
513         }
514
515         return 0;
516 }
517
518 int afsd_InitDaemons(char **reasonP)
519 {
520         long code;
521         cm_req_t req;
522
523         cm_InitReq(&req);
524
525         /* this should really be in an init daemon from here on down */
526
527         code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,                &req, CM_FLAG_CREATE, &cm_rootVolumep);
528         afsi_log("cm_GetVolumeByName code %x root vol %x", code,
529                  (code ? 0xffffffff : cm_rootVolumep));
530         if (code != 0) {
531                 *reasonP = "can't find root volume in root cell";
532                 return -1;
533         }
534
535         /* compute the root fid */
536         cm_rootFid.cell = cm_rootCellp->cellID;
537         cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
538         cm_rootFid.vnode = 1;
539         cm_rootFid.unique = 1;
540         
541         code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
542         afsi_log("cm_GetSCache code %x scache %x", code,
543                  (code ? 0xffffffff : cm_rootSCachep));
544         if (code != 0) {
545                 *reasonP = "unknown error";
546                 return -1;
547         }
548
549         cm_InitDaemon(numBkgD);
550         afsi_log("cm_InitDaemon");
551
552         return 0;
553 }
554
555 int afsd_InitSMB(char **reasonP, void *aMBfunc)
556 {
557         char hostName[200];
558         char *ctemp;
559
560         /* Do this last so that we don't handle requests before init is done.
561          * Here we initialize the SMB listener.
562          */
563         strcpy(hostName, cm_HostName);
564         ctemp = strchr(hostName, '.');  /* turn ntdfs.* into ntdfs */
565         if (ctemp) *ctemp = 0;
566         hostName[11] = 0;       /* ensure that even after adding the -A, we
567                                  * leave one byte free for the netbios server
568                                  * type.
569                                  */
570         strcat(hostName, "-AFS");
571         _strupr(hostName);
572         smb_Init(afsd_logp, hostName, smb_UseV3, LANadapter, numSvThreads,
573                  aMBfunc);
574         afsi_log("smb_Init");
575
576         return 0;
577 }