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 */
58 #define TRACE_OPTION_EVENT 1
59 #define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
61 void DebugEvent0_local(char *a)
63 HANDLE h; char *ptbuf[1];
64 if (!ISLOGONTRACE(TraceOption))
66 h = RegisterEventSource(NULL, a);
68 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
69 DeregisterEventSource(h);
74 void DebugEvent_local(char *a,char *b,...)
76 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
78 if (!ISLOGONTRACE(TraceOption))
80 h = RegisterEventSource(NULL, a);
82 _vsnprintf(buf,MAXBUF_,b,marker);
84 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
85 DeregisterEventSource(h);
90 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
99 for(tp = lineBufferp; *tp; tp++) {
108 /* comment or line end */
109 if (tc == '#' || tc == '\r' || tc == '\n')
112 /* square bracket comment -- look for closing delim */
119 if (tc == ' ' || tc == '\t')
127 /* now we have a real character, put it in the appropriate bucket */
128 if (sawEquals == 0) {
136 /* null terminate the strings */
140 return 0; /* and return success */
143 /* search for a cell, and either return an error code if we don't find it,
144 * or return 0 if we do, in which case we also fill in the addresses in
147 * new feature: we can handle abbreviations and are insensitive to case.
148 * If the caller wants the "real" cell name, it puts a non-null pointer in
149 * newCellNamep. Anomaly: if cellNamep is ambiguous, we may modify
150 * newCellNamep but return an error code.
152 long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
153 cm_configProc_t *procp, void *rockp)
157 FILE *tfilep, *bestp, *tempp;
159 char lineBuffer[257];
162 struct sockaddr_in vlSockAddr;
166 int tracking = 1, partial = 0;
167 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
177 code = GetWindowsDirectory(wdir, sizeof(wdir));
178 if (code == 0 || code > sizeof(wdir))
181 /* add trailing backslash, if required */
183 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
185 strcpy(wdir, cm_confDir);
189 strcat(wdir, AFS_CELLSERVDB);
191 tfilep = fopen(wdir, "r");
193 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
195 /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
196 /* If we are in Win95 here, we are linking with klog etc. and are
197 using DJGPP client even though DJGPP is not defined. So we still
198 need to check AFSCONF for location. */
199 afsconf_path = getenv("AFSCONF");
201 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
203 strcpy(wdir, afsconf_path);
205 strcat(wdir, AFS_CELLSERVDB_UNIX);
206 /*fprintf(stderr, "opening cellservdb file %s\n", wdir);*/
207 tfilep = fopen(wdir, "r");
208 if (!tfilep) return -2;
211 /* If we are NT or higher, we don't do DJGPP, So just fail */
216 bestp = fopen(wdir, "r");
219 DebugEvent_local("AFS- cm_searchfile fopen", "Handle[%x], wdir[%s]", bestp, wdir);
222 /* have we seen the cell line for the guy we're looking for? */
225 tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
227 (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
233 * found partial match earlier;
246 return (foundCell? 0 : -3);
251 /* turn trailing cr or lf into null */
252 tp = strchr(lineBuffer, '\r');
254 tp = strchr(lineBuffer, '\n');
257 /* skip blank lines */
258 if (lineBuffer[0] == 0) continue;
260 if (lineBuffer[0] == '>') {
261 /* trim off at white space or '#' chars */
262 tp = strchr(lineBuffer, ' ');
264 tp = strchr(lineBuffer, '\t');
266 tp = strchr(lineBuffer, '#');
269 /* now see if this is the right cell */
270 if (stricmp(lineBuffer+1, cellNamep) == 0) {
271 /* found the cell we're looking for */
273 strcpy(newCellNamep, lineBuffer+1);
277 DebugEvent_local("AFS- cm_searchfile is cell", "inRightCell[%x], linebuffer[%s]",
278 inRightCell, lineBuffer);
281 else if (strnicmp(lineBuffer+1, cellNamep,
282 strlen(cellNamep)) == 0) {
284 if (partial) { /* ambiguous */
290 strcpy(newCellNamep, lineBuffer+1);
295 else inRightCell = 0;
298 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
299 valuep = strchr(lineBuffer, '#');
300 if (valuep == NULL) {
305 valuep++; /* skip the "#" */
307 valuep += strspn(valuep, " \t"); /* skip SP & TAB */
308 /* strip spaces and tabs in the end. They should not be there according to CellServDB format
309 so do this just in case */
310 while (valuep[strlen(valuep) - 1] == ' ' || valuep[strlen(valuep) - 1] == '\t')
311 valuep[strlen(valuep) - 1] = '\0';
315 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
316 /* add the server to the VLDB list */
318 thp = gethostbyname(valuep);
321 int iErr = WSAGetLastError();
322 DebugEvent_local("AFS- cm_searchfile inRightCell",
323 "thp[%x], valuep[%s], WSAGetLastError[%d]",
328 memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
330 vlSockAddr.sin_family = AF_INET;
331 /* sin_port supplied by connection code */
333 (*procp)(rockp, &vlSockAddr, valuep);
337 /* For DJGPP, we will read IP address instead
338 of name/comment field */
339 code = sscanf(lineBuffer, "%d.%d.%d.%d #%s",
340 &c1, &c2, &c3, &c4, aname);
341 tp = (char *) &ip_addr;
346 memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
348 vlSockAddr.sin_family = AF_INET;
349 /* sin_port supplied by connection code */
351 (*procp)(rockp, &vlSockAddr, valuep);
356 } /* while loop processing all lines */
358 /* if for some unknown reason cell is not found, return negative code (-11) ??? */
359 return (foundCell) ? 0 : -11;
362 long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
363 cm_configProc_t *procp, void *rockp)
368 int cellHosts[AFSMAXCELLHOSTS];
371 struct sockaddr_in vlSockAddr;
374 DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
376 rc = getAFSServer(cellNamep, cellHosts, &numServers, ttl);
377 if (rc == 0 && numServers > 0) { /* found the cell */
378 for (i = 0; i < numServers; i++) {
379 memcpy(&vlSockAddr.sin_addr.s_addr, &cellHosts[i],
381 vlSockAddr.sin_family = AF_INET;
382 /* sin_port supplied by connection code */
384 (*procp)(rockp, &vlSockAddr, NULL);
386 strcpy(newCellNamep,cellNamep);
388 return 0; /* found cell */
391 return -1; /* not found */
392 #else /* DNSAPI_ENV */
393 PDNS_RECORD pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
394 LPSTR vlServers[AFSMAXCELLHOSTS];
395 IP4_ADDRESS vlAddrs[AFSMAXCELLHOSTS];
399 struct sockaddr_in vlSockAddr;
404 DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
407 /* query the AFSDB records of cell */
408 if(DnsQuery_A(cellNamep, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
410 memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));
412 nvlServers = 0; wttl = 0;
414 /* go through the returned records */
415 for(pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
416 /* if we find an AFSDB record with Preference set to 1, we found a volserver */
417 if(pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
418 vlServers[nvlServers++] = pDnsIter->Data.Afsdb.pNameExchange;
419 if(!wttl) wttl = pDnsIter->dwTtl;
420 if(nvlServers == AFSMAXCELLHOSTS) break;
424 for(i=0;i<nvlServers;i++) vlAddrs[i] = 0;
426 /* now check if there are any A records in the results */
427 for(pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
428 if(pDnsIter->wType == DNS_TYPE_A)
429 /* check if its for one of the volservers */
430 for(i=0;i<nvlServers;i++)
431 if(stricmp(pDnsIter->pName, vlServers[i]) == 0)
432 vlAddrs[i] = pDnsIter->Data.A.IpAddress;
435 for(i=0;i<nvlServers;i++) {
436 /* if we don't have an IP yet, then we should try resolving the volserver hostname
437 in a separate query. */
439 if(DnsQuery_A(vlServers[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
440 for(pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
441 /* if we get an A record, keep it */
442 if(pDnsVolIter->wType == DNS_TYPE_A && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
443 vlAddrs[i] = pDnsVolIter->Data.A.IpAddress;
446 /* if we get a CNAME, look for a corresponding A record */
447 if(pDnsVolIter->wType == DNS_TYPE_CNAME && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
448 for(pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
449 if(pDnsCIter->wType == DNS_TYPE_A && stricmp(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
450 vlAddrs[i] = pDnsCIter->Data.A.IpAddress;
454 if(vlAddrs[i]) break;
455 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
458 /* we are done with the volserver lookup */
459 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
463 /* if we found a volserver, then add it */
465 vlSockAddr.sin_family = AF_INET;
466 vlSockAddr.sin_addr.s_addr = vlAddrs[i];
468 (*procp)(rockp, &vlSockAddr, vlServers[i]);
473 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
476 if(!success) return -1;
478 strcpy(newCellNamep, cellNamep);
479 if(ttl) *ttl = (int) wttl;
483 #endif /* DNSAPI_ENV */
485 return -1; /* not found */
486 #endif /* AFS_AFSDB_ENV */
489 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
490 /* look up the root cell's name in the Registry */
491 long cm_GetRootCellName(char *cellNamep)
493 DWORD code, dummyLen;
496 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
497 0, KEY_QUERY_VALUE, &parmKey);
498 if (code != ERROR_SUCCESS)
502 code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
503 cellNamep, &dummyLen);
504 RegCloseKey (parmKey);
505 if (code != ERROR_SUCCESS || cellNamep[0] == 0)
511 /* look up the root cell's name in the THISCELL file */
512 long cm_GetRootCellName(char *cellNamep)
515 char thisCellPath[256];
519 strcpy(thisCellPath, cm_confDir);
523 afsconf_path = getenv("AFSCONF");
525 strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
527 strcpy(thisCellPath, afsconf_path);
529 strcat(thisCellPath,"/");
531 strcat(thisCellPath, AFS_THISCELL);
532 thisCell = fopen(thisCellPath, "r");
533 if (thisCell == NULL)
536 fgets(cellNamep, 256, thisCell);
539 newline = strrchr(cellNamep,'\n');
540 if (newline) *newline = '\0';
541 newline = strrchr(cellNamep,'\r');
542 if (newline) *newline = '\0';
548 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
555 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
556 code = GetWindowsDirectory(wdir, sizeof(wdir));
557 if (code == 0 || code > sizeof(wdir))
560 /* add trailing backslash, if required */
562 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
565 strcpy(wdir,cm_confDir);
567 char *afsconf_path = getenv("AFSCONF");
569 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
571 strcpy(wdir, afsconf_path);
574 #endif /* DJGPP || WIN95 */
578 tfilep = fopen(wdir, rwp);
580 return ((cm_configFile_t *) tfilep);
584 long cm_WriteConfigString(char *labelp, char *valuep)
586 DWORD code, dummyDisp;
589 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
590 0, "container", 0, KEY_SET_VALUE, NULL,
591 &parmKey, &dummyDisp);
592 if (code != ERROR_SUCCESS)
595 code = RegSetValueEx(parmKey, labelp, 0, REG_SZ,
596 valuep, strlen(valuep) + 1);
597 RegCloseKey (parmKey);
598 if (code != ERROR_SUCCESS)
606 long cm_WriteConfigInt(char *labelp, long value)
608 DWORD code, dummyDisp;
611 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
612 0, "container", 0, KEY_SET_VALUE, NULL,
613 &parmKey, &dummyDisp);
614 if (code != ERROR_SUCCESS)
617 code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
618 (LPBYTE)&value, sizeof(value));
619 RegCloseKey (parmKey);
620 if (code != ERROR_SUCCESS)
627 cm_configFile_t *cm_OpenCellFile(void)
629 cm_configFile_t *cfp;
631 cfp = cm_CommonOpen("afsdcel2.ini", "w");
635 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
637 cm_configFile_t *tfilep; /* input file */
639 char lineBuffer[256];
644 tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
645 if (!tfilep) return -1;
649 /* have we seen the cell line for the guy we're looking for? */
652 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
654 if (feof((FILE *)tfilep)) {
656 fclose((FILE *)tfilep);
661 /* turn trailing cr or lf into null */
662 tp = strchr(lineBuffer, '\r');
664 tp = strchr(lineBuffer, '\n');
667 /* skip blank lines */
668 if (lineBuffer[0] == 0) {
669 fprintf((FILE *)ofp, "%s\n", lineBuffer);
673 if (lineBuffer[0] == '>') {
674 /* trim off at white space or '#' chars */
675 tp = strchr(lineBuffer, ' ');
677 tp = strchr(lineBuffer, '\t');
679 tp = strchr(lineBuffer, '#');
682 /* now see if this is the right cell */
683 if (strcmp(lineBuffer+1, cellNamep) == 0) {
684 /* found the cell we're looking for */
689 fprintf((FILE *)ofp, "%s\n", lineBuffer);
693 valuep = strchr(lineBuffer, '#');
694 if (valuep == NULL) return -2;
695 valuep++; /* skip the "#" */
697 fprintf((FILE *)ofp, "%s\n", lineBuffer);
700 } /* while loop processing all lines */
703 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
705 fprintf((FILE *)filep, ">%s\n", cellNamep);
709 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
711 fprintf((FILE *)filep, "%s\n", linep);
715 long cm_CloseCellFile(cm_configFile_t *filep)
725 closeCode = fclose((FILE *)filep);
727 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
728 code = GetWindowsDirectory(wdir, sizeof(wdir));
729 if (code == 0 || code > sizeof(wdir))
732 /* add trailing backslash, if required */
734 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
737 strcpy(wdir,cm_confDir);
739 afsconf_path = getenv("AFSCONF");
741 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
743 strcpy(wdir, afsconf_path);
746 #endif /* DJGPP || WIN95 */
750 if (closeCode != 0) {
751 /* something went wrong, preserve original database */
752 strcat(wdir, "afsdcel2.ini");
757 strcat(wdir, AFS_CELLSERVDB);
758 strcat(sdir, "afsdcel2.ini"); /* new file */
760 unlink(wdir); /* delete old file */
762 code = rename(sdir, wdir); /* do the rename */
770 void cm_GetConfigDir(char *dir)
779 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
780 code = GetWindowsDirectory(wdir, sizeof(wdir));
781 if (code == 0 || code > sizeof(wdir)) wdir[0] = 0;
783 /* add trailing backslash, if required */
785 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
788 strcpy(wdir,cm_confDir);
790 afsconf_path = getenv("AFSCONF");
792 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
794 strcpy(wdir, afsconf_path);
797 #endif /* DJGPP || WIN95 */