@@ -720,18 +720,14 @@ impl DnsPacket {
720
720
}
721
721
}
722
722
723
- fn main ( ) -> Result < ( ) > {
724
- // perform a query for youtube.com
725
- let q_name = "youtube.com" ;
726
- let q_type = QueryType :: A ;
727
-
728
- //use youtube public dns server
723
+ // Add lookup method to lookup DNS records
724
+ fn lookup ( query_name : & str , query_type : QueryType ) -> Result < DnsPacket > {
725
+ //forward query to public dns
729
726
let server = ( "8.8.8.8" , 53 ) ;
730
727
731
728
// bind a UDP socket to arbitrary port
732
729
let socket = UdpSocket :: bind ( ( "0.0.0.0" , 42340 ) ) ?;
733
730
734
-
735
731
// Build our query packet. It's important that we remember to set the
736
732
// `recursion_desired` flag. As noted earlier, the packet id is arbitrary.
737
733
let mut packet = DnsPacket :: new ( ) ;
@@ -740,37 +736,105 @@ fn main() -> Result<()> {
740
736
packet. header . recursion_desired = true ;
741
737
packet
742
738
. questions
743
- . push ( DnsQuestion :: new ( q_name. to_string ( ) , q_type) ) ;
744
-
739
+ . push ( DnsQuestion :: new ( query_name. to_string ( ) , query_type) ) ;
745
740
746
741
// Use our new write method to write the packet to a buffer...
747
742
let mut req_buffer = BytePacketBuffer :: new ( ) ;
748
743
packet. write ( & mut req_buffer) ?;
749
744
750
- // ...and send it off to the server using our socket:
751
- socket. send_to ( & req_buffer. buf [ 0 ..req_buffer. pos ] , server) ?;
745
+ // ...and send it off to the server using our socket:
746
+ socket. send_to ( & req_buffer. buf [ 0 ..req_buffer. pos ] , server) ?;
752
747
753
748
// To prepare for receiving the response, we'll create a new `BytePacketBuffer`,
754
749
// and ask the socket to write the response directly into our buffer.
755
750
let mut res_buffer = BytePacketBuffer :: new ( ) ;
756
751
socket. recv_from ( & mut res_buffer. buf ) ?;
757
752
758
- //`DnsPacket::from_buffer()` is used to parse the response and print it
759
- let packet = DnsPacket :: from_buffer ( & mut res_buffer) ?;
760
- println ! ( "{:#?}" , packet. header) ;
753
+ //`DnsPacket::from_buffer()` is used to parse the response
754
+ DnsPacket :: from_buffer ( & mut res_buffer)
761
755
762
- for q in packet. questions {
763
- println ! ( "{:#?}" , q) ;
764
- }
765
- for rec in packet. answers {
766
- println ! ( "{:#?}" , rec) ;
767
- }
768
- for rec in packet. authorities {
769
- println ! ( "{:#?}" , rec) ;
756
+ }
757
+ /// Handle a single incoming packet
758
+ fn handle_query ( socket : & UdpSocket ) -> Result < ( ) > {
759
+ // With a socket ready, we can go ahead and read a packet. This will
760
+ // block until one is received.
761
+ let mut req_buffer = BytePacketBuffer :: new ( ) ;
762
+
763
+ // The `recv_from` function will write the data into the provided buffer,
764
+ // and return the length of the data read as well as the source address.
765
+ // We're not interested in the length, but we need to keep track of the
766
+ // source in order to send our reply later on.
767
+ let ( _, src) = socket. recv_from ( & mut req_buffer. buf ) ?;
768
+
769
+ // Next, `DnsPacket::from_buffer` is used to parse the raw bytes into
770
+ // a `DnsPacket`.
771
+ let mut request = DnsPacket :: from_buffer ( & mut req_buffer) ?;
772
+
773
+ // Create and initialize the response packet
774
+ let mut packet = DnsPacket :: new ( ) ;
775
+ packet. header . id = request. header . id ;
776
+ packet. header . recursion_desired = true ;
777
+ packet. header . recursion_available = true ;
778
+ packet. header . response = true ;
779
+
780
+ // In the normal case, exactly one question is present
781
+ if let Some ( question) = request. questions . pop ( ) {
782
+ println ! ( "Received query: {:?}" , question) ;
783
+
784
+ // Since all is set up and as expected, the query can be forwarded to the
785
+ // target server. There's always the possibility that the query will
786
+ // fail, in which case the `SERVFAIL` response code is set to indicate
787
+ // as much to the client. If rather everything goes as planned, the
788
+ // question and response records as copied into our response packet.
789
+ if let Ok ( result) = lookup ( & question. name , question. question_type ) {
790
+ packet. questions . push ( question) ;
791
+ packet. header . rescode = result. header . rescode ;
792
+
793
+ for rec in result. answers {
794
+ println ! ( "Answer: {:?}" , rec) ;
795
+ packet. answers . push ( rec) ;
796
+ }
797
+ for rec in result. authorities {
798
+ println ! ( "Authority: {:?}" , rec) ;
799
+ packet. authorities . push ( rec) ;
800
+ }
801
+ for rec in result. resources {
802
+ println ! ( "Resource: {:?}" , rec) ;
803
+ packet. resources . push ( rec) ;
804
+ }
805
+ } else {
806
+ packet. header . rescode = ResultCode :: SERVFAIL ;
807
+ }
770
808
}
771
- for rec in packet. resources {
772
- println ! ( "{:#?}" , rec) ;
809
+ // Being mindful of how unreliable input data from arbitrary senders can be, we
810
+ // need make sure that a question is actually present. If not, we return `FORMERR`
811
+ // to indicate that the sender made something wrong.
812
+ else {
813
+ packet. header . rescode = ResultCode :: FORMERR ;
773
814
}
774
815
816
+ // encode our response and send it back
817
+ let mut res_buffer = BytePacketBuffer :: new ( ) ;
818
+ packet. write ( & mut res_buffer) ?;
819
+
820
+ let len = res_buffer. pos ( ) ;
821
+ let data = res_buffer. get_range ( 0 , len) ?;
822
+
823
+ socket. send_to ( data, src) ?;
824
+
775
825
Ok ( ( ) )
776
826
}
827
+
828
+ fn main ( ) -> Result < ( ) > {
829
+ // Bind an UDP socket on port 2053
830
+ let socket = UdpSocket :: bind ( ( "0.0.0.0" , 2053 ) ) ?;
831
+
832
+ // For now, queries are handled sequentially, so an infinite loop for servicing
833
+ // requests is initiated.
834
+ loop {
835
+ match handle_query ( & socket) {
836
+ Ok ( _) => { } ,
837
+ Err ( e) => eprintln ! ( "An error occurred: {}" , e) ,
838
+ }
839
+ }
840
+ }
0 commit comments