Based on Job's work lets introduce conn_info() which prints the URI / host plus the IP address. This may be helpful to better understand errors.
With this ip_info() becomes much simpler. I also decided to not check snprintf returns because the buffer is big enough and afaik encoding errors can't happen with %s. In http_connect() when hitting the error case after the for () loop needs a to set conn->res to the last valid res used else it will print (unknown) for the IP (since conn->res is NULL at that time). With this the errors will show up like this: rpki-client: Error retrieving https://rpki.luys.cloud/rrdp/notification.xml (54.254.122.29): 504 Gateway Time-out rpki-client: https://rpki.sailx.co/rrdp/notification.xml (208.82.103.214): TLS handshake: certificate verification failed: certificate has expired rpki-client: https://chloe.sobornost.net/rpki/news-public.xml (127.0.0.2): connect: Network is unreachable rpki-client: https://rpki1.terratransit.de/rrdp/notification.xml (2a01:6f0:101:17::1): connect timeout rpki-client: https://rpki1.terratransit.de/rrdp/notification.xml (77.237.224.23): connect timeout -- :wq Claudio Index: http.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v retrieving revision 1.72 diff -u -p -r1.72 http.c --- http.c 2 Nov 2022 11:44:19 -0000 1.72 +++ http.c 2 Nov 2022 14:20:31 -0000 @@ -215,23 +215,30 @@ http_info(const char *uri) static const char * ip_info(const struct http_connection *conn) { - static char buf[NI_MAXHOST + 3]; - char ipbuf[NI_MAXHOST]; - int ret; - - assert(conn->state == STATE_CONNECT); + static char ipbuf[NI_MAXHOST]; if (conn->res == NULL) - return (" (unknown)"); + return "unknown"; if (getnameinfo(conn->res->ai_addr, conn->res->ai_addrlen, ipbuf, sizeof(ipbuf), NULL, 0, NI_NUMERICHOST) != 0) - return (" (unknown)"); + return "unknown"; - ret = snprintf(buf, sizeof(buf), " (%s)", ipbuf); - if (ret < 0 || (size_t)ret >= sizeof(buf)) - err(1, NULL); + return ipbuf; +} +static const char * +conn_info(const struct http_connection *conn) +{ + static char buf[100 + NI_MAXHOST]; + const char *uri; + + if (conn->req == NULL) + uri = conn->host; + else + uri = conn->req->uri; + + snprintf(buf, sizeof(buf), "%s (%s)", http_info(uri), ip_info(conn)); return buf; } @@ -818,7 +825,7 @@ http_do(struct http_connection *conn, en break; default: errx(1, "%s: unexpected function return", - http_info(conn->host)); + conn_info(conn)); } } @@ -840,6 +847,7 @@ static enum res http_connect(struct http_connection *conn) { const char *cause = NULL; + struct addrinfo *res; assert(conn->fd == -1); conn->state = STATE_CONNECT; @@ -850,9 +858,9 @@ http_connect(struct http_connection *con else conn->res = conn->res->ai_next; for (; conn->res != NULL; conn->res = conn->res->ai_next) { - struct addrinfo *res = conn->res; int fd, save_errno; + res = conn->res; fd = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK, res->ai_protocol); if (fd == -1) { @@ -891,8 +899,10 @@ http_connect(struct http_connection *con } if (conn->fd == -1) { - if (cause != NULL) - warn("%s: %s", http_info(conn->req->uri), cause); + if (cause != NULL) { + conn->res = res; + warn("%s: %s", conn_info(conn), cause); + } return http_failed(conn); } @@ -910,12 +920,12 @@ http_finish_connect(struct http_connecti len = sizeof(error); if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { - warn("%s: getsockopt SO_ERROR", http_info(conn->req->uri)); + warn("%s: getsockopt SO_ERROR", conn_info(conn)); return http_connect_failed(conn); } if (error != 0) { errno = error; - warn("%s: connect", http_info(conn->req->uri)); + warn("%s: connect", conn_info(conn)); return http_connect_failed(conn); } @@ -936,12 +946,12 @@ http_tls_connect(struct http_connection return http_failed(conn); } if (tls_configure(conn->tls, tls_config) == -1) { - warnx("%s: TLS configuration: %s\n", http_info(conn->req->uri), + warnx("%s: TLS configuration: %s\n", conn_info(conn), tls_error(conn->tls)); return http_failed(conn); } if (tls_connect_socket(conn->tls, conn->fd, conn->host) == -1) { - warnx("%s: TLS connect: %s\n", http_info(conn->req->uri), + warnx("%s: TLS connect: %s\n", conn_info(conn), tls_error(conn->tls)); return http_failed(conn); } @@ -957,7 +967,7 @@ http_tls_handshake(struct http_connectio { switch (tls_handshake(conn->tls)) { case -1: - warnx("%s: TLS handshake: %s", http_info(conn->req->uri), + warnx("%s: TLS handshake: %s", conn_info(conn), tls_error(conn->tls)); return http_failed(conn); case TLS_WANT_POLLIN: @@ -1089,7 +1099,7 @@ http_parse_status(struct http_connection cp = strchr(buf, ' '); if (cp == NULL) { - warnx("Improper response from %s", http_info(conn->host)); + warnx("Improper response from %s", conn_info(conn)); return -1; } else cp++; @@ -1098,7 +1108,7 @@ http_parse_status(struct http_connection status = strtonum(ststr, 100, 599, &errstr); if (errstr != NULL) { strnvis(gerror, cp, sizeof gerror, VIS_SAFE); - warnx("Error retrieving %s: %s", http_info(conn->host), + warnx("Error retrieving %s: %s", conn_info(conn), gerror); return -1; } @@ -1111,7 +1121,7 @@ http_parse_status(struct http_connection case 308: /* Redirect: permanent redirect */ if (conn->req->redirect_loop++ > 10) { warnx("%s: Too many redirections requested", - http_info(conn->host)); + conn_info(conn)); return -1; } /* FALLTHROUGH */ @@ -1125,7 +1135,7 @@ http_parse_status(struct http_connection break; default: strnvis(gerror, cp, sizeof gerror, VIS_SAFE); - warnx("Error retrieving %s: %s", http_info(conn->host), + warnx("Error retrieving %s: %s", conn_info(conn), gerror); return -1; } @@ -1202,7 +1212,7 @@ http_parse_header(struct http_connection conn->iosz = strtonum(cp, 0, MAX_CONTENTLEN, &errstr); if (errstr != NULL) { warnx("Content-Length of %s is %s", - http_info(conn->req->uri), errstr); + conn_info(conn), errstr); return -1; } } else if (http_isredirect(conn) && @@ -1344,7 +1354,7 @@ read_more: s = tls_read(conn->tls, conn->buf + conn->bufpos, conn->bufsz - conn->bufpos); if (s == -1) { - warnx("%s: TLS read: %s", http_info(conn->host), + warnx("%s: TLS read: %s", conn_info(conn), tls_error(conn->tls)); return http_failed(conn); } else if (s == TLS_WANT_POLLIN) { @@ -1356,7 +1366,7 @@ read_more: if (s == 0) { if (conn->req) warnx("%s: short read, connection closed", - http_info(conn->req->uri)); + conn_info(conn)); return http_failed(conn); } @@ -1474,7 +1484,7 @@ again: if (buf == NULL) goto read_more; if (http_parse_chunked(conn, buf) != 0) { - warnx("%s: bad chunk encoding", http_info(conn->host)); + warnx("%s: bad chunk encoding", conn_info(conn)); free(buf); return http_failed(conn); } @@ -1495,7 +1505,7 @@ again: goto read_more; /* expect empty line to finish a chunk of data */ if (*buf != '\0') { - warnx("%s: bad chunk encoding", http_info(conn->host)); + warnx("%s: bad chunk encoding", conn_info(conn)); free(buf); return http_failed(conn); } @@ -1533,7 +1543,7 @@ http_write(struct http_connection *conn) s = tls_write(conn->tls, conn->buf + conn->bufpos, conn->bufsz - conn->bufpos); if (s == -1) { - warnx("%s: TLS write: %s", http_info(conn->host), + warnx("%s: TLS write: %s", conn_info(conn), tls_error(conn->tls)); return http_failed(conn); } else if (s == TLS_WANT_POLLIN) { @@ -1568,14 +1578,14 @@ proxy_read(struct http_connection *conn) s = read(conn->fd, conn->buf + conn->bufpos, conn->bufsz - conn->bufpos); if (s == -1) { - warn("%s: read", http_info(conn->host)); + warn("%s: read", conn_info(conn)); return http_failed(conn); } if (s == 0) { if (conn->req) warnx("%s: short read, connection closed", - http_info(conn->host)); + conn_info(conn)); return http_failed(conn); } @@ -1629,7 +1639,7 @@ proxy_write(struct http_connection *conn s = write(conn->fd, conn->buf + conn->bufpos, conn->bufsz - conn->bufpos); if (s == -1) { - warn("%s: write", http_info(conn->host)); + warn("%s: write", conn_info(conn)); return http_failed(conn); } conn->bufpos += s; @@ -1692,13 +1702,13 @@ data_write(struct http_connection *conn) s = write(conn->req->outfd, conn->buf, bsz); if (s == -1) { - warn("%s: data write", http_info(conn->req->uri)); + warn("%s: data write", conn_info(conn)); return http_failed(conn); } conn->totalsz += s; if (conn->totalsz > MAX_CONTENTLEN) { - warn("%s: too much data offered", http_info(conn->req->uri)); + warn("%s: too much data offered", conn_info(conn)); return http_failed(conn); } @@ -1946,13 +1956,12 @@ proc_http(char *bind_addr, int fd) http_do(conn, http_handle); else if (conn->io_time <= now) { if (conn->state == STATE_CONNECT) { - warnx("%s%s: connect timeout", - ip_info(conn), - http_info(conn->host)); + warnx("%s: connect timeout", + conn_info(conn)); http_do(conn, http_connect_failed); } else { warnx("%s: timeout, connection closed", - http_info(conn->host)); + conn_info(conn)); http_do(conn, http_failed); } }