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/dnshdr.cpp@43:bc028d5a6424, 2017-10-19 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Oct 19 20:56:58 2017 +0000
- Revision:
- 43:bc028d5a6424
- Parent:
- 37:793b39683406
- Child:
- 44:83ce5ace337b
Added verbose option to trace
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 13:9cd54f7db57a | 1 | #include "mbed.h" |
andrewboyson | 13:9cd54f7db57a | 2 | #include "dns.h" |
andrewboyson | 13:9cd54f7db57a | 3 | #include "net.h" |
andrewboyson | 13:9cd54f7db57a | 4 | #include "log.h" |
andrewboyson | 14:e75a59c1123d | 5 | #include "net.h" |
andrewboyson | 14:e75a59c1123d | 6 | #include "eth.h" |
andrewboyson | 14:e75a59c1123d | 7 | #include "ip4.h" |
andrewboyson | 14:e75a59c1123d | 8 | #include "ip6.h" |
andrewboyson | 14:e75a59c1123d | 9 | #include "udp.h" |
andrewboyson | 37:793b39683406 | 10 | #include "dnsname.h" |
andrewboyson | 13:9cd54f7db57a | 11 | |
andrewboyson | 13:9cd54f7db57a | 12 | #define HEADER_LENGTH 12 |
andrewboyson | 13:9cd54f7db57a | 13 | |
andrewboyson | 13:9cd54f7db57a | 14 | __packed struct header |
andrewboyson | 13:9cd54f7db57a | 15 | { |
andrewboyson | 13:9cd54f7db57a | 16 | uint16_t id; |
andrewboyson | 13:9cd54f7db57a | 17 | uint8_t uflags; |
andrewboyson | 13:9cd54f7db57a | 18 | uint8_t lflags; |
andrewboyson | 13:9cd54f7db57a | 19 | |
andrewboyson | 13:9cd54f7db57a | 20 | uint16_t qdcount; |
andrewboyson | 13:9cd54f7db57a | 21 | uint16_t ancount; |
andrewboyson | 13:9cd54f7db57a | 22 | uint16_t nscount; |
andrewboyson | 13:9cd54f7db57a | 23 | uint16_t arcount; |
andrewboyson | 13:9cd54f7db57a | 24 | }; |
andrewboyson | 13:9cd54f7db57a | 25 | |
andrewboyson | 13:9cd54f7db57a | 26 | uint16_t DnsHdrId; |
andrewboyson | 13:9cd54f7db57a | 27 | |
andrewboyson | 13:9cd54f7db57a | 28 | bool DnsHdrIsReply; |
andrewboyson | 13:9cd54f7db57a | 29 | bool DnsHdrIsAuthoritative; |
andrewboyson | 13:9cd54f7db57a | 30 | bool DnsHdrIsRecursiveQuery; |
andrewboyson | 13:9cd54f7db57a | 31 | |
andrewboyson | 13:9cd54f7db57a | 32 | uint16_t DnsHdrQdcount; |
andrewboyson | 13:9cd54f7db57a | 33 | uint16_t DnsHdrAncount; |
andrewboyson | 13:9cd54f7db57a | 34 | uint16_t DnsHdrNscount; |
andrewboyson | 13:9cd54f7db57a | 35 | uint16_t DnsHdrArcount; |
andrewboyson | 13:9cd54f7db57a | 36 | |
andrewboyson | 13:9cd54f7db57a | 37 | char* DnsHdrPacket; |
andrewboyson | 13:9cd54f7db57a | 38 | char* DnsHdrData; |
andrewboyson | 13:9cd54f7db57a | 39 | |
andrewboyson | 13:9cd54f7db57a | 40 | void DnsHdrSetup(void* pPacket) |
andrewboyson | 13:9cd54f7db57a | 41 | { |
andrewboyson | 13:9cd54f7db57a | 42 | DnsHdrPacket = (char*)pPacket; |
andrewboyson | 13:9cd54f7db57a | 43 | DnsHdrData = DnsHdrPacket + HEADER_LENGTH; |
andrewboyson | 13:9cd54f7db57a | 44 | } |
andrewboyson | 13:9cd54f7db57a | 45 | |
andrewboyson | 13:9cd54f7db57a | 46 | void DnsHdrRead() |
andrewboyson | 13:9cd54f7db57a | 47 | { |
andrewboyson | 13:9cd54f7db57a | 48 | struct header* pHeader = (header*)DnsHdrPacket; |
andrewboyson | 13:9cd54f7db57a | 49 | |
andrewboyson | 13:9cd54f7db57a | 50 | DnsHdrId = NetToHost16(pHeader->id); |
andrewboyson | 13:9cd54f7db57a | 51 | |
andrewboyson | 13:9cd54f7db57a | 52 | uint8_t uflags = pHeader->uflags; |
andrewboyson | 13:9cd54f7db57a | 53 | DnsHdrIsReply = uflags & 0x80; |
andrewboyson | 13:9cd54f7db57a | 54 | DnsHdrIsAuthoritative = uflags & 0x04; |
andrewboyson | 33:714a0345e59b | 55 | DnsHdrIsRecursiveQuery = uflags & 0x01; |
andrewboyson | 13:9cd54f7db57a | 56 | |
andrewboyson | 13:9cd54f7db57a | 57 | DnsHdrQdcount = NetToHost16(pHeader->qdcount); |
andrewboyson | 13:9cd54f7db57a | 58 | DnsHdrAncount = NetToHost16(pHeader->ancount); |
andrewboyson | 13:9cd54f7db57a | 59 | DnsHdrNscount = NetToHost16(pHeader->nscount); |
andrewboyson | 13:9cd54f7db57a | 60 | DnsHdrArcount = NetToHost16(pHeader->arcount); |
andrewboyson | 13:9cd54f7db57a | 61 | |
andrewboyson | 13:9cd54f7db57a | 62 | } |
andrewboyson | 13:9cd54f7db57a | 63 | void DnsHdrWrite() |
andrewboyson | 13:9cd54f7db57a | 64 | { |
andrewboyson | 13:9cd54f7db57a | 65 | struct header* pHeader = (header*)DnsHdrPacket; |
andrewboyson | 13:9cd54f7db57a | 66 | |
andrewboyson | 13:9cd54f7db57a | 67 | pHeader->id = NetToHost16(DnsHdrId); |
andrewboyson | 13:9cd54f7db57a | 68 | |
andrewboyson | 13:9cd54f7db57a | 69 | uint8_t uflags = 0; |
andrewboyson | 13:9cd54f7db57a | 70 | uint8_t lflags = 0; |
andrewboyson | 13:9cd54f7db57a | 71 | if (DnsHdrIsReply) uflags |= 0x80; |
andrewboyson | 13:9cd54f7db57a | 72 | if (DnsHdrIsAuthoritative) uflags |= 0x04; |
andrewboyson | 13:9cd54f7db57a | 73 | if (DnsHdrIsRecursiveQuery) uflags |= 0x01; |
andrewboyson | 13:9cd54f7db57a | 74 | pHeader->uflags = uflags; |
andrewboyson | 13:9cd54f7db57a | 75 | pHeader->lflags = lflags; |
andrewboyson | 13:9cd54f7db57a | 76 | |
andrewboyson | 13:9cd54f7db57a | 77 | pHeader->qdcount = NetToHost16(DnsHdrQdcount); |
andrewboyson | 13:9cd54f7db57a | 78 | pHeader->ancount = NetToHost16(DnsHdrAncount); |
andrewboyson | 13:9cd54f7db57a | 79 | pHeader->nscount = NetToHost16(DnsHdrNscount); |
andrewboyson | 13:9cd54f7db57a | 80 | pHeader->arcount = NetToHost16(DnsHdrArcount); |
andrewboyson | 13:9cd54f7db57a | 81 | } |
andrewboyson | 37:793b39683406 | 82 | static void logContent() |
andrewboyson | 37:793b39683406 | 83 | { |
andrewboyson | 37:793b39683406 | 84 | char* p = DnsHdrData; //Local version of p which does not upset the global p used to build the response |
andrewboyson | 37:793b39683406 | 85 | |
andrewboyson | 37:793b39683406 | 86 | char iEncodedName; |
andrewboyson | 37:793b39683406 | 87 | |
andrewboyson | 37:793b39683406 | 88 | //Get the questions |
andrewboyson | 37:793b39683406 | 89 | for (int q = 0; q < DnsHdrQdcount; q++) |
andrewboyson | 37:793b39683406 | 90 | { |
andrewboyson | 37:793b39683406 | 91 | if (p > DnsHdrData + 500) |
andrewboyson | 37:793b39683406 | 92 | { |
andrewboyson | 37:793b39683406 | 93 | Log("Questions have overrun the buffer\r\n"); |
andrewboyson | 37:793b39683406 | 94 | return; |
andrewboyson | 37:793b39683406 | 95 | } |
andrewboyson | 37:793b39683406 | 96 | iEncodedName = DnsNameIndexFromPointer(p); |
andrewboyson | 37:793b39683406 | 97 | int nameLength = DnsNameLength(p); |
andrewboyson | 37:793b39683406 | 98 | if (!nameLength) { LogTimeF("DnsServer-readQuestions namelength is zero\r\n"); return; } |
andrewboyson | 37:793b39683406 | 99 | p += nameLength; //Skip past the name |
andrewboyson | 37:793b39683406 | 100 | p++ ; //skip the first byte of the type |
andrewboyson | 37:793b39683406 | 101 | char recordType = *p++; //read the record type |
andrewboyson | 37:793b39683406 | 102 | p += 2; //skip the class |
andrewboyson | 37:793b39683406 | 103 | |
andrewboyson | 37:793b39683406 | 104 | char text[256]; |
andrewboyson | 37:793b39683406 | 105 | DnsRecordTypeToString(recordType, sizeof(text), text); |
andrewboyson | 37:793b39683406 | 106 | LogF(" Query %s type record of ", text); |
andrewboyson | 37:793b39683406 | 107 | DnsNameDecodePtr(iEncodedName, sizeof(text), text); |
andrewboyson | 37:793b39683406 | 108 | LogF("%s\r\n", text); |
andrewboyson | 37:793b39683406 | 109 | } |
andrewboyson | 37:793b39683406 | 110 | |
andrewboyson | 37:793b39683406 | 111 | //Get the answers |
andrewboyson | 37:793b39683406 | 112 | for (int a = 0; a < DnsHdrAncount; a++) |
andrewboyson | 37:793b39683406 | 113 | { |
andrewboyson | 43:bc028d5a6424 | 114 | if (p > DnsHdrData + 500) { Log(" Answers have overrun the buffer\r\n"); return; } |
andrewboyson | 37:793b39683406 | 115 | |
andrewboyson | 37:793b39683406 | 116 | iEncodedName = DnsNameIndexFromPointer(p); |
andrewboyson | 37:793b39683406 | 117 | int nameLength = DnsNameLength(p); |
andrewboyson | 43:bc028d5a6424 | 118 | if (!nameLength) { Log(" Answer name length is zero\r\n"); return; } |
andrewboyson | 37:793b39683406 | 119 | p += nameLength; //Skip past the name |
andrewboyson | 37:793b39683406 | 120 | |
andrewboyson | 37:793b39683406 | 121 | p++; //Skip the high byte of the record type |
andrewboyson | 37:793b39683406 | 122 | int recordType = *p++; //Record type |
andrewboyson | 37:793b39683406 | 123 | |
andrewboyson | 37:793b39683406 | 124 | p++; //Skip the high byte of the class type |
andrewboyson | 37:793b39683406 | 125 | int classType = *p++; //Class type |
andrewboyson | 37:793b39683406 | 126 | |
andrewboyson | 37:793b39683406 | 127 | int ttl = *p++; //32bit TTL |
andrewboyson | 37:793b39683406 | 128 | ttl <<= 8; ttl += *p++; |
andrewboyson | 37:793b39683406 | 129 | ttl <<= 8; ttl += *p++; |
andrewboyson | 37:793b39683406 | 130 | ttl <<= 8; ttl += *p++; |
andrewboyson | 37:793b39683406 | 131 | |
andrewboyson | 37:793b39683406 | 132 | int len = *p++; //16bit length |
andrewboyson | 37:793b39683406 | 133 | len <<= 8; len += *p++; |
andrewboyson | 37:793b39683406 | 134 | |
andrewboyson | 37:793b39683406 | 135 | char text[256]; |
andrewboyson | 37:793b39683406 | 136 | DnsRecordTypeToString(recordType, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 137 | Log(" Answer "); |
andrewboyson | 43:bc028d5a6424 | 138 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 139 | Log(" type record of "); |
andrewboyson | 37:793b39683406 | 140 | DnsNameDecodePtr(iEncodedName, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 141 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 142 | Log(" ==> "); |
andrewboyson | 37:793b39683406 | 143 | |
andrewboyson | 37:793b39683406 | 144 | switch (recordType) //Log the payload if its type is known |
andrewboyson | 37:793b39683406 | 145 | { |
andrewboyson | 37:793b39683406 | 146 | case DNS_RECORD_A: |
andrewboyson | 43:bc028d5a6424 | 147 | if (len == 4) |
andrewboyson | 43:bc028d5a6424 | 148 | { |
andrewboyson | 43:bc028d5a6424 | 149 | Ip4AddressToString(*(uint32_t*)p, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 150 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 151 | } |
andrewboyson | 43:bc028d5a6424 | 152 | else |
andrewboyson | 43:bc028d5a6424 | 153 | { |
andrewboyson | 43:bc028d5a6424 | 154 | LogF("expected 4 bytes but had %d", len); |
andrewboyson | 43:bc028d5a6424 | 155 | } |
andrewboyson | 37:793b39683406 | 156 | break; |
andrewboyson | 37:793b39683406 | 157 | |
andrewboyson | 37:793b39683406 | 158 | case DNS_RECORD_AAAA: |
andrewboyson | 43:bc028d5a6424 | 159 | if (len == 16) |
andrewboyson | 43:bc028d5a6424 | 160 | { |
andrewboyson | 43:bc028d5a6424 | 161 | Ip6AddressToString(p, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 162 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 163 | } |
andrewboyson | 43:bc028d5a6424 | 164 | else |
andrewboyson | 43:bc028d5a6424 | 165 | { |
andrewboyson | 43:bc028d5a6424 | 166 | LogF("expected 16 bytes but had %d", len); |
andrewboyson | 43:bc028d5a6424 | 167 | } |
andrewboyson | 37:793b39683406 | 168 | break; |
andrewboyson | 37:793b39683406 | 169 | |
andrewboyson | 37:793b39683406 | 170 | case DNS_RECORD_PTR: |
andrewboyson | 43:bc028d5a6424 | 171 | if (len <= DNS_MAX_LABEL_LENGTH) |
andrewboyson | 43:bc028d5a6424 | 172 | { |
andrewboyson | 43:bc028d5a6424 | 173 | iEncodedName = DnsNameIndexFromPointer(p); |
andrewboyson | 43:bc028d5a6424 | 174 | DnsNameDecodePtr(iEncodedName, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 175 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 176 | } |
andrewboyson | 43:bc028d5a6424 | 177 | else |
andrewboyson | 43:bc028d5a6424 | 178 | { |
andrewboyson | 43:bc028d5a6424 | 179 | LogF("length %d is greater than max DNS label length of %d\r\n", len, DNS_MAX_LABEL_LENGTH); |
andrewboyson | 43:bc028d5a6424 | 180 | } |
andrewboyson | 37:793b39683406 | 181 | break; |
andrewboyson | 37:793b39683406 | 182 | |
andrewboyson | 37:793b39683406 | 183 | case DNS_RECORD_TXT: |
andrewboyson | 43:bc028d5a6424 | 184 | case DNS_RECORD_SRV: |
andrewboyson | 43:bc028d5a6424 | 185 | LogF("'%.*s'", len, p); |
andrewboyson | 43:bc028d5a6424 | 186 | break; |
andrewboyson | 43:bc028d5a6424 | 187 | |
andrewboyson | 43:bc028d5a6424 | 188 | default: |
andrewboyson | 43:bc028d5a6424 | 189 | LogF(" %d characters", len); |
andrewboyson | 37:793b39683406 | 190 | break; |
andrewboyson | 37:793b39683406 | 191 | } |
andrewboyson | 43:bc028d5a6424 | 192 | Log("\r\n"); |
andrewboyson | 37:793b39683406 | 193 | p += len; //Adjust the pointer to the next character after the payload |
andrewboyson | 37:793b39683406 | 194 | |
andrewboyson | 37:793b39683406 | 195 | } |
andrewboyson | 37:793b39683406 | 196 | } |
andrewboyson | 37:793b39683406 | 197 | |
andrewboyson | 37:793b39683406 | 198 | void DnsHdrLog(int protocol) |
andrewboyson | 13:9cd54f7db57a | 199 | { |
andrewboyson | 14:e75a59c1123d | 200 | char text[100]; |
andrewboyson | 43:bc028d5a6424 | 201 | if (NetTraceVerbose) |
andrewboyson | 15:6ca6778168b1 | 202 | { |
andrewboyson | 43:bc028d5a6424 | 203 | DnsProtocolToString(protocol, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 204 | LogF("%s header\r\n", text); |
andrewboyson | 43:bc028d5a6424 | 205 | LogF(" Ident %hd\r\n", DnsHdrId); |
andrewboyson | 43:bc028d5a6424 | 206 | if (DnsHdrIsReply) |
andrewboyson | 43:bc028d5a6424 | 207 | { |
andrewboyson | 43:bc028d5a6424 | 208 | if (DnsHdrIsAuthoritative) LogF(" Authoritative reply\r\n"); |
andrewboyson | 43:bc028d5a6424 | 209 | else LogF(" Non authoritative reply\r\n"); |
andrewboyson | 43:bc028d5a6424 | 210 | } |
andrewboyson | 43:bc028d5a6424 | 211 | else |
andrewboyson | 43:bc028d5a6424 | 212 | { |
andrewboyson | 43:bc028d5a6424 | 213 | if (DnsHdrIsRecursiveQuery) LogF(" Recursive query\r\n"); |
andrewboyson | 43:bc028d5a6424 | 214 | else LogF(" Non recursive query\r\n"); |
andrewboyson | 43:bc028d5a6424 | 215 | } |
andrewboyson | 43:bc028d5a6424 | 216 | LogF(" qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount); |
andrewboyson | 15:6ca6778168b1 | 217 | } |
andrewboyson | 15:6ca6778168b1 | 218 | else |
andrewboyson | 15:6ca6778168b1 | 219 | { |
andrewboyson | 43:bc028d5a6424 | 220 | DnsProtocolToString(protocol, sizeof(text), text); |
andrewboyson | 43:bc028d5a6424 | 221 | Log(text); |
andrewboyson | 43:bc028d5a6424 | 222 | LogF(" header qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount); |
andrewboyson | 15:6ca6778168b1 | 223 | } |
andrewboyson | 37:793b39683406 | 224 | logContent(); |
andrewboyson | 13:9cd54f7db57a | 225 | } |
andrewboyson | 13:9cd54f7db57a | 226 |