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
//! Handlers for network interface exploration in RIOT
// FIXME port from gnrc_netif to netif

use coap_handler_implementations::wkc;

struct AllNetifs;

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

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

impl<C> minicbor::Encode<C> for AllNetifs
{
    fn encode<W: minicbor::encode::Write>(&self, e: &mut minicbor::Encoder<W>, ctx: &mut C) -> Result<(), minicbor::encode::Error<W::Error>>
    {
        let e = e.begin_array()?;

        for netif in riot_wrappers::gnrc::Netif::all() {
            SerializedNetif(netif).encode(e, ctx)?;
        }

        e.end()?;

        Ok(())
    }
}

struct SerializedNetif(riot_wrappers::gnrc::Netif);

impl<C> minicbor::Encode<C> for SerializedNetif
{
    fn encode<W: minicbor::encode::Write>(&self, e: &mut minicbor::Encoder<W>, ctx: &mut C) -> Result<(), minicbor::encode::Error<W::Error>>
    {
        let pidnum: i16 = self.0.pid().into();
        let l2addr = serde_bytes::Bytes::new(self.0.l2addr());
        let ipaddrs = self.0.ipv6_addrs();

        let e = e.array(2 + ipaddrs.is_ok() as u64)?;

        e.i16(pidnum)?; // FIXME could be u16 (KernelPID should support both)
        e.bytes(&l2addr)?;
        if let Ok(ipaddrs) = ipaddrs {
            let e = e.array(ipaddrs.len() as _)?;
            for a in &ipaddrs {
                e.tag(minicbor::data::Tag::Unassigned(54))?;
                if a.is_link_local() {
                    #[derive(minicbor::Encode)]
                    struct IpWithZone<'a> {
                        #[cbor(n(0), encode_with = "minicbor::bytes::encode")]
                        ip: &'a [u8],
                        #[n(2)]
                        netif: i16,
                    }

                    IpWithZone { ip: a.raw(), netif: pidnum }.encode(e, ctx)?;
                } else {
                    e.bytes(a.raw())?;
                }
            }
        };
        Ok(())
    }
}

/// Build a handler that will report a summary of the current GNRC network interfaces in CBOR form
///
/// The precise format is subject to change, but currently it produces an array of netifs, each
/// with its process ID, its link-local address, and (if IPv6-enabled) a list of assigned IPv6
/// addresses.
///
/// All IP addresses are expressed using the appropriate CBOR tags.
pub fn netif() -> impl coap_handler::Handler + coap_handler::Reporting {
    wkc::ConstantSingleRecordReport::new_with_path(
        coap_handler_implementations::TypeHandler::new_minicbor(AllNetifs),
        &[coap_handler::Attribute::Title("Network interfaces")],
        &[],
        )
}