TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip6Input.c
Go to the documentation of this file.
1
11#include "Ip6Impl.h"
12
29 IN UINT32 Id
30 )
31{
32 IP6_ASSEMBLE_ENTRY *Assemble;
33
34 Assemble = AllocatePool (sizeof (IP6_ASSEMBLE_ENTRY));
35 if (Assemble == NULL) {
36 return NULL;
37 }
38
39 IP6_COPY_ADDRESS (&Assemble->Dst, Dst);
40 IP6_COPY_ADDRESS (&Assemble->Src, Src);
41 InitializeListHead (&Assemble->Fragments);
42
43 Assemble->Id = Id;
44 Assemble->Life = IP6_FRAGMENT_LIFE + 1;
45
46 Assemble->TotalLen = 0;
47 Assemble->CurLen = 0;
48 Assemble->Head = NULL;
49 Assemble->Info = NULL;
50 Assemble->Packet = NULL;
51
52 return Assemble;
53}
54
61VOID
63 IN IP6_ASSEMBLE_ENTRY *Assemble
64 )
65{
66 LIST_ENTRY *Entry;
67 LIST_ENTRY *Next;
68 NET_BUF *Fragment;
69
70 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Assemble->Fragments) {
71 Fragment = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
72
73 RemoveEntryList (Entry);
74 NetbufFree (Fragment);
75 }
76
77 if (Assemble->Packet != NULL) {
78 NetbufFree (Assemble->Packet);
79 }
80
81 FreePool (Assemble);
82}
83
92VOID
93EFIAPI
95 IN VOID *Arg
96 )
97{
99}
100
110VOID
112 IN OUT NET_BUF *Packet,
113 IN INTN Start,
114 IN INTN End
115 )
116{
117 IP6_CLIP_INFO *Info;
118 INTN Len;
119
120 Info = IP6_GET_CLIP_INFO (Packet);
121
122 ASSERT (Info->Start + Info->Length == Info->End);
123 ASSERT ((Info->Start < End) && (Start < Info->End));
124
125 if (Info->Start < Start) {
126 Len = Start - Info->Start;
127
128 NetbufTrim (Packet, (UINT32)Len, NET_BUF_HEAD);
129 Info->Start = (UINT32)Start;
130 Info->Length -= (UINT32)Len;
131 }
132
133 if (End < Info->End) {
134 Len = End - Info->End;
135
136 NetbufTrim (Packet, (UINT32)Len, NET_BUF_TAIL);
137 Info->End = (UINT32)End;
138 Info->Length -= (UINT32)Len;
139 }
140}
141
157NET_BUF *
160 IN NET_BUF *Packet
161 )
162{
163 EFI_IP6_HEADER *Head;
164 IP6_CLIP_INFO *This;
165 IP6_CLIP_INFO *Node;
166 IP6_ASSEMBLE_ENTRY *Assemble;
167 IP6_ASSEMBLE_ENTRY *Entry;
168 LIST_ENTRY *ListHead;
169 LIST_ENTRY *Prev;
170 LIST_ENTRY *Cur;
171 NET_BUF *Fragment;
172 NET_BUF *TmpPacket;
173 NET_BUF *NewPacket;
174 NET_BUF *Duplicate;
175 UINT8 *DupHead;
176 INTN Index;
177 UINT16 UnFragmentLen;
178 UINT8 *NextHeader;
179
180 Head = Packet->Ip.Ip6;
181 This = IP6_GET_CLIP_INFO (Packet);
182
183 ASSERT (Head != NULL);
184
185 //
186 // Find the corresponding assemble entry by (Dst, Src, Id)
187 //
188 Assemble = NULL;
189 Index = IP6_ASSEMBLE_HASH (&Head->DestinationAddress, &Head->SourceAddress, This->Id);
190
191 NET_LIST_FOR_EACH (Cur, &Table->Bucket[Index]) {
192 Entry = NET_LIST_USER_STRUCT (Cur, IP6_ASSEMBLE_ENTRY, Link);
193
194 if ((Entry->Id == This->Id) &&
195 EFI_IP6_EQUAL (&Entry->Src, &Head->SourceAddress) &&
196 EFI_IP6_EQUAL (&Entry->Dst, &Head->DestinationAddress)
197 )
198 {
199 Assemble = Entry;
200 break;
201 }
202 }
203
204 //
205 // Create a new entry if can not find an existing one, insert it to assemble table
206 //
207 if (Assemble == NULL) {
208 Assemble = Ip6CreateAssembleEntry (
209 &Head->DestinationAddress,
210 &Head->SourceAddress,
211 This->Id
212 );
213
214 if (Assemble == NULL) {
215 goto Error;
216 }
217
218 InsertHeadList (&Table->Bucket[Index], &Assemble->Link);
219 }
220
221 //
222 // Find the point to insert the packet: before the first
223 // fragment with THIS.Start < CUR.Start. the previous one
224 // has PREV.Start <= THIS.Start < CUR.Start.
225 //
226 ListHead = &Assemble->Fragments;
227
228 NET_LIST_FOR_EACH (Cur, ListHead) {
229 Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
230
231 if (This->Start < IP6_GET_CLIP_INFO (Fragment)->Start) {
232 break;
233 }
234 }
235
236 //
237 // Check whether the current fragment overlaps with the previous one.
238 // It holds that: PREV.Start <= THIS.Start < THIS.End. Only need to
239 // check whether THIS.Start < PREV.End for overlap. If two fragments
240 // overlaps, trim the overlapped part off THIS fragment.
241 //
242 if ((Prev = Cur->BackLink) != ListHead) {
243 Fragment = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
244 Node = IP6_GET_CLIP_INFO (Fragment);
245
246 if (This->Start < Node->End) {
247 if (This->End <= Node->End) {
248 goto Error;
249 }
250
251 //
252 // Trim the previous fragment from tail.
253 //
254 Ip6TrimPacket (Fragment, Node->Start, This->Start);
255 }
256 }
257
258 //
259 // Insert the fragment into the packet. The fragment may be removed
260 // from the list by the following checks.
261 //
262 NetListInsertBefore (Cur, &Packet->List);
263
264 //
265 // Check the packets after the insert point. It holds that:
266 // THIS.Start <= NODE.Start < NODE.End. The equality holds
267 // if PREV and NEXT are continuous. THIS fragment may fill
268 // several holes. Remove the completely overlapped fragments
269 //
270 while (Cur != ListHead) {
271 Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
272 Node = IP6_GET_CLIP_INFO (Fragment);
273
274 //
275 // Remove fragments completely overlapped by this fragment
276 //
277 if (Node->End <= This->End) {
278 Cur = Cur->ForwardLink;
279
280 RemoveEntryList (&Fragment->List);
281 Assemble->CurLen -= Node->Length;
282
283 NetbufFree (Fragment);
284 continue;
285 }
286
287 //
288 // The conditions are: THIS.Start <= NODE.Start, and THIS.End <
289 // NODE.End. Two fragments overlaps if NODE.Start < THIS.End.
290 // If two fragments start at the same offset, remove THIS fragment
291 // because ((THIS.Start == NODE.Start) && (THIS.End < NODE.End)).
292 //
293 if (Node->Start < This->End) {
294 if (This->Start == Node->Start) {
295 RemoveEntryList (&Packet->List);
296 goto Error;
297 }
298
299 Ip6TrimPacket (Packet, This->Start, Node->Start);
300 }
301
302 break;
303 }
304
305 //
306 // Update the assemble info: increase the current length. If it is
307 // the frist fragment, update the packet's IP head and per packet
308 // info. If it is the last fragment, update the total length.
309 //
310 Assemble->CurLen += This->Length;
311
312 if (This->Start == 0) {
313 //
314 // Once the first fragment is enqueued, it can't be removed
315 // from the fragment list. So, Assemble->Head always point
316 // to valid memory area.
317 //
318 if ((Assemble->Head != NULL) || (Assemble->Packet != NULL)) {
319 goto Error;
320 }
321
322 //
323 // Backup the first fragment in case the reassembly of that packet fail.
324 //
325 Duplicate = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
326 if (Duplicate == NULL) {
327 goto Error;
328 }
329
330 //
331 // Revert IP head to network order.
332 //
333 DupHead = NetbufGetByte (Duplicate, 0, NULL);
334 ASSERT (DupHead != NULL);
335 Duplicate->Ip.Ip6 = Ip6NtohHead ((EFI_IP6_HEADER *)DupHead);
336 Assemble->Packet = Duplicate;
337
338 //
339 // Adjust the unfragmentable part in first fragment
340 //
341 UnFragmentLen = (UINT16)(This->HeadLen - sizeof (EFI_IP6_HEADER));
342 if (UnFragmentLen == 0) {
343 //
344 // There is not any unfragmentable extension header.
345 //
346 ASSERT (Head->NextHeader == IP6_FRAGMENT);
347 Head->NextHeader = This->NextHeader;
348 } else {
349 NextHeader = NetbufGetByte (
350 Packet,
351 This->FormerNextHeader + sizeof (EFI_IP6_HEADER),
352 0
353 );
354 if (NextHeader == NULL) {
355 goto Error;
356 }
357
358 *NextHeader = This->NextHeader;
359 }
360
361 Assemble->Head = Head;
362 Assemble->Info = IP6_GET_CLIP_INFO (Packet);
363 }
364
365 //
366 // Don't update the length more than once.
367 //
368 if ((This->LastFrag != 0) && (Assemble->TotalLen == 0)) {
369 Assemble->TotalLen = This->End;
370 }
371
372 //
373 // Deliver the whole packet if all the fragments received.
374 // All fragments received if:
375 // 1. received the last one, so, the total length is known
376 // 2. received all the data. If the last fragment on the
377 // queue ends at the total length, all data is received.
378 //
379 if ((Assemble->TotalLen != 0) && (Assemble->CurLen >= Assemble->TotalLen)) {
380 RemoveEntryList (&Assemble->Link);
381
382 //
383 // If the packet is properly formatted, the last fragment's End
384 // equals to the packet's total length. Otherwise, the packet
385 // is a fake, drop it now.
386 //
387 Fragment = NET_LIST_USER_STRUCT (ListHead->BackLink, NET_BUF, List);
388 if (IP6_GET_CLIP_INFO (Fragment)->End != (INTN)Assemble->TotalLen) {
389 Ip6FreeAssembleEntry (Assemble);
390 goto Error;
391 }
392
393 Fragment = NET_LIST_HEAD (ListHead, NET_BUF, List);
394 This = Assemble->Info;
395
396 //
397 // This TmpPacket is used to hold the unfragmentable part, i.e.,
398 // the IPv6 header and the unfragmentable extension headers. Be noted that
399 // the Fragment Header is excluded.
400 //
401 TmpPacket = NetbufGetFragment (Fragment, 0, This->HeadLen, 0);
402 ASSERT (TmpPacket != NULL);
403
404 NET_LIST_FOR_EACH (Cur, ListHead) {
405 //
406 // Trim off the unfragment part plus the fragment header from all fragments.
407 //
408 Fragment = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
409 NetbufTrim (Fragment, This->HeadLen + sizeof (IP6_FRAGMENT_HEADER), TRUE);
410 }
411
412 InsertHeadList (ListHead, &TmpPacket->List);
413
414 //
415 // Wrap the packet in a net buffer then deliver it up
416 //
417 NewPacket = NetbufFromBufList (
418 &Assemble->Fragments,
419 0,
420 0,
422 Assemble
423 );
424
425 if (NewPacket == NULL) {
426 Ip6FreeAssembleEntry (Assemble);
427 goto Error;
428 }
429
430 NewPacket->Ip.Ip6 = Assemble->Head;
431
432 CopyMem (IP6_GET_CLIP_INFO (NewPacket), Assemble->Info, sizeof (IP6_CLIP_INFO));
433
434 return NewPacket;
435 }
436
437 return NULL;
438
439Error:
440 NetbufFree (Packet);
441 return NULL;
442}
443
451VOID
452EFIAPI
454 IN VOID *Arg
455 )
456{
457 IP6_IPSEC_WRAP *Wrap;
458
459 Wrap = (IP6_IPSEC_WRAP *)Arg;
460
461 if (Wrap->IpSecRecycleSignal != NULL) {
462 gBS->SignalEvent (Wrap->IpSecRecycleSignal);
463 }
464
465 NetbufFree (Wrap->Packet);
466
467 FreePool (Wrap);
468
469 return;
470}
471
498 IN IP6_SERVICE *IpSb,
499 IN OUT EFI_IP6_HEADER **Head,
500 IN OUT UINT8 *LastHead,
501 IN OUT NET_BUF **Netbuf,
502 IN OUT UINT8 **ExtHdrs,
503 IN OUT UINT32 *ExtHdrsLen,
504 IN EFI_IPSEC_TRAFFIC_DIR Direction,
505 IN VOID *Context
506 )
507{
508 NET_FRAGMENT *FragmentTable;
509 NET_FRAGMENT *OriginalFragmentTable;
510 UINT32 FragmentCount;
511 UINT32 OriginalFragmentCount;
512 EFI_EVENT RecycleEvent;
513 NET_BUF *Packet;
514 IP6_TXTOKEN_WRAP *TxWrap;
515 IP6_IPSEC_WRAP *IpSecWrap;
516 EFI_STATUS Status;
517 EFI_IP6_HEADER *PacketHead;
518 UINT8 *Buf;
519 EFI_IP6_HEADER ZeroHead;
520
521 Status = EFI_SUCCESS;
522
523 if (!mIpSec2Installed) {
524 goto ON_EXIT;
525 }
526
527 ASSERT (mIpSec != NULL);
528
529 Packet = *Netbuf;
530 RecycleEvent = NULL;
531 IpSecWrap = NULL;
532 FragmentTable = NULL;
533 PacketHead = NULL;
534 Buf = NULL;
535 TxWrap = (IP6_TXTOKEN_WRAP *)Context;
536 FragmentCount = Packet->BlockOpNum;
537 ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
538
539 //
540 // Check whether the ipsec enable variable is set.
541 //
542 if (mIpSec->DisabledFlag) {
543 //
544 // If IPsec is disabled, restore the original MTU
545 //
546 IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;
547 goto ON_EXIT;
548 } else {
549 //
550 // If IPsec is enabled, use the MTU which reduce the IPsec header length.
551 //
552 IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP6_MAX_IPSEC_HEADLEN;
553 }
554
555 //
556 // Bypass all multicast inbound or outbound traffic.
557 //
558 if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress) || IP6_IS_MULTICAST (&(*Head)->SourceAddress)) {
559 goto ON_EXIT;
560 }
561
562 //
563 // Rebuild fragment table from netbuf to ease ipsec process.
564 //
565 FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));
566
567 if (FragmentTable == NULL) {
568 Status = EFI_OUT_OF_RESOURCES;
569 goto ON_EXIT;
570 }
571
572 Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);
573 OriginalFragmentTable = FragmentTable;
574 OriginalFragmentCount = FragmentCount;
575
576 if (EFI_ERROR (Status)) {
577 FreePool (FragmentTable);
578 goto ON_EXIT;
579 }
580
581 //
582 // Convert host byte order to network byte order
583 //
584 Ip6NtohHead (*Head);
585
586 Status = mIpSec->ProcessExt (
587 mIpSec,
588 IpSb->Controller,
589 IP_VERSION_6,
590 (VOID *)(*Head),
591 LastHead,
592 (VOID **)ExtHdrs,
593 ExtHdrsLen,
594 (EFI_IPSEC_FRAGMENT_DATA **)(&FragmentTable),
595 &FragmentCount,
596 Direction,
597 &RecycleEvent
598 );
599 //
600 // Convert back to host byte order
601 //
602 Ip6NtohHead (*Head);
603
604 if (EFI_ERROR (Status)) {
605 FreePool (OriginalFragmentTable);
606 goto ON_EXIT;
607 }
608
609 if ((OriginalFragmentCount == FragmentCount) && (OriginalFragmentTable == FragmentTable)) {
610 //
611 // For ByPass Packet
612 //
613 FreePool (FragmentTable);
614 goto ON_EXIT;
615 } else {
616 //
617 // Free the FragmentTable which allocated before calling the IPsec.
618 //
619 FreePool (OriginalFragmentTable);
620 }
621
622 if ((Direction == EfiIPsecOutBound) && (TxWrap != NULL)) {
623 TxWrap->IpSecRecycleSignal = RecycleEvent;
624 TxWrap->Packet = NetbufFromExt (
625 FragmentTable,
626 FragmentCount,
627 IP6_MAX_HEADLEN,
628 0,
630 TxWrap
631 );
632 if (TxWrap->Packet == NULL) {
633 TxWrap->Packet = *Netbuf;
634 Status = EFI_OUT_OF_RESOURCES;
635 goto ON_EXIT;
636 }
637
638 CopyMem (
639 IP6_GET_CLIP_INFO (TxWrap->Packet),
640 IP6_GET_CLIP_INFO (Packet),
641 sizeof (IP6_CLIP_INFO)
642 );
643
644 NetIpSecNetbufFree (Packet);
645 *Netbuf = TxWrap->Packet;
646 } else {
647 IpSecWrap = AllocateZeroPool (sizeof (IP6_IPSEC_WRAP));
648
649 if (IpSecWrap == NULL) {
650 Status = EFI_OUT_OF_RESOURCES;
651 gBS->SignalEvent (RecycleEvent);
652 goto ON_EXIT;
653 }
654
655 IpSecWrap->IpSecRecycleSignal = RecycleEvent;
656 IpSecWrap->Packet = Packet;
657 Packet = NetbufFromExt (
658 FragmentTable,
659 FragmentCount,
660 IP6_MAX_HEADLEN,
661 0,
663 IpSecWrap
664 );
665
666 if (Packet == NULL) {
667 Packet = IpSecWrap->Packet;
668 gBS->SignalEvent (RecycleEvent);
669 FreePool (IpSecWrap);
670 Status = EFI_OUT_OF_RESOURCES;
671 goto ON_EXIT;
672 }
673
674 if ((Direction == EfiIPsecInBound) && (0 != CompareMem (&ZeroHead, *Head, sizeof (EFI_IP6_HEADER)))) {
675 PacketHead = (EFI_IP6_HEADER *)NetbufAllocSpace (
676 Packet,
677 sizeof (EFI_IP6_HEADER) + *ExtHdrsLen,
678 NET_BUF_HEAD
679 );
680 if (PacketHead == NULL) {
681 *Netbuf = Packet;
682 Status = EFI_OUT_OF_RESOURCES;
683 goto ON_EXIT;
684 }
685
686 CopyMem (PacketHead, *Head, sizeof (EFI_IP6_HEADER));
687 *Head = PacketHead;
688 Packet->Ip.Ip6 = PacketHead;
689
690 if (*ExtHdrs != NULL) {
691 Buf = (UINT8 *)(PacketHead + 1);
692 CopyMem (Buf, *ExtHdrs, *ExtHdrsLen);
693 }
694
695 NetbufTrim (Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
696 CopyMem (
697 IP6_GET_CLIP_INFO (Packet),
698 IP6_GET_CLIP_INFO (IpSecWrap->Packet),
699 sizeof (IP6_CLIP_INFO)
700 );
701 }
702
703 *Netbuf = Packet;
704 }
705
706ON_EXIT:
707 return Status;
708}
709
733 IN IP6_SERVICE *IpSb,
734 IN OUT NET_BUF **Packet,
735 IN UINT32 Flag,
736 OUT UINT8 **Payload,
737 OUT UINT8 **LastHead,
738 OUT UINT32 *ExtHdrsLen,
739 OUT UINT32 *UnFragmentLen,
740 OUT BOOLEAN *Fragmented,
741 OUT EFI_IP6_HEADER **Head
742 )
743{
744 UINT16 PayloadLen;
745 UINT16 TotalLen;
746 UINT32 FormerHeadOffset;
747 UINT32 HeadLen;
748 IP6_FRAGMENT_HEADER *FragmentHead;
749 UINT16 FragmentOffset;
750 IP6_CLIP_INFO *Info;
751 EFI_IPv6_ADDRESS Loopback;
752
753 HeadLen = 0;
754 PayloadLen = 0;
755 //
756 // Check whether the input packet is a valid packet
757 //
758 if ((*Packet)->TotalSize < IP6_MIN_HEADLEN) {
759 return EFI_INVALID_PARAMETER;
760 }
761
762 //
763 // Get header information of the packet.
764 //
765 *Head = (EFI_IP6_HEADER *)NetbufGetByte (*Packet, 0, NULL);
766 if (*Head == NULL) {
767 return EFI_INVALID_PARAMETER;
768 }
769
770 //
771 // Multicast addresses must not be used as source addresses in IPv6 packets.
772 //
773 if (((*Head)->Version != 6) || (IP6_IS_MULTICAST (&(*Head)->SourceAddress))) {
774 return EFI_INVALID_PARAMETER;
775 }
776
777 //
778 // A packet with a destination address of loopback ::1/128 or unspecified must be dropped.
779 //
780 ZeroMem (&Loopback, sizeof (EFI_IPv6_ADDRESS));
781 Loopback.Addr[15] = 0x1;
782 if ((CompareMem (&Loopback, &(*Head)->DestinationAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) ||
783 (NetIp6IsUnspecifiedAddr (&(*Head)->DestinationAddress)))
784 {
785 return EFI_INVALID_PARAMETER;
786 }
787
788 //
789 // Convert the IP header to host byte order.
790 //
791 (*Packet)->Ip.Ip6 = Ip6NtohHead (*Head);
792
793 //
794 // Get the per packet info.
795 //
796 Info = IP6_GET_CLIP_INFO (*Packet);
797 Info->LinkFlag = Flag;
798 Info->CastType = 0;
799
800 if (IpSb->MnpConfigData.EnablePromiscuousReceive) {
801 Info->CastType = Ip6Promiscuous;
802 }
803
804 if (Ip6IsOneOfSetAddress (IpSb, &(*Head)->DestinationAddress, NULL, NULL)) {
805 Info->CastType = Ip6Unicast;
806 } else if (IP6_IS_MULTICAST (&(*Head)->DestinationAddress)) {
807 if (Ip6FindMldEntry (IpSb, &(*Head)->DestinationAddress) != NULL) {
808 Info->CastType = Ip6Multicast;
809 }
810 }
811
812 //
813 // Drop the packet that is not delivered to us.
814 //
815 if (Info->CastType == 0) {
816 return EFI_INVALID_PARAMETER;
817 }
818
819 PayloadLen = (*Head)->PayloadLength;
820
821 Info->Start = 0;
822 Info->Length = PayloadLen;
823 Info->End = Info->Start + Info->Length;
824 Info->HeadLen = (UINT16)sizeof (EFI_IP6_HEADER);
825 Info->Status = EFI_SUCCESS;
826 Info->LastFrag = FALSE;
827
828 TotalLen = (UINT16)(PayloadLen + sizeof (EFI_IP6_HEADER));
829
830 //
831 // Mnp may deliver frame trailer sequence up, trim it off.
832 //
833 if (TotalLen < (*Packet)->TotalSize) {
834 NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE);
835 }
836
837 if (TotalLen != (*Packet)->TotalSize) {
838 return EFI_INVALID_PARAMETER;
839 }
840
841 //
842 // Check the extension headers, if exist validate them
843 //
844 if (PayloadLen != 0) {
845 *Payload = AllocatePool ((UINTN)PayloadLen);
846 if (*Payload == NULL) {
847 return EFI_INVALID_PARAMETER;
848 }
849
850 NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
851 }
852
853 if (!Ip6IsExtsValid (
854 IpSb,
855 *Packet,
856 &(*Head)->NextHeader,
857 *Payload,
858 (UINT32)PayloadLen,
859 TRUE,
860 &FormerHeadOffset,
861 LastHead,
862 ExtHdrsLen,
863 UnFragmentLen,
864 Fragmented
865 ))
866 {
867 return EFI_INVALID_PARAMETER;
868 }
869
870 HeadLen = sizeof (EFI_IP6_HEADER) + *UnFragmentLen;
871
872 if (*Fragmented) {
873 //
874 // Get the fragment offset from the Fragment header
875 //
876 FragmentHead = (IP6_FRAGMENT_HEADER *)NetbufGetByte (*Packet, HeadLen, NULL);
877 if (FragmentHead == NULL) {
878 return EFI_INVALID_PARAMETER;
879 }
880
881 FragmentOffset = NTOHS (FragmentHead->FragmentOffset);
882
883 if ((FragmentOffset & 0x1) == 0) {
884 Info->LastFrag = TRUE;
885 }
886
887 FragmentOffset &= (~0x1);
888
889 //
890 // This is the first fragment of the packet
891 //
892 if (FragmentOffset == 0) {
893 Info->NextHeader = FragmentHead->NextHeader;
894 }
895
896 Info->HeadLen = (UINT16)HeadLen;
897 HeadLen += sizeof (IP6_FRAGMENT_HEADER);
898 Info->Start = FragmentOffset;
899 Info->Length = TotalLen - (UINT16)HeadLen;
900 Info->End = Info->Start + Info->Length;
901 Info->Id = FragmentHead->Identification;
902 Info->FormerNextHeader = FormerHeadOffset;
903
904 //
905 // Fragments should in the unit of 8 octets long except the last one.
906 //
907 if ((Info->LastFrag == 0) && (Info->Length % 8 != 0)) {
908 return EFI_INVALID_PARAMETER;
909 }
910
911 //
912 // Reassemble the packet.
913 //
914 *Packet = Ip6Reassemble (&IpSb->Assemble, *Packet);
915 if (*Packet == NULL) {
916 return EFI_INVALID_PARAMETER;
917 }
918
919 //
920 // Re-check the assembled packet to get the right values.
921 //
922 *Head = (*Packet)->Ip.Ip6;
923 PayloadLen = (*Head)->PayloadLength;
924 if (PayloadLen != 0) {
925 if (*Payload != NULL) {
926 FreePool (*Payload);
927 }
928
929 *Payload = AllocatePool ((UINTN)PayloadLen);
930 if (*Payload == NULL) {
931 return EFI_INVALID_PARAMETER;
932 }
933
934 NetbufCopy (*Packet, sizeof (EFI_IP6_HEADER), PayloadLen, *Payload);
935 }
936
937 if (!Ip6IsExtsValid (
938 IpSb,
939 *Packet,
940 &(*Head)->NextHeader,
941 *Payload,
942 (UINT32)PayloadLen,
943 TRUE,
944 NULL,
945 LastHead,
946 ExtHdrsLen,
947 UnFragmentLen,
948 Fragmented
949 ))
950 {
951 return EFI_INVALID_PARAMETER;
952 }
953 }
954
955 //
956 // Trim the head off, after this point, the packet is headless.
957 // and Packet->TotalLen == Info->Length.
958 //
959 NetbufTrim (*Packet, sizeof (EFI_IP6_HEADER) + *ExtHdrsLen, TRUE);
960
961 return EFI_SUCCESS;
962}
963
975VOID
977 IN NET_BUF *Packet,
978 IN EFI_STATUS IoStatus,
979 IN UINT32 Flag,
980 IN VOID *Context
981 )
982{
983 IP6_SERVICE *IpSb;
984 EFI_IP6_HEADER *Head;
985 UINT8 *Payload;
986 UINT8 *LastHead;
987 UINT32 UnFragmentLen;
988 UINT32 ExtHdrsLen;
989 BOOLEAN Fragmented;
990 EFI_STATUS Status;
991 EFI_IP6_HEADER ZeroHead;
992
993 IpSb = (IP6_SERVICE *)Context;
994 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
995
996 Payload = NULL;
997 LastHead = NULL;
998
999 //
1000 // Check input parameters
1001 //
1002 if (EFI_ERROR (IoStatus) || (IpSb->State == IP6_SERVICE_DESTROY)) {
1003 goto Drop;
1004 }
1005
1006 //
1007 // Pre-Process the Ipv6 Packet and then reassemble if it is necessary.
1008 //
1009 Status = Ip6PreProcessPacket (
1010 IpSb,
1011 &Packet,
1012 Flag,
1013 &Payload,
1014 &LastHead,
1015 &ExtHdrsLen,
1016 &UnFragmentLen,
1017 &Fragmented,
1018 &Head
1019 );
1020 if (EFI_ERROR (Status)) {
1021 goto Restart;
1022 }
1023
1024 //
1025 // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer,
1026 // and no need consider any other ahead ext headers.
1027 //
1028 Status = Ip6IpSecProcessPacket (
1029 IpSb,
1030 &Head,
1031 LastHead, // need get the lasthead value for input
1032 &Packet,
1033 &Payload,
1034 &ExtHdrsLen,
1036 NULL
1037 );
1038
1039 if (EFI_ERROR (Status)) {
1040 goto Restart;
1041 }
1042
1043 //
1044 // If the packet is protected by IPsec Tunnel Mode, Check the Inner Ip Packet.
1045 //
1046 ZeroMem (&ZeroHead, sizeof (EFI_IP6_HEADER));
1047 if (0 == CompareMem (Head, &ZeroHead, sizeof (EFI_IP6_HEADER))) {
1048 Status = Ip6PreProcessPacket (
1049 IpSb,
1050 &Packet,
1051 Flag,
1052 &Payload,
1053 &LastHead,
1054 &ExtHdrsLen,
1055 &UnFragmentLen,
1056 &Fragmented,
1057 &Head
1058 );
1059 if (EFI_ERROR (Status)) {
1060 goto Restart;
1061 }
1062 }
1063
1064 //
1065 // Check the Packet again.
1066 //
1067 if (Packet == NULL) {
1068 goto Restart;
1069 }
1070
1071 //
1072 // Packet may have been changed. The ownership of the packet
1073 // is transferred to the packet process logic.
1074 //
1075 Head = Packet->Ip.Ip6;
1076 IP6_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS;
1077
1078 switch (*LastHead) {
1079 case IP6_ICMP:
1080 Ip6IcmpHandle (IpSb, Head, Packet);
1081 break;
1082 default:
1083 Ip6Demultiplex (IpSb, Head, Packet);
1084 }
1085
1086 Packet = NULL;
1087
1088 //
1089 // Dispatch the DPCs queued by the NotifyFunction of the rx token's events
1090 // which are signaled with received data.
1091 //
1092 DispatchDpc ();
1093
1094Restart:
1095 if (Payload != NULL) {
1096 FreePool (Payload);
1097 }
1098
1100
1101Drop:
1102 if (Packet != NULL) {
1103 NetbufFree (Packet);
1104 }
1105
1106 return;
1107}
1108
1116VOID
1119 )
1120{
1121 UINT32 Index;
1122
1123 for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
1124 InitializeListHead (&Table->Bucket[Index]);
1125 }
1126}
1127
1135VOID
1138 )
1139{
1140 LIST_ENTRY *Entry;
1141 LIST_ENTRY *Next;
1142 IP6_ASSEMBLE_ENTRY *Assemble;
1143 UINT32 Index;
1144
1145 for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
1146 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Table->Bucket[Index]) {
1147 Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
1148
1149 RemoveEntryList (Entry);
1150 Ip6FreeAssembleEntry (Assemble);
1151 }
1152 }
1153}
1154
1163VOID
1164EFIAPI
1166 IN EFI_EVENT Event,
1167 IN VOID *Context
1168 )
1169{
1170 IP6_RXDATA_WRAP *Wrap;
1171
1172 Wrap = (IP6_RXDATA_WRAP *)Context;
1173
1174 EfiAcquireLockOrFail (&Wrap->IpInstance->RecycleLock);
1175 RemoveEntryList (&Wrap->Link);
1176 EfiReleaseLock (&Wrap->IpInstance->RecycleLock);
1177
1178 ASSERT (!NET_BUF_SHARED (Wrap->Packet));
1179 NetbufFree (Wrap->Packet);
1180
1181 gBS->CloseEvent (Wrap->RxData.RecycleSignal);
1182 FreePool (Wrap);
1183}
1184
1201 IN IP6_PROTOCOL *IpInstance,
1202 IN NET_BUF *Packet
1203 )
1204{
1205 IP6_RXDATA_WRAP *Wrap;
1206 EFI_IP6_RECEIVE_DATA *RxData;
1207 EFI_STATUS Status;
1208
1209 Wrap = AllocatePool (IP6_RXDATA_WRAP_SIZE (Packet->BlockOpNum));
1210
1211 if (Wrap == NULL) {
1212 return NULL;
1213 }
1214
1215 InitializeListHead (&Wrap->Link);
1216
1217 Wrap->IpInstance = IpInstance;
1218 Wrap->Packet = Packet;
1219 RxData = &Wrap->RxData;
1220
1221 ZeroMem (&RxData->TimeStamp, sizeof (EFI_TIME));
1222
1223 Status = gBS->CreateEvent (
1224 EVT_NOTIFY_SIGNAL,
1225 TPL_NOTIFY,
1227 Wrap,
1228 &RxData->RecycleSignal
1229 );
1230
1231 if (EFI_ERROR (Status)) {
1232 FreePool (Wrap);
1233 return NULL;
1234 }
1235
1236 ASSERT (Packet->Ip.Ip6 != NULL);
1237
1238 //
1239 // The application expects a network byte order header.
1240 //
1241 RxData->HeaderLength = sizeof (EFI_IP6_HEADER);
1242 RxData->Header = (EFI_IP6_HEADER *)Ip6NtohHead (Packet->Ip.Ip6);
1243 RxData->DataLength = Packet->TotalSize;
1244
1245 //
1246 // Build the fragment table to be delivered up.
1247 //
1248 RxData->FragmentCount = Packet->BlockOpNum;
1249 NetbufBuildExt (Packet, (NET_FRAGMENT *)RxData->FragmentTable, &RxData->FragmentCount);
1250
1251 return Wrap;
1252}
1253
1265BOOLEAN
1267 IN IP6_PROTOCOL *IpInstance,
1268 IN EFI_IP6_HEADER *Head,
1269 IN NET_BUF *Packet
1270 )
1271{
1273 EFI_IP6_CONFIG_DATA *Config;
1274 IP6_CLIP_INFO *Info;
1275 UINT8 *Proto;
1276 UINT32 Index;
1277 UINT8 *ExtHdrs;
1278 UINT16 ErrMsgPayloadLen;
1279 UINT8 *ErrMsgPayload;
1280
1281 Config = &IpInstance->ConfigData;
1282 Proto = NULL;
1283
1284 //
1285 // Dirty trick for the Tiano UEFI network stack implementation. If
1286 // ReceiveTimeout == -1, the receive of the packet for this instance
1287 // is disabled. The UEFI spec don't have such captibility. We add
1288 // this to improve the performance because IP will make a copy of
1289 // the received packet for each accepting instance. Some IP instances
1290 // used by UDP/TCP only send packets, they don't wants to receive.
1291 //
1292 if (Config->ReceiveTimeout == (UINT32)(-1)) {
1293 return FALSE;
1294 }
1295
1296 if (Config->AcceptPromiscuous) {
1297 return TRUE;
1298 }
1299
1300 //
1301 // Check whether the protocol is acceptable.
1302 //
1303 ExtHdrs = NetbufGetByte (Packet, 0, NULL);
1304
1305 if (!Ip6IsExtsValid (
1306 IpInstance->Service,
1307 Packet,
1308 &Head->NextHeader,
1309 ExtHdrs,
1310 (UINT32)Head->PayloadLength,
1311 TRUE,
1312 NULL,
1313 &Proto,
1314 NULL,
1315 NULL,
1316 NULL
1317 ))
1318 {
1319 return FALSE;
1320 }
1321
1322 //
1323 // The upper layer driver may want to receive the ICMPv6 error packet
1324 // invoked by its packet, like UDP.
1325 //
1326 if ((*Proto == IP6_ICMP) && (!Config->AcceptAnyProtocol) && (*Proto != Config->DefaultProtocol)) {
1327 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
1328
1329 if (Icmp.Head.Type <= ICMP_V6_ERROR_MAX) {
1330 if (!Config->AcceptIcmpErrors) {
1331 return FALSE;
1332 }
1333
1334 //
1335 // Get the protocol of the invoking packet of ICMPv6 error packet.
1336 //
1337 ErrMsgPayloadLen = NTOHS (Icmp.IpHead.PayloadLength);
1338 ErrMsgPayload = NetbufGetByte (Packet, sizeof (Icmp), NULL);
1339
1340 if (!Ip6IsExtsValid (
1341 NULL,
1342 NULL,
1343 &Icmp.IpHead.NextHeader,
1344 ErrMsgPayload,
1345 ErrMsgPayloadLen,
1346 TRUE,
1347 NULL,
1348 &Proto,
1349 NULL,
1350 NULL,
1351 NULL
1352 ))
1353 {
1354 return FALSE;
1355 }
1356 }
1357 }
1358
1359 //
1360 // Match the protocol
1361 //
1362 if (!Config->AcceptAnyProtocol && (*Proto != Config->DefaultProtocol)) {
1363 return FALSE;
1364 }
1365
1366 //
1367 // Check for broadcast, the caller has computed the packet's
1368 // cast type for this child's interface.
1369 //
1370 Info = IP6_GET_CLIP_INFO (Packet);
1371
1372 //
1373 // If it is a multicast packet, check whether we are in the group.
1374 //
1375 if (Info->CastType == Ip6Multicast) {
1376 //
1377 // Receive the multicast if the instance wants to receive all packets.
1378 //
1379 if (NetIp6IsUnspecifiedAddr (&IpInstance->ConfigData.StationAddress)) {
1380 return TRUE;
1381 }
1382
1383 for (Index = 0; Index < IpInstance->GroupCount; Index++) {
1384 if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, &Head->DestinationAddress)) {
1385 break;
1386 }
1387 }
1388
1389 return (BOOLEAN)(Index < IpInstance->GroupCount);
1390 }
1391
1392 return TRUE;
1393}
1394
1412 IN IP6_PROTOCOL *IpInstance,
1413 IN EFI_IP6_HEADER *Head,
1414 IN NET_BUF *Packet
1415 )
1416{
1417 IP6_CLIP_INFO *Info;
1418 NET_BUF *Clone;
1419
1420 //
1421 // Check whether the packet is acceptable to this instance.
1422 //
1423 if (IpInstance->State != IP6_STATE_CONFIGED) {
1424 return EFI_NOT_STARTED;
1425 }
1426
1427 if (!Ip6InstanceFrameAcceptable (IpInstance, Head, Packet)) {
1428 return EFI_INVALID_PARAMETER;
1429 }
1430
1431 //
1432 // Enqueue a shared copy of the packet.
1433 //
1434 Clone = NetbufClone (Packet);
1435
1436 if (Clone == NULL) {
1437 return EFI_OUT_OF_RESOURCES;
1438 }
1439
1440 //
1441 // Set the receive time out for the assembled packet. If it expires,
1442 // packet will be removed from the queue.
1443 //
1444 Info = IP6_GET_CLIP_INFO (Clone);
1445 Info->Life = IP6_US_TO_SEC (IpInstance->ConfigData.ReceiveTimeout);
1446
1447 InsertTailList (&IpInstance->Received, &Clone->List);
1448 return EFI_SUCCESS;
1449}
1450
1467 IN IP6_PROTOCOL *IpInstance
1468 )
1469{
1471 IP6_RXDATA_WRAP *Wrap;
1472 NET_BUF *Packet;
1473 NET_BUF *Dup;
1474 UINT8 *Head;
1475
1476 //
1477 // Deliver a packet if there are both a packet and a receive token.
1478 //
1479 while (!IsListEmpty (&IpInstance->Received) && !NetMapIsEmpty (&IpInstance->RxTokens)) {
1480 Packet = NET_LIST_HEAD (&IpInstance->Received, NET_BUF, List);
1481
1482 if (!NET_BUF_SHARED (Packet)) {
1483 //
1484 // If this is the only instance that wants the packet, wrap it up.
1485 //
1486 Wrap = Ip6WrapRxData (IpInstance, Packet);
1487
1488 if (Wrap == NULL) {
1489 return EFI_OUT_OF_RESOURCES;
1490 }
1491
1492 RemoveEntryList (&Packet->List);
1493 } else {
1494 //
1495 // Create a duplicated packet if this packet is shared
1496 //
1497 Dup = NetbufDuplicate (Packet, NULL, sizeof (EFI_IP6_HEADER));
1498
1499 if (Dup == NULL) {
1500 return EFI_OUT_OF_RESOURCES;
1501 }
1502
1503 //
1504 // Copy the IP head over. The packet to deliver up is
1505 // headless. Trim the head off after copy. The IP head
1506 // may be not continuous before the data.
1507 //
1508 Head = NetbufAllocSpace (Dup, sizeof (EFI_IP6_HEADER), NET_BUF_HEAD);
1509 ASSERT (Head != NULL);
1510 Dup->Ip.Ip6 = (EFI_IP6_HEADER *)Head;
1511
1512 CopyMem (Head, Packet->Ip.Ip6, sizeof (EFI_IP6_HEADER));
1513 NetbufTrim (Dup, sizeof (EFI_IP6_HEADER), TRUE);
1514
1515 Wrap = Ip6WrapRxData (IpInstance, Dup);
1516
1517 if (Wrap == NULL) {
1518 NetbufFree (Dup);
1519 return EFI_OUT_OF_RESOURCES;
1520 }
1521
1522 RemoveEntryList (&Packet->List);
1523 NetbufFree (Packet);
1524
1525 Packet = Dup;
1526 }
1527
1528 //
1529 // Insert it into the delivered packet, then get a user's
1530 // receive token, pass the wrapped packet up.
1531 //
1532 EfiAcquireLockOrFail (&IpInstance->RecycleLock);
1533 InsertHeadList (&IpInstance->Delivered, &Wrap->Link);
1534 EfiReleaseLock (&IpInstance->RecycleLock);
1535
1536 Token = NetMapRemoveHead (&IpInstance->RxTokens, NULL);
1537 Token->Status = IP6_GET_CLIP_INFO (Packet)->Status;
1538 Token->Packet.RxData = &Wrap->RxData;
1539
1540 gBS->SignalEvent (Token->Event);
1541 }
1542
1543 return EFI_SUCCESS;
1544}
1545
1558INTN
1560 IN IP6_SERVICE *IpSb,
1561 IN EFI_IP6_HEADER *Head,
1562 IN NET_BUF *Packet,
1563 IN IP6_INTERFACE *IpIf
1564 )
1565{
1566 IP6_PROTOCOL *IpInstance;
1567 IP6_CLIP_INFO *Info;
1568 LIST_ENTRY *Entry;
1569 INTN Enqueued;
1570 INTN LocalType;
1571 INTN SavedType;
1572
1573 //
1574 // First, check that the packet is acceptable to this interface
1575 // and find the local cast type for the interface.
1576 //
1577 LocalType = 0;
1578 Info = IP6_GET_CLIP_INFO (Packet);
1579
1580 if (IpIf->PromiscRecv) {
1581 LocalType = Ip6Promiscuous;
1582 } else {
1583 LocalType = Info->CastType;
1584 }
1585
1586 //
1587 // Iterate through the ip instances on the interface, enqueue
1588 // the packet if filter passed. Save the original cast type,
1589 // and pass the local cast type to the IP children on the
1590 // interface. The global cast type will be restored later.
1591 //
1592 SavedType = Info->CastType;
1593 Info->CastType = (UINT32)LocalType;
1594
1595 Enqueued = 0;
1596
1597 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
1598 IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
1599 NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
1600
1601 if (Ip6InstanceEnquePacket (IpInstance, Head, Packet) == EFI_SUCCESS) {
1602 Enqueued++;
1603 }
1604 }
1605
1606 Info->CastType = (UINT32)SavedType;
1607 return Enqueued;
1608}
1609
1617VOID
1619 IN IP6_SERVICE *IpSb,
1620 IN IP6_INTERFACE *IpIf
1621 )
1622{
1623 IP6_PROTOCOL *IpInstance;
1624 LIST_ENTRY *Entry;
1625
1626 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
1627 IpInstance = NET_LIST_USER_STRUCT (Entry, IP6_PROTOCOL, AddrLink);
1628 Ip6InstanceDeliverPacket (IpInstance);
1629 }
1630}
1631
1652 IN IP6_SERVICE *IpSb,
1653 IN EFI_IP6_HEADER *Head,
1654 IN NET_BUF *Packet
1655 )
1656{
1657 LIST_ENTRY *Entry;
1658 IP6_INTERFACE *IpIf;
1659 INTN Enqueued;
1660
1661 //
1662 // Two pass delivery: first, enqueue a shared copy of the packet
1663 // to each instance that accept the packet.
1664 //
1665 Enqueued = 0;
1666
1667 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
1668 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
1669
1670 if (IpIf->Configured) {
1671 Enqueued += Ip6InterfaceEnquePacket (IpSb, Head, Packet, IpIf);
1672 }
1673 }
1674
1675 //
1676 // Second: deliver a duplicate of the packet to each instance.
1677 // Release the local reference first, so that the last instance
1678 // getting the packet will not copy the data.
1679 //
1680 NetbufFree (Packet);
1681 Packet = NULL;
1682
1683 if (Enqueued == 0) {
1684 return EFI_NOT_FOUND;
1685 }
1686
1687 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
1688 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
1689
1690 if (IpIf->Configured) {
1691 Ip6InterfaceDeliverPacket (IpSb, IpIf);
1692 }
1693 }
1694
1695 return EFI_SUCCESS;
1696}
1697
1713EFIAPI
1715 IN NET_MAP *Map,
1716 IN NET_MAP_ITEM *Item,
1717 IN VOID *Context
1718 )
1719{
1720 IP6_TXTOKEN_WRAP *Wrap;
1721
1722 Wrap = (IP6_TXTOKEN_WRAP *)Item->Value;
1723 ASSERT (Wrap != NULL);
1724
1725 if ((Wrap->Life > 0) && (--Wrap->Life == 0)) {
1726 Ip6CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
1727 }
1728
1729 return EFI_SUCCESS;
1730}
1731
1738VOID
1740 IN IP6_SERVICE *IpSb
1741 )
1742{
1743 LIST_ENTRY *InstanceEntry;
1744 LIST_ENTRY *Entry;
1745 LIST_ENTRY *Next;
1746 IP6_PROTOCOL *IpInstance;
1747 IP6_ASSEMBLE_ENTRY *Assemble;
1748 NET_BUF *Packet;
1749 IP6_CLIP_INFO *Info;
1750 UINT32 Index;
1751
1752 //
1753 // First, time out the fragments. The packet's life is counting down
1754 // once the first-arriving fragment of that packet was received.
1755 //
1756 for (Index = 0; Index < IP6_ASSEMLE_HASH_SIZE; Index++) {
1757 NET_LIST_FOR_EACH_SAFE (Entry, Next, &(IpSb->Assemble.Bucket[Index])) {
1758 Assemble = NET_LIST_USER_STRUCT (Entry, IP6_ASSEMBLE_ENTRY, Link);
1759
1760 if ((Assemble->Life > 0) && (--Assemble->Life == 0)) {
1761 //
1762 // If the first fragment (the one with a Fragment Offset of zero)
1763 // has been received, an ICMP Time Exceeded - Fragment Reassembly
1764 // Time Exceeded message should be sent to the source of that fragment.
1765 //
1766 if ((Assemble->Packet != NULL) &&
1767 !IP6_IS_MULTICAST (&Assemble->Head->DestinationAddress))
1768 {
1770 IpSb,
1771 Assemble->Packet,
1772 NULL,
1773 &Assemble->Head->SourceAddress,
1774 ICMP_V6_TIME_EXCEEDED,
1775 ICMP_V6_TIMEOUT_REASSEMBLE,
1776 NULL
1777 );
1778 }
1779
1780 //
1781 // If reassembly of a packet is not completed within 60 seconds of
1782 // the reception of the first-arriving fragment of that packet, the
1783 // reassembly must be abandoned and all the fragments that have been
1784 // received for that packet must be discarded.
1785 //
1786 RemoveEntryList (Entry);
1787 Ip6FreeAssembleEntry (Assemble);
1788 }
1789 }
1790 }
1791
1792 NET_LIST_FOR_EACH (InstanceEntry, &IpSb->Children) {
1793 IpInstance = NET_LIST_USER_STRUCT (InstanceEntry, IP6_PROTOCOL, Link);
1794
1795 //
1796 // Second, time out the assembled packets enqueued on each IP child.
1797 //
1798 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpInstance->Received) {
1799 Packet = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
1800 Info = IP6_GET_CLIP_INFO (Packet);
1801
1802 if ((Info->Life > 0) && (--Info->Life == 0)) {
1803 RemoveEntryList (Entry);
1804 NetbufFree (Packet);
1805 }
1806 }
1807
1808 //
1809 // Third: time out the transmitted packets.
1810 //
1811 NetMapIterate (&IpInstance->TxTokens, Ip6SentPacketTicking, NULL);
1812 }
1813}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
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
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI DispatchDpc(VOID)
Definition: DpcLib.c:86
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
struct _EFI_IP6_HEADER EFI_IP6_HEADER
EFI_IP6_HEADER * Ip6NtohHead(IN OUT EFI_IP6_HEADER *Head)
Definition: Ip6Common.c:659
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
EFI_STATUS Ip6SendIcmpError(IN IP6_SERVICE *IpSb, IN NET_BUF *Packet, IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, IN EFI_IPv6_ADDRESS *DestinationAddress, IN UINT8 Type, IN UINT8 Code, IN UINT32 *Pointer OPTIONAL)
Definition: Ip6Icmp.c:564
EFI_STATUS Ip6IcmpHandle(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Icmp.c:402
EFI_STATUS Ip6ReceiveFrame(IN IP6_FRAME_CALLBACK CallBack, IN IP6_SERVICE *IpSb)
Definition: Ip6If.c:561
VOID EFIAPI Ip6FreeTxToken(IN VOID *Context)
Definition: Ip6Impl.c:1117
VOID EFIAPI Ip6OnRecyclePacket(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6Input.c:1165
INTN Ip6InterfaceEnquePacket(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet, IN IP6_INTERFACE *IpIf)
Definition: Ip6Input.c:1559
VOID Ip6FreeAssembleEntry(IN IP6_ASSEMBLE_ENTRY *Assemble)
Definition: Ip6Input.c:62
VOID Ip6TrimPacket(IN OUT NET_BUF *Packet, IN INTN Start, IN INTN End)
Definition: Ip6Input.c:111
EFI_STATUS Ip6InstanceDeliverPacket(IN IP6_PROTOCOL *IpInstance)
Definition: Ip6Input.c:1466
NET_BUF * Ip6Reassemble(IN OUT IP6_ASSEMBLE_TABLE *Table, IN NET_BUF *Packet)
Definition: Ip6Input.c:158
VOID Ip6InterfaceDeliverPacket(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *IpIf)
Definition: Ip6Input.c:1618
EFI_STATUS EFIAPI Ip6SentPacketTicking(IN NET_MAP *Map, IN NET_MAP_ITEM *Item, IN VOID *Context)
Definition: Ip6Input.c:1714
VOID Ip6CleanAssembleTable(IN OUT IP6_ASSEMBLE_TABLE *Table)
Definition: Ip6Input.c:1136
VOID Ip6AcceptFrame(IN NET_BUF *Packet, IN EFI_STATUS IoStatus, IN UINT32 Flag, IN VOID *Context)
Definition: Ip6Input.c:976
EFI_STATUS Ip6Demultiplex(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Input.c:1651
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
VOID Ip6CreateAssembleTable(IN OUT IP6_ASSEMBLE_TABLE *Table)
Definition: Ip6Input.c:1117
IP6_RXDATA_WRAP * Ip6WrapRxData(IN IP6_PROTOCOL *IpInstance, IN NET_BUF *Packet)
Definition: Ip6Input.c:1200
VOID EFIAPI Ip6OnFreeFragments(IN VOID *Arg)
Definition: Ip6Input.c:94
EFI_STATUS Ip6PreProcessPacket(IN IP6_SERVICE *IpSb, IN OUT NET_BUF **Packet, IN UINT32 Flag, OUT UINT8 **Payload, OUT UINT8 **LastHead, OUT UINT32 *ExtHdrsLen, OUT UINT32 *UnFragmentLen, OUT BOOLEAN *Fragmented, OUT EFI_IP6_HEADER **Head)
Definition: Ip6Input.c:732
VOID EFIAPI Ip6IpSecFree(IN VOID *Arg)
Definition: Ip6Input.c:453
BOOLEAN Ip6InstanceFrameAcceptable(IN IP6_PROTOCOL *IpInstance, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Input.c:1266
EFI_STATUS Ip6InstanceEnquePacket(IN IP6_PROTOCOL *IpInstance, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Input.c:1411
IP6_ASSEMBLE_ENTRY * Ip6CreateAssembleEntry(IN EFI_IPv6_ADDRESS *Dst, IN EFI_IPv6_ADDRESS *Src, IN UINT32 Id)
Definition: Ip6Input.c:26
VOID Ip6PacketTimerTicking(IN IP6_SERVICE *IpSb)
Definition: Ip6Input.c:1739
#define IP6_FRAGMENT_LIFE
Definition: Ip6Input.h:24
#define IP6_MAX_IPSEC_HEADLEN
Definition: Ip6Input.h:18
IP6_MLD_GROUP * Ip6FindMldEntry(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Mld.c:56
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
VOID Ip6CancelPacket(IN IP6_INTERFACE *IpIf, IN NET_BUF *Packet, IN EFI_STATUS IoStatus)
Definition: Ip6Output.c:1081
EFI_IPSEC_TRAFFIC_DIR
Definition: IpSecConfig.h:129
@ EfiIPsecInBound
Definition: IpSecConfig.h:135
@ 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
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
NET_BUF *EFIAPI NetbufClone(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:229
UINT32 EFIAPI NetbufTrim(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1134
EFI_STATUS EFIAPI NetbufBuildExt(IN NET_BUF *Nbuf, IN OUT NET_FRAGMENT *ExtFragment, IN OUT UINT32 *ExtNum)
Definition: NetBuffer.c:866
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
NET_BUF *EFIAPI NetbufGetFragment(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT32 HeadSpace)
Definition: NetBuffer.c:510
NET_BUF *EFIAPI NetbufFromExt(IN NET_FRAGMENT *ExtFragment, IN UINT32 ExtNum, IN UINT32 HeadSpace, IN UINT32 HeadLen, IN NET_VECTOR_EXT_FREE ExtFree, IN VOID *Arg OPTIONAL)
Definition: NetBuffer.c:693
NET_BUF *EFIAPI NetbufFromBufList(IN LIST_ENTRY *BufList, IN UINT32 HeadSpace, IN UINT32 HeaderLen, IN NET_VECTOR_EXT_FREE ExtFree, IN VOID *Arg OPTIONAL)
Definition: NetBuffer.c:914
BOOLEAN EFIAPI NetIp6IsUnspecifiedAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:766
VOID NetIpSecNetbufFree(NET_BUF *Nbuf)
Definition: NetBuffer.c:1812
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
NET_BUF *EFIAPI NetbufDuplicate(IN NET_BUF *Nbuf, IN OUT NET_BUF *Duplicate OPTIONAL, IN UINT32 HeadSpace)
Definition: NetBuffer.c:280
BOOLEAN EFIAPI NetMapIsEmpty(IN NET_MAP *Map)
Definition: DxeNetLib.c:1413
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID *EFIAPI NetMapRemoveHead(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1710
EFI_STATUS EFIAPI NetMapIterate(IN NET_MAP *Map, IN NET_MAP_CALLBACK CallBack, IN VOID *Arg OPTIONAL)
Definition: DxeNetLib.c:1800
VOID EFIAPI NetListInsertBefore(IN OUT LIST_ENTRY *PostEntry, IN OUT LIST_ENTRY *NewEntry)
Definition: DxeNetLib.c:1199
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:499
EFI_STATUS EFIAPI EfiAcquireLockOrFail(IN EFI_LOCK *Lock)
Definition: UefiLib.c:463
EFI_TIME TimeStamp
Definition: Ip6.h:427
UINT32 HeaderLength
Definition: Ip6.h:437
UINT32 FragmentCount
Definition: Ip6.h:452
EFI_IP6_HEADER * Header
Definition: Ip6.h:443
UINT32 DataLength
Definition: Ip6.h:448
EFI_EVENT RecycleSignal
Definition: Ip6.h:432
EFI_IP6_FRAGMENT_DATA FragmentTable[1]
Definition: Ip6.h:456
EFI_STATUS Status
Definition: Ip6.h:536
EFI_EVENT Event
Definition: Ip6.h:522
EFI_IP6_RECEIVE_DATA * RxData
Definition: Ip6.h:541
BOOLEAN AcceptIcmpErrors
Definition: Ip6.h:157
UINT32 ReceiveTimeout
Definition: Ip6.h:208
UINT8 DefaultProtocol
Definition: Ip6.h:144
BOOLEAN AcceptAnyProtocol
Definition: Ip6.h:152
BOOLEAN AcceptPromiscuous
Definition: Ip6.h:163