| 355 | } |
| 356 | |
| 357 | pub fn min_ttl(packet: &[u8], min_ttl: u32, max_ttl: u32, failure_ttl: u32) -> Result<u32, Error> { |
| 358 | let packet_len = packet.len(); |
| 359 | ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet"); |
| 360 | ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet"); |
| 361 | ensure!(qdcount(packet) == 1, "No question"); |
| 362 | let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?; |
| 363 | assert!(offset > DNS_OFFSET_QUESTION); |
| 364 | ensure!(packet_len - offset > 4, "Short packet"); |
| 365 | offset += 4; |
| 366 | let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet)); |
| 367 | let rrcount = ancount as usize + nscount as usize + arcount as usize; |
| 368 | let mut found_min_ttl = if rrcount > 0 { max_ttl } else { failure_ttl }; |
| 369 | |
| 370 | offset = traverse_rrs(packet, offset, rrcount, |offset| { |
| 371 | let qtype = BigEndian::read_u16(&packet[offset..]); |
| 372 | let ttl = BigEndian::read_u32(&packet[offset + 4..]); |
| 373 | if qtype != DNS_TYPE_OPT && ttl < found_min_ttl { |
| 374 | found_min_ttl = ttl; |
| 375 | } |
| 376 | Ok(()) |
| 377 | })?; |
| 378 | if found_min_ttl < min_ttl { |
| 379 | found_min_ttl = min_ttl; |
| 380 | } |
| 381 | ensure!(packet_len == offset, "Garbage after packet"); |
| 382 | Ok(found_min_ttl) |
| 383 | } |
| 384 | |
| 385 | pub fn set_ttl(packet: &mut [u8], ttl: u32) -> Result<(), Error> { |
| 386 | let packet_len = packet.len(); |