chiark / gitweb /
Actually report "no such host" errors properly
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Thu, 29 Apr 2010 00:02:09 +0000 (01:02 +0100)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 22 May 2010 12:05:21 +0000 (13:05 +0100)
lib/remopen.c

index ab8a7705059571a07649ffc758a6b83b6cc90bb7..dfe08654dec98661287e1aaded6cc31cbf618f35 100644 (file)
 #include "nntp.h"
 #include "paths.h"
 
+/*
+** store an error message in buff like libinn(3) says NNTPconnect does
+*/
+static void store_error(char *buff, char *string1, char *string2) {
+    /* we put these in [...] to make it easier to tell them apart
+     * from messages sent by the server */
+    snprintf(buff, NNTP_STRLEN, "[%s%s]", string1, string2);
+    buff[NNTP_STRLEN-1] = 0;
+}
+
 /*
 **  Open a connection to an NNTP server and create stdio FILE's for talking
 **  to it.  Return -1 on error.
@@ -29,6 +39,7 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
     int                        i = -1;
     int                j;
     int                        oerrno;
+    int                        gai_r;
     FILE               *F;
 #ifdef HAVE_INET6
     struct addrinfo    hints, *ressave, *addr;
@@ -53,8 +64,11 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
     hints.ai_family = PF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
     sprintf(portbuf, "%d", port);
-    if (getaddrinfo(host, portbuf, &hints, &addr) != 0)
+    if ((gai_r = getaddrinfo(host, portbuf, &hints, &addr)) != 0) {
+       store_error(buff, "getaddrinfo failed: ", gai_strerror(gai_r));
+       errno = 0;
        return -1;
+    }
 
     for (ressave = addr; addr; addr = addr->ai_next) {
        if ((i = socket(addr->ai_family, addr->ai_socktype,
@@ -103,6 +117,7 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
        /* all connect(2) calls failed or some other error has occurred */
        oerrno = errno;
        close(i);
+       store_error(buff, "connect(s) failed: ", strerror(oerrno));
        errno = oerrno;
        return -1;
     }
@@ -120,9 +135,12 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
     }
     else if ((hp = gethostbyname(host)) != NULL)
        ap = hp->h_addr_list;
-    else
+    else {
        /* Not a host name. */
+       store_error(buff, "gethostbyname failed: ", hstrerror(h_errno));
+       errno = 0;
        return -1;
+    }
 
     /* Set up the socket address. */
     memset(&server, 0, sizeof server);
@@ -139,20 +157,31 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
     client.sin_len = sizeof( struct sockaddr_in );
 #endif
     if (innconf->sourceaddress) {
-        if (!inet_aton(innconf->sourceaddress, &client.sin_addr))
+        if (!inet_aton(innconf->sourceaddress, &client.sin_addr)) {
+           store_error(buff, "inet_aton failed on innconf's"
+                       " source address: ", innconf->sourceaddress);
+           errno = EINVAL;
            return -1;
+       }
     } else
        client.sin_addr.s_addr = htonl(INADDR_ANY);
-  
+
     /* Loop through the address list, trying to connect. */
     for (; ap && *ap; ap++) {
        /* Make a socket and try to connect. */
-       if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
+       if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
+           if (!buff[0]) {
+               oerrno = errno;
+               store_error(buff, "create socket failed: ", strerror(oerrno));
+               errno = oerrno;
+           }
            break;
+       }
        /* Bind to the source address we want. */
        if (bind(i, (struct sockaddr *)&client, sizeof client) < 0) {
            oerrno = errno;
            close(i);
+           store_error(buff, "bind failed: ", strerror(oerrno));
            errno = oerrno;
            continue;
        }
@@ -164,6 +193,7 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
        if (connect(i, (struct sockaddr *)&server, sizeof server) < 0) {
            oerrno = errno;
            close(i);
+           store_error(buff, "connect failed: ", strerror(oerrno));
            errno = oerrno;
            continue;
        }
@@ -174,9 +204,13 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
            oerrno = errno;
            close(i);
            errno = oerrno;
+           store_error(buff, "fdopen failed: ", strerror(oerrno));
+           errno = EINVAL;
            return -1;
        }
        if (fgets(buff, sizeof mybuff, F) == NULL) {
+           if (ferror(F)) store_error(buff, "peer closed connection","");
+           else store_error(buff, "fgets failed: ", strerror(errno));
            oerrno = errno;
            fclose(F);
            errno = oerrno;
@@ -194,12 +228,16 @@ int NNTPconnect(char *host, int port, FILE **FromServerp, FILE **ToServerp, char
        if ((*ToServerp = fdopen(dup(i), "w")) == NULL) {
            oerrno = errno;
            fclose(F);
+           store_error(buff, "fdopen/dup failed: ", strerror(oerrno));
            errno = oerrno;
            return -1;
        }
        return 0;
     }
 
+    if (!buff[0])
+       store_error(buff, "no address(es) for host","");
+
     return -1;
 }