1#[repr(C)]
8pub struct ServEnt {
9 pub s_name: *mut c_char,
10 pub s_aliases: *mut *mut c_char,
11 pub s_port: c_int,
12 pub s_proto: *mut c_char,
13}
14
15#[repr(C)]
16pub struct ProtoEnt {
17 pub p_name: *mut c_char,
18 pub p_aliases: *mut *mut c_char,
19 pub p_proto: c_int,
20}
21
22#[repr(C)]
23pub struct NetEnt {
24 pub n_name: *mut c_char,
25 pub n_aliases: *mut *mut c_char,
26 pub n_addrtype: c_int,
27 pub n_net: u32,
28}
29
30const NDB_ENOENT: c_int = 2;
31const NDB_ERANGE: c_int = 34;
32const NDB_ENOTTY: c_int = 25;
33
34const EAI_BADFLAGS_V: c_int = -1;
35const EAI_NONAME_V: c_int = -2;
36const EAI_AGAIN_V: c_int = -3;
37const EAI_FAIL_V: c_int = -4;
38const EAI_FAMILY_V: c_int = -6;
39const EAI_SOCKTYPE_V: c_int = -7;
40const EAI_SERVICE_V: c_int = -8;
41const EAI_MEMORY_V: c_int = -10;
42const EAI_SYSTEM_V: c_int = -11;
43const EAI_OVERFLOW_V: c_int = -12;
44
45const AI_PASSIVE_V: c_int = 0x01;
46const AI_CANONNAME_V: c_int = 0x02;
47const AI_NUMERICHOST_V: c_int = 0x04;
48const AI_V4MAPPED_V: c_int = 0x08;
49const AI_ALL_V: c_int = 0x10;
50const AI_ADDRCONFIG_V: c_int = 0x20;
51const AI_NUMERICSERV_V: c_int = 0x400;
52
53const NI_NUMERICHOST_V: c_int = 0x01;
54const NI_NUMERICSERV_V: c_int = 0x02;
55const NI_NOFQDN_V: c_int = 0x04;
56const NI_NAMEREQD_V: c_int = 0x08;
57const NI_DGRAM_V: c_int = 0x10;
58const NI_NUMERICSCOPE_V: c_int = 0x100;
59
60unsafe fn nd_isspace(c: c_char) -> bool {
61 c == b' ' as c_char || c == b'\t' as c_char || c == b'\r' as c_char || c == b'\n' as c_char
62}
63
64unsafe fn nd_copy_line(src: *const c_char, dst: *mut c_char, cap: usize) -> bool {
65 let mut i = 0usize;
66 while i + 1 < cap {
67 let c = *src.add(i);
68 *dst.add(i) = c;
69 if c == 0 { return true; }
70 i += 1;
71 }
72 *dst.add(cap - 1) = 0;
73 true
74}
75
76unsafe fn nd_split(buf: *mut c_char, toks: *mut *mut c_char, maxtok: usize) -> usize {
78 let mut n = 0usize;
79 let mut p = buf;
80 loop {
81 while *p != 0 && nd_isspace(*p) { p = p.add(1); }
82 if *p == 0 || *p == b'#' as c_char { break; }
83 if n < maxtok {
84 *toks.add(n) = p;
85 n += 1;
86 }
87 while *p != 0 && !nd_isspace(*p) && *p != b'#' as c_char { p = p.add(1); }
88 if *p == 0 { break; }
89 if *p == b'#' as c_char { *p = 0; break; }
90 *p = 0;
91 p = p.add(1);
92 }
93 n
94}
95
96unsafe fn nd_tokens(line: *const c_char, buf: *mut c_char, cap: usize, toks: &mut [*mut c_char; 24]) -> usize {
97 if !nd_copy_line(line, buf, cap) { return 0; }
98 nd_split(buf, toks.as_mut_ptr(), toks.len())
99}
100
101static mut SERV_FILE: *mut FILE = core::ptr::null_mut();
106static mut SERV_ENT: ServEnt = ServEnt {
107 s_name: core::ptr::null_mut(),
108 s_aliases: core::ptr::null_mut(),
109 s_port: 0,
110 s_proto: core::ptr::null_mut(),
111};
112static mut SERV_BUF: [c_char; 1024] = [0; 1024];
113static mut SERV_ALIASES: [*mut c_char; 16] = [core::ptr::null_mut(); 16];
114
115unsafe fn serv_parse(line: *const c_char) -> bool {
116 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
117 let n = nd_tokens(line, SERV_BUF.as_mut_ptr(), SERV_BUF.len(), &mut toks);
118 if n < 2 { return false; }
119 let mut p = toks[1];
120 let port = crate::strtoul(p, &mut p, 10);
121 if p == toks[1] || port > 65535 { return false; }
122 let mut proto: *mut c_char = b"tcp\0".as_ptr() as *mut c_char;
123 if *p == b'/' as c_char {
124 p = p.add(1);
125 if *p == 0 { return false; }
126 proto = p;
127 }
128 SERV_ENT.s_name = toks[0];
129 SERV_ENT.s_port = htons(port as u16) as c_int;
130 SERV_ENT.s_proto = proto;
131 let mut ai = 0usize;
132 for i in 2..n {
133 if ai + 1 >= SERV_ALIASES.len() { break; }
134 SERV_ALIASES[ai] = toks[i];
135 ai += 1;
136 }
137 SERV_ALIASES[ai] = core::ptr::null_mut();
138 SERV_ENT.s_aliases = SERV_ALIASES.as_mut_ptr();
139 true
140}
141
142unsafe fn serv_next(f: *mut FILE) -> bool {
143 let mut line = [0 as c_char; 1024];
144 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
145 if serv_parse(line.as_ptr()) { return true; }
146 }
147 false
148}
149
150#[no_mangle]
151pub unsafe extern "C" fn setservent(stayopen: c_int) {
152 endservent();
153 SERV_FILE = crate::fopen(b"/etc/services\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
154 let _ = stayopen;
155}
156
157#[no_mangle]
158pub unsafe extern "C" fn endservent() {
159 if !SERV_FILE.is_null() {
160 crate::fclose(SERV_FILE);
161 SERV_FILE = core::ptr::null_mut();
162 }
163}
164
165#[no_mangle]
166pub unsafe extern "C" fn getservent() -> *mut ServEnt {
167 if SERV_FILE.is_null() {
168 SERV_FILE = crate::fopen(b"/etc/services\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
169 if SERV_FILE.is_null() { return core::ptr::null_mut(); }
170 }
171 if serv_next(SERV_FILE) { &raw mut SERV_ENT } else { core::ptr::null_mut() }
172}
173
174unsafe fn serv_name_matches(name: *const c_char) -> bool {
175 if crate::strcmp(SERV_ENT.s_name as *const u8, name as *const u8) == 0 { return true; }
176 let mut i = 0usize;
177 while !(*SERV_ENT.s_aliases.add(i)).is_null() {
178 if crate::strcmp(*SERV_ENT.s_aliases.add(i) as *const u8, name as *const u8) == 0 {
179 return true;
180 }
181 i += 1;
182 }
183 false
184}
185
186unsafe fn serv_proto_matches(proto: *const c_char) -> bool {
187 proto.is_null() || crate::strcmp(SERV_ENT.s_proto as *const u8, proto as *const u8) == 0
188}
189
190unsafe fn serv_search(name: *const c_char, proto: *const c_char, port: c_int) -> bool {
191 let f = crate::fopen(b"/etc/services\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
192 if f.is_null() { return false; }
193 let mut found = false;
194 while serv_next(f) {
195 if !serv_proto_matches(proto) { continue; }
196 let hit = if name.is_null() {
197 SERV_ENT.s_port == port
198 } else {
199 serv_name_matches(name)
200 };
201 if hit { found = true; break; }
202 }
203 crate::fclose(f);
204 found
205}
206
207#[no_mangle]
208pub unsafe extern "C" fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut ServEnt {
209 if name.is_null() { return core::ptr::null_mut(); }
210 if serv_search(name, proto, 0) { &raw mut SERV_ENT } else { core::ptr::null_mut() }
211}
212
213#[no_mangle]
214pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *mut ServEnt {
215 if serv_search(core::ptr::null(), proto, port) { &raw mut SERV_ENT } else { core::ptr::null_mut() }
216}
217
218unsafe fn serv_copy_out(se: *mut ServEnt, buf: *mut c_char, buflen: usize, res: *mut *mut ServEnt) -> c_int {
219 if res.is_null() || se.is_null() { return EINVAL; }
220 *res = core::ptr::null_mut();
221 let ptrsz = core::mem::size_of::<*mut c_char>();
222 let mut need = crate::strlen((*se).s_name) + 1 + crate::strlen((*se).s_proto) + 1;
223 let mut nalias = 0usize;
224 while !(*(*se).s_aliases.add(nalias)).is_null() {
225 need += crate::strlen(*(*se).s_aliases.add(nalias)) + 1;
226 nalias += 1;
227 }
228 let align = (ptrsz - (buf as usize & (ptrsz - 1))) & (ptrsz - 1);
229 need += align + (nalias + 1) * ptrsz;
230 if need > buflen { return NDB_ERANGE; }
231
232 let mut p = buf.add(align);
233 let aliases = p as *mut *mut c_char;
234 p = p.add((nalias + 1) * ptrsz);
235
236 let n = crate::strlen((*se).s_name);
237 core::ptr::copy_nonoverlapping((*se).s_name, p, n + 1);
238 (*se).s_name = p;
239 p = p.add(n + 1);
240
241 let n = crate::strlen((*se).s_proto);
242 core::ptr::copy_nonoverlapping((*se).s_proto, p, n + 1);
243 (*se).s_proto = p;
244 p = p.add(n + 1);
245
246 for j in 0..nalias {
247 let src = *(*se).s_aliases.add(j);
248 let n = crate::strlen(src);
249 core::ptr::copy_nonoverlapping(src, p, n + 1);
250 *aliases.add(j) = p;
251 p = p.add(n + 1);
252 }
253 *aliases.add(nalias) = core::ptr::null_mut();
254 (*se).s_aliases = aliases;
255 *res = se;
256 0
257}
258
259#[no_mangle]
260pub unsafe extern "C" fn getservbyname_r(
261 name: *const c_char,
262 proto: *const c_char,
263 _se: *mut ServEnt,
264 buf: *mut c_char,
265 buflen: usize,
266 res: *mut *mut ServEnt,
267) -> c_int {
268 if res.is_null() { return EINVAL; }
269 *res = core::ptr::null_mut();
270 let p = getservbyname(name, proto);
271 if p.is_null() { return NDB_ENOENT; }
272 let mut tmp = ServEnt { s_name: (*p).s_name, s_aliases: (*p).s_aliases, s_port: (*p).s_port, s_proto: (*p).s_proto };
273 serv_copy_out(&mut tmp, buf, buflen, res)
274}
275
276#[no_mangle]
277pub unsafe extern "C" fn getservbyport_r(
278 port: c_int,
279 proto: *const c_char,
280 _se: *mut ServEnt,
281 buf: *mut c_char,
282 buflen: usize,
283 res: *mut *mut ServEnt,
284) -> c_int {
285 if res.is_null() { return EINVAL; }
286 *res = core::ptr::null_mut();
287 let p = getservbyport(port, proto);
288 if p.is_null() { return NDB_ENOENT; }
289 let mut tmp = ServEnt { s_name: (*p).s_name, s_aliases: (*p).s_aliases, s_port: (*p).s_port, s_proto: (*p).s_proto };
290 serv_copy_out(&mut tmp, buf, buflen, res)
291}
292
293static PROTO_TABLE: [(&[u8], c_int); 36] = [
298 (b"ip\0", 0), (b"icmp\0", 1), (b"igmp\0", 2), (b"ggp\0", 3),
299 (b"ipencap\0", 4), (b"st\0", 5), (b"tcp\0", 6), (b"egp\0", 8),
300 (b"pup\0", 12), (b"udp\0", 17), (b"hmp\0", 20), (b"xns-idp\0", 22),
301 (b"rdp\0", 27), (b"iso-tp4\0", 29), (b"xtp\0", 36), (b"ddp\0", 37),
302 (b"idpr-cmtp\0", 38), (b"ipv6\0", 41), (b"ipv6-route\0", 43),
303 (b"ipv6-frag\0", 44), (b"idrp\0", 45), (b"rsvp\0", 46), (b"gre\0", 47),
304 (b"esp\0", 50), (b"ah\0", 51), (b"skip\0", 57), (b"ipv6-icmp\0", 58),
305 (b"ipv6-nonxt\0", 59), (b"ipv6-opts\0", 60), (b"rspf\0", 73),
306 (b"vmtp\0", 81), (b"ospf\0", 89), (b"ipip\0", 94), (b"encap\0", 98),
307 (b"pim\0", 103), (b"raw\0", 255),
308];
309
310static mut PROTO_FILE: *mut FILE = core::ptr::null_mut();
311static mut PROTO_ENT: ProtoEnt = ProtoEnt {
312 p_name: core::ptr::null_mut(),
313 p_aliases: core::ptr::null_mut(),
314 p_proto: 0,
315};
316static mut PROTO_BUF: [c_char; 1024] = [0; 1024];
317static mut PROTO_ALIASES: [*mut c_char; 16] = [core::ptr::null_mut(); 16];
318static mut PROTO_IDX: usize = 0;
319
320unsafe fn proto_parse(line: *const c_char) -> bool {
321 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
322 let n = nd_tokens(line, PROTO_BUF.as_mut_ptr(), PROTO_BUF.len(), &mut toks);
323 if n < 2 { return false; }
324 let num = crate::strtol(toks[1], core::ptr::null_mut(), 10);
325 if num < 0 || num > 255 { return false; }
326 PROTO_ENT.p_name = toks[0];
327 PROTO_ENT.p_proto = num as c_int;
328 let mut ai = 0usize;
329 for i in 2..n {
330 if ai + 1 >= PROTO_ALIASES.len() { break; }
331 PROTO_ALIASES[ai] = toks[i];
332 ai += 1;
333 }
334 PROTO_ALIASES[ai] = core::ptr::null_mut();
335 PROTO_ENT.p_aliases = PROTO_ALIASES.as_mut_ptr();
336 true
337}
338
339unsafe fn proto_from_table(i: usize) -> bool {
340 if i >= PROTO_TABLE.len() { return false; }
341 PROTO_ENT.p_name = PROTO_TABLE[i].0.as_ptr() as *mut c_char;
342 PROTO_ENT.p_proto = PROTO_TABLE[i].1;
343 PROTO_ALIASES[0] = core::ptr::null_mut();
344 PROTO_ENT.p_aliases = PROTO_ALIASES.as_mut_ptr();
345 true
346}
347
348unsafe fn proto_file() -> *mut FILE {
349 if PROTO_FILE.is_null() {
350 PROTO_FILE = crate::fopen(b"/etc/protocols\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
351 }
352 PROTO_FILE
353}
354
355#[no_mangle]
356pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
357 endprotoent();
358 PROTO_IDX = 0;
359 PROTO_FILE = crate::fopen(b"/etc/protocols\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
360 let _ = stayopen;
361}
362
363#[no_mangle]
364pub unsafe extern "C" fn endprotoent() {
365 if !PROTO_FILE.is_null() {
366 crate::fclose(PROTO_FILE);
367 PROTO_FILE = core::ptr::null_mut();
368 }
369 PROTO_IDX = 0;
370}
371
372#[no_mangle]
373pub unsafe extern "C" fn getprotoent() -> *mut ProtoEnt {
374 if PROTO_FILE.is_null() {
375 let f = crate::fopen(b"/etc/protocols\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
376 if f.is_null() {
377 let ok = proto_from_table(PROTO_IDX);
378 PROTO_IDX += 1;
379 return if ok { &raw mut PROTO_ENT } else { core::ptr::null_mut() };
380 }
381 PROTO_FILE = f;
382 }
383 let mut line = [0 as c_char; 1024];
384 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, PROTO_FILE).is_null() {
385 if proto_parse(line.as_ptr()) { return &raw mut PROTO_ENT; }
386 }
387 core::ptr::null_mut()
388}
389
390unsafe fn proto_name_matches(name: *const c_char) -> bool {
391 if crate::strcmp(PROTO_ENT.p_name as *const u8, name as *const u8) == 0 { return true; }
392 let mut i = 0usize;
393 while !(*PROTO_ENT.p_aliases.add(i)).is_null() {
394 if crate::strcmp(*PROTO_ENT.p_aliases.add(i) as *const u8, name as *const u8) == 0 { return true; }
395 i += 1;
396 }
397 false
398}
399
400unsafe fn proto_scan(name: *const c_char, num: c_int, by_name: bool) -> bool {
401 let f = crate::fopen(b"/etc/protocols\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
402 if !f.is_null() {
403 let mut line = [0 as c_char; 1024];
404 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
405 if !proto_parse(line.as_ptr()) { continue; }
406 let hit = if by_name { proto_name_matches(name) } else { PROTO_ENT.p_proto == num };
407 if hit { crate::fclose(f); return true; }
408 }
409 crate::fclose(f);
410 }
411 for i in 0..PROTO_TABLE.len() {
412 proto_from_table(i);
413 let hit = if by_name { proto_name_matches(name) } else { PROTO_ENT.p_proto == num };
414 if hit { return true; }
415 }
416 false
417}
418
419#[no_mangle]
420pub unsafe extern "C" fn getprotobyname(name: *const c_char) -> *mut ProtoEnt {
421 if name.is_null() { return core::ptr::null_mut(); }
422 if proto_scan(name, 0, true) { &raw mut PROTO_ENT } else { core::ptr::null_mut() }
423}
424
425#[no_mangle]
426pub unsafe extern "C" fn getprotobynumber(num: c_int) -> *mut ProtoEnt {
427 if proto_scan(core::ptr::null(), num, false) { &raw mut PROTO_ENT } else { core::ptr::null_mut() }
428}
429
430static mut NET_FILE: *mut FILE = core::ptr::null_mut();
435static mut NET_ENT: NetEnt = NetEnt {
436 n_name: core::ptr::null_mut(),
437 n_aliases: core::ptr::null_mut(),
438 n_addrtype: AF_INET,
439 n_net: 0,
440};
441static mut NET_BUF: [c_char; 1024] = [0; 1024];
442static mut NET_ALIASES: [*mut c_char; 16] = [core::ptr::null_mut(); 16];
443
444unsafe fn net_parse(line: *const c_char) -> bool {
445 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
446 let n = nd_tokens(line, NET_BUF.as_mut_ptr(), NET_BUF.len(), &mut toks);
447 if n < 2 { return false; }
448 let net = inet_network(toks[1]);
449 if net == u32::MAX { return false; }
450 NET_ENT.n_name = toks[0];
451 NET_ENT.n_addrtype = AF_INET;
452 NET_ENT.n_net = net;
453 let mut ai = 0usize;
454 for i in 2..n {
455 if ai + 1 >= NET_ALIASES.len() { break; }
456 NET_ALIASES[ai] = toks[i];
457 ai += 1;
458 }
459 NET_ALIASES[ai] = core::ptr::null_mut();
460 NET_ENT.n_aliases = NET_ALIASES.as_mut_ptr();
461 true
462}
463
464unsafe fn net_next(f: *mut FILE) -> bool {
465 let mut line = [0 as c_char; 1024];
466 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
467 if net_parse(line.as_ptr()) { return true; }
468 }
469 false
470}
471
472#[no_mangle]
473pub unsafe extern "C" fn setnetent(stayopen: c_int) {
474 endnetent();
475 NET_FILE = crate::fopen(b"/etc/networks\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
476 let _ = stayopen;
477}
478
479#[no_mangle]
480pub unsafe extern "C" fn endnetent() {
481 if !NET_FILE.is_null() {
482 crate::fclose(NET_FILE);
483 NET_FILE = core::ptr::null_mut();
484 }
485}
486
487#[no_mangle]
488pub unsafe extern "C" fn getnetent() -> *mut NetEnt {
489 if NET_FILE.is_null() {
490 NET_FILE = crate::fopen(b"/etc/networks\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
491 if NET_FILE.is_null() { return core::ptr::null_mut(); }
492 }
493 if net_next(NET_FILE) { &raw mut NET_ENT } else { core::ptr::null_mut() }
494}
495
496unsafe fn net_name_matches(name: *const c_char) -> bool {
497 if crate::strcmp(NET_ENT.n_name as *const u8, name as *const u8) == 0 { return true; }
498 let mut i = 0usize;
499 while !(*NET_ENT.n_aliases.add(i)).is_null() {
500 if crate::strcmp(*NET_ENT.n_aliases.add(i) as *const u8, name as *const u8) == 0 { return true; }
501 i += 1;
502 }
503 false
504}
505
506#[no_mangle]
507pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *mut NetEnt {
508 if name.is_null() { return core::ptr::null_mut(); }
509 let f = crate::fopen(b"/etc/networks\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
510 if !f.is_null() {
511 while net_next(f) {
512 if net_name_matches(name) { crate::fclose(f); return &raw mut NET_ENT; }
513 }
514 crate::fclose(f);
515 }
516 if crate::strcmp(name as *const u8, b"loopback\0".as_ptr()) == 0 {
518 net_parse(b"loopback 127.0.0.0\0".as_ptr() as *const c_char);
519 return &raw mut NET_ENT;
520 }
521 if crate::strcmp(name as *const u8, b"default\0".as_ptr()) == 0 {
522 net_parse(b"default 0.0.0.0\0".as_ptr() as *const c_char);
523 return &raw mut NET_ENT;
524 }
525 core::ptr::null_mut()
526}
527
528#[no_mangle]
529pub unsafe extern "C" fn getnetbyaddr(net: u32, type_: c_int) -> *mut NetEnt {
530 if type_ != AF_INET { return core::ptr::null_mut(); }
531 let f = crate::fopen(b"/etc/networks\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
532 if !f.is_null() {
533 while net_next(f) {
534 let shift = if NET_ENT.n_net < 0x80000000 { 24 }
535 else if NET_ENT.n_net < 0xc0000000 { 16 } else { 8 };
536 if (NET_ENT.n_net >> shift) == (net >> shift) { crate::fclose(f); return &raw mut NET_ENT; }
537 }
538 crate::fclose(f);
539 }
540 core::ptr::null_mut()
541}
542
543#[no_mangle]
548pub unsafe extern "C" fn ether_line(line: *const c_char, ea: *mut u8, hostname: *mut c_char) -> c_int {
549 if line.is_null() || ea.is_null() || hostname.is_null() { return -1; }
550 let mut buf = [0 as c_char; 512];
551 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
552 let n = nd_tokens(line, buf.as_mut_ptr(), buf.len(), &mut toks);
553 if n < 2 { return -1; }
554 if ether_aton_r(toks[0], ea).is_null() { return -1; }
555 let mut i = 0usize;
556 while *toks[1].add(i) != 0 {
557 *hostname.add(i) = *toks[1].add(i);
558 i += 1;
559 }
560 *hostname.add(i) = 0;
561 0
562}
563
564unsafe fn ether_scan(want_name: *const c_char, ea: *mut u8, hostname: *mut c_char) -> c_int {
565 let f = crate::fopen(b"/etc/ethers\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
566 if f.is_null() { return -1; }
567 let mut line = [0 as c_char; 512];
568 let mut found = -1;
569 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
570 let mut mac = [0u8; 6];
571 let mut host = [0 as c_char; 256];
572 if ether_line(line.as_ptr(), mac.as_mut_ptr(), host.as_mut_ptr()) != 0 { continue; }
573 if !want_name.is_null() {
574 if crate::strcmp(host.as_ptr() as *const u8, want_name as *const u8) != 0 { continue; }
575 core::ptr::copy_nonoverlapping(mac.as_ptr(), ea, 6);
576 found = 0;
577 break;
578 } else {
579 let mut same = true;
580 for i in 0..6 {
581 if mac[i] != *ea.add(i) { same = false; break; }
582 }
583 if !same { continue; }
584 let mut i = 0usize;
585 while host[i] != 0 {
586 *hostname.add(i) = host[i];
587 i += 1;
588 }
589 *hostname.add(i) = 0;
590 found = 0;
591 break;
592 }
593 }
594 crate::fclose(f);
595 found
596}
597
598#[no_mangle]
599pub unsafe extern "C" fn ether_hostton(hostname: *const c_char, ea: *mut u8) -> c_int {
600 if hostname.is_null() || ea.is_null() { return -1; }
601 ether_scan(hostname, ea, core::ptr::null_mut())
602}
603
604#[no_mangle]
605pub unsafe extern "C" fn ether_ntohost(hostname: *mut c_char, ea: *const u8) -> c_int {
606 if hostname.is_null() || ea.is_null() { return -1; }
607 ether_scan(core::ptr::null(), ea as *mut u8, hostname)
608}
609
610static mut HOSTS_FILE: *mut FILE = core::ptr::null_mut();
615static mut HOSTS_BUF: [c_char; 1024] = [0; 1024];
616static mut HOSTS_ADDR: [u8; 4] = [0; 4];
617static mut HOSTS_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
618static mut HOSTS_ALIASES: [*mut c_char; 16] = [core::ptr::null_mut(); 16];
619
620unsafe fn hosts_parse(line: *const c_char) -> bool {
621 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
622 let n = nd_tokens(line, HOSTS_BUF.as_mut_ptr(), HOSTS_BUF.len(), &mut toks);
623 if n < 2 { return false; }
624 if inet_pton(AF_INET, toks[0], HOSTS_ADDR.as_mut_ptr() as *mut c_void) != 1 { return false; }
625 HOST_ENT.h_name = toks[1];
626 HOST_ENT.h_addrtype = AF_INET;
627 HOST_ENT.h_length = 4;
628 HOST_ENT.h_addr_list = HOSTS_ADDR_PTRS.as_mut_ptr();
629 HOSTS_ADDR_PTRS[0] = HOSTS_ADDR.as_mut_ptr() as *mut c_char;
630 HOSTS_ADDR_PTRS[1] = core::ptr::null_mut();
631 let mut ai = 0usize;
632 for i in 2..n {
633 if ai + 1 >= HOSTS_ALIASES.len() { break; }
634 HOSTS_ALIASES[ai] = toks[i];
635 ai += 1;
636 }
637 HOSTS_ALIASES[ai] = core::ptr::null_mut();
638 HOST_ENT.h_aliases = HOSTS_ALIASES.as_mut_ptr();
639 true
640}
641
642#[no_mangle]
643pub unsafe extern "C" fn sethostent(_stayopen: c_int) {
644 endhostent();
645}
646
647#[no_mangle]
648pub unsafe extern "C" fn endhostent() {
649 if !HOSTS_FILE.is_null() {
650 crate::fclose(HOSTS_FILE);
651 HOSTS_FILE = core::ptr::null_mut();
652 }
653}
654
655#[no_mangle]
656pub unsafe extern "C" fn gethostent() -> *mut HostEnt {
657 if HOSTS_FILE.is_null() {
658 HOSTS_FILE = crate::fopen(b"/etc/hosts\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
659 if HOSTS_FILE.is_null() { return core::ptr::null_mut(); }
660 }
661 let mut line = [0 as c_char; 1024];
662 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, HOSTS_FILE).is_null() {
663 if hosts_parse(line.as_ptr()) { return &raw mut HOST_ENT; }
664 }
665 core::ptr::null_mut()
666}
667
668unsafe fn hosts_lookup_addr(addr: *const u8, family: c_int) -> bool {
669 let f = crate::fopen(b"/etc/hosts\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
670 if f.is_null() { return false; }
671 let mut line = [0 as c_char; 1024];
672 let mut found = false;
673 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
674 let mut toks: [*mut c_char; 24] = [core::ptr::null_mut(); 24];
675 let n = nd_tokens(line.as_ptr(), HOSTS_BUF.as_mut_ptr(), HOSTS_BUF.len(), &mut toks);
676 if n < 2 { continue; }
677 let mut tmp = [0u8; 16];
678 if inet_pton(AF_INET, toks[0], tmp.as_mut_ptr() as *mut c_void) == 1 {
679 if family != AF_INET { continue; }
680 } else if inet_pton(AF_INET6, toks[0], tmp.as_mut_ptr() as *mut c_void) == 1 {
681 if family != AF_INET6 { continue; }
682 } else {
683 continue;
684 }
685 let len = if family == AF_INET6 { 16 } else { 4 };
686 let mut same = true;
687 for i in 0..len {
688 if tmp[i] != *addr.add(i) { same = false; break; }
689 }
690 if !same { continue; }
691 let nl = crate::strlen(toks[1]);
692 core::ptr::copy_nonoverlapping(toks[1], HOST_NAME.as_mut_ptr(), nl + 1);
693 found = true;
694 break;
695 }
696 crate::fclose(f);
697 found
698}
699
700unsafe fn hosts_lookup_name(name: *const c_char) -> bool {
701 let f = crate::fopen(b"/etc/hosts\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
702 if f.is_null() { return false; }
703 let mut line = [0 as c_char; 1024];
704 let mut found = false;
705 while !crate::fgets(line.as_mut_ptr(), line.len() as c_int, f).is_null() {
706 if !hosts_parse(line.as_ptr()) { continue; }
707 let mut hit = crate::strcmp(HOST_ENT.h_name as *const u8, name as *const u8) == 0;
708 if !hit {
709 let mut i = 0usize;
710 while !(*HOST_ENT.h_aliases.add(i)).is_null() {
711 if crate::strcmp(*HOST_ENT.h_aliases.add(i) as *const u8, name as *const u8) == 0 {
712 hit = true;
713 break;
714 }
715 i += 1;
716 }
717 }
718 if hit { found = true; break; }
719 }
720 crate::fclose(f);
721 found
722}
723
724unsafe fn nd_itoa(mut v: u32, out: *mut c_char) -> usize {
729 let mut digits = [0u8; 10];
730 let mut n = 0usize;
731 if v == 0 { digits[0] = 0; n = 1; }
732 while v > 0 { digits[n] = (v % 10) as u8; v /= 10; n += 1; }
733 let mut o = 0usize;
734 while n > 0 { n -= 1; *out.add(o) = (b'0' + digits[n]) as c_char; o += 1; }
735 *out.add(o) = 0;
736 o
737}
738
739unsafe fn nd_reverse6(addr: *const u8, out: *mut c_char, cap: usize) -> bool {
740 if cap < 74 { return false; }
741 let hex = b"0123456789abcdef";
742 let mut o = 0usize;
743 let mut i = 16isize;
744 while i > 0 {
745 i -= 1;
746 let b = *addr.add(i as usize);
747 *out.add(o) = hex[(b & 0xf) as usize] as c_char; o += 1;
748 *out.add(o) = b'.' as c_char; o += 1;
749 *out.add(o) = hex[(b >> 4) as usize] as c_char; o += 1;
750 *out.add(o) = b'.' as c_char; o += 1;
751 }
752 for &c in b"ip6.arpa\0" { *out.add(o) = c as c_char; o += 1; }
753 true
754}
755
756#[no_mangle]
757pub unsafe extern "C" fn getnameinfo(
758 sa: *const c_void,
759 salen: u32,
760 host: *mut c_char,
761 hostlen: u32,
762 serv: *mut c_char,
763 servlen: u32,
764 flags: c_int,
765) -> c_int {
766 if sa.is_null() { return EAI_FAIL_V; }
767 let family = *(sa as *const u16) as c_int;
768 let mut addr = [0u8; 16];
769 let mut scope: u32 = 0;
770 let port: u16;
771 match family {
772 AF_INET => {
773 if salen < 16 { return EAI_FAMILY_V; }
774 port = u16::from_be(*((sa as *const u8).add(2) as *const u16));
775 core::ptr::copy_nonoverlapping((sa as *const u8).add(4), addr.as_mut_ptr(), 4);
776 }
777 AF_INET6 => {
778 if salen < 28 { return EAI_FAMILY_V; }
779 port = u16::from_be(*((sa as *const u8).add(2) as *const u16));
780 core::ptr::copy_nonoverlapping((sa as *const u8).add(8), addr.as_mut_ptr(), 16);
781 scope = *((sa as *const u8).add(24) as *const u32);
782 }
783 _ => return EAI_FAMILY_V,
784 }
785
786 if !host.is_null() && hostlen > 0 {
787 let mut buf = [0 as c_char; 300];
788 let mut have = false;
789 if flags & NI_NUMERICHOST_V == 0 {
790 have = hosts_lookup_addr(addr.as_ptr(), family);
791 if have {
792 let l = crate::strlen(HOST_NAME.as_ptr());
793 let l = core::cmp::min(l, buf.len() - 1);
794 core::ptr::copy_nonoverlapping(HOST_NAME.as_ptr(), buf.as_mut_ptr(), l);
795 buf[l] = 0;
796 }
797 if !have {
798 let mut ptr = [0 as c_char; 80];
799 let ok = if family == AF_INET {
800 let a = addr;
801 let mut o = 0usize;
803 let mut i = 4usize;
804 while i > 0 {
805 i -= 1;
806 o += nd_itoa(a[i] as u32, ptr.as_mut_ptr().add(o));
807 *ptr.as_mut_ptr().add(o) = b'.' as c_char;
808 o += 1;
809 }
810 for &c in b"in-addr.arpa\0" { *ptr.as_mut_ptr().add(o) = c as c_char; o += 1; }
811 true
812 } else {
813 nd_reverse6(addr.as_ptr(), ptr.as_mut_ptr(), ptr.len())
814 };
815 if ok {
816 let mut answer = [0u8; 512];
817 let r = res_query(ptr.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
818 if r >= 12 {
819 let end = answer.as_ptr().add(r as usize);
820 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
821 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
822 let mut p = answer.as_ptr().add(12);
823 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
824 for _ in 0..an {
825 p = dns_skip_name(p, end);
826 if p.add(10) > end { break; }
827 let typ = dns_read_u16(p);
828 let rdlen = dns_read_u16(p.add(8)) as usize;
829 let rdata = p.add(10);
830 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), buf.as_mut_ptr(), buf.len()) {
831 let mut l = crate::strlen(buf.as_ptr());
832 if l > 0 && buf[l - 1] == b'.' as c_char { l -= 1; }
833 buf[l] = 0;
834 have = l > 0;
835 break;
836 }
837 p = rdata.add(rdlen);
838 }
839 }
840 }
841 }
842 }
843 if !have {
844 if flags & NI_NAMEREQD_V != 0 { return EAI_NONAME_V; }
845 let aptr = if family == AF_INET { addr.as_ptr() as *const c_void } else { addr.as_ptr() as *const c_void };
846 if inet_ntop(family, aptr, buf.as_mut_ptr(), buf.len() as u32).is_null() {
847 return EAI_FAIL_V;
848 }
849 if scope != 0 && family == AF_INET6 {
850 let mut l = crate::strlen(buf.as_ptr());
851 *buf.as_mut_ptr().add(l) = b'%' as c_char;
852 l += 1;
853 let mut name = [0 as c_char; 32];
854 let have_name = flags & NI_NUMERICSCOPE_V == 0
855 && if_indextoname(scope, name.as_mut_ptr()) != core::ptr::null_mut();
856 if have_name {
857 let nl = crate::strlen(name.as_ptr());
858 core::ptr::copy_nonoverlapping(name.as_ptr(), buf.as_mut_ptr().add(l), nl + 1);
859 } else {
860 nd_itoa(scope, buf.as_mut_ptr().add(l));
861 }
862 }
863 }
864 if flags & NI_NOFQDN_V != 0 {
865 let mut i = 0usize;
866 while buf[i] != 0 {
867 if buf[i] == b'.' as c_char { buf[i] = 0; break; }
868 i += 1;
869 }
870 }
871 if crate::strlen(buf.as_ptr()) >= hostlen as usize { return EAI_OVERFLOW_V; }
872 let l = crate::strlen(buf.as_ptr());
873 core::ptr::copy_nonoverlapping(buf.as_ptr(), host, l + 1);
874 }
875
876 if !serv.is_null() && servlen > 0 {
877 let mut buf = [0 as c_char; 64];
878 let mut have = false;
879 if flags & NI_NUMERICSERV_V == 0 {
880 let proto = if flags & NI_DGRAM_V != 0 { b"udp\0" } else { b"tcp\0" };
881 let port_net = (port as u16).to_be() as c_int;
882 let se = getservbyport(port_net, proto.as_ptr() as *const c_char);
883 if !se.is_null() {
884 let l = crate::strlen((*se).s_name);
885 if l < buf.len() {
886 core::ptr::copy_nonoverlapping((*se).s_name, buf.as_mut_ptr(), l + 1);
887 have = true;
888 }
889 }
890 }
891 if !have {
892 nd_itoa(port as u32, buf.as_mut_ptr());
893 }
894 if crate::strlen(buf.as_ptr()) >= servlen as usize { return EAI_OVERFLOW_V; }
895 let l = crate::strlen(buf.as_ptr());
896 core::ptr::copy_nonoverlapping(buf.as_ptr(), serv, l + 1);
897 }
898 0
899}
900
901unsafe fn nd_make_addrinfo(
906 family: c_int,
907 socktype: c_int,
908 protocol: c_int,
909 addr: *const u8,
910 port: u16,
911 flags: c_int,
912 canon: *const c_char,
913) -> *mut AddrInfo {
914 let addrlen: usize = if family == AF_INET6 { 28 } else { 16 };
915 let canonlen = if !canon.is_null() { crate::strlen(canon) + 1 } else { 0 };
916 let total = core::mem::size_of::<AddrInfo>() + addrlen + canonlen;
917 let p = crate::malloc(total) as *mut u8;
918 if p.is_null() { return core::ptr::null_mut(); }
919 core::ptr::write_bytes(p, 0, total);
920 let ai = p as *mut AddrInfo;
921 (*ai).ai_flags = flags;
922 (*ai).ai_family = family;
923 (*ai).ai_socktype = socktype;
924 (*ai).ai_protocol = protocol;
925 (*ai).ai_addrlen = addrlen as u32;
926 let sa = p.add(core::mem::size_of::<AddrInfo>());
927 (*ai).ai_addr = sa as *mut c_void;
928 if family == AF_INET6 {
929 *(sa as *mut u16) = AF_INET6 as u16;
930 *(sa.add(2) as *mut u16) = port.to_be();
931 core::ptr::copy_nonoverlapping(addr, sa.add(8), 16);
932 } else {
933 *(sa as *mut u16) = AF_INET as u16;
934 *(sa.add(2) as *mut u16) = port.to_be();
935 core::ptr::copy_nonoverlapping(addr, sa.add(4), 4);
936 }
937 if canonlen > 0 {
938 let c = sa.add(addrlen);
939 core::ptr::copy_nonoverlapping(canon as *const u8, c, canonlen);
940 (*ai).ai_canonname = c as *mut c_char;
941 }
942 ai
943}
944
945unsafe fn nd_parse_service(service: *const c_char, socktype: c_int, protocol: c_int, port: *mut u16, proto_out: *mut c_int) -> bool {
946 if service.is_null() { *port = 0; return true; }
947 let mut end: *mut c_char = core::ptr::null_mut();
948 let v = crate::strtoul(service, &mut end, 10);
949 let numeric = !end.is_null() && *end == 0;
950 if numeric {
951 if v > 65535 { return false; }
952 *port = v as u16;
953 return true;
954 }
955 let proto_name: *const c_char = if protocol == 6 { b"tcp\0".as_ptr() as *const c_char }
956 else if protocol == 17 { b"udp\0".as_ptr() as *const c_char }
957 else if socktype == SOCK_STREAM { b"tcp\0".as_ptr() as *const c_char }
958 else if socktype == SOCK_DGRAM { b"udp\0".as_ptr() as *const c_char }
959 else { core::ptr::null() };
960 let se = getservbyname(service, proto_name);
961 if se.is_null() { return false; }
962 *port = ntohs((*se).s_port as u16);
963 *proto_out = if crate::strcmp((*se).s_proto as *const u8, b"udp\0".as_ptr()) == 0 { 17 } else { 6 };
964 true
965}
966
967#[no_mangle]
968pub unsafe extern "C" fn getaddrinfo(
969 node: *const c_char,
970 service: *const c_char,
971 hints: *const AddrInfo,
972 res: *mut *mut AddrInfo,
973) -> c_int {
974 if res.is_null() { return EAI_FAIL_V; }
975 *res = core::ptr::null_mut();
976
977 let mut family = 0;
978 let mut socktype = 0;
979 let mut protocol = 0;
980 let mut flags = 0;
981 if !hints.is_null() {
982 family = (*hints).ai_family;
983 socktype = (*hints).ai_socktype;
984 protocol = (*hints).ai_protocol;
985 flags = (*hints).ai_flags;
986 }
987 if family != 0 && family != AF_INET && family != AF_INET6 { return EAI_FAMILY_V; }
988 if socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM { return EAI_SOCKTYPE_V; }
989 if flags & AI_NUMERICSERV_V != 0 && !service.is_null() {
990 let mut end: *mut c_char = core::ptr::null_mut();
991 let _ = crate::strtoul(service, &mut end, 10);
992 if end.is_null() || *end != 0 { return EAI_NONAME_V; }
993 }
994
995 let mut port: u16 = 0;
996 let mut proto_from_service = 0;
997 if !nd_parse_service(service, socktype, protocol, &mut port, &mut proto_from_service) {
998 return EAI_SERVICE_V;
999 }
1000
1001 let mut addrs: [[u8; 16]; 8] = [[0; 16]; 8];
1002 let mut fams: [c_int; 8] = [0; 8];
1003 let mut count = 0usize;
1004 let mut canon: [c_char; 256] = [0; 256];
1005
1006 if node.is_null() {
1007 if family == 0 || family == AF_INET6 {
1008 if family == 0 && flags & AI_V4MAPPED_V != 0 && flags & AI_ALL_V != 0 {
1009 }
1011 addrs[count] = [0; 16];
1012 if flags & AI_PASSIVE_V == 0 {
1013 addrs[count][15] = 1;
1014 }
1015 fams[count] = AF_INET6;
1016 count += 1;
1017 }
1018 if family == 0 || family == AF_INET {
1019 addrs[count] = [0; 16];
1020 if flags & AI_PASSIVE_V == 0 {
1021 addrs[count][0] = 127;
1022 addrs[count][3] = 1;
1023 }
1024 fams[count] = AF_INET;
1025 count += 1;
1026 }
1027 } else {
1028 let mut numeric = false;
1029 let mut tmp = [0u8; 16];
1030 if inet_pton(AF_INET, node, tmp.as_mut_ptr() as *mut c_void) == 1 {
1031 numeric = true;
1032 if family == 0 || family == AF_INET {
1033 addrs[count][..4].copy_from_slice(&tmp[..4]);
1034 fams[count] = AF_INET;
1035 count += 1;
1036 }
1037 }
1038 if !numeric && inet_pton(AF_INET6, node, tmp.as_mut_ptr() as *mut c_void) == 1 {
1039 numeric = true;
1040 if family == 0 || family == AF_INET6 {
1041 addrs[count] = tmp;
1042 fams[count] = AF_INET6;
1043 count += 1;
1044 }
1045 }
1046 if flags & AI_NUMERICHOST_V != 0 && !numeric {
1047 return EAI_NONAME_V;
1048 }
1049 if !numeric {
1050 let mut got = false;
1051 if hosts_lookup_name(node) {
1053 let l = core::cmp::min(crate::strlen(HOST_ENT.h_name), canon.len() - 1);
1054 core::ptr::copy_nonoverlapping(HOST_ENT.h_name, canon.as_mut_ptr(), l);
1055 canon[l] = 0;
1056 if family == 0 || family == AF_INET {
1057 core::ptr::copy_nonoverlapping(HOSTS_ADDR.as_ptr(), addrs[count].as_mut_ptr(), 4);
1058 fams[count] = AF_INET;
1059 count += 1;
1060 got = true;
1061 }
1062 if family == AF_INET6 {
1065 got = false;
1066 }
1067 }
1068 if !got {
1069 let order: [c_int; 2] = if family == AF_INET6 { [AF_INET6, AF_INET] } else { [AF_INET, AF_INET6] };
1070 for &f in &order {
1071 if family != 0 && family != f { continue; }
1072 let h = gethostbyname2(node, f);
1073 if h.is_null() { continue; }
1074 let n = core::cmp::min((*h).h_length as usize, 16);
1075 core::ptr::copy_nonoverlapping((*h).h_addr_list.read() as *const u8, addrs[count].as_mut_ptr(), n);
1076 fams[count] = f;
1077 count += 1;
1078 let hl = crate::strlen((*h).h_name);
1079 let l = core::cmp::min(hl, canon.len() - 1);
1080 core::ptr::copy_nonoverlapping((*h).h_name, canon.as_mut_ptr(), l);
1081 canon[l] = 0;
1082 got = true;
1083 if family != 0 { break; }
1084 }
1085 }
1086 if !got {
1087 return if h_errno == TRY_AGAIN { EAI_AGAIN_V } else { EAI_NONAME_V };
1088 }
1089 }
1090 }
1091 if count == 0 { return EAI_NONAME_V; }
1092
1093 let canonptr: *const c_char = if flags & AI_CANONNAME_V != 0 && canon[0] != 0 {
1094 canon.as_ptr()
1095 } else if flags & AI_CANONNAME_V != 0 && !node.is_null() {
1096 node
1097 } else {
1098 core::ptr::null()
1099 };
1100
1101 let mut head: *mut AddrInfo = core::ptr::null_mut();
1102 let mut tail: *mut AddrInfo = core::ptr::null_mut();
1103 let mut emitted = 0usize;
1104 for i in 0..count {
1105 let types: [c_int; 2] = if socktype == 0 { [SOCK_STREAM, SOCK_DGRAM] } else { [socktype, socktype] };
1106 let ntypes = if socktype == 0 { 2 } else { 1 };
1107 for t in 0..ntypes {
1108 let st = types[t];
1109 if protocol != 0 {
1110 if (protocol == 6 && st != SOCK_STREAM) || (protocol == 17 && st != SOCK_DGRAM) { continue; }
1111 }
1112 if proto_from_service != 0 && protocol == 0 {
1113 if (proto_from_service == 6 && st != SOCK_STREAM) || (proto_from_service == 17 && st != SOCK_DGRAM) { continue; }
1114 }
1115 let proto = if protocol != 0 { protocol } else if st == SOCK_STREAM { 6 } else { 17 };
1116 let cp = if emitted == 0 { canonptr } else { core::ptr::null() };
1117 let ai = nd_make_addrinfo(fams[i], st, proto, addrs[i].as_ptr(), port, flags, cp);
1118 if ai.is_null() {
1119 freeaddrinfo(head);
1120 return EAI_MEMORY_V;
1121 }
1122 if head.is_null() { head = ai; } else { (*tail).ai_next = ai; }
1123 tail = ai;
1124 emitted += 1;
1125 }
1126 }
1127 if emitted == 0 { return EAI_SERVICE_V; }
1128 *res = head;
1129 0
1130}
1131
1132#[no_mangle]
1133pub unsafe extern "C" fn freeaddrinfo(mut ai: *mut AddrInfo) {
1134 while !ai.is_null() {
1135 let next = (*ai).ai_next;
1136 crate::free(ai as *mut c_void);
1137 ai = next;
1138 }
1139}
1140
1141#[no_mangle]
1142pub unsafe extern "C" fn gai_strerror(code: c_int) -> *const c_char {
1143 let s: &[u8] = match code {
1144 EAI_BADFLAGS_V => b"Bad flags\0",
1145 EAI_NONAME_V => b"Name not known\0",
1146 EAI_AGAIN_V => b"Try again\0",
1147 EAI_FAIL_V => b"Non-recoverable failure\0",
1148 -5 => b"No address data\0",
1149 EAI_FAMILY_V => b"Unsupported family\0",
1150 EAI_SOCKTYPE_V => b"Unsupported socket type\0",
1151 EAI_SERVICE_V => b"Unsupported service\0",
1152 -9 => b"Address family not supported\0",
1153 EAI_MEMORY_V => b"Out of memory\0",
1154 EAI_SYSTEM_V => b"System error\0",
1155 EAI_OVERFLOW_V => b"Overflow\0",
1156 _ => b"Unknown error\0",
1157 };
1158 s.as_ptr() as *const c_char
1159}
1160
1161#[no_mangle]
1166pub unsafe extern "C" fn ttyname_r(fd: c_int, name: *mut c_char, size: usize) -> c_int {
1167 if name.is_null() || size == 0 { return EINVAL; }
1168 if crate::isatty(fd) != 1 { return NDB_ENOTTY; }
1169 let mut procname = [0 as c_char; 32];
1170 let mut o = 0usize;
1171 for &c in b"/proc/self/fd/" { procname[o] = c as c_char; o += 1; }
1172 o += nd_itoa(fd as u32, procname.as_mut_ptr().add(o));
1173 procname[o] = 0;
1174 let n = crate::readlink(procname.as_ptr(), name, size - 1);
1175 if n < 0 { return ERRNO!(); }
1176 if n as usize == size - 1 { return NDB_ERANGE; }
1177 *name.add(n as usize) = 0;
1178 0
1179}
1180
1181#[no_mangle]
1182pub unsafe extern "C" fn ttyname(fd: c_int) -> *mut c_char {
1183 static mut TTY_BUF: [c_char; 64] = [0; 64];
1184 if ttyname_r(fd, TTY_BUF.as_mut_ptr(), TTY_BUF.len()) != 0 {
1185 core::ptr::null_mut()
1186 } else {
1187 TTY_BUF.as_mut_ptr()
1188 }
1189}
1190
1191unsafe fn host_copy_out(
1196 h: *mut HostEnt,
1197 ret: *mut HostEnt,
1198 buf: *mut c_char,
1199 buflen: usize,
1200 result: *mut *mut HostEnt,
1201) -> c_int {
1202 if result.is_null() { return EINVAL; }
1203 *result = core::ptr::null_mut();
1204 let ptrsz = core::mem::size_of::<*mut c_char>();
1205 let mut need = crate::strlen((*h).h_name) + 1;
1206 let mut nalias = 0usize;
1207 if !(*h).h_aliases.is_null() {
1208 while !(*(*h).h_aliases.add(nalias)).is_null() {
1209 need += crate::strlen(*(*h).h_aliases.add(nalias)) + 1;
1210 nalias += 1;
1211 }
1212 }
1213 let alen = (*h).h_length as usize;
1214 let align = (ptrsz - (buf as usize & (ptrsz - 1))) & (ptrsz - 1);
1215 need += align + (nalias + 1) * ptrsz + alen + 2 * ptrsz;
1216 if need > buflen { return NDB_ERANGE; }
1217
1218 let mut p = buf.add(align);
1219 let aliases = p as *mut *mut c_char;
1220 p = p.add((nalias + 1) * ptrsz);
1221 let addr_list = p as *mut *mut c_char;
1222 p = p.add(2 * ptrsz);
1223
1224 let n = crate::strlen((*h).h_name);
1225 core::ptr::copy_nonoverlapping((*h).h_name, p, n + 1);
1226 (*ret).h_name = p;
1227 p = p.add(n + 1);
1228
1229 for i in 0..nalias {
1230 let src = *(*h).h_aliases.add(i);
1231 let n = crate::strlen(src);
1232 core::ptr::copy_nonoverlapping(src, p, n + 1);
1233 *aliases.add(i) = p;
1234 p = p.add(n + 1);
1235 }
1236 *aliases.add(nalias) = core::ptr::null_mut();
1237
1238 let src = *(*h).h_addr_list;
1239 core::ptr::copy_nonoverlapping(src, p, alen);
1240 *addr_list = p;
1241 *addr_list.add(1) = core::ptr::null_mut();
1242
1243 (*ret).h_aliases = aliases;
1244 (*ret).h_addrtype = (*h).h_addrtype;
1245 (*ret).h_length = (*h).h_length;
1246 (*ret).h_addr_list = addr_list;
1247 *result = ret;
1248 0
1249}
1250
1251#[no_mangle]
1252pub unsafe extern "C" fn gethostbyname_r(
1253 name: *const c_char,
1254 ret: *mut HostEnt,
1255 buf: *mut c_char,
1256 buflen: usize,
1257 result: *mut *mut HostEnt,
1258 errnop: *mut c_int,
1259) -> c_int {
1260 gethostbyname2_r(name, AF_INET, ret, buf, buflen, result, errnop)
1261}
1262
1263#[no_mangle]
1264pub unsafe extern "C" fn gethostbyname2_r(
1265 name: *const c_char,
1266 af: c_int,
1267 ret: *mut HostEnt,
1268 buf: *mut c_char,
1269 buflen: usize,
1270 result: *mut *mut HostEnt,
1271 errnop: *mut c_int,
1272) -> c_int {
1273 if result.is_null() { return EINVAL; }
1274 *result = core::ptr::null_mut();
1275 let h = gethostbyname2(name, af);
1276 if h.is_null() {
1277 if !errnop.is_null() { *errnop = if h_errno != 0 { h_errno } else { HOST_NOT_FOUND }; }
1278 return 0;
1279 }
1280 let r = host_copy_out(h, ret, buf, buflen, result);
1281 if r == NDB_ERANGE {
1282 if !errnop.is_null() { *errnop = NO_RECOVERY; }
1283 *result = core::ptr::null_mut();
1284 }
1285 r
1286}
1287
1288#[no_mangle]
1289pub unsafe extern "C" fn gethostbyaddr_r(
1290 addr: *const c_void,
1291 len: u32,
1292 type_: c_int,
1293 ret: *mut HostEnt,
1294 buf: *mut c_char,
1295 buflen: usize,
1296 result: *mut *mut HostEnt,
1297 errnop: *mut c_int,
1298) -> c_int {
1299 if result.is_null() { return EINVAL; }
1300 *result = core::ptr::null_mut();
1301 let h = gethostbyaddr(addr, len, type_);
1302 if h.is_null() {
1303 if !errnop.is_null() { *errnop = if h_errno != 0 { h_errno } else { HOST_NOT_FOUND }; }
1304 return 0;
1305 }
1306 let r = host_copy_out(h, ret, buf, buflen, result);
1307 if r == NDB_ERANGE {
1308 if !errnop.is_null() { *errnop = NO_RECOVERY; }
1309 *result = core::ptr::null_mut();
1310 }
1311 r
1312}
1313
1314
1315#[no_mangle]
1316pub unsafe extern "C" fn initgroups(user: *const c_char, group: u32) -> c_int {
1317 if user.is_null() { ERRNO!() = EINVAL; return -1; }
1318 let mut buf = [0u32; 256];
1319 let mut n: c_int = buf.len() as c_int;
1320 if getgrouplist(user, group, buf.as_mut_ptr(), &mut n) < 0 {
1321 if n <= 0 { return -1; }
1322 let p = crate::malloc(n as usize * core::mem::size_of::<u32>()) as *mut u32;
1323 if p.is_null() { return -1; }
1324 let mut n2 = n;
1325 let r = getgrouplist(user, group, p, &mut n2);
1326 let rr = if r < 0 { -1 } else { crate::setgroups(n2 as usize, p) };
1327 crate::free(p as *mut c_void);
1328 return rr;
1329 }
1330 crate::setgroups(n as usize, buf.as_ptr())
1331}