Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Dec 23 09:52:47 2020 +0000
Revision:
173:9bc30cd82a76
Parent:
172:9bc3c7b2cca1
Child:
175:2d7aa004d881
Fixed problem with decoding 32 bit numbers in ndp

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 46:40d33e9037e4 5 #include "log.h"
andrewboyson 47:73af5c0b0dc2 6 #include "net.h"
andrewboyson 46:40d33e9037e4 7 #include "mac.h"
andrewboyson 49:1a6336f2b3f9 8 #include "ip6addr.h"
andrewboyson 46:40d33e9037e4 9 #include "slaac.h"
andrewboyson 119:8e1a7805b801 10 #include "rs.h"
andrewboyson 93:580fc113d9e9 11 #include "mstimer.h"
andrewboyson 46:40d33e9037e4 12
andrewboyson 47:73af5c0b0dc2 13 int NdpHopLimit = 0;
andrewboyson 47:73af5c0b0dc2 14 bool NdpManagedConfiguration = false;
andrewboyson 47:73af5c0b0dc2 15 bool NdpOtherConfiguration = false;
andrewboyson 46:40d33e9037e4 16
andrewboyson 46:40d33e9037e4 17 char NdpRouterMac[6];
andrewboyson 46:40d33e9037e4 18
andrewboyson 172:9bc3c7b2cca1 19
andrewboyson 172:9bc3c7b2cca1 20 int NdpGlobalPrefixLength = 0;
andrewboyson 172:9bc3c7b2cca1 21 bool NdpGlobalPrefixFlagL = false;
andrewboyson 172:9bc3c7b2cca1 22 bool NdpGlobalPrefixFlagA = false;
andrewboyson 172:9bc3c7b2cca1 23 uint32_t NdpGlobalPrefixValidLifetime = 0;
andrewboyson 172:9bc3c7b2cca1 24 uint32_t NdpGlobalPrefixPreferredLifetime = 0;
andrewboyson 172:9bc3c7b2cca1 25 char NdpGlobalPrefix[16];
andrewboyson 172:9bc3c7b2cca1 26
andrewboyson 172:9bc3c7b2cca1 27 int NdpUniqueLocalPrefixLength = 0;
andrewboyson 172:9bc3c7b2cca1 28 bool NdpUniqueLocalPrefixFlagL = false;
andrewboyson 172:9bc3c7b2cca1 29 bool NdpUniqueLocalPrefixFlagA = false;
andrewboyson 172:9bc3c7b2cca1 30 uint32_t NdpUniqueLocalPrefixValidLifetime = 0;
andrewboyson 172:9bc3c7b2cca1 31 uint32_t NdpUniqueLocalPrefixPreferredLifetime = 0;
andrewboyson 172:9bc3c7b2cca1 32 char NdpUniqueLocalPrefix[16];
andrewboyson 46:40d33e9037e4 33
andrewboyson 46:40d33e9037e4 34 uint32_t NdpDnsLifetime = 0;
andrewboyson 46:40d33e9037e4 35 char NdpDnsServer[16];
andrewboyson 46:40d33e9037e4 36
andrewboyson 46:40d33e9037e4 37 int NdpMtu = 0;
andrewboyson 46:40d33e9037e4 38
andrewboyson 119:8e1a7805b801 39 static uint32_t elapsedLifeMsTimer = 0;
andrewboyson 93:580fc113d9e9 40
andrewboyson 93:580fc113d9e9 41 uint32_t NdpGetElapsedLife()
andrewboyson 93:580fc113d9e9 42 {
andrewboyson 119:8e1a7805b801 43 return (MsTimerCount - elapsedLifeMsTimer) / 1000;
andrewboyson 119:8e1a7805b801 44 }
andrewboyson 119:8e1a7805b801 45 static int lease = 0;
andrewboyson 119:8e1a7805b801 46 int NdpGetLease() { return lease; }
andrewboyson 119:8e1a7805b801 47 void NdpSetLease(int value) //Set whenever an IP address request has been acknowledged
andrewboyson 119:8e1a7805b801 48 {
andrewboyson 119:8e1a7805b801 49 lease = value;
andrewboyson 119:8e1a7805b801 50 elapsedLifeMsTimer = MsTimerCount;
andrewboyson 93:580fc113d9e9 51 }
andrewboyson 119:8e1a7805b801 52 bool NdpIsFresh()
andrewboyson 93:580fc113d9e9 53 {
andrewboyson 119:8e1a7805b801 54 uint32_t elapsedLifeMs = MsTimerCount - elapsedLifeMsTimer;
andrewboyson 119:8e1a7805b801 55 uint32_t leaseMs = lease * 1000;
andrewboyson 119:8e1a7805b801 56
andrewboyson 119:8e1a7805b801 57 if (lease && elapsedLifeMs < (leaseMs >> 1)) return true; //Fresh if within half the lease
andrewboyson 119:8e1a7805b801 58
andrewboyson 119:8e1a7805b801 59 if (!lease || elapsedLifeMs >= leaseMs)
andrewboyson 119:8e1a7805b801 60 {
andrewboyson 119:8e1a7805b801 61 if (lease)
andrewboyson 119:8e1a7805b801 62 {
andrewboyson 119:8e1a7805b801 63 if (NetTraceNewLine) Log("\r\n");
andrewboyson 119:8e1a7805b801 64 LogTime("NDP lease has expired -> clearing NDP information\r\n");
andrewboyson 119:8e1a7805b801 65 }
andrewboyson 119:8e1a7805b801 66 elapsedLifeMsTimer = MsTimerCount;
andrewboyson 172:9bc3c7b2cca1 67 Ip6AddrClear(SlaacUniqueLocalIp);
andrewboyson 172:9bc3c7b2cca1 68 Ip6AddrClear(SlaacGlobalIp);
andrewboyson 172:9bc3c7b2cca1 69 Ip6AddrClear(NdpDnsServer);
andrewboyson 119:8e1a7805b801 70 }
andrewboyson 119:8e1a7805b801 71
andrewboyson 119:8e1a7805b801 72 return false;
andrewboyson 93:580fc113d9e9 73 }
andrewboyson 46:40d33e9037e4 74
andrewboyson 46:40d33e9037e4 75 bool NdpIpNeedsToBeRouted(char* ip)
andrewboyson 46:40d33e9037e4 76 {
andrewboyson 46:40d33e9037e4 77 //Check address is assigned to internet
andrewboyson 172:9bc3c7b2cca1 78 if (!Ip6AddrIsGlobal(ip)) return false;
andrewboyson 119:8e1a7805b801 79
andrewboyson 46:40d33e9037e4 80 //Check it is not our own prefix
andrewboyson 172:9bc3c7b2cca1 81 if (memcmp(ip, NdpGlobalPrefix, 8) == 0) return false;
andrewboyson 119:8e1a7805b801 82
andrewboyson 46:40d33e9037e4 83 return true;
andrewboyson 46:40d33e9037e4 84 }
andrewboyson 46:40d33e9037e4 85
andrewboyson 46:40d33e9037e4 86 static uint32_t decodeUint32(char* p)
andrewboyson 46:40d33e9037e4 87 {
andrewboyson 173:9bc30cd82a76 88 uint32_t value;
andrewboyson 173:9bc30cd82a76 89 value = *p++;
andrewboyson 173:9bc30cd82a76 90 value = value << 8 | *p++;
andrewboyson 173:9bc30cd82a76 91 value = value << 8 | *p++;
andrewboyson 173:9bc30cd82a76 92 value = value << 8 | *p;
andrewboyson 46:40d33e9037e4 93 return value;
andrewboyson 46:40d33e9037e4 94 }
andrewboyson 47:73af5c0b0dc2 95 static int decodeOption(char* p, char* srcMac, char* dstMac)
andrewboyson 46:40d33e9037e4 96 {
andrewboyson 46:40d33e9037e4 97 int type = *p++;
andrewboyson 46:40d33e9037e4 98 int size = *p++;
andrewboyson 52:fbc5a46b5e16 99 if (size == 0) return 0;
andrewboyson 46:40d33e9037e4 100 switch (type)
andrewboyson 46:40d33e9037e4 101 {
andrewboyson 46:40d33e9037e4 102 case 1:
andrewboyson 47:73af5c0b0dc2 103 if (srcMac) MacCopy(srcMac, p);
andrewboyson 46:40d33e9037e4 104 break;
andrewboyson 46:40d33e9037e4 105 case 2:
andrewboyson 47:73af5c0b0dc2 106 if (dstMac) MacCopy(dstMac, p);
andrewboyson 46:40d33e9037e4 107 break;
andrewboyson 46:40d33e9037e4 108 case 3:
andrewboyson 172:9bc3c7b2cca1 109 {
andrewboyson 172:9bc3c7b2cca1 110 int length = *p; p += 1;
andrewboyson 172:9bc3c7b2cca1 111 uint8_t flags = *p; p += 1;
andrewboyson 172:9bc3c7b2cca1 112 uint32_t validLifetime = decodeUint32(p); p += 4;
andrewboyson 172:9bc3c7b2cca1 113 uint32_t preferredLifetime = decodeUint32(p); p += 4;
andrewboyson 172:9bc3c7b2cca1 114 /*Ignore the reserved2 field*/ p += 4;
andrewboyson 172:9bc3c7b2cca1 115 if (Ip6AddrIsGlobal(p))
andrewboyson 172:9bc3c7b2cca1 116 {
andrewboyson 172:9bc3c7b2cca1 117 Ip6AddrCopy(NdpGlobalPrefix, p);
andrewboyson 172:9bc3c7b2cca1 118 NdpGlobalPrefixLength = length;
andrewboyson 172:9bc3c7b2cca1 119 NdpGlobalPrefixFlagL = flags & 0x80;
andrewboyson 172:9bc3c7b2cca1 120 NdpGlobalPrefixFlagA = flags & 0x40;
andrewboyson 172:9bc3c7b2cca1 121 NdpGlobalPrefixValidLifetime = validLifetime;
andrewboyson 172:9bc3c7b2cca1 122 NdpGlobalPrefixPreferredLifetime = preferredLifetime;
andrewboyson 172:9bc3c7b2cca1 123 SlaacMakeGlobal(p);
andrewboyson 172:9bc3c7b2cca1 124 }
andrewboyson 172:9bc3c7b2cca1 125 else if (Ip6AddrIsUniqueLocal(p))
andrewboyson 172:9bc3c7b2cca1 126 {
andrewboyson 172:9bc3c7b2cca1 127 Ip6AddrCopy(NdpUniqueLocalPrefix, p);
andrewboyson 172:9bc3c7b2cca1 128 NdpUniqueLocalPrefixLength = length;
andrewboyson 172:9bc3c7b2cca1 129 NdpUniqueLocalPrefixFlagL = flags & 0x80;
andrewboyson 172:9bc3c7b2cca1 130 NdpUniqueLocalPrefixFlagA = flags & 0x40;
andrewboyson 172:9bc3c7b2cca1 131 NdpUniqueLocalPrefixValidLifetime = validLifetime;
andrewboyson 172:9bc3c7b2cca1 132 NdpUniqueLocalPrefixPreferredLifetime = preferredLifetime;
andrewboyson 172:9bc3c7b2cca1 133 SlaacMakeUniqueLocal(p);
andrewboyson 172:9bc3c7b2cca1 134 }
andrewboyson 172:9bc3c7b2cca1 135 break;
andrewboyson 172:9bc3c7b2cca1 136 }
andrewboyson 46:40d33e9037e4 137 case 5:
andrewboyson 53:77f8a49adf89 138 /*Ignore the reserved field*/ p += 2;
andrewboyson 46:40d33e9037e4 139 NdpMtu = decodeUint32(p);
andrewboyson 46:40d33e9037e4 140 break;
andrewboyson 46:40d33e9037e4 141 case 25:
andrewboyson 53:77f8a49adf89 142 /*Ignore the reserved field*/ p += 2;
andrewboyson 53:77f8a49adf89 143 NdpDnsLifetime = decodeUint32(p); p += 4;
andrewboyson 172:9bc3c7b2cca1 144 Ip6AddrCopy(NdpDnsServer, p);
andrewboyson 46:40d33e9037e4 145 break;
andrewboyson 46:40d33e9037e4 146 }
andrewboyson 46:40d33e9037e4 147 return size * 8;
andrewboyson 46:40d33e9037e4 148 }
andrewboyson 53:77f8a49adf89 149 static void logFlagsLA(char flags)
andrewboyson 53:77f8a49adf89 150 {
andrewboyson 121:bc048b65a630 151 if (flags & 0x80) LogChar('L');
andrewboyson 121:bc048b65a630 152 if (flags & 0x40) LogChar('A');
andrewboyson 53:77f8a49adf89 153 }
andrewboyson 47:73af5c0b0dc2 154 static int logOptionVerbose(char* p)
andrewboyson 47:73af5c0b0dc2 155 {
andrewboyson 46:40d33e9037e4 156 uint32_t value;
andrewboyson 46:40d33e9037e4 157 int type = *p++;
andrewboyson 46:40d33e9037e4 158 int size = *p++;
andrewboyson 52:fbc5a46b5e16 159 if (size == 0)
andrewboyson 52:fbc5a46b5e16 160 {
andrewboyson 119:8e1a7805b801 161 LogF(" Size zero for option %d\r\n", type);
andrewboyson 52:fbc5a46b5e16 162 return 0;
andrewboyson 52:fbc5a46b5e16 163 }
andrewboyson 46:40d33e9037e4 164 switch (type)
andrewboyson 46:40d33e9037e4 165 {
andrewboyson 46:40d33e9037e4 166 case 1:
andrewboyson 53:77f8a49adf89 167 Log(" Src MAC "); MacLog(p); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 168 case 2:
andrewboyson 53:77f8a49adf89 169 Log(" Tgt MAC "); MacLog(p); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 170 case 3:
andrewboyson 53:77f8a49adf89 171 Log(" Prefix length "); LogF("%d", *p); Log("\r\n"); p += 1;
andrewboyson 53:77f8a49adf89 172 Log(" Prefix flags "); logFlagsLA(*p); Log("\r\n"); p += 1;
andrewboyson 53:77f8a49adf89 173 value = decodeUint32(p); Log(" Prefix valid "); LogF("%u", value); Log("\r\n"); p += 4;
andrewboyson 53:77f8a49adf89 174 value = decodeUint32(p); Log(" Prefix preferred "); LogF("%u", value); Log("\r\n"); p += 4;
andrewboyson 119:8e1a7805b801 175 /*Ignore the Reserved2 field*/ p += 4;
andrewboyson 172:9bc3c7b2cca1 176 Log(" Prefix "); Ip6AddrLog(p); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 177 case 5:
andrewboyson 53:77f8a49adf89 178 /*Ignore the reserved field*/ p += 2;
andrewboyson 53:77f8a49adf89 179 value = decodeUint32(p); Log(" MTU "); LogF("%u", value); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 180 case 25:
andrewboyson 53:77f8a49adf89 181 /*Ignore the reserved field*/ p += 2;
andrewboyson 53:77f8a49adf89 182 value = decodeUint32(p); Log(" DNS lifetime "); LogF("%u", value); Log("\r\n"); p += 4;
andrewboyson 172:9bc3c7b2cca1 183 Log(" DNS Server "); Ip6AddrLog(p); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 184 default:
andrewboyson 53:77f8a49adf89 185 Log(" Unknown option "); LogF("%d", type); Log("\r\n"); break;
andrewboyson 46:40d33e9037e4 186 }
andrewboyson 46:40d33e9037e4 187 return size * 8;
andrewboyson 46:40d33e9037e4 188 }
andrewboyson 47:73af5c0b0dc2 189 static int logOptionQuiet(char* p)
andrewboyson 47:73af5c0b0dc2 190 {
andrewboyson 47:73af5c0b0dc2 191 uint32_t value;
andrewboyson 47:73af5c0b0dc2 192 int type = *p++;
andrewboyson 47:73af5c0b0dc2 193 int size = *p++;
andrewboyson 52:fbc5a46b5e16 194 if (size == 0) return 0;
andrewboyson 47:73af5c0b0dc2 195 switch (type)
andrewboyson 47:73af5c0b0dc2 196 {
andrewboyson 47:73af5c0b0dc2 197 case 1:
andrewboyson 47:73af5c0b0dc2 198 Log(" src ");
andrewboyson 47:73af5c0b0dc2 199 MacLog(p);
andrewboyson 47:73af5c0b0dc2 200 break;
andrewboyson 47:73af5c0b0dc2 201 case 2:
andrewboyson 53:77f8a49adf89 202 Log(" tgt ");
andrewboyson 47:73af5c0b0dc2 203 MacLog(p);
andrewboyson 47:73af5c0b0dc2 204 break;
andrewboyson 47:73af5c0b0dc2 205 case 3:
andrewboyson 160:6a1d1d368f80 206 p++; //Length
andrewboyson 160:6a1d1d368f80 207 p++; //LA
andrewboyson 47:73af5c0b0dc2 208 p += 4; //Valid lifetime
andrewboyson 47:73af5c0b0dc2 209 p += 4; //Preferred lifetime
andrewboyson 47:73af5c0b0dc2 210 p += 4; //Reserved 2
andrewboyson 47:73af5c0b0dc2 211 Log(" prefix ");
andrewboyson 172:9bc3c7b2cca1 212 Ip6AddrLog(p); //IP6 address
andrewboyson 47:73af5c0b0dc2 213 break;
andrewboyson 47:73af5c0b0dc2 214 case 5:
andrewboyson 47:73af5c0b0dc2 215 p += 2; //Skip past the reserved field
andrewboyson 47:73af5c0b0dc2 216 value = decodeUint32(p);
andrewboyson 47:73af5c0b0dc2 217 p += 4;
andrewboyson 47:73af5c0b0dc2 218 LogF(" MTU %u", value);
andrewboyson 47:73af5c0b0dc2 219 break;
andrewboyson 47:73af5c0b0dc2 220 case 25:
andrewboyson 47:73af5c0b0dc2 221 p += 2; //Skip past the reserved field
andrewboyson 47:73af5c0b0dc2 222 p += 4; //DNS lifetime
andrewboyson 47:73af5c0b0dc2 223 Log(" DNS ");
andrewboyson 172:9bc3c7b2cca1 224 Ip6AddrLog(p);
andrewboyson 47:73af5c0b0dc2 225 break;
andrewboyson 47:73af5c0b0dc2 226 default:
andrewboyson 47:73af5c0b0dc2 227 LogF(" ? %d", type);
andrewboyson 47:73af5c0b0dc2 228 break;
andrewboyson 47:73af5c0b0dc2 229 }
andrewboyson 47:73af5c0b0dc2 230 return size * 8;
andrewboyson 47:73af5c0b0dc2 231 }
andrewboyson 47:73af5c0b0dc2 232 void NdpDecodeOptions(char* pData, int dataLength, char* srcMac, char* dstMac)
andrewboyson 46:40d33e9037e4 233 {
andrewboyson 46:40d33e9037e4 234 char* p = pData;
andrewboyson 46:40d33e9037e4 235 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 236 while(p < pE)
andrewboyson 52:fbc5a46b5e16 237 {
andrewboyson 52:fbc5a46b5e16 238 int size = decodeOption(p, srcMac, dstMac);
andrewboyson 52:fbc5a46b5e16 239 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 240 p += size;
andrewboyson 52:fbc5a46b5e16 241 }
andrewboyson 46:40d33e9037e4 242 }
andrewboyson 47:73af5c0b0dc2 243 void NdpLogOptionsVerbose(char* pData, int dataLength)
andrewboyson 47:73af5c0b0dc2 244 {
andrewboyson 47:73af5c0b0dc2 245 char* p = pData;
andrewboyson 47:73af5c0b0dc2 246 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 247 while(p < pE)
andrewboyson 52:fbc5a46b5e16 248 {
andrewboyson 52:fbc5a46b5e16 249 int size = logOptionVerbose(p);
andrewboyson 52:fbc5a46b5e16 250 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 251 p += size;
andrewboyson 52:fbc5a46b5e16 252 }
andrewboyson 47:73af5c0b0dc2 253 }
andrewboyson 47:73af5c0b0dc2 254 void NdpLogOptionsQuiet(char* pData, int dataLength)
andrewboyson 46:40d33e9037e4 255 {
andrewboyson 46:40d33e9037e4 256 char* p = pData;
andrewboyson 46:40d33e9037e4 257 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 258 while(p < pE)
andrewboyson 52:fbc5a46b5e16 259 {
andrewboyson 52:fbc5a46b5e16 260 int size = logOptionQuiet(p);
andrewboyson 52:fbc5a46b5e16 261 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 262 p += size;
andrewboyson 52:fbc5a46b5e16 263 }
andrewboyson 52:fbc5a46b5e16 264 }
andrewboyson 52:fbc5a46b5e16 265 int NdpAddOptionSourceMac(char* p, char* pMac)
andrewboyson 52:fbc5a46b5e16 266 {
andrewboyson 52:fbc5a46b5e16 267 *p++ = 1; //Source MAC option
andrewboyson 52:fbc5a46b5e16 268 *p++ = 1; //8 bytes
andrewboyson 52:fbc5a46b5e16 269 MacCopy(p, pMac);
andrewboyson 52:fbc5a46b5e16 270 return 8;
andrewboyson 52:fbc5a46b5e16 271 }
andrewboyson 52:fbc5a46b5e16 272 int NdpAddOptionTargetMac(char* p, char* pMac)
andrewboyson 52:fbc5a46b5e16 273 {
andrewboyson 52:fbc5a46b5e16 274 *p++ = 2; //Target MAC option
andrewboyson 52:fbc5a46b5e16 275 *p++ = 1; //8 bytes
andrewboyson 52:fbc5a46b5e16 276 MacCopy(p, pMac);
andrewboyson 52:fbc5a46b5e16 277 return 8;
andrewboyson 46:40d33e9037e4 278 }