Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ipv6_misc.c Source File

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 = &currentInterface->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(&currentAddr->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(&currentAddr->addr) < ipv6GetAddrScope(&bestAddr->addr))
00927             {
00928                if(ipv6GetAddrScope(&currentAddr->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(&currentAddr->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(&currentAddr->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