Webserver+3d print
cyclone_tcp/ipv6/ipv6_misc.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
User | Revision | Line number | New 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 = ¤tInterface->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(¤tAddr->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(¤tAddr->addr) < ipv6GetAddrScope(&bestAddr->addr)) |
Sergunb | 0:8918a71cdbe9 | 927 | { |
Sergunb | 0:8918a71cdbe9 | 928 | if(ipv6GetAddrScope(¤tAddr->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(¤tAddr->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(¤tAddr->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 |