A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Mar 11 16:42:45 2019 +0000
Revision:
128:79052cb4a41c
Parent:
121:bc048b65a630
Child:
136:8a65abb0dc63
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 <stdint.h>
andrewboyson 61:aad055f1b0d1 2 #include <stdbool.h>
andrewboyson 61:aad055f1b0d1 3
andrewboyson 128:79052cb4a41c 4 #include "dns.h"
andrewboyson 128:79052cb4a41c 5 #include "net.h"
andrewboyson 128:79052cb4a41c 6 #include "log.h"
andrewboyson 128:79052cb4a41c 7 #include "net.h"
andrewboyson 128:79052cb4a41c 8 #include "eth.h"
andrewboyson 128:79052cb4a41c 9 #include "ip4addr.h"
andrewboyson 128:79052cb4a41c 10 #include "ip6addr.h"
andrewboyson 128:79052cb4a41c 11 #include "udp.h"
andrewboyson 128:79052cb4a41c 12 #include "dnsname.h"
andrewboyson 128:79052cb4a41c 13 #include "dnslabel.h"
andrewboyson 13:9cd54f7db57a 14
andrewboyson 13:9cd54f7db57a 15 #define HEADER_LENGTH 12
andrewboyson 13:9cd54f7db57a 16
andrewboyson 13:9cd54f7db57a 17 __packed struct header
andrewboyson 13:9cd54f7db57a 18 {
andrewboyson 13:9cd54f7db57a 19 uint16_t id;
andrewboyson 13:9cd54f7db57a 20 uint8_t uflags;
andrewboyson 13:9cd54f7db57a 21 uint8_t lflags;
andrewboyson 13:9cd54f7db57a 22
andrewboyson 13:9cd54f7db57a 23 uint16_t qdcount;
andrewboyson 13:9cd54f7db57a 24 uint16_t ancount;
andrewboyson 13:9cd54f7db57a 25 uint16_t nscount;
andrewboyson 13:9cd54f7db57a 26 uint16_t arcount;
andrewboyson 13:9cd54f7db57a 27 };
andrewboyson 13:9cd54f7db57a 28
andrewboyson 13:9cd54f7db57a 29 uint16_t DnsHdrId;
andrewboyson 13:9cd54f7db57a 30
andrewboyson 13:9cd54f7db57a 31 bool DnsHdrIsReply;
andrewboyson 13:9cd54f7db57a 32 bool DnsHdrIsAuthoritative;
andrewboyson 13:9cd54f7db57a 33 bool DnsHdrIsRecursiveQuery;
andrewboyson 13:9cd54f7db57a 34
andrewboyson 13:9cd54f7db57a 35 uint16_t DnsHdrQdcount;
andrewboyson 13:9cd54f7db57a 36 uint16_t DnsHdrAncount;
andrewboyson 13:9cd54f7db57a 37 uint16_t DnsHdrNscount;
andrewboyson 13:9cd54f7db57a 38 uint16_t DnsHdrArcount;
andrewboyson 13:9cd54f7db57a 39
andrewboyson 13:9cd54f7db57a 40 char* DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 41 char* DnsHdrData;
andrewboyson 59:e0e556c8bd46 42 int DnsHdrDataLength;
andrewboyson 13:9cd54f7db57a 43
andrewboyson 59:e0e556c8bd46 44 void DnsHdrSetup(void* pPacket, int lenPacket)
andrewboyson 13:9cd54f7db57a 45 {
andrewboyson 13:9cd54f7db57a 46 DnsHdrPacket = (char*)pPacket;
andrewboyson 61:aad055f1b0d1 47 DnsHdrData = DnsHdrPacket + sizeof(struct header);
andrewboyson 61:aad055f1b0d1 48 DnsHdrDataLength = lenPacket - sizeof(struct header);
andrewboyson 13:9cd54f7db57a 49 }
andrewboyson 13:9cd54f7db57a 50
andrewboyson 13:9cd54f7db57a 51 void DnsHdrRead()
andrewboyson 13:9cd54f7db57a 52 {
andrewboyson 61:aad055f1b0d1 53 struct header* pHeader = (struct header*)DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 54
andrewboyson 13:9cd54f7db57a 55 DnsHdrId = NetToHost16(pHeader->id);
andrewboyson 13:9cd54f7db57a 56
andrewboyson 13:9cd54f7db57a 57 uint8_t uflags = pHeader->uflags;
andrewboyson 13:9cd54f7db57a 58 DnsHdrIsReply = uflags & 0x80;
andrewboyson 13:9cd54f7db57a 59 DnsHdrIsAuthoritative = uflags & 0x04;
andrewboyson 33:714a0345e59b 60 DnsHdrIsRecursiveQuery = uflags & 0x01;
andrewboyson 13:9cd54f7db57a 61
andrewboyson 13:9cd54f7db57a 62 DnsHdrQdcount = NetToHost16(pHeader->qdcount);
andrewboyson 13:9cd54f7db57a 63 DnsHdrAncount = NetToHost16(pHeader->ancount);
andrewboyson 13:9cd54f7db57a 64 DnsHdrNscount = NetToHost16(pHeader->nscount);
andrewboyson 13:9cd54f7db57a 65 DnsHdrArcount = NetToHost16(pHeader->arcount);
andrewboyson 13:9cd54f7db57a 66
andrewboyson 13:9cd54f7db57a 67 }
andrewboyson 13:9cd54f7db57a 68 void DnsHdrWrite()
andrewboyson 13:9cd54f7db57a 69 {
andrewboyson 61:aad055f1b0d1 70 struct header* pHeader = (struct header*)DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 71
andrewboyson 13:9cd54f7db57a 72 pHeader->id = NetToHost16(DnsHdrId);
andrewboyson 13:9cd54f7db57a 73
andrewboyson 13:9cd54f7db57a 74 uint8_t uflags = 0;
andrewboyson 13:9cd54f7db57a 75 uint8_t lflags = 0;
andrewboyson 13:9cd54f7db57a 76 if (DnsHdrIsReply) uflags |= 0x80;
andrewboyson 13:9cd54f7db57a 77 if (DnsHdrIsAuthoritative) uflags |= 0x04;
andrewboyson 13:9cd54f7db57a 78 if (DnsHdrIsRecursiveQuery) uflags |= 0x01;
andrewboyson 13:9cd54f7db57a 79 pHeader->uflags = uflags;
andrewboyson 13:9cd54f7db57a 80 pHeader->lflags = lflags;
andrewboyson 13:9cd54f7db57a 81
andrewboyson 13:9cd54f7db57a 82 pHeader->qdcount = NetToHost16(DnsHdrQdcount);
andrewboyson 13:9cd54f7db57a 83 pHeader->ancount = NetToHost16(DnsHdrAncount);
andrewboyson 13:9cd54f7db57a 84 pHeader->nscount = NetToHost16(DnsHdrNscount);
andrewboyson 13:9cd54f7db57a 85 pHeader->arcount = NetToHost16(DnsHdrArcount);
andrewboyson 13:9cd54f7db57a 86 }
andrewboyson 58:d48c899e482f 87 static uint16_t decodeUint16(char* p)
andrewboyson 58:d48c899e482f 88 {
andrewboyson 58:d48c899e482f 89 uint16_t value = *p++;
andrewboyson 58:d48c899e482f 90 value <<= 8; value += *p++;
andrewboyson 58:d48c899e482f 91 return value;
andrewboyson 58:d48c899e482f 92 }
andrewboyson 58:d48c899e482f 93 static uint32_t decodeUint32(char* p)
andrewboyson 58:d48c899e482f 94 {
andrewboyson 58:d48c899e482f 95 uint32_t value = *p++;
andrewboyson 58:d48c899e482f 96 value <<= 8; value += *p++;
andrewboyson 58:d48c899e482f 97 value <<= 8; value += *p++;
andrewboyson 58:d48c899e482f 98 value <<= 8; value += *p++;
andrewboyson 58:d48c899e482f 99 return value;
andrewboyson 58:d48c899e482f 100 }
andrewboyson 58:d48c899e482f 101 static void logRecordA(int len, char* p)
andrewboyson 58:d48c899e482f 102 {
andrewboyson 58:d48c899e482f 103 if (len == 4) Ip4AddressLog(*(uint32_t*)p);
andrewboyson 58:d48c899e482f 104 else LogF("expected 4 bytes but had %d", len);
andrewboyson 58:d48c899e482f 105 }
andrewboyson 58:d48c899e482f 106 static void logRecordAAAA(int len, char* p)
andrewboyson 58:d48c899e482f 107 {
andrewboyson 58:d48c899e482f 108 if (len == 16) Ip6AddressLog(p);
andrewboyson 58:d48c899e482f 109 else LogF("expected 16 bytes but had %d", len);
andrewboyson 58:d48c899e482f 110 }
andrewboyson 58:d48c899e482f 111 static void logRecordPTR(int len, char* p)
andrewboyson 58:d48c899e482f 112 {
andrewboyson 58:d48c899e482f 113 if (len <= DNS_MAX_LABEL_LENGTH) DnsNameLogPtr(p);
andrewboyson 58:d48c899e482f 114 else LogF("length %d is greater than max DNS label length of %d\r\n", len, DNS_MAX_LABEL_LENGTH);
andrewboyson 58:d48c899e482f 115 }
andrewboyson 58:d48c899e482f 116 static void logRecordSRV(int len, char* p)
andrewboyson 58:d48c899e482f 117 {
andrewboyson 58:d48c899e482f 118 LogF("pri=%d " , decodeUint16(p)); p += 2;
andrewboyson 58:d48c899e482f 119 LogF("wei=%d " , decodeUint16(p)); p += 2;
andrewboyson 58:d48c899e482f 120 LogF("port=%d ", decodeUint16(p)); p += 2;
andrewboyson 58:d48c899e482f 121 DnsNameLogPtr(p);
andrewboyson 58:d48c899e482f 122 }
andrewboyson 58:d48c899e482f 123 static void logRecordTXT(int len, char* p)
andrewboyson 58:d48c899e482f 124 {
andrewboyson 58:d48c899e482f 125 char* pEnd = p + len;
andrewboyson 58:d48c899e482f 126 while (p < pEnd)
andrewboyson 58:d48c899e482f 127 {
andrewboyson 58:d48c899e482f 128 Log("\r\n ");
andrewboyson 58:d48c899e482f 129 int fieldLen = *p++;
andrewboyson 121:bc048b65a630 130 for (int i = 0; i < fieldLen; i++) LogChar(*p++);
andrewboyson 58:d48c899e482f 131 }
andrewboyson 58:d48c899e482f 132 }
andrewboyson 37:793b39683406 133 static void logContent()
andrewboyson 37:793b39683406 134 {
andrewboyson 58:d48c899e482f 135 char* p = DnsHdrData;
andrewboyson 37:793b39683406 136
andrewboyson 37:793b39683406 137 //Get the questions
andrewboyson 37:793b39683406 138 for (int q = 0; q < DnsHdrQdcount; q++)
andrewboyson 37:793b39683406 139 {
andrewboyson 59:e0e556c8bd46 140 if (p >= DnsHdrData + DnsHdrDataLength)
andrewboyson 37:793b39683406 141 {
andrewboyson 58:d48c899e482f 142 Log(" Questions have overrun the buffer\r\n");
andrewboyson 37:793b39683406 143 return;
andrewboyson 37:793b39683406 144 }
andrewboyson 58:d48c899e482f 145 char* pEncodedName = p;
andrewboyson 37:793b39683406 146 int nameLength = DnsNameLength(p);
andrewboyson 58:d48c899e482f 147 if (!nameLength) { LogTimeF(" Questions namelength is zero\r\n"); return; }
andrewboyson 37:793b39683406 148 p += nameLength; //Skip past the name
andrewboyson 37:793b39683406 149 p++ ; //skip the first byte of the type
andrewboyson 37:793b39683406 150 char recordType = *p++; //read the record type
andrewboyson 37:793b39683406 151 p += 2; //skip the class
andrewboyson 37:793b39683406 152
andrewboyson 47:73af5c0b0dc2 153 LogF(" Query ");
andrewboyson 47:73af5c0b0dc2 154 DnsRecordTypeLog(recordType);
andrewboyson 47:73af5c0b0dc2 155 Log(" type record of ");
andrewboyson 58:d48c899e482f 156 DnsNameLogPtr(pEncodedName);
andrewboyson 47:73af5c0b0dc2 157 Log("\r\n");
andrewboyson 37:793b39683406 158 }
andrewboyson 37:793b39683406 159
andrewboyson 37:793b39683406 160 //Get the answers
andrewboyson 37:793b39683406 161 for (int a = 0; a < DnsHdrAncount; a++)
andrewboyson 37:793b39683406 162 {
andrewboyson 59:e0e556c8bd46 163 if (p >= DnsHdrData + DnsHdrDataLength) { Log(" Answers have overrun the buffer\r\n"); return; }
andrewboyson 37:793b39683406 164
andrewboyson 58:d48c899e482f 165 char* pEncodedName = p;
andrewboyson 37:793b39683406 166 int nameLength = DnsNameLength(p);
andrewboyson 43:bc028d5a6424 167 if (!nameLength) { Log(" Answer name length is zero\r\n"); return; }
andrewboyson 37:793b39683406 168 p += nameLength; //Skip past the name
andrewboyson 37:793b39683406 169
andrewboyson 37:793b39683406 170 p++; //Skip the high byte of the record type
andrewboyson 37:793b39683406 171 int recordType = *p++; //Record type
andrewboyson 37:793b39683406 172
andrewboyson 37:793b39683406 173 p++; //Skip the high byte of the class type
andrewboyson 37:793b39683406 174 int classType = *p++; //Class type
andrewboyson 37:793b39683406 175
andrewboyson 58:d48c899e482f 176 int ttl = decodeUint32(p); p += 4; //32bit TTL
andrewboyson 37:793b39683406 177
andrewboyson 58:d48c899e482f 178 int len = decodeUint16(p); p += 2; //16bit length
andrewboyson 37:793b39683406 179
andrewboyson 43:bc028d5a6424 180 Log(" Answer ");
andrewboyson 47:73af5c0b0dc2 181 DnsRecordTypeLog(recordType);
andrewboyson 43:bc028d5a6424 182 Log(" type record of ");
andrewboyson 58:d48c899e482f 183 DnsNameLogPtr(pEncodedName);
andrewboyson 43:bc028d5a6424 184 Log(" ==> ");
andrewboyson 37:793b39683406 185
andrewboyson 37:793b39683406 186 switch (recordType) //Log the payload if its type is known
andrewboyson 37:793b39683406 187 {
andrewboyson 58:d48c899e482f 188 case DNS_RECORD_A: logRecordA (len, p); break;
andrewboyson 58:d48c899e482f 189 case DNS_RECORD_AAAA: logRecordAAAA(len, p); break;
andrewboyson 58:d48c899e482f 190 case DNS_RECORD_PTR: logRecordPTR (len, p); break;
andrewboyson 58:d48c899e482f 191 case DNS_RECORD_SRV: logRecordSRV (len, p); break;
andrewboyson 58:d48c899e482f 192 case DNS_RECORD_TXT: logRecordTXT (len, p); break;
andrewboyson 58:d48c899e482f 193 default: LogF("%d characters", len); break;
andrewboyson 37:793b39683406 194 }
andrewboyson 43:bc028d5a6424 195 Log("\r\n");
andrewboyson 37:793b39683406 196 p += len; //Adjust the pointer to the next character after the payload
andrewboyson 37:793b39683406 197 }
andrewboyson 37:793b39683406 198 }
andrewboyson 37:793b39683406 199
andrewboyson 37:793b39683406 200 void DnsHdrLog(int protocol)
andrewboyson 13:9cd54f7db57a 201 {
andrewboyson 43:bc028d5a6424 202 if (NetTraceVerbose)
andrewboyson 15:6ca6778168b1 203 {
andrewboyson 47:73af5c0b0dc2 204 DnsProtocolLog(protocol);
andrewboyson 47:73af5c0b0dc2 205 Log(" header\r\n");
andrewboyson 43:bc028d5a6424 206 LogF(" Ident %hd\r\n", DnsHdrId);
andrewboyson 43:bc028d5a6424 207 if (DnsHdrIsReply)
andrewboyson 43:bc028d5a6424 208 {
andrewboyson 43:bc028d5a6424 209 if (DnsHdrIsAuthoritative) LogF(" Authoritative reply\r\n");
andrewboyson 43:bc028d5a6424 210 else LogF(" Non authoritative reply\r\n");
andrewboyson 43:bc028d5a6424 211 }
andrewboyson 43:bc028d5a6424 212 else
andrewboyson 43:bc028d5a6424 213 {
andrewboyson 43:bc028d5a6424 214 if (DnsHdrIsRecursiveQuery) LogF(" Recursive query\r\n");
andrewboyson 43:bc028d5a6424 215 else LogF(" Non recursive query\r\n");
andrewboyson 43:bc028d5a6424 216 }
andrewboyson 43:bc028d5a6424 217 LogF(" qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount);
andrewboyson 15:6ca6778168b1 218 }
andrewboyson 15:6ca6778168b1 219 else
andrewboyson 15:6ca6778168b1 220 {
andrewboyson 47:73af5c0b0dc2 221 DnsProtocolLog(protocol);
andrewboyson 47:73af5c0b0dc2 222 LogF(" header qd, an, ns, ar %hu, %hu, %hu, %hu\r\n", DnsHdrQdcount, DnsHdrAncount, DnsHdrNscount, DnsHdrArcount);
andrewboyson 15:6ca6778168b1 223 }
andrewboyson 37:793b39683406 224 logContent();
andrewboyson 13:9cd54f7db57a 225 }
andrewboyson 13:9cd54f7db57a 226