Change krb5 kcmd to use getaddrinfo, and add some hooks for future ipv6
authorKen Raeburn <raeburn@mit.edu>
Mon, 11 Feb 2002 00:15:47 +0000 (00:15 +0000)
committerKen Raeburn <raeburn@mit.edu>
Mon, 11 Feb 2002 00:15:47 +0000 (00:15 +0000)
support.

* defines.h: Include fake-addrinfo.h.
(FAI_PREFIX): Define.
(getport): Update.
* kcmd.c: Include fake-addrinfo.c.
(kcmd): Use getaddrinfo instead of gethostbyname, but only get AF_INET
addresses for now.
(k4cmd): Update argument list to getport.
(getport): Accept new argument, pointer to address family to use.  If zero, try
inet6 and then inet.
* krshd.c (doit): Update argument list to getport.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14140 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/bsd/ChangeLog
src/appl/bsd/defines.h
src/appl/bsd/kcmd.c
src/appl/bsd/krshd.c

index 5b8bef8de2bc8adbc1168b04a69df295da914fab..7f1ebb0939408d55d64fc253e1badc48b4fa12de 100644 (file)
@@ -1,3 +1,16 @@
+2002-02-10  Ken Raeburn  <raeburn@mit.edu>
+
+       * defines.h: Include fake-addrinfo.h.
+       (FAI_PREFIX): Define.
+       (getport): Update.
+       * kcmd.c: Include fake-addrinfo.c.
+       (kcmd): Use getaddrinfo instead of gethostbyname, but only get
+       AF_INET addresses for now.
+       (k4cmd): Update argument list to getport.
+       (getport): Accept new argument, pointer to address family to use.
+       If zero, try inet6 and then inet.
+       * krshd.c (doit): Update argument list to getport.
+
 2001-12-06  Ezra Peisach  <epeisach@mit.edu>
 
        * krcp.c, krlogin.c, krlogind.c, krsh.c, krshd.c, login.c,
