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

Committer:
andrewboyson
Date:
Wed Oct 04 07:51:02 2017 +0000
Revision:
37:793b39683406
Parent:
35:93c39d260a83
Child:
43:bc028d5a6424
Added trace back and trace forward to log messages

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 37:793b39683406 1 #include "mbed.h"
andrewboyson 37:793b39683406 2 #include "log.h"
andrewboyson 37:793b39683406 3 #include "net.h"
andrewboyson 37:793b39683406 4 #include "action.h"
andrewboyson 37:793b39683406 5 #include "ip4.h"
andrewboyson 37:793b39683406 6 #include "ip6.h"
andrewboyson 37:793b39683406 7 #include "ar.h"
andrewboyson 37:793b39683406 8 #include "nr.h"
andrewboyson 37:793b39683406 9 #include "dns.h"
andrewboyson 37:793b39683406 10 #include "dnshdr.h"
andrewboyson 37:793b39683406 11 #include "dnsname.h"
andrewboyson 37:793b39683406 12 #include "dhcp.h"
andrewboyson 13:9cd54f7db57a 13
andrewboyson 37:793b39683406 14 bool DnsReplyTrace = false;
andrewboyson 13:9cd54f7db57a 15
andrewboyson 13:9cd54f7db57a 16 char DnsReplyRecordName[256];
andrewboyson 13:9cd54f7db57a 17 uint32_t DnsReplyRecordNameAsIp4 = 0;
andrewboyson 13:9cd54f7db57a 18 char DnsReplyRecordNameAsIp6[16];
andrewboyson 13:9cd54f7db57a 19 char DnsReplyName[64];
andrewboyson 13:9cd54f7db57a 20 uint32_t DnsReplyIp4 = 0;
andrewboyson 13:9cd54f7db57a 21 char DnsReplyIp6[16];
andrewboyson 13:9cd54f7db57a 22
andrewboyson 13:9cd54f7db57a 23 static char *p;
andrewboyson 13:9cd54f7db57a 24 static int recordNameOffset;
andrewboyson 13:9cd54f7db57a 25 static int recordType;
andrewboyson 13:9cd54f7db57a 26 static int recordDataLength;
andrewboyson 13:9cd54f7db57a 27 static char* pRecordData;
andrewboyson 13:9cd54f7db57a 28
andrewboyson 13:9cd54f7db57a 29 static int scanQuery()
andrewboyson 13:9cd54f7db57a 30 {
andrewboyson 13:9cd54f7db57a 31 int recordNameLength = DnsNameLength(p);
andrewboyson 13:9cd54f7db57a 32 if (!recordNameLength)
andrewboyson 13:9cd54f7db57a 33 {
andrewboyson 37:793b39683406 34 if (DnsReplyTrace) LogTimeF("DnsReply scanRecord name length of zero\r\n");
andrewboyson 13:9cd54f7db57a 35 return -1; //failure
andrewboyson 13:9cd54f7db57a 36 }
andrewboyson 13:9cd54f7db57a 37
andrewboyson 13:9cd54f7db57a 38 recordNameOffset = DnsNameIndexFromPointer(p);
andrewboyson 13:9cd54f7db57a 39 p += recordNameLength;
andrewboyson 13:9cd54f7db57a 40
andrewboyson 13:9cd54f7db57a 41 p++ ; //skip the first byte of the type
andrewboyson 13:9cd54f7db57a 42 recordType = *p++;
andrewboyson 13:9cd54f7db57a 43
andrewboyson 13:9cd54f7db57a 44 p += 2; //skip the class
andrewboyson 13:9cd54f7db57a 45
andrewboyson 13:9cd54f7db57a 46 return 0; //success
andrewboyson 13:9cd54f7db57a 47 }
andrewboyson 13:9cd54f7db57a 48
andrewboyson 13:9cd54f7db57a 49 static int scanAnswer()
andrewboyson 13:9cd54f7db57a 50 {
andrewboyson 13:9cd54f7db57a 51 int recordNameLength = DnsNameLength(p);
andrewboyson 13:9cd54f7db57a 52 if (!recordNameLength)
andrewboyson 13:9cd54f7db57a 53 {
andrewboyson 37:793b39683406 54 if (DnsReplyTrace) LogTimeF("DnsReply scanRecord name length of zero\r\n");
andrewboyson 13:9cd54f7db57a 55 return -1; //failure
andrewboyson 13:9cd54f7db57a 56 }
andrewboyson 13:9cd54f7db57a 57
andrewboyson 13:9cd54f7db57a 58 recordNameOffset = DnsNameIndexFromPointer(p);
andrewboyson 13:9cd54f7db57a 59 p += recordNameLength;
andrewboyson 13:9cd54f7db57a 60
andrewboyson 13:9cd54f7db57a 61 p++ ; //skip the first byte of the type
andrewboyson 13:9cd54f7db57a 62 recordType = *p++;
andrewboyson 13:9cd54f7db57a 63
andrewboyson 13:9cd54f7db57a 64 p += 6; //skip the class, TTL
andrewboyson 13:9cd54f7db57a 65 recordDataLength = 0;
andrewboyson 13:9cd54f7db57a 66 recordDataLength |= *p++ << 8;
andrewboyson 13:9cd54f7db57a 67 recordDataLength |= *p++;
andrewboyson 13:9cd54f7db57a 68
andrewboyson 13:9cd54f7db57a 69 pRecordData = p; //record the start of the data
andrewboyson 13:9cd54f7db57a 70
andrewboyson 13:9cd54f7db57a 71 p += recordDataLength; //Move to the start of the next record
andrewboyson 13:9cd54f7db57a 72
andrewboyson 13:9cd54f7db57a 73 return 0; //success
andrewboyson 13:9cd54f7db57a 74 }
andrewboyson 13:9cd54f7db57a 75 static void readAnswer()
andrewboyson 13:9cd54f7db57a 76 {
andrewboyson 13:9cd54f7db57a 77 DnsReplyRecordName[0] = 0;
andrewboyson 13:9cd54f7db57a 78 DnsReplyRecordNameAsIp4 = 0;
andrewboyson 13:9cd54f7db57a 79 DnsReplyRecordNameAsIp6[0] = 0;
andrewboyson 13:9cd54f7db57a 80 DnsReplyName[0] = 0;
andrewboyson 13:9cd54f7db57a 81 DnsReplyIp4 = 0;
andrewboyson 13:9cd54f7db57a 82 DnsReplyIp6[0] = 0;
andrewboyson 13:9cd54f7db57a 83
andrewboyson 13:9cd54f7db57a 84 switch (recordType)
andrewboyson 13:9cd54f7db57a 85 {
andrewboyson 13:9cd54f7db57a 86 case DNS_RECORD_A:
andrewboyson 13:9cd54f7db57a 87 case DNS_RECORD_AAAA:
andrewboyson 13:9cd54f7db57a 88 case DNS_RECORD_PTR:
andrewboyson 15:6ca6778168b1 89 case DNS_RECORD_SRV:
andrewboyson 15:6ca6778168b1 90 case DNS_RECORD_TXT:
andrewboyson 13:9cd54f7db57a 91 break;
andrewboyson 13:9cd54f7db57a 92 default:
andrewboyson 13:9cd54f7db57a 93 LogTimeF("DnsReply readAnswer unrecognised record type %d\r\n", recordType);
andrewboyson 15:6ca6778168b1 94 return;
andrewboyson 15:6ca6778168b1 95 }
andrewboyson 13:9cd54f7db57a 96
andrewboyson 37:793b39683406 97 DnsNameDecodePtr(recordNameOffset, sizeof(DnsReplyRecordName), DnsReplyRecordName);
andrewboyson 13:9cd54f7db57a 98 DnsNameDecodeIp4(recordNameOffset, &DnsReplyRecordNameAsIp4);
andrewboyson 13:9cd54f7db57a 99 DnsNameDecodeIp6(recordNameOffset, DnsReplyRecordNameAsIp6);
andrewboyson 15:6ca6778168b1 100
andrewboyson 13:9cd54f7db57a 101 switch (recordType)
andrewboyson 13:9cd54f7db57a 102 {
andrewboyson 13:9cd54f7db57a 103 case DNS_RECORD_A:
andrewboyson 13:9cd54f7db57a 104 if (recordDataLength != 4)
andrewboyson 13:9cd54f7db57a 105 {
andrewboyson 13:9cd54f7db57a 106 LogTimeF("DnsReply A type length of %d\r\n", recordDataLength);
andrewboyson 13:9cd54f7db57a 107 return;
andrewboyson 13:9cd54f7db57a 108 }
andrewboyson 13:9cd54f7db57a 109 memcpy(&DnsReplyIp4, pRecordData, 4);
andrewboyson 13:9cd54f7db57a 110 break;
andrewboyson 13:9cd54f7db57a 111 case DNS_RECORD_AAAA:
andrewboyson 13:9cd54f7db57a 112 if (recordDataLength != 16)
andrewboyson 13:9cd54f7db57a 113 {
andrewboyson 13:9cd54f7db57a 114 LogTimeF("DnsReply AAAA type length of %d\r\n", recordDataLength);
andrewboyson 13:9cd54f7db57a 115 return;
andrewboyson 13:9cd54f7db57a 116 }
andrewboyson 13:9cd54f7db57a 117 memcpy(DnsReplyIp6, pRecordData, 16);
andrewboyson 13:9cd54f7db57a 118 break;
andrewboyson 13:9cd54f7db57a 119 case DNS_RECORD_PTR:
andrewboyson 35:93c39d260a83 120 if (recordDataLength > DNS_MAX_LABEL_LENGTH)
andrewboyson 13:9cd54f7db57a 121 {
andrewboyson 35:93c39d260a83 122 LogTimeF("DnsReply PTR type length %d is greater than max DNS label length of %d\r\n", recordDataLength, DNS_MAX_LABEL_LENGTH);
andrewboyson 13:9cd54f7db57a 123 return;
andrewboyson 13:9cd54f7db57a 124 }
andrewboyson 37:793b39683406 125 DnsNameDecodePtr(DnsNameIndexFromPointer(pRecordData), sizeof(DnsReplyName), DnsReplyName);
andrewboyson 13:9cd54f7db57a 126 break;
andrewboyson 13:9cd54f7db57a 127 }
andrewboyson 15:6ca6778168b1 128
andrewboyson 37:793b39683406 129 if (DnsReplyTrace)
andrewboyson 13:9cd54f7db57a 130 {
andrewboyson 15:6ca6778168b1 131 LogF(" answer: %s", DnsReplyRecordName);
andrewboyson 13:9cd54f7db57a 132 char text[100];
andrewboyson 15:6ca6778168b1 133 if (DnsReplyRecordNameAsIp4)
andrewboyson 15:6ca6778168b1 134 {
andrewboyson 15:6ca6778168b1 135 Ip4AddressToString(DnsReplyRecordNameAsIp4, sizeof(text), text);
andrewboyson 15:6ca6778168b1 136 LogF(" (%s)", text);
andrewboyson 15:6ca6778168b1 137 }
andrewboyson 15:6ca6778168b1 138 if (DnsReplyRecordNameAsIp6[0])
andrewboyson 15:6ca6778168b1 139 {
andrewboyson 15:6ca6778168b1 140 Ip6AddressToString(DnsReplyRecordNameAsIp6, sizeof(text), text);
andrewboyson 15:6ca6778168b1 141 LogF(" (%s)", text);
andrewboyson 15:6ca6778168b1 142 }
andrewboyson 15:6ca6778168b1 143 LogF(" == ");
andrewboyson 13:9cd54f7db57a 144 switch (recordType)
andrewboyson 13:9cd54f7db57a 145 {
andrewboyson 13:9cd54f7db57a 146 case DNS_RECORD_A:
andrewboyson 14:e75a59c1123d 147 Ip4AddressToString(DnsReplyIp4, sizeof(text), text);
andrewboyson 15:6ca6778168b1 148 LogF("%s\r\n", text);
andrewboyson 13:9cd54f7db57a 149 break;
andrewboyson 13:9cd54f7db57a 150 case DNS_RECORD_AAAA:
andrewboyson 14:e75a59c1123d 151 Ip6AddressToString(DnsReplyIp6, sizeof(text), text);
andrewboyson 15:6ca6778168b1 152 LogF("%s\r\n", text);
andrewboyson 13:9cd54f7db57a 153 break;
andrewboyson 13:9cd54f7db57a 154 case DNS_RECORD_PTR:
andrewboyson 15:6ca6778168b1 155 LogF("%s\r\n", DnsReplyName);
andrewboyson 15:6ca6778168b1 156 break;
andrewboyson 15:6ca6778168b1 157 default:
andrewboyson 15:6ca6778168b1 158 DnsRecordTypeToString(recordType, sizeof(text), text);
andrewboyson 15:6ca6778168b1 159 LogF("%d bytes of %s\r\n", recordDataLength, text);
andrewboyson 13:9cd54f7db57a 160 break;
andrewboyson 13:9cd54f7db57a 161 }
andrewboyson 13:9cd54f7db57a 162 }
andrewboyson 13:9cd54f7db57a 163 }
andrewboyson 13:9cd54f7db57a 164
andrewboyson 32:679654f2d023 165 static void sendToDnsCache(int dnsProtocol)
andrewboyson 30:e34173b7585c 166 {
andrewboyson 32:679654f2d023 167 char strippedName[100];
andrewboyson 32:679654f2d023 168 if (DnsReplyRecordName[0]) DnsStripNameFromFullName(dnsProtocol, DnsReplyRecordName, sizeof(strippedName), strippedName);
andrewboyson 32:679654f2d023 169 if (DnsReplyName[0] ) DnsStripNameFromFullName(dnsProtocol, DnsReplyName , sizeof(strippedName), strippedName);
andrewboyson 32:679654f2d023 170
andrewboyson 35:93c39d260a83 171 if (DnsReplyIp4 && DnsReplyRecordName[0]) NrAddIp4Record(DnsReplyIp4, strippedName, dnsProtocol);
andrewboyson 35:93c39d260a83 172 if (DnsReplyIp6[0] && DnsReplyRecordName[0]) NrAddIp6Record(DnsReplyIp6, strippedName, dnsProtocol);
andrewboyson 35:93c39d260a83 173 if (DnsReplyRecordNameAsIp4 && DnsReplyName[0] ) NrAddIp4Record(DnsReplyRecordNameAsIp4, strippedName, dnsProtocol);
andrewboyson 35:93c39d260a83 174 if (DnsReplyRecordNameAsIp6[0] && DnsReplyName[0] ) NrAddIp6Record(DnsReplyRecordNameAsIp6, strippedName, dnsProtocol);
andrewboyson 30:e34173b7585c 175 }
andrewboyson 37:793b39683406 176 int DnsReplyHandle(void (*traceback)(void), int dnsProtocol, int *pSize)
andrewboyson 13:9cd54f7db57a 177 {
andrewboyson 13:9cd54f7db57a 178 if (!DnsHdrAncount) return DO_NOTHING;
andrewboyson 37:793b39683406 179 if (DnsReplyTrace)
andrewboyson 37:793b39683406 180 {
andrewboyson 37:793b39683406 181 LogTimeF("DNS received reply\r\n");
andrewboyson 37:793b39683406 182 if (NetTraceBack) traceback();
andrewboyson 37:793b39683406 183 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 184 }
andrewboyson 13:9cd54f7db57a 185
andrewboyson 13:9cd54f7db57a 186 p = DnsHdrData;
andrewboyson 13:9cd54f7db57a 187
andrewboyson 13:9cd54f7db57a 188 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 13:9cd54f7db57a 189 {
andrewboyson 13:9cd54f7db57a 190 if (scanQuery()) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 191 }
andrewboyson 13:9cd54f7db57a 192 for (int a = 0; a < DnsHdrAncount; a++)
andrewboyson 13:9cd54f7db57a 193 {
andrewboyson 13:9cd54f7db57a 194 if (scanAnswer()) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 195 readAnswer();
andrewboyson 32:679654f2d023 196 sendToDnsCache(dnsProtocol);
andrewboyson 13:9cd54f7db57a 197 }
andrewboyson 13:9cd54f7db57a 198
andrewboyson 13:9cd54f7db57a 199 return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 200 }