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}