]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c
Fix capitalization
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeBc / Dxe / pxe_bc_ip.c
1 /*++
2
3 Copyright (c) 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
8
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.
11
12 Module Name:
13 pxe_bc_ip.c
14
15 Abstract:
16
17 --*/
18
19
20 #include "Bc.h"
21
22 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
23 BOOLEAN
24 OnSameSubnet (
25 IN UINTN IpLength,
26 IN EFI_IP_ADDRESS *Ip1,
27 IN EFI_IP_ADDRESS *Ip2,
28 IN EFI_IP_ADDRESS *SubnetMask
29 )
30 /*++
31
32 Routine Description:
33 Check if two IP addresses are on the same subnet.
34
35 Arguments:
36 IpLength - Length of IP address in bytes.
37 Ip1 - IP address to check.
38 Ip2 - IP address to check.
39 SubnetMask - Subnet mask to check with.
40
41 Returns:
42 TRUE - IP addresses are on the same subnet.
43 FALSE - IP addresses are on different subnets.
44
45 --*/
46 {
47 if (IpLength == 0 || Ip1 == NULL || Ip2 == NULL || SubnetMask == NULL) {
48 return FALSE;
49 }
50
51 while (IpLength-- != 0) {
52 if ((Ip1->v6.Addr[IpLength] ^ Ip2->v6.Addr[IpLength]) & SubnetMask->v6.Addr[IpLength]) {
53 return FALSE;
54 }
55 }
56
57 return TRUE;
58 }
59
60 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
61 VOID
62 IpAddRouter (
63 IN PXE_BASECODE_DEVICE *Private,
64 IN EFI_IP_ADDRESS *RouterIpPtr
65 )
66 /*++
67
68 Routine Description:
69 Add router to router table.
70
71 Arguments:
72 Private - Pointer PxeBc instance data.
73 RouterIpPtr - Pointer to router IP address.
74
75 Returns:
76 Nothing
77
78 --*/
79 {
80 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
81 UINTN Index;
82
83 if (Private == NULL || RouterIpPtr == NULL) {
84 return ;
85 }
86
87 PxeBcMode = Private->EfiBc.Mode;
88
89 //
90 // if we are filled up or this is not on the same subnet, forget it
91 //
92 if ((PxeBcMode->RouteTableEntries == PXE_ROUTER_TABLE_SIZE) ||
93 !OnSameSubnet(Private->IpLength, &PxeBcMode->StationIp, RouterIpPtr, &PxeBcMode->SubnetMask)) {
94 return ;
95 }
96 //
97 // make sure we don't already have it
98 //
99 for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
100 if (!CompareMem (
101 &PxeBcMode->RouteTable[Index].GwAddr,
102 RouterIpPtr,
103 Private->IpLength
104 )) {
105 return ;
106 }
107 }
108 //
109 // keep it
110 //
111 ZeroMem (
112 &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries],
113 sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY)
114 );
115
116 CopyMem (
117 &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries++].GwAddr,
118 RouterIpPtr,
119 Private->IpLength
120 );
121 }
122
123 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
124
125 //
126 // return router ip to use for DestIp (0 if none)
127 //
128 STATIC
129 EFI_IP_ADDRESS *
130 GetRouterIp (
131 PXE_BASECODE_DEVICE *Private,
132 EFI_IP_ADDRESS *DestIpPtr
133 )
134 {
135 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
136 UINTN Index;
137
138 if (Private == NULL || DestIpPtr == NULL) {
139 return NULL;
140 }
141
142 PxeBcMode = Private->EfiBc.Mode;
143
144 for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) {
145 if (OnSameSubnet (
146 Private->IpLength,
147 &PxeBcMode->RouteTable[Index].IpAddr,
148 DestIpPtr,
149 &PxeBcMode->RouteTable[Index].SubnetMask
150 )) {
151 return &PxeBcMode->RouteTable[Index].GwAddr;
152 }
153 }
154
155 return NULL;
156 }
157
158 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
159
160 //
161 // routine to send ipv4 packet
162 // ipv4 header of length HdrLth in TransmitBufferPtr
163 // routine fills in ipv4hdr Ver_Hdl, TotalLength, and Checksum, moves in Data
164 // and gets dest MAC address
165 //
166 #define IP_TX_BUFFER ((IPV4_BUFFER *) Private->TransmitBufferPtr)
167 #define IP_TX_HEADER IP_TX_BUFFER->IpHeader
168
169 EFI_STATUS
170 Ipv4Xmt (
171 PXE_BASECODE_DEVICE *Private,
172 UINT32 GatewayIp,
173 UINTN IpHeaderLength,
174 UINTN TotalHeaderLength,
175 VOID *Data,
176 UINTN DataLength,
177 EFI_PXE_BASE_CODE_FUNCTION Function
178 )
179 {
180 EFI_MAC_ADDRESS DestMac;
181 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
182 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
183 EFI_STATUS StatCode;
184 UINTN PacketLength;
185
186 Snp = Private->SimpleNetwork;
187 PxeBcMode = Private->EfiBc.Mode;
188 StatCode = EFI_SUCCESS;
189 PacketLength = TotalHeaderLength + DataLength;
190
191 //
192 // get dest MAC address
193 // multicast - convert to hw equiv
194 // unicast on same net, use arp
195 // on different net, arp for router
196 //
197 if (IP_TX_HEADER.DestAddr.L == BROADCAST_IPv4) {
198 CopyMem (&DestMac, &Snp->Mode->BroadcastAddress, sizeof (DestMac));
199 } else if (IS_MULTICAST (&IP_TX_HEADER.DestAddr)) {
200 StatCode = (*Snp->MCastIpToMac) (Snp, PxeBcMode->UsingIpv6, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr, &DestMac);
201 } else {
202 UINT32 Ip;
203
204 if (OnSameSubnet (
205 Private->IpLength,
206 &PxeBcMode->StationIp,
207 (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr,
208 &PxeBcMode->SubnetMask
209 )) {
210 Ip = IP_TX_HEADER.DestAddr.L;
211 } else if (GatewayIp != 0) {
212 Ip = GatewayIp;
213 } else {
214 EFI_IP_ADDRESS *TmpIp;
215
216 TmpIp = GetRouterIp (Private, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr);
217
218 if (TmpIp == NULL) {
219 DEBUG (
220 (EFI_D_WARN,
221 "\nIpv4Xmit() Exit #1 %xh (%r)",
222 EFI_NO_RESPONSE,
223 EFI_NO_RESPONSE)
224 );
225
226 return EFI_NO_RESPONSE;
227 //
228 // no router
229 //
230 }
231
232 Ip = TmpIp->Addr[0];
233 }
234
235 if (!GetHwAddr (
236 Private,
237 (EFI_IP_ADDRESS *) &Ip,
238 (EFI_MAC_ADDRESS *) &DestMac
239 )) {
240 if (!PxeBcMode->AutoArp) {
241 DEBUG (
242 (EFI_D_WARN,
243 "\nIpv4Xmit() Exit #2 %xh (%r)",
244 EFI_DEVICE_ERROR,
245 EFI_DEVICE_ERROR)
246 );
247
248 return EFI_DEVICE_ERROR;
249 } else {
250 StatCode = DoArp (
251 Private,
252 (EFI_IP_ADDRESS *) &Ip,
253 (EFI_MAC_ADDRESS *) &DestMac
254 );
255 }
256 }
257 }
258
259 if (EFI_ERROR (StatCode)) {
260 DEBUG ((EFI_D_WARN, "\nIpv4Xmit() Exit #3 %xh (%r)", StatCode, StatCode));
261 return StatCode;
262 }
263 //
264 // fill in packet info
265 //
266 SET_IPV4_VER_HDL (&IP_TX_HEADER, IpHeaderLength);
267 IP_TX_HEADER.TotalLength = HTONS (PacketLength);
268 IP_TX_HEADER.HeaderChecksum = IpChecksum ((UINT16 *) &IP_TX_HEADER, IpHeaderLength);
269 CopyMem (((UINT8 *) &IP_TX_HEADER) + TotalHeaderLength, Data, DataLength);
270
271 //
272 // send it
273 //
274 return SendPacket (
275 Private,
276 (UINT8 *) &IP_TX_HEADER - Snp->Mode->MediaHeaderSize,
277 &IP_TX_HEADER,
278 PacketLength,
279 &DestMac,
280 PXE_PROTOCOL_ETHERNET_IP,
281 Function
282 );
283 }
284
285 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
286
287 //
288 // send ipv4 packet with option
289 //
290 EFI_STATUS
291 Ipv4SendWOp (
292 PXE_BASECODE_DEVICE *Private,
293 UINT32 GatewayIp,
294 UINT8 *Msg,
295 UINTN MessageLength,
296 UINT8 Prot,
297 UINT8 *Option,
298 UINTN OptionLength,
299 UINT32 DestIp,
300 EFI_PXE_BASE_CODE_FUNCTION Function
301 )
302 {
303 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
304 UINTN HdrLth;
305
306 PxeBcMode = Private->EfiBc.Mode;
307 HdrLth = sizeof (IPV4_HEADER) + OptionLength;
308
309 ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
310 IP_TX_HEADER.TimeToLive = PxeBcMode->TTL;
311 IP_TX_HEADER.TypeOfService = PxeBcMode->ToS;
312 IP_TX_HEADER.Protocol = Prot;
313 IP_TX_HEADER.SrcAddr.L = *(UINT32 *) &PxeBcMode->StationIp;
314 IP_TX_HEADER.DestAddr.L = DestIp;
315 IP_TX_HEADER.Id = Random (Private);
316 CopyMem (IP_TX_BUFFER->u.Data, Option, OptionLength);
317 return Ipv4Xmt (
318 Private,
319 GatewayIp,
320 HdrLth,
321 HdrLth,
322 Msg,
323 MessageLength,
324 Function
325 );
326 }
327
328 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
329
330 //
331 // send MessageLength message at MessagePtr - higher level protocol header already in TransmitBufferPtr, length HdrSize
332 //
333 EFI_STATUS
334 Ip4Send (
335 PXE_BASECODE_DEVICE *Private, // pointer to instance data
336 UINTN MayFrag, //
337 UINT8 Prot, // protocol
338 UINT32 SrcIp, // Source IP address
339 UINT32 DestIp, // Destination IP address
340 UINT32 GatewayIp, // used if not NULL and needed
341 UINTN HdrSize, // protocol header byte length
342 UINT8 *MessagePtr, // pointer to data
343 UINTN MessageLength // data byte length
344 )
345 {
346 EFI_STATUS StatCode;
347 UINTN TotDataLength;
348
349 TotDataLength = HdrSize + MessageLength;
350
351 if (TotDataLength > MAX_IPV4_DATA_SIZE) {
352 DEBUG (
353 (EFI_D_WARN,
354 "\nIp4Send() Exit #1 %xh (%r)",
355 EFI_BAD_BUFFER_SIZE,
356 EFI_BAD_BUFFER_SIZE)
357 );
358
359 return EFI_BAD_BUFFER_SIZE;
360 }
361
362 ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER));
363 IP_TX_HEADER.TimeToLive = DEFAULT_TTL;
364 IP_TX_HEADER.Protocol = Prot;
365 IP_TX_HEADER.SrcAddr.L = SrcIp;
366 IP_TX_HEADER.DestAddr.L = DestIp;
367 IP_TX_HEADER.Id = Random (Private);
368
369 if (!MayFrag) {
370 *(UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_NO_FRAG >> 8;
371 }
372 //
373 // check for need to fragment
374 //
375 if (TotDataLength > MAX_IPV4_FRAME_DATA_SIZE) {
376 UINTN DataLengthSent;
377 UINT16 FragmentOffset;
378
379 FragmentOffset = IP_MORE_FRAG;
380 //
381 // frag offset field
382 //
383 if (!MayFrag) {
384 DEBUG (
385 (EFI_D_WARN,
386 "\nIp4Send() Exit #2 %xh (%r)",
387 EFI_BAD_BUFFER_SIZE,
388 EFI_BAD_BUFFER_SIZE)
389 );
390
391 return EFI_BAD_BUFFER_SIZE;
392 }
393 //
394 // send out in fragments - first includes upper level header
395 // all are max and include more frag bit except last
396 //
397 * (UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_MORE_FRAG >> 8;
398
399 #define IPV4_FRAG_SIZE (MAX_IPV4_FRAME_DATA_SIZE & 0xfff8)
400 #define IPV4_FRAG_OFF_INC (IPV4_FRAG_SIZE >> 3)
401
402 DataLengthSent = IPV4_FRAG_SIZE - HdrSize;
403
404 StatCode = Ipv4Xmt (
405 Private,
406 GatewayIp,
407 sizeof (IPV4_HEADER),
408 sizeof (IPV4_HEADER) + HdrSize,
409 MessagePtr,
410 DataLengthSent,
411 Private->Function
412 );
413
414 if (EFI_ERROR (StatCode)) {
415 DEBUG (
416 (EFI_D_WARN,
417 "\nIp4Send() Exit #3 %xh (%r)",
418 StatCode,
419 StatCode)
420 );
421
422 return StatCode;
423 }
424
425 MessagePtr += DataLengthSent;
426 MessageLength -= DataLengthSent;
427 FragmentOffset += IPV4_FRAG_OFF_INC;
428 IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
429
430 while (MessageLength > IPV4_FRAG_SIZE) {
431 StatCode = Ipv4Xmt (
432 Private,
433 GatewayIp,
434 sizeof (IPV4_HEADER),
435 sizeof (IPV4_HEADER),
436 MessagePtr,
437 IPV4_FRAG_SIZE,
438 Private->Function
439 );
440
441 if (EFI_ERROR (StatCode)) {
442 DEBUG (
443 (EFI_D_WARN,
444 "\nIp4Send() Exit #3 %xh (%r)",
445 StatCode,
446 StatCode)
447 );
448
449 return StatCode;
450 }
451
452 MessagePtr += IPV4_FRAG_SIZE;
453 MessageLength -= IPV4_FRAG_SIZE;
454 FragmentOffset += IPV4_FRAG_OFF_INC;
455 IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset);
456 }
457
458 * (UINT8 *) (&IP_TX_HEADER.FragmentFields) &= ~(IP_MORE_FRAG >> 8);
459 HdrSize = 0;
460 }
461 //
462 // transmit
463 //
464 return Ipv4Xmt (
465 Private,
466 GatewayIp,
467 sizeof (IPV4_HEADER),
468 sizeof (IPV4_HEADER) + HdrSize,
469 MessagePtr,
470 MessageLength,
471 Private->Function
472 );
473 }
474
475 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
476
477 //
478 // return true if dst IP in receive header matched with what's enabled
479 //
480 STATIC
481 BOOLEAN
482 IPgood (
483 PXE_BASECODE_DEVICE *Private,
484 IPV4_HEADER *IpHeader
485 )
486 {
487 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
488 UINTN Index;
489
490 PxeBcMode = Private->EfiBc.Mode;
491
492 if (PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
493 return TRUE;
494 }
495
496 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) &&
497 IS_MULTICAST (&IpHeader->DestAddr)
498 ) {
499 return TRUE;
500 }
501
502 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) &&
503 PxeBcMode->StationIp.Addr[0] == IpHeader->DestAddr.L
504 ) {
505 return TRUE;
506 }
507
508 if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) && IpHeader->DestAddr.L == BROADCAST_IPv4) {
509 return TRUE;
510 }
511
512 for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; ++Index) {
513 if (IpHeader->DestAddr.L == PxeBcMode->IpFilter.IpList[Index].Addr[0]) {
514 return TRUE;
515 }
516 }
517
518 return FALSE;
519 }
520
521 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
522
523 //
524 // receive up to MessageLength message into MessagePtr for protocol Prot
525 // return message length, src/dest ips if select any, and pointer to protocol
526 // header routine will filter based on source and/or dest ip if OpFlags set.
527 //
528 EFI_STATUS
529 IpReceive (
530 PXE_BASECODE_DEVICE *Private,
531 PXE_OPFLAGS OpFlags,
532 EFI_IP_ADDRESS *SrcIpPtr,
533 EFI_IP_ADDRESS *DestIpPtr,
534 UINT8 Prot,
535 VOID *HeaderPtr,
536 UINTN HdrSize,
537 UINT8 *MessagePtr,
538 UINTN *MessageLengthPtr,
539 EFI_EVENT TimeoutEvent
540 )
541 {
542 EFI_PXE_BASE_CODE_MODE *PxeBcMode;
543 EFI_STATUS StatCode;
544 UINTN ByteCount;
545 UINTN FragmentCount;
546 UINTN ExpectedPacketLength;
547 UINTN Id;
548 BOOLEAN GotFirstFragment;
549 BOOLEAN GotLastFragment;
550
551 DEBUG (
552 (EFI_D_NET,
553 "\nIpReceive() Hdr=%Xh HdrSz=%d Data=%Xh DataSz=%d",
554 HeaderPtr,
555 HdrSize,
556 MessagePtr,
557 *MessageLengthPtr)
558 );
559
560 PxeBcMode = Private->EfiBc.Mode;
561 PxeBcMode->IcmpErrorReceived = FALSE;
562
563 ExpectedPacketLength = 0;
564 GotFirstFragment = FALSE;
565 GotLastFragment = FALSE;
566 FragmentCount = 0;
567 ByteCount = 0;
568 Id = 0;
569
570 for (;;) {
571 IPV4_HEADER IpHdr;
572 UINTN FFlds;
573 UINTN TotalLength;
574 UINTN FragmentOffset;
575 UINTN HeaderSize;
576 UINTN BufferSize;
577 UINTN IpHeaderLength;
578 UINTN DataLength;
579 UINT16 Protocol;
580 UINT8 *NextHdrPtr;
581 UINT8 *PacketPtr;
582
583 StatCode = WaitForReceive (
584 Private,
585 Private->Function,
586 TimeoutEvent,
587 &HeaderSize,
588 &BufferSize,
589 &Protocol
590 );
591
592 if (EFI_ERROR (StatCode)) {
593 return StatCode;
594 }
595
596 PacketPtr = Private->ReceiveBufferPtr + HeaderSize;
597
598 if (Protocol == PXE_PROTOCOL_ETHERNET_ARP) {
599 HandleArpReceive (
600 Private,
601 (ARP_PACKET *) PacketPtr,
602 Private->ReceiveBufferPtr
603 );
604
605 continue;
606 }
607
608 if (Protocol != PXE_PROTOCOL_ETHERNET_IP) {
609 continue;
610 }
611
612 #if SUPPORT_IPV6
613 if (PxeBcMode->UsingIpv6) {
614 //
615 // TBD
616 //
617 }
618 #endif
619
620 #define IpRxHeader ((IPV4_HEADER *) PacketPtr)
621
622 //
623 // filter for version & check sum
624 //
625 IpHeaderLength = IPV4_HEADER_LENGTH (IpRxHeader);
626
627 if ((IpRxHeader->VersionIhl >> 4) != IPVER4) {
628 continue;
629 }
630
631 if (IpChecksum ((UINT16 *) IpRxHeader, IpHeaderLength)) {
632 continue;
633 }
634
635 CopyMem (&IpHdr, IpRxHeader, sizeof (IpHdr));
636 //IpHdr = *IpRxHeader;
637 TotalLength = NTOHS (IpHdr.TotalLength);
638
639 if (IpHdr.Protocol == PROT_TCP) {
640 //
641 // The NextHdrPtr is used to seed the header buffer we are passing back.
642 // That being the case, we want to see everything in pPkt which contains
643 // everything but the ethernet (or whatever) frame. IP + TCP in this case.
644 //
645 DataLength = TotalLength;
646 NextHdrPtr = PacketPtr;
647 } else {
648 DataLength = TotalLength - IpHeaderLength;
649 NextHdrPtr = PacketPtr + IpHeaderLength;
650 }
651 //
652 // If this is an ICMP, it might not be for us.
653 // Double check the state of the IP stack and the
654 // packet fields before assuming it is an ICMP
655 // error. ICMP requests are not supported by the
656 // PxeBc IP stack and should be ignored.
657 //
658 if (IpHdr.Protocol == PROT_ICMP) {
659 ICMPV4_HEADER *Icmpv4;
660
661 Icmpv4 = (ICMPV4_HEADER *) NextHdrPtr;
662
663 //
664 // For now only obvious ICMP error replies will be accepted by
665 // this stack. This still makes us vulnerable to DoS attacks.
666 // But at least we will not be killed by DHCP daemons.
667 //
668 switch (Icmpv4->Type) {
669 case ICMP_REDIRECT:
670 case ICMP_ECHO:
671 case ICMP_ROUTER_ADV:
672 case ICMP_ROUTER_SOLICIT:
673 case ICMP_TIMESTAMP:
674 case ICMP_TIMESTAMP_REPLY:
675 case ICMP_INFO_REQ:
676 case ICMP_INFO_REQ_REPLY:
677 case ICMP_SUBNET_MASK_REQ:
678 case ICMP_SUBNET_MASK_REPLY:
679 default:
680 continue;
681
682 //
683 // %%TBD - This should be implemented.
684 //
685 case ICMP_ECHO_REPLY:
686 continue;
687
688 case ICMP_DEST_UNREACHABLE:
689 case ICMP_TIME_EXCEEDED:
690 case ICMP_PARAMETER_PROBLEM:
691 case ICMP_SOURCE_QUENCH:
692 PxeBcMode->IcmpErrorReceived = TRUE;
693
694 CopyMem (
695 &PxeBcMode->IcmpError,
696 NextHdrPtr,
697 sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
698 );
699
700 DEBUG (
701 (EFI_D_NET,
702 "\nIpReceive() Exit #1 %Xh (%r)",
703 EFI_ICMP_ERROR,
704 EFI_ICMP_ERROR)
705 );
706 }
707
708 return EFI_ICMP_ERROR;
709 }
710
711 if (IpHdr.Protocol == PROT_IGMP) {
712 HandleIgmp (Private, (IGMPV2_MESSAGE *) NextHdrPtr, DataLength);
713
714 DEBUG ((EFI_D_NET, "\n IGMP"));
715 continue;
716 }
717 //
718 // check for protocol
719 //
720 if (IpHdr.Protocol != Prot) {
721 continue;
722 }
723 //
724 // do filtering
725 //
726 if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr && SrcIpPtr->Addr[0] != IpHdr.SrcAddr.L) {
727 DEBUG ((EFI_D_NET, "\n Not expected source IP address."));
728 continue;
729 }
730
731 if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) {
732 if (!IPgood (Private, &IpHdr)) {
733 continue;
734 }
735 } else if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP)) {
736 if (DestIpPtr == NULL) {
737 if (PxeBcMode->StationIp.Addr[0] != IpHdr.DestAddr.L) {
738 continue;
739 }
740 } else if (DestIpPtr->Addr[0] != IpHdr.DestAddr.L) {
741 continue;
742 }
743 }
744 //
745 // get some data we need
746 //
747 FFlds = NTOHS (IpHdr.FragmentFields);
748 FragmentOffset = ((FFlds & IP_FRAG_OFF_MSK) << 3);
749
750 /* Keep count of fragments that belong to this session.
751 * If we get packets with a different IP ID number,
752 * ignore them. Ignored packets should be handled
753 * by the upper level protocol.
754 */
755 if (FragmentCount == 0) {
756 Id = IpHdr.Id;
757
758 if (DestIpPtr != NULL) {
759 DestIpPtr->Addr[0] = IpHdr.DestAddr.L;
760 }
761
762 if (SrcIpPtr != NULL) {
763 SrcIpPtr->Addr[0] = IpHdr.SrcAddr.L;
764 }
765 } else {
766 if (IpHdr.Id != Id) {
767 continue;
768 }
769 }
770
771 ++FragmentCount;
772
773 /* Fragment management.
774 */
775 if (FragmentOffset == 0) {
776 /* This is the first fragment (may also be the
777 * only fragment).
778 */
779 GotFirstFragment = TRUE;
780
781 /* If there is a separate protocol header buffer,
782 * copy the header, adjust the data pointer and
783 * the data length.
784 */
785 if (HdrSize != 0) {
786 CopyMem (HeaderPtr, NextHdrPtr, HdrSize);
787
788 NextHdrPtr += HdrSize;
789 DataLength -= HdrSize;
790 }
791 } else {
792 /* If there is a separate protocol header buffer,
793 * adjust the fragment offset.
794 */
795 FragmentOffset -= HdrSize;
796 }
797
798 /* See if this is the last fragment.
799 */
800 if (!(FFlds & IP_MORE_FRAG)) {
801 //
802 // This is the last fragment (may also be the only fragment).
803 //
804 GotLastFragment = TRUE;
805
806 /* Compute the expected length of the assembled
807 * packet. This will be used to decide if we
808 * have gotten all of the fragments.
809 */
810 ExpectedPacketLength = FragmentOffset + DataLength;
811 }
812
813 DEBUG (
814 (EFI_D_NET,
815 "\n ID = %Xh Off = %d Len = %d",
816 Id,
817 FragmentOffset,
818 DataLength)
819 );
820
821 /* Check for receive buffer overflow.
822 */
823 if (FragmentOffset + DataLength > *MessageLengthPtr) {
824 /* There is not enough space in the receive
825 * buffer for the fragment.
826 */
827 DEBUG (
828 (EFI_D_NET,
829 "\nIpReceive() Exit #3 %Xh (%r)",
830 EFI_BUFFER_TOO_SMALL,
831 EFI_BUFFER_TOO_SMALL)
832 );
833
834 return EFI_BUFFER_TOO_SMALL;
835 }
836
837 /* Copy data into receive buffer.
838 */
839 if (DataLength != 0) {
840 DEBUG ((EFI_D_NET, " To = %Xh", MessagePtr + FragmentOffset));
841
842 CopyMem (MessagePtr + FragmentOffset, NextHdrPtr, DataLength);
843 ByteCount += DataLength;
844 }
845
846 /* If we have seen the first and last fragments and
847 * the receive byte count is at least as large as the
848 * expected byte count, return SUCCESS.
849 *
850 * We could be tricked by receiving a fragment twice
851 * but the upper level protocol should figure this
852 * out.
853 */
854 if (GotFirstFragment && GotLastFragment && ByteCount >= ExpectedPacketLength) {
855 *MessageLengthPtr = ExpectedPacketLength;
856 return EFI_SUCCESS;
857 }
858 }
859 }
860
861 /* eof - pxe_bc_ip.c */