xref: /DragonOS/kernel/src/net/syscall.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
1cde5492fSlogin use core::cmp::min;
2cde5492fSlogin 
3cde5492fSlogin use alloc::{boxed::Box, sync::Arc};
4cde5492fSlogin use num_traits::{FromPrimitive, ToPrimitive};
5cde5492fSlogin use smoltcp::wire;
6cde5492fSlogin 
7cde5492fSlogin use crate::{
8cde5492fSlogin     filesystem::vfs::{
9cde5492fSlogin         file::{File, FileMode},
10cde5492fSlogin         syscall::{IoVec, IoVecs},
11cde5492fSlogin     },
12ab5c8ca4Slogin     include::bindings::bindings::verify_area,
13ab5c8ca4Slogin     libs::spinlock::SpinLockGuard,
14cde5492fSlogin     net::socket::{AddressFamily, SOL_SOCKET},
15*1496ba7bSLoGin     process::ProcessManager,
16ab5c8ca4Slogin     syscall::{Syscall, SystemError},
17cde5492fSlogin };
18cde5492fSlogin 
19cde5492fSlogin use super::{
20cde5492fSlogin     socket::{PosixSocketType, RawSocket, SocketInode, SocketOptions, TcpSocket, UdpSocket},
21cde5492fSlogin     Endpoint, Protocol, ShutdownType, Socket,
22cde5492fSlogin };
23cde5492fSlogin 
24ab5c8ca4Slogin impl Syscall {
25cde5492fSlogin     /// @brief sys_socket系统调用的实际执行函数
26cde5492fSlogin     ///
27cde5492fSlogin     /// @param address_family 地址族
28cde5492fSlogin     /// @param socket_type socket类型
29cde5492fSlogin     /// @param protocol 传输协议
30ab5c8ca4Slogin     pub fn socket(
31cde5492fSlogin         address_family: usize,
32cde5492fSlogin         socket_type: usize,
33cde5492fSlogin         protocol: usize,
34ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
35cde5492fSlogin         let address_family = AddressFamily::try_from(address_family as u16)?;
36cde5492fSlogin         let socket_type = PosixSocketType::try_from((socket_type & 0xf) as u8)?;
37cde5492fSlogin         // kdebug!("do_socket: address_family: {address_family:?}, socket_type: {socket_type:?}, protocol: {protocol}");
38cde5492fSlogin         // 根据地址族和socket类型创建socket
39cde5492fSlogin         let socket: Box<dyn Socket> = match address_family {
40cde5492fSlogin             AddressFamily::Unix | AddressFamily::INet => match socket_type {
41cde5492fSlogin                 PosixSocketType::Stream => Box::new(TcpSocket::new(SocketOptions::default())),
42cde5492fSlogin                 PosixSocketType::Datagram => Box::new(UdpSocket::new(SocketOptions::default())),
43cde5492fSlogin                 PosixSocketType::Raw => Box::new(RawSocket::new(
44cde5492fSlogin                     Protocol::from(protocol as u8),
45cde5492fSlogin                     SocketOptions::default(),
46cde5492fSlogin                 )),
47cde5492fSlogin                 _ => {
48cde5492fSlogin                     // kdebug!("do_socket: EINVAL");
49cde5492fSlogin                     return Err(SystemError::EINVAL);
50cde5492fSlogin                 }
51cde5492fSlogin             },
52cde5492fSlogin             _ => {
53cde5492fSlogin                 // kdebug!("do_socket: EAFNOSUPPORT");
54cde5492fSlogin                 return Err(SystemError::EAFNOSUPPORT);
55cde5492fSlogin             }
56cde5492fSlogin         };
57cde5492fSlogin         // kdebug!("do_socket: socket: {socket:?}");
58cde5492fSlogin         let socketinode: Arc<SocketInode> = SocketInode::new(socket);
59cde5492fSlogin         let f = File::new(socketinode, FileMode::O_RDWR)?;
60cde5492fSlogin         // kdebug!("do_socket: f: {f:?}");
61cde5492fSlogin         // 把socket添加到当前进程的文件描述符表中
62*1496ba7bSLoGin         let binding = ProcessManager::current_pcb().fd_table();
63*1496ba7bSLoGin         let mut fd_table_guard = binding.write();
64*1496ba7bSLoGin 
65*1496ba7bSLoGin         let fd = fd_table_guard.alloc_fd(f, None).map(|x| x as usize);
66*1496ba7bSLoGin         drop(fd_table_guard);
67cde5492fSlogin         // kdebug!("do_socket: fd: {fd:?}");
68cde5492fSlogin         return fd;
69cde5492fSlogin     }
70cde5492fSlogin 
71cde5492fSlogin     /// @brief sys_setsockopt系统调用的实际执行函数
72cde5492fSlogin     ///
73cde5492fSlogin     /// @param fd 文件描述符
74cde5492fSlogin     /// @param level 选项级别
75cde5492fSlogin     /// @param optname 选项名称
76cde5492fSlogin     /// @param optval 选项值
77cde5492fSlogin     /// @param optlen optval缓冲区长度
78ab5c8ca4Slogin     pub fn setsockopt(
79cde5492fSlogin         fd: usize,
80cde5492fSlogin         level: usize,
81cde5492fSlogin         optname: usize,
82ab5c8ca4Slogin         optval: &[u8],
83ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
84*1496ba7bSLoGin         let socket_inode: Arc<SocketInode> = ProcessManager::current_pcb()
85cde5492fSlogin             .get_socket(fd as i32)
86cde5492fSlogin             .ok_or(SystemError::EBADF)?;
87cde5492fSlogin         // 获取内层的socket(真正的数据)
88ab5c8ca4Slogin         let socket: SpinLockGuard<Box<dyn Socket>> = socket_inode.inner();
89ab5c8ca4Slogin         return socket.setsockopt(level, optname, optval).map(|_| 0);
90cde5492fSlogin     }
91cde5492fSlogin 
92cde5492fSlogin     /// @brief sys_getsockopt系统调用的实际执行函数
93cde5492fSlogin     ///
94cde5492fSlogin     /// 参考:https://man7.org/linux/man-pages/man2/setsockopt.2.html
95cde5492fSlogin     ///
96cde5492fSlogin     /// @param fd 文件描述符
97cde5492fSlogin     /// @param level 选项级别
98cde5492fSlogin     /// @param optname 选项名称
99cde5492fSlogin     /// @param optval 返回的选项值
100cde5492fSlogin     /// @param optlen 返回的optval缓冲区长度
101ab5c8ca4Slogin     pub fn getsockopt(
102cde5492fSlogin         fd: usize,
103cde5492fSlogin         level: usize,
104cde5492fSlogin         optname: usize,
105cde5492fSlogin         optval: *mut u8,
106cde5492fSlogin         optlen: *mut u32,
107ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
108cde5492fSlogin         // 获取socket
109cde5492fSlogin         let optval = optval as *mut u32;
110*1496ba7bSLoGin         let binding: Arc<SocketInode> = ProcessManager::current_pcb()
111cde5492fSlogin             .get_socket(fd as i32)
112cde5492fSlogin             .ok_or(SystemError::EBADF)?;
113cde5492fSlogin         let socket = binding.inner();
114cde5492fSlogin 
115cde5492fSlogin         if level as u8 == SOL_SOCKET {
116ab5c8ca4Slogin             let optname = PosixSocketOption::try_from(optname as i32)
117ab5c8ca4Slogin                 .map_err(|_| SystemError::ENOPROTOOPT)?;
118cde5492fSlogin             match optname {
119cde5492fSlogin                 PosixSocketOption::SO_SNDBUF => {
120cde5492fSlogin                     // 返回发送缓冲区大小
121cde5492fSlogin                     unsafe {
122cde5492fSlogin                         *optval = socket.metadata()?.send_buf_size as u32;
123cde5492fSlogin                         *optlen = core::mem::size_of::<u32>() as u32;
124cde5492fSlogin                     }
125cde5492fSlogin                     return Ok(0);
126cde5492fSlogin                 }
127cde5492fSlogin                 PosixSocketOption::SO_RCVBUF => {
128cde5492fSlogin                     let optval = optval as *mut u32;
129cde5492fSlogin                     // 返回默认的接收缓冲区大小
130cde5492fSlogin                     unsafe {
131cde5492fSlogin                         *optval = socket.metadata()?.recv_buf_size as u32;
132cde5492fSlogin                         *optlen = core::mem::size_of::<u32>() as u32;
133cde5492fSlogin                     }
134cde5492fSlogin                     return Ok(0);
135cde5492fSlogin                 }
136cde5492fSlogin                 _ => {
137cde5492fSlogin                     return Err(SystemError::ENOPROTOOPT);
138cde5492fSlogin                 }
139cde5492fSlogin             }
140cde5492fSlogin         }
141cde5492fSlogin         drop(socket);
142cde5492fSlogin 
143cde5492fSlogin         // To manipulate options at any other level the
144cde5492fSlogin         // protocol number of the appropriate protocol controlling the
145cde5492fSlogin         // option is supplied.  For example, to indicate that an option is
146cde5492fSlogin         // to be interpreted by the TCP protocol, level should be set to the
147cde5492fSlogin         // protocol number of TCP.
148cde5492fSlogin 
149cde5492fSlogin         let posix_protocol =
150cde5492fSlogin             PosixIpProtocol::try_from(level as u16).map_err(|_| SystemError::ENOPROTOOPT)?;
151cde5492fSlogin         if posix_protocol == PosixIpProtocol::TCP {
152cde5492fSlogin             let optname = PosixTcpSocketOptions::try_from(optname as i32)
153cde5492fSlogin                 .map_err(|_| SystemError::ENOPROTOOPT)?;
154cde5492fSlogin             match optname {
155cde5492fSlogin                 PosixTcpSocketOptions::Congestion => return Ok(0),
156cde5492fSlogin                 _ => {
157cde5492fSlogin                     return Err(SystemError::ENOPROTOOPT);
158cde5492fSlogin                 }
159cde5492fSlogin             }
160cde5492fSlogin         }
161cde5492fSlogin         return Err(SystemError::ENOPROTOOPT);
162cde5492fSlogin     }
163cde5492fSlogin 
164cde5492fSlogin     /// @brief sys_connect系统调用的实际执行函数
165cde5492fSlogin     ///
166cde5492fSlogin     /// @param fd 文件描述符
167cde5492fSlogin     /// @param addr SockAddr
168cde5492fSlogin     /// @param addrlen 地址长度
169cde5492fSlogin     ///
170cde5492fSlogin     /// @return 成功返回0,失败返回错误码
171ab5c8ca4Slogin     pub fn connect(fd: usize, addr: *const SockAddr, addrlen: usize) -> Result<usize, SystemError> {
172cde5492fSlogin         let endpoint: Endpoint = SockAddr::to_endpoint(addr, addrlen)?;
173*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
174cde5492fSlogin             .get_socket(fd as i32)
175cde5492fSlogin             .ok_or(SystemError::EBADF)?;
176cde5492fSlogin         let mut socket = socket.inner();
177cde5492fSlogin         // kdebug!("connect to {:?}...", endpoint);
178cde5492fSlogin         socket.connect(endpoint)?;
179cde5492fSlogin         return Ok(0);
180cde5492fSlogin     }
181cde5492fSlogin 
182cde5492fSlogin     /// @brief sys_bind系统调用的实际执行函数
183cde5492fSlogin     ///
184cde5492fSlogin     /// @param fd 文件描述符
185cde5492fSlogin     /// @param addr SockAddr
186cde5492fSlogin     /// @param addrlen 地址长度
187cde5492fSlogin     ///
188cde5492fSlogin     /// @return 成功返回0,失败返回错误码
189ab5c8ca4Slogin     pub fn bind(fd: usize, addr: *const SockAddr, addrlen: usize) -> Result<usize, SystemError> {
190cde5492fSlogin         let endpoint: Endpoint = SockAddr::to_endpoint(addr, addrlen)?;
191*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
192cde5492fSlogin             .get_socket(fd as i32)
193cde5492fSlogin             .ok_or(SystemError::EBADF)?;
194cde5492fSlogin         let mut socket = socket.inner();
195cde5492fSlogin         socket.bind(endpoint)?;
196cde5492fSlogin         return Ok(0);
197cde5492fSlogin     }
198cde5492fSlogin 
199cde5492fSlogin     /// @brief sys_sendto系统调用的实际执行函数
200cde5492fSlogin     ///
201cde5492fSlogin     /// @param fd 文件描述符
202cde5492fSlogin     /// @param buf 发送缓冲区
203cde5492fSlogin     /// @param flags 标志
204cde5492fSlogin     /// @param addr SockAddr
205cde5492fSlogin     /// @param addrlen 地址长度
206cde5492fSlogin     ///
207cde5492fSlogin     /// @return 成功返回发送的字节数,失败返回错误码
208ab5c8ca4Slogin     pub fn sendto(
209cde5492fSlogin         fd: usize,
210ab5c8ca4Slogin         buf: &[u8],
211ab5c8ca4Slogin         _flags: u32,
212cde5492fSlogin         addr: *const SockAddr,
213cde5492fSlogin         addrlen: usize,
214ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
215cde5492fSlogin         let endpoint = if addr.is_null() {
216cde5492fSlogin             None
217cde5492fSlogin         } else {
218cde5492fSlogin             Some(SockAddr::to_endpoint(addr, addrlen)?)
219cde5492fSlogin         };
220cde5492fSlogin 
221*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
222cde5492fSlogin             .get_socket(fd as i32)
223cde5492fSlogin             .ok_or(SystemError::EBADF)?;
224cde5492fSlogin         let socket = socket.inner();
225ab5c8ca4Slogin         return socket.write(buf, endpoint);
226cde5492fSlogin     }
227cde5492fSlogin 
228cde5492fSlogin     /// @brief sys_recvfrom系统调用的实际执行函数
229cde5492fSlogin     ///
230cde5492fSlogin     /// @param fd 文件描述符
231cde5492fSlogin     /// @param buf 接收缓冲区
232cde5492fSlogin     /// @param flags 标志
233cde5492fSlogin     /// @param addr SockAddr
234cde5492fSlogin     /// @param addrlen 地址长度
235cde5492fSlogin     ///
236cde5492fSlogin     /// @return 成功返回接收的字节数,失败返回错误码
237ab5c8ca4Slogin     pub fn recvfrom(
238cde5492fSlogin         fd: usize,
239ab5c8ca4Slogin         buf: &mut [u8],
240ab5c8ca4Slogin         _flags: u32,
241cde5492fSlogin         addr: *mut SockAddr,
242cde5492fSlogin         addrlen: *mut u32,
243ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
244*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
245cde5492fSlogin             .get_socket(fd as i32)
246cde5492fSlogin             .ok_or(SystemError::EBADF)?;
247cde5492fSlogin         let socket = socket.inner();
248cde5492fSlogin 
249cde5492fSlogin         let (n, endpoint) = socket.read(buf);
250cde5492fSlogin         drop(socket);
251cde5492fSlogin 
252cde5492fSlogin         let n: usize = n?;
253cde5492fSlogin 
254cde5492fSlogin         // 如果有地址信息,将地址信息写入用户空间
255cde5492fSlogin         if !addr.is_null() {
256cde5492fSlogin             let sockaddr_in = SockAddr::from(endpoint);
257cde5492fSlogin             unsafe {
258cde5492fSlogin                 sockaddr_in.write_to_user(addr, addrlen)?;
259cde5492fSlogin             }
260cde5492fSlogin         }
261ab5c8ca4Slogin         return Ok(n);
262cde5492fSlogin     }
263cde5492fSlogin 
264cde5492fSlogin     /// @brief sys_recvmsg系统调用的实际执行函数
265cde5492fSlogin     ///
266cde5492fSlogin     /// @param fd 文件描述符
267cde5492fSlogin     /// @param msg MsgHdr
268ab5c8ca4Slogin     /// @param flags 标志,暂时未使用
269cde5492fSlogin     ///
270cde5492fSlogin     /// @return 成功返回接收的字节数,失败返回错误码
271ab5c8ca4Slogin     pub fn recvmsg(fd: usize, msg: &mut MsgHdr, _flags: u32) -> Result<usize, SystemError> {
272cde5492fSlogin         // 检查每个缓冲区地址是否合法,生成iovecs
273cde5492fSlogin         let mut iovs = unsafe { IoVecs::from_user(msg.msg_iov, msg.msg_iovlen, true)? };
274cde5492fSlogin 
275*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
276cde5492fSlogin             .get_socket(fd as i32)
277cde5492fSlogin             .ok_or(SystemError::EBADF)?;
278cde5492fSlogin         let socket = socket.inner();
279cde5492fSlogin 
280cde5492fSlogin         let mut buf = iovs.new_buf(true);
281cde5492fSlogin         // 从socket中读取数据
282cde5492fSlogin         let (n, endpoint) = socket.read(&mut buf);
283cde5492fSlogin         drop(socket);
284cde5492fSlogin 
285cde5492fSlogin         let n: usize = n?;
286cde5492fSlogin 
287cde5492fSlogin         // 将数据写入用户空间的iovecs
288cde5492fSlogin         iovs.scatter(&buf[..n]);
289cde5492fSlogin 
290cde5492fSlogin         let sockaddr_in = SockAddr::from(endpoint);
291cde5492fSlogin         unsafe {
292cde5492fSlogin             sockaddr_in.write_to_user(msg.msg_name, &mut msg.msg_namelen)?;
293cde5492fSlogin         }
294ab5c8ca4Slogin         return Ok(n);
295cde5492fSlogin     }
296cde5492fSlogin 
297cde5492fSlogin     /// @brief sys_listen系统调用的实际执行函数
298cde5492fSlogin     ///
299cde5492fSlogin     /// @param fd 文件描述符
300ab5c8ca4Slogin     /// @param backlog 队列最大连接数
301cde5492fSlogin     ///
302cde5492fSlogin     /// @return 成功返回0,失败返回错误码
303ab5c8ca4Slogin     pub fn listen(fd: usize, backlog: usize) -> Result<usize, SystemError> {
304*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
305cde5492fSlogin             .get_socket(fd as i32)
306cde5492fSlogin             .ok_or(SystemError::EBADF)?;
307cde5492fSlogin         let mut socket = socket.inner();
308cde5492fSlogin         socket.listen(backlog)?;
309cde5492fSlogin         return Ok(0);
310cde5492fSlogin     }
311cde5492fSlogin 
312cde5492fSlogin     /// @brief sys_shutdown系统调用的实际执行函数
313cde5492fSlogin     ///
314cde5492fSlogin     /// @param fd 文件描述符
315cde5492fSlogin     /// @param how 关闭方式
316cde5492fSlogin     ///
317cde5492fSlogin     /// @return 成功返回0,失败返回错误码
318ab5c8ca4Slogin     pub fn shutdown(fd: usize, how: usize) -> Result<usize, SystemError> {
319*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
320cde5492fSlogin             .get_socket(fd as i32)
321cde5492fSlogin             .ok_or(SystemError::EBADF)?;
322cde5492fSlogin         let socket = socket.inner();
323cde5492fSlogin         socket.shutdown(ShutdownType::try_from(how as i32)?)?;
324cde5492fSlogin         return Ok(0);
325cde5492fSlogin     }
326cde5492fSlogin 
327cde5492fSlogin     /// @brief sys_accept系统调用的实际执行函数
328cde5492fSlogin     ///
329cde5492fSlogin     /// @param fd 文件描述符
330cde5492fSlogin     /// @param addr SockAddr
331cde5492fSlogin     /// @param addrlen 地址长度
332cde5492fSlogin     ///
333cde5492fSlogin     /// @return 成功返回新的文件描述符,失败返回错误码
334ab5c8ca4Slogin     pub fn accept(fd: usize, addr: *mut SockAddr, addrlen: *mut u32) -> Result<usize, SystemError> {
335*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
336cde5492fSlogin             .get_socket(fd as i32)
337cde5492fSlogin             .ok_or(SystemError::EBADF)?;
338cde5492fSlogin         // kdebug!("accept: socket={:?}", socket);
339cde5492fSlogin         let mut socket = socket.inner();
340cde5492fSlogin         // 从socket中接收连接
341cde5492fSlogin         let (new_socket, remote_endpoint) = socket.accept()?;
342cde5492fSlogin         drop(socket);
343cde5492fSlogin 
344cde5492fSlogin         // kdebug!("accept: new_socket={:?}", new_socket);
345cde5492fSlogin         // Insert the new socket into the file descriptor vector
346cde5492fSlogin         let new_socket: Arc<SocketInode> = SocketInode::new(new_socket);
347*1496ba7bSLoGin         let new_fd = ProcessManager::current_pcb()
348*1496ba7bSLoGin             .fd_table()
349*1496ba7bSLoGin             .write()
350*1496ba7bSLoGin             .alloc_fd(File::new(new_socket, FileMode::O_RDWR)?, None)?;
351cde5492fSlogin         // kdebug!("accept: new_fd={}", new_fd);
352cde5492fSlogin         if !addr.is_null() {
353cde5492fSlogin             // kdebug!("accept: write remote_endpoint to user");
354cde5492fSlogin             // 将对端地址写入用户空间
355cde5492fSlogin             let sockaddr_in = SockAddr::from(remote_endpoint);
356cde5492fSlogin             unsafe {
357cde5492fSlogin                 sockaddr_in.write_to_user(addr, addrlen)?;
358cde5492fSlogin             }
359cde5492fSlogin         }
360ab5c8ca4Slogin         return Ok(new_fd as usize);
361cde5492fSlogin     }
362cde5492fSlogin 
363cde5492fSlogin     /// @brief sys_getsockname系统调用的实际执行函数
364cde5492fSlogin     ///
365cde5492fSlogin     ///  Returns the current address to which the socket
366cde5492fSlogin     ///     sockfd is bound, in the buffer pointed to by addr.
367cde5492fSlogin     ///
368cde5492fSlogin     /// @param fd 文件描述符
369cde5492fSlogin     /// @param addr SockAddr
370cde5492fSlogin     /// @param addrlen 地址长度
371cde5492fSlogin     ///
372cde5492fSlogin     /// @return 成功返回0,失败返回错误码
373ab5c8ca4Slogin     pub fn getsockname(
374cde5492fSlogin         fd: usize,
375cde5492fSlogin         addr: *mut SockAddr,
376cde5492fSlogin         addrlen: *mut u32,
377ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
378cde5492fSlogin         if addr.is_null() {
379cde5492fSlogin             return Err(SystemError::EINVAL);
380cde5492fSlogin         }
381*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
382cde5492fSlogin             .get_socket(fd as i32)
383cde5492fSlogin             .ok_or(SystemError::EBADF)?;
384cde5492fSlogin         let socket = socket.inner();
385cde5492fSlogin         let endpoint: Endpoint = socket.endpoint().ok_or(SystemError::EINVAL)?;
386cde5492fSlogin         drop(socket);
387cde5492fSlogin 
388cde5492fSlogin         let sockaddr_in = SockAddr::from(endpoint);
389cde5492fSlogin         unsafe {
390cde5492fSlogin             sockaddr_in.write_to_user(addr, addrlen)?;
391cde5492fSlogin         }
392cde5492fSlogin         return Ok(0);
393cde5492fSlogin     }
394cde5492fSlogin 
395cde5492fSlogin     /// @brief sys_getpeername系统调用的实际执行函数
396cde5492fSlogin     ///
397cde5492fSlogin     /// @param fd 文件描述符
398cde5492fSlogin     /// @param addr SockAddr
399cde5492fSlogin     /// @param addrlen 地址长度
400cde5492fSlogin     ///
401cde5492fSlogin     /// @return 成功返回0,失败返回错误码
402ab5c8ca4Slogin     pub fn getpeername(
403cde5492fSlogin         fd: usize,
404cde5492fSlogin         addr: *mut SockAddr,
405cde5492fSlogin         addrlen: *mut u32,
406ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
407cde5492fSlogin         if addr.is_null() {
408cde5492fSlogin             return Err(SystemError::EINVAL);
409cde5492fSlogin         }
410cde5492fSlogin 
411*1496ba7bSLoGin         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
412cde5492fSlogin             .get_socket(fd as i32)
413cde5492fSlogin             .ok_or(SystemError::EBADF)?;
414cde5492fSlogin         let socket = socket.inner();
415cde5492fSlogin         let endpoint: Endpoint = socket.peer_endpoint().ok_or(SystemError::EINVAL)?;
416cde5492fSlogin         drop(socket);
417cde5492fSlogin 
418cde5492fSlogin         let sockaddr_in = SockAddr::from(endpoint);
419cde5492fSlogin         unsafe {
420cde5492fSlogin             sockaddr_in.write_to_user(addr, addrlen)?;
421cde5492fSlogin         }
422cde5492fSlogin         return Ok(0);
423cde5492fSlogin     }
424ab5c8ca4Slogin }
425cde5492fSlogin 
426cde5492fSlogin // 参考资料: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html#tag_13_32
427cde5492fSlogin #[repr(C)]
428cde5492fSlogin #[derive(Debug, Clone, Copy)]
429cde5492fSlogin pub struct SockAddrIn {
430cde5492fSlogin     pub sin_family: u16,
431cde5492fSlogin     pub sin_port: u16,
432cde5492fSlogin     pub sin_addr: u32,
433cde5492fSlogin     pub sin_zero: [u8; 8],
434cde5492fSlogin }
435cde5492fSlogin 
436cde5492fSlogin #[repr(C)]
437cde5492fSlogin #[derive(Debug, Clone, Copy)]
438cde5492fSlogin pub struct SockAddrUn {
439cde5492fSlogin     pub sun_family: u16,
440cde5492fSlogin     pub sun_path: [u8; 108],
441cde5492fSlogin }
442cde5492fSlogin 
443cde5492fSlogin #[repr(C)]
444cde5492fSlogin #[derive(Debug, Clone, Copy)]
445cde5492fSlogin pub struct SockAddrLl {
446cde5492fSlogin     pub sll_family: u16,
447cde5492fSlogin     pub sll_protocol: u16,
448cde5492fSlogin     pub sll_ifindex: u32,
449cde5492fSlogin     pub sll_hatype: u16,
450cde5492fSlogin     pub sll_pkttype: u8,
451cde5492fSlogin     pub sll_halen: u8,
452cde5492fSlogin     pub sll_addr: [u8; 8],
453cde5492fSlogin }
454cde5492fSlogin 
455cde5492fSlogin #[repr(C)]
456cde5492fSlogin #[derive(Debug, Clone, Copy)]
457cde5492fSlogin pub struct SockAddrNl {
458cde5492fSlogin     nl_family: u16,
459cde5492fSlogin     nl_pad: u16,
460cde5492fSlogin     nl_pid: u32,
461cde5492fSlogin     nl_groups: u32,
462cde5492fSlogin }
463cde5492fSlogin 
464cde5492fSlogin #[repr(C)]
465cde5492fSlogin #[derive(Debug, Clone, Copy)]
466cde5492fSlogin pub struct SockAddrPlaceholder {
467cde5492fSlogin     pub family: u16,
468cde5492fSlogin     pub data: [u8; 14],
469cde5492fSlogin }
470cde5492fSlogin 
471cde5492fSlogin #[repr(C)]
472cde5492fSlogin #[derive(Clone, Copy)]
473cde5492fSlogin pub union SockAddr {
474cde5492fSlogin     pub family: u16,
475cde5492fSlogin     pub addr_in: SockAddrIn,
476cde5492fSlogin     pub addr_un: SockAddrUn,
477cde5492fSlogin     pub addr_ll: SockAddrLl,
478cde5492fSlogin     pub addr_nl: SockAddrNl,
479cde5492fSlogin     pub addr_ph: SockAddrPlaceholder,
480cde5492fSlogin }
481cde5492fSlogin 
482cde5492fSlogin impl SockAddr {
483cde5492fSlogin     /// @brief 把用户传入的SockAddr转换为Endpoint结构体
484cde5492fSlogin     pub fn to_endpoint(addr: *const SockAddr, len: usize) -> Result<Endpoint, SystemError> {
485cde5492fSlogin         if unsafe {
486cde5492fSlogin             verify_area(
487cde5492fSlogin                 addr as usize as u64,
488cde5492fSlogin                 core::mem::size_of::<SockAddr>() as u64,
489cde5492fSlogin             )
490cde5492fSlogin         } == false
491cde5492fSlogin         {
492cde5492fSlogin             return Err(SystemError::EFAULT);
493cde5492fSlogin         }
494cde5492fSlogin 
495cde5492fSlogin         let addr = unsafe { addr.as_ref() }.ok_or(SystemError::EFAULT)?;
496cde5492fSlogin         if len < addr.len()? {
497cde5492fSlogin             return Err(SystemError::EINVAL);
498cde5492fSlogin         }
499cde5492fSlogin         unsafe {
500cde5492fSlogin             match AddressFamily::try_from(addr.family)? {
501cde5492fSlogin                 AddressFamily::INet => {
502cde5492fSlogin                     let addr_in: SockAddrIn = addr.addr_in;
503cde5492fSlogin 
504cde5492fSlogin                     let ip: wire::IpAddress = wire::IpAddress::from(wire::Ipv4Address::from_bytes(
505cde5492fSlogin                         &u32::from_be(addr_in.sin_addr).to_be_bytes()[..],
506cde5492fSlogin                     ));
507cde5492fSlogin                     let port = u16::from_be(addr_in.sin_port);
508cde5492fSlogin 
509cde5492fSlogin                     return Ok(Endpoint::Ip(Some(wire::IpEndpoint::new(ip, port))));
510cde5492fSlogin                 }
511cde5492fSlogin                 AddressFamily::Packet => {
512cde5492fSlogin                     // TODO: support packet socket
513cde5492fSlogin                     return Err(SystemError::EINVAL);
514cde5492fSlogin                 }
515cde5492fSlogin                 AddressFamily::Netlink => {
516cde5492fSlogin                     // TODO: support netlink socket
517cde5492fSlogin                     return Err(SystemError::EINVAL);
518cde5492fSlogin                 }
519cde5492fSlogin                 AddressFamily::Unix => {
520cde5492fSlogin                     return Err(SystemError::EINVAL);
521cde5492fSlogin                 }
522cde5492fSlogin                 _ => {
523cde5492fSlogin                     return Err(SystemError::EINVAL);
524cde5492fSlogin                 }
525cde5492fSlogin             }
526cde5492fSlogin         }
527cde5492fSlogin     }
528cde5492fSlogin 
529cde5492fSlogin     /// @brief 获取地址长度
530cde5492fSlogin     pub fn len(&self) -> Result<usize, SystemError> {
531cde5492fSlogin         let ret = match AddressFamily::try_from(unsafe { self.family })? {
532cde5492fSlogin             AddressFamily::INet => Ok(core::mem::size_of::<SockAddrIn>()),
533cde5492fSlogin             AddressFamily::Packet => Ok(core::mem::size_of::<SockAddrLl>()),
534cde5492fSlogin             AddressFamily::Netlink => Ok(core::mem::size_of::<SockAddrNl>()),
535cde5492fSlogin             AddressFamily::Unix => Err(SystemError::EINVAL),
536cde5492fSlogin             _ => Err(SystemError::EINVAL),
537cde5492fSlogin         };
538cde5492fSlogin 
539cde5492fSlogin         return ret;
540cde5492fSlogin     }
541cde5492fSlogin 
542cde5492fSlogin     /// @brief 把SockAddr的数据写入用户空间
543cde5492fSlogin     ///
544cde5492fSlogin     /// @param addr 用户空间的SockAddr的地址
545cde5492fSlogin     /// @param len 要写入的长度
546cde5492fSlogin     ///
547cde5492fSlogin     /// @return 成功返回写入的长度,失败返回错误码
548cde5492fSlogin     pub unsafe fn write_to_user(
549cde5492fSlogin         &self,
550cde5492fSlogin         addr: *mut SockAddr,
551cde5492fSlogin         addr_len: *mut u32,
552cde5492fSlogin     ) -> Result<usize, SystemError> {
553cde5492fSlogin         // 当用户传入的地址或者长度为空时,直接返回0
554cde5492fSlogin         if addr.is_null() || addr_len.is_null() {
555cde5492fSlogin             return Ok(0);
556cde5492fSlogin         }
557cde5492fSlogin         // 检查用户传入的地址是否合法
558cde5492fSlogin         if !verify_area(
559cde5492fSlogin             addr as usize as u64,
560cde5492fSlogin             core::mem::size_of::<SockAddr>() as u64,
561cde5492fSlogin         ) || !verify_area(addr_len as usize as u64, core::mem::size_of::<u32>() as u64)
562cde5492fSlogin         {
563cde5492fSlogin             return Err(SystemError::EFAULT);
564cde5492fSlogin         }
565cde5492fSlogin 
566cde5492fSlogin         let to_write = min(self.len()?, *addr_len as usize);
567cde5492fSlogin         if to_write > 0 {
568cde5492fSlogin             let buf = core::slice::from_raw_parts_mut(addr as *mut u8, to_write);
569cde5492fSlogin             buf.copy_from_slice(core::slice::from_raw_parts(
570cde5492fSlogin                 self as *const SockAddr as *const u8,
571cde5492fSlogin                 to_write,
572cde5492fSlogin             ));
573cde5492fSlogin         }
574cde5492fSlogin         *addr_len = self.len()? as u32;
575cde5492fSlogin         return Ok(to_write);
576cde5492fSlogin     }
577cde5492fSlogin }
578cde5492fSlogin 
579cde5492fSlogin impl From<Endpoint> for SockAddr {
580cde5492fSlogin     fn from(value: Endpoint) -> Self {
581cde5492fSlogin         match value {
582cde5492fSlogin             Endpoint::Ip(ip_endpoint) => {
583cde5492fSlogin                 // 未指定地址
584cde5492fSlogin                 if let None = ip_endpoint {
585cde5492fSlogin                     return SockAddr {
586cde5492fSlogin                         addr_ph: SockAddrPlaceholder {
587cde5492fSlogin                             family: AddressFamily::Unspecified as u16,
588cde5492fSlogin                             data: [0; 14],
589cde5492fSlogin                         },
590cde5492fSlogin                     };
591cde5492fSlogin                 }
592cde5492fSlogin                 // 指定了地址
593cde5492fSlogin                 let ip_endpoint = ip_endpoint.unwrap();
594cde5492fSlogin                 match ip_endpoint.addr {
595cde5492fSlogin                     wire::IpAddress::Ipv4(ipv4_addr) => {
596cde5492fSlogin                         let addr_in = SockAddrIn {
597cde5492fSlogin                             sin_family: AddressFamily::INet as u16,
598cde5492fSlogin                             sin_port: ip_endpoint.port.to_be(),
599cde5492fSlogin                             sin_addr: u32::from_be_bytes(ipv4_addr.0).to_be(),
600cde5492fSlogin                             sin_zero: [0; 8],
601cde5492fSlogin                         };
602cde5492fSlogin 
603cde5492fSlogin                         return SockAddr { addr_in };
604cde5492fSlogin                     }
605cde5492fSlogin                     _ => {
606cde5492fSlogin                         unimplemented!("not support ipv6");
607cde5492fSlogin                     }
608cde5492fSlogin                 }
609cde5492fSlogin             }
610cde5492fSlogin 
611cde5492fSlogin             Endpoint::LinkLayer(link_endpoint) => {
612cde5492fSlogin                 let addr_ll = SockAddrLl {
613cde5492fSlogin                     sll_family: AddressFamily::Packet as u16,
614cde5492fSlogin                     sll_protocol: 0,
615cde5492fSlogin                     sll_ifindex: link_endpoint.interface as u32,
616cde5492fSlogin                     sll_hatype: 0,
617cde5492fSlogin                     sll_pkttype: 0,
618cde5492fSlogin                     sll_halen: 0,
619cde5492fSlogin                     sll_addr: [0; 8],
620cde5492fSlogin                 };
621cde5492fSlogin 
622cde5492fSlogin                 return SockAddr { addr_ll };
623cde5492fSlogin             } // _ => {
624cde5492fSlogin               //     // todo: support other endpoint, like Netlink...
625cde5492fSlogin               //     unimplemented!("not support {value:?}");
626cde5492fSlogin               // }
627cde5492fSlogin         }
628cde5492fSlogin     }
629cde5492fSlogin }
630cde5492fSlogin 
631cde5492fSlogin #[repr(C)]
632cde5492fSlogin #[derive(Debug, Clone, Copy)]
633cde5492fSlogin pub struct MsgHdr {
634cde5492fSlogin     /// 指向一个SockAddr结构体的指针
635cde5492fSlogin     pub msg_name: *mut SockAddr,
636cde5492fSlogin     /// SockAddr结构体的大小
637cde5492fSlogin     pub msg_namelen: u32,
638cde5492fSlogin     /// scatter/gather array
639cde5492fSlogin     pub msg_iov: *mut IoVec,
640cde5492fSlogin     /// elements in msg_iov
641cde5492fSlogin     pub msg_iovlen: usize,
642cde5492fSlogin     /// 辅助数据
643cde5492fSlogin     pub msg_control: *mut u8,
644cde5492fSlogin     /// 辅助数据长度
645cde5492fSlogin     pub msg_controllen: usize,
646cde5492fSlogin     /// 接收到的消息的标志
647cde5492fSlogin     pub msg_flags: u32,
648cde5492fSlogin }
649cde5492fSlogin 
650cde5492fSlogin #[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive, PartialEq, Eq)]
651cde5492fSlogin pub enum PosixIpProtocol {
652cde5492fSlogin     /// Dummy protocol for TCP.
653cde5492fSlogin     IP = 0,
654cde5492fSlogin     /// Internet Control Message Protocol.
655cde5492fSlogin     ICMP = 1,
656cde5492fSlogin     /// Internet Group Management Protocol.
657cde5492fSlogin     IGMP = 2,
658cde5492fSlogin     /// IPIP tunnels (older KA9Q tunnels use 94).
659cde5492fSlogin     IPIP = 4,
660cde5492fSlogin     /// Transmission Control Protocol.
661cde5492fSlogin     TCP = 6,
662cde5492fSlogin     /// Exterior Gateway Protocol.
663cde5492fSlogin     EGP = 8,
664cde5492fSlogin     /// PUP protocol.
665cde5492fSlogin     PUP = 12,
666cde5492fSlogin     /// User Datagram Protocol.
667cde5492fSlogin     UDP = 17,
668cde5492fSlogin     /// XNS IDP protocol.
669cde5492fSlogin     IDP = 22,
670cde5492fSlogin     /// SO Transport Protocol Class 4.
671cde5492fSlogin     TP = 29,
672cde5492fSlogin     /// Datagram Congestion Control Protocol.
673cde5492fSlogin     DCCP = 33,
674cde5492fSlogin     /// IPv6-in-IPv4 tunnelling.
675cde5492fSlogin     IPv6 = 41,
676cde5492fSlogin     /// RSVP Protocol.
677cde5492fSlogin     RSVP = 46,
678cde5492fSlogin     /// Generic Routing Encapsulation. (Cisco GRE) (rfc 1701, 1702)
679cde5492fSlogin     GRE = 47,
680cde5492fSlogin     /// Encapsulation Security Payload protocol
681cde5492fSlogin     ESP = 50,
682cde5492fSlogin     /// Authentication Header protocol
683cde5492fSlogin     AH = 51,
684cde5492fSlogin     /// Multicast Transport Protocol.
685cde5492fSlogin     MTP = 92,
686cde5492fSlogin     /// IP option pseudo header for BEET
687cde5492fSlogin     BEETPH = 94,
688cde5492fSlogin     /// Encapsulation Header.
689cde5492fSlogin     ENCAP = 98,
690cde5492fSlogin     /// Protocol Independent Multicast.
691cde5492fSlogin     PIM = 103,
692cde5492fSlogin     /// Compression Header Protocol.
693cde5492fSlogin     COMP = 108,
694cde5492fSlogin     /// Stream Control Transport Protocol
695cde5492fSlogin     SCTP = 132,
696cde5492fSlogin     /// UDP-Lite protocol (RFC 3828)
697cde5492fSlogin     UDPLITE = 136,
698cde5492fSlogin     /// MPLS in IP (RFC 4023)
699cde5492fSlogin     MPLSINIP = 137,
700cde5492fSlogin     /// Ethernet-within-IPv6 Encapsulation
701cde5492fSlogin     ETHERNET = 143,
702cde5492fSlogin     /// Raw IP packets
703cde5492fSlogin     RAW = 255,
704cde5492fSlogin     /// Multipath TCP connection
705cde5492fSlogin     MPTCP = 262,
706cde5492fSlogin }
707cde5492fSlogin 
708cde5492fSlogin impl TryFrom<u16> for PosixIpProtocol {
709cde5492fSlogin     type Error = SystemError;
710cde5492fSlogin 
711cde5492fSlogin     fn try_from(value: u16) -> Result<Self, Self::Error> {
712cde5492fSlogin         match <Self as FromPrimitive>::from_u16(value) {
713cde5492fSlogin             Some(p) => Ok(p),
714cde5492fSlogin             None => Err(SystemError::EPROTONOSUPPORT),
715cde5492fSlogin         }
716cde5492fSlogin     }
717cde5492fSlogin }
718cde5492fSlogin 
719cde5492fSlogin impl Into<u16> for PosixIpProtocol {
720cde5492fSlogin     fn into(self) -> u16 {
721cde5492fSlogin         <Self as ToPrimitive>::to_u16(&self).unwrap()
722cde5492fSlogin     }
723cde5492fSlogin }
724cde5492fSlogin 
725cde5492fSlogin #[allow(non_camel_case_types)]
726cde5492fSlogin #[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive, PartialEq, Eq)]
727cde5492fSlogin pub enum PosixSocketOption {
728cde5492fSlogin     SO_DEBUG = 1,
729cde5492fSlogin     SO_REUSEADDR = 2,
730cde5492fSlogin     SO_TYPE = 3,
731cde5492fSlogin     SO_ERROR = 4,
732cde5492fSlogin     SO_DONTROUTE = 5,
733cde5492fSlogin     SO_BROADCAST = 6,
734cde5492fSlogin     SO_SNDBUF = 7,
735cde5492fSlogin     SO_RCVBUF = 8,
736cde5492fSlogin     SO_SNDBUFFORCE = 32,
737cde5492fSlogin     SO_RCVBUFFORCE = 33,
738cde5492fSlogin     SO_KEEPALIVE = 9,
739cde5492fSlogin     SO_OOBINLINE = 10,
740cde5492fSlogin     SO_NO_CHECK = 11,
741cde5492fSlogin     SO_PRIORITY = 12,
742cde5492fSlogin     SO_LINGER = 13,
743cde5492fSlogin     SO_BSDCOMPAT = 14,
744cde5492fSlogin     SO_REUSEPORT = 15,
745cde5492fSlogin     SO_PASSCRED = 16,
746cde5492fSlogin     SO_PEERCRED = 17,
747cde5492fSlogin     SO_RCVLOWAT = 18,
748cde5492fSlogin     SO_SNDLOWAT = 19,
749cde5492fSlogin     SO_RCVTIMEO_OLD = 20,
750cde5492fSlogin     SO_SNDTIMEO_OLD = 21,
751cde5492fSlogin 
752cde5492fSlogin     SO_SECURITY_AUTHENTICATION = 22,
753cde5492fSlogin     SO_SECURITY_ENCRYPTION_TRANSPORT = 23,
754cde5492fSlogin     SO_SECURITY_ENCRYPTION_NETWORK = 24,
755cde5492fSlogin 
756cde5492fSlogin     SO_BINDTODEVICE = 25,
757cde5492fSlogin 
758cde5492fSlogin     /// 与SO_GET_FILTER相同
759cde5492fSlogin     SO_ATTACH_FILTER = 26,
760cde5492fSlogin     SO_DETACH_FILTER = 27,
761cde5492fSlogin 
762cde5492fSlogin     SO_PEERNAME = 28,
763cde5492fSlogin 
764cde5492fSlogin     SO_ACCEPTCONN = 30,
765cde5492fSlogin 
766cde5492fSlogin     SO_PEERSEC = 31,
767cde5492fSlogin     SO_PASSSEC = 34,
768cde5492fSlogin 
769cde5492fSlogin     SO_MARK = 36,
770cde5492fSlogin 
771cde5492fSlogin     SO_PROTOCOL = 38,
772cde5492fSlogin     SO_DOMAIN = 39,
773cde5492fSlogin 
774cde5492fSlogin     SO_RXQ_OVFL = 40,
775cde5492fSlogin 
776cde5492fSlogin     /// 与SCM_WIFI_STATUS相同
777cde5492fSlogin     SO_WIFI_STATUS = 41,
778cde5492fSlogin     SO_PEEK_OFF = 42,
779cde5492fSlogin 
780cde5492fSlogin     /* Instruct lower device to use last 4-bytes of skb data as FCS */
781cde5492fSlogin     SO_NOFCS = 43,
782cde5492fSlogin 
783cde5492fSlogin     SO_LOCK_FILTER = 44,
784cde5492fSlogin     SO_SELECT_ERR_QUEUE = 45,
785cde5492fSlogin     SO_BUSY_POLL = 46,
786cde5492fSlogin     SO_MAX_PACING_RATE = 47,
787cde5492fSlogin     SO_BPF_EXTENSIONS = 48,
788cde5492fSlogin     SO_INCOMING_CPU = 49,
789cde5492fSlogin     SO_ATTACH_BPF = 50,
790cde5492fSlogin     // SO_DETACH_BPF = SO_DETACH_FILTER,
791cde5492fSlogin     SO_ATTACH_REUSEPORT_CBPF = 51,
792cde5492fSlogin     SO_ATTACH_REUSEPORT_EBPF = 52,
793cde5492fSlogin 
794cde5492fSlogin     SO_CNX_ADVICE = 53,
795cde5492fSlogin     SCM_TIMESTAMPING_OPT_STATS = 54,
796cde5492fSlogin     SO_MEMINFO = 55,
797cde5492fSlogin     SO_INCOMING_NAPI_ID = 56,
798cde5492fSlogin     SO_COOKIE = 57,
799cde5492fSlogin     SCM_TIMESTAMPING_PKTINFO = 58,
800cde5492fSlogin     SO_PEERGROUPS = 59,
801cde5492fSlogin     SO_ZEROCOPY = 60,
802cde5492fSlogin     /// 与SCM_TXTIME相同
803cde5492fSlogin     SO_TXTIME = 61,
804cde5492fSlogin 
805cde5492fSlogin     SO_BINDTOIFINDEX = 62,
806cde5492fSlogin 
807cde5492fSlogin     SO_TIMESTAMP_OLD = 29,
808cde5492fSlogin     SO_TIMESTAMPNS_OLD = 35,
809cde5492fSlogin     SO_TIMESTAMPING_OLD = 37,
810cde5492fSlogin     SO_TIMESTAMP_NEW = 63,
811cde5492fSlogin     SO_TIMESTAMPNS_NEW = 64,
812cde5492fSlogin     SO_TIMESTAMPING_NEW = 65,
813cde5492fSlogin 
814cde5492fSlogin     SO_RCVTIMEO_NEW = 66,
815cde5492fSlogin     SO_SNDTIMEO_NEW = 67,
816cde5492fSlogin 
817cde5492fSlogin     SO_DETACH_REUSEPORT_BPF = 68,
818cde5492fSlogin 
819cde5492fSlogin     SO_PREFER_BUSY_POLL = 69,
820cde5492fSlogin     SO_BUSY_POLL_BUDGET = 70,
821cde5492fSlogin 
822cde5492fSlogin     SO_NETNS_COOKIE = 71,
823cde5492fSlogin     SO_BUF_LOCK = 72,
824cde5492fSlogin     SO_RESERVE_MEM = 73,
825cde5492fSlogin     SO_TXREHASH = 74,
826cde5492fSlogin     SO_RCVMARK = 75,
827cde5492fSlogin }
828cde5492fSlogin 
829cde5492fSlogin impl TryFrom<i32> for PosixSocketOption {
830cde5492fSlogin     type Error = SystemError;
831cde5492fSlogin 
832cde5492fSlogin     fn try_from(value: i32) -> Result<Self, Self::Error> {
833cde5492fSlogin         match <Self as FromPrimitive>::from_i32(value) {
834cde5492fSlogin             Some(p) => Ok(p),
835cde5492fSlogin             None => Err(SystemError::EINVAL),
836cde5492fSlogin         }
837cde5492fSlogin     }
838cde5492fSlogin }
839cde5492fSlogin 
840cde5492fSlogin impl Into<i32> for PosixSocketOption {
841cde5492fSlogin     fn into(self) -> i32 {
842cde5492fSlogin         <Self as ToPrimitive>::to_i32(&self).unwrap()
843cde5492fSlogin     }
844cde5492fSlogin }
845cde5492fSlogin 
846cde5492fSlogin #[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
847cde5492fSlogin pub enum PosixTcpSocketOptions {
848cde5492fSlogin     /// Turn off Nagle's algorithm.
849cde5492fSlogin     NoDelay = 1,
850cde5492fSlogin     /// Limit MSS.
851cde5492fSlogin     MaxSegment = 2,
852cde5492fSlogin     /// Never send partially complete segments.
853cde5492fSlogin     Cork = 3,
854cde5492fSlogin     /// Start keeplives after this period.
855cde5492fSlogin     KeepIdle = 4,
856cde5492fSlogin     /// Interval between keepalives.
857cde5492fSlogin     KeepIntvl = 5,
858cde5492fSlogin     /// Number of keepalives before death.
859cde5492fSlogin     KeepCnt = 6,
860cde5492fSlogin     /// Number of SYN retransmits.
861cde5492fSlogin     Syncnt = 7,
862cde5492fSlogin     /// Lifetime for orphaned FIN-WAIT-2 state.
863cde5492fSlogin     Linger2 = 8,
864cde5492fSlogin     /// Wake up listener only when data arrive.
865cde5492fSlogin     DeferAccept = 9,
866cde5492fSlogin     /// Bound advertised window
867cde5492fSlogin     WindowClamp = 10,
868cde5492fSlogin     /// Information about this connection.
869cde5492fSlogin     Info = 11,
870cde5492fSlogin     /// Block/reenable quick acks.
871cde5492fSlogin     QuickAck = 12,
872cde5492fSlogin     /// Congestion control algorithm.
873cde5492fSlogin     Congestion = 13,
874cde5492fSlogin     /// TCP MD5 Signature (RFC2385).
875cde5492fSlogin     Md5Sig = 14,
876cde5492fSlogin     /// Use linear timeouts for thin streams
877cde5492fSlogin     ThinLinearTimeouts = 16,
878cde5492fSlogin     /// Fast retrans. after 1 dupack.
879cde5492fSlogin     ThinDupack = 17,
880cde5492fSlogin     /// How long for loss retry before timeout.
881cde5492fSlogin     UserTimeout = 18,
882cde5492fSlogin     /// TCP sock is under repair right now.
883cde5492fSlogin     Repair = 19,
884cde5492fSlogin     RepairQueue = 20,
885cde5492fSlogin     QueueSeq = 21,
886cde5492fSlogin     RepairOptions = 22,
887cde5492fSlogin     /// Enable FastOpen on listeners
888cde5492fSlogin     FastOpen = 23,
889cde5492fSlogin     Timestamp = 24,
890cde5492fSlogin     /// Limit number of unsent bytes in write queue.
891cde5492fSlogin     NotSentLowat = 25,
892cde5492fSlogin     /// Get Congestion Control (optional) info.
893cde5492fSlogin     CCInfo = 26,
894cde5492fSlogin     /// Record SYN headers for new connections.
895cde5492fSlogin     SaveSyn = 27,
896cde5492fSlogin     /// Get SYN headers recorded for connection.
897cde5492fSlogin     SavedSyn = 28,
898cde5492fSlogin     /// Get/set window parameters.
899cde5492fSlogin     RepairWindow = 29,
900cde5492fSlogin     /// Attempt FastOpen with connect.
901cde5492fSlogin     FastOpenConnect = 30,
902cde5492fSlogin     /// Attach a ULP to a TCP connection.
903cde5492fSlogin     ULP = 31,
904cde5492fSlogin     /// TCP MD5 Signature with extensions.
905cde5492fSlogin     Md5SigExt = 32,
906cde5492fSlogin     /// Set the key for Fast Open(cookie).
907cde5492fSlogin     FastOpenKey = 33,
908cde5492fSlogin     /// Enable TFO without a TFO cookie.
909cde5492fSlogin     FastOpenNoCookie = 34,
910cde5492fSlogin     ZeroCopyReceive = 35,
911cde5492fSlogin     /// Notify bytes available to read as a cmsg on read.
912cde5492fSlogin     /// 与TCP_CM_INQ相同
913cde5492fSlogin     INQ = 36,
914cde5492fSlogin     /// delay outgoing packets by XX usec
915cde5492fSlogin     TxDelay = 37,
916cde5492fSlogin }
917cde5492fSlogin 
918cde5492fSlogin impl TryFrom<i32> for PosixTcpSocketOptions {
919cde5492fSlogin     type Error = SystemError;
920cde5492fSlogin 
921cde5492fSlogin     fn try_from(value: i32) -> Result<Self, Self::Error> {
922cde5492fSlogin         match <Self as FromPrimitive>::from_i32(value) {
923cde5492fSlogin             Some(p) => Ok(p),
924cde5492fSlogin             None => Err(SystemError::EINVAL),
925cde5492fSlogin         }
926cde5492fSlogin     }
927cde5492fSlogin }
928cde5492fSlogin 
929cde5492fSlogin impl Into<i32> for PosixTcpSocketOptions {
930cde5492fSlogin     fn into(self) -> i32 {
931cde5492fSlogin         <Self as ToPrimitive>::to_i32(&self).unwrap()
932cde5492fSlogin     }
933cde5492fSlogin }
934