Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.

Committer:
Benoit
Date:
Sun Jun 26 09:56:31 2011 +0000
Revision:
7:8e12f7357b9f
Parent:
5:3cd83fcb1467
Added IPv4 global broadcast address to processed frames inside IPv4 layer.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Benoit 1:f4040665bc61 1 /*
Benoit 1:f4040665bc61 2 * $Id: ICMPv4.c 29 2011-06-11 14:53:08Z benoit $
Benoit 1:f4040665bc61 3 * $Author: benoit $
Benoit 1:f4040665bc61 4 * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $
Benoit 1:f4040665bc61 5 * $Rev: 29 $
Benoit 1:f4040665bc61 6 *
Benoit 1:f4040665bc61 7 *
Benoit 1:f4040665bc61 8 *
Benoit 1:f4040665bc61 9 *
Benoit 1:f4040665bc61 10 *
Benoit 1:f4040665bc61 11 */
Benoit 1:f4040665bc61 12
Benoit 1:f4040665bc61 13 #include "ICMPv4.h"
Benoit 1:f4040665bc61 14 #include "Ethernet.h"
Benoit 1:f4040665bc61 15 #include "Debug.h"
Benoit 1:f4040665bc61 16
Benoit 1:f4040665bc61 17
Benoit 1:f4040665bc61 18 #define DEBUG_CURRENT_MODULE_NAME "ICMPv4"
Benoit 1:f4040665bc61 19 #define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ICMPV4
Benoit 1:f4040665bc61 20
Benoit 1:f4040665bc61 21
Benoit 1:f4040665bc61 22 static void Init(void);
Benoit 5:3cd83fcb1467 23 static void Handler(NetIF_t *netIF, NetPacket_t *packet);
Benoit 1:f4040665bc61 24
Benoit 1:f4040665bc61 25
Benoit 1:f4040665bc61 26 Protocol_Handler_t icmpv4 =
Benoit 1:f4040665bc61 27 {
Benoit 1:f4040665bc61 28 PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */
Benoit 1:f4040665bc61 29 Protocol_ID_ICMPv4, /* Protocol ID */
Benoit 1:f4040665bc61 30 IPV4_PROTO_ICMPV4, /* Protocol number */
Benoit 1:f4040665bc61 31 Init, /* Protocol initialisation function */
Benoit 1:f4040665bc61 32 Handler, /* Protocol handler */
Benoit 1:f4040665bc61 33 NULL, /* Protocol registration function */
Benoit 1:f4040665bc61 34 NULL, /* API registration function */
Benoit 1:f4040665bc61 35 };
Benoit 1:f4040665bc61 36
Benoit 1:f4040665bc61 37
Benoit 1:f4040665bc61 38 static void Init(void)
Benoit 1:f4040665bc61 39 {
Benoit 1:f4040665bc61 40 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ICMPv4 layer"));
Benoit 1:f4040665bc61 41 }
Benoit 1:f4040665bc61 42
Benoit 1:f4040665bc61 43
Benoit 5:3cd83fcb1467 44 static void Handler(NetIF_t *netIF, NetPacket_t *packet)
Benoit 1:f4040665bc61 45 {
Benoit 1:f4040665bc61 46 ICMPv4_Header_t *icmpv4Packet;
Benoit 1:f4040665bc61 47 ICMPv4_Type_t type;
Benoit 1:f4040665bc61 48 ICMPv4_Code_t code;
Benoit 1:f4040665bc61 49 IPv4_Header_t *ipv4Header;
Benoit 1:f4040665bc61 50 Ethernet_Header_t *ethernetHeader;
Benoit 1:f4040665bc61 51 int32_t depth, lengthToSend;
Benoit 1:f4040665bc61 52
Benoit 1:f4040665bc61 53 //Debug_DumpBufferHex(packet, length);
Benoit 1:f4040665bc61 54
Benoit 1:f4040665bc61 55 icmpv4Packet = (ICMPv4_Header_t *)packet->data;
Benoit 1:f4040665bc61 56 type = icmpv4Packet->type;
Benoit 1:f4040665bc61 57 code = icmpv4Packet->code;
Benoit 1:f4040665bc61 58
Benoit 1:f4040665bc61 59 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("icmpv4 frame of %d bytes icmpv4(%02x, %02x) frame of %d bytes",
Benoit 1:f4040665bc61 60 packet->length,
Benoit 1:f4040665bc61 61 type,
Benoit 1:f4040665bc61 62 code,
Benoit 1:f4040665bc61 63 packet->length
Benoit 1:f4040665bc61 64 ));
Benoit 1:f4040665bc61 65 depth = packet->depth;
Benoit 1:f4040665bc61 66 ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth];
Benoit 1:f4040665bc61 67 ethernetHeader = (Ethernet_Header_t *)packet->headerPtrTable[depth - 1];
Benoit 1:f4040665bc61 68
Benoit 1:f4040665bc61 69 switch(type)
Benoit 1:f4040665bc61 70 {
Benoit 1:f4040665bc61 71 case ICMPV4_TYPE_ECHO_REQUEST:
Benoit 1:f4040665bc61 72 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 73 {
Benoit 1:f4040665bc61 74 ICMPv4_DumpHeader("Got ", ipv4Header);
Benoit 1:f4040665bc61 75 }
Benoit 1:f4040665bc61 76
Benoit 1:f4040665bc61 77 ipv4Header->dest.addr = ipv4Header->source.addr;
Benoit 1:f4040665bc61 78 ipv4Header->source.addr = netIF->ipv4Address.addr;
Benoit 1:f4040665bc61 79 ethernetHeader->destination = ethernetHeader->source;
Benoit 1:f4040665bc61 80 ethernetHeader->source = *((Ethernet_Addr_t *)netIF->driverParameter);
Benoit 1:f4040665bc61 81 icmpv4Packet->type = ICMPV4_TYPE_ECHO_REPLY;
Benoit 1:f4040665bc61 82 lengthToSend = packet->headerLenTable[depth - 1] + packet->headerLenTable[depth - 1] + ntohs(ipv4Header->totalLength);
Benoit 1:f4040665bc61 83 icmpv4Packet->crc = 0;
Benoit 1:f4040665bc61 84 icmpv4Packet->crc = ICMPv4_ComputeCRC(icmpv4Packet, ntohs(ipv4Header->totalLength) - packet->headerLenTable[depth]);
Benoit 1:f4040665bc61 85
Benoit 1:f4040665bc61 86 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 87 {
Benoit 1:f4040665bc61 88 ICMPv4_DumpHeader("Replying ", ipv4Header);
Benoit 1:f4040665bc61 89 }
Benoit 1:f4040665bc61 90
Benoit 1:f4040665bc61 91 netIF->driver->Write((uint8_t *)ethernetHeader, lengthToSend );
Benoit 1:f4040665bc61 92
Benoit 1:f4040665bc61 93 break;
Benoit 1:f4040665bc61 94
Benoit 1:f4040665bc61 95 default:
Benoit 1:f4040665bc61 96 break;
Benoit 1:f4040665bc61 97 }
Benoit 1:f4040665bc61 98 }
Benoit 1:f4040665bc61 99
Benoit 1:f4040665bc61 100
Benoit 1:f4040665bc61 101 uint16_t ICMPv4_ComputeCRC(ICMPv4_Header_t *packet, int32_t length)
Benoit 1:f4040665bc61 102 {
Benoit 1:f4040665bc61 103 uint32_t crc = 0, size = length;
Benoit 1:f4040665bc61 104 uint16_t *data = (uint16_t *)packet, tmp;
Benoit 1:f4040665bc61 105
Benoit 1:f4040665bc61 106 while(size > 1)
Benoit 1:f4040665bc61 107 {
Benoit 1:f4040665bc61 108 tmp = ntohs(*data);
Benoit 1:f4040665bc61 109 crc += tmp;
Benoit 1:f4040665bc61 110 data++;
Benoit 1:f4040665bc61 111 size -= sizeof(uint16_t);
Benoit 1:f4040665bc61 112 }
Benoit 1:f4040665bc61 113
Benoit 1:f4040665bc61 114 if (size > 0)
Benoit 1:f4040665bc61 115 {
Benoit 1:f4040665bc61 116 tmp = (*((uint8_t *)data)) << 8;
Benoit 1:f4040665bc61 117 crc += tmp;
Benoit 1:f4040665bc61 118 }
Benoit 1:f4040665bc61 119
Benoit 1:f4040665bc61 120 crc = (crc >> 16) + (crc & 0xFFFF);
Benoit 1:f4040665bc61 121 if (crc & 0xFFFF0000) crc = (crc >> 16) + (crc & 0xFFFF);
Benoit 1:f4040665bc61 122
Benoit 1:f4040665bc61 123 return htons((~crc) & 0xFFFF);
Benoit 1:f4040665bc61 124 }
Benoit 1:f4040665bc61 125
Benoit 1:f4040665bc61 126
Benoit 1:f4040665bc61 127 Bool_t ICMPv4_CheckCRC(ICMPv4_Header_t *packet, int32_t length)
Benoit 1:f4040665bc61 128 {
Benoit 1:f4040665bc61 129 return True;
Benoit 1:f4040665bc61 130 }
Benoit 1:f4040665bc61 131
Benoit 1:f4040665bc61 132
Benoit 1:f4040665bc61 133 void ICMPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header)
Benoit 1:f4040665bc61 134 {
Benoit 1:f4040665bc61 135 ICMPv4_Header_t *icmpv4Header = (ICMPv4_Header_t *)(ipv4Header + 1);
Benoit 1:f4040665bc61 136
Benoit 1:f4040665bc61 137 switch(icmpv4Header->type)
Benoit 1:f4040665bc61 138 {
Benoit 1:f4040665bc61 139 case ICMPV4_TYPE_ECHO_REQUEST:
Benoit 1:f4040665bc61 140 DEBUG_RAW((
Benoit 1:f4040665bc61 141 "%sICMPv4 echo request from %d.%d.%d.%d",
Benoit 1:f4040665bc61 142 prefix != NULL ? prefix : "",
Benoit 1:f4040665bc61 143 ipv4Header->source.IP0,
Benoit 1:f4040665bc61 144 ipv4Header->source.IP1,
Benoit 1:f4040665bc61 145 ipv4Header->source.IP2,
Benoit 1:f4040665bc61 146 ipv4Header->source.IP3
Benoit 1:f4040665bc61 147 ));
Benoit 1:f4040665bc61 148 break;
Benoit 1:f4040665bc61 149
Benoit 1:f4040665bc61 150 case ICMPV4_TYPE_ECHO_REPLY:
Benoit 1:f4040665bc61 151 DEBUG_RAW((
Benoit 1:f4040665bc61 152 "%sICMPv4 echo reply to %d.%d.%d.%d",
Benoit 1:f4040665bc61 153 prefix != NULL ? prefix : "",
Benoit 1:f4040665bc61 154 ipv4Header->dest.IP0,
Benoit 1:f4040665bc61 155 ipv4Header->dest.IP1,
Benoit 1:f4040665bc61 156 ipv4Header->dest.IP2,
Benoit 1:f4040665bc61 157 ipv4Header->dest.IP3
Benoit 1:f4040665bc61 158 ));
Benoit 1:f4040665bc61 159 break;
Benoit 1:f4040665bc61 160
Benoit 1:f4040665bc61 161 }
Benoit 1:f4040665bc61 162 }