[GH-ISSUE #105] Add a IpAddr conversion to Name for ease of use #54

Closed
opened 2026-03-07 22:18:22 +03:00 by kerem · 6 comments
Owner

Originally created by @mersinvald on GitHub (Mar 18, 2017).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/105

I'm trying to query domain names from IP addresses. Here is how I do it (using 8.8.8.8 nameserver):

let ip = "93.158.134.3"; // A record is www.yandex.ru
let labels = ip.split('.').map(str::to_owned).collect();
client.query(
    Name::with_labels(labels), 
    DNSClass::IN, 
    RecordType::PTR,
)

Message I get as a result:

Message { header: Header { id: 21949, message_type: Response, op_code: Query, authoritative: false, truncation: false, recursion_desired: true, recursion_available: true, authentic_data: false, checking_disabled: false, response_code: 3, query_count: 1, answer_count: 0, name_server_count: 1, additional_count: 1 }, queries: [Query { name: Name { labels: ["93", "158", "134", "3"] }, query_type: PTR, query_class: IN }], answers: [], name_servers: [Record { name_labels: Name { labels: [] }, rr_type: SOA, dns_class: IN, ttl: 86383, rdata: SOA(SOA { mname: Name { labels: ["a", "root-servers", "net"] }, rname: Name { labels: ["nstld", "verisign-grs", "com"] }, serial: 2017031801, refresh: 1800, retry: 900, expire: 604800, minimum: 86400 }) }], additionals: [], sig0: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 512, options: OPT { options: {} } }) }

So, answers is empty.
Is there my mistake in this query or that's a bug?

Originally created by @mersinvald on GitHub (Mar 18, 2017). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/105 I'm trying to query domain names from IP addresses. Here is how I do it (using 8.8.8.8 nameserver): ```rust let ip = "93.158.134.3"; // A record is www.yandex.ru let labels = ip.split('.').map(str::to_owned).collect(); client.query( Name::with_labels(labels), DNSClass::IN, RecordType::PTR, ) ``` Message I get as a result: ``` Message { header: Header { id: 21949, message_type: Response, op_code: Query, authoritative: false, truncation: false, recursion_desired: true, recursion_available: true, authentic_data: false, checking_disabled: false, response_code: 3, query_count: 1, answer_count: 0, name_server_count: 1, additional_count: 1 }, queries: [Query { name: Name { labels: ["93", "158", "134", "3"] }, query_type: PTR, query_class: IN }], answers: [], name_servers: [Record { name_labels: Name { labels: [] }, rr_type: SOA, dns_class: IN, ttl: 86383, rdata: SOA(SOA { mname: Name { labels: ["a", "root-servers", "net"] }, rname: Name { labels: ["nstld", "verisign-grs", "com"] }, serial: 2017031801, refresh: 1800, retry: 900, expire: 604800, minimum: 86400 }) }], additionals: [], sig0: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 512, options: OPT { options: {} } }) } ``` So, `answers` is empty. Is there my mistake in this query or that's a bug?
kerem 2026-03-07 22:18:22 +03:00
  • closed this issue
  • added the
    enhance
    label
Author
Owner

@mersinvald commented on GitHub (Mar 18, 2017):

As wikipedia explained me, I need to go deeper. Sorry for inconvenience.

<!-- gh-comment-id:287583748 --> @mersinvald commented on GitHub (Mar 18, 2017): As wikipedia explained me, I need to go deeper. Sorry for inconvenience.
Author
Owner

@bluejekyll commented on GitHub (Mar 19, 2017):

I'm planning to start a full resolver soon, where I can handle this more elegantly. But yeah, you need to do the lookup by converting the ip into the proper in-addr format first.

I think I have some tests in the codebase with this as examples.

<!-- gh-comment-id:287586335 --> @bluejekyll commented on GitHub (Mar 19, 2017): I'm planning to start a full resolver soon, where I can handle this more elegantly. But yeah, you need to do the lookup by converting the ip into the proper in-addr format first. I think I have some tests in the codebase with this as examples.
Author
Owner

@mersinvald commented on GitHub (Mar 19, 2017):

But yeah, you need to do the lookup by converting the ip into the proper in-addr format first.

So, the way I make name now is wrong?
Could you please explain how to convert IP to a Name?
My queries just fail now, I'm not getting any name servers in Message to run recursive PTR requests

