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