afs_FindService should handle iana portnames
[openafs.git] / src / auth / cellconfig.c
index 1dc4a51..ec94469 100644 (file)
@@ -10,8 +10,6 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
@@ -21,6 +19,7 @@ RCSID
 #include "des/des.h"
 #include "rx/rxkad.h"
 #include <netdb.h>
+#include <ctype.h>
 #else /* UKERNEL */
 #include <sys/types.h>
 #ifdef AFS_NT40_ENV
@@ -34,6 +33,7 @@ RCSID
 #include <netdb.h>
 #include <sys/file.h>
 #include <sys/time.h>
+#include <ctype.h>
 #ifdef AFS_AFSDB_ENV
 #include <arpa/nameser.h>
 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
@@ -72,27 +72,32 @@ RCSID
 #include <rx/rx.h>
 #include <rx/rxkad.h>
 
+struct afsconf_servPair {
+    const char *name;
+    const char *ianaName;
+    int port;
+};
+
 static struct afsconf_servPair serviceTable[] = {
-    {"afs", 7000,},
-    {"afscb", 7001,},
-    {"afsprot", 7002,},
-    {"afsvldb", 7003,},
-    {"afskauth", 7004,},
-    {"afsvol", 7005,},
-    {"afserror", 7006,},
-    {"afsnanny", 7007,},
-    {"afsupdate", 7008,},
-    {"afsrmtsys", 7009,},
-    {"afsres", 7010,},         /* residency database for MR-AFS */
-    {"afsremio", 7011,},       /* remote I/O interface for MR-AFS */
-    {0, 0}                     /* insert new services before this spot */
+    {"afs", "afs3-fileserver", 7000,},
+    {"afscb", "afs3-callback", 7001,},
+    {"afsprot", "afs3-prserver", 7002,},
+    {"afsvldb", "afs3-vlserver", 7003,},
+    {"afskauth", "afs3-kaserver", 7004,},
+    {"afsvol", "afs3-volserver", 7005,},
+    {"afserror", "afs3-errors", 7006,},
+    {"afsnanny", "afs3-bos", 7007,},
+    {"afsupdate", "afs3-update", 7008,},
+    {"afsrmtsys", "afs3-rmtsys", 7009,},
+    {"afsres", NULL, 7010,},/* residency database for MR-AFS */
+    {"afsremio", NULL, 7011,}, /* remote I/O interface for MR-AFS */
+    {0, 0, 0}                  /* insert new services before this spot */
 };
 
 /* Prototypes */
-static afs_int32 afsconf_FindService(register const char *aname);
 static int TrimLine(char *abuffer, int abufsize);
-#ifdef AFS_NT40_ENV
 static int IsClientConfigDirectory(const char *path);
+#ifdef AFS_NT40_ENV
 static int GetCellNT(struct afsconf_dir *adir);
 #endif
 static int afsconf_Check(register struct afsconf_dir *adir);
@@ -227,12 +232,15 @@ afsconf_fgets(char *s, int n, afsconf_FILE *iop)
 #endif /* AFS_SUN5_ENV && ! __sparcv9 */
 
 /* return port number in network byte order in the low 16 bits of a long; return -1 if not found */
-static afs_int32
-afsconf_FindService(register const char *aname)
+afs_int32
+afsconf_FindService(const char *aname)
 {
     /* lookup a service name */
     struct servent *ts;
-    register struct afsconf_servPair *tsp;
+    struct afsconf_servPair *tsp;
+
+    if (aname == NULL || aname[0] == '\0')
+       return -1;
 
 #if     defined(AFS_OSF_ENV) 
     ts = getservbyname(aname, "");
@@ -245,12 +253,30 @@ afsconf_FindService(register const char *aname)
     }
 
     /* not found in /etc/services, see if it is one of ours */
-    for (tsp = serviceTable;; tsp++) {
-       if (tsp->name == NULL)
-           return -1;
-       if (!strcmp(tsp->name, aname))
+    for (tsp = serviceTable; tsp->port; tsp++) {
+       if ((tsp->name && (!strcmp(tsp->name, aname)))
+           || (tsp->ianaName && (!strcmp(tsp->ianaName, aname))))
            return htons(tsp->port);
     }
+    return -1;
+}
+
+const char *
+afsconf_FindIANAName(const char *aname)
+{
+    /* lookup a service name */
+    struct afsconf_servPair *tsp;
+
+    if (aname == NULL || aname[0] == '\0')
+        return NULL;
+
+    /* see if it is one of ours */
+    for (tsp = serviceTable; tsp->port; tsp++) {
+       if ((tsp->name && (!strcmp(tsp->name, aname)))
+           || (tsp->ianaName && (!strcmp(tsp->ianaName, aname))))
+           return tsp->ianaName;
+    }
+    return NULL;
 }
 
 static int
@@ -271,20 +297,25 @@ TrimLine(char *abuffer, int abufsize)
     return 0;
 }
 
