Webserver+3d print

Dependents:   Nucleo

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ipv6_misc.c
Sergunb 0:8918a71cdbe9 3 * @brief Helper functions for IPv6
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL IPV6_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include "core/net.h"
Sergunb 0:8918a71cdbe9 34 #include "ipv6/ipv6.h"
Sergunb 0:8918a71cdbe9 35 #include "ipv6/ipv6_misc.h"
Sergunb 0:8918a71cdbe9 36 #include "ipv6/ndp.h"
Sergunb 0:8918a71cdbe9 37 #include "ipv6/ndp_cache.h"
Sergunb 0:8918a71cdbe9 38 #include "mdns/mdns_responder.h"
Sergunb 0:8918a71cdbe9 39 #include "debug.h"
Sergunb 0:8918a71cdbe9 40
Sergunb 0:8918a71cdbe9 41 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 42 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 43
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45 /**
Sergunb 0:8918a71cdbe9 46 * @brief Get the state of the specified IPv6 address
Sergunb 0:8918a71cdbe9 47 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 48 * @param[in] addr IPv6 address
Sergunb 0:8918a71cdbe9 49 * @return Address state
Sergunb 0:8918a71cdbe9 50 **/
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 Ipv6AddrState ipv6GetAddrState(NetInterface *interface, const Ipv6Addr *addr)
Sergunb 0:8918a71cdbe9 53 {
Sergunb 0:8918a71cdbe9 54 uint_t i;
Sergunb 0:8918a71cdbe9 55 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 //Loop through the list of IPv6 addresses assigned to the interface
Sergunb 0:8918a71cdbe9 58 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 59 {
Sergunb 0:8918a71cdbe9 60 //Point to the current entry
Sergunb 0:8918a71cdbe9 61 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 62
Sergunb 0:8918a71cdbe9 63 //Valid IPv6 address
Sergunb 0:8918a71cdbe9 64 if(entry->state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 65 {
Sergunb 0:8918a71cdbe9 66 //Check whether the current entry matches the specified address
Sergunb 0:8918a71cdbe9 67 if(ipv6CompAddr(&entry->addr, addr))
Sergunb 0:8918a71cdbe9 68 {
Sergunb 0:8918a71cdbe9 69 //Return the state of the IPv6 address
Sergunb 0:8918a71cdbe9 70 return entry->state;
Sergunb 0:8918a71cdbe9 71 }
Sergunb 0:8918a71cdbe9 72 }
Sergunb 0:8918a71cdbe9 73 }
Sergunb 0:8918a71cdbe9 74
Sergunb 0:8918a71cdbe9 75 //The specified IPv6 address is not valid
Sergunb 0:8918a71cdbe9 76 return IPV6_ADDR_STATE_INVALID;
Sergunb 0:8918a71cdbe9 77 }
Sergunb 0:8918a71cdbe9 78
Sergunb 0:8918a71cdbe9 79
Sergunb 0:8918a71cdbe9 80 /**
Sergunb 0:8918a71cdbe9 81 * @brief Set IPv6 address and address state
Sergunb 0:8918a71cdbe9 82 * @param[in] interface Pointer to the desired network interface
Sergunb 0:8918a71cdbe9 83 * @param[in] index Zero-based index
Sergunb 0:8918a71cdbe9 84 * @param[in] addr IPv6 address
Sergunb 0:8918a71cdbe9 85 * @param[in] state State of the IPv6 address
Sergunb 0:8918a71cdbe9 86 * @param[in] validLifetime Valid lifetime
Sergunb 0:8918a71cdbe9 87 * @param[in] preferredLifetime Preferred lifetime
Sergunb 0:8918a71cdbe9 88 * @param[in] permanent Permanently assigned address
Sergunb 0:8918a71cdbe9 89 * @return Error code
Sergunb 0:8918a71cdbe9 90 **/
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr,
Sergunb 0:8918a71cdbe9 93 Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent)
Sergunb 0:8918a71cdbe9 94 {
Sergunb 0:8918a71cdbe9 95 error_t error;
Sergunb 0:8918a71cdbe9 96 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 97 Ipv6Addr solicitedNodeAddr;
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99 //Check parameters
Sergunb 0:8918a71cdbe9 100 if(interface == NULL || addr == NULL)
Sergunb 0:8918a71cdbe9 101 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 102
Sergunb 0:8918a71cdbe9 103 //Make sure that the index is valid
Sergunb 0:8918a71cdbe9 104 if(index >= IPV6_ADDR_LIST_SIZE)
Sergunb 0:8918a71cdbe9 105 return ERROR_OUT_OF_RANGE;
Sergunb 0:8918a71cdbe9 106
Sergunb 0:8918a71cdbe9 107 //The IPv6 address must be a valid unicast address
Sergunb 0:8918a71cdbe9 108 if(ipv6IsMulticastAddr(addr))
Sergunb 0:8918a71cdbe9 109 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 110
Sergunb 0:8918a71cdbe9 111 //Initialize status code
Sergunb 0:8918a71cdbe9 112 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Point to the corresponding entry
Sergunb 0:8918a71cdbe9 115 entry = &interface->ipv6Context.addrList[index];
Sergunb 0:8918a71cdbe9 116
Sergunb 0:8918a71cdbe9 117 //Check whether an IPv6 address is already assigned
Sergunb 0:8918a71cdbe9 118 if(!ipv6CompAddr(&entry->addr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 119 {
Sergunb 0:8918a71cdbe9 120 //Check the state of the IPv6 address
Sergunb 0:8918a71cdbe9 121 if(entry->state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 122 {
Sergunb 0:8918a71cdbe9 123 //Ethernet interface?
Sergunb 0:8918a71cdbe9 124 if(interface->nicDriver->type == NIC_TYPE_ETHERNET)
Sergunb 0:8918a71cdbe9 125 {
Sergunb 0:8918a71cdbe9 126 //Form the Solicited-Node address
Sergunb 0:8918a71cdbe9 127 ipv6ComputeSolicitedNodeAddr(&entry->addr, &solicitedNodeAddr);
Sergunb 0:8918a71cdbe9 128 //Leave the Solicited-Node multicast group
Sergunb 0:8918a71cdbe9 129 ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr);
Sergunb 0:8918a71cdbe9 130 }
Sergunb 0:8918a71cdbe9 131 }
Sergunb 0:8918a71cdbe9 132 }
Sergunb 0:8918a71cdbe9 133
Sergunb 0:8918a71cdbe9 134 //The current IPv6 address is no more valid
Sergunb 0:8918a71cdbe9 135 entry->state = IPV6_ADDR_STATE_INVALID;
Sergunb 0:8918a71cdbe9 136 entry->validLifetime = 0;
Sergunb 0:8918a71cdbe9 137 entry->preferredLifetime = 0;
Sergunb 0:8918a71cdbe9 138 entry->permanent = FALSE;
Sergunb 0:8918a71cdbe9 139
Sergunb 0:8918a71cdbe9 140 //Assign the new IPv6 address
Sergunb 0:8918a71cdbe9 141 entry->addr = *addr;
Sergunb 0:8918a71cdbe9 142
Sergunb 0:8918a71cdbe9 143 //Check whether the new IPv6 address is valid
Sergunb 0:8918a71cdbe9 144 if(!ipv6CompAddr(addr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 145 {
Sergunb 0:8918a71cdbe9 146 //Check the state of the IPv6 address
Sergunb 0:8918a71cdbe9 147 if(state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 148 {
Sergunb 0:8918a71cdbe9 149 //Ethernet interface?
Sergunb 0:8918a71cdbe9 150 if(interface->nicDriver->type == NIC_TYPE_ETHERNET)
Sergunb 0:8918a71cdbe9 151 {
Sergunb 0:8918a71cdbe9 152 //Form the Solicited-Node address for the link-local address
Sergunb 0:8918a71cdbe9 153 ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr);
Sergunb 0:8918a71cdbe9 154 //Join the Solicited-Node multicast group for each assigned address
Sergunb 0:8918a71cdbe9 155 error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr);
Sergunb 0:8918a71cdbe9 156 }
Sergunb 0:8918a71cdbe9 157 //6LoWPAN interface?
Sergunb 0:8918a71cdbe9 158 else if(interface->nicDriver->type == NIC_TYPE_6LOWPAN)
Sergunb 0:8918a71cdbe9 159 {
Sergunb 0:8918a71cdbe9 160 //There is no need to join the solicited-node multicast address,
Sergunb 0:8918a71cdbe9 161 //since nobody multicasts Neighbor Solicitations in this type of
Sergunb 0:8918a71cdbe9 162 //network (refer to RFC 6775 section 5.2)
Sergunb 0:8918a71cdbe9 163 }
Sergunb 0:8918a71cdbe9 164 }
Sergunb 0:8918a71cdbe9 165
Sergunb 0:8918a71cdbe9 166 //Check status code
Sergunb 0:8918a71cdbe9 167 if(!error)
Sergunb 0:8918a71cdbe9 168 {
Sergunb 0:8918a71cdbe9 169 //Set the state of the IPv6 address
Sergunb 0:8918a71cdbe9 170 entry->state = state;
Sergunb 0:8918a71cdbe9 171
Sergunb 0:8918a71cdbe9 172 //Clear duplicate flag
Sergunb 0:8918a71cdbe9 173 entry->duplicate = FALSE;
Sergunb 0:8918a71cdbe9 174
Sergunb 0:8918a71cdbe9 175 //Save preferred and valid lifetimes
Sergunb 0:8918a71cdbe9 176 entry->preferredLifetime = preferredLifetime;
Sergunb 0:8918a71cdbe9 177 entry->validLifetime = validLifetime;
Sergunb 0:8918a71cdbe9 178
Sergunb 0:8918a71cdbe9 179 //Set time stamp
Sergunb 0:8918a71cdbe9 180 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 181
Sergunb 0:8918a71cdbe9 182 //Initialize DAD related variables
Sergunb 0:8918a71cdbe9 183 entry->dadTimeout = 0;
Sergunb 0:8918a71cdbe9 184 entry->dadRetransmitCount = 0;
Sergunb 0:8918a71cdbe9 185 }
Sergunb 0:8918a71cdbe9 186
Sergunb 0:8918a71cdbe9 187 //This flag tells whether the IPv6 address should be permanently assigned
Sergunb 0:8918a71cdbe9 188 entry->permanent = permanent;
Sergunb 0:8918a71cdbe9 189 }
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 192 //Link-local address?
Sergunb 0:8918a71cdbe9 193 if(index == 0)
Sergunb 0:8918a71cdbe9 194 {
Sergunb 0:8918a71cdbe9 195 //Restart mDNS probing process
Sergunb 0:8918a71cdbe9 196 mdnsResponderStartProbing(interface->mdnsResponderContext);
Sergunb 0:8918a71cdbe9 197 }
Sergunb 0:8918a71cdbe9 198 #endif
Sergunb 0:8918a71cdbe9 199
Sergunb 0:8918a71cdbe9 200 //Return status code
Sergunb 0:8918a71cdbe9 201 return error;
Sergunb 0:8918a71cdbe9 202 }
Sergunb 0:8918a71cdbe9 203
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 /**
Sergunb 0:8918a71cdbe9 206 * @brief Add a new entry to the list of IPv6 addresses
Sergunb 0:8918a71cdbe9 207 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 208 * @param[in] addr IPv6 address
Sergunb 0:8918a71cdbe9 209 * @param[in] validLifetime Valid lifetime, in seconds
Sergunb 0:8918a71cdbe9 210 * @param[in] preferredLifetime Preferred lifetime, in seconds
Sergunb 0:8918a71cdbe9 211 **/
Sergunb 0:8918a71cdbe9 212
Sergunb 0:8918a71cdbe9 213 void ipv6AddAddr(NetInterface *interface, const Ipv6Addr *addr,
Sergunb 0:8918a71cdbe9 214 uint32_t validLifetime, uint32_t preferredLifetime)
Sergunb 0:8918a71cdbe9 215 {
Sergunb 0:8918a71cdbe9 216 uint_t i;
Sergunb 0:8918a71cdbe9 217 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 218
Sergunb 0:8918a71cdbe9 219 //Check the valid lifetime
Sergunb 0:8918a71cdbe9 220 if(validLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 221 {
Sergunb 0:8918a71cdbe9 222 //The length of time in seconds that the address is valid
Sergunb 0:8918a71cdbe9 223 if(validLifetime < (MAX_DELAY / 1000))
Sergunb 0:8918a71cdbe9 224 validLifetime *= 1000;
Sergunb 0:8918a71cdbe9 225 else
Sergunb 0:8918a71cdbe9 226 validLifetime = MAX_DELAY;
Sergunb 0:8918a71cdbe9 227 }
Sergunb 0:8918a71cdbe9 228 else
Sergunb 0:8918a71cdbe9 229 {
Sergunb 0:8918a71cdbe9 230 //A value of all one bits (0xffffffff) represents infinity
Sergunb 0:8918a71cdbe9 231 validLifetime = INFINITE_DELAY;
Sergunb 0:8918a71cdbe9 232 }
Sergunb 0:8918a71cdbe9 233
Sergunb 0:8918a71cdbe9 234 //Check the preferred lifetime
Sergunb 0:8918a71cdbe9 235 if(preferredLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 236 {
Sergunb 0:8918a71cdbe9 237 //The length of time in seconds that the address remains preferred
Sergunb 0:8918a71cdbe9 238 if(preferredLifetime < (MAX_DELAY / 1000))
Sergunb 0:8918a71cdbe9 239 preferredLifetime *= 1000;
Sergunb 0:8918a71cdbe9 240 else
Sergunb 0:8918a71cdbe9 241 preferredLifetime = MAX_DELAY;
Sergunb 0:8918a71cdbe9 242 }
Sergunb 0:8918a71cdbe9 243 else
Sergunb 0:8918a71cdbe9 244 {
Sergunb 0:8918a71cdbe9 245 //A value of all one bits (0xffffffff) represents infinity
Sergunb 0:8918a71cdbe9 246 preferredLifetime = INFINITE_DELAY;
Sergunb 0:8918a71cdbe9 247 }
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249 //Loop through the list of IPv6 addresses assigned to the interface
Sergunb 0:8918a71cdbe9 250 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 251 {
Sergunb 0:8918a71cdbe9 252 //Point to the current entry
Sergunb 0:8918a71cdbe9 253 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Check the state of the IPv6 address
Sergunb 0:8918a71cdbe9 256 if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
Sergunb 0:8918a71cdbe9 257 entry->state == IPV6_ADDR_STATE_DEPRECATED)
Sergunb 0:8918a71cdbe9 258 {
Sergunb 0:8918a71cdbe9 259 //Check whether the current entry matches the specified address
Sergunb 0:8918a71cdbe9 260 if(ipv6CompAddr(&entry->addr, addr))
Sergunb 0:8918a71cdbe9 261 {
Sergunb 0:8918a71cdbe9 262 //The IPv6 address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 263 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 264 {
Sergunb 0:8918a71cdbe9 265 //Update the lifetimes of the entry
Sergunb 0:8918a71cdbe9 266 entry->validLifetime = validLifetime;
Sergunb 0:8918a71cdbe9 267 entry->preferredLifetime = preferredLifetime;
Sergunb 0:8918a71cdbe9 268
Sergunb 0:8918a71cdbe9 269 //Save current time
Sergunb 0:8918a71cdbe9 270 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 271 //Update the state of the IPv6 address
Sergunb 0:8918a71cdbe9 272 entry->state = IPV6_ADDR_STATE_PREFERRED;
Sergunb 0:8918a71cdbe9 273 }
Sergunb 0:8918a71cdbe9 274
Sergunb 0:8918a71cdbe9 275 //Exit immediately
Sergunb 0:8918a71cdbe9 276 return;
Sergunb 0:8918a71cdbe9 277 }
Sergunb 0:8918a71cdbe9 278 }
Sergunb 0:8918a71cdbe9 279 }
Sergunb 0:8918a71cdbe9 280
Sergunb 0:8918a71cdbe9 281 //If no matching entry was found, then try to create a new entry
Sergunb 0:8918a71cdbe9 282 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 283 {
Sergunb 0:8918a71cdbe9 284 //Point to the current entry
Sergunb 0:8918a71cdbe9 285 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 286
Sergunb 0:8918a71cdbe9 287 //Check the state of the IPv6 address
Sergunb 0:8918a71cdbe9 288 if(entry->state == IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 289 {
Sergunb 0:8918a71cdbe9 290 //The IPv6 address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 291 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 292 {
Sergunb 0:8918a71cdbe9 293 #if (NDP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 294 //Check whether Duplicate Address Detection should be performed
Sergunb 0:8918a71cdbe9 295 if(interface->ndpContext.dupAddrDetectTransmits > 0)
Sergunb 0:8918a71cdbe9 296 {
Sergunb 0:8918a71cdbe9 297 //Use the IPv6 address as a tentative address
Sergunb 0:8918a71cdbe9 298 ipv6SetAddr(interface, i, addr, IPV6_ADDR_STATE_TENTATIVE,
Sergunb 0:8918a71cdbe9 299 validLifetime, preferredLifetime, FALSE);
Sergunb 0:8918a71cdbe9 300 }
Sergunb 0:8918a71cdbe9 301 else
Sergunb 0:8918a71cdbe9 302 #endif
Sergunb 0:8918a71cdbe9 303 {
Sergunb 0:8918a71cdbe9 304 //The use of the IPv6 address is now unrestricted
Sergunb 0:8918a71cdbe9 305 ipv6SetAddr(interface, i, addr, IPV6_ADDR_STATE_PREFERRED,
Sergunb 0:8918a71cdbe9 306 validLifetime, preferredLifetime, FALSE);
Sergunb 0:8918a71cdbe9 307 }
Sergunb 0:8918a71cdbe9 308
Sergunb 0:8918a71cdbe9 309 //Exit immediately
Sergunb 0:8918a71cdbe9 310 return;
Sergunb 0:8918a71cdbe9 311 }
Sergunb 0:8918a71cdbe9 312 }
Sergunb 0:8918a71cdbe9 313 }
Sergunb 0:8918a71cdbe9 314 }
Sergunb 0:8918a71cdbe9 315
Sergunb 0:8918a71cdbe9 316
Sergunb 0:8918a71cdbe9 317 /**
Sergunb 0:8918a71cdbe9 318 * @brief Remove an entry from the list of IPv6 addresses
Sergunb 0:8918a71cdbe9 319 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 320 * @param[in] addr IPv6 address
Sergunb 0:8918a71cdbe9 321 **/
Sergunb 0:8918a71cdbe9 322
Sergunb 0:8918a71cdbe9 323 void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
Sergunb 0:8918a71cdbe9 324 {
Sergunb 0:8918a71cdbe9 325 uint_t i;
Sergunb 0:8918a71cdbe9 326 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 327
Sergunb 0:8918a71cdbe9 328 //Loop through the list of IPv6 addresses assigned to the interface
Sergunb 0:8918a71cdbe9 329 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 330 {
Sergunb 0:8918a71cdbe9 331 //Point to the current entry
Sergunb 0:8918a71cdbe9 332 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 333
Sergunb 0:8918a71cdbe9 334 //Valid IPv6 address?
Sergunb 0:8918a71cdbe9 335 if(entry->validLifetime)
Sergunb 0:8918a71cdbe9 336 {
Sergunb 0:8918a71cdbe9 337 //Check whether the current entry matches the specified address
Sergunb 0:8918a71cdbe9 338 if(ipv6CompAddr(&entry->addr, addr))
Sergunb 0:8918a71cdbe9 339 {
Sergunb 0:8918a71cdbe9 340 //The IPv6 address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 341 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 342 {
Sergunb 0:8918a71cdbe9 343 //Remove the IPv6 address from the list
Sergunb 0:8918a71cdbe9 344 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
Sergunb 0:8918a71cdbe9 345 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE);
Sergunb 0:8918a71cdbe9 346 }
Sergunb 0:8918a71cdbe9 347 }
Sergunb 0:8918a71cdbe9 348 }
Sergunb 0:8918a71cdbe9 349 }
Sergunb 0:8918a71cdbe9 350 }
Sergunb 0:8918a71cdbe9 351
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 /**
Sergunb 0:8918a71cdbe9 354 * @brief Add a new entry to the Prefix List
Sergunb 0:8918a71cdbe9 355 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 356 * @param[in] prefix IPv6 prefix
Sergunb 0:8918a71cdbe9 357 * @param[in] length The number of leading bits in the prefix that are valid
Sergunb 0:8918a71cdbe9 358 * @param[in] validLifetime Valid lifetime, in seconds
Sergunb 0:8918a71cdbe9 359 * @param[in] preferredLifetime Preferred lifetime, in seconds
Sergunb 0:8918a71cdbe9 360 **/
Sergunb 0:8918a71cdbe9 361
Sergunb 0:8918a71cdbe9 362 void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix,
Sergunb 0:8918a71cdbe9 363 uint_t length, uint32_t validLifetime, uint32_t preferredLifetime)
Sergunb 0:8918a71cdbe9 364 {
Sergunb 0:8918a71cdbe9 365 uint_t i;
Sergunb 0:8918a71cdbe9 366 Ipv6PrefixEntry *entry;
Sergunb 0:8918a71cdbe9 367 Ipv6PrefixEntry *firstFreeEntry;
Sergunb 0:8918a71cdbe9 368
Sergunb 0:8918a71cdbe9 369 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 370 firstFreeEntry = NULL;
Sergunb 0:8918a71cdbe9 371
Sergunb 0:8918a71cdbe9 372 //Loop through the Prefix List
Sergunb 0:8918a71cdbe9 373 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 374 {
Sergunb 0:8918a71cdbe9 375 //Point to the current entry
Sergunb 0:8918a71cdbe9 376 entry = &interface->ipv6Context.prefixList[i];
Sergunb 0:8918a71cdbe9 377
Sergunb 0:8918a71cdbe9 378 //Valid prefix?
Sergunb 0:8918a71cdbe9 379 if(entry->validLifetime)
Sergunb 0:8918a71cdbe9 380 {
Sergunb 0:8918a71cdbe9 381 //Compare prefix length against the specified value
Sergunb 0:8918a71cdbe9 382 if(entry->prefixLength == length)
Sergunb 0:8918a71cdbe9 383 {
Sergunb 0:8918a71cdbe9 384 //Check whether the current entry matches the specified prefix
Sergunb 0:8918a71cdbe9 385 if(ipv6CompPrefix(&entry->prefix, prefix, length))
Sergunb 0:8918a71cdbe9 386 break;
Sergunb 0:8918a71cdbe9 387 }
Sergunb 0:8918a71cdbe9 388 }
Sergunb 0:8918a71cdbe9 389 else
Sergunb 0:8918a71cdbe9 390 {
Sergunb 0:8918a71cdbe9 391 //The IPv6 prefix should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 392 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 393 {
Sergunb 0:8918a71cdbe9 394 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 395 if(firstFreeEntry == NULL)
Sergunb 0:8918a71cdbe9 396 firstFreeEntry = entry;
Sergunb 0:8918a71cdbe9 397 }
Sergunb 0:8918a71cdbe9 398 }
Sergunb 0:8918a71cdbe9 399 }
Sergunb 0:8918a71cdbe9 400
Sergunb 0:8918a71cdbe9 401 //No matching entry found?
Sergunb 0:8918a71cdbe9 402 if(i >= IPV6_PREFIX_LIST_SIZE)
Sergunb 0:8918a71cdbe9 403 entry = firstFreeEntry;
Sergunb 0:8918a71cdbe9 404
Sergunb 0:8918a71cdbe9 405 //Update the entry if necessary
Sergunb 0:8918a71cdbe9 406 if(entry != NULL)
Sergunb 0:8918a71cdbe9 407 {
Sergunb 0:8918a71cdbe9 408 //The IPv6 prefix should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 409 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 410 {
Sergunb 0:8918a71cdbe9 411 //Save the IPv6 prefix
Sergunb 0:8918a71cdbe9 412 entry->prefix = *prefix;
Sergunb 0:8918a71cdbe9 413 entry->prefixLength = length;
Sergunb 0:8918a71cdbe9 414
Sergunb 0:8918a71cdbe9 415 //Check the valid lifetime
Sergunb 0:8918a71cdbe9 416 if(validLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 417 {
Sergunb 0:8918a71cdbe9 418 //The length of time in seconds that the prefix is valid
Sergunb 0:8918a71cdbe9 419 //for the purpose of on-link determination
Sergunb 0:8918a71cdbe9 420 if(validLifetime < (MAX_DELAY / 1000))
Sergunb 0:8918a71cdbe9 421 entry->validLifetime = validLifetime * 1000;
Sergunb 0:8918a71cdbe9 422 else
Sergunb 0:8918a71cdbe9 423 entry->validLifetime = MAX_DELAY;
Sergunb 0:8918a71cdbe9 424 }
Sergunb 0:8918a71cdbe9 425 else
Sergunb 0:8918a71cdbe9 426 {
Sergunb 0:8918a71cdbe9 427 //A value of all one bits (0xffffffff) represents infinity
Sergunb 0:8918a71cdbe9 428 entry->validLifetime = INFINITE_DELAY;
Sergunb 0:8918a71cdbe9 429 }
Sergunb 0:8918a71cdbe9 430
Sergunb 0:8918a71cdbe9 431 //Check the preferred lifetime
Sergunb 0:8918a71cdbe9 432 if(preferredLifetime != NDP_INFINITE_LIFETIME)
Sergunb 0:8918a71cdbe9 433 {
Sergunb 0:8918a71cdbe9 434 //The length of time in seconds that addresses generated from the
Sergunb 0:8918a71cdbe9 435 //prefix via stateless address autoconfiguration remain preferred
Sergunb 0:8918a71cdbe9 436 if(preferredLifetime < (MAX_DELAY / 1000))
Sergunb 0:8918a71cdbe9 437 entry->preferredLifetime = preferredLifetime * 1000;
Sergunb 0:8918a71cdbe9 438 else
Sergunb 0:8918a71cdbe9 439 entry->preferredLifetime = MAX_DELAY;
Sergunb 0:8918a71cdbe9 440 }
Sergunb 0:8918a71cdbe9 441 else
Sergunb 0:8918a71cdbe9 442 {
Sergunb 0:8918a71cdbe9 443 //A value of all one bits (0xffffffff) represents infinity
Sergunb 0:8918a71cdbe9 444 entry->preferredLifetime = INFINITE_DELAY;
Sergunb 0:8918a71cdbe9 445 }
Sergunb 0:8918a71cdbe9 446
Sergunb 0:8918a71cdbe9 447 //Save current time
Sergunb 0:8918a71cdbe9 448 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 449 }
Sergunb 0:8918a71cdbe9 450 }
Sergunb 0:8918a71cdbe9 451 }
Sergunb 0:8918a71cdbe9 452
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 /**
Sergunb 0:8918a71cdbe9 455 * @brief Remove an entry from the Prefix List
Sergunb 0:8918a71cdbe9 456 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 457 * @param[in] prefix IPv6 prefix
Sergunb 0:8918a71cdbe9 458 * @param[in] length The number of leading bits in the prefix that are valid
Sergunb 0:8918a71cdbe9 459 **/
Sergunb 0:8918a71cdbe9 460
Sergunb 0:8918a71cdbe9 461 void ipv6RemovePrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length)
Sergunb 0:8918a71cdbe9 462 {
Sergunb 0:8918a71cdbe9 463 uint_t i;
Sergunb 0:8918a71cdbe9 464 Ipv6PrefixEntry *entry;
Sergunb 0:8918a71cdbe9 465
Sergunb 0:8918a71cdbe9 466 //Loop through the Prefix List
Sergunb 0:8918a71cdbe9 467 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 468 {
Sergunb 0:8918a71cdbe9 469 //Point to the current entry
Sergunb 0:8918a71cdbe9 470 entry = &interface->ipv6Context.prefixList[i];
Sergunb 0:8918a71cdbe9 471
Sergunb 0:8918a71cdbe9 472 //Valid prefix?
Sergunb 0:8918a71cdbe9 473 if(entry->validLifetime)
Sergunb 0:8918a71cdbe9 474 {
Sergunb 0:8918a71cdbe9 475 //Compare prefix length against the specified value
Sergunb 0:8918a71cdbe9 476 if(entry->prefixLength == length)
Sergunb 0:8918a71cdbe9 477 {
Sergunb 0:8918a71cdbe9 478 //Check whether the current entry matches the specified prefix
Sergunb 0:8918a71cdbe9 479 if(ipv6CompPrefix(&entry->prefix, prefix, length))
Sergunb 0:8918a71cdbe9 480 {
Sergunb 0:8918a71cdbe9 481 //The IPv6 prefix should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 482 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 483 {
Sergunb 0:8918a71cdbe9 484 //When removing an entry from the Prefix List, there is no need
Sergunb 0:8918a71cdbe9 485 //to purge any entries from the Destination or Neighbor Caches
Sergunb 0:8918a71cdbe9 486 entry->prefix = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 487 entry->prefixLength = 0;
Sergunb 0:8918a71cdbe9 488 entry->validLifetime = 0;
Sergunb 0:8918a71cdbe9 489 }
Sergunb 0:8918a71cdbe9 490 }
Sergunb 0:8918a71cdbe9 491 }
Sergunb 0:8918a71cdbe9 492 }
Sergunb 0:8918a71cdbe9 493 }
Sergunb 0:8918a71cdbe9 494 }
Sergunb 0:8918a71cdbe9 495
Sergunb 0:8918a71cdbe9 496
Sergunb 0:8918a71cdbe9 497 /**
Sergunb 0:8918a71cdbe9 498 * @brief Add a new entry to the Default Router List
Sergunb 0:8918a71cdbe9 499 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 500 * @param[in] addr IPv6 address of the router
Sergunb 0:8918a71cdbe9 501 * @param[in] lifetime Router lifetime, in seconds
Sergunb 0:8918a71cdbe9 502 **/
Sergunb 0:8918a71cdbe9 503
Sergunb 0:8918a71cdbe9 504 void ipv6AddDefaultRouter(NetInterface *interface,
Sergunb 0:8918a71cdbe9 505 const Ipv6Addr *addr, uint16_t lifetime)
Sergunb 0:8918a71cdbe9 506 {
Sergunb 0:8918a71cdbe9 507 uint_t i;
Sergunb 0:8918a71cdbe9 508 Ipv6RouterEntry *entry;
Sergunb 0:8918a71cdbe9 509 Ipv6RouterEntry *firstFreeEntry;
Sergunb 0:8918a71cdbe9 510
Sergunb 0:8918a71cdbe9 511 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 512 firstFreeEntry = NULL;
Sergunb 0:8918a71cdbe9 513
Sergunb 0:8918a71cdbe9 514 //Loop through the Default Router List
Sergunb 0:8918a71cdbe9 515 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 516 {
Sergunb 0:8918a71cdbe9 517 //Point to the current entry
Sergunb 0:8918a71cdbe9 518 entry = &interface->ipv6Context.routerList[i];
Sergunb 0:8918a71cdbe9 519
Sergunb 0:8918a71cdbe9 520 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 521 if(entry->lifetime)
Sergunb 0:8918a71cdbe9 522 {
Sergunb 0:8918a71cdbe9 523 //Check whether the current entry matches the specified router address
Sergunb 0:8918a71cdbe9 524 if(ipv6CompAddr(&entry->addr, addr))
Sergunb 0:8918a71cdbe9 525 break;
Sergunb 0:8918a71cdbe9 526 }
Sergunb 0:8918a71cdbe9 527 else
Sergunb 0:8918a71cdbe9 528 {
Sergunb 0:8918a71cdbe9 529 //The router address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 530 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 531 {
Sergunb 0:8918a71cdbe9 532 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 533 if(firstFreeEntry == NULL)
Sergunb 0:8918a71cdbe9 534 firstFreeEntry = entry;
Sergunb 0:8918a71cdbe9 535 }
Sergunb 0:8918a71cdbe9 536 }
Sergunb 0:8918a71cdbe9 537 }
Sergunb 0:8918a71cdbe9 538
Sergunb 0:8918a71cdbe9 539 //No matching entry found?
Sergunb 0:8918a71cdbe9 540 if(i >= IPV6_ROUTER_LIST_SIZE)
Sergunb 0:8918a71cdbe9 541 entry = firstFreeEntry;
Sergunb 0:8918a71cdbe9 542
Sergunb 0:8918a71cdbe9 543 //Update the entry if necessary
Sergunb 0:8918a71cdbe9 544 if(entry != NULL)
Sergunb 0:8918a71cdbe9 545 {
Sergunb 0:8918a71cdbe9 546 //The router address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 547 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 548 {
Sergunb 0:8918a71cdbe9 549 //Save the IPv6 address of the router
Sergunb 0:8918a71cdbe9 550 entry->addr = *addr;
Sergunb 0:8918a71cdbe9 551 //The lifetime associated with the default router
Sergunb 0:8918a71cdbe9 552 entry->lifetime = lifetime * 1000;
Sergunb 0:8918a71cdbe9 553 //Save current time
Sergunb 0:8918a71cdbe9 554 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 555 }
Sergunb 0:8918a71cdbe9 556 }
Sergunb 0:8918a71cdbe9 557 }
Sergunb 0:8918a71cdbe9 558
Sergunb 0:8918a71cdbe9 559
Sergunb 0:8918a71cdbe9 560 /**
Sergunb 0:8918a71cdbe9 561 * @brief Remove an entry from the Default Router List
Sergunb 0:8918a71cdbe9 562 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 563 * @param[in] addr IPv6 address of the router to be removed from the list
Sergunb 0:8918a71cdbe9 564 **/
Sergunb 0:8918a71cdbe9 565
Sergunb 0:8918a71cdbe9 566 void ipv6RemoveDefaultRouter(NetInterface *interface, const Ipv6Addr *addr)
Sergunb 0:8918a71cdbe9 567 {
Sergunb 0:8918a71cdbe9 568 uint_t i;
Sergunb 0:8918a71cdbe9 569 bool_t flag;
Sergunb 0:8918a71cdbe9 570 Ipv6RouterEntry *entry;
Sergunb 0:8918a71cdbe9 571
Sergunb 0:8918a71cdbe9 572 //This flag will be set if any entry has been removed from
Sergunb 0:8918a71cdbe9 573 //the Default Router List
Sergunb 0:8918a71cdbe9 574 flag = FALSE;
Sergunb 0:8918a71cdbe9 575
Sergunb 0:8918a71cdbe9 576 //Loop through the Default Router List
Sergunb 0:8918a71cdbe9 577 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 578 {
Sergunb 0:8918a71cdbe9 579 //Point to the current entry
Sergunb 0:8918a71cdbe9 580 entry = &interface->ipv6Context.routerList[i];
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582 //Check the lifetime associated with the default router
Sergunb 0:8918a71cdbe9 583 if(entry->lifetime)
Sergunb 0:8918a71cdbe9 584 {
Sergunb 0:8918a71cdbe9 585 //Check whether the current entry matches the specified router address
Sergunb 0:8918a71cdbe9 586 if(ipv6CompAddr(&entry->addr, addr))
Sergunb 0:8918a71cdbe9 587 {
Sergunb 0:8918a71cdbe9 588 //The router address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 589 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 590 {
Sergunb 0:8918a71cdbe9 591 //Immediately time-out the entry
Sergunb 0:8918a71cdbe9 592 entry->addr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 593 entry->lifetime = 0;
Sergunb 0:8918a71cdbe9 594
Sergunb 0:8918a71cdbe9 595 //Set flag
Sergunb 0:8918a71cdbe9 596 flag = TRUE;
Sergunb 0:8918a71cdbe9 597 }
Sergunb 0:8918a71cdbe9 598 }
Sergunb 0:8918a71cdbe9 599 }
Sergunb 0:8918a71cdbe9 600 }
Sergunb 0:8918a71cdbe9 601
Sergunb 0:8918a71cdbe9 602 //Check whether an entry has been removed from the list
Sergunb 0:8918a71cdbe9 603 if(flag)
Sergunb 0:8918a71cdbe9 604 {
Sergunb 0:8918a71cdbe9 605 #if (NDP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 606 //When removing a router from the Default Router list, the node must
Sergunb 0:8918a71cdbe9 607 //update the Destination Cache in such a way that all entries using
Sergunb 0:8918a71cdbe9 608 //the router perform next-hop determination again
Sergunb 0:8918a71cdbe9 609 ndpFlushDestCache(interface);
Sergunb 0:8918a71cdbe9 610 #endif
Sergunb 0:8918a71cdbe9 611 }
Sergunb 0:8918a71cdbe9 612 }
Sergunb 0:8918a71cdbe9 613
Sergunb 0:8918a71cdbe9 614
Sergunb 0:8918a71cdbe9 615 /**
Sergunb 0:8918a71cdbe9 616 * @brief Flush the list of IPv6 addresses
Sergunb 0:8918a71cdbe9 617 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 618 **/
Sergunb 0:8918a71cdbe9 619
Sergunb 0:8918a71cdbe9 620 void ipv6FlushAddrList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 621 {
Sergunb 0:8918a71cdbe9 622 uint_t i;
Sergunb 0:8918a71cdbe9 623 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 624
Sergunb 0:8918a71cdbe9 625 //Go through the list of IPv6 addresses
Sergunb 0:8918a71cdbe9 626 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 627 {
Sergunb 0:8918a71cdbe9 628 //Point to the current entry
Sergunb 0:8918a71cdbe9 629 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 630
Sergunb 0:8918a71cdbe9 631 //Valid IPv6 address?
Sergunb 0:8918a71cdbe9 632 if(entry->validLifetime > 0)
Sergunb 0:8918a71cdbe9 633 {
Sergunb 0:8918a71cdbe9 634 //The IPv6 address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 635 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 636 {
Sergunb 0:8918a71cdbe9 637 //The IPv6 address is not longer valid
Sergunb 0:8918a71cdbe9 638 ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
Sergunb 0:8918a71cdbe9 639 IPV6_ADDR_STATE_INVALID, 0, 0, FALSE);
Sergunb 0:8918a71cdbe9 640 }
Sergunb 0:8918a71cdbe9 641 }
Sergunb 0:8918a71cdbe9 642 }
Sergunb 0:8918a71cdbe9 643 }
Sergunb 0:8918a71cdbe9 644
Sergunb 0:8918a71cdbe9 645
Sergunb 0:8918a71cdbe9 646 /**
Sergunb 0:8918a71cdbe9 647 * @brief Flush the Prefix List
Sergunb 0:8918a71cdbe9 648 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 649 **/
Sergunb 0:8918a71cdbe9 650
Sergunb 0:8918a71cdbe9 651 void ipv6FlushPrefixList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 652 {
Sergunb 0:8918a71cdbe9 653 uint_t i;
Sergunb 0:8918a71cdbe9 654 Ipv6PrefixEntry *entry;
Sergunb 0:8918a71cdbe9 655
Sergunb 0:8918a71cdbe9 656 //Go through the Prefix List
Sergunb 0:8918a71cdbe9 657 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 658 {
Sergunb 0:8918a71cdbe9 659 //Point to the current entry
Sergunb 0:8918a71cdbe9 660 entry = &interface->ipv6Context.prefixList[i];
Sergunb 0:8918a71cdbe9 661
Sergunb 0:8918a71cdbe9 662 //Valid IPv6 prefix?
Sergunb 0:8918a71cdbe9 663 if(entry->validLifetime > 0)
Sergunb 0:8918a71cdbe9 664 {
Sergunb 0:8918a71cdbe9 665 //The IPv6 prefix should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 666 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 667 {
Sergunb 0:8918a71cdbe9 668 //Clear the current entry
Sergunb 0:8918a71cdbe9 669 entry->prefix = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 670 entry->prefixLength = 0;
Sergunb 0:8918a71cdbe9 671 //Remove the entry from the Prefix List
Sergunb 0:8918a71cdbe9 672 entry->validLifetime = 0;
Sergunb 0:8918a71cdbe9 673 }
Sergunb 0:8918a71cdbe9 674 }
Sergunb 0:8918a71cdbe9 675 }
Sergunb 0:8918a71cdbe9 676 }
Sergunb 0:8918a71cdbe9 677
Sergunb 0:8918a71cdbe9 678
Sergunb 0:8918a71cdbe9 679 /**
Sergunb 0:8918a71cdbe9 680 * @brief Flush the Default Router List
Sergunb 0:8918a71cdbe9 681 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 682 **/
Sergunb 0:8918a71cdbe9 683
Sergunb 0:8918a71cdbe9 684 void ipv6FlushDefaultRouterList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 685 {
Sergunb 0:8918a71cdbe9 686 uint_t i;
Sergunb 0:8918a71cdbe9 687 Ipv6RouterEntry *entry;
Sergunb 0:8918a71cdbe9 688
Sergunb 0:8918a71cdbe9 689 //Go through the Default Router List
Sergunb 0:8918a71cdbe9 690 for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 691 {
Sergunb 0:8918a71cdbe9 692 //Point to the current entry
Sergunb 0:8918a71cdbe9 693 entry = &interface->ipv6Context.routerList[i];
Sergunb 0:8918a71cdbe9 694
Sergunb 0:8918a71cdbe9 695 //Valid entry?
Sergunb 0:8918a71cdbe9 696 if(entry->lifetime > 0)
Sergunb 0:8918a71cdbe9 697 {
Sergunb 0:8918a71cdbe9 698 //The router address should be preserved if it has been manually assigned
Sergunb 0:8918a71cdbe9 699 if(!entry->permanent)
Sergunb 0:8918a71cdbe9 700 {
Sergunb 0:8918a71cdbe9 701 //Clear the current entry
Sergunb 0:8918a71cdbe9 702 entry->addr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 703 //Remove the entry from the Default Router List
Sergunb 0:8918a71cdbe9 704 entry->lifetime = 0;
Sergunb 0:8918a71cdbe9 705 }
Sergunb 0:8918a71cdbe9 706 }
Sergunb 0:8918a71cdbe9 707 }
Sergunb 0:8918a71cdbe9 708 }
Sergunb 0:8918a71cdbe9 709
Sergunb 0:8918a71cdbe9 710
Sergunb 0:8918a71cdbe9 711 /**
Sergunb 0:8918a71cdbe9 712 * @brief Flush the list of DNS servers
Sergunb 0:8918a71cdbe9 713 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 714 **/
Sergunb 0:8918a71cdbe9 715
Sergunb 0:8918a71cdbe9 716 void ipv6FlushDnsServerList(NetInterface *interface)
Sergunb 0:8918a71cdbe9 717 {
Sergunb 0:8918a71cdbe9 718 //Clear the list of DNS servers
Sergunb 0:8918a71cdbe9 719 memset(interface->ipv6Context.dnsServerList, 0,
Sergunb 0:8918a71cdbe9 720 sizeof(interface->ipv6Context.dnsServerList));
Sergunb 0:8918a71cdbe9 721 }
Sergunb 0:8918a71cdbe9 722
Sergunb 0:8918a71cdbe9 723
Sergunb 0:8918a71cdbe9 724 /**
Sergunb 0:8918a71cdbe9 725 * @brief Source IPv6 address filtering
Sergunb 0:8918a71cdbe9 726 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 727 * @param[in] ipAddr Source IPv6 address to be checked
Sergunb 0:8918a71cdbe9 728 * @return Error code
Sergunb 0:8918a71cdbe9 729 **/
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 error_t ipv6CheckSourceAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 732 {
Sergunb 0:8918a71cdbe9 733 //Multicast addresses cannot be used as source address
Sergunb 0:8918a71cdbe9 734 if(ipv6IsMulticastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 735 {
Sergunb 0:8918a71cdbe9 736 //Debug message
Sergunb 0:8918a71cdbe9 737 TRACE_WARNING("Wrong source IPv6 address!\r\n");
Sergunb 0:8918a71cdbe9 738 //The source address not is acceptable
Sergunb 0:8918a71cdbe9 739 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 740 }
Sergunb 0:8918a71cdbe9 741
Sergunb 0:8918a71cdbe9 742 //The source address is acceptable
Sergunb 0:8918a71cdbe9 743 return NO_ERROR;
Sergunb 0:8918a71cdbe9 744 }
Sergunb 0:8918a71cdbe9 745
Sergunb 0:8918a71cdbe9 746
Sergunb 0:8918a71cdbe9 747 /**
Sergunb 0:8918a71cdbe9 748 * @brief Destination IPv6 address filtering
Sergunb 0:8918a71cdbe9 749 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 750 * @param[in] ipAddr Destination IPv6 address to be checked
Sergunb 0:8918a71cdbe9 751 * @return Error code
Sergunb 0:8918a71cdbe9 752 **/
Sergunb 0:8918a71cdbe9 753
Sergunb 0:8918a71cdbe9 754 error_t ipv6CheckDestAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 755 {
Sergunb 0:8918a71cdbe9 756 error_t error;
Sergunb 0:8918a71cdbe9 757 uint_t i;
Sergunb 0:8918a71cdbe9 758
Sergunb 0:8918a71cdbe9 759 //Filter out any invalid addresses
Sergunb 0:8918a71cdbe9 760 error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 761
Sergunb 0:8918a71cdbe9 762 //Multicast address?
Sergunb 0:8918a71cdbe9 763 if(ipv6IsMulticastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 764 {
Sergunb 0:8918a71cdbe9 765 //Go through the multicast filter table
Sergunb 0:8918a71cdbe9 766 for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 767 {
Sergunb 0:8918a71cdbe9 768 Ipv6FilterEntry *entry;
Sergunb 0:8918a71cdbe9 769
Sergunb 0:8918a71cdbe9 770 //Point to the current entry
Sergunb 0:8918a71cdbe9 771 entry = &interface->ipv6Context.multicastFilter[i];
Sergunb 0:8918a71cdbe9 772
Sergunb 0:8918a71cdbe9 773 //Valid entry?
Sergunb 0:8918a71cdbe9 774 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 775 {
Sergunb 0:8918a71cdbe9 776 //Check whether the destination IPv6 address matches
Sergunb 0:8918a71cdbe9 777 //a relevant multicast address
Sergunb 0:8918a71cdbe9 778 if(ipv6CompAddr(&entry->addr, ipAddr))
Sergunb 0:8918a71cdbe9 779 {
Sergunb 0:8918a71cdbe9 780 //The multicast address is acceptable
Sergunb 0:8918a71cdbe9 781 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 782 //Stop immediately
Sergunb 0:8918a71cdbe9 783 break;
Sergunb 0:8918a71cdbe9 784 }
Sergunb 0:8918a71cdbe9 785 }
Sergunb 0:8918a71cdbe9 786 }
Sergunb 0:8918a71cdbe9 787 }
Sergunb 0:8918a71cdbe9 788 //Unicast address?
Sergunb 0:8918a71cdbe9 789 else
Sergunb 0:8918a71cdbe9 790 {
Sergunb 0:8918a71cdbe9 791 //Loop through the list of IPv6 unicast addresses
Sergunb 0:8918a71cdbe9 792 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 793 {
Sergunb 0:8918a71cdbe9 794 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 795
Sergunb 0:8918a71cdbe9 796 //Point to the current entry
Sergunb 0:8918a71cdbe9 797 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 798
Sergunb 0:8918a71cdbe9 799 //Valid entry?
Sergunb 0:8918a71cdbe9 800 if(entry->state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 801 {
Sergunb 0:8918a71cdbe9 802 //Check whether the destination address matches a valid unicast
Sergunb 0:8918a71cdbe9 803 //address assigned to the interface
Sergunb 0:8918a71cdbe9 804 if(ipv6CompAddr(&entry->addr, ipAddr))
Sergunb 0:8918a71cdbe9 805 {
Sergunb 0:8918a71cdbe9 806 //The destination address is acceptable
Sergunb 0:8918a71cdbe9 807 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 808 //We are done
Sergunb 0:8918a71cdbe9 809 break;
Sergunb 0:8918a71cdbe9 810 }
Sergunb 0:8918a71cdbe9 811 }
Sergunb 0:8918a71cdbe9 812 }
Sergunb 0:8918a71cdbe9 813
Sergunb 0:8918a71cdbe9 814 //Check whether the specified is a valid unicast address
Sergunb 0:8918a71cdbe9 815 if(error == ERROR_INVALID_ADDRESS)
Sergunb 0:8918a71cdbe9 816 {
Sergunb 0:8918a71cdbe9 817 Ipv6Addr *anycastAddrList;
Sergunb 0:8918a71cdbe9 818
Sergunb 0:8918a71cdbe9 819 //Point to the list of anycast addresses assigned to the interface
Sergunb 0:8918a71cdbe9 820 anycastAddrList = interface->ipv6Context.anycastAddrList;
Sergunb 0:8918a71cdbe9 821
Sergunb 0:8918a71cdbe9 822 //Loop through the list of IPv6 anycast addresses
Sergunb 0:8918a71cdbe9 823 for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 824 {
Sergunb 0:8918a71cdbe9 825 //Valid entry?
Sergunb 0:8918a71cdbe9 826 if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 827 {
Sergunb 0:8918a71cdbe9 828 //Check whether the destination address matches a valid anycast
Sergunb 0:8918a71cdbe9 829 //address assigned to the interface
Sergunb 0:8918a71cdbe9 830 if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
Sergunb 0:8918a71cdbe9 831 {
Sergunb 0:8918a71cdbe9 832 //The destination address is acceptable
Sergunb 0:8918a71cdbe9 833 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 834 //We are done
Sergunb 0:8918a71cdbe9 835 break;
Sergunb 0:8918a71cdbe9 836 }
Sergunb 0:8918a71cdbe9 837 }
Sergunb 0:8918a71cdbe9 838 }
Sergunb 0:8918a71cdbe9 839 }
Sergunb 0:8918a71cdbe9 840 }
Sergunb 0:8918a71cdbe9 841
Sergunb 0:8918a71cdbe9 842 //Return status code
Sergunb 0:8918a71cdbe9 843 return error;
Sergunb 0:8918a71cdbe9 844 }
Sergunb 0:8918a71cdbe9 845
Sergunb 0:8918a71cdbe9 846
Sergunb 0:8918a71cdbe9 847 /**
Sergunb 0:8918a71cdbe9 848 * @brief IPv6 source address selection
Sergunb 0:8918a71cdbe9 849 *
Sergunb 0:8918a71cdbe9 850 * This function selects the source address and the relevant network interface
Sergunb 0:8918a71cdbe9 851 * to be used in order to join the specified destination address
Sergunb 0:8918a71cdbe9 852 *
Sergunb 0:8918a71cdbe9 853 * @param[in,out] interface A pointer to a valid network interface may be provided as
Sergunb 0:8918a71cdbe9 854 * a hint. The function returns a pointer identifying the interface to be used
Sergunb 0:8918a71cdbe9 855 * @param[in] destAddr Destination IPv6 address
Sergunb 0:8918a71cdbe9 856 * @param[out] srcAddr Local IPv6 address to be used
Sergunb 0:8918a71cdbe9 857 * @return Error code
Sergunb 0:8918a71cdbe9 858 **/
Sergunb 0:8918a71cdbe9 859
Sergunb 0:8918a71cdbe9 860 error_t ipv6SelectSourceAddr(NetInterface **interface,
Sergunb 0:8918a71cdbe9 861 const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
Sergunb 0:8918a71cdbe9 862 {
Sergunb 0:8918a71cdbe9 863 uint_t i;
Sergunb 0:8918a71cdbe9 864 uint_t j;
Sergunb 0:8918a71cdbe9 865 NetInterface *currentInterface;
Sergunb 0:8918a71cdbe9 866 NetInterface *bestInterface;
Sergunb 0:8918a71cdbe9 867 Ipv6AddrEntry *currentAddr;
Sergunb 0:8918a71cdbe9 868 Ipv6AddrEntry *bestAddr;
Sergunb 0:8918a71cdbe9 869
Sergunb 0:8918a71cdbe9 870 //Initialize variables
Sergunb 0:8918a71cdbe9 871 bestInterface = NULL;
Sergunb 0:8918a71cdbe9 872 bestAddr = NULL;
Sergunb 0:8918a71cdbe9 873
Sergunb 0:8918a71cdbe9 874 //Loop through network interfaces
Sergunb 0:8918a71cdbe9 875 for(i = 0; i < NET_INTERFACE_COUNT; i++)
Sergunb 0:8918a71cdbe9 876 {
Sergunb 0:8918a71cdbe9 877 //Point to the current interface
Sergunb 0:8918a71cdbe9 878 currentInterface = &netInterface[i];
Sergunb 0:8918a71cdbe9 879
Sergunb 0:8918a71cdbe9 880 //A network interface may be provided as a hint...
Sergunb 0:8918a71cdbe9 881 if(*interface != currentInterface && *interface != NULL)
Sergunb 0:8918a71cdbe9 882 {
Sergunb 0:8918a71cdbe9 883 //Select the next interface in the list
Sergunb 0:8918a71cdbe9 884 continue;
Sergunb 0:8918a71cdbe9 885 }
Sergunb 0:8918a71cdbe9 886
Sergunb 0:8918a71cdbe9 887 //A sort of the candidate source addresses is being performed, where a
Sergunb 0:8918a71cdbe9 888 //set of rules define the ordering among addresses (refer to RFC 6724)
Sergunb 0:8918a71cdbe9 889 for(j = 0; j < IPV6_ADDR_LIST_SIZE; j++)
Sergunb 0:8918a71cdbe9 890 {
Sergunb 0:8918a71cdbe9 891 //Point to the current entry
Sergunb 0:8918a71cdbe9 892 currentAddr = &currentInterface->ipv6Context.addrList[j];
Sergunb 0:8918a71cdbe9 893
Sergunb 0:8918a71cdbe9 894 //Check the state of the address
Sergunb 0:8918a71cdbe9 895 if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED ||
Sergunb 0:8918a71cdbe9 896 currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
Sergunb 0:8918a71cdbe9 897 {
Sergunb 0:8918a71cdbe9 898 //Select the first address as default
Sergunb 0:8918a71cdbe9 899 if(bestAddr == NULL)
Sergunb 0:8918a71cdbe9 900 {
Sergunb 0:8918a71cdbe9 901 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 902 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 903 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 904
Sergunb 0:8918a71cdbe9 905 //Select the next address in the list
Sergunb 0:8918a71cdbe9 906 continue;
Sergunb 0:8918a71cdbe9 907 }
Sergunb 0:8918a71cdbe9 908
Sergunb 0:8918a71cdbe9 909 //Rule 1: Prefer same address
Sergunb 0:8918a71cdbe9 910 if(ipv6CompAddr(&bestAddr->addr, destAddr))
Sergunb 0:8918a71cdbe9 911 {
Sergunb 0:8918a71cdbe9 912 //Select the next address in the list
Sergunb 0:8918a71cdbe9 913 continue;
Sergunb 0:8918a71cdbe9 914 }
Sergunb 0:8918a71cdbe9 915 else if(ipv6CompAddr(&currentAddr->addr, destAddr))
Sergunb 0:8918a71cdbe9 916 {
Sergunb 0:8918a71cdbe9 917 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 918 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 919 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 920
Sergunb 0:8918a71cdbe9 921 //Select the next address in the list
Sergunb 0:8918a71cdbe9 922 continue;
Sergunb 0:8918a71cdbe9 923 }
Sergunb 0:8918a71cdbe9 924
Sergunb 0:8918a71cdbe9 925 //Rule 2: Prefer appropriate scope
Sergunb 0:8918a71cdbe9 926 if(ipv6GetAddrScope(&currentAddr->addr) < ipv6GetAddrScope(&bestAddr->addr))
Sergunb 0:8918a71cdbe9 927 {
Sergunb 0:8918a71cdbe9 928 if(ipv6GetAddrScope(&currentAddr->addr) >= ipv6GetAddrScope(destAddr))
Sergunb 0:8918a71cdbe9 929 {
Sergunb 0:8918a71cdbe9 930 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 931 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 932 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 933 }
Sergunb 0:8918a71cdbe9 934
Sergunb 0:8918a71cdbe9 935 //Select the next address in the list
Sergunb 0:8918a71cdbe9 936 continue;
Sergunb 0:8918a71cdbe9 937 }
Sergunb 0:8918a71cdbe9 938 else if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(&currentAddr->addr))
Sergunb 0:8918a71cdbe9 939 {
Sergunb 0:8918a71cdbe9 940 if(ipv6GetAddrScope(&bestAddr->addr) < ipv6GetAddrScope(destAddr))
Sergunb 0:8918a71cdbe9 941 {
Sergunb 0:8918a71cdbe9 942 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 943 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 944 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 945 }
Sergunb 0:8918a71cdbe9 946
Sergunb 0:8918a71cdbe9 947 //Select the next address in the list
Sergunb 0:8918a71cdbe9 948 continue;
Sergunb 0:8918a71cdbe9 949 }
Sergunb 0:8918a71cdbe9 950
Sergunb 0:8918a71cdbe9 951 //Rule 3: Avoid deprecated addresses
Sergunb 0:8918a71cdbe9 952 if(bestAddr->state == IPV6_ADDR_STATE_PREFERRED &&
Sergunb 0:8918a71cdbe9 953 currentAddr->state == IPV6_ADDR_STATE_DEPRECATED)
Sergunb 0:8918a71cdbe9 954 {
Sergunb 0:8918a71cdbe9 955 //Select the next address in the list
Sergunb 0:8918a71cdbe9 956 continue;
Sergunb 0:8918a71cdbe9 957 }
Sergunb 0:8918a71cdbe9 958 else if(currentAddr->state == IPV6_ADDR_STATE_PREFERRED &&
Sergunb 0:8918a71cdbe9 959 bestAddr->state == IPV6_ADDR_STATE_DEPRECATED)
Sergunb 0:8918a71cdbe9 960 {
Sergunb 0:8918a71cdbe9 961 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 962 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 963 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 964
Sergunb 0:8918a71cdbe9 965 //Select the next address in the list
Sergunb 0:8918a71cdbe9 966 continue;
Sergunb 0:8918a71cdbe9 967 }
Sergunb 0:8918a71cdbe9 968
Sergunb 0:8918a71cdbe9 969 //Rule 8: Use longest matching prefix
Sergunb 0:8918a71cdbe9 970 if(ipv6GetCommonPrefixLength(&currentAddr->addr, destAddr) >
Sergunb 0:8918a71cdbe9 971 ipv6GetCommonPrefixLength(&bestAddr->addr, destAddr))
Sergunb 0:8918a71cdbe9 972 {
Sergunb 0:8918a71cdbe9 973 //Give the current source address the higher precedence
Sergunb 0:8918a71cdbe9 974 bestInterface = currentInterface;
Sergunb 0:8918a71cdbe9 975 bestAddr = currentAddr;
Sergunb 0:8918a71cdbe9 976 }
Sergunb 0:8918a71cdbe9 977 }
Sergunb 0:8918a71cdbe9 978 }
Sergunb 0:8918a71cdbe9 979 }
Sergunb 0:8918a71cdbe9 980
Sergunb 0:8918a71cdbe9 981 //Source address selection failed?
Sergunb 0:8918a71cdbe9 982 if(bestAddr == NULL)
Sergunb 0:8918a71cdbe9 983 {
Sergunb 0:8918a71cdbe9 984 //Report an error
Sergunb 0:8918a71cdbe9 985 return ERROR_NO_ADDRESS;
Sergunb 0:8918a71cdbe9 986 }
Sergunb 0:8918a71cdbe9 987
Sergunb 0:8918a71cdbe9 988 //Return the out-going interface and the source address to be used
Sergunb 0:8918a71cdbe9 989 *interface = bestInterface;
Sergunb 0:8918a71cdbe9 990 *srcAddr = bestAddr->addr;
Sergunb 0:8918a71cdbe9 991
Sergunb 0:8918a71cdbe9 992 //Successful source address selection
Sergunb 0:8918a71cdbe9 993 return NO_ERROR;
Sergunb 0:8918a71cdbe9 994 }
Sergunb 0:8918a71cdbe9 995
Sergunb 0:8918a71cdbe9 996
Sergunb 0:8918a71cdbe9 997 /**
Sergunb 0:8918a71cdbe9 998 * @brief Check whether an IPv6 address is on-link
Sergunb 0:8918a71cdbe9 999 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1000 * @param[in] ipAddr IPv6 address to be checked
Sergunb 0:8918a71cdbe9 1001 * @return TRUE if the IPv6 address is on-link, else FALSE
Sergunb 0:8918a71cdbe9 1002 **/
Sergunb 0:8918a71cdbe9 1003
Sergunb 0:8918a71cdbe9 1004 bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1005 {
Sergunb 0:8918a71cdbe9 1006 uint_t i;
Sergunb 0:8918a71cdbe9 1007 Ipv6PrefixEntry *entry;
Sergunb 0:8918a71cdbe9 1008
Sergunb 0:8918a71cdbe9 1009 //Link-local prefix?
Sergunb 0:8918a71cdbe9 1010 if(ipv6IsLinkLocalUnicastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1011 {
Sergunb 0:8918a71cdbe9 1012 //The link-local prefix is considered to be on the prefix
Sergunb 0:8918a71cdbe9 1013 //list with an infinite invalidation timer regardless of
Sergunb 0:8918a71cdbe9 1014 //whether routers are advertising a prefix for it
Sergunb 0:8918a71cdbe9 1015 return TRUE;
Sergunb 0:8918a71cdbe9 1016 }
Sergunb 0:8918a71cdbe9 1017
Sergunb 0:8918a71cdbe9 1018 //Loop through the Prefix List
Sergunb 0:8918a71cdbe9 1019 for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 1020 {
Sergunb 0:8918a71cdbe9 1021 //Point to the current entry
Sergunb 0:8918a71cdbe9 1022 entry = &interface->ipv6Context.prefixList[i];
Sergunb 0:8918a71cdbe9 1023
Sergunb 0:8918a71cdbe9 1024 //Valid prefix?
Sergunb 0:8918a71cdbe9 1025 if(entry->validLifetime > 0)
Sergunb 0:8918a71cdbe9 1026 {
Sergunb 0:8918a71cdbe9 1027 //Check the specified address against the prefix
Sergunb 0:8918a71cdbe9 1028 if(ipv6CompPrefix(ipAddr, &entry->prefix, entry->prefixLength))
Sergunb 0:8918a71cdbe9 1029 {
Sergunb 0:8918a71cdbe9 1030 //The specified IPv6 address is on-link
Sergunb 0:8918a71cdbe9 1031 return TRUE;
Sergunb 0:8918a71cdbe9 1032 }
Sergunb 0:8918a71cdbe9 1033 }
Sergunb 0:8918a71cdbe9 1034 }
Sergunb 0:8918a71cdbe9 1035
Sergunb 0:8918a71cdbe9 1036 //The specified IPv6 address is off-link
Sergunb 0:8918a71cdbe9 1037 return FALSE;
Sergunb 0:8918a71cdbe9 1038 }
Sergunb 0:8918a71cdbe9 1039
Sergunb 0:8918a71cdbe9 1040
Sergunb 0:8918a71cdbe9 1041 /**
Sergunb 0:8918a71cdbe9 1042 * @brief Check whether an IPv6 address is a tentative address
Sergunb 0:8918a71cdbe9 1043 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1044 * @param[in] ipAddr IPv6 address to be checked
Sergunb 0:8918a71cdbe9 1045 * @return TRUE if the IPv6 address is a tentative address, else FALSE
Sergunb 0:8918a71cdbe9 1046 **/
Sergunb 0:8918a71cdbe9 1047
Sergunb 0:8918a71cdbe9 1048 bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1049 {
Sergunb 0:8918a71cdbe9 1050 uint_t i;
Sergunb 0:8918a71cdbe9 1051 Ipv6AddrEntry *entry;
Sergunb 0:8918a71cdbe9 1052
Sergunb 0:8918a71cdbe9 1053 //Loop through the list of IPv6 unicast addresses
Sergunb 0:8918a71cdbe9 1054 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 1055 {
Sergunb 0:8918a71cdbe9 1056 //Point to the current entry
Sergunb 0:8918a71cdbe9 1057 entry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 1058
Sergunb 0:8918a71cdbe9 1059 //Tentative address?
Sergunb 0:8918a71cdbe9 1060 if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
Sergunb 0:8918a71cdbe9 1061 {
Sergunb 0:8918a71cdbe9 1062 //Check whether the specified address matches a valid unicast
Sergunb 0:8918a71cdbe9 1063 //address assigned to the interface
Sergunb 0:8918a71cdbe9 1064 if(ipv6CompAddr(&entry->addr, ipAddr))
Sergunb 0:8918a71cdbe9 1065 {
Sergunb 0:8918a71cdbe9 1066 //The specified IPv6 address is a tentative address
Sergunb 0:8918a71cdbe9 1067 return TRUE;
Sergunb 0:8918a71cdbe9 1068 }
Sergunb 0:8918a71cdbe9 1069 }
Sergunb 0:8918a71cdbe9 1070 }
Sergunb 0:8918a71cdbe9 1071
Sergunb 0:8918a71cdbe9 1072 //The specified IPv6 address is not a tentative address
Sergunb 0:8918a71cdbe9 1073 return FALSE;
Sergunb 0:8918a71cdbe9 1074 }
Sergunb 0:8918a71cdbe9 1075
Sergunb 0:8918a71cdbe9 1076
Sergunb 0:8918a71cdbe9 1077 /**
Sergunb 0:8918a71cdbe9 1078 * @brief Check whether an IPv6 address is an anycast address
Sergunb 0:8918a71cdbe9 1079 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1080 * @param[in] ipAddr IPv6 address to be checked
Sergunb 0:8918a71cdbe9 1081 * @return TRUE if the IPv6 address is an anycast address, else FALSE
Sergunb 0:8918a71cdbe9 1082 **/
Sergunb 0:8918a71cdbe9 1083
Sergunb 0:8918a71cdbe9 1084 bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1085 {
Sergunb 0:8918a71cdbe9 1086 uint_t i;
Sergunb 0:8918a71cdbe9 1087 Ipv6Addr *anycastAddrList;
Sergunb 0:8918a71cdbe9 1088
Sergunb 0:8918a71cdbe9 1089 //Point to the list of anycast addresses assigned to the interface
Sergunb 0:8918a71cdbe9 1090 anycastAddrList = interface->ipv6Context.anycastAddrList;
Sergunb 0:8918a71cdbe9 1091
Sergunb 0:8918a71cdbe9 1092 //Loop through the list of IPv6 anycast addresses
Sergunb 0:8918a71cdbe9 1093 for(i = 0; i < IPV6_ANYCAST_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 1094 {
Sergunb 0:8918a71cdbe9 1095 //Valid entry?
Sergunb 0:8918a71cdbe9 1096 if(!ipv6CompAddr(&anycastAddrList[i], &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1097 {
Sergunb 0:8918a71cdbe9 1098 //Check whether the specified address matches a valid anycast
Sergunb 0:8918a71cdbe9 1099 //address assigned to the interface
Sergunb 0:8918a71cdbe9 1100 if(ipv6CompAddr(&anycastAddrList[i], ipAddr))
Sergunb 0:8918a71cdbe9 1101 {
Sergunb 0:8918a71cdbe9 1102 //The specified IPv6 address is an anycast address
Sergunb 0:8918a71cdbe9 1103 return TRUE;
Sergunb 0:8918a71cdbe9 1104 }
Sergunb 0:8918a71cdbe9 1105 }
Sergunb 0:8918a71cdbe9 1106 }
Sergunb 0:8918a71cdbe9 1107
Sergunb 0:8918a71cdbe9 1108 //The specified IPv6 address is not an anycast address
Sergunb 0:8918a71cdbe9 1109 return FALSE;
Sergunb 0:8918a71cdbe9 1110 }
Sergunb 0:8918a71cdbe9 1111
Sergunb 0:8918a71cdbe9 1112
Sergunb 0:8918a71cdbe9 1113 /**
Sergunb 0:8918a71cdbe9 1114 * @brief Compare IPv6 address prefixes
Sergunb 0:8918a71cdbe9 1115 * @param[in] ipAddr1 Pointer to the first IPv6 address
Sergunb 0:8918a71cdbe9 1116 * @param[in] ipAddr2 Pointer to the second IPv6 address
Sergunb 0:8918a71cdbe9 1117 * @param[in] length Prefix length
Sergunb 0:8918a71cdbe9 1118 * @return TRUE if the prefixes match each other, else FALSE
Sergunb 0:8918a71cdbe9 1119 **/
Sergunb 0:8918a71cdbe9 1120
Sergunb 0:8918a71cdbe9 1121 bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Sergunb 0:8918a71cdbe9 1122 {
Sergunb 0:8918a71cdbe9 1123 size_t n = length / 8;
Sergunb 0:8918a71cdbe9 1124 size_t m = length % 8;
Sergunb 0:8918a71cdbe9 1125
Sergunb 0:8918a71cdbe9 1126 //Ensure the prefix length is valid
Sergunb 0:8918a71cdbe9 1127 if(length > 128)
Sergunb 0:8918a71cdbe9 1128 return FALSE;
Sergunb 0:8918a71cdbe9 1129
Sergunb 0:8918a71cdbe9 1130 //Compare the first part
Sergunb 0:8918a71cdbe9 1131 if(n > 0)
Sergunb 0:8918a71cdbe9 1132 {
Sergunb 0:8918a71cdbe9 1133 if(memcmp(ipAddr1, ipAddr2, n))
Sergunb 0:8918a71cdbe9 1134 return FALSE;
Sergunb 0:8918a71cdbe9 1135 }
Sergunb 0:8918a71cdbe9 1136
Sergunb 0:8918a71cdbe9 1137 //Compare the remaining bits, if any
Sergunb 0:8918a71cdbe9 1138 if(m > 0)
Sergunb 0:8918a71cdbe9 1139 {
Sergunb 0:8918a71cdbe9 1140 //Calculate the mask to be applied
Sergunb 0:8918a71cdbe9 1141 uint8_t mask = ((1 << m) - 1) << (8 - m);
Sergunb 0:8918a71cdbe9 1142
Sergunb 0:8918a71cdbe9 1143 //Check remaining bits
Sergunb 0:8918a71cdbe9 1144 if((ipAddr1->b[n] & mask) != (ipAddr2->b[n] & mask))
Sergunb 0:8918a71cdbe9 1145 return FALSE;
Sergunb 0:8918a71cdbe9 1146 }
Sergunb 0:8918a71cdbe9 1147
Sergunb 0:8918a71cdbe9 1148 //The prefixes match each other
Sergunb 0:8918a71cdbe9 1149 return TRUE;
Sergunb 0:8918a71cdbe9 1150 }
Sergunb 0:8918a71cdbe9 1151
Sergunb 0:8918a71cdbe9 1152
Sergunb 0:8918a71cdbe9 1153 /**
Sergunb 0:8918a71cdbe9 1154 * @brief Retrieve the scope of an IPv6 address
Sergunb 0:8918a71cdbe9 1155 * @param[in] ipAddr Pointer to an IPv6 address
Sergunb 0:8918a71cdbe9 1156 * @return IPv6 address scope
Sergunb 0:8918a71cdbe9 1157 **/
Sergunb 0:8918a71cdbe9 1158
Sergunb 0:8918a71cdbe9 1159 uint_t ipv6GetAddrScope(const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1160 {
Sergunb 0:8918a71cdbe9 1161 uint_t scope;
Sergunb 0:8918a71cdbe9 1162
Sergunb 0:8918a71cdbe9 1163 //Multicast address?
Sergunb 0:8918a71cdbe9 1164 if(ipv6IsMulticastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1165 {
Sergunb 0:8918a71cdbe9 1166 //Retrieve the scope of the multicast address
Sergunb 0:8918a71cdbe9 1167 scope = ipv6GetMulticastAddrScope(ipAddr);
Sergunb 0:8918a71cdbe9 1168 }
Sergunb 0:8918a71cdbe9 1169 //Loopback address?
Sergunb 0:8918a71cdbe9 1170 else if(ipv6CompAddr(ipAddr, &IPV6_LOOPBACK_ADDR))
Sergunb 0:8918a71cdbe9 1171 {
Sergunb 0:8918a71cdbe9 1172 //The loopback address may be used by a node to send an IPv6 packet to itself
Sergunb 0:8918a71cdbe9 1173 scope = IPV6_ADDR_SCOPE_INTERFACE_LOCAL;
Sergunb 0:8918a71cdbe9 1174 }
Sergunb 0:8918a71cdbe9 1175 //Link-local unicast address?
Sergunb 0:8918a71cdbe9 1176 else if(ipv6IsLinkLocalUnicastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1177 {
Sergunb 0:8918a71cdbe9 1178 //A link-local address is for use on a single link
Sergunb 0:8918a71cdbe9 1179 scope = IPV6_ADDR_SCOPE_LINK_LOCAL;
Sergunb 0:8918a71cdbe9 1180 }
Sergunb 0:8918a71cdbe9 1181 //Site-local unicast address?
Sergunb 0:8918a71cdbe9 1182 else if(ipv6IsSiteLocalUnicastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1183 {
Sergunb 0:8918a71cdbe9 1184 //A site-local address is for use in a single site
Sergunb 0:8918a71cdbe9 1185 scope = IPV6_ADDR_SCOPE_SITE_LOCAL;
Sergunb 0:8918a71cdbe9 1186 }
Sergunb 0:8918a71cdbe9 1187 //Global address?
Sergunb 0:8918a71cdbe9 1188 else
Sergunb 0:8918a71cdbe9 1189 {
Sergunb 0:8918a71cdbe9 1190 //Global scope
Sergunb 0:8918a71cdbe9 1191 scope = IPV6_ADDR_SCOPE_GLOBAL;
Sergunb 0:8918a71cdbe9 1192 }
Sergunb 0:8918a71cdbe9 1193
Sergunb 0:8918a71cdbe9 1194 //Return the scope of the specified IPv6 address
Sergunb 0:8918a71cdbe9 1195 return scope;
Sergunb 0:8918a71cdbe9 1196 }
Sergunb 0:8918a71cdbe9 1197
Sergunb 0:8918a71cdbe9 1198
Sergunb 0:8918a71cdbe9 1199 /**
Sergunb 0:8918a71cdbe9 1200 * @brief Retrieve the scope of an IPv6 multicast address
Sergunb 0:8918a71cdbe9 1201 * @param[in] ipAddr Pointer to an IPv6 multicast address
Sergunb 0:8918a71cdbe9 1202 * @return IPv6 address scope
Sergunb 0:8918a71cdbe9 1203 **/
Sergunb 0:8918a71cdbe9 1204
Sergunb 0:8918a71cdbe9 1205 uint_t ipv6GetMulticastAddrScope(const Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1206 {
Sergunb 0:8918a71cdbe9 1207 uint_t scope;
Sergunb 0:8918a71cdbe9 1208
Sergunb 0:8918a71cdbe9 1209 //The scope field is a 4-bit value
Sergunb 0:8918a71cdbe9 1210 scope = ipAddr->b[1] & 0x0F;
Sergunb 0:8918a71cdbe9 1211
Sergunb 0:8918a71cdbe9 1212 //If the scope field contains the reserved value F, an IPv6 packet
Sergunb 0:8918a71cdbe9 1213 //must be treated the same as packets destined to a global multicast
Sergunb 0:8918a71cdbe9 1214 //address (refer to RFC 3513 section 2.7)
Sergunb 0:8918a71cdbe9 1215 if(scope == 0x0F)
Sergunb 0:8918a71cdbe9 1216 scope = IPV6_ADDR_SCOPE_GLOBAL;
Sergunb 0:8918a71cdbe9 1217
Sergunb 0:8918a71cdbe9 1218 //Return the scope of the specified IPv6 multicast address
Sergunb 0:8918a71cdbe9 1219 return scope;
Sergunb 0:8918a71cdbe9 1220 }
Sergunb 0:8918a71cdbe9 1221
Sergunb 0:8918a71cdbe9 1222
Sergunb 0:8918a71cdbe9 1223 /**
Sergunb 0:8918a71cdbe9 1224 * @brief Compute the length of the longest common prefix
Sergunb 0:8918a71cdbe9 1225 * @param[in] ipAddr1 Pointer to the first IPv6 address
Sergunb 0:8918a71cdbe9 1226 * @param[in] ipAddr2 Pointer to the second IPv6 address
Sergunb 0:8918a71cdbe9 1227 * @return The length of the longest common prefix, in bits
Sergunb 0:8918a71cdbe9 1228 **/
Sergunb 0:8918a71cdbe9 1229
Sergunb 0:8918a71cdbe9 1230 uint_t ipv6GetCommonPrefixLength(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2)
Sergunb 0:8918a71cdbe9 1231 {
Sergunb 0:8918a71cdbe9 1232 uint_t i;
Sergunb 0:8918a71cdbe9 1233 uint_t j;
Sergunb 0:8918a71cdbe9 1234
Sergunb 0:8918a71cdbe9 1235 //Clear bit counter
Sergunb 0:8918a71cdbe9 1236 j = 0;
Sergunb 0:8918a71cdbe9 1237
Sergunb 0:8918a71cdbe9 1238 //Perform a byte-for-byte comparison
Sergunb 0:8918a71cdbe9 1239 for(i = 0; i < sizeof(Ipv6Addr); i++)
Sergunb 0:8918a71cdbe9 1240 {
Sergunb 0:8918a71cdbe9 1241 //Loop as long as prefixes match
Sergunb 0:8918a71cdbe9 1242 if(ipAddr1->b[i] != ipAddr2->b[i])
Sergunb 0:8918a71cdbe9 1243 break;
Sergunb 0:8918a71cdbe9 1244 }
Sergunb 0:8918a71cdbe9 1245
Sergunb 0:8918a71cdbe9 1246 //Mismatch?
Sergunb 0:8918a71cdbe9 1247 if(i < sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 1248 {
Sergunb 0:8918a71cdbe9 1249 //Perform a bit-for-bit comparison
Sergunb 0:8918a71cdbe9 1250 for(j = 0; j < 8; j++)
Sergunb 0:8918a71cdbe9 1251 {
Sergunb 0:8918a71cdbe9 1252 //Calculate the mask to be applied
Sergunb 0:8918a71cdbe9 1253 uint8_t mask = 1 << (7 - j);
Sergunb 0:8918a71cdbe9 1254
Sergunb 0:8918a71cdbe9 1255 //Loop as long as prefixes match
Sergunb 0:8918a71cdbe9 1256 if((ipAddr1->b[i] & mask) != (ipAddr2->b[i] & mask))
Sergunb 0:8918a71cdbe9 1257 break;
Sergunb 0:8918a71cdbe9 1258 }
Sergunb 0:8918a71cdbe9 1259 }
Sergunb 0:8918a71cdbe9 1260
Sergunb 0:8918a71cdbe9 1261 //Return the length of the longest common prefix, in bits
Sergunb 0:8918a71cdbe9 1262 return i * 8 + j;
Sergunb 0:8918a71cdbe9 1263 }
Sergunb 0:8918a71cdbe9 1264
Sergunb 0:8918a71cdbe9 1265
Sergunb 0:8918a71cdbe9 1266 /**
Sergunb 0:8918a71cdbe9 1267 * @brief Form a solicited-node address from an IPv6 address
Sergunb 0:8918a71cdbe9 1268 * @param[in] ipAddr Unicast or anycast address
Sergunb 0:8918a71cdbe9 1269 * @param[out] solicitedNodeAddr Corresponding solicited-node address
Sergunb 0:8918a71cdbe9 1270 * @return Error code
Sergunb 0:8918a71cdbe9 1271 **/
Sergunb 0:8918a71cdbe9 1272
Sergunb 0:8918a71cdbe9 1273 error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr,
Sergunb 0:8918a71cdbe9 1274 Ipv6Addr *solicitedNodeAddr)
Sergunb 0:8918a71cdbe9 1275 {
Sergunb 0:8918a71cdbe9 1276 //Ensure the specified address is a valid unicast or anycast address
Sergunb 0:8918a71cdbe9 1277 if(ipv6IsMulticastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1278 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 1279
Sergunb 0:8918a71cdbe9 1280 //Copy the 104-bit prefix
Sergunb 0:8918a71cdbe9 1281 ipv6CopyAddr(solicitedNodeAddr, &IPV6_SOLICITED_NODE_ADDR_PREFIX);
Sergunb 0:8918a71cdbe9 1282
Sergunb 0:8918a71cdbe9 1283 //Take the low-order 24 bits of the address (unicast or
Sergunb 0:8918a71cdbe9 1284 //anycast) and append those bits to the prefix
Sergunb 0:8918a71cdbe9 1285 solicitedNodeAddr->b[13] = ipAddr->b[13];
Sergunb 0:8918a71cdbe9 1286 solicitedNodeAddr->b[14] = ipAddr->b[14];
Sergunb 0:8918a71cdbe9 1287 solicitedNodeAddr->b[15] = ipAddr->b[15];
Sergunb 0:8918a71cdbe9 1288
Sergunb 0:8918a71cdbe9 1289 //No error to report
Sergunb 0:8918a71cdbe9 1290 return NO_ERROR;
Sergunb 0:8918a71cdbe9 1291 }
Sergunb 0:8918a71cdbe9 1292
Sergunb 0:8918a71cdbe9 1293
Sergunb 0:8918a71cdbe9 1294 /**
Sergunb 0:8918a71cdbe9 1295 * @brief Map an IPv6 multicast address to a MAC-layer multicast address
Sergunb 0:8918a71cdbe9 1296 * @param[in] ipAddr IPv6 multicast address
Sergunb 0:8918a71cdbe9 1297 * @param[out] macAddr Corresponding MAC-layer multicast address
Sergunb 0:8918a71cdbe9 1298 * @return Error code
Sergunb 0:8918a71cdbe9 1299 **/
Sergunb 0:8918a71cdbe9 1300
Sergunb 0:8918a71cdbe9 1301 error_t ipv6MapMulticastAddrToMac(const Ipv6Addr *ipAddr, MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 1302 {
Sergunb 0:8918a71cdbe9 1303 //Ensure the specified IPv6 address is a multicast address
Sergunb 0:8918a71cdbe9 1304 if(!ipv6IsMulticastAddr(ipAddr))
Sergunb 0:8918a71cdbe9 1305 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 1306
Sergunb 0:8918a71cdbe9 1307 //To support IPv6 multicasting, MAC address range of 33-33-00-00-00-00
Sergunb 0:8918a71cdbe9 1308 //to 33-33-FF-FF-FF-FF is reserved (refer to RFC 2464)
Sergunb 0:8918a71cdbe9 1309 macAddr->b[0] = 0x33;
Sergunb 0:8918a71cdbe9 1310 macAddr->b[1] = 0x33;
Sergunb 0:8918a71cdbe9 1311
Sergunb 0:8918a71cdbe9 1312 //The low-order 32 bits of the IPv6 multicast address are mapped directly
Sergunb 0:8918a71cdbe9 1313 //to the low-order 32 bits in the MAC-layer multicast address
Sergunb 0:8918a71cdbe9 1314 macAddr->b[2] = ipAddr->b[12];
Sergunb 0:8918a71cdbe9 1315 macAddr->b[3] = ipAddr->b[13];
Sergunb 0:8918a71cdbe9 1316 macAddr->b[4] = ipAddr->b[14];
Sergunb 0:8918a71cdbe9 1317 macAddr->b[5] = ipAddr->b[15];
Sergunb 0:8918a71cdbe9 1318
Sergunb 0:8918a71cdbe9 1319 //The specified IPv6 multicast address was successfully
Sergunb 0:8918a71cdbe9 1320 //mapped to a MAC-layer address
Sergunb 0:8918a71cdbe9 1321 return NO_ERROR;
Sergunb 0:8918a71cdbe9 1322 }
Sergunb 0:8918a71cdbe9 1323
Sergunb 0:8918a71cdbe9 1324
Sergunb 0:8918a71cdbe9 1325 /**
Sergunb 0:8918a71cdbe9 1326 * @brief Generate a IPv6 link-local address from an interface identifier
Sergunb 0:8918a71cdbe9 1327 * @param[in] interfaceId Interface identifier
Sergunb 0:8918a71cdbe9 1328 * @param[out] ipAddr Corresponding IPv6 link-local address
Sergunb 0:8918a71cdbe9 1329 **/
Sergunb 0:8918a71cdbe9 1330
Sergunb 0:8918a71cdbe9 1331 void ipv6GenerateLinkLocalAddr(const Eui64* interfaceId, Ipv6Addr *ipAddr)
Sergunb 0:8918a71cdbe9 1332 {
Sergunb 0:8918a71cdbe9 1333 //A link-local address is formed by combining the well-known
Sergunb 0:8918a71cdbe9 1334 //link-local prefix fe80::/10 with the interface identifier
Sergunb 0:8918a71cdbe9 1335 ipAddr->w[0] = HTONS(0xFE80);
Sergunb 0:8918a71cdbe9 1336 ipAddr->w[1] = HTONS(0x0000);
Sergunb 0:8918a71cdbe9 1337 ipAddr->w[2] = HTONS(0x0000);
Sergunb 0:8918a71cdbe9 1338 ipAddr->w[3] = HTONS(0x0000);
Sergunb 0:8918a71cdbe9 1339 ipAddr->w[4] = interfaceId->w[0];
Sergunb 0:8918a71cdbe9 1340 ipAddr->w[5] = interfaceId->w[1];
Sergunb 0:8918a71cdbe9 1341 ipAddr->w[6] = interfaceId->w[2];
Sergunb 0:8918a71cdbe9 1342 ipAddr->w[7] = interfaceId->w[3];
Sergunb 0:8918a71cdbe9 1343 }
Sergunb 0:8918a71cdbe9 1344
Sergunb 0:8918a71cdbe9 1345 #endif
Sergunb 0:8918a71cdbe9 1346