(packet: &mut Vec<u8>)
| 600 | } |
| 601 | |
| 602 | pub fn query_meta(packet: &mut Vec<u8>) -> Result<Option<String>, Error> { |
| 603 | let packet_len = packet.len(); |
| 604 | ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet"); |
| 605 | ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet"); |
| 606 | ensure!(qdcount(packet) == 1, "No question"); |
| 607 | let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?; |
| 608 | assert!(offset > DNS_OFFSET_QUESTION); |
| 609 | ensure!(packet_len - offset >= 4, "Short packet"); |
| 610 | offset += 4; |
| 611 | let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet)); |
| 612 | offset = traverse_rrs( |
| 613 | packet, |
| 614 | offset, |
| 615 | ancount as usize + nscount as usize, |
| 616 | |_offset| Ok(()), |
| 617 | )?; |
| 618 | let mut token = None; |
| 619 | traverse_rrs(packet, offset, arcount as _, |mut offset| { |
| 620 | let qtype = BigEndian::read_u16(&packet[offset..]); |
| 621 | let qclass = BigEndian::read_u16(&packet[offset + 2..]); |
| 622 | if qtype != DNS_TYPE_TXT || qclass != DNS_CLASS_INET { |
| 623 | return Ok(()); |
| 624 | } |
| 625 | let len = BigEndian::read_u16(&packet[offset + 8..]) as usize; |
| 626 | offset += 10; |
| 627 | ensure!(packet_len - offset >= len, "Short packet"); |
| 628 | let rrdata = &packet[offset..offset + len]; |
| 629 | parse_txt_rrdata(rrdata, |txt| { |
| 630 | if txt.len() < 7 || !txt.starts_with("token:") { |
| 631 | return Ok(()); |
| 632 | } |
| 633 | ensure!(token.is_none(), "Duplicate token"); |
| 634 | let found_token = &txt[6..]; |
| 635 | let found_token = found_token.to_owned(); |
| 636 | token = Some(found_token); |
| 637 | Ok(()) |
| 638 | })?; |
| 639 | Ok(()) |
| 640 | })?; |
| 641 | if token.is_some() { |
| 642 | arcount_clear(packet)?; |
| 643 | packet.truncate(offset); |
| 644 | } |
| 645 | Ok(token) |
| 646 | } |
| 647 | |
| 648 | pub fn serve_nxdomain_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error> { |
| 649 | ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); |
no test coverage detected