pub struct Message<'arrays, 'innards> { /* private fields */ }
Expand description
The message for a DNS query.
Implementations§
Source§impl<'arrays, 'innards> Message<'arrays, 'innards>
impl<'arrays, 'innards> Message<'arrays, 'innards>
Sourcepub fn new(
id: u16,
flags: Flags,
questions: &'arrays mut [Question<'innards>],
answers: &'arrays mut [ResourceRecord<'innards>],
authorities: &'arrays mut [ResourceRecord<'innards>],
additional: &'arrays mut [ResourceRecord<'innards>],
) -> Self
pub fn new( id: u16, flags: Flags, questions: &'arrays mut [Question<'innards>], answers: &'arrays mut [ResourceRecord<'innards>], authorities: &'arrays mut [ResourceRecord<'innards>], additional: &'arrays mut [ResourceRecord<'innards>], ) -> Self
Create a new message from a set of buffers for each section.
§Panics
This function panics if the number of questions, answers, authorities, or additional records
is greater than u16::MAX
.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}
Sourcepub fn flags(&self) -> Flags
pub fn flags(&self) -> Flags
Get the flags for this message.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}
Sourcepub fn flags_mut(&mut self) -> &mut Flags
pub fn flags_mut(&mut self) -> &mut Flags
Get a mutable reference to the flags for this message.
Sourcepub fn questions_mut(&mut self) -> &mut [Question<'innards>]
pub fn questions_mut(&mut self) -> &mut [Question<'innards>]
Get a mutable reference to the questions in this message.
Sourcepub fn answers(&self) -> &[ResourceRecord<'innards>]
pub fn answers(&self) -> &[ResourceRecord<'innards>]
Get the answers in this message.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}
Sourcepub fn answers_mut(&mut self) -> &mut [ResourceRecord<'innards>]
pub fn answers_mut(&mut self) -> &mut [ResourceRecord<'innards>]
Get a mutable reference to the answers in this message.
Get the authorities in this message.
Get a mutable reference to the authorities in this message.
Sourcepub fn additional(&self) -> &[ResourceRecord<'innards>]
pub fn additional(&self) -> &[ResourceRecord<'innards>]
Get the additional records in this message.
Sourcepub fn additional_mut(&mut self) -> &mut [ResourceRecord<'innards>]
pub fn additional_mut(&mut self) -> &mut [ResourceRecord<'innards>]
Get a mutable reference to the additional records in this message.
Sourcepub fn space_needed(&self) -> usize
pub fn space_needed(&self) -> usize
Get the buffer space needed to serialize this message.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}
Sourcepub fn write(&self, buffer: &mut [u8]) -> Result<usize, Error>
pub fn write(&self, buffer: &mut [u8]) -> Result<usize, Error>
Write this message to a buffer.
Returns the number of bytes written.
§Errors
This function may raise Error::NameTooLong
if a Label
is too long to be serialized.
§Panics
This function panics if the buffer is not large enough to hold the serialized message. This
panic can be avoided by ensuring the buffer contains at least [space_needed
] bytes.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}
Sourcepub fn read(
buffer: &'innards [u8],
questions: &'arrays mut [Question<'innards>],
answers: &'arrays mut [ResourceRecord<'innards>],
authorities: &'arrays mut [ResourceRecord<'innards>],
additional: &'arrays mut [ResourceRecord<'innards>],
) -> Result<Message<'arrays, 'innards>, Error>
pub fn read( buffer: &'innards [u8], questions: &'arrays mut [Question<'innards>], answers: &'arrays mut [ResourceRecord<'innards>], authorities: &'arrays mut [ResourceRecord<'innards>], additional: &'arrays mut [ResourceRecord<'innards>], ) -> Result<Message<'arrays, 'innards>, Error>
Read a message from a buffer.
§Errors
This function may raise one of the following errors:
Error::NotEnoughReadBytes
if the buffer is not large enough to hold the entire structure. You may need to read more data before calling this function again.Error::NotEnoughWriteSpace
if the buffers provided are not large enough to hold the entire structure. You may need to allocate larger buffers before calling this function.Error::InvalidUtf8
if a domain name contains invalid UTF-8.Error::NameTooLong
if a domain name is too long to be deserialized.Error::InvalidCode
if a domain name contains an invalid label code.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // The first argument is the name to lookup.
17 let mut args = env::args();
18 let program_name = args.next().unwrap();
19 let name = match args.next() {
20 Some(name) => name,
21 None => {
22 eprintln!("Usage: {} <name>", &program_name);
23 process::exit(1);
24 }
25 };
26
27 // Search in resolv.conf for the nameserver.
28 //
29 // A production-grade implementation would consider multiple nameservers in
30 // resolv.conf, and then poll them all at once.
31 let resolv = BufReader::new(fs::File::open("/etc/resolv.conf")?);
32 let mut nameserver = None;
33
34 for line in resolv.lines() {
35 let line = line?;
36 if line.starts_with("nameserver") {
37 let result = line.split_whitespace().nth(1).unwrap();
38 if let Ok(ns) = result.parse::<IpAddr>() {
39 nameserver = Some(ns);
40 break;
41 }
42 }
43 }
44
45 let nameserver = match nameserver {
46 Some(ns) => ns,
47 None => {
48 eprintln!("No nameserver found in /etc/resolv.conf");
49 process::exit(1);
50 }
51 };
52
53 println!("Nameserver: {}", nameserver);
54
55 // Create the message we need to send.
56 let mut questions = [Question::new(name.as_str(), ResourceType::A, 1)];
57 let message = Message::new(
58 0xFEE7,
59 Flags::standard_query(),
60 &mut questions,
61 &mut [],
62 &mut [],
63 &mut [],
64 );
65
66 // Allocate the buffer that we need to send.
67 let mut buffer = vec![0; message.space_needed()];
68 message.write(&mut buffer)?;
69
70 // Send the packet to our nameserver over UDP.
71 let socket = UdpSocket::bind((Ipv4Addr::from([127, 0, 0, 1]), 0))?;
72 socket.send_to(&buffer, (nameserver, 53))?;
73
74 // Wait for a response.
75 //
76 // A production-grade implementation would respect timeout/attempts settings in
77 // resolv.conf.
78 let mut buffer = vec![0; 1024];
79 let len = socket.recv(&mut buffer)?;
80
81 // Parse the response.
82 let mut answers = [ResourceRecord::default(); 16];
83 let mut authority = [ResourceRecord::default(); 16];
84 let mut additional = [ResourceRecord::default(); 16];
85 let message = Message::read(
86 &buffer[..len],
87 &mut questions,
88 &mut answers,
89 &mut authority,
90 &mut additional,
91 )?;
92
93 println!(";; Got answer: {:?}", message.flags().response_code());
94
95 // Print the answers.
96 for answer in message.answers() {
97 // Determine the IP address.
98 match answer.data().len() {
99 4 => {
100 let mut ip = [0u8; 4];
101 ip.copy_from_slice(answer.data());
102 let ip = Ipv4Addr::from(ip);
103 println!("{} has address {}", answer.name(), ip);
104 }
105 16 => {
106 let mut ip = [0u8; 16];
107 ip.copy_from_slice(answer.data());
108 let ip = IpAddr::from(ip);
109 println!("{} has address {}", answer.name(), ip);
110 }
111 _ => {
112 println!("{} has unknown address type", answer.name());
113 }
114 }
115 }
116
117 Ok(())
118}