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/dnsquery.cpp

Committer:
andrewboyson
Date:
2017-08-10
Revision:
30:e34173b7585c
Parent:
22:914b970356f0
Child:
32:679654f2d023

File content as of revision 30:e34173b7585c:

#include    "mbed.h"
#include     "log.h"
#include     "net.h"
#include     "ip4.h"
#include     "ip6.h"
#include    "dhcp.h"
#include     "dns.h"
#include     "udp.h"
#include   "slaac.h"
#include  "dnshdr.h"
#include "dnsname.h"

#define DEBUG false

#define TIME_OUT_SENT 3

#define MDNS_UNICAST false

char     DnsQueryName[63];
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)
    {
        char text[100];
        LogTimeF("DNS reaped ongoing request for ");
        if (DnsQueryName[0]) LogF("name %s", DnsQueryName);
        if (DnsQueryIp4)
        {
            Ip4AddressToString(DnsQueryIp4, sizeof(text), text);
            LogF("ip4 %s", text);
        }
        if (DnsQueryIp6[0])
        {
            Ip6AddressToString(DnsQueryIp6, sizeof(text), text);
            LogF("ip6 %s", text);
        }
        LogF("\r\n");
        
        DnsQueryName[0]    = 0;
        DnsQueryIp4        = 0;
        DnsQueryIp6[0]     = 0;
        DnsQueryIsBusy     = false;
        started            = 0;
        DnsQueryProtocol   = DNS_PROTOCOL_NONE;
        DnsQueryRecordType = DNS_RECORD_NONE;
    }
}
void DnsQueryTick()
{
    elapsed++;
    reap();
}
void DnsQueryIp4FromName(char * name, int protocol)
{
    strcpy(DnsQueryName, name);
    DnsQueryIp4        = 0;
    DnsQueryIp6[0]     = 0;
    DnsQueryIsBusy     = true;
    started            = elapsed;
    DnsQueryProtocol   = protocol;
    DnsQueryRecordType = DNS_RECORD_A;
}
void DnsQueryIp6FromName(char * name, int protocol)
{
    strcpy(DnsQueryName, name);
    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;
    memcpy(DnsQueryIp6, ip, 16);
    DnsQueryIsBusy     = true;
    started            = elapsed;
    DnsQueryProtocol   = protocol;
    DnsQueryRecordType = DNS_RECORD_PTR;
}
static void logQuery()
{
    if (!DEBUG) return;
    char text[60];
    DnsProtocolToString(DnsQueryProtocol, sizeof(text), text);
    LogTimeF("%s sent request for ", text);
    DnsRecordTypeToString(DnsQueryRecordType, sizeof(text), text);
    LogF("%s ", text);
    if (DnsQueryIp4) //Reverse
    {
        Ip4AddressToString(DnsQueryIp4, sizeof(text), text);
        LogF("%s\r\n", text);
    }
    else if (DnsQueryIp6[0])
    {
        Ip6AddressToString(DnsQueryIp6, sizeof(text), text);
        LogF("%s\r\n", text);
    }
    else //Forward
    {
        LogF("%s\r\n", DnsQueryName);
    }
}
int DnsQueryPoll(int* pSize)
{   
    if (!DnsQueryIsBusy)                                           return DO_NOTHING;
    if (DnsQueryProtocol == DNS_PROTOCOL_UDNS && DhcpLocalIp == 0) return DO_NOTHING;
    
    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                     DnsNameEncode   (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;

    switch (DnsQueryProtocol)
    {
        case DNS_PROTOCOL_UDNS:  return   UNICAST_DNS;    //IPv6 ==> NdpDnsServer; IPv4 ==> DhcpDnsServer
        case DNS_PROTOCOL_MDNS:  return MULTICAST_MDNS;
        case DNS_PROTOCOL_LLMNR: return MULTICAST_LLMNR;
        default:
            LogTimeF("DNS unknown query protocol %d\r\n", DnsQueryProtocol);
            return DO_NOTHING;
    }
}