netdb.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. use libc;
  2. use types::{in_addr, sockaddr, socklen_t};
  3. use RawLineBuffer;
  4. use core::ptr::null;
  5. use core::{mem, str};
  6. use alloc::vec::IntoIter;
  7. use alloc::string::ToString;
  8. use alloc::{Vec, String};
  9. use alloc::str::SplitWhitespace;
  10. use alloc::boxed::Box;
  11. use dns::{Dns, DnsQuery};
  12. use syscall::{self, Result, EINVAL, Error};
  13. use libc::c_char;
  14. const MAXADDRS: usize = 35;
  15. const MAXALIASES: usize = 35;
  16. struct LookupHost(IntoIter<in_addr>);
  17. impl Iterator for LookupHost {
  18. type Item = in_addr;
  19. fn next(&mut self) -> Option<Self::Item> {
  20. self.0.next()
  21. }
  22. }
  23. #[repr(C)]
  24. pub struct hostent {
  25. h_name: *const libc::c_char,
  26. h_aliases: *const *const libc::c_char,
  27. h_addrtype: libc::c_int,
  28. h_length: libc::c_int,
  29. h_addr_list: *const *const libc::c_char,
  30. }
  31. /*
  32. *#[repr(C)]
  33. *pub struct netent {
  34. * n_name: *const libc::c_char, [> official name of net <]
  35. * n_aliases: *const *const libc::c_char, [> alias list <]
  36. * n_addrtype: libc::c_int, [> net address type <]
  37. * n_net: libc::c_ulong, [> network # <]
  38. *}
  39. */
  40. #[repr(C)]
  41. pub struct servent {
  42. s_name: *const libc::c_char, /* official service name */
  43. s_aliases: *const *const libc::c_char, /* alias list */
  44. s_port: libc::c_int, /* port # */
  45. s_proto: *const libc::c_char, /* protocol to use */
  46. }
  47. #[repr(C)]
  48. pub struct protoent {
  49. p_name: *const libc::c_char, /* official protocol name */
  50. p_aliases: *const *const libc::c_char, /* alias list */
  51. p_proto: libc::c_int, /* protocol # */
  52. }
  53. #[repr(C)]
  54. pub struct addrinfo {
  55. ai_flags: libc::c_int, /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
  56. ai_family: libc::c_int, /* PF_xxx */
  57. ai_socktype: libc::c_int, /* SOCK_xxx */
  58. ai_protocol: libc::c_int, /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
  59. ai_addrlen: libc::size_t, /* length of ai_addr */
  60. ai_canonname: *const libc::c_char, /* canonical name for hostname */
  61. ai_addr: *const sockaddr, /* binary address */
  62. ai_next: *const addrinfo, /* next structure in linked list */
  63. }
  64. static mut HOSTDB: usize = 0;
  65. //static mut NETDB: usize = 0;
  66. static mut PROTODB: usize = 0;
  67. static mut SERVDB: usize = 0;
  68. /*
  69. *static mut NET_ENTRY: netent = netent {
  70. * n_name: 0 as *const libc::c_char,
  71. * n_aliases: 0 as *const *const libc::c_char,
  72. * n_addrtype: 0,
  73. * n_net: 0 as u64,
  74. *};
  75. *static mut NET_NAME: Option<Vec<u8>> = None;
  76. *static mut NET_ALIASES: [*const c_char; MAXALIASES] = [null(); MAXALIASES];
  77. *static mut NET_NUM: Option<u64> = None;
  78. */
  79. static mut HOST_ENTRY: hostent = hostent {
  80. h_name: 0 as *const libc::c_char,
  81. h_aliases: 0 as *const *const libc::c_char,
  82. h_addrtype: 0,
  83. h_length: 0,
  84. h_addr_list: 0 as *const *const libc::c_char,
  85. };
  86. static mut HOST_NAME: Option<Vec<u8>> = None;
  87. static mut HOST_ALIASES: Option<Vec<Vec<u8>>> = None;
  88. static mut HOST_ADDR: Option<in_addr> = None;
  89. static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
  90. static mut H_LINE: RawLineBuffer = RawLineBuffer {
  91. fd: 0,
  92. cur: 0,
  93. read: 0,
  94. buf: [0; 8 * 1024],
  95. };
  96. static mut PROTO_ENTRY: protoent = protoent {
  97. p_name: 0 as *const libc::c_char,
  98. p_aliases: 0 as *const *const libc::c_char,
  99. p_proto: 0 as libc::c_int,
  100. };
  101. static mut PROTO_NAME: Option<Vec<u8>> = None;
  102. static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
  103. static mut PROTO_NUM: Option<libc::c_int> = None;
  104. static mut P_LINE: RawLineBuffer = RawLineBuffer {
  105. fd: 0,
  106. cur: 0,
  107. read: 0,
  108. buf: [0; 8 * 1024],
  109. };
  110. static mut SERV_ENTRY: servent = servent {
  111. s_name: 0 as *const libc::c_char,
  112. s_aliases: 0 as *const *const libc::c_char,
  113. s_port: 0 as libc::c_int,
  114. s_proto: 0 as *const libc::c_char,
  115. };
  116. static mut SERV_NAME: Option<Vec<u8>> = None;
  117. static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
  118. static mut SERV_PORT: Option<libc::c_int> = None;
  119. static mut SERV_PROTO: Option<Vec<u8>> = None;
  120. static mut S_LINE: RawLineBuffer = RawLineBuffer {
  121. fd: 0,
  122. cur: 0,
  123. read: 0,
  124. buf: [0; 8 * 1024],
  125. };
  126. fn lookup_host(host: &str) -> Result<LookupHost> {
  127. // XXX better error handling
  128. let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
  129. Error::new(syscall::EIO),
  130. ))?;
  131. let ip: Vec<u8> = ip_string
  132. .trim()
  133. .split(".")
  134. .map(|part| part.parse::<u8>().unwrap_or(0))
  135. .collect();
  136. let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
  137. Error::new(syscall::EIO),
  138. ))?;
  139. let dns: Vec<u8> = dns_string
  140. .trim()
  141. .split(".")
  142. .map(|part| part.parse::<u8>().unwrap_or(0))
  143. .collect();
  144. if ip.len() == 4 && dns.len() == 4 {
  145. let mut timespec = syscall::TimeSpec::default();
  146. syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
  147. let tid = (timespec.tv_nsec >> 16) as u16;
  148. let packet = Dns {
  149. transaction_id: tid,
  150. flags: 0x0100,
  151. queries: vec![
  152. DnsQuery {
  153. name: host.to_string(),
  154. q_type: 0x0001,
  155. q_class: 0x0001,
  156. },
  157. ],
  158. answers: vec![],
  159. };
  160. let packet_data = packet.compile();
  161. let fd = ::RawFile::open(
  162. format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
  163. syscall::O_RDWR,
  164. )?;
  165. let timeout = syscall::TimeSpec {
  166. tv_sec: 5,
  167. tv_nsec: 0,
  168. };
  169. let rt = fd.dup(b"read_timeout")?;
  170. syscall::write(*rt, &timeout)?;
  171. drop(rt);
  172. let wt = fd.dup(b"write_timeout")?;
  173. syscall::write(*wt, &timeout)?;
  174. drop(wt);
  175. let sendrecvfd = fd.dup(
  176. format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
  177. .as_bytes(),
  178. )?;
  179. syscall::write(*sendrecvfd, &packet_data)?;
  180. let mut buf = [0; 65536];
  181. let count = syscall::read(*sendrecvfd, &mut buf)?;
  182. drop(sendrecvfd);
  183. drop(fd);
  184. match Dns::parse(&buf[..count]) {
  185. Ok(response) => {
  186. let mut addrs = vec![];
  187. for answer in response.answers.iter() {
  188. if answer.a_type == 0x0001 && answer.a_class == 0x0001 &&
  189. answer.data.len() == 4
  190. {
  191. let addr = in_addr {
  192. s_addr: [
  193. answer.data[0],
  194. answer.data[1],
  195. answer.data[2],
  196. answer.data[3],
  197. ],
  198. };
  199. addrs.push(addr);
  200. }
  201. }
  202. Ok(LookupHost(addrs.into_iter()))
  203. }
  204. Err(_err) => Err(Error::new(EINVAL)),
  205. }
  206. } else {
  207. Err(Error::new(EINVAL))
  208. }
  209. }
  210. unsafe fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>> {
  211. // XXX better error handling
  212. let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
  213. Error::new(syscall::EIO),
  214. ))?;
  215. let ip: Vec<u8> = ip_string
  216. .trim()
  217. .split(".")
  218. .map(|part| part.parse::<u8>().unwrap_or(0))
  219. .collect();
  220. let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
  221. Error::new(syscall::EIO),
  222. ))?;
  223. let dns: Vec<u8> = dns_string
  224. .trim()
  225. .split(".")
  226. .map(|part| part.parse::<u8>().unwrap_or(0))
  227. .collect();
  228. let mut addr_vec: Vec<u8> = addr.s_addr.to_vec();
  229. addr_vec.reverse();
  230. let mut name: Vec<u8> = vec![];
  231. for octet in addr_vec {
  232. for ch in format!("{}", octet).as_bytes() {
  233. name.push(*ch);
  234. }
  235. name.push(b"."[0]);
  236. }
  237. name.pop();
  238. for ch in b".IN-ADDR.ARPA" {
  239. name.push(*ch);
  240. }
  241. let _ = syscall::write(2, name.as_slice());
  242. let _ = syscall::write(2, "\n".as_bytes());
  243. if ip.len() == 4 && dns.len() == 4 {
  244. let mut timespec = syscall::TimeSpec::default();
  245. syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
  246. let tid = (timespec.tv_nsec >> 16) as u16;
  247. let packet = Dns {
  248. transaction_id: tid,
  249. flags: 0x0100,
  250. queries: vec![
  251. DnsQuery {
  252. name: String::from_utf8(name).unwrap(),
  253. q_type: 0x000C,
  254. q_class: 0x0001,
  255. },
  256. ],
  257. answers: vec![],
  258. };
  259. let packet_data = packet.compile();
  260. let fd = ::RawFile::open(
  261. format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
  262. syscall::O_RDWR,
  263. )?;
  264. let timeout = syscall::TimeSpec {
  265. tv_sec: 5,
  266. tv_nsec: 0,
  267. };
  268. let rt = fd.dup(b"read_timeout")?;
  269. syscall::write(*rt, &timeout)?;
  270. drop(rt);
  271. let wt = fd.dup(b"write_timeout")?;
  272. syscall::write(*wt, &timeout)?;
  273. drop(wt);
  274. let sendrecvfd = fd.dup(
  275. format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
  276. .as_bytes(),
  277. )?;
  278. syscall::write(*sendrecvfd, &packet_data)?;
  279. let mut buf = [0; 65536];
  280. let count = syscall::read(*sendrecvfd, &mut buf)?;
  281. drop(sendrecvfd);
  282. drop(fd);
  283. match Dns::parse(&buf[..count]) {
  284. Ok(response) => {
  285. let _ = syscall::write(2, format!("{:?}", response).as_bytes());
  286. let _ = syscall::write(2, "\n".as_bytes());
  287. let mut names = vec![];
  288. for answer in response.answers.iter() {
  289. if answer.a_type == 0x000C && answer.a_class == 0x0001
  290. {
  291. // answer.data is encoded kinda weird.
  292. // Basically length-prefixed strings for each
  293. // subsection of the domain.
  294. // We need to parse this to insert periods where
  295. // they belong (ie at the end of each string)
  296. let data = parse_data(answer.data.clone());
  297. names.push(data);
  298. }
  299. }
  300. Ok(names)
  301. }
  302. Err(_err) => Err(Error::new(EINVAL)),
  303. }
  304. } else {
  305. Err(Error::new(EINVAL))
  306. }
  307. }
  308. fn parse_data(mut data: Vec<u8>) -> Vec<u8> {
  309. let mut cursor = 0;
  310. let mut offset = 0;
  311. let mut index = 0;
  312. let mut output = data.clone();
  313. while index < data.len() - 1 {
  314. offset = data[index] as usize;
  315. index = cursor + offset + 1;
  316. output[index] = '.' as u8;
  317. cursor = index;
  318. }
  319. //we don't want an extra period at the end
  320. output.pop();
  321. return output
  322. }
  323. libc_fn!(unsafe endhostent() {
  324. let _ = syscall::close(HOSTDB);
  325. });
  326. /*
  327. *libc_fn!(unsafe endnetent() {
  328. * let _ = syscall::close(NETDB);
  329. *});
  330. */
  331. libc_fn!(unsafe endprotoent() {
  332. let _ = syscall::close(PROTODB);
  333. });
  334. libc_fn!(unsafe endservent() {
  335. let _ = syscall::close(SERVDB);
  336. });
  337. libc_fn!(unsafe gethostbyaddr(v: *const libc::c_void, length: socklen_t, format: libc::c_int) -> Result <*const hostent> {
  338. let mut addr: in_addr = *(v as *mut in_addr);
  339. match lookup_addr(addr) {
  340. Ok(s) => {
  341. HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
  342. let host_name = s[0].to_vec();
  343. HOST_ENTRY = hostent {
  344. h_name: host_name.as_ptr() as *const c_char,
  345. h_aliases: [null();2].as_mut_ptr(),
  346. h_addrtype: format,
  347. h_length: length as i32,
  348. h_addr_list: HOST_ADDR_LIST.as_ptr()
  349. };
  350. HOST_NAME = Some(host_name);
  351. return Ok(&HOST_ENTRY)
  352. }
  353. Err(err) => Err(err)
  354. }
  355. });
  356. libc_fn!(unsafe gethostbyname(name: *const c_char) -> Result<*const hostent> {
  357. // XXX h_errno
  358. let mut addr = mem::uninitialized();
  359. let mut host_addr = if ::socket::inet_aton(name, &mut addr) == 1 {
  360. addr
  361. } else {
  362. // XXX
  363. let mut host = lookup_host(str::from_utf8_unchecked(::cstr_to_slice(name)))?;
  364. host.next().ok_or(Error::new(syscall::ENOENT))? // XXX
  365. };
  366. let host_name: Vec<u8> = ::cstr_to_slice(name).to_vec();
  367. HOST_ADDR_LIST = [host_addr.s_addr.as_mut_ptr() as *const c_char, null()];
  368. HOST_ADDR = Some(host_addr);
  369. HOST_ENTRY = hostent {
  370. h_name: host_name.as_ptr() as *const c_char,
  371. h_aliases: [null();2].as_mut_ptr(),
  372. h_addrtype: ::socket::AF_INET,
  373. h_length: 4,
  374. h_addr_list: HOST_ADDR_LIST.as_ptr()
  375. };
  376. HOST_NAME = Some(host_name);
  377. Ok(&HOST_ENTRY as *const hostent)
  378. });
  379. libc_fn!(unsafe gethostent() -> *const hostent {
  380. if HOSTDB == 0 {
  381. HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
  382. H_LINE = RawLineBuffer::new(HOSTDB);
  383. }
  384. let mut r: Box<str> = Box::default();
  385. while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
  386. r = match H_LINE.next() {
  387. Some(Ok(s)) => s,
  388. Some(Err(_)) => return null(),
  389. None => return null(),
  390. };
  391. }
  392. let mut iter: SplitWhitespace = r.split_whitespace();
  393. let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
  394. addr_vec.push(b'\0');
  395. let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
  396. let mut addr = mem::uninitialized();
  397. ::socket::inet_aton(addr_cstr, &mut addr);
  398. HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
  399. HOST_ADDR = Some(addr);
  400. let mut host_name = iter.next().unwrap().as_bytes().to_vec();
  401. host_name.push(b'\0');
  402. let mut host_aliases: Vec<Vec<u8>> = Vec::new();
  403. loop {
  404. let mut alias = match iter.next() {
  405. Some(s) => s.as_bytes().to_vec(),
  406. None => break
  407. };
  408. alias.push(b'\0');
  409. host_aliases.push(alias);
  410. }
  411. //push a 0 so c doesn't segfault when it tries to read the next entry
  412. host_aliases.push(vec![b'\0']);
  413. HOST_ENTRY = hostent {
  414. h_name: host_name.as_ptr() as *const c_char,
  415. h_aliases: host_aliases.as_slice().as_ptr() as *const *const i8,
  416. h_addrtype: ::socket::AF_INET,
  417. h_length: 4,
  418. h_addr_list: HOST_ADDR_LIST.as_ptr()
  419. };
  420. HOST_ALIASES = Some(host_aliases);
  421. HOST_NAME = Some(host_name);
  422. &HOST_ENTRY as *const hostent
  423. });
  424. /*
  425. *libc_fn!(getnetbyaddr(net: libc::uint32_t, net_type: libc::c_int) -> Result<*const netent> {
  426. * if NETDB == 0 {
  427. * NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
  428. * }
  429. *});
  430. *
  431. *libc_fn!(getnetbyname(name: *const libc::c_char) -> Result<*const netent> {
  432. * if NETDB == 0 {
  433. * NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
  434. * }
  435. *});
  436. *
  437. */
  438. /*
  439. *libc_fn!(getnetent() -> Result<*const netent> {
  440. * if NETDB == 0 {
  441. * NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
  442. * }
  443. *
  444. *});
  445. */
  446. libc_fn!(unsafe getprotobyname(name: *const libc::c_char) -> Result<*const protoent> {
  447. setprotoent(0);
  448. let mut p: *const protoent;
  449. while {p=getprotoent();
  450. p!=null()} {
  451. if libc::strcmp((*p).p_name, name) == 0 {
  452. return Ok(p);
  453. }
  454. loop {
  455. let mut cp = (*p).p_aliases;
  456. if cp == null() {
  457. break;
  458. }
  459. if libc::strcmp(*cp, name) == 0 {
  460. return Ok(p);
  461. }
  462. cp = cp.offset(1);
  463. }
  464. }
  465. endprotoent();
  466. Err(Error::new(syscall::ENOENT))
  467. });
  468. libc_fn!(unsafe getprotobynumber(number: libc::c_int) -> Result<*const protoent> {
  469. setprotoent(0);
  470. let mut p: *const protoent;
  471. while {p=getprotoent();
  472. p!=null()} {
  473. if (*p).p_proto == number {
  474. return Ok(p);
  475. }
  476. }
  477. endprotoent();
  478. Err(Error::new(syscall::ENOENT))
  479. });
  480. libc_fn!(unsafe getprotoent() -> *const protoent {
  481. if PROTODB == 0 {
  482. PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
  483. P_LINE = RawLineBuffer::new(PROTODB);
  484. }
  485. let mut r: Box<str> = Box::default();
  486. while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
  487. r = match P_LINE.next() {
  488. Some(Ok(s)) => s,
  489. Some(Err(_)) => return null(),
  490. None => return null(),
  491. };
  492. }
  493. let mut iter: SplitWhitespace = r.split_whitespace();
  494. let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
  495. proto_name.push(b'\0');
  496. let mut num = iter.next().unwrap().as_bytes().to_vec();
  497. num.push(b'\0');
  498. PROTO_NUM = Some(libc::atoi(num.as_slice().as_ptr() as *mut i8));
  499. let mut proto_aliases: Vec<Vec<u8>> = Vec::new();
  500. loop {
  501. let mut alias = match iter.next() {
  502. Some(s) => s.as_bytes().to_vec(),
  503. None => break
  504. };
  505. alias.push(b'\0');
  506. proto_aliases.push(alias);
  507. }
  508. //push a 0 so c doesn't segfault when it tries to read the next entry
  509. proto_aliases.push(vec![b'\0']);
  510. PROTO_ENTRY = protoent {
  511. p_name: proto_name.as_slice().as_ptr() as *const c_char,
  512. p_aliases: proto_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
  513. p_proto: PROTO_NUM.unwrap()
  514. };
  515. PROTO_ALIASES = Some(proto_aliases);
  516. PROTO_NAME = Some(proto_name);
  517. &PROTO_ENTRY as *const protoent
  518. });
  519. libc_fn!(unsafe getservbyname(name: *const libc::c_char, proto: *const libc::c_char) -> Result<*const servent> {
  520. setservent(0);
  521. let mut p: *const servent;
  522. while {p=getservent();
  523. p!=null()} {
  524. if libc::strcmp((*p).s_name, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
  525. return Ok(p);
  526. }
  527. loop {
  528. let mut cp = (*p).s_aliases;
  529. if cp == null() {
  530. break;
  531. }
  532. if libc::strcmp(*cp, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
  533. return Ok(p);
  534. }
  535. cp = cp.offset(1);
  536. }
  537. }
  538. Err(Error::new(syscall::ENOENT))
  539. });
  540. libc_fn!(unsafe getservbyport(port: libc::c_int, proto: *const libc::c_char) -> Result<*const servent> {
  541. setprotoent(0);
  542. let mut p: *const servent;
  543. while {p=getservent();
  544. p!=null()} {
  545. if (*p).s_port == port && libc::strcmp((*p).s_proto, proto) == 0 {
  546. return Ok(p);
  547. }
  548. }
  549. endprotoent();
  550. Err(Error::new(syscall::ENOENT))
  551. });
  552. libc_fn!(unsafe getservent() -> *const servent {
  553. if SERVDB == 0 {
  554. SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
  555. S_LINE = RawLineBuffer::new(SERVDB);
  556. }
  557. let mut r: Box<str> = Box::default();
  558. while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
  559. r = match S_LINE.next() {
  560. Some(Ok(s)) => s,
  561. Some(Err(_)) => return null(),
  562. None => return null(),
  563. };
  564. }
  565. let mut iter: SplitWhitespace = r.split_whitespace();
  566. let mut serv_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
  567. serv_name.push(b'\0');
  568. let port_proto = iter.next().unwrap();
  569. let mut split = port_proto.split("/");
  570. let port = libc::atoi(split.next().unwrap().as_ptr() as *const i8);
  571. SERV_PORT = Some(port);
  572. let proto = split.next().unwrap().as_bytes().to_vec();
  573. let mut serv_aliases: Vec<Vec<u8>> = Vec::new();
  574. loop {
  575. let mut alias = match iter.next() {
  576. Some(s) => s.as_bytes().to_vec(),
  577. None => break
  578. };
  579. alias.push(b'\0');
  580. serv_aliases.push(alias);
  581. }
  582. //push a 0 so c doesn't segfault when it tries to read the next entry
  583. serv_aliases.push(vec![b'\0']);
  584. SERV_ENTRY = servent {
  585. s_name: serv_name.as_slice().as_ptr() as *const c_char,
  586. s_aliases: serv_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
  587. s_port: SERV_PORT.unwrap(),
  588. s_proto: proto.as_slice().as_ptr() as *const c_char
  589. };
  590. SERV_ALIASES = Some(serv_aliases);
  591. SERV_NAME = Some(serv_name);
  592. SERV_PROTO = Some(proto);
  593. &SERV_ENTRY as *const servent
  594. });
  595. libc_fn!(unsafe sethostent(stayopen: libc::c_int) {
  596. if HOSTDB == 0 {
  597. HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
  598. } else {
  599. let _ = syscall::lseek(HOSTDB, 0, syscall::SEEK_SET);
  600. }
  601. H_LINE = RawLineBuffer::new(HOSTDB);
  602. });
  603. /*
  604. *libc_fn!(unsafe setnetent(stayopen: libc::c_int) {
  605. * if NETDB == 0 {
  606. * NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
  607. * } else {
  608. * let _ = syscall::lseek(NETDB, 0, syscall::SEEK_SET);
  609. * }
  610. *});
  611. */
  612. libc_fn!(unsafe setprotoent(stayopen: libc::c_int) {
  613. if PROTODB == 0 {
  614. PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
  615. } else {
  616. let _ = syscall::lseek(PROTODB, 0, syscall::SEEK_SET);
  617. }
  618. P_LINE = RawLineBuffer::new(PROTODB);
  619. });
  620. libc_fn!(unsafe setservent(stayopen: libc::c_int) {
  621. if SERVDB == 0 {
  622. SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
  623. } else {
  624. let _ = syscall::lseek(SERVDB, 0, syscall::SEEK_SET);
  625. }
  626. S_LINE = RawLineBuffer::new(SERVDB);
  627. });
  628. //libc_fn!(getaddrinfo(node: *const libc::c_char, service: *const libc::c_char, hints: *const addrinfo, res: *mut *mut addrinfo) -> libc::c_int {
  629. //});
  630. //libc_fn!(getnameinfo(addr: *const sockaddr, addrlen: socklen_t, host: *mut libc::c_char, hostlen: socklen_t, serv: *mut libc::c_char, servlen: socklen_t, flags: libc::c_int) -> libc::c_int {
  631. //});
  632. //libc_fn!(freeaddrinfo(res: *mut addrinfo) {
  633. //});
  634. //libc_fn!(gai_strerror(errcode: libc::c_int) -> *const libc::c_char {
  635. //});