implement getaddr for netlink, ip l/ip a is working now

master
Jiajie Chen 6 years ago
parent a7a8c3aa92
commit 2c3a4d75dd

@ -3,7 +3,7 @@ use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use smoltcp::wire::{EthernetAddress, IpAddress, Ipv4Address}; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use spin::RwLock; use spin::RwLock;
use crate::sync::Condvar; use crate::sync::Condvar;
@ -56,6 +56,11 @@ pub trait Driver: Send + Sync {
unimplemented!("not a net driver") unimplemented!("not a net driver")
} }
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!("not a net driver")
}
// get ipv4 address // get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address> { fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver") unimplemented!("not a net driver")

@ -73,6 +73,11 @@ impl Driver for E1000Interface {
self.name.clone() self.name.clone()
} }
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn ipv4_address(&self) -> Option<Ipv4Address> { fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address() self.iface.lock().ipv4_address()
} }

@ -82,6 +82,11 @@ impl Driver for IXGBEInterface {
self.ifname.clone() self.ifname.clone()
} }
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn ipv4_address(&self) -> Option<Ipv4Address> { fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address() self.iface.lock().ipv4_address()
} }

@ -745,7 +745,7 @@ impl Socket for PacketSocketState {
} }
/// Common structure: /// Common structure:
/// | nlmsghdr | ifinfomsg | rtattr | rtattr | rtattr | ... | rtattr /// | nlmsghdr | ifinfomsg/ifaddrmsg | rtattr | rtattr | rtattr | ... | rtattr
/// All aligned to 4 bytes boundary /// All aligned to 4 bytes boundary
#[repr(C)] #[repr(C)]
@ -768,6 +768,16 @@ struct IfaceInfoMsg {
ifi_change: u32, 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)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
struct RouteAttr { struct RouteAttr {
@ -982,22 +992,70 @@ impl Socket for NetlinkSocketState {
buffer.push(msg); 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 msg = Vec::new();
let mut new_header = NetlinkMessageHeader { let mut new_header = NetlinkMessageHeader {
nlmsg_len: 0, // to be determined later nlmsg_len: 0, // to be determined later
nlmsg_type: NetlinkMessageType::Done.into(), nlmsg_type: NetlinkMessageType::NewAddr.into(),
nlmsg_flags: NetlinkMessageFlags::MULTI, nlmsg_flags: NetlinkMessageFlags::MULTI,
nlmsg_seq: header.nlmsg_seq, nlmsg_seq: header.nlmsg_seq,
nlmsg_pid: header.nlmsg_pid, nlmsg_pid: header.nlmsg_pid,
}; };
msg.push_ext(new_header); 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::<RouteAttr>()) as u16,
rta_type: RouteAttrTypes::Address.into(),
};
attrs.align4();
attrs.push_ext(attr);
for byte in ip_addr.as_bytes() {
attrs.push(*byte);
}
msg.align4();
msg.append(&mut attrs);
msg.align4(); msg.align4();
msg.set_ext(0, msg.len() as u32); msg.set_ext(0, msg.len() as u32);
buffer.push(msg); 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()) Ok(data.len())
} }

