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
84 All kinds of redirect is treated as host redirect as
85 specified by RFC1122 3.3.1.2:
86 "Since the subnet mask appropriate to the destination
87 address is generally not known, a Network Redirect
88 message SHOULD be treated identically to a Host Redirect
91 @param IpSb The IP4 service binding instance that received the
93 @param Head The IP head of the received ICMPpacket.
94 @param Packet The content of the ICMP redirect packet with IP
96 @param Icmp The buffer to store the ICMP error message if
99 @retval EFI_INVALID_PARAMETER The parameter is invalid
100 @retval EFI_SUCCESS Successfully updated the route caches
104 Ip4ProcessIcmpRedirect (
105 IN IP4_SERVICE
*IpSb
,
108 IN IP4_ICMP_ERROR_HEAD
*Icmp
112 IP4_PROTOCOL
*Ip4Instance
;
113 IP4_ROUTE_CACHE_ENTRY
*CacheEntry
;
118 // Find the interface whose IP address is the source of the
119 // orgianl IP packet.
121 IpIf
= Ip4FindInterface (IpSb
, NTOHL (Icmp
->IpHead
.Src
));
122 Gateway
= NTOHL (Icmp
->Fourth
);
125 // discard the packet if the new gateway address it specifies
126 // is not on the same connected net through which the Redirect
127 // arrived. (RFC1122 3.2.2.2).
129 if ((IpIf
== NULL
) || !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
)) {
131 return EFI_INVALID_PARAMETER
;
135 // Update each IP child's route cache on the interface.
137 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
138 Ip4Instance
= NET_LIST_USER_STRUCT (Entry
, IP4_PROTOCOL
, AddrLink
);
140 if (Ip4Instance
->RouteTable
== NULL
) {
144 CacheEntry
= Ip4FindRouteCache (
145 Ip4Instance
->RouteTable
,
146 NTOHL (Icmp
->IpHead
.Dst
),
147 NTOHL (Icmp
->IpHead
.Src
)
151 // Only update the route cache's gateway if the source of the
152 // Redirect is the current first-hop gateway
154 if ((CacheEntry
!= NULL
) && (NTOHL (Head
->Src
) == CacheEntry
->NextHop
)) {
155 CacheEntry
->NextHop
= Gateway
;
165 Process the ICMP error packet. If it is an ICMP redirect packet,
166 update call Ip4ProcessIcmpRedirect to update the IP instance's
167 route cache, otherwise, deliver the packet to upper layer.
169 @param IpSb The IP service that received the packet.
170 @param Head The IP head of the ICMP error packet
171 @param Packet The content of the ICMP error with IP head
174 @retval EFI_SUCCESS The ICMP error is processed successfully.
175 @retval EFI_INVALID_PARAMETER The packet is invalid
176 @retval Others Failed to process the packet.
180 Ip4ProcessIcmpError (
181 IN IP4_SERVICE
*IpSb
,
186 IP4_ICMP_ERROR_HEAD Icmp
;
188 if (Packet
->TotalSize
< sizeof (Icmp
)) {
190 return EFI_INVALID_PARAMETER
;
193 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
196 // If it is an ICMP redirect error, update the route cache
197 // as RFC1122. Otherwise, demultiplex it to IP instances.
199 if (Icmp
.Head
.Type
== ICMP_REDIRECT
) {
200 return Ip4ProcessIcmpRedirect (IpSb
, Head
, Packet
, &Icmp
);
203 IP4_GET_CLIP_INFO (Packet
)->Status
= EFI_ICMP_ERROR
;
204 return Ip4Demultiplex (IpSb
, Head
, Packet
);
209 Replay an ICMP echo request.
211 @param IpSb The IP service that receivd the packet
212 @param Head The IP head of the ICMP error packet
213 @param Packet The content of the ICMP error with IP head
216 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
217 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.
218 @retval Others Failed to answer the ICMP echo request.
223 IN IP4_SERVICE
*IpSb
,
228 IP4_ICMP_QUERY_HEAD
*Icmp
;
234 // make a copy the packet, it is really a bad idea to
235 // send the MNP's buffer back to MNP.
237 Data
= NetbufDuplicate (Packet
, NULL
, IP4_MAX_HEADLEN
);
240 Status
= EFI_OUT_OF_RESOURCES
;
245 // Change the ICMP type to echo reply, exchange the source
246 // and destination, then send it. The source is updated to
247 // use specific destination. See RFC1122. SRR/RR option
248 // update is omitted.
250 Icmp
= (IP4_ICMP_QUERY_HEAD
*) NetbufGetByte (Data
, 0, NULL
);
251 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
252 Icmp
->Head
.Checksum
= 0;
253 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
256 ReplyHead
.Fragment
= 0;
258 ReplyHead
.Protocol
= IP4_PROTO_ICMP
;
262 // Ip4Output will select a source for us
264 ReplyHead
.Dst
= Head
->Src
;
285 Process the ICMP query message. If it is an ICMP echo
286 request, answer it. Otherwise deliver it to upper layer.
288 @param IpSb The IP service that receivd the packet
289 @param Head The IP head of the ICMP query packet
290 @param Packet The content of the ICMP query with IP head
293 @retval EFI_INVALID_PARAMETER The packet is invalid
294 @retval EFI_SUCCESS The ICMP query message is processed
295 @retval Others Failed to process ICMP query.
299 Ip4ProcessIcmpQuery (
300 IN IP4_SERVICE
*IpSb
,
305 IP4_ICMP_QUERY_HEAD Icmp
;
307 if (Packet
->TotalSize
< sizeof (Icmp
)) {
309 return EFI_INVALID_PARAMETER
;
312 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
314 if (Icmp
.Head
.Type
== ICMP_ECHO_REQUEST
) {
315 return Ip4IcmpReplyEcho (IpSb
, Head
, Packet
);
318 return Ip4Demultiplex (IpSb
, Head
, Packet
);
323 Handle the ICMP packet. First validate the message format,
324 then according to the message types, process it as query or
327 @param IpSb The IP service that receivd the packet
328 @param Head The IP head of the ICMP query packet
329 @param Packet The content of the ICMP query with IP head
332 @retval EFI_INVALID_PARAMETER The packet is malformated.
333 @retval EFI_SUCCESS The ICMP message is successfully processed.
334 @retval Others Failed to handle ICMP packet.
339 IN IP4_SERVICE
*IpSb
,
347 if (Packet
->TotalSize
< sizeof (Icmp
)) {
351 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
353 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
357 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
358 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
362 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
363 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
365 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
366 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
372 return EFI_INVALID_PARAMETER
;