riot_coap_handler_demos/
nib.rs

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
//! Handler for network neighbor exploration

use crate::minicbor_helpers::*;

struct AllNeigh;

impl coap_handler_implementations::TypeRenderable for AllNeigh {
    type Get = Self;
    type Put = ();
    type Post = ();

    fn get(&mut self) -> Result<Self, u8> {
        Ok(AllNeigh)
    }
}

#[derive(minicbor::Encode)]
struct NeighRecord<'a> {
    #[cbor(n(0))]
    // could be NonZero but for https://gitlab.com/twittner/minicbor/-/merge_requests/48
    iface: Option<usize>,
    #[cbor(n(1), encode_with = "encode_as_mac")]
    l2: &'a [u8],
    #[n(2)]
    ip: IpWithZone<&'a core::net::Ipv6Addr>,
    #[n(3)]
    nud: Option<&'static str>,
    #[n(4)]
    ar: Option<&'static str>,
}

impl<C> minicbor::encode::Encode<C> for AllNeigh {
    fn encode<W: minicbor::encode::Write>(
        &self,
        e: &mut minicbor::encode::Encoder<W>,
        _: &mut C,
    ) -> Result<(), minicbor::encode::Error<W::Error>> {
        let e = e.begin_array()?;
        for neigh in riot_wrappers::gnrc::nib::NcEntry::all() {
            let ip = neigh.ipv6_addr().into();
            e.encode(NeighRecord {
                // unwrap_or_default is impedance matching for https://gitlab.com/twittner/minicbor/-/merge_requests/48
                iface: neigh
                    .iface()
                    .map(|i| usize::try_from(i).unwrap_or_default()),
                // the iface (zone identifier) is a bit redundant, but not wrong either, and useful
                // when copying addresses within the same host
                ip: IpWithZone {
                    ip: &ip,
                    zone: neigh.iface().and_then(|a| a.try_into().ok()),
                },
                l2: neigh.l2addr(),
                nud: neigh.nud_state().map(|s| s.label()),
                ar: neigh.ar_state().map(|s| s.label()),
            })?;
        }
        e.end()?;

        Ok(())
    }
}

/// A handler expressing the current GNRC NIB neighbor cache
///
/// The format of the results is not stable; currently, it includes the interface, the neightbor's
/// link layer address, its Neighbor Unreachability Detection state, and its 6LoWPAN Address
/// Registration state.
pub fn neighbor_cache() -> impl coap_handler::Handler + coap_handler::Reporting {
    coap_handler_implementations::wkc::ConstantSingleRecordReport::new_with_path(
        coap_handler_implementations::TypeHandler::new_minicbor_0_24(AllNeigh),
        &[coap_handler::Attribute::Title("Neighbors")],
        &[],
    )
}