Home | History | Annotate | Download | only in layers
      1 from scapy.fields import *
      2 from scapy.packet import *
      3 from scapy.layers.inet import UDP
      4 from scapy.layers.dns import DNSQRField, DNSRRField, DNSRRCountField
      5 
      6 """
      7 LLMNR (Link Local Multicast Node Resolution).
      8 
      9 [RFC 4795]
     10 """
     11 
     12 #############################################################################
     13 ###                           LLMNR (RFC4795)                             ###
     14 #############################################################################
     15 # LLMNR is based on the DNS packet format (RFC1035 Section 4)
     16 # RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno
     17 
     18 _LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3"
     19 _LLMNR_IPv4_mcast_addr = "224.0.0.252"
     20 
     21 class LLMNRQuery(Packet):
     22     name = "Link Local Multicast Node Resolution - Query"
     23     fields_desc = [ ShortField("id", 0),
     24                     BitField("qr", 0, 1),
     25                     BitEnumField("opcode", 0, 4, { 0:"QUERY" }),
     26                     BitField("c", 0, 1),
     27                     BitField("tc", 0, 2),
     28                     BitField("z", 0, 4),
     29                     BitEnumField("rcode", 0, 4, { 0:"ok" }),
     30                     DNSRRCountField("qdcount", None, "qd"),
     31                     DNSRRCountField("ancount", None, "an"),
     32                     DNSRRCountField("nscount", None, "ns"),
     33                     DNSRRCountField("arcount", None, "ar"),
     34                     DNSQRField("qd", "qdcount"),
     35                     DNSRRField("an", "ancount"),
     36                     DNSRRField("ns", "nscount"),
     37                     DNSRRField("ar", "arcount",0)]
     38     overload_fields = {UDP: {"sport": 5355, "dport": 5355 }}
     39     def hashret(self):
     40         return struct.pack("!H", self.id)
     41 
     42 class LLMNRResponse(LLMNRQuery):
     43     name = "Link Local Multicast Node Resolution - Response"
     44     qr = 1
     45     def answers(self, other):
     46         return (isinstance(other, LLMNRQuery) and
     47                 self.id == other.id and
     48                 self.qr == 1 and
     49                 other.qr == 0)
     50 
     51 def _llmnr_dispatcher(x, *args, **kargs):
     52     cls = conf.raw_layer
     53     if len(x) >= 2:
     54         if (orb(x[2]) & 0x80): # Response
     55             cls = LLMNRResponse
     56         else:                  # Query
     57             cls = LLMNRQuery
     58     return cls(x, *args, **kargs)
     59 
     60 bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 })
     61 bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 })
     62 
     63 # LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista.")))
     64 
     65 
     66