1----------------------------------------------------------------
2-- IRONSIDES - DNS SERVER
3--
4-- By: Martin C. Carlisle and Barry S. Fagin
5--     Department of Computer Science
6--     United States Air Force Academy
7--
8-- This is free software; you can redistribute it and/or
9-- modify without restriction.  We do ask that you please keep
10-- the original author information, and clearly indicate if the
11-- software has been modified.
12--
13-- This software is distributed in the hope that it will be useful,
14-- but WITHOUT ANY WARRANTY; without even the implied warranty
15-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16----------------------------------------------------------------
17
18with System;
19
20--# inherit System;
21package DNS_Types is
22   Packet_Size : constant := 8192;
23   Header_Bits : constant := 96;
24
25   type QNAME_PTR_RANGE is range 0..2**14-1;
26
27   type Packet_Length_Range is range 0..Packet_Size;
28   --# assert Packet_Length_Range'Base is Integer;
29   UDP_Max_Size : constant Packet_Length_Range := 512;
30
31   type Packet_Bytes_Range is range 1..(Packet_Size - Header_Bits/8);
32   --# assert Packet_Bytes_Range'Base is Integer;
33
34   type Byte is mod 256;
35   --# accept Warning, 2, "representation clause ok";
36   for Byte'Size use 8;
37   --# end accept;
38
39
40   type Unsigned_Short is range 0 .. 2**16 - 1;
41   --# assert Unsigned_Short'Base is Integer;
42   --# accept Warning, 2, "representation clause ok";
43   for Unsigned_Short'Size use 16;
44   --# end accept;
45
46   -- used in OPCODE field below
47   type Opcode_Type is (Query, IQuery, Status);
48   --# accept Warning, 2, "representation clause ok";
49   for Opcode_Type'Size use 4;
50   --# end accept;
51
52   -- used in RCODE field below
53   type Response_Code is
54         (No_Error,
55          Format_Error,
56          Server_Failure,
57          Name_Error,
58          Not_Implemented,
59          Refused);
60   --# accept Warning, 2, "representation clause ok";
61   for Response_Code'Size use 4;
62   --# end accept;
63
64
65   -- See http://www.zytrax.com/books/dns/ch15/ for a description
66   -- of these fields.
67   type Header_Type is
68      record
69         -- 16 bit message ID supplied by requester and mirrored by responder
70         MessageID : Unsigned_Short;
71         -- False for query, true for response
72         QR : Boolean;
73         -- 0 for query, 1 for inverse query, 2 for status request
74         Opcode : Opcode_Type;
75         -- Authoritative Answer (response only)
76         AA : Boolean;
77         -- Truncated (partial message, true until last portion)
78         TC : Boolean;
79         -- recursion desired (query)
80         RD : Boolean;
81         -- recursion available (response)
82         RA : Boolean;
83         -- Reserved for future use (zone transfers??)
84         Res1 : Boolean;
85         Res2 : Boolean;
86         Res3 : Boolean;
87         -- response code.
88         RCODE : Response_Code;
89         -- number of queries (echo in answer!)
90         QDCOUNT : Unsigned_Short;
91         -- number of answers
92         ANCOUNT : Unsigned_Short;
93         -- number of name server resource records
94         NSCOUNT : Unsigned_Short;
95         -- number of additional records
96         ARCOUNT : Unsigned_Short;
97      end record;
98   --   for Header use record
99   --      MessageID at 0 range 0..15;
100   --      QR at 0 range 23..23;
101   --      Opcode at 0 range 19..22;
102   --      AA at 0 range 18..18;
103   --      TC at 0 range 17..17;
104   --      RD at 0 range 16..16;
105   --      RA at 0 range 31..31;
106   --      Res1 at 0 range 30..30;
107   --      Res2 at 0 range 29..29;
108   --      Res3 at 0 range 28..28;
109   --      RCODE at 0 range 24..27;
110   --      QDCOUNT at 4 range 0..15;
111   --      ANCOUNT at 4 range 16..31;
112   --      NSCOUNT at 8 range 0..15;
113   --      ARCOUNT at 8 range 16..31;
114   --   end record;
115   --   for Header'Bit_Order use System.Low_Order_First;
116   --# accept Warning, 2, "representation clause ok";
117   for Header_Type use record
118      MessageID at 0 range 16..31;
119      QR at 0 range 8..8;
120      Opcode at 0 range 9..12;
121      AA at 0 range 13..13;
122      TC at 0 range 14..14;
123      RD at 0 range 15..15;
124      RA at 0 range 0..0;
125      Res1 at 0 range 1..1;
126      Res2 at 0 range 2..2;
127      Res3 at 0 range 3..3;
128      RCODE at 0 range 4..7;
129      QDCOUNT at 4 range 16..31;
130      ANCOUNT at 4 range 0..15;
131      NSCOUNT at 8 range 16..31;
132      ARCOUNT at 8 range 0..15;
133   end record;
134   for Header_Type'Size use Header_Bits;
135   for Header_Type'Bit_Order use System.High_Order_First;
136   --# end accept;
137
138   Empty_Header : constant Header_Type := Header_Type'(
139      MessageID => 0,
140      QR => False,
141      Opcode => Query,
142      Rcode => No_Error,
143      AA => False,
144      TC => False,
145      RD => False,
146      RA => False,
147      Res1 => False,
148      Res2 => False,
149      Res3 => False,
150      QDCOUNT => 0,
151      ANCOUNT => 0,
152      NSCOUNT => 0,
153      ARCOUNT => 0);
154
155   function Byte_Swap_US(U : Unsigned_Short) return Unsigned_Short;
156   --# accept Warning, 3, "Inline ok";
157   pragma Inline(Byte_Swap_US);
158   --# end accept;
159
160   -- swap bytes in Unsigned_Short fields
161   -- to switch between network and host order for little endian machines
162   procedure Byte_Swap (
163         H : in out Header_Type);
164   --# derives H from H;
165   --# post H = H~[MessageID => Byte_Swap_US(H~.MessageID);
166   --#   QDCount => Byte_Swap_US(H~.QDCount);
167   --#   ANCount => Byte_Swap_US(H~.ANCount);
168   --#   NSCount => Byte_Swap_US(H~.NSCount);
169   --#   ARCount => Byte_Swap_US(H~.ARCount)];
170   type Query_Class is
171        (IN_CLASS,
172         CH_CLASS,
173         HS_CLASS,
174         NONE_CLASS,
175         ANY_CLASS);
176   --# accept Warning, 2, "representation clause ok";
177   for Query_Class use
178      (
179      IN_CLASS   => 1,
180      CH_CLASS   => 3,
181      HS_CLASS   => 4,
182      NONE_CLASS => 254,
183      ANY_CLASS  => 255);
184   for Query_Class'Size use 16;
185   --# end accept;
186
187   type Query_Type is
188         (A,
189          NS,
190          CNAME,
191          SOA,
192          WKS,
193          PTR,
194          MX,
195          AAAA,
196          SRV,
197          A6,
198          OPT,
199          --DNSSEC
200          DS,
201          RRSIG,
202          NSEC,
203          DNSKEY,
204          --
205          ANY,
206          CAA,
207          ERROR,
208          UNIMPLEMENTED);
209   --# accept Warning, 2, "representation clause ok";
210   for Query_Type use
211      (
212      A     => 1,
213      NS    => 2,
214      CNAME => 5,
215      SOA   => 6,
216      WKS   => 11,
217      PTR   => 12,
218      MX    => 15,
219      AAAA  => 28,
220      SRV   => 33,
221      A6    => 38,
222      OPT   => 41,
223      DS    => 43,
224      RRSIG => 46,
225      NSEC  => 47,
226      DNSKEY => 48,
227      ANY   => 255,
228      CAA   => 257,
229      ERROR => 65280,
230      UNIMPLEMENTED => 65281);
231   for Query_Type'Size use 16;
232   --# end accept;
233
234   type EDNS_Record is record
235      Root         : Character;
236      Code         : Query_Type;
237      Payload_Size : Unsigned_Short;
238      RCode        : Byte;
239      Version      : Byte;
240      ZTop         : Byte;
241      ZBottom      : Byte;
242      RDLen        : Unsigned_Short;
243   end record;
244   --this record won't pack b/c payload_size isn't aligned correctly.
245   --for EDNS_Record'Size use 9*8;
246   --for EDNS_Record'Bit_Order use System.High_Order_First;
247   DNSSECMASK : constant := 128;
248
249   type Bytes_Array_Type is array(Packet_Bytes_Range) of Byte;
250
251   type DNS_Packet is record
252      Header : Header_Type;
253      Bytes  : Bytes_Array_Type;
254   end record;
255   type DNS_Tcp_Packet is record
256      Length : Unsigned_Short;
257      Rest   : DNS_Packet;
258   END RECORD;
259end Dns_Types;
260
261