mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
Build fixes, InetAddress in Rust implementing union of C sockaddrs.
This commit is contained in:
parent
a88d89a854
commit
aa4336db98
8 changed files with 484 additions and 5 deletions
2
network-hypervisor/Cargo.lock
generated
2
network-hypervisor/Cargo.lock
generated
|
@ -422,6 +422,8 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"gcrypt",
|
"gcrypt",
|
||||||
|
"libc",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
"winapi",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,3 +21,9 @@ x25519-dalek = "^1"
|
||||||
ed25519-dalek = "^1"
|
ed25519-dalek = "^1"
|
||||||
gcrypt = "^0"
|
gcrypt = "^0"
|
||||||
base64 = "^0"
|
base64 = "^0"
|
||||||
|
|
||||||
|
[target."cfg(not(windows))".dependencies]
|
||||||
|
libc = "^0"
|
||||||
|
|
||||||
|
[target."cfg(windows)".dependencies]
|
||||||
|
winapi = { version = "0.3.9", features = ["handleapi", "ws2ipdef", "ws2tcpip"] }
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::convert::TryInto;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use ed25519_dalek::Digest;
|
use ed25519_dalek::Digest;
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
pub const C25519_PUBLIC_KEY_SIZE: usize = 32;
|
pub const C25519_PUBLIC_KEY_SIZE: usize = 32;
|
||||||
pub const C25519_SECRET_KEY_SIZE: usize = 32;
|
pub const C25519_SECRET_KEY_SIZE: usize = 32;
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
pub mod hex;
|
pub mod hex;
|
||||||
|
|
||||||
|
pub(crate) unsafe fn equal_bytes(a: *const u8, b: *const u8, l: usize) -> bool {
|
||||||
|
for i in 0..l {
|
||||||
|
if *a.offset(i as isize) != *b.offset(i as isize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn integer_store_be_u16(i: u16, d: &mut [u8]) {
|
pub(crate) fn integer_store_be_u16(i: u16, d: &mut [u8]) {
|
||||||
d[0] = (i >> 8) as u8;
|
d[0] = (i >> 8) as u8;
|
||||||
|
|
458
network-hypervisor/src/vl1/inetaddress.rs
Normal file
458
network-hypervisor/src/vl1/inetaddress.rs
Normal file
|
@ -0,0 +1,458 @@
|
||||||
|
use std::mem::{zeroed, size_of};
|
||||||
|
use std::ptr::{write_bytes, copy_nonoverlapping, null};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::net::{IpAddr, Ipv6Addr};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use winapi::um::winsock2 as winsock2;
|
||||||
|
|
||||||
|
use crate::error::InvalidFormatError;
|
||||||
|
use crate::util::equal_bytes;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
type sockaddr = libc::sockaddr;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
type sockaddr_in = libc::sockaddr_in;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
type sockaddr_in6 = libc::sockaddr_in6;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
type in6_addr = libc::in6_addr;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub const AF_INET: u8 = libc::AF_INET as u8;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub const AF_INET6: u8 = libc::AF_INET6 as u8;
|
||||||
|
|
||||||
|
const NO_IP: [u8; 0] = [];
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum IpScope {
|
||||||
|
None = 0,
|
||||||
|
Multicast = 1,
|
||||||
|
Loopback = 2,
|
||||||
|
PseudoPrivate = 3,
|
||||||
|
Global = 4,
|
||||||
|
LinkLocal = 5,
|
||||||
|
Shared = 6,
|
||||||
|
Private = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub union InetAddress {
|
||||||
|
sa: sockaddr,
|
||||||
|
sin: sockaddr_in,
|
||||||
|
sin6: sockaddr_in6
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InetAddress {
|
||||||
|
#[inline(always)]
|
||||||
|
fn default() -> InetAddress {
|
||||||
|
unsafe { zeroed() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InetAddress {
|
||||||
|
/// Get a new zero/nil InetAddress.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new() -> InetAddress {
|
||||||
|
unsafe { zeroed() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Zero the contents of this InetAddress.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn zero(&mut self) {
|
||||||
|
unsafe { write_bytes((self as *mut InetAddress).cast::<u8>(), 0, size_of::<Self>()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this InetAddress is the nil value (zero).
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_nil(&self) -> bool {
|
||||||
|
unsafe { self.sa.sa_family == 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if this is an IPv4 address.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_ipv4(&self) -> bool {
|
||||||
|
unsafe { self.sa.sa_family as u8 == AF_INET }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if this is an IPv6 address.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_ipv6(&self) -> bool {
|
||||||
|
unsafe { self.sa.sa_family as u8 == AF_INET6 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pointer to the C "sockaddr" structure and the size of the returned structure in bytes.
|
||||||
|
/// This is useful for interacting with C-level socket APIs. If this is a nil InetAddress this
|
||||||
|
/// returns a null pointer and 0 for the size.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn c_sockaddr(&self) -> (*const (), usize) {
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => ((&self.sin as *const sockaddr_in).cast(), size_of::<sockaddr_in>()),
|
||||||
|
AF_INET6 => ((&self.sin6 as *const sockaddr_in6).cast(), size_of::<sockaddr_in6>()),
|
||||||
|
_ => (null(), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the IP and port of this InetAddress.
|
||||||
|
/// Whether this is IPv4 or IPv6 is inferred from the size of ip[], which must be
|
||||||
|
/// either 4 or 16 bytes. The family (AF_INET or AF_INET6) is returned, or zero on
|
||||||
|
/// success.
|
||||||
|
pub fn set(&mut self, ip: &[u8], port: u16) -> u8 {
|
||||||
|
self.zero();
|
||||||
|
let port = port.to_be();
|
||||||
|
unsafe {
|
||||||
|
if ip.len() == 4 {
|
||||||
|
self.sin.sin_family = AF_INET.into();
|
||||||
|
self.sin.sin_port = port.into();
|
||||||
|
copy_nonoverlapping(ip.as_ptr(), (&mut self.sin.sin_addr.s_addr as *mut u32).cast::<u8>(), 4);
|
||||||
|
AF_INET
|
||||||
|
} else if ip.len() == 16 {
|
||||||
|
self.sin6.sin6_family = AF_INET6.into();
|
||||||
|
self.sin6.sin6_port = port.into();
|
||||||
|
copy_nonoverlapping(ip.as_ptr(), (&mut self.sin6.sin6_addr as *mut in6_addr).cast::<u8>(), 16);
|
||||||
|
AF_INET6
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get raw IP bytes, with length dependent on address family.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn ip(&self) -> &[u8] {
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => &*(&self.sin.sin_addr.s_addr as *const u32).cast::<[u8; 4]>(),
|
||||||
|
AF_INET6 => &*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>(),
|
||||||
|
_ => &NO_IP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the IP port for this InetAddress.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn port(&self) -> u16 {
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => u16::from_be(self.sin.sin_port as u16),
|
||||||
|
AF_INET6 => u16::from_be(self.sin6.sin6_port as u16),
|
||||||
|
_ => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the IP port.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn set_port(&mut self, port: u16) {
|
||||||
|
let port = port.to_be();
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => self.sin.sin_port = port,
|
||||||
|
AF_INET6 => self.sin6.sin6_port = port,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get this IP address's scope as per RFC documents and what is advertised via BGP.
|
||||||
|
pub fn scope(&self) -> IpScope {
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => {
|
||||||
|
let ip = self.sin.sin_addr.s_addr as u32;
|
||||||
|
let class_a = (ip >> 24) as u8;
|
||||||
|
match class_a {
|
||||||
|
0x00 | 0xff => IpScope::None, // 0.0.0.0/8 and 255.0.0.0/8 are not usable
|
||||||
|
0x0a => IpScope::Private, // 10.0.0.0/8
|
||||||
|
0x7f => IpScope::Loopback, // 127.0.0.0/8
|
||||||
|
0x64 => {
|
||||||
|
if (ip & 0xffc00000) == 0x64400000 { // 100.64.0.0/10
|
||||||
|
IpScope::Private
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xa9 => {
|
||||||
|
if (ip & 0xffff0000) == 0xa9fe0000 { // 169.254.0.0/16
|
||||||
|
IpScope::LinkLocal
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xac => {
|
||||||
|
if (ip & 0xfff00000) == 0xac100000 { // 172.16.0.0/12
|
||||||
|
IpScope::Private
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xc0 => {
|
||||||
|
if (ip & 0xffff0000) == 0xc0a80000 || (ip & 0xffffff00) == 0xc0000200 { // 192.168.0.0/16 and 192.0.2.0/24
|
||||||
|
IpScope::Private
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xc6 => {
|
||||||
|
if (ip & 0xfffe0000) == 0xc6120000 || (ip & 0xffffff00) == 0xc6336400 { // 198.18.0.0/15 and 198.51.100.0/24
|
||||||
|
IpScope::Private
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xcb => {
|
||||||
|
if (ip & 0xffffff00) == 0xcb007100 { // 203.0.113.0/24
|
||||||
|
IpScope::Private
|
||||||
|
} else {
|
||||||
|
IpScope::Global
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if [
|
||||||
|
0x06_u8, // 6.0.0.0/8 (US Army)
|
||||||
|
0x15_u8, // 21.0.0.0/8 (US DDN-RVN)
|
||||||
|
0x16_u8, // 22.0.0.0/8 (US DISA)
|
||||||
|
0x19_u8, // 25.0.0.0/8 (UK Ministry of Defense)
|
||||||
|
0x1a_u8, // 26.0.0.0/8 (US DISA)
|
||||||
|
0x1c_u8, // 28.0.0.0/8 (US DSI-North)
|
||||||
|
0x1d_u8, // 29.0.0.0/8 (US DISA)
|
||||||
|
0x1e_u8, // 30.0.0.0/8 (US DISA)
|
||||||
|
0x33_u8, // 51.0.0.0/8 (UK Department of Social Security)
|
||||||
|
0x37_u8, // 55.0.0.0/8 (US DoD)
|
||||||
|
0x38_u8, // 56.0.0.0/8 (US Postal Service)
|
||||||
|
].contains(&class_a) {
|
||||||
|
IpScope::PseudoPrivate
|
||||||
|
} else {
|
||||||
|
match ip >> 28 {
|
||||||
|
0xe => IpScope::Multicast, // 224.0.0.0/4
|
||||||
|
0xf => IpScope::Private, // 240.0.0.0/4 ("reserved," usually unusable)
|
||||||
|
_ => IpScope::Global
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AF_INET6 => {
|
||||||
|
let ip = &*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>();
|
||||||
|
if (ip[0] & 0xf0) == 0xf0 {
|
||||||
|
if ip[0] == 0xff {
|
||||||
|
return IpScope::Multicast; // ff00::/8
|
||||||
|
}
|
||||||
|
if ip[0] == 0xfe && (ip[1] & 0xc0) == 0x80 {
|
||||||
|
let mut k: usize = 2;
|
||||||
|
while ip[k] == 0 && k < 15 {
|
||||||
|
k += 1;
|
||||||
|
}
|
||||||
|
if k == 15 && ip[15] == 0x01 {
|
||||||
|
return IpScope::Loopback; // fe80::1/128
|
||||||
|
} else {
|
||||||
|
return IpScope::LinkLocal; // fe80::/10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ip[0] & 0xfe) == 0xfc {
|
||||||
|
return IpScope::Private; // fc00::/7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut k: usize = 0;
|
||||||
|
while ip[k] == 0 && k < 15 {
|
||||||
|
k += 1;
|
||||||
|
}
|
||||||
|
if k == 15 {
|
||||||
|
if ip[15] == 0x01 {
|
||||||
|
return IpScope::Loopback; // ::1/128
|
||||||
|
} else if ip[15] == 0x00 {
|
||||||
|
return IpScope::None; // ::/128
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IpScope::Global
|
||||||
|
},
|
||||||
|
_ => IpScope::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get only the IP portion of this address as a string.
|
||||||
|
pub fn to_ip_string(&self) -> String {
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => {
|
||||||
|
let ip = self.sin.sin_addr.s_addr as u32;
|
||||||
|
format!("{}.{}.{}.{}", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff)
|
||||||
|
},
|
||||||
|
AF_INET6 => {
|
||||||
|
Ipv6Addr::from(*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>()).to_string()
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
String::from("(null)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for InetAddress {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let mut s = self.to_ip_string();
|
||||||
|
unsafe {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => {
|
||||||
|
s.push('/');
|
||||||
|
s.push_str(u16::from_be(self.sin.sin_port as u16).to_string().as_str())
|
||||||
|
},
|
||||||
|
AF_INET6 => {
|
||||||
|
s.push('/');
|
||||||
|
s.push_str(u16::from_be(self.sin6.sin6_port as u16).to_string().as_str())
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for InetAddress {
|
||||||
|
type Err = InvalidFormatError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let mut addr = InetAddress::new();
|
||||||
|
let (ip_str, port) = s.find('/').map_or_else(|| {
|
||||||
|
(s, 0)
|
||||||
|
}, |pos| {
|
||||||
|
let ss = s.split_at(pos);
|
||||||
|
(ss.0, u16::from_str_radix(ss.1, 10).unwrap_or(0).to_be())
|
||||||
|
});
|
||||||
|
IpAddr::from_str(ip_str).map_or_else(|_| Err(InvalidFormatError), |ip| {
|
||||||
|
unsafe {
|
||||||
|
match ip {
|
||||||
|
IpAddr::V4(v4) => {
|
||||||
|
addr.sin.sin_family = AF_INET.into();
|
||||||
|
addr.sin.sin_port = port.into();
|
||||||
|
copy_nonoverlapping(v4.octets().as_ptr(), (&mut (addr.sin.sin_addr.s_addr) as *mut u32).cast(), 4);
|
||||||
|
},
|
||||||
|
IpAddr::V6(v6) => {
|
||||||
|
addr.sin6.sin6_family = AF_INET6.into();
|
||||||
|
addr.sin6.sin6_port = port.into();
|
||||||
|
copy_nonoverlapping(v6.octets().as_ptr(), (&mut (addr.sin6.sin6_addr) as *mut in6_addr).cast(), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(addr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for InetAddress {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
if self.sa.sa_family == other.sa.sa_family {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => { self.sin.sin_port == other.sin.sin_port && self.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr },
|
||||||
|
AF_INET6 => {
|
||||||
|
if self.sin6.sin6_port == other.sin6.sin6_port {
|
||||||
|
equal_bytes((&(self.sin6.sin6_addr) as *const in6_addr).cast(), (&(other.sin6.sin6_addr) as *const in6_addr).cast(), 16)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for InetAddress {}
|
||||||
|
|
||||||
|
impl PartialOrd for InetAddress {
|
||||||
|
#[inline(always)]
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for InetAddress {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
unsafe {
|
||||||
|
if self.sa.sa_family == other.sa.sa_family {
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => {
|
||||||
|
if self.sin.sin_port == other.sin.sin_port {
|
||||||
|
u32::from_be(self.sin.sin_addr.s_addr as u32).cmp(&u32::from_be(other.sin.sin_addr.s_addr as u32))
|
||||||
|
} else {
|
||||||
|
u16::from_be(self.sin.sin_port as u16).cmp(&u16::from_be(other.sin.sin_port as u16))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AF_INET6 => {
|
||||||
|
if self.sin6.sin6_port == other.sin6.sin6_port {
|
||||||
|
let a = &*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>();
|
||||||
|
let b = &*(&(other.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>();
|
||||||
|
a.cmp(b)
|
||||||
|
} else {
|
||||||
|
u16::from_be(self.sin6.sin6_port as u16).cmp(&u16::from_be(other.sin6.sin6_port as u16))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if self.sa.sa_family < other.sa.sa_family {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for InetAddress {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
unsafe {
|
||||||
|
state.write_u8(self.sa.sa_family as u8);
|
||||||
|
match self.sa.sa_family as u8 {
|
||||||
|
AF_INET => {
|
||||||
|
state.write_u16(self.sin.sin_port as u16);
|
||||||
|
state.write_u32(self.sin.sin_addr.s_addr as u32);
|
||||||
|
},
|
||||||
|
AF_INET6 => {
|
||||||
|
state.write_u16(self.sin6.sin6_port as u16);
|
||||||
|
state.write(&*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::vl1::inetaddress::InetAddress;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_layout() {
|
||||||
|
let mut tmp = InetAddress::new();
|
||||||
|
unsafe {
|
||||||
|
tmp.sa.sa_family = 0xf7;
|
||||||
|
if tmp.sin.sin_family != 0xf7 {
|
||||||
|
panic!("sin_family misaligned in union");
|
||||||
|
}
|
||||||
|
if tmp.sin6.sin6_family != 0xf7 {
|
||||||
|
panic!("sin6_family misaligned in union");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ pub mod packet;
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod identity;
|
pub mod identity;
|
||||||
|
pub mod inetaddress;
|
||||||
|
|
||||||
mod address;
|
mod address;
|
||||||
pub use address::Address;
|
pub use address::Address;
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl FragmentHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fragment = Buffer<FragmentHeader, { crate::vl1::protocol::PACKET_SIZE_MAX }>;
|
pub type Fragment = Buffer<FragmentHeader, { crate::vl1::protocol::PACKET_SIZE_MAX }>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -27,10 +27,14 @@ use crate::osdep as osdep;
|
||||||
* for each thread using options like SO_REUSEPORT and concurrent packet listening.
|
* for each thread using options like SO_REUSEPORT and concurrent packet listening.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[cfg(windows)] use winapi::um::winsock2 as winsock2;
|
#[cfg(windows)]
|
||||||
|
use winapi::um::winsock2 as winsock2;
|
||||||
|
|
||||||
#[cfg(windows)] pub(crate) type FastUDPRawOsSocket = winsock2::SOCKET;
|
#[cfg(windows)]
|
||||||
#[cfg(unix)] pub(crate) type FastUDPRawOsSocket = c_int;
|
pub(crate) type FastUDPRawOsSocket = winsock2::SOCKET;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub(crate) type FastUDPRawOsSocket = c_int;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result<FastUDPRawOsSocket, &'static str> {
|
fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result<FastUDPRawOsSocket, &'static str> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue