3 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
4 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.
18 {ICMP_ECHO_REPLY
, ICMP_QUERY_MESSAGE
},
19 {1, ICMP_INVALID_MESSAGE
},
20 {2, ICMP_INVALID_MESSAGE
},
21 {ICMP_DEST_UNREACHABLE
, ICMP_ERROR_MESSAGE
},
22 {ICMP_SOURCE_QUENCH
, ICMP_ERROR_MESSAGE
},
23 {ICMP_REDIRECT
, ICMP_ERROR_MESSAGE
},
24 {6, ICMP_INVALID_MESSAGE
},
25 {7, ICMP_INVALID_MESSAGE
},
26 {ICMP_ECHO_REQUEST
, ICMP_QUERY_MESSAGE
},
27 {9, ICMP_INVALID_MESSAGE
},
28 {10, ICMP_INVALID_MESSAGE
},
29 {ICMP_TIME_EXCEEDED
, ICMP_ERROR_MESSAGE
},
30 {ICMP_PARAMETER_PROBLEM
, ICMP_ERROR_MESSAGE
},
31 {ICMP_TIMESTAMP
, ICMP_QUERY_MESSAGE
},
32 {14, ICMP_INVALID_MESSAGE
},
33 {ICMP_INFO_REQUEST
, ICMP_QUERY_MESSAGE
},
34 {ICMP_INFO_REPLY
, ICMP_QUERY_MESSAGE
},
38 mIp4SupportedIcmp
[23] = {
39 {ICMP_ECHO_REPLY
, ICMP_DEFAULT_CODE
},
41 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE
},
42 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE
},
43 {ICMP_DEST_UNREACHABLE
, ICMP_PROTO_UNREACHABLE
},
44 {ICMP_DEST_UNREACHABLE
, ICMP_PORT_UNREACHABLE
},
45 {ICMP_DEST_UNREACHABLE
, ICMP_FRAGMENT_FAILED
},
46 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCEROUTE_FAILED
},
47 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNKNOWN
},
48 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNKNOWN
},
49 {ICMP_DEST_UNREACHABLE
, ICMP_SOURCE_ISOLATED
},
50 {ICMP_DEST_UNREACHABLE
, ICMP_NET_PROHIBITED
},
51 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_PROHIBITED
},
52 {ICMP_DEST_UNREACHABLE
, ICMP_NET_UNREACHABLE_TOS
},
53 {ICMP_DEST_UNREACHABLE
, ICMP_HOST_UNREACHABLE_TOS
},
55 {ICMP_SOURCE_QUENCH
, ICMP_DEFAULT_CODE
},
57 {ICMP_REDIRECT
, ICMP_NET_REDIRECT
},
58 {ICMP_REDIRECT
, ICMP_HOST_REDIRECT
},
59 {ICMP_REDIRECT
, ICMP_NET_TOS_REDIRECT
},
60 {ICMP_REDIRECT
, ICMP_HOST_TOS_REDIRECT
},
62 {ICMP_ECHO_REQUEST
, ICMP_DEFAULT_CODE
},
64 {ICMP_TIME_EXCEEDED
, ICMP_TIMEOUT_IN_TRANSIT
},
65 {ICMP_TIME_EXCEEDED
, ICMP_TIMEOUT_REASSEMBLE
},
67 {ICMP_PARAMETER_PROBLEM
, ICMP_DEFAULT_CODE
},
73 Process the ICMP redirect. Find the instance then update
76 All kinds of redirect is treated as host redirect as
77 specified by RFC1122 3.3.1.2:
78 "Since the subnet mask appropriate to the destination
79 address is generally not known, a Network Redirect
80 message SHOULD be treated identically to a Host Redirect
83 @param[in] IpSb The IP4 service binding instance that received
85 @param[in] Head The IP head of the received ICMPpacket.
86 @param[in] Packet The content of the ICMP redirect packet with IP
88 @param[in] Icmp The buffer to store the ICMP error message if
91 @retval EFI_INVALID_PARAMETER The parameter is invalid
92 @retval EFI_SUCCESS Successfully updated the route caches
96 Ip4ProcessIcmpRedirect (
100 IN IP4_ICMP_ERROR_HEAD
*Icmp
104 IP4_PROTOCOL
*Ip4Instance
;
105 IP4_ROUTE_CACHE_ENTRY
*CacheEntry
;
112 // Find the interface whose IP address is the source of the
113 // orgianl IP packet.
115 IpIf
= Ip4FindInterface (IpSb
, NTOHL (Icmp
->IpHead
.Src
));
116 Gateway
= NTOHL (Icmp
->Fourth
);
119 // discard the packet if the new gateway address it specifies
120 // is not on the same connected net through which the Redirect
121 // arrived. (RFC1122 3.2.2.2).
123 if ((IpIf
== NULL
) || !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
)) {
125 return EFI_INVALID_PARAMETER
;
129 // Update each IP child's route cache on the interface.
131 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
132 Ip4Instance
= NET_LIST_USER_STRUCT (Entry
, IP4_PROTOCOL
, AddrLink
);
134 if (Ip4Instance
->RouteTable
== NULL
) {
138 Dst
= NTOHL (Icmp
->IpHead
.Dst
);
139 Src
= NTOHL (Icmp
->IpHead
.Src
);
140 CacheEntry
= Ip4FindRouteCache (Ip4Instance
->RouteTable
, Dst
, Src
);
143 // Only update the route cache's gateway if the source of the
144 // Redirect is the current first-hop gateway
146 if ((CacheEntry
!= NULL
) && (NTOHL (Head
->Src
) == CacheEntry
->NextHop
)) {
147 CacheEntry
->NextHop
= Gateway
;
157 Process the ICMP error packet. If it is an ICMP redirect packet,
158 update call Ip4ProcessIcmpRedirect to update the IP instance's
159 route cache, otherwise, deliver the packet to upper layer.
161 @param[in] IpSb The IP4 service that received the packet.
162 @param[in] Head The IP4 head of the ICMP error packet
163 @param[in] Packet The content of the ICMP error with IP4 head
166 @retval EFI_SUCCESS The ICMP error is processed successfully.
167 @retval EFI_INVALID_PARAMETER The packet is invalid
168 @retval Others Failed to process the packet.
172 Ip4ProcessIcmpError (
173 IN IP4_SERVICE
*IpSb
,
178 IP4_ICMP_ERROR_HEAD Icmp
;
180 if (Packet
->TotalSize
< sizeof (Icmp
)) {
182 return EFI_INVALID_PARAMETER
;
185 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
188 // If it is an ICMP redirect error, update the route cache
189 // as RFC1122. Otherwise, demultiplex it to IP instances.
191 if (Icmp
.Head
.Type
== ICMP_REDIRECT
) {
192 return Ip4ProcessIcmpRedirect (IpSb
, Head
, Packet
, &Icmp
);
195 IP4_GET_CLIP_INFO (Packet
)->Status
= EFI_ICMP_ERROR
;
196 return Ip4Demultiplex (IpSb
, Head
, Packet
, NULL
, 0);
201 Replay an ICMP echo request.
203 @param[in] IpSb The IP4 service that receivd the packet
204 @param[in] Head The IP4 head of the ICMP error packet
205 @param[in] Packet The content of the ICMP error with IP4 head
208 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
209 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.
210 @retval Others Failed to answer the ICMP echo request.
215 IN IP4_SERVICE
*IpSb
,
220 IP4_ICMP_QUERY_HEAD
*Icmp
;
226 // make a copy the packet, it is really a bad idea to
227 // send the MNP's buffer back to MNP.
229 Data
= NetbufDuplicate (Packet
, NULL
, IP4_MAX_HEADLEN
);
232 Status
= EFI_OUT_OF_RESOURCES
;
237 // Change the ICMP type to echo reply, exchange the source
238 // and destination, then send it. The source is updated to
239 // use specific destination. See RFC1122. SRR/RR option
240 // update is omitted.
242 Icmp
= (IP4_ICMP_QUERY_HEAD
*) NetbufGetByte (Data
, 0, NULL
);
243 ASSERT (Icmp
!= NULL
);
244 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
245 Icmp
->Head
.Checksum
= 0;
246 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
249 ReplyHead
.Fragment
= 0;
251 ReplyHead
.Protocol
= EFI_IP_PROTO_ICMP
;
255 // Ip4Output will select a source for us
257 ReplyHead
.Dst
= Head
->Src
;
278 Process the ICMP query message. If it is an ICMP echo
279 request, answer it. Otherwise deliver it to upper layer.
281 @param[in] IpSb The IP4 service that receivd the packet
282 @param[in] Head The IP4 head of the ICMP query packet
283 @param[in] Packet The content of the ICMP query with IP4 head
286 @retval EFI_INVALID_PARAMETER The packet is invalid
287 @retval EFI_SUCCESS The ICMP query message is processed
288 @retval Others Failed to process ICMP query.
292 Ip4ProcessIcmpQuery (
293 IN IP4_SERVICE
*IpSb
,
298 IP4_ICMP_QUERY_HEAD Icmp
;
300 if (Packet
->TotalSize
< sizeof (Icmp
)) {
302 return EFI_INVALID_PARAMETER
;
305 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
307 if (Icmp
.Head
.Type
== ICMP_ECHO_REQUEST
) {
308 return Ip4IcmpReplyEcho (IpSb
, Head
, Packet
);
311 return Ip4Demultiplex (IpSb
, Head
, Packet
, NULL
, 0);
316 Handle the ICMP packet. First validate the message format,
317 then according to the message types, process it as query or
320 @param[in] IpSb The IP4 service that receivd the packet.
321 @param[in] Head The IP4 head of the ICMP query packet.
322 @param[in] Packet The content of the ICMP query with IP4 head
325 @retval EFI_INVALID_PARAMETER The packet is malformated.
326 @retval EFI_SUCCESS The ICMP message is successfully processed.
327 @retval Others Failed to handle ICMP packet.
332 IN IP4_SERVICE
*IpSb
,
340 if (Packet
->TotalSize
< sizeof (Icmp
)) {
344 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
346 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
350 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
351 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
355 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
356 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
358 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
359 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
365 return EFI_INVALID_PARAMETER
;