3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 {ICMP_ECHO_REPLY
, ICMP_QUERY_MESSAGE
},
27 {1, ICMP_INVALID_MESSAGE
},
28 {2, ICMP_INVALID_MESSAGE
},
29 {ICMP_DEST_UNREACHABLE
, ICMP_ERROR_MESSAGE
},
30 {ICMP_SOURCE_QUENCH
, ICMP_ERROR_MESSAGE
},
31 {ICMP_REDIRECT
, ICMP_ERROR_MESSAGE
},
32 {6, ICMP_INVALID_MESSAGE
},
33 {7, ICMP_INVALID_MESSAGE
},
34 {ICMP_ECHO_REQUEST
, ICMP_QUERY_MESSAGE
},
35 {9, ICMP_INVALID_MESSAGE
},
36 {10, ICMP_INVALID_MESSAGE
},
37 {ICMP_TIME_EXCEEDED
, ICMP_ERROR_MESSAGE
},
38 {ICMP_PARAMETER_PROBLEM
, ICMP_ERROR_MESSAGE
},
39 {ICMP_TIMESTAMP
, ICMP_QUERY_MESSAGE
},
40 {14, ICMP_INVALID_MESSAGE
},
41 {ICMP_INFO_REQUEST
, ICMP_QUERY_MESSAGE
},
42 {ICMP_INFO_REPLY
, ICMP_QUERY_MESSAGE
},
46 mIp4SupportedIcmp
[23] = {
47 {ICMP_ECHO_REPLY
, ICMP_DEFAULT_CODE
},
49 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE
},
50 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE
},
51 {ICMP_DEST_UNREACHABLE
, ICMP_PROTO_UNREACHABLE
},
52 {ICMP_DEST_UNREACHABLE
, ICMP_PORT_UNREACHABLE
},
53 {ICMP_DEST_UNREACHABLE
, ICMP_FRAGMENT_FAILED
},
54 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCEROUTE_FAILED
},
55 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNKNOWN
},
56 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNKNOWN
},
57 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCE_ISOLATED
},
58 {ICMP_DEST_UNREACHABLE
, ICMP_NET_PROHIBITED
},
59 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_PROHIBITED
},
60 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE_TOS
},
61 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE_TOS
},
63 {ICMP_SOURCE_QUENCH
, ICMP_DEFAULT_CODE
},
65 {ICMP_REDIRECT
, ICMP_NET_REDIRECT
},
66 {ICMP_REDIRECT
, ICMP_HOST_REDIRECT
},
67 {ICMP_REDIRECT
, ICMP_NET_TOS_REDIRECT
},
68 {ICMP_REDIRECT
, ICMP_HOST_TOS_REDIRECT
},
70 {ICMP_ECHO_REQUEST
, ICMP_DEFAULT_CODE
},
72 {ICMP_TIME_EXCEEDED
, ICMP_TIMEOUT_IN_TRANSIT
},
73 {ICMP_TIME_EXCEEDED
, ICMp_TIMEOUT_REASSEMBLE
},
75 {ICMP_PARAMETER_PROBLEM
, ICMP_DEFAULT_CODE
},
81 Process the ICMP redirect. Find the instance then update
83 All kinds of redirect is treated as host redirect as
84 specified by RFC1122 3.3.1.2:
85 "Since the subnet mask appropriate to the destination
86 address is generally not known, a Network Redirect
87 message SHOULD be treated identically to a Host Redirect
90 @param IpSb The IP4 service binding instance that received the
92 @param Head The IP head of the received ICMPpacket.
93 @param Packet The content of the ICMP redirect packet with IP
95 @param Icmp The buffer to store the ICMP error message if
98 @retval EFI_INVALID_PARAMETER The parameter is invalid
99 @retval EFI_SUCCESS Successfully updated the route caches
103 Ip4ProcessIcmpRedirect (
104 IN IP4_SERVICE
*IpSb
,
107 IN IP4_ICMP_ERROR_HEAD
*Icmp
111 IP4_PROTOCOL
*Ip4Instance
;
112 IP4_ROUTE_CACHE_ENTRY
*CacheEntry
;
117 // Find the interface whose IP address is the source of the
118 // orgianl IP packet.
120 IpIf
= Ip4FindInterface (IpSb
, NTOHL (Icmp
->IpHead
.Src
));
121 Gateway
= NTOHL (Icmp
->Fourth
);
124 // discard the packet if the new gateway address it specifies
125 // is not on the same connected net through which the Redirect
126 // arrived. (RFC1122 3.2.2.2).
128 if ((IpIf
== NULL
) || !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
)) {
130 return EFI_INVALID_PARAMETER
;
134 // Update each IP child's route cache on the interface.
136 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
137 Ip4Instance
= NET_LIST_USER_STRUCT (Entry
, IP4_PROTOCOL
, AddrLink
);
139 if (Ip4Instance
->RouteTable
== NULL
) {
143 CacheEntry
= Ip4FindRouteCache (
144 Ip4Instance
->RouteTable
,
145 NTOHL (Icmp
->IpHead
.Dst
),
146 NTOHL (Icmp
->IpHead
.Src
)
150 // Only update the route cache's gateway if the source of the
151 // Redirect is the current first-hop gateway
153 if ((CacheEntry
!= NULL
) && (NTOHL (Head
->Src
) == CacheEntry
->NextHop
)) {
154 CacheEntry
->NextHop
= Gateway
;
164 Process the ICMP error packet. If it is an ICMP redirect packet,
165 update call Ip4ProcessIcmpRedirect to update the IP instance's
166 route cache, otherwise, deliver the packet to upper layer.
168 @param IpSb The IP service that received the packet.
169 @param Head The IP head of the ICMP error packet
170 @param Packet The content of the ICMP error with IP head
173 @retval EFI_INVALID_PARAMETER The packet is invalid
174 @retval Others Failed to process the packet.
175 @retval EFI_SUCCESS The ICMP error is processed successfully.
179 Ip4ProcessIcmpError (
180 IN IP4_SERVICE
*IpSb
,
185 IP4_ICMP_ERROR_HEAD Icmp
;
187 if (Packet
->TotalSize
< sizeof (Icmp
)) {
189 return EFI_INVALID_PARAMETER
;
192 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
195 // If it is an ICMP redirect error, update the route cache
196 // as RFC1122. Otherwise, demultiplex it to IP instances.
198 if (Icmp
.Head
.Type
== ICMP_REDIRECT
) {
199 return Ip4ProcessIcmpRedirect (IpSb
, Head
, Packet
, &Icmp
);
202 IP4_GET_CLIP_INFO (Packet
)->Status
= EFI_ICMP_ERROR
;
203 return Ip4Demultiplex (IpSb
, Head
, Packet
);
208 Replay an ICMP echo request.
210 @param IpSb The IP service that receivd the packet
211 @param Head The IP head of the ICMP error packet
212 @param Packet The content of the ICMP error with IP head
215 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
216 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.
217 @retval Others Failed to answer the ICMP echo request.
222 IN IP4_SERVICE
*IpSb
,
227 IP4_ICMP_QUERY_HEAD
*Icmp
;
233 // make a copy the packet, it is really a bad idea to
234 // send the MNP's buffer back to MNP.
236 Data
= NetbufDuplicate (Packet
, NULL
, IP4_MAX_HEADLEN
);
239 Status
= EFI_OUT_OF_RESOURCES
;
244 // Change the ICMP type to echo reply, exchange the source
245 // and destination, then send it. The source is updated to
246 // use specific destination. See RFC1122. SRR/RR option
247 // update is omitted.
249 Icmp
= (IP4_ICMP_QUERY_HEAD
*) NetbufGetByte (Data
, 0, NULL
);
250 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
251 Icmp
->Head
.Checksum
= 0;
252 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
255 ReplyHead
.Fragment
= 0;
257 ReplyHead
.Protocol
= IP4_PROTO_ICMP
;
261 // Ip4Output will select a source for us
263 ReplyHead
.Dst
= Head
->Src
;
284 Process the ICMP query message. If it is an ICMP echo
285 request, answer it. Otherwise deliver it to upper layer.
287 @param IpSb The IP service that receivd the packet
288 @param Head The IP head of the ICMP query packet
289 @param Packet The content of the ICMP query with IP head
292 @retval EFI_INVALID_PARAMETER The packet is invalid
293 @retval EFI_SUCCESS The ICMP query message is processed
297 Ip4ProcessIcmpQuery (
298 IN IP4_SERVICE
*IpSb
,
303 IP4_ICMP_QUERY_HEAD Icmp
;
305 if (Packet
->TotalSize
< sizeof (Icmp
)) {
307 return EFI_INVALID_PARAMETER
;
310 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
312 if (Icmp
.Head
.Type
== ICMP_ECHO_REQUEST
) {
313 return Ip4IcmpReplyEcho (IpSb
, Head
, Packet
);
316 return Ip4Demultiplex (IpSb
, Head
, Packet
);
321 Handle the ICMP packet. First validate the message format,
322 then according to the message types, process it as query or
325 @param IpSb The IP service that receivd the packet
326 @param Head The IP head of the ICMP query packet
327 @param Packet The content of the ICMP query with IP head
330 @retval EFI_INVALID_PARAMETER The packet is malformated.
331 @retval EFI_SUCCESS The ICMP message is successfully processed.
336 IN IP4_SERVICE
*IpSb
,
344 if (Packet
->TotalSize
< sizeof (Icmp
)) {
348 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
350 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
354 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
355 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
359 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
360 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
362 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
363 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
369 return EFI_INVALID_PARAMETER
;