diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index ba3217aa8a9..78e214b0eb9 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -248,37 +248,51 @@ fetch_resolve(const char *addr, int port, int af) { char hbuf[256], sbuf[8]; struct addrinfo hints, *res; - const char *sep, *host, *service; + const char *hb, *he, *sep; + const char *host, *service; int err, len; - /* split address if necessary */ - err = EAI_SYSTEM; - if ((sep = strchr(addr, ':')) != NULL) { + /* first, check for a bracketed IPv6 address */ + if (*addr == '[') { + hb = addr + 1; + if ((sep = strchr(hb, ']')) == NULL) { + errno = EINVAL; + goto syserr; + } + he = sep++; + } else { + hb = addr; + sep = strchrnul(hb, ':'); + he = sep; + } + + /* see if we need to copy the host name */ + if (*he != '\0') { len = snprintf(hbuf, sizeof(hbuf), - "%.*s", (int)(sep - addr), addr); + "%.*s", (int)(he - hb), hb); if (len < 0) - return (NULL); + goto syserr; if (len >= (int)sizeof(hbuf)) { errno = ENAMETOOLONG; - fetch_syserr(); - return (NULL); + goto syserr; } host = hbuf; - service = sep + 1; - } else if (port != 0) { + } else { + host = hb; + } + + /* was it followed by a service name? */ + if (*sep == '\0' && port != 0) { if (port < 1 || port > 65535) { errno = EINVAL; - fetch_syserr(); - return (NULL); + goto syserr; } - if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0) { - fetch_syserr(); - return (NULL); - } - host = addr; + if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0) + goto syserr; service = sbuf; + } else if (*sep != '\0') { + service = sep; } else { - host = addr; service = NULL; } @@ -292,6 +306,9 @@ fetch_resolve(const char *addr, int port, int af) return (NULL); } return (res); +syserr: + fetch_syserr(); + return (NULL); } diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c index dd6b98f04bb..f2510831c00 100644 --- a/lib/libfetch/fetch.c +++ b/lib/libfetch/fetch.c @@ -386,18 +386,17 @@ fetchParseURL(const char *URL) } /* hostname */ -#ifdef INET6 if (*p == '[' && (q = strchr(p + 1, ']')) != NULL && (*++q == '\0' || *q == '/' || *q == ':')) { - if ((i = q - p - 2) > MAXHOSTNAMELEN) + if ((i = q - p) > MAXHOSTNAMELEN) i = MAXHOSTNAMELEN; - strncpy(u->host, ++p, i); + strncpy(u->host, p, i); p = q; - } else -#endif + } else { for (i = 0; *p && (*p != '/') && (*p != ':'); p++) if (i < MAXHOSTNAMELEN) u->host[i++] = *p; + } /* port */ if (*p == ':') { @@ -444,12 +443,12 @@ nohost: } DEBUG(fprintf(stderr, - "scheme: [%s]\n" - "user: [%s]\n" - "password: [%s]\n" - "host: [%s]\n" - "port: [%d]\n" - "document: [%s]\n", + "scheme: \"%s\"\n" + "user: \"%s\"\n" + "password: \"%s\"\n" + "host: \"%s\"\n" + "port: \"%d\"\n" + "document: \"%s\"\n", u->scheme, u->user, u->pwd, u->host, u->port, u->doc)); diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index 7e60f8b9118..fe4e9dec63d 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -118,7 +118,7 @@ __FBSDID("$FreeBSD$"); || (xyz) == HTTP_USE_PROXY \ || (xyz) == HTTP_SEE_OTHER) -#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599) +#define HTTP_ERROR(xyz) ((xyz) >= 400 && (xyz) <= 599) /***************************************************************************** @@ -1604,20 +1604,11 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us, if ((conn = http_connect(url, purl, flags)) == NULL) goto ouch; + /* append port number only if necessary */ host = url->host; -#ifdef INET6 - if (strchr(url->host, ':')) { - snprintf(hbuf, sizeof(hbuf), "[%s]", url->host); - host = hbuf; - } -#endif if (url->port != fetch_default_port(url->scheme)) { - if (host != hbuf) { - strcpy(hbuf, host); - host = hbuf; - } - snprintf(hbuf + strlen(hbuf), - sizeof(hbuf) - strlen(hbuf), ":%d", url->port); + snprintf(hbuf, sizeof(hbuf), "%s:%d", host, url->port); + host = hbuf; } /* send request */