mod.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. //! netdb implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/netdb.h.html
  2. mod dns;
  3. use core::{
  4. mem, ptr, slice,
  5. str::{self, FromStr},
  6. };
  7. use alloc::{borrow::ToOwned, boxed::Box, str::SplitWhitespace, vec::Vec};
  8. use crate::{
  9. c_str::{CStr, CString},
  10. header::{
  11. arpa_inet::{htons, inet_aton, ntohl},
  12. errno::*,
  13. fcntl::O_RDONLY,
  14. netinet_in::{in_addr, sockaddr_in, sockaddr_in6},
  15. stdlib::atoi,
  16. strings::strcasecmp,
  17. sys_socket::{constants::AF_INET, sa_family_t, sockaddr, socklen_t},
  18. unistd::SEEK_SET,
  19. },
  20. platform::{
  21. self,
  22. rlb::{Line, RawLineBuffer},
  23. types::*,
  24. Pal, Sys,
  25. },
  26. };
  27. #[cfg(target_os = "linux")]
  28. #[path = "linux.rs"]
  29. pub mod sys;
  30. #[cfg(target_os = "redox")]
  31. #[path = "redox.rs"]
  32. pub mod sys;
  33. pub use self::host::*;
  34. pub mod host;
  35. pub use self::lookup::*;
  36. pub mod lookup;
  37. #[repr(C)]
  38. pub struct hostent {
  39. h_name: *mut c_char,
  40. h_aliases: *mut *mut c_char,
  41. h_addrtype: c_int,
  42. h_length: c_int,
  43. h_addr_list: *mut *mut c_char,
  44. }
  45. #[repr(C)]
  46. pub struct netent {
  47. n_name: *mut c_char, /* official name of net */
  48. n_aliases: *mut *mut c_char, /* alias list */
  49. n_addrtype: c_int, /* net address type */
  50. n_net: c_ulong, /* network # */
  51. }
  52. #[repr(C)]
  53. pub struct protoent {
  54. p_name: *mut c_char, /* official protocol name */
  55. p_aliases: *mut *mut c_char, /* alias list */
  56. p_proto: c_int, /* protocol # */
  57. }
  58. #[repr(C)]
  59. pub struct servent {
  60. s_name: *mut c_char, /* official service name */
  61. s_aliases: *mut *mut c_char, /* alias list */
  62. s_port: c_int, /* port # */
  63. s_proto: *mut c_char, /* protocol to use */
  64. }
  65. #[repr(C)]
  66. #[derive(Debug)]
  67. pub struct addrinfo {
  68. ai_flags: c_int, /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
  69. ai_family: c_int, /* PF_xxx */
  70. ai_socktype: c_int, /* SOCK_xxx */
  71. ai_protocol: c_int, /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
  72. ai_addrlen: size_t, /* length of ai_addr */
  73. ai_canonname: *mut c_char, /* canonical name for hostname */
  74. ai_addr: *mut sockaddr, /* binary address */
  75. ai_next: *mut addrinfo, /* next structure in linked list */
  76. }
  77. pub const AI_PASSIVE: c_int = 0x0001;
  78. pub const AI_CANONNAME: c_int = 0x0002;
  79. pub const AI_NUMERICHOST: c_int = 0x0004;
  80. pub const AI_V4MAPPED: c_int = 0x0008;
  81. pub const AI_ALL: c_int = 0x0010;
  82. pub const AI_ADDRCONFIG: c_int = 0x0020;
  83. pub const AI_NUMERICSERV: c_int = 0x0400;
  84. pub const EAI_BADFLAGS: c_int = -1;
  85. pub const EAI_NONAME: c_int = -2;
  86. pub const EAI_AGAIN: c_int = -3;
  87. pub const EAI_FAIL: c_int = -4;
  88. pub const EAI_NODATA: c_int = -5;
  89. pub const EAI_FAMILY: c_int = -6;
  90. pub const EAI_SOCKTYPE: c_int = -7;
  91. pub const EAI_SERVICE: c_int = -8;
  92. pub const EAI_ADDRFAMILY: c_int = -9;
  93. pub const EAI_MEMORY: c_int = -10;
  94. pub const EAI_SYSTEM: c_int = -11;
  95. pub const EAI_OVERFLOW: c_int = -12;
  96. pub const NI_MAXHOST: c_int = 1025;
  97. pub const NI_MAXSERV: c_int = 32;
  98. pub const NI_NUMERICHOST: c_int = 0x0001;
  99. pub const NI_NUMERICSERV: c_int = 0x0002;
  100. pub const NI_NOFQDN: c_int = 0x0004;
  101. pub const NI_NAMEREQD: c_int = 0x0008;
  102. pub const NI_DGRAM: c_int = 0x0010;
  103. static mut NETDB: c_int = 0;
  104. pub static mut NET_ENTRY: netent = netent {
  105. n_name: ptr::null_mut(),
  106. n_aliases: ptr::null_mut(),
  107. n_addrtype: 0,
  108. n_net: 0,
  109. };
  110. pub static mut NET_NAME: Option<Vec<u8>> = None;
  111. pub static mut NET_ALIASES: Option<Vec<Vec<u8>>> = None;
  112. pub static mut NET_ADDR: Option<u32> = None;
  113. static mut N_POS: usize = 0;
  114. static mut NET_STAYOPEN: c_int = 0;
  115. #[allow(non_upper_case_globals)]
  116. #[no_mangle]
  117. pub static mut h_errno: c_int = 0;
  118. pub const HOST_NOT_FOUND: c_int = 1;
  119. pub const NO_DATA: c_int = 2;
  120. pub const NO_RECOVERY: c_int = 3;
  121. pub const TRY_AGAIN: c_int = 4;
  122. static mut PROTODB: c_int = 0;
  123. static mut PROTO_ENTRY: protoent = protoent {
  124. p_name: ptr::null_mut(),
  125. p_aliases: ptr::null_mut(),
  126. p_proto: 0 as c_int,
  127. };
  128. static mut PROTO_NAME: Option<Vec<u8>> = None;
  129. static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
  130. static mut PROTO_NUM: Option<c_int> = None;
  131. static mut P_POS: usize = 0;
  132. static mut PROTO_STAYOPEN: c_int = 0;
  133. static mut SERVDB: c_int = 0;
  134. static mut SERV_ENTRY: servent = servent {
  135. s_name: ptr::null_mut(),
  136. s_aliases: ptr::null_mut(),
  137. s_port: 0 as c_int,
  138. s_proto: ptr::null_mut(),
  139. };
  140. static mut SERV_NAME: Option<Vec<u8>> = None;
  141. static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
  142. static mut SERV_PORT: Option<c_int> = None;
  143. static mut SERV_PROTO: Option<Vec<u8>> = None;
  144. static mut S_POS: usize = 0;
  145. static mut SERV_STAYOPEN: c_int = 0;
  146. fn bytes_to_box_str(bytes: &[u8]) -> Box<str> {
  147. Box::from(core::str::from_utf8(bytes).unwrap_or(""))
  148. }
  149. #[no_mangle]
  150. pub unsafe extern "C" fn endnetent() {
  151. Sys::close(NETDB);
  152. NETDB = 0;
  153. }
  154. #[no_mangle]
  155. pub unsafe extern "C" fn endprotoent() {
  156. Sys::close(PROTODB);
  157. PROTODB = 0;
  158. }
  159. #[no_mangle]
  160. pub unsafe extern "C" fn endservent() {
  161. Sys::close(SERVDB);
  162. SERVDB = 0;
  163. }
  164. #[no_mangle]
  165. pub unsafe extern "C" fn gethostbyaddr(
  166. v: *const c_void,
  167. length: socklen_t,
  168. format: c_int,
  169. ) -> *mut hostent {
  170. let addr: in_addr = *(v as *mut in_addr);
  171. // check the hosts file first
  172. let mut p: *mut hostent;
  173. sethostent(HOST_STAYOPEN);
  174. while {
  175. p = gethostent();
  176. !p.is_null()
  177. } {
  178. let mut cp = (*p).h_addr_list;
  179. loop {
  180. if cp.is_null() {
  181. break;
  182. }
  183. if (*cp).is_null() {
  184. break;
  185. }
  186. let mut cp_slice: [i8; 4] = [0i8; 4];
  187. (*cp).copy_to(cp_slice.as_mut_ptr(), 4);
  188. let cp_s_addr = mem::transmute::<[i8; 4], u32>(cp_slice);
  189. if cp_s_addr == addr.s_addr {
  190. sethostent(HOST_STAYOPEN);
  191. return p;
  192. }
  193. cp = cp.offset(1);
  194. }
  195. }
  196. //TODO actually get aliases
  197. let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
  198. _host_aliases.push(vec![b'\0']);
  199. let mut host_aliases: Vec<*mut i8> = Vec::new();
  200. host_aliases.push(ptr::null_mut());
  201. HOST_ALIASES = Some(_host_aliases);
  202. match lookup_addr(addr) {
  203. Ok(s) => {
  204. _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(addr.s_addr);
  205. HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut c_char, ptr::null_mut()];
  206. let host_name = s[0].to_vec();
  207. HOST_NAME = Some(host_name);
  208. HOST_ENTRY = hostent {
  209. h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
  210. h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
  211. h_addrtype: format,
  212. h_length: length as i32,
  213. h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
  214. };
  215. &mut HOST_ENTRY
  216. }
  217. Err(e) => {
  218. platform::errno = e;
  219. ptr::null_mut()
  220. }
  221. }
  222. }
  223. #[no_mangle]
  224. pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
  225. // check if some idiot gave us an address instead of a name
  226. let name_cstr = CStr::from_ptr(name);
  227. let mut octets = str::from_utf8_unchecked(name_cstr.to_bytes()).split('.');
  228. let mut s_addr = [0u8; 4];
  229. let mut is_addr = true;
  230. for item in &mut s_addr {
  231. if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
  232. *item = n;
  233. } else {
  234. is_addr = false;
  235. }
  236. }
  237. if octets.next() != None {
  238. is_addr = false;
  239. }
  240. if is_addr {
  241. let addr = in_addr {
  242. s_addr: mem::transmute::<[u8; 4], u32>(s_addr),
  243. };
  244. return gethostbyaddr(&addr as *const _ as *const c_void, 4, AF_INET);
  245. }
  246. // check the hosts file first
  247. let mut p: *mut hostent;
  248. sethostent(HOST_STAYOPEN);
  249. while {
  250. p = gethostent();
  251. !p.is_null()
  252. } {
  253. if strcasecmp((*p).h_name, name) == 0 {
  254. sethostent(HOST_STAYOPEN);
  255. return p;
  256. }
  257. let mut cp = (*p).h_aliases;
  258. loop {
  259. if cp.is_null() {
  260. break;
  261. }
  262. if (*cp).is_null() {
  263. break;
  264. }
  265. if strcasecmp(*cp, name) == 0 {
  266. sethostent(HOST_STAYOPEN);
  267. return p;
  268. }
  269. cp = cp.offset(1);
  270. }
  271. }
  272. let name_cstr = CStr::from_ptr(name);
  273. let mut host = match lookup_host(str::from_utf8_unchecked(name_cstr.to_bytes())) {
  274. Ok(lookuphost) => lookuphost,
  275. Err(e) => {
  276. platform::errno = e;
  277. return ptr::null_mut();
  278. }
  279. };
  280. let host_addr = match host.next() {
  281. Some(result) => result,
  282. None => {
  283. platform::errno = ENOENT;
  284. return ptr::null_mut();
  285. }
  286. };
  287. let host_name: Vec<u8> = name_cstr.to_bytes().to_vec();
  288. HOST_NAME = Some(host_name);
  289. _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(host_addr.s_addr);
  290. HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut c_char, ptr::null_mut()];
  291. HOST_ADDR = Some(host_addr);
  292. //TODO actually get aliases
  293. let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
  294. _host_aliases.push(vec![b'\0']);
  295. let mut host_aliases: Vec<*mut i8> = Vec::new();
  296. host_aliases.push(ptr::null_mut());
  297. host_aliases.push(ptr::null_mut());
  298. HOST_ALIASES = Some(_host_aliases);
  299. HOST_ENTRY = hostent {
  300. h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
  301. h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
  302. h_addrtype: AF_INET,
  303. h_length: 4,
  304. h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
  305. };
  306. sethostent(HOST_STAYOPEN);
  307. &mut HOST_ENTRY as *mut hostent
  308. }
  309. pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: c_int) -> *mut netent {
  310. unimplemented!();
  311. }
  312. #[no_mangle]
  313. pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *mut netent {
  314. let mut n: *mut netent;
  315. setnetent(NET_STAYOPEN);
  316. while {
  317. n = getnetent();
  318. !n.is_null()
  319. } {
  320. if strcasecmp((*n).n_name, name) == 0 {
  321. setnetent(NET_STAYOPEN);
  322. return n;
  323. }
  324. }
  325. setnetent(NET_STAYOPEN);
  326. platform::errno = ENOENT;
  327. ptr::null_mut() as *mut netent
  328. }
  329. #[no_mangle]
  330. pub unsafe extern "C" fn getnetent() -> *mut netent {
  331. if NETDB == 0 {
  332. NETDB = Sys::open(&CString::new("/etc/networks").unwrap(), O_RDONLY, 0);
  333. }
  334. let mut rlb = RawLineBuffer::new(NETDB);
  335. rlb.seek(N_POS);
  336. let mut r: Box<str> = Box::default();
  337. while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
  338. r = match rlb.next() {
  339. Line::Some(s) => bytes_to_box_str(s),
  340. _ => {
  341. if NET_STAYOPEN == 0 {
  342. endnetent();
  343. }
  344. return ptr::null_mut();
  345. }
  346. };
  347. }
  348. rlb.next();
  349. N_POS = rlb.line_pos();
  350. let mut iter: SplitWhitespace = r.split_whitespace();
  351. let mut net_name = iter.next().unwrap().as_bytes().to_vec();
  352. net_name.push(b'\0');
  353. NET_NAME = Some(net_name);
  354. let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
  355. addr_vec.push(b'\0');
  356. let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
  357. let mut addr = mem::MaybeUninit::uninit();
  358. inet_aton(addr_cstr, addr.as_mut_ptr());
  359. let addr = addr.assume_init();
  360. NET_ADDR = Some(ntohl(addr.s_addr));
  361. let mut _net_aliases: Vec<Vec<u8>> = Vec::new();
  362. for s in iter {
  363. let mut alias = s.as_bytes().to_vec();
  364. alias.push(b'\0');
  365. _net_aliases.push(alias);
  366. }
  367. let mut net_aliases: Vec<*mut i8> = _net_aliases
  368. .iter_mut()
  369. .map(|x| x.as_mut_ptr() as *mut i8)
  370. .collect();
  371. net_aliases.push(ptr::null_mut());
  372. NET_ALIASES = Some(_net_aliases);
  373. NET_ENTRY = netent {
  374. n_name: NET_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
  375. n_aliases: net_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
  376. n_addrtype: AF_INET,
  377. n_net: NET_ADDR.unwrap() as u64,
  378. };
  379. &mut NET_ENTRY as *mut netent
  380. }
  381. #[no_mangle]
  382. pub unsafe extern "C" fn getprotobyname(name: *const c_char) -> *mut protoent {
  383. let mut p: *mut protoent;
  384. setprotoent(PROTO_STAYOPEN);
  385. while {
  386. p = getprotoent();
  387. !p.is_null()
  388. } {
  389. if strcasecmp((*p).p_name, name) == 0 {
  390. setprotoent(PROTO_STAYOPEN);
  391. return p;
  392. }
  393. let mut cp = (*p).p_aliases;
  394. loop {
  395. if cp.is_null() {
  396. setprotoent(PROTO_STAYOPEN);
  397. break;
  398. }
  399. if (*cp).is_null() {
  400. setprotoent(PROTO_STAYOPEN);
  401. break;
  402. }
  403. if strcasecmp(*cp, name) == 0 {
  404. setprotoent(PROTO_STAYOPEN);
  405. return p;
  406. }
  407. cp = cp.offset(1);
  408. }
  409. }
  410. setprotoent(PROTO_STAYOPEN);
  411. platform::errno = ENOENT;
  412. ptr::null_mut() as *mut protoent
  413. }
  414. #[no_mangle]
  415. pub unsafe extern "C" fn getprotobynumber(number: c_int) -> *mut protoent {
  416. setprotoent(PROTO_STAYOPEN);
  417. let mut p: *mut protoent;
  418. while {
  419. p = getprotoent();
  420. !p.is_null()
  421. } {
  422. if (*p).p_proto == number {
  423. setprotoent(PROTO_STAYOPEN);
  424. return p;
  425. }
  426. }
  427. setprotoent(PROTO_STAYOPEN);
  428. platform::errno = ENOENT;
  429. ptr::null_mut() as *mut protoent
  430. }
  431. #[no_mangle]
  432. pub unsafe extern "C" fn getprotoent() -> *mut protoent {
  433. if PROTODB == 0 {
  434. PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0);
  435. }
  436. let mut rlb = RawLineBuffer::new(PROTODB);
  437. rlb.seek(P_POS);
  438. let mut r: Box<str> = Box::default();
  439. while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
  440. r = match rlb.next() {
  441. Line::Some(s) => bytes_to_box_str(s),
  442. _ => {
  443. if PROTO_STAYOPEN == 0 {
  444. endprotoent();
  445. }
  446. return ptr::null_mut();
  447. }
  448. };
  449. }
  450. rlb.next();
  451. P_POS = rlb.line_pos();
  452. let mut iter: SplitWhitespace = r.split_whitespace();
  453. let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
  454. proto_name.push(b'\0');
  455. let mut num = iter.next().unwrap().as_bytes().to_vec();
  456. num.push(b'\0');
  457. PROTO_NUM = Some(atoi(num.as_mut_slice().as_mut_ptr() as *mut i8));
  458. let mut _proto_aliases: Vec<Vec<u8>> = Vec::new();
  459. for s in iter {
  460. let mut alias = s.as_bytes().to_vec();
  461. alias.push(b'\0');
  462. _proto_aliases.push(alias);
  463. }
  464. let mut proto_aliases: Vec<*mut i8> = _proto_aliases
  465. .iter_mut()
  466. .map(|x| x.as_mut_ptr() as *mut i8)
  467. .collect();
  468. proto_aliases.push(ptr::null_mut());
  469. PROTO_ALIASES = Some(_proto_aliases);
  470. PROTO_NAME = Some(proto_name);
  471. PROTO_ENTRY = protoent {
  472. p_name: PROTO_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
  473. p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
  474. p_proto: PROTO_NUM.unwrap(),
  475. };
  476. if PROTO_STAYOPEN == 0 {
  477. endprotoent();
  478. }
  479. &mut PROTO_ENTRY as *mut protoent
  480. }
  481. #[no_mangle]
  482. pub unsafe extern "C" fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut servent {
  483. setservent(SERV_STAYOPEN);
  484. let mut p: *mut servent;
  485. if proto.is_null() {
  486. while {
  487. p = getservent();
  488. !p.is_null()
  489. } {
  490. if strcasecmp((*p).s_name, name) == 0 {
  491. setservent(SERV_STAYOPEN);
  492. return p;
  493. }
  494. }
  495. } else {
  496. while {
  497. p = getservent();
  498. !p.is_null()
  499. } {
  500. if strcasecmp((*p).s_name, name) == 0 && strcasecmp((*p).s_proto, proto) == 0 {
  501. setservent(SERV_STAYOPEN);
  502. return p;
  503. }
  504. }
  505. }
  506. setservent(SERV_STAYOPEN);
  507. platform::errno = ENOENT;
  508. ptr::null_mut() as *mut servent
  509. }
  510. #[no_mangle]
  511. pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *mut servent {
  512. setservent(SERV_STAYOPEN);
  513. let mut p: *mut servent;
  514. if proto.is_null() {
  515. while {
  516. p = getservent();
  517. !p.is_null()
  518. } {
  519. if (*p).s_port == port {
  520. setservent(SERV_STAYOPEN);
  521. return p;
  522. }
  523. }
  524. } else {
  525. while {
  526. p = getservent();
  527. !p.is_null()
  528. } {
  529. if (*p).s_port == port && strcasecmp((*p).s_proto, proto) == 0 {
  530. setservent(SERV_STAYOPEN);
  531. return p;
  532. }
  533. }
  534. }
  535. setservent(SERV_STAYOPEN);
  536. platform::errno = ENOENT;
  537. ptr::null_mut()
  538. }
  539. #[no_mangle]
  540. pub unsafe extern "C" fn getservent() -> *mut servent {
  541. if SERVDB == 0 {
  542. SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0);
  543. }
  544. let mut rlb = RawLineBuffer::new(SERVDB);
  545. rlb.seek(S_POS);
  546. let r: Box<str> = Box::default();
  547. loop {
  548. let r = match rlb.next() {
  549. Line::Some(s) => bytes_to_box_str(s),
  550. _ => {
  551. if SERV_STAYOPEN == 0 {
  552. endservent();
  553. }
  554. return ptr::null_mut();
  555. }
  556. };
  557. let mut iter = r.split_whitespace();
  558. let mut serv_name = match iter.next() {
  559. Some(serv_name) => serv_name.as_bytes().to_vec(),
  560. None => continue,
  561. };
  562. serv_name.push(b'\0');
  563. let port_proto = match iter.next() {
  564. Some(port_proto) => port_proto,
  565. None => continue,
  566. };
  567. let mut split = port_proto.split('/');
  568. let mut port = match split.next() {
  569. Some(port) => port.as_bytes().to_vec(),
  570. None => continue,
  571. };
  572. port.push(b'\0');
  573. SERV_PORT =
  574. Some(htons(atoi(port.as_mut_slice().as_mut_ptr() as *mut i8) as u16) as u32 as i32);
  575. let mut proto = match split.next() {
  576. Some(proto) => proto.as_bytes().to_vec(),
  577. None => continue,
  578. };
  579. proto.push(b'\0');
  580. rlb.next();
  581. S_POS = rlb.line_pos();
  582. /*
  583. *let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
  584. *loop {
  585. * let mut alias = match iter.next() {
  586. * Some(s) => s.as_bytes().to_vec(),
  587. * _ => break
  588. * };
  589. * alias.push(b'\0');
  590. * _serv_aliases.push(alias);
  591. *}
  592. *let mut serv_aliases: Vec<*mut i8> = _serv_aliases.iter_mut().map(|x| x.as_mut_ptr() as *mut i8).collect();
  593. *serv_aliases.push(ptr::null_mut());
  594. *
  595. */
  596. let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
  597. _serv_aliases.push(vec![b'\0']);
  598. let mut serv_aliases: Vec<*mut i8> = Vec::new();
  599. serv_aliases.push(ptr::null_mut());
  600. serv_aliases.push(ptr::null_mut());
  601. SERV_ALIASES = Some(_serv_aliases);
  602. SERV_NAME = Some(serv_name);
  603. SERV_PROTO = Some(proto);
  604. SERV_ENTRY = servent {
  605. s_name: SERV_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
  606. s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
  607. s_port: SERV_PORT.unwrap(),
  608. s_proto: SERV_PROTO.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
  609. };
  610. if SERV_STAYOPEN == 0 {
  611. endservent();
  612. }
  613. break &mut SERV_ENTRY as *mut servent;
  614. }
  615. }
  616. #[no_mangle]
  617. pub unsafe extern "C" fn setnetent(stayopen: c_int) {
  618. NET_STAYOPEN = stayopen;
  619. if NETDB == 0 {
  620. NETDB = Sys::open(&CString::new("/etc/networks").unwrap(), O_RDONLY, 0)
  621. } else {
  622. Sys::lseek(NETDB, 0, SEEK_SET);
  623. N_POS = 0;
  624. }
  625. }
  626. #[no_mangle]
  627. pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
  628. PROTO_STAYOPEN = stayopen;
  629. if PROTODB == 0 {
  630. PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0)
  631. } else {
  632. Sys::lseek(PROTODB, 0, SEEK_SET);
  633. P_POS = 0;
  634. }
  635. }
  636. #[no_mangle]
  637. pub unsafe extern "C" fn setservent(stayopen: c_int) {
  638. SERV_STAYOPEN = stayopen;
  639. if SERVDB == 0 {
  640. SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0)
  641. } else {
  642. Sys::lseek(SERVDB, 0, SEEK_SET);
  643. S_POS = 0;
  644. }
  645. }
  646. #[no_mangle]
  647. pub unsafe extern "C" fn getaddrinfo(
  648. node: *const c_char,
  649. service: *const c_char,
  650. hints: *const addrinfo,
  651. res: *mut *mut addrinfo,
  652. ) -> c_int {
  653. //TODO: getaddrinfo
  654. let node_opt = if node.is_null() {
  655. None
  656. } else {
  657. Some(CStr::from_ptr(node))
  658. };
  659. let service_opt = if service.is_null() {
  660. None
  661. } else {
  662. Some(CStr::from_ptr(service))
  663. };
  664. let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
  665. trace!(
  666. "getaddrinfo({:?}, {:?}, {:?})",
  667. node_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
  668. service_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
  669. hints_opt
  670. );
  671. //TODO: Use hints
  672. let mut ai_flags = hints_opt.map_or(0, |hints| hints.ai_flags);
  673. let mut ai_family; // = hints_opt.map_or(AF_UNSPEC, |hints| hints.ai_family);
  674. let ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype);
  675. let mut ai_protocol; // = hints_opt.map_or(0, |hints| hints.ai_protocol);
  676. *res = ptr::null_mut();
  677. let mut port = 0;
  678. if let Some(service) = service_opt {
  679. //TODO: Support other service definitions as well as AI_NUMERICSERV
  680. match str::from_utf8_unchecked(service.to_bytes()).parse::<u16>() {
  681. Ok(ok) => port = ok,
  682. Err(_err) => (),
  683. }
  684. }
  685. //TODO: Check hosts file
  686. if let Some(node) = node_opt {
  687. //TODO: Support AI_NUMERICHOST
  688. let lookuphost = match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
  689. Ok(lookuphost) => lookuphost,
  690. Err(e) => {
  691. platform::errno = e;
  692. return EAI_SYSTEM;
  693. }
  694. };
  695. for in_addr in lookuphost {
  696. ai_family = AF_INET;
  697. ai_protocol = 0;
  698. let ai_addr = Box::into_raw(Box::new(sockaddr_in {
  699. sin_family: ai_family as sa_family_t,
  700. sin_port: htons(port),
  701. sin_addr: in_addr,
  702. sin_zero: [0; 8],
  703. })) as *mut sockaddr;
  704. let ai_addrlen = mem::size_of::<sockaddr_in>();
  705. let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
  706. ai_flags &= !AI_CANONNAME;
  707. node.to_owned().into_raw()
  708. } else {
  709. ptr::null_mut()
  710. };
  711. let addrinfo = Box::new(addrinfo {
  712. ai_flags: 0,
  713. ai_family,
  714. ai_socktype,
  715. ai_protocol,
  716. ai_addrlen,
  717. ai_canonname,
  718. ai_addr,
  719. ai_next: ptr::null_mut(),
  720. });
  721. let mut indirect = res;
  722. while !(*indirect).is_null() {
  723. indirect = &mut (**indirect).ai_next;
  724. }
  725. *indirect = Box::into_raw(addrinfo);
  726. }
  727. }
  728. 0
  729. }
  730. #[no_mangle]
  731. pub unsafe extern "C" fn getnameinfo(
  732. addr: *const sockaddr,
  733. addrlen: socklen_t,
  734. host: *mut c_char,
  735. hostlen: socklen_t,
  736. serv: *mut c_char,
  737. servlen: socklen_t,
  738. flags: c_int,
  739. ) -> c_int {
  740. //TODO: getnameinfo
  741. if addrlen as usize != mem::size_of::<sockaddr_in>() {
  742. return EAI_FAMILY;
  743. }
  744. let addr = &*(addr as *const sockaddr_in);
  745. let host_opt = if host.is_null() {
  746. None
  747. } else {
  748. Some(slice::from_raw_parts_mut(host, hostlen as usize))
  749. };
  750. let serv_opt = if serv.is_null() {
  751. None
  752. } else {
  753. Some(slice::from_raw_parts_mut(serv, servlen as usize))
  754. };
  755. eprintln!("getnameinfo({:p}, {}, {:#x})", addr, addrlen, flags);
  756. platform::errno = ENOSYS;
  757. EAI_SYSTEM
  758. }
  759. #[no_mangle]
  760. pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
  761. let mut ai = res;
  762. while !ai.is_null() {
  763. let bai = Box::from_raw(ai);
  764. if !bai.ai_canonname.is_null() {
  765. CString::from_raw(bai.ai_canonname);
  766. }
  767. if !bai.ai_addr.is_null() {
  768. if bai.ai_addrlen == mem::size_of::<sockaddr_in>() {
  769. Box::from_raw(bai.ai_addr as *mut sockaddr_in);
  770. } else if bai.ai_addrlen == mem::size_of::<sockaddr_in6>() {
  771. Box::from_raw(bai.ai_addr as *mut sockaddr_in6);
  772. } else {
  773. eprintln!("freeaddrinfo: unknown ai_addrlen {}", bai.ai_addrlen);
  774. }
  775. }
  776. ai = bai.ai_next;
  777. }
  778. }
  779. #[no_mangle]
  780. pub extern "C" fn gai_strerror(errcode: c_int) -> *const c_char {
  781. match errcode {
  782. EAI_BADFLAGS => c_str!("Invalid flags"),
  783. EAI_NONAME => c_str!("Name does not resolve"),
  784. EAI_AGAIN => c_str!("Try again"),
  785. EAI_FAIL => c_str!("Non-recoverable error"),
  786. EAI_NODATA => c_str!("Unknown error"),
  787. EAI_FAMILY => c_str!("Unrecognized address family or invalid length"),
  788. EAI_SOCKTYPE => c_str!("Unrecognized socket type"),
  789. EAI_SERVICE => c_str!("Unrecognized service"),
  790. EAI_ADDRFAMILY => c_str!("Address family for name not supported"),
  791. EAI_MEMORY => c_str!("Out of memory"),
  792. EAI_SYSTEM => c_str!("System error"),
  793. EAI_OVERFLOW => c_str!("Overflow"),
  794. _ => c_str!("Unknown error"),
  795. }
  796. .as_ptr()
  797. }