netlink_rust/core/
mod.rs

1mod system;
2mod hardware_address;
3mod variant;
4#[macro_use] mod helpers;
5
6use errors::Result;
7use self::system::Address;
8use libc;
9use std::fmt;
10use std::str;
11use std::io;
12use std::io::{Read, Write, Seek, SeekFrom};
13use std::mem::size_of;
14use std::ffi::{CStr, CString};
15use std::os::unix::io::{RawFd, AsRawFd};
16
17pub use self::hardware_address::HardwareAddress;
18
19pub use self::variant::{NativeRead, NativeWrite, NativeParse};
20
21/// A trait for converting a value from one type to another.
22/// Any failure in converting will return None.
23pub trait ConvertFrom<T: Sized>
24    where Self: Sized
25{
26    fn convert_from(value: T) -> Option<Self>;
27}
28
29extended_enum!(Protocol, i32,
30    Route => 0,
31    Unused => 1,
32    Usersock => 2,
33    Firewall => 3,
34    SockDiag => 4,
35    Nflog => 5,
36    Xfrm => 6,
37    SELinux => 7,
38    ISCSI => 8,
39    Audit => 9,
40    FibLookup => 10,
41    Connector => 11,
42    Netfilter => 12,
43    IP6Fw => 13,
44    DNRtMsg => 14,
45    KObjectUevent => 15,
46    Generic => 16,
47    SCSITransport => 17,
48    ECryptFs => 18,
49    RDMA => 19,
50    Crypto => 20,
51    SMC => 21
52);
53
54const NLMSG_NOOP: u16 = 1;
55const NLMSG_ERROR: u16 = 2;
56const NLMSG_DONE: u16 = 3;
57// const NLMSG_OVERRUN: u16 = 4;
58
59const NETLINK_ADD_MEMBERSHIP: i32 = 1;
60// const NETLINK_DROP_MEMBERSHIP: i32 = 2;
61// const NETLINK_PKTINFO: i32 = 3;
62// const NETLINK_BROADCAST_ERROR: i32 = 4;
63// const NETLINK_NO_ENOBUFS: i32 = 5;
64// const NETLINK_RX_RING: i32 = 6;
65// const NETLINK_TX_RING: i32 = 7;
66// const NETLINK_LISTEN_ALL_NSID: i32 = 8;
67// const NETLINK_LIST_MEMBERSHIPS: i32 = 9;
68// const NETLINK_CAP_ACK: i32 = 10;
69// const NETLINK_EXT_ACK: i32 = 11;
70
71bitflags! {
72    pub struct MessageFlags: u16 {
73        const REQUEST     = 0x0001;
74        const MULTIPART   = 0x0002;
75        const ACKNOWLEDGE = 0x0004;
76        const DUMP        = 0x0100 | 0x0200;
77    }
78}
79
80pub enum MessageMode {
81    None,
82    Acknowledge,
83    Dump,
84}
85
86impl Into<MessageFlags> for MessageMode {
87    fn into(self) -> MessageFlags {
88        let flags = MessageFlags::REQUEST;
89        match self {
90            MessageMode::None => flags,
91            MessageMode::Acknowledge => flags | MessageFlags::ACKNOWLEDGE,
92            MessageMode::Dump => flags | MessageFlags::DUMP,
93        }
94    }
95}
96
97#[inline]
98fn align_to(len: usize, align_to: usize) -> usize
99{
100    (len + align_to - 1) & !(align_to - 1)
101}
102
103#[inline]
104fn netlink_align(len: usize) -> usize
105{
106    align_to(len, 4usize)
107}
108
109#[inline]
110fn netlink_padding(len: usize) -> usize
111{
112    netlink_align(len) - len
113}
114
115pub trait Sendable {
116    fn write<W: Write>(&self, writer: &mut W) -> Result<()>;
117    fn message_type(&self) -> u16;
118    fn query_flags(&self) -> MessageFlags;
119}
120
121#[repr(C)]
122pub struct Header {
123    pub length: u32,
124    pub identifier: u16,
125    pub flags: u16,
126    pub sequence: u32,
127    pub pid: u32,
128}
129
130impl Header {
131    pub fn parse<R: Read + Seek>(reader: &mut R) -> Result<Header> {
132        let length = u32::read(reader)?;
133        let identifier = u16::read(reader)?;
134        let flags = u16::read(reader)?;
135        let sequence = u32::read(reader)?;
136        let pid = u32::read(reader)?;
137        Ok(Header {
138            length: length,
139            identifier: identifier,
140            flags: flags,
141            sequence: sequence,
142            pid: pid,
143            })
144    }
145
146    pub fn length(&self) -> usize {
147        self.length as usize
148    }
149
150    pub fn data_length(&self) -> usize {
151        self.length() - size_of::<Header>()
152    }
153
154    pub fn padding(&self) -> usize {
155        netlink_padding(self.length())
156    }
157
158    pub fn aligned_length(&self) -> usize {
159        netlink_align(self.length())
160    }
161
162    pub fn aligned_data_length(&self) -> usize {
163        netlink_align(self.data_length())
164    }
165
166    pub fn check_pid(&self, pid: u32) -> bool {
167        self.pid == 0 || self.pid == pid
168    }
169
170    pub fn check_sequence(&self, sequence: u32) -> bool {
171        self.pid == 0 || self.sequence == sequence
172    }
173}
174
175impl fmt::Display for Header {
176    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177        write!(f,
178            "Length: {0:08x} {0}\nIdentifier: {1:04x}\nFlags: {2:04x}\n\
179            Sequence: {3:08x} {3}\nPID: {4:08x} {4}",
180            self.length,
181            self.identifier,
182            self.flags,
183            self.sequence,
184            self.pid,
185        )
186    }
187}
188
189pub struct DataMessage {
190    pub header: Header,
191    pub data: Vec<u8>,
192}
193
194impl DataMessage {
195    pub fn parse<R: Read + Seek>(reader: &mut R, header: Header) -> Result<DataMessage> {
196        let mut data = vec![0u8; header.data_length()];
197        reader.read_exact(&mut data)?;
198        Ok(DataMessage { header: header, data: data })
199    }
200}
201
202pub struct ErrorMessage {
203    pub header: Header,
204    pub code: i32,
205    pub original_header: Header,
206}
207
208impl ErrorMessage {
209    pub fn parse<R: Read + Seek>(reader: &mut R, header: Header) -> Result<ErrorMessage> {
210        let code = i32::read(reader)?;
211        let original_header = Header::parse(reader)?;
212        Ok(ErrorMessage { header: header, code: code,
213            original_header: original_header })
214    }
215}
216
217pub enum Message {
218    Data(DataMessage),
219    Acknowledge,
220    Done,
221}
222
223pub struct Attribute {
224    pub identifier: u16,
225    data: Vec<u8>,
226}
227
228impl Attribute {
229    const HEADER_SIZE: u16 = 4;
230
231    pub fn parse<R: Read + Seek>(reader: &mut R) -> Result<Attribute> {
232        let length = u16::read(reader)?;
233        let padding = netlink_padding(length as usize) as i64;
234        let data_length = (length - Attribute::HEADER_SIZE) as usize;
235        let identifier = u16::read(reader)?;
236        let mut data = vec![0u8; data_length];
237        reader.read_exact(&mut data)?;
238        reader.seek(SeekFrom::Current(padding))?;
239        Ok(Attribute { identifier: identifier, data: data })
240    }
241    pub fn new_string<ID: Into<u16>>(identifier: ID, value: &str) -> Attribute {
242        let c_string = CString::new(value).unwrap();
243        Attribute { identifier: identifier.into(), data: c_string.into_bytes_with_nul() }
244    }
245    pub fn new<ID: Into<u16>, V: NativeWrite>(identifier: ID, value: V) -> Attribute {
246        let mut writer = io::Cursor::new(Vec::new());
247        value.write(&mut writer).unwrap();
248        Attribute { identifier: identifier.into(), data: writer.into_inner() }
249    }
250    pub fn len(&self) -> u16 {
251        self.data.len() as u16
252    }
253    pub fn total_len(&self) -> usize {
254        netlink_align(self.data.len() + 4)
255    }
256    pub fn as_u16(&self) -> Result<u16> {
257        u16::parse(&self.data)
258    }
259    pub fn as_i32(&self) -> Result<i32> {
260        i32::parse(&self.data)
261    }
262    pub fn as_u32(&self) -> Result<u32> {
263        u32::parse(&self.data)
264    }
265    pub fn as_u64(&self) -> Result<u64> {
266        u64::parse(&self.data)
267    }
268    pub fn as_string(&self) -> Result<String> {
269        match CStr::from_bytes_with_nul(&self.data) {
270            Ok(bytes) => {
271                let s = bytes.to_str()?;
272                Ok(String::from(s))
273            },
274            Err(_) => {
275                let s = str::from_utf8(&self.data)?;
276                Ok(String::from(s))
277            }
278        }
279    }
280    pub fn as_hardware_address(&self) -> Result<HardwareAddress> {
281        HardwareAddress::parse(&self.data)
282    }
283    pub fn as_bytes(&self) -> Vec<u8> {
284        self.data.clone()
285    }
286    pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
287        let length = (self.len() + Attribute::HEADER_SIZE) as u16;
288        length.write(writer)?;
289        self.identifier.write(writer)?;
290        writer.write_all(&self.data)?;
291        Ok(())
292    }
293}
294
295pub fn parse_attributes<R: Read + Seek>(reader: &mut R) -> Vec<Attribute>
296{
297    let mut attrs = vec![];
298    let mut run = true;
299    while run {
300        match Attribute::parse(reader) {
301            Ok(attr) => { attrs.push(attr); },
302            Err(_) => { run = false; },
303        }
304    }
305    attrs
306}
307
308/// Netlink Socket can be used to communicate with the Linux kernel using the
309/// netlink protocol.
310pub struct Socket {
311    local: Address,
312    peer: Address,
313    socket: RawFd,
314    sequence_next: u32,
315    sequence_expected: u32,
316    page_size: usize,
317    receive_buffer: Vec<u8>,
318    send_buffer: Vec<u8>,
319    acknowledge_expected: bool,
320}
321
322impl Socket {
323    /// Create a new Socket
324    pub fn new(protocol: Protocol) -> Result<Socket>
325    {
326        Socket::new_multicast(protocol, 0)
327    }
328
329    /// Create a new Socket which subscribes to the provided multi-cast groups
330    pub fn new_multicast(protocol: Protocol, groups: u32) -> Result<Socket>
331    {
332        let socket = system::netlink_socket(protocol as i32)?;
333        system::set_socket_option(socket, libc::SOL_SOCKET, libc::SO_SNDBUF, 32768)?;
334        system::set_socket_option(socket, libc::SOL_SOCKET, libc::SO_RCVBUF, 32768)?;
335        let mut local_addr = Address {
336            family: libc::AF_NETLINK as u16,
337            _pad: 0,
338            pid: 0,
339            groups: groups,
340        };
341        system::bind(socket, &mut local_addr)?;
342        system::get_socket_address(socket, &mut local_addr)?;
343        let page_size = netlink_align(system::get_page_size());
344        let peer_addr = Address {
345            family: libc::AF_NETLINK as u16,
346            _pad: 0,
347            pid: 0,
348            groups: groups,
349        };
350        Ok(Socket {
351            local: local_addr,
352            peer: peer_addr,
353            socket: socket,
354            sequence_next: 1,
355            sequence_expected: 0,
356            page_size: page_size,
357            receive_buffer: vec![0u8; page_size],
358            send_buffer: vec![0u8; page_size],
359            acknowledge_expected: false,
360        })
361    }
362
363    /// Subscribe to the multi-cast group provided
364    pub fn multicast_group_subscribe(&mut self, group: u32) -> Result<()>
365    {
366        system::set_socket_option(self.socket, libc::SOL_NETLINK,
367            NETLINK_ADD_MEMBERSHIP as i32, group as i32)?;
368        Ok(())
369    }
370
371    #[cfg(not(target_env = "musl"))]
372    fn message_header(&mut self, iov: &mut [libc::iovec]) -> libc::msghdr
373    {
374        let addr_ptr = &mut self.peer as *mut Address;
375        libc::msghdr {
376            msg_iovlen: iov.len(),
377            msg_iov: iov.as_mut_ptr(),
378            msg_namelen: size_of::<system::Address>() as u32,
379            msg_name: addr_ptr as *mut libc::c_void,
380            msg_flags: 0,
381            msg_controllen: 0,
382            msg_control: 0 as *mut libc::c_void,
383        }
384    }
385
386    #[cfg(target_env = "musl")]
387    fn message_header(&mut self, iov: &mut [libc::iovec]) -> libc::msghdr
388    {
389        let addr_ptr = &mut self.peer as *mut Address;
390        libc::msghdr {
391            msg_iovlen: iov.len() as i32,
392            msg_iov: iov.as_mut_ptr(),
393            msg_namelen: size_of::<system::Address>() as u32,
394            msg_name: addr_ptr as *mut libc::c_void,
395            msg_flags: 0,
396            msg_controllen: 0,
397            msg_control: 0 as *mut libc::c_void,
398        }
399    }
400
401    /// Send the provided package on the socket
402    pub fn send_message<S: Sendable>(&mut self, payload: &S) -> Result<usize>
403    {
404        self.send_buffer.clear();
405        let mut writer = io::Cursor::new(vec![0u8; self.page_size]);
406        let hdr_size = netlink_align(size_of::<Header>());
407        writer.seek(SeekFrom::Start(hdr_size as u64))?;
408        payload.write(&mut writer)?;
409        let payload_size = writer.seek(SeekFrom::Current(0))? as usize;
410        writer.seek(SeekFrom::Start(0))?;
411        (payload_size as u32).write(&mut writer)?;
412        payload.message_type().write(&mut writer)?;
413        let flags = payload.query_flags();
414        flags.bits().write(&mut writer)?;
415        self.sequence_next.write(&mut writer)?;
416        self.local.pid.write(&mut writer)?;
417
418        let mut iov = [
419            libc::iovec {
420                iov_base: writer.get_mut().as_mut_ptr() as *mut libc::c_void,
421                iov_len: payload_size, 
422            },
423        ];
424
425        let msg_header = self.message_header(&mut iov);
426        
427        self.acknowledge_expected = flags.contains(MessageFlags::ACKNOWLEDGE);
428        self.sequence_expected = self.sequence_next;
429        self.sequence_next += 1;
430
431        Ok(system::send_message(self.socket, &msg_header, 0)?)
432    }
433
434    fn receive_bytes(&mut self) -> Result<usize>
435    {
436        let mut iov = [
437            libc::iovec {
438                iov_base: self.receive_buffer.as_mut_ptr() as *mut libc::c_void,
439                iov_len: self.page_size,
440            },
441        ];
442        let mut msg_header = self.message_header(&mut iov);
443        let result = system::receive_message(self.socket, &mut msg_header);
444        match result {
445            Err(err) => {
446                if err.raw_os_error() == Some(libc::EAGAIN) {
447                    return Ok(0);
448                }
449                Err(err.into())
450            }
451            Ok(bytes) => {
452                Ok(bytes)
453            }
454        }
455    }
456
457    /// Receive binary data on the socket
458    pub fn receive(&mut self) -> Result<Vec<u8>>
459    {
460        let bytes = self.receive_bytes()?;
461        Ok(self.receive_buffer[0..bytes].to_vec())
462    }
463
464    /// Receive Messages pending on the socket
465    pub fn receive_messages(&mut self) -> Result<Vec<Message>>
466    {
467        let mut more_messages = true;
468        let mut result_messages = Vec::new();
469        while more_messages {
470            match self.receive_bytes() {
471                Err(err) => {
472                    return Err(err);
473                }
474                Ok(bytes) => {
475                    if bytes == 0 {
476                        break;
477                    }
478                    more_messages = self.parse_data(bytes, &mut result_messages)?;
479                }
480            }
481        }
482        Ok(result_messages)
483    }
484
485    fn parse_data(&self, bytes: usize, messages: &mut Vec<Message>) -> Result<bool>
486    {
487        let mut more_messages = false;
488        let mut reader = io::Cursor::new(&self.receive_buffer[0..bytes]);
489        let mut pos = 0;
490        while pos < bytes {
491            reader.seek(SeekFrom::Start(pos as u64))?;
492            let header = Header::parse(&mut reader)?;
493            pos = pos + header.aligned_length();
494            if !header.check_pid(self.local.pid) {
495                return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid PID").into());
496            }
497            if !header.check_sequence(self.sequence_expected) {
498                return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid Sequence").into());
499            }
500            if header.identifier == NLMSG_NOOP {
501                continue;
502            }
503            else if header.identifier == NLMSG_ERROR {
504                let emsg = ErrorMessage::parse(&mut reader, header)?;
505                if emsg.code != 0 {
506                    return Err(io::Error::from_raw_os_error(-emsg.code).into());
507                }
508                else {
509                    messages.push(Message::Acknowledge);
510                }
511            }
512            else if header.identifier == NLMSG_DONE {
513                messages.push(Message::Done);
514            }
515            else {
516                let flags = MessageFlags::from_bits(header.flags).unwrap_or(MessageFlags::empty());
517                messages.push(Message::Data(DataMessage::parse(&mut reader, header)?));
518                if flags.contains(MessageFlags::MULTIPART) || self.acknowledge_expected {
519                    more_messages = true;
520                }
521            }
522        }
523        return Ok(more_messages);
524    }
525}
526
527impl AsRawFd for Socket {
528    fn as_raw_fd(&self) -> RawFd
529    {
530        self.socket
531    }
532}