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 DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
396 /* query the AFSDB records of cell */
397 if(DnsQuery_A(cellNamep, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
399 memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));
401 nvlServers = 0; wttl = 0;
403 /* go through the returned records */
404 for(pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
405 /* if we find an AFSDB record with Preference set to 1, we found a volserver */
406 if(pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
407 vlServers[nvlServers++] = pDnsIter->Data.Afsdb.pNameExchange;
408 if(!wttl) wttl = pDnsIter->dwTtl;
409 if(nvlServers == AFSMAXCELLHOSTS) break;
413 for(i=0;i<nvlServers;i++) vlAddrs[i] = 0;
415 /* now check if there are any A records in the results */
416 for(pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
417 if(pDnsIter->wType == DNS_TYPE_A)
418 /* check if its for one of the volservers */
419 for(i=0;i<nvlServers;i++)
420 if(stricmp(pDnsIter->pName, vlServers[i]) == 0)
421 vlAddrs[i] = pDnsIter->Data.A.IpAddress;
424 for(i=0;i<nvlServers;i++) {
425 /* if we don't have an IP yet, then we should try resolving the volserver hostname
426 in a separate query. */
428 if(DnsQuery_A(vlServers[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
429 for(pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
430 /* if we get an A record, keep it */
431 if(pDnsVolIter->wType == DNS_TYPE_A && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
432 vlAddrs[i] = pDnsVolIter->Data.A.IpAddress;
435 /* if we get a CNAME, look for a corresponding A record */
436 if(pDnsVolIter->wType == DNS_TYPE_CNAME && stricmp(vlServers[i], pDnsVolIter->pName)==0) {
437 for(pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
438 if(pDnsCIter->wType == DNS_TYPE_A && stricmp(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
439 vlAddrs[i] = pDnsCIter->Data.A.IpAddress;
443 if(vlAddrs[i]) break;
444 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
447 /* we are done with the volserver lookup */
448 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
452 /* if we found a volserver, then add it */
454 vlSockAddr.sin_family = AF_INET;
455 vlSockAddr.sin_addr.s_addr = vlAddrs[i];
457 (*procp)(rockp, &vlSockAddr, vlServers[i]);
462 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
465 if(!success) return -1;
467 strcpy(newCellNamep, cellNamep);
468 if(ttl) *ttl = (int) wttl;
472 #endif /* DNSAPI_ENV */
474 return -1; /* not found */
475 #endif /* AFS_AFSDB_ENV */
478 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
479 /* look up the root cell's name in the Registry */
480 long cm_GetRootCellName(char *cellNamep)
482 DWORD code, dummyLen;
485 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
486 0, KEY_QUERY_VALUE, &parmKey);
487 if (code != ERROR_SUCCESS)
491 code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
492 cellNamep, &dummyLen);
493 RegCloseKey (parmKey);
494 if (code != ERROR_SUCCESS || cellNamep[0] == 0)
500 /* look up the root cell's name in the THISCELL file */
501 long cm_GetRootCellName(char *cellNamep)
504 char thisCellPath[256];
508 strcpy(thisCellPath, cm_confDir);
512 afsconf_path = getenv("AFSCONF");
514 strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
516 strcpy(thisCellPath, afsconf_path);
518 strcat(thisCellPath,"/");
520 strcat(thisCellPath, AFS_THISCELL);
521 thisCell = fopen(thisCellPath, "r");
522 if (thisCell == NULL)
525 fgets(cellNamep, 256, thisCell);
528 newline = strrchr(cellNamep,'\n');
529 if (newline) *newline = '\0';
530 newline = strrchr(cellNamep,'\r');
531 if (newline) *newline = '\0';
537 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
544 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
545 code = GetWindowsDirectory(wdir, sizeof(wdir));
546 if (code == 0 || code > sizeof(wdir))
549 /* add trailing backslash, if required */
551 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
554 strcpy(wdir,cm_confDir);
556 char *afsconf_path = getenv("AFSCONF");
558 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
560 strcpy(wdir, afsconf_path);
563 #endif /* DJGPP || WIN95 */
567 tfilep = fopen(wdir, rwp);
569 return ((cm_configFile_t *) tfilep);
573 long cm_WriteConfigString(char *labelp, char *valuep)
575 DWORD code, dummyDisp;
578 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
579 0, "container", 0, KEY_SET_VALUE, NULL,
580 &parmKey, &dummyDisp);
581 if (code != ERROR_SUCCESS)
584 code = RegSetValueEx(parmKey, labelp, 0, REG_SZ,
585 valuep, strlen(valuep) + 1);
586 RegCloseKey (parmKey);
587 if (code != ERROR_SUCCESS)
595 long cm_WriteConfigInt(char *labelp, long value)
597 DWORD code, dummyDisp;
600 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
601 0, "container", 0, KEY_SET_VALUE, NULL,
602 &parmKey, &dummyDisp);
603 if (code != ERROR_SUCCESS)
606 code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
607 (LPBYTE)&value, sizeof(value));
608 RegCloseKey (parmKey);
609 if (code != ERROR_SUCCESS)
616 cm_configFile_t *cm_OpenCellFile(void)
618 cm_configFile_t *cfp;
620 cfp = cm_CommonOpen("afsdcel2.ini", "w");
624 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
626 cm_configFile_t *tfilep; /* input file */
628 char lineBuffer[256];
633 tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
634 if (!tfilep) return -1;
638 /* have we seen the cell line for the guy we're looking for? */
641 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
643 if (feof((FILE *)tfilep)) {
645 fclose((FILE *)tfilep);
650 /* turn trailing cr or lf into null */
651 tp = strchr(lineBuffer, '\r');
653 tp = strchr(lineBuffer, '\n');
656 /* skip blank lines */
657 if (lineBuffer[0] == 0) {
658 fprintf((FILE *)ofp, "%s\n", lineBuffer);
662 if (lineBuffer[0] == '>') {
663 /* trim off at white space or '#' chars */
664 tp = strchr(lineBuffer, ' ');
666 tp = strchr(lineBuffer, '\t');
668 tp = strchr(lineBuffer, '#');
671 /* now see if this is the right cell */
672 if (strcmp(lineBuffer+1, cellNamep) == 0) {
673 /* found the cell we're looking for */
678 fprintf((FILE *)ofp, "%s\n", lineBuffer);
682 valuep = strchr(lineBuffer, '#');
683 if (valuep == NULL) return -2;
684 valuep++; /* skip the "#" */
686 fprintf((FILE *)ofp, "%s\n", lineBuffer);
689 } /* while loop processing all lines */
692 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
694 fprintf((FILE *)filep, ">%s\n", cellNamep);
698 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
700 fprintf((FILE *)filep, "%s\n", linep);
704 long cm_CloseCellFile(cm_configFile_t *filep)
714 closeCode = fclose((FILE *)filep);
716 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
717 code = GetWindowsDirectory(wdir, sizeof(wdir));
718 if (code == 0 || code > sizeof(wdir))
721 /* add trailing backslash, if required */
723 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
726 strcpy(wdir,cm_confDir);
728 afsconf_path = getenv("AFSCONF");
730 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
732 strcpy(wdir, afsconf_path);
735 #endif /* DJGPP || WIN95 */
739 if (closeCode != 0) {
740 /* something went wrong, preserve original database */
741 strcat(wdir, "afsdcel2.ini");
746 strcat(wdir, AFS_CELLSERVDB);
747 strcat(sdir, "afsdcel2.ini"); /* new file */
749 unlink(wdir); /* delete old file */
751 code = rename(sdir, wdir); /* do the rename */
759 void cm_GetConfigDir(char *dir)
768 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
769 code = GetWindowsDirectory(wdir, sizeof(wdir));
770 if (code == 0 || code > sizeof(wdir)) wdir[0] = 0;
772 /* add trailing backslash, if required */
774 if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
777 strcpy(wdir,cm_confDir);
779 afsconf_path = getenv("AFSCONF");
781 strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
783 strcpy(wdir, afsconf_path);
786 #endif /* DJGPP || WIN95 */