Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Sep 25 07:09:32 2017 +0000
Revision:
36:900e24b27bfb
Parent:
33:714a0345e59b
Child:
37:793b39683406
Corrected DNS NameCompare to correctly compare a shortcut name

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 13:9cd54f7db57a 5 #include "dns.h"
andrewboyson 13:9cd54f7db57a 6 #include "log.h"
andrewboyson 13:9cd54f7db57a 7 #include "dhcp.h"
andrewboyson 13:9cd54f7db57a 8 #include "slaac.h"
andrewboyson 13:9cd54f7db57a 9 #include "io.h"
andrewboyson 13:9cd54f7db57a 10
andrewboyson 36:900e24b27bfb 11 #define DEBUG true
andrewboyson 13:9cd54f7db57a 12
andrewboyson 32:679654f2d023 13 //Set by 'initialise'
andrewboyson 36:900e24b27bfb 14 static char* p; //Position relative to DnsHdrData and is updated while both reading questions and writing answers
andrewboyson 36:900e24b27bfb 15 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 16 static int myFullNameLength;
andrewboyson 32:679654f2d023 17
andrewboyson 32:679654f2d023 18 //Set by readQuestions and used by answerQuestions
andrewboyson 36:900e24b27bfb 19 static int questionTypes[4];
andrewboyson 36:900e24b27bfb 20 static int nodeNameTypes[4];
andrewboyson 36:900e24b27bfb 21 static bool mdnsUnicastReply;
andrewboyson 32:679654f2d023 22
andrewboyson 32:679654f2d023 23 static int initialise(int dnsProtocol, int size)
andrewboyson 13:9cd54f7db57a 24 {
andrewboyson 32:679654f2d023 25 if ( size > 512) { if (DEBUG) LogTimeF("DnsServer-initialise length %d too long\r\n", size ); return -1; }
andrewboyson 32:679654f2d023 26 if (DnsHdrQdcount > 4) { if (DEBUG) LogTimeF("DnsServer-initialise too many queries %d\r\n", DnsHdrQdcount); return -1; }
andrewboyson 13:9cd54f7db57a 27
andrewboyson 32:679654f2d023 28 p = DnsHdrData;
andrewboyson 32:679654f2d023 29
andrewboyson 36:900e24b27bfb 30 myFullNameLength = DnsMakeFullNameFromName(dnsProtocol, NetName, sizeof(myFullName), myFullName);
andrewboyson 13:9cd54f7db57a 31
andrewboyson 32:679654f2d023 32 return 0;
andrewboyson 32:679654f2d023 33 }
andrewboyson 32:679654f2d023 34 static int readQuestions()
andrewboyson 32:679654f2d023 35 {
andrewboyson 13:9cd54f7db57a 36 char iEncodedName;
andrewboyson 32:679654f2d023 37 mdnsUnicastReply = false;
andrewboyson 13:9cd54f7db57a 38
andrewboyson 13:9cd54f7db57a 39 //Get the questions
andrewboyson 13:9cd54f7db57a 40 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 13:9cd54f7db57a 41 {
andrewboyson 13:9cd54f7db57a 42 iEncodedName = DnsNameIndexFromPointer(p);
andrewboyson 13:9cd54f7db57a 43 int nameLength = DnsNameLength(p);
andrewboyson 36:900e24b27bfb 44 if (!nameLength) { if (DEBUG) LogTimeF("DnsServer-readQuestions namelength is zero\r\n"); return -1; }
andrewboyson 33:714a0345e59b 45 nodeNameTypes[q] = DNS_RECORD_NONE;
andrewboyson 36:900e24b27bfb 46 if (!nodeNameTypes[q] && DnsNameCompare (p, myFullName) ) nodeNameTypes[q] = DNS_RECORD_PTR; //rtc.local
andrewboyson 33:714a0345e59b 47 if (!nodeNameTypes[q] && DnsNameCompareIp4(p, DhcpLocalIp) ) nodeNameTypes[q] = DNS_RECORD_A; //3.1.168.192.inaddr.arpa
andrewboyson 33:714a0345e59b 48 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 49 p += nameLength; //Skip past the name
andrewboyson 32:679654f2d023 50 p++ ; //skip the first byte of the type
andrewboyson 32:679654f2d023 51 char recordType = *p++; //read the record type
andrewboyson 32:679654f2d023 52 if (*p++ & 0x80) mdnsUnicastReply = true; //Check the 15th bit (UNICAST-RESPONSE)
andrewboyson 32:679654f2d023 53 p += 1; //skip the class
andrewboyson 13:9cd54f7db57a 54
andrewboyson 32:679654f2d023 55 questionTypes[q] = recordType;
andrewboyson 13:9cd54f7db57a 56
andrewboyson 13:9cd54f7db57a 57 if (DEBUG)
andrewboyson 13:9cd54f7db57a 58 {
andrewboyson 13:9cd54f7db57a 59 switch (recordType)
andrewboyson 13:9cd54f7db57a 60 {
andrewboyson 36:900e24b27bfb 61 case DNS_RECORD_A: LogF(" for IP4 address of "); break;
andrewboyson 36:900e24b27bfb 62 case DNS_RECORD_PTR: LogF(" for name of "); break;
andrewboyson 36:900e24b27bfb 63 case DNS_RECORD_AAAA: LogF(" for IP6 address of "); break;
andrewboyson 36:900e24b27bfb 64 default: LogF(" for unrecognised record type %d of ", recordType); break;
andrewboyson 13:9cd54f7db57a 65 }
andrewboyson 13:9cd54f7db57a 66 char text[256];
andrewboyson 13:9cd54f7db57a 67 DnsNameDecode(iEncodedName, sizeof(text), text);
andrewboyson 36:900e24b27bfb 68 LogF("%s\r\n", text);
andrewboyson 13:9cd54f7db57a 69 }
andrewboyson 13:9cd54f7db57a 70 }
andrewboyson 32:679654f2d023 71 return 0;
andrewboyson 32:679654f2d023 72 }
andrewboyson 32:679654f2d023 73 static int addAnswers(int dnsProtocol)
andrewboyson 32:679654f2d023 74 {
andrewboyson 33:714a0345e59b 75 DnsHdrAncount = 0;
andrewboyson 13:9cd54f7db57a 76 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 13:9cd54f7db57a 77 {
andrewboyson 36:900e24b27bfb 78 if (DEBUG) LogF(" deal with question %d, answer %d, question %d, node %d\r\n", q, DnsHdrAncount, questionTypes[q], nodeNameTypes[q]);
andrewboyson 36:900e24b27bfb 79
andrewboyson 32:679654f2d023 80 //Skip unwanted record types
andrewboyson 32:679654f2d023 81 switch (questionTypes[q])
andrewboyson 13:9cd54f7db57a 82 {
andrewboyson 13:9cd54f7db57a 83 case DNS_RECORD_A:
andrewboyson 32:679654f2d023 84 case DNS_RECORD_AAAA:
andrewboyson 33:714a0345e59b 85 case DNS_RECORD_PTR: break;
andrewboyson 33:714a0345e59b 86 default: continue;
andrewboyson 32:679654f2d023 87 }
andrewboyson 33:714a0345e59b 88 if (!nodeNameTypes[q]) continue; //Skip queries which are not addressed to me
andrewboyson 32:679654f2d023 89 if (p - DnsHdrPacket > 500)
andrewboyson 32:679654f2d023 90 {
andrewboyson 32:679654f2d023 91 LogTimeF("DnsServer-addAnswers Ip4 query reply is getting too big\r\n");
andrewboyson 32:679654f2d023 92 return -1;
andrewboyson 32:679654f2d023 93 }
andrewboyson 32:679654f2d023 94 DnsHdrAncount++;
andrewboyson 32:679654f2d023 95 int lenPayload = 0;
andrewboyson 32:679654f2d023 96 char* pPayload = 0;
andrewboyson 32:679654f2d023 97 switch (questionTypes[q])
andrewboyson 32:679654f2d023 98 {
andrewboyson 32:679654f2d023 99 case DNS_RECORD_A:
andrewboyson 36:900e24b27bfb 100 if (DEBUG) Log(" replied with my IPv4 address\r\n");
andrewboyson 36:900e24b27bfb 101 DnsNameEncode(myFullName, &p);
andrewboyson 36:900e24b27bfb 102 pPayload = (char*)&DhcpLocalIp;
andrewboyson 32:679654f2d023 103 lenPayload = 4;
andrewboyson 13:9cd54f7db57a 104 break;
andrewboyson 13:9cd54f7db57a 105
andrewboyson 13:9cd54f7db57a 106 case DNS_RECORD_AAAA:
andrewboyson 36:900e24b27bfb 107 if (DEBUG) Log(" replied with my IPv6 address\r\n");
andrewboyson 36:900e24b27bfb 108 DnsNameEncode(myFullName, &p);
andrewboyson 36:900e24b27bfb 109 pPayload = SlaacLinkLocalIp;
andrewboyson 32:679654f2d023 110 lenPayload = 16;
andrewboyson 32:679654f2d023 111 break;
andrewboyson 13:9cd54f7db57a 112
andrewboyson 32:679654f2d023 113 case DNS_RECORD_PTR:
andrewboyson 36:900e24b27bfb 114 if (DEBUG) Log(" replied with my name\r\n");
andrewboyson 33:714a0345e59b 115 if (nodeNameTypes[q] == DNS_RECORD_A ) DnsNameEncodeIp4(DhcpLocalIp, &p);
andrewboyson 33:714a0345e59b 116 if (nodeNameTypes[q] == DNS_RECORD_AAAA) DnsNameEncodeIp6(SlaacLinkLocalIp, &p);
andrewboyson 36:900e24b27bfb 117 pPayload = myFullName;
andrewboyson 36:900e24b27bfb 118 lenPayload = myFullNameLength;
andrewboyson 13:9cd54f7db57a 119 break;
andrewboyson 13:9cd54f7db57a 120 }
andrewboyson 32:679654f2d023 121 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 122 *p++ = 0; *p++ = questionTypes[q]; //16 bit Type
andrewboyson 32:679654f2d023 123 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 32:679654f2d023 124 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 32:679654f2d023 125 *p++ = 0; *p++ = lenPayload; //16 bit length in bytes
andrewboyson 32:679654f2d023 126 memcpy(p, pPayload, lenPayload); //Copy the payload
andrewboyson 36:900e24b27bfb 127 p += lenPayload; //Adjust the pointer to the next character after the payload
andrewboyson 32:679654f2d023 128
andrewboyson 13:9cd54f7db57a 129 }
andrewboyson 32:679654f2d023 130 return 0;
andrewboyson 32:679654f2d023 131 }
andrewboyson 32:679654f2d023 132
andrewboyson 32:679654f2d023 133 int DnsServerHandleQuery(int dnsProtocol, int *pSize) //Received an mdns or llmnr query on port 5353 or 5355
andrewboyson 32:679654f2d023 134 {
andrewboyson 32:679654f2d023 135 if (DEBUG) DnsHdrLog("DnsServer received query", dnsProtocol);
andrewboyson 32:679654f2d023 136
andrewboyson 32:679654f2d023 137 if (initialise(dnsProtocol, *pSize)) return DO_NOTHING;
andrewboyson 32:679654f2d023 138 if (readQuestions() ) return DO_NOTHING;
andrewboyson 32:679654f2d023 139 if (addAnswers(dnsProtocol) ) return DO_NOTHING;
andrewboyson 32:679654f2d023 140 if (!DnsHdrAncount) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 141
andrewboyson 13:9cd54f7db57a 142 DnsHdrIsReply = true;
andrewboyson 13:9cd54f7db57a 143 DnsHdrIsAuthoritative = true;
andrewboyson 13:9cd54f7db57a 144 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 145
andrewboyson 13:9cd54f7db57a 146 *pSize = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 147
andrewboyson 32:679654f2d023 148 if (DEBUG) DnsHdrLog("DnsServer sending reply", dnsProtocol);
andrewboyson 13:9cd54f7db57a 149
andrewboyson 13:9cd54f7db57a 150 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) return MULTICAST_MDNS;
andrewboyson 13:9cd54f7db57a 151 return UNICAST;
andrewboyson 13:9cd54f7db57a 152 }