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

Error when populating a MutableFragmentPacket #487

Open
johanmazelanssi opened this issue May 5, 2021 · 7 comments
Open

Error when populating a MutableFragmentPacket #487

johanmazelanssi opened this issue May 5, 2021 · 7 comments

Comments

@johanmazelanssi
Copy link

johanmazelanssi commented May 5, 2021

I am using libpnet 0.27.2.

I get an error when I try to populate a MutableFragmentPacket.

For example with something like this.

extern crate pnet;

use pnet::packet::Packet;
use pnet::packet::ip::IpNextHeaderProtocol;
use pnet::packet::ipv6;

fn main() {
    let id = 3;
    let fragment_offset = 0;
    let mf = 1;

    let payload = [0, 1, 2, 3];
    let payload_len = payload.len();
    println!(
        "main: payload_len: {}",
        payload_len
    );

    let ipv6fragment_extension_header_header_len = 8;
    let ipv6_fragment_exetension_header_packet_len =
        ipv6fragment_extension_header_header_len + payload_len;
    println!(
        "main: ipv6_fragment_exetension_header_packet_len: {}",
        ipv6_fragment_exetension_header_packet_len
    );

    // We shift fragment_offset 3 bits to the left and add the MF bit from fragment_flag (last bit).
    let fragment_offset_with_flags = fragment_offset * 8 + mf;

    let mut fragment_data_like_v: Vec<u8> = vec![0; ipv6_fragment_exetension_header_packet_len + 8];
    let fragment = ipv6::Fragment {
        next_header: IpNextHeaderProtocol::new(0),
        reserved: 0,
        fragment_offset_with_flags,
        id: id as u32,
        payload: payload.to_vec(),
    };
    let mut mutable_fragment_packet =
        ipv6::MutableFragmentPacket::new(&mut fragment_data_like_v[..]).unwrap();
    mutable_fragment_packet.populate(&fragment);

    println!(
        "main: data: {:?}",
        mutable_fragment_packet.packet().to_vec()
    );
}

I get an error on the line with "mutable_fragment_packet.populate(&fragment);".

When I check the backtrace, it looks like that the generated code that set the payload of an IPv6 fragment contains an assert that check that the payload is 0.
Here is the code that is generated on my machine:

    /// Set the value of the payload field (copies contents)
    #[inline]
    #[allow(trivial_numeric_casts)]
    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
    pub fn set_payload(&mut self, vals: &[u8]) {
        let mut _self = self;
        let current_offset = 8;
        let len = 0;
        assert!(vals . len (  ) <= len);
        _self.packet[current_offset..current_offset +
                                         vals.len()].copy_from_slice(vals);
    }

I think like the len variable should not be set to 0, but to the complete size of the extension and the payload of the other extensions and upper protocols.

@infosechoudini
Copy link

@johanmazelanssi this error still persistent or was it resolved in v0.29?

@johanmazelanssi
Copy link
Author

I just recompiled the code above with rustc 1.60.0 and pnet 0.29.
I got the same error.

@infosechoudini
Copy link

@johanmazelanssi okay, I'll take a look at it

infosechoudini pushed a commit to infosechoudini/libpnet_fork that referenced this issue Apr 22, 2022
…e payload is at the end of the packet, github issue libpnet#487
@infosechoudini
Copy link

@johanmazelanssi try this brach: https://github.com/infosechoudini/libpnet/tree/issue-487

it has your code in it ~pnet/src/gh_issue_487.rs

@infosechoudini
Copy link

Also, in you code, I modified the the following

    let ipv6_fragment_exetension_header_packet_len = ipv6fragment_extension_header_header_len + payload_len;
    println!(
        "main: ipv6_fragment_exetension_header_packet_len: {}",
        ipv6_fragment_exetension_header_packet_len
    );

    // We shift fragment_offset 3 bits to the left and add the MF bit from fragment_flag (last bit).
    let fragment_offset_with_flags = fragment_offset * 8 + mf;

    //original line
    let mut fragment_data_like_v: Vec<u8> = vec![0; ipv6_fragment_exetension_header_packet_len + 8]; 

   //modified
    let mut fragment_data_like_v: Vec<u8> = vec![0; ipv6_fragment_exetension_header_packet_len]; 
    //got rid of '+ 8'
    
   // When adding +8 to the fragmnt_data_like_v and populating the mutable_fragment_packet, it caused the extra 8 bytes of    
  // the vec to be added to the end of the payload, I'm assuming you didn't want that hence the ' let payload = [0, 1, 2, 3];'


@johanmazelanssi
Copy link
Author

johanmazelanssi commented Apr 22, 2022

I confirm that this branch fixes this problem. Thank you very much.

I noticed another correctness problem that does impact this bug.
let fragment_offset_with_flags = fragment_offset * 8 + mf;
should actually be:
let fragment_offset_with_flags = (fragment_offset << 3) + mf;

@infosechoudini
Copy link

@johanmazelanssi awesome! let me do a PR and get this merged

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

No branches or pull requests

2 participants