Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ndp_router_adv.c
Go to the documentation of this file.
00001 /** 00002 * @file ndp_router_adv.c 00003 * @brief Router advertisement service 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL NDP_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "core/ip.h" 00035 #include "ipv6/ipv6.h" 00036 #include "ipv6/ipv6_misc.h" 00037 #include "ipv6/icmpv6.h" 00038 #include "ipv6/ndp.h" 00039 #include "ipv6/ndp_cache.h" 00040 #include "ipv6/ndp_misc.h" 00041 #include "ipv6/ndp_router_adv.h" 00042 #include "debug.h" 00043 00044 //Check TCP/IP stack configuration 00045 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED) 00046 00047 //Tick counter to handle periodic operations 00048 systime_t ndpRouterAdvTickCounter; 00049 00050 00051 /** 00052 * @brief Initialize settings with default values 00053 * @param[out] settings Structure that contains the RA service configuration variables 00054 **/ 00055 00056 void ndpRouterAdvGetDefaultSettings(NdpRouterAdvSettings *settings) 00057 { 00058 //Underlying network interface 00059 settings->interface = netGetDefaultInterface(); 00060 00061 //The maximum time allowed between sending unsolicited multicast 00062 //Router Advertisements from the interface 00063 settings->maxRtrAdvInterval = NDP_MAX_RTR_ADVERT_INTERVAL; 00064 00065 //The minimum time allowed between sending unsolicited multicast 00066 //Router Advertisements from the interface 00067 settings->minRtrAdvInterval = NDP_MAX_RTR_ADVERT_INTERVAL / 3; 00068 00069 //The default value to be placed in the Cur Hop Limit field in the 00070 //Router Advertisement messages sent by the router 00071 settings->curHopLimit = 0; 00072 00073 //The value to be placed in the Managed Address Configuration 00074 //flag in the Router Advertisement 00075 settings->managedFlag = FALSE; 00076 00077 //The value to be placed in the Other Configuration flag 00078 //in the Router Advertisement 00079 settings->otherConfigFlag = FALSE; 00080 00081 //The value to be placed in the Mobile IPv6 Home Agent 00082 //flag in the Router Advertisement 00083 settings->homeAgentFlag = FALSE; 00084 00085 //The value to be placed in the Router Selection Preferences 00086 //field in the Router Advertisement 00087 settings->preference = NDP_ROUTER_SEL_PREFERENCE_MEDIUM; 00088 00089 //The value to be placed in the Neighbor Discovery Proxy 00090 //flag in the Router Advertisement 00091 settings->proxyFlag = FALSE; 00092 00093 //The value to be placed in the Router Lifetime field of 00094 //Router Advertisements sent from the interface 00095 settings->defaultLifetime = 3 * (NDP_MAX_RTR_ADVERT_INTERVAL / 1000); 00096 00097 //The value to be placed in the Reachable Time field in the 00098 //Router Advertisement messages sent by the router 00099 settings->reachableTime = 0; 00100 00101 //The value to be placed in the Retrans Timer field in the 00102 //Router Advertisement messages sent by the router 00103 settings->retransTimer = 0; 00104 00105 //The value to be placed in the MTU option sent by the router 00106 settings->linkMtu = 0; 00107 00108 //A list of prefixes to be placed in Prefix Information options (PIO) 00109 //in Router Advertisement messages sent from the interface 00110 settings->prefixList = NULL; 00111 settings->prefixListLength = 0; 00112 00113 //A list of routes to be placed in Route Information options (RIO) 00114 //in Router Advertisement messages sent from the interface 00115 settings->routeList = NULL; 00116 settings->routeListLength = 0; 00117 00118 //A list of header compression contexts to be placed in the 6LoWPAN Context 00119 //options (6CO) in Router Advertisement messages sent from the interface 00120 settings->contextList = NULL; 00121 settings->contextListLength = 0; 00122 } 00123 00124 00125 /** 00126 * @brief RA service initialization 00127 * @param[in] context Pointer to the RA service context 00128 * @param[in] settings RA service configuration variables 00129 * @return Error code 00130 **/ 00131 00132 error_t ndpRouterAdvInit(NdpRouterAdvContext *context, const NdpRouterAdvSettings *settings) 00133 { 00134 NetInterface *interface; 00135 00136 //Debug message 00137 TRACE_INFO("Initializing Router Advertisement service...\r\n"); 00138 00139 //Ensure the parameters are valid 00140 if(!context || !settings) 00141 return ERROR_INVALID_PARAMETER; 00142 00143 //Valid network interface? 00144 if(!settings->interface) 00145 return ERROR_INVALID_PARAMETER; 00146 00147 //Get exclusive access 00148 osAcquireMutex(&netMutex); 00149 00150 //Point to the underlying network interface 00151 interface = settings->interface; 00152 00153 //Clear the RA service context 00154 memset(context, 0, sizeof(NdpRouterAdvContext)); 00155 //Save user settings 00156 context->settings = *settings; 00157 00158 //The RA service is currently disabled on the interface 00159 context->running = FALSE; 00160 //Attach the RA service context to the network interface 00161 interface->ndpRouterAdvContext = context; 00162 00163 //Release exclusive access 00164 osReleaseMutex(&netMutex); 00165 00166 //Successful initialization 00167 return NO_ERROR; 00168 } 00169 00170 00171 /** 00172 * @brief Start RA service 00173 * @param[in] context Pointer to the RA service context 00174 * @return Error code 00175 **/ 00176 00177 error_t ndpRouterAdvStart(NdpRouterAdvContext *context) 00178 { 00179 error_t error; 00180 NetInterface *interface; 00181 00182 //Check parameter 00183 if(context == NULL) 00184 return ERROR_INVALID_PARAMETER; 00185 00186 //Debug message 00187 TRACE_INFO("Starting Router Advertisement service...\r\n"); 00188 00189 //Get exclusive access 00190 osAcquireMutex(&netMutex); 00191 00192 //Check whether the service is running 00193 if(!context->running) 00194 { 00195 //Point to the underlying network interface 00196 interface = context->settings.interface; 00197 00198 //Join the All-Routers multicast address 00199 error = ipv6JoinMulticastGroup(interface, &IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR); 00200 00201 //Successful membership registration? 00202 if(!error) 00203 { 00204 //Reset variables 00205 context->timestamp = osGetSystemTime(); 00206 context->timeout = 0; 00207 context->routerAdvCount = 0; 00208 00209 //Enable the router to forward packets to or from the interface 00210 interface->ipv6Context.isRouter = TRUE; 00211 00212 //Default Hop Limit value 00213 if(context->settings.curHopLimit != 0) 00214 interface->ipv6Context.curHopLimit = context->settings.curHopLimit; 00215 00216 //The time a node assumes a neighbor is reachable 00217 if(context->settings.reachableTime != 0) 00218 interface->ndpContext.reachableTime = context->settings.reachableTime; 00219 00220 //The time between retransmissions of NS messages 00221 if(context->settings.retransTimer != 0) 00222 interface->ndpContext.retransTimer = context->settings.retransTimer; 00223 00224 //Start transmitting Router Advertisements 00225 context->running = TRUE; 00226 } 00227 } 00228 else 00229 { 00230 //The service is already running... 00231 error = NO_ERROR; 00232 } 00233 00234 //Release exclusive access 00235 osReleaseMutex(&netMutex); 00236 00237 //Return status code 00238 return error; 00239 } 00240 00241 00242 /** 00243 * @brief Stop RA service 00244 * @param[in] context Pointer to the RA service context 00245 * @return Error code 00246 **/ 00247 00248 error_t ndpRouterAdvStop(NdpRouterAdvContext *context) 00249 { 00250 error_t error; 00251 NetInterface *interface; 00252 00253 //Check parameter 00254 if(context == NULL) 00255 return ERROR_INVALID_PARAMETER; 00256 00257 //Debug message 00258 TRACE_INFO("Stopping Router Advertisement service...\r\n"); 00259 00260 //Get exclusive access 00261 osAcquireMutex(&netMutex); 00262 00263 //Check whether the service is running 00264 if(context->running) 00265 { 00266 //Point to the underlying network interface 00267 interface = context->settings.interface; 00268 00269 //The router should transmit one or more final multicast Router 00270 //Advertisements with a Router Lifetime field of zero 00271 ndpSendRouterAdv(context, 0); 00272 00273 //Leave the All-Routers multicast address 00274 error = ipv6LeaveMulticastGroup(interface, &IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR); 00275 00276 //Restore default parameters 00277 interface->ipv6Context.curHopLimit = IPV6_DEFAULT_HOP_LIMIT; 00278 interface->ndpContext.reachableTime = NDP_REACHABLE_TIME; 00279 interface->ndpContext.retransTimer = NDP_RETRANS_TIMER; 00280 00281 //Stop transmitting Router Advertisements 00282 context->running = FALSE; 00283 } 00284 else 00285 { 00286 //The service is not running... 00287 error = NO_ERROR; 00288 } 00289 00290 //Release exclusive access 00291 osReleaseMutex(&netMutex); 00292 00293 //Return status code 00294 return error; 00295 } 00296 00297 00298 /** 00299 * @brief RA service timer handler 00300 * @param[in] context Pointer to the RA service context 00301 **/ 00302 00303 void ndpRouterAdvTick(NdpRouterAdvContext *context) 00304 { 00305 systime_t time; 00306 NetInterface *interface; 00307 NdpRouterAdvSettings *settings; 00308 00309 //Make sure the RA service has been properly instantiated 00310 if(context == NULL) 00311 return; 00312 00313 //Point to the underlying network interface 00314 interface = context->settings.interface; 00315 //Point to the router configuration variables 00316 settings = &context->settings; 00317 00318 //Get current time 00319 time = osGetSystemTime(); 00320 00321 //Make sure that the link is up and the service is running 00322 if(interface->linkState && context->running) 00323 { 00324 //Make sure that a valid link-local address has been assigned to the interface 00325 if(ipv6GetLinkLocalAddrState(interface) == IPV6_ADDR_STATE_PREFERRED) 00326 { 00327 //Check current time 00328 if(timeCompare(time, context->timestamp + context->timeout) >= 0) 00329 { 00330 //Send an unsolicited Router Advertisement 00331 ndpSendRouterAdv(context, context->settings.defaultLifetime); 00332 00333 //Save the time at which the message was sent 00334 context->timestamp = time; 00335 00336 //Whenever a multicast advertisement is sent from an interface, the 00337 //timer is reset to a uniformly distributed random value between 00338 //MinRtrAdvInterval and MaxRtrAdvInterval 00339 context->timeout = netGetRandRange(settings->minRtrAdvInterval, 00340 settings->maxRtrAdvInterval); 00341 00342 //First Router Advertisements to be sent from this interface? 00343 if(context->routerAdvCount < NDP_MAX_INITIAL_RTR_ADVERTISEMENTS) 00344 { 00345 //For the first few advertisements sent from an interface when it 00346 //becomes an advertising interface, the randomly chosen interval 00347 //should not be greater than MAX_INITIAL_RTR_ADVERT_INTERVAL 00348 context->timeout = MIN(context->timeout, NDP_MAX_INITIAL_RTR_ADVERT_INTERVAL); 00349 } 00350 00351 //Increment counter 00352 context->routerAdvCount++; 00353 } 00354 } 00355 } 00356 } 00357 00358 00359 /** 00360 * @brief Callback function for link change event 00361 * @param[in] context Pointer to the RA service context 00362 **/ 00363 00364 void ndpRouterAdvLinkChangeEvent(NdpRouterAdvContext *context) 00365 { 00366 NetInterface *interface; 00367 00368 //Make sure the RA service has been properly instantiated 00369 if(context == NULL) 00370 return; 00371 00372 //Point to the underlying network interface 00373 interface = context->settings.interface; 00374 00375 //Reset variables 00376 context->timestamp = osGetSystemTime(); 00377 context->timeout = 0; 00378 context->routerAdvCount = 0; 00379 00380 //Default Hop Limit value 00381 if(context->settings.curHopLimit != 0) 00382 interface->ipv6Context.curHopLimit = context->settings.curHopLimit; 00383 00384 //The time a node assumes a neighbor is reachable 00385 if(context->settings.reachableTime != 0) 00386 interface->ndpContext.reachableTime = context->settings.reachableTime; 00387 00388 //The time between retransmissions of NS messages 00389 if(context->settings.retransTimer != 0) 00390 interface->ndpContext.retransTimer = context->settings.retransTimer; 00391 } 00392 00393 00394 /** 00395 * @brief Router Solicitation message processing 00396 * @param[in] interface Underlying network interface 00397 * @param[in] pseudoHeader IPv6 pseudo header 00398 * @param[in] buffer Multi-part buffer containing the Router Advertisement message 00399 * @param[in] offset Offset to the first byte of the message 00400 * @param[in] hopLimit Hop Limit field from IPv6 header 00401 **/ 00402 00403 void ndpProcessRouterSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, 00404 const NetBuffer *buffer, size_t offset, uint8_t hopLimit) 00405 { 00406 error_t error; 00407 uint_t n; 00408 size_t length; 00409 systime_t time; 00410 systime_t delay; 00411 NdpRouterAdvContext *context; 00412 NdpRouterSolMessage *message; 00413 NdpLinkLayerAddrOption *option; 00414 NdpNeighborCacheEntry *entry; 00415 00416 //Point to the RA service context 00417 context = interface->ndpRouterAdvContext; 00418 00419 //A host must silently discard any received Router Solicitation 00420 if(context == NULL) 00421 return; 00422 00423 //Get current time 00424 time = osGetSystemTime(); 00425 00426 //Retrieve the length of the message 00427 length = netBufferGetLength(buffer) - offset; 00428 00429 //Check the length of the Router Solicitation message 00430 if(length < sizeof(NdpRouterSolMessage)) 00431 return; 00432 00433 //Point to the beginning of the message 00434 message = netBufferAt(buffer, offset); 00435 //Sanity check 00436 if(message == NULL) 00437 return; 00438 00439 //Debug message 00440 TRACE_INFO("Router Solicitation message received (%" PRIuSIZE " bytes)...\r\n", length); 00441 //Dump message contents for debugging purpose 00442 ndpDumpRouterSolMessage(message); 00443 00444 //The IPv6 Hop Limit field must have a value of 255 to ensure 00445 //that the packet has not been forwarded by a router 00446 if(hopLimit != NDP_HOP_LIMIT) 00447 return; 00448 00449 //ICMPv6 Code must be 0 00450 if(message->code) 00451 return; 00452 00453 //Calculate the length of the Options field 00454 length -= sizeof(NdpRouterSolMessage); 00455 00456 //Parse Options field 00457 error = ndpCheckOptions(message->options, length); 00458 //All included options must have a length that is greater than zero 00459 if(error) 00460 return; 00461 00462 //Search for the Source Link-Layer Address option 00463 option = ndpGetOption(message->options, 00464 length, NDP_OPT_SOURCE_LINK_LAYER_ADDR); 00465 00466 //Source Link-Layer Address option found? 00467 if(option != NULL && option->length == 1) 00468 { 00469 //Debug message 00470 TRACE_DEBUG(" Source Link-Layer Address = %s\r\n", 00471 macAddrToString(&option->linkLayerAddr, NULL)); 00472 00473 //The Source Link-Layer Address option must not be included when the 00474 //source IP address is the unspecified address 00475 if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR)) 00476 return; 00477 00478 //Search the Neighbor Cache for the source address of the solicitation 00479 entry = ndpFindNeighborCacheEntry(interface, &pseudoHeader->srcAddr); 00480 00481 //No matching entry has been found? 00482 if(!entry) 00483 { 00484 //Create an entry 00485 entry = ndpCreateNeighborCacheEntry(interface); 00486 00487 //Neighbor Cache entry successfully created? 00488 if(entry) 00489 { 00490 //Record the IPv6 and the corresponding MAC address 00491 entry->ipAddr = pseudoHeader->srcAddr; 00492 entry->macAddr = option->linkLayerAddr; 00493 //The IsRouter flag must be set to FALSE 00494 entry->isRouter = FALSE; 00495 //Save current time 00496 entry->timestamp = time; 00497 //Enter the STALE state 00498 entry->state = NDP_STATE_STALE; 00499 } 00500 } 00501 else 00502 { 00503 //If a Neighbor Cache entry for the solicitation's sender exists 00504 //the entry's IsRouter flag must be set to FALSE 00505 entry->isRouter = FALSE; 00506 00507 //INCOMPLETE state? 00508 if(entry->state == NDP_STATE_INCOMPLETE) 00509 { 00510 //Record link-layer address 00511 entry->macAddr = option->linkLayerAddr; 00512 //Send all the packets that are pending for transmission 00513 n = ndpSendQueuedPackets(interface, entry); 00514 //Save current time 00515 entry->timestamp = time; 00516 00517 //Check whether any packets have been sent 00518 if(n > 0) 00519 { 00520 //Start delay timer 00521 entry->timeout = NDP_DELAY_FIRST_PROBE_TIME; 00522 //Switch to the DELAY state 00523 entry->state = NDP_STATE_DELAY; 00524 } 00525 else 00526 { 00527 //Enter the STALE state 00528 entry->state = NDP_STATE_STALE; 00529 } 00530 } 00531 //REACHABLE, STALE, DELAY or PROBE state? 00532 else 00533 { 00534 //Different link-layer address than cached? 00535 if(!macCompAddr(&entry->macAddr, &option->linkLayerAddr)) 00536 { 00537 //Update link-layer address 00538 entry->macAddr = option->linkLayerAddr; 00539 //Save current time 00540 entry->timestamp = time; 00541 //Enter the STALE state 00542 entry->state = NDP_STATE_STALE; 00543 } 00544 } 00545 } 00546 } 00547 00548 //Upon receipt of a Router Solicitation, compute a random delay within the 00549 //range 0 through MAX_RA_DELAY_TIME 00550 delay = netGetRandRange(0, NDP_MAX_RA_DELAY_TIME); 00551 00552 //If the computed value corresponds to a time later than the time the next 00553 //multicast Router Advertisement is scheduled to be sent, ignore the random 00554 //delay and send the advertisement at the already-scheduled time 00555 if(timeCompare(time + delay, context->timestamp + context->timeout) > 0) 00556 return; 00557 00558 //Check whether the router sent a multicast Router Advertisement (solicited 00559 //or unsolicited) within the last MIN_DELAY_BETWEEN_RAS seconds 00560 if(timeCompare(time, context->timestamp + NDP_MIN_DELAY_BETWEEN_RAS) < 0) 00561 { 00562 //Schedule the advertisement to be sent at a time corresponding to 00563 //MIN_DELAY_BETWEEN_RAS plus the random value after the previous 00564 //advertisement was sent. This ensures that the multicast Router 00565 //Advertisements are rate limited 00566 context->timeout = NDP_MIN_DELAY_BETWEEN_RAS + delay; 00567 } 00568 else 00569 { 00570 //Schedule the sending of a Router Advertisement at the time given 00571 //by the random value 00572 context->timeout = time + delay - context->timestamp; 00573 } 00574 } 00575 00576 00577 /** 00578 * @brief Send a Router Advertisement message 00579 * @param[in] context Pointer to the RA service context 00580 * @param[in] routerLifetime Router Lifetime field 00581 * @return Error code 00582 **/ 00583 00584 error_t ndpSendRouterAdv(NdpRouterAdvContext *context, uint16_t routerLifetime) 00585 { 00586 error_t error; 00587 uint_t i; 00588 uint32_t n; 00589 size_t offset; 00590 size_t length; 00591 NetBuffer *buffer; 00592 NetInterface *interface; 00593 NdpRouterAdvMessage *message; 00594 NdpRouterAdvSettings *settings; 00595 Ipv6PseudoHeader pseudoHeader; 00596 00597 //Point to the underlying network interface 00598 interface = context->settings.interface; 00599 //Point to the router configuration variables 00600 settings = &context->settings; 00601 00602 //The destination address is typically the all-nodes multicast address 00603 pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_NODES_ADDR; 00604 00605 //Routers must use their link-local address as the source for Router 00606 //Advertisement messages so that hosts can uniquely identify routers 00607 error = ipv6SelectSourceAddr(&interface, 00608 &pseudoHeader.destAddr, &pseudoHeader.srcAddr); 00609 00610 //No link-local address assigned to the interface? 00611 if(error) 00612 return error; 00613 00614 //Compute the maximum size of the Router Advertisement message 00615 length = sizeof(NdpRouterAdvMessage) + 00616 sizeof(NdpLinkLayerAddrOption) + sizeof(NdpMtuOption) + 00617 settings->prefixListLength * sizeof(NdpPrefixInfoOption) + 00618 settings->routeListLength * sizeof(NdpRouteInfoOption) + 00619 settings->contextListLength * sizeof(NdpContextOption); 00620 00621 //Sanity check 00622 if((length + sizeof(Ipv6Header)) > IPV6_DEFAULT_MTU) 00623 return ERROR_FAILURE; 00624 00625 //Allocate a memory buffer to hold the Router Advertisement message 00626 buffer = ipAllocBuffer(length, &offset); 00627 //Failed to allocate memory? 00628 if(buffer == NULL) 00629 return ERROR_OUT_OF_MEMORY; 00630 00631 //Point to the beginning of the message 00632 message = netBufferAt(buffer, offset); 00633 00634 //Format Router Advertisement message 00635 message->type = ICMPV6_TYPE_ROUTER_ADV; 00636 message->code = 0; 00637 message->checksum = 0; 00638 message->curHopLimit = settings->curHopLimit; 00639 message->m = settings->managedFlag; 00640 message->o = settings->otherConfigFlag; 00641 message->h = settings->homeAgentFlag; 00642 message->prf = settings->preference; 00643 message->p = settings->proxyFlag; 00644 message->reserved = 0; 00645 message->routerLifetime = htons(routerLifetime); 00646 message->reachableTime = htonl(settings->reachableTime); 00647 message->retransTimer = htonl(settings->retransTimer); 00648 00649 //If the Router Lifetime is zero, the preference value must be 00650 //set to zero by the sender 00651 if(routerLifetime == 0) 00652 message->prf = NDP_ROUTER_SEL_PREFERENCE_MEDIUM; 00653 00654 //Length of the message, excluding any option 00655 length = sizeof(NdpRouterAdvMessage); 00656 00657 #if (ETH_SUPPORT == ENABLED) 00658 //Check whether a MAC address has been assigned to the interface 00659 if(!macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR)) 00660 { 00661 //Add Source Link-Layer Address option 00662 ndpAddOption(message, &length, NDP_OPT_SOURCE_LINK_LAYER_ADDR, 00663 &interface->macAddr, sizeof(MacAddr)); 00664 } 00665 #endif 00666 00667 //A value of zero indicates that no MTU option is sent 00668 if(settings->linkMtu > 0) 00669 { 00670 NdpMtuOption mtuOption; 00671 00672 //The MTU option specifies the recommended MTU for the link 00673 mtuOption.reserved = 0; 00674 mtuOption.mtu = htonl(settings->linkMtu); 00675 00676 //Add MTU option 00677 ndpAddOption(message, &length, NDP_OPT_MTU, 00678 (uint8_t *) &mtuOption + sizeof(NdpOption), 00679 sizeof(NdpMtuOption) - sizeof(NdpOption)); 00680 } 00681 00682 //Loop through the list of IPv6 prefixes 00683 for(i = 0; i < settings->prefixListLength; i++) 00684 { 00685 NdpPrefixInfoOption prefixInfoOption; 00686 00687 //The Prefix Information option provide hosts with on-link 00688 //prefixes and prefixes for Address Autoconfiguration 00689 prefixInfoOption.prefixLength = settings->prefixList[i].length; 00690 prefixInfoOption.l = settings->prefixList[i].onLinkFlag; 00691 prefixInfoOption.a = settings->prefixList[i].autonomousFlag; 00692 prefixInfoOption.reserved1 = 0; 00693 prefixInfoOption.validLifetime = htonl(settings->prefixList[i].validLifetime); 00694 prefixInfoOption.preferredLifetime = htonl(settings->prefixList[i].preferredLifetime); 00695 prefixInfoOption.reserved2 = 0; 00696 prefixInfoOption.prefix = settings->prefixList[i].prefix; 00697 00698 //Add Prefix Information option (PIO) 00699 ndpAddOption(message, &length, NDP_OPT_PREFIX_INFORMATION, 00700 (uint8_t *) &prefixInfoOption + sizeof(NdpOption), 00701 sizeof(NdpPrefixInfoOption) - sizeof(NdpOption)); 00702 } 00703 00704 //Loop through the list of routes 00705 for(i = 0; i < settings->routeListLength; i++) 00706 { 00707 NdpRouteInfoOption routeInfoOption; 00708 00709 //The Route Information option specifies prefixes that are 00710 //reachable via the router 00711 routeInfoOption.prefixLength = settings->routeList[i].length; 00712 routeInfoOption.reserved1 = 0; 00713 routeInfoOption.prf = settings->routeList[i].preference; 00714 routeInfoOption.reserved2 = 0; 00715 routeInfoOption.routeLifetime = htonl(settings->routeList[i].routeLifetime); 00716 routeInfoOption.prefix = settings->routeList[i].prefix; 00717 00718 //Add Route Information option (RIO) 00719 ndpAddOption(message, &length, NDP_OPT_ROUTE_INFORMATION, 00720 (uint8_t *) &routeInfoOption + sizeof(NdpOption), 00721 sizeof(NdpRouteInfoOption) - sizeof(NdpOption)); 00722 } 00723 00724 //Loop through the list of 6LoWPAN compression contexts 00725 for(i = 0; i < settings->contextListLength; i++) 00726 { 00727 NdpContextOption contextOption; 00728 00729 //The 6LoWPAN Context option (6CO) carries prefix information for 00730 //LoWPAN header compression 00731 contextOption.contextLength = settings->contextList[i].length; 00732 contextOption.reserved1 = 0; 00733 contextOption.c = settings->contextList[i].compression; 00734 contextOption.cid = settings->contextList[i].cid; 00735 contextOption.reserved2 = 0; 00736 contextOption.validLifetime = htons(settings->contextList[i].validLifetime); 00737 contextOption.contextPrefix = settings->contextList[i].prefix; 00738 00739 //Calculate the length of the option in bytes 00740 n = sizeof(NdpContextOption) - sizeof(Ipv6Addr) + (contextOption.contextLength / 8); 00741 00742 //Add 6LoWPAN Context option (6CO) 00743 ndpAddOption(message, &length, NDP_OPT_6LOWPAN_CONTEXT, 00744 (uint8_t *) &contextOption + sizeof(NdpOption), n - sizeof(NdpOption)); 00745 } 00746 00747 //Adjust the length of the multi-part buffer 00748 netBufferSetLength(buffer, offset + length); 00749 00750 //Format IPv6 pseudo header 00751 pseudoHeader.length = htonl(length); 00752 pseudoHeader.reserved = 0; 00753 pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER; 00754 00755 //Calculate ICMPv6 header checksum 00756 message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader, 00757 sizeof(Ipv6PseudoHeader), buffer, offset, length); 00758 00759 //Debug message 00760 TRACE_INFO("Sending Router Advertisement message (%" PRIuSIZE " bytes)...\r\n", length); 00761 //Dump message contents for debugging purpose 00762 ndpDumpRouterAdvMessage(message); 00763 00764 //Send Router Advertisement message 00765 error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT); 00766 00767 //Free previously allocated memory 00768 netBufferFree(buffer); 00769 //Return status code 00770 return error; 00771 } 00772 00773 #endif 00774
Generated on Tue Jul 12 2022 17:10:15 by
