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