I did this
I consider following fragment using libcurl C API:
(this is great simplification to illustrate the issues)
CURLcode fetch(CURL *curl, char *ipv6, int scope)
{
char url[256];
snprintf(url, sizeof(url), "http://[%s]/", ipv6);
CURLcode ret;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, scope);
return curl_easy_perform(curl);
}
This was working as expected but it fails inside container running Alpine 3.9. (libcurl 7.64.0)
bash-4.4$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
129: eth0@if130: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
bash-4.4$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
129: eth0@if130: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fc00::242:ac11:4/64 scope global flags 02
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:4/64 scope link
valid_lft forever preferred_lft forever
The issue with docker is that it uses high interface index number and than:
https://github.com/curl/curl/blob/master/lib/setopt.c#L2302-L2312
case CURLOPT_ADDRESS_SCOPE:
/*
* We always get longs when passed plain numericals, but for this value we
* know that an unsigned int will always hold the value so we blindly
* typecast to this type
*/
arg = va_arg(param, long);
if((arg < 0) || (arg > 0xf))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.scope_id = curlx_sltoui(arg);
break;
after some digging I found workaround where I can insert scope_id to URL and the code in url.c would take it out and set scope_id to proper value:
https://github.com/curl/curl/blob/master/lib/url.c#L2177
conn->scope_id = (unsigned int)scope;
...
if(data->set.scope_id)
/* Override any scope that was set above. */
conn->scope_id = data->set.scope_id;
I verified with strace that we pass correct sockaddr_in6 to connect() call.
It seems like the argument check for CURLOPT_ADDRESS_SCOPE is incorrect and we should let OS decide if it is valid or not.
I verified that if removed, the code works ok. There should be no harm to existing use.
I'd be happy to craft PR.
I expected the following
I expect this to work consistently, docker or not.
curl/libcurl version
bash-4.4$ curl --version
curl 7.64.0 (x86_64-alpine-linux-musl) libcurl/7.64.0 OpenSSL/1.1.1a zlib/1.2.11 libssh2/1.8.2 nghttp2/1.35.1
Release-Date: 2019-02-06
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy
operating system
Alpine Linux 3.9
I did this
I consider following fragment using libcurl C API:
(this is great simplification to illustrate the issues)
This was working as expected but it fails inside container running Alpine 3.9. (libcurl 7.64.0)
The issue with docker is that it uses high interface index number and than:
https://github.com/curl/curl/blob/master/lib/setopt.c#L2302-L2312
after some digging I found workaround where I can insert scope_id to URL and the code in url.c would take it out and set scope_id to proper value:
https://github.com/curl/curl/blob/master/lib/url.c#L2177
I verified with
stracethat we pass correctsockaddr_in6to connect() call.It seems like the argument check for CURLOPT_ADDRESS_SCOPE is incorrect and we should let OS decide if it is valid or not.
I verified that if removed, the code works ok. There should be no harm to existing use.
I'd be happy to craft PR.
I expected the following
I expect this to work consistently, docker or not.
curl/libcurl version
bash-4.4$ curl --version
curl 7.64.0 (x86_64-alpine-linux-musl) libcurl/7.64.0 OpenSSL/1.1.1a zlib/1.2.11 libssh2/1.8.2 nghttp2/1.35.1
Release-Date: 2019-02-06
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy
operating system
Alpine Linux 3.9