svn commit: r315455 - head/lib/libfetch
Dag-Erling Smørgrav
des at FreeBSD.org
Fri Mar 17 14:18:53 UTC 2017
Author: des
Date: Fri Mar 17 14:18:52 2017
New Revision: 315455
URL: https://svnweb.freebsd.org/changeset/base/315455
Log:
r308996 broke IP literals by assuming that a colon could only occur as
a separator between host and port, and using strchr() to search for it.
Rewrite fetch_resolve() so it handles bracketed literals correctly, and
remove similar code elsewhere to avoid passing unbracketed literals to
fetch_resolve(). Remove #ifdef INET6 so we still parse IP literals
correctly even if we do not have the ability to connect to them.
While there, fix an off-by-one error which caused HTTP 400 errors to be
misinterpreted as redirects.
PR: 217723
MFC after: 1 week
Reported by: bapt, bz, cem, ngie
Modified:
head/lib/libfetch/common.c
head/lib/libfetch/fetch.c
head/lib/libfetch/http.c
Modified: head/lib/libfetch/common.c
==============================================================================
--- head/lib/libfetch/common.c Fri Mar 17 13:49:05 2017 (r315454)
+++ head/lib/libfetch/common.c Fri Mar 17 14:18:52 2017 (r315455)
@@ -248,37 +248,51 @@ fetch_resolve(const char *addr, int port
{
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);
- }
- if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0) {
- fetch_syserr();
- return (NULL);
+ goto syserr;
}
- 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
return (NULL);
}
return (res);
+syserr:
+ fetch_syserr();
+ return (NULL);
}
Modified: head/lib/libfetch/fetch.c
==============================================================================
--- head/lib/libfetch/fetch.c Fri Mar 17 13:49:05 2017 (r315454)
+++ head/lib/libfetch/fetch.c Fri Mar 17 14:18:52 2017 (r315455)
@@ -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));
Modified: head/lib/libfetch/http.c
==============================================================================
--- head/lib/libfetch/http.c Fri Mar 17 13:49:05 2017 (r315454)
+++ head/lib/libfetch/http.c Fri Mar 17 14:18:52 2017 (r315455)
@@ -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
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 */
More information about the svn-src-all
mailing list