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 dnsreply.c Source File

dnsreply.c

00001 #include <stdint.h>
00002 #include <stdbool.h>
00003 #include <string.h>
00004 
00005 #include    "log.h"
00006 #include    "net.h"
00007 #include "action.h"
00008 #include    "ip4.h"
00009 #include    "ip6.h"
00010 #include     "nr.h"
00011 #include    "dns.h"
00012 #include "dnshdr.h"
00013 #include "dnsname.h"
00014 #include "dnslabel.h"
00015 #include   "dhcp.h"
00016 
00017 bool DnsReplyTrace = false;
00018 
00019 char     DnsReplyRecordName[256];
00020 uint32_t DnsReplyRecordNameAsIp4 = 0;
00021 char     DnsReplyRecordNameAsIp6[16];
00022 char     DnsReplyName[64];
00023 uint32_t DnsReplyIp4 = 0;
00024 char     DnsReplyIp6[16];
00025 
00026 static char* p;
00027 static char* pRecordName;
00028 static int    recordType;
00029 static int    recordDataLength;
00030 static char* pRecordData;
00031 
00032 static int scanQuery()
00033 {
00034     int recordNameLength = DnsNameLength(p);
00035     if (!recordNameLength) return -1; //failure
00036     
00037     pRecordName = p;
00038     p += recordNameLength;
00039     
00040     p++ ; //skip the first byte of the type
00041     recordType = *p++;
00042     
00043     p += 2; //skip the class
00044     
00045     return 0; //success
00046 }
00047 
00048 static int scanAnswer()
00049 {
00050     int recordNameLength = DnsNameLength(p);
00051     if (!recordNameLength) return -1; //failure
00052     
00053     pRecordName = p;
00054     p += recordNameLength;
00055     
00056     p++ ; //skip the first byte of the type
00057     recordType = *p++;
00058     
00059     p += 6; //skip the class, TTL
00060     recordDataLength = 0;
00061     recordDataLength |= *p++ <<  8;
00062     recordDataLength |= *p++;
00063     
00064     pRecordData = p; //record the start of the data
00065     
00066     p += recordDataLength; //Move to the start of the next record
00067     
00068     return 0; //success
00069 }
00070 static void readAnswer()
00071 {
00072     DnsReplyRecordName[0]      = 0;
00073     DnsReplyRecordNameAsIp4    = 0;
00074     DnsReplyRecordNameAsIp6[0] = 0;
00075     DnsReplyName[0]            = 0;
00076     DnsReplyIp4                = 0;
00077     DnsReplyIp6[0]             = 0;
00078     
00079     switch (recordType)
00080     {
00081         case DNS_RECORD_A:
00082         case DNS_RECORD_AAAA:
00083         case DNS_RECORD_PTR:
00084         case DNS_RECORD_SRV:
00085         case DNS_RECORD_TXT:
00086             break;
00087         default:
00088             return;
00089     }
00090 
00091     DnsNameDecodePtr(pRecordName,  DnsReplyRecordName, sizeof(DnsReplyRecordName));
00092     DnsNameDecodeIp4(pRecordName, &DnsReplyRecordNameAsIp4);
00093     DnsNameDecodeIp6(pRecordName,  DnsReplyRecordNameAsIp6);
00094 
00095     switch (recordType)
00096     {
00097         case DNS_RECORD_A:
00098             if (recordDataLength != 4) return;
00099             memcpy(&DnsReplyIp4, pRecordData, 4);
00100             break;
00101         case DNS_RECORD_AAAA:
00102             if (recordDataLength != 16) return;
00103             memcpy(DnsReplyIp6, pRecordData, 16);
00104             break;
00105         case DNS_RECORD_PTR:
00106             if (recordDataLength > DNS_MAX_LABEL_LENGTH) return;
00107             DnsNameDecodePtr(pRecordData, DnsReplyName, sizeof(DnsReplyName));
00108             break;
00109     }
00110 }
00111 
00112 static void sendToDnsCache(int dnsProtocol)
00113 {
00114     char strippedName[100];
00115     if (DnsReplyRecordName[0]) DnsLabelStripNameFromFullName(dnsProtocol, DnsReplyRecordName, sizeof(strippedName), strippedName);
00116     if (DnsReplyName[0]      ) DnsLabelStripNameFromFullName(dnsProtocol, DnsReplyName      , sizeof(strippedName), strippedName);
00117     
00118     if (DnsReplyIp4                && DnsReplyRecordName[0]) NrAddAddress4(DnsReplyIp4,             strippedName, dnsProtocol);
00119     if (DnsReplyIp6[0]             && DnsReplyRecordName[0]) NrAddAddress6(DnsReplyIp6,             strippedName, dnsProtocol);
00120     if (DnsReplyRecordNameAsIp4    && DnsReplyName[0]      ) NrAddAddress4(DnsReplyRecordNameAsIp4, strippedName, dnsProtocol);
00121     if (DnsReplyRecordNameAsIp6[0] && DnsReplyName[0]      ) NrAddAddress6(DnsReplyRecordNameAsIp6, strippedName, dnsProtocol);
00122 }
00123 int DnsReplyHandle(void (*traceback)(void), int dnsProtocol)
00124 {
00125     bool ok = true;
00126     if (!DnsHdrAncount) ok = false;
00127 
00128     p = DnsHdrData;
00129     
00130     if (DnsReplyTrace || NetTraceHostGetMatched())
00131     {
00132         if (NetTraceNewLine) Log("\r\n");
00133         LogTimeF("DnsReply received\r\n");
00134         if (NetTraceStack) traceback();
00135         DnsHdrLog(dnsProtocol);
00136     }
00137 
00138     if (ok)
00139     {
00140         for (int q = 0; q < DnsHdrQdcount; q++)
00141         {
00142             if (scanQuery())
00143             {
00144                 ok = false;
00145                 break;
00146             }
00147         }
00148     }
00149     if (ok)
00150     {
00151         for (int a = 0; a < DnsHdrAncount; a++)
00152         {
00153             if (scanAnswer())
00154             {
00155                 ok = false;
00156                 break;
00157             }
00158             readAnswer();
00159             sendToDnsCache(dnsProtocol);
00160         }
00161     }
00162     
00163     NetTraceHostCheckIp6(DnsReplyIp6);
00164     NetTraceHostCheckIp6(DnsReplyRecordNameAsIp6);
00165     
00166     return DO_NOTHING;
00167 }