#define ICMP_TYPE_ECHO_REPLY 0 #define ICMP_TYPE_ECHO_REQUEST 8 class CICMPHeader // Shrine's use of id and seq indicate this header is for Address Mask Reply/Request { U8 type; U8 code; U16 checksum; U16 identifier; U16 sequence_number; }; U0 ICMPSendReply(U32 destination_ip_address, U16 identifier, U16 sequence_number, U16 request_checksum, U8 *payload, I64 length) { U8 *frame; I64 de_index; CICMPHeader *header; de_index = IPV4PacketAllocate(&frame, IP_PROTOCOL_ICMP, IPV4GetAddress(), destination_ip_address, sizeof(CICMPHeader) + length); if (de_index < 0) { NetErr("ICMP SEND REPLY: Failed to allocate IPV4 packet."); return; } header = frame; header->type = ICMP_TYPE_ECHO_REPLY; header->code = 0; // why is 0 okay? header->checksum = EndianU16(EndianU16(request_checksum) + 0x0800); header->identifier = identifier; header->sequence_number = sequence_number; // TODO: header checksum is awful. Shrine says hack alert. MemCopy(frame + sizeof(CICMPHeader), payload, length); IPV4PacketFinish(de_index); } I64 ICMPHandler(CIPV4Packet *packet) { CICMPHeader *header; if (packet->length < sizeof(CICMPHeader)) { NetErr("ICMP HANDLER: Caught wrong IPV4 length."); return -1; } header = packet->data; if (header->type == ICMP_TYPE_ECHO_REQUEST && header->code == 0)//why zero? need more #defines in here { ARPCachePut(packet->source_ip_address, packet->ethernet_frame->source_address); ICMPSendReply(packet->source_ip_address, header->identifier, header->sequence_number, header->checksum, packet->data + sizeof(CICMPHeader), packet->length - sizeof(CICMPHeader)); // TODO: ?? } else NetWarn("ICMP HANDLER: Unhandled ICMP packet. type, code: 0x%X, 0x%X", header->type, header->code); NetLog("ICMP HANDLER: Exiting."); return 0; }