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
21pub 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;
57const NETLINK_ADD_MEMBERSHIP: i32 = 1;
60bitflags! {
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
308pub 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 pub fn new(protocol: Protocol) -> Result<Socket>
325 {
326 Socket::new_multicast(protocol, 0)
327 }
328
329 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 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 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 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 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}