Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copying Rtmsg value #248

Open
pseusys opened this issue Oct 30, 2024 · 5 comments
Open

Copying Rtmsg value #248

pseusys opened this issue Oct 30, 2024 · 5 comments
Assignees
Labels

Comments

@pseusys
Copy link

pseusys commented Oct 30, 2024

I would like to implement something close to ip route save command, store all the contents of a routing table and clear it.

For that purpose I have implemented a simple function:

fn save_table(table_idx: i32) -> Result<Vec<Rtmsg>, Box<dyn Error>> {
    let table_const = RtTable::UnrecognizedConst(table_idx as u8);
    let mut receiver_socket = NlSocketHandle::connect(NlFamily::Route, None, &[])?;
    let mut sender_socket = NlSocketHandle::connect(NlFamily::Route, None, &[]).unwrap();

    let mut table_data = Vec::new();
    let send_payload = Rtmsg {rtm_family: RtAddrFamily::Inet, rtm_dst_len: 0, rtm_src_len: 0, rtm_tos: 0, rtm_table: table_const, rtm_protocol: Rtprot::Unspec, rtm_scope: RtScope::Universe, rtm_type: Rtn::Unspec, rtm_flags: RtmFFlags::empty(), rtattrs: RtBuffer::new()};
    let send_msg = Nlmsghdr::new(None, Rtm::Getroute, NlmFFlags::new(&[NlmF::Request, NlmF::Dump]), None, None, NlPayload::Payload(send_payload));
    receiver_socket.send(send_msg).unwrap();
    for response in receiver_socket.iter(false) {
        let header: Nlmsghdr<Rtm, Rtmsg> = response.unwrap();
        if let NlPayload::Payload(recv_payload) = header.nl_payload {
            if recv_payload.rtm_table == table_const {
                table_data.push(recv_payload);
                let rm_msg = Nlmsghdr::new(None, Rtm::Delroute, NlmFFlags::new(&[NlmF::Request]), None, None, header.nl_payload);  // Here an error appears, since `header.nl_payload` is partially moved.
                sender_socket.send(rm_msg).unwrap();
            }
        }
    }

    Ok(table_data)
}
}

For now I am struggling with copying received Rtmsg instances.
Basically I can not store them in an array and also use for removing from the table call at the same time, since they do not implement Copy trait.
How could I possibly save the message instance for future use and also remove it from the table?
Is there a way to copy it?

@pseusys
Copy link
Author

pseusys commented Oct 30, 2024

Maybe I'm just not proficient with rust enough yet tho :(

@pseusys pseusys changed the title Storing Rtmsg value Copying Rtmsg value Oct 30, 2024
@jbaublitz
Copy link
Owner

Hi @pseusys, have you tried .clone()? I'm pretty sure that should be implemented on all data structures.

@pseusys
Copy link
Author

pseusys commented Oct 31, 2024

Yes. I doublechecked that: it is implemented, but only in the latest releases (0.7.0), that are still release candidates. In the latest stable release, there is no Clone trait available.

@jbaublitz
Copy link
Owner

I see your problem after digging into this a little bit deeper. Here's what I would suggest as a workaround. It's not ergonomic, but I think it should work:

        if let NlPayload::Payload(recv_payload) = header.nl_payload {
            if recv_payload.rtm_table == table_const {
                let rm_msg = Nlmsghdr::new(None, Rtm::Delroute, NlmFFlags::new(&[NlmF::Request]), None, None, /* Reconstruct an NlPayload::(Rtmsg::new()) here. All of the fields are able to be copied and are public except for the attributes which can be borrowed. That should be sufficient for sending the message. /*);
                sender_socket.send(rm_msg).unwrap();
                table_data.push(recv_payload); // The above will not consume the data structure, just borrow it, so then you can move ownership to the vector.
            }
        }

Let me know if you need any more help with this.

@pseusys
Copy link
Author

pseusys commented Nov 7, 2024

I will come back to it again once 0.7.0 is released and try different solutions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants