1201 lines
62 KiB
Groff
1201 lines
62 KiB
Groff
|
with System;
|
||
|
with Protected_SPARK_IO_05;
|
||
|
with DNS_Types;
|
||
|
with Unsigned_Types;
|
||
|
use type DNS_Types.Packet_Bytes_Range;
|
||
|
use type DNS_Types.Packet_Length_Range;
|
||
|
use type DNS_Types.Byte;
|
||
|
use type DNS_Types.Query_Type;
|
||
|
use type DNS_Types.Query_Class;
|
||
|
use type Unsigned_Types.Unsigned16;
|
||
|
use type Unsigned_Types.Unsigned32;
|
||
|
use type DNS_Types.Unsigned_Short;
|
||
|
use type DNS_Types.QNAME_PTR_RANGE;
|
||
|
use type System.Bit_Order;
|
||
|
with Ada.Text_Io;
|
||
|
with ada.Unchecked_Conversion;
|
||
|
package body Process_Dns_Request is
|
||
|
procedure Set_Unsigned_32(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Value : in Unsigned_Types.Unsigned32) is
|
||
|
begin
|
||
|
Bytes(Start_Byte) := DNS_Types.Byte(Value/2**24);
|
||
|
Bytes(Start_Byte+1) := DNS_Types.Byte((Value/2**16) mod 256);
|
||
|
Bytes(Start_Byte+2) := DNS_Types.Byte((Value/2**8) mod 256);
|
||
|
Bytes(Start_Byte+3) := DNS_Types.Byte(Value mod 256);
|
||
|
end Set_Unsigned_32;
|
||
|
procedure Set_Unsigned_16(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Value : in Unsigned_Types.Unsigned16) is
|
||
|
begin
|
||
|
Bytes(Start_Byte) := DNS_Types.Byte((Value/2**8) mod 256);
|
||
|
Bytes(Start_Byte+1) := DNS_Types.Byte(Value mod 256);
|
||
|
end Set_Unsigned_16;
|
||
|
|
||
|
procedure Set_TTL_Data_IP(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
A_Record : in Rr_Type.A_Record_Type.ARecordType) is
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,A_Record.ttlInSeconds);
|
||
|
-- DATA 4 bytes
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,4);
|
||
|
-- IP address
|
||
|
Set_Unsigned_32(Bytes,Start_Byte+6,A_Record.ipv4);
|
||
|
end Set_TTL_Data_IP;
|
||
|
|
||
|
procedure Set_TTL_Data_NS_Response(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
NS_Record : in Rr_Type.ns_record_type.NSRecordType;
|
||
|
Current_Name_Length : in RR_Type.WireStringTypeIndex) is
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,NS_Record.ttlInSeconds);
|
||
|
-- DATA # bytes is equal to length of WireString
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,Unsigned_Types.Unsigned16(Current_name_Length));
|
||
|
-- copy NS record
|
||
|
for i in RR_Type.WireStringTypeIndex range 1..Current_Name_Length loop
|
||
|
--# assert Start_Byte <= (DNS_Types.Packet_Bytes_Range'Last-6)-DNS_Types.Packet_Bytes_Range(Current_Name_Length) and
|
||
|
--# i>=RR_Type.WireStringTypeIndex'First and i<= RR_Type.WireStringTypeIndex'Last;
|
||
|
Bytes((Start_Byte+5)+DNS_Types.Packet_Bytes_Range(I)) := DNS_Types.Byte(
|
||
|
Character'Pos(NS_Record.nameServer(i)));
|
||
|
end loop;
|
||
|
end Set_TTL_Data_NS_Response;
|
||
|
|
||
|
procedure Set_TTL_Data_PTR_Response(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
PTR_Record : in Rr_Type.ptr_record_type.PTRRecordType;
|
||
|
Current_Name_Length : in RR_Type.WireStringTypeIndex) is
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,PTR_Record.ttlInSeconds);
|
||
|
-- DATA # bytes is equal to length of WireString
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,Unsigned_Types.Unsigned16(Current_name_Length));
|
||
|
-- copy NS record
|
||
|
for i in RR_Type.WireStringTypeIndex range 1..Current_Name_Length loop
|
||
|
--# assert Start_Byte <= (DNS_Types.Packet_Bytes_Range'Last-6)-DNS_Types.Packet_Bytes_Range(Current_Name_Length) and
|
||
|
--# i>=RR_Type.WireStringTypeIndex'First and i<= RR_Type.WireStringTypeIndex'Last;
|
||
|
Bytes((Start_Byte+5)+DNS_Types.Packet_Bytes_Range(I)) := DNS_Types.Byte(
|
||
|
Character'Pos(PTR_Record.domainname(i)));
|
||
|
end loop;
|
||
|
end Set_TTL_Data_PTR_Response;
|
||
|
|
||
|
|
||
|
procedure Set_TTL_Data_MX_Response(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
MX_Record : in Rr_Type.MX_record_type.MXRecordType;
|
||
|
Current_Name_Length : in RR_Type.WireStringTypeIndex) is
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,MX_Record.ttlInSeconds);
|
||
|
-- DATA # bytes is equal to length of WireString + 2
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,Unsigned_Types.Unsigned16(Current_Name_Length+2));
|
||
|
-- MAIL exchanger preference
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+6,MX_Record.pref);
|
||
|
-- copy NS record
|
||
|
for i in RR_Type.WireStringTypeIndex range 1..Current_Name_Length loop
|
||
|
--# assert Start_Byte <= (DNS_Types.Packet_Bytes_Range'Last-8)-DNS_Types.Packet_Bytes_Range(Current_Name_Length) and
|
||
|
--# i>=RR_Type.WireStringTypeIndex'First and i<= RR_Type.WireStringTypeIndex'Last;
|
||
|
Bytes((Start_Byte+7)+DNS_Types.Packet_Bytes_Range(I)) := DNS_Types.Byte(
|
||
|
Character'Pos(MX_Record.mailExchanger(i)));
|
||
|
end loop;
|
||
|
end Set_TTL_Data_MX_Response;
|
||
|
|
||
|
procedure Set_TTL_Data_SOA_Response(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
SOA_Record : in Rr_Type.SOA_record_type.SOARecordType;
|
||
|
Nameserver_Name_Length : in RR_Type.WireStringTypeIndex;
|
||
|
Mailbox_Name_Length : in RR_Type.WireStringTypeIndex) is
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,SOA_Record.ttlInSeconds);
|
||
|
-- DATA # bytes is equal to length of both WireStrings + 20
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,Unsigned_Types.Unsigned16(
|
||
|
Nameserver_Name_Length + (Mailbox_Name_Length+20)));
|
||
|
-- copy NS record
|
||
|
for i in RR_Type.WireStringTypeIndex range 1..Nameserver_Name_Length loop
|
||
|
--# assert Start_Byte <= (DNS_Types.Packet_Bytes_Range'Last-20)-
|
||
|
--# DNS_Types.Packet_Bytes_Range(Mailbox_Name_Length+Nameserver_Name_Length) and
|
||
|
--# i>=RR_Type.WireStringTypeIndex'First and i<= RR_Type.WireStringTypeIndex'Last;
|
||
|
Bytes((Start_Byte+5)+DNS_Types.Packet_Bytes_Range(I)) := DNS_Types.Byte(
|
||
|
Character'Pos(SOA_Record.nameServer(i)));
|
||
|
end loop;
|
||
|
Current_Byte := Start_Byte+DNS_Types.Packet_Bytes_Range(
|
||
|
5+(Nameserver_Name_Length));
|
||
|
-- copy MB record
|
||
|
for i in RR_Type.WireStringTypeIndex range 1..Mailbox_Name_Length loop
|
||
|
--# assert Current_Byte>=1 and Current_Byte <= (DNS_Types.Packet_Bytes_Range'Last-20)-
|
||
|
--# DNS_Types.Packet_Bytes_Range(Mailbox_Name_Length) and
|
||
|
--# i>=RR_Type.WireStringTypeIndex'First and i<= RR_Type.WireStringTypeIndex'Last;
|
||
|
Bytes(Current_Byte+DNS_Types.Packet_Bytes_Range(I)) := DNS_Types.Byte(
|
||
|
Character'Pos(SOA_Record.email(i)));
|
||
|
end loop;
|
||
|
Current_Byte := Start_Byte+DNS_Types.Packet_Bytes_Range(
|
||
|
6+(Nameserver_Name_Length + Mailbox_Name_Length));
|
||
|
-- serial number
|
||
|
Set_Unsigned_32(Bytes,Current_Byte,SOA_Record.SerialNumber);
|
||
|
-- refresh interval
|
||
|
Set_Unsigned_32(Bytes,Current_Byte+4,SOA_Record.refresh);
|
||
|
-- retry interval
|
||
|
Set_Unsigned_32(Bytes,Current_Byte+8,SOA_Record.retry);
|
||
|
-- expiration limit
|
||
|
Set_Unsigned_32(Bytes,Current_Byte+12,SOA_Record.expiry);
|
||
|
-- minimum TTL
|
||
|
Set_Unsigned_32(Bytes,Current_Byte+16,SOA_Record.minimum);
|
||
|
end Set_TTL_Data_SOA_Response;
|
||
|
|
||
|
|
||
|
procedure Set_TTL_Data_AAAA_IP(
|
||
|
Bytes : in out DNS_Types.Bytes_Array_Type;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
AAAA_Record : in Rr_Type.AAAA_Record_Type.AAAARecordType) is
|
||
|
begin
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Bytes,Start_Byte,AAAA_Record.ttlInSeconds);
|
||
|
-- DATA 16 bytes
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+4,16);
|
||
|
for i in rr_type.aaaa_record_type.IPV6AddrTypeIndex loop
|
||
|
-- IP address
|
||
|
Set_Unsigned_16(Bytes,Start_Byte+
|
||
|
DNS_Types.Packet_Bytes_Range(6+2*(I-Rr_Type.Aaaa_Record_Type.IPV6AddrTypeIndex'First)),
|
||
|
AAAA_Record.Ipv6(i));
|
||
|
end loop;
|
||
|
end Set_TTL_Data_AAAA_IP;
|
||
|
|
||
|
|
||
|
procedure Get_Query_Name_Type_Class(
|
||
|
Input_Packet : in DNS_Types.DNS_Packet;
|
||
|
Input_Bytes : in DNS_Types.Packet_Length_Range;
|
||
|
Domainname : out RR_Type.wireStringType;
|
||
|
Query_Type : out DNS_Types.Query_Type;
|
||
|
Query_Class : out DNS_Types.Query_Class;
|
||
|
End_Byte : out Dns_types.Packet_Bytes_Range) is
|
||
|
Byte : Dns_types.Packet_Bytes_Range := DNS_Types.Packet_Bytes_Range'First;
|
||
|
I : Natural := RR_Type.WireStringType'First;
|
||
|
QT_Natural, QC_Natural : Natural;
|
||
|
function Type_To_Natural is new Ada.Unchecked_Conversion(Dns_Types.Query_Type,Natural);
|
||
|
function to_type is new ada.Unchecked_Conversion(natural,dns_types.query_type);
|
||
|
function class_to_natural is new ada.Unchecked_Conversion(dns_types.query_class,natural);
|
||
|
function To_Class is new Ada.Unchecked_Conversion(Natural,Dns_Types.Query_Class);
|
||
|
begin
|
||
|
Domainname := RR_Type.WireStringType'(others => ' ');
|
||
|
while Integer(Byte) <= Integer(Input_Bytes-5) and then Input_Packet.Bytes(Byte)/=0
|
||
|
and then I < RR_Type.WireStringType'Last loop
|
||
|
--# assert I>=RR_Type.WireStringType'First and I < RR_Type.WireStringType'Last and
|
||
|
--# Byte >= DNS_Types.Packet_Bytes_Range'First and Integer(Byte) <= Integer(Input_Bytes-5);
|
||
|
Domainname(I) := Character'Val(Input_Packet.Bytes(Byte));
|
||
|
I := I + 1;
|
||
|
Byte := Byte + 1;
|
||
|
end loop;
|
||
|
Domainname(I) := Character'Val(0);
|
||
|
-- for I in Byte-2..Byte+4 loop
|
||
|
-- Ada.Text_IO.Put_Line("byte: " & Dns_Types.Packet_Bytes_Range'Image(I) & ":" &
|
||
|
-- Natural'Image(natural(Input_Packet.Bytes(I))));
|
||
|
-- end loop;
|
||
|
QT_Natural := Natural(Input_Packet.Bytes(Byte+1))*256+Natural(Input_Packet.Bytes(Byte+2));
|
||
|
QC_Natural := Natural(Input_Packet.Bytes(Byte+3))*256+Natural(Input_Packet.Bytes(Byte+4));
|
||
|
-- ada.Text_IO.put_line("qt: " & natural'image(qt_natural));
|
||
|
-- ada.Text_IO.put_line("qc: " & natural'image(qc_natural));
|
||
|
--# accept Warning, 12, type_To_Natural, "unchecked conversions ok";
|
||
|
if QT_Natural >= type_To_Natural(DNS_Types.Query_Type'First) and QT_Natural <= type_To_Natural(DNS_Types.Query_Type'Last) then
|
||
|
--# end accept;
|
||
|
--# accept Warning, 12, To_Type, "unchecked conversions ok";
|
||
|
Query_Type := To_Type(QT_Natural);
|
||
|
--# end accept;
|
||
|
if not Query_Type'Valid then
|
||
|
Query_Type := DNS_Types.UNIMPLEMENTED;
|
||
|
end if;
|
||
|
else
|
||
|
Query_Type := DNS_Types.UNIMPLEMENTED;
|
||
|
end if;
|
||
|
--# accept Warning, 12, class_To_Natural, "unchecked conversions ok";
|
||
|
if QC_Natural >= class_to_natural(DNS_Types.Query_Class'First) and QC_Natural <= class_to_natural(DNS_Types.Query_Class'Last) then
|
||
|
--# end accept;
|
||
|
--# accept Warning, 12, To_Class, "unchecked conversions ok";
|
||
|
Query_Class := To_Class(QC_Natural);
|
||
|
--# end accept;
|
||
|
if not Query_Class'Valid then
|
||
|
Query_Class := DNS_Types.NONE_CLASS;
|
||
|
end if;
|
||
|
else
|
||
|
Query_Class := DNS_Types.NONE_CLASS;
|
||
|
end if;
|
||
|
End_Byte := Byte + 4;
|
||
|
end Get_Query_Name_Type_Class;
|
||
|
|
||
|
procedure Create_Response_Error(
|
||
|
Input_Bytes : in DNS_Types.Packet_Length_Range;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
begin
|
||
|
Output_Packet.Header.AA := True;
|
||
|
Output_Packet.Header.RCODE := DNS_Types.Not_Implemented;
|
||
|
Output_Packet.Header.ANCount := 0;
|
||
|
Output_Bytes := Input_Bytes;
|
||
|
end Create_Response_Error;
|
||
|
|
||
|
procedure Create_Response_AAAA(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
ReturnedAAAARecords : Rr_Type.AAAA_Record_Type.AAAARecordBucketType;
|
||
|
NumFound : Natural;
|
||
|
Response_Counter : Natural;
|
||
|
begin
|
||
|
-- accept Flow, 23, ReturnedAAAARecords, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryAAAARecords(DomainName => Domainname,
|
||
|
ReturnedRecords => ReturnedAAAARecords, HowMany => NumFound);
|
||
|
-- end accept;
|
||
|
Current_Byte := Start_Byte;
|
||
|
|
||
|
if NumFound>=1 then
|
||
|
Response_Counter := 1;
|
||
|
while Response_Counter <= NumFound and Integer(Current_Byte) < DNS_Types.Packet_Size-(28+DNS_Types.Header_Bits/8) loop
|
||
|
--# assert Response_Counter >=1 and Response_Counter <= NumFound
|
||
|
--# and Answer_Count = Answer_Count~
|
||
|
--# and Answer_Count <= DNS_Types.Unsigned_Short'Last-DNS_types.Unsigned_Short(rr_type.MaxNumRecords)
|
||
|
--# and Current_Byte = Start_Byte +
|
||
|
--# DNS_Types.Packet_Bytes_Range(28*(Response_Counter-1))
|
||
|
--# and Integer(Current_Byte) < DNS_Types.Packet_Size-(28+DNS_Types.Header_Bits/8)
|
||
|
--# and numfound <= rr_type.MaxNumRecords ;
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- AAAA
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#1C#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Set_TTL_Data_AAAA_IP(Output_Packet.Bytes,Current_Byte+7,ReturnedAAAARecords(ReturnedAAAARecords'First+(Response_Counter-1)));
|
||
|
Response_Counter := Response_Counter + 1;
|
||
|
Current_Byte := Current_Byte + 28;
|
||
|
end loop;
|
||
|
--Output_Bytes := Input_Bytes+DNS_Types.Packet_Length_Range(28*(Response_Counter-1));
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(numFound);
|
||
|
-- accept Flow, 602, Output_Packet, ReturnedAAAARecords, "initialization is unneeded";
|
||
|
end Create_Response_AAAA;
|
||
|
|
||
|
procedure Create_Response_A(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
ReturnedARecords : Rr_Type.A_Record_Type.ARecordBucketType;
|
||
|
NumFound : Natural;
|
||
|
Response_Counter : Natural;
|
||
|
begin
|
||
|
-- accept Flow, 23, ReturnedARecords, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryARecords(DomainName => Domainname,
|
||
|
ReturnedRecords => ReturnedARecords, HowMany => NumFound);
|
||
|
-- end accept;
|
||
|
Current_Byte := Start_Byte;
|
||
|
|
||
|
|
||
|
if NumFound>=1 then
|
||
|
Response_Counter := 1;
|
||
|
while Response_Counter <= NumFound and Integer(Current_Byte) < DNS_Types.Packet_Size-(16+DNS_Types.Header_Bits/8) loop
|
||
|
--# assert Response_Counter >=1 and Response_Counter <= NumFound
|
||
|
--# and Integer(Start_Byte) <= DNS_Types.Packet_Size
|
||
|
--# and Answer_Count = Answer_Count~
|
||
|
--# and Answer_Count <= DNS_Types.Unsigned_Short'Last-DNS_types.Unsigned_Short(rr_type.MaxNumRecords)
|
||
|
--# and Current_Byte = Start_Byte +
|
||
|
--# DNS_Types.Packet_Bytes_Range(16*(Response_Counter-1))
|
||
|
--# and Integer(Current_Byte) < DNS_Types.Packet_Size-(16+DNS_Types.Header_Bits/8)
|
||
|
--# and numfound <= rr_type.MaxNumRecords ;
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- A
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#01#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Set_TTL_Data_IP(Output_Packet.Bytes,Current_Byte+7,ReturnedARecords(ReturnedARecords'First+(Response_Counter-1)));
|
||
|
Response_Counter := Response_Counter + 1;
|
||
|
Current_Byte := Current_Byte + 16;
|
||
|
end loop;
|
||
|
--Output_Bytes := Input_Bytes+DNS_Types.Packet_Length_Range(16*(Response_Counter-1));
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(numFound);
|
||
|
-- accept Flow, 602, Output_Packet, ReturnedARecords, "initialization is unneeded";
|
||
|
end Create_Response_A;
|
||
|
|
||
|
procedure Create_Response_NS(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Num_Found : out RR_Type.NumberOfRecordsType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Qname_Locations : out QNAME_PTR_RANGE_Array;
|
||
|
Replies : out RR_Type.ns_record_type.NSRecordBucketType;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Response_Counter : Natural;
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Current_Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
begin
|
||
|
Qname_Locations := QNAME_PTR_RANGE_Array'(others => 0);
|
||
|
Current_Byte := Start_Byte;
|
||
|
-- accept Flow, 23, Replies, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryNSRecords(
|
||
|
DomainName => Domainname,
|
||
|
ReturnedRecords => Replies,
|
||
|
HowMany => Num_Found);
|
||
|
-- end accept;
|
||
|
if Num_Found>=1 then
|
||
|
Response_Counter := 1;
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).nameServer);
|
||
|
while Response_Counter <= Num_Found and then
|
||
|
Integer(Current_Byte) < (DNS_Types.Packet_Size-(12+DNS_Types.Header_Bits/8))-
|
||
|
(Current_Name_Length) loop
|
||
|
--# assert Response_Counter >=1 and Response_Counter <= Num_Found
|
||
|
--# and current_name_length >=1 and current_name_length<=rr_type.WireStringTypeIndex'last
|
||
|
--# and Num_Found <= rr_type.MaxNumRecords
|
||
|
--# and Integer(Start_Byte) <= DNS_Types.Packet_Size
|
||
|
--# and Answer_Count = Answer_Count~
|
||
|
--# and Answer_Count <= DNS_Types.Unsigned_Short'Last-DNS_types.Unsigned_Short(rr_type.MaxNumRecords)
|
||
|
--# and Integer(Current_Byte) < (DNS_Types.Packet_Size-(12+DNS_Types.Header_Bits/8))-
|
||
|
--# (Current_Name_Length)
|
||
|
--# and Current_Byte >= 0;
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- NS
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#02#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Qname_Locations(Response_Counter) := DNS_Types.QNAME_PTR_RANGE(
|
||
|
(Current_Byte+12)+ DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Set_TTL_Data_NS_Response(Output_Packet.Bytes,Current_Byte+7,
|
||
|
Replies(Response_Counter),Current_Name_Length);
|
||
|
Response_Counter := Response_Counter + 1;
|
||
|
Current_Byte := (Current_Byte + 12) + DNS_Types.Packet_Bytes_Range(Current_Name_Length);
|
||
|
if Response_Counter <= Num_Found then
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).nameServer);
|
||
|
end if;
|
||
|
end loop;
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(Num_Found);
|
||
|
-- accept Flow, 602, Output_Packet, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Output_Bytes, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Replies, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Qname_Locations, Replies, "initialization is unneeded";
|
||
|
end Create_Response_NS;
|
||
|
|
||
|
procedure Create_Response_PTR(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Num_Found : RR_Type.NumberOfRecordsType;
|
||
|
Response_Counter : Natural;
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Current_Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
Replies : RR_Type.PTR_record_type.PTRRecordBucketType;
|
||
|
begin
|
||
|
Current_Byte := Start_Byte;
|
||
|
-- accept Flow, 23, Replies, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryPTRRecords(
|
||
|
DomainName => Domainname,
|
||
|
ReturnedRecords => Replies,
|
||
|
HowMany => Num_Found);
|
||
|
-- end accept;
|
||
|
if Num_Found>=1 then
|
||
|
Response_Counter := 1;
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).domainname);
|
||
|
while Response_Counter <= Num_Found and then
|
||
|
Integer(Current_Byte) < (DNS_Types.Packet_Size-(12+DNS_Types.Header_Bits/8))-
|
||
|
(Current_Name_Length) loop
|
||
|
--# assert Response_Counter >=1 and Response_Counter <= Num_Found
|
||
|
--# and current_name_length >=1 and current_name_length<=rr_type.WireStringTypeIndex'last
|
||
|
--# and Num_Found <= rr_type.MaxNumRecords
|
||
|
--# and Integer(Start_Byte) <= DNS_Types.Packet_Size
|
||
|
--# and Answer_Count = Answer_Count~
|
||
|
--# and Answer_Count <= DNS_Types.Unsigned_Short'Last-DNS_types.Unsigned_Short(rr_type.MaxNumRecords)
|
||
|
--# and Integer(Current_Byte) < (DNS_Types.Packet_Size-(12+DNS_Types.Header_Bits/8))-
|
||
|
--# (Current_Name_Length)
|
||
|
--# and Current_Byte >= 0;
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- PTR
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#0C#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Set_TTL_Data_PTR_Response(Output_Packet.Bytes,Current_Byte+7,
|
||
|
Replies(Response_Counter),Current_Name_Length);
|
||
|
Response_Counter := Response_Counter + 1;
|
||
|
Current_Byte := (Current_Byte + 12) + DNS_Types.Packet_Bytes_Range(Current_Name_Length);
|
||
|
if Response_Counter <= Num_Found then
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).domainname);
|
||
|
end if;
|
||
|
end loop;
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(Num_Found);
|
||
|
-- accept Flow, 602, Output_Packet, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Output_Bytes, Replies, "initialization is unneeded";
|
||
|
end Create_Response_PTR;
|
||
|
|
||
|
procedure Create_Response_MX(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Num_Found : out RR_Type.NumberOfRecordsType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Qname_Locations : out QNAME_PTR_RANGE_Array;
|
||
|
Replies : out RR_Type.mx_record_type.MXRecordBucketType;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Response_Counter : Natural;
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Current_Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
begin
|
||
|
Qname_Locations := QNAME_PTR_RANGE_Array'(others => 0);
|
||
|
Current_Byte := Start_Byte;
|
||
|
-- accept Flow, 23, Replies, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryMXRecords(
|
||
|
DomainName => Domainname,
|
||
|
ReturnedRecords => Replies,
|
||
|
HowMany => Num_Found);
|
||
|
-- end accept;
|
||
|
if Num_Found>=1 then
|
||
|
Response_Counter := 1;
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).mailExchanger);
|
||
|
while Response_Counter <= Num_Found and then
|
||
|
Integer(Current_Byte) < (DNS_Types.Packet_Size-(14+DNS_Types.Header_Bits/8))-
|
||
|
(Current_Name_Length) loop
|
||
|
--# assert Response_Counter >=1 and Response_Counter <= Num_Found
|
||
|
--# and current_name_length >=1 and current_name_length<=rr_type.WireStringTypeIndex'last
|
||
|
--# and Num_Found <= rr_type.MaxNumRecords
|
||
|
--# and Integer(Start_Byte) <= DNS_Types.Packet_Size
|
||
|
--# and Answer_Count = Answer_Count~
|
||
|
--# and Answer_Count <= DNS_Types.Unsigned_Short'Last-DNS_types.Unsigned_Short(rr_type.MaxNumRecords)
|
||
|
--# and Integer(Current_Byte) < (DNS_Types.Packet_Size-(14+DNS_Types.Header_Bits/8))-
|
||
|
--# (Current_Name_Length)
|
||
|
--# and Current_Byte >= 0;
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- MX
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#0F#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Qname_Locations(Response_Counter) := DNS_Types.QNAME_PTR_RANGE(
|
||
|
(Current_Byte+14)+ DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Set_TTL_Data_MX_Response(Output_Packet.Bytes,Current_Byte+7,
|
||
|
Replies(Response_Counter),Current_Name_Length);
|
||
|
Response_Counter := Response_Counter + 1;
|
||
|
Current_Byte := (Current_Byte + 14) + DNS_Types.Packet_Bytes_Range(Current_Name_Length);
|
||
|
if Response_Counter <= Num_Found then
|
||
|
Current_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).mailExchanger);
|
||
|
end if;
|
||
|
end loop;
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(Num_Found);
|
||
|
-- accept Flow, 602, Output_Packet, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Output_Bytes, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Replies, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Qname_Locations, Replies, "initialization is unneeded";
|
||
|
end Create_Response_MX;
|
||
|
|
||
|
procedure Create_Response_SOA(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Answer_Count : in out DNS_Types.Unsigned_Short;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Response_Counter : Natural;
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Nameserver_Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
Mailbox_Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
Num_Found : RR_Type.NumberOfRecordsType;
|
||
|
Replies : RR_Type.SOA_record_type.SOARecordBucketType;
|
||
|
begin
|
||
|
Current_Byte := Start_Byte;
|
||
|
-- accept Flow, 23, Replies, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QuerySOARecords(
|
||
|
DomainName => Domainname,
|
||
|
ReturnedRecords => Replies,
|
||
|
HowMany => Num_Found);
|
||
|
-- end accept;
|
||
|
if Num_Found>=1 then
|
||
|
Response_Counter := 1;
|
||
|
Nameserver_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).nameserver);
|
||
|
Mailbox_Name_Length := RR_Type.WireNameLength(Replies(Response_Counter).email);
|
||
|
if Integer(Current_Byte) < (DNS_Types.Packet_Size-(32+DNS_Types.Header_Bits/8))-
|
||
|
(Nameserver_Name_Length+Mailbox_Name_Length) then
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- SOA
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#06#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
Set_TTL_Data_SOA_Response(Output_Packet.Bytes,Current_Byte+7,
|
||
|
Replies(Response_Counter),Nameserver_Name_Length,Mailbox_Name_Length);
|
||
|
Current_Byte := (Current_Byte + 32) + DNS_Types.Packet_Bytes_Range(
|
||
|
Nameserver_Name_Length+Mailbox_name_Length);
|
||
|
end if;
|
||
|
end if;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Answer_Count := Answer_Count + DNS_Types.Unsigned_Short(Num_Found);
|
||
|
-- accept Flow, 602, Output_Packet, Replies, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Output_Bytes, Replies, "initialization is unneeded";
|
||
|
end Create_Response_SOA;
|
||
|
|
||
|
|
||
|
procedure Process_Response_Cname(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Cnames : in RR_Type.cname_record_type.CNAMERecordBucketType;
|
||
|
Domainname : out RR_Type.WireStringType;
|
||
|
Qname_Location : in out DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Current_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Name_Length : RR_Type.WireStringTypeIndex;
|
||
|
I : RR_Type.WireStringTypeIndex;
|
||
|
begin
|
||
|
-- Cnames(Cnames'First).CanonicalDomainName := Character'Val(8) & "carlisle" & Character'Val(4) &
|
||
|
-- "dfcs" & Character'Val(5) & "usafa" & Character'Val(3) & "edu" & Character'Val(0) &
|
||
|
-- " ";
|
||
|
Current_Byte := Start_Byte;
|
||
|
Domainname := Cnames(Cnames'First).CanonicalDomainName;
|
||
|
Name_Length := RR_Type.WirenameLength(Cnames(Cnames'First).CanonicalDomainName);
|
||
|
if Integer(Current_Byte) < DNS_Types.Packet_Size-(12+DNS_Types.Header_Bits/8) then
|
||
|
-- PTR to character of message
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+1,Unsigned_Types.Unsigned16(Qname_Location)+16#C000#);
|
||
|
-- CNAME
|
||
|
Output_Packet.Bytes(Current_Byte+3) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+4) := 16#05#;
|
||
|
-- IN
|
||
|
Output_Packet.Bytes(Current_Byte+5) := 16#00#;
|
||
|
Output_Packet.Bytes(Current_Byte+6) := 16#01#;
|
||
|
-- TTL
|
||
|
Set_Unsigned_32(Output_Packet.Bytes,Current_Byte+7,Cnames(Cnames'First).TtlInSeconds);
|
||
|
Set_Unsigned_16(Output_Packet.Bytes,Current_Byte+11,Unsigned_Types.Unsigned16(Name_Length));
|
||
|
Current_Byte := Current_Byte + 12;
|
||
|
end if;
|
||
|
Qname_Location := DNS_Types.QNAME_PTR_RANGE(
|
||
|
(Integer(Current_Byte)) + DNS_Types.Header_Bits/8);
|
||
|
I := 1;
|
||
|
while I<=Name_Length and I<RR_Type.WireStringTypeIndex'Last and
|
||
|
Integer(Current_Byte)+DNS_Types.Header_Bits/8<DNS_Types.Packet_Size loop
|
||
|
--# assert I<RR_Type.WireStringTypeIndex'Last and
|
||
|
--# I<=Name_Length and
|
||
|
--# Output_Packet.Header.ANCount = 0 and
|
||
|
--# Current_Byte >= Start_Byte and
|
||
|
--# Integer(Current_Byte)+DNS_Types.Header_Bits/8<DNS_Types.Packet_Size;
|
||
|
Current_Byte := Current_Byte + 1;
|
||
|
Output_Packet.Bytes(Current_Byte) := DNS_Types.Byte(Character'Pos(Cnames(Cnames'First).CanonicalDomainName(I)));
|
||
|
I := I + 1;
|
||
|
end loop;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Current_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Output_Packet.Header.ANCount := Output_Packet.Header.ANCount + 1;
|
||
|
end Process_Response_Cname;
|
||
|
|
||
|
procedure Trim_Name(
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Trimmed_name : out RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
New_Qname_Location : out DNS_Types.QNAME_PTR_RANGE) is
|
||
|
Zone_Length : Natural;
|
||
|
begin
|
||
|
Zone_Length := natural(character'pos(domainname(domainname'first))+1);
|
||
|
Trimmed_Name := RR_Type.WireStringType'(others => ' ');
|
||
|
New_Qname_Location := Qname_Location;
|
||
|
if Zone_Length > 0 and Zone_Length < Rr_Type.WireStringTypeIndex'Last then
|
||
|
New_Qname_Location := New_Qname_Location + DNS_Types.QNAME_PTR_RANGE(Zone_Length);
|
||
|
-- the assertion below is kind of interesting b/c we need to tell SPARK
|
||
|
-- that zone_Length hasn't changed, and I don't really use it in the loop
|
||
|
for I in RR_Type.WireStringTypeIndex range 1..RR_Type.WireStringTypeIndex'Last-natural(character'pos(domainname(domainname'first))+1) loop
|
||
|
--# assert I+Zone_Length<=RR_Type.WireStringTypeIndex'Last and I>=1 and
|
||
|
--# zone_length = natural(character'pos(domainname(domainname'first))+1);
|
||
|
Trimmed_Name(I) := Domainname(I+natural(character'pos(domainname(domainname'first))+1));
|
||
|
end loop;
|
||
|
end if;
|
||
|
end Trim_Name;
|
||
|
|
||
|
procedure Create_NXDOMAIN_Response(
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : in RR_Type.WireStringType;
|
||
|
Qname_Location : in DNS_Types.QNAME_PTR_RANGE;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range) is
|
||
|
Answer_Count : DNS_Types.Unsigned_Short := 0;
|
||
|
Amount_Trimmed : Natural := 0;
|
||
|
Trimmed_Name : RR_Type.WireStringType;
|
||
|
Current_Name : RR_Type.WireStringType;
|
||
|
Current_Qname_Location : DNS_Types.QNAME_PTR_RANGE;
|
||
|
New_Qname_Location : DNS_Types.QNAME_PTR_RANGE;
|
||
|
begin
|
||
|
Current_Qname_Location := Qname_Location;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Start_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
Current_Name := Domainname;
|
||
|
Output_Packet.Header.RCODE := DNS_Types.Name_Error;
|
||
|
Output_Packet.Header.ANCount := 0;
|
||
|
|
||
|
-- Amount_Trimmed is used to guarantee we don't end up in an infinite loop
|
||
|
while Answer_Count=0 and Amount_Trimmed<RR_Type.WireStringType'Last and
|
||
|
Natural(Character'Pos(Current_Name(Current_Name'First)))/=0 and
|
||
|
Current_Qname_Location <= DNS_Types.QNAME_PTR_RANGE(Output_Bytes) loop
|
||
|
--# assert Answer_Count=0 and Amount_Trimmed>=0 and Amount_Trimmed<RR_Type.WireStringType'Last
|
||
|
--# and Output_Bytes <= DNS_Types.Packet_Length_Range'Last
|
||
|
--# and Current_Qname_Location <= DNS_Types.QNAME_PTR_RANGE(Output_Bytes);
|
||
|
Trim_Name(
|
||
|
Domainname => Current_Name,
|
||
|
Trimmed_Name => Trimmed_Name,
|
||
|
Qname_Location => Current_Qname_Location,
|
||
|
New_Qname_Location => New_Qname_Location);
|
||
|
Create_Response_SOA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Trimmed_name,
|
||
|
Qname_Location => New_Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Current_Name := Trimmed_Name;
|
||
|
Current_Qname_Location := New_Qname_Location;
|
||
|
Amount_Trimmed := Amount_Trimmed + Natural(Character'Pos(Domainname(Domainname'First))+1);
|
||
|
end loop;
|
||
|
if Answer_Count >= 1 then
|
||
|
Output_Packet.Header.AA := True;
|
||
|
end if;
|
||
|
Output_Packet.Header.NSCount := Answer_Count;
|
||
|
end Create_NXDOMAIN_Response;
|
||
|
|
||
|
procedure Create_Response_EDNS(
|
||
|
Input_Packet : in DNS_Types.DNS_Packet;
|
||
|
Input_Bytes : in DNS_Types.Packet_Length_Range;
|
||
|
Query_End_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Start_Byte : in DNS_Types.Packet_Bytes_Range;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range;
|
||
|
Additional_Count : in out DNS_Types.Unsigned_Short;
|
||
|
DNSSEC : out Boolean;
|
||
|
Max_Transmit : out DNS_Types.Packet_Length_Range) is
|
||
|
EDNS_Rec : DNS_Types.EDNS_Record;
|
||
|
function To_Query_Type is new Ada.Unchecked_Conversion(DNS_Types.Unsigned_Short,DNS_Types.Query_Type);
|
||
|
function From_Query_Type is new Ada.Unchecked_Conversion(DNS_Types.Query_Type,DNS_Types.Unsigned_Short);
|
||
|
begin
|
||
|
Max_Transmit := DNS_Types.UDP_Max_Size;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range(Start_Byte + DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
DNSSEC := False;
|
||
|
|
||
|
if (Integer(Query_End_Byte)+11)+(DNS_Types.Header_Bits/8)<=Integer(Input_Bytes) and
|
||
|
(Integer(Start_Byte)+11)+(DNS_Types.Header_Bits/8)<DNS_Types.Packet_Size then
|
||
|
EDNS_Rec.Root := Character'Val(Input_Packet.Bytes(Query_End_Byte+1));
|
||
|
EDNS_Rec.Code := To_Query_Type(DNS_Types.Unsigned_Short(
|
||
|
Input_Packet.Bytes(Query_End_Byte+2))*256+
|
||
|
DNS_Types.Unsigned_Short(Input_Packet.Bytes(Query_End_Byte+3)));
|
||
|
if EDNS_Rec.Root = Character'Val(0) and
|
||
|
EDNS_Rec.Code = DNS_Types.OPT then
|
||
|
EDNS_Rec.Payload_Size := DNS_Types.Unsigned_Short(Input_Packet.Bytes(
|
||
|
Query_End_Byte+4))*256+
|
||
|
DNS_Types.Unsigned_Short(Input_Packet.Bytes(Query_End_Byte+5));
|
||
|
--EDNS_Rec.RCODE := Input_Packet.Bytes(Query_End_Byte+6);
|
||
|
--EDNS_Rec.Version := Input_Packet.Bytes(Query_End_Byte+7);
|
||
|
EDNS_Rec.ZTop := Input_Packet.Bytes(Query_End_Byte+8);
|
||
|
--EDNS_Rec.ZBottom := Input_Packet.Bytes(Query_End_Byte+9);
|
||
|
--EDNS_Rec.RDLEN := DNS_Types.Unsigned_Short(
|
||
|
-- Input_Packet.Bytes(Query_End_Byte+10))*256+
|
||
|
-- DNS_Types.Unsigned_Short(Input_Packet.Bytes(Query_End_Byte+11));
|
||
|
Max_Transmit := DNS_Types.Packet_Length_Range(
|
||
|
DNS_Types.Unsigned_Short'Min(DNS_Types.Packet_Size,
|
||
|
EDNS_Rec.Payload_Size));
|
||
|
Max_Transmit := DNS_Types.Packet_Length_Range'Max(
|
||
|
DNS_Types.UDP_Max_Size, Max_Transmit);
|
||
|
|
||
|
Output_Packet.Bytes(Start_Byte+1) := 0;
|
||
|
-- high order byte of OPT is 0
|
||
|
Output_Packet.Bytes(Start_Byte+2) := 0;
|
||
|
Output_Packet.Bytes(Start_Byte+3) := DNS_Types.Byte(
|
||
|
From_Query_Type(DNS_Types.OPT) mod 256);
|
||
|
Output_Packet.Bytes(Start_Byte+4) := DNS_Types.Byte(
|
||
|
Max_Transmit/256);
|
||
|
Output_Packet.Bytes(Start_Byte+5) := DNS_Types.Byte(
|
||
|
Max_Transmit mod 256);
|
||
|
Output_Packet.Bytes(Start_Byte+6) := 0;
|
||
|
Output_Packet.Bytes(Start_Byte+7) := 0;
|
||
|
-- FLAGS (DNSSEC ONLY)
|
||
|
if (EDNS_Rec.ZTop and Dns_Types.DNSSECMASK) /= 0 then
|
||
|
Output_Packet.Bytes(Start_Byte+8) := Dns_Types.DNSSECMASK;
|
||
|
DNSSEC := True;
|
||
|
else
|
||
|
Output_Packet.Bytes(Start_Byte+8) := 0;
|
||
|
end if;
|
||
|
Output_Packet.Bytes(Start_Byte+9) := 0;
|
||
|
-- RDLEN = 0
|
||
|
Output_Packet.Bytes(Start_Byte+10) := 0;
|
||
|
Output_Packet.Bytes(Start_Byte+11) := 0;
|
||
|
|
||
|
Additional_Count := Additional_Count + 1;
|
||
|
Output_Bytes := DNS_Types.Packet_Length_Range((Start_Byte + 11) +
|
||
|
DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8));
|
||
|
end if;
|
||
|
end if;
|
||
|
end Create_Response_EDNS;
|
||
|
|
||
|
procedure Create_Response(
|
||
|
Input_Packet : in DNS_Types.DNS_Packet;
|
||
|
Input_Bytes : in DNS_Types.Packet_Length_Range;
|
||
|
Output_Packet : in out DNS_Types.DNS_Packet;
|
||
|
Output_Bytes : out DNS_Types.Packet_Length_Range;
|
||
|
Max_Transmit : out DNS_Types.Packet_Length_Range) is
|
||
|
Start_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Query_End_Byte : DNS_Types.Packet_Bytes_Range;
|
||
|
Domainname : RR_Type.WireStringType;
|
||
|
Query_Type : DNS_Types.Query_Type;
|
||
|
Query_Class : DNS_Types.Query_Class;
|
||
|
NumFound : Natural;
|
||
|
Counter : Natural;
|
||
|
Qname_Location : DNS_Types.QNAME_PTR_RANGE := 12;
|
||
|
Qname_Locations : QNAME_PTR_RANGE_Array;
|
||
|
ReturnedCNAMERecords : Rr_Type.CNAME_Record_Type.CNAMERecordBucketType;
|
||
|
NS_Replies : RR_Type.Ns_Record_Type.NSRecordBucketType;
|
||
|
MX_Replies : RR_Type.MX_Record_Type.MXRecordBucketType;
|
||
|
Answer_Count : DNS_Types.Unsigned_Short;
|
||
|
Additional_Count : DNS_Types.Unsigned_Short;
|
||
|
DNSSEC : Boolean;
|
||
|
begin
|
||
|
Max_Transmit := DNS_Types.UDP_Max_Size;
|
||
|
-- the following line makes SPARK happy, but aren't truly needed
|
||
|
--Output_Packet.Bytes := DNS_Types.Bytes_Array_Type'(others => 0);
|
||
|
|
||
|
-- I would like to only copy the header here, but I get a flow error!!
|
||
|
--# accept Flow, 10, Output_Packet.Header.QR,
|
||
|
--# "The rest of the header fields retain their newly assigned values";
|
||
|
--# accept Flow, 10, Output_Packet.Header.ANCOUNT,
|
||
|
--# "The rest of the header fields retain their newly assigned values";
|
||
|
--# accept Flow, 10, Output_Packet.Header.AA,
|
||
|
--# "The rest of the header fields retain their newly assigned values";
|
||
|
-- accept Flow, 10, Output_Packet.Header.RCODE,
|
||
|
-- "The rest of the header fields retain their newly assigned values";
|
||
|
Output_Packet.Header := Input_Packet.Header;
|
||
|
Output_Packet.Header.AA := False;
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
-- end accept;
|
||
|
Output_Packet.Header.QR := True;
|
||
|
-- Keep # of queries and send the query back!! (i.e. don't do line below)
|
||
|
-- Response_Header.QDCOUNT := 0;
|
||
|
|
||
|
--# assert Integer(Input_Bytes) >=DNS_Types.Header_Bits/8+1
|
||
|
--# and Qname_Location >=0 and Qname_Location < 16384
|
||
|
--# and Integer(Input_Bytes) < 312;
|
||
|
Get_Query_Name_Type_Class(Input_Packet, Input_Bytes, Domainname, Query_Type, Query_Class, Query_End_Byte);
|
||
|
Start_Byte := Query_End_Byte;
|
||
|
--Start_Byte := DNS_Types.Packet_Bytes_Range(Input_Bytes) -
|
||
|
-- DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8);
|
||
|
for I in DNS_Types.Packet_Bytes_Range range 1..Start_Byte loop
|
||
|
--# assert Integer(Input_Bytes) >=DNS_Types.Header_Bits/8
|
||
|
--# and Qname_Location >=0 and Qname_Location < 16384
|
||
|
--# and Integer(Input_Bytes) < 312
|
||
|
--# and Start_Byte <= DNS_Types.Packet_Bytes_Range(Input_Bytes) and Start_Byte >= 4;
|
||
|
Output_Packet.Bytes(I) := Input_Packet.Bytes(I);
|
||
|
end loop;
|
||
|
|
||
|
-- we start out with no responses
|
||
|
Output_Packet.Header.ANCount := 0;
|
||
|
|
||
|
-- accept Flow, 23, ReturnedCNAMERecords, "it will fill in enough";
|
||
|
DNS_Table_Pkg.DNS_Table.QueryCNAMERecords(DomainName => Domainname,
|
||
|
ReturnedRecords => ReturnedCNAMERecords, HowMany => NumFound);
|
||
|
-- end accept;
|
||
|
if NumFound>1 then
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"more than one cname?", 0);
|
||
|
elsif NumFound=1 then
|
||
|
Process_Response_Cname(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Cnames => ReturnedCNAMERecords,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
end if;
|
||
|
Answer_Count := Output_Packet.Header.ANCount;
|
||
|
Additional_Count := 0;
|
||
|
--ada.text_io.put_line("numfound: " & integer'image(numfound));
|
||
|
if Query_Class /= DNS_Types.IN_CLASS then
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"bad query class", 0);
|
||
|
-- ada.text_io.put_line("qc: " & dns_types.Query_Class'image(Query_Class));
|
||
|
Create_Response_Error(
|
||
|
Input_Bytes => Input_Bytes,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.ANY then
|
||
|
Create_Response_A(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_AAAA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
--# accept Flow, 10, MX_Replies, "not needed for ANY query";
|
||
|
--# accept Flow, 10, Qname_Locations, "not needed for ANY query";
|
||
|
--# accept Flow, 10, NumFound, "not needed for any query";
|
||
|
Create_Response_MX(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Num_Found => NumFound,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Qname_Locations => Qname_Locations,
|
||
|
Replies => MX_Replies,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
--# accept Flow, 10, NS_Replies, "not needed for ANY query";
|
||
|
--# accept Flow, 10, Qname_Locations, "not needed for ANY query";
|
||
|
--# accept Flow, 10, NumFound, "not needed for any query";
|
||
|
Create_Response_NS(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Num_Found => NumFound,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Qname_Locations => Qname_Locations,
|
||
|
Replies => NS_Replies,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_PTR(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_SOA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.SOA then
|
||
|
Create_Response_SOA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.PTR then
|
||
|
Create_Response_PTR(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.A then
|
||
|
Create_Response_A(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.AAAA then
|
||
|
Create_Response_AAAA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
elsif Query_Type = DNS_Types.MX then
|
||
|
Create_Response_MX(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Num_Found => NumFound,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Qname_Locations => Qname_Locations,
|
||
|
Replies => MX_Replies,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Counter := 1;
|
||
|
Additional_Count := 0;
|
||
|
while Counter <= NumFound and Additional_Count < DNS_Types.Unsigned_Short'Last-DNS_Types.Unsigned_Short(
|
||
|
2*Rr_Type.MaxNumRecords) loop
|
||
|
--# assert Counter >= 1 and Counter<=NumFound and
|
||
|
--# Answer_Count >=0 and Answer_Count <= 65535 and
|
||
|
--# Additional_Count >= 0 and
|
||
|
--# (for all Z in RR_Type.ReturnedRecordsIndexType =>
|
||
|
--# (Qname_Locations(Z) >= 0 and Qname_Locations(Z) < 16384)) and
|
||
|
--# Qname_Location >=0 and Qname_Location <= 16383 and
|
||
|
--# Additional_Count < DNS_Types.Unsigned_Short'Last-DNS_Types.Unsigned_Short(
|
||
|
--# 2*Rr_Type.MaxNumRecords) and
|
||
|
--# NumFound >= 0 and NumFound <= rr_type.MaxNumRecords and
|
||
|
--# Integer(Output_Bytes) >= DNS_Types.Header_Bits/8+1 and
|
||
|
--# Integer(Output_Bytes) <= DNS_Types.Packet_Size;
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_A(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => MX_Replies(Counter).mailExchanger,
|
||
|
Qname_Location => Qname_Locations(Counter),
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Additional_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_AAAA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => MX_Replies(Counter).mailExchanger,
|
||
|
Qname_Location => Qname_Locations(Counter),
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Additional_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Counter := Counter + 1;
|
||
|
end loop;
|
||
|
elsif Query_Type = DNS_Types.NS then
|
||
|
Create_Response_NS(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => Domainname,
|
||
|
Num_Found => NumFound,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Qname_Locations => Qname_Locations,
|
||
|
Replies => NS_Replies,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Answer_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Counter := 1;
|
||
|
Additional_Count := 0;
|
||
|
while Counter <= NumFound and Additional_Count < DNS_Types.Unsigned_Short'Last-DNS_Types.Unsigned_Short(
|
||
|
2*Rr_Type.MaxNumRecords) loop
|
||
|
--# assert Counter >= 1 and Counter<=NumFound and
|
||
|
--# (for all Z in RR_Type.ReturnedRecordsIndexType =>
|
||
|
--# (Qname_Locations(Z) >= 0 and Qname_Locations(Z) < 16384)) and
|
||
|
--# Qname_Location >=0 and Qname_Location <= 16383 and
|
||
|
--# Answer_Count >=0 and Answer_Count <= 65535 and
|
||
|
--# Additional_Count >= 0 and
|
||
|
--# Additional_Count < DNS_Types.Unsigned_Short'Last-DNS_Types.Unsigned_Short(
|
||
|
--# 2*Rr_Type.MaxNumRecords) and
|
||
|
--# NumFound >= 0 and NumFound <= rr_type.MaxNumRecords and
|
||
|
--# Integer(Output_Bytes) >= DNS_Types.Header_Bits/8+1 and
|
||
|
--# Integer(Output_Bytes) <= DNS_Types.Packet_Size;
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_A(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => NS_Replies(Counter).nameserver,
|
||
|
Qname_Location => Qname_Locations(Counter),
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Additional_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_AAAA(
|
||
|
Start_Byte => Start_Byte,
|
||
|
Domainname => NS_Replies(Counter).nameserver,
|
||
|
Qname_Location => Qname_Locations(Counter),
|
||
|
Output_Packet => Output_Packet,
|
||
|
Answer_Count => Additional_Count,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
Counter := Counter + 1;
|
||
|
end loop;
|
||
|
else
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"bad query type", 0);
|
||
|
-- ada.text_io.put_line("qc: " & dns_types.Query_Type'image(Query_Type));
|
||
|
Create_Response_Error(
|
||
|
Input_Bytes => Input_Bytes,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
end if;
|
||
|
|
||
|
-- this assert helps with the VCG Heap overflow
|
||
|
--# assert
|
||
|
--# Answer_Count >=0 and Answer_Count <= 65535 and
|
||
|
--# Additional_Count >= 0 and
|
||
|
--# (for all Z in RR_Type.ReturnedRecordsIndexType =>
|
||
|
--# (Qname_Locations(Z) >= 0 and Qname_Locations(Z) < 16384)) and
|
||
|
--# Qname_Location >=0 and Qname_Location <= 16383 and
|
||
|
--# NumFound >= 0 and NumFound <= rr_type.MaxNumRecords and
|
||
|
--# Integer(Output_Bytes) >= DNS_Types.Header_Bits/8+1 and
|
||
|
--# Integer(Output_Bytes) <= DNS_Types.Packet_Size;
|
||
|
|
||
|
DNSSEC := False;
|
||
|
-- Handle EDNS additional OPT record here!
|
||
|
if Input_Packet.Header.QDCount = 1 and
|
||
|
Input_Packet.Header.ARCount = 1 and
|
||
|
Additional_Count < DNS_Types.Unsigned_Short'Last then
|
||
|
Start_Byte := DNS_Types.Packet_Bytes_Range(Integer(Output_Bytes) -
|
||
|
DNS_Types.Header_Bits/8);
|
||
|
Create_Response_EDNS(
|
||
|
Input_Packet => Input_Packet,
|
||
|
Input_Bytes => Input_Bytes,
|
||
|
Query_End_Byte => Query_End_Byte,
|
||
|
Start_Byte => Start_Byte,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Output_Bytes => Output_Bytes,
|
||
|
Additional_Count => Additional_Count,
|
||
|
DNSSEC => DNSSEC,
|
||
|
Max_Transmit => Max_Transmit);
|
||
|
elsif Input_Packet.Header.QDCount /= 1 then
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"query count > 1", 0);
|
||
|
elsif Input_Packet.Header.ARCount > 1 then
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"ar count > 1", 0);
|
||
|
end if;
|
||
|
|
||
|
-- this assert helps with the VCG Heap overflow
|
||
|
--# assert
|
||
|
--# Answer_Count >=0 and Answer_Count <= 65535 and
|
||
|
--# Additional_Count >= 0 and
|
||
|
--# (for all Z in RR_Type.ReturnedRecordsIndexType =>
|
||
|
--# (Qname_Locations(Z) >= 0 and Qname_Locations(Z) < 16384)) and
|
||
|
--# Qname_Location >=0 and Qname_Location <= 16383 and
|
||
|
--# NumFound >= 0 and NumFound <= rr_type.MaxNumRecords and
|
||
|
--# Integer(Output_Bytes) >= DNS_Types.Header_Bits/8+1 and
|
||
|
--# Integer(Output_Bytes) <= DNS_Types.Packet_Size;
|
||
|
|
||
|
|
||
|
if DNSSEC and Answer_Count > 0 then
|
||
|
Output_Bytes := (Output_Bytes-1)+1;
|
||
|
end if;
|
||
|
|
||
|
Output_Packet.Header.ANCount := Answer_Count;
|
||
|
Output_Packet.Header.ARCount := Additional_Count;
|
||
|
if Answer_Count > 0 then
|
||
|
-- our answer is authoritative
|
||
|
Output_Packet.Header.AA := True;
|
||
|
Output_Packet.Header.RCODE := DNS_Types.No_Error;
|
||
|
elsif Output_Packet.Header.AA = False then
|
||
|
Create_NXDOMAIN_Response(
|
||
|
Start_Byte => DNS_Types.Packet_Bytes_Range(Input_Bytes) -
|
||
|
DNS_Types.Packet_Bytes_Range(DNS_Types.Header_Bits/8),
|
||
|
Domainname => Domainname,
|
||
|
Qname_Location => Qname_Location,
|
||
|
Output_Packet => Output_Packet,
|
||
|
Output_Bytes => Output_Bytes);
|
||
|
end if;
|
||
|
-- accept Flow, 602, Output_Packet, ReturnedCNAMERecords, "initialization is unneeded";
|
||
|
-- accept Flow, 602, Output_Bytes, ReturnedCNAMERecords, "initialization is unneeded";
|
||
|
end Create_Response;
|
||
|
|
||
|
|
||
|
procedure Process_Request_Tcp(
|
||
|
Reply_Socket : in DNS_Network.DNS_Socket)
|
||
|
is
|
||
|
Input_Packet : DNS_Types.DNS_Tcp_Packet;
|
||
|
Input_Bytes : DNS_Types.Packet_Length_Range;
|
||
|
Output_Packet : DNS_Types.DNS_Tcp_Packet;
|
||
|
Output_Bytes : DNS_Types.Packet_Length_Range;
|
||
|
Max_Transmit : DNS_Types.Packet_Length_Range;
|
||
|
Failure : Boolean;
|
||
|
begin
|
||
|
--Output_Packet.Rest.Bytes := DNS_Types.Bytes_Array_Type'(others => 0);
|
||
|
|
||
|
DNS_Network_Receive.Receive_DNS_Packet_Tcp(
|
||
|
Packet => Input_Packet,
|
||
|
Number_Bytes => Input_Bytes,
|
||
|
Socket => Reply_Socket,
|
||
|
Failure => Failure);
|
||
|
-- SPARK_IO_05.Put_Line(SPARK_IO_05.Standard_Output,"Input ID", 0);
|
||
|
-- SPARK_IO_05.Put_Integer(SPARK_IO_05.Standard_Output,
|
||
|
-- Integer(Input_Packet.Rest.Header.MessageID), 0, 16);
|
||
|
-- SPARK_IO_05.New_Line(SPARK_IO_05.Standard_Output,1);
|
||
|
if Failure then
|
||
|
--Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"Receive failed", 0);
|
||
|
null;
|
||
|
else
|
||
|
--Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"got packet", 0);
|
||
|
--# accept Flow, 23, Output_Packet.Rest, "init not needed";
|
||
|
--# accept Flow, 10, Max_Transmit, "only needed for UDP";
|
||
|
Create_Response(
|
||
|
Input_Packet => Input_Packet.Rest,
|
||
|
Input_Bytes => Input_Bytes,
|
||
|
Output_Packet => Output_Packet.Rest,
|
||
|
Output_Bytes => Output_Bytes,
|
||
|
Max_Transmit => Max_Transmit);
|
||
|
--# end accept;
|
||
|
--# end accept;
|
||
|
--Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"Reply created", 0);
|
||
|
--# accept Flow, 22,
|
||
|
--# "allow use of static expression for portability across platforms";
|
||
|
if System.Default_Bit_Order=System.Low_Order_First then
|
||
|
--# end accept;
|
||
|
Output_Packet.Length := DNS_Types.Byte_Swap_US(DNS_Types.Unsigned_Short(Output_Bytes));
|
||
|
else
|
||
|
Output_Packet.Length := DNS_Types.Unsigned_Short(Output_Bytes);
|
||
|
end if;
|
||
|
-- SPARK_IO_05.Put_Line(SPARK_IO_05.Standard_Output,"Output ID", 0);
|
||
|
-- SPARK_IO_05.Put_Integer(SPARK_IO_05.Standard_Output,
|
||
|
-- Integer(Output_Packet.Rest.Header.MessageID), 0, 16);
|
||
|
-- SPARK_IO_05.New_Line(SPARK_IO_05.Standard_Output,1);
|
||
|
-- Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"sending", 0);
|
||
|
|
||
|
DNS_Network.Send_DNS_Packet_Tcp(
|
||
|
Packet => Output_Packet,
|
||
|
Number_Bytes => Output_Bytes,
|
||
|
Socket => Reply_Socket,
|
||
|
Failure => Failure);
|
||
|
if Failure then
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Integer(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,
|
||
|
Integer(Output_Packet.Rest.Header.MessageID), 0, 16);
|
||
|
Protected_SPARK_IO_05.SPARK_IO_PO.Put_Line(Protected_SPARK_IO_05.SPARK_IO_PO.Standard_Output,"Respond failed", 0);
|
||
|
end if;
|
||
|
end if;
|
||
|
--# accept Flow, 602, DNS_Network.Network, Output_Packet.Rest, "initialization is unneeded";
|
||
|
--# accept Flow, 602, Protected_SPARK_IO_05.SPARK_IO_PO, Output_Packet.Rest, "initialization is unneeded";
|
||
|
--# accept Flow, 33, Max_Transmit, "Max_Transmit only for UDP";
|
||
|
end Process_Request_Tcp;
|
||
|
|
||
|
|
||
|
|
||
|
end Process_Dns_Request;
|
||
|
|