hostname.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. use core::ptr::null;
  2. use core::{mem, str, slice};
  3. use alloc::vec::IntoIter;
  4. use alloc::string::ToString;
  5. use alloc::{Vec, String};
  6. use ::dns::{Dns, DnsQuery};
  7. use syscall::{self, Result, EINVAL, Error};
  8. use libc::{c_char, size_t, c_int};
  9. use ::types::{in_addr, hostent};
  10. static mut HOST_ENTRY: hostent = hostent { h_name: null(), h_aliases: null(), h_addrtype: 0, h_length: 0, h_addr_list: null() };
  11. static mut HOST_NAME: Option<Vec<u8>> = None;
  12. static mut HOST_ALIASES: [*const c_char; 1] = [null()];
  13. static mut HOST_ADDR: Option<in_addr> = None;
  14. static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
  15. struct LookupHost(IntoIter<in_addr>);
  16. impl Iterator for LookupHost {
  17. type Item = in_addr;
  18. fn next(&mut self) -> Option<Self::Item> {
  19. self.0.next()
  20. }
  21. }
  22. // Modified from rust/sys/redox/net/mod.rs
  23. fn lookup_host(host: &str) -> Result<LookupHost> {
  24. // XXX better error handling
  25. let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?)
  26. .or(Err(Error::new(syscall::EIO)))?;
  27. let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
  28. .unwrap_or(0)).collect();
  29. let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?)
  30. .or(Err(Error::new(syscall::EIO)))?;
  31. let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
  32. .unwrap_or(0)).collect();
  33. if ip.len() == 4 && dns.len() == 4 {
  34. let mut timespec = syscall::TimeSpec::default();
  35. syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
  36. let tid = (timespec.tv_nsec >> 16) as u16;
  37. let packet = Dns {
  38. transaction_id: tid,
  39. flags: 0x0100,
  40. queries: vec![DnsQuery {
  41. name: host.to_string(),
  42. q_type: 0x0001,
  43. q_class: 0x0001,
  44. }],
  45. answers: vec![]
  46. };
  47. let packet_data = packet.compile();
  48. let fd = ::RawFile::open(format!("udp:/{}.{}.{}.{}:0",
  49. ip[0], ip[1], ip[2], ip[3]).as_bytes(),
  50. syscall::O_RDWR)?;
  51. let timeout = syscall::TimeSpec {
  52. tv_sec: 5,
  53. tv_nsec: 0,
  54. };
  55. let rt = fd.dup(b"read_timeout")?;
  56. syscall::write(*rt, &timeout)?;
  57. drop(rt);
  58. let wt = fd.dup(b"write_timeout")?;
  59. syscall::write(*wt, &timeout)?;
  60. drop(wt);
  61. let sendrecvfd = fd.dup(format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3]).as_bytes())?;
  62. syscall::write(*sendrecvfd, &packet_data)?;
  63. let mut buf = [0; 65536];
  64. let count = syscall::read(*sendrecvfd, &mut buf)?;
  65. drop(sendrecvfd);
  66. drop(fd);
  67. match Dns::parse(&buf[.. count]) {
  68. Ok(response) => {
  69. let mut addrs = vec![];
  70. for answer in response.answers.iter() {
  71. if answer.a_type == 0x0001 && answer.a_class == 0x0001
  72. && answer.data.len() == 4
  73. {
  74. let addr = in_addr {
  75. s_addr: [answer.data[0], answer.data[1], answer.data[2], answer.data[3]]
  76. };
  77. addrs.push(addr);
  78. }
  79. }
  80. Ok(LookupHost(addrs.into_iter()))
  81. },
  82. Err(_err) => Err(Error::new(EINVAL))
  83. }
  84. } else {
  85. Err(Error::new(EINVAL))
  86. }
  87. }
  88. libc_fn!(unsafe gethostname(name: *mut c_char, namelen: size_t) -> Result<c_int> {
  89. let slice = slice::from_raw_parts_mut(name as *mut u8, namelen);
  90. let fd = ::RawFile::open("/etc/hostname", syscall::O_RDONLY)?;
  91. let len = syscall::read(*fd, &mut slice[..namelen-1])?;
  92. slice[len] = b'\0';
  93. Ok(0)
  94. });