Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ipv6_misc.c
Go to the documentation of this file.
00001 /** 00002 * @file ipv6_misc.c 00003 * @brief Helper functions for IPv6 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 IPV6_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "ipv6/ipv6.h" 00035 #include "ipv6/ipv6_misc.h" 00036 #include "ipv6/ndp.h" 00037 #include "ipv6/ndp_cache.h" 00038 #include "mdns/mdns_responder.h" 00039 #include "debug.h" 00040 00041 //Check TCP/IP stack configuration 00042 #if (IPV6_SUPPORT == ENABLED) 00043 00044 00045 /** 00046 * @brief Get the state of the specified IPv6 address 00047 * @param[in] interface Underlying network interface 00048 * @param[in] addr IPv6 address 00049 * @return Address state 00050 **/ 00051 00052 Ipv6AddrState ipv6GetAddrState(NetInterface *interface, const Ipv6Addr *addr) 00053 { 00054 uint_t i; 00055 Ipv6AddrEntry *entry; 00056 00057 //Loop through the list of IPv6 addresses assigned to the interface 00058 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00059 { 00060 //Point to the current entry 00061 entry = &interface->ipv6Context.addrList[i]; 00062 00063 //Valid IPv6 address 00064 if(entry->state != IPV6_ADDR_STATE_INVALID) 00065 { 00066 //Check whether the current entry matches the specified address 00067 if(ipv6CompAddr(&entry->addr, addr)) 00068 { 00069 //Return the state of the IPv6 address 00070 return entry->state; 00071 } 00072 } 00073 } 00074 00075 //The specified IPv6 address is not valid 00076 return IPV6_ADDR_STATE_INVALID; 00077 } 00078 00079 00080 /** 00081 * @brief Set IPv6 address and address state 00082 * @param[in] interface Pointer to the desired network interface 00083 * @param[in] index Zero-based index 00084 * @param[in] addr IPv6 address 00085 * @param[in] state State of the IPv6 address 00086 * @param[in] validLifetime Valid lifetime 00087 * @param[in] preferredLifetime Preferred lifetime 00088 * @param[in] permanent Permanently assigned address 00089 * @return Error code 00090 **/ 00091 00092 error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr, 00093 Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent) 00094 { 00095 error_t error; 00096 Ipv6AddrEntry *entry; 00097 Ipv6Addr solicitedNodeAddr; 00098 00099 //Check parameters 00100 if(interface == NULL || addr == NULL) 00101 return ERROR_INVALID_PARAMETER; 00102 00103 //Make sure that the index is valid 00104 if(index >= IPV6_ADDR_LIST_SIZE) 00105 return ERROR_OUT_OF_RANGE; 00106 00107 //The IPv6 address must be a valid unicast address 00108 if(ipv6IsMulticastAddr(addr)) 00109 return ERROR_INVALID_ADDRESS; 00110 00111 //Initialize status code 00112 error = NO_ERROR; 00113 00114 //Point to the corresponding entry 00115 entry = &interface->ipv6Context.addrList[index]; 00116 00117 //Check whether an IPv6 address is already assigned 00118 if(!ipv6CompAddr(&entry->addr, &IPV6_UNSPECIFIED_ADDR)) 00119 { 00120 //Check the state of the IPv6 address 00121 if(entry->state != IPV6_ADDR_STATE_INVALID) 00122 { 00123 //Ethernet interface? 00124 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 00125 { 00126 //Form the Solicited-Node address 00127 ipv6ComputeSolicitedNodeAddr(&entry->addr, &solicitedNodeAddr); 00128 //Leave the Solicited-Node multicast group 00129 ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr); 00130 } 00131 } 00132 } 00133 00134 //The current IPv6 address is no more valid 00135 entry->state = IPV6_ADDR_STATE_INVALID; 00136 entry->validLifetime = 0; 00137 entry->preferredLifetime = 0; 00138 entry->permanent = FALSE; 00139 00140 //Assign the new IPv6 address 00141 entry->addr = *addr; 00142 00143 //Check whether the new IPv6 address is valid 00144 if(!ipv6CompAddr(addr, &IPV6_UNSPECIFIED_ADDR)) 00145 { 00146 //Check the state of the IPv6 address 00147 if(state != IPV6_ADDR_STATE_INVALID) 00148 { 00149 //Ethernet interface? 00150 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 00151 { 00152 //Form the Solicited-Node address for the link-local address 00153 ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr); 00154 //Join the Solicited-Node multicast group for each assigned address 00155 error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr); 00156 } 00157 //6LoWPAN interface? 00158 else if(interface->nicDriver->type == NIC_TYPE_6LOWPAN) 00159 { 00160 //There is no need to join the solicited-node multicast address, 00161 //since nobody multicasts Neighbor Solicitations in this type of 00162 //network (refer to RFC 6775 section 5.2) 00163 } 00164 } 00165 00166 //Check status code 00167 if(!error) 00168 { 00169 //Set the state of the IPv6 address 00170 entry->state = state; 00171 00172 //Clear duplicate flag 00173 entry->duplicate = FALSE; 00174 00175 //Save preferred and valid lifetimes 00176 entry->preferredLifetime = preferredLifetime; 00177 entry->validLifetime = validLifetime; 00178 00179 //Set time stamp 00180 entry->timestamp = osGetSystemTime(); 00181 00182 //Initialize DAD related variables 00183 entry->dadTimeout = 0; 00184 entry->dadRetransmitCount = 0; 00185 } 00186 00187 //This flag tells whether the IPv6 address should be permanently assigned 00188 entry->permanent = permanent; 00189 } 00190 00191 #if (MDNS_RESPONDER_SUPPORT == ENABLED) 00192 //Link-local address? 00193 if(index == 0) 00194 { 00195 //Restart mDNS probing process 00196 mdnsResponderStartProbing(interface->mdnsResponderContext); 00197 } 00198 #endif 00199 00200 //Return status code 00201 return error; 00202 } 00203 00204 00205 /** 00206 * @brief Add a new entry to the list of IPv6 addresses 00207 * @param[in] interface Underlying network interface 00208 * @param[in] addr IPv6 address 00209 * @param[in] validLifetime Valid lifetime, in seconds 00210 * @param[in] preferredLifetime Preferred lifetime, in seconds 00211 **/ 00212 00213 void ipv6AddAddr(NetInterface *interface, const Ipv6Addr *addr, 00214 uint32_t validLifetime, uint32_t preferredLifetime) 00215 { 00216 uint_t i; 00217 Ipv6AddrEntry *entry; 00218 00219 //Check the valid lifetime 00220 if(validLifetime != NDP_INFINITE_LIFETIME) 00221 { 00222 //The length of time in seconds that the address is valid 00223 if(validLifetime < (MAX_DELAY / 1000)) 00224 validLifetime *= 1000; 00225 else 00226 validLifetime = MAX_DELAY; 00227 } 00228 else 00229 { 00230 //A value of all one bits (0xffffffff) represents infinity 00231 validLifetime = INFINITE_DELAY; 00232 } 00233 00234 //Check the preferred lifetime 00235 if(preferredLifetime != NDP_INFINITE_LIFETIME) 00236 { 00237 //The length of time in seconds that the address remains preferred 00238 if(preferredLifetime < (MAX_DELAY / 1000)) 00239 preferredLifetime *= 1000; 00240 else 00241 preferredLifetime = MAX_DELAY; 00242 } 00243 else 00244 { 00245 //A value of all one bits (0xffffffff) represents infinity 00246 preferredLifetime = INFINITE_DELAY; 00247 } 00248 00249 //Loop through the list of IPv6 addresses assigned to the interface 00250 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00251 { 00252 //Point to the current entry 00253 entry = &interface->ipv6Context.addrList[i]; 00254 00255 //Check the state of the IPv6 address 00256 if(entry->state == IPV6_ADDR_STATE_PREFERRED || 00257 entry->state == IPV6_ADDR_STATE_DEPRECATED) 00258 { 00259 //Check whether the current entry matches the specified address 00260 if(ipv6CompAddr(&entry->addr, addr)) 00261 { 00262 //The IPv6 address should be preserved if it has been manually assigned 00263 if(!entry->permanent) 00264 { 00265 //Update the lifetimes of the entry 00266 entry->validLifetime = validLifetime; 00267 entry->preferredLifetime = preferredLifetime; 00268 00269 //Save current time 00270 entry->timestamp = osGetSystemTime(); 00271 //Update the state of the IPv6 address 00272 entry->state = IPV6_ADDR_STATE_PREFERRED; 00273 } 00274 00275 //Exit immediately 00276 return; 00277 } 00278 } 00279 } 00280 00281 //If no matching entry was found, then try to create a new entry 00282 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00283 { 00284 //Point to the current entry 00285 entry = &interface->ipv6Context.addrList[i]; 00286 00287 //Check the state of the IPv6 address 00288 if(entry->state == IPV6_ADDR_STATE_INVALID) 00289 { 00290 //The IPv6 address should be preserved if it has been manually assigned 00291 if(!entry->permanent) 00292 { 00293 #if (NDP_SUPPORT == ENABLED) 00294 //Check whether Duplicate Address Detection should be performed 00295 if(interface->ndpContext.dupAddrDetectTransmits > 0) 00296 { 00297 //Use the IPv6 address as a tentative address 00298 ipv6SetAddr(interface, i, addr, IPV6_ADDR_STATE_TENTATIVE, 00299 validLifetime, preferredLifetime, FALSE); 00300 } 00301 else 00302 #endif 00303 { 00304 //The use of the IPv6 address is now unrestricted 00305 ipv6SetAddr(interface, i, addr, IPV6_ADDR_STATE_PREFERRED, 00306 validLifetime, preferredLifetime, FALSE); 00307 } 00308 00309 //Exit immediately 00310 return; 00311 } 00312 } 00313 } 00314 } 00315 00316 00317 /** 00318 * @brief Remove an entry from the list of IPv6 addresses 00319 * @param[in] interface Underlying network interface 00320 * @param[in] addr IPv6 address 00321 **/ 00322 00323 void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr) 00324 { 00325 uint_t i; 00326 Ipv6AddrEntry *entry; 00327 00328 //Loop through the list of IPv6 addresses assigned to the interface 00329 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00330 { 00331 //Point to the current entry 00332 entry = &interface->ipv6Context.addrList[i]; 00333 00334 //Valid IPv6 address? 00335 if(entry->validLifetime) 00336 { 00337 //Check whether the current entry matches the specified address 00338 if(ipv6CompAddr(&entry->addr, addr)) 00339 { 00340 //The IPv6 address should be preserved if it has been manually assigned 00341 if(!entry->permanent) 00342 { 00343 //Remove the IPv6 address from the list 00344 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR, 00345 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE); 00346 } 00347 } 00348 } 00349 } 00350 } 00351 00352 00353 /** 00354 * @brief Add a new entry to the Prefix List 00355 * @param[in] interface Underlying network interface 00356 * @param[in] prefix IPv6 prefix 00357 * @param[in] length The number of leading bits in the prefix that are valid 00358 * @param[in] validLifetime Valid lifetime, in seconds 00359 * @param[in] preferredLifetime Preferred lifetime, in seconds 00360 **/ 00361 00362 void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix, 00363 uint_t length, uint32_t validLifetime, uint32_t preferredLifetime) 00364 { 00365 uint_t i; 00366 Ipv6PrefixEntry *entry; 00367 Ipv6PrefixEntry *firstFreeEntry; 00368 00369 //Keep track of the first free entry 00370 firstFreeEntry = NULL; 00371 00372 //Loop through the Prefix List 00373 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++) 00374 { 00375 //Point to the current entry 00376 entry = &interface->ipv6Context.prefixList[i]; 00377 00378 //Valid prefix? 00379 if(entry->validLifetime) 00380 { 00381 //Compare prefix length against the specified value 00382 if(entry->prefixLength == length) 00383 { 00384 //Check whether the current entry matches the specified prefix 00385 if(ipv6CompPrefix(&entry->prefix, prefix, length)) 00386 break; 00387 } 00388 } 00389 else 00390 { 00391 //The IPv6 prefix should be preserved if it has been manually assigned 00392 if(!entry->permanent) 00393 { 00394 //Keep track of the first free entry 00395 if(firstFreeEntry == NULL) 00396 firstFreeEntry = entry; 00397 } 00398 } 00399 } 00400 00401 //No matching entry found? 00402 if(i >= IPV6_PREFIX_LIST_SIZE) 00403 entry = firstFreeEntry; 00404 00405 //Update the entry if necessary 00406 if(entry != NULL) 00407 { 00408 //The IPv6 prefix should be preserved if it has been manually assigned 00409 if(!entry->permanent) 00410 { 00411 //Save the IPv6 prefix 00412 entry->prefix = *prefix; 00413 entry->prefixLength = length; 00414 00415 //Check the valid lifetime 00416 if(validLifetime != NDP_INFINITE_LIFETIME) 00417 { 00418 //The length of time in seconds that the prefix is valid 00419 //for the purpose of on-link determination 00420 if(validLifetime < (MAX_DELAY / 1000)) 00421 entry->validLifetime = validLifetime * 1000; 00422 else 00423 entry->validLifetime = MAX_DELAY; 00424 } 00425 else 00426 { 00427 //A value of all one bits (0xffffffff) represents infinity 00428 entry->validLifetime = INFINITE_DELAY; 00429 } 00430 00431 //Check the preferred lifetime 00432 if(preferredLifetime != NDP_INFINITE_LIFETIME) 00433 { 00434 //The length of time in seconds that addresses generated from the 00435 //prefix via stateless address autoconfiguration remain preferred 00436 if(preferredLifetime < (MAX_DELAY / 1000)) 00437 entry->preferredLifetime = preferredLifetime * 1000; 00438 else 00439 entry->preferredLifetime = MAX_DELAY; 00440 } 00441 else 00442 { 00443 //A value of all one bits (0xffffffff) represents infinity 00444 entry->preferredLifetime = INFINITE_DELAY; 00445 } 00446 00447 //Save current time 00448 entry->timestamp = osGetSystemTime(); 00449 } 00450 } 00451 } 00452 00453 00454 /** 00455 * @brief Remove an entry from the Prefix List 00456 * @param[in] interface Underlying network interface 00457 * @param[in] prefix IPv6 prefix 00458 * @param[in] length The number of leading bits in the prefix that are valid 00459 **/ 00460 00461 void ipv6RemovePrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length) 00462 { 00463 uint_t i; 00464 Ipv6PrefixEntry *entry; 00465 00466 //Loop through the Prefix List 00467 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++) 00468 { 00469 //Point to the current entry 00470 entry = &interface->ipv6Context.prefixList[i]; 00471 00472 //Valid prefix? 00473 if(entry->validLifetime) 00474 { 00475 //Compare prefix length against the specified value 00476 if(entry->prefixLength == length) 00477 { 00478 //Check whether the current entry matches the specified prefix 00479 if(ipv6CompPrefix(&entry->prefix, prefix, length)) 00480 { 00481 //The IPv6 prefix should be preserved if it has been manually assigned 00482 if(!entry->permanent) 00483 { 00484 //When removing an entry from the Prefix List, there is no need 00485 //to purge any entries from the Destination or Neighbor Caches 00486 entry->prefix = IPV6_UNSPECIFIED_ADDR; 00487 entry->prefixLength = 0; 00488 entry->validLifetime = 0; 00489 } 00490 } 00491 } 00492 } 00493 } 00494 } 00495 00496 00497 /** 00498 * @brief Add a new entry to the Default Router List 00499 * @param[in] interface Underlying network interface 00500 * @param[in] addr IPv6 address of the router 00501 * @param[in] lifetime Router lifetime, in seconds 00502 **/ 00503 00504 void ipv6AddDefaultRouter(NetInterface *interface, 00505 const Ipv6Addr *addr, uint16_t lifetime) 00506 { 00507 uint_t i; 00508 Ipv6RouterEntry *entry; 00509 Ipv6RouterEntry *firstFreeEntry; 00510 00511 //Keep track of the first free entry 00512 firstFreeEntry = NULL; 00513 00514 //Loop through the Default Router List 00515 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++) 00516 { 00517 //Point to the current entry 00518 entry = &interface->ipv6Context.routerList[i]; 00519 00520 //Check the lifetime associated with the default router 00521 if(entry->lifetime) 00522 { 00523 //Check whether the current entry matches the specified router address 00524 if(ipv6CompAddr(&entry->addr, addr)) 00525 break; 00526 } 00527 else 00528 { 00529 //The router address should be preserved if it has been manually assigned 00530 if(!entry->permanent) 00531 { 00532 //Keep track of the first free entry 00533 if(firstFreeEntry == NULL) 00534 firstFreeEntry = entry; 00535 } 00536 } 00537 } 00538 00539 //No matching entry found? 00540 if(i >= IPV6_ROUTER_LIST_SIZE) 00541 entry = firstFreeEntry; 00542 00543 //Update the entry if necessary 00544 if(entry != NULL) 00545 { 00546 //The router address should be preserved if it has been manually assigned 00547 if(!entry->permanent) 00548 { 00549 //Save the IPv6 address of the router 00550 entry->addr = *addr; 00551 //The lifetime associated with the default router 00552 entry->lifetime = lifetime * 1000; 00553 //Save current time 00554 entry->timestamp = osGetSystemTime(); 00555 } 00556 } 00557 } 00558 00559 00560 /** 00561 * @brief Remove an entry from the Default Router List 00562 * @param[in] interface Underlying network interface 00563 * @param[in] addr IPv6 address of the router to be removed from the list 00564 **/ 00565 00566 void ipv6RemoveDefaultRouter(NetInterface *interface, const Ipv6Addr *addr) 00567 { 00568 uint_t i; 00569 bool_t flag; 00570 Ipv6RouterEntry *entry; 00571 00572 //This flag will be set if any entry has been removed from 00573 //the Default Router List 00574 flag = FALSE; 00575 00576 //Loop through the Default Router List 00577 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++) 00578 { 00579 //Point to the current entry 00580 entry = &interface->ipv6Context.routerList[i]; 00581 00582 //Check the lifetime associated with the default router 00583 if(entry->lifetime) 00584 { 00585 //Check whether the current entry matches the specified router address 00586 if(ipv6CompAddr(&entry->addr, addr)) 00587 { 00588 //The router address should be preserved if it has been manually assigned 00589 if(!entry->permanent) 00590 { 00591 //Immediately time-out the entry 00592 entry->addr = IPV6_UNSPECIFIED_ADDR; 00593 entry->lifetime = 0; 00594 00595 //Set flag 00596 flag = TRUE; 00597 } 00598 } 00599 } 00600 } 00601 00602 //Check whether an entry has been removed from the list 00603 if(flag) 00604 { 00605 #if (NDP_SUPPORT == ENABLED) 00606 //When removing a router from the Default Router list, the node must 00607 //update the Destination Cache in such a way that all entries using 00608 //the router perform next-hop determination again 00609 ndpFlushDestCache(interface); 00610 #endif 00611 } 00612 } 00613 00614 00615 /** 00616 * @brief Flush the list of IPv6 addresses 00617 * @param[in] interface Underlying network interface 00618 **/ 00619 00620 void ipv6FlushAddrList(NetInterface *interface) 00621 { 00622 uint_t i; 00623 Ipv6AddrEntry *entry; 00624 00625 //Go through the list of IPv6 addresses 00626 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00627 { 00628 //Point to the current entry 00629 entry = &interface->ipv6Context.addrList[i]; 00630 00631 //Valid IPv6 address? 00632 if(entry->validLifetime > 0) 00633 { 00634 //The IPv6 address should be preserved if it has been manually assigned 00635 if(!entry->permanent) 00636 { 00637 //The IPv6 address is not longer valid 00638 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR, 00639 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE); 00640 } 00641 } 00642 } 00643 } 00644 00645 00646 /** 00647 * @brief Flush the Prefix List 00648 * @param[in] interface Underlying network interface 00649 **/ 00650 00651 void ipv6FlushPrefixList(NetInterface *interface) 00652 { 00653 uint_t i; 00654 Ipv6PrefixEntry *entry; 00655 00656 //Go through the Prefix List 00657 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++) 00658 { 00659 //Point to the current entry 00660 entry = &interface->ipv6Context.prefixList[i]; 00661 00662 //Valid IPv6 prefix? 00663 if(entry->validLifetime > 0) 00664 { 00665 //The IPv6 prefix should be preserved if it has been manually assigned 00666 if(!entry->permanent) 00667 { 00668 //Clear the current entry 00669 entry->prefix = IPV6_UNSPECIFIED_ADDR; 00670 entry->prefixLength = 0; 00671 //Remove the entry from the Prefix List 00672 entry->validLifetime = 0; 00673 } 00674 } 00675 } 00676 } 00677 00678 00679 /** 00680 * @brief Flush the Default Router List 00681 * @param[in] interface Underlying network interface 00682 **/ 00683 00684 void ipv6FlushDefaultRouterList(NetInterface *interface) 00685 { 00686 uint_t i; 00687 Ipv6RouterEntry *entry; 00688 00689 //Go through the Default Router List 00690 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++) 00691 { 00692 //Point to the current entry 00693 entry = &interface->ipv6Context.routerList[i]; 00694 00695 //Valid entry? 00696 if(entry->lifetime > 0) 00697 { 00698 //The router address should be preserved if it has been manually assigned 00699 if(!entry->permanent) 00700 { 00701 //Clear the current entry 00702 entry->addr = IPV6_UNSPECIFIED_ADDR; 00703 //Remove the entry from the Default Router List 00704 entry->lifetime = 0; 00705 } 00706 } 00707 } 00708 } 00709 00710 00711 /** 00712 * @brief Flush the list of DNS servers 00713 * @param[in] interface Underlying network interface 00714 **/ 00715 00716 void ipv6FlushDnsServerList(NetInterface *interface) 00717 { 00718 //Clear the list of DNS servers 00719 memset(interface->ipv6Context.dnsServerList, 0, 00720 sizeof(interface->ipv6Context.dnsServerList)); 00721 } 00722 00723 00724 /** 00725 * @brief Source IPv6 address filtering 00726 * @param[in] interface Underlying network interface 00727 * @param[in] ipAddr Source IPv6 address to be checked 00728 * @return Error code 00729 **/ 00730 00731 error_t ipv6CheckSourceAddr(NetInterface *interface, const Ipv6Addr *ipAddr) 00732 { 00733 //Multicast addresses cannot be used as source address 00734 if(ipv6IsMulticastAddr(ipAddr)) 00735 { 00736 //Debug message 00737 TRACE_WARNING("Wrong source IPv6 address!\r\n"); 00738 //The source address not is acceptable 00739 return ERROR_INVALID_ADDRESS; 00740 } 00741 00742 //The source address is acceptable 00743 return NO_ERROR; 00744 } 00745 00746 00747 /** 00748 * @brief Destination IPv6 address filtering 00749 * @param[in] interface Underlying network interface 00750 * @param[in] ipAddr Destination IPv6 address to be checked 00751 * @return Error code 00752 **/ 00753 00754 error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr) 00755 { 00756 error_t error; 00757 uint_t i; 00758 00759 //Filter out any invalid addresses 00760 error = ERROR_INVALID_ADDRESS; 00761 00762 //Multicast address? 00763 if(ipv6IsMulticastAddr(ipAddr)) 00764 { 00765 //Go through the multicast filter table 00766 for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++) 00767 { 00768 Ipv6FilterEntry *entry; 00769 00770 //Point to the current entry 00771 entry = &interface->ipv6Context.multicastFilter[i]; 00772 00773 //Valid entry? 00774 if(entry->refCount > 0) 00775 { 00776 //Check whether the destination IPv6 address matches 00777 //a relevant multicast address 00778 if(ipv6CompAddr(&entry->addr, ipAddr)) 00779 { 00780 //The multicast address is acceptable 00781 error = NO_ERROR; 00782 //Stop immediately 00783 break; 00784 } 00785 } 00786 } 00787 } 00788 //Unicast address? 00789 else 00790 { 00791 //Loop through the list of IPv6 unicast addresses 00792 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00793 { 00794 Ipv6AddrEntry *entry; 00795 00796 //Point to the current entry 00797 entry = &interface->ipv6Context.addrList[i]; 00798 00799 //Valid entry? 00800 if(entry->state != IPV6_ADDR_STATE_INVALID) 00801 { 00802 //Check whether the destination address matches a valid unicast 00803 //address assigned to the interface 00804 if(ipv6CompAddr(&entry->addr, ipAddr)) 00805 { 00806 //The destination address is acceptable 00807 error = NO_ERROR; 00808 //We are done 00809 break; 00810 } 00811 } 00812 } 00813 00814 //Check whether the specified is a valid unicast address 00815 if(error == ERROR_INVALID_ADDRESS) 00816 { 00817 Ipv6Addr *anycastAddrList; 00818 00819 //Point to the list of anycast addresses assigned to the interface 00820 anycastAddrList = interface->ipv6Context.anycastAddrList; 00821 00822 //Loop through the list of IPv6 anycast addresses 00823 for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++) 00824 { 00825 //Valid entry? 00826 if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR)) 00827 { 00828 //Check whether the destination address matches a valid anycast 00829 //address assigned to the interface 00830 if(ipv6CompAddr(&anycastAddrList[i], ipAddr)) 00831 { 00832 //The destination address is acceptable 00833 error = NO_ERROR; 00834 //We are done 00835 break; 00836 } 00837 } 00838 } 00839 } 00840 } 00841 00842 //Return status code 00843 return error; 00844 } 00845 00846 00847 /** 00848 * @brief IPv6 source address selection 00849 * 00850 * This function selects the source address and the relevant network interface 00851 * to be used in order to join the specified destination address 00852 * 00853 * @param[in,out] interface A pointer to a valid network interface may be provided as 00854 * a hint. The function returns a pointer identifying the interface to be used 00855 * @param[in] destAddr Destination IPv6 address 00856 * @param[out] srcAddr Local IPv6 address to be used 00857 * @return Error code 00858 **/ 00859 00860 error_t ipv6SelectSourceAddr(NetInterface **interface, 00861 const Ipv6Addr *destAddr, Ipv6Addr *srcAddr) 00862 { 00863 uint_t i; 00864 uint_t j; 00865 NetInterface *currentInterface; 00866 NetInterface *bestInterface; 00867 Ipv6AddrEntry *currentAddr; 00868 Ipv6AddrEntry *bestAddr; 00869 00870 //Initialize variables 00871 bestInterface = NULL; 00872 bestAddr = NULL; 00873 00874 //Loop through network interfaces 00875 for(i = 0; i < NET_INTERFACE_COUNT; i++) 00876 { 00877 //Point to the current interface 00878 currentInterface = &netInterface[i]; 00879 00880 //A network interface may be provided as a hint... 00881 if(*interface != currentInterface && *interface != NULL) 00882 { 00883 //Select the next interface in the list 00884 continue; 00885 } 00886 00887 //A sort of the candidate source addresses is being performed, where a 00888 //set of rules define the ordering among addresses (refer to RFC 6724) 00889 for(j = 0; j < IPV6_ADDR_LIST_SIZE; j++) 00890 { 00891 //Point to the current entry 00892 currentAddr = ¤tInterface->ipv6Context.addrList[j]; 00893 00894 //Check the state of the address 00895 if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED || 00896 currentAddr->state == IPV6_ADDR_STATE_DEPRECATED) 00897 { 00898 //Select the first address as default 00899 if(bestAddr == NULL) 00900 { 00901 //Give the current source address the higher precedence 00902 bestInterface = currentInterface; 00903 bestAddr = currentAddr; 00904 00905 //Select the next address in the list 00906 continue; 00907 } 00908 00909 //Rule 1: Prefer same address 00910 if(ipv6CompAddr(&bestAddr->addr, destAddr)) 00911 { 00912 //Select the next address in the list 00913 continue; 00914 } 00915 else if(ipv6CompAddr(¤tAddr->addr, destAddr)) 00916 { 00917 //Give the current source address the higher precedence 00918 bestInterface = currentInterface; 00919 bestAddr = currentAddr; 00920 00921 //Select the next address in the list 00922 continue; 00923 } 00924 00925 //Rule 2: Prefer appropriate scope 00926 if(ipv6GetAddrScope(¤tAddr->addr) < ipv6GetAddrScope(&bestAddr->addr)) 00927 { 00928 if(ipv6GetAddrScope(¤tAddr->addr) >= ipv6GetAddrScope(destAddr)) 00929 { 00930 //Give the current source address the higher precedence 00931 bestInterface = currentInterface; 00932 bestAddr = currentAddr; 00933 } 00934 00935 //Select the next address in the list 00936 continue; 00937 } 00938 else if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(¤tAddr->addr)) 00939 { 00940 if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(destAddr)) 00941 { 00942 //Give the current source address the higher precedence 00943 bestInterface = currentInterface; 00944 bestAddr = currentAddr; 00945 } 00946 00947 //Select the next address in the list 00948 continue; 00949 } 00950 00951 //Rule 3: Avoid deprecated addresses 00952 if(bestAddr->state == IPV6_ADDR_STATE_PREFERRED && 00953 currentAddr->state == IPV6_ADDR_STATE_DEPRECATED) 00954 { 00955 //Select the next address in the list 00956 continue; 00957 } 00958 else if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED && 00959 bestAddr->state == IPV6_ADDR_STATE_DEPRECATED) 00960 { 00961 //Give the current source address the higher precedence 00962 bestInterface = currentInterface; 00963 bestAddr = currentAddr; 00964 00965 //Select the next address in the list 00966 continue; 00967 } 00968 00969 //Rule 8: Use longest matching prefix 00970 if(ipv6GetCommonPrefixLength(¤tAddr->addr, destAddr) > 00971 ipv6GetCommonPrefixLength(&bestAddr->addr, destAddr)) 00972 { 00973 //Give the current source address the higher precedence 00974 bestInterface = currentInterface; 00975 bestAddr = currentAddr; 00976 } 00977 } 00978 } 00979 } 00980 00981 //Source address selection failed? 00982 if(bestAddr == NULL) 00983 { 00984 //Report an error 00985 return ERROR_NO_ADDRESS; 00986 } 00987 00988 //Return the out-going interface and the source address to be used 00989 *interface = bestInterface; 00990 *srcAddr = bestAddr->addr; 00991 00992 //Successful source address selection 00993 return NO_ERROR; 00994 } 00995 00996 00997 /** 00998 * @brief Check whether an IPv6 address is on-link 00999 * @param[in] interface Underlying network interface 01000 * @param[in] ipAddr IPv6 address to be checked 01001 * @return TRUE if the IPv6 address is on-link, else FALSE 01002 **/ 01003 01004 bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr) 01005 { 01006 uint_t i; 01007 Ipv6PrefixEntry *entry; 01008 01009 //Link-local prefix? 01010 if(ipv6IsLinkLocalUnicastAddr(ipAddr)) 01011 { 01012 //The link-local prefix is considered to be on the prefix 01013 //list with an infinite invalidation timer regardless of 01014 //whether routers are advertising a prefix for it 01015 return TRUE; 01016 } 01017 01018 //Loop through the Prefix List 01019 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++) 01020 { 01021 //Point to the current entry 01022 entry = &interface->ipv6Context.prefixList[i]; 01023 01024 //Valid prefix? 01025 if(entry->validLifetime > 0) 01026 { 01027 //Check the specified address against the prefix 01028 if(ipv6CompPrefix(ipAddr, &entry->prefix, entry->prefixLength)) 01029 { 01030 //The specified IPv6 address is on-link 01031 return TRUE; 01032 } 01033 } 01034 } 01035 01036 //The specified IPv6 address is off-link 01037 return FALSE; 01038 } 01039 01040 01041 /** 01042 * @brief Check whether an IPv6 address is a tentative address 01043 * @param[in] interface Underlying network interface 01044 * @param[in] ipAddr IPv6 address to be checked 01045 * @return TRUE if the IPv6 address is a tentative address, else FALSE 01046 **/ 01047 01048 bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr) 01049 { 01050 uint_t i; 01051 Ipv6AddrEntry *entry; 01052 01053 //Loop through the list of IPv6 unicast addresses 01054 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 01055 { 01056 //Point to the current entry 01057 entry = &interface->ipv6Context.addrList[i]; 01058 01059 //Tentative address? 01060 if(entry->state == IPV6_ADDR_STATE_TENTATIVE) 01061 { 01062 //Check whether the specified address matches a valid unicast 01063 //address assigned to the interface 01064 if(ipv6CompAddr(&entry->addr, ipAddr)) 01065 { 01066 //The specified IPv6 address is a tentative address 01067 return TRUE; 01068 } 01069 } 01070 } 01071 01072 //The specified IPv6 address is not a tentative address 01073 return FALSE; 01074 } 01075 01076 01077 /** 01078 * @brief Check whether an IPv6 address is an anycast address 01079 * @param[in] interface Underlying network interface 01080 * @param[in] ipAddr IPv6 address to be checked 01081 * @return TRUE if the IPv6 address is an anycast address, else FALSE 01082 **/ 01083 01084 bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr) 01085 { 01086 uint_t i; 01087 Ipv6Addr *anycastAddrList; 01088 01089 //Point to the list of anycast addresses assigned to the interface 01090 anycastAddrList = interface->ipv6Context.anycastAddrList; 01091 01092 //Loop through the list of IPv6 anycast addresses 01093 for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++) 01094 { 01095 //Valid entry? 01096 if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR)) 01097 { 01098 //Check whether the specified address matches a valid anycast 01099 //address assigned to the interface 01100 if(ipv6CompAddr(&anycastAddrList[i], ipAddr)) 01101 { 01102 //The specified IPv6 address is an anycast address 01103 return TRUE; 01104 } 01105 } 01106 } 01107 01108 //The specified IPv6 address is not an anycast address 01109 return FALSE; 01110 } 01111 01112 01113 /** 01114 * @brief Compare IPv6 address prefixes 01115 * @param[in] ipAddr1 Pointer to the first IPv6 address 01116 * @param[in] ipAddr2 Pointer to the second IPv6 address 01117 * @param[in] length Prefix length 01118 * @return TRUE if the prefixes match each other, else FALSE 01119 **/ 01120 01121 bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length) 01122 { 01123 size_t n = length / 8; 01124 size_t m = length % 8; 01125 01126 //Ensure the prefix length is valid 01127 if(length > 128) 01128 return FALSE; 01129 01130 //Compare the first part 01131 if(n > 0) 01132 { 01133 if(memcmp(ipAddr1, ipAddr2, n)) 01134 return FALSE; 01135 } 01136 01137 //Compare the remaining bits, if any 01138 if(m > 0) 01139 { 01140 //Calculate the mask to be applied 01141 uint8_t mask = ((1 << m) - 1) << (8 - m); 01142 01143 //Check remaining bits 01144 if((ipAddr1->b[n] & mask) != (ipAddr2->b[n] & mask)) 01145 return FALSE; 01146 } 01147 01148 //The prefixes match each other 01149 return TRUE; 01150 } 01151 01152 01153 /** 01154 * @brief Retrieve the scope of an IPv6 address 01155 * @param[in] ipAddr Pointer to an IPv6 address 01156 * @return IPv6 address scope 01157 **/ 01158 01159 uint_t ipv6GetAddrScope(const Ipv6Addr *ipAddr) 01160 { 01161 uint_t scope; 01162 01163 //Multicast address? 01164 if(ipv6IsMulticastAddr(ipAddr)) 01165 { 01166 //Retrieve the scope of the multicast address 01167 scope = ipv6GetMulticastAddrScope(ipAddr); 01168 } 01169 //Loopback address? 01170 else if(ipv6CompAddr(ipAddr, &IPV6_LOOPBACK_ADDR)) 01171 { 01172 //The loopback address may be used by a node to send an IPv6 packet to itself 01173 scope = IPV6_ADDR_SCOPE_INTERFACE_LOCAL; 01174 } 01175 //Link-local unicast address? 01176 else if(ipv6IsLinkLocalUnicastAddr(ipAddr)) 01177 { 01178 //A link-local address is for use on a single link 01179 scope = IPV6_ADDR_SCOPE_LINK_LOCAL; 01180 } 01181 //Site-local unicast address? 01182 else if(ipv6IsSiteLocalUnicastAddr(ipAddr)) 01183 { 01184 //A site-local address is for use in a single site 01185 scope = IPV6_ADDR_SCOPE_SITE_LOCAL; 01186 } 01187 //Global address? 01188 else 01189 { 01190 //Global scope 01191 scope = IPV6_ADDR_SCOPE_GLOBAL; 01192 } 01193 01194 //Return the scope of the specified IPv6 address 01195 return scope; 01196 } 01197 01198 01199 /** 01200 * @brief Retrieve the scope of an IPv6 multicast address 01201 * @param[in] ipAddr Pointer to an IPv6 multicast address 01202 * @return IPv6 address scope 01203 **/ 01204 01205 uint_t ipv6GetMulticastAddrScope(const Ipv6Addr *ipAddr) 01206 { 01207 uint_t scope; 01208 01209 //The scope field is a 4-bit value 01210 scope = ipAddr->b[1] & 0x0F; 01211 01212 //If the scope field contains the reserved value F, an IPv6 packet 01213 //must be treated the same as packets destined to a global multicast 01214 //address (refer to RFC 3513 section 2.7) 01215 if(scope == 0x0F) 01216 scope = IPV6_ADDR_SCOPE_GLOBAL; 01217 01218 //Return the scope of the specified IPv6 multicast address 01219 return scope; 01220 } 01221 01222 01223 /** 01224 * @brief Compute the length of the longest common prefix 01225 * @param[in] ipAddr1 Pointer to the first IPv6 address 01226 * @param[in] ipAddr2 Pointer to the second IPv6 address 01227 * @return The length of the longest common prefix, in bits 01228 **/ 01229 01230 uint_t ipv6GetCommonPrefixLength(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2) 01231 { 01232 uint_t i; 01233 uint_t j; 01234 01235 //Clear bit counter 01236 j = 0; 01237 01238 //Perform a byte-for-byte comparison 01239 for(i = 0; i < sizeof(Ipv6Addr); i++) 01240 { 01241 //Loop as long as prefixes match 01242 if(ipAddr1->b[i] != ipAddr2->b[i]) 01243 break; 01244 } 01245 01246 //Mismatch? 01247 if(i < sizeof(Ipv6Addr)) 01248 { 01249 //Perform a bit-for-bit comparison 01250 for(j = 0; j < 8; j++) 01251 { 01252 //Calculate the mask to be applied 01253 uint8_t mask = 1 << (7 - j); 01254 01255 //Loop as long as prefixes match 01256 if((ipAddr1->b[i] & mask) != (ipAddr2->b[i] & mask)) 01257 break; 01258 } 01259 } 01260 01261 //Return the length of the longest common prefix, in bits 01262 return i * 8 + j; 01263 } 01264 01265 01266 /** 01267 * @brief Form a solicited-node address from an IPv6 address 01268 * @param[in] ipAddr Unicast or anycast address 01269 * @param[out] solicitedNodeAddr Corresponding solicited-node address 01270 * @return Error code 01271 **/ 01272 01273 error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr, 01274 Ipv6Addr *solicitedNodeAddr) 01275 { 01276 //Ensure the specified address is a valid unicast or anycast address 01277 if(ipv6IsMulticastAddr(ipAddr)) 01278 return ERROR_INVALID_ADDRESS; 01279 01280 //Copy the 104-bit prefix 01281 ipv6CopyAddr(solicitedNodeAddr, &IPV6_SOLICITED_NODE_ADDR_PREFIX); 01282 01283 //Take the low-order 24 bits of the address (unicast or 01284 //anycast) and append those bits to the prefix 01285 solicitedNodeAddr->b[13] = ipAddr->b[13]; 01286 solicitedNodeAddr->b[14] = ipAddr->b[14]; 01287 solicitedNodeAddr->b[15] = ipAddr->b[15]; 01288 01289 //No error to report 01290 return NO_ERROR; 01291 } 01292 01293 01294 /** 01295 * @brief Map an IPv6 multicast address to a MAC-layer multicast address 01296 * @param[in] ipAddr IPv6 multicast address 01297 * @param[out] macAddr Corresponding MAC-layer multicast address 01298 * @return Error code 01299 **/ 01300 01301 error_t ipv6MapMulticastAddrToMac(const Ipv6Addr *ipAddr, MacAddr *macAddr) 01302 { 01303 //Ensure the specified IPv6 address is a multicast address 01304 if(!ipv6IsMulticastAddr(ipAddr)) 01305 return ERROR_INVALID_ADDRESS; 01306 01307 //To support IPv6 multicasting, MAC address range of 33-33-00-00-00-00 01308 //to 33-33-FF-FF-FF-FF is reserved (refer to RFC 2464) 01309 macAddr->b[0] = 0x33; 01310 macAddr->b[1] = 0x33; 01311 01312 //The low-order 32 bits of the IPv6 multicast address are mapped directly 01313 //to the low-order 32 bits in the MAC-layer multicast address 01314 macAddr->b[2] = ipAddr->b[12]; 01315 macAddr->b[3] = ipAddr->b[13]; 01316 macAddr->b[4] = ipAddr->b[14]; 01317 macAddr->b[5] = ipAddr->b[15]; 01318 01319 //The specified IPv6 multicast address was successfully 01320 //mapped to a MAC-layer address 01321 return NO_ERROR; 01322 } 01323 01324 01325 /** 01326 * @brief Generate a IPv6 link-local address from an interface identifier 01327 * @param[in] interfaceId Interface identifier 01328 * @param[out] ipAddr Corresponding IPv6 link-local address 01329 **/ 01330 01331 void ipv6GenerateLinkLocalAddr(const Eui64* interfaceId, Ipv6Addr *ipAddr) 01332 { 01333 //A link-local address is formed by combining the well-known 01334 //link-local prefix fe80::/10 with the interface identifier 01335 ipAddr->w[0] = HTONS(0xFE80); 01336 ipAddr->w[1] = HTONS(0x0000); 01337 ipAddr->w[2] = HTONS(0x0000); 01338 ipAddr->w[3] = HTONS(0x0000); 01339 ipAddr->w[4] = interfaceId->w[0]; 01340 ipAddr->w[5] = interfaceId->w[1]; 01341 ipAddr->w[6] = interfaceId->w[2]; 01342 ipAddr->w[7] = interfaceId->w[3]; 01343 } 01344 01345 #endif 01346
Generated on Tue Jul 12 2022 17:10:14 by
