| 1760 | | ############################################################################# |
|---|
| 1761 | | ### LLMNR (RFC4795) ### |
|---|
| 1762 | | ############################################################################# |
|---|
| 1763 | | # LLMNR is based on the DNS packet format (RFC1035 Section 4) |
|---|
| 1764 | | # RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno |
|---|
| 1765 | | |
|---|
| 1766 | | _LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3" |
|---|
| 1767 | | _LLMNR_IPv4_mcast_addr = "224.0.0.252" |
|---|
| 1768 | | |
|---|
| 1769 | | class LLMNRQuery(Packet): |
|---|
| 1770 | | name = "Link Local Multicast Node Resolution - Query" |
|---|
| 1771 | | fields_desc = [ ShortField("id", 0), |
|---|
| 1772 | | BitField("qr", 0, 1), |
|---|
| 1773 | | BitEnumField("opcode", 0, 4, { 0:"QUERY" }), |
|---|
| 1774 | | BitField("c", 0, 1), |
|---|
| 1775 | | BitField("tc", 0, 2), |
|---|
| 1776 | | BitField("z", 0, 4), |
|---|
| 1777 | | BitEnumField("rcode", 0, 4, { 0:"ok" }), |
|---|
| 1778 | | DNSRRCountField("qdcount", None, "qd"), |
|---|
| 1779 | | DNSRRCountField("ancount", None, "an"), |
|---|
| 1780 | | DNSRRCountField("nscount", None, "ns"), |
|---|
| 1781 | | DNSRRCountField("arcount", None, "ar"), |
|---|
| 1782 | | DNSQRField("qd", "qdcount"), |
|---|
| 1783 | | DNSRRField("an", "ancount"), |
|---|
| 1784 | | DNSRRField("ns", "nscount"), |
|---|
| 1785 | | DNSRRField("ar", "arcount",0)] |
|---|
| 1786 | | overload_fields = {UDP: {"sport": 5355, "dport": 5355 }} |
|---|
| 1787 | | def hashret(self): |
|---|
| 1788 | | return struct.pack("!H", id) |
|---|
| 1789 | | |
|---|
| 1790 | | class LLMNRResponse(LLMNRQuery): |
|---|
| 1791 | | name = "Link Local Multicast Node Resolution - Response" |
|---|
| 1792 | | __metaclass__ = NewDefaultValues |
|---|
| 1793 | | qr = 1 |
|---|
| 1794 | | fields_desc = [] |
|---|
| 1795 | | |
|---|
| 1796 | | def answers(self, other): |
|---|
| 1797 | | return (isinstance(other, LLMNRQuery) and |
|---|
| 1798 | | self.id == other.id and |
|---|
| 1799 | | self.qr == 1 and |
|---|
| 1800 | | other.qr == 0) |
|---|
| 1801 | | |
|---|
| 1802 | | def _llmnr_dispatcher(x, *args, **kargs): |
|---|
| 1803 | | cls = Raw |
|---|
| 1804 | | if len(x) >= 3: |
|---|
| 1805 | | if (ord(x[4]) & 0x80): # Response |
|---|
| 1806 | | cls = LLMNRResponse |
|---|
| 1807 | | else: # Query |
|---|
| 1808 | | cls = LLMNRQuery |
|---|
| 1809 | | return cls(x, *args, **kargs) |
|---|
| 1810 | | |
|---|
| 1811 | | bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 }) |
|---|
| 1812 | | bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 }) |
|---|
| 1813 | | |
|---|
| 1814 | | # LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista."))) |
|---|
| 1815 | | |
|---|
| 1816 | | |
|---|
| 1817 | | |
|---|