приведите `

#rust #nftables

Вопрос:

Я использую nftnl-rs для построения таблицы правил nftables с большим успехом. Но теперь я хочу знать, есть ли уже таблица с таким же именем в системе. Я нашел две функции в nftnl-rs nftnl/src/table.rs , которые, похоже, точно созданы для этого : get_tables_nlmsg() и get_tables_cb(). Однако я не смог успешно их использовать. get_tables_cb() в строке документа говорится, что он был создан для обработки вывода первого , но get_tables_nlmsg() возвращает a Vec<u8> , по-видимому, содержащий адрес памяти созданного nlmsghdr, в то get_tables_cb() время как принимает an amp;nlmsghdr в качестве аргумента.

В частности, я пытался :

 use std::collections::HashSet;
use std::ffi::CString;
use nftnl{self, nftnl_sys::libc};

fn dump_tables() -> Result<(), Box<dyn std::error::Error> {
    let mut tables: amp;mut HashSet<CString> = amp;mut HashSet::new();
    let mut buffer = nftnl::table::get_tables_nlmsg(0);
    let buffer = buffer.as_ptr() as *const libc::nlmsghdr;

    nftnl::table::get_tables_cb(amp;amp;buffer, amp;mut tables);
    println!("{:?}", tables);
    Ok(())
}
 

rustc жалуется , что он ожидал amp;nlmsghdr и получил amp;amp;*const nlmsghdr «а», и я не смог бросить первое во второе. Я просмотрел исходный код и примеры, не видя появления этого случая приведения. Перескакивая назад и вперед в источнике, я обнаружил, что часть Номикона говорит о непрозрачных структурах, которые , похоже, применимы nlmsghdr , но также не решают мою проблему. На самом деле я немного запутался с объявлением функции :

 pub fn get_tables_cb(header: amp;libc::nlmsghdr, tables: amp;mut HashSet<CString>) -> libc::c_int
 

Если *const libc::nlmsghdr это чужеродная Структура, то что, черт возьми, может amp;libc::nlmsghdr быть ? Может быть, где-то в источнике nftnl-rs есть опечатка ?

Комментарии:

1. Вы пробовали отправлять сообщение, сгенерированное с get_tables_nlmsg помощью сокета netfilter, и анализировать результат с помощью get_tables_cb ?

2. Я попробую это сделать. Вы случайно не Ls256 в Вики-арке ? Недавно я скопировал статью о NanoPi_M1 из упомянутой вики на свою страницу пользователя, потому что они угрожают удалить ее как нецелевое использование.

3. Я не они, но рад, что смог помочь!

Ответ №1:

Используя предложение Coder-256, можно найти mnl::cb_run2() в дочернем пакете mnl-rs, который может использоваться nftnl::tables::get_tables_cb() в качестве обратного вызова при получении пакета netlink. Поскольку пакеты netlink могут быть многопакетными, если данные слишком велики, чтобы поместиться в одном NlMsg, вероятно, можно было бы использовать его следующим образом :

 use std::collections::HashSet;
use mnl;
use nftnl;

fn dump_tables() -> Result<(), Box<dyn std::error::Error>> {
    let seq = 0;
    let tables = amp;mut HashSet::new();
    let mut buffer = nftnl::table::get_tables_nlmsg(seq);
    let socket = mnl::Socket::new(mnl::Bus::Netfilter)?;

    socket.send(amp;buffer)?;
    // Answer may be multi-packed, loop over what we get.
    loop {
        let chars_written = socket.recv(amp;mut *buffer)?;
        if chars_written == 0 { break; }
        let message = amp;buffer[..chars_written];
        match mnl::cb_run2(message, seq, socket.portid(), nftnl::table::get_tables_cb, tables)? {
            mnl::CbResult::Stop => break,
            mnl::CbResult::Ok => ()
        }
    }
    println!("{:?}", tables);
    Ok(())
}
 

Я должен признаться, что до сих пор не знаю, что amp;libc::nlmsghdr именно означает, как и зачем его строить ; я с радостью приму любой ответ, который сможет прояснить этот момент.