From 14fcd5f3a3a5611a61cb6e9861113b0c16579d84 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 May 2019 09:43:10 +0200 Subject: url: convert the zone id from a IPv6 URL to correct scope id Reported-by: GitYuanQu on github Fixes #3902 --- lib/url.c | 65 +++++++++++++++++++++------------------------------------------ 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/lib/url.c b/lib/url.c index 944754816..c441ae716 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2002,61 +2002,40 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, hostname = (char *)""; if(hostname[0] == '[') { - /* This looks like an IPv6 address literal. See if there is an address + /* This looks like an IPv6 address literal. See if there is an address scope. */ - char *percent = strchr(++hostname, '%'); + char *zoneid; + size_t hlen; + uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0); conn->bits.ipv6_ip = TRUE; - if(percent) { - unsigned int identifier_offset = 3; + + /* cut off the brackets! */ + hostname++; + hlen = strlen(hostname); + hostname[hlen - 1] = 0; + if(!uc && zoneid) { char *endp; unsigned long scope; - if(strncmp("%25", percent, 3) != 0) { - infof(data, - "Please URL encode %% as %%25, see RFC 6874.\n"); - identifier_offset = 1; - } - scope = strtoul(percent + identifier_offset, &endp, 10); - if(*endp == ']') { - /* The address scope was well formed. Knock it out of the - hostname. */ - memmove(percent, endp, strlen(endp) + 1); + scope = strtoul(zoneid, &endp, 10); + if(!*endp && (scope < UINT_MAX)) { + /* A plain number, use it direcly as a scope id. */ conn->scope_id = (unsigned int)scope; } +#ifdef HAVE_IF_NAMETOINDEX else { /* Zone identifier is not numeric */ -#if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX) - char ifname[IFNAMSIZ + 2]; - char *square_bracket; unsigned int scopeidx = 0; - strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2); - /* Ensure nullbyte termination */ - ifname[IFNAMSIZ + 1] = '\0'; - square_bracket = strchr(ifname, ']'); - if(square_bracket) { - /* Remove ']' */ - *square_bracket = '\0'; - scopeidx = if_nametoindex(ifname); - if(scopeidx == 0) { - infof(data, "Invalid network interface: %s; %s\n", ifname, - strerror(errno)); - } - } - if(scopeidx > 0) { - char *p = percent + identifier_offset + strlen(ifname); - - /* Remove zone identifier from hostname */ - memmove(percent, p, strlen(p) + 1); - conn->scope_id = scopeidx; - } + scopeidx = if_nametoindex(zoneid); + if(!scopeidx) + infof(data, "Invalid zoneid id: %s; %s\n", zoneid, + strerror(errno)); else -#endif /* HAVE_NET_IF_H && IFNAMSIZ */ - infof(data, "Invalid IPv6 address format\n"); + conn->scope_id = scopeidx; + } +#endif /* HAVE_IF_NAMETOINDEX */ + free(zoneid); } - percent = strchr(hostname, ']'); - if(percent) - /* terminate IPv6 numerical at end bracket */ - *percent = 0; } /* make sure the connect struct gets its own copy of the host name */ -- cgit v1.2.1