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

dnshdr.c

00001 #include <stdint.h>
00002 #include <stdbool.h>
00003 
00004 #include      "dns.h"
00005 #include      "net.h"
00006 #include      "log.h"
00007 #include      "net.h"
00008 #include      "eth.h"
00009 #include  "ip4addr.h"
00010 #include  "ip6addr.h"
00011 #include      "udp.h"
00012 #include  "dnsname.h"
00013 #include "dnslabel.h"
00014 
00015 #define HEADER_LENGTH 12
00016 
00017 uint16_t DnsHdrId;
00018 
00019 bool     DnsHdrIsReply;
00020 bool     DnsHdrIsAuthoritative;
00021 bool     DnsHdrIsRecursiveQuery;
00022 
00023 uint16_t DnsHdrQdcount;
00024 uint16_t DnsHdrAncount;
00025 uint16_t DnsHdrNscount;
00026 uint16_t DnsHdrArcount;
00027 
00028 char*    DnsHdrPacket;
00029 char*    DnsHdrData;
00030 int      DnsHdrDataLength;
00031 
00032 void DnsHdrSetup(void* pPacket, int lenPacket)
00033 {
00034     DnsHdrPacket = (char*)pPacket;
00035     DnsHdrData    = DnsHdrPacket + HEADER_LENGTH;
00036     DnsHdrDataLength = lenPacket - HEADER_LENGTH;
00037 }
00038 
00039 void DnsHdrRead()
00040 {
00041     NetInvert16(&DnsHdrId, DnsHdrPacket + 0);
00042     
00043     uint8_t uflags = *(DnsHdrPacket + 2);
00044     DnsHdrIsReply          = uflags & 0x80;
00045     DnsHdrIsAuthoritative  = uflags & 0x04;
00046     DnsHdrIsRecursiveQuery = uflags & 0x01;
00047     
00048     NetInvert16(&DnsHdrQdcount, DnsHdrPacket +  4);
00049     NetInvert16(&DnsHdrAncount, DnsHdrPacket +  6);
00050     NetInvert16(&DnsHdrNscount, DnsHdrPacket +  8);
00051     NetInvert16(&DnsHdrArcount, DnsHdrPacket + 10);
00052 }
00053 void DnsHdrWrite()
00054 {
00055     NetInvert16(DnsHdrPacket + 0, &DnsHdrId);
00056     
00057     uint8_t uflags = 0;
00058     uint8_t lflags = 0;
00059     if (DnsHdrIsReply)          uflags |= 0x80;
00060     if (DnsHdrIsAuthoritative)  uflags |= 0x04;
00061     if (DnsHdrIsRecursiveQuery) uflags |= 0x01;
00062     *(DnsHdrPacket + 2) = uflags;
00063     *(DnsHdrPacket + 3) = lflags;
00064     
00065     NetInvert16(DnsHdrPacket +  4, &DnsHdrQdcount);
00066     NetInvert16(DnsHdrPacket +  6, &DnsHdrAncount);
00067     NetInvert16(DnsHdrPacket +  8, &DnsHdrNscount);
00068     NetInvert16(DnsHdrPacket + 10, &DnsHdrArcount);
00069 
00070 }
00071 static uint16_t decodeUint16(char* p)
00072 {
00073     uint16_t     value  = *p++;
00074     value <<= 8; value += *p++;
00075     return value;
00076 }
00077 static uint32_t decodeUint32(char* p)
00078 {
00079     uint32_t     value  = *p++;
00080     value <<= 8; value += *p++;
00081     value <<= 8; value += *p++;
00082     value <<= 8; value += *p++;
00083     return value;
00084 }
00085 static void logRecordA(int len, char* p)
00086 {
00087     if (len == 4) Ip4AddrLog(*(uint32_t*)p);
00088     else          LogF("expected 4 bytes but had %d", len);
00089 }
00090 static void logRecordAAAA(int len, char* p)
00091 {
00092     if (len == 16) Ip6AddrLog(p);
00093     else           LogF("expected 16 bytes but had %d", len);
00094 }
00095 static void logRecordPTR(int len, char* p)
00096 {
00097     if (len <= DNS_MAX_LABEL_LENGTH) DnsNameLogPtr(p);
00098     else LogF("length %d is greater than max DNS label length of %d\r\n", len, DNS_MAX_LABEL_LENGTH);
00099 }
00100 static void logRecordSRV(int len, char* p)
00101 {
00102     LogF("pri=%d " , decodeUint16(p)); p += 2;
00103     LogF("wei=%d " , decodeUint16(p)); p += 2;
00104     LogF("port=%d ", decodeUint16(p)); p += 2;
00105     DnsNameLogPtr(p);
00106 }
00107 static void logRecordTXT(int len, char* p)
00108 {
00109     char* pEnd = p + len;
00110     while (p < pEnd)
00111     {
00112         Log("\r\n    ");
00113         int fieldLen = *p++;
00114         for (int i = 0; i < fieldLen; i++) LogChar(*p++);
00115     }
00116 }
00117 static void logContent()
00118 {
00119     char* p = DnsHdrData;
00120     
00121     //Get the questions
00122     for (int q = 0; q < DnsHdrQdcount; q++)
00123     {
00124         if (p >= DnsHdrData + DnsHdrDataLength)
00125         {
00126             Log("   Questions have overrun the buffer\r\n");
00127             return;
00128         }
00129         char* pEncodedName = p;
00130         int nameLength = DnsNameLength(p);
00131         if (!nameLength) { LogTimeF("   Questions namelength is zero\r\n"); return; }
00132         p += nameLength;                            //Skip past the name
00133         p++ ;                                       //skip the first byte of the type
00134         char recordType = *p++;                     //read the record type
00135         p += 2;                                     //skip the class
00136 
00137         LogF("   Query ");
00138         DnsRecordTypeLog(recordType);
00139         Log(" type record of ");
00140         DnsNameLogPtr(pEncodedName);
00141         Log("\r\n");
00142     }
00143     
00144     //Get the answers
00145     for (int a = 0; a < DnsHdrAncount; a++)
00146     {
00147         if (p >= DnsHdrData + DnsHdrDataLength) { Log("  Answers have overrun the buffer\r\n"); return; }
00148         
00149         char* pEncodedName = p;
00150         int nameLength = DnsNameLength(p);
00151         if (!nameLength) { Log("  Answer name length is zero\r\n"); return; }
00152         p += nameLength;               //Skip past the name
00153         
00154         p++;                           //Skip the high byte of the record type
00155         int recordType = *p++;         //Record type
00156         
00157         p++;                           //Skip the high byte of the class type
00158         int classType = *p++;          //Class type
00159         
00160         int ttl = decodeUint32(p); p += 4;     //32bit TTL
00161         
00162         int len = decodeUint16(p); p += 2;     //16bit length
00163         
00164         Log("  Answer ");
00165         DnsRecordTypeLog(recordType);
00166         Log(" type record of ");
00167         DnsNameLogPtr(pEncodedName);
00168         Log(" ==> ");
00169         
00170         switch (recordType)           //Log the payload if its type is known
00171         {
00172             case DNS_RECORD_A:    logRecordA   (len, p);      break;
00173             case DNS_RECORD_AAAA: logRecordAAAA(len, p);      break;
00174             case DNS_RECORD_PTR:  logRecordPTR (len, p);      break;
00175             case DNS_RECORD_SRV:  logRecordSRV (len, p);      break;
00176             case DNS_RECORD_TXT:  logRecordTXT (len, p);      break;
00177             default:              LogF("%d characters", len); break;
00178         }
00179         Log("\r\n");
00180         p += len; //Adjust the pointer to the next character after the payload
00181     }
00182 }
00183 
00184 void DnsHdrLog(int protocol)
00185 {
00186     if (NetTraceVerbose)
00187     {
00188         DnsProtocolLog(protocol);
00189         Log(" header\r\n");
00190         LogF("  Ident    %hd\r\n", DnsHdrId);
00191         if (DnsHdrIsReply)
00192         {
00193             if (DnsHdrIsAuthoritative)  LogF("  Authoritative reply\r\n");
00194             else                        LogF("  Non authoritative reply\r\n");
00195         }
00196         else
00197         {
00198             if (DnsHdrIsRecursiveQuery) LogF("  Recursive query\r\n");
00199             else                        LogF("  Non recursive query\r\n");
00200         }
00201         LogF("  qd, an, ns, ar  %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount);
00202     }
00203     else
00204     {
00205         DnsProtocolLog(protocol);
00206         LogF(" header qd, an, ns, ar  %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount);
00207     }
00208     logContent();
00209 }
00210