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.c@187:122fc1996c86, 2021-01-18 (annotated)
- Committer:
- andrewboyson
- Date:
- Mon Jan 18 18:23:46 2021 +0000
- Revision:
- 187:122fc1996c86
- Parent:
- 175:2d7aa004d881
Changed Ip4Address to Ip4Addr.; Moved Ip6AddrIsExternal from NdpNeedsToBeRouted.
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 | 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 | static uint32_t decodeUint32(char* p) | 
| andrewboyson | 46:40d33e9037e4 | 76 | { | 
| andrewboyson | 175:2d7aa004d881 | 77 | uint32_t value = *p++; | 
| andrewboyson | 175:2d7aa004d881 | 78 | value <<= 8; value += *p++; | 
| andrewboyson | 175:2d7aa004d881 | 79 | value <<= 8; value += *p++; | 
| andrewboyson | 175:2d7aa004d881 | 80 | value <<= 8; value += *p++; | 
| andrewboyson | 46:40d33e9037e4 | 81 | return value; | 
| andrewboyson | 46:40d33e9037e4 | 82 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 83 | static int decodeOption(char* p, char* srcMac, char* dstMac) | 
| andrewboyson | 46:40d33e9037e4 | 84 | { | 
| andrewboyson | 46:40d33e9037e4 | 85 | int type = *p++; | 
| andrewboyson | 46:40d33e9037e4 | 86 | int size = *p++; | 
| andrewboyson | 52:fbc5a46b5e16 | 87 | if (size == 0) return 0; | 
| andrewboyson | 46:40d33e9037e4 | 88 | switch (type) | 
| andrewboyson | 46:40d33e9037e4 | 89 | { | 
| andrewboyson | 46:40d33e9037e4 | 90 | case 1: | 
| andrewboyson | 47:73af5c0b0dc2 | 91 | if (srcMac) MacCopy(srcMac, p); | 
| andrewboyson | 46:40d33e9037e4 | 92 | break; | 
| andrewboyson | 46:40d33e9037e4 | 93 | case 2: | 
| andrewboyson | 47:73af5c0b0dc2 | 94 | if (dstMac) MacCopy(dstMac, p); | 
| andrewboyson | 46:40d33e9037e4 | 95 | break; | 
| andrewboyson | 46:40d33e9037e4 | 96 | case 3: | 
| andrewboyson | 172:9bc3c7b2cca1 | 97 | { | 
| andrewboyson | 172:9bc3c7b2cca1 | 98 | int length = *p; p += 1; | 
| andrewboyson | 172:9bc3c7b2cca1 | 99 | uint8_t flags = *p; p += 1; | 
| andrewboyson | 172:9bc3c7b2cca1 | 100 | uint32_t validLifetime = decodeUint32(p); p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 101 | uint32_t preferredLifetime = decodeUint32(p); p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 102 | /*Ignore the reserved2 field*/ p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 103 | if (Ip6AddrIsGlobal(p)) | 
| andrewboyson | 172:9bc3c7b2cca1 | 104 | { | 
| andrewboyson | 172:9bc3c7b2cca1 | 105 | Ip6AddrCopy(NdpGlobalPrefix, p); | 
| andrewboyson | 172:9bc3c7b2cca1 | 106 | NdpGlobalPrefixLength = length; | 
| andrewboyson | 172:9bc3c7b2cca1 | 107 | NdpGlobalPrefixFlagL = flags & 0x80; | 
| andrewboyson | 172:9bc3c7b2cca1 | 108 | NdpGlobalPrefixFlagA = flags & 0x40; | 
| andrewboyson | 172:9bc3c7b2cca1 | 109 | NdpGlobalPrefixValidLifetime = validLifetime; | 
| andrewboyson | 172:9bc3c7b2cca1 | 110 | NdpGlobalPrefixPreferredLifetime = preferredLifetime; | 
| andrewboyson | 172:9bc3c7b2cca1 | 111 | SlaacMakeGlobal(p); | 
| andrewboyson | 172:9bc3c7b2cca1 | 112 | } | 
| andrewboyson | 172:9bc3c7b2cca1 | 113 | else if (Ip6AddrIsUniqueLocal(p)) | 
| andrewboyson | 172:9bc3c7b2cca1 | 114 | { | 
| andrewboyson | 172:9bc3c7b2cca1 | 115 | Ip6AddrCopy(NdpUniqueLocalPrefix, p); | 
| andrewboyson | 172:9bc3c7b2cca1 | 116 | NdpUniqueLocalPrefixLength = length; | 
| andrewboyson | 172:9bc3c7b2cca1 | 117 | NdpUniqueLocalPrefixFlagL = flags & 0x80; | 
| andrewboyson | 172:9bc3c7b2cca1 | 118 | NdpUniqueLocalPrefixFlagA = flags & 0x40; | 
| andrewboyson | 172:9bc3c7b2cca1 | 119 | NdpUniqueLocalPrefixValidLifetime = validLifetime; | 
| andrewboyson | 172:9bc3c7b2cca1 | 120 | NdpUniqueLocalPrefixPreferredLifetime = preferredLifetime; | 
| andrewboyson | 172:9bc3c7b2cca1 | 121 | SlaacMakeUniqueLocal(p); | 
| andrewboyson | 172:9bc3c7b2cca1 | 122 | } | 
| andrewboyson | 172:9bc3c7b2cca1 | 123 | break; | 
| andrewboyson | 172:9bc3c7b2cca1 | 124 | } | 
| andrewboyson | 46:40d33e9037e4 | 125 | case 5: | 
| andrewboyson | 53:77f8a49adf89 | 126 | /*Ignore the reserved field*/ p += 2; | 
| andrewboyson | 46:40d33e9037e4 | 127 | NdpMtu = decodeUint32(p); | 
| andrewboyson | 46:40d33e9037e4 | 128 | break; | 
| andrewboyson | 46:40d33e9037e4 | 129 | case 25: | 
| andrewboyson | 53:77f8a49adf89 | 130 | /*Ignore the reserved field*/ p += 2; | 
| andrewboyson | 53:77f8a49adf89 | 131 | NdpDnsLifetime = decodeUint32(p); p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 132 | Ip6AddrCopy(NdpDnsServer, p); | 
| andrewboyson | 46:40d33e9037e4 | 133 | break; | 
| andrewboyson | 46:40d33e9037e4 | 134 | } | 
| andrewboyson | 46:40d33e9037e4 | 135 | return size * 8; | 
| andrewboyson | 46:40d33e9037e4 | 136 | } | 
| andrewboyson | 53:77f8a49adf89 | 137 | static void logFlagsLA(char flags) | 
| andrewboyson | 53:77f8a49adf89 | 138 | { | 
| andrewboyson | 121:bc048b65a630 | 139 | if (flags & 0x80) LogChar('L'); | 
| andrewboyson | 121:bc048b65a630 | 140 | if (flags & 0x40) LogChar('A'); | 
| andrewboyson | 53:77f8a49adf89 | 141 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 142 | static int logOptionVerbose(char* p) | 
| andrewboyson | 47:73af5c0b0dc2 | 143 | { | 
| andrewboyson | 46:40d33e9037e4 | 144 | uint32_t value; | 
| andrewboyson | 46:40d33e9037e4 | 145 | int type = *p++; | 
| andrewboyson | 46:40d33e9037e4 | 146 | int size = *p++; | 
| andrewboyson | 52:fbc5a46b5e16 | 147 | if (size == 0) | 
| andrewboyson | 52:fbc5a46b5e16 | 148 | { | 
| andrewboyson | 119:8e1a7805b801 | 149 | LogF(" Size zero for option %d\r\n", type); | 
| andrewboyson | 52:fbc5a46b5e16 | 150 | return 0; | 
| andrewboyson | 52:fbc5a46b5e16 | 151 | } | 
| andrewboyson | 46:40d33e9037e4 | 152 | switch (type) | 
| andrewboyson | 46:40d33e9037e4 | 153 | { | 
| andrewboyson | 46:40d33e9037e4 | 154 | case 1: | 
| andrewboyson | 53:77f8a49adf89 | 155 | Log(" Src MAC "); MacLog(p); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 156 | case 2: | 
| andrewboyson | 53:77f8a49adf89 | 157 | Log(" Tgt MAC "); MacLog(p); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 158 | case 3: | 
| andrewboyson | 53:77f8a49adf89 | 159 | Log(" Prefix length "); LogF("%d", *p); Log("\r\n"); p += 1; | 
| andrewboyson | 53:77f8a49adf89 | 160 | Log(" Prefix flags "); logFlagsLA(*p); Log("\r\n"); p += 1; | 
| andrewboyson | 53:77f8a49adf89 | 161 | value = decodeUint32(p); Log(" Prefix valid "); LogF("%u", value); Log("\r\n"); p += 4; | 
| andrewboyson | 53:77f8a49adf89 | 162 | value = decodeUint32(p); Log(" Prefix preferred "); LogF("%u", value); Log("\r\n"); p += 4; | 
| andrewboyson | 119:8e1a7805b801 | 163 | /*Ignore the Reserved2 field*/ p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 164 | Log(" Prefix "); Ip6AddrLog(p); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 165 | case 5: | 
| andrewboyson | 53:77f8a49adf89 | 166 | /*Ignore the reserved field*/ p += 2; | 
| andrewboyson | 53:77f8a49adf89 | 167 | value = decodeUint32(p); Log(" MTU "); LogF("%u", value); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 168 | case 25: | 
| andrewboyson | 53:77f8a49adf89 | 169 | /*Ignore the reserved field*/ p += 2; | 
| andrewboyson | 53:77f8a49adf89 | 170 | value = decodeUint32(p); Log(" DNS lifetime "); LogF("%u", value); Log("\r\n"); p += 4; | 
| andrewboyson | 172:9bc3c7b2cca1 | 171 | Log(" DNS Server "); Ip6AddrLog(p); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 172 | default: | 
| andrewboyson | 53:77f8a49adf89 | 173 | Log(" Unknown option "); LogF("%d", type); Log("\r\n"); break; | 
| andrewboyson | 46:40d33e9037e4 | 174 | } | 
| andrewboyson | 46:40d33e9037e4 | 175 | return size * 8; | 
| andrewboyson | 46:40d33e9037e4 | 176 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 177 | static int logOptionQuiet(char* p) | 
| andrewboyson | 47:73af5c0b0dc2 | 178 | { | 
| andrewboyson | 47:73af5c0b0dc2 | 179 | uint32_t value; | 
| andrewboyson | 47:73af5c0b0dc2 | 180 | int type = *p++; | 
| andrewboyson | 47:73af5c0b0dc2 | 181 | int size = *p++; | 
| andrewboyson | 52:fbc5a46b5e16 | 182 | if (size == 0) return 0; | 
| andrewboyson | 47:73af5c0b0dc2 | 183 | switch (type) | 
| andrewboyson | 47:73af5c0b0dc2 | 184 | { | 
| andrewboyson | 47:73af5c0b0dc2 | 185 | case 1: | 
| andrewboyson | 47:73af5c0b0dc2 | 186 | Log(" src "); | 
| andrewboyson | 47:73af5c0b0dc2 | 187 | MacLog(p); | 
| andrewboyson | 47:73af5c0b0dc2 | 188 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 189 | case 2: | 
| andrewboyson | 53:77f8a49adf89 | 190 | Log(" tgt "); | 
| andrewboyson | 47:73af5c0b0dc2 | 191 | MacLog(p); | 
| andrewboyson | 47:73af5c0b0dc2 | 192 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 193 | case 3: | 
| andrewboyson | 160:6a1d1d368f80 | 194 | p++; //Length | 
| andrewboyson | 160:6a1d1d368f80 | 195 | p++; //LA | 
| andrewboyson | 47:73af5c0b0dc2 | 196 | p += 4; //Valid lifetime | 
| andrewboyson | 47:73af5c0b0dc2 | 197 | p += 4; //Preferred lifetime | 
| andrewboyson | 47:73af5c0b0dc2 | 198 | p += 4; //Reserved 2 | 
| andrewboyson | 47:73af5c0b0dc2 | 199 | Log(" prefix "); | 
| andrewboyson | 172:9bc3c7b2cca1 | 200 | Ip6AddrLog(p); //IP6 address | 
| andrewboyson | 47:73af5c0b0dc2 | 201 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 202 | case 5: | 
| andrewboyson | 47:73af5c0b0dc2 | 203 | p += 2; //Skip past the reserved field | 
| andrewboyson | 47:73af5c0b0dc2 | 204 | value = decodeUint32(p); | 
| andrewboyson | 47:73af5c0b0dc2 | 205 | p += 4; | 
| andrewboyson | 47:73af5c0b0dc2 | 206 | LogF(" MTU %u", value); | 
| andrewboyson | 47:73af5c0b0dc2 | 207 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 208 | case 25: | 
| andrewboyson | 47:73af5c0b0dc2 | 209 | p += 2; //Skip past the reserved field | 
| andrewboyson | 47:73af5c0b0dc2 | 210 | p += 4; //DNS lifetime | 
| andrewboyson | 47:73af5c0b0dc2 | 211 | Log(" DNS "); | 
| andrewboyson | 172:9bc3c7b2cca1 | 212 | Ip6AddrLog(p); | 
| andrewboyson | 47:73af5c0b0dc2 | 213 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 214 | default: | 
| andrewboyson | 47:73af5c0b0dc2 | 215 | LogF(" ? %d", type); | 
| andrewboyson | 47:73af5c0b0dc2 | 216 | break; | 
| andrewboyson | 47:73af5c0b0dc2 | 217 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 218 | return size * 8; | 
| andrewboyson | 47:73af5c0b0dc2 | 219 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 220 | void NdpDecodeOptions(char* pData, int dataLength, char* srcMac, char* dstMac) | 
| andrewboyson | 46:40d33e9037e4 | 221 | { | 
| andrewboyson | 46:40d33e9037e4 | 222 | char* p = pData; | 
| andrewboyson | 46:40d33e9037e4 | 223 | char* pE = pData + dataLength; | 
| andrewboyson | 52:fbc5a46b5e16 | 224 | while(p < pE) | 
| andrewboyson | 52:fbc5a46b5e16 | 225 | { | 
| andrewboyson | 52:fbc5a46b5e16 | 226 | int size = decodeOption(p, srcMac, dstMac); | 
| andrewboyson | 52:fbc5a46b5e16 | 227 | if (size == 0) break; | 
| andrewboyson | 52:fbc5a46b5e16 | 228 | p += size; | 
| andrewboyson | 52:fbc5a46b5e16 | 229 | } | 
| andrewboyson | 46:40d33e9037e4 | 230 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 231 | void NdpLogOptionsVerbose(char* pData, int dataLength) | 
| andrewboyson | 47:73af5c0b0dc2 | 232 | { | 
| andrewboyson | 47:73af5c0b0dc2 | 233 | char* p = pData; | 
| andrewboyson | 47:73af5c0b0dc2 | 234 | char* pE = pData + dataLength; | 
| andrewboyson | 52:fbc5a46b5e16 | 235 | while(p < pE) | 
| andrewboyson | 52:fbc5a46b5e16 | 236 | { | 
| andrewboyson | 52:fbc5a46b5e16 | 237 | int size = logOptionVerbose(p); | 
| andrewboyson | 52:fbc5a46b5e16 | 238 | if (size == 0) break; | 
| andrewboyson | 52:fbc5a46b5e16 | 239 | p += size; | 
| andrewboyson | 52:fbc5a46b5e16 | 240 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 241 | } | 
| andrewboyson | 47:73af5c0b0dc2 | 242 | void NdpLogOptionsQuiet(char* pData, int dataLength) | 
| andrewboyson | 46:40d33e9037e4 | 243 | { | 
| andrewboyson | 46:40d33e9037e4 | 244 | char* p = pData; | 
| andrewboyson | 46:40d33e9037e4 | 245 | char* pE = pData + dataLength; | 
| andrewboyson | 52:fbc5a46b5e16 | 246 | while(p < pE) | 
| andrewboyson | 52:fbc5a46b5e16 | 247 | { | 
| andrewboyson | 52:fbc5a46b5e16 | 248 | int size = logOptionQuiet(p); | 
| andrewboyson | 52:fbc5a46b5e16 | 249 | if (size == 0) break; | 
| andrewboyson | 52:fbc5a46b5e16 | 250 | p += size; | 
| andrewboyson | 52:fbc5a46b5e16 | 251 | } | 
| andrewboyson | 52:fbc5a46b5e16 | 252 | } | 
| andrewboyson | 52:fbc5a46b5e16 | 253 | int NdpAddOptionSourceMac(char* p, char* pMac) | 
| andrewboyson | 52:fbc5a46b5e16 | 254 | { | 
| andrewboyson | 52:fbc5a46b5e16 | 255 | *p++ = 1; //Source MAC option | 
| andrewboyson | 52:fbc5a46b5e16 | 256 | *p++ = 1; //8 bytes | 
| andrewboyson | 52:fbc5a46b5e16 | 257 | MacCopy(p, pMac); | 
| andrewboyson | 52:fbc5a46b5e16 | 258 | return 8; | 
| andrewboyson | 52:fbc5a46b5e16 | 259 | } | 
| andrewboyson | 52:fbc5a46b5e16 | 260 | int NdpAddOptionTargetMac(char* p, char* pMac) | 
| andrewboyson | 52:fbc5a46b5e16 | 261 | { | 
| andrewboyson | 52:fbc5a46b5e16 | 262 | *p++ = 2; //Target MAC option | 
| andrewboyson | 52:fbc5a46b5e16 | 263 | *p++ = 1; //8 bytes | 
| andrewboyson | 52:fbc5a46b5e16 | 264 | MacCopy(p, pMac); | 
| andrewboyson | 52:fbc5a46b5e16 | 265 | return 8; | 
| andrewboyson | 46:40d33e9037e4 | 266 | } |