feat: parse iiface
This commit is contained in:
parent
8f2e09ed8d
commit
6a56127f84
115
src/main.rs
115
src/main.rs
|
@ -1,64 +1,105 @@
|
||||||
const ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
|
const ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
|
||||||
use color_eyre::Result;
|
use color_eyre::{eyre::bail, Result};
|
||||||
use pnet::datalink::interfaces;
|
use pnet::datalink::{interfaces, NetworkInterface};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use simple_dns::Packet;
|
use simple_dns::Packet;
|
||||||
use socket2::{Domain, Protocol, Socket, Type};
|
use socket2::{Domain, Protocol, Socket, Type};
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||||
|
};
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
|
fn get_iface(from: &SocketAddr, ifaces: &Vec<&NetworkInterface>) -> Result<String> {
|
||||||
|
for i in ifaces {
|
||||||
|
for ip in i.ips.iter() {
|
||||||
|
if ip.contains(from.ip()) {
|
||||||
|
return Ok(i.name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bail!("No interface found")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_questions(packet: &Packet) -> HashSet<String> {
|
||||||
|
packet
|
||||||
|
.questions
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.qname.to_string())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
fn get_answers(packet: &Packet) -> HashSet<String> {
|
||||||
|
packet.answers.iter().map(|x| x.name.to_string()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Rule {
|
||||||
|
from: Regex,
|
||||||
|
to: String,
|
||||||
|
allow_questions: Regex,
|
||||||
|
allow_answers: Regex,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
let mut rules = Vec::new();
|
||||||
|
rules.push(Rule {
|
||||||
|
from: Regex::new("lan01")?,
|
||||||
|
to: "lan01".to_string(),
|
||||||
|
allow_answers: Regex::new(".*")?,
|
||||||
|
allow_questions: Regex::new(".*")?,
|
||||||
|
});
|
||||||
|
let iface_reg = Regex::new(r"^lan.*$")?;
|
||||||
|
|
||||||
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
|
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
|
||||||
socket.set_reuse_address(true)?;
|
socket.set_reuse_address(true)?;
|
||||||
socket.set_reuse_port(true)?;
|
socket.set_reuse_port(true)?;
|
||||||
let addr = SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 251), 5353).into();
|
let addr = SocketAddrV4::new(ADDR, 5353).into();
|
||||||
socket.bind(&addr)?;
|
socket.bind(&addr)?;
|
||||||
socket.join_multicast_v4(&ADDR, &Ipv4Addr::new(10, 99, 10, 1))?;
|
socket.join_multicast_v4(&ADDR, &Ipv4Addr::UNSPECIFIED)?;
|
||||||
//socket.set_nonblocking(true)?;
|
//socket.set_nonblocking(true)?;
|
||||||
|
|
||||||
let iface_reg = Regex::new(r"^lan.*$")?;
|
|
||||||
let interfaces = interfaces();
|
let interfaces = interfaces();
|
||||||
let interfaces = interfaces.iter().filter(|x| {
|
let interfaces = interfaces
|
||||||
|
.iter()
|
||||||
|
.filter(|x| {
|
||||||
x.is_up() && !x.is_loopback() && !x.ips.is_empty() && iface_reg.is_match(&x.name)
|
x.is_up() && !x.is_loopback() && !x.ips.is_empty() && iface_reg.is_match(&x.name)
|
||||||
});
|
})
|
||||||
for i in interfaces {
|
.collect();
|
||||||
println!("{:?}", i);
|
println!("{:?}", interfaces);
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
let socket = UdpSocket::from_std(socket.into())?;
|
let socket = UdpSocket::from_std(socket.into())?;
|
||||||
loop {
|
loop {
|
||||||
match socket.recv_from(&mut buf).await {
|
match socket.recv_from(&mut buf).await {
|
||||||
Ok((_l, from)) => {
|
Ok((_l, from)) => {
|
||||||
let packet = Packet::parse(&buf)?;
|
let packet = Packet::parse(&buf)?;
|
||||||
println!("{:?} {:?}\n", from, packet);
|
//println!("{:?} {:?}\n", from, packet);
|
||||||
|
let iface = match get_iface(&from, &interfaces) {
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Invalid packet received from {}", from);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Ok(name) => name,
|
||||||
|
};
|
||||||
|
let questions = get_questions(&packet);
|
||||||
|
let answers = get_answers(&packet);
|
||||||
|
println!(
|
||||||
|
"received packet on interface {} from {} questioning {:?} and answering {:?}",
|
||||||
|
iface, from, questions, answers
|
||||||
|
);
|
||||||
|
let mut out = HashSet::new();
|
||||||
|
for r in &rules {
|
||||||
|
if r.from.is_match(&iface)
|
||||||
|
&& (questions.iter().any(|x| r.allow_questions.is_match(x))
|
||||||
|
|| answers.iter().any(|x| r.allow_answers.is_match(x)))
|
||||||
|
{
|
||||||
|
out.insert(r.to.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.remove(&iface);
|
||||||
|
println!("relaying packet to {:?}", out);
|
||||||
|
// socket.send_to(&buf, addr);
|
||||||
}
|
}
|
||||||
Err(_) => todo!(),
|
Err(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 5354))?;
|
|
||||||
|
|
||||||
} */
|
|
||||||
/*
|
|
||||||
table ip mdns {
|
|
||||||
chain prerouting {
|
|
||||||
type filter hook prerouting priority mangle; policy accept;
|
|
||||||
|
|
||||||
iifname lan01 ip daddr 224.0.0.251 meta mark 0xa5f3 jump mdns-saddr
|
|
||||||
iifname lan01 ip daddr 224.0.0.251 meta mark != 0xa5f3 jump mdns
|
|
||||||
}
|
|
||||||
chain mdns {
|
|
||||||
meta mark set 0xa5f3
|
|
||||||
iifname lan01 dup to 224.0.0.251
|
|
||||||
}
|
|
||||||
chain mdns-saddr {
|
|
||||||
# repeat mDNS from IoT to main
|
|
||||||
#iifname lan-services ip saddr set 10.99.20.1
|
|
||||||
#iifname lan-home ip saddr set 10.99.10.1
|
|
||||||
iifname lan01 udp dport set 5354
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in a new issue