diff --git a/rust/src/bittorrent_dht/logger.rs b/rust/src/bittorrent_dht/logger.rs index 3145a956a3..2cfb9270ef 100644 --- a/rust/src/bittorrent_dht/logger.rs +++ b/rust/src/bittorrent_dht/logger.rs @@ -97,6 +97,19 @@ fn log_bittorrent_dht( js.close()?; } } + if let Some(nodes) = &response.nodes6 { + if !nodes.is_empty() { + js.open_array("nodes6")?; + for node in nodes { + js.start_object()?; + js.set_hex("id", &node.id)?; + js.set_string("ip", &print_ip_addr(&node.ip))?; + js.set_uint("port", node.port.into())?; + js.close()?; + } + js.close()?; + } + } if let Some(values) = &response.values { js.open_array("values")?; for value in values { diff --git a/rust/src/bittorrent_dht/parser.rs b/rust/src/bittorrent_dht/parser.rs index 7a6ce32434..ffc31ac52b 100644 --- a/rust/src/bittorrent_dht/parser.rs +++ b/rust/src/bittorrent_dht/parser.rs @@ -23,9 +23,9 @@ use crate::bittorrent_dht::bittorrent_dht::BitTorrentDHTTransaction; use bendy::decoding::{Decoder, Error, FromBencode, Object, ResultExt}; -use nom7::IResult; use nom7::bytes::complete::take; use nom7::number::complete::be_u16; +use nom7::IResult; #[derive(Debug, Eq, PartialEq)] pub struct BitTorrentDHTRequest { @@ -51,6 +51,7 @@ pub struct BitTorrentDHTResponse { /// q = find_node/get_peers - compact node info for target node or /// K(8) closest good nodes in routing table pub nodes: Option>, + pub nodes6: Option>, /// q = get_peers - list of compact peer infos pub values: Option>, /// q = get_peers - token key required for sender's future @@ -94,6 +95,21 @@ pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> { )) } +/// Parse IPv6 node structures. +pub fn parse_node6(i: &[u8]) -> IResult<&[u8], Node> { + let (i, id) = take(20usize)(i)?; + let (i, ip) = take(16usize)(i)?; + let (i, port) = be_u16(i)?; + Ok(( + i, + Node { + id: id.to_vec(), + ip: ip.to_vec(), + port, + }, + )) +} + fn parse_peer(i: &[u8]) -> IResult<&[u8], Peer> { let (i, ip) = if i.len() < 18 { take(4usize)(i) @@ -213,6 +229,7 @@ impl FromBencode for BitTorrentDHTResponse { { let mut id = None; let mut nodes = None; + let mut nodes6 = None; let mut values = vec![]; let mut token = None; @@ -231,6 +248,14 @@ impl FromBencode for BitTorrentDHTResponse { nodes = Some(decoded_nodes); } } + (b"nodes6", value) => { + let (_, decoded_nodes) = + nom7::multi::many0(parse_node6)(value.try_into_bytes().context("nodes6")?) + .map_err(|_| Error::malformed_content("nodes6.nodes6"))?; + if !decoded_nodes.is_empty() { + nodes6 = Some(decoded_nodes); + } + } (b"values", value) => { if let Object::List(mut list) = value { while let Some(entry) = list.next_object()? { @@ -256,6 +281,7 @@ impl FromBencode for BitTorrentDHTResponse { Ok(BitTorrentDHTResponse { id: id.to_vec(), nodes, + nodes6, values: if values.is_empty() { None } else {