Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 13:9cd54f7db57a 1 #include "mbed.h"
andrewboyson 13:9cd54f7db57a 2 #include "dnshdr.h"
andrewboyson 13:9cd54f7db57a 3 #include "dnsname.h"
andrewboyson 13:9cd54f7db57a 4 #include "net.h"
andrewboyson 37:793b39683406 5 #include "action.h"
andrewboyson 13:9cd54f7db57a 6 #include "dns.h"
andrewboyson 13:9cd54f7db57a 7 #include "log.h"
andrewboyson 13:9cd54f7db57a 8 #include "dhcp.h"
andrewboyson 13:9cd54f7db57a 9 #include "slaac.h"
andrewboyson 13:9cd54f7db57a 10 #include "io.h"
andrewboyson 37:793b39683406 11 #include "ip4.h"
andrewboyson 37:793b39683406 12 #include "ip6.h"
andrewboyson 13:9cd54f7db57a 13
andrewboyson 37:793b39683406 14 bool DnsServerTrace = false;
andrewboyson 37:793b39683406 15
andrewboyson 37:793b39683406 16 #define MAX_QUERIES 16
andrewboyson 13:9cd54f7db57a 17
andrewboyson 32:679654f2d023 18 //Set by 'initialise'
andrewboyson 36:900e24b27bfb 19 static char* p; //Position relative to DnsHdrData and is updated while both reading questions and writing answers
andrewboyson 36:900e24b27bfb 20 static char myFullName[100]; //The name, adjusted to include the domain if needed by the protocol, used when reading and when writing
andrewboyson 36:900e24b27bfb 21 static int myFullNameLength;
andrewboyson 32:679654f2d023 22
andrewboyson 32:679654f2d023 23 //Set by readQuestions and used by answerQuestions
andrewboyson 37:793b39683406 24 static int questionTypes[MAX_QUERIES];
andrewboyson 37:793b39683406 25 static int nodeNameTypes[MAX_QUERIES];
andrewboyson 37:793b39683406 26 static bool hadQueryForMe;
andrewboyson 36:900e24b27bfb 27 static bool mdnsUnicastReply;
andrewboyson 32:679654f2d023 28
andrewboyson 32:679654f2d023 29 static int readQuestions()
andrewboyson 32:679654f2d023 30 {
andrewboyson 37:793b39683406 31 p = DnsHdrData;
andrewboyson 32:679654f2d023 32 mdnsUnicastReply = false;
andrewboyson 37:793b39683406 33 hadQueryForMe = false;
andrewboyson 13:9cd54f7db57a 34
andrewboyson 13:9cd54f7db57a 35 //Get the questions
andrewboyson 13:9cd54f7db57a 36 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 13:9cd54f7db57a 37 {
andrewboyson 37:793b39683406 38 //Bomb out if we are tending to overrun the buffer
andrewboyson 37:793b39683406 39 if (q >= MAX_QUERIES)
andrewboyson 37:793b39683406 40 {
andrewboyson 37:793b39683406 41 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - exceeded MAX_QUERIES\r\n");
andrewboyson 37:793b39683406 42 break;
andrewboyson 37:793b39683406 43 }
andrewboyson 37:793b39683406 44
andrewboyson 37:793b39683406 45 //Bomb out if we are tending to overrun the buffer
andrewboyson 37:793b39683406 46 if (p - DnsHdrPacket > 512)
andrewboyson 37:793b39683406 47 {
andrewboyson 37:793b39683406 48 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - overrunning the buffer\r\n");
andrewboyson 37:793b39683406 49 return -1;
andrewboyson 37:793b39683406 50 }
andrewboyson 37:793b39683406 51
andrewboyson 37:793b39683406 52 //Node name
andrewboyson 13:9cd54f7db57a 53 int nameLength = DnsNameLength(p);
andrewboyson 37:793b39683406 54 if (!nameLength)
andrewboyson 37:793b39683406 55 {
andrewboyson 37:793b39683406 56 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions namelength is zero\r\n");
andrewboyson 37:793b39683406 57 return -1;
andrewboyson 37:793b39683406 58 }
andrewboyson 33:714a0345e59b 59 nodeNameTypes[q] = DNS_RECORD_NONE;
andrewboyson 37:793b39683406 60 if (!nodeNameTypes[q] && DnsNameComparePtr(p, myFullName) ) nodeNameTypes[q] = DNS_RECORD_PTR; //rtc.local
andrewboyson 33:714a0345e59b 61 if (!nodeNameTypes[q] && DnsNameCompareIp4(p, DhcpLocalIp) ) nodeNameTypes[q] = DNS_RECORD_A; //3.1.168.192.inaddr.arpa
andrewboyson 33:714a0345e59b 62 if (!nodeNameTypes[q] && DnsNameCompareIp6(p, SlaacLinkLocalIp)) nodeNameTypes[q] = DNS_RECORD_AAAA; //5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 63 p += nameLength; //Skip past the name
andrewboyson 13:9cd54f7db57a 64
andrewboyson 37:793b39683406 65 //Remember had a query for me
andrewboyson 37:793b39683406 66 if (nodeNameTypes[q]) hadQueryForMe = true;
andrewboyson 13:9cd54f7db57a 67
andrewboyson 37:793b39683406 68 //Type
andrewboyson 37:793b39683406 69 p++ ; //skip the first byte of the type
andrewboyson 37:793b39683406 70 questionTypes[q] = *p++; //read the record type
andrewboyson 37:793b39683406 71
andrewboyson 37:793b39683406 72 //Class
andrewboyson 37:793b39683406 73 if (*p++ & 0x80) mdnsUnicastReply = true; //check the class 15th bit (UNICAST-RESPONSE)
andrewboyson 37:793b39683406 74 p++; //skip the class
andrewboyson 13:9cd54f7db57a 75 }
andrewboyson 32:679654f2d023 76 return 0;
andrewboyson 32:679654f2d023 77 }
andrewboyson 32:679654f2d023 78 static int addAnswers(int dnsProtocol)
andrewboyson 32:679654f2d023 79 {
andrewboyson 37:793b39683406 80 //Strip the questions if this is MDNS
andrewboyson 37:793b39683406 81 //if (dnsProtocol == DNS_PROTOCOL_MDNS) p = DnsHdrData;
andrewboyson 37:793b39683406 82
andrewboyson 37:793b39683406 83 //Go through each question
andrewboyson 33:714a0345e59b 84 DnsHdrAncount = 0;
andrewboyson 13:9cd54f7db57a 85 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 37:793b39683406 86 {
andrewboyson 32:679654f2d023 87 //Skip unwanted record types
andrewboyson 32:679654f2d023 88 switch (questionTypes[q])
andrewboyson 13:9cd54f7db57a 89 {
andrewboyson 13:9cd54f7db57a 90 case DNS_RECORD_A:
andrewboyson 32:679654f2d023 91 case DNS_RECORD_AAAA:
andrewboyson 33:714a0345e59b 92 case DNS_RECORD_PTR: break;
andrewboyson 33:714a0345e59b 93 default: continue;
andrewboyson 32:679654f2d023 94 }
andrewboyson 37:793b39683406 95
andrewboyson 37:793b39683406 96 //Skip queries which are not addressed to me
andrewboyson 37:793b39683406 97 if (!nodeNameTypes[q]) continue;
andrewboyson 37:793b39683406 98
andrewboyson 37:793b39683406 99 //Bomb out if we are tending to overrun the buffer
andrewboyson 37:793b39683406 100 if (p - DnsHdrPacket > 512)
andrewboyson 32:679654f2d023 101 {
andrewboyson 37:793b39683406 102 if (DnsServerTrace) LogTimeF("DnsServer-addAnswers - reply is getting too big\r\n");
andrewboyson 32:679654f2d023 103 return -1;
andrewboyson 32:679654f2d023 104 }
andrewboyson 37:793b39683406 105
andrewboyson 37:793b39683406 106 //Count the number of answers
andrewboyson 32:679654f2d023 107 DnsHdrAncount++;
andrewboyson 37:793b39683406 108
andrewboyson 37:793b39683406 109 //Log what we are doing
andrewboyson 37:793b39683406 110 if (DnsServerTrace)
andrewboyson 37:793b39683406 111 {
andrewboyson 37:793b39683406 112 switch (questionTypes[q])
andrewboyson 37:793b39683406 113 {
andrewboyson 37:793b39683406 114 case DNS_RECORD_A: Log(" replied with my IPv4 address\r\n"); break;
andrewboyson 37:793b39683406 115 case DNS_RECORD_AAAA: Log(" replied with my IPv6 address\r\n"); break;
andrewboyson 37:793b39683406 116 case DNS_RECORD_PTR: Log(" replied with my name\r\n"); break;
andrewboyson 37:793b39683406 117 }
andrewboyson 37:793b39683406 118 }
andrewboyson 37:793b39683406 119
andrewboyson 37:793b39683406 120 //Encode the node name
andrewboyson 32:679654f2d023 121 switch (questionTypes[q])
andrewboyson 32:679654f2d023 122 {
andrewboyson 32:679654f2d023 123 case DNS_RECORD_A:
andrewboyson 37:793b39683406 124 DnsNameEncodePtr(myFullName, &p);
andrewboyson 13:9cd54f7db57a 125 break;
andrewboyson 13:9cd54f7db57a 126 case DNS_RECORD_AAAA:
andrewboyson 37:793b39683406 127 DnsNameEncodePtr(myFullName, &p);
andrewboyson 32:679654f2d023 128 break;
andrewboyson 32:679654f2d023 129 case DNS_RECORD_PTR:
andrewboyson 33:714a0345e59b 130 if (nodeNameTypes[q] == DNS_RECORD_A ) DnsNameEncodeIp4(DhcpLocalIp, &p);
andrewboyson 33:714a0345e59b 131 if (nodeNameTypes[q] == DNS_RECORD_AAAA) DnsNameEncodeIp6(SlaacLinkLocalIp, &p);
andrewboyson 13:9cd54f7db57a 132 break;
andrewboyson 13:9cd54f7db57a 133 }
andrewboyson 37:793b39683406 134
andrewboyson 37:793b39683406 135 //Add the type
andrewboyson 32:679654f2d023 136 *p++ = 0; *p++ = questionTypes[q]; //16 bit Type
andrewboyson 37:793b39683406 137
andrewboyson 37:793b39683406 138 //Add the class
andrewboyson 37:793b39683406 139 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 140 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 37:793b39683406 141
andrewboyson 37:793b39683406 142 //Add the TTL
andrewboyson 32:679654f2d023 143 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 37:793b39683406 144
andrewboyson 37:793b39683406 145
andrewboyson 37:793b39683406 146 //Add the 16 bit payload length
andrewboyson 37:793b39683406 147 switch (questionTypes[q])
andrewboyson 37:793b39683406 148 {
andrewboyson 37:793b39683406 149 case DNS_RECORD_A: *p++ = 0; *p++ = 4; break;
andrewboyson 37:793b39683406 150 case DNS_RECORD_AAAA: *p++ = 0; *p++ = 16; break;
andrewboyson 37:793b39683406 151 case DNS_RECORD_PTR: *p++ = 0; *p++ = myFullNameLength + 2; break; //name length plus one byte for initial length plus one byte for terminating zero
andrewboyson 37:793b39683406 152 }
andrewboyson 37:793b39683406 153
andrewboyson 37:793b39683406 154 //Add the payload
andrewboyson 37:793b39683406 155 switch (questionTypes[q])
andrewboyson 37:793b39683406 156 {
andrewboyson 37:793b39683406 157 case DNS_RECORD_A: memcpy(p, &DhcpLocalIp, 4); p += 4; break;
andrewboyson 37:793b39683406 158 case DNS_RECORD_AAAA: memcpy(p, SlaacLinkLocalIp, 16); p += 16; break;
andrewboyson 37:793b39683406 159 case DNS_RECORD_PTR: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 37:793b39683406 160 }
andrewboyson 13:9cd54f7db57a 161 }
andrewboyson 32:679654f2d023 162 return 0;
andrewboyson 32:679654f2d023 163 }
andrewboyson 32:679654f2d023 164
andrewboyson 37:793b39683406 165 int DnsServerHandleQuery(void (*traceback)(void), int dnsProtocol, int *pSize) //Received an mdns or llmnr query on port 5353 or 5355
andrewboyson 37:793b39683406 166 {
andrewboyson 37:793b39683406 167 if (*pSize > 512)
andrewboyson 37:793b39683406 168 {
andrewboyson 37:793b39683406 169 if (DnsServerTrace) LogTimeF("DnsServerHandleQuery length %d too long\r\n", *pSize );
andrewboyson 37:793b39683406 170 return DO_NOTHING;
andrewboyson 37:793b39683406 171 }
andrewboyson 37:793b39683406 172
andrewboyson 37:793b39683406 173 myFullNameLength = DnsMakeFullNameFromName(dnsProtocol, NetName, sizeof(myFullName), myFullName);
andrewboyson 32:679654f2d023 174
andrewboyson 37:793b39683406 175 if (readQuestions()) return DO_NOTHING;
andrewboyson 37:793b39683406 176 if (!hadQueryForMe ) return DO_NOTHING;
andrewboyson 37:793b39683406 177
andrewboyson 37:793b39683406 178 if (DnsServerTrace)
andrewboyson 37:793b39683406 179 {
andrewboyson 37:793b39683406 180 LogTimeF("DnsServer received query\r\n");
andrewboyson 37:793b39683406 181 if (NetTraceBack) traceback();
andrewboyson 37:793b39683406 182 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 183 }
andrewboyson 37:793b39683406 184
andrewboyson 37:793b39683406 185 if (addAnswers(dnsProtocol)) return DO_NOTHING;
andrewboyson 37:793b39683406 186 if (!DnsHdrAncount) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 187
andrewboyson 13:9cd54f7db57a 188 DnsHdrIsReply = true;
andrewboyson 13:9cd54f7db57a 189 DnsHdrIsAuthoritative = true;
andrewboyson 13:9cd54f7db57a 190 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 191
andrewboyson 13:9cd54f7db57a 192 *pSize = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 193
andrewboyson 37:793b39683406 194 if (DnsServerTrace) DnsHdrLog(dnsProtocol);
andrewboyson 13:9cd54f7db57a 195
andrewboyson 37:793b39683406 196 int dest;
andrewboyson 37:793b39683406 197 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) dest = MULTICAST_MDNS;
andrewboyson 37:793b39683406 198 else dest = UNICAST;
andrewboyson 37:793b39683406 199
andrewboyson 37:793b39683406 200 return ActionMakeFromDestAndTrace(dest, NetTraceForward && DnsServerTrace);
andrewboyson 13:9cd54f7db57a 201 }