Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ipv6.c
Go to the documentation of this file.
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
