TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip4Icmp.c
Go to the documentation of this file.
1
8#include "Ip4Impl.h"
9
11 mIcmpClass[] = {
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 },
29};
30
32 mIp4SupportedIcmp[23] = {
33 { ICMP_ECHO_REPLY, ICMP_DEFAULT_CODE },
34
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 },
48
49 { ICMP_SOURCE_QUENCH, ICMP_DEFAULT_CODE },
50
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 },
55
56 { ICMP_ECHO_REQUEST, ICMP_DEFAULT_CODE },
57
58 { ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_IN_TRANSIT },
59 { ICMP_TIME_EXCEEDED, ICMP_TIMEOUT_REASSEMBLE },
60
61 { ICMP_PARAMETER_PROBLEM, ICMP_DEFAULT_CODE },
62};
63
89 IN IP4_SERVICE *IpSb,
90 IN IP4_HEAD *Head,
91 IN NET_BUF *Packet,
93 )
94{
95 LIST_ENTRY *Entry;
96 IP4_PROTOCOL *Ip4Instance;
97 IP4_ROUTE_CACHE_ENTRY *CacheEntry;
98 IP4_INTERFACE *IpIf;
99 IP4_ADDR Gateway;
100 IP4_ADDR Src;
101 IP4_ADDR Dst;
102
103 //
104 // Find the interface whose IP address is the source of the
105 // orgianl IP packet.
106 //
107 IpIf = Ip4FindInterface (IpSb, NTOHL (Icmp->IpHead.Src));
108 Gateway = NTOHL (Icmp->Fourth);
109
110 //
111 // discard the packet if the new gateway address it specifies
112 // is not on the same connected net through which the Redirect
113 // arrived. (RFC1122 3.2.2.2).
114 //
115 if ((IpIf == NULL) || !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask)) {
116 NetbufFree (Packet);
117 return EFI_INVALID_PARAMETER;
118 }
119
120 //
121 // Update each IP child's route cache on the interface.
122 //
123 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
124 Ip4Instance = NET_LIST_USER_STRUCT (Entry, IP4_PROTOCOL, AddrLink);
125
126 if (Ip4Instance->RouteTable == NULL) {
127 continue;
128 }
129
130 Dst = NTOHL (Icmp->IpHead.Dst);
131 Src = NTOHL (Icmp->IpHead.Src);
132 CacheEntry = Ip4FindRouteCache (Ip4Instance->RouteTable, Dst, Src);
133
134 //
135 // Only update the route cache's gateway if the source of the
136 // Redirect is the current first-hop gateway
137 //
138 if ((CacheEntry != NULL) && (NTOHL (Head->Src) == CacheEntry->NextHop)) {
139 CacheEntry->NextHop = Gateway;
140 }
141 }
142
143 NetbufFree (Packet);
144 return EFI_SUCCESS;
145}
146
164 IN IP4_SERVICE *IpSb,
165 IN IP4_HEAD *Head,
166 IN NET_BUF *Packet
167 )
168{
170
171 if (Packet->TotalSize < sizeof (Icmp)) {
172 NetbufFree (Packet);
173 return EFI_INVALID_PARAMETER;
174 }
175
176 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
177
178 //
179 // If it is an ICMP redirect error, update the route cache
180 // as RFC1122. Otherwise, demultiplex it to IP instances.
181 //
182 if (Icmp.Head.Type == ICMP_REDIRECT) {
183 return Ip4ProcessIcmpRedirect (IpSb, Head, Packet, &Icmp);
184 }
185
186 IP4_GET_CLIP_INFO (Packet)->Status = EFI_ICMP_ERROR;
187 return Ip4Demultiplex (IpSb, Head, Packet, NULL, 0);
188}
189
205 IN IP4_SERVICE *IpSb,
206 IN IP4_HEAD *Head,
207 IN NET_BUF *Packet
208 )
209{
211 NET_BUF *Data;
212 EFI_STATUS Status;
213 IP4_HEAD ReplyHead;
214
215 //
216 // make a copy the packet, it is really a bad idea to
217 // send the MNP's buffer back to MNP.
218 //
219 Data = NetbufDuplicate (Packet, NULL, IP4_MAX_HEADLEN);
220
221 if (Data == NULL) {
222 Status = EFI_OUT_OF_RESOURCES;
223 goto ON_EXIT;
224 }
225
226 //
227 // Change the ICMP type to echo reply, exchange the source
228 // and destination, then send it. The source is updated to
229 // use specific destination. See RFC1122. SRR/RR option
230 // update is omitted.
231 //
232 Icmp = (IP4_ICMP_QUERY_HEAD *)NetbufGetByte (Data, 0, NULL);
233 ASSERT (Icmp != NULL);
234 Icmp->Head.Type = ICMP_ECHO_REPLY;
235 Icmp->Head.Checksum = 0;
236 Icmp->Head.Checksum = (UINT16)(~NetblockChecksum ((UINT8 *)Icmp, Data->TotalSize));
237
238 ReplyHead.Tos = 0;
239 ReplyHead.Fragment = 0;
240 ReplyHead.Ttl = 64;
241 ReplyHead.Protocol = EFI_IP_PROTO_ICMP;
242 ReplyHead.Src = 0;
243
244 //
245 // Ip4Output will select a source for us
246 //
247 ReplyHead.Dst = Head->Src;
248
249 Status = Ip4Output (
250 IpSb,
251 NULL,
252 Data,
253 &ReplyHead,
254 NULL,
255 0,
256 IP4_ALLZERO_ADDRESS,
258 NULL
259 );
260 if (EFI_ERROR (Status)) {
261 NetbufFree (Data);
262 }
263
264ON_EXIT:
265 NetbufFree (Packet);
266 return Status;
267}
268
285 IN IP4_SERVICE *IpSb,
286 IN IP4_HEAD *Head,
287 IN NET_BUF *Packet
288 )
289{
291
292 if (Packet->TotalSize < sizeof (Icmp)) {
293 NetbufFree (Packet);
294 return EFI_INVALID_PARAMETER;
295 }
296
297 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
298
299 if (Icmp.Head.Type == ICMP_ECHO_REQUEST) {
300 return Ip4IcmpReplyEcho (IpSb, Head, Packet);
301 }
302
303 return Ip4Demultiplex (IpSb, Head, Packet, NULL, 0);
304}
305
323 IN IP4_SERVICE *IpSb,
324 IN IP4_HEAD *Head,
325 IN NET_BUF *Packet
326 )
327{
328 IP4_ICMP_HEAD Icmp;
329 UINT16 Checksum;
330
331 if (Packet->TotalSize < sizeof (Icmp)) {
332 goto DROP;
333 }
334
335 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
336
337 if (Icmp.Type > ICMP_TYPE_MAX) {
338 goto DROP;
339 }
340
341 Checksum = (UINT16)(~NetbufChecksum (Packet));
342 if ((Icmp.Checksum != 0) && (Checksum != 0)) {
343 goto DROP;
344 }
345
346 if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_ERROR_MESSAGE) {
347 return Ip4ProcessIcmpError (IpSb, Head, Packet);
348 } else if (mIcmpClass[Icmp.Type].IcmpClass == ICMP_QUERY_MESSAGE) {
349 return Ip4ProcessIcmpQuery (IpSb, Head, Packet);
350 }
351
352DROP:
353 NetbufFree (Packet);
354 return EFI_INVALID_PARAMETER;
355}
IP4_INTERFACE * Ip4FindInterface(IN IP4_SERVICE *IpSb, IN IP4_ADDR Ip)
Definition: Ip4Common.c:124
EFI_STATUS Ip4ProcessIcmpError(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet)
Definition: Ip4Icmp.c:163
EFI_STATUS Ip4IcmpReplyEcho(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet)
Definition: Ip4Icmp.c:204
EFI_STATUS Ip4ProcessIcmpRedirect(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet, IN IP4_ICMP_ERROR_HEAD *Icmp)
Definition: Ip4Icmp.c:88
EFI_STATUS Ip4ProcessIcmpQuery(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet)
Definition: Ip4Icmp.c:284
EFI_STATUS Ip4IcmpHandle(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet)
Definition: Ip4Icmp.c:322
EFI_STATUS Ip4Demultiplex(IN IP4_SERVICE *IpSb, IN IP4_HEAD *Head, IN NET_BUF *Packet, IN UINT8 *Option, IN UINT32 OptionLen)
Definition: Ip4Input.c:1495
VOID Ip4SysPacketSent(IP4_PROTOCOL *Ip4Instance, NET_BUF *Packet, EFI_STATUS IoStatus, UINT32 LinkFlag, VOID *Context)
Definition: Ip4Output.c:158
EFI_STATUS Ip4Output(IN IP4_SERVICE *IpSb, IN IP4_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN IP4_HEAD *Head, IN UINT8 *Option, IN UINT32 OptLen, IN IP4_ADDR GateWay, IN IP4_FRAME_CALLBACK Callback, IN VOID *Context)
Definition: Ip4Output.c:205
IP4_ROUTE_CACHE_ENTRY * Ip4FindRouteCache(IN IP4_ROUTE_TABLE *RtTable, IN IP4_ADDR Dest, IN IP4_ADDR Src)
Definition: Ip4Route.c:397
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
UINT16 EFIAPI NetbufChecksum(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:1687
UINT16 EFIAPI NetblockChecksum(IN UINT8 *Bulk, IN UINT32 Len)
Definition: NetBuffer.c:1615
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
NET_BUF *EFIAPI NetbufDuplicate(IN NET_BUF *Nbuf, IN OUT NET_BUF *Duplicate OPTIONAL, IN UINT32 HeadSpace)
Definition: NetBuffer.c:280
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112