{"action":"created","issue":{"url":"https://api.github.com/repos/libpnet/libpnet/issues/134","labels_url":"https://api.github.com/repos/libpnet/libpnet/issues/134/labels{/name}","comments_url":"https://api.github.com/repos/libpnet/libpnet/issues/134/comments","events_url":"https://api.github.com/repos/libpnet/libpnet/issues/134/events","html_url":"https://github.com/libpnet/libpnet/issues/134","id":120553342,"number":134,"title":"a few questions and issues about using libpnet","user":{"login":"little-dude","id":6646324,"avatar_url":"https://avatars.githubusercontent.com/u/6646324?v=3","gravatar_id":"","url":"https://api.github.com/users/little-dude","html_url":"https://github.com/little-dude","followers_url":"https://api.github.com/users/little-dude/followers","following_url":"https://api.github.com/users/little-dude/following{/other_user}","gists_url":"https://api.github.com/users/little-dude/gists{/gist_id}","starred_url":"https://api.github.com/users/little-dude/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/little-dude/subscriptions","organizations_url":"https://api.github.com/users/little-dude/orgs","repos_url":"https://api.github.com/users/little-dude/repos","events_url":"https://api.github.com/users/little-dude/events{/privacy}","received_events_url":"https://api.github.com/users/little-dude/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-12-05T13:07:41Z","updated_at":"2015-12-06T12:17:01Z","closed_at":null,"body":"## Checksum\r\n\r\nWhen trying to implement icmp packets, I've added one `#[packet]` per icmp\r\ntype. Checksum calculation is the same for all those packets, but the function\r\nI wrote for it only accepts one type of packets:\r\n\r\n```rust\r\n/// Calculates the checksum of an ICMP packet\r\npub fn checksum(packet: &IcmpPacket) -> u16be {\r\n    use packet::Packet;\r\n\r\n    let mut sum = 0u32;\r\n    let mut i = 0;\r\n    while i < packet.packet().len() {\r\n        let word = (packet.packet()[i] as u32) << 8 | packet.packet()[i + 1] as u32;\r\n        sum = sum + word;\r\n        i = i + 2;\r\n    }\r\n    while sum >> 16 != 0 {\r\n        sum = (sum >> 16) + (sum & 0xFFFF);\r\n    }\r\n\r\n    !sum as u16\r\n}\r\n```\r\n\r\nI didn't try too much but I guess I could solve this by implementing a trait\r\n`IcmpChecksum` and use `#[derive(IcmpChecksum)]` on all the icmp packets.\r\n\r\n## Struggling with ownership concepts\r\n\r\nComing from python, I still struggling with some basic things. Here is what I would have been able to do but could get working.\r\n\r\n### nested `new`\r\n\r\nWhen I `know` a buffer represents an icmp packet, I'd like to be able to do\r\nthis:\r\n\r\n```rust\r\nlet capture = &testutils::read_capture(\"echo_request\");\r\n// let say `capture[0]` is a Vec<u8> representing an icmp echo request packet\r\nlet icmp_packet =\r\n    EchoRequest::new(\r\n        Ipv4Packet::new(\r\n            EthernetPacket::new($capture[0][..])\r\n            .unwrap()\r\n            .payload())\r\n        .unwrap()\r\n        .payload())\r\n    .unwrap();\r\n```\r\n\r\nBut this does not work because the ethernet packet does not live long enough.\r\nSo I have to go with this version:\r\n\r\n```rust\r\nlet capture = &testutils::read_capture(\"echo_request\");\r\n// let say `capture[0]` is a Vec<u8> representing an icmp echo request packet\r\nlet ethernet = EthernetPacket::new($capture[0][..]).unwrap();\r\nlet ip = Ipv4Packet::new(ethernet.payload()).unwrap();\r\nlet echo_request =  EchoRequest::new(ip.payload()).unwrap();\r\n```\r\n\r\n### returning a packet\r\n\r\nwhen writing tests for icmp packets I wanted to be able to write something like\r\nthis (I know, it saves only two lines, but these are two lines I would have to\r\nwrite all the time):\r\n\r\n```rust\r\nfn get_icmp_buf(packet_buf: &[u8]) -> &[u8] {\r\n    let eth = EthernetPacket::new(packet_buf).unwrap();\r\n    let ip = Ipv4Packet::new(eth.payload()).unwrap():\r\n    ip.payload();\r\n}\r\n\r\n// then later:\r\n\r\nlet capture = testutils::read_capture(\"time_exceeded\");\r\nlet time_exceeded_packet = TimeExceeded::new(get_icmp_buf(&capture[0][..])).unwrap();\r\n```\r\n\r\nBut the compiler complains so I ended up copying the data:\r\n\r\n```rust\r\nfn get_ip_payload(packet_bytes: &[u8]) -> Vec<u8> {\r\n    let eth_packet = EthernetPacket::new(packet_bytes).unwrap();\r\n    let ip_packet = Ipv4Packet::new(eth_packet.payload()).unwrap();\r\n    let mut bytes = vec![];\r\n    for byte in ip_packet.payload() {\r\n        bytes.push(*byte);\r\n    }\r\n    bytes\r\n}\r\n```\r\n\r\nFor the same reason, I cannot make a function that returns an ip packet\r\n\r\n```rust\r\nfn get_ip_pakcet(packet_bytes: &[u8]) -> Ipv4Packet {\r\n    let eth_packet = EthernetPacket::new(packet_bytes).unwrap();\r\n    Ipv4Packet::new(eth_packet.payload()).unwrap();\r\n}\r\n```\r\n\r\n## panic! \r\n\r\nwhen an ip packet does not have any option in the header the following seems to `panic!`:\r\n\r\n```rust\r\nip_packet.get_options_raw()\r\n thread 'packet::icmp::tests::destination_unreachable' panicked at 'slice index starts at 20 but ends at 0', src/libcore/slice.rs:578\r\n```\r\n\r\n## bump version\r\n\r\nI don't really know how versioning works with rust, but I had to change pnet version to `0.5.2` to make it compile. Should I open a PR for this?\r\nhttps://github.com/little-dude/libpnet/commit/c9bbacd6c02126d863cd558f2dfc41d07964fcf8#diff-80398c5faae3c069e4e6aa2ed11b28c0L3\r\n\r\n## implementing `fmt::Debug` for packets\r\n\r\nIt would be really nice to debug tests if we could print the packets like this:\r\n\r\n```rust\r\nprintln!(\"{:?}\", my_ip_packet);\r\n// output would look like:\r\n// \r\n// source: (0x0A, 0x00, 0x00, 0x01)\r\n// destination: (0x08, 0x08, 0x08, 0x08)\r\n// header_length: 0x05\r\n// etc.\r\n```\r\n\r\nNot sure how hard it would be, but I could look into it."},"comment":{"url":"https://api.github.com/repos/libpnet/libpnet/issues/comments/162309805","html_url":"https://github.com/libpnet/libpnet/issues/134#issuecomment-162309805","issue_url":"https://api.github.com/repos/libpnet/libpnet/issues/134","id":162309805,"user":{"login":"david415","id":50611,"avatar_url":"https://avatars.githubusercontent.com/u/50611?v=3","gravatar_id":"","url":"https://api.github.com/users/david415","html_url":"https://github.com/david415","followers_url":"https://api.github.com/users/david415/followers","following_url":"https://api.github.com/users/david415/following{/other_user}","gists_url":"https://api.github.com/users/david415/gists{/gist_id}","starred_url":"https://api.github.com/users/david415/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/david415/subscriptions","organizations_url":"https://api.github.com/users/david415/orgs","repos_url":"https://api.github.com/users/david415/repos","events_url":"https://api.github.com/users/david415/events{/privacy}","received_events_url":"https://api.github.com/users/david415/received_events","type":"User","site_admin":false},"created_at":"2015-12-06T12:17:01Z","updated_at":"2015-12-06T12:17:01Z","body":"yes we should really make the proper abstractions here so we don't have code duplication for packet checksums... i think that this was not a good first rust project for me as i lost steam trying to debug the bit fiddling. i'd really just like for the library to exist in a complete enough form so that i can write scanning tools and protocol analysis tools like the infamous honeybadger. https://github.com/david415/HoneyBadger ;-p"}}