diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-10-15 10:43:11 +0200 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-10-15 10:50:20 +0200 |
commit | 1d8fad5a244117202c84c0660baec32f9fa6f58e (patch) | |
tree | 3fbab920aa614c43bafcd5e9eb39ceb570171090 | |
parent | 778001f5863a3d0953b15f5f72f9971ac9371dc2 (diff) |
rewrite sit tunnel creation to use libc rather than bindings
-rw-r--r-- | Cargo.lock | 12 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/tunnel.rs | 106 |
3 files changed, 101 insertions, 19 deletions
@@ -45,6 +45,12 @@ dependencies = [ ] [[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -269,9 +275,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "log" @@ -477,9 +483,11 @@ dependencies = [ name = "rsdsl_netlinkd" version = "0.7.0-dev" dependencies = [ + "bitfield", "futures", "futures-util", "ipnet", + "libc", "netlink-packet-route", "notify", "rsdsl_ip_config", @@ -6,9 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitfield = "0.14.0" futures = "0.3.28" futures-util = "0.3.27" ipnet = "2.8.0" +libc = "0.2.149" netlink-packet-route = "0.17.0" notify = "5.1.0" rsdsl_ip_config = { git = "https://github.com/rsdsl/ip_config.git", version = "0.2.2" } diff --git a/src/tunnel.rs b/src/tunnel.rs index 240e5fb..ac5d074 100644 --- a/src/tunnel.rs +++ b/src/tunnel.rs @@ -4,6 +4,10 @@ use std::ffi::CString; use std::io; use std::net::{Ipv4Addr, Ipv6Addr}; +use bitfield::bitfield; + +const SIOCADDTUNNEL: u64 = 0x89F0 + 1; + /// A handle to a 6in4 tunnel. The interface is automatically deleted on drop. #[derive(Debug)] pub struct Sit { @@ -18,28 +22,53 @@ impl Drop for Sit { impl Sit { pub fn new(name: &str, master: &str, laddr: Ipv4Addr, raddr: Ipv4Addr) -> Result<Self> { - let tnlname = CString::new(name)?.into_raw(); - let ifmaster = CString::new(master)?.into_raw(); + let mut vihl = VerIhl::default(); + + vihl.set_version(4); + vihl.set_ihl(5); + + let p = IpTunnelParm { + name: CString::new(name)?, + link: libc::if_nametoindex(CString::new(master)?.as_ptr()), + i_flags: 0, + o_flags: 0, + i_key: 0, + o_key: 0, + iph: IpHdr { + vihl, + tos: 0, + tot_len: 0, + id: 0, + frag_off: 0, + check: 0, + ttl: 64, + protocol: libc::IPPROTO_IPV6 as u8, + saddr: laddr, + daddr: raddr, + }, + }; - let err = unsafe { - internal::netlinkd_create_6in4( - tnlname, - ifmaster, - u32::from(laddr).to_be(), - u32::from(raddr).to_be(), - ) + if p.link == 0 { + return Err(Error::LinkNotFound(master.to_owned())); + } + + let ifr = IfReq { + name: CString::new("sit0")?, + ifru_data: &p, }; - let _ = unsafe { CString::from_raw(tnlname) }; - let _ = unsafe { CString::from_raw(ifmaster) }; + let fd = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); + if fd < 0 { + return Err(io::Error::last_os_error().into()); + } - if err < 0 { - Err(Error::Io(io::Error::last_os_error())) - } else { - Ok(Self { - name: name.to_owned(), - }) + if libc::ioctl(fd, SIOCADDTUNNEL, &ifr) < 0 { + return Err(io::Error::last_os_error().into()); } + + Ok(Self { + name: name.to_owned(), + }) } fn do_delete(&self) -> Result<()> { @@ -105,3 +134,46 @@ impl IpIp6 { } } } + +bitfield! { + #[derive(Default)] + struct VerIhl(u8); + impl Debug; + + version, set_version: 7, 4; + ihl, set_ihl: 3, 0; +} + +#[derive(Debug)] +#[repr(C)] +struct IpHdr { + vihl: VerIhl, + tos: u8, + tot_len: u16, + id: u16, + frag_off: u16, + ttl: u8, + protocol: u8, + check: u16, + saddr: Ipv4Addr, + daddr: Ipv4Addr, +} + +#[derive(Debug)] +#[repr(C)] +struct IpTunnelParm { + name: CString, + link: u32, + i_flags: u16, + o_flags: u16, + i_key: u32, + o_key: u32, + iph: IpHdr, +} + +#[derive(Debug)] +#[repr(C)] +struct IfReq { + name: CString, + ifru_data: *const IpTunnelParm, +} |