<!-- gh-comment-id:287630618 --> @mersinvald commented on GitHub (Mar 19, 2017): > But yeah, you need to do the lookup by converting the ip into the proper in-addr format first. So, the way I make name now is wrong? Could you please explain how to convert IP to a Name? My queries just fail now, I'm not getting any name servers in Message to run recursive PTR requests
Author
Owner

@bluejekyll commented on GitHub (Mar 19, 2017):

So you can take a look at how I'm constructing this in the txt_tests functions: https://github.com/bluejekyll/trust-dns/blob/master/server/tests/txt_tests.rs#L233

I thought I had some query tests, but sadly, I don't (hopefully there is no bug here).

Basically IP addresses are represented in DNS in reverse order. Each name label represents a byte of the IP address, followed by the "zone" of in-addr.arpa. So the IPv4 address "10.0.1.23" is represented in reverse order: "23.1.0.10.in-addr.arpa.". The parser for Name::parse() will handle this conversion from a string properly. I never added a from ip address to Name function, but given this conversation, it seems like that would be very valuable. The reason it is reversed is that IP's have the most generic byte first, whereas DNS has the most generic name last... it's almost like no-one ever talked with others when deciding this stuff... :)

<!-- gh-comment-id:287642888 --> @bluejekyll commented on GitHub (Mar 19, 2017): So you can take a look at how I'm constructing this in the txt_tests functions: https://github.com/bluejekyll/trust-dns/blob/master/server/tests/txt_tests.rs#L233 I thought I had some query tests, but sadly, I don't (hopefully there is no bug here). Basically IP addresses are represented in DNS in reverse order. Each name label represents a byte of the IP address, followed by the "zone" of in-addr.arpa. So the IPv4 address "10.0.1.23" is represented in reverse order: "23.1.0.10.in-addr.arpa.". The parser for `Name::parse()` will handle this conversion from a string properly. I never added a from ip address to Name function, but given this conversation, it seems like that would be very valuable. The reason it is reversed is that IP's have the most generic byte first, whereas DNS has the most generic name last... it's almost like no-one ever talked with others when deciding this stuff... :)
Author
Owner

@mersinvald commented on GitHub (Mar 20, 2017):

Thank you!
I finally managed to implement it using futures::loop_fn for recursive queries

let resolve_loop = future::loop_fn(state, move |mut state| {
    let nameserver = state.nameservers.pop().unwrap();
    state.visited.insert(nameserver.clone());
    Self::resolve_with_ns(
        state.loop_handle.clone(),
        state.client_factory.clone(),
        nameserver,
        name.clone(), query_class, query_type
    ).map(move |message| {
        message.map(|mut msg| {
            let authority_ns = msg.take_name_servers().into_iter()
                .map(|ns| NS::KeedResolve(ns.name()))
                .filter(|ns| !state.visited.contains(ns))
                .collect::<Vec<_>>();
            state.nameservers.extend(authority);
            state.answers.extend(msg.answers());
        });
        state
    })
    .and_then(|state| {
        if !state.result.is_empty() || state.nameservers.is_empty() {
            Ok(Loop::Break(state))
        } else {
            Ok(Loop::Continue(state))
        }
    })
});
<!-- gh-comment-id:287684702 --> @mersinvald commented on GitHub (Mar 20, 2017): Thank you! I finally managed to implement it using futures::loop_fn for recursive queries ```rust let resolve_loop = future::loop_fn(state, move |mut state| { let nameserver = state.nameservers.pop().unwrap(); state.visited.insert(nameserver.clone()); Self::resolve_with_ns( state.loop_handle.clone(), state.client_factory.clone(), nameserver, name.clone(), query_class, query_type ).map(move |message| { message.map(|mut msg| { let authority_ns = msg.take_name_servers().into_iter() .map(|ns| NS::KeedResolve(ns.name())) .filter(|ns| !state.visited.contains(ns)) .collect::<Vec<_>>(); state.nameservers.extend(authority); state.answers.extend(msg.answers()); }); state }) .and_then(|state| { if !state.result.is_empty() || state.nameservers.is_empty() { Ok(Loop::Break(state)) } else { Ok(Loop::Continue(state)) } }) }); ```
Author
Owner

@bluejekyll commented on GitHub (Mar 20, 2017):

Awesome! I'm glad you got it to work!

I'll have a patch posted possibly tonight to make ip -> Name a lot easier...

<!-- gh-comment-id:287685105 --> @bluejekyll commented on GitHub (Mar 20, 2017): Awesome! I'm glad you got it to work! I'll have a patch posted possibly tonight to make ip -> Name a lot easier...
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#54
No description provided.