1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/* * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //! Query struct for looking up resource records use ::rr::domain::Name; use ::rr::record_type::RecordType; use ::rr::dns_class::DNSClass; use ::serialize::binary::*; use ::error::*; /// Query struct for looking up resource records, basically a resource record without RDATA. /// /// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035) /// /// ```text /// 4.1.2. Question section format /// /// The question section is used to carry the "question" in most queries, /// i.e., the parameters that define what is being asked. The section /// contains QDCOUNT (usually 1) entries, each of the following format: /// /// 1 1 1 1 1 1 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ /// | | /// / QNAME / ZNAME / /// / / /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ /// | QTYPE / ZTYPE | /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ /// | QCLASS / ZCLASS | /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ /// /// ``` #[derive(PartialEq, Debug)] pub struct Query { name: Name, query_type: RecordType, query_class: DNSClass } impl Query { /// return a default query with an empty name and A, IN for the query_type and query_class pub fn new() -> Self { Query { name: Name::new(), query_type: RecordType::A, query_class: DNSClass::IN } } /// replaces name with the new name pub fn name(&mut self, name: Name) -> &mut Self { self.name = name; self } pub fn query_type(&mut self, query_type: RecordType) -> &mut Self { self.query_type = query_type; self } pub fn query_class(&mut self, query_class: DNSClass) -> &mut Self { self.query_class = query_class; self } /// ```text /// QNAME a domain name represented as a sequence of labels, where /// each label consists of a length octet followed by that /// number of octets. The domain name terminates with the /// zero length octet for the null label of the root. Note /// that this field may be an odd number of octets; no /// padding is used. /// ``` pub fn get_name(&self) -> &Name { &self.name } /// ```text /// QTYPE a two octet code which specifies the type of the query. /// The values for this field include all codes valid for a /// TYPE field, together with some more general codes which /// can match more than one type of RR. /// ``` pub fn get_query_type(&self) -> RecordType { self.query_type } /// ```text /// QCLASS a two octet code that specifies the class of the query. /// For example, the QCLASS field is IN for the Internet. /// ``` pub fn get_query_class(&self) -> DNSClass { self.query_class } } impl BinSerializable<Query> for Query { fn read(decoder: &mut BinDecoder) -> DecodeResult<Self> { let name = try!(Name::read(decoder)); let query_type = try!(RecordType::read(decoder)); let query_class = try!(DNSClass::read(decoder)); Ok(Query { name: name, query_type: query_type, query_class: query_class}) } fn emit(&self, encoder: &mut BinEncoder) -> EncodeResult { try!(self.name.emit(encoder)); try!(self.query_type.emit(encoder)); try!(self.query_class.emit(encoder)); Ok(()) } } #[test] fn test_read_and_emit() { let expect = Query { name: Name::with_labels(vec!["www".to_string(),"example".to_string(),"com".to_string()]), query_type: RecordType::AAAA, query_class: DNSClass::IN }; let mut byte_vec: Vec<u8> = Vec::with_capacity(512); { let mut encoder = BinEncoder::new(&mut byte_vec); expect.emit(&mut encoder).unwrap(); } let mut decoder = BinDecoder::new(&byte_vec); let got = Query::read(&mut decoder).unwrap(); assert_eq!(got, expect); }