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