afsi_log-buffer-20040301
[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 #include "lanahelper.h"
31
32 extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
33 extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
34
35 extern afs_int32 cryptall;
36
37 char AFSConfigKeyName[] =
38         "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
39
40 osi_log_t *afsd_logp;
41
42 char cm_rootVolumeName[64];
43 DWORD cm_rootVolumeNameLen;
44 cm_volume_t *cm_rootVolumep = NULL;
45 cm_cell_t *cm_rootCellp = NULL;
46 cm_fid_t cm_rootFid;
47 cm_scache_t *cm_rootSCachep;
48 char cm_mountRoot[1024];
49 DWORD cm_mountRootLen;
50 int cm_logChunkSize;
51 int cm_chunkSize;
52 #ifdef AFS_FREELANCE_CLIENT
53 char *cm_FakeRootDir;
54 #endif /* freelance */
55
56 int smb_UseV3;
57
58 int LANadapter;
59
60 int numBkgD;
61 int numSvThreads;
62
63 int traceOnPanic = 0;
64
65 int logReady = 0;
66
67 char cm_HostName[200];
68 long cm_HostAddr;
69
70 char cm_CachePath[200];
71 DWORD cm_CachePathLen;
72
73 BOOL isGateway = FALSE;
74
75 BOOL reportSessionStartups = FALSE;
76
77 cm_initparams_v1 cm_initParams;
78
79 /*
80  * AFSD Initialization Log
81  *
82  * This is distinct from the regular debug logging facility.
83  * Log items go directly to a file, not to an array in memory, so that even
84  * if AFSD crashes, the log can be inspected.
85  */
86
87 HANDLE afsi_file;
88
89 #ifdef AFS_AFSDB_ENV
90 int cm_dnsEnabled = 1;
91 #endif
92
93 char cm_NetBiosName[32];
94
95 void
96 afsi_start()
97 {
98         char wd[100];
99         char t[100], u[100];
100         int zilch;
101         int code;
102
103         afsi_file = INVALID_HANDLE_VALUE;
104     if (getenv("TEMP"))
105     {
106         strcpy(wd, getenv("TEMP"));
107     }
108     else
109     {
110         code = GetWindowsDirectory(wd, sizeof(wd));
111         if (code == 0) return;
112     }
113         strcat(wd, "\\afsd_init.log");
114         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
115         afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
116                            OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
117     SetFilePointer(afsi_file, 0, NULL, FILE_END);
118         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));
119         strcat(t, ": Create log file\n");
120         strcat(u, ": Created log file\n");
121         WriteFile(afsi_file, t, strlen(t), &zilch, NULL);
122         WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
123 }
124
125 static int afsi_log_useTimestamp = 1;
126
127 void
128 afsi_log(char *pattern, ...)
129 {
130         char s[100], t[100], d[100], u[300];
131         int zilch;
132         va_list ap;
133         va_start(ap, pattern);
134
135         vsprintf(s, pattern, ap);
136     if ( afsi_log_useTimestamp ) {
137         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
138                 GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, d, sizeof(d));
139                 sprintf(u, "%s %s: %s\n", d, t, s);
140         if (afsi_file != INVALID_HANDLE_VALUE)
141             WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
142 #ifdef NOTSERVICE
143         printf("%s", u);
144 #endif 
145     } else {
146         if (afsi_file != INVALID_HANDLE_VALUE)
147             WriteFile(afsi_file, s, strlen(s), &zilch, NULL);
148     }
149 }
150
151 /*
152  * Standard AFSD trace
153  */
154
155 void afsd_ForceTrace(BOOL flush)
156 {
157         HANDLE handle;
158         int len;
159         char buf[100];
160
161         if (!logReady) return;
162
163         len = GetTempPath(99, buf);
164         strcpy(&buf[len], "/afsd.log");
165         handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ,
166                             NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
167         if (handle == INVALID_HANDLE_VALUE) {
168                 logReady = 0;
169                 osi_panic("Cannot create log file", __FILE__, __LINE__);
170         }
171         osi_LogPrint(afsd_logp, handle);
172         if (flush)
173                 FlushFileBuffers(handle);
174         CloseHandle(handle);
175 }
176
177 /*
178  * AFSD Initialization
179  */
180
181 int afsd_InitCM(char **reasonP)
182 {
183         osi_uid_t debugID;
184         long cacheBlocks;
185         long cacheSize;
186         long logChunkSize;
187         long stats;
188         long traceBufSize;
189         long ltt, ltto;
190     long rx_mtu, rx_nojumbo;
191         char rootCellName[256];
192         struct rx_service *serverp;
193         static struct rx_securityClass *nullServerSecurityClassp;
194         struct hostent *thp;
195         char *msgBuf;
196         char buf[200];
197         HKEY parmKey;
198         DWORD dummyLen;
199         long code;
200         /*int freelanceEnabled;*/
201         WSADATA WSAjunk;
202
203         WSAStartup(0x0101, &WSAjunk);
204
205         /* setup osidebug server at RPC slot 1000 */
206         osi_LongToUID(1000, &debugID);
207         code = osi_InitDebug(&debugID);
208         afsi_log("osi_InitDebug code %d", code);
209 //      osi_LockTypeSetDefault("stat"); /* comment this out for speed *
210         if (code != 0) {
211                 *reasonP = "unknown error";
212                 return -1;
213         }
214
215         /* who are we ? */
216         gethostname(cm_HostName, sizeof(cm_HostName));
217         afsi_log("gethostname %s", cm_HostName);
218         thp = gethostbyname(cm_HostName);
219         memcpy(&cm_HostAddr, thp->h_addr_list[0], 4);
220
221         /* seed random number generator */
222         srand(ntohl(cm_HostAddr));
223
224         /* Look up configuration parameters in Registry */
225         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
226                                 0, KEY_QUERY_VALUE, &parmKey);
227         if (code != ERROR_SUCCESS) {
228                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
229                                 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
230                               NULL, code, 0, (LPTSTR)&msgBuf, 0, NULL);
231                 sprintf(buf,
232                         "Failure in configuration while opening Registry: %s",
233                         msgBuf);
234                 osi_panic(buf, __FILE__, __LINE__);
235         }
236
237         dummyLen = sizeof(LANadapter);
238         code = RegQueryValueEx(parmKey, "LANadapter", NULL, NULL,
239                                 (BYTE *) &LANadapter, &dummyLen);
240         if (code == ERROR_SUCCESS) {
241                 afsi_log("LAN adapter number %d", LANadapter);
242         if (LANadapter < 0 || LANadapter > MAX_LANA)
243             LANadapter = -1;
244         } else {
245                 LANadapter = -1;
246     }
247     if ( LANadapter == -1 )
248                 afsi_log("Default LAN adapter number");
249
250         dummyLen = sizeof(cacheSize);
251         code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
252                                 (BYTE *) &cacheSize, &dummyLen);
253         if (code == ERROR_SUCCESS)
254                 afsi_log("Cache size %d", cacheSize);
255         else {
256                 cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
257                 afsi_log("Default cache size %d", cacheSize);
258         }
259
260         dummyLen = sizeof(logChunkSize);
261         code = RegQueryValueEx(parmKey, "ChunkSize", NULL, NULL,
262                                 (BYTE *) &logChunkSize, &dummyLen);
263         if (code == ERROR_SUCCESS) {
264                 if (logChunkSize < 12 || logChunkSize > 30) {
265                         afsi_log("Invalid chunk size %d, using default",
266                                  logChunkSize);
267                         logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
268                 }
269                 afsi_log("Chunk size %d", logChunkSize);
270         } else {
271                 logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
272                 afsi_log("Default chunk size %d", logChunkSize);
273         }
274         cm_logChunkSize = logChunkSize;
275         cm_chunkSize = 1 << logChunkSize;
276
277         dummyLen = sizeof(numBkgD);
278         code = RegQueryValueEx(parmKey, "Daemons", NULL, NULL,
279                                 (BYTE *) &numBkgD, &dummyLen);
280         if (code == ERROR_SUCCESS)
281                 afsi_log("%d background daemons", numBkgD);
282         else {
283                 numBkgD = CM_CONFIGDEFAULT_DAEMONS;
284                 afsi_log("Defaulting to %d background daemons", numBkgD);
285         }
286
287         dummyLen = sizeof(numSvThreads);
288         code = RegQueryValueEx(parmKey, "ServerThreads", NULL, NULL,
289                                 (BYTE *) &numSvThreads, &dummyLen);
290         if (code == ERROR_SUCCESS)
291                 afsi_log("%d server threads", numSvThreads);
292         else {
293                 numSvThreads = CM_CONFIGDEFAULT_SVTHREADS;
294                 afsi_log("Defaulting to %d server threads", numSvThreads);
295         }
296
297         dummyLen = sizeof(stats);
298         code = RegQueryValueEx(parmKey, "Stats", NULL, NULL,
299                                 (BYTE *) &stats, &dummyLen);
300         if (code == ERROR_SUCCESS)
301                 afsi_log("Status cache size %d", stats);
302         else {
303                 stats = CM_CONFIGDEFAULT_STATS;
304                 afsi_log("Default status cache size %d", stats);
305         }
306
307         dummyLen = sizeof(ltt);
308         code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
309                                 (BYTE *) &ltt, &dummyLen);
310         if (code == ERROR_SUCCESS)
311                 afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
312         else {
313                 ltt = 1;
314                 afsi_log("Logoff token transfer on by default");
315         }
316         smb_LogoffTokenTransfer = ltt;
317
318         if (ltt) {
319                 dummyLen = sizeof(ltto);
320                 code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
321                                         NULL, NULL, (BYTE *) &ltto, &dummyLen);
322                 if (code == ERROR_SUCCESS)
323                         afsi_log("Logoff token tranfer timeout %d seconds",
324                                  ltto);
325                 else {
326                         ltto = 10;
327                         afsi_log("Default logoff token transfer timeout 10 seconds");
328                 }
329         }
330         smb_LogoffTransferTimeout = ltto;
331
332         dummyLen = sizeof(cm_rootVolumeName);
333         code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
334                                 cm_rootVolumeName, &dummyLen);
335         if (code == ERROR_SUCCESS)
336                 afsi_log("Root volume %s", cm_rootVolumeName);
337         else {
338                 strcpy(cm_rootVolumeName, "root.afs");
339                 afsi_log("Default root volume name root.afs");
340         }
341
342         cm_mountRootLen = sizeof(cm_mountRoot);
343         code = RegQueryValueEx(parmKey, "Mountroot", NULL, NULL,
344                                 cm_mountRoot, &cm_mountRootLen);
345         if (code == ERROR_SUCCESS) {
346                 afsi_log("Mount root %s", cm_mountRoot);
347                 cm_mountRootLen = strlen(cm_mountRoot);
348         } else {
349                 strcpy(cm_mountRoot, "/afs");
350                 cm_mountRootLen = 4;
351                 /* Don't log */
352         }
353
354         dummyLen = sizeof(cm_CachePath);
355         code = RegQueryValueEx(parmKey, "CachePath", NULL, NULL,
356                                 cm_CachePath, &dummyLen);
357         if (code == ERROR_SUCCESS)
358                 afsi_log("Cache path %s", cm_CachePath);
359         else {
360                 GetWindowsDirectory(cm_CachePath, sizeof(cm_CachePath));
361                 cm_CachePath[2] = 0;    /* get drive letter only */
362                 strcat(cm_CachePath, "\\AFSCache");
363                 afsi_log("Default cache path %s", cm_CachePath);
364         }
365
366         dummyLen = sizeof(traceOnPanic);
367         code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
368                                 (BYTE *) &traceOnPanic, &dummyLen);
369         if (code == ERROR_SUCCESS)
370                 afsi_log("Set to %s on panic",
371                          traceOnPanic ? "trap" : "not trap");
372         else {
373                 traceOnPanic = 0;
374                 /* Don't log */
375         }
376
377         dummyLen = sizeof(isGateway);
378         code = RegQueryValueEx(parmKey, "IsGateway", NULL, NULL,
379                                 (BYTE *) &isGateway, &dummyLen);
380         if (code == ERROR_SUCCESS)
381                 afsi_log("Set for %s service",
382                          isGateway ? "gateway" : "stand-alone");
383         else {
384                 isGateway = 0;
385                 /* Don't log */
386         }
387
388         dummyLen = sizeof(reportSessionStartups);
389         code = RegQueryValueEx(parmKey, "ReportSessionStartups", NULL, NULL,
390                                 (BYTE *) &reportSessionStartups, &dummyLen);
391         if (code == ERROR_SUCCESS)
392                 afsi_log("Session startups %s be recorded in the Event Log",
393                          reportSessionStartups ? "will" : "will not");
394         else {
395                 reportSessionStartups = 0;
396                 /* Don't log */
397         }
398
399         dummyLen = sizeof(traceBufSize);
400         code = RegQueryValueEx(parmKey, "TraceBufferSize", NULL, NULL,
401                                 (BYTE *) &traceBufSize, &dummyLen);
402         if (code == ERROR_SUCCESS)
403                 afsi_log("Trace Buffer size %d", traceBufSize);
404         else {
405                 traceBufSize = CM_CONFIGDEFAULT_TRACEBUFSIZE;
406                 afsi_log("Default trace buffer size %d", traceBufSize);
407         }
408
409         dummyLen = sizeof(cm_sysName);
410         code = RegQueryValueEx(parmKey, "SysName", NULL, NULL,
411                                 cm_sysName, &dummyLen);
412         if (code == ERROR_SUCCESS)
413                 afsi_log("Sys name %s", cm_sysName);
414         else {
415                 strcat(cm_sysName, "i386_nt40");
416                 afsi_log("Default sys name %s", cm_sysName);
417         }
418
419         dummyLen = sizeof(cryptall);
420         code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
421                                 (BYTE *) &cryptall, &dummyLen);
422         if (code == ERROR_SUCCESS)
423                 afsi_log("SecurityLevel is %s", cryptall?"crypt":"clear");
424         else {
425                 cryptall = rxkad_clear;
426                 afsi_log("Default SecurityLevel is clear");
427         }
428
429 #ifdef AFS_AFSDB_ENV
430         dummyLen = sizeof(cm_dnsEnabled);
431         code = RegQueryValueEx(parmKey, "UseDNS", NULL, NULL,
432                                 (BYTE *) &cm_dnsEnabled, &dummyLen);
433         if (code == ERROR_SUCCESS) {
434                 afsi_log("DNS %s be used to find AFS cell servers",
435                          cm_dnsEnabled ? "will" : "will not");
436         }
437         else {
438           cm_dnsEnabled = 1;   /* default on */
439           afsi_log("Default to use DNS to find AFS cell servers");
440         }
441 #else /* AFS_AFSDB_ENV */
442         afsi_log("AFS not built with DNS support to find AFS cell servers");
443 #endif /* AFS_AFSDB_ENV */
444
445 #ifdef AFS_FREELANCE_CLIENT
446         dummyLen = sizeof(cm_freelanceEnabled);
447         code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
448                                 (BYTE *) &cm_freelanceEnabled, &dummyLen);
449         if (code == ERROR_SUCCESS) {
450                 afsi_log("Freelance client feature %s activated",
451                          cm_freelanceEnabled ? "is" : "is not");
452         }
453         else {
454           cm_freelanceEnabled = 0;  /* default off */
455         }
456 #endif /* AFS_FREELANCE_CLIENT */
457
458     dummyLen = sizeof(cm_NetBiosName);
459     code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
460                            (BYTE *) &cm_NetBiosName, &dummyLen);
461     if (code == ERROR_SUCCESS) {
462         afsi_log("Explicit NetBios name is used %s", cm_NetBiosName);
463     }
464     else {
465         cm_NetBiosName[0] = 0;   /* default off */
466     }
467
468     dummyLen = sizeof(smb_hideDotFiles);
469     code = RegQueryValueEx(parmKey, "HideDotFiles", NULL, NULL,
470                            (BYTE *) &smb_hideDotFiles, &dummyLen);
471     if (code != ERROR_SUCCESS) {
472         smb_hideDotFiles = 1; /* default on */
473     }
474     afsi_log("Dot files/dirs will %sbe marked hidden",
475               smb_hideDotFiles ? "" : "not ");
476
477     dummyLen = sizeof(smb_maxMpxRequests);
478     code = RegQueryValueEx(parmKey, "MaxMpxRequests", NULL, NULL,
479                            (BYTE *) &smb_maxMpxRequests, &dummyLen);
480     if (code != ERROR_SUCCESS) {
481         smb_maxMpxRequests = 50;
482     }
483     afsi_log("Maximum number of multiplexed sessions is %d", smb_maxMpxRequests);
484
485     dummyLen = sizeof(smb_maxVCPerServer);
486     code = RegQueryValueEx(parmKey, "MaxVCPerServer", NULL, NULL,
487                            (BYTE *) &smb_maxVCPerServer, &dummyLen);
488     if (code != ERROR_SUCCESS) {
489         smb_maxVCPerServer = 100;
490     }
491     afsi_log("Maximum number of VCs per server is %d", smb_maxVCPerServer);
492
493     dummyLen = sizeof(rx_nojumbo);
494     code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
495                            (BYTE *) &rx_nojumbo, &dummyLen);
496     if (code != ERROR_SUCCESS) {
497         rx_nojumbo = 0;
498     }
499     if(rx_nojumbo)
500         afsi_log("RX Jumbograms are disabled");
501
502     dummyLen = sizeof(rx_mtu);
503     code = RegQueryValueEx(parmKey, "RxMaxMTU", NULL, NULL,
504                            (BYTE *) &rx_mtu, &dummyLen);
505     if (code != ERROR_SUCCESS || !rx_mtu) {
506         rx_mtu = -1;
507     }
508     if(rx_mtu != -1)
509         afsi_log("RX maximum MTU is %d", rx_mtu);
510
511         RegCloseKey (parmKey);
512
513         /* setup early variables */
514         /* These both used to be configurable. */
515         smb_UseV3 = 1;
516     buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
517
518         /* turn from 1024 byte units into memory blocks */
519     cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
520         
521         /* setup and enable debug log */
522         afsd_logp = osi_LogCreate("afsd", traceBufSize);
523         afsi_log("osi_LogCreate log addr %x", (int)afsd_logp);
524     osi_LogEnable(afsd_logp);
525         logReady = 1;
526
527     osi_Log0(afsd_logp, "Log init");
528
529         /* get network related info */
530         cm_noIPAddr = CM_MAXINTERFACE_ADDR;
531         code = syscfg_GetIFInfo(&cm_noIPAddr,
532                             cm_IPAddr, cm_SubnetMask,
533                             cm_NetMtu, cm_NetFlags);
534
535         if ( (cm_noIPAddr <= 0) || (code <= 0 ) )
536             afsi_log("syscfg_GetIFInfo error code %d", code);
537         else
538             afsi_log("First Network address %x SubnetMask %x",
539                  cm_IPAddr[0], cm_SubnetMask[0]);
540
541         /*
542          * Save client configuration for GetCacheConfig requests
543          */
544         cm_initParams.nChunkFiles = 0;
545         cm_initParams.nStatCaches = stats;
546         cm_initParams.nDataCaches = 0;
547         cm_initParams.nVolumeCaches = 0;
548         cm_initParams.firstChunkSize = cm_chunkSize;
549         cm_initParams.otherChunkSize = cm_chunkSize;
550         cm_initParams.cacheSize = cacheSize;
551         cm_initParams.setTime = 0;
552         cm_initParams.memCache = 0;
553
554     /* Set RX parameters before initializing RX */
555     if ( rx_nojumbo )
556         rx_SetNoJumbo();
557
558     if ( rx_mtu != -1 )
559         rx_SetMaxMTU(rx_mtu);
560
561         /* initialize RX, and tell it to listen to port 7001, which is used for
562      * callback RPC messages.
563      */
564         code = rx_Init(htons(7001));
565         afsi_log("rx_Init code %x", code);
566         if (code != 0) {
567                 *reasonP = "afsd: failed to init rx client on port 7001";
568                 return -1;
569         }
570
571         /* Initialize the RPC server for session keys */
572         RpcInit();
573
574         /* create an unauthenticated service #1 for callbacks */
575         nullServerSecurityClassp = rxnull_NewServerSecurityObject();
576     serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
577                             RXAFSCB_ExecuteRequest);
578         afsi_log("rx_NewService addr %x", (int)serverp);
579         if (serverp == NULL) {
580                 *reasonP = "unknown error";
581                 return -1;
582         }
583
584         nullServerSecurityClassp = rxnull_NewServerSecurityObject();
585     serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
586                             &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
587         afsi_log("rx_NewService addr %x", (int)serverp);
588         if (serverp == NULL) {
589                 *reasonP = "unknown error";
590                 return -1;
591         }
592         
593     /* start server threads, *not* donating this one to the pool */
594     rx_StartServer(0);
595         afsi_log("rx_StartServer");
596
597         /* init user daemon, and other packages */
598         cm_InitUser();
599
600         cm_InitACLCache(2*stats);
601
602         cm_InitConn();
603
604     cm_InitCell();
605         
606     cm_InitServer();
607         
608     cm_InitVolume();
609
610     cm_InitIoctl();
611         
612     smb_InitIoctl();
613         
614     cm_InitCallback();
615         
616     cm_InitSCache(stats);
617         
618     code = cm_InitDCache(0, cacheBlocks);
619         afsi_log("cm_InitDCache code %x", code);
620         if (code != 0) {
621                 *reasonP = "error initializing cache";
622                 return -1;
623         }
624
625 #ifdef AFS_AFSDB_ENV
626 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x500
627         if (cm_InitDNS(cm_dnsEnabled) == -1)
628           cm_dnsEnabled = 0;  /* init failed, so deactivate */
629         afsi_log("cm_InitDNS %d", cm_dnsEnabled);
630 #endif
631 #endif
632
633         code = cm_GetRootCellName(rootCellName);
634         afsi_log("cm_GetRootCellName code %d, cm_freelanceEnabled= %d, rcn= %s", 
635              code, cm_freelanceEnabled, (code ? "<none>" : rootCellName));
636         if (code != 0 && !cm_freelanceEnabled) 
637     {
638             *reasonP = "can't find root cell name in afsd.ini";
639             return -1;
640     }
641     else if (cm_freelanceEnabled)
642         cm_rootCellp = NULL;
643
644     if (code == 0 && !cm_freelanceEnabled) 
645     {
646         cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
647         afsi_log("cm_GetCell addr %x", (int)cm_rootCellp);
648         if (cm_rootCellp == NULL) 
649         {
650             *reasonP = "can't find root cell in afsdcell.ini";
651             return -1;
652         }
653         }
654
655 #ifdef AFS_FREELANCE_CLIENT
656         if (cm_freelanceEnabled)
657           cm_InitFreelance();
658 #endif
659
660         return 0;
661 }
662
663 int afsd_InitDaemons(char **reasonP)
664 {
665         long code;
666         cm_req_t req;
667
668         cm_InitReq(&req);
669
670         /* this should really be in an init daemon from here on down */
671
672     if (!cm_freelanceEnabled) {
673         code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
674                                   &req, CM_FLAG_CREATE, &cm_rootVolumep);
675         afsi_log("cm_GetVolumeByName code %x root vol %x", code,
676                  (code ? (cm_volume_t *)-1 : cm_rootVolumep));
677         if (code != 0) {
678             *reasonP = "can't find root volume in root cell";
679             return -1;
680         }
681     }
682
683         /* compute the root fid */
684         if (!cm_freelanceEnabled) {
685         cm_rootFid.cell = cm_rootCellp->cellID;
686         cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
687         cm_rootFid.vnode = 1;
688         cm_rootFid.unique = 1;
689         }
690         else
691         cm_FakeRootFid(&cm_rootFid);
692         
693     code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
694         afsi_log("cm_GetSCache code %x scache %x", code,
695              (code ? (cm_scache_t *)-1 : cm_rootSCachep));
696         if (code != 0) {
697                 *reasonP = "unknown error";
698                 return -1;
699         }
700
701         cm_InitDaemon(numBkgD);
702         afsi_log("cm_InitDaemon");
703
704         return 0;
705 }
706
707 int afsd_InitSMB(char **reasonP, void *aMBfunc)
708 {
709         char hostName[200];
710         char *ctemp;
711     lana_number_t lana = LANA_INVALID;
712
713         /* Do this last so that we don't handle requests before init is done.
714      * Here we initialize the SMB listener.
715      */
716     if (LANadapter == -1) {
717         DWORD noFindByName = 0;
718         HKEY parmKey;
719         DWORD dummyLen;
720         long code;
721
722         /* Find the default LAN adapter to use.  First look for
723          * the adapter named AFS; otherwise, unless we are doing
724          * gateway service, look for any valid loopback adapter.
725          */
726         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
727                              0, KEY_QUERY_VALUE, &parmKey);
728         if (code == ERROR_SUCCESS) {
729             dummyLen = sizeof(LANadapter);
730             code = RegQueryValueEx(parmKey, "NoFindLanaByName", NULL, NULL,
731                                     (BYTE *) &noFindByName, &dummyLen);
732             RegCloseKey(parmKey);
733         }
734
735         if ( !noFindByName )
736             lana = lana_FindLanaByName("AFS");
737         if (lana == LANA_INVALID && !isGateway)
738             lana = lana_FindLoopback();
739         if (lana != LANA_INVALID)
740             LANadapter = lana;
741     }
742     afsi_log("Lana %d", (int) lana);
743     /* If we are using a loopback adapter, we can use the preferred
744      * (but non-unique) server name; otherwise, we must fall back to
745      * the <machine>-AFS name.
746      */
747     if (LANadapter >= 0 && lana_IsLoopback((lana_number_t) LANadapter)) {
748         if ( cm_NetBiosName[0] )
749             strcpy(hostName, cm_NetBiosName);
750         else
751             strcpy(hostName, "AFS");
752     } else {
753         if (!cm_NetBiosName[0])
754         {
755             strcpy(hostName, cm_HostName);
756             ctemp = strchr(hostName, '.');      /* turn ntdfs.* into ntdfs */
757             if (ctemp) *ctemp = 0;
758             hostName[11] = 0; /* ensure that even after adding the -A, we
759                                * leave one byte free for the netbios server
760                                * type.
761                                */
762             strcat(hostName, "-AFS");
763         } else {
764             strcpy(hostName, cm_NetBiosName);
765         }
766         _strupr(hostName);
767     }
768     smb_Init(afsd_logp, hostName, smb_UseV3, LANadapter, numSvThreads, aMBfunc);
769         afsi_log("smb_Init");
770
771         return 0;
772 }
773
774 #ifdef ReadOnly
775 #undef ReadOnly
776 #endif
777
778 #ifdef File
779 #undef File
780 #endif
781
782 #pragma pack( push, before_imagehlp, 8 )
783 #include <imagehlp.h>
784 #pragma pack( pop, before_imagehlp )
785
786 #define MAXNAMELEN 1024
787
788 void afsd_printStack(HANDLE hThread, CONTEXT *c)
789 {
790     HANDLE hProcess = GetCurrentProcess();
791     int frameNum;
792     DWORD offset;
793     DWORD symOptions;
794     char functionName[MAXNAMELEN];
795   
796     IMAGEHLP_MODULE Module;
797     IMAGEHLP_LINE Line;
798   
799     STACKFRAME s;
800     IMAGEHLP_SYMBOL *pSym;
801   
802     afsi_log_useTimestamp = 0;
803   
804     pSym = (IMAGEHLP_SYMBOL *) GlobalAlloc(0, sizeof (IMAGEHLP_SYMBOL) + MAXNAMELEN);
805   
806     memset( &s, '\0', sizeof s );
807     if (!SymInitialize(hProcess, NULL, 1) )
808     {
809         afsi_log("SymInitialize(): GetLastError() = %lu\n", GetLastError() );
810       
811         SymCleanup( hProcess );
812         GlobalFree(pSym);
813       
814         return;
815     }
816   
817     symOptions = SymGetOptions();
818     symOptions |= SYMOPT_LOAD_LINES;
819     symOptions &= ~SYMOPT_UNDNAME;
820     SymSetOptions( symOptions );
821   
822     /*
823      * init STACKFRAME for first call
824      * Notes: AddrModeFlat is just an assumption. I hate VDM debugging.
825      * Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,
826      * and good riddance.
827      */
828 #if defined (_ALPHA_) || defined (_MIPS_) || defined (_PPC_)
829 #error The STACKFRAME initialization in afsd_printStack() for this platform
830 #error must be properly configured
831 #else
832     s.AddrPC.Offset = c->Eip;
833     s.AddrPC.Mode = AddrModeFlat;
834     s.AddrFrame.Offset = c->Ebp;
835     s.AddrFrame.Mode = AddrModeFlat;
836 #endif
837
838     memset( pSym, '\0', sizeof (IMAGEHLP_SYMBOL) + MAXNAMELEN );
839     pSym->SizeOfStruct = sizeof (IMAGEHLP_SYMBOL);
840     pSym->MaxNameLength = MAXNAMELEN;
841   
842     memset( &Line, '\0', sizeof Line );
843     Line.SizeOfStruct = sizeof Line;
844   
845     memset( &Module, '\0', sizeof Module );
846     Module.SizeOfStruct = sizeof Module;
847   
848     offset = 0;
849   
850     afsi_log("\n--# FV EIP----- RetAddr- FramePtr StackPtr Symbol" );
851   
852     for ( frameNum = 0; ; ++ frameNum )
853     {
854         /*
855          * get next stack frame (StackWalk(), SymFunctionTableAccess(), 
856          * SymGetModuleBase()). if this returns ERROR_INVALID_ADDRESS (487) or
857          * ERROR_NOACCESS (998), you can assume that either you are done, or
858          * that the stack is so hosed that the next deeper frame could not be
859          * found.
860          */
861         if ( ! StackWalk( IMAGE_FILE_MACHINE_I386, hProcess, hThread, &s, c, 
862                           NULL, SymFunctionTableAccess, SymGetModuleBase, 
863                           NULL ) )
864             break;
865       
866         /* display its contents */
867         afsi_log("\n%3d %c%c %08lx %08lx %08lx %08lx ",
868                  frameNum, s.Far? 'F': '.', s.Virtual? 'V': '.',
869                  s.AddrPC.Offset, s.AddrReturn.Offset,
870                  s.AddrFrame.Offset, s.AddrStack.Offset );
871       
872         if ( s.AddrPC.Offset == 0 )
873         {
874             afsi_log("(-nosymbols- PC == 0)" );
875         }
876         else
877         { 
878             /* show procedure info from a valid PC */
879             if (!SymGetSymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym))
880             {
881                 if ( GetLastError() != ERROR_INVALID_ADDRESS )
882                 {
883                     afsi_log("SymGetSymFromAddr(): errno = %lu", 
884                              GetLastError());
885                 }
886             }
887             else
888             {
889                 UnDecorateSymbolName(pSym->Name, functionName, MAXNAMELEN, 
890                                      UNDNAME_NAME_ONLY);
891                 afsi_log("%s", functionName );
892
893                 if ( offset != 0 )
894                 {
895                     afsi_log(" %+ld bytes", (long) offset);
896                 }
897             }
898
899             if (!SymGetLineFromAddr(hProcess, s.AddrPC.Offset, &offset, &Line))
900             {
901                 if (GetLastError() != ERROR_INVALID_ADDRESS)
902                 {
903                     afsi_log("Error: SymGetLineFromAddr(): errno = %lu", 
904                              GetLastError());
905                 }
906             }
907             else
908             {
909                 afsi_log("    Line: %s(%lu) %+ld bytes", Line.FileName, 
910                          Line.LineNumber, offset);
911             }
912         }
913       
914         /* no return address means no deeper stackframe */
915         if (s.AddrReturn.Offset == 0)
916         {
917             SetLastError(0);
918             break;
919         }
920     }
921   
922     if (GetLastError() != 0)
923     {
924         afsi_log("\nStackWalk(): errno = %lu\n", GetLastError());
925     }
926   
927     SymCleanup(hProcess);
928     GlobalFree(pSym);
929 }
930
931 #ifdef _DEBUG
932 static DWORD *afsd_crtDbgBreakCurrent = NULL;
933 static DWORD afsd_crtDbgBreaks[256];
934 #endif
935
936 LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
937 {
938     CONTEXT context;
939 #ifdef _DEBUG  
940     BOOL allocRequestBrk = FALSE;
941 #endif 
942   
943     afsi_log("UnhandledException : code : 0x%x, address: 0x%x\n", 
944              ep->ExceptionRecord->ExceptionCode, 
945              ep->ExceptionRecord->ExceptionAddress);
946            
947 #ifdef _DEBUG
948     if (afsd_crtDbgBreakCurrent && 
949         *afsd_crtDbgBreakCurrent == _CrtSetBreakAlloc(*afsd_crtDbgBreakCurrent))
950     { 
951         allocRequestBrk = TRUE;
952         afsi_log("Breaking on alloc request # %d\n", *afsd_crtDbgBreakCurrent);
953     }
954 #endif
955            
956     /* save context if we want to print the stack information */
957     context = *ep->ContextRecord;
958            
959     afsd_printStack(GetCurrentThread(), &context);
960            
961     if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
962     {
963         afsi_log("\nEXCEPTION_BREAKPOINT - continue execition ...\n");
964     
965 #ifdef _DEBUG
966         if (allocRequestBrk)
967         {
968             afsd_crtDbgBreakCurrent++;
969             _CrtSetBreakAlloc(*afsd_crtDbgBreakCurrent);
970         }
971 #endif         
972     
973         ep->ContextRecord->Eip++;
974         return EXCEPTION_CONTINUE_EXECUTION;
975     }
976     else
977     {
978         return EXCEPTION_CONTINUE_SEARCH;
979     }
980 }
981   
982 void afsd_SetUnhandledExceptionFilter()
983 {
984     SetUnhandledExceptionFilter(afsd_ExceptionFilter);
985 }
986   
987 #ifdef _DEBUG
988 void afsd_DbgBreakAllocInit()
989 {
990     memset(afsd_crtDbgBreaks, -1, sizeof(afsd_crtDbgBreaks));
991     afsd_crtDbgBreakCurrent = afsd_crtDbgBreaks;
992 }
993   
994 void afsd_DbgBreakAdd(DWORD requestNumber)
995 {
996     int i;
997     for (i = 0; i < sizeof(afsd_crtDbgBreaks) - 1; i++)
998         {
999         if (afsd_crtDbgBreaks[i] == -1)
1000             {
1001             break;
1002             }
1003         }
1004     afsd_crtDbgBreaks[i] = requestNumber;
1005
1006     _CrtSetBreakAlloc(afsd_crtDbgBreaks[0]);
1007 }
1008 #endif