1use core::ffi::{CStr, c_char};
4
5macro_rules! set_sockopt_bool {
6 ($optval:expr, $optlen:expr, $field:expr) => {
7 if $optlen >= 4 {
8 let val = *($optval as *const i32);
9 $field = val != 0;
10 }
11 };
12}
13
14macro_rules! set_sockopt_int {
15 ($optval:expr, $optlen:expr, $field:expr) => {
16 if $optlen >= 4 {
17 let val = *($optval as *const i32);
18 if val < 0 {
19 return -(EINVAL as isize);
20 }
21 $field = val as usize;
22 }
23 };
24}
25
26macro_rules! get_sockopt_bool {
27 ($optval:expr, $avail:expr, $field:expr, $written:expr) => {
28 if $avail >= 4 {
29 *($optval as *mut i32) = if $field { 1 } else { 0 };
30 $written = 4;
31 }
32 };
33}
34
35macro_rules! get_sockopt_int {
36 ($optval:expr, $avail:expr, $field:expr, $written:expr) => {
37 if $avail >= 4 {
38 *($optval as *mut i32) = $field as i32;
39 $written = 4;
40 }
41 };
42}
43
44use crate::{
45 arch::trap::SumGuard,
46 kernel::current_cpu,
47 net::{
48 config::NetworkConfigManager,
49 interface::NETWORK_INTERFACE_MANAGER,
50 socket::{
51 SOCKET_SET, SocketFile, SocketHandle, create_tcp_socket, create_udp_socket,
52 get_socket_handle, parse_sockaddr_in, register_socket_fd, unregister_socket_fd,
53 write_sockaddr_in,
54 },
55 },
56 println,
57};
58use alloc::sync::Arc;
59use smoltcp::socket::{tcp, udp};
60use smoltcp::wire::{IpAddress, IpEndpoint, Ipv4Address};
61
62pub fn get_network_interfaces() -> isize {
64 0
65}
66
67pub fn set_network_interface_config(
69 ifname: *const c_char,
70 ip: *const c_char,
71 gateway: *const c_char,
72 mask: *const c_char,
73) -> isize {
74 unsafe {
76 let _guard = SumGuard::new();
77
78 let ifname_str = match get_c_str_safe(ifname) {
79 Some(s) => s,
80 None => {
81 return -1;
82 }
83 };
84
85 let ip_str = match get_c_str_safe(ip) {
86 Some(s) => s,
87 None => {
88 return -2;
89 }
90 };
91
92 let gateway_str = match get_c_str_safe(gateway) {
93 Some(s) => s,
94 None => {
95 return -3;
96 }
97 };
98
99 let mask_str = match get_c_str_safe(mask) {
100 Some(s) => s,
101 None => {
102 return -4;
103 }
104 };
105
106 match NetworkConfigManager::set_interface_config(ifname_str, ip_str, gateway_str, mask_str)
108 {
109 Ok(_) => 0,
110 Err(e) => {
111 println!("Network config error: {:?}", e);
112 -5
113 }
114 }
115 }
116}
117
118pub fn socket(domain: i32, socket_type: i32, _protocol: i32) -> isize {
120 if domain != 2 {
121 return -97;
122 } let handle = match socket_type {
125 1 => match create_tcp_socket() {
126 Ok(h) => h,
127 Err(_) => return -12, },
129 2 => match create_udp_socket() {
130 Ok(h) => h,
131 Err(_) => return -12, },
133 _ => return -94, };
135
136 let socket_file = Arc::new(SocketFile::new(handle));
137 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
138
139 let mut task_lock = task.lock();
140 match task_lock.fd_table.alloc(socket_file) {
141 Ok(fd) => {
142 register_socket_fd(task_lock.tid as usize, fd, handle);
143 fd as isize
144 }
145 Err(_) => -24, }
147}
148
149pub fn bind(sockfd: i32, addr: *const u8, addrlen: u32) -> isize {
151 let endpoint = unsafe {
152 let _guard = SumGuard::new();
153 let ep = parse_sockaddr_in(addr, addrlen);
154 match ep {
155 Ok(e) => e,
156 Err(_) => return -22, }
158 };
159
160 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
161 let task_lock = task.lock();
162 let tid = task_lock.tid as usize;
163
164 let handle = match get_socket_handle(tid, sockfd as usize) {
165 Some(h) => h,
166 None => return -88, };
168
169 let file = match task_lock.fd_table.get(sockfd as usize) {
170 Ok(f) => f,
171 Err(_) => return -9, };
173 drop(task_lock);
174
175 match handle {
178 SocketHandle::Tcp(_) => {
179 use crate::net::socket::set_socket_local_endpoint;
180 if set_socket_local_endpoint(&file, endpoint).is_err() {
181 return -22; }
183 }
184 SocketHandle::Udp(h) => {
185 let mut sockets = SOCKET_SET.lock();
186 let socket = sockets.get_mut::<udp::Socket>(h);
187 if socket.bind(endpoint).is_err() {
188 return -98; }
190 }
191 }
192
193 0
194}
195
196pub fn listen(sockfd: i32, backlog: i32) -> isize {
198 if backlog < 0 {
199 return -22; }
201
202 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
203 let task_lock = task.lock();
204 let tid = task_lock.tid as usize;
205
206 let handle = match get_socket_handle(tid, sockfd as usize) {
207 Some(h) => h,
208 None => return -88, };
210
211 let file = match task_lock.fd_table.get(sockfd as usize) {
212 Ok(f) => f,
213 Err(_) => return -9, };
215 drop(task_lock);
216
217 match handle {
218 SocketHandle::Tcp(h) => {
219 use crate::net::socket::get_socket_local_endpoint;
220 let endpoint = match get_socket_local_endpoint(&file) {
221 Some(ep) => ep,
222 None => return -22, };
224
225 let mut sockets = SOCKET_SET.lock();
226 let socket = sockets.get_mut::<tcp::Socket>(h);
227 if socket.listen(endpoint).is_err() {
228 return -98; }
230 0
231 }
232 SocketHandle::Udp(_) => -95, }
234}
235
236pub fn accept(sockfd: i32, addr: *mut u8, addrlen: *mut u32) -> isize {
238 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
239 let tid = task.lock().tid;
240
241 let listen_handle = match get_socket_handle(tid as usize, sockfd as usize) {
242 Some(SocketHandle::Tcp(h)) => h,
243 Some(SocketHandle::Udp(_)) => return -95, None => return -88, };
246
247 let mut sockets = SOCKET_SET.lock();
248 let listen_socket = sockets.get_mut::<tcp::Socket>(listen_handle);
249
250 if !listen_socket.is_listening() {
251 return -22; }
253
254 if !listen_socket.is_active() {
255 return -11; }
257
258 let remote_endpoint = match listen_socket.remote_endpoint() {
260 Some(ep) => ep,
261 None => return -11, };
263 let local_endpoint = listen_socket.local_endpoint().unwrap();
264
265 let new_listen_handle = match create_tcp_socket() {
267 Ok(SocketHandle::Tcp(h)) => h,
268 _ => return -12, };
270
271 let new_listen_socket = sockets.get_mut::<tcp::Socket>(new_listen_handle);
273 if new_listen_socket.listen(local_endpoint).is_err() {
274 sockets.remove(new_listen_handle);
275 return -12; }
277
278 use crate::net::socket::{update_socket_file_handle, update_socket_handle};
281 update_socket_handle(
282 tid as usize,
283 sockfd as usize,
284 SocketHandle::Tcp(new_listen_handle),
285 );
286
287 let file = match task.lock().fd_table.get(sockfd as usize) {
289 Ok(f) => f,
290 Err(_) => return -9, };
292 update_socket_file_handle(&file, SocketHandle::Tcp(new_listen_handle)).unwrap();
293
294 drop(sockets);
295
296 if !addr.is_null() && !addrlen.is_null() {
298 let _guard = SumGuard::new();
299 unsafe {
300 let _ = write_sockaddr_in(addr, addrlen, remote_endpoint);
301 }
302 }
303
304 let conn_handle = SocketHandle::Tcp(listen_handle);
306 let socket_file = Arc::new(SocketFile::new(conn_handle));
307 match task.lock().fd_table.alloc(socket_file) {
308 Ok(fd) => {
309 register_socket_fd(tid as usize, fd, conn_handle);
310 fd as isize
311 }
312 Err(_) => -24, }
314}
315
316pub fn connect(sockfd: i32, addr: *const u8, addrlen: u32) -> isize {
318 let endpoint = unsafe {
319 let _guard = SumGuard::new();
320 let ep = parse_sockaddr_in(addr, addrlen);
321 match ep {
322 Ok(e) => e,
323 Err(_) => return -22, }
325 };
326
327 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
328 let task_lock = task.lock();
329 let tid = task_lock.tid as usize;
330
331 let handle = match get_socket_handle(tid, sockfd as usize) {
332 Some(h) => h,
333 None => return -88, };
335
336 let file = match task_lock.fd_table.get(sockfd as usize) {
337 Ok(f) => f,
338 Err(_) => return -9, };
340 drop(task_lock);
341
342 use crate::net::socket::set_socket_remote_endpoint;
343 set_socket_remote_endpoint(&file, endpoint).unwrap();
344
345 let is_nonblock = file
346 .flags()
347 .contains(crate::uapi::fcntl::OpenFlags::O_NONBLOCK);
348
349 match handle {
350 SocketHandle::Tcp(h) => {
351 let sockets = SOCKET_SET.lock();
352 let socket = sockets.get::<tcp::Socket>(h);
353 if socket.is_open() {
354 return -106; }
356 let local_endpoint = socket.local_endpoint().unwrap_or(IpEndpoint::new(
357 IpAddress::Ipv4(Ipv4Address::UNSPECIFIED),
358 0,
359 ));
360 drop(sockets);
361
362 use crate::net::socket::tcp_connect;
363 if let Err(_) = tcp_connect(h, endpoint, local_endpoint) {
364 return -22; }
366
367 if is_nonblock {
368 return -115; }
370 }
371 SocketHandle::Udp(_) => {}
372 }
373
374 0
375}
376
377pub fn send(sockfd: i32, buf: *const u8, len: usize, _flags: i32) -> isize {
379 let data = unsafe {
380 let _guard = SumGuard::new();
381 let slice = core::slice::from_raw_parts(buf, len);
382 slice
383 };
384
385 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
386 let file = match task.lock().fd_table.get(sockfd as usize) {
387 Ok(f) => f,
388 Err(_) => return -9,
389 };
390
391 match file.write(data) {
392 Ok(n) => n as isize,
393 Err(_) => -11, }
395}
396
397pub fn recv(sockfd: i32, buf: *mut u8, len: usize, _flags: i32) -> isize {
399 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
400 let file = match task.lock().fd_table.get(sockfd as usize) {
401 Ok(f) => f,
402 Err(_) => return -9,
403 };
404
405 let data = unsafe {
406 let _guard = SumGuard::new();
407 let slice = core::slice::from_raw_parts_mut(buf, len);
408 slice
409 };
410
411 match file.read(data) {
412 Ok(n) => n as isize,
413 Err(_) => -11, }
415}
416
417pub fn close_sock(sockfd: i32) -> isize {
419 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
420 let mut task_lock = task.lock();
421 let tid = task_lock.tid;
422
423 unregister_socket_fd(tid as usize, sockfd as usize);
424
425 match task_lock.fd_table.close(sockfd as usize) {
426 Ok(_) => 0,
427 Err(_) => -9,
428 }
429}
430
431unsafe fn get_c_str_safe(ptr: *const c_char) -> Option<&'static str> {
433 if ptr.is_null() {
434 return None;
435 }
436
437 match CStr::from_ptr(ptr).to_str() {
438 Ok(s) => Some(s),
439 Err(_) => None,
440 }
441}
442
443fn get_interface_stats(ifname: *const c_char, stats: *mut u8, size: usize) -> isize {
445 0 }
448
449pub fn init_network_syscalls() {
450 println!("Network syscalls initialized");
451}
452
453pub fn getifaddrs(ifap: *mut *mut u8) -> isize {
455 unsafe {
456 let _guard = SumGuard::new();
457
458 let interfaces = NETWORK_INTERFACE_MANAGER.lock().get_interfaces().to_vec();
460
461 if interfaces.is_empty() {
462 return -1; }
464
465 0 }
469}
470
471pub fn freeifaddrs(ifa: *mut u8) -> isize {
473 unsafe {
474 let _guard = SumGuard::new();
475
476 0
480 }
481}
482
483pub fn setsockopt(sockfd: i32, level: i32, optname: i32, optval: *const u8, optlen: u32) -> isize {
485 use crate::arch::trap::SumGuard;
486 use crate::kernel::current_cpu;
487 use crate::uapi::errno::{EBADF, EINVAL, ENOPROTOOPT, ENOTSOCK};
488 use crate::uapi::socket::*;
489
490 if sockfd < 0 || optval.is_null() {
491 return -(EINVAL as isize);
492 }
493
494 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
495 let file = match task.lock().fd_table.get(sockfd as usize) {
496 Ok(f) => f,
497 Err(_) => return -(EBADF as isize),
498 };
499
500 let socket_file = match file
501 .as_any()
502 .downcast_ref::<crate::net::socket::SocketFile>()
503 {
504 Some(sf) => sf,
505 None => return -(ENOTSOCK as isize),
506 };
507
508 let mut opts = socket_file.get_socket_options();
509
510 {
511 let _guard = SumGuard::new();
512 unsafe {
513 match level {
514 SOL_SOCKET => match optname {
515 SO_REUSEADDR => set_sockopt_bool!(optval, optlen, opts.reuse_addr),
516 SO_REUSEPORT => set_sockopt_bool!(optval, optlen, opts.reuse_port),
517 SO_KEEPALIVE => set_sockopt_bool!(optval, optlen, opts.keepalive),
518 SO_SNDBUF => set_sockopt_int!(optval, optlen, opts.send_buffer_size),
519 SO_RCVBUF => set_sockopt_int!(optval, optlen, opts.recv_buffer_size),
520 _ => return -(ENOPROTOOPT as isize),
521 },
522 IPPROTO_TCP => match optname {
523 TCP_NODELAY => set_sockopt_bool!(optval, optlen, opts.tcp_nodelay),
524 _ => return -(ENOPROTOOPT as isize),
525 },
526 _ => return -(ENOPROTOOPT as isize),
527 }
528 }
529 }
530
531 socket_file.set_socket_options(opts);
532 0
533}
534
535pub fn getsockopt(
537 sockfd: i32,
538 level: i32,
539 optname: i32,
540 optval: *mut u8,
541 optlen: *mut u32,
542) -> isize {
543 use crate::arch::trap::SumGuard;
544 use crate::kernel::current_cpu;
545 use crate::uapi::errno::{EBADF, EINVAL, ENOPROTOOPT, ENOTSOCK};
546 use crate::uapi::socket::*;
547
548 if sockfd < 0 || optval.is_null() || optlen.is_null() {
549 return -(EINVAL as isize);
550 }
551
552 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
553 let file = match task.lock().fd_table.get(sockfd as usize) {
554 Ok(f) => f,
555 Err(_) => return -(EBADF as isize),
556 };
557
558 let socket_file = match file
559 .as_any()
560 .downcast_ref::<crate::net::socket::SocketFile>()
561 {
562 Some(sf) => sf,
563 None => return -(ENOTSOCK as isize),
564 };
565
566 let opts = socket_file.get_socket_options();
567
568 {
569 let _guard = SumGuard::new();
570 unsafe {
571 let available_len = *optlen as usize;
572 let mut written_len = 0usize;
573
574 match level {
575 SOL_SOCKET => match optname {
576 SO_REUSEADDR => {
577 get_sockopt_bool!(optval, available_len, opts.reuse_addr, written_len)
578 }
579 SO_REUSEPORT => {
580 get_sockopt_bool!(optval, available_len, opts.reuse_port, written_len)
581 }
582 SO_KEEPALIVE => {
583 get_sockopt_bool!(optval, available_len, opts.keepalive, written_len)
584 }
585 SO_SNDBUF => {
586 get_sockopt_int!(optval, available_len, opts.send_buffer_size, written_len)
587 }
588 SO_RCVBUF => {
589 get_sockopt_int!(optval, available_len, opts.recv_buffer_size, written_len)
590 }
591 _ => return -(ENOPROTOOPT as isize),
592 },
593 IPPROTO_TCP => match optname {
594 TCP_NODELAY => {
595 get_sockopt_bool!(optval, available_len, opts.tcp_nodelay, written_len)
596 }
597 _ => return -(ENOPROTOOPT as isize),
598 },
599 _ => return -(ENOPROTOOPT as isize),
600 }
601
602 *optlen = written_len as u32;
603 }
604 }
605
606 0
607}
608
609pub fn accept4(sockfd: i32, addr: *mut u8, addrlen: *mut u32, flags: i32) -> isize {
611 unsafe {
612 let _guard = SumGuard::new();
613
614 if sockfd < 0 {
617 return -1; }
619
620 4
622 }
623}
624
625pub fn sendto(
627 sockfd: i32,
628 buf: *const u8,
629 len: usize,
630 _flags: i32,
631 dest_addr: *const u8,
632 addrlen: u32,
633) -> isize {
634 if dest_addr.is_null() {
636 return send(sockfd, buf, len, 0);
637 }
638
639 let endpoint = unsafe {
640 let _guard = SumGuard::new();
641 let ep = parse_sockaddr_in(dest_addr, addrlen);
642 match ep {
643 Ok(e) => e,
644 Err(_) => return -22, }
646 };
647
648 let data = unsafe {
649 let _guard = SumGuard::new();
650 let slice = core::slice::from_raw_parts(buf, len);
651 slice
652 };
653
654 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
655 let tid = task.lock().tid as usize;
656
657 let handle = match get_socket_handle(tid, sockfd as usize) {
658 Some(h) => h,
659 None => return -88, };
661
662 use crate::net::socket::socket_sendto;
663 match socket_sendto(handle, data, endpoint) {
664 Ok(n) => n as isize,
665 Err(e) => e.to_errno(),
666 }
667}
668
669pub fn recvfrom(
671 sockfd: i32,
672 buf: *mut u8,
673 len: usize,
674 _flags: i32,
675 src_addr: *mut u8,
676 addrlen: *mut u32,
677) -> isize {
678 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
679 let file = match task.lock().fd_table.get(sockfd as usize) {
680 Ok(f) => f,
681 Err(_) => return -9, };
683
684 let data = unsafe {
685 let _guard = SumGuard::new();
686 let slice = core::slice::from_raw_parts_mut(buf, len);
687 slice
688 };
689
690 match file.recvfrom(data) {
691 Ok((n, Some(addr_buf))) => {
692 if !src_addr.is_null() && !addrlen.is_null() {
693 unsafe {
694 let _guard = SumGuard::new();
695 let len = (*addrlen as usize).min(addr_buf.len());
696 core::ptr::copy_nonoverlapping(addr_buf.as_ptr(), src_addr, len);
697 *addrlen = len as u32;
698 }
699 }
700 n as isize
701 }
702 Ok((n, None)) => n as isize,
703 Err(_) => -11, }
705}
706
707pub fn shutdown(sockfd: i32, how: i32) -> isize {
709 const SHUT_RD: i32 = 0;
710 const SHUT_WR: i32 = 1;
711 const SHUT_RDWR: i32 = 2;
712
713 if how < 0 || how > 2 {
714 return -22; }
716
717 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
718 let task_lock = task.lock();
719 let tid = task_lock.tid as usize;
720
721 let handle = match get_socket_handle(tid, sockfd as usize) {
722 Some(h) => h,
723 None => return -88, };
725
726 let file = match task_lock.fd_table.get(sockfd as usize) {
727 Ok(f) => f,
728 Err(_) => return -9, };
730 drop(task_lock);
731
732 use crate::net::socket::{socket_shutdown_read, socket_shutdown_write};
733
734 let should_close_tcp = match how {
735 SHUT_RD => {
736 socket_shutdown_read(&file);
737 false
738 }
739 SHUT_WR | SHUT_RDWR => {
740 if how == SHUT_RDWR {
741 socket_shutdown_read(&file);
742 }
743 socket_shutdown_write(&file);
744 true
745 }
746 _ => unreachable!(), };
748
749 if should_close_tcp {
750 if let SocketHandle::Tcp(h) = handle {
751 let mut sockets = SOCKET_SET.lock();
752 let socket = sockets.get_mut::<tcp::Socket>(h);
753 socket.close();
754 }
755 }
756
757 0
758}
759
760pub fn getsockname(sockfd: i32, addr: *mut u8, addrlen: *mut u32) -> isize {
762 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
763 let tid = task.lock().tid as usize;
764
765 let handle = match get_socket_handle(tid, sockfd as usize) {
766 Some(h) => h,
767 None => return -88, };
769
770 let sockets = SOCKET_SET.lock();
771 let local_endpoint = match handle {
772 SocketHandle::Tcp(h) => {
773 let socket = sockets.get::<tcp::Socket>(h);
774 socket.local_endpoint()
775 }
776 SocketHandle::Udp(h) => {
777 let socket = sockets.get::<udp::Socket>(h);
778 let listen_ep = socket.endpoint();
779 listen_ep
780 .addr
781 .map(|addr| IpEndpoint::new(addr, listen_ep.port))
782 }
783 };
784
785 drop(sockets);
786
787 if let Some(ep) = local_endpoint {
788 {
789 let _guard = SumGuard::new();
790 unsafe {
791 let _ = write_sockaddr_in(addr, addrlen, ep);
792 }
793 }
794 0
795 } else {
796 -22 }
798}
799
800pub fn getpeername(sockfd: i32, addr: *mut u8, addrlen: *mut u32) -> isize {
802 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
803 let tid = task.lock().tid as usize;
804
805 let handle = match get_socket_handle(tid, sockfd as usize) {
806 Some(h) => h,
807 None => return -88, };
809
810 let sockets = SOCKET_SET.lock();
811 let remote_endpoint = match handle {
812 SocketHandle::Tcp(h) => {
813 let socket = sockets.get::<tcp::Socket>(h);
814 socket.remote_endpoint()
815 }
816 SocketHandle::Udp(_) => {
817 drop(sockets);
819 let file = match task.lock().fd_table.get(sockfd as usize) {
820 Ok(f) => f,
821 Err(_) => return -9, };
823 use crate::net::socket::get_socket_remote_endpoint;
824 get_socket_remote_endpoint(&file)
825 }
826 };
827
828 if let Some(ep) = remote_endpoint {
829 {
830 let _guard = SumGuard::new();
831 unsafe {
832 let _ = write_sockaddr_in(addr, addrlen, ep);
833 }
834 }
835 0
836 } else {
837 -107 }
839}