Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
udp/dns/dnsserver.cpp
- Committer:
- andrewboyson
- Date:
- 2017-08-23
- Revision:
- 33:714a0345e59b
- Parent:
- 32:679654f2d023
- Child:
- 36:900e24b27bfb
File content as of revision 33:714a0345e59b:
#include "mbed.h" #include "dnshdr.h" #include "dnsname.h" #include "net.h" #include "dns.h" #include "log.h" #include "dhcp.h" #include "slaac.h" #include "io.h" #define DEBUG false //Set by 'initialise' char* p; //Position relative to DnsHdrData and is updated while both reading questions and writing answers char fullname[100]; //The name, adjusted to include the domain if needed by the protocol, used when reading and when writing int fullnamelength; //Set by readQuestions and used by answerQuestions int questionTypes[4]; int nodeNameTypes[4]; bool mdnsUnicastReply; static int initialise(int dnsProtocol, int size) { if ( size > 512) { if (DEBUG) LogTimeF("DnsServer-initialise length %d too long\r\n", size ); return -1; } if (DnsHdrQdcount > 4) { if (DEBUG) LogTimeF("DnsServer-initialise too many queries %d\r\n", DnsHdrQdcount); return -1; } p = DnsHdrData; fullnamelength = DnsMakeFullNameFromName(dnsProtocol, NetName, sizeof(fullname), fullname); return 0; } static int readQuestions() { char iEncodedName; mdnsUnicastReply = false; //Get the questions for (int q = 0; q < DnsHdrQdcount; q++) { iEncodedName = DnsNameIndexFromPointer(p); int nameLength = DnsNameLength(p); if (!nameLength) return DO_NOTHING; nodeNameTypes[q] = DNS_RECORD_NONE; if (!nodeNameTypes[q] && DnsNameCompare (p, fullname) ) nodeNameTypes[q] = DNS_RECORD_PTR; //rtc.local if (!nodeNameTypes[q] && DnsNameCompareIp4(p, DhcpLocalIp) ) nodeNameTypes[q] = DNS_RECORD_A; //3.1.168.192.inaddr.arpa 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 p += nameLength; //Skip past the name p++ ; //skip the first byte of the type char recordType = *p++; //read the record type if (*p++ & 0x80) mdnsUnicastReply = true; //Check the 15th bit (UNICAST-RESPONSE) p += 1; //skip the class questionTypes[q] = recordType; if (DEBUG) { switch (recordType) { case DNS_RECORD_A: LogF(" for IP4 address\r\n"); break; case DNS_RECORD_PTR: LogF(" for name\r\n"); break; case DNS_RECORD_AAAA: LogF(" for IP6 address\r\n"); break; default: LogF(" for unrecognised record type %d\r\n", recordType); break; } char text[256]; DnsNameDecode(iEncodedName, sizeof(text), text); LogF(" Name %s\r\n", text); } } return 0; } static int addAnswers(int dnsProtocol) { DnsHdrAncount = 0; for (int q = 0; q < DnsHdrQdcount; q++) { //Skip unwanted record types switch (questionTypes[q]) { case DNS_RECORD_A: case DNS_RECORD_AAAA: case DNS_RECORD_PTR: break; default: continue; } if (!nodeNameTypes[q]) continue; //Skip queries which are not addressed to me if (p - DnsHdrPacket > 500) { LogTimeF("DnsServer-addAnswers Ip4 query reply is getting too big\r\n"); return -1; } DnsHdrAncount++; int lenPayload = 0; char* pPayload = 0; switch (questionTypes[q]) { case DNS_RECORD_A: DnsNameEncode(fullname, &p); lenPayload = 4; pPayload = (char*)&DhcpLocalIp; break; case DNS_RECORD_AAAA: DnsNameEncode(fullname, &p); lenPayload = 16; pPayload = SlaacLinkLocalIp; break; case DNS_RECORD_PTR: if (nodeNameTypes[q] == DNS_RECORD_A ) DnsNameEncodeIp4(DhcpLocalIp, &p); if (nodeNameTypes[q] == DNS_RECORD_AAAA) DnsNameEncodeIp6(SlaacLinkLocalIp, &p); lenPayload = fullnamelength; pPayload = fullname; break; } char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS *p++ = 0; *p++ = questionTypes[q]; //16 bit Type *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024 *p++ = 0; *p++ = lenPayload; //16 bit length in bytes memcpy(p, pPayload, lenPayload); //Copy the payload p += lenPayload; //Adjust the pointer to the next character afetr the payload } return 0; } int DnsServerHandleQuery(int dnsProtocol, int *pSize) //Received an mdns or llmnr query on port 5353 or 5355 { if (DEBUG) DnsHdrLog("DnsServer received query", dnsProtocol); if (initialise(dnsProtocol, *pSize)) return DO_NOTHING; if (readQuestions() ) return DO_NOTHING; if (addAnswers(dnsProtocol) ) return DO_NOTHING; if (!DnsHdrAncount) return DO_NOTHING; DnsHdrIsReply = true; DnsHdrIsAuthoritative = true; DnsHdrWrite(); *pSize = p - DnsHdrPacket; if (DEBUG) DnsHdrLog("DnsServer sending reply", dnsProtocol); if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) return MULTICAST_MDNS; return UNICAST; }