From 1165d687ffade5113ced423ef8f96da772ff59a9 Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Mon, 1 May 2023 06:30:39 -0400 Subject: [PATCH] docs: added basic documentation to libnl --- nl-sys/src/netlink.rs | 14 +++++++++++++ nl-sys/src/nl_ffi.rs | 1 + nl-sys/src/route.rs | 47 ++++++++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/nl-sys/src/netlink.rs b/nl-sys/src/netlink.rs index 2fead51..4add910 100644 --- a/nl-sys/src/netlink.rs +++ b/nl-sys/src/netlink.rs @@ -19,11 +19,13 @@ use libc::{AF_UNSPEC, AF_INET}; use crate::{nl_ffi::*, error, route::{Link, Neigh, Route}}; +/// A netlink socket used to communicate with the kernel pub struct Socket { pub(crate) sock: *mut nl_sock } impl Socket { + /// Establish a new connection with the Linux kernel pub fn new() -> error::Result { unsafe { let sock = Socket { sock: nl_socket_alloc() }; @@ -89,6 +91,15 @@ impl Socket { } } +impl Drop for Socket { + fn drop(&mut self) { + unsafe { + nl_close(self.sock); + } + } +} + +/// Tries to get a link by the specified ifindex pub fn get_link_by_index(cache: &Cache, index: i32) -> Option { unsafe { let link = rtnl_link_get(cache.cache, index); @@ -101,6 +112,8 @@ pub fn get_link_by_index(cache: &Cache, index: i32) -> Option { } } +/// Represents the nl_cache in the libnl library, which is itself a general +/// collection of nl_objects pub struct Cache where T: From<*mut nl_object> @@ -132,6 +145,7 @@ impl> Drop for Cache { } } +/// Iterates over caches and provides an easy way to work with them pub struct CacheIter<'a, T> { obj: *mut nl_object, cache_size: usize, diff --git a/nl-sys/src/nl_ffi.rs b/nl-sys/src/nl_ffi.rs index 330a97d..0fefb6b 100644 --- a/nl-sys/src/nl_ffi.rs +++ b/nl-sys/src/nl_ffi.rs @@ -43,6 +43,7 @@ extern "C" { pub fn nl_socket_free(sock: *mut nl_sock); pub fn nl_socket_get_local_port(sock: *const nl_sock) -> u32; pub fn nl_connect(sock: *mut nl_sock, protocol: c_int) -> c_int; + pub fn nl_close(sock: *mut nl_sock) -> c_void; pub fn nl_geterror(error: c_int) -> *const c_char; pub fn nl_object_put(obj: *mut nl_object) -> c_void; diff --git a/nl-sys/src/route.rs b/nl-sys/src/route.rs index e3fdf4f..49760cb 100644 --- a/nl-sys/src/route.rs +++ b/nl-sys/src/route.rs @@ -21,11 +21,14 @@ use crate::{error, netlink::Cache}; use super::nl_ffi::*; + +/// Represents a network link, which can represent a network device pub struct Link { pub(crate) link: *mut rtnl_link } impl Link { + /// Returns the network link name, e.g. eth0 pub fn name(&self) -> String { unsafe { let name = rtnl_link_get_name(self.link); @@ -34,12 +37,15 @@ impl Link { } } + /// Provides the address of the link. Can change based on the type of link, + /// representing MAC addresses or IP addresses pub fn addr(&self) -> Addr { unsafe { Addr { addr: rtnl_link_get_addr(self.link) } } } + /// Determines the type of link. Ethernet devices are "veth" pub fn ltype(&self) -> Option { unsafe { let ltype = rtnl_link_get_type(self.link); @@ -51,12 +57,15 @@ impl Link { } } + /// Determines the index of the interface in the kernel table pub fn ifindex(&self) -> c_int { unsafe { rtnl_link_get_ifindex(self.link) } } + /// Tries to get the neighbor for this link, which can provide the destination address and the + /// link layer address (lladdr) pub fn get_neigh(&self, neigh_table: &Cache, addr: &Addr) -> Option { unsafe { let neigh = rtnl_neigh_get(neigh_table.cache, self.ifindex(), addr.addr); @@ -78,6 +87,7 @@ impl From<*mut nl_object> for Link { } } +/// Gets the neighbor record for the source IP specified pub fn get_neigh_for_addr(neighs: &Cache, links: &Cache, addr: &Addr) -> Option<(Link, Neigh)> { for link in links.iter() { let Some(neigh) = link.get_neigh(&neighs, addr) else { continue; }; @@ -87,11 +97,13 @@ pub fn get_neigh_for_addr(neighs: &Cache, links: &Cache, addr: &Add None } +/// A struct representing the neighbor of a link pub struct Neigh { neigh: *mut rtnl_neigh } impl Neigh { + /// Pull up the destination address for this neighbor record pub fn dst(&self) -> Addr { unsafe { let addr = rtnl_neigh_get_dst(self.neigh); @@ -99,6 +111,7 @@ impl Neigh { } } + // Bring up the link local address for the neighbor link pub fn lladdr(&self) -> Addr { unsafe { let addr = rtnl_neigh_get_lladdr(self.neigh); @@ -115,17 +128,21 @@ impl From<*mut nl_object> for Neigh { } } +/// Represents "an address" +/// IPv4? IPv6? MAC? Whatever the "any" or "lo" devices use? Yes! pub struct Addr { addr: *mut nl_addr } impl Addr { + /// Returns the number of bytes that are in the address pub fn len(&self) -> u32 { unsafe { nl_addr_get_len(self.addr) } } + /// Returns the address, which can be interpreted based on the results of [`Addr::atype`] pub fn hw_address(&self) -> Vec { unsafe { let hw_address_ptr = nl_addr_get_binary_addr(self.addr) as *const u8; @@ -135,12 +152,14 @@ impl Addr { } } + // Determines the type of data in [`Addr::hw_address`] pub fn atype(&self) -> c_int { unsafe { nl_addr_get_family(self.addr) } } + /// Returns the length of the subnet mask applying to this address pub fn cidrlen(&self) -> c_uint { unsafe { nl_addr_get_prefixlen(self.addr) @@ -175,23 +194,13 @@ impl TryFrom for Ipv4Addr { } } +/// Represents a route in the kernel routing table pub struct Route { route: *mut rtnl_route } impl Route { - pub fn src(&self) -> Option { - unsafe { - let addr = rtnl_route_get_src(self.route); - - if addr.is_null() { - return None; - } - - Some(Addr { addr }) - } - } - + /// Represents the destination of the route pub fn dst(&self) -> Option { unsafe { let addr = rtnl_route_get_dst(self.route); @@ -204,18 +213,21 @@ impl Route { } } + /// Determines which interface is affected by this route pub fn ifindex(&self) -> c_int { unsafe { rtnl_route_get_iif(self.route) } } + /// Returns the amount of hops are in this route pub fn nexthop_len(&self) -> c_int { unsafe { rtnl_route_get_nnexthops(self.route) } } + /// Gets the hop at the index specify pub fn nexthop(&self, ind: i32) -> Option { unsafe { let nexthop = rtnl_route_nexthop_n(self.route, ind); @@ -226,6 +238,7 @@ impl Route { } } + /// Returns an iterator representing all the hops for this route pub fn hop_iter(&self) -> NexthopIter<'_> { NexthopIter { route: &self, index: 0 } } @@ -239,11 +252,13 @@ impl From<*mut nl_object> for Route { } } +/// Represents the hops of a network route pub struct Nexthop { nexthop: *mut rtnl_nexthop } impl Nexthop { + /// Returns the gateway used for this network hop pub fn gateway(&self) -> Option { unsafe { let addr = rtnl_route_nh_get_gateway(self.nexthop); @@ -256,6 +271,7 @@ impl Nexthop { } } + /// Returns the interface index for this network hop pub fn ifindex(&self) -> i32 { unsafe { rtnl_route_nh_get_ifindex(self.nexthop) @@ -263,6 +279,7 @@ impl Nexthop { } } +/// An iterator for working with route hops pub struct NexthopIter<'a> { route: &'a Route, index: i32 @@ -288,7 +305,8 @@ impl Iterator for NexthopIter<'_> { } } -pub fn get_route_for_ip(routes: &Cache, ip: Ipv4Addr) -> Option { +/// Determines the source IP address to use in order to make a network request +pub fn get_srcip_for_dstip(routes: &Cache, ip: Ipv4Addr) -> Option { let mut sorted_routes = routes.iter().collect::>(); sorted_routes.sort_by(|r1, r2| { @@ -325,4 +343,5 @@ pub fn get_route_for_ip(routes: &Cache, ip: Ipv4Addr) -> Option .flatten() .map(|gateway| gateway.try_into().ok()) .flatten() -} \ No newline at end of file +} +