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