#include "idl_types.h"

/*
   IDL structures for DNS operations

   DNS is not traditionally encoded using IDL/NDR. This is a bit of an
   experiment, and I may well switch us back to a more traditional
   encoding if it doesn't work out
*/

import "misc.idl";
[
	helper("librpc/ndr/ndr_dns.h"),
	helpstring("DNS records"),
	version(0.0),
	uuid("a047c001-5f22-40b0-9d52-7042c43f711a")
]
interface dns
{
	const int DNS_SERVICE_PORT       = 53;

	typedef [public,bitmap16bit] bitmap {
		DNS_RCODE                   = 0x000F,
		DNS_FLAG_BROADCAST          = 0x0010,
		DNS_FLAG_RECURSION_AVAIL    = 0x0080,
		DNS_FLAG_RECURSION_DESIRED  = 0x0100,
		DNS_FLAG_TRUNCATION         = 0x0200,
		DNS_FLAG_AUTHORITATIVE      = 0x0400,
		DNS_OPCODE                  = 0x7800,
		DNS_FLAG_REPLY              = 0x8000
	} dns_operation;

	/* the opcodes are in the operation field, masked with
	   DNS_OPCODE */
	typedef [public] enum {
		DNS_OPCODE_QUERY          =  (0x0<<11),
		DNS_OPCODE_IQUERY         =  (0x1<<11),
		DNS_OPCODE_STATUS         =  (0x2<<11),
		DNS_OPCODE_REGISTER       =  (0x5<<11),
		DNS_OPCODE_RELEASE        =  (0x6<<11),
		DNS_OPCODE_WACK           =  (0x7<<11),
		DNS_OPCODE_REFRESH        =  (0x8<<11),
		DNS_OPCODE_REFRESH2       =  (0x9<<11),
		DNS_OPCODE_MULTI_HOME_REG =  (0xf<<11)
	} dns_opcode;

	/* rcode values */
	typedef [public] enum {
		DNS_RCODE_OK       = 0x0,
		DNS_RCODE_FORMERR  = 0x1,
		DNS_RCODE_SERVFAIL = 0x2,
		DNS_RCODE_NXDOMAIN = 0x3,
		DNS_RCODE_NOTIMP   = 0x4,
		DNS_RCODE_REFUSED  = 0x5,
		DNS_RCODE_YXDOMAIN = 0x6,
		DNS_RCODE_YXRRSET  = 0x7,
		DNS_RCODE_NXRRSET  = 0x8,
		DNS_RCODE_NOTAUTH  = 0x9,
		DNS_RCODE_NOTZONE  = 0xA
	} dns_rcode;

	typedef [public,enum16bit] enum {
		DNS_QCLASS_IP   = 0x0001,
		DNS_QCLASS_NONE = 0x00FE,
		DNS_QCLASS_ANY  = 0x00FF
	} dns_qclass;

