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:
128:79052cb4a41c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/dns/dnsreply.c	Thu Jan 11 17:38:21 2018 +0000
@@ -0,0 +1,169 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include    "log.h"
+#include    "net.h"
+#include "action.h"
+#include    "ip4.h"
+#include    "ip6.h"
+#include    "nr4.h"
+#include    "nr6.h"
+#include    "dns.h"
+#include "dnshdr.h"
+#include "dnsname.h"
+#include   "dhcp.h"
+
+bool DnsReplyTrace = false;
+
+char     DnsReplyRecordName[256];
+uint32_t DnsReplyRecordNameAsIp4 = 0;
+char     DnsReplyRecordNameAsIp6[16];
+char     DnsReplyName[64];
+uint32_t DnsReplyIp4 = 0;
+char     DnsReplyIp6[16];
+
+static char* p;
+static char* pRecordName;
+static int    recordType;
+static int    recordDataLength;
+static char* pRecordData;
+
+static int scanQuery()
+{
+    int recordNameLength = DnsNameLength(p);
+    if (!recordNameLength) return -1; //failure
+    
+    pRecordName = p;
+    p += recordNameLength;
+    
+    p++ ; //skip the first byte of the type
+    recordType = *p++;
+    
+    p += 2; //skip the class
+    
+    return 0; //success
+}
+
+static int scanAnswer()
+{
+    int recordNameLength = DnsNameLength(p);
+    if (!recordNameLength) return -1; //failure
+    
+    pRecordName = p;
+    p += recordNameLength;
+    
+    p++ ; //skip the first byte of the type
+    recordType = *p++;
+    
+    p += 6; //skip the class, TTL
+    recordDataLength = 0;
+    recordDataLength |= *p++ <<  8;
+    recordDataLength |= *p++;
+    
+    pRecordData = p; //record the start of the data
+    
+    p += recordDataLength; //Move to the start of the next record
+    
+    return 0; //success
+}
+static void readAnswer()
+{
+    DnsReplyRecordName[0]      = 0;
+    DnsReplyRecordNameAsIp4    = 0;
+    DnsReplyRecordNameAsIp6[0] = 0;
+    DnsReplyName[0]            = 0;
+    DnsReplyIp4                = 0;
+    DnsReplyIp6[0]             = 0;
+    
+    switch (recordType)
+    {
+        case DNS_RECORD_A:
+        case DNS_RECORD_AAAA:
+        case DNS_RECORD_PTR:
+        case DNS_RECORD_SRV:
+        case DNS_RECORD_TXT:
+            break;
+        default:
+            return;
+    }
+
+    DnsNameDecodePtr(pRecordName,  DnsReplyRecordName, sizeof(DnsReplyRecordName));
+    DnsNameDecodeIp4(pRecordName, &DnsReplyRecordNameAsIp4);
+    DnsNameDecodeIp6(pRecordName,  DnsReplyRecordNameAsIp6);
+
+    switch (recordType)
+    {
+        case DNS_RECORD_A:
+            if (recordDataLength != 4) return;
+            memcpy(&DnsReplyIp4, pRecordData, 4);
+            break;
+        case DNS_RECORD_AAAA:
+            if (recordDataLength != 16) return;
+            memcpy(DnsReplyIp6, pRecordData, 16);
+            break;
+        case DNS_RECORD_PTR:
+            if (recordDataLength > DNS_MAX_LABEL_LENGTH) return;
+            DnsNameDecodePtr(pRecordData, DnsReplyName, sizeof(DnsReplyName));
+            break;
+    }
+}
+
+static void sendToDnsCache(int dnsProtocol)
+{
+    char strippedName[100];
+    if (DnsReplyRecordName[0]) DnsStripNameFromFullName(dnsProtocol, DnsReplyRecordName, sizeof(strippedName), strippedName);
+    if (DnsReplyName[0]      ) DnsStripNameFromFullName(dnsProtocol, DnsReplyName      , sizeof(strippedName), strippedName);
+    
+    if (DnsReplyIp4                && DnsReplyRecordName[0]) Nr4AddIpRecord(DnsReplyIp4,             strippedName, dnsProtocol);
+    if (DnsReplyIp6[0]             && DnsReplyRecordName[0]) Nr6AddIpRecord(DnsReplyIp6,             strippedName, dnsProtocol);
+    if (DnsReplyRecordNameAsIp4    && DnsReplyName[0]      ) Nr4AddIpRecord(DnsReplyRecordNameAsIp4, strippedName, dnsProtocol);
+    if (DnsReplyRecordNameAsIp6[0] && DnsReplyName[0]      ) Nr6AddIpRecord(DnsReplyRecordNameAsIp6, strippedName, dnsProtocol);
+}
+int DnsReplyHandle(void (*traceback)(void), int dnsProtocol)
+{
+    
+    bool ok = true;
+    if (!DnsHdrAncount) ok = false;
+
+    p = DnsHdrData;
+
+    if (ok)
+    {
+        for (int q = 0; q < DnsHdrQdcount; q++)
+        {
+            if (scanQuery())
+            {
+                ok = false;
+                break;
+            }
+        }
+    }
+    if (ok)
+    {
+        for (int a = 0; a < DnsHdrAncount; a++)
+        {
+            if (scanAnswer())
+            {
+                ok = false;
+                break;
+            }
+            readAnswer();
+            sendToDnsCache(dnsProtocol);
+        }
+    }
+    
+    NetTraceHostCheckIp6(DnsReplyIp6);
+    NetTraceHostCheckIp6(DnsReplyRecordNameAsIp6);
+    
+    if (DnsReplyTrace || NetTraceHostGetMatched())
+    {
+        if (NetTraceNewLine) Log("\r\n");
+        LogTimeF("DnsReply received\r\n");
+        if (NetTraceStack) traceback();
+        DnsHdrLog(dnsProtocol);
+    }
+
+    
+    return DO_NOTHING;
+}