Skip to content

Commit

Permalink
Merge branch 'devel'
Browse files Browse the repository at this point in the history
  • Loading branch information
chamaken committed Jun 2, 2017
2 parents 4b53ae9 + c06cd5d commit 0856b78
Show file tree
Hide file tree
Showing 28 changed files with 1,670 additions and 465 deletions.
62 changes: 39 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
crslmnl
=======

Rust wrapper of libmnl, less safe.
A Rust wrapper for libmnl.


sample
Expand All @@ -13,7 +13,12 @@ see examples
requires
--------

* libmnl
* libmnl - C libmnl library
* Rust gcc
* for examples:
- Rust time
- Rust mio
- Rust pnet


links
Expand All @@ -34,7 +39,7 @@ thanks to [Shepmaster](http://stackoverflow.com/users/155423/shepmaster)
comparison
----------

| original | cgolmnl | remarks |
| original | crslmnl | remarks |
| ------------------------------------- | ----------------------------- | ----------------------------- |
| mnl_attr_get_type | Attr.atype | |
| mnl_attr_get_len | Attr.len | |
Expand All @@ -47,38 +52,44 @@ comparison
| mnl_attr_validate | Attr.validate | |
| mnl_attr_validate2 | Attr.validate2 | |
| mnl_attr_parse | Attr.parse | |
| (add) | Attr.cl_parse | |
| mnl_attr_parse_nested | Attr.parse_nested | |
| mnl_attr_parse_payload | parse_payload | |
| (add) | Attr.cl_parse_nested | |
| mnl_attr_parse_payload | parse_attrs | |
| (add) | cl_parse_attrs | |
| mnl_attr_get_u8 | Attr.u8 | |
| mnl_attr_get_u16 | Attr.u16 | |
| mnl_attr_get_u32 | Attr.u32 | |
| mnl_attr_get_u64 | Attr.u64 | |
| mnl_attr_get_str | Attr.str | |
| (add) | Attr.string | |
| mnl_attr_put | Nlmsg.put | |
| mnl_attr_put_u8 | Nlmsg.put_u8 | |
| mnl_attr_put_u16 | Nlmsg.put_u16 | |
| mnl_attr_put_u32 | Nlmsg.put_u32 | |
| mnl_attr_put_u64 | Nlmsg.put_u64 | |
| mnl_attr_put_str | Nlmsg.put_str | |
| mnl_attr_put_strz | Nlmsg.put_strz | |
| mnl_attr_put_check | Nlmsg.put_check | |
| mnl_attr_put_u8_check | Nlmsg.put_u8_check | |
| mnl_attr_put_u16_check | Nlmsg.put_u16_check | |
| mnl_attr_put_u32_check | Nlmsg.put_u32_check | |
| mnl_attr_put_u64_check | Nlmsg.put_u64_check | |
| mnl_attr_put_str_check | Nlmsg.put_str_check | |
| mnl_attr_put_strz_check | Nlmsg.put_strz_check | |
| mnl_attr_nest_start | Nlmsg.nest_start | |
| mnl_attr_nest_start_check | Nlmsg.nest_start_check | |
| mnl_attr_put | Nlmsg.put_raw | |
| mnl_attr_put_u8 | Nlmsg.put_u8_raw | |
| mnl_attr_put_u16 | Nlmsg.put_u16_raw | |
| mnl_attr_put_u32 | Nlmsg.put_u32_raw | |
| mnl_attr_put_u64 | Nlmsg.put_u64_raw | |
| mnl_attr_put_str | Nlmsg.put_str_raw | |
| mnl_attr_put_strz | Nlmsg.put_strz_raw | |
| mnl_attr_put_check | Nlmsg.put | |
| mnl_attr_put_u8_check | Nlmsg.put_u8 | |
| mnl_attr_put_u16_check | Nlmsg.put_u16 | |
| mnl_attr_put_u32_check | Nlmsg.put_u32 | |
| mnl_attr_put_u64_check | Nlmsg.put_u64 | |
| mnl_attr_put_str_check | Nlmsg.put_str | |
| mnl_attr_put_strz_check | Nlmsg.put_strz | |
| mnl_attr_nest_start | Nlmsg.nest_start_raw | |
| mnl_attr_nest_start_check | Nlmsg.nest_start | |
| mnl_attr_nest_end | Nlmsg.nest_end | |
| mnl_attr_nest_cancel | Nlmsg.nest_cancel | |
| ------------------------------------- | ----------------------------- | ----------------------------- |
| mnl_nlmsg_size | Nlmsg::size | |
| mnl_nlmsg_get_payload_len | Nlmsg.payload_len | |
| mnl_nlmsg_put_header | Nlmsg::new | |
| mnl_nlmsg_put_header | Nlmsg.put_header | |
| mnl_nlmsg_put_extra_header | Nlmsg.put_extra_header | |
| mnl_nlmsg_put_header | Nlmsg.put_header_raw | |
| (add) | Nlmsg.put_header_check | |
| mnl_nlmsg_put_extra_header | Nlmsg.put_extra_header_raw | |
| (add) | Nlmsg.put_sized_header | |
| (add) | Nlmsg.put_sized_header_raw | |
| (add) | Nlmsg.put_sized_header | |
| mnl_nlmsg_get_paylod | Nlmsg.payload | |
| mnl_nlmsg_get_paylod | Nlmsg.payload_mut | |
Expand All @@ -102,7 +113,9 @@ comparison
| mnl_nlmsg_batch_is_empty | NlmsgBatch.is_empty | |
| ------------------------------------- | ----------------------------- | ----------------------------- |
| mnl_cb_run | cb_run | |
| mnl_cb_run2 | cb_run2 | changed signature |
| mnl_cb_run2 | cb_run2 | |
| (add) | cl_run | closure instead of callback |
| (add) | cl_run2 | closure instead of callback |
| ------------------------------------- | ----------------------------- | ----------------------------- |
| mnl_socket_get_fd | Socket.as_raw_fd | |
| mnl_socket_get_portid | Socket.portid | |
Expand All @@ -120,3 +133,6 @@ comparison
| ------------------------------------- | ----------------------------- | ----------------------------- |
| mnl_attr_for_each | Nlmsg.attrs | |
| mnl_attr_for_each_nested | Attr.nesteds | |
| ------------------------------------- | ----------------------------- | ----------------------------- |
| (add) | NlmsgIterator | |
| (add) | Iterator for NlmsgBatch | |
1 change: 1 addition & 0 deletions examples/genl-family-get2.rs
8 changes: 4 additions & 4 deletions examples/genl/genl-family-get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,18 @@ fn main() {
let mut buf = vec![0u8; mnl::SOCKET_BUFFER_SIZE()];
let seq = time::now().to_timespec().sec as u32;
{
let mut nlh = mnl::Nlmsg::new(&mut buf);
let mut nlh = mnl::Nlmsg::new(&mut buf).unwrap();
*nlh.nlmsg_type = genl::GENL_ID_CTRL;
*nlh.nlmsg_flags = netlink::NLM_F_REQUEST | netlink::NLM_F_ACK;
*nlh.nlmsg_seq = seq;

let genl = nlh.put_sized_header::<genl::Genlmsghdr>();
let genl = nlh.put_sized_header::<genl::Genlmsghdr>().unwrap();
genl.cmd = genl::CtrlCmd::GETFAMILY as u8;
genl.version = 1;

nlh.put_u16(genl::CtrlAttr::FAMILY_ID as u16, genl::GENL_ID_CTRL);
nlh.put_u16(genl::CtrlAttr::FAMILY_ID as u16, genl::GENL_ID_CTRL).unwrap();
if args.len() >= 2 {
nlh.put_strz(genl::CtrlAttr::FAMILY_NAME as u16, &args[1]);
nlh.put_strz(genl::CtrlAttr::FAMILY_NAME as u16, &args[1]).unwrap();
} else {
*nlh.nlmsg_flags |= netlink::NLM_F_DUMP;
}
Expand Down
226 changes: 226 additions & 0 deletions examples/genl/genl-family-get2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
use std::env;
use std::io::Write;
use std::mem::size_of;

extern crate libc;
extern crate time;
extern crate crslmnl as mnl;

use mnl::linux::netlink as netlink;
use mnl::linux::genetlink as genl;


macro_rules! println_stderr(
($($arg:tt)*) => { {
let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
r.expect("failed printing to stderr");
} }
);

fn parse_mc_grps_cb<'a, 'b>(tb: &'b mut [Option<&'a mnl::Attr>]) -> Box<FnMut(&'a mnl::Attr) -> mnl::CbRet + 'b> {
Box::new(move |attr: &'a mnl::Attr| {
// skip unsupported attribute in user-space
if let Err(_) = attr.type_valid(genl::CTRL_ATTR_MCAST_GRP_MAX as u16) {
return mnl::CbRet::OK;
}

let atype = attr.atype();
match atype {
n if n == genl::CtrlAttrMcastGrp::ID as u16 => {
if let Err(errno) = attr.validate(mnl::AttrDataType::U32) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
n if n == genl::CtrlAttrMcastGrp::NAME as u16 => {
if let Err(errno) = attr.validate(mnl::AttrDataType::STRING) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
_ => {},
}
tb[atype as usize] = Some(attr);
mnl::CbRet::OK
})
}

fn parse_genl_mc_grps(nested: &mnl::Attr) {
for pos in nested.nesteds() {
let mut tb: [Option<&mnl::Attr>; genl::CTRL_ATTR_MCAST_GRP_MAX as usize + 1]
= [None; genl::CTRL_ATTR_MCAST_GRP_MAX as usize + 1];

let _ = pos.cl_parse_nested(parse_mc_grps_cb(&mut tb));

tb[genl::CtrlAttrMcastGrp::ID as usize]
.map(|attr| print!("id-0x{:x} ", attr.u32()));
tb[genl::CtrlAttrMcastGrp::NAME as usize]
.map(|attr| print!("name: {} ", attr.str()));
println!("");
}
}

fn parse_genl_family_ops<'a>(nested: &mnl::Attr) {
for pos in nested.nesteds() {
let mut tb: [Option<&'a mnl::Attr>; genl::CTRL_ATTR_OP_MAX as usize + 1]
= [None; genl::CTRL_ATTR_OP_MAX as usize + 1];

let _ = pos.cl_parse_nested(Box::new(|attr: &'a mnl::Attr| {
if let Err(_) = attr.type_valid(genl::CTRL_ATTR_OP_MAX) {
return mnl::CbRet::OK;
}

let atype = attr.atype();
match atype {
n if (n == genl::CtrlAttrOp::ID as u16 ||
n == genl::CtrlAttrOp::FLAGS as u16) => {
if let Err(errno) = attr.validate(mnl::AttrDataType::U32) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
n if n == genl::CTRL_ATTR_OP_MAX => {},
_ => {
return mnl::CbRet::OK;
},
}

tb[atype as usize] = Some(attr);
return mnl::CbRet::OK;
}));

tb[genl::CtrlAttrOp::ID as usize]
.map(|attr| print!("id-0x{:x} ", attr.u32()));
tb[genl::CtrlAttrOp::FLAGS as usize]
.map(|attr| print!("flags 0x{:08x}", attr.u32()));
println!("");
}
}

fn data_attr_cb<'a, 'b>(tb: &'b mut [Option<&'a mnl::Attr>])
-> Box<FnMut(&'a mnl::Attr) -> mnl::CbRet + 'b>
{
Box::new(move |attr: &'a mnl::Attr| {
if let Err(_) = attr.type_valid(genl::CTRL_ATTR_MAX) {
return mnl::CbRet::OK;
}

let atype = attr.atype();
match atype {
n if n == genl::CtrlAttr::FAMILY_NAME as u16 => {
if let Err(errno) = attr.validate(mnl::AttrDataType::STRING) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
n if n == genl::CtrlAttr::FAMILY_ID as u16 => {
if let Err(errno) = attr.validate(mnl::AttrDataType::U16) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
n if (n == genl::CtrlAttr::VERSION as u16 ||
n == genl::CtrlAttr::HDRSIZE as u16 ||
n == genl::CtrlAttr::MAXATTR as u16) => {
if let Err(errno) = attr.validate(mnl::AttrDataType::U32) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
n if (n == genl::CtrlAttr::OPS as u16 ||
n == genl::CtrlAttr::MCAST_GROUPS as u16) => {
if let Err(errno) = attr.validate(mnl::AttrDataType::NESTED) {
println_stderr!("mnl_attr_validate - {}: {}", atype, errno);
return mnl::CbRet::ERROR;
}
},
_ => {},
}

tb[atype as usize] = Some(attr);
return mnl::CbRet::OK;
})
}

fn data_cb() -> Box<FnMut(mnl::Nlmsg) -> mnl::CbRet> {
Box::new(|nlh: mnl::Nlmsg| {
let mut tb: [Option<&mnl::Attr>; genl::CTRL_ATTR_MAX as usize + 1]
= [None; genl::CTRL_ATTR_MAX as usize + 1];

let _ = nlh.cl_parse(size_of::<genl::Genlmsghdr>(), data_attr_cb(&mut tb));

tb[genl::CtrlAttr::FAMILY_NAME as usize]
.map(|attr| print!("name={}\t", attr.str()));
tb[genl::CtrlAttr::FAMILY_ID as usize]
.map(|attr| print!("id={}\t", attr.u16()));
tb[genl::CtrlAttr::VERSION as usize]
.map(|attr| print!("version={}\t", attr.u32()));
tb[genl::CtrlAttr::HDRSIZE as usize]
.map(|attr| print!("hdrsize={}\t", attr.u32()));
tb[genl::CtrlAttr::MAXATTR as usize]
.map(|attr| print!("maxattr={}\t", attr.u32()));
println!("");

tb[genl::CtrlAttr::OPS as usize]
.map(|attr| {
println!("ops:");
parse_genl_family_ops(attr);
});
tb[genl::CtrlAttr::MCAST_GROUPS as usize]
.map(|attr| {
println!("grps:");
parse_genl_mc_grps(attr);
});
println!("");

return mnl::CbRet::OK;
})
}

fn main() {
let args: Vec<_> = env::args().collect();
if args.len() > 2 {
panic!("{} [family name]", args[0]);
}

let nl = mnl::Socket::open(netlink::Family::GENERIC)
.unwrap_or_else(|errno| panic!("mnl_socket_open: {}", errno));
nl.bind(0, mnl::SOCKET_AUTOPID)
.unwrap_or_else(|errno| panic!("mnl_socket_bind: {}", errno));
let portid = nl.portid();

let mut buf = vec![0u8; mnl::SOCKET_BUFFER_SIZE()];
let seq = time::now().to_timespec().sec as u32;
{
let mut nlh = mnl::Nlmsg::new(&mut buf).unwrap();
*nlh.nlmsg_type = genl::GENL_ID_CTRL;
*nlh.nlmsg_flags = netlink::NLM_F_REQUEST | netlink::NLM_F_ACK;
*nlh.nlmsg_seq = seq;

let genl = nlh.put_sized_header::<genl::Genlmsghdr>().unwrap();
genl.cmd = genl::CtrlCmd::GETFAMILY as u8;
genl.version = 1;

nlh.put_u16(genl::CtrlAttr::FAMILY_ID as u16, genl::GENL_ID_CTRL).unwrap();
if args.len() >= 2 {
nlh.put_strz(genl::CtrlAttr::FAMILY_NAME as u16, &args[1]).unwrap();
} else {
*nlh.nlmsg_flags |= netlink::NLM_F_DUMP;
}

nl.send_nlmsg(&nlh)
.unwrap_or_else(|errno| panic!("mnl_socket_sendto: {}", errno));
}

loop {
let nrecv = nl.recvfrom(&mut buf)
.unwrap_or_else(|errno| panic!("mnl_socket_recvfrom: {}", errno));

if mnl::cl_run(&buf[0..nrecv], seq, portid, Some(data_cb()))
.unwrap_or_else(|errno| panic!("mnl_cb_run: {}", errno))
== mnl::CbRet::STOP {
break;
}
}
let _ = nl.close();
}
Loading

0 comments on commit 0856b78

Please sign in to comment.