3 Copyright (c) 2005 - 2009, Intel Corporation.<BR>
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.
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 IP service that received the packet.
162 @param[in] Head The IP head of the ICMP error packet
163 @param[in] Packet The content of the ICMP error with IP 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
);
201 Replay an ICMP echo request.
203 @param[in] IpSb The IP service that receivd the packet
204 @param[in] Head The IP head of the ICMP error packet
205 @param[in] Packet The content of the ICMP error with IP 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 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
244 Icmp
->Head
.Checksum
= 0;
245 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
248 ReplyHead
.Fragment
= 0;
250 ReplyHead
.Protocol
= EFI_IP_PROTO_ICMP
;
254 // Ip4Output will select a source for us
256 ReplyHead
.Dst
= Head
->Src
;
277 Process the ICMP query message. If it is an ICMP echo
278 request, answer it. Otherwise deliver it to upper layer.
280 @param[in] IpSb The IP service that receivd the packet
281 @param[in] Head The IP head of the ICMP query packet
282 @param[in] Packet The content of the ICMP query with IP head
285 @retval EFI_INVALID_PARAMETER The packet is invalid
286 @retval EFI_SUCCESS The ICMP query message is processed
287 @retval Others Failed to process ICMP query.
291 Ip4ProcessIcmpQuery (
292 IN IP4_SERVICE
*IpSb
,
297 IP4_ICMP_QUERY_HEAD Icmp
;
299 if (Packet
->TotalSize
< sizeof (Icmp
)) {
301 return EFI_INVALID_PARAMETER
;
304 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
306 if (Icmp
.Head
.Type
== ICMP_ECHO_REQUEST
) {
307 return Ip4IcmpReplyEcho (IpSb
, Head
, Packet
);
310 return Ip4Demultiplex (IpSb
, Head
, Packet
);
315 Handle the ICMP packet. First validate the message format,
316 then according to the message types, process it as query or
319 @param[in] IpSb The IP service that receivd the packet
320 @param[in] Head The IP head of the ICMP query packet
321 @param[in] Packet The content of the ICMP query with IP head
324 @retval EFI_INVALID_PARAMETER The packet is malformated.
325 @retval EFI_SUCCESS The ICMP message is successfully processed.
326 @retval Others Failed to handle ICMP packet.
331 IN IP4_SERVICE
*IpSb
,
339 if (Packet
->TotalSize
< sizeof (Icmp
)) {
343 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
345 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
349 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
350 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
354 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
355 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
357 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
358 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
364 return EFI_INVALID_PARAMETER
;