Skip to content

Commit

Permalink
Fixed issues mentioned in PR review, and added test case for the sock…
Browse files Browse the repository at this point in the history
…_addr utils.
  • Loading branch information
wa5i committed May 9, 2024
1 parent e7407ff commit e5a516c
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 207 deletions.
5 changes: 4 additions & 1 deletion src/utils/cidr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! This module is a Rust replica of
//! https://github.com/hashicorp/vault/blob/main/sdk/helper/cidrutil/cidr.go
use std::{
str::FromStr,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
Expand All @@ -7,7 +10,7 @@ use std::{
use ipnetwork::IpNetwork;

use super::{
sockaddr::{new_sock_addr, SockAddrType, SockAddr},
sock_addr::{new_sock_addr, SockAddrType, SockAddr},
};

use crate::errors::RvError;
Expand Down
119 changes: 119 additions & 0 deletions src/utils/ip_sock_addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//! This module is a Rust replica of
//! https://github.com/hashicorp/go-sockaddr/blob/master/ipv4addr.go
use std::{
fmt,
str::FromStr,
net::SocketAddr,
};

use as_any::Downcast;
use ipnetwork::IpNetwork;
use serde::{Deserialize, Serialize};

use super::{
sock_addr::{SockAddr, SockAddrType},
};

use crate::errors::RvError;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct IpSockAddr {
pub addr: IpNetwork,
pub port: u16,
}

impl IpSockAddr {
pub fn new(s: &str) -> Result<Self, RvError> {
if let Ok(sock_addr) = SocketAddr::from_str(s) {
return Ok(IpSockAddr {
addr: IpNetwork::from(sock_addr.ip()),
port: sock_addr.port(),
});
} else if let Ok(ip_addr) = IpNetwork::from_str(s) {
return Ok(IpSockAddr {
addr: ip_addr,
port: 0,
});
}
return Err(RvError::ErrResponse(format!("Unable to parse {} to an IP address:", s)));
}
}

impl SockAddr for IpSockAddr {
fn contains(&self, other: &dyn SockAddr) -> bool {
if let Some(ip_addr) = other.downcast_ref::<IpSockAddr>() {
return self.addr.contains(ip_addr.addr.ip());
}

false
}

fn equal(&self, other: &dyn SockAddr) -> bool {
if let Some(ip_addr) = other.downcast_ref::<IpSockAddr>() {
return self.addr == ip_addr.addr && self.port == ip_addr.port;
}

false
}

fn sock_addr_type(&self) -> SockAddrType {
match self.addr {
IpNetwork::V4(_) => SockAddrType::IPv4,
IpNetwork::V6(_) => SockAddrType::IPv6,
}
}
}

impl fmt::Display for IpSockAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.port == 0 {
write!(f, "{}", self.addr.ip())
} else {
write!(f, "{}:{}", self.addr.ip(), self.port)
}
}
}

#[cfg(test)]
mod test {
use super::{
*, super::sock_addr::{SockAddrType},
};

#[test]
fn test_ip_sock_addr() {
let addr1 = IpSockAddr::new("1.1.1.1").unwrap();
let addr2 = IpSockAddr::new("1.1.1.1").unwrap();
let addr3 = IpSockAddr::new("2.2.2.2").unwrap();
let addr4 = IpSockAddr::new("333.333.333.333");
let addr5 = IpSockAddr::new("1.1.1.1:80").unwrap();
let addr6 = IpSockAddr::new("1.1.1.1:80").unwrap();
let addr7 = IpSockAddr::new("1.1.1.1:8080").unwrap();
let addr8 = IpSockAddr::new("2.2.2.2:80").unwrap();
let addr9 = IpSockAddr::new("192.168.0.0/16").unwrap();
let addr10 = IpSockAddr::new("192.168.0.0/24").unwrap();
let addr11 = IpSockAddr::new("192.168.0.1").unwrap();
let addr12 = IpSockAddr::new("192.168.1.1").unwrap();

assert!(addr4.is_err());
assert!(addr1.contains(&addr2));
assert!(addr1.equal(&addr2));
assert!(!addr1.contains(&addr3));
assert!(!addr1.equal(&addr3));
assert_eq!(addr1.sock_addr_type(), SockAddrType::IPv4);
assert!(addr5.contains(&addr6));
assert!(addr5.equal(&addr6));
assert!(!addr5.equal(&addr7));
assert!(!addr5.equal(&addr8));
assert!(addr9.contains(&addr10));
assert!(addr9.contains(&addr11));
assert!(addr9.contains(&addr12));
assert!(!addr9.contains(&addr1));
assert!(addr10.contains(&addr9));
assert!(addr10.contains(&addr11));
assert!(!addr10.contains(&addr12));
assert!(!addr9.equal(&addr10));
assert!(!addr9.equal(&addr11));
}
}
74 changes: 0 additions & 74 deletions src/utils/ipaddr.rs

This file was deleted.

6 changes: 3 additions & 3 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ pub mod cert;
pub mod key;
pub mod salt;
pub mod cidr;
pub mod sockaddr;
pub mod ipaddr;
pub mod unixsock;
pub mod sock_addr;
pub mod ip_sock_addr;
pub mod unix_sock_addr;

