From 09c1b63335363dfcdbe8acc22cc1297cb52c2543 Mon Sep 17 00:00:00 2001 From: liuxu Date: Sat, 23 Sep 2023 22:43:36 +0800 Subject: [PATCH] add new_route example --- examples/new_route.rs | 93 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 examples/new_route.rs diff --git a/examples/new_route.rs b/examples/new_route.rs new file mode 100644 index 00000000..acbc4a3c --- /dev/null +++ b/examples/new_route.rs @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT + +use netlink_packet_core::{ + NetlinkHeader, NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_CREATE, + NLM_F_EXCL, NLM_F_REQUEST, +}; +use netlink_packet_route::{ + constants::AF_INET, route, RouteFlags, RouteHeader, RouteMessage, + RtnlMessage, RTN_UNICAST, RTPROT_BOOT, RT_SCOPE_UNIVERSE, RT_TABLE_MAIN, +}; +use netlink_sys::{protocols::NETLINK_ROUTE, Socket, SocketAddr}; +use std::net::Ipv4Addr; + +fn main() { + let mut socket = Socket::new(NETLINK_ROUTE).unwrap(); + let _port_number = socket.bind_auto().unwrap().port_number(); + socket.connect(&SocketAddr::new(0, 0)).unwrap(); + + let mut route_msg_hdr = RouteHeader::default(); + route_msg_hdr.address_family = AF_INET as u8; + route_msg_hdr.table = RT_TABLE_MAIN; + route_msg_hdr.scope = RT_SCOPE_UNIVERSE; + route_msg_hdr.protocol = RTPROT_BOOT; + route_msg_hdr.kind = RTN_UNICAST; + route_msg_hdr.source_prefix_length = 0; + route_msg_hdr.destination_prefix_length = 32; + route_msg_hdr.flags = RouteFlags::RTNH_F_ONLINK; + + let mut route_msg = RouteMessage::default(); + route_msg.header = route_msg_hdr; + route_msg.nlas = vec![ + // lo + route::Nla::Oif(1), + route::Nla::Gateway( + "169.254.1.1".parse::().unwrap().octets().to_vec(), + ), + route::Nla::Destination( + "1.1.1.1".parse::().unwrap().octets().to_vec(), + ), + ]; + let mut nl_hdr = NetlinkHeader::default(); + nl_hdr.flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK; + + let mut msg = NetlinkMessage::new( + nl_hdr, + NetlinkPayload::from(RtnlMessage::NewRoute(route_msg)), + ); + + msg.finalize(); + let mut buf = vec![0; msg.header.length as usize]; + + msg.serialize(&mut buf[..msg.buffer_len()]); + + println!(">>> {msg:?}"); + + socket + .send(&buf, 0) + .expect("failed to send netlink message"); + + let mut receive_buffer = vec![0; 4096]; + let mut offset = 0; + + 'outer: loop { + let size = socket.recv(&mut &mut receive_buffer[..], 0).unwrap(); + + loop { + let bytes = &receive_buffer[offset..]; + // Parse the message + let rx_packet: NetlinkMessage = + NetlinkMessage::deserialize(bytes).unwrap(); + + match rx_packet.payload { + NetlinkPayload::Error(err) => match err.code { + None => { + println!("Done!"); + break 'outer; + } + Some(_) => { + eprintln!("Received a netlink error message: {err:?}"); + return; + } + }, + _ => {} + } + + offset += rx_packet.header.length as usize; + if offset == size || rx_packet.header.length == 0 { + offset = 0; + break; + } + } + } +}