index c32d840800c9fbce096d52b35b2b209cd2523e42..d8bf86765902436b2e0415c7757baf0db7526eb4 100644 (file)
@@ -36,7 +36,7 @@ extern int kcmd (int *sock, char **ahost, int /* u_short */ rport,
 
 extern int rcmd_stream_read (int fd, char *buf, size_t len, int secondary);
 extern int rcmd_stream_write (int fd, char *buf, size_t len, int secondary);
-extern int getport (int *);
+extern int getport (int * /* portnum */, int * /* addrfamily */);
 
 extern void rcmd_stream_init_krb5 (krb5_keyblock *in_keyblock,
                                   int encrypt_flag, int lencheck,
@@ -68,3 +68,6 @@ krb5_error_code rd_and_store_for_creds(krb5_context context,
 #ifdef NEED_SETENV
 extern int setenv(char *, char *, int);
 #endif
+
+#define FAI_PREFIX bsd
+#include "fake-addrinfo.h"
index 4c8ca7a23bdcc3bc0b3757c2625c1e09b48e46b2..d7829a416262a3bfc5fc66e0dd62863f44c3a835 100644 (file)
@@ -93,6 +93,8 @@
 
 #include "defines.h"
 
+#include "fake-addrinfo.c"
+
 extern krb5_context bsd_context;
 #ifdef KRB5_KRB4_COMPAT
 extern Key_schedule v4_schedule;
@@ -189,7 +191,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     krb5_creds *get_cred, *ret_cred = 0;
     char c;
     int lport;
-    struct hostent *hp;
+    struct addrinfo *ap, *ap2;
     int rc;
     char *host_save;
     krb5_error_code status;
@@ -204,6 +206,13 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     krb5_data cksumdat;
     char *kcmd_version;
     enum kcmd_proto protonum = *protonump;
+    char rport_buf[10];
+    struct addrinfo ai_hints;
+    int addrfamily = AF_INET;
+    int err;
+    int inet6_ok = 1;
+
+    sprintf(rport_buf, "%d", ntohs(rport));
 
     if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) {
        fprintf(stderr, "Unable to allocate memory for checksum buffer.\n");
@@ -216,11 +225,20 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     cksumdat.length = strlen(cksumbuf);
        
     pid = getpid();
-    hp = gethostbyname(*ahost);
-    if (hp == 0) {
-       fprintf(stderr, "%s: unknown host\n", *ahost);
-       return (-1);
+    memset(&ai_hints, 0, sizeof (ai_hints));
+    ai_hints.ai_socktype = SOCK_STREAM;
+    ai_hints.ai_flags = AI_CANONNAME;
+    ai_hints.ai_family = AF_INET;
+    err = getaddrinfo(*ahost, rport_buf, &ai_hints, &ap);
+    if (err != 0) {
+       fprintf(stderr, "%s: %s\n", *ahost, gai_strerror (err));
+       return -1;
+    }
+    if (ap == 0) {
+       fprintf(stderr, "%s: no addresses?\n", *ahost);
+       return -1;
     }
+    fixup_addrinfo(ap);
 
 #ifdef POSIX_SIGNALS
     sigemptyset(&urgmask);
@@ -229,47 +247,66 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
 #else
     oldmask = sigblock(sigmask(SIGURG));
 #endif /* POSIX_SIGNALS */
-    
-    for (;;) {
-        s = getport(0);
-       if (s < 0) {
+
+    for (ap2 = ap; ap2; ap2 = ap2->ai_next) {
+       int af = ap2->ai_family;
+       switch (af) {
+       case AF_INET:
+           break;
+#ifdef KRB5_USE_INET6
+       case AF_INET6:
+           if (inet6_ok)
+               break;
+           continue;
+#endif
+       default:
+           break;
+       }
+       s = getport(0, &af);
+       if (s < 0) {
+           char *fam = (af == AF_INET) ? "inet" : "inet6";
+           char perrorbuf[40];
            if (errno == EAGAIN)
-               fprintf(stderr, "socket: All ports in use\n");
-           else
-               perror("kcmd: socket");
-#ifdef POSIX_SIGNALS
-           sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
-#else
-           sigsetmask(oldmask);
-#endif /* POSIX_SIGNALS */
-           return (-1);
-       }
-       sockin.sin_family = hp->h_addrtype;
-       memcpy((caddr_t)&sockin.sin_addr,hp->h_addr, sizeof(sockin.sin_addr));
-       sockin.sin_port = rport;
-       if (connect(s, (struct sockaddr *)&sockin, sizeof (sockin)) >= 0)
+               fprintf(stderr, "socket(%s): All ports in use\n", fam);
+           else {
+               sprintf(perrorbuf, "kcmd: socket(%s)", fam);
+               perror(perrorbuf);
+           }
+#ifdef KRB5_USE_INET6
+           /* Should this be done only for certain error codes?  */
+           if (af == AF_INET6) {
+               inet6_ok = 0;
+               continue;
+           }
+#endif
+           goto fix_signals_and_return;
+       }
+       /* Got a socket, now connect.  */
+       if (connect(s, ap2->ai_addr, ap2->ai_addrlen) >= 0)
            break;
-       (void) close(s);
-       if (errno == EADDRINUSE)
+       (void) close(s);
+       if (errno == EADDRINUSE)
            continue;
-
-#if !(defined(tek) || defined(ultrix) || defined(sun) || defined(SYSV))
-       if (hp->h_addr_list[1] != NULL) {
+       /* Print message about failing on this address before moving
+          on to the next.  */
+       if (ap2->ai_next) {
+           char naddrbuf[NI_MAXHOST];
            int oerrno = errno;
-           
-           fprintf(stderr,
-                   "connect to address %s: ", inet_ntoa(sockin.sin_addr));
-           errno = oerrno;
-           perror(0);
-           hp->h_addr_list++;
-           memcpy((caddr_t)&sockin.sin_addr,hp->h_addr_list[0],
-                  sizeof(sockin.sin_addr));
-           fprintf(stderr, "Trying %s...\n",
-                   inet_ntoa(sockin.sin_addr));
-           continue;
-       }
-#endif /* !(defined(ultrix) || defined(sun)) */
-       perror(hp->h_name);
+           if (getnameinfo(ap2->ai_addr, ap2->ai_addrlen,
+                           naddrbuf, sizeof(naddrbuf), 0, 0,
+                           NI_NUMERICHOST) == 0) {
+               fprintf(stderr, "connect to address %s: ", naddrbuf);
+               errno = oerrno;
+               perror(0);
+           } else {
+               errno = oerrno;
+               perror("connect failed");
+           }
+           fprintf(stderr, "trying next address...\n");
+       }
+    }
+    if (ap2 == 0) {
+    fix_signals_and_return:
 #ifdef POSIX_SIGNALS
        sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
 #else
@@ -284,13 +321,13 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
         fprintf(stderr,"kcmd: no memory\n");
         return(-1);
     }
-    host_save = malloc(strlen(hp->h_name) + 1);
+    host_save = malloc(strlen(ap->ai_canonname) + 1);
     if (host_save == NULL) {
        fprintf(stderr, "kcmd: no memory\n");
        free(get_cred);
        return -1;
     }
-    strcpy(host_save, hp->h_name);
+    strcpy(host_save, ap->ai_canonname);
     status = krb5_sname_to_principal(bsd_context, host_save, service,
                                     KRB5_NT_SRV_HST, &get_cred->server);
     if (status) {
@@ -313,7 +350,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
        lport = 0;
     } else {
        char num[8];
-       int s2 = getport(&lport), s3;
+       int s2 = getport(&lport, &addrfamily), s3;
        int len = sizeof (from);
        
        if (s2 < 0) {
@@ -561,6 +598,7 @@ k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
     GETSOCKNAME_ARG3_TYPE sin_len;
     char *host_save;
     int status;
+    int addrfamily = AF_INET;
 
     pid = getpid();
     hp = gethostbyname(*ahost);
@@ -580,7 +618,7 @@ k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
     oldmask = sigblock(sigmask(SIGURG));
 #endif /* POSIX_SIGNALS */
     for (;;) {
-       s = getport(&lport);
+       s = getport(&lport, &addrfamily);
        if (s < 0) {
            if (errno == EAGAIN)
                fprintf(stderr, "socket: All ports in use\n");
@@ -636,7 +674,7 @@ k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
        lport = 0;
     } else {
        char num[8];
-       int s2 = getport(&lport), s3;
+       int s2 = getport(&lport, &addrfamily), s3;
        int len = sizeof (from);
 
        if (s2 < 0) {
@@ -769,34 +807,81 @@ reread:
 
 
 int
-getport(alport)
-     int *alport;
+getport(alport, family)
+    int *alport, *family;
 {
-    struct sockaddr_in sockin;
     int s;
-    GETSOCKNAME_ARG3_TYPE len = sizeof(sockin);
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-       return (-1);
 
-    memset((char *) &sockin, 0,sizeof(sockin));
-    sockin.sin_family = AF_INET;
-    sockin.sin_addr.s_addr = INADDR_ANY;
+    if (*family == 0) {
+#ifdef KRB5_USE_INET6
+       *family = AF_INET6;
+       s = getport (alport, family);
+       if (s >= 0)
+           return s;
+#endif
+       *family = AF_INET;
+       s = getport (alport, family);
+       return s;
+    }
 
-    if (bind(s, (struct sockaddr *)&sockin, sizeof (sockin)) >= 0) {
-       if (alport) {
-           if (getsockname(s, (struct sockaddr *)&sockin, &len) < 0) {
-               (void) close(s);
-               return -1;
-           } else {
-               *alport = ntohs(sockin.sin_port);
+#ifdef KRB5_USE_INET6
+    if (*family == AF_INET6) {
+       struct sockaddr_in6 sockin6;
+       GETSOCKNAME_ARG3_TYPE len = sizeof(sockin6);
+
+       s = socket(AF_INET6, SOCK_STREAM, 0);
+       if (s < 0)
+           return (-1);
+
+       memset((char *) &sockin6, 0,sizeof(sockin6));
+       sockin6.sin6_family = AF_INET6;
+       sockin6.sin6_addr = in6addr_any;
+
+       if (bind(s, (struct sockaddr *)&sockin6, sizeof (sockin6)) >= 0) {
+           if (alport) {
+               if (getsockname(s, (struct sockaddr *)&sockin6, &len) < 0) {
+                   (void) close(s);
+                   return -1;
+               } else {
+                   *alport = ntohs(sockin6.sin6_port);
+               }
            }
+           return s;
        }
-       return s;
+
+       (void) close(s);
+       return -1;
+    }
+#endif
+
+    if (*family == AF_INET) {
+       struct sockaddr_in sockin;
+       GETSOCKNAME_ARG3_TYPE len = sizeof(sockin);
+
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s < 0)
+           return (-1);
+
+       memset((char *) &sockin, 0,sizeof(sockin));
+       sockin.sin_family = AF_INET;
+       sockin.sin_addr.s_addr = INADDR_ANY;
+
+       if (bind(s, (struct sockaddr *)&sockin, sizeof (sockin)) >= 0) {
+           if (alport) {
+               if (getsockname(s, (struct sockaddr *)&sockin, &len) < 0) {
+                   (void) close(s);
+                   return -1;
+               } else {
+                   *alport = ntohs(sockin.sin_port);
+               }
+           }
+           return s;
+       }
+
+       (void) close(s);
+       return -1;
     }
 
-    (void) close(s);
     return -1;
 }
 
@@ -1283,8 +1368,8 @@ int secondary;
    into all programs. */
 
 char *
-  strsave(sp)
-const char *sp;
+strsave(sp)
+    const char *sp;
 {
     register char *ret;
     
index 56fefc99af44be18322479bae479f7ae68f89580..6f7f447d99b4b3729eefa844a38fc0ec80f5f652 100644 (file)
@@ -768,7 +768,8 @@ void doit(f, fromp)
     (void) alarm(0);
     if (port != 0) {
        if (anyport) {
-           s = getport(0);
+           int addrfamily = AF_INET;
+           s = getport(0, &addrfamily);
        } else {
            int lport = IPPORT_RESERVED - 1;
            s = rresvport(&lport);