diff --git a/scapy/layers/dns.py b/scapy/layers/dns.py
index 2532633a41d2e005bce4282c78ba3c576bbe5f99..e177496730041677041e71b603b384529062a8b1 100644
--- a/scapy/layers/dns.py
+++ b/scapy/layers/dns.py
@@ -14,7 +14,7 @@ from scapy.packet import *
 from scapy.fields import *
 from scapy.ansmachine import *
 from scapy.sendrecv import sr1
-from scapy.layers.inet import IP, DestIPField, UDP
+from scapy.layers.inet import IP, DestIPField, UDP, TCP
 from scapy.layers.inet6 import DestIP6Field
 
 class DNSStrField(StrField):
@@ -233,36 +233,43 @@ class RDLenField(Field):
             rdataf = pkt.get_field("rdata")
             x = len(rdataf.i2m(pkt, pkt.rdata))
         return x
-    
+
 
 class DNS(Packet):
     name = "DNS"
-    fields_desc = [ ShortField("id", 0),
-                    BitField("qr", 0, 1),
-                    BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}),
-                    BitField("aa", 0, 1),
-                    BitField("tc", 0, 1),
-                    BitField("rd", 1, 1),
-                    BitField("ra", 0, 1),
-                    BitField("z", 0, 1),
-                    # AD and CD bits are defined in RFC 2535
-                    BitField("ad", 0, 1), # Authentic Data
-                    BitField("cd", 0, 1), # Checking Disabled
-                    BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}),
-                    DNSRRCountField("qdcount", None, "qd"),
-                    DNSRRCountField("ancount", None, "an"),
-                    DNSRRCountField("nscount", None, "ns"),
-                    DNSRRCountField("arcount", None, "ar"),
-                    DNSQRField("qd", "qdcount"),
-                    DNSRRField("an", "ancount"),
-                    DNSRRField("ns", "nscount"),
-                    DNSRRField("ar", "arcount",0) ]
+    fields_desc = [
+        ConditionalField(ShortField("length", None),
+                         lambda p: isinstance(p.underlayer, TCP)),
+        ShortField("id", 0),
+        BitField("qr", 0, 1),
+        BitEnumField("opcode", 0, 4, {0: "QUERY", 1: "IQUERY", 2: "STATUS"}),
+        BitField("aa", 0, 1),
+        BitField("tc", 0, 1),
+        BitField("rd", 1, 1),
+        BitField("ra", 0, 1),
+        BitField("z", 0, 1),
+        # AD and CD bits are defined in RFC 2535
+        BitField("ad", 0, 1),  # Authentic Data
+        BitField("cd", 0, 1),  # Checking Disabled
+        BitEnumField("rcode", 0, 4, {0: "ok", 1: "format-error",
+                                     2: "server-failure", 3: "name-error",
+                                     4: "not-implemented", 5: "refused"}),
+        DNSRRCountField("qdcount", None, "qd"),
+        DNSRRCountField("ancount", None, "an"),
+        DNSRRCountField("nscount", None, "ns"),
+        DNSRRCountField("arcount", None, "ar"),
+        DNSQRField("qd", "qdcount"),
+        DNSRRField("an", "ancount"),
+        DNSRRField("ns", "nscount"),
+        DNSRRField("ar", "arcount", 0),
+    ]
+
     def answers(self, other):
         return (isinstance(other, DNS)
                 and self.id == other.id
                 and self.qr == 1
                 and other.qr == 0)
-        
+
     def mysummary(self):
         type = ["Qry","Ans"][self.qr]
         name = ""
@@ -276,14 +283,30 @@ class DNS(Packet):
                 name = ' "%s"' % self.qd.qname
         return 'DNS %s%s ' % (type, name)
 
