3 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
12 {ICMP_ECHO_REPLY
, ICMP_QUERY_MESSAGE
},
13 {1, ICMP_INVALID_MESSAGE
},
14 {2, ICMP_INVALID_MESSAGE
},
15 {ICMP_DEST_UNREACHABLE
, ICMP_ERROR_MESSAGE
},
16 {ICMP_SOURCE_QUENCH
, ICMP_ERROR_MESSAGE
},
17 {ICMP_REDIRECT
, ICMP_ERROR_MESSAGE
},
18 {6, ICMP_INVALID_MESSAGE
},
19 {7, ICMP_INVALID_MESSAGE
},
20 {ICMP_ECHO_REQUEST
, ICMP_QUERY_MESSAGE
},
21 {9, ICMP_INVALID_MESSAGE
},
22 {10, ICMP_INVALID_MESSAGE
},
23 {ICMP_TIME_EXCEEDED
, ICMP_ERROR_MESSAGE
},
24 {ICMP_PARAMETER_PROBLEM
, ICMP_ERROR_MESSAGE
},
25 {ICMP_TIMESTAMP
, ICMP_QUERY_MESSAGE
},
26 {14, ICMP_INVALID_MESSAGE
},
27 {ICMP_INFO_REQUEST
, ICMP_QUERY_MESSAGE
},
28 {ICMP_INFO_REPLY
, ICMP_QUERY_MESSAGE
},
32 mIp4SupportedIcmp
[23] = {
33 {ICMP_ECHO_REPLY
, ICMP_DEFAULT_CODE
},
35 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE
},
36 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE
},
37 {ICMP_DEST_UNREACHABLE
, ICMP_PROTO_UNREACHABLE
},
38 {ICMP_DEST_UNREACHABLE
, ICMP_PORT_UNREACHABLE
},
39 {ICMP_DEST_UNREACHABLE
, ICMP_FRAGMENT_FAILED
},
40 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCEROUTE_FAILED
},
41 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNKNOWN
},
42 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNKNOWN
},
43 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCE_ISOLATED
},
44 {ICMP_DEST_UNREACHABLE
, ICMP_NET_PROHIBITED
},
45 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_PROHIBITED
},
46 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE_TOS
},
47 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE_TOS
},
49 {ICMP_SOURCE_QUENCH
, ICMP_DEFAULT_CODE
},
51 {ICMP_REDIRECT
, ICMP_NET_REDIRECT
},
52 {ICMP_REDIRECT
, ICMP_HOST_REDIRECT
},
53 {ICMP_REDIRECT
, ICMP_NET_TOS_REDIRECT
},
54 {ICMP_REDIRECT
, ICMP_HOST_TOS_REDIRECT
},
56 {ICMP_ECHO_REQUEST
, ICMP_DEFAULT_CODE
},
58 {ICMP_TIME_EXCEEDED
, ICMP_TIMEOUT_IN_TRANSIT
},
59 {ICMP_TIME_EXCEEDED
, ICMP_TIMEOUT_REASSEMBLE
},
61 {ICMP_PARAMETER_PROBLEM
, ICMP_DEFAULT_CODE
},
67 Process the ICMP redirect. Find the instance then update
70 All kinds of redirect is treated as host redirect as
71 specified by RFC1122 3.3.1.2:
72 "Since the subnet mask appropriate to the destination
73 address is generally not known, a Network Redirect
74 message SHOULD be treated identically to a Host Redirect
77 @param[in] IpSb The IP4 service binding instance that received
79 @param[in] Head The IP head of the received ICMPpacket.
80 @param[in] Packet The content of the ICMP redirect packet with IP
82 @param[in] Icmp The buffer to store the ICMP error message if
85 @retval EFI_INVALID_PARAMETER The parameter is invalid
86 @retval EFI_SUCCESS Successfully updated the route caches
90 Ip4ProcessIcmpRedirect (
94 IN IP4_ICMP_ERROR_HEAD
*Icmp
98 IP4_PROTOCOL
*Ip4Instance
;
99 IP4_ROUTE_CACHE_ENTRY
*CacheEntry
;
106 // Find the interface whose IP address is the source of the
107 // orgianl IP packet.
109 IpIf
= Ip4FindInterface (IpSb
, NTOHL (Icmp
->IpHead
.Src
));
110 Gateway
= NTOHL (Icmp
->Fourth
);
113 // discard the packet if the new gateway address it specifies
114 // is not on the same connected net through which the Redirect
115 // arrived. (RFC1122 3.2.2.2).
117 if ((IpIf
== NULL
) || !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
)) {
119 return EFI_INVALID_PARAMETER
;
123 // Update each IP child's route cache on the interface.
125 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
126 Ip4Instance
= NET_LIST_USER_STRUCT (Entry
, IP4_PROTOCOL
, AddrLink
);
128 if (Ip4Instance
->RouteTable
== NULL
) {
132 Dst
= NTOHL (Icmp
->IpHead
.Dst
);
133 Src
= NTOHL (Icmp
->IpHead
.Src
);
134 CacheEntry
= Ip4FindRouteCache (Ip4Instance
->RouteTable
, Dst
, Src
);
137 // Only update the route cache's gateway if the source of the
138 // Redirect is the current first-hop gateway
140 if ((CacheEntry
!= NULL
) && (NTOHL (Head
->Src
) == CacheEntry
->NextHop
)) {
141 CacheEntry
->NextHop
= Gateway
;
151 Process the ICMP error packet. If it is an ICMP redirect packet,
152 update call Ip4ProcessIcmpRedirect to update the IP instance's
153 route cache, otherwise, deliver the packet to upper layer.
155 @param[in] IpSb The IP4 service that received the packet.
156 @param[in] Head The IP4 head of the ICMP error packet
157 @param[in] Packet The content of the ICMP error with IP4 head
160 @retval EFI_SUCCESS The ICMP error is processed successfully.
161 @retval EFI_INVALID_PARAMETER The packet is invalid
162 @retval Others Failed to process the packet.
166 Ip4ProcessIcmpError (
167 IN IP4_SERVICE
*IpSb
,
172 IP4_ICMP_ERROR_HEAD Icmp
;
174 if (Packet
->TotalSize
< sizeof (Icmp
)) {
176 return EFI_INVALID_PARAMETER
;
179 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
182 // If it is an ICMP redirect error, update the route cache
183 // as RFC1122. Otherwise, demultiplex it to IP instances.
185 if (Icmp
.Head
.Type
== ICMP_REDIRECT
) {
186 return Ip4ProcessIcmpRedirect (IpSb
, Head
, Packet
, &Icmp
);
189 IP4_GET_CLIP_INFO (Packet
)->Status
= EFI_ICMP_ERROR
;
190 return Ip4Demultiplex (IpSb
, Head
, Packet
, NULL
, 0);
195 Replay an ICMP echo request.
197 @param[in] IpSb The IP4 service that receivd the packet
198 @param[in] Head The IP4 head of the ICMP error packet
199 @param[in] Packet The content of the ICMP error with IP4 head
202 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
203 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.
204 @retval Others Failed to answer the ICMP echo request.
209 IN IP4_SERVICE
*IpSb
,
214 IP4_ICMP_QUERY_HEAD
*Icmp
;
220 // make a copy the packet, it is really a bad idea to
221 // send the MNP's buffer back to MNP.
223 Data
= NetbufDuplicate (Packet
, NULL
, IP4_MAX_HEADLEN
);
226 Status
= EFI_OUT_OF_RESOURCES
;
231 // Change the ICMP type to echo reply, exchange the source
232 // and destination, then send it. The source is updated to
233 // use specific destination. See RFC1122. SRR/RR option
234 // update is omitted.
236 Icmp
= (IP4_ICMP_QUERY_HEAD
*) NetbufGetByte (Data
, 0, NULL
);
237 ASSERT (Icmp
!= NULL
);
238 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
239 Icmp
->Head
.Checksum
= 0;
240 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
243 ReplyHead
.Fragment
= 0;
245 ReplyHead
.Protocol
= EFI_IP_PROTO_ICMP
;
249 // Ip4Output will select a source for us
251 ReplyHead
.Dst
= Head
->Src
;
264 if (EFI_ERROR (Status
)) {
275 Process the ICMP query message. If it is an ICMP echo
276 request, answer it. Otherwise deliver it to upper layer.
278 @param[in] IpSb The IP4 service that receivd the packet
279 @param[in] Head The IP4 head of the ICMP query packet
280 @param[in] Packet The content of the ICMP query with IP4 head
283 @retval EFI_INVALID_PARAMETER The packet is invalid
284 @retval EFI_SUCCESS The ICMP query message is processed
285 @retval Others Failed to process ICMP query.
289 Ip4ProcessIcmpQuery (
290 IN IP4_SERVICE
*IpSb
,
295 IP4_ICMP_QUERY_HEAD Icmp
;
297 if (Packet
->TotalSize
< sizeof (Icmp
)) {
299 return EFI_INVALID_PARAMETER
;
302 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
304 if (Icmp
.Head
.Type
== ICMP_ECHO_REQUEST
) {
305 return Ip4IcmpReplyEcho (IpSb
, Head
, Packet
);
308 return Ip4Demultiplex (IpSb
, Head
, Packet
, NULL
, 0);
313 Handle the ICMP packet. First validate the message format,
314 then according to the message types, process it as query or
317 @param[in] IpSb The IP4 service that receivd the packet.
318 @param[in] Head The IP4 head of the ICMP query packet.
319 @param[in] Packet The content of the ICMP query with IP4 head
322 @retval EFI_INVALID_PARAMETER The packet is malformatted.
323 @retval EFI_SUCCESS The ICMP message is successfully processed.
324 @retval Others Failed to handle ICMP packet.
329 IN IP4_SERVICE
*IpSb
,
337 if (Packet
->TotalSize
< sizeof (Icmp
)) {
341 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
343 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
347 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
348 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
352 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
353 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
355 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
356 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
362 return EFI_INVALID_PARAMETER
;