	/* These vese values could have been merged with NBT_QTYPE values, but
	   DNS_QTYPE_SRV and NBT_QTYPE_STATUS have the same numeric value. */
	typedef [public,enum16bit] enum {
		DNS_QTYPE_ZERO   = 0x0000,
		DNS_QTYPE_A      = 0x0001,
		DNS_QTYPE_NS     = 0x0002,
		DNS_QTYPE_MD     = 0x0003,
		DNS_QTYPE_MF     = 0x0004,
		DNS_QTYPE_CNAME  = 0x0005,
		DNS_QTYPE_SOA    = 0x0006,
		DNS_QTYPE_MB     = 0x0007,
		DNS_QTYPE_MG     = 0x0008,
		DNS_QTYPE_MR     = 0x0009,
		DNS_QTYPE_NULL   = 0x000A,
		DNS_QTYPE_WKS    = 0x000B,
		DNS_QTYPE_PTR    = 0x000C,
		DNS_QTYPE_HINFO  = 0x000D,
		DNS_QTYPE_MINFO  = 0x000E,
		DNS_QTYPE_MX     = 0x000F,
		DNS_QTYPE_TXT    = 0x0010,
		DNS_QTYPE_RP     = 0x0011,
		DNS_QTYPE_AFSDB  = 0x0012,
		DNS_QTYPE_X25    = 0x0013,
		DNS_QTYPE_ISDN   = 0x0014,
		DNS_QTYPE_RT     = 0x0015,
		DNS_QTYPE_SIG    = 0x0018,
		DNS_QTYPE_KEY    = 0x0019,
		DNS_QTYPE_AAAA   = 0x001C,
		DNS_QTYPE_LOC    = 0x001D,
		DNS_QTYPE_NXT    = 0x001E,
		DNS_QTYPE_NETBIOS= 0x0020,
		DNS_QTYPE_SRV    = 0x0021,
		DNS_QTYPE_ATMA   = 0x0022,
		DNS_QTYPE_NAPTR  = 0x0023,
		DNS_QTYPE_DNAME  = 0x0027,
		DNS_QTYPE_DS     = 0x002B,
		DNS_QTYPE_RRSIG  = 0x002E,
		DNS_QTYPE_NSEC   = 0x002F,
		DNS_QTYPE_DNSKEY = 0x0030,
		DNS_QTYPE_DHCID  = 0x0031,
		DNS_QTYPE_ALL    = 0x00FF,
		DNS_QTYPE_WINS   = 0xFF01,
		DNS_QTYPE_WINSR  = 0xFF02
	} dns_qtype;

	typedef [public] struct {
		dns_string name;
		dns_qtype  question_type;
		dns_qclass question_class;
	} dns_name_question;

	typedef [public] struct {
		uint16 length;
		uint8  data[length];
	} dns_rdata_data;

	typedef struct {
		dns_string mname;
		dns_string rname;
		uint32     serial;
		uint32     refresh;
		uint32     retry;
		uint32     expire;
		uint32     minimum;
	} dns_soa_record;

	typedef [public] struct {
		uint16     priority;
		uint16     weight;
		uint16     port;
		dns_string target;
	} dns_srv_record;

	typedef [public] struct {
		uint16     preference;
		dns_string exchange;
	} dns_mx_record;

	typedef [nodiscriminant,public,flag(NDR_NOALIGN)] union {
		[case(DNS_QTYPE_A)]     ipv4address	 ipv4_record;
		[case(DNS_QTYPE_NS)]    dns_string       ns_record;
		[case(DNS_QTYPE_CNAME)] dns_string       cname_record;
		[case(DNS_QTYPE_SOA)]   dns_soa_record   soa_record;
		[case(DNS_QTYPE_PTR)]   dns_string       ptr_record;
		[case(DNS_QTYPE_MX)]    dns_mx_record    mx_record;
		[case(DNS_QTYPE_AAAA)]	ipv6address	 ipv6_record;
		[case(DNS_QTYPE_SRV)]	dns_srv_record	 srv_record;
		[default];
	} dns_rdata;

	typedef [flag(LIBNDR_PRINT_ARRAY_HEX|NDR_NOALIGN),nopush,nopull] struct {
		dns_string name;
		dns_qtype  rr_type;
		dns_qclass rr_class;
		uint32     ttl;
		uint16     length; /* Should be set to either UINT16_MAX or 0 */
		[switch_is(rr_type)] dns_rdata rdata;
		DATA_BLOB  unexpected;
	} dns_res_rec;

	typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct {
		uint16            id;
		dns_operation     operation;
		uint16            qdcount;
		uint16            ancount;
		uint16            nscount;
		uint16            arcount;
		dns_name_question questions[qdcount];
		dns_res_rec       answers[ancount];
		dns_res_rec       nsrecs[nscount];
		dns_res_rec       additional[arcount];
	} dns_name_packet;

        /*
	   this is a convenience hook for ndrdump
	*/
	void decode_dns_name_packet(
				    [in] dns_name_packet packet
				   );
}