1199 lines
37 KiB
Rust
1199 lines
37 KiB
Rust
use std::{net::SocketAddr, sync::atomic::Ordering, time::Duration};
|
|
|
|
use crate::tcp::NatType;
|
|
use crate::{network::TunTapPacketHandler, utils::mac_to_string};
|
|
|
|
use crate::{
|
|
config::{NULL_MAC, REGISTER_INTERVAL},
|
|
pb::{
|
|
encode_to_tcp_message, encode_to_udp_message, SdlData, SdlEmpty, SdlPeerInfo, SdlQueryInfo,
|
|
SdlRegister, SdlRegisterAck, SdlStunProbeReply,
|
|
},
|
|
tcp::{get_tcp_conn, PacketType},
|
|
utils::{send_to_sock, Socket},
|
|
};
|
|
use etherparse::Ethernet2Header;
|
|
use num_enum::TryFromPrimitive;
|
|
use prost::Message;
|
|
use sdlan_sn_rs::utils::BROADCAST_MAC;
|
|
use sdlan_sn_rs::{
|
|
config::{AF_INET, AF_INET6},
|
|
peer::{is_sdlan_sock_equal, SdlanSock, V6Info},
|
|
utils::{
|
|
aes_decrypt, get_current_timestamp, get_sdlan_sock_from_socketaddr, is_multi_broadcast,
|
|
Mac, Result, SDLanError,
|
|
},
|
|
};
|
|
use std::sync::Arc;
|
|
|
|
use tracing::{debug, error, info};
|
|
|
|
use super::{EdgePeer, Node};
|
|
|
|
pub async fn read_and_parse_packet(
|
|
eee: &'static Node,
|
|
sock: &Socket,
|
|
timeout: Option<Duration>,
|
|
_is_multicast_sock: bool,
|
|
// cancel: CancellationToken,
|
|
) -> Result<()> {
|
|
let mut buf = vec![0; 3000];
|
|
let res;
|
|
if timeout.is_some() {
|
|
tokio::select! {
|
|
_ = tokio::time::sleep(timeout.unwrap()) => {
|
|
return Err(SDLanError::NormalError("timeouted"));
|
|
}
|
|
r = sock.recv_from(&mut buf) => {
|
|
res=r;
|
|
}
|
|
}
|
|
} else {
|
|
res = sock.recv_from(&mut buf).await;
|
|
}
|
|
debug!("read_and_parse packet, got packet");
|
|
// let res = sock.recv_from(&mut buf).await;
|
|
match res {
|
|
Ok((0, _)) => {
|
|
// received 0
|
|
error!("received zero bytes");
|
|
// return Ok(())
|
|
}
|
|
Err(e) => {
|
|
// error occured
|
|
error!("receive error occured: {:?}", e);
|
|
}
|
|
Ok((size, from)) => {
|
|
// size > 0
|
|
|
|
/*
|
|
if is_multicast_sock {
|
|
println!(
|
|
"xxxx got packet from multicast sock from {}",
|
|
from.to_string()
|
|
);
|
|
}
|
|
*/
|
|
|
|
buf.truncate(size);
|
|
match handle_packet(eee, from, &buf).await {
|
|
Ok(_) => {}
|
|
Err(e) => {
|
|
error!("failed to handle_packet: {:?}", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn handle_packet(eee: &'static Node, addr: SocketAddr, buf: &[u8]) -> Result<()> {
|
|
if buf.len() < 1 {
|
|
return Err(SDLanError::NormalError("buf length error"));
|
|
}
|
|
let Ok(pkt_type) = PacketType::try_from(buf[0]) else {
|
|
return Err(SDLanError::NormalError("invalid packet type"));
|
|
};
|
|
match pkt_type {
|
|
PacketType::Data => {
|
|
debug!("got data");
|
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
|
debug!("[PPP]Rx data from {}", from_sock.to_string());
|
|
if !eee.is_authorized() {
|
|
error!("dropping PACKET received before authorized");
|
|
return Ok(());
|
|
}
|
|
|
|
let Ok(data) = SdlData::decode(&buf[1..]) else {
|
|
error!("failed to decode to SDLData");
|
|
return Err(SDLanError::NormalError("failed to decode to SDLData"));
|
|
};
|
|
let Ok(src_mac) = data.src_mac.clone().try_into() else {
|
|
error!("failed to convert src mac");
|
|
return Err(SDLanError::NormalError("failed to convert vec to Mac"));
|
|
};
|
|
// let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
|
if data.is_p2p {
|
|
debug!("[P2P] Rx data from {}", from_sock.to_string());
|
|
} else {
|
|
debug!(
|
|
"[PsP] Rx data from {} via {}",
|
|
mac_to_string(&src_mac),
|
|
from_sock.to_string()
|
|
);
|
|
}
|
|
if data.is_p2p {
|
|
let from_sock = from_sock.deepcopy();
|
|
tokio::spawn(async move {
|
|
check_peer_registration_needed(
|
|
eee,
|
|
!data.is_p2p,
|
|
src_mac,
|
|
NatType::NoNat,
|
|
&None,
|
|
&from_sock,
|
|
)
|
|
.await;
|
|
});
|
|
}
|
|
handle_tun_packet(eee, &from_sock, !data.is_p2p, data).await;
|
|
}
|
|
PacketType::StunProbeReply => {
|
|
debug!("got StunProbeReply");
|
|
let Ok(reply) = SdlStunProbeReply::decode(&buf[1..]) else {
|
|
error!("failed to decode SdlStunReply");
|
|
return Ok(());
|
|
};
|
|
println!("got stun probe reply: {:?}", reply);
|
|
eee.send_nat_probe_reply(reply.cookie, reply).await;
|
|
}
|
|
PacketType::StunReply => {
|
|
debug!("got stun reply");
|
|
// stun reply, like pong
|
|
}
|
|
PacketType::Register => {
|
|
debug!("got Register");
|
|
if !eee.is_authorized() {
|
|
error!("dropping REGISTER received before authorized");
|
|
return Ok(());
|
|
}
|
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
|
let _ = handle_packet_register(eee, &buf[1..], false, &from_sock).await;
|
|
}
|
|
PacketType::RegisterACK => {
|
|
debug!("got RegisterACK");
|
|
if !eee.is_authorized() {
|
|
error!("dropping REGISTER received before authorized");
|
|
return Ok(());
|
|
}
|
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
|
let _ = handle_packet_register_ack(eee, &buf[1..], &from_sock).await;
|
|
}
|
|
other => {
|
|
error!("udp not processing {:?}", other);
|
|
}
|
|
}
|
|
/*
|
|
let pkt_type = buf[0].into();
|
|
debug!("got packet {} bytes", buf.len());
|
|
let (cmn, slice) = packet::decode_common(&buf)?;
|
|
println!("got packet: {:?}", cmn.pc);
|
|
|
|
if !eee.is_authorized() {
|
|
error!("unauthorized, returning");
|
|
return Ok(());
|
|
}
|
|
|
|
let from_sn = (cmn.flags & config::SDLAN_FLAGS_FROM_SN) != 0;
|
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
|
if from_sn {
|
|
if !eee.sn_is_known(&from_sock) {
|
|
error!("drop incoming data from unknown supernode");
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
let res = match cmn.pc {
|
|
PacketType::PKTPacket => {
|
|
// handle packet
|
|
handle_packet_packet(eee, cmn, slice, from_sn, &from_sock).await
|
|
}
|
|
PacketType::PKTRegister => {
|
|
// handle register from other peer
|
|
handle_packet_register(eee, slice, from_sn, &from_sock).await
|
|
}
|
|
PacketType::PKTRegisterACK => {
|
|
// handle register ack from other peer
|
|
handle_packet_register_ack(eee, slice, &from_sock).await
|
|
}
|
|
PacketType::PKTRegisterSuperAcknowledge => {
|
|
// handle register super acknowledge
|
|
handle_packet_register_super_acknowledge(eee)
|
|
}
|
|
PacketType::PKTRegisterSuperACK => {
|
|
// handle register super ack
|
|
handle_packet_register_super_ack(eee, cmn, slice)
|
|
}
|
|
PacketType::PKTRegisterSuperNAK => {
|
|
// handle register super nak
|
|
handle_packet_register_super_nak(eee, cmn, slice)
|
|
}
|
|
PacketType::PKTPeerInfo => {
|
|
// handle peer info from sn
|
|
handle_packet_peer_info(eee, slice).await
|
|
}
|
|
PacketType::PKTCommand => {
|
|
// handle command
|
|
Ok(())
|
|
}
|
|
other => {
|
|
error!("unknown packet {:?}", other);
|
|
Ok(())
|
|
}
|
|
};
|
|
|
|
if let Err(e) = res {
|
|
error!("handle packet error occured: {}", e.as_str());
|
|
}
|
|
|
|
*/
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn handle_packet_peer_info(
|
|
eee: &'static Node,
|
|
// cmn: Common<'_>,
|
|
body: &[u8],
|
|
//sender_sock: &SdlanSock,
|
|
) -> Result<()> {
|
|
let Ok(pi) = SdlPeerInfo::decode(body) else {
|
|
error!("failed to decode PEER_INFO");
|
|
return Ok(());
|
|
};
|
|
|
|
debug!("got peer info: {:?}", pi);
|
|
let Ok(dst_mac) = pi.dst_mac.try_into() else {
|
|
error!("mac is null");
|
|
return Ok(());
|
|
};
|
|
|
|
if pi.v4_info.is_none() {
|
|
error!("PEER's v4_info is none");
|
|
return Ok(());
|
|
}
|
|
|
|
let v4 = pi.v4_info.unwrap();
|
|
let Ok(v4_u32) = v4.v4.try_into() else {
|
|
error!("failed to convert v4");
|
|
return Ok(());
|
|
};
|
|
let remote_nat_byte = v4.nat_type as u8;
|
|
let remote_nat = match NatType::try_from(remote_nat_byte) {
|
|
Ok(nat) => nat,
|
|
Err(_) => NatType::Invalid,
|
|
};
|
|
|
|
let mut v6: [u8; 16] = [0; 16];
|
|
let mut v6_port = 0;
|
|
if let Some(v6_info) = pi.v6_info {
|
|
if let Ok(v6_bytes) = v6_info.v6.as_slice().try_into() {
|
|
v6 = v6_bytes;
|
|
v6_port = v6_info.port as u16;
|
|
}
|
|
}
|
|
// let src_ip = u32::from_be_bytes(v4_u32);
|
|
|
|
if dst_mac == NULL_MAC {
|
|
// pong from sn
|
|
} else {
|
|
let pending = eee.pending_peers.peers.get_mut(&dst_mac);
|
|
match pending {
|
|
Some(mut v) => {
|
|
let sock = SdlanSock {
|
|
family: AF_INET,
|
|
port: v4.port as u16,
|
|
v4: v4_u32,
|
|
v6: [0; 16],
|
|
};
|
|
v.nat_type = remote_nat;
|
|
v.sock = sock.deepcopy();
|
|
// v.sock = sock.deepcopy();
|
|
|
|
info!(
|
|
"Rx PEERINFO for {}: is at {}",
|
|
mac_to_string(&dst_mac),
|
|
sock.to_string()
|
|
);
|
|
let mut v6_info = None;
|
|
if v6_port != 0 {
|
|
v6_info = Some(V6Info { port: v6_port, v6 })
|
|
}
|
|
send_register(eee, remote_nat, &sock, dst_mac, &v6_info).await;
|
|
}
|
|
None => {
|
|
debug!("Rx PEERINFO unknown peer: {}", mac_to_string(&dst_mac));
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/*
|
|
fn handle_packet_register_super_nak(eee: &Node, _cmn: Common<'_>, slice: &[u8]) -> Result<()> {
|
|
let nak: RegisterSuperNAK = serde_json::from_slice(slice)?;
|
|
if nak.src_ip == eee.device_config.get_ip() {
|
|
eee.set_authorized(false, Vec::new());
|
|
error!("unauthorized");
|
|
} else {
|
|
eee.known_peers.delete_peer_with_ip(&nak.src_ip);
|
|
eee.pending_peers.delete_peer_with_ip(&nak.src_ip);
|
|
}
|
|
Ok(())
|
|
}
|
|
*/
|
|
|
|
/*
|
|
fn handle_packet_register_super_ack(eee: &Node, _cmn: Common<'_>, slice: &[u8]) -> Result<()> {
|
|
debug!("handling REGISTER_SUPER_ACK");
|
|
let ack: RegisterSuperACK = serde_json::from_slice(slice)?;
|
|
|
|
if ack.dev_addr.net_addr != 0 && ack.dev_addr.net_bit_len != 0 {
|
|
// i'm authorized or moved;
|
|
// eee.device
|
|
eee.device_config
|
|
.set_ip(ack.dev_addr.net_addr, ack.dev_addr.net_bit_len);
|
|
debug!(
|
|
"ip addr assigned: {}/{}",
|
|
ip_to_string(&ack.dev_addr.net_addr),
|
|
ack.dev_addr.net_bit_len
|
|
)
|
|
}
|
|
|
|
let Ok(private_key) = load_private_key_file(".client/id_rsa") else {
|
|
error!("failed to load private key");
|
|
return Err(SDLanError::NormalError("failed to load private key"));
|
|
};
|
|
|
|
let encrypt_key = rsa_decrypt(&private_key, &ack.encrypted_key)?;
|
|
let header_key = rsa_decrypt(&private_key, &ack.header_key)?;
|
|
|
|
eee.config
|
|
.super_attempts
|
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
|
eee.stats
|
|
.last_sup
|
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
|
debug!("changed to Authorized");
|
|
eee.set_authorized(true, encrypt_key);
|
|
|
|
eee.device.reload_config(&eee.device_config);
|
|
eee.known_peers.clear();
|
|
eee.pending_peers.clear();
|
|
Ok(())
|
|
}
|
|
*/
|
|
|
|
/*
|
|
fn handle_packet_register_super_acknowledge(
|
|
eee: &Node,
|
|
// cmn: Common<'_>,
|
|
// slice: &[u8],
|
|
) -> Result<()> {
|
|
debug!("handling REGISTER_SUPER_ACKNOWLEDGE");
|
|
// TODO: should check the common and the slice content.
|
|
eee.config
|
|
.super_attempts
|
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
|
eee.stats
|
|
.last_sup
|
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
|
Ok(())
|
|
}
|
|
*/
|
|
|
|
async fn handle_packet_register_ack(
|
|
eee: &Node,
|
|
// cmn: Common<'_>,
|
|
body: &[u8],
|
|
sender_sock: &SdlanSock,
|
|
) -> Result<()> {
|
|
let Ok(ack) = SdlRegisterAck::decode(body) else {
|
|
error!("failed to decode REGISTER_ACK");
|
|
return Ok(());
|
|
};
|
|
|
|
let origin_sender = sender_sock;
|
|
let Ok(src_mac) = ack.src_mac.try_into() else {
|
|
error!("failed to get src_mac");
|
|
return Ok(());
|
|
};
|
|
let Ok(dst_mac) = ack.dst_mac.try_into() else {
|
|
error!("failed to get dst_mac");
|
|
return Ok(());
|
|
};
|
|
|
|
let via_multicast = is_multi_broadcast(&dst_mac);
|
|
if via_multicast && src_mac == eee.device_config.get_mac() {
|
|
debug!("skipping register ack from self");
|
|
return Ok(());
|
|
}
|
|
|
|
debug!(
|
|
"Rx REGISTER ACK from {} [{}] to {} via {}",
|
|
mac_to_string(&src_mac),
|
|
origin_sender.to_string(),
|
|
mac_to_string(&dst_mac),
|
|
sender_sock.to_string(),
|
|
);
|
|
peer_set_p2p_confirmed(eee, src_mac, sender_sock);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn handle_packet_register(
|
|
eee: &'static Node,
|
|
// cmn: Common<'_>,
|
|
body: &[u8],
|
|
from_sn: bool,
|
|
sender_sock: &SdlanSock,
|
|
) -> Result<()> {
|
|
if !eee.is_authorized() {
|
|
error!("drop register due to not authed");
|
|
return Ok(());
|
|
}
|
|
|
|
let Ok(reg) = SdlRegister::decode(body) else {
|
|
error!("failed to decode REGISTER");
|
|
return Ok(());
|
|
};
|
|
|
|
let origin_sender = sender_sock;
|
|
|
|
let Ok(src_mac) = reg.src_mac.clone().try_into() else {
|
|
error!("[REGISTER] failed to get src_mac");
|
|
return Ok(());
|
|
};
|
|
let Ok(dst_mac) = reg.dst_mac.clone().try_into() else {
|
|
error!("[REGISTER] failed to get dst_mac");
|
|
return Ok(());
|
|
};
|
|
|
|
let via_multicast = is_multi_broadcast(&dst_mac);
|
|
if via_multicast && src_mac == eee.device_config.get_mac() {
|
|
debug!("skipping register from self");
|
|
return Ok(());
|
|
}
|
|
|
|
let mut remote_nat = NatType::NoNat;
|
|
if !from_sn {
|
|
info!(
|
|
"[P2P] Rx REGISTER from {}, deleting from pending",
|
|
sender_sock.to_string()
|
|
);
|
|
if let Some((_, v)) = eee.pending_peers.delete_peer_with_mac(&src_mac) {
|
|
remote_nat = v.get_nat_type();
|
|
}
|
|
send_register_ack(eee, origin_sender, ®).await;
|
|
info!("sent back REGISTERACK");
|
|
} else {
|
|
info!(
|
|
"[PsP] Rx REGISTER from {} [{}] to {} via {}",
|
|
mac_to_string(&src_mac),
|
|
mac_to_string(&dst_mac),
|
|
sender_sock.to_string(),
|
|
origin_sender.to_string(),
|
|
);
|
|
}
|
|
// check_peer_registration_needed(eee, from_sn, reg.src_ip, &None, origin_sender).await;
|
|
check_peer_registration_needed(eee, from_sn, src_mac, remote_nat, &None, origin_sender).await;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/*
|
|
async fn handle_packet_packet(
|
|
eee: &Node,
|
|
cmn: Common<'_>,
|
|
body: &[u8],
|
|
from_sn: bool,
|
|
sender_sock: &SdlanSock,
|
|
) -> Result<()> {
|
|
if eee.stats.last_sup.load(Ordering::Relaxed) == 0 {
|
|
error!("dropping PACKET received before first registration with sn");
|
|
return Ok(());
|
|
}
|
|
let has_sock = cmn.flags & config::SDLAN_FLAGS_SOCKET != 0;
|
|
let has_v6 = cmn.flags & config::SDLAN_FLAGS_HAS_V6 != 0;
|
|
let pkt = packet::Packet::unmarshal(body, has_sock, has_v6)?;
|
|
|
|
// let mut orig_sender: &SdlanSock = sender_sock;
|
|
|
|
// here, the origin sender ref should be checked
|
|
// if let Some(ref sk) = pkt.sock {
|
|
// orig_sender = sk;
|
|
// }
|
|
// println!("orig_sender: {:?}", orig_sender);
|
|
|
|
let mut origin_sender = sender_sock;
|
|
if let Some(ref k) = pkt.sock {
|
|
origin_sender = k;
|
|
}
|
|
println!("orig_sender: {:?}", origin_sender);
|
|
if !from_sn {
|
|
// data from other peer
|
|
debug!("[P2P] Rx data from {}", sender_sock.to_string());
|
|
eee.pending_peers.peers.remove(&pkt.src_ip);
|
|
} else {
|
|
// from sn, sock should not be None
|
|
debug!(
|
|
"[PsP] Rx data from {} (via {})",
|
|
origin_sender.to_string(),
|
|
sender_sock.to_string()
|
|
);
|
|
}
|
|
|
|
check_peer_registration_needed(eee, from_sn, pkt.src_ip, &pkt.v6_info, origin_sender).await;
|
|
// handle_tun_packet(eee, from_sn, pkt).await;
|
|
|
|
Ok(())
|
|
}
|
|
*/
|
|
|
|
pub async fn check_peer_registration_needed(
|
|
eee: &'static Node,
|
|
from_sn: bool,
|
|
src_mac: Mac,
|
|
remote_nat: NatType,
|
|
_v6_info: &Option<V6Info>,
|
|
peer_sock: &SdlanSock,
|
|
) {
|
|
let mut p = eee.known_peers.peers.get(&src_mac);
|
|
let last_seen;
|
|
let now;
|
|
match p {
|
|
None => {
|
|
debug!("check peer registration needed, not found in known peers");
|
|
let _ = register_with_new_peer(eee, from_sn, src_mac, _v6_info, remote_nat, peer_sock)
|
|
.await;
|
|
return;
|
|
// unimplemented!();
|
|
}
|
|
Some(k) => {
|
|
// let mut ipv4_to_ipv6 = false;
|
|
now = get_current_timestamp();
|
|
if !from_sn {
|
|
k.last_p2p.store(now, Ordering::Relaxed);
|
|
}
|
|
let origin_family = k.sock.family;
|
|
if origin_family != peer_sock.family {
|
|
return;
|
|
}
|
|
/*
|
|
if peer_sock.family == AF_INET6 && k.sock.read().unwrap().family == AF_INET {
|
|
println!("changing to ipv6");
|
|
*k.sock.write().unwrap() = peer_sock.deepcopy();
|
|
ipv4_to_ipv6 = true;
|
|
} else {
|
|
println!("already is ipv6");
|
|
}
|
|
*/
|
|
last_seen = k.last_seen.load(Ordering::Relaxed);
|
|
// more than 3 seconds
|
|
}
|
|
}
|
|
|
|
if now - last_seen > 300 {
|
|
check_known_peer_sock_change(eee, from_sn, src_mac, peer_sock, now, false).await;
|
|
}
|
|
}
|
|
|
|
async fn check_known_peer_sock_change(
|
|
eee: &'static Node,
|
|
from_sn: bool,
|
|
mac: Mac,
|
|
// v6_info: &Option<V6Info>,
|
|
// dev_addr: &IpSubnet,
|
|
peersock: &SdlanSock,
|
|
when: u64,
|
|
ipv4_to_ipv6: bool,
|
|
) {
|
|
if is_multi_broadcast(&mac) {
|
|
return;
|
|
}
|
|
let mut delete_from_known_peers = false;
|
|
let remote_nat;
|
|
match eee.known_peers.peers.get_mut(&mac) {
|
|
Some(p) => {
|
|
if !ipv4_to_ipv6 && !is_sdlan_sock_equal(&p.sock, peersock) {
|
|
if !from_sn {
|
|
info!(
|
|
"peer changed: {}: {} -> {}",
|
|
mac_to_string(&mac),
|
|
&p.sock.to_string(),
|
|
peersock.to_string()
|
|
);
|
|
delete_from_known_peers = true;
|
|
remote_nat = p.get_nat_type();
|
|
} else {
|
|
// from sn, sn could see a different sock with us, just ignore it
|
|
return;
|
|
}
|
|
} else {
|
|
p.last_seen.store(when, Ordering::Relaxed);
|
|
return;
|
|
// from sn, sn could see a different sock with us, just ignore it
|
|
}
|
|
}
|
|
None => return,
|
|
}
|
|
|
|
if delete_from_known_peers {
|
|
eee.known_peers.delete_peer_with_mac(&mac);
|
|
error!("known peers is deleted");
|
|
register_with_new_peer(eee, from_sn, mac, &None, remote_nat, peersock).await;
|
|
}
|
|
}
|
|
|
|
async fn register_with_new_peer(
|
|
eee: &'static Node,
|
|
from_sn: bool,
|
|
mac: Mac,
|
|
v6_info: &Option<V6Info>,
|
|
// dev_addr: &IpSubnet,
|
|
remote_nat: NatType,
|
|
peersock: &SdlanSock,
|
|
) {
|
|
let now = get_current_timestamp();
|
|
let entry = eee.pending_peers.peers.entry(mac);
|
|
let mut new_created = false;
|
|
|
|
let mut scan = entry.or_insert_with(|| {
|
|
new_created = true;
|
|
let temp = EdgePeer::new(0, eee.device_config.get_net_bit(), peersock, &None, now);
|
|
temp
|
|
});
|
|
|
|
if new_created {
|
|
debug!(
|
|
"===> new pending {} => {}",
|
|
mac_to_string(&mac),
|
|
peersock.to_string(),
|
|
);
|
|
|
|
if from_sn {
|
|
// should send register to peer
|
|
if eee.config.register_ttl == 1 {
|
|
/* We are DMZ host or port is directly accessible. Just let peer to send back the ack */
|
|
} else if eee.config.register_ttl > 1 {
|
|
/*
|
|
let mut alter = 16;
|
|
if let Ok(ttl) = eee.udp_sock_v4.ttl() {
|
|
let mut temp = peersock.deepcopy();
|
|
send_register(eee, remote_nat, &temp, mac, v6_info).await;
|
|
|
|
let _ = eee.udp_sock_v4.set_ttl(eee.config.register_ttl as u32);
|
|
while alter > 0 {
|
|
temp.port += 1;
|
|
send_register(eee, &temp, mac, v6_info).await;
|
|
alter -= 1;
|
|
}
|
|
let _ = eee.udp_sock_v4.set_ttl(ttl);
|
|
}
|
|
*/
|
|
} else {
|
|
// Normal STUN
|
|
send_register(eee, remote_nat, peersock, mac, v6_info).await;
|
|
}
|
|
// 发送给sn
|
|
send_register(
|
|
eee,
|
|
remote_nat,
|
|
&eee.config.super_nodes
|
|
[eee.config.super_node_index.load(Ordering::Relaxed) as usize],
|
|
mac,
|
|
v6_info,
|
|
)
|
|
.await;
|
|
} else {
|
|
// P2P register, send directly
|
|
send_register(eee, remote_nat, peersock, mac, v6_info).await;
|
|
}
|
|
register_with_local_peers(eee).await;
|
|
} else {
|
|
scan.sock = peersock.deepcopy();
|
|
}
|
|
|
|
scan.last_seen
|
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
|
}
|
|
|
|
async fn register_with_local_peers(eee: &'static Node) {
|
|
if !eee.config._drop_multicast {
|
|
send_register(
|
|
eee,
|
|
NatType::NoNat,
|
|
&eee.multicast_sock,
|
|
BROADCAST_MAC,
|
|
&None,
|
|
)
|
|
.await;
|
|
}
|
|
}
|
|
|
|
async fn send_register(
|
|
eee: &'static Node,
|
|
remote_nat: NatType,
|
|
sock: &SdlanSock,
|
|
mac: Mac,
|
|
_v6_info: &Option<V6Info>,
|
|
) {
|
|
if !eee.config.allow_p2p {
|
|
debug!("skipping register as p2p is disabled");
|
|
return;
|
|
}
|
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
|
if network_id == 0 {
|
|
error!("not authed");
|
|
return;
|
|
}
|
|
|
|
let self_nat = eee.get_nat_type();
|
|
|
|
let register = SdlRegister {
|
|
network_id: network_id,
|
|
src_mac: Vec::from(eee.device_config.get_mac()),
|
|
// src_ip: eee.device_config.get_ip(),
|
|
dst_mac: Vec::from(mac),
|
|
// dst_ip: u32::from_be_bytes(sock.v4),
|
|
};
|
|
|
|
let msg = encode_to_udp_message(Some(register), PacketType::Register as u8).unwrap();
|
|
|
|
let _ = send_to_sock(eee, &msg, sock).await;
|
|
if let Some(ref v6_info) = _v6_info {
|
|
let _ = send_to_sock(
|
|
eee,
|
|
&msg,
|
|
&SdlanSock {
|
|
family: AF_INET6,
|
|
port: v6_info.port,
|
|
v4: [0; 4],
|
|
v6: v6_info.v6,
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
let mut need_guess_port = false;
|
|
match self_nat {
|
|
NatType::PortRestricted => {
|
|
if let NatType::Symmetric = remote_nat {
|
|
need_guess_port = true;
|
|
}
|
|
}
|
|
NatType::Symmetric => {
|
|
if let NatType::PortRestricted = remote_nat {
|
|
need_guess_port = true;
|
|
}
|
|
}
|
|
_other => {}
|
|
}
|
|
|
|
if need_guess_port {
|
|
println!("need guess port");
|
|
}
|
|
|
|
/*
|
|
let mut target_sock_v4 = sock.deepcopy();
|
|
tokio::spawn(async move {
|
|
for i in 1..=10 {
|
|
target_sock_v4.port += i;
|
|
let _ = send_to_sock(eee, &msg, &target_sock_v4).await;
|
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
}
|
|
for i in 1..=10 {
|
|
target_sock_v4.port -= i;
|
|
let _ = send_to_sock(eee, &msg, &target_sock_v4).await;
|
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
}
|
|
});
|
|
*/
|
|
/*
|
|
let key = eee.get_header_key();
|
|
if key.len() > 0 {
|
|
if let Ok(cnt) = encode_packet_encrypted(&cmn, &r, key.as_slice()) {
|
|
let _ = send_to_sock_v4_and_v6(eee, &cnt, sock, v6_info).await;
|
|
}
|
|
} else {
|
|
error!("not authed");
|
|
}
|
|
*/
|
|
}
|
|
|
|
async fn handle_tun_packet(
|
|
eee: &Node,
|
|
_from_sock: &SdlanSock,
|
|
_from_sn: bool,
|
|
pkt: SdlData, //orig_sender: &SdlanSock
|
|
) {
|
|
let payload = pkt.data;
|
|
let key = eee.get_encrypt_key();
|
|
if key.len() == 0 {
|
|
// check the encrypt key
|
|
error!("packet encrypt key not provided");
|
|
return;
|
|
}
|
|
|
|
let origin = aes_decrypt(key.as_slice(), &payload);
|
|
if let Err(_e) = origin {
|
|
error!("failed to decrypt original data");
|
|
return;
|
|
}
|
|
let data = origin.unwrap();
|
|
if let Err(e) = eee
|
|
.device
|
|
.handle_packet_from_net(&data, key.as_slice())
|
|
.await
|
|
{
|
|
error!("failed to handle packet from net: {}", e.to_string());
|
|
}
|
|
/*
|
|
let msg_size = data.len() as u64;
|
|
|
|
let Ok(dst_mac) = pkt.dst_mac.try_into() else {
|
|
error!("[PACKET] failed to decode dst_mac");
|
|
return;
|
|
};
|
|
|
|
if from_sn {
|
|
if is_multi_broadcast(&dst_mac) {
|
|
eee.stats
|
|
.rx_broadcast
|
|
.fetch_add(msg_size, Ordering::Relaxed);
|
|
}
|
|
eee.stats.rx_sup.fetch_add(msg_size, Ordering::Relaxed);
|
|
eee.stats.last_sup.store(now, Ordering::Relaxed);
|
|
} else {
|
|
eee.stats.rx_p2p.fetch_add(msg_size, Ordering::Relaxed);
|
|
eee.stats.last_p2p.store(now, Ordering::Relaxed);
|
|
}
|
|
|
|
// TODO: parse the mac
|
|
debug!("got packet from sock, will send to tun");
|
|
match Ethernet2Header::from_slice(&data) {
|
|
Ok((hdr, rest)) => {
|
|
if rest.len() < 4 {
|
|
error!("payload length error");
|
|
return;
|
|
}
|
|
let crc_code = &rest[(rest.len() - 4)..rest.len()];
|
|
let rest = &rest[..(rest.len() - 4)];
|
|
|
|
let crc_hash: crc::Crc<u32> = crc::Crc::<u32>::new(&crc::CRC_32_CKSUM);
|
|
let ck = CRC_HASH.checksum(&data[..(data.len()) - 4]);
|
|
let sent_ck = u32::from_be_bytes(crc_code.try_into().unwrap());
|
|
debug!("ck = {}, sent_ck = {}", ck, sent_ck);
|
|
|
|
debug!("ip size is {}", rest.len());
|
|
let edge = get_edge();
|
|
let self_mac = edge.device_config.get_mac();
|
|
|
|
/*
|
|
if hdr.destination != self_mac && hdr.destination != BROADCAST_MAC {
|
|
error!(
|
|
"packet to [{:?}] not direct to us",
|
|
mac_to_string(&hdr.destination)
|
|
);
|
|
return;
|
|
}
|
|
*/
|
|
|
|
if hdr.ether_type == ARP {
|
|
let mut arp = ArpHdr::from_slice(&data);
|
|
let self_ip = edge.device_config.get_ip();
|
|
|
|
println!("self_ip: {:?}", self_ip.to_be_bytes());
|
|
let from_ip = ((arp.sipaddr[0] as u32) << 16) + arp.sipaddr[1] as u32;
|
|
println!("from_ip: {:?}", from_ip.to_be_bytes());
|
|
let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32;
|
|
println!("dest_ip: {:?}", dest_ip.to_be_bytes());
|
|
|
|
match arp.opcode {
|
|
ARP_REQUEST => {
|
|
// handle ARP REQUEST
|
|
debug!("got ARP REQUEST");
|
|
if arp.ethhdr.dest != [0xff; 6] {
|
|
println!("ARP REQUEST not broadcast");
|
|
return;
|
|
}
|
|
if dest_ip == self_ip {
|
|
send_arp_request(ArpRequestInfo::Set {
|
|
ip: from_ip,
|
|
mac: arp.shwaddr,
|
|
})
|
|
.await;
|
|
// target to us
|
|
arp.opcode = ARP_REPLY;
|
|
arp.dhwaddr = arp.shwaddr;
|
|
arp.shwaddr = self_mac;
|
|
arp.ethhdr.src = self_mac;
|
|
arp.ethhdr.dest = arp.dhwaddr;
|
|
|
|
arp.dipaddr = arp.sipaddr;
|
|
|
|
arp.sipaddr =
|
|
[((self_ip >> 16) & 0xffff) as u16, (self_ip & 0xffff) as u16];
|
|
|
|
let data = arp.marshal_to_bytes();
|
|
let Ok(encrypted) = aes_encrypt(key.as_slice(), &data) else {
|
|
error!("failed to encrypt arp reply");
|
|
return;
|
|
};
|
|
|
|
let data = SdlData {
|
|
is_p2p: true,
|
|
ttl: 2,
|
|
network_id: edge.network_id.load(Ordering::Relaxed),
|
|
src_mac: Vec::from(self_mac),
|
|
dst_mac: Vec::from(arp.dhwaddr),
|
|
data: encrypted,
|
|
};
|
|
|
|
let v =
|
|
encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap();
|
|
println!(
|
|
"xxxx send arp reply to [{}], selfmac=[{}]",
|
|
mac_to_string(&arp.dhwaddr),
|
|
mac_to_string(&self_mac)
|
|
);
|
|
send_packet_to_net(edge, arp.dhwaddr, &v, 0).await;
|
|
// send_to_sock(edge, &v, from_sock);
|
|
// edge.sock.send(v).await;
|
|
}
|
|
}
|
|
ARP_REPLY => {
|
|
println!("got arp reply",);
|
|
|
|
println!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
|
|
if dest_ip == self_ip {
|
|
send_arp_request(ArpRequestInfo::Set {
|
|
ip: from_ip,
|
|
mac: arp.shwaddr,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
other => {
|
|
println!("unknown arp type info");
|
|
}
|
|
}
|
|
} else {
|
|
match IpHeaders::from_slice(rest) {
|
|
Ok((iphdr, _)) => {
|
|
let Some(ipv4) = iphdr.ipv4() else {
|
|
error!("not ipv4, dropping");
|
|
return;
|
|
};
|
|
let ip = u32::from_be_bytes(ipv4.0.source);
|
|
let mac = hdr.source;
|
|
if !is_multi_broadcast(&mac) {
|
|
send_arp_request(ArpRequestInfo::Set { ip, mac }).await;
|
|
}
|
|
}
|
|
Err(e) => {
|
|
error!("failed to parse ip header, dropping");
|
|
return;
|
|
}
|
|
}
|
|
|
|
println!("got ip packet");
|
|
println!("got data: {:?}", rest);
|
|
match edge.device.send(rest) {
|
|
Ok(size) => {
|
|
debug!("send to tun {} bytes", size);
|
|
}
|
|
Err(e) => {
|
|
error!("failed to send to device: {}", e.to_string());
|
|
}
|
|
}
|
|
// edge.tun.send_data_to_tun(Vec::from(hdr.1)).await;
|
|
}
|
|
}
|
|
Err(e) => {
|
|
error!("failed to parse tap packet: {}", e);
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
async fn send_register_ack(eee: &Node, orig_sender: &SdlanSock, reg: &SdlRegister) {
|
|
if !eee.config.allow_p2p {
|
|
debug!("Skipping REGISTER ACK as P2P is disallowed");
|
|
return;
|
|
}
|
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
|
if network_id == 0 {
|
|
error!("not authed");
|
|
return;
|
|
}
|
|
let src_mac = reg.src_mac.clone();
|
|
let ack = SdlRegisterAck {
|
|
network_id,
|
|
src_mac: Vec::from(eee.device_config.get_mac()),
|
|
dst_mac: src_mac,
|
|
};
|
|
let Ok(ack) = encode_to_udp_message(Some(ack), PacketType::RegisterACK as u8) else {
|
|
error!("failed to encode to udp message");
|
|
return;
|
|
};
|
|
let _ = send_to_sock(eee, &ack, orig_sender).await;
|
|
}
|
|
|
|
fn peer_set_p2p_confirmed(eee: &Node, src_mac: Mac, sender_sock: &SdlanSock) {
|
|
// let mut scan = eee.pending_peers.get_peer(&src_mac);
|
|
let scan = eee.pending_peers.peers.remove(&src_mac);
|
|
|
|
if let None = scan {
|
|
error!(
|
|
"failed to find sender in pending peer: {}",
|
|
sender_sock.to_string()
|
|
);
|
|
return;
|
|
}
|
|
let (_, scan) = scan.unwrap();
|
|
|
|
{
|
|
let entry = eee.known_peers.peers.entry(src_mac);
|
|
let mut scan2 = entry.or_insert(scan);
|
|
scan2.sock = sender_sock.deepcopy();
|
|
|
|
let now = get_current_timestamp();
|
|
scan2.last_p2p.store(now, Ordering::Relaxed);
|
|
scan2.last_seen.store(now, Ordering::Relaxed);
|
|
}
|
|
|
|
let mac_string = mac_to_string(&src_mac);
|
|
let sock_string = sender_sock.to_string();
|
|
info!(
|
|
"P2P connection established: {} [{}]",
|
|
&mac_string, &sock_string,
|
|
);
|
|
// eee.known_peers.insert_peer(src_mac, scan);
|
|
debug!("==> new peer: {} -> {}", &mac_string, &sock_string,);
|
|
}
|
|
|
|
pub async fn check_query_peer_info(eee: &'static Node, mac: Mac) {
|
|
let scan: Arc<EdgePeer>;
|
|
let now = get_current_timestamp();
|
|
|
|
let last_sent_query;
|
|
let mut need_send_query = false;
|
|
{
|
|
let entry = eee.pending_peers.peers.entry(mac);
|
|
|
|
let sock = SdlanSock {
|
|
family: AF_INET,
|
|
port: 0,
|
|
v4: [0; 4],
|
|
v6: [0; 16],
|
|
};
|
|
let peer = EdgePeer::new(
|
|
// mac,
|
|
0,
|
|
eee.device_config.get_net_bit(),
|
|
&sock,
|
|
&None,
|
|
now,
|
|
);
|
|
debug!("insert peer {} to pending", mac_to_string(&mac));
|
|
let val = entry.or_insert(peer);
|
|
last_sent_query = val.last_sent_query.load(Ordering::Relaxed);
|
|
if now - last_sent_query > (REGISTER_INTERVAL as u64) {
|
|
need_send_query = true;
|
|
val.last_sent_query.store(now, Ordering::Relaxed);
|
|
}
|
|
}
|
|
|
|
debug!(
|
|
"now={}, last_sent_query={}, REGISTER_INTERVAL={}",
|
|
now, last_sent_query, REGISTER_INTERVAL,
|
|
);
|
|
if need_send_query {
|
|
/*
|
|
send_register(
|
|
eee,
|
|
&eee.config.super_nodes[eee.config.super_node_index.load(Ordering::Relaxed) as usize],
|
|
&None,
|
|
)
|
|
.await;
|
|
*/
|
|
debug!("sending query for {}", mac_to_string(&mac));
|
|
register_with_local_peers(eee).await;
|
|
send_query_peer(eee, mac).await;
|
|
}
|
|
}
|
|
|
|
async fn send_query_peer(eee: &Node, dst_mac: Mac) -> Result<()> {
|
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
|
|
|
if network_id == 0 {
|
|
error!("not authed");
|
|
return Err(SDLanError::NormalError("not connected"));
|
|
}
|
|
let query = SdlQueryInfo {
|
|
dst_mac: Vec::from(dst_mac),
|
|
};
|
|
|
|
let Ok(content) = encode_to_tcp_message(
|
|
Some(query),
|
|
eee.get_next_packet_id(),
|
|
PacketType::QueryInfo as u8,
|
|
) else {
|
|
error!("failed to encode query");
|
|
return Err(SDLanError::NormalError("encode query error"));
|
|
};
|
|
let tcp_conn = get_tcp_conn();
|
|
tcp_conn.send(&content).await
|
|
}
|
|
|
|
pub async fn ping_to_sn() {
|
|
let Ok(msg) = encode_to_tcp_message::<SdlEmpty>(None, 0, PacketType::Ping as u8) else {
|
|
error!("failed to encode ping");
|
|
return;
|
|
};
|
|
debug!("ping to sn");
|
|
let tcp_conn = get_tcp_conn();
|
|
if let Err(e) = tcp_conn.send(&msg).await {
|
|
error!("failed to ping to sn: {:?}", e);
|
|
}
|
|
}
|
|
|
|
/*
|
|
pub async fn update_supernode_reg(eee: &Node) {
|
|
let now = get_current_timestamp();
|
|
let authed = eee.is_authorized();
|
|
let last_reg = eee.last_register_req.load(Ordering::Relaxed);
|
|
if !authed {
|
|
if now > (last_reg + (REGISTER_INTERVAL as u64) / 10) {
|
|
debug!("update supernode reg, fast retry");
|
|
} else {
|
|
return;
|
|
}
|
|
} else if now < (last_reg + REGISTER_INTERVAL as u64) {
|
|
return;
|
|
}
|
|
|
|
if eee.config.super_attempts.load(Ordering::Relaxed) == 0 {
|
|
eee.config
|
|
.super_attempts
|
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
|
error!("sup attempts = 0");
|
|
// next time, the supernode will use the new one
|
|
let node_index = eee.config.super_node_index.fetch_add(1, Ordering::Relaxed);
|
|
if node_index >= (eee.config.super_nodes.len() - 1) as u8 {
|
|
eee.config.super_node_index.store(0, Ordering::Relaxed);
|
|
}
|
|
} else {
|
|
eee.config.super_attempts.fetch_sub(1, Ordering::Relaxed);
|
|
}
|
|
if let Err(e) = eee.send_register_super().await {
|
|
error!("failed to send register_super: {}", e.as_str());
|
|
}
|
|
eee.last_register_req.store(now, Ordering::Relaxed);
|
|
register_with_local_peers(eee).await;
|
|
}
|
|
*/
|
|
|
|
pub fn form_ethernet_packet(src_mac: Mac, dst_mac: Mac, data: &[u8]) -> Vec<u8> {
|
|
let mut etherheader = Ethernet2Header::default();
|
|
etherheader.destination = dst_mac;
|
|
etherheader.ether_type = etherparse::EtherType::IPV4;
|
|
etherheader.source = src_mac;
|
|
let mut packet = Vec::with_capacity(14 + data.len() + 4);
|
|
packet.extend_from_slice(ðerheader.to_bytes()[..]);
|
|
packet.extend_from_slice(&data);
|
|
packet
|
|
}
|