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:
65:37acccf2752f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/dns/dnsquery.c	Thu Jan 11 17:38:21 2018 +0000
@@ -0,0 +1,182 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include     "log.h"
+#include   "clock.h"
+#include     "net.h"
+#include  "action.h"
+#include "ip4addr.h"
+#include "ip6addr.h"
+#include    "dhcp.h"
+#include     "dns.h"
+#include     "udp.h"
+#include   "slaac.h"
+#include  "dnshdr.h"
+#include "dnsname.h"
+
+bool DnsQueryTrace = false;
+
+#define TIME_OUT_SENT 3
+
+#define MDNS_UNICAST false
+
+char     DnsQueryName[DNS_MAX_LABEL_LENGTH+1];
+uint32_t DnsQueryIp4 = 0;
+char     DnsQueryIp6[16];
+
+char     DnsQueryRecordType = DNS_RECORD_NONE;
+int      DnsQueryProtocol   = DNS_PROTOCOL_NONE;
+bool     DnsQueryIsBusy     = false;
+
+static uint32_t started = 0;
+static uint32_t elapsed = 0;
+static void reap()
+{
+    if (!DnsQueryIsBusy) return;
+    
+    if (elapsed - started >= TIME_OUT_SENT)
+    {
+        LogTimeF("DNS reaped ongoing request for ");
+        if (DnsQueryName[0]) LogF("name %s", DnsQueryName);
+        if (DnsQueryIp4)
+        {
+            Log("ip4 "); Ip4AddressLog(DnsQueryIp4);
+        }
+        if (DnsQueryIp6[0])
+        {
+            Log("ip6 "); Ip6AddressLog(DnsQueryIp6);
+        }
+        LogF("\r\n");
+        
+        DnsQueryName[0]    = 0;
+        DnsQueryIp4        = 0;
+        DnsQueryIp6[0]     = 0;
+        DnsQueryIsBusy     = false;
+        started            = 0;
+        DnsQueryProtocol   = DNS_PROTOCOL_NONE;
+        DnsQueryRecordType = DNS_RECORD_NONE;
+    }
+}
+void DnsQueryMain()
+{
+    if (ClockTicked)
+    {
+        elapsed++;
+        reap();
+    }
+}
+void DnsQueryIp4FromName(char * name, int protocol)
+{
+    DnsMakeFullNameFromName(protocol, name, sizeof(DnsQueryName), DnsQueryName);
+    DnsQueryIp4        = 0;
+    DnsQueryIp6[0]     = 0;
+    DnsQueryIsBusy     = true;
+    started            = elapsed;
+    DnsQueryProtocol   = protocol;
+    DnsQueryRecordType = DNS_RECORD_A;
+}
+void DnsQueryIp6FromName(char * name, int protocol)
+{
+    DnsMakeFullNameFromName(protocol, name, sizeof(DnsQueryName), DnsQueryName);
+    DnsQueryIp4        = 0;
+    DnsQueryIp6[0]     = 0;
+    DnsQueryIsBusy     = true;
+    started            = elapsed;
+    DnsQueryProtocol   = protocol;
+    DnsQueryRecordType = DNS_RECORD_AAAA;
+}
+void DnsQueryNameFromIp4(uint32_t ip, int protocol)
+{
+    DnsQueryName[0]    = 0;
+    DnsQueryIp4        = ip;
+    DnsQueryIp6[0]     = 0;
+    DnsQueryIsBusy     = true;
+    started            = elapsed;
+    DnsQueryProtocol   = protocol;
+    DnsQueryRecordType = DNS_RECORD_PTR;
+}
+void DnsQueryNameFromIp6(char* ip, int protocol)
+{
+    DnsQueryName[0]    = 0;
+    DnsQueryIp4        = 0;
+    Ip6AddressCopy(DnsQueryIp6, ip);
+    DnsQueryIsBusy     = true;
+    started            = elapsed;
+    DnsQueryProtocol   = protocol;
+    DnsQueryRecordType = DNS_RECORD_PTR;
+}
+static void logQuery()
+{
+    if (NetTraceNewLine) Log("\r\n");
+    LogTimeF("DnsQuery sent ");
+    DnsProtocolLog(DnsQueryProtocol);
+    Log(" request for ");
+    DnsRecordTypeLog(DnsQueryRecordType);
+    Log(" ");
+    if (DnsQueryIp4) //Reverse
+    {
+        Ip4AddressLog(DnsQueryIp4);
+    }
+    else if (DnsQueryIp6[0])
+    {
+        Ip6AddressLog(DnsQueryIp6);
+    }
+    else //Forward
+    {
+        Log(DnsQueryName);
+    }
+    Log("\r\n");
+}
+int DnsQueryPoll(void* pPacket, int* pSize)
+{   
+    DnsHdrSetup(pPacket, *pSize);
+
+    if (!DnsQueryIsBusy)                                           return DO_NOTHING;
+    if (DnsQueryProtocol == DNS_PROTOCOL_UDNS && DhcpLocalIp == 0) return DO_NOTHING;
+    
+    NetTraceHostCheckIp6(DnsQueryIp6);
+    
+    if (DnsQueryTrace || NetTraceHostGetMatched()) logQuery();
+    
+    static uint16_t id = 0;
+    DnsHdrId = ++id;
+    DnsHdrIsReply          = false;
+    DnsHdrIsRecursiveQuery = false;
+    
+    DnsHdrQdcount = 1;
+    DnsHdrAncount = 0;
+    DnsHdrNscount = 0;
+    DnsHdrArcount = 0;    
+
+    DnsHdrWrite();
+    char* p = DnsHdrData;
+    
+    if      (DnsQueryIp4   ) DnsNameEncodeIp4(DnsQueryIp4,  &p);
+    else if (DnsQueryIp6[0]) DnsNameEncodeIp6(DnsQueryIp6,  &p);
+    else                     DnsNameEncodePtr(DnsQueryName, &p);
+    
+    *p++ = 0;
+    *p++ = DnsQueryRecordType;
+    *p++ = DnsQueryProtocol == DNS_PROTOCOL_MDNS && MDNS_UNICAST ? 0x80 : 0; //Set the 15th bit (UNICAST_RESPONSE) to 1 if MDNS
+    *p++ = 1;  //QCLASS_IN = 1 - internet
+    
+    *pSize = p - DnsHdrPacket;
+    
+    DnsQueryIsBusy = false;
+    
+    if (DnsQueryTrace || NetTraceHostGetMatched()) DnsHdrLog(DnsQueryProtocol);
+
+    int dest = DO_NOTHING;
+
+    switch (DnsQueryProtocol)
+    {
+        case DNS_PROTOCOL_UDNS:  dest =   UNICAST_DNS;   break;   //IPv6 ==> NdpDnsServer; IPv4 ==> DhcpDnsServer
+        case DNS_PROTOCOL_MDNS:  dest = MULTICAST_MDNS;  break;
+        case DNS_PROTOCOL_LLMNR: dest = MULTICAST_LLMNR; break;
+        default:
+            LogTimeF("DNS unknown query protocol %d\r\n", DnsQueryProtocol);
+            return DO_NOTHING;
+    }
+    
+    return ActionMakeFromDestAndTrace(dest, DnsQueryTrace || NetTraceHostGetMatched());
+}