summaryrefslogtreecommitdiff
path: root/external/construct/protocols/application/dns.py
diff options
context:
space:
mode:
Diffstat (limited to 'external/construct/protocols/application/dns.py')
-rw-r--r--external/construct/protocols/application/dns.py147
1 files changed, 147 insertions, 0 deletions
diff --git a/external/construct/protocols/application/dns.py b/external/construct/protocols/application/dns.py
new file mode 100644
index 0000000..8a586ce
--- /dev/null
+++ b/external/construct/protocols/application/dns.py
@@ -0,0 +1,147 @@
+"""
+Domain Name System (TCP/IP protocol stack)
+"""
+from construct import *
+from construct.protocols.layer3.ipv4 import IpAddressAdapter
+from binascii import unhexlify
+import six
+
+
+class DnsStringAdapter(Adapter):
+ def _encode(self, obj, context):
+ parts = obj.split(".")
+ parts.append("")
+ return parts
+ def _decode(self, obj, context):
+ return ".".join(obj[:-1])
+
+dns_record_class = Enum(UBInt16("class"),
+ RESERVED = 0,
+ INTERNET = 1,
+ CHAOS = 3,
+ HESIOD = 4,
+ NONE = 254,
+ ANY = 255,
+)
+
+dns_record_type = Enum(UBInt16("type"),
+ IPv4 = 1,
+ AUTHORITIVE_NAME_SERVER = 2,
+ CANONICAL_NAME = 5,
+ NULL = 10,
+ MAIL_EXCHANGE = 15,
+ TEXT = 16,
+ X25 = 19,
+ ISDN = 20,
+ IPv6 = 28,
+ UNSPECIFIED = 103,
+ ALL = 255,
+)
+
+query_record = Struct("query_record",
+ DnsStringAdapter(
+ RepeatUntil(lambda obj, ctx: obj == "",
+ PascalString("name")
+ )
+ ),
+ dns_record_type,
+ dns_record_class,
+)
+
+rdata = Field("rdata", lambda ctx: ctx.rdata_length)
+
+resource_record = Struct("resource_record",
+ CString("name", terminators = six.b("\xc0\x00")),
+ Padding(1),
+ dns_record_type,
+ dns_record_class,
+ UBInt32("ttl"),
+ UBInt16("rdata_length"),
+ IfThenElse("data", lambda ctx: ctx.type == "IPv4",
+ IpAddressAdapter(rdata),
+ rdata
+ )
+)
+
+dns = Struct("dns",
+ UBInt16("id"),
+ BitStruct("flags",
+ Enum(Bit("type"),
+ QUERY = 0,
+ RESPONSE = 1,
+ ),
+ Enum(Nibble("opcode"),
+ STANDARD_QUERY = 0,
+ INVERSE_QUERY = 1,
+ SERVER_STATUS_REQUEST = 2,
+ NOTIFY = 4,
+ UPDATE = 5,
+ ),
+ Flag("authoritive_answer"),
+ Flag("truncation"),
+ Flag("recurssion_desired"),
+ Flag("recursion_available"),
+ Padding(1),
+ Flag("authenticated_data"),
+ Flag("checking_disabled"),
+ Enum(Nibble("response_code"),
+ SUCCESS = 0,
+ FORMAT_ERROR = 1,
+ SERVER_FAILURE = 2,
+ NAME_DOES_NOT_EXIST = 3,
+ NOT_IMPLEMENTED = 4,
+ REFUSED = 5,
+ NAME_SHOULD_NOT_EXIST = 6,
+ RR_SHOULD_NOT_EXIST = 7,
+ RR_SHOULD_EXIST = 8,
+ NOT_AUTHORITIVE = 9,
+ NOT_ZONE = 10,
+ ),
+ ),
+ UBInt16("question_count"),
+ UBInt16("answer_count"),
+ UBInt16("authority_count"),
+ UBInt16("additional_count"),
+ Array(lambda ctx: ctx.question_count,
+ Rename("questions", query_record),
+ ),
+ Rename("answers",
+ Array(lambda ctx: ctx.answer_count, resource_record)
+ ),
+ Rename("authorities",
+ Array(lambda ctx: ctx.authority_count, resource_record)
+ ),
+ Array(lambda ctx: ctx.additional_count,
+ Rename("additionals", resource_record),
+ ),
+)
+
+
+if __name__ == "__main__":
+ cap1 = unhexlify(six.b("2624010000010000000000000377777706676f6f676c6503636f6d0000010001"))
+
+ cap2 = unhexlify(six.b(
+ "2624818000010005000600060377777706676f6f676c6503636f6d0000010001c00c00"
+ "05000100089065000803777777016cc010c02c0001000100000004000440e9b768c02c"
+ "0001000100000004000440e9b793c02c0001000100000004000440e9b763c02c000100"
+ "0100000004000440e9b767c030000200010000a88600040163c030c030000200010000"
+ "a88600040164c030c030000200010000a88600040165c030c030000200010000a88600"
+ "040167c030c030000200010000a88600040161c030c030000200010000a88600040162"
+ "c030c0c00001000100011d0c0004d8ef3509c0d0000100010000ca7c000440e9b309c0"
+ "80000100010000c4c5000440e9a109c0900001000100004391000440e9b709c0a00001"
+ "00010000ca7c000442660b09c0b00001000100000266000440e9a709"
+ ))
+
+ obj = dns.parse(cap1)
+ print (obj)
+ print (repr(dns.build(obj)))
+
+ print ("-" * 80)
+
+ obj = dns.parse(cap2)
+ print (obj)
+ print (repr(dns.build(obj)))
+
+
+
+