* sclient.c: Include fake-addrinfo.h. Include stdlib.h unconditionally.
authorKen Raeburn <raeburn@mit.edu>
Sat, 6 Apr 2002 00:20:53 +0000 (00:20 +0000)
committerKen Raeburn <raeburn@mit.edu>
Sat, 6 Apr 2002 00:20:53 +0000 (00:20 +0000)
(net_read): New function, borrowed from krb5_net_read.
(main): Use krb5_c_valid_cksumtype, net_read, getaddrinfo, getnameinfo.  Try
contacting each address for the host.

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

src/appl/sample/sclient/ChangeLog
src/appl/sample/sclient/sclient.c

index 50cd264920794310c8dce118044365a96c2d9418..4fdcef4ad55ba4e0915dac95b39d2e4a7dc3d6f9 100644 (file)
@@ -1,3 +1,11 @@
+2002-04-05  Ken Raeburn  <raeburn@mit.edu>
+
+       * sclient.c: Include fake-addrinfo.h.  Include stdlib.h
+       unconditionally.
+       (net_read): New function, borrowed from krb5_net_read.
+       (main): Use krb5_c_valid_cksumtype, net_read, getaddrinfo,
+       getnameinfo.  Try contacting each address for the host.
+
 2002-03-28  Ken Raeburn  <raeburn@mit.edu>
 
        * sclient.c: Include errno.h.
index a1fff5125dad8c85935857b71fe712517d7e2fdd..46877211b0d75003d0d432f924a9f6383fb7d53e 100644 (file)
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include "fake-addrinfo.h" /* not everyone implements getaddrinfo yet */
+
 #include <signal.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
-#else
-extern char *malloc();
-#endif
 
 #include "../sample.h"
 
@@ -59,16 +57,42 @@ extern char *malloc();
 #define GETSOCKNAME_ARG3_TYPE int
 #endif
 
+static int
+net_read(fd, buf, len)
+    int fd;
+    char *buf;
+    int len;
+{
+    int cc, len2 = 0;
+
+    do {
+       cc = SOCKET_READ((SOCKET)fd, buf, len);
+       if (cc < 0) {
+           if (SOCKET_ERRNO == SOCKET_EINTR)
+               continue;
+               
+               /* XXX this interface sucks! */
+        errno = SOCKET_ERRNO;    
+               
+           return(cc);          /* errno is already set */
+       }               
+       else if (cc == 0) {
+           return(len2);
+       } else {
+           buf += cc;
+           len2 += cc;
+           len -= cc;
+       }
+    } while (len > 0);
+    return(len2);
+}
+
 int
