Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue with connecting to IPv6 link local address #3713

Closed
wfurt opened this issue Mar 28, 2019 · 3 comments

Comments

Projects
None yet
3 participants
@wfurt
Copy link

commented Mar 28, 2019

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

@gvanem

This comment has been minimized.

Copy link
Member

commented Mar 29, 2019

What if you try:

 snprintf(url, sizeof(url), "http://[%s%%d]/", ipv6, scope);

instead?

@bagder

This comment has been minimized.

Copy link
Member

commented Mar 29, 2019

Is #3655 the fix?

@wfurt

This comment has been minimized.

Copy link
Author

commented Mar 29, 2019

yes, I think #3655 is correct fix. The workaround I use is http://[%s%%25%d]/.
It seems like parsing did not like unencoded '%'

@wfurt wfurt closed this Mar 29, 2019

bagder added a commit that referenced this issue Apr 13, 2019

CURLOPT_ADDRESS_SCOPE: fix range check and more
Commit 9081014 fixed most of the confusing issues between scope id and
scope however 844896d added bad limits checking assuming that the scope
is being set and not the scope id.

I have fixed the documentation so it all refers to scope ids.

In addition Curl_if2ip refered to the scope id as remote_scope_id which
is incorrect, so I renamed it to local_scope_id.

Adjusted-by: Daniel Stenberg

Closes #3655
Closes #3765
Fixes #3713
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.