pub fn generate_uuid() -> String {
let mut buf = [0u8; 16];
Expand Down
3 changes: 3 additions & 0 deletions src/utils/salt.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! This module is a Rust replica of
//! https://github.com/hashicorp/vault/blob/main/sdk/helper/salt/salt.go
use openssl::{
hash::{hash, MessageDigest},
pkey::PKey,
Expand Down
144 changes: 144 additions & 0 deletions src/utils/sock_addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! This module is a Rust replica of
//! https://github.com/hashicorp/go-sockaddr/blob/master/sockaddr.go
use std::{
fmt,
str::FromStr,
};

use as_any::AsAny;
use serde::{Deserialize, Serialize};

use super::{
ip_sock_addr::IpSockAddr,
};

use crate::errors::RvError;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SockAddrType {
Unknown = 0x0,
Unix = 0x1,
IPv4 = 0x2,
IPv6 = 0x4,
// IP is the union of IPv4 and IPv6
IP = 0x6,
}

pub trait SockAddr: fmt::Display + AsAny {
// contains returns true if the other SockAddr is contained within the receiver
fn contains(&self, other: &dyn SockAddr) -> bool;

// equal allows for the comparison of two SockAddrs
fn equal(&self, other: &dyn SockAddr) -> bool;

fn sock_addr_type(&self) -> SockAddrType;
}

pub struct SockAddrMarshaler {
pub sock_addr: Box<dyn SockAddr>,
}

impl SockAddrMarshaler {
pub fn new(sock_addr: Box<dyn SockAddr>) -> Self {
SockAddrMarshaler { sock_addr }
}
}

impl fmt::Display for SockAddrMarshaler {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.sock_addr)
}
}

impl fmt::Display for SockAddrType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let type_str = match self {
SockAddrType::IPv4 => "IPv4",
SockAddrType::IPv6 => "IPv6",
SockAddrType::Unix => "Unix",
_ => "Unknown",
};
write!(f, "{}", type_str)
}
}

impl FromStr for SockAddrType {
type Err = RvError;
fn from_str(s: &str) -> Result<Self, RvError> {
match s {
"IPv4" | "ipv4" => Ok(SockAddrType::IPv4),
"IPv6" | "ipv6" => Ok(SockAddrType::IPv6),
"Unix" | "UNIX" | "unix" => Ok(SockAddrType::Unix),
_ => Err(RvError::ErrResponse("invalid sockaddr type".to_string()))
}
}
}

pub fn new_sock_addr(s: &str) -> Result<Box<dyn SockAddr>, RvError> {
let ret = IpSockAddr::new(s)?;
Ok(Box::new(ret))
}

#[cfg(test)]
mod test {
use super::{
*, super::{
sock_addr::{SockAddrType},
ip_sock_addr::IpSockAddr,
unix_sock_addr::UnixSockAddr,
},
};

#[test]
fn test_sock_addr() {
let unix_addr1 = UnixSockAddr::new("/tmp/bar").unwrap();
let unix_addr2 = UnixSockAddr::new("/tmp/bar").unwrap();
let unix_addr3 = UnixSockAddr::new("/tmp/foo").unwrap();
let ip_addr1 = IpSockAddr::new("1.1.1.1").unwrap();
let ip_addr2 = IpSockAddr::new("1.1.1.1").unwrap();
let ip_addr3 = IpSockAddr::new("2.2.2.2").unwrap();
let ip_addr4 = IpSockAddr::new("333.333.333.333");
let ip_addr5 = IpSockAddr::new("1.1.1.1:80").unwrap();
let ip_addr6 = IpSockAddr::new("1.1.1.1:80").unwrap();
let ip_addr7 = IpSockAddr::new("1.1.1.1:8080").unwrap();
let ip_addr8 = IpSockAddr::new("2.2.2.2:80").unwrap();
let ip_addr9 = IpSockAddr::new("192.168.0.0/16").unwrap();
let ip_addr10 = IpSockAddr::new("192.168.0.0/24").unwrap();
let ip_addr11 = IpSockAddr::new("192.168.0.1").unwrap();
let ip_addr12 = IpSockAddr::new("192.168.1.1").unwrap();

assert!(unix_addr1.contains(&unix_addr2));
assert!(unix_addr1.equal(&unix_addr2));
assert!(!unix_addr1.contains(&unix_addr3));
assert!(!unix_addr1.equal(&unix_addr3));
assert_ne!(unix_addr1.sock_addr_type(), ip_addr1.sock_addr_type());

assert!(ip_addr4.is_err());
assert!(ip_addr1.contains(&ip_addr2));
assert!(ip_addr1.equal(&ip_addr2));
assert!(!ip_addr1.contains(&ip_addr3));
assert!(!ip_addr1.equal(&ip_addr3));
assert_eq!(ip_addr1.sock_addr_type(), SockAddrType::IPv4);
assert_eq!(ip_addr1.sock_addr_type(), ip_addr2.sock_addr_type());
assert_ne!(ip_addr1.sock_addr_type(), unix_addr2.sock_addr_type());
assert!(ip_addr5.contains(&ip_addr6));
assert!(ip_addr5.equal(&ip_addr6));
assert!(!ip_addr5.equal(&ip_addr7));
assert!(!ip_addr5.equal(&ip_addr8));
assert!(ip_addr9.contains(&ip_addr10));
assert!(ip_addr9.contains(&ip_addr11));
assert!(ip_addr9.contains(&ip_addr12));
assert!(!ip_addr9.contains(&ip_addr1));
assert!(ip_addr10.contains(&ip_addr9));
assert!(ip_addr10.contains(&ip_addr11));
assert!(!ip_addr10.contains(&ip_addr12));
assert!(!ip_addr9.equal(&ip_addr10));
assert!(!ip_addr9.equal(&ip_addr11));

assert!(!ip_addr1.contains(&unix_addr1));
assert!(!ip_addr1.equal(&unix_addr1));
assert!(!unix_addr1.contains(&ip_addr1));
assert!(!unix_addr1.equal(&ip_addr1));
}
}
Loading

0 comments on commit e5a516c

Please sign in to comment.