Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Oct 19 20:56:58 2017 +0000
Revision:
43:bc028d5a6424
Parent:
37:793b39683406
Child:
44:83ce5ace337b
Added verbose option to trace

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 43:bc028d5a6424 108
andrewboyson 37:793b39683406 109 //Encode the node name
andrewboyson 32:679654f2d023 110 switch (questionTypes[q])
andrewboyson 32:679654f2d023 111 {
andrewboyson 32:679654f2d023 112 case DNS_RECORD_A:
andrewboyson 37:793b39683406 113 DnsNameEncodePtr(myFullName, &p);
andrewboyson 13:9cd54f7db57a 114 break;
andrewboyson 13:9cd54f7db57a 115 case DNS_RECORD_AAAA:
andrewboyson 37:793b39683406 116 DnsNameEncodePtr(myFullName, &p);
andrewboyson 32:679654f2d023 117 break;
andrewboyson 32:679654f2d023 118 case DNS_RECORD_PTR:
andrewboyson 33:714a0345e59b 119 if (nodeNameTypes[q] == DNS_RECORD_A ) DnsNameEncodeIp4(DhcpLocalIp, &p);
andrewboyson 33:714a0345e59b 120 if (nodeNameTypes[q] == DNS_RECORD_AAAA) DnsNameEncodeIp6(SlaacLinkLocalIp, &p);
andrewboyson 13:9cd54f7db57a 121 break;
andrewboyson 13:9cd54f7db57a 122 }
andrewboyson 37:793b39683406 123
andrewboyson 37:793b39683406 124 //Add the type
andrewboyson 32:679654f2d023 125 *p++ = 0; *p++ = questionTypes[q]; //16 bit Type
andrewboyson 37:793b39683406 126
andrewboyson 37:793b39683406 127 //Add the class
andrewboyson 37:793b39683406 128 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 129 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 37:793b39683406 130
andrewboyson 37:793b39683406 131 //Add the TTL
andrewboyson 32:679654f2d023 132 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 37:793b39683406 133
andrewboyson 37:793b39683406 134
andrewboyson 37:793b39683406 135 //Add the 16 bit payload length
andrewboyson 37:793b39683406 136 switch (questionTypes[q])
andrewboyson 37:793b39683406 137 {
andrewboyson 37:793b39683406 138 case DNS_RECORD_A: *p++ = 0; *p++ = 4; break;
andrewboyson 37:793b39683406 139 case DNS_RECORD_AAAA: *p++ = 0; *p++ = 16; break;
andrewboyson 37:793b39683406 140 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 141 }
andrewboyson 37:793b39683406 142
andrewboyson 37:793b39683406 143 //Add the payload
andrewboyson 37:793b39683406 144 switch (questionTypes[q])
andrewboyson 37:793b39683406 145 {
andrewboyson 37:793b39683406 146 case DNS_RECORD_A: memcpy(p, &DhcpLocalIp, 4); p += 4; break;
andrewboyson 37:793b39683406 147 case DNS_RECORD_AAAA: memcpy(p, SlaacLinkLocalIp, 16); p += 16; break;
andrewboyson 37:793b39683406 148 case DNS_RECORD_PTR: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 37:793b39683406 149 }
andrewboyson 13:9cd54f7db57a 150 }
andrewboyson 32:679654f2d023 151 return 0;
andrewboyson 32:679654f2d023 152 }
andrewboyson 32:679654f2d023 153
andrewboyson 37:793b39683406 154 int DnsServerHandleQuery(void (*traceback)(void), int dnsProtocol, int *pSize) //Received an mdns or llmnr query on port 5353 or 5355
andrewboyson 37:793b39683406 155 {
andrewboyson 37:793b39683406 156 if (*pSize > 512)
andrewboyson 37:793b39683406 157 {
andrewboyson 43:bc028d5a6424 158 if (DnsServerTrace)
andrewboyson 43:bc028d5a6424 159 {
andrewboyson 43:bc028d5a6424 160 if (NetTraceNewLine) Log("\r\n");
andrewboyson 43:bc028d5a6424 161 LogTimeF("DnsServer length %d too long\r\n", *pSize );
andrewboyson 43:bc028d5a6424 162 if (NetTraceStack) traceback();
andrewboyson 43:bc028d5a6424 163 }
andrewboyson 37:793b39683406 164 return DO_NOTHING;
andrewboyson 37:793b39683406 165 }
andrewboyson 37:793b39683406 166
andrewboyson 37:793b39683406 167 myFullNameLength = DnsMakeFullNameFromName(dnsProtocol, NetName, sizeof(myFullName), myFullName);
andrewboyson 32:679654f2d023 168
andrewboyson 37:793b39683406 169 if (readQuestions()) return DO_NOTHING;
andrewboyson 37:793b39683406 170 if (!hadQueryForMe ) return DO_NOTHING;
andrewboyson 37:793b39683406 171
andrewboyson 37:793b39683406 172 if (DnsServerTrace)
andrewboyson 37:793b39683406 173 {
andrewboyson 43:bc028d5a6424 174 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 175 LogTimeF("DnsServer received query\r\n");
andrewboyson 43:bc028d5a6424 176 if (NetTraceStack) traceback();
andrewboyson 37:793b39683406 177 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 178 }
andrewboyson 37:793b39683406 179
andrewboyson 37:793b39683406 180 if (addAnswers(dnsProtocol)) return DO_NOTHING;
andrewboyson 37:793b39683406 181 if (!DnsHdrAncount) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 182
andrewboyson 13:9cd54f7db57a 183 DnsHdrIsReply = true;
andrewboyson 13:9cd54f7db57a 184 DnsHdrIsAuthoritative = true;
andrewboyson 13:9cd54f7db57a 185 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 186
andrewboyson 13:9cd54f7db57a 187 *pSize = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 188
andrewboyson 37:793b39683406 189 if (DnsServerTrace) DnsHdrLog(dnsProtocol);
andrewboyson 13:9cd54f7db57a 190
andrewboyson 37:793b39683406 191 int dest;
andrewboyson 37:793b39683406 192 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) dest = MULTICAST_MDNS;
andrewboyson 37:793b39683406 193 else dest = UNICAST;
andrewboyson 37:793b39683406 194
andrewboyson 43:bc028d5a6424 195 return ActionMakeFromDestAndTrace(dest, NetTraceStack && DnsServerTrace);
andrewboyson 13:9cd54f7db57a 196 }