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

Revision:
61:aad055f1b0d1
Parent:
59:e0e556c8bd46
Child:
121:bc048b65a630
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/dns/dnshdr.c	Thu Jan 11 17:38:21 2018 +0000
@@ -0,0 +1,225 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include     "dns.h"
+#include     "net.h"
+#include     "log.h"
+#include     "net.h"
+#include     "eth.h"
+#include "ip4addr.h"
+#include "ip6addr.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;
+int      DnsHdrDataLength;
+
+void DnsHdrSetup(void* pPacket, int lenPacket)
+{
+    DnsHdrPacket = (char*)pPacket;
+    DnsHdrData = DnsHdrPacket + sizeof(struct header);
+    DnsHdrDataLength = lenPacket - sizeof(struct header);
+}
+
+void DnsHdrRead()
+{
+    struct header* pHeader = (struct 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 = (struct 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 uint16_t decodeUint16(char* p)
+{
+    uint16_t     value  = *p++;
+    value <<= 8; value += *p++;
+    return value;
+}
+static uint32_t decodeUint32(char* p)
+{
+    uint32_t     value  = *p++;
+    value <<= 8; value += *p++;
+    value <<= 8; value += *p++;
+    value <<= 8; value += *p++;
+    return value;
+}
+static void logRecordA(int len, char* p)
+{
+    if (len == 4) Ip4AddressLog(*(uint32_t*)p);
+    else          LogF("expected 4 bytes but had %d", len);
+}
+static void logRecordAAAA(int len, char* p)
+{
+    if (len == 16) Ip6AddressLog(p);
+    else           LogF("expected 16 bytes but had %d", len);
+}
+static void logRecordPTR(int len, char* p)
+{
+    if (len <= DNS_MAX_LABEL_LENGTH) DnsNameLogPtr(p);
+    else LogF("length %d is greater than max DNS label length of %d\r\n", len, DNS_MAX_LABEL_LENGTH);
+}
+static void logRecordSRV(int len, char* p)
+{
+    LogF("pri=%d " , decodeUint16(p)); p += 2;
+    LogF("wei=%d " , decodeUint16(p)); p += 2;
+    LogF("port=%d ", decodeUint16(p)); p += 2;
+    DnsNameLogPtr(p);
+}
+static void logRecordTXT(int len, char* p)
+{
+    char* pEnd = p + len;
+    while (p < pEnd)
+    {
+        Log("\r\n    ");
+        int fieldLen = *p++;
+        for (int i = 0; i < fieldLen; i++) LogPush(*p++);
+    }
+}
+static void logContent()
+{
+    char* p = DnsHdrData;
+    
+    //Get the questions
+    for (int q = 0; q < DnsHdrQdcount; q++)
+    {
+        if (p >= DnsHdrData + DnsHdrDataLength)
+        {
+            Log("   Questions have overrun the buffer\r\n");
+            return;
+        }
+        char* pEncodedName = p;
+        int nameLength = DnsNameLength(p);
+        if (!nameLength) { LogTimeF("   Questions 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
+
+        LogF("   Query ");
+        DnsRecordTypeLog(recordType);
+        Log(" type record of ");
+        DnsNameLogPtr(pEncodedName);
+        Log("\r\n");
+    }
+    
+    //Get the answers
+    for (int a = 0; a < DnsHdrAncount; a++)
+    {
+        if (p >= DnsHdrData + DnsHdrDataLength) { Log("  Answers have overrun the buffer\r\n"); return; }
+        
+        char* pEncodedName = 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 = decodeUint32(p); p += 4;     //32bit TTL
+        
+        int len = decodeUint16(p); p += 2;     //16bit length
+        
+        Log("  Answer ");
+        DnsRecordTypeLog(recordType);
+        Log(" type record of ");
+        DnsNameLogPtr(pEncodedName);
+        Log(" ==> ");
+        
+        switch (recordType)           //Log the payload if its type is known
+        {
+            case DNS_RECORD_A:    logRecordA   (len, p);      break;
+            case DNS_RECORD_AAAA: logRecordAAAA(len, p);      break;
+            case DNS_RECORD_PTR:  logRecordPTR (len, p);      break;
+            case DNS_RECORD_SRV:  logRecordSRV (len, p);      break;
+            case DNS_RECORD_TXT:  logRecordTXT (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)
+{
+    if (NetTraceVerbose)
+    {
+        DnsProtocolLog(protocol);
+        Log(" header\r\n");
+        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
+    {
+        DnsProtocolLog(protocol);
+        LogF(" header qd, an, ns, ar  %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount);
+    }
+    logContent();
+}
+