@ -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)?; 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 { pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
@ -302,9 +302,9 @@ impl Process {
} }
} }
// cancel alignment #[repr(C)]
#[repr(packed)]
pub struct SockAddrIn { pub struct SockAddrIn {
pub sin_family: u16,
pub sin_port: u16, pub sin_port: u16,
pub sin_addr: u32, pub sin_addr: u32,
pub sin_zero: [u8; 8], pub sin_zero: [u8; 8],
@ -312,12 +312,13 @@ pub struct SockAddrIn {
#[repr(C)] #[repr(C)]
pub struct SockAddrUn { pub struct SockAddrUn {
pub sun_family: u16,
pub sun_path: [u8; 108], pub sun_path: [u8; 108],
} }
// beware of alignment issue #[repr(C)]
#[repr(C, packed)]
pub struct SockAddrLl { pub struct SockAddrLl {
pub sll_family: u16,
pub sll_protocol: u16, pub sll_protocol: u16,
pub sll_ifindex: u32, pub sll_ifindex: u32,
pub sll_hatype: u16, pub sll_hatype: u16,
@ -326,26 +327,22 @@ pub struct SockAddrLl {
pub sll_addr: [u8; 8], pub sll_addr: [u8; 8],
} }
// cancel alignment #[repr(C)]
#[repr(packed)]
pub struct SockAddrNl { pub struct SockAddrNl {
nl_family: u16,
nl_pad: u16, nl_pad: u16,
nl_pid: u32, nl_pid: u32,
nl_groups: u32, nl_groups: u32,
} }
#[repr(C)] #[repr(C)]
pub union SockAddrPayload { pub union SockAddr {
pub family: u16,
pub addr_in: SockAddrIn, pub addr_in: SockAddrIn,
pub addr_un: SockAddrUn, pub addr_un: SockAddrUn,
pub addr_ll: SockAddrLl, pub addr_ll: SockAddrLl,
pub addr_nl: SockAddrNl, pub addr_nl: SockAddrNl,
} pub addr_ph: SockAddrPlaceholder,
#[repr(C)]
pub struct SockAddr {
pub family: u16,
pub payload: SockAddrPayload,
} }
#[repr(C)] #[repr(C)]
@ -359,17 +356,42 @@ impl From<Endpoint> for SockAddr {
if let Endpoint::Ip(ip) = endpoint { if let Endpoint::Ip(ip) = endpoint {
match ip.addr { match ip.addr {
IpAddress::Ipv4(ipv4) => SockAddr { IpAddress::Ipv4(ipv4) => SockAddr {
family: AddressFamily::Internet.into(),
payload: SockAddrPayload {
addr_in: SockAddrIn { addr_in: SockAddrIn {
sin_family: AddressFamily::Internet.into(),
sin_port: u16::to_be(ip.port), sin_port: u16::to_be(ip.port),
sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)), sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)),
sin_zero: [0; 8], sin_zero: [0; 8],
}, },
}, },
IpAddress::Unspecified => SockAddr {
addr_ph: SockAddrPlaceholder {
family: AddressFamily::Unspecified.into(),
data: [0; 14],
},
}, },
_ => unimplemented!("only ipv4"), _ => 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 { } else {
unimplemented!("only ip"); unimplemented!("only ip");
} }
@ -390,31 +412,31 @@ fn sockaddr_to_endpoint(
unsafe { unsafe {
match AddressFamily::from((*addr).family) { match AddressFamily::from((*addr).family) {
AddressFamily::Internet => { AddressFamily::Internet => {
if len < size_of::<u16>() + size_of::<SockAddrIn>() { if len < size_of::<SockAddrIn>() {
return Err(SysError::EINVAL); 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( 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())) Ok(Endpoint::Ip((addr, port).into()))
} }
AddressFamily::Unix => Err(SysError::EINVAL), AddressFamily::Unix => Err(SysError::EINVAL),
AddressFamily::Packet => { AddressFamily::Packet => {
if len < size_of::<u16>() + size_of::<SockAddrLl>() { if len < size_of::<SockAddrLl>() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
(*addr).payload.addr_ll.sll_ifindex as usize, (*addr).addr_ll.sll_ifindex as usize,
))) )))
} }
AddressFamily::Netlink => { AddressFamily::Netlink => {
if len < size_of::<u16>() + size_of::<SockAddrNl>() { if len < size_of::<SockAddrNl>() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
Ok(Endpoint::Netlink(NetlinkEndpoint::new( Ok(Endpoint::Netlink(NetlinkEndpoint::new(
(*addr).payload.addr_nl.nl_pid, (*addr).addr_nl.nl_pid,
(*addr).payload.addr_nl.nl_groups, (*addr).addr_nl.nl_groups,
))) )))
} }
_ => Err(SysError::EINVAL), _ => Err(SysError::EINVAL),
@ -439,7 +461,9 @@ impl SockAddr {
proc.vm.check_write_ptr(addr_len)?; proc.vm.check_write_ptr(addr_len)?;
let max_addr_len = *addr_len as usize; let max_addr_len = *addr_len as usize;
let full_len = match AddressFamily::from(self.family) { let full_len = match AddressFamily::from(self.family) {
AddressFamily::Internet => size_of::<u16>() + size_of::<SockAddrIn>(), AddressFamily::Internet => size_of::<SockAddrIn>(),
AddressFamily::Packet => size_of::<SockAddrLl>(),
AddressFamily::Netlink => size_of::<SockAddrNl>(),
AddressFamily::Unix => return Err(SysError::EINVAL), AddressFamily::Unix => return Err(SysError::EINVAL),
_ => return Err(SysError::EINVAL), _ => return Err(SysError::EINVAL),
}; };

Loading…
Cancel
Save