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 <afs/param.h>
17 #include <sys/socket.h>
24 #include "cm_config.h"
26 #if !defined(DJGPP) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x500
32 #include <afs/afsint.h>
35 char AFSConfigKeyName[] =
36 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
38 /* TODO: these should be pulled in from dirpath.h */
39 #define AFS_THISCELL "ThisCell"
40 #define AFS_CELLSERVDB_UNIX "CellServDB"
41 #define AFS_CELLSERVDB_NT "afsdcell.ini"
42 #ifndef AFSDIR_CLIENT_ETC_DIRPATH
43 #define AFSDIR_CLIENT_ETC_DIRPATH "c:/afs"
45 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
46 #define AFS_CELLSERVDB AFS_CELLSERVDB_UNIX
48 extern char cm_confDir[];
52 #define AFS_CELLSERVDB AFS_CELLSERVDB_NT
53 #endif /* DJGPP || WIN95 */
57 #define TRACE_OPTION_EVENT 1
58 #define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
60 void DebugEvent0_local(char *a)
62 HANDLE h; char *ptbuf[1];
63 if (!ISLOGONTRACE(TraceOption))
65 h = RegisterEventSource(NULL, a);
67 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
68 DeregisterEventSource(h);
73 void DebugEvent_local(char *a,char *b,...)
75 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
77 if (!ISLOGONTRACE(TraceOption))
79 h = RegisterEventSource(NULL, a);
81 _vsnprintf(buf,MAXBUF_,b,marker);
83 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
84 DeregisterEventSource(h);
88 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
97 for(tp = lineBufferp; *tp; tp++) {
106 /* comment or line end */
107 if (tc == '#' || tc == '\r' || tc == '\n')
110 /* square bracket comment -- look for closing delim */
117 if (tc == ' ' || tc == '\t')
125 /* now we have a real character, put it in the appropriate bucket */
126 if (sawEquals == 0) {
134 /* null terminate the strings */
138 return 0; /* and return success */
141 /* search for a cell, and either return an error code if we don't find it,
142 * or return 0 if we do, in which case we also fill in the addresses in
145 * new feature: we can handle abbreviations and are insensitive to case.
146 * If the caller wants the "real" cell name, it puts a non-null pointer in
147 * newCellNamep. Anomaly: if cellNamep is ambiguous, we may modify
148 * newCellNamep but return an error code.
150 long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
151 cm_configProc_t *procp, void *rockp)
155 FILE *tfilep, *bestp, *tempp;
157 char lineBuffer[256];
160 struct sockaddr_in vlSockAddr;
164 int tracking = 1, partial = 0;
165 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
175 code = GetWindowsDirectory(wdir, sizeof(wdir));
176 if (code == 0 || code > sizeof(wdir))
179 /* add trailing backslash, if required */
181 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
183 strcpy(wdir, cm_confDir);
187 strcat(wdir, AFS_CELLSERVDB);
189 tfilep = fopen(wdir, "r");
191 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
193 /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
194 /* If we are in Win95 here, we are linking with klog etc. and are
195 using DJGPP client even though DJGPP is not defined. So we still
196 need to check AFSCONF for location. */
197 afsconf_path = getenv("AFSCONF");
199 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
201 strcpy(wdir, afsconf_path);
203 strcat(wdir, AFS_CELLSERVDB_UNIX);
204 /*fprintf(stderr, "opening cellservdb file %s\n", wdir);*/
205 tfilep = fopen(wdir, "r");
206 if (!tfilep) return -2;
209 /* If we are NT or higher, we don't do DJGPP, So just fail */
214 bestp = fopen(wdir, "r");
216 DebugEvent_local("AFS- cm_searchfile fopen", "Handle[%x], wdir[%s]", bestp, wdir);
218 /* have we seen the cell line for the guy we're looking for? */
221 tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
223 (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
229 * found partial match earlier;
242 return (foundCell? 0 : -3);
247 /* turn trailing cr or lf into null */
248 tp = strchr(lineBuffer, '\r');
250 tp = strchr(lineBuffer, '\n');
253 /* skip blank lines */
254 if (lineBuffer[0] == 0) continue;
256 if (lineBuffer[0] == '>') {
257 /* trim off at white space or '#' chars */
258 tp = strchr(lineBuffer, ' ');
260 tp = strchr(lineBuffer, '\t');
262 tp = strchr(lineBuffer, '#');
265 /* now see if this is the right cell */
266 if (stricmp(lineBuffer+1, cellNamep) == 0) {
267 /* found the cell we're looking for */
269 strcpy(newCellNamep, lineBuffer+1);
272 DebugEvent_local("AFS- cm_searchfile is cell", "inRightCell[%x], linebuffer[%s]",
273 inRightCell, lineBuffer);
275 else if (strnicmp(lineBuffer+1, cellNamep,
276 strlen(cellNamep)) == 0) {
278 if (partial) { /* ambiguous */
284 strcpy(newCellNamep, lineBuffer+1);
289 else inRightCell = 0;
292 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
293 valuep = strchr(lineBuffer, '#');
294 if (valuep == NULL) {
299 valuep++; /* skip the "#" */
301 valuep += strspn(valuep, " \t"); /* skip SP & TAB */
302 /* strip spaces and tabs in the end. They should not be there according to CellServDB format
303 so do this just in case */
304 while (valuep[strlen(valuep) - 1] == ' ' || valuep[strlen(valuep) - 1] == '\t')
305 valuep[strlen(valuep) - 1] = '\0';
309 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
310 /* add the server to the VLDB list */
312 thp = gethostbyname(valuep);
315 iErr = WSAGetLastError();
316 DebugEvent_local("AFS- cm_searchfile inRightCell",
317 "thp[%x], valuep[%s], WSAGetLastError[%d]",
321 memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
323 vlSockAddr.sin_family = AF_INET;
324 /* sin_port supplied by connection code */
326 (*procp)(rockp, &vlSockAddr, valuep);
330 /* For DJGPP, we will read IP address instead
331 of name/comment field */
332 code = sscanf(lineBuffer, "%d.%d.%d.%d #%s",
333 &c1, &c2, &c3, &c4, aname);
334 tp = (char *) &ip_addr;
339 memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
341 vlSockAddr.sin_family = AF_INET;
342 /* sin_port supplied by connection code */
344 (*procp)(rockp, &vlSockAddr, valuep);
349 } /* while loop processing all lines */
351 /* if for some unknown reason cell is not found, return negative code (-11) ??? */
352 return (foundCell) ? 0 : -11;
355 long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
356 cm_configProc_t *procp, void *rockp)
361 int cellHosts[AFSMAXCELLHOSTS];
364 struct sockaddr_in vlSockAddr;
366 DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
367 rc = getAFSServer(cellNamep, cellHosts, &numServers, ttl);
368 if (rc == 0 && numServers > 0) { /* found the cell */
369 for (i = 0; i < numServers; i++) {
370 memcpy(&vlSockAddr.sin_addr.s_addr, &cellHosts[i],
372 vlSockAddr.sin_family = AF_INET;
373 /* sin_port supplied by connection code */
375 (*procp)(rockp, &vlSockAddr, NULL);
377 strcpy(newCellNamep,cellNamep);
379 return 0; /* found cell */
382 return -1; /* not found */
383 #else /* DNSAPI_ENV */
384 PDNS_RECORD pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
385 LPSTR vlServers[AFSMAXCELLHOSTS];
386 IP4_ADDRESS vlAddrs[AFSMAXCELLHOSTS];
390 struct sockaddr_in vlSockAddr;
394 /* query the AFSDB records of cell */
395 if(DnsQuery_A(cellNamep, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
397 memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));
399 nvlServers = 0; wttl = 0;
401 /* go through the returned records */
402 for(pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
403 /* if we find an AFSDB record with Preference set to 1, we found a volserver */
404 if(pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
405 vlServers[nvlServers++] = pDnsIter->Data.Afsdb.pNameExchange;
406 if(!wttl) wttl = pDnsIter->dwTtl;
407 if(nvlServers == AFSMAXCELLHOSTS) break;
411 for(i=0;i<nvlServers;i++) vlAddrs[i] = 0;
413 /* now check if there are any A records in the results */
414 for(pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
415 if(pDnsIter->wType == DNS_TYPE_A)
416 /* check if its for one of the volservers */
417 for(i=0;i<nvlServers;i++)
418 if(stricmp(pDnsIter->pName, vlServers[i]) == 0)
419 vlAddrs[i] = pDnsIter->Data.A.IpAddress;
422 for(i=0;i<nvlServers;i++) {
423 /* if we don't have an IP yet, then we should try resolving the volserver hostname
424 in a separate query. */
426 if(DnsQuery_A(vlServers[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
427 for(pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
428 /* if we get an A record, keep it */
429 if(pDnsVolIter->wType == DNS_TYPE_A && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
430 vlAddrs[i] = pDnsVolIter->Data.A.IpAddress;
433 /* if we get a CNAME, look for a corresponding A record */
434 if(pDnsVolIter->wType == DNS_TYPE_CNAME && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
435 for(pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
436 if(pDnsCIter->wType == DNS_TYPE_A && stricmp(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
437 vlAddrs[i] = pDnsCIter->Data.A.IpAddress;
441 if(vlAddrs[i]) break;
442 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
445 /* we are done with the volserver lookup */
446 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
450 /* if we found a volserver, then add it */
452 vlSockAddr.sin_family = AF_INET;
453 vlSockAddr.sin_addr.s_addr = vlAddrs[i];
455 (*procp)(rockp, &vlSockAddr, vlServers[i]);
460 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
463 if(!success) return -1;
465 strcpy(newCellNamep, cellNamep);
466 if(ttl) *ttl = (int) wttl;
470 #endif /* DNSAPI_ENV */
472 return -1; /* not found */
473 #endif /* AFS_AFSDB_ENV */
476 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
477 /* look up the root cell's name in the Registry */
478 long cm_GetRootCellName(char *cellNamep)
480 DWORD code, dummyLen;
483 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
484 0, KEY_QUERY_VALUE, &parmKey);
485 if (code != ERROR_SUCCESS)
489 code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
490 cellNamep, &dummyLen);
491 RegCloseKey (parmKey);
492 if (code != ERROR_SUCCESS || cellNamep[0] == 0)
498 /* look up the root cell's name in the THISCELL file */
499 long cm_GetRootCellName(char *cellNamep)
502 char thisCellPath[256];
506 strcpy(thisCellPath, cm_confDir);
510 afsconf_path = getenv("AFSCONF");
512 strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
514 strcpy(thisCellPath, afsconf_path);
516 strcat(thisCellPath,"/");
518 strcat(thisCellPath, AFS_THISCELL);
519 thisCell = fopen(thisCellPath, "r");
520 if (thisCell == NULL)
523 fgets(cellNamep, 256, thisCell);
526 newline = strrchr(cellNamep,'\n');
527 if (newline) *newline = '\0';
528 newline = strrchr(cellNamep,'\r');
529 if (newline) *newline = '\0';
535 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
542 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
543 code = GetWindowsDirectory(wdir, sizeof(wdir));
544 if (code == 0 || code > sizeof(wdir))
547 /* add trailing backslash, if required */
549 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
552 strcpy(wdir,cm_confDir);
554 char *afsconf_path = getenv("AFSCONF");
556 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
558 strcpy(wdir, afsconf_path);
561 #endif /* DJGPP || WIN95 */
565 tfilep = fopen(wdir, rwp);
567 return ((cm_configFile_t *) tfilep);
571 long cm_WriteConfigString(char *labelp, char *valuep)
573 DWORD code, dummyDisp;
576 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
577 0, "container", 0, KEY_SET_VALUE, NULL,
578 &parmKey, &dummyDisp);
579 if (code != ERROR_SUCCESS)
582 code = RegSetValueEx(parmKey, labelp, 0, REG_SZ,
583 valuep, strlen(valuep) + 1);
584 RegCloseKey (parmKey);
585 if (code != ERROR_SUCCESS)
593 long cm_WriteConfigInt(char *labelp, long value)
595 DWORD code, dummyDisp;
598 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
599 0, "container", 0, KEY_SET_VALUE, NULL,
600 &parmKey, &dummyDisp);
601 if (code != ERROR_SUCCESS)
604 code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
605 (LPBYTE)&value, sizeof(value));
606 RegCloseKey (parmKey);
607 if (code != ERROR_SUCCESS)
614 cm_configFile_t *cm_OpenCellFile(void)
616 cm_configFile_t *cfp;
618 cfp = cm_CommonOpen("afsdcel2.ini", "w");
622 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
624 cm_configFile_t *tfilep; /* input file */
626 char lineBuffer[256];
631 tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
632 if (!tfilep) return -1;
636 /* have we seen the cell line for the guy we're looking for? */
639 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
641 if (feof((FILE *)tfilep)) {
643 fclose((FILE *)tfilep);
648 /* turn trailing cr or lf into null */
649 tp = strchr(lineBuffer, '\r');
651 tp = strchr(lineBuffer, '\n');
654 /* skip blank lines */
655 if (lineBuffer[0] == 0) {
656 fprintf((FILE *)ofp, "%s\n", lineBuffer);
660 if (lineBuffer[0] == '>') {
661 /* trim off at white space or '#' chars */
662 tp = strchr(lineBuffer, ' ');
664 tp = strchr(lineBuffer, '\t');
666 tp = strchr(lineBuffer, '#');
669 /* now see if this is the right cell */
670 if (strcmp(lineBuffer+1, cellNamep) == 0) {
671 /* found the cell we're looking for */
676 fprintf((FILE *)ofp, "%s\n", lineBuffer);
680 valuep = strchr(lineBuffer, '#');
681 if (valuep == NULL) return -2;
682 valuep++; /* skip the "#" */
684 fprintf((FILE *)ofp, "%s\n", lineBuffer);
687 } /* while loop processing all lines */
690 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
692 fprintf((FILE *)filep, ">%s\n", cellNamep);
696 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
698 fprintf((FILE *)filep, "%s\n", linep);
702 long cm_CloseCellFile(cm_configFile_t *filep)
712 closeCode = fclose((FILE *)filep);
714 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
715 code = GetWindowsDirectory(wdir, sizeof(wdir));
716 if (code == 0 || code > sizeof(wdir))
719 /* add trailing backslash, if required */
721 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
724 strcpy(wdir,cm_confDir);
726 afsconf_path = getenv("AFSCONF");
728 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
730 strcpy(wdir, afsconf_path);
733 #endif /* DJGPP || WIN95 */
737 if (closeCode != 0) {
738 /* something went wrong, preserve original database */
739 strcat(wdir, "afsdcel2.ini");
744 strcat(wdir, AFS_CELLSERVDB);
745 strcat(sdir, "afsdcel2.ini"); /* new file */
747 unlink(wdir); /* delete old file */
749 code = rename(sdir, wdir); /* do the rename */
757 void cm_GetConfigDir(char *dir)
766 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
767 code = GetWindowsDirectory(wdir, sizeof(wdir));
768 if (code == 0 || code > sizeof(wdir)) wdir[0] = 0;
770 /* add trailing backslash, if required */
772 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
775 strcpy(wdir,cm_confDir);
777 afsconf_path = getenv("AFSCONF");
779 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
781 strcpy(wdir, afsconf_path);
784 #endif /* DJGPP || WIN95 */