Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
davidv1992 committed Jan 11, 2024
1 parent 0878517 commit 6bf979e
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 71 deletions.
42 changes: 20 additions & 22 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,26 @@ jobs:
env:
RUST_BACKTRACE: 1

# no support for RawFd on freebsd; lots of our code relies on that
#
# build-freebsd:
# name: Clippy & Test FreeBSD
# runs-on: macos-12
# steps:
# - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
# - name: test on freebsd
# uses: vmactions/freebsd-vm@v0
# with:
# usesh: true
# mem: 4096
# copyback: false
# prepare: |
# pkg install -y curl
# curl https://sh.rustup.rs -sSf --output rustup.sh
# sh rustup.sh -y --profile default --default-toolchain 1.65.0 # cannot use `--profile minimal` because of clippy
# echo "~~~~ rustc --version ~~~~"
# $HOME/.cargo/bin/rustc --version
# echo "~~~~ freebsd-version ~~~~"
# freebsd-version
# run: $HOME/.cargo/bin/cargo clippy -- -D warnings && $HOME/.cargo/bin/cargo build && $HOME/.cargo/bin/cargo test
build-freebsd:
name: Clippy & Test FreeBSD
runs-on: macos-12
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
- name: test on freebsd
uses: vmactions/freebsd-vm@v0
with:
usesh: true
mem: 4096
copyback: false
prepare: |
pkg install -y curl
curl https://sh.rustup.rs -sSf --output rustup.sh
sh rustup.sh -y --profile default --default-toolchain 1.66.0 # cannot use `--profile minimal` because of clippy
echo "~~~~ rustc --version ~~~~"
$HOME/.cargo/bin/rustc --version
echo "~~~~ freebsd-version ~~~~"
freebsd-version
run: $HOME/.cargo/bin/cargo clippy -- -D warnings && $HOME/.cargo/bin/cargo build && $HOME/.cargo/bin/cargo test

clippy-raspberry-pi:
name: ClippyRaspberryPi
Expand Down
5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "timestamped-socket"
description = "Implementation of async UDP and raw ethernet sockets with timestamping"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/pendulum-project/timestamped-socket"
Expand All @@ -21,5 +21,4 @@ serde = { version = "1.0.145", features = ["derive"], optional = true }
tokio = { version = "1.32.0", features = ["rt", "macros"] }

[features]
default = ["std", "serde"]
std = []
default = ["serde"]
2 changes: 2 additions & 0 deletions src/control_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub(crate) const fn control_message_space<T>() -> usize {

pub(crate) enum MessageQueue {
Normal,
#[cfg(target_os = "linux")]
Error,
}

Expand Down Expand Up @@ -51,6 +52,7 @@ pub(crate) enum ControlMessage {
software: Option<Timestamp>,
hardware: Option<Timestamp>,
},
#[cfg(target_os = "linux")]
ReceiveError(libc::sock_extended_err),
Other(libc::cmsghdr),
}
Expand Down
25 changes: 0 additions & 25 deletions src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,21 +223,6 @@ impl<'de> serde::Deserialize<'de> for InterfaceName {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LinuxNetworkMode {
Ipv4,
Ipv6,
}

impl LinuxNetworkMode {
pub fn unspecified_ip_addr(&self) -> IpAddr {
match self {
LinuxNetworkMode::Ipv4 => IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED),
LinuxNetworkMode::Ipv6 => IpAddr::V6(std::net::Ipv6Addr::UNSPECIFIED),
}
}
}

/// Convert a libc::sockaddr to a rust std::net::SocketAddr
///
/// # Safety
Expand Down Expand Up @@ -291,16 +276,6 @@ unsafe fn sockaddr_to_socket_addr(sockaddr: *const libc::sockaddr) -> Option<Soc
}
}

pub fn sockaddr_storage_to_socket_addr(
sockaddr_storage: &libc::sockaddr_storage,
) -> Option<SocketAddr> {
// Safety:
//
// sockaddr_storage always has enough space to store either a sockaddr_in or
// sockaddr_in6
unsafe { sockaddr_to_socket_addr(sockaddr_storage as *const _ as *const libc::sockaddr) }
}

#[cfg(test)]
mod tests {
use std::net::Ipv4Addr;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod control_message;
#[cfg(target_os = "linux")]
pub mod interface;
pub mod networkaddress;
mod raw_socket;
Expand Down
26 changes: 21 additions & 5 deletions src/networkaddress.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::{
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
os::fd::RawFd,
};
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};

use crate::{cerr, control_message::zeroed_sockaddr_storage, interface::InterfaceName};
#[cfg(target_os = "linux")]
use std::os::fd::RawFd;

use crate::control_message::zeroed_sockaddr_storage;

#[cfg(target_os = "linux")]
use crate::{cerr, interface::InterfaceName};

use self::sealed::{PrivateToken, SealedMC, SealedNA};

Expand All @@ -25,6 +28,7 @@ pub trait NetworkAddress: Sized + SealedNA {
fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self>;
}

