TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip6Output.c
Go to the documentation of this file.
1
10#include "Ip6Impl.h"
11
12UINT32 mIp6Id;
13
31 IN IP6_SERVICE *IpSb,
32 OUT LIST_ENTRY *SourceList,
33 OUT UINT32 *SourceCount
34 )
35{
36 IP6_INTERFACE *IpIf;
37 LIST_ENTRY *Entry;
38 LIST_ENTRY *Entry2;
39 IP6_ADDRESS_INFO *AddrInfo;
40 IP6_ADDRESS_INFO *Copy;
41
42 *SourceCount = 0;
43
44 if (IpSb->LinkLocalOk) {
45 Copy = AllocatePool (sizeof (IP6_ADDRESS_INFO));
46 if (Copy == NULL) {
47 return EFI_OUT_OF_RESOURCES;
48 }
49
50 Copy->Signature = IP6_ADDR_INFO_SIGNATURE;
51 IP6_COPY_ADDRESS (&Copy->Address, &IpSb->LinkLocalAddr);
52 Copy->IsAnycast = FALSE;
53 Copy->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
54 Copy->ValidLifetime = (UINT32)IP6_INFINIT_LIFETIME;
55 Copy->PreferredLifetime = (UINT32)IP6_INFINIT_LIFETIME;
56
57 InsertTailList (SourceList, &Copy->Link);
58 (*SourceCount)++;
59 }
60
61 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
62 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
63
64 NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
65 AddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
66
67 if (AddrInfo->IsAnycast) {
68 //
69 // Never use an anycast address.
70 //
71 continue;
72 }
73
74 Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), AddrInfo);
75 if (Copy == NULL) {
76 return EFI_OUT_OF_RESOURCES;
77 }
78
79 InsertTailList (SourceList, &Copy->Link);
80 (*SourceCount)++;
81 }
82 }
83
84 return EFI_SUCCESS;
85}
86
96UINT8
98 IN EFI_IPv6_ADDRESS *AddressA,
99 IN EFI_IPv6_ADDRESS *AddressB
100 )
101{
102 UINT8 Count;
103 UINT8 Index;
104 UINT8 ByteA;
105 UINT8 ByteB;
106 UINT8 NumBits;
107
108 Count = 0;
109 Index = 0;
110
111 while (Index < 16) {
112 ByteA = AddressA->Addr[Index];
113 ByteB = AddressB->Addr[Index];
114
115 if (ByteA == ByteB) {
116 Count += 8;
117 Index++;
118 continue;
119 }
120
121 //
122 // Check how many bits are common between the two bytes.
123 //
124 NumBits = 8;
125 ByteA = (UINT8)(ByteA ^ ByteB);
126
127 while (ByteA != 0) {
128 NumBits--;
129 ByteA = (UINT8)(ByteA >> 1);
130 }
131
132 return (UINT8)(Count + NumBits);
133 }
134
135 return Count;
136}
137
154 IN IP6_SERVICE *IpSb,
155 IN EFI_IPv6_ADDRESS *Destination,
156 OUT EFI_IPv6_ADDRESS *Source
157 )
158{
159 EFI_STATUS Status;
160 LIST_ENTRY SourceList;
161 UINT32 SourceCount;
162 UINT8 ScopeD;
163 LIST_ENTRY *Entry;
164 IP6_ADDRESS_INFO *AddrInfo;
165 IP6_PREFIX_LIST_ENTRY *Prefix;
166 UINT8 LastCommonLength;
167 UINT8 CurrentCommonLength;
168 EFI_IPv6_ADDRESS *TmpAddress;
169
170 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
171
172 Status = EFI_SUCCESS;
173 InitializeListHead (&SourceList);
174
175 if (!IpSb->LinkLocalOk) {
176 return EFI_NO_MAPPING;
177 }
178
179 //
180 // Rule 1: Prefer same address.
181 //
182 if (Ip6IsOneOfSetAddress (IpSb, Destination, NULL, NULL)) {
183 IP6_COPY_ADDRESS (Source, Destination);
184 goto Exit;
185 }
186
187 //
188 // Rule 2: Prefer appropriate scope.
189 //
190 if (IP6_IS_MULTICAST (Destination)) {
191 ScopeD = (UINT8)(Destination->Addr[1] >> 4);
192 } else if (NetIp6IsLinkLocalAddr (Destination)) {
193 ScopeD = 0x2;
194 } else {
195 ScopeD = 0xE;
196 }
197
198 if (ScopeD <= 0x2) {
199 //
200 // Return the link-local address if it exists
201 // One IP6_SERVICE only has one link-local address.
202 //
203 IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
204 goto Exit;
205 }
206
207 //
208 // All candidate source addresses are global unicast address.
209 //
210 Ip6CandidateSource (IpSb, &SourceList, &SourceCount);
211
212 if (SourceCount == 0) {
213 Status = EFI_NO_MAPPING;
214 goto Exit;
215 }
216
217 IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
218
219 if (SourceCount == 1) {
220 goto Exit;
221 }
222
223 //
224 // Rule 3: Avoid deprecated addresses.
225 // TODO: check the "deprecated" state of the stateful configured address
226 //
227 NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
228 Prefix = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
229 if (Prefix->PreferredLifetime == 0) {
230 Ip6RemoveAddr (NULL, &SourceList, &SourceCount, &Prefix->Prefix, Prefix->PrefixLength);
231
232 if (SourceCount == 1) {
233 goto Exit;
234 }
235 }
236 }
237
238 //
239 // TODO: Rule 4: Prefer home addresses.
240 // TODO: Rule 5: Prefer outgoing interface.
241 // TODO: Rule 6: Prefer matching label.
242 // TODO: Rule 7: Prefer public addresses.
243 //
244
245 //
246 // Rule 8: Use longest matching prefix.
247 //
248 LastCommonLength = Ip6CommonPrefixLen (Source, Destination);
249 TmpAddress = NULL;
250
251 for (Entry = SourceList.ForwardLink; Entry != &SourceList; Entry = Entry->ForwardLink) {
252 AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
253
254 CurrentCommonLength = Ip6CommonPrefixLen (&AddrInfo->Address, Destination);
255 if (CurrentCommonLength > LastCommonLength) {
256 LastCommonLength = CurrentCommonLength;
257 TmpAddress = &AddrInfo->Address;
258 }
259 }
260
261 if (TmpAddress != NULL) {
262 IP6_COPY_ADDRESS (Source, TmpAddress);
263 }
264
265Exit:
266
267 Ip6RemoveAddr (NULL, &SourceList, &SourceCount, NULL, 0);
268
269 return Status;
270}
271
287 IN IP6_SERVICE *IpSb,
288 IN EFI_IPv6_ADDRESS *Destination,
289 IN OUT EFI_IPv6_ADDRESS *Source
290 )
291{
292 EFI_STATUS Status;
293 EFI_IPv6_ADDRESS SelectedSource;
294 IP6_INTERFACE *IpIf;
295 BOOLEAN Exist;
296
297 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
298 ASSERT (Destination != NULL && Source != NULL);
299
300 if (NetIp6IsUnspecifiedAddr (Destination)) {
301 return NULL;
302 }
303
304 if (!NetIp6IsUnspecifiedAddr (Source)) {
305 Exist = Ip6IsOneOfSetAddress (IpSb, Source, &IpIf, NULL);
306 ASSERT (Exist);
307
308 return IpIf;
309 }
310
311 //
312 // If source is unspecified, select a source according to the destination.
313 //
314 Status = Ip6SelectSourceAddress (IpSb, Destination, &SelectedSource);
315 if (EFI_ERROR (Status)) {
316 return IpSb->DefaultInterface;
317 }
318
319 Ip6IsOneOfSetAddress (IpSb, &SelectedSource, &IpIf, NULL);
320 IP6_COPY_ADDRESS (Source, &SelectedSource);
321
322 return IpIf;
323}
324
336VOID
338 NET_BUF *Packet,
339 EFI_STATUS IoStatus,
340 UINT32 LinkFlag,
341 VOID *Context
342 )
343{
344 NetbufFree (Packet);
345 Packet = NULL;
346}
347
368 IN IP6_SERVICE *IpSb,
369 IN NET_BUF *Packet,
370 IN EFI_IP6_HEADER *Head,
371 IN UINT16 FragmentOffset,
372 IN UINT8 *ExtHdrs,
373 IN UINT32 ExtHdrsLen,
374 IN UINT8 LastHeader,
375 IN UINT32 HeadLen
376 )
377{
378 UINT32 Len;
379 UINT32 UnFragExtHdrsLen;
380 EFI_IP6_HEADER *PacketHead;
381 UINT8 *UpdatedExtHdrs;
382 EFI_STATUS Status;
383 UINT8 NextHeader;
384
385 UpdatedExtHdrs = NULL;
386
387 //
388 // HeadLen is the length of the fixed part of the sequences of fragments, i.e.
389 // the unfragment part.
390 //
391 PacketHead = (EFI_IP6_HEADER *)NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
392 if (PacketHead == NULL) {
393 return EFI_BAD_BUFFER_SIZE;
394 }
395
396 //
397 // Set the head up, convert the host byte order to network byte order
398 //
399 CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
400 PacketHead->PayloadLength = HTONS ((UINT16)(Packet->TotalSize - sizeof (EFI_IP6_HEADER)));
401 Packet->Ip.Ip6 = PacketHead;
402
403 Len = HeadLen - sizeof (EFI_IP6_HEADER);
404 UnFragExtHdrsLen = Len - sizeof (IP6_FRAGMENT_HEADER);
405
406 if (UnFragExtHdrsLen == 0) {
407 PacketHead->NextHeader = IP6_FRAGMENT;
408 }
409
410 //
411 // Append the extension headers: firstly copy the unfragmentable headers, then append
412 // fragmentation header.
413 //
414 if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) {
415 NextHeader = Head->NextHeader;
416 } else {
417 NextHeader = PacketHead->NextHeader;
418 }
419
420 Status = Ip6FillFragmentHeader (
421 IpSb,
422 NextHeader,
423 LastHeader,
424 ExtHdrs,
425 ExtHdrsLen,
426 FragmentOffset,
427 &UpdatedExtHdrs
428 );
429 if (EFI_ERROR (Status)) {
430 return Status;
431 }
432
433 CopyMem (
434 (UINT8 *)(PacketHead + 1),
435 UpdatedExtHdrs,
436 UnFragExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER)
437 );
438
439 FreePool (UpdatedExtHdrs);
440 return EFI_SUCCESS;
441}
442
477 IN IP6_SERVICE *IpSb,
478 IN IP6_INTERFACE *Interface OPTIONAL,
479 IN IP6_PROTOCOL *IpInstance OPTIONAL,
480 IN NET_BUF *Packet,
481 IN EFI_IP6_HEADER *Head,
482 IN UINT8 *ExtHdrs,
483 IN UINT32 ExtHdrsLen,
484 IN IP6_FRAME_CALLBACK Callback,
485 IN VOID *Context
486 )
487{
488 IP6_INTERFACE *IpIf;
489 EFI_IPv6_ADDRESS NextHop;
490 IP6_NEIGHBOR_ENTRY *NeighborCache;
491 IP6_ROUTE_CACHE_ENTRY *RouteCache;
492 EFI_STATUS Status;
493 UINT32 Mtu;
494 UINT32 HeadLen;
495 UINT16 FragmentOffset;
496 UINT8 *LastHeader;
497 UINT32 UnFragmentLen;
498 UINT32 UnFragmentHdrsLen;
499 UINT32 FragmentHdrsLen;
500 UINT16 *Checksum;
501 UINT16 PacketChecksum;
502 UINT16 PseudoChecksum;
503 UINT32 Index;
504 UINT32 PacketLen;
505 UINT32 RealExtLen;
506 UINT32 Offset;
507 NET_BUF *TmpPacket;
508 NET_BUF *Fragment;
509 UINT32 Num;
510 UINT8 *Buf;
511 EFI_IP6_HEADER *PacketHead;
512 IP6_ICMP_HEAD *IcmpHead;
513 IP6_TXTOKEN_WRAP *Wrap;
514 IP6_ROUTE_ENTRY *RouteEntry;
515 UINT8 *UpdatedExtHdrs;
516 UINT8 NextHeader;
517 UINT8 LastHeaderBackup;
518 BOOLEAN FragmentHeadInserted;
519 UINT8 *ExtHdrsBackup;
520 UINT8 NextHeaderBackup;
521 EFI_IPv6_ADDRESS Source;
522 EFI_IPv6_ADDRESS Destination;
523
524 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
525
526 //
527 // RFC2460: Each extension header is an integer multiple of 8 octets long,
528 // in order to retain 8-octet alignment for subsequent headers.
529 //
530 if ((ExtHdrsLen & 0x7) != 0) {
531 return EFI_INVALID_PARAMETER;
532 }
533
534 LastHeader = NULL;
535
537 NULL,
538 NULL,
539 &Head->NextHeader,
540 ExtHdrs,
541 ExtHdrsLen,
542 FALSE,
543 NULL,
544 &LastHeader,
545 NULL,
546 NULL,
547 NULL
548 );
549
550 //
551 // Select an interface/source for system packet, application
552 // should select them itself.
553 //
554 IpIf = Interface;
555 if (IpIf == NULL) {
556 //
557 // IpInstance->Interface is NULL when IpInstance is configured with both stationaddress
558 // and destinationaddress is unspecified.
559 //
560 if ((IpInstance == NULL) || (IpInstance->Interface == NULL)) {
561 IpIf = Ip6SelectInterface (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
562 if (IpInstance != NULL) {
563 IpInstance->Interface = IpIf;
564 }
565 } else {
566 IpIf = IpInstance->Interface;
567 }
568 }
569
570 if (IpIf == NULL) {
571 return EFI_NO_MAPPING;
572 }
573
574 //
575 // Update the common field in Head here.
576 //
577 Head->Version = 6;
578 Head->TrafficClassL = 0;
579 Head->TrafficClassH = 0;
580
581 Checksum = NULL;
582 NextHeader = *LastHeader;
583
584 switch (NextHeader) {
585 case EFI_IP_PROTO_UDP:
586 Packet->Udp = (EFI_UDP_HEADER *)NetbufGetByte (Packet, 0, NULL);
587 ASSERT (Packet->Udp != NULL);
588 if (Packet->Udp->Checksum == 0) {
589 Checksum = &Packet->Udp->Checksum;
590 }
591
592 break;
593
594 case EFI_IP_PROTO_TCP:
595 Packet->Tcp = (TCP_HEAD *)NetbufGetByte (Packet, 0, NULL);
596 ASSERT (Packet->Tcp != NULL);
597 if (Packet->Tcp->Checksum == 0) {
598 Checksum = &Packet->Tcp->Checksum;
599 }
600
601 break;
602
603 case IP6_ICMP:
604 //
605 // Don't send ICMP packet to an IPv6 anycast address.
606 //
607 if (Ip6IsAnycast (IpSb, &Head->DestinationAddress)) {
608 return EFI_INVALID_PARAMETER;
609 }
610
611 IcmpHead = (IP6_ICMP_HEAD *)NetbufGetByte (Packet, 0, NULL);
612 ASSERT (IcmpHead != NULL);
613 if (IcmpHead->Checksum == 0) {
614 Checksum = &IcmpHead->Checksum;
615 }
616
617 break;
618
619 default:
620 break;
621 }
622
623 if (Checksum != NULL) {
624 //
625 // Calculate the checksum for upper layer protocol if it is not calculated due to lack of
626 // IPv6 source address.
627 //
628 PacketChecksum = NetbufChecksum (Packet);
629 PseudoChecksum = NetIp6PseudoHeadChecksum (
630 &Head->SourceAddress,
631 &Head->DestinationAddress,
632 NextHeader,
633 Packet->TotalSize
634 );
635 *Checksum = (UINT16) ~NetAddChecksum (PacketChecksum, PseudoChecksum);
636 }
637
638 Status = Ip6IpSecProcessPacket (
639 IpSb,
640 &Head,
641 LastHeader, // no need get the lasthead value for output
642 &Packet,
643 &ExtHdrs,
644 &ExtHdrsLen,
646 Context
647 );
648
649 if (EFI_ERROR (Status)) {
650 return Status;
651 }
652
653 LastHeader = NULL;
654 //
655 // Check incoming parameters.
656 //
657 if (!Ip6IsExtsValid (
658 IpSb,
659 Packet,
660 &Head->NextHeader,
661 ExtHdrs,
662 ExtHdrsLen,
663 FALSE,
664 NULL,
665 &LastHeader,
666 &RealExtLen,
667 &UnFragmentHdrsLen,
668 NULL
669 ))
670 {
671 return EFI_INVALID_PARAMETER;
672 }
673
674 if ((RealExtLen & 0x7) != 0) {
675 return EFI_INVALID_PARAMETER;
676 }
677
678 LastHeaderBackup = *LastHeader;
679
680 //
681 // Perform next hop determination:
682 // For multicast packets, the next-hop is always the destination address and
683 // is considered to be on-link.
684 //
685 if (IP6_IS_MULTICAST (&Head->DestinationAddress)) {
686 IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
687 } else {
688 //
689 // For unicast packets, use a combination of the Destination Cache, the Prefix List
690 // and the Default Router List to determine the IP address of the appropriate next hop.
691 //
692
693 NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->DestinationAddress);
694 if (NeighborCache != NULL) {
695 //
696 // Hit Neighbor Cache.
697 //
698 IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
699 } else {
700 //
701 // Not in Neighbor Cache, check Router cache
702 //
703 RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
704 if (RouteCache == NULL) {
705 return EFI_NOT_FOUND;
706 }
707
708 IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop);
709 Ip6FreeRouteCacheEntry (RouteCache);
710 }
711 }
712
713 //
714 // Examines the Neighbor Cache for link-layer information about that neighbor.
715 // DO NOT create neighbor cache if neighbor is itself - when reporting ICMP error.
716 //
717 if (!IP6_IS_MULTICAST (&NextHop) && !EFI_IP6_EQUAL (&Head->DestinationAddress, &Head->SourceAddress)) {
718 NeighborCache = Ip6FindNeighborEntry (IpSb, &NextHop);
719 if (NeighborCache == NULL) {
720 NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &NextHop, NULL);
721
722 if (NeighborCache == NULL) {
723 return EFI_OUT_OF_RESOURCES;
724 }
725
726 //
727 // Send out multicast neighbor solicitation for address resolution immediately.
728 //
729 Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
730 Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734
735 Status = Ip6SendNeighborSolicit (
736 IpSb,
737 &Source,
738 &Destination,
739 &NeighborCache->Neighbor,
740 &IpSb->SnpMode.CurrentAddress
741 );
742 if (EFI_ERROR (Status)) {
743 return Status;
744 }
745
746 --NeighborCache->Transmit;
747 NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer) + 1;
748 }
749
750 NeighborCache->Interface = IpIf;
751 }
752
753 UpdatedExtHdrs = NULL;
754 ExtHdrsBackup = NULL;
755 NextHeaderBackup = 0;
756 FragmentHeadInserted = FALSE;
757
758 //
759 // Check whether we received Packet Too Big message for the packet sent to the
760 // Destination. If yes include a Fragment Header in the subsequent packets.
761 //
762 RouteEntry = Ip6FindRouteEntry (
763 IpSb->RouteTable,
764 &Head->DestinationAddress,
765 NULL
766 );
767 if (RouteEntry != NULL) {
768 if ((RouteEntry->Flag & IP6_PACKET_TOO_BIG) == IP6_PACKET_TOO_BIG) {
769 //
770 // FragmentHead is inserted after Hop-by-Hop Options header, Destination
771 // Options header (first occur), Routing header, and before Fragment header,
772 // Authentication header, Encapsulating Security Payload header, and
773 // Destination Options header (last occur), and upper-layer header.
774 //
775 Status = Ip6FillFragmentHeader (
776 IpSb,
777 Head->NextHeader,
778 LastHeaderBackup,
779 ExtHdrs,
780 ExtHdrsLen,
781 0,
782 &UpdatedExtHdrs
783 );
784 if (EFI_ERROR (Status)) {
785 return Status;
786 }
787
788 if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
789 NextHeaderBackup = Head->NextHeader;
790 Head->NextHeader = IP6_FRAGMENT;
791 }
792
793 ExtHdrsBackup = ExtHdrs;
794 ExtHdrs = UpdatedExtHdrs;
795 ExtHdrsLen = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
796 RealExtLen = RealExtLen + sizeof (IP6_FRAGMENT_HEADER);
797
798 mIp6Id++;
799
800 FragmentHeadInserted = TRUE;
801 }
802
803 Ip6FreeRouteEntry (RouteEntry);
804 }
805
806 //
807 // OK, selected the source and route, fragment the packet then send
808 // them. Tag each fragment other than the first one as spawn from it.
809 // Each extension header is an integer multiple of 8 octets long, in
810 // order to retain 8-octet alignment for subsequent headers.
811 //
812 Mtu = IpSb->MaxPacketSize + sizeof (EFI_IP6_HEADER);
813 HeadLen = sizeof (EFI_IP6_HEADER) + RealExtLen;
814
815 if (Packet->TotalSize + HeadLen > Mtu) {
816 //
817 // Remove the inserted Fragment Header since we need fragment the packet.
818 //
819 if (FragmentHeadInserted) {
820 ExtHdrs = ExtHdrsBackup;
821 ExtHdrsLen = ExtHdrsLen - sizeof (IP6_FRAGMENT_HEADER);
822
823 if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
824 Head->NextHeader = NextHeaderBackup;
825 }
826 }
827
828 FragmentHdrsLen = ExtHdrsLen - UnFragmentHdrsLen;
829
830 //
831 // The packet is beyond the maximum which can be described through the
832 // fragment offset field in Fragment header.
833 //
834 if ((((Packet->TotalSize + FragmentHdrsLen) >> 3) & (~0x1fff)) != 0) {
835 Status = EFI_BAD_BUFFER_SIZE;
836 goto Error;
837 }
838
839 if (FragmentHdrsLen != 0) {
840 //
841 // Append the fragmentable extension hdrs before the upper layer payload
842 // to form a new NET_BUF. This NET_BUF contains all the buffer which will
843 // be fragmented below.
844 //
845 TmpPacket = NetbufGetFragment (Packet, 0, Packet->TotalSize, FragmentHdrsLen);
846 ASSERT (TmpPacket != NULL);
847
848 //
849 // Allocate the space to contain the fragmentable hdrs and copy the data.
850 //
851 Buf = NetbufAllocSpace (TmpPacket, FragmentHdrsLen, TRUE);
852 ASSERT (Buf != NULL);
853 CopyMem (Buf, ExtHdrs + UnFragmentHdrsLen, FragmentHdrsLen);
854
855 //
856 // Free the old Packet.
857 //
858 NetbufFree (Packet);
859 Packet = TmpPacket;
860 }
861
862 //
863 // The unfragment part which appears in every fragmented IPv6 packet includes
864 // the IPv6 header, the unfragmentable extension hdrs and the fragment header.
865 //
866 UnFragmentLen = sizeof (EFI_IP6_HEADER) + UnFragmentHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
867
868 //
869 // Mtu now is the length of the fragment part in a full-length fragment.
870 //
871 Mtu = (Mtu - UnFragmentLen) & (~0x07);
872 Num = (Packet->TotalSize + Mtu - 1) / Mtu;
873
874 for (Index = 0, Offset = 0, PacketLen = Mtu; Index < Num; Index++) {
875 //
876 // Get fragment from the Packet, append UnFragmentLen spare buffer
877 // before the fragmented data, the corresponding data is filled in later.
878 //
879 Fragment = NetbufGetFragment (Packet, Offset, PacketLen, UnFragmentLen);
880 if (Fragment == NULL) {
881 Status = EFI_OUT_OF_RESOURCES;
882 goto Error;
883 }
884
885 FragmentOffset = (UINT16)((UINT16)Offset | 0x1);
886 if (Index == Num - 1) {
887 //
888 // The last fragment, clear the M flag.
889 //
890 FragmentOffset &= (~0x1);
891 }
892
893 Status = Ip6PrependHead (
894 IpSb,
895 Fragment,
896 Head,
897 FragmentOffset,
898 ExtHdrs,
899 ExtHdrsLen,
900 LastHeaderBackup,
901 UnFragmentLen
902 );
903 ASSERT (Status == EFI_SUCCESS);
904
905 Status = Ip6SendFrame (
906 IpIf,
907 IpInstance,
908 Fragment,
909 &NextHop,
911 Packet
912 );
913 if (EFI_ERROR (Status)) {
914 goto Error;
915 }
916
917 //
918 // The last fragment of upper layer packet, update the IP6 token status.
919 //
920 if ((Index == Num -1) && (Context != NULL)) {
921 Wrap = (IP6_TXTOKEN_WRAP *)Context;
922 Wrap->Token->Status = Status;
923 }
924
925 Offset += PacketLen;
926 PacketLen = Packet->TotalSize - Offset;
927 if (PacketLen > Mtu) {
928 PacketLen = Mtu;
929 }
930 }
931
932 NetbufFree (Packet);
933 mIp6Id++;
934
935 if (UpdatedExtHdrs != NULL) {
936 FreePool (UpdatedExtHdrs);
937 }
938
939 return EFI_SUCCESS;
940 }
941
942 //
943 // Need not fragment the packet, send it in one frame.
944 //
945 PacketHead = (EFI_IP6_HEADER *)NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
946 if (PacketHead == NULL) {
947 Status = EFI_BAD_BUFFER_SIZE;
948 goto Error;
949 }
950
951 CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
952 Packet->Ip.Ip6 = PacketHead;
953
954 if (ExtHdrs != NULL) {
955 Buf = (UINT8 *)(PacketHead + 1);
956 CopyMem (Buf, ExtHdrs, ExtHdrsLen);
957 }
958
959 if (UpdatedExtHdrs != NULL) {
960 //
961 // A Fragment Header is inserted to the packet, update the payload length.
962 //
963 PacketHead->PayloadLength = (UINT16)(NTOHS (PacketHead->PayloadLength) +
964 sizeof (IP6_FRAGMENT_HEADER));
965 PacketHead->PayloadLength = HTONS (PacketHead->PayloadLength);
966 FreePool (UpdatedExtHdrs);
967 }
968
969 return Ip6SendFrame (
970 IpIf,
971 IpInstance,
972 Packet,
973 &NextHop,
974 Callback,
975 Context
976 );
977
978Error:
979 if (UpdatedExtHdrs != NULL) {
980 FreePool (UpdatedExtHdrs);
981 }
982
983 Ip6CancelPacket (IpIf, Packet, Status);
984 return Status;
985}
986
998BOOLEAN
1000 IN IP6_LINK_TX_TOKEN *Frame,
1001 IN VOID *Context
1002 )
1003{
1004 if ((Frame->Packet == (NET_BUF *)Context) || (Frame->Context == Context)) {
1005 return TRUE;
1006 }
1007
1008 return FALSE;
1009}
1010
1023VOID
1025 IN IP6_INTERFACE *Interface,
1026 IN EFI_STATUS IoStatus,
1027 IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
1028 IN VOID *Context OPTIONAL
1029 )
1030{
1031 LIST_ENTRY *Entry;
1032 LIST_ENTRY *Next;
1033 IP6_LINK_TX_TOKEN *Token;
1034 IP6_SERVICE *IpSb;
1035 IP6_NEIGHBOR_ENTRY *ArpQue;
1036 EFI_STATUS Status;
1037
1038 IpSb = Interface->Service;
1039 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
1040
1041 //
1042 // Cancel all the pending frames on ARP requests
1043 //
1044 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
1045 ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
1046
1047 Status = Ip6FreeNeighborEntry (
1048 IpSb,
1049 ArpQue,
1050 FALSE,
1051 FALSE,
1052 IoStatus,
1053 FrameToCancel,
1054 Context
1055 );
1056 ASSERT_EFI_ERROR (Status);
1057 }
1058
1059 //
1060 // Cancel all the frames that have been delivered to MNP
1061 // but not yet recycled.
1062 //
1063 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
1064 Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
1065
1066 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
1067 IpSb->Mnp->Cancel (IpSb->Mnp, &Token->MnpToken);
1068 }
1069 }
1070}
1071
1080VOID
1082 IN IP6_INTERFACE *IpIf,
1083 IN NET_BUF *Packet,
1084 IN EFI_STATUS IoStatus
1085 )
1086{
1087 Ip6CancelFrames (IpIf, IoStatus, Ip6CancelPacketFragments, Packet);
1088}
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
struct _EFI_IP6_HEADER EFI_IP6_HEADER
VOID Ip6CreateSNMulticastAddr(IN EFI_IPv6_ADDRESS *Ip6Addr, OUT EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Common.c:291
EFI_STATUS Ip6RemoveAddr(IN IP6_SERVICE *IpSb OPTIONAL, IN OUT LIST_ENTRY *AddressList, IN OUT UINT32 *AddressCount, IN EFI_IPv6_ADDRESS *Prefix OPTIONAL, IN UINT8 PrefixLength)
Definition: Ip6Common.c:411
BOOLEAN Ip6IsOneOfSetAddress(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Address, OUT IP6_INTERFACE **Interface OPTIONAL, OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL)
Definition: Ip6Common.c:504
BOOLEAN Ip6IsAnycast(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *DestinationAddress)
Definition: Ip6Icmp.c:506
EFI_STATUS Ip6SendFrame(IN IP6_INTERFACE *Interface, IN IP6_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN EFI_IPv6_ADDRESS *NextHop, IN IP6_FRAME_CALLBACK CallBack, IN VOID *Context)
Definition: Ip6If.c:654
EFI_STATUS Ip6IpSecProcessPacket(IN IP6_SERVICE *IpSb, IN OUT EFI_IP6_HEADER **Head, IN OUT UINT8 *LastHead, IN OUT NET_BUF **Netbuf, IN OUT UINT8 **ExtHdrs, IN OUT UINT32 *ExtHdrsLen, IN EFI_IPSEC_TRAFFIC_DIR Direction, IN VOID *Context)
Definition: Ip6Input.c:497
EFI_STATUS Ip6SendNeighborSolicit(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *SourceAddress, IN EFI_IPv6_ADDRESS *DestinationAddress, IN EFI_IPv6_ADDRESS *TargetIp6Address, IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL)
Definition: Ip6Nd.c:1340
VOID Ip6OnArpResolved(IN VOID *Context)
Definition: Ip6Nd.c:416
IP6_NEIGHBOR_ENTRY * Ip6CreateNeighborEntry(IN IP6_SERVICE *IpSb, IN IP6_ARP_CALLBACK CallBack, IN EFI_IPv6_ADDRESS *Ip6Address, IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL)
Definition: Ip6Nd.c:505
EFI_STATUS Ip6FreeNeighborEntry(IN IP6_SERVICE *IpSb, IN IP6_NEIGHBOR_ENTRY *NeighborCache, IN BOOLEAN SendIcmpError, IN BOOLEAN FullFree, IN EFI_STATUS IoStatus, IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, IN VOID *Context OPTIONAL)
Definition: Ip6Nd.c:613
IP6_NEIGHBOR_ENTRY * Ip6FindNeighborEntry(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Ip6Address)
Definition: Ip6Nd.c:566
BOOLEAN Ip6IsExtsValid(IN IP6_SERVICE *IpSb OPTIONAL, IN NET_BUF *Packet OPTIONAL, IN UINT8 *NextHeader, IN UINT8 *ExtHdrs, IN UINT32 ExtHdrsLen, IN BOOLEAN Rcvd, OUT UINT32 *FormerHeader OPTIONAL, OUT UINT8 **LastHeader, OUT UINT32 *RealExtsLen OPTIONAL, OUT UINT32 *UnFragmentLen OPTIONAL, OUT BOOLEAN *Fragmented OPTIONAL)
Definition: Ip6Option.c:318
EFI_STATUS Ip6FillFragmentHeader(IN IP6_SERVICE *IpSb, IN UINT8 NextHeader, IN UINT8 LastHeader, IN UINT8 *ExtHdrs, IN UINT32 ExtHdrsLen, IN UINT16 FragmentOffset, OUT UINT8 **UpdatedExtHdrs)
Definition: Ip6Option.c:711
UINT8 Ip6CommonPrefixLen(IN EFI_IPv6_ADDRESS *AddressA, IN EFI_IPv6_ADDRESS *AddressB)
Definition: Ip6Output.c:97
VOID Ip6CancelFrames(IN IP6_INTERFACE *Interface, IN EFI_STATUS IoStatus, IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, IN VOID *Context OPTIONAL)
Definition: Ip6Output.c:1024
EFI_STATUS Ip6PrependHead(IN IP6_SERVICE *IpSb, IN NET_BUF *Packet, IN EFI_IP6_HEADER *Head, IN UINT16 FragmentOffset, IN UINT8 *ExtHdrs, IN UINT32 ExtHdrsLen, IN UINT8 LastHeader, IN UINT32 HeadLen)
Definition: Ip6Output.c:367
IP6_INTERFACE * Ip6SelectInterface(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Destination, IN OUT EFI_IPv6_ADDRESS *Source)
Definition: Ip6Output.c:286
EFI_STATUS Ip6CandidateSource(IN IP6_SERVICE *IpSb, OUT LIST_ENTRY *SourceList, OUT UINT32 *SourceCount)
Definition: Ip6Output.c:30
EFI_STATUS Ip6Output(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface OPTIONAL, IN IP6_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN EFI_IP6_HEADER *Head, IN UINT8 *ExtHdrs, IN UINT32 ExtHdrsLen, IN IP6_FRAME_CALLBACK Callback, IN VOID *Context)
Definition: Ip6Output.c:476
VOID Ip6CancelPacket(IN IP6_INTERFACE *IpIf, IN NET_BUF *Packet, IN EFI_STATUS IoStatus)
Definition: Ip6Output.c:1081
BOOLEAN Ip6CancelPacketFragments(IN IP6_LINK_TX_TOKEN *Frame, IN VOID *Context)
Definition: Ip6Output.c:999
EFI_STATUS Ip6SelectSourceAddress(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Destination, OUT EFI_IPv6_ADDRESS *Source)
Definition: Ip6Output.c:153
VOID Ip6SysPacketSent(NET_BUF *Packet, EFI_STATUS IoStatus, UINT32 LinkFlag, VOID *Context)
Definition: Ip6Output.c:337
VOID Ip6FreeRouteCacheEntry(IN OUT IP6_ROUTE_CACHE_ENTRY *RtCacheEntry)
Definition: Ip6Route.c:199
IP6_ROUTE_ENTRY * Ip6FindRouteEntry(IN IP6_ROUTE_TABLE *RtTable, IN EFI_IPv6_ADDRESS *Destination OPTIONAL, IN EFI_IPv6_ADDRESS *NextHop OPTIONAL)
Definition: Ip6Route.c:118
IP6_ROUTE_CACHE_ENTRY * Ip6Route(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Dest, IN EFI_IPv6_ADDRESS *Src)
Definition: Ip6Route.c:557
VOID Ip6FreeRouteEntry(IN OUT IP6_ROUTE_ENTRY *RtEntry)
Definition: Ip6Route.c:87
@ EfiIPsecOutBound
Definition: IpSecConfig.h:141
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
UINT16 EFIAPI NetIp6PseudoHeadChecksum(IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *Dst, IN UINT8 NextHeader, IN UINT32 Len)
Definition: NetBuffer.c:1777
UINT16 EFIAPI NetbufChecksum(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:1687
BOOLEAN EFIAPI NetIp6IsLinkLocalAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:796
UINT16 EFIAPI NetAddChecksum(IN UINT16 Checksum1, IN UINT16 Checksum2)
Definition: NetBuffer.c:1658
NET_BUF *EFIAPI NetbufGetFragment(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT32 HeadSpace)
Definition: NetBuffer.c:510
BOOLEAN EFIAPI NetIp6IsUnspecifiedAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:766
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS Status
Definition: Ip6.h:536