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

fix DNS resolution in ping6 #13450

Merged
merged 5 commits into from
Feb 24, 2020
Merged

fix DNS resolution in ping6 #13450

merged 5 commits into from
Feb 24, 2020

Conversation

benpicco
Copy link
Contributor

@benpicco benpicco commented Feb 22, 2020

Contribution description

Previously DNS resolution in ping6 would always fail.
This was due to a slew of minor bugs in sock_dns and gnrc_icmpv6_echo.
This PR fixes them, so DNS resolution is working properly now.

Testing procedure

If you are using a board with direct WiFi or Ethernet connection (e.g. esp8266 or esp32), it should suffice to add USEMODULE += sock_dns to examples/gnrc_networking.

On a 6LoWPAN device, the border router (examples/gnrc_border_router) doesn't seem to forward DNS information, so you have to resort to tests/gnrc_sock_dns to being able to set the DNS server manually by calling e.g. dns server 2620:119:35::35:.

You should now be able to ping a host by name:

2020-02-22 20:10:44,986 #  ping6 riot-os.org
2020-02-22 20:10:45,114 # 12 bytes from 2a01:4f8:151:64::11: icmp_seq=0 ttl=56 time=71.772 ms
2020-02-22 20:10:46,071 # 12 bytes from 2a01:4f8:151:64::11: icmp_seq=1 ttl=56 time=29.318 ms
2020-02-22 20:10:47,122 # 12 bytes from 2a01:4f8:151:64::11: icmp_seq=2 ttl=56 time=79.199 ms

Issues/PRs references

fixes #13447
follow-up on #13443

@benpicco benpicco added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Area: network Area: Networking labels Feb 22, 2020
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Feb 22, 2020
sys/net/application_layer/dns/dns.c Show resolved Hide resolved
sys/net/application_layer/dns/dns.c Outdated Show resolved Hide resolved
sys/net/application_layer/dns/dns.c Outdated Show resolved Hide resolved
@benpicco benpicco removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Feb 23, 2020
Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/gnrc_sock_udp is failing with this PR. On master it still works.

sys/net/application_layer/dns/dns.c Outdated Show resolved Hide resolved
@benpicco
Copy link
Contributor Author

I restored the test to use AF_UNSPEC and sock_dns_query() to return the size of the address again, updated the documentation to reflect that.

The test is passing now again on native.

@miri64 miri64 added the Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. label Feb 24, 2020
@miri64
Copy link
Member

miri64 commented Feb 24, 2020

I've marked it as an API change due to the doc change. However, since the doc is just adopted to the behavior, I don't think we need two ACKs here.

