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
- Committer:
- andrewboyson
- Date:
- 2017-10-22
- Revision:
- 44:83ce5ace337b
- Parent:
- 43:bc028d5a6424
- Child:
- 47:73af5c0b0dc2
File content as of revision 44:83ce5ace337b:
#include "mbed.h" #include "dns.h" #include "net.h" #include "log.h" #include "net.h" #include "eth.h" #include "ip4.h" #include "ip6.h" #include "udp.h" #include "dnsname.h" #define HEADER_LENGTH 12 __packed struct header { uint16_t id; uint8_t uflags; uint8_t lflags; uint16_t qdcount; uint16_t ancount; uint16_t nscount; uint16_t arcount; }; uint16_t DnsHdrId; bool DnsHdrIsReply; bool DnsHdrIsAuthoritative; bool DnsHdrIsRecursiveQuery; uint16_t DnsHdrQdcount; uint16_t DnsHdrAncount; uint16_t DnsHdrNscount; uint16_t DnsHdrArcount; char* DnsHdrPacket; char* DnsHdrData; void DnsHdrSetup(void* pPacket) { DnsHdrPacket = (char*)pPacket; DnsHdrData = DnsHdrPacket + HEADER_LENGTH; } void DnsHdrRead() { struct header* pHeader = (header*)DnsHdrPacket; DnsHdrId = NetToHost16(pHeader->id); uint8_t uflags = pHeader->uflags; DnsHdrIsReply = uflags & 0x80; DnsHdrIsAuthoritative = uflags & 0x04; DnsHdrIsRecursiveQuery = uflags & 0x01; DnsHdrQdcount = NetToHost16(pHeader->qdcount); DnsHdrAncount = NetToHost16(pHeader->ancount); DnsHdrNscount = NetToHost16(pHeader->nscount); DnsHdrArcount = NetToHost16(pHeader->arcount); } void DnsHdrWrite() { struct header* pHeader = (header*)DnsHdrPacket; pHeader->id = NetToHost16(DnsHdrId); uint8_t uflags = 0; uint8_t lflags = 0; if (DnsHdrIsReply) uflags |= 0x80; if (DnsHdrIsAuthoritative) uflags |= 0x04; if (DnsHdrIsRecursiveQuery) uflags |= 0x01; pHeader->uflags = uflags; pHeader->lflags = lflags; pHeader->qdcount = NetToHost16(DnsHdrQdcount); pHeader->ancount = NetToHost16(DnsHdrAncount); pHeader->nscount = NetToHost16(DnsHdrNscount); pHeader->arcount = NetToHost16(DnsHdrArcount); } static void logContent() { char* p = DnsHdrData; //Local version of p which does not upset the global p used to build the response char iEncodedName; //Get the questions for (int q = 0; q < DnsHdrQdcount; q++) { if (p > DnsHdrData + 500) { Log("Questions have overrun the buffer\r\n"); return; } iEncodedName = DnsNameIndexFromPointer(p); int nameLength = DnsNameLength(p); if (!nameLength) { LogTimeF("DnsServer-readQuestions namelength is zero\r\n"); return; } p += nameLength; //Skip past the name p++ ; //skip the first byte of the type char recordType = *p++; //read the record type p += 2; //skip the class char text[256]; DnsRecordTypeToString(recordType, sizeof(text), text); LogF(" Query %s type record of ", text); DnsNameDecodePtr(iEncodedName, sizeof(text), text); LogF("%s\r\n", text); } //Get the answers for (int a = 0; a < DnsHdrAncount; a++) { if (p > DnsHdrData + 500) { Log(" Answers have overrun the buffer\r\n"); return; } iEncodedName = DnsNameIndexFromPointer(p); int nameLength = DnsNameLength(p); if (!nameLength) { Log(" Answer name length is zero\r\n"); return; } p += nameLength; //Skip past the name p++; //Skip the high byte of the record type int recordType = *p++; //Record type p++; //Skip the high byte of the class type int classType = *p++; //Class type int ttl = *p++; //32bit TTL ttl <<= 8; ttl += *p++; ttl <<= 8; ttl += *p++; ttl <<= 8; ttl += *p++; int len = *p++; //16bit length len <<= 8; len += *p++; char text[256]; DnsRecordTypeToString(recordType, sizeof(text), text); Log(" Answer "); Log(text); Log(" type record of "); DnsNameDecodePtr(iEncodedName, sizeof(text), text); Log(text); Log(" ==> "); switch (recordType) //Log the payload if its type is known { case DNS_RECORD_A: if (len == 4) { Ip4AddressToString(*(uint32_t*)p, sizeof(text), text); Log(text); } else { LogF("expected 4 bytes but had %d", len); } break; case DNS_RECORD_AAAA: if (len == 16) { Ip6AddressToString(p, sizeof(text), text); Log(text); } else { LogF("expected 16 bytes but had %d", len); } break; case DNS_RECORD_PTR: if (len <= DNS_MAX_LABEL_LENGTH) { iEncodedName = DnsNameIndexFromPointer(p); DnsNameDecodePtr(iEncodedName, sizeof(text), text); Log(text); } else { LogF("length %d is greater than max DNS label length of %d\r\n", len, DNS_MAX_LABEL_LENGTH); } break; case DNS_RECORD_TXT: case DNS_RECORD_SRV: LogF("'%.*s'", len, p); break; default: LogF(" %d characters", len); break; } Log("\r\n"); p += len; //Adjust the pointer to the next character after the payload } } void DnsHdrLog(int protocol) { char text[100]; if (NetTraceVerbose) { DnsProtocolToString(protocol, sizeof(text), text); LogF("%s header\r\n", text); LogF(" Ident %hd\r\n", DnsHdrId); if (DnsHdrIsReply) { if (DnsHdrIsAuthoritative) LogF(" Authoritative reply\r\n"); else LogF(" Non authoritative reply\r\n"); } else { if (DnsHdrIsRecursiveQuery) LogF(" Recursive query\r\n"); else LogF(" Non recursive query\r\n"); } LogF(" qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount); } else { DnsProtocolToString(protocol, sizeof(text), text); LogF("%-5s header qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", text, DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount); } logContent(); }