pub mod af_netlink; pub mod callback; pub mod endpoint; pub mod netlink_proto; pub mod skbuff; pub mod sock; use super::{family, inet::datagram, Inode, Socket, Type}; use crate::driver::base::uevent::KobjUeventEnv; use alloc::sync::Arc; use alloc::{boxed::Box, slice, vec::Vec}; use system_error::SystemError; // https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/ use crate::libs::mutex::Mutex; use core::mem; use af_netlink::{netlink_insert, Listeners, NetlinkFlags, NetlinkSock, NetlinkSocket, NL_TABLE}; // 监听事件类型 pub const NETLINK_ADD_MEMBERSHIP: usize = 1; pub const NETLINK_DROP_MEMBERSHIP: usize = 2; pub const NETLINK_PKTINFO: usize = 3; // 接收包信息。如果设置了这个选项,套接字将接收包含发送者信息(如发送者的端口号和地址)的消息 // Netlink protocol family pub const NETLINK_ROUTE: usize = 0; pub const NETLINK_UNUSED: usize = 1; pub const NETLINK_USERSOCK: usize = 2; pub const NETLINK_FIREWALL: usize = 3; pub const NETLINK_SOCK_DIAG: usize = 4; pub const NETLINK_NFLOG: usize = 5; pub const NETLINK_XFRM: usize = 6; pub const NETLINK_SELINUX: usize = 7; pub const NETLINK_ISCSI: usize = 8; pub const NETLINK_AUDIT: usize = 9; pub const NETLINK_FIB_LOOKUP: usize = 10; pub const NETLINK_CONNECTOR: usize = 11; pub const NETLINK_NETFILTER: usize = 12; pub const NETLINK_IP6_FW: usize = 13; pub const NETLINK_DNRTMSG: usize = 14; // implemente uevent needed pub const NETLINK_KOBJECT_UEVENT: usize = 15; pub const NETLINK_GENERIC: usize = 16; // pub const NETLINK_DM : usize = 17; // Assuming DM Events is unused, not defined pub const NETLINK_SCSITRANSPORT: usize = 18; pub const NETLINK_ECRYPTFS: usize = 19; pub const NETLINK_RDMA: usize = 20; pub const NETLINK_CRYPTO: usize = 21; pub const NETLINK_SMC: usize = 22; //pub const NETLINK_INET_DIAG = NETLINK_SOCK_DIAG; pub const NETLINK_INET_DIAG: usize = 4; pub const MAX_LINKS: usize = 32; pub const NL_CFG_F_NONROOT_RECV: u32 = 1 << 0; pub const NL_CFG_F_NONROOT_SEND: u32 = 1 << 1; bitflags! { /// 四种通用的消息类型 nlmsg_type pub struct NLmsgType: u8 { /* Nothing. */ const NLMSG_NOOP = 0x1; /* Error */ const NLMSG_ERROR = 0x2; /* End of a dump */ const NLMSG_DONE = 0x3; /* Data lost */ const NLMSG_OVERRUN = 0x4; } //消息标记 nlmsg_flags // const NLM_F_REQUEST = 1; /* It is request message. */ // const NLM_F_MULTI = 2; /* Multipart message, terminated by NLMSG_DONE */ // const NLM_F_ACK = 4; /* Reply with ack, with zero or error code */ // const NLM_F_ECHO = 8; /* Echo this request */ // const NLM_F_DUMP_INTR = 16; /* Dump was inconsistent due to sequence change */ pub struct NLmsgFlags: u16 { /* Flags values */ const NLM_F_REQUEST = 0x01; const NLM_F_MULTI = 0x02; const NLM_F_ACK = 0x04; const NLM_F_ECHO = 0x08; const NLM_F_DUMP_INTR = 0x10; const NLM_F_DUMP_FILTERED = 0x20; /* Modifiers to GET request */ const NLM_F_ROOT = 0x100; /* specify tree root */ const NLM_F_MATCH = 0x200; /* return all matching */ const NLM_F_ATOMIC = 0x400; /* atomic GET */ //const NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH; const NLM_F_DUMP = 0x100 | 0x200; /* Modifiers to NEW request */ const NLM_F_REPLACE = 0x100; /* Override existing */ const NLM_F_EXCL = 0x200; /* Do not touch, if it exists */ const NLM_F_CREATE = 0x400; /* Create, if it does not exist */ const NLM_F_APPEND = 0x800; /* Add to end of list */ /* Modifiers to DELETE request */ const NLM_F_NONREC = 0x100; /* Do not delete recursively */ /* Flags for ACK message */ const NLM_F_CAPPED = 0x100; /* request was capped */ const NLM_F_ACK_TLVS = 0x200; /* extended ACK TVLs were included */ } } // 定义Netlink消息的结构体,如NLmsghdr和geNLmsghdr(拓展的netlink消息头),以及用于封包和解包消息的函数。 // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/netlink.h /// netlink消息报头 /** * struct NLmsghdr - fixed format metadata header of Netlink messages * @nlmsg_len: Length of message including header * @nlmsg_type: Message content type * @nlmsg_flags: Additional flags * @nlmsg_seq: Sequence number * @nlmsg_pid: Sending process port ID */ pub struct NLmsghdr { pub nlmsg_len: usize, pub nlmsg_type: NLmsgType, pub nlmsg_flags: NLmsgFlags, pub nlmsg_seq: u32, pub nlmsg_pid: u32, } const NLMSG_ALIGNTO: usize = 4; #[derive(Debug, PartialEq, Copy, Clone)] pub enum NetlinkState { NetlinkUnconnected = 0, NetlinkConnected, NETLINK_S_CONGESTED = 2, } fn nlmsg_align(len: usize) -> usize { (len + NLMSG_ALIGNTO - 1) & !(NLMSG_ALIGNTO - 1) } fn nlmsg_hdrlen() -> usize { nlmsg_align(mem::size_of::()) } fn nlmsg_length(len: usize) -> usize { len + nlmsg_hdrlen() } fn nlmsg_space(len: usize) -> usize { nlmsg_align(nlmsg_length(len)) } unsafe fn nlmsg_data(nlh: &NLmsghdr) -> *mut u8 { ((nlh as *const NLmsghdr) as *mut u8).add(nlmsg_length(0)) } unsafe fn nlmsg_next(nlh: *mut NLmsghdr, len: usize) -> *mut NLmsghdr { let nlmsg_len = (*nlh).nlmsg_len; let new_len = len - nlmsg_align(nlmsg_len); nlh.add(nlmsg_align(nlmsg_len)) } fn nlmsg_ok(nlh: &NLmsghdr, len: usize) -> bool { len >= nlmsg_hdrlen() && nlh.nlmsg_len >= nlmsg_hdrlen() && nlh.nlmsg_len <= len } fn nlmsg_payload(nlh: &NLmsghdr, len: usize) -> usize { nlh.nlmsg_len - nlmsg_space(len) } // 定义类型别名来简化闭包类型的定义 type InputCallback = Arc; type BindCallback = Arc i32 + Send + Sync>; type UnbindCallback = Arc i32 + Send + Sync>; type CompareCallback = Arc bool + Send + Sync>; /// 该结构包含了内核netlink的可选参数: #[derive(Default)] pub struct NetlinkKernelCfg { pub groups: u32, pub flags: u32, pub input: Option, pub bind: Option, pub unbind: Option, pub compare: Option, } impl NetlinkKernelCfg { pub fn new() -> Self { NetlinkKernelCfg { groups: 32, flags: 0, input: None, bind: None, unbind: None, compare: None, } } pub fn set_input(&mut self, callback: F) where F: FnMut() + Send + Sync + 'static, { self.input = Some(Arc::new(callback)); } pub fn set_bind(&mut self, callback: F) where F: Fn(i32) -> i32 + Send + Sync + 'static, { self.bind = Some(Arc::new(callback)); } pub fn set_unbind(&mut self, callback: F) where F: Fn(i32) -> i32 + Send + Sync + 'static, { self.unbind = Some(Arc::new(callback)); } pub fn set_compare(&mut self, callback: F) where F: Fn(&NetlinkSock) -> bool + Send + Sync + 'static, { self.compare = Some(Arc::new(callback)); } } // https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/netlink.h#229 // netlink属性头 struct NLattr { nla_len: u16, nla_type: u16, } pub trait VecExt { fn align4(&mut self); fn push_ext(&mut self, data: T); fn set_ext(&mut self, offset: usize, data: T); } impl VecExt for Vec { fn align4(&mut self) { let len = (self.len() + 3) & !3; if len > self.len() { self.resize(len, 0); } } fn push_ext(&mut self, data: T) { #[allow(unsafe_code)] let bytes = unsafe { slice::from_raw_parts(&data as *const T as *const u8, size_of::()) }; for byte in bytes { self.push(*byte); } } fn set_ext(&mut self, offset: usize, data: T) { if self.len() < offset + size_of::() { self.resize(offset + size_of::(), 0); } #[allow(unsafe_code)] let bytes = unsafe { slice::from_raw_parts(&data as *const T as *const u8, size_of::()) }; self[offset..(bytes.len() + offset)].copy_from_slice(bytes); } } // todo: net namespace pub fn netlink_kernel_create( unit: usize, cfg: Option, ) -> Result { // THIS_MODULE let mut nlk: NetlinkSock = NetlinkSock::new(); let sk: Arc>> = Arc::new(Mutex::new(Box::new(nlk.clone()))); let groups: u32; if unit >= MAX_LINKS { return Err(SystemError::EINVAL); } __netlink_create(&mut nlk, unit, 1).expect("__netlink_create failed"); if let Some(cfg) = cfg.as_ref() { if cfg.groups < 32 { groups = 32; } else { groups = cfg.groups; } } else { groups = 32; } let listeners = Listeners::new(); // todo:设计和实现回调函数 // sk.sk_data_read = netlink_data_ready; // if cfg.is_some() && cfg.unwrap().input.is_some(){ // nlk.netlink_rcv = cfg.unwrap().input; // } netlink_insert(sk, 0).expect("netlink_insert failed"); nlk.flags |= NetlinkFlags::NETLINK_F_KERNEL_SOCKET.bits(); let mut nl_table = NL_TABLE.write(); if nl_table[unit].get_registered() == 0 { nl_table[unit].set_groups(groups); if let Some(cfg) = cfg.as_ref() { nl_table[unit].bind = cfg.bind.clone(); nl_table[unit].unbind = cfg.unbind.clone(); nl_table[unit].set_flags(cfg.flags); if cfg.compare.is_some() { nl_table[unit].compare = cfg.compare.clone(); } nl_table[unit].set_registered(1); } else { drop(listeners); let registered = nl_table[unit].get_registered(); nl_table[unit].set_registered(registered + 1); } } return Ok(nlk); } fn __netlink_create(nlk: &mut NetlinkSock, unit: usize, kern: usize) -> Result { // 其他的初始化配置参数 nlk.flags = kern as u32; nlk.protocol = unit; return Ok(0); } pub fn sk_data_ready(nlk: Arc) -> Result<(), SystemError> { // 唤醒 return Ok(()); } pub struct Netlink; impl family::Family for Netlink { /// 用户空间创建一个新的套接字的入口 fn socket(stype: Type, _protocol: u32) -> Result, SystemError> { let socket = create_netlink_socket(_protocol)?; Ok(Inode::new(socket)) } } /// 用户空间创建一个新的Netlink套接字 fn create_netlink_socket(_protocol: u32) -> Result, SystemError> { match _protocol as usize { NETLINK_KOBJECT_UEVENT => Ok(Arc::new(af_netlink::NetlinkSock::new())), _ => Err(SystemError::EPROTONOSUPPORT), } }