diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index 661cfb6..05735c1 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -3,7 +3,7 @@ use alloc::sync::Arc; use alloc::vec::Vec; use lazy_static::lazy_static; -use smoltcp::wire::{EthernetAddress, IpAddress, Ipv4Address}; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}; use spin::RwLock; use crate::sync::Condvar; @@ -56,6 +56,11 @@ pub trait Driver: Send + Sync { unimplemented!("not a net driver") } + // get ip addresses + fn get_ip_addresses(&self) -> Vec { + unimplemented!("not a net driver") + } + // get ipv4 address fn ipv4_address(&self) -> Option { unimplemented!("not a net driver") diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index 0dbcb0b..24e34aa 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -73,6 +73,11 @@ impl Driver for E1000Interface { self.name.clone() } + // get ip addresses + fn get_ip_addresses(&self) -> Vec { + Vec::from(self.iface.lock().ip_addrs()) + } + fn ipv4_address(&self) -> Option { self.iface.lock().ipv4_address() } diff --git a/kernel/src/drivers/net/ixgbe.rs b/kernel/src/drivers/net/ixgbe.rs index 2d3816e..115a0bd 100644 --- a/kernel/src/drivers/net/ixgbe.rs +++ b/kernel/src/drivers/net/ixgbe.rs @@ -82,6 +82,11 @@ impl Driver for IXGBEInterface { self.ifname.clone() } + // get ip addresses + fn get_ip_addresses(&self) -> Vec { + Vec::from(self.iface.lock().ip_addrs()) + } + fn ipv4_address(&self) -> Option { self.iface.lock().ipv4_address() } diff --git a/kernel/src/net/structs.rs b/kernel/src/net/structs.rs index 6da97f7..7dcb754 100644 --- a/kernel/src/net/structs.rs +++ b/kernel/src/net/structs.rs @@ -745,7 +745,7 @@ impl Socket for PacketSocketState { } /// Common structure: -/// | nlmsghdr | ifinfomsg | rtattr | rtattr | rtattr | ... | rtattr +/// | nlmsghdr | ifinfomsg/ifaddrmsg | rtattr | rtattr | rtattr | ... | rtattr /// All aligned to 4 bytes boundary #[repr(C)] @@ -768,6 +768,16 @@ struct IfaceInfoMsg { ifi_change: u32, } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct IfaceAddrMsg { + ifa_family: u8, + ifa_prefixlen: u8, + ifa_flags: u8, + ifa_scope: u8, + ifa_index: u32, +} + #[repr(C)] #[derive(Debug, Copy, Clone)] struct RouteAttr { @@ -982,22 +992,70 @@ impl Socket for NetlinkSocketState { buffer.push(msg); } + } + NetlinkMessageType::GetAddr => { + let ifaces = NET_DRIVERS.read(); + for i in 0..ifaces.len() { + let ip_addrs = ifaces[i].get_ip_addresses(); + for j in 0..ip_addrs.len() { + let mut msg = Vec::new(); + let mut new_header = NetlinkMessageHeader { + nlmsg_len: 0, // to be determined later + nlmsg_type: NetlinkMessageType::NewAddr.into(), + nlmsg_flags: NetlinkMessageFlags::MULTI, + nlmsg_seq: header.nlmsg_seq, + nlmsg_pid: header.nlmsg_pid, + }; + msg.push_ext(new_header); + + let family: u16 = AddressFamily::Internet.into(); + let if_addr = IfaceAddrMsg { + ifa_family: family as u8, + ifa_prefixlen: ip_addrs[j].prefix_len(), + ifa_flags: 0, + ifa_scope: 0, + ifa_index: i as u32, + }; + msg.align4(); + msg.push_ext(if_addr); + + let mut attrs = Vec::new(); + + let ip_addr = ip_addrs[j].address(); + let attr = RouteAttr { + rta_len: (ip_addr.as_bytes().len() + size_of::()) as u16, + rta_type: RouteAttrTypes::Address.into(), + }; + attrs.align4(); + attrs.push_ext(attr); + for byte in ip_addr.as_bytes() { + attrs.push(*byte); + } - let mut msg = Vec::new(); - let mut new_header = NetlinkMessageHeader { - nlmsg_len: 0, // to be determined later - nlmsg_type: NetlinkMessageType::Done.into(), - nlmsg_flags: NetlinkMessageFlags::MULTI, - nlmsg_seq: header.nlmsg_seq, - nlmsg_pid: header.nlmsg_pid, - }; - msg.push_ext(new_header); - msg.align4(); - msg.set_ext(0, msg.len() as u32); - buffer.push(msg); + msg.align4(); + msg.append(&mut attrs); + + msg.align4(); + msg.set_ext(0, msg.len() as u32); + + buffer.push(msg); + } + } } _ => {} } + let mut msg = Vec::new(); + let mut new_header = NetlinkMessageHeader { + nlmsg_len: 0, // to be determined later + nlmsg_type: NetlinkMessageType::Done.into(), + nlmsg_flags: NetlinkMessageFlags::MULTI, + nlmsg_seq: header.nlmsg_seq, + nlmsg_pid: header.nlmsg_pid, + }; + msg.push_ext(new_header); + msg.align4(); + msg.set_ext(0, msg.len() as u32); + buffer.push(msg); Ok(data.len()) } diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index b771422..1372340 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -193,7 +193,7 @@ pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult { sockaddr_in.write_to(&mut proc, hdr.msg_name, &mut hdr.msg_namelen as *mut u32)?; } } - unimplemented!() + result } pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult { @@ -302,9 +302,9 @@ impl Process { } } -// cancel alignment -#[repr(packed)] +#[repr(C)] pub struct SockAddrIn { + pub sin_family: u16, pub sin_port: u16, pub sin_addr: u32, pub sin_zero: [u8; 8], @@ -312,12 +312,13 @@ pub struct SockAddrIn { #[repr(C)] pub struct SockAddrUn { + pub sun_family: u16, pub sun_path: [u8; 108], } -// beware of alignment issue -#[repr(C, packed)] +#[repr(C)] pub struct SockAddrLl { + pub sll_family: u16, pub sll_protocol: u16, pub sll_ifindex: u32, pub sll_hatype: u16, @@ -326,26 +327,22 @@ pub struct SockAddrLl { pub sll_addr: [u8; 8], } -// cancel alignment -#[repr(packed)] +#[repr(C)] pub struct SockAddrNl { + nl_family: u16, nl_pad: u16, nl_pid: u32, nl_groups: u32, } #[repr(C)] -pub union SockAddrPayload { +pub union SockAddr { + pub family: u16, pub addr_in: SockAddrIn, pub addr_un: SockAddrUn, pub addr_ll: SockAddrLl, pub addr_nl: SockAddrNl, -} - -#[repr(C)] -pub struct SockAddr { - pub family: u16, - pub payload: SockAddrPayload, + pub addr_ph: SockAddrPlaceholder, } #[repr(C)] @@ -359,17 +356,42 @@ impl From for SockAddr { if let Endpoint::Ip(ip) = endpoint { match ip.addr { IpAddress::Ipv4(ipv4) => SockAddr { - family: AddressFamily::Internet.into(), - payload: SockAddrPayload { - addr_in: SockAddrIn { - sin_port: u16::to_be(ip.port), - sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)), - sin_zero: [0; 8], - }, + addr_in: SockAddrIn { + sin_family: AddressFamily::Internet.into(), + sin_port: u16::to_be(ip.port), + sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)), + sin_zero: [0; 8], + }, + }, + IpAddress::Unspecified => SockAddr { + addr_ph: SockAddrPlaceholder { + family: AddressFamily::Unspecified.into(), + data: [0; 14], }, }, _ => unimplemented!("only ipv4"), } + } else if let Endpoint::LinkLevel(link_level) = endpoint { + SockAddr { + addr_ll: SockAddrLl { + sll_family: AddressFamily::Packet.into(), + sll_protocol: 0, + sll_ifindex: link_level.interface_index as u32, + sll_hatype: 0, + sll_pkttype: 0, + sll_halen: 0, + sll_addr: [0; 8], + }, + } + } else if let Endpoint::Netlink(netlink) = endpoint { + SockAddr { + addr_nl: SockAddrNl { + nl_family: AddressFamily::Netlink.into(), + nl_pad: 0, + nl_pid: netlink.port_id, + nl_groups: netlink.multicast_groups_mask, + }, + } } else { unimplemented!("only ip"); } @@ -390,31 +412,31 @@ fn sockaddr_to_endpoint( unsafe { match AddressFamily::from((*addr).family) { AddressFamily::Internet => { - if len < size_of::() + size_of::() { + if len < size_of::() { return Err(SysError::EINVAL); } - let port = u16::from_be((*addr).payload.addr_in.sin_port); + let port = u16::from_be((*addr).addr_in.sin_port); let addr = IpAddress::from(Ipv4Address::from_bytes( - &u32::from_be((*addr).payload.addr_in.sin_addr).to_be_bytes()[..], + &u32::from_be((*addr).addr_in.sin_addr).to_be_bytes()[..], )); Ok(Endpoint::Ip((addr, port).into())) } AddressFamily::Unix => Err(SysError::EINVAL), AddressFamily::Packet => { - if len < size_of::() + size_of::() { + if len < size_of::() { return Err(SysError::EINVAL); } Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( - (*addr).payload.addr_ll.sll_ifindex as usize, + (*addr).addr_ll.sll_ifindex as usize, ))) } AddressFamily::Netlink => { - if len < size_of::() + size_of::() { + if len < size_of::() { return Err(SysError::EINVAL); } Ok(Endpoint::Netlink(NetlinkEndpoint::new( - (*addr).payload.addr_nl.nl_pid, - (*addr).payload.addr_nl.nl_groups, + (*addr).addr_nl.nl_pid, + (*addr).addr_nl.nl_groups, ))) } _ => Err(SysError::EINVAL), @@ -439,7 +461,9 @@ impl SockAddr { proc.vm.check_write_ptr(addr_len)?; let max_addr_len = *addr_len as usize; let full_len = match AddressFamily::from(self.family) { - AddressFamily::Internet => size_of::() + size_of::(), + AddressFamily::Internet => size_of::(), + AddressFamily::Packet => size_of::(), + AddressFamily::Netlink => size_of::(), AddressFamily::Unix => return Err(SysError::EINVAL), _ => return Err(SysError::EINVAL), };