-main(argc, argv)
-int argc;
-char *argv[];
+main(int argc, char *argv[])
 {
-    struct servent *sp;
-    struct hostent *hp;
-    struct sockaddr_in sockin, lsockin;
+    struct addrinfo *ap, aihints;
+    int aierr;
     int sock;
-    GETSOCKNAME_ARG3_TYPE namelen;
     krb5_context context;
     krb5_data recv_data;
     krb5_data cksum_data;
@@ -79,6 +103,7 @@ char *argv[];
     krb5_ap_rep_enc_part *rep_ret;
     krb5_auth_context auth_context = 0;
     short xmitlen;
+    char *portstr;
     char *service = SAMPLE_SERVICE;
 
     if (argc != 2 && argc != 3 && argc != 4) {
@@ -93,76 +118,68 @@ char *argv[];
     }
 
     (void) signal(SIGPIPE, SIG_IGN);
-    if (!valid_cksumtype(CKSUMTYPE_CRC32)) {
-       com_err(argv[0], KRB5_PROG_SUMTYPE_NOSUPP, "while using CRC-32");
+
+    if (argc > 2)
+       portstr = argv[2];
+    else
+       portstr = SAMPLE_PORT;
+
+    memset(&aihints, 0, sizeof(aihints));
+    aihints.ai_socktype = SOCK_STREAM;
+    aierr = getaddrinfo(argv[1], portstr, &aihints, &ap);
+    if (aierr) {
+       fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: %s\n",
+               argv[0], argv[1], portstr, gai_strerror(aierr));
        exit(1);
     }
-
-    /* clear out the structure first */
-    (void) memset((char *)&sockin, 0, sizeof(sockin));
-
-    if (argc > 2) {
-       sockin.sin_family = AF_INET;
-       sockin.sin_port = htons(atoi(argv[2]));
-    } else {
-       /* find the port number for knetd */
-       sp = getservbyname(SAMPLE_PORT, "tcp");
-       if (!sp) {
-           fprintf(stderr,
-                   "unknown service %s/tcp; check /etc/services\n",
-                   SAMPLE_PORT);
-           exit(1);
-       }
-       /* copy the port number */
-       sockin.sin_port = sp->s_port;
-       sockin.sin_family = AF_INET;
+    if (ap == 0) {
+       /* Should never happen.  */
+       fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: no addresses returned?\n",
+               argv[0], argv[1], portstr);
+       exit(1);
     }
+
     if (argc > 3) {
        service = argv[3];
     }
 
-    /* look up the server host */
-    hp = gethostbyname(argv[1]);
-    if (!hp) {
-       fprintf(stderr, "unknown host %s\n",argv[1]);
-       exit(1);
-    }
-
     retval = krb5_sname_to_principal(context, argv[1], service,
                                     KRB5_NT_SRV_HST, &server);
     if (retval) {
-       com_err(argv[0], retval, "while creating server name for %s/%s",
+       com_err(argv[0], retval, "while creating server name for host %s service %s",
                argv[1], service);
        exit(1);
     }
 
     /* set up the address of the foreign socket for connect() */
-    sockin.sin_family = hp->h_addrtype;
-    (void) memcpy((char *)&sockin.sin_addr,
-                 (char *)hp->h_addr,
-                 sizeof(hp->h_addr));
-
-    /* open a TCP socket */
-    sock = socket(PF_INET, SOCK_STREAM, 0);
-    if (sock < 0) {
-       perror("socket");
-       exit(1);
-    }
-
-    /* connect to the server */
-    if (connect(sock, (struct sockaddr *)&sockin, sizeof(sockin)) < 0) {
-       perror("connect");
-       close(sock);
-       exit(1);
+    for (sock = -1; ap && sock == -1; ap = ap->ai_next) {
+       char abuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+       char mbuf[NI_MAXHOST + NI_MAXSERV + 64];
+       if (getnameinfo(ap->ai_addr, ap->ai_addrlen, abuf, sizeof(abuf),
+                       pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+           memset(abuf, 0, sizeof(abuf));
+           strncpy(abuf, "[error, cannot print address?]",
+                   sizeof(abuf)-1);
+           strcpy(pbuf, "[?]");
+       }
+       sprintf(mbuf, "error contacting %s port %s", abuf, pbuf);
+       sock = socket(ap->ai_family, SOCK_STREAM, 0);
+       if (sock < 0) {
+           fprintf(stderr, "%s: socket: %s\n", mbuf, strerror(errno));
+           continue;
+       }
+       if (connect(sock, ap->ai_addr, ap->ai_addrlen) < 0) {
+           fprintf(stderr, "%s: connect: %s\n", mbuf, strerror(errno));
+           close(sock);
+           sock = -1;
+           continue;
+       }
+       /* connected, yay! */
     }
-
-    /* find out who I am, now that we are connected and therefore bound */
-    namelen = sizeof(lsockin);
-    if (getsockname(sock, (struct sockaddr *) &lsockin, &namelen) < 0) {
-       perror("getsockname");
-       close(sock);
+    if (sock == -1)
+       /* Already printed error message above.  */
        exit(1);
-    }
+    printf("connected\n");
 
     cksum_data.data = argv[1];
     cksum_data.length = strlen(argv[1]);
@@ -203,8 +220,8 @@ char *argv[];
        krb5_free_ap_rep_enc_part(context, rep_ret);
 
        printf("sendauth succeeded, reply is:\n");
-       if ((retval = krb5_net_read(context, sock, (char *)&xmitlen,
-                                   sizeof(xmitlen))) <= 0) {
+       if ((retval = net_read(sock, (char *)&xmitlen,
+                              sizeof(xmitlen))) <= 0) {
            if (retval == 0)
                errno = ECONNABORTED;
            com_err(argv[0], errno, "while reading data from server");
@@ -216,8 +233,8 @@ char *argv[];
                    "while allocating buffer to read from server");
            exit(1);
        }
-       if ((retval = krb5_net_read(context, sock, (char *)recv_data.data,
-                                   recv_data.length)) <= 0) {
+       if ((retval = net_read(sock, (char *)recv_data.data,
+                              recv_data.length)) <= 0) {
            if (retval == 0)
                errno = ECONNABORTED;
            com_err(argv[0], errno, "while reading data from server");