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