ipquery/
lib.rs

1use std::net::*;
2use std::str::FromStr;
3use trust_dns::client::{Client, SyncClient};
4use trust_dns::op::DnsResponse;
5use trust_dns::rr::{DNSClass, Name, RData, Record, RecordType};
6use trust_dns::udp::UdpClientConnection;
7use failure::*;
8
9mod dns_ip;
10pub use dns_ip::{Provider as DnsIpProvider};
11
12#[derive(Fail, Debug)]
13enum Errors {
14    #[fail(display = "No response.")]
15    NoResponse,
16}
17
18pub enum Provider {
19    OpenDNS,
20}
21
22impl Default for Provider {
23    fn default() -> Provider {
24        Provider::OpenDNS
25    }
26}
27
28impl Provider {
29    pub fn query_ipv4(&self) -> Result<Ipv4Addr, Error> {
30        match self {
31            Provider::OpenDNS => self.query_ipv4_opendns(),
32        }
33    }
34
35    pub fn query_ipv6(&self) -> Result<Ipv6Addr, Error> {
36        match self {
37            Provider::OpenDNS => self.query_ipv6_opendns(),
38        }
39    }
40
41    fn query_ipv4_opendns(&self) -> Result<Ipv4Addr, Error> {
42        let address = "208.67.222.222:53".parse()?;
43        let conn = UdpClientConnection::new(address)?;
44        let client = SyncClient::new(conn);
45
46        let name = Name::from_str("myip.opendns.com.")?;
47
48        let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::A)?;
49
50        let answers: &[Record] = response.answers();
51
52        if let &RData::A(ref ip) = answers[0].rdata() {
53            Ok(*ip)
54        } else {
55            bail!(Errors::NoResponse)
56        }
57    }
58
59    fn query_ipv6_opendns(&self) -> Result<Ipv6Addr, Error> {
60        let address = "[2620:119:35::35]:53".parse()?;
61        let conn = UdpClientConnection::new(address)?;
62        let client = SyncClient::new(conn);
63
64        let name = Name::from_str("myip.opendns.com.")?;
65
66        let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AAAA)?;
67
68        let answers: &[Record] = response.answers();
69
70        if let &RData::AAAA(ref ip) = answers[0].rdata() {
71            Ok(*ip)
72        } else {
73            bail!(Errors::NoResponse)
74        }
75    }
76}