Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ipv6.c
00001 /** 00002 * @file ipv6.c 00003 * @brief IPv6 (Internet Protocol Version 6) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * IP version 6 (IPv6) is a new version of the Internet Protocol, designed 00028 * as the successor to IP version 4 (IPv4). Refer to RFC 2460 00029 * 00030 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00031 * @version 1.7.6 00032 **/ 00033 00034 //Switch to the appropriate trace level 00035 #define TRACE_LEVEL IPV6_TRACE_LEVEL 00036 00037 //Dependencies 00038 #include <string.h> 00039 #include <ctype.h> 00040 #include "core/net.h" 00041 #include "ipv6/ipv6.h" 00042 #include "ipv6/ipv6_frag.h" 00043 #include "ipv6/ipv6_misc.h" 00044 #include "ipv6/ipv6_pmtu.h" 00045 #include "ipv6/ipv6_routing.h" 00046 #include "ipv6/icmpv6.h" 00047 #include "ipv6/mld.h" 00048 #include "ipv6/ndp.h" 00049 #include "ipv6/ndp_cache.h" 00050 #include "ipv6/ndp_misc.h" 00051 #include "ipv6/ndp_router_adv.h" 00052 #include "ipv6/slaac.h" 00053 #include "dhcpv6/dhcpv6_client.h" 00054 #include "core/udp.h" 00055 #include "core/tcp_fsm.h" 00056 #include "core/raw_socket.h" 00057 #include "debug.h" 00058 00059 //Check TCP/IP stack configuration 00060 #if (IPV6_SUPPORT == ENABLED) 00061 00062 //Unspecified IPv6 address 00063 const Ipv6Addr IPV6_UNSPECIFIED_ADDR = 00064 IPV6_ADDR(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); 00065 00066 //Loopback IPv6 address 00067 const Ipv6Addr IPV6_LOOPBACK_ADDR = 00068 IPV6_ADDR(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001); 00069 00070 //Link-local All-Nodes IPv6 address 00071 const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR = 00072 IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001); 00073 00074 //Link-local All-Routers IPv6 address 00075 const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR = 00076 IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002); 00077 00078 //Link-local IPv6 address prefix 00079 const Ipv6Addr IPV6_LINK_LOCAL_ADDR_PREFIX = 00080 IPV6_ADDR(0xFE80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); 00081 00082 //Solicited-node IPv6 address prefix 00083 const Ipv6Addr IPV6_SOLICITED_NODE_ADDR_PREFIX = 00084 IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xFF00, 0x0000); 00085 00086 00087 /** 00088 * @brief IPv6 related initialization 00089 * @param[in] interface Underlying network interface 00090 * @return Error code 00091 **/ 00092 00093 error_t ipv6Init(NetInterface *interface) 00094 { 00095 Ipv6Context *context; 00096 00097 //Point to the IPv6 context 00098 context = &interface->ipv6Context; 00099 00100 //Clear the IPv6 context 00101 memset(context, 0, sizeof(Ipv6Context)); 00102 00103 //Initialize interface specific variables 00104 context->linkMtu = interface->nicDriver->mtu; 00105 context->isRouter = FALSE; 00106 context->curHopLimit = IPV6_DEFAULT_HOP_LIMIT; 00107 00108 //Multicast ICMPv6 Echo Request messages are allowed by default 00109 context->enableMulticastEchoReq = TRUE; 00110 00111 //Initialize the list of IPv6 addresses assigned to the interface 00112 memset(context->addrList, 0, sizeof(context->addrList)); 00113 //Initialize the Prefix List 00114 memset(context->prefixList, 0, sizeof(context->prefixList)); 00115 //Initialize the Default Router List 00116 memset(context->routerList, 0, sizeof(context->routerList)); 00117 //Initialize the list of DNS servers 00118 memset(context->dnsServerList, 0, sizeof(context->dnsServerList)); 00119 //Initialize the multicast filter table 00120 memset(context->multicastFilter, 0, sizeof(context->multicastFilter)); 00121 00122 #if (IPV6_FRAG_SUPPORT == ENABLED) 00123 //Identification field is used to identify fragments of an original IP datagram 00124 context->identification = 0; 00125 //Initialize the reassembly queue 00126 memset(context->fragQueue, 0, sizeof(context->fragQueue)); 00127 #endif 00128 00129 //Successful initialization 00130 return NO_ERROR; 00131 } 00132 00133 00134 /** 00135 * @brief Change the MTU of a network interface 00136 * @param[in] interface Pointer to the desired network interface 00137 * @param[in] mtu Maximum transmit unit 00138 * @return Error code 00139 **/ 00140 00141 error_t ipv6SetMtu(NetInterface *interface, size_t mtu) 00142 { 00143 error_t error; 00144 00145 //Check parameters 00146 if(interface == NULL) 00147 return ERROR_INVALID_PARAMETER; 00148 00149 //Get exclusive access 00150 osAcquireMutex(&netMutex); 00151 00152 //Make sure the specified MTU is greater than or equal to the minimum 00153 //IPv6 MTU and does not exceed the maximum MTU of the interface 00154 if(mtu >= IPV6_DEFAULT_MTU && mtu <= interface->nicDriver->mtu) 00155 { 00156 //Set the MTU to be used 00157 interface->ipv6Context.linkMtu = mtu; 00158 //Successful processing 00159 error = NO_ERROR; 00160 } 00161 else 00162 { 00163 //The specified MTU is not valid 00164 error = ERROR_OUT_OF_RANGE; 00165 } 00166 00167 //Release exclusive access 00168 osReleaseMutex(&netMutex); 00169 00170 //Return status code 00171 return error; 00172 } 00173 00174 00175 /** 00176 * @brief Retrieve the MTU for the specified interface 00177 * @param[in] interface Pointer to the desired network interface 00178 * @param[out] mtu Maximum transmit unit 00179 * @return Error code 00180 **/ 00181 00182 error_t ipv6GetMtu(NetInterface *interface, size_t *mtu) 00183 { 00184 //Check parameters 00185 if(interface == NULL || mtu == NULL) 00186 return ERROR_INVALID_PARAMETER; 00187 00188 //Get exclusive access 00189 osAcquireMutex(&netMutex); 00190 //Return the current MTU value 00191 *mtu = interface->ipv6Context.linkMtu; 00192 //Release exclusive access 00193 osReleaseMutex(&netMutex); 00194 00195 //Successful processing 00196 return NO_ERROR; 00197 } 00198 00199 00200 /** 00201 * @brief Assign link-local address 00202 * @param[in] interface Pointer to the desired network interface 00203 * @param[in] addr Link-local address 00204 * @return Error code 00205 **/ 00206 00207 error_t ipv6SetLinkLocalAddr(NetInterface *interface, const Ipv6Addr *addr) 00208 { 00209 error_t error; 00210 00211 //Get exclusive access 00212 osAcquireMutex(&netMutex); 00213 00214 #if (NDP_SUPPORT == ENABLED) 00215 //Check whether Duplicate Address Detection should be performed 00216 if(interface->ndpContext.dupAddrDetectTransmits > 0) 00217 { 00218 //Use the link-local address as a tentative address 00219 error = ipv6SetAddr(interface, 0, addr, IPV6_ADDR_STATE_TENTATIVE, 00220 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00221 } 00222 else 00223 #endif 00224 { 00225 //The use of the link-local address is now unrestricted 00226 error = ipv6SetAddr(interface, 0, addr, IPV6_ADDR_STATE_PREFERRED, 00227 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00228 } 00229 00230 //Release exclusive access 00231 osReleaseMutex(&netMutex); 00232 00233 //Return status code 00234 return error; 00235 } 00236 00237 00238 /** 00239 * @brief Retrieve link-local address 00240 * @param[in] interface Pointer to the desired network interface 00241 * @param[out] addr link-local address 00242 * @return Error code 00243 **/ 00244 00245 error_t ipv6GetLinkLocalAddr(NetInterface *interface, Ipv6Addr *addr) 00246 { 00247 Ipv6AddrEntry *entry; 00248 00249 //Check parameters 00250 if(interface == NULL || addr == NULL) 00251 return ERROR_INVALID_PARAMETER; 00252 00253 //Get exclusive access 00254 osAcquireMutex(&netMutex); 00255 00256 //Point to the corresponding address entry 00257 entry = &interface->ipv6Context.addrList[0]; 00258 00259 //Check whether the IPv6 address is valid 00260 if(entry->state == IPV6_ADDR_STATE_PREFERRED || 00261 entry->state == IPV6_ADDR_STATE_DEPRECATED) 00262 { 00263 //Get IPv6 address 00264 *addr = entry->addr; 00265 } 00266 else 00267 { 00268 //Return the unspecified address when no address has been assigned 00269 *addr = IPV6_UNSPECIFIED_ADDR; 00270 } 00271 00272 //Release exclusive access 00273 osReleaseMutex(&netMutex); 00274 00275 //Successful processing 00276 return NO_ERROR; 00277 } 00278 00279 00280 /** 00281 * @brief Assign global address 00282 * @param[in] interface Pointer to the desired network interface 00283 * @param[in] index Zero-based index 00284 * @param[in] addr Global address 00285 * @return Error code 00286 **/ 00287 00288 error_t ipv6SetGlobalAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr) 00289 { 00290 error_t error; 00291 00292 //Get exclusive access 00293 osAcquireMutex(&netMutex); 00294 00295 #if (NDP_SUPPORT == ENABLED) 00296 //Check whether Duplicate Address Detection should be performed 00297 if(interface->ndpContext.dupAddrDetectTransmits > 0) 00298 { 00299 //Use the global address as a tentative address 00300 error = ipv6SetAddr(interface, index + 1, addr, IPV6_ADDR_STATE_TENTATIVE, 00301 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00302 } 00303 else 00304 #endif 00305 { 00306 //The use of the global address is now unrestricted 00307 error = ipv6SetAddr(interface, index + 1, addr, IPV6_ADDR_STATE_PREFERRED, 00308 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00309 } 00310 00311 //Release exclusive access 00312 osReleaseMutex(&netMutex); 00313 00314 //Return status code 00315 return error; 00316 } 00317 00318 00319 /** 00320 * @brief Retrieve global address 00321 * @param[in] interface Pointer to the desired network interface 00322 * @param[in] index Zero-based index 00323 * @param[out] addr Global address 00324 * @return Error code 00325 **/ 00326 00327 error_t ipv6GetGlobalAddr(NetInterface *interface, uint_t index, Ipv6Addr *addr) 00328 { 00329 Ipv6AddrEntry *entry; 00330 00331 //Check parameters 00332 if(interface == NULL || addr == NULL) 00333 return ERROR_INVALID_PARAMETER; 00334 00335 //Make sure that the index is valid 00336 if((index + 1) >= IPV6_ADDR_LIST_SIZE) 00337 { 00338 //Return the unspecified address when the index is out of range 00339 *addr = IPV6_UNSPECIFIED_ADDR; 00340 //Report an error 00341 return ERROR_OUT_OF_RANGE; 00342 } 00343 00344 //Get exclusive access 00345 osAcquireMutex(&netMutex); 00346 00347 //Point to the corresponding address entry 00348 entry = &interface->ipv6Context.addrList[index + 1]; 00349 00350 //Check whether the IPv6 address is valid 00351 if(entry->state == IPV6_ADDR_STATE_PREFERRED || 00352 entry->state == IPV6_ADDR_STATE_DEPRECATED) 00353 { 00354 //Get IPv6 address 00355 *addr = entry->addr; 00356 } 00357 else 00358 { 00359 //Return the unspecified address when no address has been assigned 00360 *addr = IPV6_UNSPECIFIED_ADDR; 00361 } 00362 00363 //Release exclusive access 00364 osReleaseMutex(&netMutex); 00365 00366 //Successful processing 00367 return NO_ERROR; 00368 } 00369 00370 00371 /** 00372 * @brief Assign anycast address 00373 * @param[in] interface Pointer to the desired network interface 00374 * @param[in] index Zero-based index 00375 * @param[in] addr Anycast address 00376 * @return Error code 00377 **/ 00378 00379 error_t ipv6SetAnycastAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr) 00380 { 00381 error_t error; 00382 Ipv6Addr *anycastAddrList; 00383 Ipv6Addr solicitedNodeAddr; 00384 00385 //Check parameters 00386 if(interface == NULL || addr == NULL) 00387 return ERROR_INVALID_PARAMETER; 00388 00389 //Make sure that the index is valid 00390 if(index >= IPV6_ANYCAST_ADDR_LIST_SIZE) 00391 return ERROR_OUT_OF_RANGE; 00392 00393 //The IPv6 address must be a valid unicast address 00394 if(ipv6IsMulticastAddr(addr)) 00395 return ERROR_INVALID_ADDRESS; 00396 00397 //Initialize status code 00398 error = NO_ERROR; 00399 00400 //Get exclusive access 00401 osAcquireMutex(&netMutex); 00402 00403 //Point to the list of anycast addresses assigned to the interface 00404 anycastAddrList = interface->ipv6Context.anycastAddrList; 00405 00406 //Check whether an anycast address is already assigned 00407 if(!ipv6CompAddr(&anycastAddrList[index], &IPV6_UNSPECIFIED_ADDR)) 00408 { 00409 //Ethernet interface? 00410 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 00411 { 00412 //Form the Solicited-Node address 00413 ipv6ComputeSolicitedNodeAddr(&anycastAddrList[index], &solicitedNodeAddr); 00414 //Leave the Solicited-Node multicast group 00415 ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr); 00416 } 00417 } 00418 00419 //Assign the specified anycast address to the interface 00420 anycastAddrList[index] = *addr; 00421 00422 //Check whether the anycast address is valid 00423 if(!ipv6CompAddr(addr, &IPV6_UNSPECIFIED_ADDR)) 00424 { 00425 //Ethernet interface? 00426 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 00427 { 00428 //Form the Solicited-Node address for the link-local address 00429 ipv6ComputeSolicitedNodeAddr(addr, &solicitedNodeAddr); 00430 //Join the Solicited-Node multicast group for each assigned address 00431 error = ipv6JoinMulticastGroup(interface, &solicitedNodeAddr); 00432 } 00433 } 00434 00435 //Release exclusive access 00436 osReleaseMutex(&netMutex); 00437 00438 //Return status code 00439 return error; 00440 } 00441 00442 00443 /** 00444 * @brief Retrieve anycast address 00445 * @param[in] interface Pointer to the desired network interface 00446 * @param[in] index Zero-based index 00447 * @param[out] addr Anycast address 00448 * @return Error code 00449 **/ 00450 00451 error_t ipv6GetAnycastAddr(NetInterface *interface, uint_t index, Ipv6Addr *addr) 00452 { 00453 //Check parameters 00454 if(interface == NULL || addr == NULL) 00455 return ERROR_INVALID_PARAMETER; 00456 00457 //Make sure that the index is valid 00458 if(index >= IPV6_ANYCAST_ADDR_LIST_SIZE) 00459 { 00460 //Return the unspecified address when the index is out of range 00461 *addr = IPV6_UNSPECIFIED_ADDR; 00462 //Report an error 00463 return ERROR_OUT_OF_RANGE; 00464 } 00465 00466 //Get exclusive access 00467 osAcquireMutex(&netMutex); 00468 //Return the corresponding address entry 00469 *addr = interface->ipv6Context.anycastAddrList[index]; 00470 //Release exclusive access 00471 osReleaseMutex(&netMutex); 00472 00473 //Successful processing 00474 return NO_ERROR; 00475 } 00476 00477 00478 /** 00479 * @brief Configure IPv6 prefix 00480 * @param[in] interface Pointer to the desired network interface 00481 * @param[in] index Zero-based index 00482 * @param[in] prefix IPv6 prefix 00483 * @param[in] length The number of leading bits in the prefix that are valid 00484 **/ 00485 00486 error_t ipv6SetPrefix(NetInterface *interface, 00487 uint_t index, const Ipv6Addr *prefix, uint_t length) 00488 { 00489 Ipv6PrefixEntry *entry; 00490 00491 //Check parameters 00492 if(interface == NULL || prefix == NULL) 00493 return ERROR_INVALID_PARAMETER; 00494 00495 //Make sure that the index is valid 00496 if(index >= IPV6_PREFIX_LIST_SIZE) 00497 return ERROR_OUT_OF_RANGE; 00498 00499 //Make sure the prefix length is valid 00500 if(length >= 128) 00501 return ERROR_INVALID_PARAMETER; 00502 00503 //Get exclusive access 00504 osAcquireMutex(&netMutex); 00505 00506 //Point to the corresponding entry 00507 entry = &interface->ipv6Context.prefixList[index]; 00508 00509 //Set up IPv6 prefix 00510 entry->prefix = *prefix; 00511 entry->prefixLength = length; 00512 00513 //Check prefix length 00514 if(length > 0) 00515 { 00516 //Manually assigned prefixes have infinite lifetime 00517 entry->validLifetime = INFINITE_DELAY; 00518 entry->preferredLifetime = INFINITE_DELAY; 00519 entry->permanent = TRUE; 00520 } 00521 else 00522 { 00523 //Immediately time-out the entry 00524 entry->validLifetime = 0; 00525 entry->preferredLifetime = 0; 00526 entry->permanent = FALSE; 00527 } 00528 00529 //Release exclusive access 00530 osReleaseMutex(&netMutex); 00531 00532 //Successful processing 00533 return NO_ERROR; 00534 } 00535 00536 00537 /** 00538 * @brief Retrieve IPv6 prefix 00539 * @param[in] interface Pointer to the desired network interface 00540 * @param[in] index Zero-based index 00541 * @param[out] prefix IPv6 prefix 00542 * @param[out] length The number of leading bits in the prefix that are valid 00543 * @return Error code 00544 **/ 00545 00546 error_t ipv6GetPrefix(NetInterface *interface, 00547 uint_t index, Ipv6Addr *prefix, uint_t *length) 00548 { 00549 Ipv6PrefixEntry *entry; 00550 00551 //Check parameters 00552 if(interface == NULL || prefix == NULL) 00553 return ERROR_INVALID_PARAMETER; 00554 00555 //Make sure that the index is valid 00556 if(index >= IPV6_PREFIX_LIST_SIZE) 00557 { 00558 //Return the ::/0 prefix when the index is out of range 00559 *prefix = IPV6_UNSPECIFIED_ADDR; 00560 *length = 0; 00561 //Report an error 00562 return ERROR_OUT_OF_RANGE; 00563 } 00564 00565 //Get exclusive access 00566 osAcquireMutex(&netMutex); 00567 00568 //Point to the corresponding entry 00569 entry = &interface->ipv6Context.prefixList[index]; 00570 00571 //Check whether the prefix is valid 00572 if(entry->validLifetime > 0) 00573 { 00574 //Get IPv6 prefix 00575 *prefix = entry->prefix; 00576 *length = entry->prefixLength; 00577 } 00578 else 00579 { 00580 //Return the ::/0 prefix when the valid lifetime has expired 00581 *prefix = IPV6_UNSPECIFIED_ADDR; 00582 *length = 0; 00583 } 00584 00585 //Release exclusive access 00586 osReleaseMutex(&netMutex); 00587 00588 //Successful processing 00589 return NO_ERROR; 00590 } 00591 00592 00593 /** 00594 * @brief Configure default router 00595 * @param[in] interface Pointer to the desired network interface 00596 * @param[in] index Zero-based index 00597 * @param[in] addr Default router address 00598 * @return Error code 00599 **/ 00600 00601 error_t ipv6SetDefaultRouter(NetInterface *interface, uint_t index, const Ipv6Addr *addr) 00602 { 00603 Ipv6RouterEntry *entry; 00604 00605 //Check parameters 00606 if(interface == NULL || addr == NULL) 00607 return ERROR_INVALID_PARAMETER; 00608 00609 //Make sure that the index is valid 00610 if(index >= IPV6_ROUTER_LIST_SIZE) 00611 return ERROR_OUT_OF_RANGE; 00612 00613 //The IPv6 address must be a valid unicast address 00614 if(ipv6IsMulticastAddr(addr)) 00615 return ERROR_INVALID_ADDRESS; 00616 00617 //Get exclusive access 00618 osAcquireMutex(&netMutex); 00619 00620 //Point to the corresponding entry 00621 entry = &interface->ipv6Context.routerList[index]; 00622 00623 //Set up router address 00624 entry->addr = *addr; 00625 00626 //Valid IPv6 address? 00627 if(!ipv6CompAddr(addr, &IPV6_UNSPECIFIED_ADDR)) 00628 { 00629 //Manually assigned routers have infinite lifetime 00630 entry->lifetime = INFINITE_DELAY; 00631 entry->permanent = TRUE; 00632 } 00633 else 00634 { 00635 //Immediately time-out the entry 00636 entry->lifetime = 0; 00637 entry->permanent = FALSE; 00638 } 00639 00640 //Release exclusive access 00641 osReleaseMutex(&netMutex); 00642 00643 //Successful processing 00644 return NO_ERROR; 00645 } 00646 00647 00648 /** 00649 * @brief Retrieve default router 00650 * @param[in] interface Pointer to the desired network interface 00651 * @param[in] index Zero-based index 00652 * @param[out] addr Default router address 00653 * @return Error code 00654 **/ 00655 00656 error_t ipv6GetDefaultRouter(NetInterface *interface, uint_t index, Ipv6Addr *addr) 00657 { 00658 Ipv6RouterEntry *entry; 00659 00660 //Check parameters 00661 if(interface == NULL || addr == NULL) 00662 return ERROR_INVALID_PARAMETER; 00663 00664 //Make sure that the index is valid 00665 if(index >= IPV6_ROUTER_LIST_SIZE) 00666 { 00667 //Return the unspecified address when the index is out of range 00668 *addr = IPV6_UNSPECIFIED_ADDR; 00669 //Report an error 00670 return ERROR_OUT_OF_RANGE; 00671 } 00672 00673 //Get exclusive access 00674 osAcquireMutex(&netMutex); 00675 00676 //Point to the corresponding entry 00677 entry = &interface->ipv6Context.routerList[index]; 00678 00679 //Check the lifetime of the entry 00680 if(entry->lifetime > 0) 00681 { 00682 //Get router address 00683 *addr = entry->addr; 00684 } 00685 else 00686 { 00687 //Return the unspecified address when the lifetime has expired 00688 *addr = IPV6_UNSPECIFIED_ADDR; 00689 } 00690 00691 //Release exclusive access 00692 osReleaseMutex(&netMutex); 00693 00694 //Successful processing 00695 return NO_ERROR; 00696 } 00697 00698 00699 /** 00700 * @brief Configure DNS server 00701 * @param[in] interface Pointer to the desired network interface 00702 * @param[in] index This parameter selects between the primary and secondary DNS server 00703 * @param[in] addr DNS server address 00704 * @return Error code 00705 **/ 00706 00707 error_t ipv6SetDnsServer(NetInterface *interface, uint_t index, const Ipv6Addr *addr) 00708 { 00709 //Check parameters 00710 if(interface == NULL || addr == NULL) 00711 return ERROR_INVALID_PARAMETER; 00712 00713 //Make sure that the index is valid 00714 if(index >= IPV6_DNS_SERVER_LIST_SIZE) 00715 return ERROR_OUT_OF_RANGE; 00716 00717 //The IPv6 address must be a valid unicast address 00718 if(ipv6IsMulticastAddr(addr)) 00719 return ERROR_INVALID_ADDRESS; 00720 00721 //Get exclusive access 00722 osAcquireMutex(&netMutex); 00723 //Set up DNS server address 00724 interface->ipv6Context.dnsServerList[index] = *addr; 00725 //Release exclusive access 00726 osReleaseMutex(&netMutex); 00727 00728 //Successful processing 00729 return NO_ERROR; 00730 } 00731 00732 00733 /** 00734 * @brief Retrieve DNS server 00735 * @param[in] interface Pointer to the desired network interface 00736 * @param[in] index This parameter selects between the primary and secondary DNS server 00737 * @param[out] addr DNS server address 00738 * @return Error code 00739 **/ 00740 00741 error_t ipv6GetDnsServer(NetInterface *interface, uint_t index, Ipv6Addr *addr) 00742 { 00743 //Check parameters 00744 if(interface == NULL || addr == NULL) 00745 return ERROR_INVALID_PARAMETER; 00746 00747 //Make sure that the index is valid 00748 if(index >= IPV6_DNS_SERVER_LIST_SIZE) 00749 { 00750 //Return the unspecified address when the index is out of range 00751 *addr = IPV6_UNSPECIFIED_ADDR; 00752 //Report an error 00753 return ERROR_OUT_OF_RANGE; 00754 } 00755 00756 //Get exclusive access 00757 osAcquireMutex(&netMutex); 00758 //Get DNS server address 00759 *addr = interface->ipv6Context.dnsServerList[index]; 00760 //Release exclusive access 00761 osReleaseMutex(&netMutex); 00762 00763 //Successful processing 00764 return NO_ERROR; 00765 } 00766 00767 00768 /** 00769 * @brief Callback function for link change event 00770 * @param[in] interface Underlying network interface 00771 **/ 00772 00773 void ipv6LinkChangeEvent(NetInterface *interface) 00774 { 00775 uint_t i; 00776 Ipv6Context *context; 00777 Ipv6AddrEntry *entry; 00778 00779 //Point to the IPv6 context 00780 context = &interface->ipv6Context; 00781 00782 //Restore default parameters 00783 context->linkMtu = interface->nicDriver->mtu; 00784 context->curHopLimit = IPV6_DEFAULT_HOP_LIMIT; 00785 00786 //Clear the list of IPv6 addresses 00787 ipv6FlushAddrList(interface); 00788 //Clear the Prefix List 00789 ipv6FlushPrefixList(interface); 00790 //Clear the Default Router List 00791 ipv6FlushDefaultRouterList(interface); 00792 00793 #if (IPV6_FRAG_SUPPORT == ENABLED) 00794 //Flush the reassembly queue 00795 ipv6FlushFragQueue(interface); 00796 #endif 00797 00798 #if (MLD_SUPPORT == ENABLED) 00799 //Notify MLD of link state changes 00800 mldLinkChangeEvent(interface); 00801 #endif 00802 00803 #if (NDP_SUPPORT == ENABLED) 00804 //Notify NDP of link state changes 00805 ndpLinkChangeEvent(interface); 00806 #endif 00807 00808 #if (NDP_ROUTER_ADV_SUPPORT == ENABLED) 00809 //Notify the RA service of link state changes 00810 ndpRouterAdvLinkChangeEvent(interface->ndpRouterAdvContext); 00811 #endif 00812 00813 #if (SLAAC_SUPPORT == ENABLED) 00814 //Notify the SLAAC service of link state changes 00815 slaacLinkChangeEvent(interface->slaacContext); 00816 #endif 00817 00818 #if (DHCPV6_CLIENT_SUPPORT == ENABLED) 00819 //Notify the DHCPv6 client of link state changes 00820 dhcpv6ClientLinkChangeEvent(interface->dhcpv6ClientContext); 00821 #endif 00822 00823 //Go through the list of IPv6 addresses 00824 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++) 00825 { 00826 //Point to the current entry 00827 entry = &context->addrList[i]; 00828 00829 //Check whether the IPv6 address has been manually assigned 00830 if(entry->permanent) 00831 { 00832 #if (NDP_SUPPORT == ENABLED) 00833 //Check whether Duplicate Address Detection should be performed 00834 if(interface->ndpContext.dupAddrDetectTransmits > 0) 00835 { 00836 //Use the IPv6 address as a tentative address 00837 ipv6SetAddr(interface, i, &entry->addr, IPV6_ADDR_STATE_TENTATIVE, 00838 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00839 } 00840 else 00841 #endif 00842 { 00843 //The use of the IPv6 address is now unrestricted 00844 ipv6SetAddr(interface, i, &entry->addr, IPV6_ADDR_STATE_PREFERRED, 00845 NDP_INFINITE_LIFETIME, NDP_INFINITE_LIFETIME, TRUE); 00846 } 00847 } 00848 } 00849 } 00850 00851 00852 /** 00853 * @brief Incoming IPv6 packet processing 00854 * @param[in] interface Underlying network interface 00855 * @param[in] ipPacket Multi-part buffer that holds the incoming IPv6 packet 00856 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 00857 **/ 00858 00859 void ipv6ProcessPacket(NetInterface *interface, 00860 NetBuffer *ipPacket, size_t ipPacketOffset) 00861 { 00862 error_t error; 00863 size_t i; 00864 size_t length; 00865 size_t nextHeaderOffset; 00866 uint8_t *type; 00867 Ipv6Header *ipHeader; 00868 IpPseudoHeader pseudoHeader; 00869 00870 //Retrieve the length of the IPv6 packet 00871 length = netBufferGetLength(ipPacket); 00872 00873 //Ensure the packet length is greater than 40 bytes 00874 if(length < sizeof(Ipv6Header)) 00875 return; 00876 00877 //Point to the IPv6 header 00878 ipHeader = netBufferAt(ipPacket, ipPacketOffset); 00879 //Sanity check 00880 if(ipHeader == NULL) 00881 return; 00882 00883 //Debug message 00884 TRACE_INFO("IPv6 packet received (%" PRIuSIZE " bytes)...\r\n", length); 00885 //Dump IPv6 header contents for debugging purpose 00886 ipv6DumpHeader(ipHeader); 00887 00888 //Check IP version number 00889 if(ipHeader->version != IPV6_VERSION) 00890 return; 00891 //Ensure the payload length is correct before processing the packet 00892 if(ntohs(ipHeader->payloadLength) > (length - sizeof(Ipv6Header))) 00893 return; 00894 //Source address filtering 00895 if(ipv6CheckSourceAddr(interface, &ipHeader->srcAddr)) 00896 return; 00897 00898 #if defined(IPV6_PACKET_FORWARD_HOOK) 00899 IPV6_PACKET_FORWARD_HOOK(interface, ipPacket, ipPacketOffset); 00900 #else 00901 //Destination address filtering 00902 if(ipv6CheckDestAddr(interface, &ipHeader->destAddr)) 00903 { 00904 #if(IPV6_ROUTING_SUPPORT == ENABLED) 00905 //Forward the packet according to the routing table 00906 ipv6ForwardPacket(interface, ipPacket, ipPacketOffset); 00907 #endif 00908 //We are done 00909 return; 00910 } 00911 #endif 00912 00913 //Calculate the effective length of the multi-part buffer 00914 length = ipPacketOffset + sizeof(Ipv6Header) + 00915 ntohs(ipHeader->payloadLength); 00916 00917 //Adjust the length of the multi-part buffer if necessary 00918 netBufferSetLength(ipPacket, length); 00919 00920 //Form the IPv6 pseudo header 00921 pseudoHeader.length = sizeof(Ipv6PseudoHeader); 00922 pseudoHeader.ipv6Data.srcAddr = ipHeader->srcAddr; 00923 pseudoHeader.ipv6Data.destAddr = ipHeader->destAddr; 00924 pseudoHeader.ipv6Data.reserved = 0; 00925 00926 //Keep track of Next Header field 00927 nextHeaderOffset = ipPacketOffset + &ipHeader->nextHeader - 00928 (uint8_t *) ipHeader; 00929 00930 //Point to the first extension header 00931 i = ipPacketOffset + sizeof(Ipv6Header); 00932 00933 //Parse extension headers 00934 while(i < length) 00935 { 00936 //Retrieve the Next Header field of preceding header 00937 type = netBufferAt(ipPacket, nextHeaderOffset); 00938 //Sanity check 00939 if(type == NULL) 00940 return; 00941 00942 //Update IPv6 pseudo header 00943 pseudoHeader.ipv6Data.length = htonl(length - i); 00944 pseudoHeader.ipv6Data.nextHeader = *type; 00945 00946 //Each extension header is identified by the 00947 //Next Header field of the preceding header 00948 switch(*type) 00949 { 00950 //Hop-by-Hop Options header? 00951 case IPV6_HOP_BY_HOP_OPT_HEADER: 00952 //Parse current extension header 00953 error = ipv6ParseHopByHopOptHeader(interface, 00954 ipPacket, ipPacketOffset, &i, &nextHeaderOffset); 00955 //Continue processing 00956 break; 00957 00958 //Destination Options header? 00959 case IPV6_DEST_OPT_HEADER: 00960 //Parse current extension header 00961 error = ipv6ParseDestOptHeader(interface, 00962 ipPacket, ipPacketOffset, &i, &nextHeaderOffset); 00963 //Continue processing 00964 break; 00965 00966 //Routing header? 00967 case IPV6_ROUTING_HEADER: 00968 //Parse current extension header 00969 error = ipv6ParseRoutingHeader(interface, 00970 ipPacket, ipPacketOffset, &i, &nextHeaderOffset); 00971 //Continue processing 00972 break; 00973 00974 //Fragment header? 00975 case IPV6_FRAGMENT_HEADER: 00976 #if (IPV6_FRAG_SUPPORT == ENABLED) 00977 //Parse current extension header 00978 ipv6ParseFragmentHeader(interface, 00979 ipPacket, ipPacketOffset, i, nextHeaderOffset); 00980 #endif 00981 //Exit immediately 00982 return; 00983 00984 //Authentication header? 00985 case IPV6_AUTH_HEADER: 00986 //Parse current extension header 00987 error = ipv6ParseAuthHeader(interface, 00988 ipPacket, ipPacketOffset, &i, &nextHeaderOffset); 00989 //Continue processing 00990 break; 00991 00992 //Encapsulating Security Payload header? 00993 case IPV6_ESP_HEADER: 00994 //Parse current extension header 00995 error = ipv6ParseEspHeader(interface, 00996 ipPacket, ipPacketOffset, &i, &nextHeaderOffset); 00997 //Continue processing 00998 break; 00999 01000 //ICMPv6 header? 01001 case IPV6_ICMPV6_HEADER: 01002 //Process incoming ICMPv6 message 01003 icmpv6ProcessMessage(interface, &pseudoHeader.ipv6Data, 01004 ipPacket, i, ipHeader->hopLimit); 01005 01006 #if (RAW_SOCKET_SUPPORT == ENABLED) 01007 //Packets addressed to the tentative address should be silently discarded 01008 if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr)) 01009 { 01010 //Allow raw sockets to process ICMPv6 messages 01011 rawSocketProcessIpPacket(interface, &pseudoHeader, ipPacket, i); 01012 } 01013 #endif 01014 //Exit immediately 01015 return; 01016 01017 #if (TCP_SUPPORT == ENABLED) 01018 //TCP header? 01019 case IPV6_TCP_HEADER: 01020 //Packets addressed to the tentative address should be silently discarded 01021 if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr)) 01022 { 01023 //Process incoming TCP segment 01024 tcpProcessSegment(interface, &pseudoHeader, ipPacket, i); 01025 } 01026 //Exit immediately 01027 return; 01028 #endif 01029 01030 #if (UDP_SUPPORT == ENABLED) 01031 //UDP header? 01032 case IPV6_UDP_HEADER: 01033 //Packets addressed to the tentative address should be silently discarded 01034 if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr)) 01035 { 01036 //Process incoming UDP datagram 01037 error = udpProcessDatagram(interface, &pseudoHeader, ipPacket, i); 01038 01039 //Unreachable port? 01040 if(error == ERROR_PORT_UNREACHABLE) 01041 { 01042 //A destination node should originate a Destination Unreachable 01043 //message with Code 4 in response to a packet for which the 01044 //transport protocol has no listener 01045 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_DEST_UNREACHABLE, 01046 ICMPV6_CODE_PORT_UNREACHABLE, 0, ipPacket, ipPacketOffset); 01047 } 01048 } 01049 //Exit immediately 01050 return; 01051 #endif 01052 01053 //No next header? 01054 case IPV6_NO_NEXT_HEADER: 01055 //If the payload length field of the IPv6 header indicates the presence of 01056 //octets past the end of the previous header, these octets must be ignored 01057 return; 01058 01059 //Unrecognized header type? 01060 default: 01061 //Debug message 01062 TRACE_WARNING("Unrecognized Next Header type\r\n"); 01063 01064 //Packets addressed to the tentative address should be silently discarded 01065 if(!ipv6IsTentativeAddr(interface, &ipHeader->destAddr)) 01066 { 01067 //Compute the offset of the unrecognized Next Header field within the packet 01068 size_t n = nextHeaderOffset - ipPacketOffset; 01069 01070 //Send an ICMP Parameter Problem message 01071 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_PARAM_PROBLEM, 01072 ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset); 01073 } 01074 01075 //Discard incoming packet 01076 return; 01077 } 01078 01079 //Any error while processing the current extension header? 01080 if(error) 01081 return; 01082 } 01083 } 01084 01085 01086 /** 01087 * @brief Parse Hop-by-Hop Options header 01088 * @param[in] interface Underlying network interface 01089 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01090 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01091 * @param[in,out] headerOffset Offset to the Hop-by-Hop Options header 01092 * @param[in,out] nextHeaderOffset Offset to the Next Header field 01093 * @brief Error code 01094 **/ 01095 01096 error_t ipv6ParseHopByHopOptHeader(NetInterface *interface, const NetBuffer *ipPacket, 01097 size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset) 01098 { 01099 error_t error; 01100 size_t n; 01101 size_t length; 01102 size_t headerLength; 01103 Ipv6HopByHopOptHeader *header; 01104 01105 //Remaining bytes to process in the IPv6 packet 01106 length = netBufferGetLength(ipPacket) - *headerOffset; 01107 01108 //Make sure the extension header is valid 01109 if(length < sizeof(Ipv6HopByHopOptHeader)) 01110 return ERROR_INVALID_HEADER; 01111 01112 //Point to the Hop-by-Hop Options header 01113 header = netBufferAt(ipPacket, *headerOffset); 01114 //Sanity check 01115 if(header == NULL) 01116 return ERROR_FAILURE; 01117 01118 //Calculate the length of the entire header 01119 headerLength = (header->hdrExtLen * 8) + 8; 01120 01121 //Check header length 01122 if(headerLength > length) 01123 return ERROR_INVALID_HEADER; 01124 01125 //Debug message 01126 TRACE_DEBUG(" Hop-by-Hop Options header\r\n"); 01127 01128 //The Hop-by-Hop Options header, when present, must immediately follow 01129 //the IPv6 header 01130 if(*headerOffset != (ipPacketOffset + sizeof(Ipv6Header))) 01131 { 01132 //Compute the offset of the unrecognized Next Header field within the packet 01133 n = *nextHeaderOffset - ipPacketOffset; 01134 01135 //Send an ICMP Parameter Problem message to the source of the packet 01136 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_PARAM_PROBLEM, 01137 ICMPV6_CODE_UNKNOWN_NEXT_HEADER, n, ipPacket, ipPacketOffset); 01138 01139 //Discard incoming packet 01140 return ERROR_INVALID_HEADER; 01141 } 01142 01143 //Compute the length of the Options field 01144 n = headerLength - sizeof(Ipv6HopByHopOptHeader); 01145 01146 //Parse options 01147 error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset, 01148 *headerOffset + sizeof(Ipv6HopByHopOptHeader), n); 01149 01150 //Any error to report? 01151 if(error) 01152 return error; 01153 01154 //Keep track of Next Header field 01155 *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header; 01156 //Point to the next extension header 01157 *headerOffset += headerLength; 01158 01159 //Successful processing 01160 return NO_ERROR; 01161 } 01162 01163 01164 /** 01165 * @brief Parse Destination Options header 01166 * @param[in] interface Underlying network interface 01167 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01168 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01169 * @param[in,out] headerOffset Offset to the Destination Options header 01170 * @param[in,out] nextHeaderOffset Offset to the Next Header field 01171 * @brief Error code 01172 **/ 01173 01174 error_t ipv6ParseDestOptHeader(NetInterface *interface, const NetBuffer *ipPacket, 01175 size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset) 01176 { 01177 error_t error; 01178 size_t n; 01179 size_t length; 01180 size_t headerLength; 01181 Ipv6DestOptHeader *header; 01182 01183 //Remaining bytes to process in the IPv6 packet 01184 length = netBufferGetLength(ipPacket) - *headerOffset; 01185 01186 //Make sure the extension header is valid 01187 if(length < sizeof(Ipv6DestOptHeader)) 01188 return ERROR_INVALID_HEADER; 01189 01190 //Point to the Destination Options header 01191 header = netBufferAt(ipPacket, *headerOffset); 01192 //Sanity check 01193 if(header == NULL) 01194 return ERROR_FAILURE; 01195 01196 //Calculate the length of the entire header 01197 headerLength = (header->hdrExtLen * 8) + 8; 01198 01199 //Check header length 01200 if(headerLength > length) 01201 return ERROR_INVALID_HEADER; 01202 01203 //Debug message 01204 TRACE_DEBUG(" Destination Options header\r\n"); 01205 01206 //Compute the length of the Options field 01207 n = headerLength - sizeof(Ipv6DestOptHeader); 01208 01209 //Parse options 01210 error = ipv6ParseOptions(interface, ipPacket, ipPacketOffset, 01211 *headerOffset + sizeof(Ipv6DestOptHeader), n); 01212 01213 //Any error to report? 01214 if(error) 01215 return error; 01216 01217 //Keep track of Next Header field 01218 *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header; 01219 //Point to the next extension header 01220 *headerOffset += headerLength; 01221 01222 //Successful processing 01223 return NO_ERROR; 01224 } 01225 01226 01227 /** 01228 * @brief Parse Routing header 01229 * @param[in] interface Underlying network interface 01230 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01231 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01232 * @param[in,out] headerOffset Offset to the Routing header 01233 * @param[in,out] nextHeaderOffset Offset to the Next Header field 01234 * @brief Error code 01235 **/ 01236 01237 error_t ipv6ParseRoutingHeader(NetInterface *interface, const NetBuffer *ipPacket, 01238 size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset) 01239 { 01240 size_t n; 01241 size_t length; 01242 size_t headerLength; 01243 Ipv6RoutingHeader *header; 01244 01245 //Remaining bytes to process in the IPv6 packet 01246 length = netBufferGetLength(ipPacket) - *headerOffset; 01247 01248 //Make sure the extension header is valid 01249 if(length < sizeof(Ipv6RoutingHeader)) 01250 return ERROR_INVALID_HEADER; 01251 01252 //Point to the Routing header 01253 header = netBufferAt(ipPacket, *headerOffset); 01254 //Sanity check 01255 if(header == NULL) 01256 return ERROR_FAILURE; 01257 01258 //Calculate the length of the entire header 01259 headerLength = (header->hdrExtLen * 8) + 8; 01260 01261 //Check header length 01262 if(headerLength > length) 01263 return ERROR_INVALID_HEADER; 01264 01265 //Debug message 01266 TRACE_DEBUG(" Routing header\r\n"); 01267 01268 //If, while processing a received packet, a node encounters a Routing 01269 //header with an unrecognized Routing Type value, the required behavior 01270 //of the node depends on the value of the Segments Left field 01271 if(header->segmentsLeft != 0) 01272 { 01273 //Retrieve the offset of the Routing header within the packet 01274 n = *headerOffset - ipPacketOffset; 01275 //Compute the exact offset of the Routing Type field 01276 n += (uint8_t *) &header->routingType - (uint8_t *) header; 01277 01278 //If Segments Left is non-zero, send an ICMP Parameter Problem, 01279 //Code 0, message to the packet's Source Address, pointing to 01280 //the unrecognized Routing Type 01281 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_PARAM_PROBLEM, 01282 ICMPV6_CODE_INVALID_HEADER_FIELD, n, ipPacket, ipPacketOffset); 01283 01284 //The node must discard the packet 01285 return ERROR_INVALID_TYPE; 01286 } 01287 01288 //Keep track of Next Header field 01289 *nextHeaderOffset = *headerOffset + &header->nextHeader - (uint8_t *) header; 01290 //Point to the next extension header 01291 *headerOffset += headerLength; 01292 01293 //Successful processing 01294 return NO_ERROR; 01295 } 01296 01297 01298 /** 01299 * @brief Parse Authentication header 01300 * @param[in] interface Underlying network interface 01301 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01302 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01303 * @param[in,out] headerOffset Offset to the Authentication header 01304 * @param[in,out] nextHeaderOffset Offset to the Next Header field 01305 * @brief Error code 01306 **/ 01307 01308 error_t ipv6ParseAuthHeader(NetInterface *interface, const NetBuffer *ipPacket, 01309 size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset) 01310 { 01311 //Debug message 01312 TRACE_DEBUG(" Authentication header\r\n"); 01313 //Authentication not supported 01314 return ERROR_FAILURE; 01315 } 01316 01317 01318 /** 01319 * @brief Parse Encapsulating Security Payload header 01320 * @param[in] interface Underlying network interface 01321 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01322 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01323 * @param[in,out] headerOffset Offset to the Encapsulating Security Payload header 01324 * @param[in,out] nextHeaderOffset Offset to the Next Header field 01325 * @brief Error code 01326 **/ 01327 01328 error_t ipv6ParseEspHeader(NetInterface *interface, const NetBuffer *ipPacket, 01329 size_t ipPacketOffset, size_t *headerOffset, size_t *nextHeaderOffset) 01330 { 01331 //Debug message 01332 TRACE_DEBUG(" Encapsulating Security Payload header\r\n"); 01333 //Authentication not supported 01334 return ERROR_FAILURE; 01335 } 01336 01337 01338 /** 01339 * @brief Parse IPv6 options 01340 * @param[in] interface Underlying network interface 01341 * @param[in] ipPacket Multi-part buffer containing the IPv6 packet 01342 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet 01343 * @param[in] optOffset Offset to the first byte of the Options field 01344 * @param[in] optLength Length of the Options field 01345 * @brief Error code 01346 **/ 01347 01348 error_t ipv6ParseOptions(NetInterface *interface, const NetBuffer *ipPacket, 01349 size_t ipPacketOffset, size_t optOffset, size_t optLength) 01350 { 01351 size_t i; 01352 size_t n; 01353 uint8_t type; 01354 uint8_t action; 01355 uint8_t *options; 01356 Ipv6Option *option; 01357 Ipv6Header *ipHeader; 01358 01359 //Point to the first byte of the Options field 01360 options = netBufferAt(ipPacket, optOffset); 01361 01362 //Sanity check 01363 if(options == NULL) 01364 return ERROR_FAILURE; 01365 01366 //Parse options 01367 for(i = 0; i < optLength; ) 01368 { 01369 //Point to the current option 01370 option = (Ipv6Option *) (options + i); 01371 //Get option type 01372 type = option->type & IPV6_OPTION_TYPE_MASK; 01373 01374 //Pad1 option? 01375 if(type == IPV6_OPTION_TYPE_PAD1) 01376 { 01377 //Advance data pointer 01378 i++; 01379 } 01380 //PadN option? 01381 else if(type == IPV6_OPTION_TYPE_PADN) 01382 { 01383 //Malformed IPv6 packet? 01384 if((i + sizeof(Ipv6Option)) > optLength) 01385 return ERROR_INVALID_LENGTH; 01386 01387 //Advance data pointer 01388 i += sizeof(Ipv6Option) + option->length; 01389 } 01390 //Unrecognized option? 01391 else 01392 { 01393 //Point to the IPv6 header 01394 ipHeader = netBufferAt(ipPacket, ipPacketOffset); 01395 01396 //Sanity check 01397 if(ipHeader == NULL) 01398 return ERROR_FAILURE; 01399 01400 //Get the value of the highest-order two bits 01401 action = option->type & IPV6_ACTION_MASK; 01402 01403 //The highest-order two bits specify the action that must be taken 01404 //if the processing IPv6 node does not recognize the option type 01405 if(action == IPV6_ACTION_SKIP_OPTION) 01406 { 01407 //Skip over this option and continue processing the header 01408 } 01409 else if(action == IPV6_ACTION_DISCARD_PACKET) 01410 { 01411 //Discard the packet 01412 return ERROR_INVALID_OPTION; 01413 } 01414 else if(action == IPV6_ACTION_SEND_ICMP_ERROR_ALL) 01415 { 01416 //Calculate the octet offset within the invoking packet 01417 //where the error was detected 01418 n = optOffset + i - ipPacketOffset; 01419 01420 //Send an ICMP Parameter Problem message to the source of the 01421 //packet, regardless of whether or not the destination address 01422 //was a multicast address 01423 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_PARAM_PROBLEM, 01424 ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset); 01425 01426 //Discard the packet 01427 return ERROR_INVALID_OPTION; 01428 } 01429 else if(action == IPV6_ACTION_SEND_ICMP_ERROR_UNI) 01430 { 01431 //Send an ICMP Parameter Problem message to the source of the 01432 //packet, only if the destination address was not a multicast 01433 //address 01434 if(!ipv6IsMulticastAddr(&ipHeader->destAddr)) 01435 { 01436 //Calculate the octet offset within the invoking packet 01437 //where the error was detected 01438 n = optOffset + i - ipPacketOffset; 01439 01440 //Send the ICMP Parameter Problem message 01441 icmpv6SendErrorMessage(interface, ICMPV6_TYPE_PARAM_PROBLEM, 01442 ICMPV6_CODE_UNKNOWN_IPV6_OPTION, n, ipPacket, ipPacketOffset); 01443 } 01444 01445 //Discard the packet 01446 return ERROR_INVALID_OPTION; 01447 } 01448 01449 //Malformed IPv6 packet? 01450 if((i + sizeof(Ipv6Option)) > optLength) 01451 return ERROR_INVALID_LENGTH; 01452 01453 //Advance data pointer 01454 i += sizeof(Ipv6Option) + option->length; 01455 } 01456 } 01457 01458 //Successful processing 01459 return NO_ERROR; 01460 } 01461 01462 01463 /** 01464 * @brief Send an IPv6 datagram 01465 * @param[in] interface Underlying network interface 01466 * @param[in] pseudoHeader IPv6 pseudo header 01467 * @param[in] buffer Multi-part buffer containing the payload 01468 * @param[in] offset Offset to the first byte of the payload 01469 * @param[in] hopLimit Hop Limit value. Default value is used when this parameter is zero 01470 * @return Error code 01471 **/ 01472 01473 error_t ipv6SendDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, 01474 NetBuffer *buffer, size_t offset, uint8_t hopLimit) 01475 { 01476 error_t error; 01477 size_t length; 01478 size_t pathMtu; 01479 01480 //Retrieve the length of payload 01481 length = netBufferGetLength(buffer) - offset; 01482 01483 //Check whether the Hop Limit value is zero 01484 if(hopLimit == 0) 01485 { 01486 //Use default Hop Limit value 01487 hopLimit = interface->ipv6Context.curHopLimit; 01488 } 01489 01490 #if (IPV6_PMTU_SUPPORT == ENABLED) 01491 //Retrieve the PMTU for the specified destination address 01492 pathMtu = ipv6GetPathMtu(interface, &pseudoHeader->destAddr); 01493 01494 //The PMTU should not exceed the MTU of the first-hop link 01495 if(pathMtu > interface->ipv6Context.linkMtu) 01496 pathMtu = interface->ipv6Context.linkMtu; 01497 #else 01498 //The PMTU value for the path is assumed to be the MTU of the first-hop link 01499 pathMtu = interface->ipv6Context.linkMtu; 01500 #endif 01501 01502 //If the payload is smaller than the PMTU then no fragmentation is needed 01503 if((length + sizeof(Ipv6Header)) <= pathMtu) 01504 { 01505 //Send data as is 01506 error = ipv6SendPacket(interface, pseudoHeader, 01507 0, 0, buffer, offset, hopLimit); 01508 } 01509 //If the payload length exceeds the PMTU then the device must fragment the data 01510 else 01511 { 01512 #if (IPV6_FRAG_SUPPORT == ENABLED) 01513 //Fragment IP datagram into smaller packets 01514 error = ipv6FragmentDatagram(interface, pseudoHeader, 01515 buffer, offset, pathMtu, hopLimit); 01516 #else 01517 //Fragmentation is not supported 01518 error = ERROR_MESSAGE_TOO_LONG; 01519 #endif 01520 } 01521 01522 //Return status code 01523 return error; 01524 } 01525 01526 01527 /** 01528 * @brief Send an IPv6 packet 01529 * @param[in] interface Underlying network interface 01530 * @param[in] pseudoHeader IPv6 pseudo header 01531 * @param[in] fragId Fragment identification field 01532 * @param[in] fragOffset Fragment offset field 01533 * @param[in] buffer Multi-part buffer containing the payload 01534 * @param[in] offset Offset to the first byte of the payload 01535 * @param[in] hopLimit Hop Limit value 01536 * @return Error code 01537 **/ 01538 01539 error_t ipv6SendPacket(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, 01540 uint32_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t hopLimit) 01541 { 01542 error_t error; 01543 size_t length; 01544 Ipv6Header *packet; 01545 01546 //Calculate the length of the payload 01547 length = netBufferGetLength(buffer) - offset; 01548 01549 //Add Fragment header? 01550 if(fragOffset != 0) 01551 { 01552 Ipv6FragmentHeader *header; 01553 01554 //Is there enough space for the IPv6 header and the Fragment header? 01555 if(offset < (sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader))) 01556 return ERROR_INVALID_PARAMETER; 01557 01558 //Make room for the Fragment header 01559 offset -= sizeof(Ipv6FragmentHeader); 01560 length += sizeof(Ipv6FragmentHeader); 01561 01562 //Point to the Fragment header 01563 header = netBufferAt(buffer, offset); 01564 //Format the Fragment header 01565 header->nextHeader = pseudoHeader->nextHeader; 01566 header->reserved = 0; 01567 header->fragmentOffset = htons(fragOffset); 01568 header->identification = htonl(fragId); 01569 01570 //Make room for the IPv6 header 01571 offset -= sizeof(Ipv6Header); 01572 length += sizeof(Ipv6Header); 01573 01574 //Point to the IPv6 header 01575 packet = netBufferAt(buffer, offset); 01576 //Properly set the Next Header field 01577 packet->nextHeader = IPV6_FRAGMENT_HEADER; 01578 } 01579 else 01580 { 01581 //Is there enough space for the IPv6 header? 01582 if(offset < sizeof(Ipv6Header)) 01583 return ERROR_INVALID_PARAMETER; 01584 01585 //Make room for the IPv6 header 01586 offset -= sizeof(Ipv6Header); 01587 length += sizeof(Ipv6Header); 01588 01589 //Point to the IPv6 header 01590 packet = netBufferAt(buffer, offset); 01591 //Properly set the Next Header field 01592 packet->nextHeader = pseudoHeader->nextHeader; 01593 } 01594 01595 //Format IPv6 header 01596 packet->version = IPV6_VERSION; 01597 packet->trafficClassH = 0; 01598 packet->trafficClassL = 0; 01599 packet->flowLabelH = 0; 01600 packet->flowLabelL = 0; 01601 packet->payloadLength = htons(length - sizeof(Ipv6Header)); 01602 packet->hopLimit = hopLimit; 01603 packet->srcAddr = pseudoHeader->srcAddr; 01604 packet->destAddr = pseudoHeader->destAddr; 01605 01606 //Check whether the source address is acceptable 01607 error = ipv6CheckSourceAddr(interface, &pseudoHeader->srcAddr); 01608 //Invalid source address? 01609 if(error) 01610 return error; 01611 01612 //Destination IPv6 address is the unspecified address? 01613 if(ipv6CompAddr(&pseudoHeader->destAddr, &IPV6_UNSPECIFIED_ADDR)) 01614 { 01615 //Destination address is not acceptable 01616 return ERROR_INVALID_ADDRESS; 01617 } 01618 //Destination address is the loopback address? 01619 else if(ipv6CompAddr(&pseudoHeader->destAddr, &IPV6_LOOPBACK_ADDR)) 01620 { 01621 //Not yet implemented... 01622 return ERROR_NOT_IMPLEMENTED; 01623 } 01624 01625 #if (ETH_SUPPORT == ENABLED) 01626 //Ethernet interface? 01627 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 01628 { 01629 Ipv6Addr destIpAddr; 01630 MacAddr destMacAddr; 01631 NdpDestCacheEntry *entry; 01632 01633 //When the sending node has a packet to send, it first examines 01634 //the Destination Cache 01635 entry = ndpFindDestCacheEntry(interface, &pseudoHeader->destAddr); 01636 01637 //Check whether a matching entry exists 01638 if(entry != NULL) 01639 { 01640 //Retrieve the address of the next-hop 01641 destIpAddr = entry->nextHop; 01642 //Update timestamp 01643 entry->timestamp = osGetSystemTime(); 01644 //No error to report 01645 error = NO_ERROR; 01646 } 01647 else 01648 { 01649 //Perform next-hop determination 01650 error = ndpSelectNextHop(interface, 01651 &pseudoHeader->destAddr, NULL, &destIpAddr); 01652 01653 //Check status code 01654 if(error == NO_ERROR) 01655 { 01656 //Create a new Destination Cache entry 01657 entry = ndpCreateDestCacheEntry(interface); 01658 01659 //Destination cache entry successfully created? 01660 if(entry != NULL) 01661 { 01662 //Destination address 01663 entry->destAddr = pseudoHeader->destAddr; 01664 //Address of the next hop 01665 entry->nextHop = destIpAddr; 01666 01667 //Initially, the PMTU value for a path is assumed to be 01668 //the MTU of the first-hop link 01669 entry->pathMtu = interface->ipv6Context.linkMtu; 01670 01671 //Set timestamp 01672 entry->timestamp = osGetSystemTime(); 01673 } 01674 } 01675 } 01676 01677 //Successful next-hop determination? 01678 if(error == NO_ERROR) 01679 { 01680 //Destination IPv6 address is a multicast address? 01681 if(ipv6IsMulticastAddr(&destIpAddr)) 01682 { 01683 //Map IPv6 multicast address to MAC-layer multicast address 01684 error = ipv6MapMulticastAddrToMac(&destIpAddr, &destMacAddr); 01685 } 01686 else 01687 { 01688 //Resolve host address using Neighbor Discovery protocol 01689 error = ndpResolve(interface, &destIpAddr, &destMacAddr); 01690 } 01691 01692 //Successful address resolution? 01693 if(error == NO_ERROR) 01694 { 01695 //Debug message 01696 TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length); 01697 //Dump IP header contents for debugging purpose 01698 ipv6DumpHeader(packet); 01699 01700 //Send Ethernet frame 01701 error = ethSendFrame(interface, &destMacAddr, buffer, offset, ETH_TYPE_IPV6); 01702 } 01703 //Address resolution is in progress? 01704 else if(error == ERROR_IN_PROGRESS) 01705 { 01706 //Debug message 01707 TRACE_INFO("Enqueuing IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length); 01708 //Dump IP header contents for debugging purpose 01709 ipv6DumpHeader(packet); 01710 01711 //Enqueue packets waiting for address resolution 01712 error = ndpEnqueuePacket(NULL, interface, &destIpAddr, buffer, offset); 01713 } 01714 //Address resolution failed? 01715 else 01716 { 01717 //Debug message 01718 TRACE_WARNING("Cannot map IPv6 address to Ethernet address!\r\n"); 01719 } 01720 } 01721 } 01722 else 01723 #endif 01724 #if (PPP_SUPPORT == ENABLED) 01725 //PPP interface? 01726 if(interface->nicDriver->type == NIC_TYPE_PPP) 01727 { 01728 //Debug message 01729 TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length); 01730 //Dump IP header contents for debugging purpose 01731 ipv6DumpHeader(packet); 01732 01733 //Send PPP frame 01734 error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IPV6); 01735 } 01736 else 01737 #endif 01738 //6LoWPAN interface? 01739 if(interface->nicDriver->type == NIC_TYPE_6LOWPAN) 01740 { 01741 //Debug message 01742 TRACE_INFO("Sending IPv6 packet (%" PRIuSIZE " bytes)...\r\n", length); 01743 //Dump IP header contents for debugging purpose 01744 ipv6DumpHeader(packet); 01745 01746 //Send the packet over the specified link 01747 error = nicSendPacket(interface, buffer, offset); 01748 } 01749 else 01750 //Unknown interface type? 01751 { 01752 //Report an error 01753 error = ERROR_INVALID_INTERFACE; 01754 } 01755 01756 //Return status code 01757 return error; 01758 } 01759 01760 01761 /** 01762 * @brief Join an IPv6 multicast group 01763 * @param[in] interface Underlying network interface 01764 * @param[in] groupAddr IPv6 Multicast address to join 01765 * @return Error code 01766 **/ 01767 01768 error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr) 01769 { 01770 error_t error; 01771 uint_t i; 01772 Ipv6FilterEntry *entry; 01773 Ipv6FilterEntry *firstFreeEntry; 01774 #if (ETH_SUPPORT == ENABLED) 01775 MacAddr macAddr; 01776 #endif 01777 01778 //The IPv6 address must be a valid multicast address 01779 if(!ipv6IsMulticastAddr(groupAddr)) 01780 return ERROR_INVALID_ADDRESS; 01781 01782 //Initialize error code 01783 error = NO_ERROR; 01784 //Keep track of the first free entry 01785 firstFreeEntry = NULL; 01786 01787 //Go through the multicast filter table 01788 for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++) 01789 { 01790 //Point to the current entry 01791 entry = &interface->ipv6Context.multicastFilter[i]; 01792 01793 //Valid entry? 01794 if(entry->refCount > 0) 01795 { 01796 //Check whether the table already contains the specified IPv6 address 01797 if(ipv6CompAddr(&entry->addr, groupAddr)) 01798 { 01799 //Increment the reference count 01800 entry->refCount++; 01801 //Successful processing 01802 return NO_ERROR; 01803 } 01804 } 01805 else 01806 { 01807 //Keep track of the first free entry 01808 if(firstFreeEntry == NULL) 01809 firstFreeEntry = entry; 01810 } 01811 } 01812 01813 //Check whether the multicast filter table is full 01814 if(firstFreeEntry == NULL) 01815 { 01816 //A new entry cannot be added 01817 return ERROR_FAILURE; 01818 } 01819 01820 #if (ETH_SUPPORT == ENABLED) 01821 //Map the IPv6 multicast address to a MAC-layer address 01822 ipv6MapMulticastAddrToMac(groupAddr, &macAddr); 01823 //Add the corresponding address to the MAC filter table 01824 error = ethAcceptMulticastAddr(interface, &macAddr); 01825 #endif 01826 01827 //MAC filter table successfully updated? 01828 if(!error) 01829 { 01830 //Now we can safely add a new entry to the table 01831 firstFreeEntry->addr = *groupAddr; 01832 //Initialize the reference count 01833 firstFreeEntry->refCount = 1; 01834 01835 #if (MLD_SUPPORT == ENABLED) 01836 //Start listening to the multicast address 01837 mldStartListening(interface, firstFreeEntry); 01838 #endif 01839 } 01840 01841 //Return status code 01842 return error; 01843 } 01844 01845 01846 /** 01847 * @brief Leave an IPv6 multicast group 01848 * @param[in] interface Underlying network interface 01849 * @param[in] groupAddr IPv6 multicast address to drop 01850 * @return Error code 01851 **/ 01852 01853 error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr) 01854 { 01855 uint_t i; 01856 Ipv6FilterEntry *entry; 01857 #if (ETH_SUPPORT == ENABLED) 01858 MacAddr macAddr; 01859 #endif 01860 01861 //The IPv6 address must be a valid multicast address 01862 if(!ipv6IsMulticastAddr(groupAddr)) 01863 return ERROR_INVALID_ADDRESS; 01864 01865 //Go through the multicast filter table 01866 for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++) 01867 { 01868 //Point to the current entry 01869 entry = &interface->ipv6Context.multicastFilter[i]; 01870 01871 //Valid entry? 01872 if(entry->refCount > 0) 01873 { 01874 //Specified IPv6 address found? 01875 if(ipv6CompAddr(&entry->addr, groupAddr)) 01876 { 01877 //Decrement the reference count 01878 entry->refCount--; 01879 01880 //Remove the entry if the reference count drops to zero 01881 if(entry->refCount == 0) 01882 { 01883 #if (MLD_SUPPORT == ENABLED) 01884 //Stop listening to the multicast address 01885 mldStopListening(interface, entry); 01886 #endif 01887 #if (ETH_SUPPORT == ENABLED) 01888 //Map the IPv6 multicast address to a MAC-layer address 01889 ipv6MapMulticastAddrToMac(groupAddr, &macAddr); 01890 //Drop the corresponding address from the MAC filter table 01891 ethDropMulticastAddr(interface, &macAddr); 01892 #endif 01893 //Remove the multicast address from the list 01894 entry->addr = IPV6_UNSPECIFIED_ADDR; 01895 } 01896 01897 //Successful processing 01898 return NO_ERROR; 01899 } 01900 } 01901 } 01902 01903 //The specified IPv6 address does not exist 01904 return ERROR_ADDRESS_NOT_FOUND; 01905 } 01906 01907 01908 /** 01909 * @brief Convert a string representation of an IPv6 address to a binary IPv6 address 01910 * @param[in] str NULL-terminated string representing the IPv6 address 01911 * @param[out] ipAddr Binary representation of the IPv6 address 01912 * @return Error code 01913 **/ 01914 01915 error_t ipv6StringToAddr(const char_t *str, Ipv6Addr *ipAddr) 01916 { 01917 error_t error; 01918 int_t i = 0; 01919 int_t j = -1; 01920 int_t k = 0; 01921 int32_t value = -1; 01922 01923 //Parse input string 01924 while(1) 01925 { 01926 //Hexadecimal digit found? 01927 if(isxdigit((uint8_t) *str)) 01928 { 01929 //First digit to be decoded? 01930 if(value < 0) 01931 value = 0; 01932 01933 //Update the value of the current 16-bit word 01934 if(isdigit((uint8_t) *str)) 01935 value = (value * 16) + (*str - '0'); 01936 else if(isupper((uint8_t) *str)) 01937 value = (value * 16) + (*str - 'A' + 10); 01938 else 01939 value = (value * 16) + (*str - 'a' + 10); 01940 01941 //Check resulting value 01942 if(value > 0xFFFF) 01943 { 01944 //The conversion failed 01945 error = ERROR_INVALID_SYNTAX; 01946 break; 01947 } 01948 } 01949 //"::" symbol found? 01950 else if(!strncmp(str, "::", 2)) 01951 { 01952 //The "::" can only appear once in an IPv6 address 01953 if(j >= 0) 01954 { 01955 //The conversion failed 01956 error = ERROR_INVALID_SYNTAX; 01957 break; 01958 } 01959 01960 //The "::" symbol is preceded by a number? 01961 if(value >= 0) 01962 { 01963 //Save the current 16-bit word 01964 ipAddr->w[i++] = htons(value); 01965 //Prepare to decode the next 16-bit word 01966 value = -1; 01967 } 01968 01969 //Save the position of the "::" symbol 01970 j = i; 01971 //Point to the next character 01972 str++; 01973 } 01974 //":" symbol found? 01975 else if(*str == ':' && i < 8) 01976 { 01977 //Each ":" must be preceded by a valid number 01978 if(value < 0) 01979 { 01980 //The conversion failed 01981 error = ERROR_INVALID_SYNTAX; 01982 break; 01983 } 01984 01985 //Save the current 16-bit word 01986 ipAddr->w[i++] = htons(value); 01987 //Prepare to decode the next 16-bit word 01988 value = -1; 01989 } 01990 //End of string detected? 01991 else if(*str == '\0' && i == 7 && j < 0) 01992 { 01993 //The NULL character must be preceded by a valid number 01994 if(value < 0) 01995 { 01996 //The conversion failed 01997 error = ERROR_INVALID_SYNTAX; 01998 } 01999 else 02000 { 02001 //Save the last 16-bit word of the IPv6 address 02002 ipAddr->w[i] = htons(value); 02003 //The conversion succeeded 02004 error = NO_ERROR; 02005 } 02006 02007 //We are done 02008 break; 02009 } 02010 else if(*str == '\0' && i < 7 && j >= 0) 02011 { 02012 //Save the last 16-bit word of the IPv6 address 02013 if(value >= 0) 02014 ipAddr->w[i++] = htons(value); 02015 02016 //Move the part of the address that follows the "::" symbol 02017 for(k = 0; k < (i - j); k++) 02018 ipAddr->w[7 - k] = ipAddr->w[i - 1 - k]; 02019 //A sequence of zeroes can now be written in place of "::" 02020 for(k = 0; k < (8 - i); k++) 02021 ipAddr->w[j + k] = 0; 02022 02023 //The conversion succeeded 02024 error = NO_ERROR; 02025 break; 02026 } 02027 //Invalid character... 02028 else 02029 { 02030 //The conversion failed 02031 error = ERROR_INVALID_SYNTAX; 02032 break; 02033 } 02034 02035 //Point to the next character 02036 str++; 02037 } 02038 02039 //Return status code 02040 return error; 02041 } 02042 02043 02044 /** 02045 * @brief Convert a binary IPv6 address to a string representation 02046 * 02047 * Call ipv6AddrToString() to convert an IPv6 address to a text representation. The 02048 * implementation of ipv6AddrToString() function follows RFC 5952 recommendations 02049 * 02050 * @param[in] ipAddr Binary representation of the IPv6 address 02051 * @param[out] str NULL-terminated string representing the IPv6 address 02052 * @return Pointer to the formatted string 02053 **/ 02054 02055 char_t *ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str) 02056 { 02057 static char_t buffer[40]; 02058 uint_t i; 02059 uint_t j; 02060 char_t *p; 02061 02062 //Best run of zeroes 02063 uint_t zeroRunStart = 0; 02064 uint_t zeroRunEnd = 0; 02065 02066 //If the NULL pointer is given as parameter, then the internal buffer is used 02067 if(str == NULL) 02068 str = buffer; 02069 02070 //Find the longest run of zeros for "::" short-handing 02071 for(i = 0; i < 8; i++) 02072 { 02073 //Compute the length of the current sequence of zeroes 02074 for(j = i; j < 8 && !ipAddr->w[j]; j++); 02075 02076 //Keep track of the longest one 02077 if((j - i) > 1 && (j - i) > (zeroRunEnd - zeroRunStart)) 02078 { 02079 //The symbol "::" should not be used to shorten just one zero field 02080 zeroRunStart = i; 02081 zeroRunEnd = j; 02082 } 02083 } 02084 02085 //Format IPv6 address 02086 for(p = str, i = 0; i < 8; i++) 02087 { 02088 //Are we inside the best run of zeroes? 02089 if(i >= zeroRunStart && i < zeroRunEnd) 02090 { 02091 //Append a separator 02092 *(p++) = ':'; 02093 //Skip the sequence of zeroes 02094 i = zeroRunEnd - 1; 02095 } 02096 else 02097 { 02098 //Add a separator between each 16-bit word 02099 if(i > 0) 02100 *(p++) = ':'; 02101 02102 //Convert the current 16-bit word to string 02103 p += sprintf(p, "%" PRIx16, ntohs(ipAddr->w[i])); 02104 } 02105 } 02106 02107 //A trailing run of zeroes has been found? 02108 if(zeroRunEnd == 8) 02109 *(p++) = ':'; 02110 02111 //Properly terminate the string 02112 *p = '\0'; 02113 02114 //Return a pointer to the formatted string 02115 return str; 02116 } 02117 02118 02119 /** 02120 * @brief Dump IPv6 header for debugging purpose 02121 * @param[in] ipHeader IPv6 header 02122 **/ 02123 02124 void ipv6DumpHeader(const Ipv6Header *ipHeader) 02125 { 02126 //Dump IPv6 header contents 02127 TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version); 02128 TRACE_DEBUG(" Traffic Class = %u\r\n", (ipHeader->trafficClassH << 4) | ipHeader->trafficClassL); 02129 TRACE_DEBUG(" Flow Label = 0x%05X\r\n", (ipHeader->flowLabelH << 16) | ntohs(ipHeader->flowLabelL)); 02130 TRACE_DEBUG(" Payload Length = %" PRIu16 "\r\n", ntohs(ipHeader->payloadLength)); 02131 TRACE_DEBUG(" Next Header = %" PRIu8 "\r\n", ipHeader->nextHeader); 02132 TRACE_DEBUG(" Hop Limit = %" PRIu8 "\r\n", ipHeader->hopLimit); 02133 TRACE_DEBUG(" Src Addr = %s\r\n", ipv6AddrToString(&ipHeader->srcAddr, NULL)); 02134 TRACE_DEBUG(" Dest Addr = %s\r\n", ipv6AddrToString(&ipHeader->destAddr, NULL)); 02135 } 02136 02137 #endif 02138
Generated on Tue Jul 12 2022 17:10:14 by
1.7.2