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
104 Ip4ProcessIcmpRedirect (
105 IN IP4_SERVICE
*IpSb
,
108 IN IP4_ICMP_ERROR_HEAD
*Icmp
111 NET_LIST_ENTRY
*Entry
;
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_INVALID_PARAMETER The packet is invalid
175 @retval Others Failed to process the packet.
176 @retval EFI_SUCCESS The ICMP error is processed successfully.
181 Ip4ProcessIcmpError (
182 IN IP4_SERVICE
*IpSb
,
187 IP4_ICMP_ERROR_HEAD Icmp
;
189 if (Packet
->TotalSize
< sizeof (Icmp
)) {
191 return EFI_INVALID_PARAMETER
;
194 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
197 // If it is an ICMP redirect error, update the route cache
198 // as RFC1122. Otherwise, demultiplex it to IP instances.
200 if (Icmp
.Head
.Type
== ICMP_REDIRECT
) {
201 return Ip4ProcessIcmpRedirect (IpSb
, Head
, Packet
, &Icmp
);
204 IP4_GET_CLIP_INFO (Packet
)->Status
= EFI_ICMP_ERROR
;
205 return Ip4Demultiplex (IpSb
, Head
, Packet
);
210 Replay an ICMP echo request.
212 @param IpSb The IP service that receivd the packet
213 @param Head The IP head of the ICMP error packet
214 @param Packet The content of the ICMP error with IP head
217 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
218 @retval EFI_SUCCESS The ICMP Echo request is successfully answered.
219 @retval Others Failed to answer the ICMP echo request.
224 IN IP4_SERVICE
*IpSb
,
229 IP4_ICMP_QUERY_HEAD
*Icmp
;
235 // make a copy the packet, it is really a bad idea to
236 // send the MNP's buffer back to MNP.
238 Data
= NetbufDuplicate (Packet
, NULL
, IP4_MAX_HEADLEN
);
241 Status
= EFI_OUT_OF_RESOURCES
;
246 // Change the ICMP type to echo reply, exchange the source
247 // and destination, then send it. The source is updated to
248 // use specific destination. See RFC1122. SRR/RR option
249 // update is omitted.
251 Icmp
= (IP4_ICMP_QUERY_HEAD
*) NetbufGetByte (Data
, 0, NULL
);
252 Icmp
->Head
.Type
= ICMP_ECHO_REPLY
;
253 Icmp
->Head
.Checksum
= 0;
254 Icmp
->Head
.Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Icmp
, Data
->TotalSize
));
257 ReplyHead
.Fragment
= 0;
259 ReplyHead
.Protocol
= IP4_PROTO_ICMP
;
263 // Ip4Output will select a source for us
265 ReplyHead
.Dst
= Head
->Src
;
286 Process the ICMP query message. If it is an ICMP echo
287 request, answer it. Otherwise deliver it to upper layer.
289 @param IpSb The IP service that receivd the packet
290 @param Head The IP head of the ICMP query packet
291 @param Packet The content of the ICMP query with IP head
294 @retval EFI_INVALID_PARAMETER The packet is invalid
295 @retval EFI_SUCCESS The ICMP query message is processed
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.
338 IN IP4_SERVICE
*IpSb
,
346 if (Packet
->TotalSize
< sizeof (Icmp
)) {
350 NetbufCopy (Packet
, 0, sizeof (Icmp
), (UINT8
*) &Icmp
);
352 if (Icmp
.Type
> ICMP_TYPE_MAX
) {
356 Checksum
= (UINT16
) (~NetbufChecksum (Packet
));
357 if ((Icmp
.Checksum
!= 0) && (Checksum
!= 0)) {
361 if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_ERROR_MESSAGE
) {
362 return Ip4ProcessIcmpError (IpSb
, Head
, Packet
);
364 } else if (mIcmpClass
[Icmp
.Type
].IcmpClass
== ICMP_QUERY_MESSAGE
) {
365 return Ip4ProcessIcmpQuery (IpSb
, Head
, Packet
);
371 return EFI_INVALID_PARAMETER
;