Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Mar 11 16:42:45 2019 +0000
Revision:
128:79052cb4a41c
Parent:
61:aad055f1b0d1
Child:
160:6a1d1d368f80
Tidied up the DNS label module and removed some declarations that had not left room for the terminating null.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 61:aad055f1b0d1 1 #include <stdbool.h>
andrewboyson 61:aad055f1b0d1 2 #include <string.h>
andrewboyson 61:aad055f1b0d1 3
andrewboyson 128:79052cb4a41c 4 #include "dns.h"
andrewboyson 128:79052cb4a41c 5 #include "dnshdr.h"
andrewboyson 128:79052cb4a41c 6 #include "dnsname.h"
andrewboyson 128:79052cb4a41c 7 #include "dnslabel.h"
andrewboyson 128:79052cb4a41c 8 #include "net.h"
andrewboyson 128:79052cb4a41c 9 #include "action.h"
andrewboyson 128:79052cb4a41c 10 #include "log.h"
andrewboyson 128:79052cb4a41c 11 #include "dhcp.h"
andrewboyson 128:79052cb4a41c 12 #include "slaac.h"
andrewboyson 128:79052cb4a41c 13 #include "ip4.h"
andrewboyson 128:79052cb4a41c 14 #include "ip6.h"
andrewboyson 13:9cd54f7db57a 15
andrewboyson 37:793b39683406 16 bool DnsServerTrace = false;
andrewboyson 37:793b39683406 17
andrewboyson 44:83ce5ace337b 18 #define RECORD_NONE 0
andrewboyson 44:83ce5ace337b 19 #define RECORD_PTR4 1
andrewboyson 44:83ce5ace337b 20 #define RECORD_PTR6_LOCAL 2
andrewboyson 44:83ce5ace337b 21 #define RECORD_PTR6_GLOBAL 3
andrewboyson 44:83ce5ace337b 22 #define RECORD_A 4
andrewboyson 44:83ce5ace337b 23 #define RECORD_AAAA_LOCAL 5
andrewboyson 44:83ce5ace337b 24 #define RECORD_AAAA_GLOBAL 6
andrewboyson 44:83ce5ace337b 25
andrewboyson 44:83ce5ace337b 26 #define MAX_ANSWERS 4
andrewboyson 13:9cd54f7db57a 27
andrewboyson 32:679654f2d023 28 //Set by 'initialise'
andrewboyson 36:900e24b27bfb 29 static char* p; //Position relative to DnsHdrData and is updated while both reading questions and writing answers
andrewboyson 44:83ce5ace337b 30 static char myFullName4[100]; //The name, adjusted to include the domain if needed by the protocol, used when reading and when writing
andrewboyson 44:83ce5ace337b 31 static int myFullName4Length;
andrewboyson 44:83ce5ace337b 32 static char myFullName6[100]; //The name, adjusted to include the domain if needed by the protocol, used when reading and when writing
andrewboyson 44:83ce5ace337b 33 static int myFullName6Length;
andrewboyson 32:679654f2d023 34
andrewboyson 32:679654f2d023 35 //Set by readQuestions and used by answerQuestions
andrewboyson 44:83ce5ace337b 36 static int answers[MAX_ANSWERS];
andrewboyson 44:83ce5ace337b 37 static int answerCount = 0;
andrewboyson 36:900e24b27bfb 38 static bool mdnsUnicastReply;
andrewboyson 32:679654f2d023 39
andrewboyson 32:679654f2d023 40 static int readQuestions()
andrewboyson 32:679654f2d023 41 {
andrewboyson 37:793b39683406 42 p = DnsHdrData;
andrewboyson 32:679654f2d023 43 mdnsUnicastReply = false;
andrewboyson 13:9cd54f7db57a 44
andrewboyson 13:9cd54f7db57a 45 //Get the questions
andrewboyson 44:83ce5ace337b 46 answerCount = 0;
andrewboyson 44:83ce5ace337b 47 for (int i = 0; i < DnsHdrQdcount; i++)
andrewboyson 13:9cd54f7db57a 48 {
andrewboyson 44:83ce5ace337b 49 //Bomb out if there are too many answers
andrewboyson 44:83ce5ace337b 50 if (answerCount >= MAX_ANSWERS)
andrewboyson 37:793b39683406 51 {
andrewboyson 44:83ce5ace337b 52 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - exceeded %d answers\r\n", MAX_ANSWERS);
andrewboyson 37:793b39683406 53 break;
andrewboyson 37:793b39683406 54 }
andrewboyson 37:793b39683406 55
andrewboyson 37:793b39683406 56 //Bomb out if we are tending to overrun the buffer
andrewboyson 61:aad055f1b0d1 57 if (p - DnsHdrData > DnsHdrDataLength)
andrewboyson 37:793b39683406 58 {
andrewboyson 61:aad055f1b0d1 59 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - overrunning the buffer of %d bytes\r\n", DnsHdrDataLength);
andrewboyson 37:793b39683406 60 return -1;
andrewboyson 37:793b39683406 61 }
andrewboyson 37:793b39683406 62
andrewboyson 37:793b39683406 63 //Node name
andrewboyson 13:9cd54f7db57a 64 int nameLength = DnsNameLength(p);
andrewboyson 37:793b39683406 65 if (!nameLength)
andrewboyson 37:793b39683406 66 {
andrewboyson 37:793b39683406 67 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions namelength is zero\r\n");
andrewboyson 37:793b39683406 68 return -1;
andrewboyson 37:793b39683406 69 }
andrewboyson 44:83ce5ace337b 70 bool nodeIsName4 = DnsNameComparePtr(p, myFullName4);
andrewboyson 44:83ce5ace337b 71 bool nodeIsName6 = DnsNameComparePtr(p, myFullName6);
andrewboyson 44:83ce5ace337b 72 bool nodeIsAddr4 = DnsNameCompareIp4(p, DhcpLocalIp);
andrewboyson 44:83ce5ace337b 73 bool nodeIsLocl6 = DnsNameCompareIp6(p, SlaacLinkLocalIp);
andrewboyson 44:83ce5ace337b 74 bool nodeIsGlob6 = DnsNameCompareIp6(p, SlaacGlobalIp);
andrewboyson 44:83ce5ace337b 75 p += nameLength; //Skip past the name
andrewboyson 44:83ce5ace337b 76
andrewboyson 37:793b39683406 77 //Type
andrewboyson 44:83ce5ace337b 78 p++ ; //skip the first byte of the type
andrewboyson 44:83ce5ace337b 79 char recordType = *p++; //read the record type
andrewboyson 37:793b39683406 80
andrewboyson 37:793b39683406 81 //Class
andrewboyson 44:83ce5ace337b 82 if (*p++ & 0x80) mdnsUnicastReply = true; //check the class 15th bit (UNICAST-RESPONSE)
andrewboyson 44:83ce5ace337b 83 p++; //skip the class
andrewboyson 44:83ce5ace337b 84
andrewboyson 44:83ce5ace337b 85 //Handle the questions
andrewboyson 44:83ce5ace337b 86 if (nodeIsName4 && recordType == DNS_RECORD_A ) answers[answerCount++] = RECORD_A;
andrewboyson 44:83ce5ace337b 87 if (nodeIsName6 && recordType == DNS_RECORD_AAAA) { answers[answerCount++] = RECORD_AAAA_LOCAL; answers[answerCount++] = RECORD_AAAA_GLOBAL; }
andrewboyson 44:83ce5ace337b 88 if (nodeIsAddr4 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR4;
andrewboyson 44:83ce5ace337b 89 if (nodeIsLocl6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_LOCAL;
andrewboyson 44:83ce5ace337b 90 if (nodeIsGlob6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_GLOBAL;
andrewboyson 13:9cd54f7db57a 91 }
andrewboyson 32:679654f2d023 92 return 0;
andrewboyson 32:679654f2d023 93 }
andrewboyson 32:679654f2d023 94 static int addAnswers(int dnsProtocol)
andrewboyson 59:e0e556c8bd46 95 {
andrewboyson 44:83ce5ace337b 96 //Go through each answer
andrewboyson 33:714a0345e59b 97 DnsHdrAncount = 0;
andrewboyson 44:83ce5ace337b 98 for (int i = 0; i < answerCount; i++)
andrewboyson 44:83ce5ace337b 99 {
andrewboyson 37:793b39683406 100 //Bomb out if we are tending to overrun the buffer
andrewboyson 61:aad055f1b0d1 101 if (p - DnsHdrData > DnsHdrDataLength)
andrewboyson 32:679654f2d023 102 {
andrewboyson 37:793b39683406 103 if (DnsServerTrace) LogTimeF("DnsServer-addAnswers - reply is getting too big\r\n");
andrewboyson 32:679654f2d023 104 return -1;
andrewboyson 32:679654f2d023 105 }
andrewboyson 43:bc028d5a6424 106
andrewboyson 37:793b39683406 107 //Encode the node name
andrewboyson 44:83ce5ace337b 108 switch (answers[i])
andrewboyson 32:679654f2d023 109 {
andrewboyson 44:83ce5ace337b 110 case RECORD_A: DnsNameEncodePtr(myFullName4, &p); break;
andrewboyson 44:83ce5ace337b 111 case RECORD_AAAA_LOCAL: DnsNameEncodePtr(myFullName6, &p); break;
andrewboyson 44:83ce5ace337b 112 case RECORD_AAAA_GLOBAL: DnsNameEncodePtr(myFullName6, &p); break;
andrewboyson 44:83ce5ace337b 113 case RECORD_PTR4: DnsNameEncodeIp4(DhcpLocalIp, &p); break;
andrewboyson 44:83ce5ace337b 114 case RECORD_PTR6_LOCAL: DnsNameEncodeIp6(SlaacLinkLocalIp, &p); break;
andrewboyson 44:83ce5ace337b 115 case RECORD_PTR6_GLOBAL: DnsNameEncodeIp6(SlaacGlobalIp, &p); break;
andrewboyson 13:9cd54f7db57a 116 }
andrewboyson 37:793b39683406 117
andrewboyson 44:83ce5ace337b 118 //Add the 16 bit type
andrewboyson 44:83ce5ace337b 119 *p++ = 0;
andrewboyson 44:83ce5ace337b 120 switch (answers[i])
andrewboyson 44:83ce5ace337b 121 {
andrewboyson 44:83ce5ace337b 122 case RECORD_A: *p++ = DNS_RECORD_A; break;
andrewboyson 44:83ce5ace337b 123 case RECORD_AAAA_LOCAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 44:83ce5ace337b 124 case RECORD_AAAA_GLOBAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 44:83ce5ace337b 125 case RECORD_PTR4: *p++ = DNS_RECORD_PTR; break;
andrewboyson 44:83ce5ace337b 126 case RECORD_PTR6_LOCAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 44:83ce5ace337b 127 case RECORD_PTR6_GLOBAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 44:83ce5ace337b 128 }
andrewboyson 37:793b39683406 129
andrewboyson 37:793b39683406 130 //Add the class
andrewboyson 37:793b39683406 131 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 132 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 37:793b39683406 133
andrewboyson 37:793b39683406 134 //Add the TTL
andrewboyson 32:679654f2d023 135 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 37:793b39683406 136
andrewboyson 37:793b39683406 137
andrewboyson 37:793b39683406 138 //Add the 16 bit payload length
andrewboyson 44:83ce5ace337b 139 *p++ = 0;
andrewboyson 44:83ce5ace337b 140 switch (answers[i])
andrewboyson 37:793b39683406 141 {
andrewboyson 44:83ce5ace337b 142 case RECORD_A: *p++ = 4; break;
andrewboyson 44:83ce5ace337b 143 case RECORD_AAAA_LOCAL: *p++ = 16; break;
andrewboyson 44:83ce5ace337b 144 case RECORD_AAAA_GLOBAL: *p++ = 16; break;
andrewboyson 44:83ce5ace337b 145 case RECORD_PTR4: *p++ = myFullName4Length + 2; break; //add a byte for the initial length and another for the terminating zero length
andrewboyson 44:83ce5ace337b 146 case RECORD_PTR6_LOCAL: *p++ = myFullName6Length + 2; break;
andrewboyson 44:83ce5ace337b 147 case RECORD_PTR6_GLOBAL: *p++ = myFullName6Length + 2; break;
andrewboyson 37:793b39683406 148 }
andrewboyson 37:793b39683406 149
andrewboyson 37:793b39683406 150 //Add the payload
andrewboyson 44:83ce5ace337b 151 switch (answers[i])
andrewboyson 37:793b39683406 152 {
andrewboyson 44:83ce5ace337b 153 case RECORD_A: memcpy(p, &DhcpLocalIp, 4); p += 4; break;
andrewboyson 44:83ce5ace337b 154 case RECORD_AAAA_LOCAL: memcpy(p, SlaacLinkLocalIp, 16); p += 16; break;
andrewboyson 44:83ce5ace337b 155 case RECORD_AAAA_GLOBAL: memcpy(p, SlaacGlobalIp, 16); p += 16; break;
andrewboyson 44:83ce5ace337b 156 case RECORD_PTR4: DnsNameEncodePtr(myFullName4, &p); break;
andrewboyson 44:83ce5ace337b 157 case RECORD_PTR6_LOCAL: DnsNameEncodePtr(myFullName6, &p); break;
andrewboyson 44:83ce5ace337b 158 case RECORD_PTR6_GLOBAL: DnsNameEncodePtr(myFullName6, &p); break;
andrewboyson 37:793b39683406 159 }
andrewboyson 44:83ce5ace337b 160 //Increment the number of good answers to send
andrewboyson 44:83ce5ace337b 161 DnsHdrAncount++;
andrewboyson 13:9cd54f7db57a 162 }
andrewboyson 32:679654f2d023 163 return 0;
andrewboyson 32:679654f2d023 164 }
andrewboyson 32:679654f2d023 165
andrewboyson 59:e0e556c8bd46 166 int DnsServerHandleQuery(void (*traceback)(void), int dnsProtocol, void* pPacketTx, int *pSizeTx) //Received an mdns or llmnr query on port 5353 or 5355
andrewboyson 59:e0e556c8bd46 167 {
andrewboyson 128:79052cb4a41c 168 myFullName4Length = DnsLabelMakeFullNameFromName(dnsProtocol, NetName4, sizeof(myFullName4), myFullName4);
andrewboyson 128:79052cb4a41c 169 myFullName6Length = DnsLabelMakeFullNameFromName(dnsProtocol, NetName6, sizeof(myFullName6), myFullName6);
andrewboyson 32:679654f2d023 170
andrewboyson 37:793b39683406 171 if (readQuestions()) return DO_NOTHING;
andrewboyson 44:83ce5ace337b 172 if (!answerCount) return DO_NOTHING;
andrewboyson 37:793b39683406 173
andrewboyson 57:e0fb648acf48 174 if (DnsServerTrace || NetTraceHostGetMatched())
andrewboyson 37:793b39683406 175 {
andrewboyson 43:bc028d5a6424 176 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 177 LogTimeF("DnsServer received query\r\n");
andrewboyson 43:bc028d5a6424 178 if (NetTraceStack) traceback();
andrewboyson 37:793b39683406 179 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 180 }
andrewboyson 37:793b39683406 181
andrewboyson 59:e0e556c8bd46 182 char* pRx = DnsHdrData;
andrewboyson 59:e0e556c8bd46 183 char* pEndRx = p;
andrewboyson 59:e0e556c8bd46 184 int qdcount = DnsHdrQdcount;
andrewboyson 59:e0e556c8bd46 185 int nscount = DnsHdrNscount;
andrewboyson 59:e0e556c8bd46 186 int arcount = DnsHdrArcount;
andrewboyson 59:e0e556c8bd46 187
andrewboyson 59:e0e556c8bd46 188 DnsHdrSetup(pPacketTx, *pSizeTx);
andrewboyson 59:e0e556c8bd46 189 p = DnsHdrData;
andrewboyson 59:e0e556c8bd46 190
andrewboyson 59:e0e556c8bd46 191 //Add the questions if this is not MDNS
andrewboyson 59:e0e556c8bd46 192 if (dnsProtocol == DNS_PROTOCOL_MDNS)
andrewboyson 59:e0e556c8bd46 193 {
andrewboyson 59:e0e556c8bd46 194 DnsHdrQdcount = 0;
andrewboyson 59:e0e556c8bd46 195 DnsHdrNscount = 0;
andrewboyson 59:e0e556c8bd46 196 DnsHdrArcount = 0;
andrewboyson 59:e0e556c8bd46 197 }
andrewboyson 59:e0e556c8bd46 198 else
andrewboyson 59:e0e556c8bd46 199 {
andrewboyson 59:e0e556c8bd46 200 DnsHdrQdcount = qdcount;
andrewboyson 59:e0e556c8bd46 201 DnsHdrNscount = nscount;
andrewboyson 59:e0e556c8bd46 202 DnsHdrArcount = arcount;
andrewboyson 59:e0e556c8bd46 203 while (pRx < pEndRx) *p++ = *pRx++;
andrewboyson 59:e0e556c8bd46 204 }
andrewboyson 59:e0e556c8bd46 205
andrewboyson 59:e0e556c8bd46 206
andrewboyson 37:793b39683406 207 if (addAnswers(dnsProtocol)) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 208
andrewboyson 59:e0e556c8bd46 209 DnsHdrIsReply = true;
andrewboyson 59:e0e556c8bd46 210 DnsHdrIsAuthoritative = false;
andrewboyson 59:e0e556c8bd46 211 DnsHdrIsRecursiveQuery = false;
andrewboyson 59:e0e556c8bd46 212
andrewboyson 13:9cd54f7db57a 213 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 214
andrewboyson 59:e0e556c8bd46 215 *pSizeTx = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 216
andrewboyson 57:e0fb648acf48 217 if (DnsServerTrace || NetTraceHostGetMatched()) DnsHdrLog(dnsProtocol);
andrewboyson 13:9cd54f7db57a 218
andrewboyson 37:793b39683406 219 int dest;
andrewboyson 37:793b39683406 220 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) dest = MULTICAST_MDNS;
andrewboyson 37:793b39683406 221 else dest = UNICAST;
andrewboyson 37:793b39683406 222
andrewboyson 57:e0fb648acf48 223 return ActionMakeFromDestAndTrace(dest, NetTraceStack && DnsServerTrace || NetTraceHostGetMatched());
andrewboyson 13:9cd54f7db57a 224 }