1
use std::ffi::CString;
2

            
3
use crate::{cstr_to_string, raw, Error};
4

            
5
/// This is a datalink link type.
6
///
7
/// As an example, `Linktype(1)` is ethernet. A full list of linktypes is available
8
/// [here](http://www.tcpdump.org/linktypes.html). The const bellow are not exhaustive.
9
/// ```rust
10
/// use pcap::Linktype;
11
///
12
/// let lt = Linktype(1);
13
/// assert_eq!(Linktype::ETHERNET, lt);
14
/// ```
15
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
16
pub struct Linktype(pub i32);
17

            
18
impl Linktype {
19
    /// Gets the name of the link type, such as EN10MB
20
6
    pub fn get_name(&self) -> Result<String, Error> {
21
6
        unsafe { cstr_to_string(raw::pcap_datalink_val_to_name(self.0)) }?
22
6
            .ok_or(Error::InvalidLinktype)
23
6
    }
24

            
25
    /// Gets the description of a link type.
26
4
    pub fn get_description(&self) -> Result<String, Error> {
27
4
        unsafe { cstr_to_string(raw::pcap_datalink_val_to_description(self.0)) }?
28
4
            .ok_or(Error::InvalidLinktype)
29
4
    }
30

            
31
    /// Gets the linktype from a name string
32
4
    pub fn from_name(name: &str) -> Result<Linktype, Error> {
33
4
        let name = CString::new(name)?;
34
4
        let val = unsafe { raw::pcap_datalink_name_to_val(name.as_ptr()) };
35
4
        if val == -1 {
36
2
            return Err(Error::InvalidLinktype);
37
2
        }
38
2

            
39
2
        Ok(Linktype(val))
40
4
    }
41

            
42
    pub const NULL: Self = Self(0);
43
    pub const ETHERNET: Self = Self(1);
44
    pub const AX25: Self = Self(3);
45
    pub const IEEE802_5: Self = Self(6);
46
    pub const ARCNET_BSD: Self = Self(7);
47
    pub const SLIP: Self = Self(8);
48
    pub const PPP: Self = Self(9);
49
    pub const FDDI: Self = Self(10);
50
    pub const PPP_HDLC: Self = Self(50);
51
    pub const PPP_ETHER: Self = Self(51);
52
    pub const ATM_RFC1483: Self = Self(100);
53
    pub const RAW: Self = Self(101);
54
    pub const C_HDLC: Self = Self(104);
55
    pub const IEEE802_11: Self = Self(105);
56
    pub const FRELAY: Self = Self(107);
57
    pub const LOOP: Self = Self(108);
58
    pub const LINUX_SLL: Self = Self(113);
59
    pub const LTALK: Self = Self(114);
60
    pub const PFLOG: Self = Self(117);
61
    pub const IEEE802_11_PRISM: Self = Self(119);
62
    pub const IP_OVER_FC: Self = Self(122);
63
    pub const SUNATM: Self = Self(123);
64
    pub const IEEE802_11_RADIOTAP: Self = Self(127);
65
    pub const ARCNET_LINUX: Self = Self(129);
66
    pub const APPLE_IP_OVER_IEEE1394: Self = Self(138);
67
    pub const MTP2_WITH_PHDR: Self = Self(139);
68
    pub const MTP2: Self = Self(140);
69
    pub const MTP3: Self = Self(141);
70
    pub const SCCP: Self = Self(142);
71
    pub const DOCSIS: Self = Self(143);
72
    pub const LINUX_IRDA: Self = Self(144);
73
    pub const USER0: Self = Self(147);
74
    pub const USER1: Self = Self(148);
75
    pub const USER2: Self = Self(149);
76
    pub const USER3: Self = Self(150);
77
    pub const USER4: Self = Self(151);
78
    pub const USER5: Self = Self(152);
79
    pub const USER6: Self = Self(153);
80
    pub const USER7: Self = Self(154);
81
    pub const USER8: Self = Self(155);
82
    pub const USER9: Self = Self(156);
83
    pub const USER10: Self = Self(157);
84
    pub const USER11: Self = Self(158);
85
    pub const USER12: Self = Self(159);
86
    pub const USER13: Self = Self(160);
87
    pub const USER14: Self = Self(161);
88
    pub const USER15: Self = Self(162);
89
    pub const IEEE802_11_AVS: Self = Self(163);
90
    pub const BACNET_MS_TP: Self = Self(165);
91
    pub const PPP_PPPD: Self = Self(166);
92
    pub const GPRS_LLC: Self = Self(169);
93
    pub const GPF_T: Self = Self(170);
94
    pub const GPF_F: Self = Self(171);
95
    pub const LINUX_LAPD: Self = Self(177);
96
    pub const MFR: Self = Self(182);
97
    pub const BLUETOOTH_HCI_H4: Self = Self(187);
98
    pub const USB_LINUX: Self = Self(189);
99
    pub const PPI: Self = Self(192);
100
    pub const IEEE802_15_4_WITHFCS: Self = Self(195);
101
    pub const SITA: Self = Self(196);
102
    pub const ERF: Self = Self(197);
103
    pub const BLUETOOTH_HCI_H4_WITH_PHDR: Self = Self(201);
104
    pub const AX25_KISS: Self = Self(202);
105
    pub const LAPD: Self = Self(203);
106
    pub const PPP_WITH_DIR: Self = Self(204);
107
    pub const C_HDLC_WITH_DIR: Self = Self(205);
108
    pub const FRELAY_WITH_DIR: Self = Self(206);
109
    pub const LAPB_WITH_DIR: Self = Self(207);
110
    pub const IPMB_LINUX: Self = Self(209);
111
    pub const IEEE802_15_4_NONASK_PHY: Self = Self(215);
112
    pub const USB_LINUX_MMAPPED: Self = Self(220);
113
    pub const FC_2: Self = Self(224);
114
    pub const FC_2_WITH_FRAME_DELIMS: Self = Self(225);
115
    pub const IPNET: Self = Self(226);
116
    pub const CAN_SOCKETCAN: Self = Self(227);
117
    pub const IPV4: Self = Self(228);
118
    pub const IPV6: Self = Self(229);
119
    pub const IEEE802_15_4_NOFCS: Self = Self(230);
120
    pub const DBUS: Self = Self(231);
121
    pub const DVB_CI: Self = Self(235);
122
    pub const MUX27010: Self = Self(236);
123
    pub const STANAG_5066_D_PDU: Self = Self(237);
124
    pub const NFLOG: Self = Self(239);
125
    pub const NETANALYZER: Self = Self(240);
126
    pub const NETANALYZER_TRANSPARENT: Self = Self(241);
127
    pub const IPOIB: Self = Self(242);
128
    pub const MPEG_2_TS: Self = Self(243);
129
    pub const NG40: Self = Self(244);
130
    pub const NFC_LLCP: Self = Self(245);
131
    pub const INFINIBAND: Self = Self(247);
132
    pub const SCTP: Self = Self(248);
133
    pub const USBPCAP: Self = Self(249);
134
    pub const RTAC_SERIAL: Self = Self(250);
135
    pub const BLUETOOTH_LE_LL: Self = Self(251);
136
    pub const NETLINK: Self = Self(253);
137
    pub const BLUETOOTH_LINUX_MONITOR: Self = Self(254);
138
    pub const BLUETOOTH_BREDR_BB: Self = Self(255);
139
    pub const BLUETOOTH_LE_LL_WITH_PHDR: Self = Self(256);
140
    pub const PROFIBUS_DL: Self = Self(257);
141
    pub const PKTAP: Self = Self(258);
142
    pub const EPON: Self = Self(259);
143
    pub const IPMI_HPM_2: Self = Self(260);
144
    pub const ZWAVE_R1_R2: Self = Self(261);
145
    pub const ZWAVE_R3: Self = Self(262);
146
    pub const WATTSTOPPER_DLM: Self = Self(263);
147
    pub const ISO_14443: Self = Self(264);
148
    pub const RDS: Self = Self(265);
149
    pub const USB_DARWIN: Self = Self(266);
150
    pub const SDLC: Self = Self(268);
151
    pub const LORATAP: Self = Self(270);
152
    pub const VSOCK: Self = Self(271);
153
    pub const NORDIC_BLE: Self = Self(272);
154
    pub const DOCSIS31_XRA31: Self = Self(273);
155
    pub const ETHERNET_MPACKET: Self = Self(274);
156
    pub const DISPLAYPORT_AUX: Self = Self(275);
157
    pub const LINUX_SLL2: Self = Self(276);
158
    pub const OPENVIZSLA: Self = Self(278);
159
    pub const EBHSCR: Self = Self(279);
160
    pub const VPP_DISPATCH: Self = Self(280);
161
    pub const DSA_TAG_BRCM: Self = Self(281);
162
    pub const DSA_TAG_BRCM_PREPEND: Self = Self(282);
163
    pub const IEEE802_15_4_TAP: Self = Self(283);
164
    pub const DSA_TAG_DSA: Self = Self(284);
165
    pub const DSA_TAG_EDSA: Self = Self(285);
166
    pub const ELEE: Self = Self(286);
167
    pub const Z_WAVE_SERIAL: Self = Self(287);
168
    pub const USB_2_0: Self = Self(288);
169
    pub const ATSC_ALP: Self = Self(289);
170
}
171

            
172
#[cfg(test)]
173
mod tests {
174
    use crate::raw::testmod::RAWMTX;
175

            
176
    use super::*;
177

            
178
    #[test]
179
    fn test_get_name() {
180
        let _m = RAWMTX.lock();
181
        let name = "datalink name";
182

            
183
        let cstr = CString::new(name).unwrap();
184
        let ctx = raw::pcap_datalink_val_to_name_context();
185
        ctx.expect().return_once(|_| cstr.into_raw());
186

            
187
        let linktype_name = Linktype::ARCNET_LINUX.get_name().unwrap();
188
        assert_eq!(&linktype_name, name);
189
    }
190

            
191
    #[test]
192
    fn test_get_description() {
193
        let _m = RAWMTX.lock();
194
        let desc = "datalink description";
195

            
196
        let cstr = CString::new(desc).unwrap();
197
        let ctx = raw::pcap_datalink_val_to_description_context();
198
        ctx.expect().return_once(|_| cstr.into_raw());
199

            
200
        let linktype_name = Linktype::ARCNET_LINUX.get_description().unwrap();
201
        assert_eq!(&linktype_name, desc);
202
    }
203

            
204
    #[test]
205
    fn test_from_name() {
206
        let _m = RAWMTX.lock();
207

            
208
        let ctx = raw::pcap_datalink_name_to_val_context();
209
        ctx.expect().return_once(|_| 7);
210

            
211
        let linktype = Linktype::from_name("git rekt scrub").unwrap();
212
        assert_eq!(linktype, Linktype::ARCNET_BSD);
213

            
214
        let ctx = raw::pcap_datalink_name_to_val_context();
215
        ctx.checkpoint();
216
        ctx.expect().return_once(|_| -1);
217

            
218
        let err = Linktype::from_name("git rekt scrub").unwrap_err();
219
        assert_eq!(err, Error::InvalidLinktype);
220
    }
221
}