Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Dec 12 20:10:02 2020 +0000
Revision:
171:f708d6776752
Parent:
170:96c637dc3f52
Modified NR to accept both IPV6 and IPV4 addresses instead of having two modules with diffrent address lengths. Encapsulated 32but address into lsb 128 bit address

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 #include <string.h>
andrewboyson 61:aad055f1b0d1 4
andrewboyson 60:1d8c7a1e7483 5 #include "log.h"
andrewboyson 93:580fc113d9e9 6 #include "mstimer.h"
andrewboyson 60:1d8c7a1e7483 7 #include "net.h"
andrewboyson 60:1d8c7a1e7483 8 #include "mac.h"
andrewboyson 60:1d8c7a1e7483 9 #include "ip6addr.h"
andrewboyson 128:79052cb4a41c 10 #include "dhcp.h"
andrewboyson 60:1d8c7a1e7483 11 #include "dns.h"
andrewboyson 60:1d8c7a1e7483 12 #include "dnsquery.h"
andrewboyson 128:79052cb4a41c 13 #include "dnslabel.h"
andrewboyson 60:1d8c7a1e7483 14 #include "http.h"
andrewboyson 60:1d8c7a1e7483 15
andrewboyson 60:1d8c7a1e7483 16 bool Nr6Trace = false;
andrewboyson 60:1d8c7a1e7483 17
andrewboyson 93:580fc113d9e9 18 #define NAME_MAX_LENGTH 20
andrewboyson 170:96c637dc3f52 19 #define CACHE_TIMEOUT_MS 3600 * 1000
andrewboyson 170:96c637dc3f52 20 #define STALE_TIMEOUT_MS 1800 * 1000
andrewboyson 171:f708d6776752 21 #define EMPTY_TIMEOUT_MS 300 * 1000
andrewboyson 171:f708d6776752 22 #define REPLY_TIMEOUT_MS 100
andrewboyson 60:1d8c7a1e7483 23
andrewboyson 60:1d8c7a1e7483 24 #define RECORDS_COUNT 20
andrewboyson 60:1d8c7a1e7483 25
andrewboyson 60:1d8c7a1e7483 26 #define STATE_EMPTY 0
andrewboyson 60:1d8c7a1e7483 27 #define STATE_WANT 1
andrewboyson 60:1d8c7a1e7483 28 #define STATE_SENT 2
andrewboyson 60:1d8c7a1e7483 29 #define STATE_VALID 3
andrewboyson 60:1d8c7a1e7483 30
andrewboyson 171:f708d6776752 31 #define TODO_NONE 0
andrewboyson 171:f708d6776752 32 #define TODO_NAME_FROM_IP 1
andrewboyson 171:f708d6776752 33 #define TODO_IP4_FROM_NAME 2
andrewboyson 171:f708d6776752 34 #define TODO_IP6_FROM_NAME 3
andrewboyson 60:1d8c7a1e7483 35
andrewboyson 60:1d8c7a1e7483 36 struct record
andrewboyson 60:1d8c7a1e7483 37 {
andrewboyson 171:f708d6776752 38 uint32_t replyMs;
andrewboyson 171:f708d6776752 39 uint32_t ageMs;
andrewboyson 60:1d8c7a1e7483 40 char ip[16];
andrewboyson 60:1d8c7a1e7483 41 uint8_t todo;
andrewboyson 60:1d8c7a1e7483 42 uint8_t state;
andrewboyson 171:f708d6776752 43 uint8_t dnsProtocol;
andrewboyson 171:f708d6776752 44 uint8_t ipProtocol;
andrewboyson 60:1d8c7a1e7483 45 char name[NAME_MAX_LENGTH];
andrewboyson 60:1d8c7a1e7483 46 };
andrewboyson 60:1d8c7a1e7483 47 static struct record records[RECORDS_COUNT];
andrewboyson 60:1d8c7a1e7483 48
andrewboyson 60:1d8c7a1e7483 49 static int getExistingIp(char* ip)
andrewboyson 60:1d8c7a1e7483 50 {
andrewboyson 60:1d8c7a1e7483 51 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 52 {
andrewboyson 60:1d8c7a1e7483 53 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 60:1d8c7a1e7483 54 if (Ip6AddressIsSame(records[i].ip, ip)) return i;
andrewboyson 60:1d8c7a1e7483 55 }
andrewboyson 60:1d8c7a1e7483 56 return -1;
andrewboyson 60:1d8c7a1e7483 57 }
andrewboyson 60:1d8c7a1e7483 58 static int getExistingName(char* name)
andrewboyson 60:1d8c7a1e7483 59 {
andrewboyson 60:1d8c7a1e7483 60 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 61 {
andrewboyson 60:1d8c7a1e7483 62 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 128:79052cb4a41c 63 if (DnsLabelIsSame(records[i].name, name)) return i;
andrewboyson 60:1d8c7a1e7483 64 }
andrewboyson 60:1d8c7a1e7483 65 return -1;
andrewboyson 60:1d8c7a1e7483 66 }
andrewboyson 60:1d8c7a1e7483 67 static int getNameOnly(char* name)
andrewboyson 60:1d8c7a1e7483 68 {
andrewboyson 60:1d8c7a1e7483 69 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 70 {
andrewboyson 60:1d8c7a1e7483 71 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 60:1d8c7a1e7483 72 if (!Ip6AddressIsEmpty(records[i].ip)) continue;
andrewboyson 128:79052cb4a41c 73 if (DnsLabelIsSame(records[i].name, name)) return i;
andrewboyson 60:1d8c7a1e7483 74 }
andrewboyson 60:1d8c7a1e7483 75 return -1;
andrewboyson 60:1d8c7a1e7483 76 }
andrewboyson 170:96c637dc3f52 77 static int getIpOnly(char* ip)
andrewboyson 170:96c637dc3f52 78 {
andrewboyson 170:96c637dc3f52 79 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 170:96c637dc3f52 80 {
andrewboyson 170:96c637dc3f52 81 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 170:96c637dc3f52 82 if (records[i].name[0] != 0) continue;
andrewboyson 170:96c637dc3f52 83 if (Ip6AddressIsSame(records[i].ip, ip)) return i;
andrewboyson 170:96c637dc3f52 84 }
andrewboyson 170:96c637dc3f52 85 return -1;
andrewboyson 170:96c637dc3f52 86 }
andrewboyson 60:1d8c7a1e7483 87 static int getOldest()
andrewboyson 60:1d8c7a1e7483 88 {
andrewboyson 93:580fc113d9e9 89 int iOldest = 0;
andrewboyson 93:580fc113d9e9 90 uint32_t ageOldest = 0;
andrewboyson 60:1d8c7a1e7483 91 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 92 {
andrewboyson 60:1d8c7a1e7483 93 if (records[i].state == STATE_EMPTY) return i; //Found an empty slot so just return it
andrewboyson 171:f708d6776752 94 uint32_t age = MsTimerCount - records[i].ageMs;
andrewboyson 93:580fc113d9e9 95 if (age >= ageOldest)
andrewboyson 60:1d8c7a1e7483 96 {
andrewboyson 93:580fc113d9e9 97 ageOldest = age;
andrewboyson 93:580fc113d9e9 98 iOldest = i;
andrewboyson 60:1d8c7a1e7483 99 }
andrewboyson 60:1d8c7a1e7483 100 }
andrewboyson 93:580fc113d9e9 101 return iOldest; //Otherwise return the oldest
andrewboyson 60:1d8c7a1e7483 102 }
andrewboyson 171:f708d6776752 103 static void makeRequestForNameFromIp(char* ip)
andrewboyson 60:1d8c7a1e7483 104 {
andrewboyson 60:1d8c7a1e7483 105 //Don't treat non ips
andrewboyson 60:1d8c7a1e7483 106 if (!ip[0]) return;
andrewboyson 60:1d8c7a1e7483 107 int i;
andrewboyson 60:1d8c7a1e7483 108
andrewboyson 60:1d8c7a1e7483 109 //If a record already exists then request an update
andrewboyson 60:1d8c7a1e7483 110 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 111 if (i > -1)
andrewboyson 60:1d8c7a1e7483 112 {
andrewboyson 171:f708d6776752 113 if (records[i].state == STATE_WANT || records[i].state == STATE_SENT) return;
andrewboyson 170:96c637dc3f52 114 if (records[i].name[0] == 0)
andrewboyson 170:96c637dc3f52 115 {
andrewboyson 171:f708d6776752 116 if (!MsTimerRelative(records[i].ageMs, EMPTY_TIMEOUT_MS)) return;
andrewboyson 170:96c637dc3f52 117 }
andrewboyson 170:96c637dc3f52 118 else
andrewboyson 170:96c637dc3f52 119 {
andrewboyson 171:f708d6776752 120 if (!MsTimerRelative(records[i].ageMs, STALE_TIMEOUT_MS)) return;
andrewboyson 170:96c637dc3f52 121 }
andrewboyson 60:1d8c7a1e7483 122 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 123 {
andrewboyson 60:1d8c7a1e7483 124 LogTimeF("NR - renew name of ");
andrewboyson 60:1d8c7a1e7483 125 Ip6AddressLog(ip);
andrewboyson 60:1d8c7a1e7483 126 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 127 }
andrewboyson 171:f708d6776752 128 //Leave the ip as is
andrewboyson 171:f708d6776752 129 //Leave the name as is
andrewboyson 171:f708d6776752 130 //Leave age as is
andrewboyson 60:1d8c7a1e7483 131 }
andrewboyson 171:f708d6776752 132 else
andrewboyson 60:1d8c7a1e7483 133 {
andrewboyson 171:f708d6776752 134 //If a record does not exist then find the first empty slot and add the IP and date
andrewboyson 171:f708d6776752 135 if (Nr6Trace)
andrewboyson 171:f708d6776752 136 {
andrewboyson 171:f708d6776752 137 LogTimeF("NR - request name of ");
andrewboyson 171:f708d6776752 138 Ip6AddressLog(ip);
andrewboyson 171:f708d6776752 139 Log("\r\n");
andrewboyson 171:f708d6776752 140 }
andrewboyson 171:f708d6776752 141 i = getOldest();
andrewboyson 171:f708d6776752 142 Ip6AddressCopy(records[i].ip, ip); //Set the ip
andrewboyson 171:f708d6776752 143 records[i].name[0] = 0; //Clear the name
andrewboyson 171:f708d6776752 144 records[i].ageMs = MsTimerCount; //Start age
andrewboyson 60:1d8c7a1e7483 145 }
andrewboyson 171:f708d6776752 146 records[i].todo = TODO_NAME_FROM_IP;
andrewboyson 171:f708d6776752 147 records[i].state = STATE_WANT;
andrewboyson 171:f708d6776752 148 records[i].dnsProtocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
andrewboyson 60:1d8c7a1e7483 149 }
andrewboyson 171:f708d6776752 150 static void makeRequestForIpFromName(char* name, int todo)
andrewboyson 60:1d8c7a1e7483 151 {
andrewboyson 60:1d8c7a1e7483 152 //Don't treat non names
andrewboyson 60:1d8c7a1e7483 153 if (!name[0]) return;
andrewboyson 60:1d8c7a1e7483 154 int i;
andrewboyson 60:1d8c7a1e7483 155
andrewboyson 60:1d8c7a1e7483 156 //If a record already exists then request an update
andrewboyson 60:1d8c7a1e7483 157 i = getExistingName(name);
andrewboyson 60:1d8c7a1e7483 158 if (i > -1)
andrewboyson 60:1d8c7a1e7483 159 {
andrewboyson 171:f708d6776752 160 if (records[i].state == STATE_WANT || records[i].state == STATE_SENT) return;
andrewboyson 170:96c637dc3f52 161 if (Ip6AddressIsEmpty(records[i].ip))
andrewboyson 170:96c637dc3f52 162 {
andrewboyson 171:f708d6776752 163 if (!MsTimerRelative(records[i].ageMs, EMPTY_TIMEOUT_MS)) return;
andrewboyson 170:96c637dc3f52 164 }
andrewboyson 170:96c637dc3f52 165 else
andrewboyson 170:96c637dc3f52 166 {
andrewboyson 171:f708d6776752 167 if (!MsTimerRelative(records[i].ageMs, STALE_TIMEOUT_MS)) return;
andrewboyson 170:96c637dc3f52 168 }
andrewboyson 60:1d8c7a1e7483 169 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 170 {
andrewboyson 60:1d8c7a1e7483 171 LogTimeF("NR - renew IPv6 of %s\r\n", name);
andrewboyson 60:1d8c7a1e7483 172 }
andrewboyson 171:f708d6776752 173 //Leave name as is
andrewboyson 171:f708d6776752 174 //Leave the ip as is
andrewboyson 171:f708d6776752 175 //Leave age as is
andrewboyson 60:1d8c7a1e7483 176 }
andrewboyson 171:f708d6776752 177 else
andrewboyson 171:f708d6776752 178 {
andrewboyson 171:f708d6776752 179 //If a record does not exist then find the first empty slot and add the name and date
andrewboyson 171:f708d6776752 180 if (Nr6Trace)
andrewboyson 171:f708d6776752 181 {
andrewboyson 171:f708d6776752 182 LogTimeF("NR - request IPv6 of %s\r\n", name);
andrewboyson 171:f708d6776752 183 }
andrewboyson 171:f708d6776752 184 i = getOldest();
andrewboyson 171:f708d6776752 185 strncpy(records[i].name, name, NAME_MAX_LENGTH); //Set the name
andrewboyson 171:f708d6776752 186 records[i].name[NAME_MAX_LENGTH - 1] = 0;
andrewboyson 171:f708d6776752 187 Ip6AddressClear(records[i].ip); //Clear the ip
andrewboyson 171:f708d6776752 188 records[i].ageMs = MsTimerCount; //Start age
andrewboyson 60:1d8c7a1e7483 189 }
andrewboyson 171:f708d6776752 190 records[i].todo = todo;
andrewboyson 171:f708d6776752 191 records[i].state = STATE_WANT;
andrewboyson 171:f708d6776752 192 records[i].dnsProtocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
andrewboyson 171:f708d6776752 193 }
andrewboyson 171:f708d6776752 194 static void updateIpRecord(int i, char* ip, char* name, int dnsProtocol)
andrewboyson 171:f708d6776752 195 {
andrewboyson 171:f708d6776752 196 records[i].todo = TODO_NONE;
andrewboyson 171:f708d6776752 197 records[i].ageMs = MsTimerCount;
andrewboyson 171:f708d6776752 198 Ip6AddressCopy(records[i].ip, ip);
andrewboyson 171:f708d6776752 199 records[i].dnsProtocol = dnsProtocol;
andrewboyson 171:f708d6776752 200 records[i].state = STATE_VALID;
andrewboyson 60:1d8c7a1e7483 201 strncpy(records[i].name, name, NAME_MAX_LENGTH);
andrewboyson 60:1d8c7a1e7483 202 records[i].name[NAME_MAX_LENGTH - 1] = 0;
andrewboyson 60:1d8c7a1e7483 203 }
andrewboyson 171:f708d6776752 204 void addIpRecord(char* ip, char* name, int dnsProtocol)
andrewboyson 60:1d8c7a1e7483 205 {
andrewboyson 171:f708d6776752 206 /*
andrewboyson 171:f708d6776752 207 A number of situations may need to be handled:
andrewboyson 171:f708d6776752 208 - An existing ip with the same name ; the usual situation : just reset the elapsed time and return
andrewboyson 171:f708d6776752 209 - An existing ip with no or a different name; usual if we are resolving an ip : add or update the ip of this record
andrewboyson 171:f708d6776752 210 - Same name with an empty ip ; usual if we are resolving a name : add the ip to this record
andrewboyson 171:f708d6776752 211 - Same name with another ip ; normal situation : do nothing
andrewboyson 171:f708d6776752 212 - No existing ip or name ; usual if another device has done a reolution : add a new record and return
andrewboyson 171:f708d6776752 213
andrewboyson 171:f708d6776752 214 Quite often we will simultaneously attempt to resolve both the name and the ip of the same device.
andrewboyson 171:f708d6776752 215 When this happens there will be two entriesone with the ame and an empty ip; the othert with the ip but and an empty name.
andrewboyson 171:f708d6776752 216 In this case we first add the name to the existing ip but also check for the name with an empty ip and delete it.
andrewboyson 171:f708d6776752 217 */
andrewboyson 171:f708d6776752 218
andrewboyson 60:1d8c7a1e7483 219 int i;
andrewboyson 60:1d8c7a1e7483 220
andrewboyson 170:96c637dc3f52 221 //Print what is being handled
andrewboyson 170:96c637dc3f52 222 if (Nr6Trace)
andrewboyson 170:96c637dc3f52 223 {
andrewboyson 171:f708d6776752 224 LogTimeF("NR - received ");
andrewboyson 170:96c637dc3f52 225 Ip6AddressLog(ip);
andrewboyson 170:96c637dc3f52 226 Log(" == '");
andrewboyson 170:96c637dc3f52 227 Log(name);
andrewboyson 170:96c637dc3f52 228 Log("'\r\n");
andrewboyson 170:96c637dc3f52 229 }
andrewboyson 170:96c637dc3f52 230
andrewboyson 170:96c637dc3f52 231 //Ignore records which do not have both ip and name
andrewboyson 170:96c637dc3f52 232 if (Ip6AddressIsEmpty(ip) || name == 0 || name[0] == 0)
andrewboyson 170:96c637dc3f52 233 {
andrewboyson 171:f708d6776752 234 if (Nr6Trace) LogTimeF("NR - ignoring invalid entry\r\n");
andrewboyson 170:96c637dc3f52 235 return;
andrewboyson 170:96c637dc3f52 236 }
andrewboyson 170:96c637dc3f52 237
andrewboyson 60:1d8c7a1e7483 238 //Get existing ip and, if found, add it then clear any name only entries
andrewboyson 60:1d8c7a1e7483 239 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 240 if (i >= 0)
andrewboyson 60:1d8c7a1e7483 241 {
andrewboyson 60:1d8c7a1e7483 242 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 243 {
andrewboyson 170:96c637dc3f52 244 if (DnsLabelIsSame(name, records[i].name))
andrewboyson 170:96c637dc3f52 245 {
andrewboyson 171:f708d6776752 246 LogTimeF("NR record %d - refresh existing entry\r\n", i);
andrewboyson 170:96c637dc3f52 247 }
andrewboyson 170:96c637dc3f52 248 else
andrewboyson 170:96c637dc3f52 249 {
andrewboyson 171:f708d6776752 250 LogTimeF("NR record %d - update entry name from '%s' to '%s'\r\n", i, records[i].name, name);
andrewboyson 170:96c637dc3f52 251 }
andrewboyson 60:1d8c7a1e7483 252 }
andrewboyson 171:f708d6776752 253 updateIpRecord(i, ip, name, dnsProtocol);
andrewboyson 60:1d8c7a1e7483 254
andrewboyson 60:1d8c7a1e7483 255 i = getNameOnly(name);
andrewboyson 60:1d8c7a1e7483 256 if (i >= 0)
andrewboyson 60:1d8c7a1e7483 257 {
andrewboyson 170:96c637dc3f52 258 if (Nr6Trace) LogTimeF("NR record %d - clear name '%s' with no ip\r\n", i, name);
andrewboyson 60:1d8c7a1e7483 259 records[i].state = STATE_EMPTY;
andrewboyson 60:1d8c7a1e7483 260 }
andrewboyson 60:1d8c7a1e7483 261 return;
andrewboyson 60:1d8c7a1e7483 262 }
andrewboyson 60:1d8c7a1e7483 263
andrewboyson 60:1d8c7a1e7483 264 //Get name only entry and, if found, add it
andrewboyson 60:1d8c7a1e7483 265 i = getNameOnly(name);
andrewboyson 60:1d8c7a1e7483 266 if (i >= 0)
andrewboyson 60:1d8c7a1e7483 267 {
andrewboyson 60:1d8c7a1e7483 268 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 269 {
andrewboyson 171:f708d6776752 270 LogTimeF("NR record %d - add ip ", i);
andrewboyson 60:1d8c7a1e7483 271 Ip6AddressLog(ip);
andrewboyson 170:96c637dc3f52 272 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 273 }
andrewboyson 171:f708d6776752 274 updateIpRecord(i, ip, name, dnsProtocol);
andrewboyson 60:1d8c7a1e7483 275 return;
andrewboyson 60:1d8c7a1e7483 276 }
andrewboyson 60:1d8c7a1e7483 277
andrewboyson 60:1d8c7a1e7483 278 //No other entry exists so just add it to the next available space
andrewboyson 60:1d8c7a1e7483 279 i = getOldest();
andrewboyson 60:1d8c7a1e7483 280 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 281 {
andrewboyson 171:f708d6776752 282 LogTimeF("NR record %d - add entry\r\n", i);
andrewboyson 60:1d8c7a1e7483 283 }
andrewboyson 171:f708d6776752 284 updateIpRecord(i, ip, name, dnsProtocol);
andrewboyson 60:1d8c7a1e7483 285 }
andrewboyson 171:f708d6776752 286 static void ipToName(char* ip, char* name)
andrewboyson 60:1d8c7a1e7483 287 {
andrewboyson 60:1d8c7a1e7483 288 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 289 {
andrewboyson 60:1d8c7a1e7483 290 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 60:1d8c7a1e7483 291 if (Ip6AddressIsSame(records[i].ip, ip))
andrewboyson 60:1d8c7a1e7483 292 {
andrewboyson 60:1d8c7a1e7483 293 strcpy(name, records[i].name);
andrewboyson 60:1d8c7a1e7483 294 return;
andrewboyson 60:1d8c7a1e7483 295 }
andrewboyson 60:1d8c7a1e7483 296 }
andrewboyson 60:1d8c7a1e7483 297 name[0] = 0;
andrewboyson 60:1d8c7a1e7483 298 }
andrewboyson 171:f708d6776752 299 static void nameToIp(char* name, char* ip)
andrewboyson 60:1d8c7a1e7483 300 {
andrewboyson 93:580fc113d9e9 301 uint32_t newest = 0xFFFFFFFF;
andrewboyson 60:1d8c7a1e7483 302 Ip6AddressClear(ip);
andrewboyson 60:1d8c7a1e7483 303 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 304 {
andrewboyson 60:1d8c7a1e7483 305 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 60:1d8c7a1e7483 306 if(Ip6AddressIsEmpty(records[i].ip)) continue;
andrewboyson 128:79052cb4a41c 307 if (!DnsLabelIsSame(records[i].name, name)) continue;
andrewboyson 171:f708d6776752 308 uint32_t age = MsTimerCount - records[i].ageMs;
andrewboyson 93:580fc113d9e9 309 if (age <= newest)
andrewboyson 60:1d8c7a1e7483 310 {
andrewboyson 93:580fc113d9e9 311 newest = age;
andrewboyson 60:1d8c7a1e7483 312 Ip6AddressCopy(ip, records[i].ip);
andrewboyson 60:1d8c7a1e7483 313 }
andrewboyson 60:1d8c7a1e7483 314 }
andrewboyson 60:1d8c7a1e7483 315 }
andrewboyson 171:f708d6776752 316 void Nr6MakeRequestForNameFromIp(char* ip)
andrewboyson 171:f708d6776752 317 {
andrewboyson 171:f708d6776752 318 makeRequestForNameFromIp(ip);
andrewboyson 171:f708d6776752 319 }
andrewboyson 171:f708d6776752 320 void Nr4MakeRequestForNameFromIp(uint32_t ip4)
andrewboyson 171:f708d6776752 321 {
andrewboyson 171:f708d6776752 322 char ip6[16];
andrewboyson 171:f708d6776752 323 Ip6AddressFromIp4(ip6, ip4);
andrewboyson 171:f708d6776752 324 makeRequestForNameFromIp(ip6);
andrewboyson 171:f708d6776752 325 }
andrewboyson 171:f708d6776752 326 void Nr6MakeRequestForIpFromName(char* name)
andrewboyson 171:f708d6776752 327 {
andrewboyson 171:f708d6776752 328 makeRequestForIpFromName(name, TODO_IP6_FROM_NAME);
andrewboyson 171:f708d6776752 329 }
andrewboyson 171:f708d6776752 330 void Nr4MakeRequestForIpFromName(char* name)
andrewboyson 171:f708d6776752 331 {
andrewboyson 171:f708d6776752 332 makeRequestForIpFromName(name, TODO_IP4_FROM_NAME);
andrewboyson 171:f708d6776752 333 }
andrewboyson 171:f708d6776752 334 void Nr6AddIpRecord(char* ip, char* name, int dnsProtocol)
andrewboyson 171:f708d6776752 335 {
andrewboyson 171:f708d6776752 336 addIpRecord(ip, name, dnsProtocol);
andrewboyson 171:f708d6776752 337 }
andrewboyson 171:f708d6776752 338 void Nr4AddIpRecord(uint32_t ip4, char* name, int dnsProtocol)
andrewboyson 116:60521b29e4c9 339 {
andrewboyson 171:f708d6776752 340 char ip6[16];
andrewboyson 171:f708d6776752 341 Ip6AddressFromIp4(ip6, ip4);
andrewboyson 171:f708d6776752 342 addIpRecord(ip6, name, dnsProtocol);
andrewboyson 171:f708d6776752 343 }
andrewboyson 171:f708d6776752 344 void Nr6NameToIp(char* name, char* ip)
andrewboyson 171:f708d6776752 345 {
andrewboyson 171:f708d6776752 346 nameToIp(name, ip);
andrewboyson 116:60521b29e4c9 347 }
andrewboyson 171:f708d6776752 348 void Nr4NameToIp(char* name, uint32_t* pIp)
andrewboyson 171:f708d6776752 349 {
andrewboyson 171:f708d6776752 350 char ip6[16];
andrewboyson 171:f708d6776752 351 nameToIp(name, ip6);
andrewboyson 171:f708d6776752 352 *pIp = Ip6AddressToIp4(ip6);
andrewboyson 171:f708d6776752 353 }
andrewboyson 171:f708d6776752 354 void Nr6IpToName(char* ip, char* name)
andrewboyson 171:f708d6776752 355 {
andrewboyson 171:f708d6776752 356 ipToName(ip, name);
andrewboyson 171:f708d6776752 357 }
andrewboyson 171:f708d6776752 358 void Nr4IpToName(uint32_t ip4, char* name)
andrewboyson 171:f708d6776752 359 {
andrewboyson 171:f708d6776752 360 char ip6[16];
andrewboyson 171:f708d6776752 361 Ip6AddressFromIp4(ip6, ip4);
andrewboyson 171:f708d6776752 362 ipToName(ip6, name);
andrewboyson 171:f708d6776752 363 }
andrewboyson 171:f708d6776752 364 static char letterFromStateAndProtocol(uint8_t dnsState, uint8_t dnsProtocol)
andrewboyson 60:1d8c7a1e7483 365 {
andrewboyson 60:1d8c7a1e7483 366 switch (dnsState)
andrewboyson 60:1d8c7a1e7483 367 {
andrewboyson 60:1d8c7a1e7483 368 case STATE_WANT:
andrewboyson 60:1d8c7a1e7483 369 case STATE_SENT: return '>';
andrewboyson 60:1d8c7a1e7483 370
andrewboyson 60:1d8c7a1e7483 371 case STATE_VALID:
andrewboyson 171:f708d6776752 372 switch (dnsProtocol)
andrewboyson 60:1d8c7a1e7483 373 {
andrewboyson 60:1d8c7a1e7483 374 case DNS_PROTOCOL_UDNS: return 'd';
andrewboyson 60:1d8c7a1e7483 375 case DNS_PROTOCOL_MDNS: return 'm';
andrewboyson 60:1d8c7a1e7483 376 case DNS_PROTOCOL_LLMNR: return 'l';
andrewboyson 60:1d8c7a1e7483 377 case DNS_PROTOCOL_NONE: return '-';
andrewboyson 60:1d8c7a1e7483 378 default: return '?';
andrewboyson 60:1d8c7a1e7483 379 }
andrewboyson 60:1d8c7a1e7483 380 default: return '~';
andrewboyson 60:1d8c7a1e7483 381 }
andrewboyson 60:1d8c7a1e7483 382 }
andrewboyson 60:1d8c7a1e7483 383 void Nr6SendHttp()
andrewboyson 60:1d8c7a1e7483 384 {
andrewboyson 60:1d8c7a1e7483 385 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 386 {
andrewboyson 60:1d8c7a1e7483 387 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 60:1d8c7a1e7483 388 if (!Ip6AddressIsEmpty(records[i].ip) || records[i].name[0])
andrewboyson 60:1d8c7a1e7483 389 {
andrewboyson 171:f708d6776752 390 HttpAddF("%4u ", (MsTimerCount - records[i].ageMs) / 1000 / 60);
andrewboyson 60:1d8c7a1e7483 391
andrewboyson 171:f708d6776752 392 int ipLen;
andrewboyson 171:f708d6776752 393 ipLen = Ip6AddressHttp(records[i].ip);
andrewboyson 159:3ebef2d02f7f 394 HttpAddFillChar(' ', 40 - ipLen);
andrewboyson 60:1d8c7a1e7483 395
andrewboyson 171:f708d6776752 396 HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].dnsProtocol));
andrewboyson 60:1d8c7a1e7483 397
andrewboyson 60:1d8c7a1e7483 398 HttpAddChar(' ');
andrewboyson 60:1d8c7a1e7483 399
andrewboyson 60:1d8c7a1e7483 400 HttpAddText(records[i].name);
andrewboyson 60:1d8c7a1e7483 401
andrewboyson 60:1d8c7a1e7483 402 HttpAddChar('\r');
andrewboyson 60:1d8c7a1e7483 403 HttpAddChar('\n');
andrewboyson 60:1d8c7a1e7483 404 }
andrewboyson 60:1d8c7a1e7483 405 }
andrewboyson 60:1d8c7a1e7483 406 }
andrewboyson 140:9000ea70b220 407 void Nr6SendAjax()
andrewboyson 140:9000ea70b220 408 {
andrewboyson 140:9000ea70b220 409 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 140:9000ea70b220 410 {
andrewboyson 140:9000ea70b220 411 if (records[i].state == STATE_EMPTY) continue;
andrewboyson 140:9000ea70b220 412 if (!Ip6AddressIsEmpty(records[i].ip) || records[i].name[0])
andrewboyson 140:9000ea70b220 413 {
andrewboyson 167:3ba4e3c49631 414 HttpAddByteAsHex(i);
andrewboyson 167:3ba4e3c49631 415 HttpAddChar('\t');
andrewboyson 171:f708d6776752 416 HttpAddInt32AsHex(MsTimerCount - records[i].ageMs);
andrewboyson 167:3ba4e3c49631 417 HttpAddChar('\t');
andrewboyson 140:9000ea70b220 418 for (int b = 0; b < 16; b++) HttpAddByteAsHex(records[i].ip[b]);
andrewboyson 167:3ba4e3c49631 419 HttpAddChar('\t');
andrewboyson 171:f708d6776752 420 HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].dnsProtocol));
andrewboyson 167:3ba4e3c49631 421 HttpAddChar('\t');
andrewboyson 140:9000ea70b220 422 HttpAddText(records[i].name);
andrewboyson 140:9000ea70b220 423 HttpAddChar('\n');
andrewboyson 140:9000ea70b220 424 }
andrewboyson 140:9000ea70b220 425 }
andrewboyson 140:9000ea70b220 426 }
andrewboyson 60:1d8c7a1e7483 427 static void clearCache(struct record* pr)
andrewboyson 60:1d8c7a1e7483 428 {
andrewboyson 171:f708d6776752 429 if (MsTimerRelative(pr->ageMs, CACHE_TIMEOUT_MS)) pr->state = STATE_EMPTY;
andrewboyson 60:1d8c7a1e7483 430 }
andrewboyson 60:1d8c7a1e7483 431 static void nextProtocol(struct record* pr)
andrewboyson 60:1d8c7a1e7483 432 {
andrewboyson 171:f708d6776752 433 if (pr->state == STATE_SENT && MsTimerRelative(pr->replyMs, REPLY_TIMEOUT_MS) && pr->dnsProtocol)
andrewboyson 60:1d8c7a1e7483 434 {
andrewboyson 171:f708d6776752 435 pr->dnsProtocol = DnsGetNextProtocol(pr->dnsProtocol);
andrewboyson 171:f708d6776752 436 if (pr->dnsProtocol)
andrewboyson 60:1d8c7a1e7483 437 {
andrewboyson 60:1d8c7a1e7483 438 pr->state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 439 }
andrewboyson 171:f708d6776752 440 else //We have tried everything and resolution has failed
andrewboyson 60:1d8c7a1e7483 441 {
andrewboyson 60:1d8c7a1e7483 442 if (pr->todo == TODO_NAME_FROM_IP) pr->name[0] = 0;
andrewboyson 171:f708d6776752 443 if (pr->todo == TODO_IP4_FROM_NAME || pr->todo == TODO_IP6_FROM_NAME) Ip6AddressClear(pr->ip);
andrewboyson 171:f708d6776752 444 pr->todo = TODO_NONE;
andrewboyson 60:1d8c7a1e7483 445 pr->state = STATE_VALID;
andrewboyson 171:f708d6776752 446 pr->ageMs = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 447 }
andrewboyson 171:f708d6776752 448 pr->replyMs = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 449 }
andrewboyson 60:1d8c7a1e7483 450 }
andrewboyson 60:1d8c7a1e7483 451 static void queryNameFromIp(struct record* pr)
andrewboyson 60:1d8c7a1e7483 452 {
andrewboyson 60:1d8c7a1e7483 453 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 454 {
andrewboyson 60:1d8c7a1e7483 455 LogTime("NR - send ");
andrewboyson 171:f708d6776752 456 DnsProtocolLog(pr->dnsProtocol);
andrewboyson 171:f708d6776752 457 if (Ip6AddrIsIp4(pr->ip)) Log(" request for name from IP4 ");
andrewboyson 171:f708d6776752 458 else Log(" request for name from IP6 ");
andrewboyson 60:1d8c7a1e7483 459 Ip6AddressLog(pr->ip);
andrewboyson 60:1d8c7a1e7483 460 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 461 }
andrewboyson 171:f708d6776752 462 if (Ip6AddrIsIp4(pr->ip))
andrewboyson 171:f708d6776752 463 {
andrewboyson 171:f708d6776752 464 uint32_t ip4 = Ip6AddressToIp4(pr->ip);
andrewboyson 171:f708d6776752 465 DnsQueryNameFromIp4(ip4, pr->dnsProtocol, pr->ipProtocol);
andrewboyson 171:f708d6776752 466 }
andrewboyson 171:f708d6776752 467 else
andrewboyson 171:f708d6776752 468 {
andrewboyson 171:f708d6776752 469 DnsQueryNameFromIp6(pr->ip, pr->dnsProtocol, pr->ipProtocol);
andrewboyson 171:f708d6776752 470 }
andrewboyson 60:1d8c7a1e7483 471 }
andrewboyson 171:f708d6776752 472 static void queryIpFromName(struct record* pr, int todo)
andrewboyson 60:1d8c7a1e7483 473 {
andrewboyson 60:1d8c7a1e7483 474 if (Nr6Trace)
andrewboyson 60:1d8c7a1e7483 475 {
andrewboyson 60:1d8c7a1e7483 476 LogTime("NR - send ");
andrewboyson 171:f708d6776752 477 DnsProtocolLog(pr->dnsProtocol);
andrewboyson 171:f708d6776752 478 if (todo == TODO_IP4_FROM_NAME) Log(" request for IP4 from name '");
andrewboyson 171:f708d6776752 479 else Log(" request for IP6 from name '");
andrewboyson 60:1d8c7a1e7483 480 Log(pr->name);
andrewboyson 60:1d8c7a1e7483 481 Log("'\r\n");
andrewboyson 60:1d8c7a1e7483 482 }
andrewboyson 171:f708d6776752 483 if (todo == TODO_IP4_FROM_NAME) DnsQueryIp4FromName(pr->name, pr->dnsProtocol, pr->ipProtocol);
andrewboyson 171:f708d6776752 484 else DnsQueryIp6FromName(pr->name, pr->dnsProtocol, pr->ipProtocol);
andrewboyson 60:1d8c7a1e7483 485 }
andrewboyson 60:1d8c7a1e7483 486 static void sendRequest(struct record* pr)
andrewboyson 60:1d8c7a1e7483 487 {
andrewboyson 171:f708d6776752 488 if ( DnsQueryIsBusy ) return;
andrewboyson 171:f708d6776752 489 if ( pr->state != STATE_WANT ) return;
andrewboyson 171:f708d6776752 490 if (!pr->dnsProtocol ) return;
andrewboyson 60:1d8c7a1e7483 491
andrewboyson 171:f708d6776752 492 if (pr->todo == TODO_NAME_FROM_IP ) queryNameFromIp(pr);
andrewboyson 171:f708d6776752 493 if (pr->todo == TODO_IP4_FROM_NAME) queryIpFromName(pr, TODO_IP4_FROM_NAME);
andrewboyson 171:f708d6776752 494 if (pr->todo == TODO_IP6_FROM_NAME) queryIpFromName(pr, TODO_IP6_FROM_NAME);
andrewboyson 60:1d8c7a1e7483 495
andrewboyson 60:1d8c7a1e7483 496 pr->state = STATE_SENT;
andrewboyson 171:f708d6776752 497 pr->replyMs = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 498 }
andrewboyson 60:1d8c7a1e7483 499 void Nr6Main()
andrewboyson 60:1d8c7a1e7483 500 {
andrewboyson 60:1d8c7a1e7483 501 static int i = -1;
andrewboyson 60:1d8c7a1e7483 502 i++;
andrewboyson 60:1d8c7a1e7483 503 if (i >= RECORDS_COUNT) i = 0;
andrewboyson 60:1d8c7a1e7483 504
andrewboyson 60:1d8c7a1e7483 505 struct record* pr = &records[i];
andrewboyson 60:1d8c7a1e7483 506
andrewboyson 60:1d8c7a1e7483 507 clearCache (pr);
andrewboyson 60:1d8c7a1e7483 508 nextProtocol(pr);
andrewboyson 60:1d8c7a1e7483 509 sendRequest (pr);
andrewboyson 60:1d8c7a1e7483 510 }
andrewboyson 60:1d8c7a1e7483 511 void Nr6Init()
andrewboyson 60:1d8c7a1e7483 512 {
andrewboyson 60:1d8c7a1e7483 513 for (int i = 0; i < RECORDS_COUNT; i++) records[i].state = STATE_EMPTY;
andrewboyson 60:1d8c7a1e7483 514 }