ip4icmp.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 396 行
C
396 行
/*++
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Ip4Icmp.c
Abstract:
--*/
#include "Ip4Impl.h"
IP4_ICMP_CLASS
mIcmpClass[] = {
{ICMP_ECHO_REPLY, ICMP_QUERY_MESSAGE },
{1, ICMP_INVALID_MESSAGE},
{2, ICMP_INVALID_MESSAGE},
{ICMP_DEST_UNREACHABLE, ICMP_ERROR_MESSAGE },
{ICMP_SOURCE_QUENCH, ICMP_ERROR_MESSAGE },
{ICMP_REDIRECT, ICMP_ERROR_MESSAGE },
{6, ICMP_INVALID_MESSAGE},
{7, ICMP_INVALID_MESSAGE},
{ICMP_ECHO_REQUEST, ICMP_QUERY_MESSAGE },
{9, ICMP_INVALID_MESSAGE},
{10, ICMP_INVALID_MESSAGE},
{ICMP_TIME_EXCEEDED, ICMP_ERROR_MESSAGE },
{ICMP_PARAMETER_PROBLEM, ICMP_ERROR_MESSAGE },
{ICMP_TIMESTAMP , ICMP_QUERY_MESSAGE },
{14, ICMP_INVALID_MESSAGE},
{ICMP_INFO_REQUEST , ICMP_QUERY_MESSAGE },
{ICMP_INFO_REPLY , ICMP_QUERY_MESSAGE },
};
EFI_IP4_ICMP_TYPE
mIp4SupportedIcmp [23] = {
{ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE },
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE },
{ICMP_DEST_UNREACHABLE, ICMP_PROTO_UNREACHABLE },
{ICMP_DEST_UNREACHABLE, ICMP_PORT_UNREACHABLE },
{ICMP_DEST_UNREACHABLE, ICMP_FRAGMENT_FAILED },
{ICMP_DEST_UNREACHABLE, ICMP_SOURCEROUTE_FAILED},
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNKNOWN },
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNKNOWN },
{ICMP_DEST_UNREACHABLE, ICMP_SOURCE_ISOLATED },
{ICMP_DEST_UNREACHABLE, ICMP_NET_PROHIBITED },
{ICMP_DEST_UNREACHABLE, ICMP_HOST_PROHIBITED },
{ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACHABLE_TOS },
{ICMP_DEST_UNREACHABLE, ICMP_HOST_UNREACHABLE_TOS},
{ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },
{ICMP_REDIRECT, ICMP_NET_REDIRECT },
{ICMP_REDIRECT, ICMP_HOST_REDIRECT },
{ICMP_REDIRECT, ICMP_NET_TOS_REDIRECT },
{ICMP_REDIRECT, ICMP_HOST_TOS_REDIRECT },
{ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },
{ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT},
{ICMP_TIME_EXCEEDED, ICMp_TIMEOUT_REASSEMBLE},
{ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },
};
STATIC
EFI_STATUS
Ip4ProcessIcmpRedirect (
IN IP4_SERVICE *IpSb,
IN IP4_HEAD *Head,
IN NET_BUF *Packet,
IN IP4_ICMP_ERROR_HEAD *Icmp
)
/*++
Routine Description:
Process the ICMP redirect. Find the instance then update
its route cache.
All kinds of redirect is treated as host redirect as
specified by RFC1122 3.3.1.2:
"Since the subnet mask appropriate to the destination
address is generally not known, a Network Redirect
message SHOULD be treated identically to a Host Redirect
message;"
Arguments:
IpSb - The IP4 service binding instance that received the packet
Head - The IP head of the received ICMPpacket.
Packet - The content of the ICMP redirect packet with IP head removed.
Icmp - The buffer to store the ICMP error message if something is wrong.
Returns:
EFI_INVALID_PARAMETER - The parameter is invalid
EFI_SUCCESS - Successfully updated the route caches
--*/
{
NET_LIST_ENTRY *Entry;
IP4_PROTOCOL *Ip4Instance;
IP4_ROUTE_CACHE_ENTRY *CacheEntry;
IP4_INTERFACE *IpIf;
IP4_ADDR Gateway;
//
// Find the interface whose IP address is the source of the
// orgianl IP packet.
//
IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));
Gateway = NTOHL (Icmp->Fourth);
//
// discard the packet if the new gateway address it specifies
// is not on the same connected net through which the Redirect
// arrived. (RFC1122 3.2.2.2).
//
if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {
NetbufFree (Packet);
return EFI_INVALID_PARAMETER;
}
//
// Update each IP child's route cache on the interface.
//
NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
if (Ip4Instance->RouteTable == NULL) {
continue;
}
CacheEntry = Ip4FindRouteCache (
Ip4Instance->RouteTable,
NTOHL (Icmp->IpHead.Dst),
NTOHL (Icmp->IpHead.Src)
);
//
// Only update the route cache's gateway if the source of the
// Redirect is the current first-hop gateway
//
if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {
CacheEntry->NextHop = Gateway;
}
}
NetbufFree (Packet);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
Ip4ProcessIcmpError (
IN IP4_SERVICE *IpSb,
IN IP4_HEAD *Head,
IN NET_BUF *Packet
)
/*++
Routine Description:
Process the ICMP error packet. If it is an ICMP redirect packet,
update call Ip4ProcessIcmpRedirect to update the IP instance's
route cache, otherwise, deliver the packet to upper layer.
Arguments:
IpSb - The IP service that received the packet.
Head - The IP head of the ICMP error packet
Packet - The content of the ICMP error with IP head removed.
Returns:
EFI_INVALID_PARAMETER - The packet is invalid
Others - Failed to process the packet.
EFI_SUCCESS - The ICMP error is processed successfully.
--*/
{
IP4_ICMP_ERROR_HEAD Icmp;
if (Packet->TotalSize < sizeof (Icmp)) {
NetbufFree (Packet);
return EFI_INVALID_PARAMETER;
}
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
//
// If it is an ICMP redirect error, update the route cache
// as RFC1122. Otherwise, demultiplex it to IP instances.
//
if (Icmp.Head.Type == ICMP_REDIRECT) {
return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);
}
IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
return Ip4Demultiplex (IpSb, Head, Packet);
}
EFI_STATUS
Ip4IcmpReplyEcho (
IN IP4_SERVICE *IpSb,
IN IP4_HEAD *Head,
IN NET_BUF *Packet
)
/*++
Routine Description:
Replay an ICMP echo request.
Arguments:
IpSb - The IP service that receivd the packet
Head - The IP head of the ICMP error packet
Packet - The content of the ICMP error with IP head removed.
Returns:
EFI_OUT_OF_RESOURCES - Failed to allocate resource.
EFI_SUCCESS - The ICMP Echo request is successfully answered.
Others - Failed to answer the ICMP echo request.
--*/
{
IP4_ICMP_QUERY_HEAD *Icmp;
NET_BUF *Data;
EFI_STATUS Status;
IP4_HEAD ReplyHead;
//
// make a copy the packet, it is really a bad idea to
// send the MNP's buffer back to MNP.
//
Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);
if (Data == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Change the ICMP type to echo reply, exchange the source
// and destination, then send it. The source is updated to
// use specific destination. See RFC1122. SRR/RR option
// update is omitted.
//
Icmp = (IP4_ICMP_QUERY_HEAD *) NetbufGetByte (Data, 0, NULL);
Icmp->Head.Type = ICMP_ECHO_REPLY;
Icmp->Head.Checksum = 0;
Icmp->Head.Checksum = ~NetblockChecksum ((UINT8 *) Icmp, Data->TotalSize);
ReplyHead.Tos = 0;
ReplyHead.Fragment = 0;
ReplyHead.Ttl = 64;
ReplyHead.Protocol = IP4_PROTO_ICMP;
ReplyHead.Src = 0;
//
// Ip4Output will select a source for us
//
ReplyHead.Dst = Head->Src;
Status = Ip4Output (
IpSb,
NULL,
Data,
&ReplyHead,
NULL,
0,
IP4_ALLZERO_ADDRESS,
Ip4SysPacketSent,
NULL
);
ON_EXIT:
NetbufFree (Packet);
return Status;
}
EFI_STATUS
Ip4ProcessIcmpQuery (
IN IP4_SERVICE *IpSb,
IN IP4_HEAD *Head,
IN NET_BUF *Packet
)
/*++
Routine Description:
Process the ICMP query message. If it is an ICMP echo
request, answer it. Otherwise deliver it to upper layer.
Arguments:
IpSb - The IP service that receivd the packet
Head - The IP head of the ICMP query packet
Packet - The content of the ICMP query with IP head removed.
Returns:
EFI_INVALID_PARAMETER - The packet is invalid
EFI_SUCCESS - The ICMP query message is processed
--*/
{
IP4_ICMP_QUERY_HEAD Icmp;
if (Packet->TotalSize < sizeof (Icmp)) {
NetbufFree (Packet);
return EFI_INVALID_PARAMETER;
}
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {
return Ip4IcmpReplyEcho (IpSb, Head, Packet);
}
return Ip4Demultiplex (IpSb, Head, Packet);
}
EFI_STATUS
Ip4IcmpHandle (
IN IP4_SERVICE *IpSb,
IN IP4_HEAD *Head,
IN NET_BUF *Packet
)
/*++
Routine Description:
Handle the ICMP packet. First validate the message format,
then according to the message types, process it as query or
error packet.
Arguments:
IpSb - The IP service that receivd the packet
Head - The IP head of the ICMP query packet
Packet - The content of the ICMP query with IP head removed.
Returns:
EFI_INVALID_PARAMETER - The packet is malformated.
EFI_SUCCESS - The ICMP message is successfully processed.
--*/
{
IP4_ICMP_HEAD Icmp;
UINT16 Checksum;
if (Packet->TotalSize < sizeof (Icmp)) {
goto DROP;
}
NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
if (Icmp.Type > ICMP_TYPE_MAX) {
goto DROP;
}
Checksum = ~NetbufChecksum (Packet);
if ((Icmp.Checksum != 0) && (Checksum != 0)) {
goto DROP;
}
if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
return Ip4ProcessIcmpError (IpSb, Head, Packet);
} else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {
return Ip4ProcessIcmpQuery (IpSb, Head, Packet);
}
DROP:
NetbufFree (Packet);
return EFI_INVALID_PARAMETER;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?