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.c

Committer:
andrewboyson
Date:
2019-03-20
Revision:
132:db2174b36a6d
Parent:
128:79052cb4a41c
Child:
133:a37eb35a03f1

File content as of revision 132:db2174b36a6d:

#include <stdint.h>
#include <stdbool.h>

#include     "log.h"
#include "mstimer.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"
#include "dnslabel.h"

bool DnsQueryTrace = false;

#define TIME_OUT_SENT_MS 3000

#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 startedMs = 0;
static void reap()
{
    if (!DnsQueryIsBusy) return;
    
    if (MsTimerInterval(startedMs, TIME_OUT_SENT_MS))
    {
        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;
        startedMs          = MsTimerCount;
        DnsQueryProtocol   = DNS_PROTOCOL_NONE;
        DnsQueryRecordType = DNS_RECORD_NONE;
    }
}
void DnsQueryMain()
{
    reap();
}
void DnsQueryIp4FromName(char * name, int protocol)
{
    DnsLabelMakeFullNameFromName(protocol, name, sizeof(DnsQueryName), DnsQueryName);
    DnsQueryIp4        = 0;
    DnsQueryIp6[0]     = 0;
    DnsQueryIsBusy     = true;
    startedMs          = MsTimerCount;
    DnsQueryProtocol   = protocol;
    DnsQueryRecordType = DNS_RECORD_A;
}
void DnsQueryIp6FromName(char * name, int protocol)
{
    DnsLabelMakeFullNameFromName(protocol, name, sizeof(DnsQueryName), DnsQueryName);
    DnsQueryIp4        = 0;
    DnsQueryIp6[0]     = 0;
    DnsQueryIsBusy     = true;
    startedMs          = MsTimerCount;
    DnsQueryProtocol   = protocol;
    DnsQueryRecordType = DNS_RECORD_AAAA;
}
void DnsQueryNameFromIp4(uint32_t ip, int protocol)
{
    DnsQueryName[0]    = 0;
    DnsQueryIp4        = ip;
    DnsQueryIp6[0]     = 0;
    DnsQueryIsBusy     = true;
    startedMs          = MsTimerCount;
    DnsQueryProtocol   = protocol;
    DnsQueryRecordType = DNS_RECORD_PTR;
}
void DnsQueryNameFromIp6(char* ip, int protocol)
{
    DnsQueryName[0]    = 0;
    DnsQueryIp4        = 0;
    Ip6AddressCopy(DnsQueryIp6, ip);
    DnsQueryIsBusy     = true;
    startedMs          = MsTimerCount;
    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());
}