@miri64 miri64 added the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Feb 24, 2020
Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on native and samr21-xpro using tests/gnrc_sock_dns (don't have the set-up here to test with the border router and ping6 but I trust your testing there). One minor nit, to prevent errors introduced in future fixes. Other than that you may squash.


sock_dns_hdr_t *hdr = (sock_dns_hdr_t*) buf;
memset(hdr, 0, sizeof(*hdr));
hdr->id = 0; /* random? */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is just pulled down, but this should at least come from a variable now, that it is re-set on every retry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

random_bytes(&hdr->id, sizeof(hdr->id));?

Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't overshoot ;-)

sys/net/application_layer/dns/dns.c Outdated Show resolved Hide resolved
We need to set `res` to 0 to signal success, otherwise we end up
in the print usage case.
When using ping6 with an IP address, don't do a DNS lookup.
Hostnames can't contain ':', so use that to tell them apart
from plain IP addressees.
@miri64
Copy link
Member

miri64 commented Feb 24, 2020

Regarding the border router not forwarding the RDNSS option:

  1. Did you set GNRC_IPV6_NIB_CONF_DNS=1?
  2. Is sock_dns_server set correctly in _handle_rdnsso()?
    #if GNRC_IPV6_NIB_CONF_DNS
    static uint32_t _handle_rdnsso(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
    const ndp_opt_rdnss_impl_t *rdnsso)
    {
    uint32_t ltime = UINT32_MAX;
    const ipv6_addr_t *addr;
    if ((rdnsso->len < NDP_OPT_RDNSS_MIN_LEN) ||
    (icmpv6->type != ICMPV6_RTR_ADV)) {
    return ltime;
    }
    /* select first if unassigned, search possible address otherwise */
    addr = (sock_dns_server.port == 0) ? &rdnsso->addrs[0] : NULL;
    if (addr == NULL) {
    unsigned addrs_num = (rdnsso->len - 1) / 2;
    for (unsigned i = 0; i < addrs_num; i++) {
    if (memcmp(sock_dns_server.addr.ipv6,
    &rdnsso->addrs[i],
    sizeof(rdnsso->addrs[i])) == 0) {
    addr = &rdnsso->addrs[i];
    break;
    }
    }
    }
    #if SOCK_HAS_IPV6
    ltime = byteorder_ntohl(rdnsso->ltime);
    if (addr != NULL) {
    if (ltime > 0) {
    sock_dns_server.port = SOCK_DNS_PORT;
    sock_dns_server.family = AF_INET6;
    sock_dns_server.netif = netif->pid;
    memcpy(sock_dns_server.addr.ipv6, rdnsso->addrs,
    sizeof(sock_dns_server.addr.ipv6));
    if (ltime < UINT32_MAX) {
    /* the valid lifetime is given in seconds, but our timers work
    * in milliseconds, so we have to scale down to the smallest
    * possible value (UINT32_MAX - 1). This is however alright
    * since we ask for a new router advertisement before this
    * timeout expires */
    ltime = (ltime > (UINT32_MAX / MS_PER_SEC)) ?
    (UINT32_MAX - 1) : ltime * MS_PER_SEC;
    _evtimer_add(&sock_dns_server, GNRC_IPV6_NIB_RDNSS_TIMEOUT,
    &_rdnss_timeout, ltime);
    }
    }
    else {
    evtimer_del(&_nib_evtimer, &_rdnss_timeout.event);
    _handle_rdnss_timeout(&sock_dns_server);
    }
    }
    #else
    (void)addr;
    #endif
    return ltime;
    }
    #endif
  3. Is the option for the sent router advertisement constructed correctly in _build_ext_opts()?
    #if GNRC_IPV6_NIB_CONF_DNS && SOCK_HAS_IPV6
    uint32_t rdnss_ltime = _evtimer_lookup(&sock_dns_server,
    GNRC_IPV6_NIB_RDNSS_TIMEOUT);
    if ((rdnss_ltime < UINT32_MAX) &&
    (!ipv6_addr_is_link_local((ipv6_addr_t *)sock_dns_server.addr.ipv6))) {
    gnrc_pktsnip_t *rdnsso = gnrc_ndp_opt_rdnss_build(
    rdnss_ltime * MS_PER_SEC,
    (ipv6_addr_t *)&sock_dns_server.addr,
    1U, ext_opts
    );
    if (rdnsso == NULL) {
    /* gnrc_ndp_opt_rdnss_build() only returns NULL when pktbuf is full
    * in this configuration */
    DEBUG("nib: No space left in packet buffer. Not adding RDNSSO\n");
    return NULL;
    }
    ext_opts = rdnsso;
    }
    #endif /* GNRC_IPV6_NIB_CONF_DNS */

Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-ACK

benpicco and others added 2 commits February 24, 2020 14:29
Saving RAM is more important than saving a few cycles
used by re-creating the request buffer in the error case.

Also reduce the size of the buffer to 128 bytes.
If we are just requesting the AAAA record it is unlikely
for the reply to take up the maximum size of 512 bytes.

We were already placing restrictions on the domain name length,
those are now actually a bit more relaxed (112 bytes instead of 64)
The implementation already did that, now also reflect this in the
documentation.
@benpicco
Copy link
Contributor Author

Did you set GNRC_IPV6_NIB_CONF_DNS=1?

I didn't know such option exists, but it gets set automatically if gnrc_ipv6_nib_dns is used - for tests/gnrc_sock_dns this is the case.

I will investigate the 2. & 3. when I'm home.

@miri64
Copy link
Member

miri64 commented Feb 24, 2020

I didn't know such option exists, but it gets set automatically if gnrc_ipv6_nib_dns is used - for tests/gnrc_sock_dns this is the case.

I will investigate the 2. & 3. when I'm home.

but not for gnrc_border_router, right?

@benpicco benpicco removed the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Feb 24, 2020
@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Feb 24, 2020
@benpicco benpicco merged commit d044800 into RIOT-OS:master Feb 24, 2020
@benpicco benpicco deleted the dns-fixes branch February 24, 2020 20:58
@benpicco
Copy link
Contributor Author

When I add gnrc_ipv6_nib_dns to gnrc_border_router it will indeed forward the DNS server information!

@benpicco
Copy link
Contributor Author

benpicco commented Feb 24, 2020

And with CFLAGS += -DTHREAD_STACKSIZE_MAIN=1024 the crashes on ATmega also stop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

gnrc_sock_dns is not working
3 participants