A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.
Dependents: oldheating gps motorhome heating
udp/dns/dns.cpp@59:e0e556c8bd46, 2017-12-14 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Dec 14 20:55:40 2017 +0000
- Revision:
- 59:e0e556c8bd46
- Parent:
- 47:73af5c0b0dc2
Added buffer length to help avoid over runs
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 13:9cd54f7db57a | 1 | #include "dns.h" |
andrewboyson | 13:9cd54f7db57a | 2 | #include "dnshdr.h" |
andrewboyson | 13:9cd54f7db57a | 3 | #include "dnsquery.h" |
andrewboyson | 13:9cd54f7db57a | 4 | #include "dnsreply.h" |
andrewboyson | 13:9cd54f7db57a | 5 | #include "dnsserver.h" |
andrewboyson | 13:9cd54f7db57a | 6 | #include "io.h" |
andrewboyson | 32:679654f2d023 | 7 | #include "log.h" |
andrewboyson | 32:679654f2d023 | 8 | #include "dhcp.h" |
andrewboyson | 13:9cd54f7db57a | 9 | |
andrewboyson | 47:73af5c0b0dc2 | 10 | void DnsProtocolString(uint8_t protocol, int size, char* text) |
andrewboyson | 13:9cd54f7db57a | 11 | { |
andrewboyson | 13:9cd54f7db57a | 12 | switch (protocol) |
andrewboyson | 13:9cd54f7db57a | 13 | { |
andrewboyson | 13:9cd54f7db57a | 14 | case DNS_PROTOCOL_UDNS: strncpy (text, "DNS", size); break; |
andrewboyson | 13:9cd54f7db57a | 15 | case DNS_PROTOCOL_MDNS: strncpy (text, "MDNS", size); break; |
andrewboyson | 13:9cd54f7db57a | 16 | case DNS_PROTOCOL_LLMNR: strncpy (text, "LLMNR", size); break; |
andrewboyson | 13:9cd54f7db57a | 17 | default: snprintf(text, size, "%d", protocol); break; |
andrewboyson | 13:9cd54f7db57a | 18 | } |
andrewboyson | 13:9cd54f7db57a | 19 | } |
andrewboyson | 13:9cd54f7db57a | 20 | |
andrewboyson | 47:73af5c0b0dc2 | 21 | void DnsRecordTypeString(uint8_t recordtype, int size, char* text) |
andrewboyson | 13:9cd54f7db57a | 22 | { |
andrewboyson | 13:9cd54f7db57a | 23 | switch (recordtype) |
andrewboyson | 13:9cd54f7db57a | 24 | { |
andrewboyson | 13:9cd54f7db57a | 25 | case DNS_RECORD_A: strncpy (text, "A", size); break; |
andrewboyson | 13:9cd54f7db57a | 26 | case DNS_RECORD_AAAA: strncpy (text, "AAAA", size); break; |
andrewboyson | 13:9cd54f7db57a | 27 | case DNS_RECORD_PTR: strncpy (text, "PTR", size); break; |
andrewboyson | 15:6ca6778168b1 | 28 | case DNS_RECORD_TXT: strncpy (text, "TXT", size); break; |
andrewboyson | 15:6ca6778168b1 | 29 | case DNS_RECORD_SRV: strncpy (text, "SRV", size); break; |
andrewboyson | 13:9cd54f7db57a | 30 | default: snprintf(text, size, "%d", recordtype); break; |
andrewboyson | 13:9cd54f7db57a | 31 | } |
andrewboyson | 13:9cd54f7db57a | 32 | } |
andrewboyson | 47:73af5c0b0dc2 | 33 | void DnsProtocolLog(uint8_t protocol) |
andrewboyson | 47:73af5c0b0dc2 | 34 | { |
andrewboyson | 47:73af5c0b0dc2 | 35 | switch (protocol) |
andrewboyson | 47:73af5c0b0dc2 | 36 | { |
andrewboyson | 47:73af5c0b0dc2 | 37 | case DNS_PROTOCOL_UDNS: Log ("DNS "); break; |
andrewboyson | 47:73af5c0b0dc2 | 38 | case DNS_PROTOCOL_MDNS: Log ("MDNS "); break; |
andrewboyson | 47:73af5c0b0dc2 | 39 | case DNS_PROTOCOL_LLMNR: Log ("LLMNR"); break; |
andrewboyson | 47:73af5c0b0dc2 | 40 | default: LogF("%d", protocol); break; |
andrewboyson | 47:73af5c0b0dc2 | 41 | } |
andrewboyson | 47:73af5c0b0dc2 | 42 | } |
andrewboyson | 47:73af5c0b0dc2 | 43 | |
andrewboyson | 47:73af5c0b0dc2 | 44 | void DnsRecordTypeLog(uint8_t recordtype) |
andrewboyson | 47:73af5c0b0dc2 | 45 | { |
andrewboyson | 47:73af5c0b0dc2 | 46 | switch (recordtype) |
andrewboyson | 47:73af5c0b0dc2 | 47 | { |
andrewboyson | 47:73af5c0b0dc2 | 48 | case DNS_RECORD_A: Log ("A" ); break; |
andrewboyson | 47:73af5c0b0dc2 | 49 | case DNS_RECORD_AAAA: Log ("AAAA"); break; |
andrewboyson | 47:73af5c0b0dc2 | 50 | case DNS_RECORD_PTR: Log ("PTR" ); break; |
andrewboyson | 47:73af5c0b0dc2 | 51 | case DNS_RECORD_TXT: Log ("TXT" ); break; |
andrewboyson | 47:73af5c0b0dc2 | 52 | case DNS_RECORD_SRV: Log ("SRV" ); break; |
andrewboyson | 47:73af5c0b0dc2 | 53 | default: LogF("%d", recordtype); break; |
andrewboyson | 47:73af5c0b0dc2 | 54 | } |
andrewboyson | 47:73af5c0b0dc2 | 55 | } |
andrewboyson | 41:db727df5f98b | 56 | int DnsGetNextProtocol4(int protocol) |
andrewboyson | 32:679654f2d023 | 57 | { |
andrewboyson | 32:679654f2d023 | 58 | switch(protocol) |
andrewboyson | 32:679654f2d023 | 59 | { |
andrewboyson | 32:679654f2d023 | 60 | case DNS_PROTOCOL_NONE: return DNS_PROTOCOL_UDNS; |
andrewboyson | 32:679654f2d023 | 61 | case DNS_PROTOCOL_UDNS: return DNS_PROTOCOL_MDNS; |
andrewboyson | 32:679654f2d023 | 62 | case DNS_PROTOCOL_MDNS: return DNS_PROTOCOL_LLMNR; |
andrewboyson | 32:679654f2d023 | 63 | case DNS_PROTOCOL_LLMNR: return DNS_PROTOCOL_NONE; |
andrewboyson | 32:679654f2d023 | 64 | default: LogTimeF("DNS invalid protocol %d\r\n", protocol); return DNS_PROTOCOL_NONE; |
andrewboyson | 32:679654f2d023 | 65 | } |
andrewboyson | 32:679654f2d023 | 66 | } |
andrewboyson | 41:db727df5f98b | 67 | int DnsGetNextProtocol6(int protocol) |
andrewboyson | 41:db727df5f98b | 68 | { |
andrewboyson | 41:db727df5f98b | 69 | switch(protocol) |
andrewboyson | 41:db727df5f98b | 70 | { |
andrewboyson | 41:db727df5f98b | 71 | case DNS_PROTOCOL_NONE: return DNS_PROTOCOL_MDNS; |
andrewboyson | 41:db727df5f98b | 72 | case DNS_PROTOCOL_MDNS: return DNS_PROTOCOL_LLMNR; |
andrewboyson | 41:db727df5f98b | 73 | case DNS_PROTOCOL_LLMNR: return DNS_PROTOCOL_UDNS; |
andrewboyson | 41:db727df5f98b | 74 | case DNS_PROTOCOL_UDNS: return DNS_PROTOCOL_NONE; |
andrewboyson | 41:db727df5f98b | 75 | default: LogTimeF("DNS invalid protocol %d\r\n", protocol); return DNS_PROTOCOL_NONE; |
andrewboyson | 41:db727df5f98b | 76 | } |
andrewboyson | 41:db727df5f98b | 77 | } |
andrewboyson | 33:714a0345e59b | 78 | bool DnsHostNamesEquate(char* pA, char* pB) |
andrewboyson | 33:714a0345e59b | 79 | { |
andrewboyson | 33:714a0345e59b | 80 | while(true) |
andrewboyson | 33:714a0345e59b | 81 | { |
andrewboyson | 33:714a0345e59b | 82 | char a = *pA++; |
andrewboyson | 33:714a0345e59b | 83 | char b = *pB++; |
andrewboyson | 33:714a0345e59b | 84 | if (a >= 'A' && a <= 'Z') a |= 0x20; //Make lower case |
andrewboyson | 33:714a0345e59b | 85 | if (b >= 'A' && b <= 'Z') b |= 0x20; //Make lower case |
andrewboyson | 33:714a0345e59b | 86 | if (a != b) return false; //If different then stop and return the fact |
andrewboyson | 33:714a0345e59b | 87 | if (!a) break; //No need to check 'b' too as it will necessarily be equal to 'a' at this point. |
andrewboyson | 33:714a0345e59b | 88 | } |
andrewboyson | 33:714a0345e59b | 89 | return true; //If we get here the strings must equate. |
andrewboyson | 33:714a0345e59b | 90 | } |
andrewboyson | 33:714a0345e59b | 91 | |
andrewboyson | 59:e0e556c8bd46 | 92 | int DnsMakeFullNameFromName(int protocol, const char* p, int size, char* result) |
andrewboyson | 32:679654f2d023 | 93 | { |
andrewboyson | 32:679654f2d023 | 94 | int i = 0; |
andrewboyson | 32:679654f2d023 | 95 | char c; |
andrewboyson | 32:679654f2d023 | 96 | |
andrewboyson | 32:679654f2d023 | 97 | while (i < size - 1) |
andrewboyson | 32:679654f2d023 | 98 | { |
andrewboyson | 32:679654f2d023 | 99 | c = *p++; |
andrewboyson | 32:679654f2d023 | 100 | if (!c) break; |
andrewboyson | 32:679654f2d023 | 101 | *result++ = c; |
andrewboyson | 32:679654f2d023 | 102 | i++; |
andrewboyson | 32:679654f2d023 | 103 | } |
andrewboyson | 32:679654f2d023 | 104 | if (protocol == DNS_PROTOCOL_MDNS) |
andrewboyson | 32:679654f2d023 | 105 | { |
andrewboyson | 32:679654f2d023 | 106 | p = ".local"; |
andrewboyson | 32:679654f2d023 | 107 | while (i < size - 1) |
andrewboyson | 32:679654f2d023 | 108 | { |
andrewboyson | 32:679654f2d023 | 109 | c = *p++; |
andrewboyson | 32:679654f2d023 | 110 | if (!c) break; |
andrewboyson | 32:679654f2d023 | 111 | *result++ = c; |
andrewboyson | 32:679654f2d023 | 112 | i++; |
andrewboyson | 32:679654f2d023 | 113 | } |
andrewboyson | 32:679654f2d023 | 114 | } |
andrewboyson | 32:679654f2d023 | 115 | if (protocol == DNS_PROTOCOL_UDNS && DhcpDomainName[0]) //Shouldn't do this in IPv6 as DHCP is IPv4 only |
andrewboyson | 32:679654f2d023 | 116 | { |
andrewboyson | 32:679654f2d023 | 117 | if (i < size - 1) |
andrewboyson | 32:679654f2d023 | 118 | { |
andrewboyson | 32:679654f2d023 | 119 | *result++ = '.'; |
andrewboyson | 32:679654f2d023 | 120 | i++; |
andrewboyson | 32:679654f2d023 | 121 | } |
andrewboyson | 32:679654f2d023 | 122 | p = DhcpDomainName; |
andrewboyson | 32:679654f2d023 | 123 | while (i < size - 1) |
andrewboyson | 32:679654f2d023 | 124 | { |
andrewboyson | 32:679654f2d023 | 125 | c = *p++; |
andrewboyson | 32:679654f2d023 | 126 | if (!c) break; |
andrewboyson | 32:679654f2d023 | 127 | *result++ = c; |
andrewboyson | 32:679654f2d023 | 128 | i++; |
andrewboyson | 32:679654f2d023 | 129 | } |
andrewboyson | 32:679654f2d023 | 130 | } |
andrewboyson | 32:679654f2d023 | 131 | *result = 0; //Terminate the resulting string |
andrewboyson | 32:679654f2d023 | 132 | return i; |
andrewboyson | 32:679654f2d023 | 133 | } |
andrewboyson | 32:679654f2d023 | 134 | int DnsStripNameFromFullName(int protocol, char* p, int size, char* result) |
andrewboyson | 32:679654f2d023 | 135 | { |
andrewboyson | 32:679654f2d023 | 136 | int i = 0; |
andrewboyson | 32:679654f2d023 | 137 | char c; |
andrewboyson | 32:679654f2d023 | 138 | |
andrewboyson | 32:679654f2d023 | 139 | while (i < size - 1) |
andrewboyson | 32:679654f2d023 | 140 | { |
andrewboyson | 32:679654f2d023 | 141 | c = *p++; |
andrewboyson | 32:679654f2d023 | 142 | if (c == 0) break; //End of the fqdn so stop |
andrewboyson | 32:679654f2d023 | 143 | if (c == '.') |
andrewboyson | 32:679654f2d023 | 144 | { |
andrewboyson | 32:679654f2d023 | 145 | if (protocol == DNS_PROTOCOL_UDNS) |
andrewboyson | 32:679654f2d023 | 146 | { |
andrewboyson | 32:679654f2d023 | 147 | if (strcmp(p, DhcpDomainName) == 0) break; //Strip the domain from a UDNS fqdn if, and only if, it matches the domain given in DHCP. IPv4 only. |
andrewboyson | 32:679654f2d023 | 148 | } |
andrewboyson | 32:679654f2d023 | 149 | else |
andrewboyson | 32:679654f2d023 | 150 | { |
andrewboyson | 32:679654f2d023 | 151 | break; //Strip the domain from an LLMNR (there shouldn't be one) or MDNS (it should always be '.local') fqdn |
andrewboyson | 32:679654f2d023 | 152 | } |
andrewboyson | 32:679654f2d023 | 153 | } |
andrewboyson | 32:679654f2d023 | 154 | *result++ = c; |
andrewboyson | 32:679654f2d023 | 155 | i++; |
andrewboyson | 32:679654f2d023 | 156 | } |
andrewboyson | 32:679654f2d023 | 157 | *result = 0; //Terminate the copied string |
andrewboyson | 32:679654f2d023 | 158 | return i; |
andrewboyson | 32:679654f2d023 | 159 | } |
andrewboyson | 13:9cd54f7db57a | 160 | |
andrewboyson | 43:bc028d5a6424 | 161 | void DnsMain() |
andrewboyson | 13:9cd54f7db57a | 162 | { |
andrewboyson | 43:bc028d5a6424 | 163 | DnsQueryMain(); |
andrewboyson | 13:9cd54f7db57a | 164 | } |
andrewboyson | 13:9cd54f7db57a | 165 | |
andrewboyson | 59:e0e556c8bd46 | 166 | int DnsHandlePacketReceived(void (*traceback)(void), int dnsProtocol, int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx) |
andrewboyson | 13:9cd54f7db57a | 167 | { |
andrewboyson | 59:e0e556c8bd46 | 168 | DnsHdrSetup(pPacketRx, sizeRx); |
andrewboyson | 13:9cd54f7db57a | 169 | DnsHdrRead(); |
andrewboyson | 59:e0e556c8bd46 | 170 | |
andrewboyson | 13:9cd54f7db57a | 171 | int action; |
andrewboyson | 13:9cd54f7db57a | 172 | if (DnsHdrIsReply) |
andrewboyson | 13:9cd54f7db57a | 173 | { |
andrewboyson | 59:e0e556c8bd46 | 174 | action = DnsReplyHandle(traceback, dnsProtocol); |
andrewboyson | 13:9cd54f7db57a | 175 | } |
andrewboyson | 13:9cd54f7db57a | 176 | else |
andrewboyson | 13:9cd54f7db57a | 177 | { |
andrewboyson | 59:e0e556c8bd46 | 178 | action = DnsServerHandleQuery(traceback, dnsProtocol, pPacketTx, pSizeTx); |
andrewboyson | 13:9cd54f7db57a | 179 | } |
andrewboyson | 13:9cd54f7db57a | 180 | return action; |
andrewboyson | 13:9cd54f7db57a | 181 | } |
andrewboyson | 13:9cd54f7db57a | 182 | |
andrewboyson | 59:e0e556c8bd46 | 183 | int DnsPollForPacketToSend(void* pPacketTx, int* pSize) |
andrewboyson | 13:9cd54f7db57a | 184 | { |
andrewboyson | 59:e0e556c8bd46 | 185 | return DnsQueryPoll(pPacketTx, pSize); |
andrewboyson | 13:9cd54f7db57a | 186 | } |