diff --git a/scapy/config.py b/scapy/config.py index 7fb2de0e218be03d5a3b8b646a09d78601a39acb..3a42952a79f41be7b1abfe9e6e3c3475b764aad0 100644 --- a/scapy/config.py +++ b/scapy/config.py @@ -315,7 +315,7 @@ extensions_paths: path or list of paths where extensions are to be looked for netcache = NetCache() load_layers = ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp", "mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp", - "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6" ] + "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr" ] conf=Conf() diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index 46a729803377604509361d85de58b23848f2ba1f..9c15ae11dd219bc2b93c3a6027d574e52d9addf5 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -22,7 +22,6 @@ from scapy.layers.l2 import * from scapy.layers.inet import * -from scapy.layers.dns import * from scapy.fields import * from scapy.packet import * from scapy.volatile import * @@ -1757,64 +1756,6 @@ class ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6): XIntField("reserved",0) ] overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} -############################################################################# -### LLMNR (RFC4795) ### -############################################################################# -# LLMNR is based on the DNS packet format (RFC1035 Section 4) -# RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno - -_LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3" -_LLMNR_IPv4_mcast_addr = "224.0.0.252" - -class LLMNRQuery(Packet): - name = "Link Local Multicast Node Resolution - Query" - fields_desc = [ ShortField("id", 0), - BitField("qr", 0, 1), - BitEnumField("opcode", 0, 4, { 0:"QUERY" }), - BitField("c", 0, 1), - BitField("tc", 0, 2), - BitField("z", 0, 4), - BitEnumField("rcode", 0, 4, { 0:"ok" }), - 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)] - overload_fields = {UDP: {"sport": 5355, "dport": 5355 }} - def hashret(self): - return struct.pack("!H", id) - -class LLMNRResponse(LLMNRQuery): - name = "Link Local Multicast Node Resolution - Response" - __metaclass__ = NewDefaultValues - qr = 1 - fields_desc = [] - - def answers(self, other): - return (isinstance(other, LLMNRQuery) and - self.id == other.id and - self.qr == 1 and - other.qr == 0) - -def _llmnr_dispatcher(x, *args, **kargs): - cls = Raw - if len(x) >= 3: - if (ord(x[4]) & 0x80): # Response - cls = LLMNRResponse - else: # Query - cls = LLMNRQuery - return cls(x, *args, **kargs) - -bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 }) -bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 }) - -# LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista."))) - - - ############################################################################### # ICMPv6 Node Information Queries (RFC 4620) diff --git a/scapy/layers/llmnr.py b/scapy/layers/llmnr.py new file mode 100644 index 0000000000000000000000000000000000000000..cc84feee006fc89d0f3036dd1b890ac37630fcd9 --- /dev/null +++ b/scapy/layers/llmnr.py @@ -0,0 +1,63 @@ +from scapy.fields import * +from scapy.packet import * +from scapy.layers.inet import UDP +from scapy.layers.dns import DNSQRField, DNSRRField, DNSRRCountField + + +############################################################################# +### LLMNR (RFC4795) ### +############################################################################# +# LLMNR is based on the DNS packet format (RFC1035 Section 4) +# RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno + +_LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3" +_LLMNR_IPv4_mcast_addr = "224.0.0.252" + +class LLMNRQuery(Packet): + name = "Link Local Multicast Node Resolution - Query" + fields_desc = [ ShortField("id", 0), + BitField("qr", 0, 1), + BitEnumField("opcode", 0, 4, { 0:"QUERY" }), + BitField("c", 0, 1), + BitField("tc", 0, 2), + BitField("z", 0, 4), + BitEnumField("rcode", 0, 4, { 0:"ok" }), + 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)] + overload_fields = {UDP: {"sport": 5355, "dport": 5355 }} + def hashret(self): + return struct.pack("!H", id) + +class LLMNRResponse(LLMNRQuery): + name = "Link Local Multicast Node Resolution - Response" + __metaclass__ = NewDefaultValues + qr = 1 + fields_desc = [] + + def answers(self, other): + return (isinstance(other, LLMNRQuery) and + self.id == other.id and + self.qr == 1 and + other.qr == 0) + +def _llmnr_dispatcher(x, *args, **kargs): + cls = Raw + if len(x) >= 3: + if (ord(x[4]) & 0x80): # Response + cls = LLMNRResponse + else: # Query + cls = LLMNRQuery + return cls(x, *args, **kargs) + +bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 }) +bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 }) + +# LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista."))) + +