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.
ipv4.c
00001 /** 00002 * @file ipv4.c 00003 * @brief IPv4 (Internet Protocol Version 4) 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 * The Internet Protocol (IP) provides the functions necessary to deliver a 00028 * datagram from a source to a destination over an interconnected system of 00029 * networks. Refer to RFC 791 for complete details 00030 * 00031 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00032 * @version 1.7.6 00033 **/ 00034 00035 //Switch to the appropriate trace level 00036 #define TRACE_LEVEL IPV4_TRACE_LEVEL 00037 00038 //Dependencies 00039 #include <string.h> 00040 #include <ctype.h> 00041 #include "core/net.h" 00042 #include "core/ethernet.h" 00043 #include "core/ip.h" 00044 #include "core/udp.h" 00045 #include "core/tcp_fsm.h" 00046 #include "core/raw_socket.h" 00047 #include "ipv4/arp.h" 00048 #include "ipv4/ipv4.h" 00049 #include "ipv4/ipv4_routing.h" 00050 #include "ipv4/icmp.h" 00051 #include "ipv4/igmp.h" 00052 #include "ipv4/auto_ip.h" 00053 #include "dhcp/dhcp_client.h" 00054 #include "mdns/mdns_responder.h" 00055 #include "mibs/mib2_module.h" 00056 #include "debug.h" 00057 00058 //Check TCP/IP stack configuration 00059 #if (IPV4_SUPPORT == ENABLED) 00060 00061 00062 /** 00063 * @brief IPv4 related initialization 00064 * @param[in] interface Underlying network interface 00065 * @return Error code 00066 **/ 00067 00068 error_t ipv4Init(NetInterface *interface) 00069 { 00070 Ipv4Context *context; 00071 00072 //Point to the IPv4 context 00073 context = &interface->ipv4Context; 00074 00075 //Clear the IPv4 context 00076 memset(context, 0, sizeof(Ipv4Context)); 00077 00078 //Initialize interface specific variables 00079 context->linkMtu = interface->nicDriver->mtu; 00080 context->isRouter = FALSE; 00081 00082 //Identification field is primarily used to identify 00083 //fragments of an original IP datagram 00084 context->identification = 0; 00085 00086 //Initialize the list of DNS servers 00087 memset(context->dnsServerList, 0, sizeof(context->dnsServerList)); 00088 //Initialize the multicast filter table 00089 memset(context->multicastFilter, 0, sizeof(context->multicastFilter)); 00090 00091 #if (IPV4_FRAG_SUPPORT == ENABLED) 00092 //Initialize the reassembly queue 00093 memset(context->fragQueue, 0, sizeof(context->fragQueue)); 00094 #endif 00095 00096 //Successful initialization 00097 return NO_ERROR; 00098 } 00099 00100 00101 /** 00102 * @brief Assign host address 00103 * @param[in] interface Pointer to the desired network interface 00104 * @param[in] addr IPv4 host address 00105 * @return Error code 00106 **/ 00107 00108 error_t ipv4SetHostAddr(NetInterface *interface, Ipv4Addr addr) 00109 { 00110 //Check parameters 00111 if(interface == NULL) 00112 return ERROR_INVALID_PARAMETER; 00113 00114 //The IPv4 address must be a valid unicast address 00115 if(ipv4IsMulticastAddr(addr)) 00116 return ERROR_INVALID_ADDRESS; 00117 00118 //Get exclusive access 00119 osAcquireMutex(&netMutex); 00120 00121 //Set up host address 00122 interface->ipv4Context.addr = addr; 00123 //Clear conflict flag 00124 interface->ipv4Context.addrConflict = FALSE; 00125 00126 //Check whether the new host address is valid 00127 if(addr != IPV4_UNSPECIFIED_ADDR) 00128 { 00129 //The use of the IPv4 address is now unrestricted 00130 interface->ipv4Context.addrState = IPV4_ADDR_STATE_VALID; 00131 } 00132 else 00133 { 00134 //The IPv4 address is no longer valid 00135 interface->ipv4Context.addrState = IPV4_ADDR_STATE_INVALID; 00136 } 00137 00138 #if (MDNS_RESPONDER_SUPPORT == ENABLED) 00139 //Restart mDNS probing process 00140 mdnsResponderStartProbing(interface->mdnsResponderContext); 00141 #endif 00142 00143 //Release exclusive access 00144 osReleaseMutex(&netMutex); 00145 00146 //Successful processing 00147 return NO_ERROR; 00148 } 00149 00150 00151 /** 00152 * @brief Retrieve host address 00153 * @param[in] interface Pointer to the desired network interface 00154 * @param[out] addr IPv4 host address 00155 * @return Error code 00156 **/ 00157 00158 error_t ipv4GetHostAddr(NetInterface *interface, Ipv4Addr *addr) 00159 { 00160 //Check parameters 00161 if(interface == NULL || addr == NULL) 00162 return ERROR_INVALID_PARAMETER; 00163 00164 //Get exclusive access 00165 osAcquireMutex(&netMutex); 00166 00167 //Check whether the host address is valid 00168 if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID) 00169 { 00170 //Get IPv4 address 00171 *addr = interface->ipv4Context.addr; 00172 } 00173 else 00174 { 00175 //Return the unspecified address when no address has been assigned 00176 *addr = IPV4_UNSPECIFIED_ADDR; 00177 } 00178 00179 //Release exclusive access 00180 osReleaseMutex(&netMutex); 00181 00182 //Successful processing 00183 return NO_ERROR; 00184 } 00185 00186 00187 /** 00188 * @brief Configure subnet mask 00189 * @param[in] interface Pointer to the desired network interface 00190 * @param[in] mask Subnet mask 00191 * @return Error code 00192 **/ 00193 00194 error_t ipv4SetSubnetMask(NetInterface *interface, Ipv4Addr mask) 00195 { 00196 //Check parameters 00197 if(interface == NULL) 00198 return ERROR_INVALID_PARAMETER; 00199 00200 //Get exclusive access 00201 osAcquireMutex(&netMutex); 00202 //Set up subnet mask 00203 interface->ipv4Context.subnetMask = mask; 00204 //Release exclusive access 00205 osReleaseMutex(&netMutex); 00206 00207 //Successful processing 00208 return NO_ERROR; 00209 } 00210 00211 00212 /** 00213 * @brief Retrieve subnet mask 00214 * @param[in] interface Pointer to the desired network interface 00215 * @param[out] mask Subnet mask 00216 * @return Error code 00217 **/ 00218 00219 error_t ipv4GetSubnetMask(NetInterface *interface, Ipv4Addr *mask) 00220 { 00221 //Check parameters 00222 if(interface == NULL || mask == NULL) 00223 return ERROR_INVALID_PARAMETER; 00224 00225 //Get exclusive access 00226 osAcquireMutex(&netMutex); 00227 //Get subnet mask 00228 *mask = interface->ipv4Context.subnetMask; 00229 //Release exclusive access 00230 osReleaseMutex(&netMutex); 00231 00232 //Successful processing 00233 return NO_ERROR; 00234 } 00235 00236 00237 /** 00238 * @brief Configure default gateway 00239 * @param[in] interface Pointer to the desired network interface 00240 * @param[in] addr Default gateway address 00241 * @return Error code 00242 **/ 00243 00244 error_t ipv4SetDefaultGateway(NetInterface *interface, Ipv4Addr addr) 00245 { 00246 //Check parameters 00247 if(interface == NULL) 00248 return ERROR_INVALID_PARAMETER; 00249 00250 //The IPv4 address must be a valid unicast address 00251 if(ipv4IsMulticastAddr(addr)) 00252 return ERROR_INVALID_ADDRESS; 00253 00254 //Get exclusive access 00255 osAcquireMutex(&netMutex); 00256 //Set up default gateway address 00257 interface->ipv4Context.defaultGateway = addr; 00258 //Release exclusive access 00259 osReleaseMutex(&netMutex); 00260 00261 //Successful processing 00262 return NO_ERROR; 00263 } 00264 00265 00266 /** 00267 * @brief Retrieve default gateway 00268 * @param[in] interface Pointer to the desired network interface 00269 * @param[out] addr Default gateway address 00270 * @return Error code 00271 **/ 00272 00273 error_t ipv4GetDefaultGateway(NetInterface *interface, Ipv4Addr *addr) 00274 { 00275 //Check parameters 00276 if(interface == NULL || addr == NULL) 00277 return ERROR_INVALID_PARAMETER; 00278 00279 //Get exclusive access 00280 osAcquireMutex(&netMutex); 00281 //Get default gateway address 00282 *addr = interface->ipv4Context.defaultGateway; 00283 //Release exclusive access 00284 osReleaseMutex(&netMutex); 00285 00286 //Successful processing 00287 return NO_ERROR; 00288 } 00289 00290 00291 /** 00292 * @brief Configure DNS server 00293 * @param[in] interface Pointer to the desired network interface 00294 * @param[in] index This parameter selects between the primary and secondary DNS server 00295 * @param[in] addr DNS server address 00296 * @return Error code 00297 **/ 00298 00299 error_t ipv4SetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr addr) 00300 { 00301 //Check parameters 00302 if(interface == NULL) 00303 return ERROR_INVALID_PARAMETER; 00304 00305 //Make sure that the index is valid 00306 if(index >= IPV4_DNS_SERVER_LIST_SIZE) 00307 return ERROR_OUT_OF_RANGE; 00308 00309 //The IPv4 address must be a valid unicast address 00310 if(ipv4IsMulticastAddr(addr)) 00311 return ERROR_INVALID_ADDRESS; 00312 00313 //Get exclusive access 00314 osAcquireMutex(&netMutex); 00315 //Set up DNS server address 00316 interface->ipv4Context.dnsServerList[index] = addr; 00317 //Release exclusive access 00318 osReleaseMutex(&netMutex); 00319 00320 //Successful processing 00321 return NO_ERROR; 00322 } 00323 00324 00325 /** 00326 * @brief Retrieve DNS server 00327 * @param[in] interface Pointer to the desired network interface 00328 * @param[in] index This parameter selects between the primary and secondary DNS server 00329 * @param[out] addr DNS server address 00330 * @return Error code 00331 **/ 00332 00333 error_t ipv4GetDnsServer(NetInterface *interface, uint_t index, Ipv4Addr *addr) 00334 { 00335 //Check parameters 00336 if(interface == NULL || addr == NULL) 00337 return ERROR_INVALID_PARAMETER; 00338 00339 //Make sure that the index is valid 00340 if(index >= IPV4_DNS_SERVER_LIST_SIZE) 00341 { 00342 //Return the unspecified address when the index is out of range 00343 *addr = IPV4_UNSPECIFIED_ADDR; 00344 //Report an error 00345 return ERROR_OUT_OF_RANGE; 00346 } 00347 00348 //Get exclusive access 00349 osAcquireMutex(&netMutex); 00350 //Get DNS server address 00351 *addr = interface->ipv4Context.dnsServerList[index]; 00352 //Release exclusive access 00353 osReleaseMutex(&netMutex); 00354 00355 //Successful processing 00356 return NO_ERROR; 00357 } 00358 00359 00360 /** 00361 * @brief Get IPv4 broadcast address 00362 * @param[in] interface Pointer to the desired network interface 00363 * @param[out] addr IPv4 broadcast address 00364 **/ 00365 00366 error_t ipv4GetBroadcastAddr(NetInterface *interface, Ipv4Addr *addr) 00367 { 00368 //Check parameters 00369 if(interface == NULL || addr == NULL) 00370 return ERROR_INVALID_PARAMETER; 00371 00372 //The broadcast address is obtained by performing a bitwise OR operation 00373 //between the bit complement of the subnet mask and the host IP address 00374 *addr = interface->ipv4Context.addr; 00375 *addr |= ~interface->ipv4Context.subnetMask; 00376 00377 //Successful processing 00378 return NO_ERROR; 00379 } 00380 00381 00382 /** 00383 * @brief Callback function for link change event 00384 * @param[in] interface Underlying network interface 00385 **/ 00386 00387 void ipv4LinkChangeEvent(NetInterface *interface) 00388 { 00389 Ipv4Context *context; 00390 00391 //Point to the IPv4 context 00392 context = &interface->ipv4Context; 00393 00394 //Restore default MTU 00395 context->linkMtu = interface->nicDriver->mtu; 00396 00397 #if (ETH_SUPPORT == ENABLED) 00398 //Flush ARP cache contents 00399 arpFlushCache(interface); 00400 #endif 00401 00402 #if (IPV4_FRAG_SUPPORT == ENABLED) 00403 //Flush the reassembly queue 00404 ipv4FlushFragQueue(interface); 00405 #endif 00406 00407 #if (IGMP_SUPPORT == ENABLED) 00408 //Notify IGMP of link state changes 00409 igmpLinkChangeEvent(interface); 00410 #endif 00411 00412 #if (AUTO_IP_SUPPORT == ENABLED) 00413 //Notify Auto-IP of link state changes 00414 autoIpLinkChangeEvent(interface->autoIpContext); 00415 #endif 00416 00417 #if (DHCP_CLIENT_SUPPORT == ENABLED) 00418 //Notify the DHCP client of link state changes 00419 dhcpClientLinkChangeEvent(interface->dhcpClientContext); 00420 #endif 00421 } 00422 00423 00424 /** 00425 * @brief Incoming IPv4 packet processing 00426 * @param[in] interface Underlying network interface 00427 * @param[in] packet Incoming IPv4 packet 00428 * @param[in] length Packet length including header and payload 00429 **/ 00430 00431 void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length) 00432 { 00433 //Total number of input datagrams received from interfaces, 00434 //including those received in error 00435 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInReceives, 1); 00436 00437 //Ensure the packet length is greater than 20 bytes 00438 if(length < sizeof(Ipv4Header)) 00439 { 00440 //Number of input datagrams discarded due to errors in their IP headers 00441 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00442 //Discard the received packet 00443 return; 00444 } 00445 00446 //Debug message 00447 TRACE_INFO("IPv4 packet received (%" PRIuSIZE " bytes)...\r\n", length); 00448 //Dump IP header contents for debugging purpose 00449 ipv4DumpHeader(packet); 00450 00451 //A packet whose version number is not 4 must be silently discarded 00452 if(packet->version != IPV4_VERSION) 00453 { 00454 //Number of input datagrams discarded due to errors in their IP headers 00455 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00456 //Discard the received packet 00457 return; 00458 } 00459 00460 //Valid IPv4 header shall contains more than five 32-bit words 00461 if(packet->headerLength < 5) 00462 { 00463 //Number of input datagrams discarded due to errors in their IP headers 00464 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00465 //Discard the received packet 00466 return; 00467 } 00468 00469 //Ensure the total length is correct before processing the packet 00470 if(ntohs(packet->totalLength) < (packet->headerLength * 4)) 00471 { 00472 //Number of input datagrams discarded due to errors in their IP headers 00473 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00474 //Discard the received packet 00475 return; 00476 } 00477 if(ntohs(packet->totalLength) > length) 00478 { 00479 //Number of input datagrams discarded due to errors in their IP headers 00480 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00481 //Discard the received packet 00482 return; 00483 } 00484 00485 //Source address filtering 00486 if(ipv4CheckSourceAddr(interface, packet->srcAddr)) 00487 { 00488 //Number of input datagrams discarded due to errors in their IP headers 00489 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00490 //Discard the received packet 00491 return; 00492 } 00493 00494 #if defined(IPV4_PACKET_FORWARD_HOOK) 00495 IPV4_PACKET_FORWARD_HOOK(interface, packet, length); 00496 #else 00497 //Destination address filtering 00498 if(ipv4CheckDestAddr(interface, packet->destAddr)) 00499 { 00500 #if(IPV4_ROUTING_SUPPORT == ENABLED) 00501 NetBuffer1 buffer; 00502 00503 //Unfragmented datagrams fit in a single chunk 00504 buffer.chunkCount = 1; 00505 buffer.maxChunkCount = 1; 00506 buffer.chunk[0].address = packet; 00507 buffer.chunk[0].length = length; 00508 00509 //Forward the packet according to the routing table 00510 ipv4ForwardPacket(interface, (NetBuffer *) &buffer, 0); 00511 #else 00512 //Number of input datagrams discarded because the destination IP 00513 //address was not a valid address 00514 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInAddrErrors, 1); 00515 #endif 00516 //We are done 00517 return; 00518 } 00519 #endif 00520 00521 //Packets addressed to a tentative address should be silently discarded 00522 if(ipv4IsTentativeAddr(interface, packet->destAddr)) 00523 { 00524 //Number of input datagrams discarded because the destination IP 00525 //address was not a valid address 00526 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInAddrErrors, 1); 00527 //Discard the received packet 00528 return; 00529 } 00530 00531 //The host must verify the IP header checksum on every received 00532 //datagram and silently discard every datagram that has a bad 00533 //checksum (see RFC 1122 3.2.1.2) 00534 if(ipCalcChecksum(packet, packet->headerLength * 4) != 0x0000) 00535 { 00536 //Debug message 00537 TRACE_WARNING("Wrong IP header checksum!\r\n"); 00538 //Number of input datagrams discarded due to errors in their IP headers 00539 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInHdrErrors, 1); 00540 //Discard incoming packet 00541 return; 00542 } 00543 00544 //Convert the total length from network byte order 00545 length = ntohs(packet->totalLength); 00546 00547 //A fragmented packet was received? 00548 if(ntohs(packet->fragmentOffset) & (IPV4_FLAG_MF | IPV4_OFFSET_MASK)) 00549 { 00550 #if (IPV4_FRAG_SUPPORT == ENABLED) 00551 //Reassemble the original datagram 00552 ipv4ReassembleDatagram(interface, packet, length); 00553 #endif 00554 } 00555 else 00556 { 00557 NetBuffer1 buffer; 00558 00559 //Unfragmented datagrams fit in a single chunk 00560 buffer.chunkCount = 1; 00561 buffer.maxChunkCount = 1; 00562 buffer.chunk[0].address = packet; 00563 buffer.chunk[0].length = length; 00564 00565 //Pass the IPv4 datagram to the higher protocol layer 00566 ipv4ProcessDatagram(interface, (NetBuffer *) &buffer); 00567 } 00568 } 00569 00570 00571 /** 00572 * @brief Incoming IPv4 datagram processing 00573 * @param[in] interface Underlying network interface 00574 * @param[in] buffer Multi-part buffer that holds the incoming IPv4 datagram 00575 **/ 00576 00577 void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer) 00578 { 00579 error_t error; 00580 size_t offset; 00581 size_t length; 00582 Ipv4Header *header; 00583 IpPseudoHeader pseudoHeader; 00584 00585 //Retrieve the length of the IPv4 datagram 00586 length = netBufferGetLength(buffer); 00587 00588 //Point to the IPv4 header 00589 header = netBufferAt(buffer, 0); 00590 //Sanity check 00591 if(header == NULL) 00592 return; 00593 00594 //Debug message 00595 TRACE_INFO("IPv4 datagram received (%" PRIuSIZE " bytes)...\r\n", length); 00596 //Dump IP header contents for debugging purpose 00597 ipv4DumpHeader(header); 00598 00599 //Get the offset to the payload 00600 offset = header->headerLength * 4; 00601 //Compute the length of the payload 00602 length -= header->headerLength * 4; 00603 00604 //Form the IPv4 pseudo header 00605 pseudoHeader.length = sizeof(Ipv4PseudoHeader); 00606 pseudoHeader.ipv4Data.srcAddr = header->srcAddr; 00607 pseudoHeader.ipv4Data.destAddr = header->destAddr; 00608 pseudoHeader.ipv4Data.reserved = 0; 00609 pseudoHeader.ipv4Data.protocol = header->protocol; 00610 pseudoHeader.ipv4Data.length = htons(length); 00611 00612 #if defined(IPV4_DATAGRAM_FORWARD_HOOK) 00613 IPV4_DATAGRAM_FORWARD_HOOK(interface, &pseudoHeader, buffer, offset); 00614 #endif 00615 00616 //Check the protocol field 00617 switch(header->protocol) 00618 { 00619 //ICMP protocol? 00620 case IPV4_PROTOCOL_ICMP: 00621 //Process incoming ICMP message 00622 icmpProcessMessage(interface, header->srcAddr, buffer, offset); 00623 #if (RAW_SOCKET_SUPPORT == ENABLED) 00624 //Allow raw sockets to process ICMP messages 00625 rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset); 00626 #endif 00627 //No error to report 00628 error = NO_ERROR; 00629 //Continue processing 00630 break; 00631 00632 #if (IGMP_SUPPORT == ENABLED) 00633 //IGMP protocol? 00634 case IPV4_PROTOCOL_IGMP: 00635 //Process incoming IGMP message 00636 igmpProcessMessage(interface, buffer, offset); 00637 #if (RAW_SOCKET_SUPPORT == ENABLED) 00638 //Allow raw sockets to process IGMP messages 00639 rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset); 00640 #endif 00641 //No error to report 00642 error = NO_ERROR; 00643 //Continue processing 00644 break; 00645 #endif 00646 00647 #if (TCP_SUPPORT == ENABLED) 00648 //TCP protocol? 00649 case IPV4_PROTOCOL_TCP: 00650 //Process incoming TCP segment 00651 tcpProcessSegment(interface, &pseudoHeader, buffer, offset); 00652 //No error to report 00653 error = NO_ERROR; 00654 //Continue processing 00655 break; 00656 #endif 00657 00658 #if (UDP_SUPPORT == ENABLED) 00659 //UDP protocol? 00660 case IPV4_PROTOCOL_UDP: 00661 //Process incoming UDP datagram 00662 error = udpProcessDatagram(interface, &pseudoHeader, buffer, offset); 00663 //Continue processing 00664 break; 00665 #endif 00666 00667 //Unknown protocol? 00668 default: 00669 #if (RAW_SOCKET_SUPPORT == ENABLED) 00670 //Allow raw sockets to process IPv4 packets 00671 error = rawSocketProcessIpPacket(interface, &pseudoHeader, buffer, offset); 00672 #else 00673 //Report an error 00674 error = ERROR_PROTOCOL_UNREACHABLE; 00675 #endif 00676 //Continue processing 00677 break; 00678 } 00679 00680 //Unreachable protocol? 00681 if(error == ERROR_PROTOCOL_UNREACHABLE) 00682 { 00683 //Number of locally-addressed datagrams received successfully but 00684 //discarded because of an unknown or unsupported protocol 00685 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInUnknownProtos, 1); 00686 00687 //Send a Destination Unreachable message 00688 icmpSendErrorMessage(interface, ICMP_TYPE_DEST_UNREACHABLE, 00689 ICMP_CODE_PROTOCOL_UNREACHABLE, 0, buffer, 0); 00690 } 00691 else 00692 { 00693 //Total number of input datagrams successfully delivered to IP 00694 //user-protocols 00695 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipInDelivers, 1); 00696 } 00697 00698 //Unreachable port? 00699 if(error == ERROR_PORT_UNREACHABLE) 00700 { 00701 //Send a Destination Unreachable message 00702 icmpSendErrorMessage(interface, ICMP_TYPE_DEST_UNREACHABLE, 00703 ICMP_CODE_PORT_UNREACHABLE, 0, buffer, 0); 00704 } 00705 } 00706 00707 00708 /** 00709 * @brief Send an IPv4 datagram 00710 * @param[in] interface Underlying network interface 00711 * @param[in] pseudoHeader IPv4 pseudo header 00712 * @param[in] buffer Multi-part buffer containing the payload 00713 * @param[in] offset Offset to the first byte of the payload 00714 * @param[in] ttl TTL value. Default Time-To-Live is used when this parameter is zero 00715 * @return Error code 00716 **/ 00717 00718 error_t ipv4SendDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, 00719 NetBuffer *buffer, size_t offset, uint8_t ttl) 00720 { 00721 error_t error; 00722 size_t length; 00723 uint16_t id; 00724 00725 //Total number of IP datagrams which local IP user-protocols supplied 00726 //to IP in requests for transmission 00727 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipOutRequests, 1); 00728 00729 //Retrieve the length of payload 00730 length = netBufferGetLength(buffer) - offset; 00731 00732 //Check whether the TTL value is zero 00733 if(ttl == 0) 00734 { 00735 //Use default Time-To-Live value 00736 ttl = IPV4_DEFAULT_TTL; 00737 } 00738 00739 //Identification field is primarily used to identify 00740 //fragments of an original IP datagram 00741 id = interface->ipv4Context.identification++; 00742 00743 //If the payload length is smaller than the network 00744 //interface MTU then no fragmentation is needed 00745 if((length + sizeof(Ipv4Header)) <= interface->ipv4Context.linkMtu) 00746 { 00747 //Send data as is 00748 error = ipv4SendPacket(interface, 00749 pseudoHeader, id, 0, buffer, offset, ttl); 00750 } 00751 //If the payload length exceeds the network interface MTU 00752 //then the device must fragment the data 00753 else 00754 { 00755 #if (IPV4_FRAG_SUPPORT == ENABLED) 00756 //Fragment IP datagram into smaller packets 00757 error = ipv4FragmentDatagram(interface, 00758 pseudoHeader, id, buffer, offset, ttl); 00759 #else 00760 //Fragmentation is not supported 00761 error = ERROR_MESSAGE_TOO_LONG; 00762 #endif 00763 } 00764 00765 //Return status code 00766 return error; 00767 } 00768 00769 00770 /** 00771 * @brief Send an IPv4 packet 00772 * @param[in] interface Underlying network interface 00773 * @param[in] pseudoHeader IPv4 pseudo header 00774 * @param[in] fragId Fragment identification field 00775 * @param[in] fragOffset Fragment offset field 00776 * @param[in] buffer Multi-part buffer containing the payload 00777 * @param[in] offset Offset to the first byte of the payload 00778 * @param[in] ttl Time-To-Live value 00779 * @return Error code 00780 **/ 00781 00782 error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, 00783 uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl) 00784 { 00785 error_t error; 00786 size_t length; 00787 Ipv4Header *packet; 00788 00789 //Is there enough space for the IPv4 header? 00790 if(offset < sizeof(Ipv4Header)) 00791 return ERROR_INVALID_PARAMETER; 00792 00793 //Make room for the header 00794 offset -= sizeof(Ipv4Header); 00795 //Calculate the size of the entire packet, including header and data 00796 length = netBufferGetLength(buffer) - offset; 00797 00798 //Point to the IPv4 header 00799 packet = netBufferAt(buffer, offset); 00800 00801 //Format IPv4 header 00802 packet->version = IPV4_VERSION; 00803 packet->headerLength = 5; 00804 packet->typeOfService = 0; 00805 packet->totalLength = htons(length); 00806 packet->identification = htons(fragId); 00807 packet->fragmentOffset = htons(fragOffset); 00808 packet->timeToLive = ttl; 00809 packet->protocol = pseudoHeader->protocol; 00810 packet->headerChecksum = 0; 00811 packet->srcAddr = pseudoHeader->srcAddr; 00812 packet->destAddr = pseudoHeader->destAddr; 00813 00814 //Calculate IP header checksum 00815 packet->headerChecksum = ipCalcChecksumEx(buffer, offset, packet->headerLength * 4); 00816 00817 //Ensure the source address is valid 00818 error = ipv4CheckSourceAddr(interface, pseudoHeader->srcAddr); 00819 //Invalid source address? 00820 if(error) 00821 return error; 00822 00823 //Destination address is the unspecified address? 00824 if(pseudoHeader->destAddr == IPV4_UNSPECIFIED_ADDR) 00825 { 00826 //Destination address is not acceptable 00827 return ERROR_INVALID_ADDRESS; 00828 } 00829 //Destination address is the loopback address? 00830 else if(pseudoHeader->destAddr == IPV4_LOOPBACK_ADDR) 00831 { 00832 //Not yet implemented... 00833 return ERROR_NOT_IMPLEMENTED; 00834 } 00835 00836 #if (ETH_SUPPORT == ENABLED) 00837 //Ethernet interface? 00838 if(interface->nicDriver->type == NIC_TYPE_ETHERNET) 00839 { 00840 Ipv4Addr destIpAddr; 00841 MacAddr destMacAddr; 00842 00843 //Get the destination IPv4 address 00844 destIpAddr = pseudoHeader->destAddr; 00845 00846 //Destination address is a broadcast address? 00847 if(ipv4IsBroadcastAddr(interface, destIpAddr)) 00848 { 00849 //Use of the broadcast MAC address to send the packet 00850 destMacAddr = MAC_BROADCAST_ADDR; 00851 //No error to report 00852 error = NO_ERROR; 00853 } 00854 //Destination address is a multicast address? 00855 else if(ipv4IsMulticastAddr(destIpAddr)) 00856 { 00857 //Map IPv4 multicast address to MAC-layer multicast address 00858 error = ipv4MapMulticastAddrToMac(destIpAddr, &destMacAddr); 00859 } 00860 //Source or destination address is a link-local address? 00861 else if(ipv4IsLinkLocalAddr(pseudoHeader->srcAddr) || 00862 ipv4IsLinkLocalAddr(destIpAddr)) 00863 { 00864 //Packets with a link-local source or destination address are not 00865 //routable off the link 00866 error = arpResolve(interface, destIpAddr, &destMacAddr); 00867 } 00868 //Destination host is on the local subnet? 00869 else if(ipv4IsOnLocalSubnet(interface, destIpAddr)) 00870 { 00871 //Resolve destination address before sending the packet 00872 error = arpResolve(interface, destIpAddr, &destMacAddr); 00873 } 00874 //Destination host is outside the local subnet? 00875 else 00876 { 00877 //Make sure the default gateway is properly set 00878 if(interface->ipv4Context.defaultGateway != IPV4_UNSPECIFIED_ADDR) 00879 { 00880 //Use the default gateway to forward the packet 00881 destIpAddr = interface->ipv4Context.defaultGateway; 00882 //Perform address resolution 00883 error = arpResolve(interface, destIpAddr, &destMacAddr); 00884 } 00885 else 00886 { 00887 //Number of IP datagrams discarded because no route could be found 00888 //to transmit them to their destination 00889 MIB2_INC_COUNTER32(mib2Base.ipGroup.ipOutNoRoutes, 1); 00890 00891 //Report an error 00892 error = ERROR_NO_ROUTE; 00893 } 00894 } 00895 00896 //Successful address resolution? 00897 if(!error) 00898 { 00899 //Debug message 00900 TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length); 00901 //Dump IP header contents for debugging purpose 00902 ipv4DumpHeader(packet); 00903 00904 //Send Ethernet frame 00905 error = ethSendFrame(interface, &destMacAddr, buffer, offset, ETH_TYPE_IPV4); 00906 } 00907 //Address resolution is in progress? 00908 else if(error == ERROR_IN_PROGRESS) 00909 { 00910 //Debug message 00911 TRACE_INFO("Enqueuing IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length); 00912 //Dump IP header contents for debugging purpose 00913 ipv4DumpHeader(packet); 00914 00915 //Enqueue packets waiting for address resolution 00916 error = arpEnqueuePacket(interface, destIpAddr, buffer, offset); 00917 } 00918 //Address resolution failed? 00919 else 00920 { 00921 //Debug message 00922 TRACE_WARNING("Cannot map IPv4 address to Ethernet address!\r\n"); 00923 } 00924 } 00925 else 00926 #endif 00927 #if (PPP_SUPPORT == ENABLED) 00928 //PPP interface? 00929 if(interface->nicDriver->type == NIC_TYPE_PPP) 00930 { 00931 //Debug message 00932 TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length); 00933 //Dump IP header contents for debugging purpose 00934 ipv4DumpHeader(packet); 00935 00936 //Send PPP frame 00937 error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IP); 00938 } 00939 else 00940 #endif 00941 //Unknown interface type? 00942 { 00943 //Report an error 00944 error = ERROR_INVALID_INTERFACE; 00945 } 00946 00947 //Return status code 00948 return error; 00949 } 00950 00951 00952 /** 00953 * @brief Source IPv4 address filtering 00954 * @param[in] interface Underlying network interface 00955 * @param[in] ipAddr Source IPv4 address to be checked 00956 * @return Error code 00957 **/ 00958 00959 error_t ipv4CheckSourceAddr(NetInterface *interface, Ipv4Addr ipAddr) 00960 { 00961 //Broadcast and multicast addresses must not be used as source 00962 //address (see RFC 1122 3.2.1.3) 00963 if(ipv4IsBroadcastAddr(interface, ipAddr) || ipv4IsMulticastAddr(ipAddr)) 00964 { 00965 //Debug message 00966 TRACE_WARNING("Wrong source IPv4 address!\r\n"); 00967 //The source address not is acceptable 00968 return ERROR_INVALID_ADDRESS; 00969 } 00970 00971 //The source address is acceptable 00972 return NO_ERROR; 00973 } 00974 00975 00976 /** 00977 * @brief Destination IPv4 address filtering 00978 * @param[in] interface Underlying network interface 00979 * @param[in] ipAddr Destination IPv4 address to be checked 00980 * @return Error code 00981 **/ 00982 00983 error_t ipv4CheckDestAddr(NetInterface *interface, Ipv4Addr ipAddr) 00984 { 00985 error_t error; 00986 uint_t i; 00987 Ipv4FilterEntry *entry; 00988 00989 //Filter out any invalid addresses 00990 error = ERROR_INVALID_ADDRESS; 00991 00992 //Broadcast address? 00993 if(ipv4IsBroadcastAddr(interface, ipAddr)) 00994 { 00995 //Always accept broadcast address 00996 error = NO_ERROR; 00997 } 00998 //Multicast address? 00999 else if(ipv4IsMulticastAddr(ipAddr)) 01000 { 01001 //Go through the multicast filter table 01002 for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++) 01003 { 01004 //Point to the current entry 01005 entry = &interface->ipv4Context.multicastFilter[i]; 01006 01007 //Valid entry? 01008 if(entry->refCount > 0) 01009 { 01010 //Check whether the destination IPv4 address matches 01011 //a relevant multicast address 01012 if(entry->addr == ipAddr) 01013 { 01014 //The multicast address is acceptable 01015 error = NO_ERROR; 01016 //Stop immediately 01017 break; 01018 } 01019 } 01020 } 01021 } 01022 //Unicast address? 01023 else 01024 { 01025 //Valid host address? 01026 if(interface->ipv4Context.addrState != IPV4_ADDR_STATE_INVALID) 01027 { 01028 //Check whether the destination address matches the host address 01029 if(interface->ipv4Context.addr == ipAddr) 01030 { 01031 //The destination address is acceptable 01032 error = NO_ERROR; 01033 } 01034 } 01035 } 01036 01037 //Return status code 01038 return error; 01039 } 01040 01041 01042 /** 01043 * @brief IPv4 source address selection 01044 * 01045 * This function selects the source address and the relevant network interface 01046 * to be used in order to join the specified destination address 01047 * 01048 * @param[in,out] interface A pointer to a valid network interface may be provided as 01049 * a hint. The function returns a pointer identifying the interface to be used 01050 * @param[in] destAddr Destination IPv4 address 01051 * @param[out] srcAddr Local IPv4 address to be used 01052 * @return Error code 01053 **/ 01054 01055 error_t ipv4SelectSourceAddr(NetInterface **interface, 01056 Ipv4Addr destAddr, Ipv4Addr *srcAddr) 01057 { 01058 uint_t i; 01059 NetInterface *currentInterface; 01060 NetInterface *bestInterface; 01061 01062 //Initialize variables 01063 bestInterface = NULL; 01064 01065 //Loop through network interfaces 01066 for(i = 0; i < NET_INTERFACE_COUNT; i++) 01067 { 01068 //Point to the current interface 01069 currentInterface = &netInterface[i]; 01070 01071 //A network interface may be provided as a hint... 01072 if(*interface != currentInterface && *interface != NULL) 01073 { 01074 //Select the next interface in the list 01075 continue; 01076 } 01077 01078 //Check the state of the address 01079 if(currentInterface->ipv4Context.addrState != IPV4_ADDR_STATE_VALID) 01080 { 01081 //Select the next interface in the list 01082 continue; 01083 } 01084 01085 //Select the first interface as default 01086 if(bestInterface == NULL) 01087 { 01088 //Give the current interface the higher precedence 01089 bestInterface = currentInterface; 01090 //Select the next interface in the list 01091 continue; 01092 } 01093 01094 //Prefer same address 01095 if(bestInterface->ipv4Context.addr == destAddr) 01096 { 01097 //Select the next interface in the list 01098 continue; 01099 } 01100 else if(currentInterface->ipv4Context.addr == destAddr) 01101 { 01102 //Give the current interface the higher precedence 01103 bestInterface = currentInterface; 01104 //Select the next interface in the list 01105 continue; 01106 } 01107 01108 //Prefer appropriate scope 01109 if(ipv4GetAddrScope(currentInterface->ipv4Context.addr) < 01110 ipv4GetAddrScope(bestInterface->ipv4Context.addr)) 01111 { 01112 if(ipv4GetAddrScope(currentInterface->ipv4Context.addr) >= 01113 ipv4GetAddrScope(destAddr)) 01114 { 01115 //Give the current interface the higher precedence 01116 bestInterface = currentInterface; 01117 } 01118 01119 //Select the next interface in the list 01120 continue; 01121 } 01122 else if(ipv4GetAddrScope(bestInterface->ipv4Context.addr) < 01123 ipv4GetAddrScope(currentInterface->ipv4Context.addr)) 01124 { 01125 if(ipv4GetAddrScope(bestInterface->ipv4Context.addr) < 01126 ipv4GetAddrScope(destAddr)) 01127 { 01128 //Give the current interface the higher precedence 01129 bestInterface = currentInterface; 01130 } 01131 01132 //Select the next interface in the list 01133 continue; 01134 } 01135 01136 //Prefer appropriate subnet mask 01137 if(ipv4IsOnLocalSubnet(bestInterface, destAddr)) 01138 { 01139 //Select the next interface in the list 01140 continue; 01141 } 01142 else if(ipv4IsOnLocalSubnet(currentInterface, destAddr)) 01143 { 01144 //Give the current interface the higher precedence 01145 bestInterface = currentInterface; 01146 //Select the next interface in the list 01147 continue; 01148 } 01149 } 01150 01151 //Source address selection failed? 01152 if(bestInterface == NULL) 01153 { 01154 //Report an error 01155 return ERROR_NO_ADDRESS; 01156 } 01157 01158 //Return the out-going interface and the source address to be used 01159 *interface = bestInterface; 01160 *srcAddr = bestInterface->ipv4Context.addr; 01161 01162 //Successful source address selection 01163 return NO_ERROR; 01164 } 01165 01166 01167 /** 01168 * @brief Check whether an IPv4 address is a broadcast address 01169 * @param[in] interface Underlying network interface 01170 * @param[in] ipAddr IPv4 address to be checked 01171 * @return TRUE if the IPv4 address is a broadcast address, else FALSE 01172 **/ 01173 01174 bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr) 01175 { 01176 //Check whether the specified IPv4 address is the broadcast address 01177 if(ipAddr == IPV4_BROADCAST_ADDR) 01178 return TRUE; 01179 01180 //Check whether the specified IPv4 address belongs to the local network 01181 if(ipv4IsOnLocalSubnet(interface, ipAddr)) 01182 { 01183 //Make sure the subnet mask is not 255.255.255.255 01184 if(interface->ipv4Context.subnetMask != IPV4_BROADCAST_ADDR) 01185 { 01186 //Directed broadcast address? 01187 if((ipAddr | interface->ipv4Context.subnetMask) == IPV4_BROADCAST_ADDR) 01188 return TRUE; 01189 } 01190 } 01191 01192 //The specified IPv4 address is not a broadcast address 01193 return FALSE; 01194 } 01195 01196 01197 /** 01198 * @brief Retrieve the scope of an IPv4 address 01199 * @param[in] ipAddr IPv4 address 01200 * @return IPv4 address scope 01201 **/ 01202 01203 uint_t ipv4GetAddrScope(Ipv4Addr ipAddr) 01204 { 01205 uint_t scope; 01206 01207 //Broadcast address? 01208 if(ipAddr == IPV4_BROADCAST_ADDR) 01209 { 01210 //The broadcast address is never forwarded by the routers connecting 01211 //the local network to other networks 01212 scope = IPV4_ADDR_SCOPE_LINK_LOCAL; 01213 } 01214 //Multicast address? 01215 else if(ipv4IsMulticastAddr(ipAddr)) 01216 { 01217 //Local Network Control Block? 01218 if((ipAddr & IPV4_MULTICAST_LNCB_MASK) == IPV4_MULTICAST_LNCB_PREFIX) 01219 { 01220 //Addresses in the Local Network Control Block are used for protocol 01221 //control traffic that is not forwarded off link 01222 scope = IPV4_ADDR_SCOPE_LINK_LOCAL; 01223 } 01224 //Any other multicast address? 01225 else 01226 { 01227 //Other addresses are assigned global scope 01228 scope = IPV4_ADDR_SCOPE_GLOBAL; 01229 } 01230 } 01231 //Unicast address? 01232 else 01233 { 01234 //Loopback address? 01235 if((ipAddr & IPV4_LOOPBACK_ADDR_MASK) == IPV4_LOOPBACK_ADDR_PREFIX) 01236 { 01237 //IPv4 loopback addresses, which have the prefix 127.0.0.0/8, 01238 //are assigned interface-local scope 01239 scope = IPV4_ADDR_SCOPE_INTERFACE_LOCAL; 01240 } 01241 //Link-local address? 01242 else if((ipAddr & IPV4_LINK_LOCAL_MASK) == IPV4_LINK_LOCAL_PREFIX) 01243 { 01244 //IPv4 auto-configuration addresses, which have the prefix 01245 //169.254.0.0/16, are assigned link-local scope 01246 scope = IPV4_ADDR_SCOPE_LINK_LOCAL; 01247 } 01248 //Any other unicast address? 01249 else 01250 { 01251 //Other addresses are assigned global scope 01252 scope = IPV4_ADDR_SCOPE_GLOBAL; 01253 } 01254 } 01255 01256 //Return the scope of the specified IPv4 address 01257 return scope; 01258 } 01259 01260 01261 /** 01262 * @brief Join the specified host group 01263 * @param[in] interface Underlying network interface 01264 * @param[in] groupAddr IPv4 address identifying the host group to join 01265 * @return Error code 01266 **/ 01267 01268 error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr) 01269 { 01270 error_t error; 01271 uint_t i; 01272 Ipv4FilterEntry *entry; 01273 Ipv4FilterEntry *firstFreeEntry; 01274 #if (ETH_SUPPORT == ENABLED) 01275 MacAddr macAddr; 01276 #endif 01277 01278 //The IPv4 address must be a valid multicast address 01279 if(!ipv4IsMulticastAddr(groupAddr)) 01280 return ERROR_INVALID_ADDRESS; 01281 01282 //Initialize error code 01283 error = NO_ERROR; 01284 //Keep track of the first free entry 01285 firstFreeEntry = NULL; 01286 01287 //Go through the multicast filter table 01288 for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++) 01289 { 01290 //Point to the current entry 01291 entry = &interface->ipv4Context.multicastFilter[i]; 01292 01293 //Valid entry? 01294 if(entry->refCount > 0) 01295 { 01296 //Check whether the table already contains the specified IPv4 address 01297 if(entry->addr == groupAddr) 01298 { 01299 //Increment the reference count 01300 entry->refCount++; 01301 //Successful processing 01302 return NO_ERROR; 01303 } 01304 } 01305 else 01306 { 01307 //Keep track of the first free entry 01308 if(firstFreeEntry == NULL) 01309 firstFreeEntry = entry; 01310 } 01311 } 01312 01313 //Check whether the multicast filter table is full 01314 if(firstFreeEntry == NULL) 01315 { 01316 //A new entry cannot be added 01317 return ERROR_FAILURE; 01318 } 01319 01320 #if (ETH_SUPPORT == ENABLED) 01321 //Map the IPv4 multicast address to a MAC-layer address 01322 ipv4MapMulticastAddrToMac(groupAddr, &macAddr); 01323 //Add the corresponding address to the MAC filter table 01324 error = ethAcceptMulticastAddr(interface, &macAddr); 01325 #endif 01326 01327 //MAC filter table successfully updated? 01328 if(!error) 01329 { 01330 //Now we can safely add a new entry to the table 01331 firstFreeEntry->addr = groupAddr; 01332 //Initialize the reference count 01333 firstFreeEntry->refCount = 1; 01334 01335 #if (IGMP_SUPPORT == ENABLED) 01336 //Report multicast group membership to the router 01337 igmpJoinGroup(interface, firstFreeEntry); 01338 #endif 01339 } 01340 01341 //Return status code 01342 return error; 01343 } 01344 01345 01346 /** 01347 * @brief Leave the specified host group 01348 * @param[in] interface Underlying network interface 01349 * @param[in] groupAddr IPv4 address identifying the host group to leave 01350 * @return Error code 01351 **/ 01352 01353 error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr) 01354 { 01355 uint_t i; 01356 Ipv4FilterEntry *entry; 01357 #if (ETH_SUPPORT == ENABLED) 01358 MacAddr macAddr; 01359 #endif 01360 01361 //The IPv4 address must be a valid multicast address 01362 if(!ipv4IsMulticastAddr(groupAddr)) 01363 return ERROR_INVALID_ADDRESS; 01364 01365 //Go through the multicast filter table 01366 for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++) 01367 { 01368 //Point to the current entry 01369 entry = &interface->ipv4Context.multicastFilter[i]; 01370 01371 //Valid entry? 01372 if(entry->refCount > 0) 01373 { 01374 //Specified IPv4 address found? 01375 if(entry->addr == groupAddr) 01376 { 01377 //Decrement the reference count 01378 entry->refCount--; 01379 01380 //Remove the entry if the reference count drops to zero 01381 if(entry->refCount == 0) 01382 { 01383 #if (IGMP_SUPPORT == ENABLED) 01384 //Report group membership termination 01385 igmpLeaveGroup(interface, entry); 01386 #endif 01387 #if (ETH_SUPPORT == ENABLED) 01388 //Map the IPv4 multicast address to a MAC-layer address 01389 ipv4MapMulticastAddrToMac(groupAddr, &macAddr); 01390 //Drop the corresponding address from the MAC filter table 01391 ethDropMulticastAddr(interface, &macAddr); 01392 #endif 01393 //Remove the multicast address from the list 01394 entry->addr = IPV4_UNSPECIFIED_ADDR; 01395 } 01396 01397 //Successful processing 01398 return NO_ERROR; 01399 } 01400 } 01401 } 01402 01403 //The specified IPv4 address does not exist 01404 return ERROR_ADDRESS_NOT_FOUND; 01405 } 01406 01407 01408 /** 01409 * @brief Map an host group address to a MAC-layer multicast address 01410 * @param[in] ipAddr IPv4 host group address 01411 * @param[out] macAddr Corresponding MAC-layer multicast address 01412 * @return Error code 01413 **/ 01414 01415 error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr) 01416 { 01417 uint8_t *p; 01418 01419 //Ensure the specified IPv4 address is a valid host group address 01420 if(!ipv4IsMulticastAddr(ipAddr)) 01421 return ERROR_INVALID_ADDRESS; 01422 01423 //Cast the address to byte array 01424 p = (uint8_t *) &ipAddr; 01425 01426 //An IP host group address is mapped to an Ethernet multicast address 01427 //by placing the low-order 23-bits of the IP address into the low-order 01428 //23 bits of the Ethernet multicast address 01-00-5E-00-00-00 01429 macAddr->b[0] = 0x01; 01430 macAddr->b[1] = 0x00; 01431 macAddr->b[2] = 0x5E; 01432 macAddr->b[3] = p[1] & 0x7F; 01433 macAddr->b[4] = p[2]; 01434 macAddr->b[5] = p[3]; 01435 01436 //The specified host group address was successfully 01437 //mapped to a MAC-layer address 01438 return NO_ERROR; 01439 } 01440 01441 01442 /** 01443 * @brief Convert a dot-decimal string to a binary IPv4 address 01444 * @param[in] str NULL-terminated string representing the IPv4 address 01445 * @param[out] ipAddr Binary representation of the IPv4 address 01446 * @return Error code 01447 **/ 01448 01449 error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr) 01450 { 01451 error_t error; 01452 int_t i = 0; 01453 int_t value = -1; 01454 01455 //Parse input string 01456 while(1) 01457 { 01458 //Decimal digit found? 01459 if(isdigit((uint8_t) *str)) 01460 { 01461 //First digit to be decoded? 01462 if(value < 0) value = 0; 01463 //Update the value of the current byte 01464 value = (value * 10) + (*str - '0'); 01465 01466 //The resulting value shall be in range 0 to 255 01467 if(value > 255) 01468 { 01469 //The conversion failed 01470 error = ERROR_INVALID_SYNTAX; 01471 break; 01472 } 01473 } 01474 //Dot separator found? 01475 else if(*str == '.' && i < 4) 01476 { 01477 //Each dot must be preceded by a valid number 01478 if(value < 0) 01479 { 01480 //The conversion failed 01481 error = ERROR_INVALID_SYNTAX; 01482 break; 01483 } 01484 01485 //Save the current byte 01486 ((uint8_t *) ipAddr)[i++] = value; 01487 //Prepare to decode the next byte 01488 value = -1; 01489 } 01490 //End of string detected? 01491 else if(*str == '\0' && i == 3) 01492 { 01493 //The NULL character must be preceded by a valid number 01494 if(value < 0) 01495 { 01496 //The conversion failed 01497 error = ERROR_INVALID_SYNTAX; 01498 } 01499 else 01500 { 01501 //Save the last byte of the IPv4 address 01502 ((uint8_t *) ipAddr)[i] = value; 01503 //The conversion succeeded 01504 error = NO_ERROR; 01505 } 01506 01507 //We are done 01508 break; 01509 } 01510 //Invalid character... 01511 else 01512 { 01513 //The conversion failed 01514 error = ERROR_INVALID_SYNTAX; 01515 break; 01516 } 01517 01518 //Point to the next character 01519 str++; 01520 } 01521 01522 //Return status code 01523 return error; 01524 } 01525 01526 01527 /** 01528 * @brief Convert a binary IPv4 address to dot-decimal notation 01529 * @param[in] ipAddr Binary representation of the IPv4 address 01530 * @param[out] str NULL-terminated string representing the IPv4 address 01531 * @return Pointer to the formatted string 01532 **/ 01533 01534 char_t *ipv4AddrToString(Ipv4Addr ipAddr, char_t *str) 01535 { 01536 uint8_t *p; 01537 static char_t buffer[16]; 01538 01539 //If the NULL pointer is given as parameter, then the internal buffer is used 01540 if(str == NULL) 01541 str = buffer; 01542 01543 //Cast the address to byte array 01544 p = (uint8_t *) &ipAddr; 01545 //Format IPv4 address 01546 sprintf(str, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "", p[0], p[1], p[2], p[3]); 01547 01548 //Return a pointer to the formatted string 01549 return str; 01550 } 01551 01552 01553 /** 01554 * @brief Dump IPv4 header for debugging purpose 01555 * @param[in] ipHeader Pointer to the IPv4 header 01556 **/ 01557 01558 void ipv4DumpHeader(const Ipv4Header *ipHeader) 01559 { 01560 //Dump IP header contents 01561 TRACE_DEBUG(" Version = %" PRIu8 "\r\n", ipHeader->version); 01562 TRACE_DEBUG(" Header Length = %" PRIu8 "\r\n", ipHeader->headerLength); 01563 TRACE_DEBUG(" Type Of Service = %" PRIu8 "\r\n", ipHeader->typeOfService); 01564 TRACE_DEBUG(" Total Length = %" PRIu16 "\r\n", ntohs(ipHeader->totalLength)); 01565 TRACE_DEBUG(" Identification = %" PRIu16 "\r\n", ntohs(ipHeader->identification)); 01566 TRACE_DEBUG(" Flags = 0x%01X\r\n", ntohs(ipHeader->fragmentOffset) >> 13); 01567 TRACE_DEBUG(" Fragment Offset = %" PRIu16 "\r\n", ntohs(ipHeader->fragmentOffset) & 0x1FFF); 01568 TRACE_DEBUG(" Time To Live = %" PRIu8 "\r\n", ipHeader->timeToLive); 01569 TRACE_DEBUG(" Protocol = %" PRIu8 "\r\n", ipHeader->protocol); 01570 TRACE_DEBUG(" Header Checksum = 0x%04" PRIX16 "\r\n", ntohs(ipHeader->headerChecksum)); 01571 TRACE_DEBUG(" Src Addr = %s\r\n", ipv4AddrToString(ipHeader->srcAddr, NULL)); 01572 TRACE_DEBUG(" Dest Addr = %s\r\n", ipv4AddrToString(ipHeader->destAddr, NULL)); 01573 } 01574 01575 #endif 01576
Generated on Tue Jul 12 2022 17:10:13 by