#[cfg(target_os = "linux")]
pub trait MulticastJoinable: NetworkAddress + SealedMC {
#[doc(hidden)]
fn join_multicast(
Expand Down Expand Up @@ -96,6 +100,7 @@ impl NetworkAddress for SocketAddrV4 {

impl SealedMC for SocketAddrV4 {}

#[cfg(target_os = "linux")]
impl MulticastJoinable for SocketAddrV4 {
fn join_multicast(
&self,
Expand Down Expand Up @@ -218,6 +223,7 @@ impl NetworkAddress for SocketAddrV6 {

impl SealedMC for SocketAddrV6 {}

#[cfg(target_os = "linux")]
impl MulticastJoinable for SocketAddrV6 {
fn join_multicast(
&self,
Expand Down Expand Up @@ -301,34 +307,40 @@ impl NetworkAddress for SocketAddr {
}
}

#[cfg(target_os = "linux")]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MacAddress([u8; 6]);

#[cfg(target_os = "linux")]
impl From<[u8; 6]> for MacAddress {
fn from(value: [u8; 6]) -> Self {
MacAddress(value)
}
}

#[cfg(target_os = "linux")]
impl AsRef<[u8]> for MacAddress {
fn as_ref(&self) -> &[u8] {
&self.0
}
}

#[cfg(target_os = "linux")]
impl MacAddress {
pub const fn new(address: [u8; 6]) -> Self {
MacAddress(address)
}
}

#[cfg(target_os = "linux")]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EthernetAddress {
protocol: u16,
mac_address: MacAddress,
if_index: libc::c_int,
}

#[cfg(target_os = "linux")]
impl EthernetAddress {
pub const fn new(protocol: u16, mac_address: MacAddress, if_index: libc::c_int) -> Self {
EthernetAddress {
Expand All @@ -351,8 +363,10 @@ impl EthernetAddress {
}
}

#[cfg(target_os = "linux")]
impl SealedNA for EthernetAddress {}

#[cfg(target_os = "linux")]
impl NetworkAddress for EthernetAddress {
fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
const _: () = assert!(
Expand Down Expand Up @@ -410,8 +424,10 @@ impl NetworkAddress for EthernetAddress {
}
}

#[cfg(target_os = "linux")]
impl SealedMC for EthernetAddress {}

#[cfg(target_os = "linux")]
impl MulticastJoinable for EthernetAddress {
fn join_multicast(
&self,
Expand Down
27 changes: 25 additions & 2 deletions src/raw_socket.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
use std::{
io::IoSliceMut,
net::Ipv4Addr,
os::fd::{AsRawFd, RawFd},
};

#[cfg(target_os = "linux")]
use std::net::Ipv4Addr;

use libc::{c_void, sockaddr, sockaddr_storage};

use crate::{
cerr,
control_message::{
empty_msghdr, zeroed_sockaddr_storage, ControlMessage, ControlMessageIterator, MessageQueue,
},
interface::InterfaceName,
};

#[cfg(target_os = "linux")]
use crate::interface::InterfaceName;

// A struct providing safe wrappers around various socket api calls
#[derive(Debug, Hash)]
pub(crate) struct RawSocket {
Expand Down Expand Up @@ -49,6 +53,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn bind_to_device(&self, interface_name: InterfaceName) -> std::io::Result<()> {
let value = interface_name.as_str().as_bytes();
let len = value.len();
Expand All @@ -66,6 +71,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn ip_multicast_if(&self, interface_name: InterfaceName) -> std::io::Result<()> {
let request = libc::ip_mreqn {
imr_multiaddr: libc::in_addr {
Expand All @@ -91,6 +97,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn ipv6_multicast_if(&self, interface_name: InterfaceName) -> std::io::Result<()> {
let index = interface_name
.get_index()
Expand All @@ -108,6 +115,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn ip_multicast_loop(&self, enabled: bool) -> std::io::Result<()> {
let state: i32 = if enabled { 1 } else { 0 };
cerr(unsafe {
Expand All @@ -122,6 +130,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn ipv6_multicast_loop(&self, enabled: bool) -> std::io::Result<()> {
let state: i32 = if enabled { 1 } else { 0 };
cerr(unsafe {
Expand All @@ -136,6 +145,7 @@ impl RawSocket {
Ok(())
}

#[cfg(target_os = "linux")]
pub(crate) fn ipv6_v6only(&self, enabled: bool) -> std::io::Result<()> {
let state: i32 = if enabled { 1 } else { 0 };
cerr(unsafe {
Expand Down Expand Up @@ -166,6 +176,7 @@ impl RawSocket {
cerr(unsafe { libc::ioctl(self.fd, libc::FIONBIO, &nonblocking) }).map(drop)
}

#[cfg(target_os = "linux")]
pub(crate) fn reuse_addr(&self) -> std::io::Result<()> {
let options = 1u32;

Expand Down Expand Up @@ -210,6 +221,7 @@ impl RawSocket {

let receive_flags = match queue {
MessageQueue::Normal => 0,
#[cfg(target_os = "linux")]
MessageQueue::Error => libc::MSG_ERRQUEUE,
};

Expand Down Expand Up @@ -314,6 +326,17 @@ impl RawSocket {
std::mem::size_of_val(&options) as libc::socklen_t,
))
}?;
if options != 0 {
unsafe {
cerr(libc::setsockopt(
self.fd,
libc::SOL_SOCKET,
libc::SO_TS_CLOCK,
&(libc::SO_TS_REALTIME as u32) as *const _ as *const libc::c_void,
std::mem::size_of_val(&(libc::SO_TS_REALTIME as u32)) as libc::socklen_t,
))
}?;
}
Ok(())
}

Expand Down
Loading

0 comments on commit 6bf979e

Please sign in to comment.