1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::lldp::lldppkt::*;
use erbium_net::raw::MsgFlags;
pub mod lldppkt;
pub struct LldpService {
sock: erbium_net::raw::RawSocket,
}
impl LldpService {
pub fn new() -> std::io::Result<LldpService> {
let sock = erbium_net::raw::RawSocket::new(erbium_net::raw::EthProto::LLDP)?;
Ok(Self { sock })
}
pub async fn run(&self) -> ! {
let mut prev = None;
loop {
match self.sock.recv_msg(1500, MsgFlags::empty()).await {
Err(err) => log::warn!("LLDP Failed to receive frame: {:?}", err),
Ok(msg) => {
use crate::pktparser::Deserialise as _;
match lldppkt::LldpPacket::from_wire(&mut crate::pktparser::Buffer::new(
&msg.buffer[14..],
)) {
Ok(new) => {
if prev.is_none() || prev.as_ref().unwrap() != &new {
for i in &new.tlvs {
match i {
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::ChassisComponent,
identifier,
}) => log::info!(
"{:?}: Peer Chassis Component: {:?}",
msg.local_intf(),
identifier
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::InterfaceAlias,
identifier,
}) => log::info!(
"{:?}: Peer IfAlias: {}",
msg.local_intf(),
String::from_utf8_lossy(identifier)
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::PortComponent,
identifier,
}) => log::info!(
"{:?}: Peer entPhysicalAlias: {}",
msg.local_intf(),
String::from_utf8_lossy(identifier)
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::MacAddress,
identifier,
}) => log::info!(
"{:?}: Peer Device MAC Address: {:?}",
msg.local_intf(),
identifier
.iter()
.map(|o| format!("{:0>2x}", o))
.collect::<Vec<_>>()
.join(":")
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::NetworkAddress,
identifier,
}) => log::info!(
"{:?}: Peer Device Network Address: {:?}",
msg.local_intf(),
/* TODO: Render this as an IPv4/IPv6 address */
identifier
.iter()
.map(|o| format!("{:0>2x}", o))
.collect::<Vec<_>>()
.join(":")
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::InterfaceName,
identifier,
}) => log::info!(
"{:?}: Peer Interface Name: {}",
msg.local_intf(),
String::from_utf8_lossy(identifier)
),
LldpTlv::ChassisID(ChassisId {
r#type: ChassisIdType::Local,
identifier,
}) => log::info!(
"{:?}: Peer Locally Defined Name: {}",
msg.local_intf(),
String::from_utf8_lossy(identifier)
),
LldpTlv::PortID(PortId {
r#type: ty,
identifier,
}) => {
log::info!(
"{:?}: Peer Port {:?}: {}",
msg.local_intf(),
ty,
String::from_utf8_lossy(identifier)
);
}
other => {
log::info!(
"{:?}: Peer Attribute: {:?}",
msg.local_intf(),
other
);
}
}
}
prev = Some(new);
}
}
Err(e) => log::warn!("Failed to decode LLDP frame: {:?}", e),
}
}
}
}
}
}