1#![allow(dead_code)]
2#![allow(nonstandard_style)]
3
4mod addrinfo;
5
6use alloc::boxed::Box;
7use alloc::sync::Arc;
8use core::ffi::{c_char, c_void};
9use core::mem::{self, size_of};
10use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
11#[allow(unused_imports)]
12use core::ops::DerefMut;
13
14use cfg_if::cfg_if;
15use num_enum::{IntoPrimitive, TryFromPrimitive, TryFromPrimitiveError};
16#[cfg(any(feature = "tcp", feature = "udp"))]
17use smoltcp::wire::{IpAddress, IpEndpoint, IpListenEndpoint};
18
19use crate::errno::Errno;
20#[cfg(any(feature = "tcp", feature = "udp"))]
21use crate::executor::network::{NIC, NetworkState};
22#[cfg(feature = "tcp")]
23use crate::fd::socket::tcp;
24#[cfg(feature = "udp")]
25use crate::fd::socket::udp;
26#[cfg(feature = "vsock")]
27use crate::fd::socket::vsock::{self, VsockEndpoint, VsockListenEndpoint};
28use crate::fd::{
29 self, Endpoint, ListenEndpoint, ObjectInterface, SocketOption, get_object, insert_object,
30};
31use crate::syscalls::block_on;
32
33#[derive(TryFromPrimitive, IntoPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
34#[repr(u8)]
35pub enum Af {
36 Unspec = 0,
37 Inet = 3,
38 Inet6 = 1,
39 #[cfg(feature = "vsock")]
40 Vsock = 2,
41}
42
43impl From<IpAddr> for Af {
44 fn from(value: IpAddr) -> Self {
45 match value {
46 IpAddr::V4(_) => Self::Inet,
47 IpAddr::V6(_) => Self::Inet6,
48 }
49 }
50}
51
52#[derive(TryFromPrimitive, IntoPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
53#[repr(u8)]
54pub enum Ipproto {
55 Ip = 0,
56 Ipv6 = 41,
57 Tcp = 6,
58 Udp = 17,
59}
60
61pub const IPV6_ADD_MEMBERSHIP: i32 = 12;
62pub const IPV6_DROP_MEMBERSHIP: i32 = 13;
63pub const IPV6_MULTICAST_LOOP: i32 = 19;
64pub const IPV6_V6ONLY: i32 = 27;
65pub const IP_TOS: i32 = 1;
66pub const IP_TTL: i32 = 2;
67pub const IP_MULTICAST_TTL: i32 = 5;
68pub const IP_MULTICAST_LOOP: i32 = 7;
69pub const IP_ADD_MEMBERSHIP: i32 = 3;
70pub const IP_DROP_MEMBERSHIP: i32 = 4;
71pub const SOL_SOCKET: i32 = 4095;
72pub const SO_REUSEADDR: i32 = 0x0004;
73pub const SO_KEEPALIVE: i32 = 0x0008;
74pub const SO_BROADCAST: i32 = 0x0020;
75pub const SO_LINGER: i32 = 0x0080;
76pub const SO_SNDBUF: i32 = 0x1001;
77pub const SO_RCVBUF: i32 = 0x1002;
78pub const SO_SNDTIMEO: i32 = 0x1005;
79pub const SO_RCVTIMEO: i32 = 0x1006;
80pub const SO_ERROR: i32 = 0x1007;
81pub const TCP_NODELAY: i32 = 1;
82pub const MSG_PEEK: i32 = 1;
83pub type sa_family_t = u8;
84pub type socklen_t = u32;
85pub type in_addr_t = u32;
86pub type in_port_t = u16;
87
88#[derive(TryFromPrimitive, IntoPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
89#[repr(u8)]
90pub enum Sock {
91 Stream = 1,
92 Dgram = 2,
93 Raw = 3,
94 Seqpacket = 5,
95}
96
97bitflags! {
98 #[derive(Debug, Copy, Clone)]
99 #[repr(C)]
100 pub struct SockFlags: i32 {
101 const SOCK_NONBLOCK = 0o4000;
102 const SOCK_CLOEXEC = 0o40000;
103 const _ = !0;
104 }
105}
106
107impl Sock {
108 pub fn from_bits(bits: i32) -> Option<(Self, SockFlags)> {
109 let sock = Sock::try_from(bits as u8).ok()?;
110 let flags = SockFlags::from_bits_retain(bits & !0xff);
111 Some((sock, flags))
112 }
113}
114
115#[repr(C)]
116#[derive(Debug, Default, Copy, Clone)]
117pub struct in_addr {
118 pub s_addr: in_addr_t,
119}
120
121impl From<Ipv4Addr> for in_addr {
122 fn from(value: Ipv4Addr) -> Self {
123 Self {
124 s_addr: u32::from_ne_bytes(value.octets()),
125 }
126 }
127}
128
129#[repr(C, align(4))]
130#[derive(Debug, Default, Copy, Clone)]
131pub struct in6_addr {
132 pub s6_addr: [u8; 16],
133}
134
135impl From<Ipv6Addr> for in6_addr {
136 fn from(value: Ipv6Addr) -> Self {
137 Self {
138 s6_addr: value.octets(),
139 }
140 }
141}
142
143#[repr(C)]
144#[derive(Debug, Default, Copy, Clone)]
145pub struct sockaddr {
146 pub sa_len: u8,
147 pub sa_family: sa_family_t,
148 pub sa_data: [c_char; 14],
149}
150
151#[derive(Clone, Debug)]
152pub enum sockaddrBox {
153 sockaddr(Box<sockaddr>),
154 sockaddr_in(Box<sockaddr_in>),
155 sockaddr_in6(Box<sockaddr_in6>),
156 #[cfg(feature = "vsock")]
157 sockaddr_vm(Box<sockaddr_vm>),
158}
159
160#[derive(Clone, Copy, Debug)]
161pub enum sockaddrRef<'a> {
162 sockaddr(&'a sockaddr),
163 sockaddr_in(&'a sockaddr_in),
164 sockaddr_in6(&'a sockaddr_in6),
165 #[cfg(feature = "vsock")]
166 sockaddr_vm(&'a sockaddr_vm),
167}
168
169impl sockaddr {
170 pub unsafe fn sa_family(ptr: *const Self) -> Result<Af, TryFromPrimitiveError<Af>> {
171 let sa_family = unsafe { (*ptr).sa_family };
172 Af::try_from(sa_family)
173 }
174
175 pub unsafe fn as_ref(ptr: &*const Self) -> Result<sockaddrRef<'_>, TryFromPrimitiveError<Af>> {
176 let ptr = *ptr;
177 let sa_family = unsafe { Self::sa_family(ptr)? };
178 let ret = match sa_family {
179 Af::Unspec => sockaddrRef::sockaddr(unsafe { &*ptr }),
180 Af::Inet => sockaddrRef::sockaddr_in(unsafe { &*ptr.cast() }),
181 Af::Inet6 => sockaddrRef::sockaddr_in6(unsafe { &*ptr.cast() }),
182 #[cfg(feature = "vsock")]
183 Af::Vsock => sockaddrRef::sockaddr_vm(unsafe { &*ptr.cast() }),
184 };
185 Ok(ret)
186 }
187
188 pub unsafe fn as_box(ptr: *mut Self) -> Result<sockaddrBox, TryFromPrimitiveError<Af>> {
189 let sa_family = unsafe { Self::sa_family(ptr)? };
190 let ret = match sa_family {
191 Af::Unspec => sockaddrBox::sockaddr(unsafe { Box::from_raw(ptr) }),
192 Af::Inet => sockaddrBox::sockaddr_in(unsafe { Box::from_raw(ptr.cast()) }),
193 Af::Inet6 => sockaddrBox::sockaddr_in6(unsafe { Box::from_raw(ptr.cast()) }),
194 #[cfg(feature = "vsock")]
195 Af::Vsock => sockaddrBox::sockaddr_vm(unsafe { Box::from_raw(ptr.cast()) }),
196 };
197 Ok(ret)
198 }
199}
200
201impl sockaddrBox {
202 pub fn into_raw(self) -> *mut sockaddr {
203 match self {
204 sockaddrBox::sockaddr(sockaddr) => Box::into_raw(sockaddr),
205 sockaddrBox::sockaddr_in(sockaddr_in) => Box::into_raw(sockaddr_in).cast(),
206 sockaddrBox::sockaddr_in6(sockaddr_in6) => Box::into_raw(sockaddr_in6).cast(),
207 #[cfg(feature = "vsock")]
208 sockaddrBox::sockaddr_vm(sockaddr_vm) => Box::into_raw(sockaddr_vm).cast(),
209 }
210 }
211
212 pub fn as_ref(&self) -> sockaddrRef<'_> {
213 match self {
214 Self::sockaddr(sockaddr) => sockaddrRef::sockaddr(sockaddr.as_ref()),
215 Self::sockaddr_in(sockaddr_in) => sockaddrRef::sockaddr_in(sockaddr_in.as_ref()),
216 Self::sockaddr_in6(sockaddr_in6) => sockaddrRef::sockaddr_in6(sockaddr_in6.as_ref()),
217 #[cfg(feature = "vsock")]
218 Self::sockaddr_vm(sockaddr_vm) => sockaddrRef::sockaddr_vm(sockaddr_vm.as_ref()),
219 }
220 }
221}
222
223impl From<SocketAddr> for sockaddrBox {
224 fn from(value: SocketAddr) -> Self {
225 match value {
226 SocketAddr::V4(socket_addr_v4) => Self::sockaddr_in(Box::new(socket_addr_v4.into())),
227 SocketAddr::V6(socket_addr_v6) => Self::sockaddr_in6(Box::new(socket_addr_v6.into())),
228 }
229 }
230}
231
232impl sockaddrRef<'_> {
233 pub fn addrlen(self) -> u8 {
234 match self {
235 sockaddrRef::sockaddr(sockaddr) => sockaddr.sa_len,
236 sockaddrRef::sockaddr_in(sockaddr_in) => sockaddr_in.sin_len,
237 sockaddrRef::sockaddr_in6(sockaddr_in6) => sockaddr_in6.sin6_len,
238 #[cfg(feature = "vsock")]
239 sockaddrRef::sockaddr_vm(sockaddr_vm) => sockaddr_vm.svm_len,
240 }
241 }
242}
243
244#[cfg(feature = "vsock")]
245#[repr(C)]
246#[derive(Debug, Copy, Clone, Default)]
247pub struct sockaddr_vm {
248 pub svm_len: u8,
249 pub svm_family: sa_family_t,
250 pub svm_reserved1: u16,
251 pub svm_port: u32,
252 pub svm_cid: u32,
253 pub svm_zero: [u8; 4],
254}
255
256#[cfg(feature = "vsock")]
257impl From<sockaddr_vm> for VsockListenEndpoint {
258 fn from(addr: sockaddr_vm) -> VsockListenEndpoint {
259 let port = addr.svm_port;
260 let cid = if addr.svm_cid < u32::MAX {
261 Some(addr.svm_cid)
262 } else {
263 None
264 };
265
266 VsockListenEndpoint::new(port, cid)
267 }
268}
269
270#[cfg(feature = "vsock")]
271impl From<sockaddr_vm> for VsockEndpoint {
272 fn from(addr: sockaddr_vm) -> VsockEndpoint {
273 let port = addr.svm_port;
274 let cid = addr.svm_cid;
275
276 VsockEndpoint::new(port, cid)
277 }
278}
279
280#[cfg(feature = "vsock")]
281impl From<VsockEndpoint> for sockaddr_vm {
282 fn from(endpoint: VsockEndpoint) -> Self {
283 Self {
284 svm_len: core::mem::size_of::<sockaddr_vm>().try_into().unwrap(),
285 svm_family: Af::Vsock.into(),
286 svm_port: endpoint.port,
287 svm_cid: endpoint.cid,
288 ..Default::default()
289 }
290 }
291}
292
293#[repr(C)]
294#[derive(Debug, Default, Copy, Clone)]
295pub struct sockaddr_in {
296 pub sin_len: u8,
297 pub sin_family: sa_family_t,
298 pub sin_port: in_port_t,
299 pub sin_addr: in_addr,
300 pub sin_zero: [c_char; 8],
301}
302
303#[cfg(any(feature = "tcp", feature = "udp"))]
304impl From<sockaddr_in> for IpListenEndpoint {
305 fn from(addr: sockaddr_in) -> IpListenEndpoint {
306 let port = u16::from_be(addr.sin_port);
307 if addr.sin_addr.s_addr == 0 {
308 IpListenEndpoint { addr: None, port }
309 } else {
310 let s_addr = addr.sin_addr.s_addr.to_ne_bytes();
311
312 let address = IpAddress::v4(s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
313
314 IpListenEndpoint::from((address, port))
315 }
316 }
317}
318
319#[cfg(any(feature = "tcp", feature = "udp"))]
320impl From<sockaddr_in> for IpEndpoint {
321 fn from(addr: sockaddr_in) -> IpEndpoint {
322 let port = u16::from_be(addr.sin_port);
323 let s_addr = addr.sin_addr.s_addr.to_ne_bytes();
324 let address = IpAddress::v4(s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
325
326 IpEndpoint::from((address, port))
327 }
328}
329
330#[cfg(any(feature = "tcp", feature = "udp"))]
331impl From<IpEndpoint> for sockaddr_in {
332 fn from(endpoint: IpEndpoint) -> Self {
333 match endpoint.addr {
334 IpAddress::Ipv4(ip) => {
335 let sin_addr = in_addr {
336 s_addr: u32::from_ne_bytes(ip.octets()),
337 };
338
339 Self {
340 sin_len: core::mem::size_of::<sockaddr_in>().try_into().unwrap(),
341 sin_port: endpoint.port.to_be(),
342 sin_family: Af::Inet.into(),
343 sin_addr,
344 ..Default::default()
345 }
346 }
347 IpAddress::Ipv6(_) => panic!("Unable to convert IPv6 address to sockadd_in"),
348 }
349 }
350}
351
352impl From<SocketAddrV4> for sockaddr_in {
353 fn from(value: SocketAddrV4) -> Self {
354 Self {
355 sin_len: mem::size_of::<Self>().try_into().unwrap(),
356 sin_family: Af::Inet.into(),
357 sin_port: value.port().to_be(),
358 sin_addr: (*value.ip()).into(),
359 sin_zero: Default::default(),
360 }
361 }
362}
363
364#[repr(C)]
365#[derive(Debug, Default, Copy, Clone)]
366pub struct sockaddr_in6 {
367 pub sin6_len: u8,
368 pub sin6_family: sa_family_t,
369 pub sin6_port: in_port_t,
370 pub sin6_flowinfo: u32,
371 pub sin6_addr: in6_addr,
372 pub sin6_scope_id: u32,
373}
374
375#[cfg(any(feature = "tcp", feature = "udp"))]
376impl From<sockaddr_in6> for IpListenEndpoint {
377 fn from(addr: sockaddr_in6) -> IpListenEndpoint {
378 let port = u16::from_be(addr.sin6_port);
379 if addr.sin6_addr.s6_addr.into_iter().all(|b| b == 0) {
380 IpListenEndpoint { addr: None, port }
381 } else {
382 let s6_addr = addr.sin6_addr.s6_addr;
383 let a0 = (u16::from(s6_addr[0]) << 8) | u16::from(s6_addr[1]);
384 let a1 = (u16::from(s6_addr[2]) << 8) | u16::from(s6_addr[3]);
385 let a2 = (u16::from(s6_addr[4]) << 8) | u16::from(s6_addr[5]);
386 let a3 = (u16::from(s6_addr[6]) << 8) | u16::from(s6_addr[7]);
387 let a4 = (u16::from(s6_addr[8]) << 8) | u16::from(s6_addr[9]);
388 let a5 = (u16::from(s6_addr[10]) << 8) | u16::from(s6_addr[11]);
389 let a6 = (u16::from(s6_addr[12]) << 8) | u16::from(s6_addr[13]);
390 let a7 = (u16::from(s6_addr[14]) << 8) | u16::from(s6_addr[15]);
391 let address = IpAddress::v6(a0, a1, a2, a3, a4, a5, a6, a7);
392
393 IpListenEndpoint::from((address, port))
394 }
395 }
396}
397
398#[cfg(any(feature = "tcp", feature = "udp"))]
399impl From<sockaddr_in6> for IpEndpoint {
400 fn from(addr: sockaddr_in6) -> IpEndpoint {
401 let port = u16::from_be(addr.sin6_port);
402 let s6_addr = addr.sin6_addr.s6_addr;
403 let a0 = (u16::from(s6_addr[0]) << 8) | u16::from(s6_addr[1]);
404 let a1 = (u16::from(s6_addr[2]) << 8) | u16::from(s6_addr[3]);
405 let a2 = (u16::from(s6_addr[4]) << 8) | u16::from(s6_addr[5]);
406 let a3 = (u16::from(s6_addr[6]) << 8) | u16::from(s6_addr[7]);
407 let a4 = (u16::from(s6_addr[8]) << 8) | u16::from(s6_addr[9]);
408 let a5 = (u16::from(s6_addr[10]) << 8) | u16::from(s6_addr[11]);
409 let a6 = (u16::from(s6_addr[12]) << 8) | u16::from(s6_addr[13]);
410 let a7 = (u16::from(s6_addr[14]) << 8) | u16::from(s6_addr[15]);
411 let address = IpAddress::v6(a0, a1, a2, a3, a4, a5, a6, a7);
412
413 IpEndpoint::from((address, port))
414 }
415}
416
417#[cfg(any(feature = "tcp", feature = "udp"))]
418impl From<IpEndpoint> for sockaddr_in6 {
419 fn from(endpoint: IpEndpoint) -> Self {
420 match endpoint.addr {
421 IpAddress::Ipv6(ip) => {
422 let mut in6_addr = in6_addr::default();
423 in6_addr.s6_addr.copy_from_slice(&ip.octets());
424
425 Self {
426 sin6_len: core::mem::size_of::<sockaddr_in6>().try_into().unwrap(),
427 sin6_port: endpoint.port.to_be(),
428 sin6_family: Af::Inet6.into(),
429 sin6_addr: in6_addr,
430 ..Default::default()
431 }
432 }
433 IpAddress::Ipv4(_) => panic!("Unable to convert IPv4 address to sockadd_in6"),
434 }
435 }
436}
437
438impl From<SocketAddrV6> for sockaddr_in6 {
439 fn from(value: SocketAddrV6) -> Self {
440 Self {
441 sin6_len: mem::size_of::<Self>().try_into().unwrap(),
442 sin6_family: Af::Inet6.into(),
443 sin6_port: value.port().to_be(),
444 sin6_flowinfo: Default::default(),
445 sin6_addr: (*value.ip()).into(),
446 sin6_scope_id: Default::default(),
447 }
448 }
449}
450
451#[repr(C)]
452#[derive(Debug, Copy, Clone)]
453pub struct ip_mreq {
454 pub imr_multiaddr: in_addr,
455 pub imr_interface: in_addr,
456}
457
458#[repr(C)]
459#[derive(Debug, Copy, Clone)]
460pub struct ipv6_mreq {
461 pub ipv6mr_multiaddr: in6_addr,
462 pub ipv6mr_interface: u32,
463}
464#[repr(C)]
465#[derive(Debug, Copy, Clone)]
466pub struct linger {
467 pub l_onoff: i32,
468 pub l_linger: i32,
469}
470
471#[cfg(not(feature = "dns"))]
472#[hermit_macro::system(errno)]
473#[unsafe(no_mangle)]
474pub unsafe extern "C" fn sys_getaddrbyname(
475 _name: *const c_char,
476 _inaddr: *mut u8,
477 _len: usize,
478) -> i32 {
479 error!("Please enable the feature 'dns' to determine the network ip by name.");
480 -i32::from(Errno::Nosys)
481}
482
483#[cfg(feature = "dns")]
506#[hermit_macro::system(errno)]
507#[unsafe(no_mangle)]
508pub unsafe extern "C" fn sys_getaddrbyname(
509 name: *const c_char,
510 inaddr: *mut u8,
511 len: usize,
512) -> i32 {
513 use alloc::borrow::ToOwned;
514
515 use smoltcp::wire::DnsQueryType;
516
517 use crate::executor::block_on;
518 use crate::executor::network::get_query_result;
519
520 if len != size_of::<in_addr>() && len != size_of::<in6_addr>() {
521 return -i32::from(Errno::Inval);
522 }
523
524 if inaddr.is_null() {
525 return -i32::from(Errno::Inval);
526 }
527
528 let query_type = if len == size_of::<in6_addr>() {
529 DnsQueryType::Aaaa
530 } else {
531 DnsQueryType::A
532 };
533
534 let name = unsafe { core::ffi::CStr::from_ptr(name) };
535 let name = if let Ok(name) = name.to_str() {
536 name.to_owned()
537 } else {
538 return -i32::from(Errno::Inval);
539 };
540
541 let query = {
542 let mut guard = NIC.lock();
543 let nic = guard.as_nic_mut().unwrap();
544 let query = nic.start_query(&name, query_type).unwrap();
545 nic.poll_common(crate::executor::network::now());
546
547 query
548 };
549
550 match block_on(get_query_result(query), None) {
551 Ok(addr_vec) => {
552 let slice = unsafe { core::slice::from_raw_parts_mut(inaddr, len) };
553
554 match addr_vec[0] {
555 IpAddress::Ipv4(ipv4_addr) => slice.copy_from_slice(&ipv4_addr.octets()),
556 IpAddress::Ipv6(ipv6_addr) => slice.copy_from_slice(&ipv6_addr.octets()),
557 }
558
559 0
560 }
561 Err(e) => -i32::from(e),
562 }
563}
564
565#[hermit_macro::system(errno)]
566#[unsafe(no_mangle)]
567pub extern "C" fn sys_socket(domain: i32, type_: i32, protocol: i32) -> i32 {
568 debug!("sys_socket: domain {domain}, type {type_:?}, protocol {protocol}");
569
570 let Ok(Ok(domain)) = u8::try_from(domain).map(Af::try_from) else {
571 return -i32::from(Errno::Inval);
572 };
573
574 let Some((sock, sock_flags)) = Sock::from_bits(type_) else {
575 return -i32::from(Errno::Inval);
576 };
577
578 if protocol != 0 {
579 return -i32::from(Errno::Inval);
580 }
581
582 #[cfg(feature = "vsock")]
583 if domain == Af::Vsock && sock == Sock::Stream {
584 let socket = Arc::new(async_lock::RwLock::new(vsock::Socket::new()));
585
586 if sock_flags.contains(SockFlags::SOCK_NONBLOCK) {
587 block_on(socket.set_status_flags(fd::StatusFlags::O_NONBLOCK), None).unwrap();
588 }
589
590 let fd = insert_object(socket).expect("FD is already used");
591
592 return fd;
593 }
594
595 #[cfg(any(feature = "tcp", feature = "udp"))]
596 if (domain == Af::Inet || domain == Af::Inet6) && (sock == Sock::Stream || sock == Sock::Dgram)
597 {
598 let mut guard = NIC.lock();
599
600 if let NetworkState::Initialized(nic) = &mut *guard {
601 #[cfg(feature = "udp")]
602 if sock == Sock::Dgram {
603 let handle = nic.create_udp_handle().unwrap();
604 drop(guard);
605 let socket = Arc::new(async_lock::RwLock::new(udp::Socket::new(handle, domain)));
606
607 if sock_flags.contains(SockFlags::SOCK_NONBLOCK) {
608 block_on(socket.set_status_flags(fd::StatusFlags::O_NONBLOCK), None).unwrap();
609 }
610
611 let fd = insert_object(socket).expect("FD is already used");
612
613 return fd;
614 }
615
616 #[cfg(feature = "tcp")]
617 if sock == Sock::Stream {
618 let handle = nic.create_tcp_handle().unwrap();
619 drop(guard);
620 let socket = Arc::new(async_lock::RwLock::new(tcp::Socket::new(handle, domain)));
621
622 if sock_flags.contains(SockFlags::SOCK_NONBLOCK) {
623 block_on(socket.set_status_flags(fd::StatusFlags::O_NONBLOCK), None).unwrap();
624 }
625
626 let fd = insert_object(socket).expect("FD is already used");
627
628 return fd;
629 }
630 }
631 }
632
633 -i32::from(Errno::Inval)
634}
635
636#[hermit_macro::system(errno)]
637#[unsafe(no_mangle)]
638pub unsafe extern "C" fn sys_accept(fd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32 {
639 let obj = get_object(fd);
640 obj.map_or_else(
641 |e| -i32::from(e),
642 |v| {
643 block_on((*v).accept(), None).map_or_else(
644 |e| -i32::from(e),
645 #[cfg_attr(not(any(feature = "tcp", feature = "udp")), expect(unused_variables))]
646 |(obj, endpoint)| match endpoint {
647 #[cfg(any(feature = "tcp", feature = "udp"))]
648 Endpoint::Ip(endpoint) => {
649 let new_fd = insert_object(obj).unwrap();
650
651 if !addr.is_null() && !addrlen.is_null() {
652 let addrlen = unsafe { &mut *addrlen };
653
654 match endpoint.addr {
655 IpAddress::Ipv4(_) => {
656 if *addrlen >= u32::try_from(size_of::<sockaddr_in>()).unwrap()
657 {
658 let addr = unsafe { &mut *addr.cast() };
659 *addr = sockaddr_in::from(endpoint);
660 *addrlen = size_of::<sockaddr_in>().try_into().unwrap();
661 }
662 }
663 IpAddress::Ipv6(_) => {
664 if *addrlen >= u32::try_from(size_of::<sockaddr_in6>()).unwrap()
665 {
666 let addr = unsafe { &mut *addr.cast() };
667 *addr = sockaddr_in6::from(endpoint);
668 *addrlen = size_of::<sockaddr_in6>().try_into().unwrap();
669 }
670 }
671 }
672 }
673
674 new_fd
675 }
676 #[cfg(feature = "vsock")]
677 Endpoint::Vsock(endpoint) => {
678 let new_fd = insert_object(v.clone()).unwrap();
679
680 if !addr.is_null() && !addrlen.is_null() {
681 let addrlen = unsafe { &mut *addrlen };
682
683 if *addrlen >= u32::try_from(size_of::<sockaddr_vm>()).unwrap() {
684 let addr = unsafe { &mut *addr.cast() };
685 *addr = sockaddr_vm::from(endpoint);
686 *addrlen = size_of::<sockaddr_vm>().try_into().unwrap();
687 }
688 }
689
690 new_fd
691 }
692 },
693 )
694 },
695 )
696}
697
698#[hermit_macro::system(errno)]
699#[unsafe(no_mangle)]
700pub extern "C" fn sys_listen(fd: i32, backlog: i32) -> i32 {
701 let obj = get_object(fd);
702 obj.map_or_else(
703 |e| -i32::from(e),
704 |v| block_on((*v).listen(backlog), None).map_or_else(|e| -i32::from(e), |()| 0),
705 )
706}
707
708#[hermit_macro::system(errno)]
709#[unsafe(no_mangle)]
710pub unsafe extern "C" fn sys_bind(fd: i32, name: *const sockaddr, namelen: socklen_t) -> i32 {
711 if name.is_null() {
712 return -i32::from(Errno::Destaddrreq);
713 }
714
715 let Ok(family) = (unsafe { Af::try_from((*name).sa_family) }) else {
716 return -i32::from(Errno::Inval);
717 };
718
719 let obj = get_object(fd);
720 obj.map_or_else(
721 |e| -i32::from(e),
722 |v| match family {
723 #[cfg(any(feature = "tcp", feature = "udp"))]
724 Af::Inet => {
725 if namelen < u32::try_from(size_of::<sockaddr_in>()).unwrap() {
726 return -i32::from(Errno::Inval);
727 }
728 let endpoint = IpListenEndpoint::from(unsafe { *name.cast::<sockaddr_in>() });
729 block_on((*v).bind(ListenEndpoint::Ip(endpoint)), None)
730 .map_or_else(|e| -i32::from(e), |()| 0)
731 }
732 #[cfg(any(feature = "tcp", feature = "udp"))]
733 Af::Inet6 => {
734 if namelen < u32::try_from(size_of::<sockaddr_in6>()).unwrap() {
735 return -i32::from(Errno::Inval);
736 }
737 let endpoint = IpListenEndpoint::from(unsafe { *name.cast::<sockaddr_in6>() });
738 block_on((*v).bind(ListenEndpoint::Ip(endpoint)), None)
739 .map_or_else(|e| -i32::from(e), |()| 0)
740 }
741 #[cfg(feature = "vsock")]
742 Af::Vsock => {
743 if namelen < u32::try_from(size_of::<sockaddr_vm>()).unwrap() {
744 return -i32::from(Errno::Inval);
745 }
746 let endpoint = VsockListenEndpoint::from(unsafe { *name.cast::<sockaddr_vm>() });
747 block_on((*v).bind(ListenEndpoint::Vsock(endpoint)), None)
748 .map_or_else(|e| -i32::from(e), |()| 0)
749 }
750 _ => -i32::from(Errno::Inval),
751 },
752 )
753}
754
755#[hermit_macro::system(errno)]
756#[unsafe(no_mangle)]
757pub unsafe extern "C" fn sys_connect(fd: i32, name: *const sockaddr, namelen: socklen_t) -> i32 {
758 if name.is_null() {
759 return -i32::from(Errno::Inval);
760 }
761
762 let Ok(sa_family) = (unsafe { Af::try_from((*name).sa_family) }) else {
763 return -i32::from(Errno::Inval);
764 };
765
766 let endpoint = match sa_family {
767 #[cfg(any(feature = "tcp", feature = "udp"))]
768 Af::Inet => {
769 if namelen < u32::try_from(size_of::<sockaddr_in>()).unwrap() {
770 return -i32::from(Errno::Inval);
771 }
772 Endpoint::Ip(IpEndpoint::from(unsafe { *name.cast::<sockaddr_in>() }))
773 }
774 #[cfg(any(feature = "tcp", feature = "udp"))]
775 Af::Inet6 => {
776 if namelen < u32::try_from(size_of::<sockaddr_in6>()).unwrap() {
777 return -i32::from(Errno::Inval);
778 }
779 Endpoint::Ip(IpEndpoint::from(unsafe { *name.cast::<sockaddr_in6>() }))
780 }
781 #[cfg(feature = "vsock")]
782 Af::Vsock => {
783 if namelen < u32::try_from(size_of::<sockaddr_vm>()).unwrap() {
784 return -i32::from(Errno::Inval);
785 }
786 Endpoint::Vsock(VsockEndpoint::from(unsafe { *name.cast::<sockaddr_vm>() }))
787 }
788 _ => {
789 return -i32::from(Errno::Inval);
790 }
791 };
792
793 let obj = get_object(fd);
794 obj.map_or_else(
795 |e| -i32::from(e),
796 |v| block_on((*v).connect(endpoint), None).map_or_else(|e| -i32::from(e), |()| 0),
797 )
798}
799
800#[hermit_macro::system(errno)]
801#[unsafe(no_mangle)]
802pub unsafe extern "C" fn sys_getsockname(
803 fd: i32,
804 addr: *mut sockaddr,
805 addrlen: *mut socklen_t,
806) -> i32 {
807 let obj = get_object(fd);
808 obj.map_or_else(
809 |e| -i32::from(e),
810 |v| {
811 if let Ok(Some(endpoint)) = block_on((*v).getsockname(), None) {
812 if !addr.is_null() && !addrlen.is_null() {
813 let addrlen = unsafe { &mut *addrlen };
814
815 match endpoint {
816 #[cfg(any(feature = "tcp", feature = "udp"))]
817 Endpoint::Ip(endpoint) => match endpoint.addr {
818 IpAddress::Ipv4(_) => {
819 if *addrlen >= u32::try_from(size_of::<sockaddr_in>()).unwrap() {
820 let addr = unsafe { &mut *addr.cast() };
821 *addr = sockaddr_in::from(endpoint);
822 *addrlen = size_of::<sockaddr_in>().try_into().unwrap();
823
824 0
825 } else {
826 -i32::from(Errno::Inval)
827 }
828 }
829 #[cfg(any(feature = "tcp", feature = "udp"))]
830 IpAddress::Ipv6(_) => {
831 if *addrlen >= u32::try_from(size_of::<sockaddr_in6>()).unwrap() {
832 let addr = unsafe { &mut *addr.cast() };
833 *addr = sockaddr_in6::from(endpoint);
834 *addrlen = size_of::<sockaddr_in6>().try_into().unwrap();
835
836 0
837 } else {
838 -i32::from(Errno::Inval)
839 }
840 }
841 },
842 #[cfg(feature = "vsock")]
843 Endpoint::Vsock(_) => {
844 if *addrlen >= u32::try_from(size_of::<sockaddr_vm>()).unwrap() {
845 warn!("unsupported device");
846 0
847 } else {
848 -i32::from(Errno::Inval)
849 }
850 }
851 }
852 } else {
853 -i32::from(Errno::Inval)
854 }
855 } else {
856 -i32::from(Errno::Inval)
857 }
858 },
859 )
860}
861
862#[hermit_macro::system(errno)]
863#[unsafe(no_mangle)]
864pub unsafe extern "C" fn sys_setsockopt(
865 fd: i32,
866 level: i32,
867 optname: i32,
868 optval: *const c_void,
869 optlen: socklen_t,
870) -> i32 {
871 if level == SOL_SOCKET && optname == SO_REUSEADDR {
872 return 0;
873 }
874
875 let Ok(Ok(level)) = u8::try_from(level).map(Ipproto::try_from) else {
876 return -i32::from(Errno::Inval);
877 };
878
879 debug!("sys_setsockopt: {fd}, level {level:?}, optname {optname}");
880
881 if level == Ipproto::Tcp
882 && optname == TCP_NODELAY
883 && optlen == u32::try_from(size_of::<i32>()).unwrap()
884 {
885 if optval.is_null() {
886 return -i32::from(Errno::Inval);
887 }
888
889 let value = unsafe { *optval.cast::<i32>() };
890 let obj = get_object(fd);
891 obj.map_or_else(
892 |e| -i32::from(e),
893 |v| {
894 block_on((*v).setsockopt(SocketOption::TcpNoDelay, value != 0), None)
895 .map_or_else(|e| -i32::from(e), |()| 0)
896 },
897 )
898 } else {
899 -i32::from(Errno::Inval)
900 }
901}
902
903#[hermit_macro::system(errno)]
904#[unsafe(no_mangle)]
905pub unsafe extern "C" fn sys_getsockopt(
906 fd: i32,
907 level: i32,
908 optname: i32,
909 optval: *mut c_void,
910 optlen: *mut socklen_t,
911) -> i32 {
912 let Ok(Ok(level)) = u8::try_from(level).map(Ipproto::try_from) else {
913 return -i32::from(Errno::Inval);
914 };
915
916 debug!("sys_getsockopt: {fd}, level {level:?}, optname {optname}");
917
918 if level == Ipproto::Tcp && optname == TCP_NODELAY {
919 if optval.is_null() || optlen.is_null() {
920 return -i32::from(Errno::Inval);
921 }
922
923 let optval = unsafe { &mut *optval.cast::<i32>() };
924 let optlen = unsafe { &mut *optlen };
925 let obj = get_object(fd);
926 obj.map_or_else(
927 |e| -i32::from(e),
928 |v| {
929 block_on((*v).getsockopt(SocketOption::TcpNoDelay), None).map_or_else(
930 |e| -i32::from(e),
931 |value| {
932 if value {
933 *optval = 1;
934 } else {
935 *optval = 0;
936 }
937 *optlen = core::mem::size_of::<i32>().try_into().unwrap();
938
939 0
940 },
941 )
942 },
943 )
944 } else {
945 -i32::from(Errno::Inval)
946 }
947}
948
949#[hermit_macro::system(errno)]
950#[unsafe(no_mangle)]
951pub unsafe extern "C" fn sys_getpeername(
952 fd: i32,
953 addr: *mut sockaddr,
954 addrlen: *mut socklen_t,
955) -> i32 {
956 let obj = get_object(fd);
957 obj.map_or_else(
958 |e| -i32::from(e),
959 |v| {
960 if let Ok(Some(endpoint)) = block_on((*v).getpeername(), None) {
961 if !addr.is_null() && !addrlen.is_null() {
962 let addrlen = unsafe { &mut *addrlen };
963
964 match endpoint {
965 #[cfg(any(feature = "tcp", feature = "udp"))]
966 Endpoint::Ip(endpoint) => match endpoint.addr {
967 IpAddress::Ipv4(_) => {
968 if *addrlen >= u32::try_from(size_of::<sockaddr_in>()).unwrap() {
969 let addr = unsafe { &mut *addr.cast() };
970 *addr = sockaddr_in::from(endpoint);
971 *addrlen = size_of::<sockaddr_in>().try_into().unwrap();
972 } else {
973 return -i32::from(Errno::Inval);
974 }
975 }
976 IpAddress::Ipv6(_) => {
977 if *addrlen >= u32::try_from(size_of::<sockaddr_in6>()).unwrap() {
978 let addr = unsafe { &mut *addr.cast() };
979 *addr = sockaddr_in6::from(endpoint);
980 *addrlen = size_of::<sockaddr_in6>().try_into().unwrap();
981 } else {
982 return -i32::from(Errno::Inval);
983 }
984 }
985 },
986 #[cfg(feature = "vsock")]
987 Endpoint::Vsock(_) => {
988 if *addrlen >= u32::try_from(size_of::<sockaddr_vm>()).unwrap() {
989 warn!("unsupported device");
990 } else {
991 return -i32::from(Errno::Inval);
992 }
993 }
994 }
995 } else {
996 return -i32::from(Errno::Inval);
997 }
998 }
999
1000 0
1001 },
1002 )
1003}
1004
1005#[hermit_macro::system(errno)]
1006#[unsafe(no_mangle)]
1007pub unsafe extern "C" fn sys_send(s: i32, mem: *const c_void, len: usize, _flags: i32) -> isize {
1008 unsafe { super::write(s, mem.cast(), len) }
1009}
1010
1011fn shutdown(sockfd: i32, how: i32) -> i32 {
1012 let obj = get_object(sockfd);
1013 obj.map_or_else(
1014 |e| -i32::from(e),
1015 |v| block_on((*v).shutdown(how), None).map_or_else(|e| -i32::from(e), |()| 0),
1016 )
1017}
1018
1019#[hermit_macro::system(errno)]
1020#[unsafe(no_mangle)]
1021pub extern "C" fn sys_shutdown(sockfd: i32, how: i32) -> i32 {
1022 shutdown(sockfd, how)
1023}
1024
1025#[hermit_macro::system(errno)]
1026#[unsafe(no_mangle)]
1027pub extern "C" fn sys_shutdown_socket(fd: i32, how: i32) -> i32 {
1028 shutdown(fd, how)
1029}
1030
1031#[hermit_macro::system(errno)]
1032#[unsafe(no_mangle)]
1033pub unsafe extern "C" fn sys_recv(fd: i32, buf: *mut u8, len: usize, flags: i32) -> isize {
1034 if flags == 0 {
1035 let slice = unsafe { core::slice::from_raw_parts_mut(buf.cast(), len) };
1036 crate::fd::read(fd, slice).map_or_else(
1037 |e| isize::try_from(-i32::from(e)).unwrap(),
1038 |v| v.try_into().unwrap(),
1039 )
1040 } else {
1041 (-i32::from(Errno::Inval)).try_into().unwrap()
1042 }
1043}
1044
1045#[hermit_macro::system(errno)]
1046#[unsafe(no_mangle)]
1047pub unsafe extern "C" fn sys_sendto(
1048 fd: i32,
1049 buf: *const u8,
1050 len: usize,
1051 _flags: i32,
1052 addr: *const sockaddr,
1053 addr_len: socklen_t,
1054) -> isize {
1055 let endpoint;
1056
1057 if addr.is_null() || addr_len == 0 {
1058 return (-i32::from(Errno::Inval)).try_into().unwrap();
1059 }
1060
1061 cfg_if! {
1062 if #[cfg(any(feature = "tcp", feature = "udp"))] {
1063 let Ok(sa_family) = (unsafe { Af::try_from((*addr).sa_family) }) else {
1064 return (-i32::from(Errno::Inval)).try_into().unwrap();
1065 };
1066
1067 if sa_family == Af::Inet {
1068 if addr_len < u32::try_from(size_of::<sockaddr_in>()).unwrap() {
1069 return (-i32::from(Errno::Inval)).try_into().unwrap();
1070 }
1071
1072 endpoint = Some(Endpoint::Ip(IpEndpoint::from(unsafe {*(addr.cast::<sockaddr_in>())})));
1073 } else if sa_family == Af::Inet6 {
1074 if addr_len < u32::try_from(size_of::<sockaddr_in6>()).unwrap() {
1075 return (-i32::from(Errno::Inval)).try_into().unwrap();
1076 }
1077
1078 endpoint = Some(Endpoint::Ip(IpEndpoint::from(unsafe { *(addr.cast::<sockaddr_in6>()) })));
1079 } else {
1080 endpoint = None;
1081 }
1082 } else {
1083 endpoint = None;
1084 }
1085 }
1086
1087 if let Some(endpoint) = endpoint {
1088 let slice = unsafe { core::slice::from_raw_parts(buf, len) };
1089 let obj = get_object(fd);
1090
1091 obj.map_or_else(
1092 |e| isize::try_from(-i32::from(e)).unwrap(),
1093 |v| {
1094 block_on((*v).sendto(slice, endpoint), None).map_or_else(
1095 |e| isize::try_from(-i32::from(e)).unwrap(),
1096 |v| v.try_into().unwrap(),
1097 )
1098 },
1099 )
1100 } else {
1101 (-i32::from(Errno::Inval)).try_into().unwrap()
1102 }
1103}
1104
1105#[hermit_macro::system(errno)]
1106#[unsafe(no_mangle)]
1107pub unsafe extern "C" fn sys_recvfrom(
1108 fd: i32,
1109 buf: *mut u8,
1110 len: usize,
1111 _flags: i32,
1112 addr: *mut sockaddr,
1113 addrlen: *mut socklen_t,
1114) -> isize {
1115 let slice = unsafe { core::slice::from_raw_parts_mut(buf.cast(), len) };
1116 let obj = get_object(fd);
1117 obj.map_or_else(
1118 |e| isize::try_from(-i32::from(e)).unwrap(),
1119 |v| {
1120 block_on((*v).recvfrom(slice), None).map_or_else(
1121 |e| isize::try_from(-i32::from(e)).unwrap(),
1122 |(len, endpoint)| {
1123 if !addr.is_null() && !addrlen.is_null() {
1124 #[allow(unused_variables)]
1125 let addrlen = unsafe { &mut *addrlen };
1126
1127 match endpoint {
1128 #[cfg(any(feature = "tcp", feature = "udp"))]
1129 Endpoint::Ip(endpoint) => match endpoint.addr {
1130 IpAddress::Ipv4(_) => {
1131 if *addrlen >= u32::try_from(size_of::<sockaddr_in>()).unwrap()
1132 {
1133 let addr = unsafe { &mut *addr.cast() };
1134 *addr = sockaddr_in::from(endpoint);
1135 *addrlen = size_of::<sockaddr_in>().try_into().unwrap();
1136 } else {
1137 return (-i32::from(Errno::Inval)).try_into().unwrap();
1138 }
1139 }
1140 IpAddress::Ipv6(_) => {
1141 if *addrlen >= u32::try_from(size_of::<sockaddr_in6>()).unwrap()
1142 {
1143 let addr = unsafe { &mut *addr.cast() };
1144 *addr = sockaddr_in6::from(endpoint);
1145 *addrlen = size_of::<sockaddr_in6>().try_into().unwrap();
1146 } else {
1147 return (-i32::from(Errno::Inval)).try_into().unwrap();
1148 }
1149 }
1150 },
1151 #[cfg(feature = "vsock")]
1152 _ => {
1153 return (-i32::from(Errno::Inval)).try_into().unwrap();
1154 }
1155 }
1156 }
1157
1158 len.try_into().unwrap()
1159 },
1160 )
1161 },
1162 )
1163}