Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ndp_misc.c
Sergunb 0:8918a71cdbe9 3 * @brief Helper functions for NDP (Neighbor Discovery Protocol)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL NDP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include "core/net.h"
Sergunb 0:8918a71cdbe9 34 #include "ipv6/ipv6.h"
Sergunb 0:8918a71cdbe9 35 #include "ipv6/ipv6_misc.h"
Sergunb 0:8918a71cdbe9 36 #include "ipv6/ndp.h"
Sergunb 0:8918a71cdbe9 37 #include "ipv6/ndp_cache.h"
Sergunb 0:8918a71cdbe9 38 #include "ipv6/ndp_misc.h"
Sergunb 0:8918a71cdbe9 39 #include "mdns/mdns_responder.h"
Sergunb 0:8918a71cdbe9 40 #include "debug.h"
Sergunb 0:8918a71cdbe9 41
Sergunb 0:8918a71cdbe9 42 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 43 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45
Sergunb 0:8918a71cdbe9 46 /**
Sergunb 0:8918a71cdbe9 47 * @brief Parse Prefix Information Option
Sergunb 0:8918a71cdbe9 48 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 49 * @param[in] option Pointer to the Prefix Information option
Sergunb 0:8918a71cdbe9 50 **/
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 void ndpParsePrefixInfoOption(NetInterface *interface, NdpPrefixInfoOption *option)
Sergunb 0:8918a71cdbe9 53 {
Sergunb 0:8918a71cdbe9 54 //Make sure the Prefix Information option is valid
Sergunb 0:8918a71cdbe9 55 if(option == NULL || option->length != 4)
Sergunb 0:8918a71cdbe9 56 return;
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58 //A prefix Information option that have the on-link flag set indicates a
Sergunb 0:8918a71cdbe9 59 //prefix identifying a range of addresses that should be considered on-link
Sergunb 0:8918a71cdbe9 60 if(!option->l)
Sergunb 0:8918a71cdbe9 61 return;
Sergunb 0:8918a71cdbe9 62
Sergunb 0:8918a71cdbe9 63 //If the prefix is the link-local prefix, silently ignore the
Sergunb 0:8918a71cdbe9 64 //Prefix Information option
Sergunb 0:8918a71cdbe9 65 if(ipv6CompPrefix(&option->prefix, &IPV6_LINK_LOCAL_ADDR_PREFIX, 10))
Sergunb 0:8918a71cdbe9 66 return;
Sergunb 0:8918a71cdbe9 67
Sergunb 0:8918a71cdbe9 68 //If the preferred lifetime is greater than the valid lifetime,
Sergunb 0:8918a71cdbe9 69 //silently ignore the Prefix Information option
Sergunb 0:8918a71cdbe9 70 if(ntohl(option->preferredLifetime) > ntohl(option->validLifetime))
Sergunb 0:8918a71cdbe9 71 return;
Sergunb 0:8918a71cdbe9 72
Sergunb 0:8918a71cdbe9 73 //Check whether the Valid Lifetime field is non-zero
Sergunb 0:8918a71cdbe9 74 if(ntohl(option->validLifetime) != 0)
Sergunb 0:8918a71cdbe9 75 {
Sergunb 0:8918a71cdbe9 76 //If the prefix is not already present in the Prefix List, create a new
Sergunb 0:8918a71cdbe9 77 //entry for the prefix. If the prefix is already present in the list,
Sergunb 0:8918a71cdbe9 78 //reset its invalidation timer
Sergunb 0:8918a71cdbe9 79 ipv6AddPrefix(interface, &option->prefix, option->prefixLength,
Sergunb 0:8918a71cdbe9 80 ntohl(option->validLifetime), ntohl(option->preferredLifetime));
Sergunb 0:8918a71cdbe9 81 }
Sergunb 0:8918a71cdbe9 82 else
Sergunb 0:8918a71cdbe9 83 {
Sergunb 0:8918a71cdbe9 84 //If the new Lifetime value is zero, time-out the prefix immediately
Sergunb 0:8918a71cdbe9 85 ipv6RemovePrefix(interface, &option->prefix, option->prefixLength);
Sergunb 0:8918a71cdbe9 86 }
Sergunb 0:8918a71cdbe9 87 }
Sergunb 0:8918a71cdbe9 88
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90 /**
Sergunb 0:8918a71cdbe9 91 * @brief Manage the lifetime of IPv6 addresses
Sergunb 0:8918a71cdbe9 92 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 93 **/
Sergunb 0:8918a71cdbe9 94
Sergunb 0:8918a71cdbe9 95 void ndpUpdateAddrList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 96 {
Sergunb 0:8918a71cdbe9 97 uint_t i;
Sergunb 0:8918a71cdbe9 98 systime_t time;
Sergunb 0:8918a71cdbe9 99 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 100 NdpContext *context;
Sergunb 0:8918a71cdbe9 101
Sergunb 0:8918a71cdbe9 102 //Point to the NDP context
Sergunb 0:8918a71cdbe9 103 context = &interface->ndpContext;
Sergunb 0:8918a71cdbe9 104
Sergunb 0:8918a71cdbe9 105 //Get current time
Sergunb 0:8918a71cdbe9 106 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 107
Sergunb 0:8918a71cdbe9 108 //Go through the list of IPv6 addresses
Sergunb 0:8918a71cdbe9 109 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 110 {
Sergunb 0:8918a71cdbe9 111 //Point to the current entry
Sergunb 0:8918a71cdbe9 112 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Tentative address?
Sergunb 0:8918a71cdbe9 115 if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
Sergunb 0:8918a71cdbe9 116 {
Sergunb 0:8918a71cdbe9 117 //Check whether the link is up
Sergunb 0:8918a71cdbe9 118 if(interface->linkState)
Sergunb 0:8918a71cdbe9 119 {
Sergunb 0:8918a71cdbe9 120 //To check an address, a node should send Neighbor Solicitation messages
Sergunb 0:8918a71cdbe9 121 if(entry->dadRetransmitCount == 0)
Sergunb 0:8918a71cdbe9 122 {
Sergunb 0:8918a71cdbe9 123 //Set time stamp
Sergunb 0:8918a71cdbe9 124 entry->timestamp = time;
Sergunb 0:8918a71cdbe9 125
Sergunb 0:8918a71cdbe9 126 //Check whether Duplicate Address Detection should be performed
Sergunb 0:8918a71cdbe9 127 if(context->dupAddrDetectTransmits > 0)
Sergunb 0:8918a71cdbe9 128 {
Sergunb 0:8918a71cdbe9 129 //Link-local address?
Sergunb 0:8918a71cdbe9 130 if(i == 0)
Sergunb 0:8918a71cdbe9 131 {
Sergunb 0:8918a71cdbe9 132 //Delay before transmitting the first solicitation
Sergunb 0:8918a71cdbe9 133 entry->dadTimeout = netGetRandRange(0, NDP_MAX_RTR_SOLICITATION_DELAY);
Sergunb 0:8918a71cdbe9 134 //Prepare to send the first Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 135 entry->dadRetransmitCount = 1;
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137 else
Sergunb 0:8918a71cdbe9 138 {
Sergunb 0:8918a71cdbe9 139 //Valid link-local address?
Sergunb 0:8918a71cdbe9 140 if(ipv6GetLinkLocalAddrState(interface) == IPV6_ADDR_STATE_PREFERRED)
Sergunb 0:8918a71cdbe9 141 {
Sergunb 0:8918a71cdbe9 142 //Prepare to send the first Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 143 entry->dadTimeout = 0;
Sergunb 0:8918a71cdbe9 144 entry->dadRetransmitCount = 1;
Sergunb 0:8918a71cdbe9 145 }
Sergunb 0:8918a71cdbe9 146 }
Sergunb 0:8918a71cdbe9 147 }
Sergunb 0:8918a71cdbe9 148 else
Sergunb 0:8918a71cdbe9 149 {
Sergunb 0:8918a71cdbe9 150 //Do not perform Duplicate Address Detection
Sergunb 0:8918a71cdbe9 151 entry->state = IPV6_ADDR_STATE_PREFERRED;
Sergunb 0:8918a71cdbe9 152 }
Sergunb 0:8918a71cdbe9 153 }
Sergunb 0:8918a71cdbe9 154 else
Sergunb 0:8918a71cdbe9 155 {
Sergunb 0:8918a71cdbe9 156 //Check current time
Sergunb 0:8918a71cdbe9 157 if(timeCompare(time, entry->timestamp + entry->dadTimeout) >= 0)
Sergunb 0:8918a71cdbe9 158 {
Sergunb 0:8918a71cdbe9 159 //Duplicate Address Detection failed?
Sergunb 0:8918a71cdbe9 160 if(entry->duplicate)
Sergunb 0:8918a71cdbe9 161 {
Sergunb 0:8918a71cdbe9 162 //A tentative address that is determined to be a duplicate
Sergunb 0:8918a71cdbe9 163 //must not be assigned to an interface
Sergunb 0:8918a71cdbe9 164 if(entry->permanent)
Sergunb 0:8918a71cdbe9 165 {
Sergunb 0:8918a71cdbe9 166 //The IPv6 address should be preserved if it has been
Sergunb 0:8918a71cdbe9 167 //manually assigned
Sergunb 0:8918a71cdbe9 168 ipv6SetAddr(interface, i, &entry->addr,
Sergunb 0:8918a71cdbe9 169 IPV6_ADDR_STATE_INVALID, 0, 0, TRUE);
Sergunb 0:8918a71cdbe9 170 }
Sergunb 0:8918a71cdbe9 171 else
Sergunb 0:8918a71cdbe9 172 {
Sergunb 0:8918a71cdbe9 173 //The IPv6 address is no more valid and should be
Sergunb 0:8918a71cdbe9 174 //removed from the list
Sergunb 0:8918a71cdbe9 175 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
Sergunb 0:8918a71cdbe9 176 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE);
Sergunb 0:8918a71cdbe9 177 }
Sergunb 0:8918a71cdbe9 178 }
Sergunb 0:8918a71cdbe9 179 //Duplicate Address Detection is on-going?
Sergunb 0:8918a71cdbe9 180 else if(entry->dadRetransmitCount <= context->dupAddrDetectTransmits)
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 //Send a multicast Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 183 ndpSendNeighborSol(interface, &entry->addr, TRUE);
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Set timeout value
Sergunb 0:8918a71cdbe9 186 entry->dadTimeout += context->retransTimer;
Sergunb 0:8918a71cdbe9 187 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 188 entry->dadRetransmitCount++;
Sergunb 0:8918a71cdbe9 189 }
Sergunb 0:8918a71cdbe9 190 //Duplicate Address Detection is complete?
Sergunb 0:8918a71cdbe9 191 else
Sergunb 0:8918a71cdbe9 192 {
Sergunb 0:8918a71cdbe9 193 //The use of the IPv6 address is now unrestricted
Sergunb 0:8918a71cdbe9 194 entry->state = IPV6_ADDR_STATE_PREFERRED;
Sergunb 0:8918a71cdbe9 195
Sergunb 0:8918a71cdbe9 196 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 197 //Link-local address?
Sergunb 0:8918a71cdbe9 198 if(i == 0)
Sergunb 0:8918a71cdbe9 199 {
Sergunb 0:8918a71cdbe9 200 //Restart mDNS probing process
Sergunb 0:8918a71cdbe9 201 mdnsResponderStartProbing(interface->mdnsResponderContext);
Sergunb 0:8918a71cdbe9 202 }
Sergunb 0:8918a71cdbe9 203 #endif
Sergunb 0:8918a71cdbe9 204 }
Sergunb 0:8918a71cdbe9 205 }
Sergunb 0:8918a71cdbe9 206 }
Sergunb 0:8918a71cdbe9 207 }
Sergunb 0:8918a71cdbe9 208 }
Sergunb 0:8918a71cdbe9 209 //Preferred address?
Sergunb 0:8918a71cdbe9 210 else if(entry->state == IPV6_ADDR_STATE_PREFERRED)
Sergunb 0:8918a71cdbe9 211 {
Sergunb 0:8918a71cdbe9 212 //An IPv6 address with an infinite preferred lifetime is never timed out
Sergunb 0:8918a71cdbe9 213 if(entry->preferredLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 214 {
Sergunb 0:8918a71cdbe9 215 //When the preferred lifetime expires, the address becomes deprecated
Sergunb 0:8918a71cdbe9 216 if(timeCompare(time, entry->timestamp + entry->preferredLifetime) >= 0)
Sergunb 0:8918a71cdbe9 217 {
Sergunb 0:8918a71cdbe9 218 //A deprecated address should continue to be used as a source
Sergunb 0:8918a71cdbe9 219 //address in existing communications, but should not be used
Sergunb 0:8918a71cdbe9 220 //to initiate new communications
Sergunb 0:8918a71cdbe9 221 entry->state = IPV6_ADDR_STATE_DEPRECATED;
Sergunb 0:8918a71cdbe9 222 }
Sergunb 0:8918a71cdbe9 223 }
Sergunb 0:8918a71cdbe9 224 }
Sergunb 0:8918a71cdbe9 225 //Deprecated address?
Sergunb 0:8918a71cdbe9 226 else if(entry->state == IPV6_ADDR_STATE_DEPRECATED)
Sergunb 0:8918a71cdbe9 227 {
Sergunb 0:8918a71cdbe9 228 //An IPv6 address with an infinite valid lifetime is never timed out
Sergunb 0:8918a71cdbe9 229 if(entry->validLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 230 {
Sergunb 0:8918a71cdbe9 231 //When the valid lifetime expires, the address becomes invalid
Sergunb 0:8918a71cdbe9 232 if(timeCompare(time, entry->timestamp + entry->validLifetime) >= 0)
Sergunb 0:8918a71cdbe9 233 {
Sergunb 0:8918a71cdbe9 234 //The IPv6 address is no more valid and should be removed from the list
Sergunb 0:8918a71cdbe9 235 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
Sergunb 0:8918a71cdbe9 236 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE);
Sergunb 0:8918a71cdbe9 237 }
Sergunb 0:8918a71cdbe9 238 }
Sergunb 0:8918a71cdbe9 239 }
Sergunb 0:8918a71cdbe9 240 }
Sergunb 0:8918a71cdbe9 241 }
Sergunb 0:8918a71cdbe9 242
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244 /**
Sergunb 0:8918a71cdbe9 245 * @brief Periodically update Prefix List
Sergunb 0:8918a71cdbe9 246 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 247 **/
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249 void ndpUpdatePrefixList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 250 {
Sergunb 0:8918a71cdbe9 251 uint_t i;
Sergunb 0:8918a71cdbe9 252 systime_t time;
Sergunb 0:8918a71cdbe9 253 Ipv6PrefixEntry *entry;
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Get current time
Sergunb 0:8918a71cdbe9 256 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 257
Sergunb 0:8918a71cdbe9 258 //Go through the Prefix List
Sergunb 0:8918a71cdbe9 259 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 260 {
Sergunb 0:8918a71cdbe9 261 //Point to the current entry
Sergunb 0:8918a71cdbe9 262 entry = &interface->ipv6Context.prefixList[i];
Sergunb 0:8918a71cdbe9 263
Sergunb 0:8918a71cdbe9 264 //Check the lifetime value
Sergunb 0:8918a71cdbe9 265 if(entry->validLifetime > 0 && entry->validLifetime < INFINITE_DELAY)
Sergunb 0:8918a71cdbe9 266 {
Sergunb 0:8918a71cdbe9 267 //A node should retain entries in the Prefix List until their
Sergunb 0:8918a71cdbe9 268 //lifetimes expire
Sergunb 0:8918a71cdbe9 269 if(timeCompare(time, entry->timestamp + entry->validLifetime) >= 0)
Sergunb 0:8918a71cdbe9 270 {
Sergunb 0:8918a71cdbe9 271 //When removing an entry from the Prefix List, there is no need
Sergunb 0:8918a71cdbe9 272 //to purge any entries from the Destination or Neighbor Caches
Sergunb 0:8918a71cdbe9 273 ipv6RemovePrefix(interface, &entry->prefix, entry->prefixLength);
Sergunb 0:8918a71cdbe9 274 }
Sergunb 0:8918a71cdbe9 275 }
Sergunb 0:8918a71cdbe9 276 }
Sergunb 0:8918a71cdbe9 277 }
Sergunb 0:8918a71cdbe9 278
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 /**
Sergunb 0:8918a71cdbe9 281 * @brief Periodically update Default Router List
Sergunb 0:8918a71cdbe9 282 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 283 **/
Sergunb 0:8918a71cdbe9 284
Sergunb 0:8918a71cdbe9 285 void ndpUpdateDefaultRouterList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 286 {
Sergunb 0:8918a71cdbe9 287 uint_t i;
Sergunb 0:8918a71cdbe9 288 bool_t flag;
Sergunb 0:8918a71cdbe9 289 systime_t time;
Sergunb 0:8918a71cdbe9 290 Ipv6RouterEntry *entry;
Sergunb 0:8918a71cdbe9 291
Sergunb 0:8918a71cdbe9 292 //This flag will be set if any entry has been removed from
Sergunb 0:8918a71cdbe9 293 //the Default Router List
Sergunb 0:8918a71cdbe9 294 flag = FALSE;
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296 //Get current time
Sergunb 0:8918a71cdbe9 297 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 298
Sergunb 0:8918a71cdbe9 299 //Go through the Default Router List
Sergunb 0:8918a71cdbe9 300 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 301 {
Sergunb 0:8918a71cdbe9 302 //Point to the current entry
Sergunb 0:8918a71cdbe9 303 entry = &interface->ipv6Context.routerList[i];
Sergunb 0:8918a71cdbe9 304
Sergunb 0:8918a71cdbe9 305 //Check the lifetime value
Sergunb 0:8918a71cdbe9 306 if(entry->lifetime > 0 && entry->lifetime < INFINITE_DELAY)
Sergunb 0:8918a71cdbe9 307 {
Sergunb 0:8918a71cdbe9 308 //A node should retain entries in the Default Router List until
Sergunb 0:8918a71cdbe9 309 //their lifetimes expire
Sergunb 0:8918a71cdbe9 310 if(timeCompare(time, entry->timestamp + entry->lifetime) >= 0)
Sergunb 0:8918a71cdbe9 311 {
Sergunb 0:8918a71cdbe9 312 //Immediately time-out the entry
Sergunb 0:8918a71cdbe9 313 entry->addr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 314 entry->lifetime = 0;
Sergunb 0:8918a71cdbe9 315
Sergunb 0:8918a71cdbe9 316 //Set flag
Sergunb 0:8918a71cdbe9 317 flag = TRUE;
Sergunb 0:8918a71cdbe9 318 }
Sergunb 0:8918a71cdbe9 319 }
Sergunb 0:8918a71cdbe9 320 }
Sergunb 0:8918a71cdbe9 321
Sergunb 0:8918a71cdbe9 322 //Check whether an entry has been removed from the list
Sergunb 0:8918a71cdbe9 323 if(flag)
Sergunb 0:8918a71cdbe9 324 {
Sergunb 0:8918a71cdbe9 325 //When removing an entry from the Default Router List, any entries
Sergunb 0:8918a71cdbe9 326 //in the Destination Cache that go through that router must perform
Sergunb 0:8918a71cdbe9 327 //next-hop determination again to select a new default router
Sergunb 0:8918a71cdbe9 328 ndpFlushDestCache(interface);
Sergunb 0:8918a71cdbe9 329 }
Sergunb 0:8918a71cdbe9 330 }
Sergunb 0:8918a71cdbe9 331
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 /**
Sergunb 0:8918a71cdbe9 334 * @brief Default Router Selection
Sergunb 0:8918a71cdbe9 335 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 336 * @param[in] unreachableAddr IPv6 address of the unreachable router (optional parameter)
Sergunb 0:8918a71cdbe9 337 * @param[out] addr IPv6 address of the default router to be used
Sergunb 0:8918a71cdbe9 338 * @return Error code
Sergunb 0:8918a71cdbe9 339 **/
Sergunb 0:8918a71cdbe9 340
Sergunb 0:8918a71cdbe9 341 error_t ndpSelectDefaultRouter(NetInterface *interface,
Sergunb 0:8918a71cdbe9 342 const Ipv6Addr *unreachableAddr, Ipv6Addr *addr)
Sergunb 0:8918a71cdbe9 343 {
Sergunb 0:8918a71cdbe9 344 uint_t i;
Sergunb 0:8918a71cdbe9 345 uint_t j;
Sergunb 0:8918a71cdbe9 346 uint_t k;
Sergunb 0:8918a71cdbe9 347 Ipv6RouterEntry *routerEntry;
Sergunb 0:8918a71cdbe9 348 NdpNeighborCacheEntry *neighborCacheEntry;
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 //Initialize index
Sergunb 0:8918a71cdbe9 351 i = 0;
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 //This parameter is optional...
Sergunb 0:8918a71cdbe9 354 if(unreachableAddr != NULL)
Sergunb 0:8918a71cdbe9 355 {
Sergunb 0:8918a71cdbe9 356 //Search the Default Router List for the router whose reachability is suspect
Sergunb 0:8918a71cdbe9 357 for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
Sergunb 0:8918a71cdbe9 358 {
Sergunb 0:8918a71cdbe9 359 //Point to the current entry
Sergunb 0:8918a71cdbe9 360 routerEntry = &interface->ipv6Context.routerList[j];
Sergunb 0:8918a71cdbe9 361
Sergunb 0:8918a71cdbe9 362 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 363 if(routerEntry->lifetime)
Sergunb 0:8918a71cdbe9 364 {
Sergunb 0:8918a71cdbe9 365 //Check the router address against the address whose reachability is suspect
Sergunb 0:8918a71cdbe9 366 if(ipv6CompAddr(&routerEntry->addr, unreachableAddr))
Sergunb 0:8918a71cdbe9 367 {
Sergunb 0:8918a71cdbe9 368 //Routers should be selected in a round-robin fashion
Sergunb 0:8918a71cdbe9 369 i = j + 1;
Sergunb 0:8918a71cdbe9 370 //We are done
Sergunb 0:8918a71cdbe9 371 break;
Sergunb 0:8918a71cdbe9 372 }
Sergunb 0:8918a71cdbe9 373 }
Sergunb 0:8918a71cdbe9 374 }
Sergunb 0:8918a71cdbe9 375 }
Sergunb 0:8918a71cdbe9 376
Sergunb 0:8918a71cdbe9 377 //Routers that are reachable or probably reachable should be preferred
Sergunb 0:8918a71cdbe9 378 //over routers whose reachability is unknown or suspect
Sergunb 0:8918a71cdbe9 379 for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
Sergunb 0:8918a71cdbe9 380 {
Sergunb 0:8918a71cdbe9 381 //Get current index
Sergunb 0:8918a71cdbe9 382 k = (i + j) % IPV6_ROUTER_LIST_SIZE;
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 //Point to the corresponding entry
Sergunb 0:8918a71cdbe9 385 routerEntry = &interface->ipv6Context.routerList[k];
Sergunb 0:8918a71cdbe9 386
Sergunb 0:8918a71cdbe9 387 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 388 if(routerEntry->lifetime)
Sergunb 0:8918a71cdbe9 389 {
Sergunb 0:8918a71cdbe9 390 //Search the Neighbor Cache for the router address
Sergunb 0:8918a71cdbe9 391 neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &routerEntry->addr);
Sergunb 0:8918a71cdbe9 392
Sergunb 0:8918a71cdbe9 393 //Check whether the router is reachable or probably reachable
Sergunb 0:8918a71cdbe9 394 if(neighborCacheEntry != NULL)
Sergunb 0:8918a71cdbe9 395 {
Sergunb 0:8918a71cdbe9 396 //Any state other than INCOMPLETE?
Sergunb 0:8918a71cdbe9 397 if(neighborCacheEntry->state != NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 398 {
Sergunb 0:8918a71cdbe9 399 //Return the IPv6 address of the default router
Sergunb 0:8918a71cdbe9 400 *addr = routerEntry->addr;
Sergunb 0:8918a71cdbe9 401 //Successful default router selection
Sergunb 0:8918a71cdbe9 402 return NO_ERROR;
Sergunb 0:8918a71cdbe9 403 }
Sergunb 0:8918a71cdbe9 404 }
Sergunb 0:8918a71cdbe9 405 }
Sergunb 0:8918a71cdbe9 406 }
Sergunb 0:8918a71cdbe9 407
Sergunb 0:8918a71cdbe9 408 //When no routers on the list are known to be reachable or probably
Sergunb 0:8918a71cdbe9 409 //reachable, routers should be selected in a round-robin fashion, so
Sergunb 0:8918a71cdbe9 410 //that subsequent requests for a default router do not return the
Sergunb 0:8918a71cdbe9 411 //same router until all other routers have been selected
Sergunb 0:8918a71cdbe9 412 for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
Sergunb 0:8918a71cdbe9 413 {
Sergunb 0:8918a71cdbe9 414 //Get current index
Sergunb 0:8918a71cdbe9 415 k = (i + j) % IPV6_ROUTER_LIST_SIZE;
Sergunb 0:8918a71cdbe9 416
Sergunb 0:8918a71cdbe9 417 //Point to the corresponding entry
Sergunb 0:8918a71cdbe9 418 routerEntry = &interface->ipv6Context.routerList[k];
Sergunb 0:8918a71cdbe9 419
Sergunb 0:8918a71cdbe9 420 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 421 if(routerEntry->lifetime)
Sergunb 0:8918a71cdbe9 422 {
Sergunb 0:8918a71cdbe9 423 //Return the IPv6 address of the default router
Sergunb 0:8918a71cdbe9 424 *addr = routerEntry->addr;
Sergunb 0:8918a71cdbe9 425 //Successful default router selection
Sergunb 0:8918a71cdbe9 426 return NO_ERROR;
Sergunb 0:8918a71cdbe9 427 }
Sergunb 0:8918a71cdbe9 428 }
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 //No default router found...
Sergunb 0:8918a71cdbe9 431 return ERROR_NO_ROUTE;
Sergunb 0:8918a71cdbe9 432 }
Sergunb 0:8918a71cdbe9 433
Sergunb 0:8918a71cdbe9 434
Sergunb 0:8918a71cdbe9 435 /**
Sergunb 0:8918a71cdbe9 436 * @brief Check whether an address is the first-hop router for the specified destination
Sergunb 0:8918a71cdbe9 437 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 438 * @param[in] destAddr Destination address
Sergunb 0:8918a71cdbe9 439 * @param[in] nextHop First-hop address to be checked
Sergunb 0:8918a71cdbe9 440 * @return TRUE if the address is the first-hop router, else FALSE
Sergunb 0:8918a71cdbe9 441 **/
Sergunb 0:8918a71cdbe9 442
Sergunb 0:8918a71cdbe9 443 bool_t ndpIsFirstHopRouter(NetInterface *interface,
Sergunb 0:8918a71cdbe9 444 const Ipv6Addr *destAddr, const Ipv6Addr *nextHop)
Sergunb 0:8918a71cdbe9 445 {
Sergunb 0:8918a71cdbe9 446 uint_t i;
Sergunb 0:8918a71cdbe9 447 bool_t isFirstHopRouter;
Sergunb 0:8918a71cdbe9 448 Ipv6RouterEntry *routerEntry;
Sergunb 0:8918a71cdbe9 449 NdpDestCacheEntry *destCacheEntry;
Sergunb 0:8918a71cdbe9 450
Sergunb 0:8918a71cdbe9 451 //Clear flag
Sergunb 0:8918a71cdbe9 452 isFirstHopRouter = FALSE;
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 //Search the cache for the specified destination address
Sergunb 0:8918a71cdbe9 455 destCacheEntry = ndpFindDestCacheEntry(interface, destAddr);
Sergunb 0:8918a71cdbe9 456
Sergunb 0:8918a71cdbe9 457 //Any matching entry?
Sergunb 0:8918a71cdbe9 458 if(destCacheEntry != NULL)
Sergunb 0:8918a71cdbe9 459 {
Sergunb 0:8918a71cdbe9 460 //Check if the address is the same as the current first-hop
Sergunb 0:8918a71cdbe9 461 //router for the specified destination
Sergunb 0:8918a71cdbe9 462 if(ipv6CompAddr(&destCacheEntry->nextHop, nextHop))
Sergunb 0:8918a71cdbe9 463 isFirstHopRouter = TRUE;
Sergunb 0:8918a71cdbe9 464 }
Sergunb 0:8918a71cdbe9 465 else
Sergunb 0:8918a71cdbe9 466 {
Sergunb 0:8918a71cdbe9 467 //Loop through the Default Router List
Sergunb 0:8918a71cdbe9 468 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 469 {
Sergunb 0:8918a71cdbe9 470 //Point to the current entry
Sergunb 0:8918a71cdbe9 471 routerEntry = &interface->ipv6Context.routerList[i];
Sergunb 0:8918a71cdbe9 472
Sergunb 0:8918a71cdbe9 473 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 474 if(routerEntry->lifetime)
Sergunb 0:8918a71cdbe9 475 {
Sergunb 0:8918a71cdbe9 476 //Check whether the current entry matches the specified address
Sergunb 0:8918a71cdbe9 477 if(ipv6CompAddr(&routerEntry->addr, nextHop))
Sergunb 0:8918a71cdbe9 478 {
Sergunb 0:8918a71cdbe9 479 //The specified address is a valid first-hop router
Sergunb 0:8918a71cdbe9 480 isFirstHopRouter = TRUE;
Sergunb 0:8918a71cdbe9 481 //We are done
Sergunb 0:8918a71cdbe9 482 break;
Sergunb 0:8918a71cdbe9 483 }
Sergunb 0:8918a71cdbe9 484 }
Sergunb 0:8918a71cdbe9 485 }
Sergunb 0:8918a71cdbe9 486 }
Sergunb 0:8918a71cdbe9 487
Sergunb 0:8918a71cdbe9 488 //Return TRUE if the address is the same as the current first-hop
Sergunb 0:8918a71cdbe9 489 //router for the specified destination
Sergunb 0:8918a71cdbe9 490 return isFirstHopRouter;
Sergunb 0:8918a71cdbe9 491 }
Sergunb 0:8918a71cdbe9 492
Sergunb 0:8918a71cdbe9 493
Sergunb 0:8918a71cdbe9 494 /**
Sergunb 0:8918a71cdbe9 495 * @brief Next-hop determination
Sergunb 0:8918a71cdbe9 496 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 497 * @param[in] destAddr Destination address
Sergunb 0:8918a71cdbe9 498 * @param[in] unreachableNextHop Address of the unreachable next-hop (optional parameter)
Sergunb 0:8918a71cdbe9 499 * @param[out] nextHop Next-hop address to be used
Sergunb 0:8918a71cdbe9 500 * @return Error code
Sergunb 0:8918a71cdbe9 501 **/
Sergunb 0:8918a71cdbe9 502
Sergunb 0:8918a71cdbe9 503 error_t ndpSelectNextHop(NetInterface *interface, const Ipv6Addr *destAddr,
Sergunb 0:8918a71cdbe9 504 const Ipv6Addr *unreachableNextHop, Ipv6Addr *nextHop)
Sergunb 0:8918a71cdbe9 505 {
Sergunb 0:8918a71cdbe9 506 error_t error;
Sergunb 0:8918a71cdbe9 507
Sergunb 0:8918a71cdbe9 508 //Destination IPv6 address is a multicast address?
Sergunb 0:8918a71cdbe9 509 if(ipv6IsMulticastAddr(destAddr))
Sergunb 0:8918a71cdbe9 510 {
Sergunb 0:8918a71cdbe9 511 //For multicast packets, the next-hop is always the (multicast)
Sergunb 0:8918a71cdbe9 512 //destination address and is considered to be on-link
Sergunb 0:8918a71cdbe9 513 *nextHop = *destAddr;
Sergunb 0:8918a71cdbe9 514 //Successful next-hop determination
Sergunb 0:8918a71cdbe9 515 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 516 }
Sergunb 0:8918a71cdbe9 517 else
Sergunb 0:8918a71cdbe9 518 {
Sergunb 0:8918a71cdbe9 519 //The sender performs a longest prefix match against the Prefix
Sergunb 0:8918a71cdbe9 520 //List to determine whether the packet's destination is on-link
Sergunb 0:8918a71cdbe9 521 //or off-link
Sergunb 0:8918a71cdbe9 522 if(ipv6IsOnLink(interface, destAddr))
Sergunb 0:8918a71cdbe9 523 {
Sergunb 0:8918a71cdbe9 524 //If the destination is on-link, the next-hop address is the
Sergunb 0:8918a71cdbe9 525 //same as the packet's destination address
Sergunb 0:8918a71cdbe9 526 *nextHop = *destAddr;
Sergunb 0:8918a71cdbe9 527 //Successful next-hop determination
Sergunb 0:8918a71cdbe9 528 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 529 }
Sergunb 0:8918a71cdbe9 530 else
Sergunb 0:8918a71cdbe9 531 {
Sergunb 0:8918a71cdbe9 532 //If the destination is off-link, the sender selects a router
Sergunb 0:8918a71cdbe9 533 //from the Default Router List
Sergunb 0:8918a71cdbe9 534 error = ndpSelectDefaultRouter(interface, unreachableNextHop, nextHop);
Sergunb 0:8918a71cdbe9 535 }
Sergunb 0:8918a71cdbe9 536 }
Sergunb 0:8918a71cdbe9 537
Sergunb 0:8918a71cdbe9 538 //Return status code
Sergunb 0:8918a71cdbe9 539 return error;
Sergunb 0:8918a71cdbe9 540 }
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542
Sergunb 0:8918a71cdbe9 543 /**
Sergunb 0:8918a71cdbe9 544 * @brief Update next-hop field of Destination Cache entries
Sergunb 0:8918a71cdbe9 545 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 546 * @param[in] unreachableNextHop Address of the unreachable next-hop
Sergunb 0:8918a71cdbe9 547 **/
Sergunb 0:8918a71cdbe9 548
Sergunb 0:8918a71cdbe9 549 void ndpUpdateNextHop(NetInterface *interface, const Ipv6Addr *unreachableNextHop)
Sergunb 0:8918a71cdbe9 550 {
Sergunb 0:8918a71cdbe9 551 error_t error;
Sergunb 0:8918a71cdbe9 552 uint_t i;
Sergunb 0:8918a71cdbe9 553 NdpDestCacheEntry *entry;
Sergunb 0:8918a71cdbe9 554
Sergunb 0:8918a71cdbe9 555 //Go through Destination Cache
Sergunb 0:8918a71cdbe9 556 for(i = 0; i < NDP_DEST_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 557 {
Sergunb 0:8918a71cdbe9 558 //Point to the current entry
Sergunb 0:8918a71cdbe9 559 entry = &interface->ndpContext.destCache[i];
Sergunb 0:8918a71cdbe9 560
Sergunb 0:8918a71cdbe9 561 //Check whether the unreachable IPv6 address is used a first-hop router
Sergunb 0:8918a71cdbe9 562 if(ipv6CompAddr(&entry->nextHop, unreachableNextHop))
Sergunb 0:8918a71cdbe9 563 {
Sergunb 0:8918a71cdbe9 564 //Perform next-hop determination
Sergunb 0:8918a71cdbe9 565 error = ndpSelectNextHop(interface, &entry->destAddr,
Sergunb 0:8918a71cdbe9 566 &entry->nextHop, &entry->nextHop);
Sergunb 0:8918a71cdbe9 567
Sergunb 0:8918a71cdbe9 568 //Next-hop determination failed?
Sergunb 0:8918a71cdbe9 569 if(error)
Sergunb 0:8918a71cdbe9 570 {
Sergunb 0:8918a71cdbe9 571 //Remove the current entry from the Destination Cache
Sergunb 0:8918a71cdbe9 572 entry->destAddr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 573 }
Sergunb 0:8918a71cdbe9 574 }
Sergunb 0:8918a71cdbe9 575 }
Sergunb 0:8918a71cdbe9 576 }
Sergunb 0:8918a71cdbe9 577
Sergunb 0:8918a71cdbe9 578
Sergunb 0:8918a71cdbe9 579 /**
Sergunb 0:8918a71cdbe9 580 * @brief Append an option to a NDP message
Sergunb 0:8918a71cdbe9 581 * @param[in] message Pointer to the NDP message
Sergunb 0:8918a71cdbe9 582 * @param[in,out] messageLength Length of the entire message
Sergunb 0:8918a71cdbe9 583 * @param[in] type Option type
Sergunb 0:8918a71cdbe9 584 * @param[in] value Option value
Sergunb 0:8918a71cdbe9 585 * @param[in] length Length of the option value
Sergunb 0:8918a71cdbe9 586 **/
Sergunb 0:8918a71cdbe9 587
Sergunb 0:8918a71cdbe9 588 void ndpAddOption(void *message, size_t *messageLength,
Sergunb 0:8918a71cdbe9 589 uint8_t type, const void *value, size_t length)
Sergunb 0:8918a71cdbe9 590 {
Sergunb 0:8918a71cdbe9 591 size_t optionLength;
Sergunb 0:8918a71cdbe9 592 size_t paddingLength;
Sergunb 0:8918a71cdbe9 593 NdpOption *option;
Sergunb 0:8918a71cdbe9 594
Sergunb 0:8918a71cdbe9 595 //Length of the option in units of 8 bytes including the type and length fields
Sergunb 0:8918a71cdbe9 596 optionLength = (length + sizeof(NdpOption) + 7) / 8;
Sergunb 0:8918a71cdbe9 597
Sergunb 0:8918a71cdbe9 598 //Sanity check
Sergunb 0:8918a71cdbe9 599 if(optionLength <= UINT8_MAX)
Sergunb 0:8918a71cdbe9 600 {
Sergunb 0:8918a71cdbe9 601 //Point to the buffer where the option is to be written
Sergunb 0:8918a71cdbe9 602 option = (NdpOption *) ((uint8_t *) message + *messageLength);
Sergunb 0:8918a71cdbe9 603
Sergunb 0:8918a71cdbe9 604 //Option type
Sergunb 0:8918a71cdbe9 605 option->type = type;
Sergunb 0:8918a71cdbe9 606 //Option length
Sergunb 0:8918a71cdbe9 607 option->length = (uint8_t) optionLength;
Sergunb 0:8918a71cdbe9 608 //Option value
Sergunb 0:8918a71cdbe9 609 memcpy(option->value, value, length);
Sergunb 0:8918a71cdbe9 610
Sergunb 0:8918a71cdbe9 611 //Options should be padded when necessary to ensure that they end on
Sergunb 0:8918a71cdbe9 612 //their natural 64-bit boundaries
Sergunb 0:8918a71cdbe9 613 if((length + sizeof(NdpOption)) < (optionLength * 8))
Sergunb 0:8918a71cdbe9 614 {
Sergunb 0:8918a71cdbe9 615 //Determine the amount of padding data to append
Sergunb 0:8918a71cdbe9 616 paddingLength = (optionLength * 8) - length - sizeof(NdpOption);
Sergunb 0:8918a71cdbe9 617 //Write padding data
Sergunb 0:8918a71cdbe9 618 memset(option->value + length, 0, paddingLength);
Sergunb 0:8918a71cdbe9 619 }
Sergunb 0:8918a71cdbe9 620
Sergunb 0:8918a71cdbe9 621 //Adjust the length of the NDP message
Sergunb 0:8918a71cdbe9 622 *messageLength += optionLength * 8;
Sergunb 0:8918a71cdbe9 623 }
Sergunb 0:8918a71cdbe9 624 }
Sergunb 0:8918a71cdbe9 625
Sergunb 0:8918a71cdbe9 626
Sergunb 0:8918a71cdbe9 627 /**
Sergunb 0:8918a71cdbe9 628 * @brief Find a specified option in a NDP message
Sergunb 0:8918a71cdbe9 629 * @param[in] options Pointer to the Options field
Sergunb 0:8918a71cdbe9 630 * @param[in] length Length of the Options field
Sergunb 0:8918a71cdbe9 631 * @param[in] type Type of the option to find
Sergunb 0:8918a71cdbe9 632 * @return If the specified option is found, a pointer to the corresponding
Sergunb 0:8918a71cdbe9 633 * option is returned. Otherwise NULL pointer is returned
Sergunb 0:8918a71cdbe9 634 **/
Sergunb 0:8918a71cdbe9 635
Sergunb 0:8918a71cdbe9 636 void *ndpGetOption(uint8_t *options, size_t length, uint8_t type)
Sergunb 0:8918a71cdbe9 637 {
Sergunb 0:8918a71cdbe9 638 size_t i;
Sergunb 0:8918a71cdbe9 639 NdpOption *option;
Sergunb 0:8918a71cdbe9 640
Sergunb 0:8918a71cdbe9 641 //Point to the very first option of the NDP message
Sergunb 0:8918a71cdbe9 642 i = 0;
Sergunb 0:8918a71cdbe9 643
Sergunb 0:8918a71cdbe9 644 //Parse options
Sergunb 0:8918a71cdbe9 645 while((i + sizeof(NdpOption)) <= length)
Sergunb 0:8918a71cdbe9 646 {
Sergunb 0:8918a71cdbe9 647 //Point to the current option
Sergunb 0:8918a71cdbe9 648 option = (NdpOption *) (options + i);
Sergunb 0:8918a71cdbe9 649
Sergunb 0:8918a71cdbe9 650 //Nodes must silently discard an NDP message that contains
Sergunb 0:8918a71cdbe9 651 //an option with length zero
Sergunb 0:8918a71cdbe9 652 if(option->length == 0)
Sergunb 0:8918a71cdbe9 653 break;
Sergunb 0:8918a71cdbe9 654 //Check option length
Sergunb 0:8918a71cdbe9 655 if((i + option->length * 8) > length)
Sergunb 0:8918a71cdbe9 656 break;
Sergunb 0:8918a71cdbe9 657
Sergunb 0:8918a71cdbe9 658 //Current option type matches the specified one?
Sergunb 0:8918a71cdbe9 659 if(option->type == type || type == NDP_OPT_ANY)
Sergunb 0:8918a71cdbe9 660 return option;
Sergunb 0:8918a71cdbe9 661
Sergunb 0:8918a71cdbe9 662 //Jump to next the next option
Sergunb 0:8918a71cdbe9 663 i += option->length * 8;
Sergunb 0:8918a71cdbe9 664 }
Sergunb 0:8918a71cdbe9 665
Sergunb 0:8918a71cdbe9 666 //Specified option type not found
Sergunb 0:8918a71cdbe9 667 return NULL;
Sergunb 0:8918a71cdbe9 668 }
Sergunb 0:8918a71cdbe9 669
Sergunb 0:8918a71cdbe9 670
Sergunb 0:8918a71cdbe9 671 /**
Sergunb 0:8918a71cdbe9 672 * @brief Check NDP message options
Sergunb 0:8918a71cdbe9 673 * @param[in] options Pointer to the Options field
Sergunb 0:8918a71cdbe9 674 * @param[in] length Length of the Options field
Sergunb 0:8918a71cdbe9 675 * @return Error code
Sergunb 0:8918a71cdbe9 676 **/
Sergunb 0:8918a71cdbe9 677
Sergunb 0:8918a71cdbe9 678 error_t ndpCheckOptions(const uint8_t *options, size_t length)
Sergunb 0:8918a71cdbe9 679 {
Sergunb 0:8918a71cdbe9 680 size_t i;
Sergunb 0:8918a71cdbe9 681 NdpOption *option;
Sergunb 0:8918a71cdbe9 682
Sergunb 0:8918a71cdbe9 683 //Point to the very first option of the NDP message
Sergunb 0:8918a71cdbe9 684 i = 0;
Sergunb 0:8918a71cdbe9 685
Sergunb 0:8918a71cdbe9 686 //Parse options
Sergunb 0:8918a71cdbe9 687 while((i + sizeof(NdpOption)) <= length)
Sergunb 0:8918a71cdbe9 688 {
Sergunb 0:8918a71cdbe9 689 //Point to the current option
Sergunb 0:8918a71cdbe9 690 option = (NdpOption *) (options + i);
Sergunb 0:8918a71cdbe9 691
Sergunb 0:8918a71cdbe9 692 //Nodes must silently discard an NDP message that contains
Sergunb 0:8918a71cdbe9 693 //an option with length zero
Sergunb 0:8918a71cdbe9 694 if(option->length == 0)
Sergunb 0:8918a71cdbe9 695 return ERROR_INVALID_OPTION;
Sergunb 0:8918a71cdbe9 696
Sergunb 0:8918a71cdbe9 697 //Jump to next the next option
Sergunb 0:8918a71cdbe9 698 i += option->length * 8;
Sergunb 0:8918a71cdbe9 699 }
Sergunb 0:8918a71cdbe9 700
Sergunb 0:8918a71cdbe9 701 //The Options field is valid
Sergunb 0:8918a71cdbe9 702 return NO_ERROR;
Sergunb 0:8918a71cdbe9 703 }
Sergunb 0:8918a71cdbe9 704
Sergunb 0:8918a71cdbe9 705 #endif
Sergunb 0:8918a71cdbe9 706