-dnstypes = { 0:"ANY", 255:"ALL",
-             1:"A", 2:"NS", 3:"MD", 4:"MF", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG",
-             9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",
-             17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME",
-             41:"OPT", 43:"DS", 46:"RRSIG", 47:"NSEC", 48:"DNSKEY",
-	     50: "NSEC3", 51: "NSEC3PARAM", 32769:"DLV" }
+    def post_build(self, pkt, pay):
+        if isinstance(self.underlayer, TCP) and self.length is None:
+            pkt = struct.pack("!H", len(pkt) - 2) + pkt[2:]
+        return pkt + pay
+
+
+# http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
+dnstypes = {
+    0:"ANY",
+    1: "A", 2: "NS", 3: "MD", 4: "MF", 5: "CNAME", 6: "SOA", 7: "MB", 8: "MG",
+    9: "MR", 10: "NULL", 11: "WKS", 12: "PTR", 13: "HINFO", 14: "MINFO",
+    15: "MX", 16: "TXT", 17: "RP", 18: "AFSDB", 19: "X25", 20: "ISDN", 21: "RT",
+    22: "NSAP", 23: "NSAP-PTR", 24: "SIG", 25: "KEY", 26: "PX", 27: "GPOS",
+    28: "AAAA", 29: "LOC", 30: "NXT", 31: "EID", 32: "NIMLOC", 33: "SRV",
+    34: "ATMA", 35: "NAPTR", 36: "KX", 37: "CERT", 38: "A6", 39: "DNAME",
+    40: "SINK", 41: "OPT", 42: "APL", 43: "DS", 44: "SSHFP", 45: "IPSECKEY",
+    46: "RRSIG", 47: "NSEC", 48: "DNSKEY", 49: "DHCID", 50: "NSEC3",
+    51: "NSEC3PARAM", 55: "HIP", 56: "NINFO", 57: "RKEY", 58: "TALINK",
+    99: "SPF", 100: "UINFO", 101: "UID", 102: "GID", 103: "UNSPEC", 249: "TKEY",
+    250: "TSIG",
+    32768: "TA", 32769:"DLV",
+}
 
-dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"}
+dnsqtypes = {251: "IXFR", 252: "AXFR", 253: "MAILB", 254: "MAILA", 255: "ALL"}
 dnsqtypes.update(dnstypes)
 dnsclasses =  {1: 'IN',  2: 'CS',  3: 'CH',  4: 'HS',  255: 'ANY'}
 
@@ -627,6 +650,8 @@ bind_layers(UDP, DNS, dport=53)
 bind_layers(UDP, DNS, sport=53)
 DestIPField.bind_addr(UDP, "224.0.0.251", dport=5353)
 DestIP6Field.bind_addr(UDP, "ff02::fb", dport=5353)
+bind_layers(TCP, DNS, dport=53)
+bind_layers(TCP, DNS, sport=53)
 
 
 @conf.commands.register
diff --git a/test/regression.uts b/test/regression.uts
index a5a2f710bce3696d4ce3c291b67c4f9ffe6dbbd4..dee46d9ddec35aeee33fe440d4963a4e509b0730 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -4822,6 +4822,20 @@ pkt = IP(len=42, ihl=6, options=[IPOption_RR()]) / UDP() / ("A" * 10)
 bpkt = IP(str(pkt))
 assert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17
 
+= DNS
+
+* DNS over UDP
+pkt = IP(str(IP(src="10.0.0.1", dst="8.8.8.8")/UDP(sport=RandShort(), dport=53)/DNS(qd=DNSQR(qname="secdev.org."))))
+assert UDP in pkt and isinstance(pkt[UDP].payload, DNS)
+assert pkt[UDP].dport == 53 and pkt[UDP].length is None
+assert pkt[DNS].qdcount == 1 and pkt[DNS].qd.qname == "secdev.org."
+
+* DNS over TCP
+pkt = IP(str(IP(src="10.0.0.1", dst="8.8.8.8")/TCP(sport=RandShort(), dport=53, flags="P")/DNS(qd=DNSQR(qname="secdev.org."))))
+assert TCP in pkt and isinstance(pkt[TCP].payload, DNS)
+assert pkt[TCP].dport == 53 and pkt[DNS].length is not None
+assert pkt[DNS].qdcount == 1 and pkt[DNS].qd.qname == "secdev.org."
+
 = Layer binding
 
 * Test DestMACField & DestIPField