diff options
author | Daniel Stenberg <daniel@haxx.se> | 2019-05-21 09:43:10 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2019-05-21 18:58:45 +0200 |
commit | 8fba2d6a6b15ca287740a36715d679825c38df83 (patch) | |
tree | 1e67f92d5dafc46ab8c2e36885849899493d8521 /lib/url.c | |
parent | 9406d93e77e7923e2788e43df50cf3a577f1c42b (diff) | |
download | curl-8fba2d6a6b15ca287740a36715d679825c38df83.tar.gz |
url: convert the zone id from a IPv6 URL to correct scope id
Reported-by: GitYuanQu on github
Fixes #3902
Closes #3914
Diffstat (limited to 'lib/url.c')
-rw-r--r-- | lib/url.c | 65 |
1 files changed, 22 insertions, 43 deletions
@@ -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 */ |