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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! This package contains types that represent netlink messages. See the [`libnl` library
//! documentation][libnl] for an introduction to the Netlink protocols.
//!
//! This crate provides widely different types based on the features that are enabled. There are
//! currently two features available, which are mutually exclusive `rtnetlink` and `audit`. With
//! the `rtnetlink` feature, this crates provides types for the `NETLINK_ROUTE` protocol family
//! (see `man 7 rtnetlink`). With the `audit` feature, this crate provides types for the
//! `NETLINK_AUDIT` protocol family.
//!
//! [libnl]: https://www.infradead.org/~tgr/libnl/doc/core.html#core_netlink_fundamentals
//!
//! # Generating the documentation for the desired feature
//!
//! At the moment, rustdoc does not support features very well. If you plan on using this crate,
//! you should probably generate the appropriate documentation yourself by getting the source, and
//! running `cargo doc`:
//!
//! ```no_rust
//! cargo doc --open --features audit     # for the audit messages
//! cargo doc --open --features rtnetlink # for the rtnetlink messages
//! ```
//!
//! # Overview
//!
//! Independently of the feature that is enabled, this crate provides two representations of most
//! netlink packets:
//!
//! - **Buffer** types like [`NetlinkBuffer`](struct.NetlinkBuffer.html) for instance. These types
//! wrappers around actual byte buffers, and provide safe accessors to the various fields of the
//! packet they represent. These types are useful if you manipulate byte streams, but everytime
//! data is accessed, it must be parsed or encoded.
//!
//! - Higher level representation of netlink packets, like
//! [`NetlinkMessage`](struct.NetlinkMessage.html), which are the prefered way to build packets.
//!
//! ## Using buffer types to parse messages
//!
//! It is possible to go from on representation to another. Actually, the buffer types are used to
//! parse byte buffers into messages types, using the [`Parseable`](trait.Parseable.html) trait. In
//! the list of implementors, we can see for instance:
//!
//! ```no_rust
//! impl<'buffer, T: AsRef<[u8]> + 'buffer> Parseable<NetlinkMessage> for NetlinkBuffer<&'buffer T>
//! ```
//!
//! That means a `NetlinkBuffer` is parseable into a `NetlinkMessage` (note that the following
//! snippets assumes the crate is being used with the `rtnetlink` feature):
//!
//! ```rust,no_run
//! # // FIXME: this snippet is `no_run` because it breaks cargo test, when the rtnetlink feature
//! # // is not enabled. If rustc supports that better in the future, somehow, we should run this
//! # // example.
//! extern crate netlink_packet;
//! use netlink_packet::{NetlinkBuffer, NetlinkMessage, Parseable};
//! use netlink_packet::constants::{RTM_GETLINK, NLM_F_ROOT, NLM_F_REQUEST, NLM_F_MATCH};
//!
//! // a packet captured with tcpdump that was sent when running `ip link show`
//! static PKT: [u8; 40] = [
//!     0x28, 0x00, 0x00, 0x00, // length
//!     0x12, 0x00, // message type
//!     0x01, 0x03, // flags
//!     0x34, 0x0e, 0xf9, 0x5a, // sequence number
//!     0x00, 0x00, 0x00, 0x00, // port id
//!     // payload
//!     0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//!     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//!     0x08, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x00];
//!
//! fn main() {
//!     let pkt: NetlinkMessage =
//!         // Create a buffer. Notice the double &&. That is because Parseable<NetlinkMessage> is
//!         // implemented for NetlinkBuffer<&T> not NetlinkBuffer<T>. The reason behing this is
//!         // that we want the storage T to be able to outlive our NetlinkBuffer, if necessary. It
//!         // feels a bit weird here but can be useful in other circumstances.
//!         NetlinkBuffer::new_checked(&&PKT[..])
//!             .unwrap()
//!             // Convert the buffer into an actual message. This is when the parsing occurs.
//!             .parse()
//!             .unwrap();
//!
//!     println!("{:#?}", pkt);
//! }
//! ```
//!
//! This prints:
//!
//! ```no_rust
//! NetlinkMessage {
//!     header: NetlinkHeader {
//!         length: 40,
//!         message_type: 18,
//!         flags: NetlinkFlags(769),
//!         sequence_number: 1526271540,
//!         port_number: 0
//!     },
//!     message: GetLink(
//!         LinkMessage {
//!             header: LinkHeader {
//!                 address_family: 17,
//!                 index: 0,
//!                 link_layer_type: Netrom,
//!                 flags: LinkFlags(0),
//!                 change_mask: LinkFlags(0)
//!             },
//!             nlas: [ExtMask(1)]
//!         }
//!     ),
//! }
//! ```
//!
//! ## Emitting messages
//!
//! TODO

#![cfg_attr(rustfmt, rustfmt::skip)]

#[macro_use] extern crate log;

pub use netlink_sys::constants;

mod errors;
pub use self::errors::*;

use core::ops::{Range, RangeFrom};
/// Represent a multi-bytes field with a fixed size in a packet
pub(crate) type Field = Range<usize>;
/// Represent a field that starts at a given index in a packet
pub(crate) type Rest = RangeFrom<usize>;

#[cfg(feature = "rtnetlink")]
/// Represent a field of exactly one byte in a packet
pub(crate) type Index = usize;

#[cfg(feature = "rtnetlink")]
/// rtnetlink types (see `man 7 rtnetlink`)
mod rtnl;
#[cfg(feature = "rtnetlink")]
pub use self::rtnl::*;

#[cfg(feature = "audit")]
mod audit;
#[cfg(feature = "audit")]
pub use self::audit::*;

mod netlink;
pub use self::netlink::*;

// FIXME: should we expose these traits or only keep them for internal use?
mod traits;
pub use self::traits::*;

#[cfg(test)] #[macro_use] extern crate lazy_static;