-#ifdef AFS_NT40_ENV
 /*
  * IsClientConfigDirectory() -- determine if path matches well-known
  *     client configuration directory.
  */
+#ifdef AFS_NT40_ENV
+#define IS_SEP(x) ((x) == '\\' || (x) == '/')
+#else /* AFS_NT40_ENV */
+#define IS_SEP(x) ((x) == '/')
+#endif /* AFS_NT40_ENV */
 static int
 IsClientConfigDirectory(const char *path)
 {
     const char *cdir = AFSDIR_CLIENT_ETC_DIRPATH;
-    int i;
+    int i, cc, pc;
 
     for (i = 0; cdir[i] != '\0' && path[i] != '\0'; i++) {
-       int cc = tolower(cdir[i]);
-       int pc = tolower(path[i]);
+#ifdef AFS_NT40_ENV
+       cc = tolower(cdir[i]);
+       pc = tolower(path[i]);
 
        if (cc == '\\') {
            cc = '/';
@@ -292,25 +323,28 @@ IsClientConfigDirectory(const char *path)
        if (pc == '\\') {
            pc = '/';
        }
-       if (cc != pc) {
+#else /* AFS_NT40_ENV */
+       cc = cdir[i];
+       pc = path[i];
+#endif /* AFS_NT40_ENV */
+        if (cc != pc) {
            return 0;
        }
     }
 
     /* hit end of one or both; allow mismatch in existence of trailing slash */
     if (cdir[i] != '\0') {
-       if ((cdir[i] != '\\' && cdir[i] != '/') || (cdir[i + 1] != '\0')) {
+       if (!IS_SEP(cdir[i]) || (cdir[i + 1] != '\0')) {
            return 0;
        }
     }
     if (path[i] != '\0') {
-       if ((path[i] != '\\' && path[i] != '/') || (path[i + 1] != '\0')) {
+       if (!IS_SEP(path[i]) || (path[i + 1] != '\0')) {
            return 0;
        }
     }
     return 1;
 }
-#endif /* AFS_NT40_ENV */
 
 
 static int
@@ -1216,6 +1250,64 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
            }
        }
        acellInfo->timeout = 0;
+
+        /* 
+         * Until we figure out how to separate out ubik server
+         * queries from other server queries, only perform gethostbyname()
+         * lookup on the specified hostnames for the client CellServDB files.
+         */
+        if (IsClientConfigDirectory(adir->name) && 
+            !(acellInfo->flags & AFSCONF_CELL_FLAG_DNS_QUERIED)) {
+            int j;
+            short numServers=0;                                        /*Num active servers for the cell */
+            struct sockaddr_in hostAddr[MAXHOSTSPERCELL];      /*IP addresses for cell's servers */
+            char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS];      /*Names for cell's servers */
+
+            memset(&hostAddr, 0, sizeof(hostAddr));
+            memset(&hostName, 0, sizeof(hostName));
+
+            for ( j=0; j<acellInfo->numServers && numServers < MAXHOSTSPERCELL; j++ ) {
+                struct hostent *he = gethostbyname(acellInfo->hostName[j]);
+                int foundAddr = 0;
+
+                if (he && he->h_addrtype == AF_INET) {
+                    int i;
+                    /* obtain all the valid address from the list */
+                    for (i=0 ; he->h_addr_list[i] && numServers < MAXHOSTSPERCELL; i++) {
+                        /* check to see if this is a new address; if so insert it into the list */
+                        int k, dup;
+                        for (k=0, dup=0; !dup && k < numServers; k++) {
+                            if (hostAddr[k].sin_addr.s_addr == *(u_long *)he->h_addr_list[i])
+                                dup = 1;
+                        }
+                        if (dup)
+                            continue;
+
+                        hostAddr[numServers].sin_family = AF_INET;
+                        hostAddr[numServers].sin_port = acellInfo->hostAddr[0].sin_port;
+#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
+                        hostAddr[numServers].sin_len = sizeof(struct sockaddr_in);
+#endif
+                        memcpy(&hostAddr[numServers].sin_addr.s_addr, he->h_addr_list[i], sizeof(long));
+                        strcpy(hostName[numServers], acellInfo->hostName[j]);
+                        foundAddr = 1;
+                        numServers++;
+                    }
+                }
+                if (!foundAddr) {
+                    hostAddr[numServers] = acellInfo->hostAddr[j];
+                    strcpy(hostName[numServers], acellInfo->hostName[j]);
+                    numServers++;
+                }
+            }
+
+            for (i=0; i<numServers; i++) {
+                acellInfo->hostAddr[i] = hostAddr[i];
+                strcpy(acellInfo->hostName[i], hostName[i]);
+            }
+            acellInfo->numServers = numServers;
+            acellInfo->flags |= AFSCONF_CELL_FLAG_DNS_QUERIED;
+        }
        UNLOCK_GLOBAL_MUTEX;
        return 0;
     } else {