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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dnsquery.c Source File

dnsquery.c

00001 #include <stdint.h>
00002 #include <stdbool.h>
00003 
00004 #include     "log.h"
00005 #include "mstimer.h"
00006 #include     "net.h"
00007 #include  "action.h"
00008 #include "ip4addr.h"
00009 #include "ip6addr.h"
00010 #include    "dhcp.h"
00011 #include     "dns.h"
00012 #include     "udp.h"
00013 #include     "eth.h"
00014 #include   "slaac.h"
00015 #include  "dnshdr.h"
00016 #include "dnsname.h"
00017 #include "dnslabel.h"
00018 #include "ar6.h"
00019 #include "ndp.h"
00020 #include "mac.h"
00021 
00022 bool DnsQueryTrace = false;
00023 
00024 #define TIME_OUT_SENT_MS 3000
00025 
00026 #define MDNS_UNICAST false
00027 
00028 char     DnsQueryName[DNS_MAX_LABEL_LENGTH+1];
00029 uint32_t DnsQueryIp4 = 0;
00030 char     DnsQueryIp6[16];
00031 bool     DnsQueryIsBusy     = false;
00032 
00033 static char     _RecordType  = DNS_RECORD_NONE;
00034 static int      _DnsProtocol = DNS_PROTOCOL_NONE;
00035 static int      _IpProtocol  = 0;
00036 static uint32_t _StartedMs   = 0;
00037 
00038 static void reap()
00039 {
00040     if (!DnsQueryIsBusy) return;
00041     
00042     if (MsTimerRelative(_StartedMs, TIME_OUT_SENT_MS))
00043     {
00044         LogTimeF("DnsQuery reaped ongoing request for record type ");
00045         DnsRecordTypeLog(_RecordType);
00046         if (DnsQueryName[0]) { LogF(" name '%s'", DnsQueryName); }
00047         if (DnsQueryIp4)     { Log(" address "); Ip4AddrLog(DnsQueryIp4); }
00048         if (DnsQueryIp6[0])  { Log(" address "); Ip6AddrLog(DnsQueryIp6); }
00049         Log(" using ");
00050         DnsProtocolLog(_DnsProtocol);
00051         Log(" over ");
00052         EthProtocolLog(_IpProtocol);
00053         LogF("\r\n");
00054         
00055         DnsQueryName[0]    = 0;
00056         DnsQueryIp4        = 0;
00057         DnsQueryIp6[0]     = 0;
00058         DnsQueryIsBusy     = false;
00059         _StartedMs         = MsTimerCount;
00060         _DnsProtocol       = DNS_PROTOCOL_NONE;
00061         _IpProtocol        = 0;
00062         _RecordType        = DNS_RECORD_NONE;
00063     }
00064 }
00065 void DnsQueryMain()
00066 {
00067     reap();
00068 }
00069 void DnsQueryIp4FromName(char * name, int dnsProtocol, int ipProtocol)
00070 {
00071     if (!name[0])
00072     {
00073         LogTime("DnsQueryIp4FromName called with no name\r\n");
00074         return;
00075     }
00076     DnsLabelMakeFullNameFromName(dnsProtocol, name, sizeof(DnsQueryName), DnsQueryName);
00077     DnsQueryIp4     = 0;
00078     DnsQueryIp6[0]  = 0;
00079     DnsQueryIsBusy  = true;
00080     _StartedMs      = MsTimerCount;
00081     _DnsProtocol    = dnsProtocol;
00082     _IpProtocol     = ipProtocol;
00083     _RecordType     = DNS_RECORD_A;
00084 }
00085 void DnsQueryIp6FromName(char * name, int dnsProtocol, int ipProtocol)
00086 {
00087     if (!name[0])
00088     {
00089         LogTime("DnsQueryIp6FromName called with no name\r\n");
00090         return;
00091     }
00092     DnsLabelMakeFullNameFromName(dnsProtocol, name, sizeof(DnsQueryName), DnsQueryName);
00093     DnsQueryIp4     = 0;
00094     DnsQueryIp6[0]  = 0;
00095     DnsQueryIsBusy  = true;
00096     _StartedMs      = MsTimerCount;
00097     _DnsProtocol    = dnsProtocol;
00098     _IpProtocol     = ipProtocol;
00099     _RecordType     = DNS_RECORD_AAAA;
00100 }
00101 void DnsQueryNameFromIp4(uint32_t ip, int dnsProtocol, int ipProtocol)
00102 {
00103     if (!ip)
00104     {
00105         LogTime("DnsQueryNameFromIp4 called with no ip\r\n");
00106         return;
00107     }
00108     DnsQueryName[0] = 0;
00109     DnsQueryIp4     = ip;
00110     DnsQueryIp6[0]  = 0;
00111     DnsQueryIsBusy  = true;
00112     _StartedMs      = MsTimerCount;
00113     _DnsProtocol    = dnsProtocol;
00114     _IpProtocol     = ipProtocol;
00115     _RecordType     = DNS_RECORD_PTR;
00116 }
00117 void DnsQueryNameFromIp6(char* ip, int dnsProtocol, int ipProtocol)
00118 {
00119     if (!ip[0])
00120     {
00121         LogTime("DnsQueryNameFromIp6 called with no ip\r\n");
00122         return;
00123     }
00124     DnsQueryName[0] = 0;
00125     DnsQueryIp4     = 0;
00126     Ip6AddrCopy(DnsQueryIp6, ip);
00127     DnsQueryIsBusy  = true;
00128     _StartedMs      = MsTimerCount;
00129     _DnsProtocol    = dnsProtocol;
00130     _IpProtocol     = ipProtocol;
00131     _RecordType     = DNS_RECORD_PTR;
00132 }
00133 static void logQuery()
00134 {
00135     if (NetTraceNewLine) Log("\r\n");
00136     LogTimeF("DnsQuery sent ");
00137     DnsProtocolLog(_DnsProtocol);
00138     Log(" request for ");
00139     DnsRecordTypeLog(_RecordType);
00140     Log(" ");
00141     if (DnsQueryIp4) //Reverse
00142     {
00143         Ip4AddrLog(DnsQueryIp4);
00144     }
00145     else if (DnsQueryIp6[0])
00146     {
00147         Ip6AddrLog(DnsQueryIp6);
00148     }
00149     else //Forward
00150     {
00151         Log(DnsQueryName);
00152     }
00153     Log("\r\n");
00154 }
00155 int DnsQueryPoll(int ipType, void* pPacket, int* pSize)
00156 {   
00157     DnsHdrSetup(pPacket, *pSize);
00158 
00159     if (!DnsQueryIsBusy)                                       return DO_NOTHING;
00160     if (_IpProtocol  != EthProtocol)                           return DO_NOTHING; //Only use a poll from the required protocol
00161     if (_DnsProtocol == DNS_PROTOCOL_UDNS && DhcpLocalIp == 0) return DO_NOTHING;
00162     if (_RecordType  == DNS_RECORD_NONE)                       return DO_NOTHING;
00163     if (_DnsProtocol == DNS_PROTOCOL_NONE)                     return DO_NOTHING;
00164     
00165     
00166     //For IPv6 UDNS check if have the MAC for the DNS server and, if not, request it and stop
00167     if (_IpProtocol == ETH_IPV6 && _DnsProtocol == DNS_PROTOCOL_UDNS)
00168     {
00169         if (!Ar6CheckHaveMacAndFetchIfNot(NdpDnsServer)) return DO_NOTHING;
00170     }
00171     
00172     NetTraceHostCheckIp6(DnsQueryIp6);
00173     
00174     if (DnsQueryTrace || NetTraceHostGetMatched()) logQuery();
00175     
00176     static uint16_t id = 0;
00177     DnsHdrId = ++id;
00178     DnsHdrIsReply          = false;
00179     DnsHdrIsAuthoritative  = false; //Added 12/12/2020
00180     DnsHdrIsRecursiveQuery = false;
00181     
00182     DnsHdrQdcount = 1;
00183     DnsHdrAncount = 0;
00184     DnsHdrNscount = 0;
00185     DnsHdrArcount = 0;    
00186 
00187     DnsHdrWrite();
00188     char* p = DnsHdrData;
00189     
00190     if      (DnsQueryIp4    ) DnsNameEncodeIp4(DnsQueryIp4,  &p);
00191     else if (DnsQueryIp6[0] ) DnsNameEncodeIp6(DnsQueryIp6,  &p);
00192     else if (DnsQueryName[0]) DnsNameEncodePtr(DnsQueryName, &p);
00193     else return DO_NOTHING;
00194     
00195     *p++ = 0;
00196     *p++ = _RecordType;
00197     *p++ = _DnsProtocol == DNS_PROTOCOL_MDNS && MDNS_UNICAST ? 0x80 : 0; //Set the 15th bit (UNICAST_RESPONSE) to 1 if MDNS
00198     *p++ = 1;  //QCLASS_IN = 1 - internet
00199     
00200     *pSize = p - DnsHdrPacket;
00201     
00202     DnsQueryIsBusy = false;
00203     
00204     if (DnsQueryTrace || NetTraceHostGetMatched()) DnsHdrLog(_DnsProtocol);
00205 
00206     int dest = DO_NOTHING;
00207 
00208     switch (_DnsProtocol)
00209     {
00210         case DNS_PROTOCOL_UDNS:  dest =   UNICAST_DNS;   break;   //IPv6 ==> NdpDnsServer; IPv4 ==> DhcpDnsServer
00211         case DNS_PROTOCOL_MDNS:  dest = MULTICAST_MDNS;  break;
00212         case DNS_PROTOCOL_LLMNR: dest = MULTICAST_LLMNR; break;
00213         default:
00214             LogTimeF("DNS unknown query protocol %d\r\n", _DnsProtocol);
00215             return DO_NOTHING;
00216     }
00217     
00218     return ActionMakeFromDestAndTrace(dest, DnsQueryTrace || NetTraceHostGetMatched());
00219 }