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
// SPDX-License-Identifier: MIT
use std::{net::Ipv6Addr, str::FromStr};
use netlink_packet_core::{Emitable, Parseable};
use crate::{
route::{
flags::RouteFlags, RouteAttribute, RouteCacheInfo, RouteHeader,
RouteMessage, RouteMessageBuffer, RouteMetric, RoutePreference,
RouteProtocol, RouteScope, RouteType,
},
AddressFamily,
};
#[test]
// wireshark capture(netlink message header removed) of nlmon against command:
// ip -6 route show dev wlan0
fn test_ipv6_route_cache_info() {
let raw = vec![
0x0a, // Address family inet6(10)
0x00, // destination prefix length 0
0x00, // source prefix length 0
0x00, // tos
0xfe, // table 254(main)
0x09, // protocol RTPROT_RA 9
0x00, // scope RT_SCOPE_UNIVERSE 0
0x01, // type RTN_UNICAST 1
0x00, 0x00, 0x00, 0x00, // flags 0
0x08, 0x00, // length 8
0x0f, 0x00, // RTA_TABLE 15
0xfe, 0x00, 0x00, 0x00, // table u32 254
0x14, 0x00, // length 20
0x08, 0x00, // RTA_METRICS 8
0x08, 0x00, // length 8
0x02, 0x00, // RTAX_MTU 2
0x98, 0x05, 0x00, 0x00, // MTU 1432
0x08, 0x00, // length 8
0x0a, 0x00, // RTAX_HOPLIMIT 10
0xfe, 0x00, 0x00, 0x00, // hop limit 254
0x08, 0x00, // length 8
0x06, 0x00, // RTA_PRIORITY 6
0x00, 0x04, 0x00, 0x00, // 1024
0x14, 0x00, // length 20
0x05, 0x00, // RTA_GATEWAY 5
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x38, 0x9c, 0xff,
0xfe, 0x01, 0xe8, 0x52, // ipv6 addr
0x08, 0x00, // length 8
0x04, 0x00, // RTA_OIF 4
0x02, 0x00, 0x00, 0x00, // oif 2
0x24, 0x00, // length 36
0x0c, 0x00, // RTA_CACHEINFO
0x00, 0x00, 0x00, 0x00, // rta_clntref
0x00, 0x00, 0x00, 0x00, // rta_lastuse
0x29, 0x29, 0x05, 0x00, // rta_expires
0x00, 0x00, 0x00, 0x00, // rta_error
0x00, 0x00, 0x00, 0x00, // rta_id
0x00, 0x00, 0x00, 0x00, // rta_ts
0x00, 0x00, 0x00, 0x00, // rta_tsage
0x00, 0x00, 0x00, 0x00, // padding
0x05, 0x00, // length 5
0x14, 0x00, // RTA_PREF
0x01, // 1 ICMPV6_ROUTER_PREF_HIGH
0x00, 0x00, 0x00, // padding
];
let expected = RouteMessage {
header: RouteHeader {
address_family: AddressFamily::Inet6,
destination_prefix_length: 0,
source_prefix_length: 0,
tos: 0,
table: 254,
protocol: RouteProtocol::Ra,
scope: RouteScope::Universe,
kind: RouteType::Unicast,
flags: RouteFlags::empty(),
},
attributes: vec![
RouteAttribute::Table(254),
RouteAttribute::Metrics(vec![
RouteMetric::Mtu(1432),
RouteMetric::Hoplimit(254),
]),
RouteAttribute::Priority(1024),
RouteAttribute::Gateway(
Ipv6Addr::from_str("fe80::d638:9cff:fe01:e852")
.unwrap()
.into(),
),
RouteAttribute::Oif(2),
RouteAttribute::CacheInfo(RouteCacheInfo {
clntref: 0,
last_use: 0,
expires: 338217,
error: 0,
used: 0,
id: 0,
ts: 0,
ts_age: 0,
}),
RouteAttribute::Preference(RoutePreference::High),
],
};
assert_eq!(
expected,
RouteMessage::parse(&RouteMessageBuffer::new(&raw)).unwrap()
);
let mut buf = vec![0; expected.buffer_len()];
expected.emit(&mut buf);
assert_eq!(buf, raw);
}