mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-16 08:46:48 +00:00
Add network syscalls
This commit is contained in:
parent
8719234dc2
commit
2b59a406a6
24
services/libs/jinux-std/src/syscall/accept.rs
Normal file
24
services/libs/jinux-std/src/syscall/accept.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use crate::util::write_socket_addr_to_user;
|
||||
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||
use crate::{get_socket_without_holding_filetable_lock, log_syscall_entry};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_ACCEPT;
|
||||
|
||||
pub fn sys_accept(
|
||||
sockfd: FileDescripter,
|
||||
sockaddr_ptr: Vaddr,
|
||||
addr_len: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_ACCEPT);
|
||||
debug!("sockfd = {sockfd}, sockaddr_ptr = 0x{sockaddr_ptr:x}, addr_len = {addr_len}");
|
||||
let current = current!();
|
||||
get_socket_without_holding_filetable_lock!(socket, current, sockfd);
|
||||
let (connected_socket, socket_addr) = socket.accept()?;
|
||||
write_socket_addr_to_user(&socket_addr, sockaddr_ptr, addr_len as usize)?;
|
||||
let fd = {
|
||||
let mut file_table = current.file_table().lock();
|
||||
file_table.insert(connected_socket)
|
||||
};
|
||||
Ok(SyscallReturn::Return(fd as _))
|
||||
}
|
21
services/libs/jinux-std/src/syscall/bind.rs
Normal file
21
services/libs/jinux-std/src/syscall/bind.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use crate::log_syscall_entry;
|
||||
use crate::util::read_socket_addr_from_user;
|
||||
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_BIND;
|
||||
|
||||
pub fn sys_bind(
|
||||
sockfd: FileDescripter,
|
||||
sockaddr_ptr: Vaddr,
|
||||
addrlen: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_BIND);
|
||||
let socket_addr = read_socket_addr_from_user(sockaddr_ptr, addrlen as usize)?;
|
||||
debug!("sockfd = {sockfd}, socket_addr = {socket_addr:?}");
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table.get_socket(sockfd)?;
|
||||
socket.bind(socket_addr)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
22
services/libs/jinux-std/src/syscall/connect.rs
Normal file
22
services/libs/jinux-std/src/syscall/connect.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use crate::fs::file_table::FileDescripter;
|
||||
use crate::get_socket_without_holding_filetable_lock;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::util::read_socket_addr_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_CONNECT;
|
||||
|
||||
pub fn sys_connect(
|
||||
sockfd: FileDescripter,
|
||||
sockaddr_ptr: Vaddr,
|
||||
addr_len: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_CONNECT);
|
||||
let socket_addr = read_socket_addr_from_user(sockaddr_ptr, addr_len as _)?;
|
||||
debug!("fd = {sockfd}, socket_addr = {socket_addr:?}");
|
||||
let current = current!();
|
||||
get_socket_without_holding_filetable_lock!(socket, current, sockfd);
|
||||
socket.connect(socket_addr)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
19
services/libs/jinux-std/src/syscall/getpeername.rs
Normal file
19
services/libs/jinux-std/src/syscall/getpeername.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::util::write_socket_addr_to_user;
|
||||
use crate::{fs::file_table::FileDescripter, log_syscall_entry, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_GETPEERNAME;
|
||||
|
||||
pub fn sys_getpeername(sockfd: FileDescripter, addr: Vaddr, addrlen: u32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_GETPEERNAME);
|
||||
debug!("sockfd = {sockfd}, addr = 0x{addr:x}, addrlen = {addrlen}");
|
||||
let socket_addr = {
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table.get_socket(sockfd)?;
|
||||
socket.peer_addr()?
|
||||
};
|
||||
// FIXME: trunscate write len if addrlen is not big enough
|
||||
write_socket_addr_to_user(&socket_addr, addr, addrlen as usize)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
21
services/libs/jinux-std/src/syscall/getsockname.rs
Normal file
21
services/libs/jinux-std/src/syscall/getsockname.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use crate::fs::file_table::FileDescripter;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::util::write_socket_addr_to_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_GETSOCKNAME;
|
||||
|
||||
pub fn sys_getsockname(sockfd: FileDescripter, addr: Vaddr, addrlen: u32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_GETSOCKNAME);
|
||||
debug!("sockfd = {sockfd}, addr = 0x{addr:x}, addrlen = {addrlen}");
|
||||
let socket_addr = {
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table.get_socket(sockfd)?;
|
||||
socket.addr()?
|
||||
};
|
||||
// FIXME: trunscate write len if addrlen is not big enough
|
||||
write_socket_addr_to_user(&socket_addr, addr, addrlen as usize)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
14
services/libs/jinux-std/src/syscall/listen.rs
Normal file
14
services/libs/jinux-std/src/syscall/listen.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use crate::{fs::file_table::FileDescripter, log_syscall_entry, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_LISTEN;
|
||||
|
||||
pub fn sys_listen(sockfd: FileDescripter, backlog: i32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_LISTEN);
|
||||
debug!("sockfd = {sockfd}, backlog = {backlog}");
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table.get_socket(sockfd)?;
|
||||
socket.listen(backlog as usize)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
36
services/libs/jinux-std/src/syscall/recvfrom.rs
Normal file
36
services/libs/jinux-std/src/syscall/recvfrom.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use crate::net::socket::SendRecvFlags;
|
||||
use crate::util::{
|
||||
read_val_from_user, write_bytes_to_user, write_socket_addr_to_user, write_val_to_user,
|
||||
};
|
||||
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||
use crate::{get_socket_without_holding_filetable_lock, log_syscall_entry};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_RECVFROM;
|
||||
|
||||
pub fn sys_recvfrom(
|
||||
sockfd: FileDescripter,
|
||||
buf: Vaddr,
|
||||
len: usize,
|
||||
flags: i32,
|
||||
src_addr: Vaddr,
|
||||
addrlen: Vaddr,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_RECVFROM);
|
||||
let flags = SendRecvFlags::from_bits_truncate(flags);
|
||||
debug!("sockfd = {sockfd}, buf = 0x{buf:x}, len = {len}, flags = {flags:?}, src_addr = 0x{src_addr:x}, addrlen = 0x{addrlen:x}");
|
||||
let current = current!();
|
||||
get_socket_without_holding_filetable_lock!(socket, current, sockfd);
|
||||
let mut buffer = vec![0u8; len];
|
||||
let (recv_size, socket_addr) = socket.recvfrom(&mut buffer, flags)?;
|
||||
if buf != 0 {
|
||||
write_bytes_to_user(buf, &buffer[..recv_size])?;
|
||||
}
|
||||
if src_addr != 0 {
|
||||
debug_assert!(addrlen != 0);
|
||||
let max_len: u32 = read_val_from_user(addrlen)?;
|
||||
let write_size = write_socket_addr_to_user(&socket_addr, src_addr, max_len as usize)?;
|
||||
write_val_to_user(addrlen, &(write_size as u32))?;
|
||||
}
|
||||
Ok(SyscallReturn::Return(recv_size as _))
|
||||
}
|
35
services/libs/jinux-std/src/syscall/sendto.rs
Normal file
35
services/libs/jinux-std/src/syscall/sendto.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::fs::file_table::FileDescripter;
|
||||
use crate::get_socket_without_holding_filetable_lock;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::net::socket::SendRecvFlags;
|
||||
use crate::prelude::*;
|
||||
use crate::util::read_bytes_from_user;
|
||||
use crate::util::read_socket_addr_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_SENDTO;
|
||||
|
||||
pub fn sys_sendto(
|
||||
sockfd: FileDescripter,
|
||||
buf: Vaddr,
|
||||
len: usize,
|
||||
flags: i32,
|
||||
dest_addr: Vaddr,
|
||||
addrlen: usize,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SENDTO);
|
||||
let flags = SendRecvFlags::from_bits_truncate(flags);
|
||||
let socket_addr = if dest_addr == 0 {
|
||||
None
|
||||
} else {
|
||||
let socket_addr = read_socket_addr_from_user(dest_addr, addrlen)?;
|
||||
Some(socket_addr)
|
||||
};
|
||||
debug!("sockfd = {sockfd}, buf = 0x{buf:x}, len = 0x{len:x}, flags = {flags:?}, socket_addr = {socket_addr:?}");
|
||||
let mut buffer = vec![0u8; len];
|
||||
read_bytes_from_user(buf, &mut buffer)?;
|
||||
let current = current!();
|
||||
get_socket_without_holding_filetable_lock!(socket, current, sockfd);
|
||||
let send_size = socket.sendto(&buffer, socket_addr, flags)?;
|
||||
Ok(SyscallReturn::Return(send_size as _))
|
||||
}
|
49
services/libs/jinux-std/src/syscall/setsockopt.rs
Normal file
49
services/libs/jinux-std/src/syscall/setsockopt.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::log_syscall_entry;
|
||||
use crate::net::socket::SockOptionName;
|
||||
use crate::util::read_bytes_from_user;
|
||||
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_SETSOCKOPT;
|
||||
|
||||
pub fn sys_setsockopt(
|
||||
sockfd: FileDescripter,
|
||||
level: i32,
|
||||
optname: i32,
|
||||
optval: Vaddr,
|
||||
optlen: usize,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SETSOCKOPT);
|
||||
let level = SockOptionLevel::try_from(level)?;
|
||||
if level != SockOptionLevel::SOL_SOCKET {
|
||||
return_errno_with_message!(Errno::ENOPROTOOPT, "Unsupported sockoption level");
|
||||
}
|
||||
let sock_option_name = SockOptionName::try_from(optname)?;
|
||||
if optval == 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "optval is null pointer");
|
||||
}
|
||||
let mut sock_opt_val = vec![0u8; optlen];
|
||||
read_bytes_from_user(optval, &mut sock_opt_val)?;
|
||||
|
||||
debug!("sockfd = {sockfd}, optname = {sock_option_name:?}, optval = {sock_opt_val:?}");
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table
|
||||
.get_file(sockfd)?
|
||||
.as_socket()
|
||||
.ok_or(Error::with_message(
|
||||
Errno::ENOTSOCK,
|
||||
"the file is not socket",
|
||||
))?;
|
||||
socket.set_sock_option(sock_option_name, &sock_opt_val)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, TryFromInt, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Sock Opt level
|
||||
enum SockOptionLevel {
|
||||
SOL_IP = 0,
|
||||
SOL_SOCKET = 1,
|
||||
}
|
22
services/libs/jinux-std/src/syscall/shutdown.rs
Normal file
22
services/libs/jinux-std/src/syscall/shutdown.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use crate::net::socket::SockShutdownCmd;
|
||||
use crate::{fs::file_table::FileDescripter, log_syscall_entry, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_SHUTDOWN;
|
||||
|
||||
pub fn sys_shutdown(sockfd: FileDescripter, how: i32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SHUTDOWN);
|
||||
let shutdown_cmd = SockShutdownCmd::try_from(how)?;
|
||||
debug!("sockfd = {sockfd}, cmd = {shutdown_cmd:?}");
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let socket = file_table
|
||||
.get_file(sockfd)?
|
||||
.as_socket()
|
||||
.ok_or(Error::with_message(
|
||||
Errno::ENOTSOCK,
|
||||
"the file is not socket",
|
||||
))?;
|
||||
socket.shutdown(shutdown_cmd)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
104
services/libs/jinux-std/src/syscall/socket.rs
Normal file
104
services/libs/jinux-std/src/syscall/socket.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use crate::fs::file_handle::FileLike;
|
||||
use crate::net::socket::ip::DatagramSocket;
|
||||
use crate::net::socket::ip::StreamSocket;
|
||||
use crate::util::net::SaFamily;
|
||||
use crate::{log_syscall_entry, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_SOCKET;
|
||||
|
||||
pub fn sys_socket(domain: i32, type_: i32, protocol: i32) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SOCKET);
|
||||
let domain = SaFamily::try_from(domain)?;
|
||||
let sock_type = SockType::try_from(type_ & SOCK_TYPE_MASK)?;
|
||||
let sock_flags = SockFlags::from_bits_truncate(type_ & !SOCK_TYPE_MASK);
|
||||
let protocol = Protocol::try_from(protocol)?;
|
||||
debug!(
|
||||
"domain = {:?}, sock_type = {:?}, sock_flags = {:?}, protocol = {:?}",
|
||||
domain, sock_type, sock_flags, protocol
|
||||
);
|
||||
let file_like = match (domain, sock_type, protocol) {
|
||||
(
|
||||
SaFamily::AF_INET,
|
||||
SockType::SOCK_STREAM,
|
||||
Protocol::IPPROTO_IP | Protocol::IPPROTO_TCP,
|
||||
) => Arc::new(StreamSocket::new()) as Arc<dyn FileLike>,
|
||||
(SaFamily::AF_INET, SockType::SOCK_DGRAM, Protocol::IPPROTO_IP | Protocol::IPPROTO_UDP) => {
|
||||
Arc::new(DatagramSocket::new()) as Arc<dyn FileLike>
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EAFNOSUPPORT, "unsupported domain"),
|
||||
};
|
||||
let fd = {
|
||||
let current = current!();
|
||||
let mut file_table = current.file_table().lock();
|
||||
file_table.insert(file_like)
|
||||
};
|
||||
Ok(SyscallReturn::Return(fd as _))
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, TryFromInt)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Standard well-defined IP protocols.
|
||||
/// From https://elixir.bootlin.com/linux/v6.0.9/source/include/uapi/linux/in.h.
|
||||
enum Protocol {
|
||||
IPPROTO_IP = 0, /* Dummy protocol for TCP */
|
||||
IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
|
||||
IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
|
||||
IPPROTO_TCP = 6, /* Transmission Control Protocol */
|
||||
IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
|
||||
IPPROTO_PUP = 12, /* PUP protocol */
|
||||
IPPROTO_UDP = 17, /* User Datagram Protocol */
|
||||
IPPROTO_IDP = 22, /* XNS IDP protocol */
|
||||
IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */
|
||||
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
|
||||
IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
|
||||
IPPROTO_RSVP = 46, /* RSVP Protocol */
|
||||
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
|
||||
IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
|
||||
IPPROTO_AH = 51, /* Authentication Header protocol */
|
||||
IPPROTO_MTP = 92, /* Multicast Transport Protocol */
|
||||
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */
|
||||
IPPROTO_ENCAP = 98, /* Encapsulation Header */
|
||||
IPPROTO_PIM = 103, /* Protocol Independent Multicast */
|
||||
IPPROTO_COMP = 108, /* Compression Header Protocol */
|
||||
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
|
||||
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
|
||||
IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */
|
||||
IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation */
|
||||
IPPROTO_RAW = 255, /* Raw IP packets */
|
||||
IPPROTO_MPTCP = 262, /* Multipath TCP connection */
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Clone, Copy, TryFromInt)]
|
||||
/// Socket types.
|
||||
/// From https://elixir.bootlin.com/linux/v6.0.9/source/include/linux/net.h
|
||||
enum SockType {
|
||||
/// Stream socket
|
||||
SOCK_STREAM = 1,
|
||||
/// Datagram socket
|
||||
SOCK_DGRAM = 2,
|
||||
/// Raw socket
|
||||
SOCK_RAW = 3,
|
||||
/// Reliably-delivered message
|
||||
SOCK_RDM = 4,
|
||||
/// Sequential packet socket
|
||||
SOCK_SEQPACKET = 5,
|
||||
/// Datagram Congestion Control Protocol socket
|
||||
SOCK_DCCP = 6,
|
||||
/// Linux specific way of getting packets at the dev level
|
||||
SOCK_PACKET = 10,
|
||||
}
|
||||
|
||||
const SOCK_TYPE_MASK: i32 = 0xf;
|
||||
|
||||
bitflags! {
|
||||
#[repr(C)]
|
||||
#[derive(Pod)]
|
||||
struct SockFlags: i32 {
|
||||
const SOCK_NONBLOCK = 1 << 11;
|
||||
const SOCK_CLOEXEC = 1 << 19;
|
||||
}
|
||||
}
|
213
services/libs/jinux-std/src/util/net.rs
Normal file
213
services/libs/jinux-std/src/util/net.rs
Normal file
@ -0,0 +1,213 @@
|
||||
use crate::net::iface::Ipv4Address;
|
||||
use crate::net::socket::SocketAddr;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! get_socket_without_holding_filetable_lock {
|
||||
($name:tt, $current: expr, $sockfd: expr) => {
|
||||
let file_like = {
|
||||
let file_table = $current.file_table().lock();
|
||||
file_table.get_file($sockfd)?.clone()
|
||||
// Drop filetable here to avoid locking
|
||||
};
|
||||
let $name = file_like
|
||||
.as_socket()
|
||||
.ok_or_else(|| Error::with_message(Errno::ENOTSOCK, "the file is not socket"))?;
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
/// PlaceHolder
|
||||
pub struct SockAddr {
|
||||
sa_family: u16, // SaFamily
|
||||
sa_data: [u8; 14],
|
||||
}
|
||||
|
||||
impl SockAddr {
|
||||
pub fn sa_family(&self) -> Result<SaFamily> {
|
||||
Ok(SaFamily::try_from(self.sa_family as i32)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
pub struct SockAddrUn {
|
||||
sun_family: u16, // Always SaFamily::AF_UNIX
|
||||
sun_path: [u8; 108],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
/// IPv4 4-byte address
|
||||
pub struct InAddr {
|
||||
s_addr: [u8; 4],
|
||||
}
|
||||
|
||||
impl InAddr {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.s_addr
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Self {
|
||||
debug_assert!(bytes.len() == 4);
|
||||
let mut s_addr = [0u8; 4];
|
||||
s_addr.copy_from_slice(bytes);
|
||||
Self { s_addr }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct PortNum {
|
||||
port: [u8; 2],
|
||||
}
|
||||
|
||||
impl PortNum {
|
||||
pub fn as_u16(&self) -> u16 {
|
||||
u16::from_be_bytes(self.port)
|
||||
}
|
||||
|
||||
pub fn from_u16(value: u16) -> Self {
|
||||
let bytes = value.to_be_bytes();
|
||||
Self { port: bytes }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
/// IPv4 socket address
|
||||
pub struct SockAddrIn {
|
||||
/// always SaFamily::AF_INET
|
||||
sin_family: u16,
|
||||
/// Port number
|
||||
sin_port_t: PortNum,
|
||||
/// IPv4 address
|
||||
sin_addr: InAddr,
|
||||
/// Pad to size of 'SockAddr' structure (16 bytes)
|
||||
_pad: [u8; 8],
|
||||
}
|
||||
|
||||
impl SockAddrIn {
|
||||
pub fn new(port: u16, addr: InAddr) -> Self {
|
||||
let port = PortNum::from_u16(port);
|
||||
Self {
|
||||
sin_family: SaFamily::AF_INET as _,
|
||||
sin_port_t: port,
|
||||
sin_addr: addr,
|
||||
_pad: [0u8; 8],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
/// IPv6 address
|
||||
pub struct In6Addr {
|
||||
s6_addr: [u8; 16],
|
||||
}
|
||||
|
||||
impl In6Addr {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.s6_addr
|
||||
}
|
||||
}
|
||||
|
||||
/// IPv6 socket address
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
pub struct SockAddrIn6 {
|
||||
/// always SaFamily::AF_INET6
|
||||
sin6_family: u16,
|
||||
/// Port number
|
||||
sin6_port: PortNum,
|
||||
/// IPv6 flow information
|
||||
sin6_flowinfo: u32,
|
||||
/// IPv6 address
|
||||
sin6_addr: In6Addr,
|
||||
// Scope ID
|
||||
sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
/// Address family. The definition is from https://elixir.bootlin.com/linux/v6.0.9/source/include/linux/socket.h.
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, TryFromInt)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum SaFamily {
|
||||
AF_UNSPEC = 0,
|
||||
AF_UNIX = 1, /* Unix domain sockets */
|
||||
//AF_LOCAL 1 /* POSIX name for AF_UNIX */
|
||||
AF_INET = 2, /* Internet IP Protocol */
|
||||
AF_AX25 = 3, /* Amateur Radio AX.25 */
|
||||
AF_IPX = 4, /* Novell IPX */
|
||||
AF_APPLETALK = 5, /* AppleTalk DDP */
|
||||
AF_NETROM = 6, /* Amateur Radio NET/ROM */
|
||||
AF_BRIDGE = 7, /* Multiprotocol bridge */
|
||||
AF_ATMPVC = 8, /* ATM PVCs */
|
||||
AF_X25 = 9, /* Reserved for X.25 project */
|
||||
AF_INET6 = 10, /* IP version 6 */
|
||||
AF_ROSE = 11, /* Amateur Radio X.25 PLP */
|
||||
AF_DECnet = 12, /* Reserved for DECnet project */
|
||||
AF_NETBEUI = 13, /* Reserved for 802.2LLC project*/
|
||||
AF_SECURITY = 14, /* Security callback pseudo AF */
|
||||
AF_KEY = 15, /* PF_KEY key management API */
|
||||
AF_NETLINK = 16,
|
||||
//AF_ROUTE = AF_NETLINK /* Alias to emulate 4.4BSD */
|
||||
AF_PACKET = 17, /* Packet family */
|
||||
AF_ASH = 18, /* Ash */
|
||||
AF_ECONET = 19, /* Acorn Econet */
|
||||
AF_ATMSVC = 20, /* ATM SVCs */
|
||||
AF_RDS = 21, /* RDS sockets */
|
||||
AF_SNA = 22, /* Linux SNA Project (nutters!) */
|
||||
AF_IRDA = 23, /* IRDA sockets */
|
||||
AF_PPPOX = 24, /* PPPoX sockets */
|
||||
AF_WANPIPE = 25, /* Wanpipe API Sockets */
|
||||
AF_LLC = 26, /* Linux LLC */
|
||||
AF_IB = 27, /* Native InfiniBand address */
|
||||
AF_MPLS = 28, /* MPLS */
|
||||
AF_CAN = 29, /* Controller Area Network */
|
||||
AF_TIPC = 30, /* TIPC sockets */
|
||||
AF_BLUETOOTH = 31, /* Bluetooth sockets */
|
||||
AF_IUCV = 32, /* IUCV sockets */
|
||||
AF_RXRPC = 33, /* RxRPC sockets */
|
||||
AF_ISDN = 34, /* mISDN sockets */
|
||||
AF_PHONET = 35, /* Phonet sockets */
|
||||
AF_IEEE802154 = 36, /* IEEE802154 sockets */
|
||||
AF_CAIF = 37, /* CAIF sockets */
|
||||
AF_ALG = 38, /* Algorithm sockets */
|
||||
AF_NFC = 39, /* NFC sockets */
|
||||
AF_VSOCK = 40, /* vSockets */
|
||||
AF_KCM = 41, /* Kernel Connection Multiplexor*/
|
||||
AF_QIPCRTR = 42, /* Qualcomm IPC Router */
|
||||
AF_SMC = 43, /* smc sockets: reserve number for
|
||||
* PF_SMC protocol family that
|
||||
* reuses AF_INET address family
|
||||
*/
|
||||
AF_XDP = 44, /* XDP sockets */
|
||||
AF_MCTP = 45, /* Management component
|
||||
* transport protocol
|
||||
*/
|
||||
AF_MAX = 46, /* For now.. */
|
||||
}
|
||||
|
||||
impl From<InAddr> for Ipv4Address {
|
||||
fn from(value: InAddr) -> Self {
|
||||
let addr = value.as_bytes();
|
||||
Ipv4Address::from_bytes(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv4Address> for InAddr {
|
||||
fn from(value: Ipv4Address) -> Self {
|
||||
let bytes = value.as_bytes();
|
||||
InAddr::from_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SockAddrIn> for SocketAddr {
|
||||
fn from(value: SockAddrIn) -> Self {
|
||||
let port = value.sin_port_t.as_u16();
|
||||
let addr = Ipv4Address::from(value.sin_addr);
|
||||
SocketAddr::IPv4(addr, port)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user