Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Jan 11 17:38:21 2018 +0000
Revision:
61:aad055f1b0d1
Parent:
ip6/icmp/ndp/ndp.cpp@53:77f8a49adf89
Child:
65:37acccf2752f
Removed dependence on Mbed OS

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