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
resolve/nr6.c@171:f708d6776752, 2020-12-12 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |