extern crate byteorder;
extern crate libresolv_sys;
pub mod error;
use error::{Error, ResolutionError};
mod response;
pub use response::{Flags, RecordItems, Response, Section};
pub mod record;
pub use record::{Class, Record, RecordType};
#[cfg(test)]
mod tests;
use std::ffi::CString;
use std::ops::{Deref, DerefMut};
type Context = libresolv_sys::__res_state;
pub use libresolv_sys::ResolverOption;
pub struct Resolver {
context: Context,
}
impl Resolver {
pub fn new() -> Option<Resolver> {
let mut resolver = Resolver {
context: libresolv_sys::__res_state::default(),
};
if unsafe { libresolv_sys::res_ninit(&mut resolver.context) } != 0 {
return None;
}
resolver.option(ResolverOption::Default, true);
Some(resolver)
}
pub fn option(&mut self, option: ResolverOption, value: bool) {
if value {
self.context.options = self.context.options | (option as u64);
} else {
self.context.options = self.context.options & !(option as u64);
}
}
pub fn search(
&mut self,
name: &[u8],
class: Class,
typ: RecordType,
) -> Result<Response, Error> {
let name = match CString::new(name) {
Ok(c) => c,
Err(n) => return Err(Error::CString(n)),
};
let buflen: usize = libresolv_sys::NS_PACKETSZ as usize;
let mut buffer: Box<Vec<u8>> = Box::new(Vec::with_capacity(buflen));
let rlen: i32 = unsafe {
libresolv_sys::res_nsearch(
&mut self.context,
name.as_ptr(),
class as i32,
typ as i32,
buffer.deref_mut().as_mut_ptr(),
buflen as i32,
)
};
if rlen == -1 {
return Err(From::from(self.get_error()));
}
let mut msg: libresolv_sys::ns_msg = libresolv_sys::ns_msg::default();
unsafe {
if libresolv_sys::ns_initparse(buffer.deref().as_ptr(), rlen, &mut msg) < 0 {
return Err(Error::ParseError);
}
}
Ok(Response::new(msg, buffer))
}
pub fn query(
&mut self,
dname: &[u8],
class: Class,
typ: RecordType,
) -> Result<Response, Error> {
let name = match CString::new(dname) {
Ok(c) => c,
Err(n) => return Err(Error::CString(n)),
};
let buflen: usize = libresolv_sys::NS_PACKETSZ as usize;
let mut buffer: Box<Vec<u8>> = Box::new(Vec::with_capacity(buflen));
let rlen: i32 = unsafe {
libresolv_sys::res_nquery(
&mut self.context,
name.as_ptr(),
class as i32,
typ as i32,
buffer.deref_mut().as_mut_ptr(),
buflen as i32,
)
};
if rlen == -1 {
return Err(From::from(self.get_error()));
}
let mut msg: libresolv_sys::ns_msg = libresolv_sys::ns_msg::default();
unsafe {
if libresolv_sys::ns_initparse(buffer.deref().as_ptr(), rlen, &mut msg) < 0 {
return Err(Error::ParseError);
}
}
Ok(Response::new(msg, buffer))
}
fn get_error(&self) -> ResolutionError {
match self.context.res_h_errno {
0 => ResolutionError::Success,
1 => ResolutionError::HostNotFound,
2 => ResolutionError::TryAgain,
3 => ResolutionError::NoRecovery,
4 => ResolutionError::NoData,
_ => ResolutionError::HostNotFound, }
}
}