Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Nov 08 20:46:36 2017 +0000
Revision:
52:fbc5a46b5e16
Parent:
51:007bd938f2c3
Child:
53:77f8a49adf89
Fixed bug in NDP options decoder which was crashing the system

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 46:40d33e9037e4 1 #include "mbed.h"
andrewboyson 46:40d33e9037e4 2 #include "log.h"
andrewboyson 47:73af5c0b0dc2 3 #include "net.h"
andrewboyson 46:40d33e9037e4 4 #include "mac.h"
andrewboyson 49:1a6336f2b3f9 5 #include "ip6addr.h"
andrewboyson 46:40d33e9037e4 6 #include "slaac.h"
andrewboyson 46:40d33e9037e4 7 #include "clock.h"
andrewboyson 46:40d33e9037e4 8 #include "rs.h"
andrewboyson 46:40d33e9037e4 9
andrewboyson 47:73af5c0b0dc2 10 int NdpHopLimit = 0;
andrewboyson 47:73af5c0b0dc2 11 bool NdpManagedConfiguration = false;
andrewboyson 47:73af5c0b0dc2 12 bool NdpOtherConfiguration = false;
andrewboyson 47:73af5c0b0dc2 13 int NdpLifetime = 0;
andrewboyson 46:40d33e9037e4 14
andrewboyson 46:40d33e9037e4 15 char NdpRouterMac[6];
andrewboyson 46:40d33e9037e4 16
andrewboyson 46:40d33e9037e4 17 int NdpPrefixLength = 0;
andrewboyson 46:40d33e9037e4 18 uint8_t NdpPrefixLA = 0;
andrewboyson 46:40d33e9037e4 19 uint32_t NdpPrefixValidLifetime = 0;
andrewboyson 46:40d33e9037e4 20 uint32_t NdpPrefixPreferredLifetime = 0;
andrewboyson 46:40d33e9037e4 21 char NdpPrefix[16];
andrewboyson 46:40d33e9037e4 22
andrewboyson 46:40d33e9037e4 23 uint32_t NdpDnsLifetime = 0;
andrewboyson 46:40d33e9037e4 24 char NdpDnsServer[16];
andrewboyson 46:40d33e9037e4 25
andrewboyson 46:40d33e9037e4 26 int NdpMtu = 0;
andrewboyson 46:40d33e9037e4 27
andrewboyson 46:40d33e9037e4 28 uint32_t NdpElapsedTime = 0; //Reset whenever an IP address request has been acknowledged
andrewboyson 46:40d33e9037e4 29
andrewboyson 46:40d33e9037e4 30 bool NdpIpNeedsToBeRouted(char* ip)
andrewboyson 46:40d33e9037e4 31 {
andrewboyson 46:40d33e9037e4 32 //Check address is assigned to internet
andrewboyson 46:40d33e9037e4 33 if (*(ip + 0) != 0x20) return false;
andrewboyson 46:40d33e9037e4 34 if (*(ip + 1) != 0x00) return false;
andrewboyson 46:40d33e9037e4 35
andrewboyson 46:40d33e9037e4 36 //Check it is not our own prefix
andrewboyson 46:40d33e9037e4 37 if (memcmp(ip, NdpPrefix, 8) == 0) return false;
andrewboyson 46:40d33e9037e4 38
andrewboyson 46:40d33e9037e4 39 return true;
andrewboyson 46:40d33e9037e4 40 }
andrewboyson 46:40d33e9037e4 41
andrewboyson 46:40d33e9037e4 42 static uint32_t decodeUint32(char* p)
andrewboyson 46:40d33e9037e4 43 {
andrewboyson 46:40d33e9037e4 44 uint32_t value = 0;
andrewboyson 46:40d33e9037e4 45 value |= *p++ << 24;
andrewboyson 46:40d33e9037e4 46 value |= *p++ << 12;
andrewboyson 46:40d33e9037e4 47 value |= *p++ << 8;
andrewboyson 46:40d33e9037e4 48 value |= *p++ << 0;
andrewboyson 46:40d33e9037e4 49 return value;
andrewboyson 46:40d33e9037e4 50 }
andrewboyson 47:73af5c0b0dc2 51 static int decodeOption(char* p, char* srcMac, char* dstMac)
andrewboyson 46:40d33e9037e4 52 {
andrewboyson 46:40d33e9037e4 53 int type = *p++;
andrewboyson 46:40d33e9037e4 54 int size = *p++;
andrewboyson 52:fbc5a46b5e16 55 if (size == 0) return 0;
andrewboyson 46:40d33e9037e4 56 switch (type)
andrewboyson 46:40d33e9037e4 57 {
andrewboyson 46:40d33e9037e4 58 case 1:
andrewboyson 47:73af5c0b0dc2 59 if (srcMac) MacCopy(srcMac, p);
andrewboyson 46:40d33e9037e4 60 break;
andrewboyson 46:40d33e9037e4 61 case 2:
andrewboyson 47:73af5c0b0dc2 62 if (dstMac) MacCopy(dstMac, p);
andrewboyson 46:40d33e9037e4 63 break;
andrewboyson 46:40d33e9037e4 64 case 3:
andrewboyson 46:40d33e9037e4 65 NdpPrefixLength = *p++;
andrewboyson 46:40d33e9037e4 66 NdpPrefixLA = *p++;
andrewboyson 46:40d33e9037e4 67 NdpPrefixValidLifetime = decodeUint32(p);
andrewboyson 46:40d33e9037e4 68 p += 4;
andrewboyson 46:40d33e9037e4 69 NdpPrefixPreferredLifetime = decodeUint32(p);
andrewboyson 46:40d33e9037e4 70 p += 4;
andrewboyson 46:40d33e9037e4 71 p += 4; //Skip gracefully past the Reserved2 field
andrewboyson 49:1a6336f2b3f9 72 Ip6AddressCopy(NdpPrefix, p);
andrewboyson 46:40d33e9037e4 73 SlaacMakeGlobal(NdpPrefix);
andrewboyson 46:40d33e9037e4 74 break;
andrewboyson 46:40d33e9037e4 75 case 5:
andrewboyson 46:40d33e9037e4 76 p += 2; //Skip past the reserved field
andrewboyson 46:40d33e9037e4 77 NdpMtu = decodeUint32(p);
andrewboyson 46:40d33e9037e4 78 break;
andrewboyson 46:40d33e9037e4 79 case 25:
andrewboyson 46:40d33e9037e4 80 p += 2; //Skip past the reserved field
andrewboyson 46:40d33e9037e4 81 NdpDnsLifetime = decodeUint32(p);
andrewboyson 46:40d33e9037e4 82 p += 4;
andrewboyson 49:1a6336f2b3f9 83 Ip6AddressCopy(NdpDnsServer, p);
andrewboyson 46:40d33e9037e4 84 break;
andrewboyson 46:40d33e9037e4 85 }
andrewboyson 46:40d33e9037e4 86 return size * 8;
andrewboyson 46:40d33e9037e4 87 }
andrewboyson 47:73af5c0b0dc2 88 static int logOptionVerbose(char* p)
andrewboyson 47:73af5c0b0dc2 89 {
andrewboyson 46:40d33e9037e4 90 uint32_t value;
andrewboyson 46:40d33e9037e4 91 int type = *p++;
andrewboyson 46:40d33e9037e4 92 int size = *p++;
andrewboyson 52:fbc5a46b5e16 93 if (size == 0)
andrewboyson 52:fbc5a46b5e16 94 {
andrewboyson 52:fbc5a46b5e16 95 LogF(" Size zero for option %d\r\n", type);
andrewboyson 52:fbc5a46b5e16 96 return 0;
andrewboyson 52:fbc5a46b5e16 97 }
andrewboyson 46:40d33e9037e4 98 switch (type)
andrewboyson 46:40d33e9037e4 99 {
andrewboyson 46:40d33e9037e4 100 case 1:
andrewboyson 47:73af5c0b0dc2 101 Log(" Src MAC "); MacLog(p); Log("\r\n");
andrewboyson 46:40d33e9037e4 102 break;
andrewboyson 46:40d33e9037e4 103 case 2:
andrewboyson 47:73af5c0b0dc2 104 Log(" Dst MAC "); MacLog(p); Log("\r\n");
andrewboyson 46:40d33e9037e4 105 break;
andrewboyson 46:40d33e9037e4 106 case 3:
andrewboyson 46:40d33e9037e4 107 LogF(" Prefix length %d\r\n", *p++);
andrewboyson 46:40d33e9037e4 108 LogF(" Prefix LA %X\r\n", *p++);
andrewboyson 46:40d33e9037e4 109 value = decodeUint32(p); p += 4;
andrewboyson 46:40d33e9037e4 110 LogF(" Prefix valid %u seconds\r\n", value);
andrewboyson 46:40d33e9037e4 111 value = decodeUint32(p); p += 4;
andrewboyson 46:40d33e9037e4 112 LogF(" Prefix preferred %u seconds\r\n", value);
andrewboyson 46:40d33e9037e4 113 p += 4; //Skip gracefully past the Reserved2 field
andrewboyson 47:73af5c0b0dc2 114 LogF(" Prefix "); Ip6AddressLog(p); Log("\r\n");
andrewboyson 46:40d33e9037e4 115 break;
andrewboyson 46:40d33e9037e4 116 case 5:
andrewboyson 46:40d33e9037e4 117 p += 2; //Skip past the reserved field
andrewboyson 46:40d33e9037e4 118 value = decodeUint32(p);
andrewboyson 46:40d33e9037e4 119 p += 4;
andrewboyson 46:40d33e9037e4 120 LogF(" MTU %u\r\n", value);
andrewboyson 46:40d33e9037e4 121 break;
andrewboyson 46:40d33e9037e4 122 case 25:
andrewboyson 46:40d33e9037e4 123 p += 2; //Skip past the reserved field
andrewboyson 46:40d33e9037e4 124 value = decodeUint32(p);
andrewboyson 46:40d33e9037e4 125 p += 4;
andrewboyson 46:40d33e9037e4 126 LogF(" DNS lifetime %u\r\n", value);
andrewboyson 47:73af5c0b0dc2 127 LogF(" DNS Server "); Ip6AddressLog(p); Log("\r\n");
andrewboyson 46:40d33e9037e4 128 break;
andrewboyson 46:40d33e9037e4 129 default:
andrewboyson 46:40d33e9037e4 130 LogF(" Unknown option %d\r\n", type);
andrewboyson 46:40d33e9037e4 131 break;
andrewboyson 46:40d33e9037e4 132 }
andrewboyson 46:40d33e9037e4 133 return size * 8;
andrewboyson 46:40d33e9037e4 134 }
andrewboyson 47:73af5c0b0dc2 135 static int logOptionQuiet(char* p)
andrewboyson 47:73af5c0b0dc2 136 {
andrewboyson 47:73af5c0b0dc2 137 uint32_t value;
andrewboyson 47:73af5c0b0dc2 138 int type = *p++;
andrewboyson 47:73af5c0b0dc2 139 int size = *p++;
andrewboyson 52:fbc5a46b5e16 140 if (size == 0) return 0;
andrewboyson 47:73af5c0b0dc2 141 switch (type)
andrewboyson 47:73af5c0b0dc2 142 {
andrewboyson 47:73af5c0b0dc2 143 case 1:
andrewboyson 47:73af5c0b0dc2 144 Log(" src ");
andrewboyson 47:73af5c0b0dc2 145 MacLog(p);
andrewboyson 47:73af5c0b0dc2 146 break;
andrewboyson 47:73af5c0b0dc2 147 case 2:
andrewboyson 47:73af5c0b0dc2 148 Log(" dst ");
andrewboyson 47:73af5c0b0dc2 149 MacLog(p);
andrewboyson 47:73af5c0b0dc2 150 break;
andrewboyson 47:73af5c0b0dc2 151 case 3:
andrewboyson 47:73af5c0b0dc2 152 *p++; //Length
andrewboyson 47:73af5c0b0dc2 153 *p++; //LA
andrewboyson 47:73af5c0b0dc2 154 p += 4; //Valid lifetime
andrewboyson 47:73af5c0b0dc2 155 p += 4; //Preferred lifetime
andrewboyson 47:73af5c0b0dc2 156 p += 4; //Reserved 2
andrewboyson 47:73af5c0b0dc2 157 Log(" prefix ");
andrewboyson 47:73af5c0b0dc2 158 Ip6AddressLog(p); //IP6 address
andrewboyson 47:73af5c0b0dc2 159 break;
andrewboyson 47:73af5c0b0dc2 160 case 5:
andrewboyson 47:73af5c0b0dc2 161 p += 2; //Skip past the reserved field
andrewboyson 47:73af5c0b0dc2 162 value = decodeUint32(p);
andrewboyson 47:73af5c0b0dc2 163 p += 4;
andrewboyson 47:73af5c0b0dc2 164 LogF(" MTU %u", value);
andrewboyson 47:73af5c0b0dc2 165 break;
andrewboyson 47:73af5c0b0dc2 166 case 25:
andrewboyson 47:73af5c0b0dc2 167 p += 2; //Skip past the reserved field
andrewboyson 47:73af5c0b0dc2 168 p += 4; //DNS lifetime
andrewboyson 47:73af5c0b0dc2 169 Log(" DNS ");
andrewboyson 47:73af5c0b0dc2 170 Ip6AddressLog(p);
andrewboyson 47:73af5c0b0dc2 171 break;
andrewboyson 47:73af5c0b0dc2 172 default:
andrewboyson 47:73af5c0b0dc2 173 LogF(" ? %d", type);
andrewboyson 47:73af5c0b0dc2 174 break;
andrewboyson 47:73af5c0b0dc2 175 }
andrewboyson 47:73af5c0b0dc2 176 return size * 8;
andrewboyson 47:73af5c0b0dc2 177 }
andrewboyson 47:73af5c0b0dc2 178 void NdpDecodeOptions(char* pData, int dataLength, char* srcMac, char* dstMac)
andrewboyson 46:40d33e9037e4 179 {
andrewboyson 46:40d33e9037e4 180 char* p = pData;
andrewboyson 46:40d33e9037e4 181 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 182 while(p < pE)
andrewboyson 52:fbc5a46b5e16 183 {
andrewboyson 52:fbc5a46b5e16 184 int size = decodeOption(p, srcMac, dstMac);
andrewboyson 52:fbc5a46b5e16 185 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 186 p += size;
andrewboyson 52:fbc5a46b5e16 187 }
andrewboyson 46:40d33e9037e4 188 }
andrewboyson 47:73af5c0b0dc2 189 void NdpLogOptionsVerbose(char* pData, int dataLength)
andrewboyson 47:73af5c0b0dc2 190 {
andrewboyson 47:73af5c0b0dc2 191 char* p = pData;
andrewboyson 47:73af5c0b0dc2 192 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 193 while(p < pE)
andrewboyson 52:fbc5a46b5e16 194 {
andrewboyson 52:fbc5a46b5e16 195 int size = logOptionVerbose(p);
andrewboyson 52:fbc5a46b5e16 196 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 197 p += size;
andrewboyson 52:fbc5a46b5e16 198 }
andrewboyson 47:73af5c0b0dc2 199 }
andrewboyson 47:73af5c0b0dc2 200 void NdpLogOptionsQuiet(char* pData, int dataLength)
andrewboyson 46:40d33e9037e4 201 {
andrewboyson 46:40d33e9037e4 202 char* p = pData;
andrewboyson 46:40d33e9037e4 203 char* pE = pData + dataLength;
andrewboyson 52:fbc5a46b5e16 204 while(p < pE)
andrewboyson 52:fbc5a46b5e16 205 {
andrewboyson 52:fbc5a46b5e16 206 int size = logOptionQuiet(p);
andrewboyson 52:fbc5a46b5e16 207 if (size == 0) break;
andrewboyson 52:fbc5a46b5e16 208 p += size;
andrewboyson 52:fbc5a46b5e16 209 }
andrewboyson 52:fbc5a46b5e16 210 }
andrewboyson 52:fbc5a46b5e16 211 int NdpAddOptionSourceMac(char* p, char* pMac)
andrewboyson 52:fbc5a46b5e16 212 {
andrewboyson 52:fbc5a46b5e16 213 *p++ = 1; //Source MAC option
andrewboyson 52:fbc5a46b5e16 214 *p++ = 1; //8 bytes
andrewboyson 52:fbc5a46b5e16 215 MacCopy(p, pMac);
andrewboyson 52:fbc5a46b5e16 216 return 8;
andrewboyson 52:fbc5a46b5e16 217 }
andrewboyson 52:fbc5a46b5e16 218 int NdpAddOptionTargetMac(char* p, char* pMac)
andrewboyson 52:fbc5a46b5e16 219 {
andrewboyson 52:fbc5a46b5e16 220 *p++ = 2; //Target MAC option
andrewboyson 52:fbc5a46b5e16 221 *p++ = 1; //8 bytes
andrewboyson 52:fbc5a46b5e16 222 MacCopy(p, pMac);
andrewboyson 52:fbc5a46b5e16 223 return 8;
andrewboyson 46:40d33e9037e4 224 }
andrewboyson 47:73af5c0b0dc2 225
andrewboyson 47:73af5c0b0dc2 226 #define INITIAL_DELAY 1
andrewboyson 47:73af5c0b0dc2 227 #define REPEAT_DELAY 60
andrewboyson 47:73af5c0b0dc2 228 static uint32_t delayTime = INITIAL_DELAY; //Set to REPEAT_DELAY_TIME whenever a message is sent and blocks another send until count is back at zero
andrewboyson 47:73af5c0b0dc2 229 void NdpMain()
andrewboyson 47:73af5c0b0dc2 230 {
andrewboyson 47:73af5c0b0dc2 231 if (ClockTicked)
andrewboyson 47:73af5c0b0dc2 232 {
andrewboyson 47:73af5c0b0dc2 233 NdpElapsedTime++;
andrewboyson 47:73af5c0b0dc2 234 if (delayTime > 0) delayTime--;
andrewboyson 47:73af5c0b0dc2 235 }
andrewboyson 47:73af5c0b0dc2 236 if (delayTime) return; //Don't retry within the delay time
andrewboyson 47:73af5c0b0dc2 237
andrewboyson 47:73af5c0b0dc2 238 if (NdpLifetime && NdpElapsedTime < (NdpLifetime >> 1)) return; //Do nothing if within half the life
andrewboyson 47:73af5c0b0dc2 239
andrewboyson 47:73af5c0b0dc2 240 if (!NdpLifetime || NdpElapsedTime >= NdpLifetime)
andrewboyson 47:73af5c0b0dc2 241 {
andrewboyson 47:73af5c0b0dc2 242 if (NetTraceNewLine) Log("\r\n");
andrewboyson 47:73af5c0b0dc2 243 LogTime("NDP lifetime has expired\r\n");
andrewboyson 47:73af5c0b0dc2 244 NdpLifetime = 0;
andrewboyson 49:1a6336f2b3f9 245 Ip6AddressClear(NdpPrefix);
andrewboyson 47:73af5c0b0dc2 246 SlaacMakeGlobal(NdpPrefix);
andrewboyson 49:1a6336f2b3f9 247 Ip6AddressClear(NdpDnsServer);
andrewboyson 47:73af5c0b0dc2 248 }
andrewboyson 47:73af5c0b0dc2 249
andrewboyson 47:73af5c0b0dc2 250 delayTime = REPEAT_DELAY;
andrewboyson 47:73af5c0b0dc2 251 RsSendSolicitation = true;
andrewboyson 47:73af5c0b0dc2 252 }