{"record":{"id":"a262388ba59cf7c7","repo":"stamparm/maltrail","slug":"src-ipv4","errorCode":null,"errorMessage":"src ipv4","messagePattern":"src ipv4","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sensor/src/testkit.rs","lineNumber":450,"sourceCode":"    out.extend_from_slice(payload);\n    out\n}\n\npub fn ipv4(proto: u8, src: &str, dst: &str, payload: &[u8]) -> Vec<u8> {\n    ipv4_opts(proto, src, dst, payload, 5, 0)\n}\n\npub fn ipv4_opts(proto: u8, src: &str, dst: &str, payload: &[u8], ihl: u8, frag: u16) -> Vec<u8> {\n    let options = vec![0u8; ((ihl as usize).saturating_sub(5)) * 4];\n    let total = (ihl as usize * 4 + payload.len()) as u16;\n    let mut out = vec![0x40 | (ihl & 0x0f), 0];\n    out.extend_from_slice(&total.to_be_bytes());\n    out.extend_from_slice(&0x1234u16.to_be_bytes());\n    out.extend_from_slice(&frag.to_be_bytes());\n    out.push(64);\n    out.push(proto);\n    out.extend_from_slice(&[0, 0]);\n    out.extend_from_slice(&crate::addr::addr_to_int(src).expect(\"src ipv4\").to_be_bytes());\n    out.extend_from_slice(&crate::addr::addr_to_int(dst).expect(\"dst ipv4\").to_be_bytes());\n    out.extend_from_slice(&options);\n    out.extend_from_slice(payload);\n    out\n}\n\npub fn ipv6(proto: u8, src: &str, dst: &str, payload: &[u8]) -> Vec<u8> {\n    let mut out = vec![0x60, 0, 0, 0];\n    out.extend_from_slice(&(payload.len() as u16).to_be_bytes());\n    out.push(proto);\n    out.push(64);\n    out.extend_from_slice(&crate::addr::parse_ipv6(src).expect(\"src ipv6\").to_be_bytes());\n    out.extend_from_slice(&crate::addr::parse_ipv6(dst).expect(\"dst ipv6\").to_be_bytes());\n    out.extend_from_slice(payload);\n    out\n}\n\n/// IPv6 carrying a chain of extension headers before `proto`.","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/testkit.rs#L432-L468","documentation":"Panic from `.expect(\"src ipv4\")` when `crate::addr::addr_to_int(src)` cannot parse the source IPv4 address string passed to the packet builder `ipv4_opts`. Test helpers are strict: a malformed address means the test packet cannot be constructed.","triggerScenarios":"`ipv4_opts()` (and wrappers `ipv4`) called with a src string that is not a valid dotted-quad IPv4 address (empty string, hostname, octet >255, missing octets).","commonSituations":"Typo in a hardcoded test IP; substituting an IPv6 literal where an IPv4 is required; building addresses with format! that produce empty or malformed octets.","solutions":["Validate the src string is a valid dotted-quad IPv4 before calling ipv4_opts","Use well-formed test literals like \"10.0.0.1\"","Match on addr_to_int to panic with the address value for easier diagnosis","Ensure no IPv6 addresses are passed to the IPv4 builder"],"exampleFix":"// before\nipv4_opts(proto, \"10.0.0.300\", dst, &[], payload) // invalid octet\n// after\nipv4_opts(proto, \"10.0.0.1\", dst, &[], payload)","handlingStrategy":"validation","validationCode":"fn is_ipv4(s: &str) -> bool { s.parse::<std::net::Ipv4Addr>().is_ok() }\nassert!(is_ipv4(src), \"src must be valid IPv4: {src}\");","typeGuard":"fn is_ipv4(s: &str) -> bool { s.parse::<std::net::Ipv4Addr>().is_ok() }","tryCatchPattern":"let v = crate::addr::addr_to_int(src).unwrap_or_else(|e| panic!(\"src ipv4 '{src}': {e:?}\"));","preventionTips":["Validate all IP literals at the top of packet-builder helpers","Never pass IPv6 literals to IPv4 builders","Use named constants for common test addresses"],"tags":["rust","ipv4","test-harness","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}