TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip6Nd.c
Go to the documentation of this file.
1
10#include "Ip6Impl.h"
11
12EFI_MAC_ADDRESS mZeroMacAddress;
13
24 IN OUT IP6_SERVICE *IpSb
25 )
26{
27 UINT32 Random;
28 EFI_STATUS Status;
29
30 Status = PseudoRandomU32 (&Random);
31 if (EFI_ERROR (Status)) {
32 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
33 return Status;
34 }
35
36 Random = (Random / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
37 Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
38 IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
39
40 return EFI_SUCCESS;
41}
42
57 IN IP6_PROTOCOL *IpInstance,
58 OUT UINT32 *NeighborCount,
59 OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache
60 )
61{
62 IP6_NEIGHBOR_ENTRY *Neighbor;
63 LIST_ENTRY *Entry;
64 IP6_SERVICE *IpSb;
65 UINT32 Count;
66 EFI_IP6_NEIGHBOR_CACHE *EfiNeighborCache;
67 EFI_IP6_NEIGHBOR_CACHE *NeighborCacheTmp;
68
69 NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
70 ASSERT (NeighborCount != NULL && NeighborCache != NULL);
71
72 IpSb = IpInstance->Service;
73 Count = 0;
74
75 NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
76 Count++;
77 }
78
79 if (Count == 0) {
80 return EFI_SUCCESS;
81 }
82
83 NeighborCacheTmp = AllocatePool (Count * sizeof (EFI_IP6_NEIGHBOR_CACHE));
84 if (NeighborCacheTmp == NULL) {
85 return EFI_OUT_OF_RESOURCES;
86 }
87
88 *NeighborCount = Count;
89 Count = 0;
90
91 NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
92 Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
93
94 EfiNeighborCache = NeighborCacheTmp + Count;
95
96 EfiNeighborCache->State = Neighbor->State;
97 IP6_COPY_ADDRESS (&EfiNeighborCache->Neighbor, &Neighbor->Neighbor);
98 IP6_COPY_LINK_ADDRESS (&EfiNeighborCache->LinkAddress, &Neighbor->LinkAddress);
99
100 Count++;
101 }
102
103 ASSERT (*NeighborCount == Count);
104 *NeighborCache = NeighborCacheTmp;
105
106 return EFI_SUCCESS;
107}
108
123 IN IP6_PROTOCOL *IpInstance,
124 OUT UINT32 *PrefixCount,
125 OUT EFI_IP6_ADDRESS_INFO **PrefixTable
126 )
127{
128 LIST_ENTRY *Entry;
129 IP6_SERVICE *IpSb;
130 UINT32 Count;
131 IP6_PREFIX_LIST_ENTRY *PrefixList;
132 EFI_IP6_ADDRESS_INFO *EfiPrefix;
133 EFI_IP6_ADDRESS_INFO *PrefixTableTmp;
134
135 NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
136 ASSERT (PrefixCount != NULL && PrefixTable != NULL);
137
138 IpSb = IpInstance->Service;
139 Count = 0;
140
141 NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
142 Count++;
143 }
144
145 if (Count == 0) {
146 return EFI_SUCCESS;
147 }
148
149 PrefixTableTmp = AllocatePool (Count * sizeof (EFI_IP6_ADDRESS_INFO));
150 if (PrefixTableTmp == NULL) {
151 return EFI_OUT_OF_RESOURCES;
152 }
153
154 *PrefixCount = Count;
155 Count = 0;
156
157 NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
158 PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
159 EfiPrefix = PrefixTableTmp + Count;
160 IP6_COPY_ADDRESS (&EfiPrefix->Address, &PrefixList->Prefix);
161 EfiPrefix->PrefixLength = PrefixList->PrefixLength;
162
163 Count++;
164 }
165
166 ASSERT (*PrefixCount == Count);
167 *PrefixTable = PrefixTableTmp;
168
169 return EFI_SUCCESS;
170}
171
192 IN IP6_SERVICE *IpSb,
193 IN BOOLEAN OnLinkOrAuto,
194 IN UINT32 ValidLifetime,
195 IN UINT32 PreferredLifetime,
196 IN UINT8 PrefixLength,
197 IN EFI_IPv6_ADDRESS *Prefix
198 )
199{
200 IP6_PREFIX_LIST_ENTRY *PrefixEntry;
201 IP6_ROUTE_ENTRY *RtEntry;
202 LIST_ENTRY *ListHead;
203 LIST_ENTRY *Entry;
204 IP6_PREFIX_LIST_ENTRY *TmpPrefixEntry;
205
206 if ((Prefix == NULL) || (PreferredLifetime > ValidLifetime) || (PrefixLength > IP6_PREFIX_MAX)) {
207 return NULL;
208 }
209
210 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
211
212 PrefixEntry = Ip6FindPrefixListEntry (
213 IpSb,
214 OnLinkOrAuto,
215 PrefixLength,
216 Prefix
217 );
218 if (PrefixEntry != NULL) {
219 PrefixEntry->RefCnt++;
220 return PrefixEntry;
221 }
222
223 PrefixEntry = AllocatePool (sizeof (IP6_PREFIX_LIST_ENTRY));
224 if (PrefixEntry == NULL) {
225 return NULL;
226 }
227
228 PrefixEntry->RefCnt = 1;
229 PrefixEntry->ValidLifetime = ValidLifetime;
230 PrefixEntry->PreferredLifetime = PreferredLifetime;
231 PrefixEntry->PrefixLength = PrefixLength;
232 IP6_COPY_ADDRESS (&PrefixEntry->Prefix, Prefix);
233
234 ListHead = OnLinkOrAuto ? &IpSb->OnlinkPrefix : &IpSb->AutonomousPrefix;
235
236 //
237 // Create a direct route entry for on-link prefix and insert to route area.
238 //
239 if (OnLinkOrAuto) {
240 RtEntry = Ip6CreateRouteEntry (Prefix, PrefixLength, NULL);
241 if (RtEntry == NULL) {
242 FreePool (PrefixEntry);
243 return NULL;
244 }
245
246 RtEntry->Flag = IP6_DIRECT_ROUTE;
247 InsertHeadList (&IpSb->RouteTable->RouteArea[PrefixLength], &RtEntry->Link);
248 IpSb->RouteTable->TotalNum++;
249 }
250
251 //
252 // Insert the prefix entry in the order that a prefix with longer prefix length
253 // is put ahead in the list.
254 //
255 NET_LIST_FOR_EACH (Entry, ListHead) {
256 TmpPrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
257
258 if (TmpPrefixEntry->PrefixLength < PrefixEntry->PrefixLength) {
259 break;
260 }
261 }
262
263 NetListInsertBefore (Entry, &PrefixEntry->Link);
264
265 return PrefixEntry;
266}
267
280VOID
282 IN IP6_SERVICE *IpSb,
283 IN IP6_PREFIX_LIST_ENTRY *PrefixEntry,
284 IN BOOLEAN OnLinkOrAuto,
285 IN BOOLEAN ImmediateDelete
286 )
287{
288 LIST_ENTRY *Entry;
289 IP6_INTERFACE *IpIf;
290 EFI_STATUS Status;
291
292 if ((!ImmediateDelete) && (PrefixEntry->RefCnt > 0) && ((--PrefixEntry->RefCnt) > 0)) {
293 return;
294 }
295
296 if (OnLinkOrAuto) {
297 //
298 // Remove the direct route for onlink prefix from route table.
299 //
300 do {
301 Status = Ip6DelRoute (
302 IpSb->RouteTable,
303 &PrefixEntry->Prefix,
304 PrefixEntry->PrefixLength,
305 NULL
306 );
307 } while (Status != EFI_NOT_FOUND);
308 } else {
309 //
310 // Remove the corresponding addresses generated from this autonomous prefix.
311 //
312 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
313 IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
314
315 Ip6RemoveAddr (IpSb, &IpIf->AddressList, &IpIf->AddressCount, &PrefixEntry->Prefix, PrefixEntry->PrefixLength);
316 }
317 }
318
319 RemoveEntryList (&PrefixEntry->Link);
320 FreePool (PrefixEntry);
321}
322
338 IN IP6_SERVICE *IpSb,
339 IN BOOLEAN OnLinkOrAuto,
340 IN UINT8 PrefixLength,
341 IN EFI_IPv6_ADDRESS *Prefix
342 )
343{
344 IP6_PREFIX_LIST_ENTRY *PrefixList;
345 LIST_ENTRY *Entry;
346 LIST_ENTRY *ListHead;
347
348 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
349 ASSERT (Prefix != NULL);
350
351 if (OnLinkOrAuto) {
352 ListHead = &IpSb->OnlinkPrefix;
353 } else {
354 ListHead = &IpSb->AutonomousPrefix;
355 }
356
357 NET_LIST_FOR_EACH (Entry, ListHead) {
358 PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
359 if (PrefixLength != 255) {
360 //
361 // Perform exactly prefix match.
362 //
363 if ((PrefixList->PrefixLength == PrefixLength) &&
364 NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixLength))
365 {
366 return PrefixList;
367 }
368 } else {
369 //
370 // Perform the longest prefix match. The list is already sorted with
371 // the longest length prefix put at the head of the list.
372 //
373 if (NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixList->PrefixLength)) {
374 return PrefixList;
375 }
376 }
377 }
378
379 return NULL;
380}
381
390VOID
392 IN IP6_SERVICE *IpSb,
393 IN LIST_ENTRY *ListHead
394 )
395{
396 IP6_PREFIX_LIST_ENTRY *PrefixList;
397 BOOLEAN OnLink;
398
399 OnLink = (BOOLEAN)(ListHead == &IpSb->OnlinkPrefix);
400
401 while (!IsListEmpty (ListHead)) {
402 PrefixList = NET_LIST_HEAD (ListHead, IP6_PREFIX_LIST_ENTRY, Link);
403 Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
404 }
405}
406
415VOID
417 IN VOID *Context
418 )
419{
420 LIST_ENTRY *Entry;
421 LIST_ENTRY *Next;
422 IP6_NEIGHBOR_ENTRY *ArpQue;
423 IP6_SERVICE *IpSb;
424 IP6_LINK_TX_TOKEN *Token;
425 EFI_STATUS Status;
426 BOOLEAN Sent;
427
428 ArpQue = (IP6_NEIGHBOR_ENTRY *)Context;
429 if ((ArpQue == NULL) || (ArpQue->Interface == NULL)) {
430 return;
431 }
432
433 IpSb = ArpQue->Interface->Service;
434 if ((IpSb == NULL) || (IpSb->Signature != IP6_SERVICE_SIGNATURE)) {
435 return;
436 }
437
438 //
439 // ARP resolve failed for some reason. Release all the frame
440 // and ARP queue itself. Ip6FreeArpQue will call the frame's
441 // owner back.
442 //
443 if (NET_MAC_EQUAL (&ArpQue->LinkAddress, &mZeroMacAddress, IpSb->SnpMode.HwAddressSize)) {
444 Ip6FreeNeighborEntry (IpSb, ArpQue, FALSE, TRUE, EFI_NO_MAPPING, NULL, NULL);
445 return;
446 }
447
448 //
449 // ARP resolve succeeded, Transmit all the frame.
450 //
451 Sent = FALSE;
452 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
453 RemoveEntryList (Entry);
454
455 Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
456 IP6_COPY_LINK_ADDRESS (&Token->DstMac, &ArpQue->LinkAddress);
457
458 //
459 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
460 // may be called before Mnp->Transmit returns which will remove this tx
461 // token from the SentFrames list. Remove it from the list if the returned
462 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
463 // FrameSentDpc won't be queued.
464 //
465 InsertTailList (&ArpQue->Interface->SentFrames, &Token->Link);
466
467 Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
468 if (EFI_ERROR (Status)) {
469 RemoveEntryList (&Token->Link);
470 Token->CallBack (Token->Packet, Status, 0, Token->Context);
471
472 Ip6FreeLinkTxToken (Token);
473 continue;
474 } else {
475 Sent = TRUE;
476 }
477 }
478
479 //
480 // Free the ArpQue only but not the whole neighbor entry.
481 //
483
484 if (Sent && (ArpQue->State == EfiNeighborStale)) {
485 ArpQue->State = EfiNeighborDelay;
486 ArpQue->Ticks = (UINT32)IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
487 }
488}
489
506 IN IP6_SERVICE *IpSb,
507 IN IP6_ARP_CALLBACK CallBack,
508 IN EFI_IPv6_ADDRESS *Ip6Address,
509 IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL
510 )
511{
512 IP6_NEIGHBOR_ENTRY *Entry;
513 IP6_DEFAULT_ROUTER *DefaultRouter;
514
515 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
516 ASSERT (Ip6Address != NULL);
517
518 Entry = AllocateZeroPool (sizeof (IP6_NEIGHBOR_ENTRY));
519 if (Entry == NULL) {
520 return NULL;
521 }
522
523 Entry->RefCnt = 1;
524 Entry->IsRouter = FALSE;
525 Entry->ArpFree = FALSE;
526 Entry->Dynamic = FALSE;
527 Entry->State = EfiNeighborInComplete;
528 Entry->Transmit = IP6_MAX_MULTICAST_SOLICIT + 1;
529 Entry->CallBack = CallBack;
530 Entry->Interface = NULL;
531
532 InitializeListHead (&Entry->Frames);
533
534 IP6_COPY_ADDRESS (&Entry->Neighbor, Ip6Address);
535
536 if (LinkAddress != NULL) {
537 IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, LinkAddress);
538 } else {
539 IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, &mZeroMacAddress);
540 }
541
542 InsertHeadList (&IpSb->NeighborTable, &Entry->Link);
543
544 //
545 // If corresponding default router entry exists, establish the relationship.
546 //
547 DefaultRouter = Ip6FindDefaultRouter (IpSb, Ip6Address);
548 if (DefaultRouter != NULL) {
549 DefaultRouter->NeighborCache = Entry;
550 }
551
552 return Entry;
553}
554
567 IN IP6_SERVICE *IpSb,
568 IN EFI_IPv6_ADDRESS *Ip6Address
569 )
570{
571 LIST_ENTRY *Entry;
572 LIST_ENTRY *Next;
573 IP6_NEIGHBOR_ENTRY *Neighbor;
574
575 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
576 ASSERT (Ip6Address != NULL);
577
578 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
579 Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
580 if (EFI_IP6_EQUAL (Ip6Address, &Neighbor->Neighbor)) {
581 RemoveEntryList (Entry);
582 InsertHeadList (&IpSb->NeighborTable, Entry);
583
584 return Neighbor;
585 }
586 }
587
588 return NULL;
589}
590
614 IN IP6_SERVICE *IpSb,
615 IN IP6_NEIGHBOR_ENTRY *NeighborCache,
616 IN BOOLEAN SendIcmpError,
617 IN BOOLEAN FullFree,
618 IN EFI_STATUS IoStatus,
619 IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
620 IN VOID *Context OPTIONAL
621 )
622{
623 IP6_LINK_TX_TOKEN *TxToken;
624 LIST_ENTRY *Entry;
625 LIST_ENTRY *Next;
626 IP6_DEFAULT_ROUTER *DefaultRouter;
627
628 //
629 // If FrameToCancel fails, the token will not be released.
630 // To avoid the memory leak, stop this usage model.
631 //
632 if (FullFree && (FrameToCancel != NULL)) {
633 return EFI_INVALID_PARAMETER;
634 }
635
636 NET_LIST_FOR_EACH_SAFE (Entry, Next, &NeighborCache->Frames) {
637 TxToken = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
638
639 if (SendIcmpError && !IP6_IS_MULTICAST (&TxToken->Packet->Ip.Ip6->DestinationAddress)) {
641 IpSb,
642 TxToken->Packet,
643 NULL,
644 &TxToken->Packet->Ip.Ip6->SourceAddress,
646 ICMP_V6_ADDR_UNREACHABLE,
647 NULL
648 );
649 }
650
651 if ((FrameToCancel == NULL) || FrameToCancel (TxToken, Context)) {
652 RemoveEntryList (Entry);
653 TxToken->CallBack (TxToken->Packet, IoStatus, 0, TxToken->Context);
654 Ip6FreeLinkTxToken (TxToken);
655 }
656 }
657
658 if (NeighborCache->ArpFree && IsListEmpty (&NeighborCache->Frames)) {
659 RemoveEntryList (&NeighborCache->ArpList);
660 NeighborCache->ArpFree = FALSE;
661 }
662
663 if (FullFree) {
664 if (NeighborCache->IsRouter) {
665 DefaultRouter = Ip6FindDefaultRouter (IpSb, &NeighborCache->Neighbor);
666 if (DefaultRouter != NULL) {
667 Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
668 }
669 }
670
671 RemoveEntryList (&NeighborCache->Link);
672 FreePool (NeighborCache);
673 }
674
675 return EFI_SUCCESS;
676}
677
692 IN IP6_SERVICE *IpSb,
693 IN EFI_IPv6_ADDRESS *Ip6Address,
694 IN UINT16 RouterLifetime
695 )
696{
697 IP6_DEFAULT_ROUTER *Entry;
698 IP6_ROUTE_ENTRY *RtEntry;
699
700 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
701 ASSERT (Ip6Address != NULL);
702
703 Entry = AllocatePool (sizeof (IP6_DEFAULT_ROUTER));
704 if (Entry == NULL) {
705 return NULL;
706 }
707
708 Entry->RefCnt = 1;
709 Entry->Lifetime = RouterLifetime;
710 Entry->NeighborCache = Ip6FindNeighborEntry (IpSb, Ip6Address);
711 IP6_COPY_ADDRESS (&Entry->Router, Ip6Address);
712
713 //
714 // Add a default route into route table with both Destination and PrefixLength set to zero.
715 //
716 RtEntry = Ip6CreateRouteEntry (NULL, 0, Ip6Address);
717 if (RtEntry == NULL) {
718 FreePool (Entry);
719 return NULL;
720 }
721
722 InsertHeadList (&IpSb->RouteTable->RouteArea[0], &RtEntry->Link);
723 IpSb->RouteTable->TotalNum++;
724
725 InsertTailList (&IpSb->DefaultRouterList, &Entry->Link);
726
727 return Entry;
728}
729
737VOID
739 IN IP6_SERVICE *IpSb,
740 IN IP6_DEFAULT_ROUTER *DefaultRouter
741 )
742{
743 EFI_STATUS Status;
744
745 RemoveEntryList (&DefaultRouter->Link);
746
747 //
748 // Update the Destination Cache - all entries using the time-out router as next-hop
749 // should perform next-hop determination again.
750 //
751 do {
752 Status = Ip6DelRoute (IpSb->RouteTable, NULL, 0, &DefaultRouter->Router);
753 } while (Status != EFI_NOT_FOUND);
754
755 FreePool (DefaultRouter);
756}
757
764VOID
766 IN IP6_SERVICE *IpSb
767 )
768{
769 IP6_DEFAULT_ROUTER *DefaultRouter;
770
771 while (!IsListEmpty (&IpSb->DefaultRouterList)) {
772 DefaultRouter = NET_LIST_HEAD (&IpSb->DefaultRouterList, IP6_DEFAULT_ROUTER, Link);
773 Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
774 }
775}
776
789 IN IP6_SERVICE *IpSb,
790 IN EFI_IPv6_ADDRESS *Ip6Address
791 )
792{
793 LIST_ENTRY *Entry;
794 IP6_DEFAULT_ROUTER *DefaultRouter;
795
796 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
797 ASSERT (Ip6Address != NULL);
798
799 NET_LIST_FOR_EACH (Entry, &IpSb->DefaultRouterList) {
800 DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
801 if (EFI_IP6_EQUAL (Ip6Address, &DefaultRouter->Router)) {
802 return DefaultRouter;
803 }
804 }
805
806 return NULL;
807}
808
817VOID
819 IN BOOLEAN IsDadPassed,
820 IN IP6_INTERFACE *IpIf,
821 IN IP6_DAD_ENTRY *DadEntry
822 )
823{
824 IP6_SERVICE *IpSb;
825 IP6_ADDRESS_INFO *AddrInfo;
826 EFI_DHCP6_PROTOCOL *Dhcp6;
827 UINT16 OptBuf[4];
829 EFI_DHCP6_RETRANSMISSION InfoReqReXmit;
830 EFI_IPv6_ADDRESS AllNodes;
831
832 IpSb = IpIf->Service;
833 AddrInfo = DadEntry->AddressInfo;
834
835 if (IsDadPassed) {
836 //
837 // DAD succeed.
838 //
839 if (NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
840 ASSERT (!IpSb->LinkLocalOk);
841
842 IP6_COPY_ADDRESS (&IpSb->LinkLocalAddr, &AddrInfo->Address);
843 IpSb->LinkLocalOk = TRUE;
844 IpIf->Configured = TRUE;
845
846 //
847 // Check whether DHCP6 need to be started.
848 //
849 Dhcp6 = IpSb->Ip6ConfigInstance.Dhcp6;
850
851 if (IpSb->Dhcp6NeedStart) {
852 Dhcp6->Start (Dhcp6);
853 IpSb->Dhcp6NeedStart = FALSE;
854 }
855
856 if (IpSb->Dhcp6NeedInfoRequest) {
857 //
858 // Set the exta options to send. Here we only want the option request option
859 // with DNS SERVERS.
860 //
861 Oro = (EFI_DHCP6_PACKET_OPTION *)OptBuf;
862 Oro->OpCode = HTONS (DHCP6_OPT_ORO);
863 Oro->OpLen = HTONS (2);
864 *((UINT16 *)&Oro->Data[0]) = HTONS (DHCP6_OPT_DNS_SERVERS);
865
866 InfoReqReXmit.Irt = 4;
867 InfoReqReXmit.Mrc = 64;
868 InfoReqReXmit.Mrt = 60;
869 InfoReqReXmit.Mrd = 0;
870
871 Dhcp6->InfoRequest (
872 Dhcp6,
873 TRUE,
874 Oro,
875 0,
876 NULL,
877 &InfoReqReXmit,
878 IpSb->Ip6ConfigInstance.Dhcp6Event,
880 &IpSb->Ip6ConfigInstance
881 );
882 }
883
884 //
885 // Add an on-link prefix for link-local address.
886 //
888 IpSb,
889 TRUE,
890 (UINT32)IP6_INFINIT_LIFETIME,
891 (UINT32)IP6_INFINIT_LIFETIME,
892 IP6_LINK_LOCAL_PREFIX_LENGTH,
893 &IpSb->LinkLocalAddr
894 );
895 } else {
896 //
897 // Global scope unicast address.
898 //
899 Ip6AddAddr (IpIf, AddrInfo);
900
901 //
902 // Add an on-link prefix for this address.
903 //
905 IpSb,
906 TRUE,
907 AddrInfo->ValidLifetime,
908 AddrInfo->PreferredLifetime,
909 AddrInfo->PrefixLength,
910 &AddrInfo->Address
911 );
912
913 IpIf->Configured = TRUE;
914 }
915 } else {
916 //
917 // Leave the group we joined before.
918 //
919 Ip6LeaveGroup (IpSb, &DadEntry->Destination);
920 }
921
922 if (DadEntry->Callback != NULL) {
923 DadEntry->Callback (IsDadPassed, &AddrInfo->Address, DadEntry->Context);
924 }
925
926 if (!IsDadPassed && NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
927 FreePool (AddrInfo);
928 RemoveEntryList (&DadEntry->Link);
929 FreePool (DadEntry);
930 //
931 // Leave link-scope all-nodes multicast address (FF02::1)
932 //
933 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
934 Ip6LeaveGroup (IpSb, &AllNodes);
935 //
936 // Disable IP operation since link-local address is a duplicate address.
937 //
938 IpSb->LinkLocalDadFail = TRUE;
939 IpSb->Mnp->Configure (IpSb->Mnp, NULL);
940 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
941 gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
942 return;
943 }
944
945 if (!IsDadPassed || NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
946 //
947 // Free the AddressInfo we hold if DAD fails or it is a link-local address.
948 //
949 FreePool (AddrInfo);
950 }
951
952 RemoveEntryList (&DadEntry->Link);
953 FreePool (DadEntry);
954}
955
975 IN IP6_INTERFACE *IpIf,
976 IN IP6_ADDRESS_INFO *AddressInfo,
977 IN IP6_DAD_CALLBACK Callback OPTIONAL,
978 IN VOID *Context OPTIONAL
979 )
980{
981 IP6_DAD_ENTRY *Entry;
983 IP6_SERVICE *IpSb;
984 EFI_STATUS Status;
985 UINT32 MaxDelayTick;
986 UINT32 Random;
987
988 NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
989 ASSERT (AddressInfo != NULL);
990
991 Status = PseudoRandomU32 (&Random);
992 if (EFI_ERROR (Status)) {
993 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
994 return Status;
995 }
996
997 //
998 // Do nothing if we have already started DAD on the address.
999 //
1000 if (Ip6FindDADEntry (IpIf->Service, &AddressInfo->Address, NULL) != NULL) {
1001 return EFI_SUCCESS;
1002 }
1003
1004 Status = EFI_SUCCESS;
1005 IpSb = IpIf->Service;
1006 DadXmits = &IpSb->Ip6ConfigInstance.DadXmits;
1007
1008 //
1009 // Allocate the resources and insert info
1010 //
1011 Entry = AllocatePool (sizeof (IP6_DAD_ENTRY));
1012 if (Entry == NULL) {
1013 return EFI_OUT_OF_RESOURCES;
1014 }
1015
1016 //
1017 // Map the incoming unicast address to solicited-node multicast address
1018 //
1019 Ip6CreateSNMulticastAddr (&AddressInfo->Address, &Entry->Destination);
1020
1021 //
1022 // Join in the solicited-node multicast address.
1023 //
1024 Status = Ip6JoinGroup (IpSb, IpIf, &Entry->Destination);
1025 if (EFI_ERROR (Status)) {
1026 FreePool (Entry);
1027 return Status;
1028 }
1029
1030 Entry->Signature = IP6_DAD_ENTRY_SIGNATURE;
1031 Entry->MaxTransmit = DadXmits->DupAddrDetectTransmits;
1032 Entry->Transmit = 0;
1033 Entry->Receive = 0;
1034 MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
1035 Entry->RetransTick = (MaxDelayTick * ((Random % 5) + 1)) / 5;
1036 Entry->AddressInfo = AddressInfo;
1037 Entry->Callback = Callback;
1038 Entry->Context = Context;
1039 InsertTailList (&IpIf->DupAddrDetectList, &Entry->Link);
1040
1041 if (Entry->MaxTransmit == 0) {
1042 //
1043 // DAD is disabled on this interface, immediately mark this DAD successful.
1044 //
1045 Ip6OnDADFinished (TRUE, IpIf, Entry);
1046 }
1047
1048 return EFI_SUCCESS;
1049}
1050
1065 IN IP6_SERVICE *IpSb,
1066 IN EFI_IPv6_ADDRESS *Target,
1067 OUT IP6_INTERFACE **Interface OPTIONAL
1068 )
1069{
1070 LIST_ENTRY *Entry;
1071 LIST_ENTRY *Entry2;
1072 IP6_INTERFACE *IpIf;
1073 IP6_DAD_ENTRY *DupAddrDetect;
1074 IP6_ADDRESS_INFO *AddrInfo;
1075
1076 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
1077 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
1078
1079 NET_LIST_FOR_EACH (Entry2, &IpIf->DupAddrDetectList) {
1080 DupAddrDetect = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
1081 AddrInfo = DupAddrDetect->AddressInfo;
1082 if (EFI_IP6_EQUAL (&AddrInfo->Address, Target)) {
1083 if (Interface != NULL) {
1084 *Interface = IpIf;
1085 }
1086
1087 return DupAddrDetect;
1088 }
1089 }
1090 }
1091
1092 return NULL;
1093}
1094
1115 IN IP6_SERVICE *IpSb,
1116 IN IP6_INTERFACE *Interface OPTIONAL,
1117 IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
1118 IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL,
1119 IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
1120 )
1121{
1122 NET_BUF *Packet;
1123 EFI_IP6_HEADER Head;
1124 IP6_ICMP_INFORMATION_HEAD *IcmpHead;
1125 IP6_ETHER_ADDR_OPTION *LinkLayerOption;
1126 UINT16 PayloadLen;
1127 IP6_INTERFACE *IpIf;
1128
1129 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
1130
1131 IpIf = Interface;
1132 if ((IpIf == NULL) && (IpSb->DefaultInterface != NULL)) {
1133 IpIf = IpSb->DefaultInterface;
1134 }
1135
1136 //
1137 // Generate the packet to be sent
1138 //
1139
1140 PayloadLen = (UINT16)sizeof (IP6_ICMP_INFORMATION_HEAD);
1141 if (SourceLinkAddress != NULL) {
1142 PayloadLen += sizeof (IP6_ETHER_ADDR_OPTION);
1143 }
1144
1145 Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
1146 if (Packet == NULL) {
1147 return EFI_OUT_OF_RESOURCES;
1148 }
1149
1150 //
1151 // Create the basic IPv6 header.
1152 //
1153 Head.FlowLabelL = 0;
1154 Head.FlowLabelH = 0;
1155 Head.PayloadLength = HTONS (PayloadLen);
1156 Head.NextHeader = IP6_ICMP;
1157 Head.HopLimit = IP6_HOP_LIMIT;
1158
1159 if (SourceAddress != NULL) {
1160 IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
1161 } else {
1162 ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
1163 }
1164
1165 if (DestinationAddress != NULL) {
1166 IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
1167 } else {
1168 Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Head.DestinationAddress);
1169 }
1170
1171 NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
1172
1173 //
1174 // Fill in the ICMP header, and Source link-layer address if contained.
1175 //
1176
1178 ASSERT (IcmpHead != NULL);
1179 ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
1180 IcmpHead->Head.Type = ICMP_V6_ROUTER_SOLICIT;
1181 IcmpHead->Head.Code = 0;
1182
1183 LinkLayerOption = NULL;
1184 if (SourceLinkAddress != NULL) {
1185 LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
1186 Packet,
1187 sizeof (IP6_ETHER_ADDR_OPTION),
1188 FALSE
1189 );
1190 ASSERT (LinkLayerOption != NULL);
1191 LinkLayerOption->Type = Ip6OptionEtherSource;
1192 LinkLayerOption->Length = (UINT8)sizeof (IP6_ETHER_ADDR_OPTION);
1193 CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
1194 }
1195
1196 //
1197 // Transmit the packet
1198 //
1199 return Ip6Output (IpSb, IpIf, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
1200}
1201
1226 IN IP6_SERVICE *IpSb,
1227 IN EFI_IPv6_ADDRESS *SourceAddress,
1228 IN EFI_IPv6_ADDRESS *DestinationAddress,
1229 IN EFI_IPv6_ADDRESS *TargetIp6Address,
1230 IN EFI_MAC_ADDRESS *TargetLinkAddress,
1231 IN BOOLEAN IsRouter,
1232 IN BOOLEAN Override,
1233 IN BOOLEAN Solicited
1234 )
1235{
1236 NET_BUF *Packet;
1237 EFI_IP6_HEADER Head;
1238 IP6_ICMP_INFORMATION_HEAD *IcmpHead;
1239 IP6_ETHER_ADDR_OPTION *LinkLayerOption;
1240 EFI_IPv6_ADDRESS *Target;
1241 UINT16 PayloadLen;
1242
1243 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
1244
1245 //
1246 // The Neighbor Advertisement message must include a Target link-layer address option
1247 // when responding to multicast solicitation and should include such option when
1248 // responding to unicast solicitation. It also must include such option as unsolicited
1249 // advertisement.
1250 //
1251 ASSERT (DestinationAddress != NULL && TargetIp6Address != NULL && TargetLinkAddress != NULL);
1252
1253 PayloadLen = (UINT16)(sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS) + sizeof (IP6_ETHER_ADDR_OPTION));
1254
1255 //
1256 // Generate the packet to be sent
1257 //
1258
1259 Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
1260 if (Packet == NULL) {
1261 return EFI_OUT_OF_RESOURCES;
1262 }
1263
1264 //
1265 // Create the basic IPv6 header.
1266 //
1267 Head.FlowLabelL = 0;
1268 Head.FlowLabelH = 0;
1269 Head.PayloadLength = HTONS (PayloadLen);
1270 Head.NextHeader = IP6_ICMP;
1271 Head.HopLimit = IP6_HOP_LIMIT;
1272
1273 IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
1274 IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
1275
1276 NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
1277
1278 //
1279 // Fill in the ICMP header, Target address, and Target link-layer address.
1280 // Set the Router flag, Solicited flag and Override flag.
1281 //
1282
1284 ASSERT (IcmpHead != NULL);
1285 ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
1286 IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_ADVERTISE;
1287 IcmpHead->Head.Code = 0;
1288
1289 if (IsRouter) {
1290 IcmpHead->Fourth |= IP6_IS_ROUTER_FLAG;
1291 }
1292
1293 if (Solicited) {
1294 IcmpHead->Fourth |= IP6_SOLICITED_FLAG;
1295 }
1296
1297 if (Override) {
1298 IcmpHead->Fourth |= IP6_OVERRIDE_FLAG;
1299 }
1300
1301 Target = (EFI_IPv6_ADDRESS *)NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
1302 ASSERT (Target != NULL);
1303 IP6_COPY_ADDRESS (Target, TargetIp6Address);
1304
1305 LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
1306 Packet,
1307 sizeof (IP6_ETHER_ADDR_OPTION),
1308 FALSE
1309 );
1310 ASSERT (LinkLayerOption != NULL);
1311 LinkLayerOption->Type = Ip6OptionEtherTarget;
1312 LinkLayerOption->Length = 1;
1313 CopyMem (LinkLayerOption->EtherAddr, TargetLinkAddress, 6);
1314
1315 //
1316 // Transmit the packet
1317 //
1318 return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
1319}
1320
1341 IN IP6_SERVICE *IpSb,
1342 IN EFI_IPv6_ADDRESS *SourceAddress,
1343 IN EFI_IPv6_ADDRESS *DestinationAddress,
1344 IN EFI_IPv6_ADDRESS *TargetIp6Address,
1345 IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
1346 )
1347{
1348 NET_BUF *Packet;
1349 EFI_IP6_HEADER Head;
1350 IP6_ICMP_INFORMATION_HEAD *IcmpHead;
1351 IP6_ETHER_ADDR_OPTION *LinkLayerOption;
1352 EFI_IPv6_ADDRESS *Target;
1353 BOOLEAN IsDAD;
1354 UINT16 PayloadLen;
1355 IP6_NEIGHBOR_ENTRY *Neighbor;
1356
1357 //
1358 // Check input parameters
1359 //
1360 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
1361 if ((DestinationAddress == NULL) || (TargetIp6Address == NULL)) {
1362 return EFI_INVALID_PARAMETER;
1363 }
1364
1365 IsDAD = FALSE;
1366
1367 if ((SourceAddress == NULL) || ((SourceAddress != NULL) && NetIp6IsUnspecifiedAddr (SourceAddress))) {
1368 IsDAD = TRUE;
1369 }
1370
1371 //
1372 // The Neighbor Solicitation message should include a source link-layer address option
1373 // if the solicitation is not sent by performing DAD - Duplicate Address Detection.
1374 // Otherwise must not include it.
1375 //
1376 PayloadLen = (UINT16)(sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS));
1377
1378 if (!IsDAD) {
1379 if (SourceLinkAddress == NULL) {
1380 return EFI_INVALID_PARAMETER;
1381 }
1382
1383 PayloadLen = (UINT16)(PayloadLen + sizeof (IP6_ETHER_ADDR_OPTION));
1384 }
1385
1386 //
1387 // Generate the packet to be sent
1388 //
1389
1390 Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
1391 if (Packet == NULL) {
1392 return EFI_OUT_OF_RESOURCES;
1393 }
1394
1395 //
1396 // Create the basic IPv6 header
1397 //
1398 Head.FlowLabelL = 0;
1399 Head.FlowLabelH = 0;
1400 Head.PayloadLength = HTONS (PayloadLen);
1401 Head.NextHeader = IP6_ICMP;
1402 Head.HopLimit = IP6_HOP_LIMIT;
1403
1404 if (SourceAddress != NULL) {
1405 IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
1406 } else {
1407 ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
1408 }
1409
1410 IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
1411
1412 NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
1413
1414 //
1415 // Fill in the ICMP header, Target address, and Source link-layer address.
1416 //
1418 ASSERT (IcmpHead != NULL);
1419 ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
1420 IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_SOLICIT;
1421 IcmpHead->Head.Code = 0;
1422
1423 Target = (EFI_IPv6_ADDRESS *)NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
1424 ASSERT (Target != NULL);
1425 IP6_COPY_ADDRESS (Target, TargetIp6Address);
1426
1427 LinkLayerOption = NULL;
1428 if (!IsDAD) {
1429 //
1430 // Fill in the source link-layer address option
1431 //
1432 LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)NetbufAllocSpace (
1433 Packet,
1434 sizeof (IP6_ETHER_ADDR_OPTION),
1435 FALSE
1436 );
1437 ASSERT (LinkLayerOption != NULL);
1438 LinkLayerOption->Type = Ip6OptionEtherSource;
1439 LinkLayerOption->Length = 1;
1440 CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
1441 }
1442
1443 //
1444 // Create a Neighbor Cache entry in the INCOMPLETE state when performing
1445 // address resolution.
1446 //
1447 if (!IsDAD && Ip6IsSNMulticastAddr (DestinationAddress)) {
1448 Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
1449 if (Neighbor == NULL) {
1450 Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, NULL);
1451 ASSERT (Neighbor != NULL);
1452 }
1453 }
1454
1455 //
1456 // Transmit the packet
1457 //
1458 return Ip6Output (IpSb, IpSb->DefaultInterface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
1459}
1460
1477 IN IP6_SERVICE *IpSb,
1478 IN EFI_IP6_HEADER *Head,
1479 IN NET_BUF *Packet
1480 )
1481{
1483 EFI_IPv6_ADDRESS Target;
1484 IP6_ETHER_ADDR_OPTION LinkLayerOption;
1485 BOOLEAN IsDAD;
1486 BOOLEAN IsUnicast;
1487 BOOLEAN IsMaintained;
1488 IP6_DAD_ENTRY *DupAddrDetect;
1489 IP6_INTERFACE *IpIf;
1490 IP6_NEIGHBOR_ENTRY *Neighbor;
1491 BOOLEAN Solicited;
1492 BOOLEAN UpdateCache;
1493 EFI_IPv6_ADDRESS Dest;
1494 UINT16 OptionLen;
1495 UINT8 *Option;
1496 BOOLEAN Provided;
1497 EFI_STATUS Status;
1498 VOID *MacAddress;
1499
1500 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
1501 NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
1502
1503 //
1504 // Perform Message Validation:
1505 // The IP Hop Limit field has a value of 255, i.e., the packet
1506 // could not possibly have been forwarded by a router.
1507 // ICMP Code is 0.
1508 // Target Address is not a multicast address.
1509 //
1510 Status = EFI_INVALID_PARAMETER;
1511
1512 if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) || !NetIp6IsValidUnicast (&Target)) {
1513 goto Exit;
1514 }
1515
1516 //
1517 // ICMP length is 24 or more octets.
1518 //
1519 OptionLen = 0;
1520 if (Head->PayloadLength < IP6_ND_LENGTH) {
1521 goto Exit;
1522 } else {
1523 OptionLen = (UINT16)(Head->PayloadLength - IP6_ND_LENGTH);
1524 if (OptionLen != 0) {
1525 Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
1526 ASSERT (Option != NULL);
1527
1528 //
1529 // All included options should have a length that is greater than zero.
1530 //
1531 if (!Ip6IsNDOptionValid (Option, OptionLen)) {
1532 goto Exit;
1533 }
1534 }
1535 }
1536
1537 IsDAD = NetIp6IsUnspecifiedAddr (&Head->SourceAddress);
1538 IsUnicast = (BOOLEAN) !Ip6IsSNMulticastAddr (&Head->DestinationAddress);
1539 IsMaintained = Ip6IsOneOfSetAddress (IpSb, &Target, &IpIf, NULL);
1540
1541 Provided = FALSE;
1542 if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
1543 NetbufCopy (
1544 Packet,
1545 IP6_ND_LENGTH,
1546 sizeof (IP6_ETHER_ADDR_OPTION),
1547 (UINT8 *)&LinkLayerOption
1548 );
1549 //
1550 // The solicitation for neighbor discovery should include a source link-layer
1551 // address option. If the option is not recognized, silently ignore it.
1552 //
1553 if (LinkLayerOption.Type == Ip6OptionEtherSource) {
1554 if (IsDAD) {
1555 //
1556 // If the IP source address is the unspecified address, the source
1557 // link-layer address option must not be included in the message.
1558 //
1559 goto Exit;
1560 }
1561
1562 Provided = TRUE;
1563 }
1564 }
1565
1566 //
1567 // If the IP source address is the unspecified address, the IP
1568 // destination address is a solicited-node multicast address.
1569 //
1570 if (IsDAD && IsUnicast) {
1571 goto Exit;
1572 }
1573
1574 //
1575 // If the target address is tentative, and the source address is a unicast address,
1576 // the solicitation's sender is performing address resolution on the target;
1577 // the solicitation should be silently ignored.
1578 //
1579 if (!IsDAD && !IsMaintained) {
1580 goto Exit;
1581 }
1582
1583 //
1584 // If received unicast neighbor solicitation but destination is not this node,
1585 // drop the packet.
1586 //
1587 if (IsUnicast && !IsMaintained) {
1588 goto Exit;
1589 }
1590
1591 //
1592 // In DAD, when target address is a tentative address,
1593 // process the received neighbor solicitation message but not send out response.
1594 //
1595 if (IsDAD && !IsMaintained) {
1596 DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
1597 if (DupAddrDetect != NULL) {
1598 //
1599 // Check the MAC address of the incoming packet.
1600 //
1601 if (IpSb->RecvRequest.MnpToken.Packet.RxData == NULL) {
1602 goto Exit;
1603 }
1604
1605 MacAddress = IpSb->RecvRequest.MnpToken.Packet.RxData->SourceAddress;
1606 if (MacAddress != NULL) {
1607 if (CompareMem (
1608 MacAddress,
1609 &IpSb->SnpMode.CurrentAddress,
1610 IpSb->SnpMode.HwAddressSize
1611 ) != 0)
1612 {
1613 //
1614 // The NS is from another node to performing DAD on the same address.
1615 // Fail DAD for the tentative address.
1616 //
1617 Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
1618 Status = EFI_ICMP_ERROR;
1619 } else {
1620 //
1621 // The below layer loopback the NS we sent. Record it and wait for more.
1622 //
1623 DupAddrDetect->Receive++;
1624 Status = EFI_SUCCESS;
1625 }
1626 }
1627 }
1628
1629 goto Exit;
1630 }
1631
1632 //
1633 // If the solicitation does not contain a link-layer address, DO NOT create or
1634 // update the neighbor cache entries.
1635 //
1636 if (Provided) {
1637 Neighbor = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
1638 UpdateCache = FALSE;
1639
1640 if (Neighbor == NULL) {
1641 Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &Head->SourceAddress, NULL);
1642 if (Neighbor == NULL) {
1643 Status = EFI_OUT_OF_RESOURCES;
1644 goto Exit;
1645 }
1646
1647 UpdateCache = TRUE;
1648 } else {
1649 if (CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6) != 0) {
1650 UpdateCache = TRUE;
1651 }
1652 }
1653
1654 if (UpdateCache) {
1655 Neighbor->State = EfiNeighborStale;
1656 Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
1657 CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
1658 //
1659 // Send queued packets if exist.
1660 //
1661 Neighbor->CallBack ((VOID *)Neighbor);
1662 }
1663 }
1664
1665 //
1666 // Sends a Neighbor Advertisement as response.
1667 // Set the Router flag to zero since the node is a host.
1668 // If the source address of the solicitation is unspecified, and target address
1669 // is one of the maintained address, reply a unsolicited multicast advertisement.
1670 //
1671 if (IsDAD && IsMaintained) {
1672 Solicited = FALSE;
1673 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &Dest);
1674 } else {
1675 Solicited = TRUE;
1676 IP6_COPY_ADDRESS (&Dest, &Head->SourceAddress);
1677 }
1678
1679 Status = Ip6SendNeighborAdvertise (
1680 IpSb,
1681 &Target,
1682 &Dest,
1683 &Target,
1684 &IpSb->SnpMode.CurrentAddress,
1685 FALSE,
1686 TRUE,
1687 Solicited
1688 );
1689Exit:
1690 NetbufFree (Packet);
1691 return Status;
1692}
1693
1709 IN IP6_SERVICE *IpSb,
1710 IN EFI_IP6_HEADER *Head,
1711 IN NET_BUF *Packet
1712 )
1713{
1715 EFI_IPv6_ADDRESS Target;
1716 IP6_ETHER_ADDR_OPTION LinkLayerOption;
1717 BOOLEAN Provided;
1718 INTN Compare;
1719 IP6_NEIGHBOR_ENTRY *Neighbor;
1720 IP6_DEFAULT_ROUTER *DefaultRouter;
1721 BOOLEAN Solicited;
1722 BOOLEAN IsRouter;
1723 BOOLEAN Override;
1724 IP6_DAD_ENTRY *DupAddrDetect;
1725 IP6_INTERFACE *IpIf;
1726 UINT16 OptionLen;
1727 UINT8 *Option;
1728 EFI_STATUS Status;
1729
1730 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
1731 NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
1732
1733 //
1734 // Validate the incoming Neighbor Advertisement
1735 //
1736 Status = EFI_INVALID_PARAMETER;
1737 //
1738 // The IP Hop Limit field has a value of 255, i.e., the packet
1739 // could not possibly have been forwarded by a router.
1740 // ICMP Code is 0.
1741 // Target Address is not a multicast address.
1742 //
1743 if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) || !NetIp6IsValidUnicast (&Target)) {
1744 goto Exit;
1745 }
1746
1747 //
1748 // ICMP length is 24 or more octets.
1749 //
1750 Provided = FALSE;
1751 OptionLen = 0;
1752 if (Head->PayloadLength < IP6_ND_LENGTH) {
1753 goto Exit;
1754 } else {
1755 OptionLen = (UINT16)(Head->PayloadLength - IP6_ND_LENGTH);
1756 if (OptionLen != 0) {
1757 Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
1758 ASSERT (Option != NULL);
1759
1760 //
1761 // All included options should have a length that is greater than zero.
1762 //
1763 if (!Ip6IsNDOptionValid (Option, OptionLen)) {
1764 goto Exit;
1765 }
1766 }
1767 }
1768
1769 //
1770 // If the IP destination address is a multicast address, Solicited Flag is ZERO.
1771 //
1772 Solicited = FALSE;
1773 if ((Icmp.Fourth & IP6_SOLICITED_FLAG) == IP6_SOLICITED_FLAG) {
1774 Solicited = TRUE;
1775 }
1776
1777 if (IP6_IS_MULTICAST (&Head->DestinationAddress) && Solicited) {
1778 goto Exit;
1779 }
1780
1781 //
1782 // DAD - Check whether the Target is one of our tentative address.
1783 //
1784 DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
1785 if (DupAddrDetect != NULL) {
1786 //
1787 // DAD fails, some other node is using this address.
1788 //
1789 NetbufFree (Packet);
1790 Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
1791 return EFI_ICMP_ERROR;
1792 }
1793
1794 //
1795 // Search the Neighbor Cache for the target's entry. If no entry exists,
1796 // the advertisement should be silently discarded.
1797 //
1798 Neighbor = Ip6FindNeighborEntry (IpSb, &Target);
1799 if (Neighbor == NULL) {
1800 goto Exit;
1801 }
1802
1803 //
1804 // Get IsRouter Flag and Override Flag
1805 //
1806 IsRouter = FALSE;
1807 Override = FALSE;
1808 if ((Icmp.Fourth & IP6_IS_ROUTER_FLAG) == IP6_IS_ROUTER_FLAG) {
1809 IsRouter = TRUE;
1810 }
1811
1812 if ((Icmp.Fourth & IP6_OVERRIDE_FLAG) == IP6_OVERRIDE_FLAG) {
1813 Override = TRUE;
1814 }
1815
1816 //
1817 // Check whether link layer option is included.
1818 //
1819 if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
1820 NetbufCopy (
1821 Packet,
1822 IP6_ND_LENGTH,
1823 sizeof (IP6_ETHER_ADDR_OPTION),
1824 (UINT8 *)&LinkLayerOption
1825 );
1826
1827 if (LinkLayerOption.Type == Ip6OptionEtherTarget) {
1828 Provided = TRUE;
1829 }
1830 }
1831
1832 Compare = 0;
1833 if (Provided) {
1834 Compare = CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
1835 }
1836
1837 if (!Neighbor->IsRouter && IsRouter) {
1838 DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
1839 if (DefaultRouter != NULL) {
1840 DefaultRouter->NeighborCache = Neighbor;
1841 }
1842 }
1843
1844 if (Neighbor->State == EfiNeighborInComplete) {
1845 //
1846 // If the target's Neighbor Cache entry is in INCOMPLETE state and no
1847 // Target Link-Layer address option is included while link layer has
1848 // address, the message should be silently discarded.
1849 //
1850 if (!Provided) {
1851 goto Exit;
1852 }
1853
1854 //
1855 // Update the Neighbor Cache
1856 //
1857 CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
1858 if (Solicited) {
1859 Neighbor->State = EfiNeighborReachable;
1860 Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
1861 } else {
1862 Neighbor->State = EfiNeighborStale;
1863 Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
1864 //
1865 // Send any packets queued for the neighbor awaiting address resolution.
1866 //
1867 Neighbor->CallBack ((VOID *)Neighbor);
1868 }
1869
1870 Neighbor->IsRouter = IsRouter;
1871 } else {
1872 if (!Override && (Compare != 0)) {
1873 //
1874 // When the Override Flag is clear and supplied link-layer address differs from
1875 // that in the cache, if the state of the entry is not REACHABLE, ignore the
1876 // message. Otherwise set it to STALE but do not update the entry in any
1877 // other way.
1878 //
1879 if (Neighbor->State == EfiNeighborReachable) {
1880 Neighbor->State = EfiNeighborStale;
1881 Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
1882 }
1883 } else {
1884 if (Compare != 0) {
1885 CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
1886 }
1887
1888 //
1889 // Update the entry's state
1890 //
1891 if (Solicited) {
1892 Neighbor->State = EfiNeighborReachable;
1893 Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
1894 } else {
1895 if (Compare != 0) {
1896 Neighbor->State = EfiNeighborStale;
1897 Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
1898 }
1899 }
1900
1901 //
1902 // When IsRouter is changed from TRUE to FALSE, remove the router from the
1903 // Default Router List and remove the Destination Cache entries for all destinations
1904 // using the neighbor as a router.
1905 //
1906 if (Neighbor->IsRouter && !IsRouter) {
1907 DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
1908 if (DefaultRouter != NULL) {
1909 Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
1910 }
1911 }
1912
1913 Neighbor->IsRouter = IsRouter;
1914 }
1915 }
1916
1917 if (Neighbor->State == EfiNeighborReachable) {
1918 Neighbor->CallBack ((VOID *)Neighbor);
1919 }
1920
1921 Status = EFI_SUCCESS;
1922
1923Exit:
1924 NetbufFree (Packet);
1925 return Status;
1926}
1927
1944 IN IP6_SERVICE *IpSb,
1945 IN EFI_IP6_HEADER *Head,
1946 IN NET_BUF *Packet
1947 )
1948{
1950 UINT32 ReachableTime;
1951 UINT32 RetransTimer;
1952 UINT16 RouterLifetime;
1953 UINT32 Offset;
1954 UINT8 Type;
1955 UINT8 Length;
1956 IP6_ETHER_ADDR_OPTION LinkLayerOption;
1957 UINT32 Fourth;
1958 UINT8 CurHopLimit;
1959 BOOLEAN Mflag;
1960 BOOLEAN Oflag;
1961 IP6_DEFAULT_ROUTER *DefaultRouter;
1962 IP6_NEIGHBOR_ENTRY *NeighborCache;
1963 EFI_MAC_ADDRESS LinkLayerAddress;
1964 IP6_MTU_OPTION MTUOption;
1965 IP6_PREFIX_INFO_OPTION PrefixOption;
1966 IP6_PREFIX_LIST_ENTRY *PrefixList;
1967 BOOLEAN OnLink;
1968 BOOLEAN Autonomous;
1969 EFI_IPv6_ADDRESS StatelessAddress;
1970 EFI_STATUS Status;
1971 UINT16 OptionLen;
1972 UINT8 *Option;
1973 INTN Result;
1974
1975 Status = EFI_INVALID_PARAMETER;
1976
1977 if (IpSb->Ip6ConfigInstance.Policy != Ip6ConfigPolicyAutomatic) {
1978 //
1979 // Skip the process below as it's not required under the current policy.
1980 //
1981 goto Exit;
1982 }
1983
1984 NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *)&Icmp);
1985
1986 //
1987 // Validate the incoming Router Advertisement
1988 //
1989
1990 //
1991 // The IP source address must be a link-local address
1992 //
1993 if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
1994 goto Exit;
1995 }
1996
1997 //
1998 // The IP Hop Limit field has a value of 255, i.e. the packet
1999 // could not possibly have been forwarded by a router.
2000 // ICMP Code is 0.
2001 // ICMP length (derived from the IP length) is 16 or more octets.
2002 //
2003 if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp.Head.Code != 0) ||
2004 (Head->PayloadLength < IP6_RA_LENGTH))
2005 {
2006 goto Exit;
2007 }
2008
2009 //
2010 // All included options have a length that is greater than zero.
2011 //
2012 OptionLen = (UINT16)(Head->PayloadLength - IP6_RA_LENGTH);
2013 if (OptionLen != 0) {
2014 Option = NetbufGetByte (Packet, IP6_RA_LENGTH, NULL);
2015 ASSERT (Option != NULL);
2016
2017 if (!Ip6IsNDOptionValid (Option, OptionLen)) {
2018 goto Exit;
2019 }
2020 }
2021
2022 //
2023 // Process Fourth field.
2024 // In Router Advertisement, Fourth is composed of CurHopLimit (8bit), M flag, O flag,
2025 // and Router Lifetime (16 bit).
2026 //
2027
2028 Fourth = NTOHL (Icmp.Fourth);
2029 CopyMem (&RouterLifetime, &Fourth, sizeof (UINT16));
2030
2031 //
2032 // If the source address already in the default router list, update it.
2033 // Otherwise create a new entry.
2034 // A Lifetime of zero indicates that the router is not a default router.
2035 //
2036 DefaultRouter = Ip6FindDefaultRouter (IpSb, &Head->SourceAddress);
2037 if (DefaultRouter == NULL) {
2038 if (RouterLifetime != 0) {
2039 DefaultRouter = Ip6CreateDefaultRouter (IpSb, &Head->SourceAddress, RouterLifetime);
2040 if (DefaultRouter == NULL) {
2041 Status = EFI_OUT_OF_RESOURCES;
2042 goto Exit;
2043 }
2044 }
2045 } else {
2046 if (RouterLifetime != 0) {
2047 DefaultRouter->Lifetime = RouterLifetime;
2048 //
2049 // Check the corresponding neighbor cache entry here.
2050 //
2051 if (DefaultRouter->NeighborCache == NULL) {
2052 DefaultRouter->NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
2053 }
2054 } else {
2055 //
2056 // If the address is in the host's default router list and the router lifetime is zero,
2057 // immediately time-out the entry.
2058 //
2059 Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
2060 }
2061 }
2062
2063 CurHopLimit = *((UINT8 *)&Fourth + 3);
2064 if (CurHopLimit != 0) {
2065 IpSb->CurHopLimit = CurHopLimit;
2066 }
2067
2068 Mflag = FALSE;
2069 Oflag = FALSE;
2070 if ((*((UINT8 *)&Fourth + 2) & IP6_M_ADDR_CONFIG_FLAG) == IP6_M_ADDR_CONFIG_FLAG) {
2071 Mflag = TRUE;
2072 } else {
2073 if ((*((UINT8 *)&Fourth + 2) & IP6_O_CONFIG_FLAG) == IP6_O_CONFIG_FLAG) {
2074 Oflag = TRUE;
2075 }
2076 }
2077
2078 if (Mflag || Oflag) {
2079 //
2080 // Use Ip6Config to get available addresses or other configuration from DHCP.
2081 //
2082 Ip6ConfigStartStatefulAutoConfig (&IpSb->Ip6ConfigInstance, Oflag);
2083 }
2084
2085 //
2086 // Process Reachable Time and Retrans Timer fields.
2087 //
2088 NetbufCopy (Packet, sizeof (Icmp), sizeof (UINT32), (UINT8 *)&ReachableTime);
2089 NetbufCopy (Packet, sizeof (Icmp) + sizeof (UINT32), sizeof (UINT32), (UINT8 *)&RetransTimer);
2090 ReachableTime = NTOHL (ReachableTime);
2091 RetransTimer = NTOHL (RetransTimer);
2092
2093 if ((ReachableTime != 0) && (ReachableTime != IpSb->BaseReachableTime)) {
2094 //
2095 // If new value is not unspecified and differs from the previous one, record it
2096 // in BaseReachableTime and recompute a ReachableTime.
2097 //
2098 IpSb->BaseReachableTime = ReachableTime;
2099 Status = Ip6UpdateReachableTime (IpSb);
2100 if (EFI_ERROR (Status)) {
2101 goto Exit;
2102 }
2103 }
2104
2105 if (RetransTimer != 0) {
2106 IpSb->RetransTimer = RetransTimer;
2107 }
2108
2109 //
2110 // IsRouter flag must be set to TRUE if corresponding neighbor cache entry exists.
2111 //
2112 NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
2113 if (NeighborCache != NULL) {
2114 NeighborCache->IsRouter = TRUE;
2115 }
2116
2117 //
2118 // If an valid router advertisement is received, stops router solicitation.
2119 //
2120 IpSb->RouterAdvertiseReceived = TRUE;
2121
2122 //
2123 // The only defined options that may appear are the Source
2124 // Link-Layer Address, Prefix information and MTU options.
2125 // All included options have a length that is greater than zero and
2126 // fit within the input packet.
2127 //
2128 Offset = 16;
2129 while (Offset < (UINT32)Head->PayloadLength) {
2130 NetbufCopy (Packet, Offset, sizeof (UINT8), &Type);
2131 switch (Type) {
2132 case Ip6OptionEtherSource:
2133 //
2134 // Update the neighbor cache
2135 //
2136 NetbufCopy (Packet, Offset, sizeof (IP6_ETHER_ADDR_OPTION), (UINT8 *)&LinkLayerOption);
2137
2138 //
2139 // Option size validity ensured by Ip6IsNDOptionValid().
2140 //
2141 ASSERT (LinkLayerOption.Length != 0);
2142 ASSERT (Offset + (UINT32)LinkLayerOption.Length * 8 <= (UINT32)Head->PayloadLength);
2143
2144 ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS));
2145 CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6);
2146
2147 if (NeighborCache == NULL) {
2148 NeighborCache = Ip6CreateNeighborEntry (
2149 IpSb,
2151 &Head->SourceAddress,
2152 &LinkLayerAddress
2153 );
2154 if (NeighborCache == NULL) {
2155 Status = EFI_OUT_OF_RESOURCES;
2156 goto Exit;
2157 }
2158
2159 NeighborCache->IsRouter = TRUE;
2160 NeighborCache->State = EfiNeighborStale;
2161 NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
2162 } else {
2163 Result = CompareMem (&LinkLayerAddress, &NeighborCache->LinkAddress, 6);
2164
2165 //
2166 // If the link-local address is the same as that already in the cache,
2167 // the cache entry's state remains unchanged. Otherwise update the
2168 // reachability state to STALE.
2169 //
2170 if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
2171 CopyMem (&NeighborCache->LinkAddress, &LinkLayerAddress, 6);
2172
2173 NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
2174
2175 if (NeighborCache->State == EfiNeighborInComplete) {
2176 //
2177 // Send queued packets if exist.
2178 //
2179 NeighborCache->State = EfiNeighborStale;
2180 NeighborCache->CallBack ((VOID *)NeighborCache);
2181 } else {
2182 NeighborCache->State = EfiNeighborStale;
2183 }
2184 }
2185 }
2186
2187 Offset += (UINT32)LinkLayerOption.Length * 8;
2188 break;
2189 case Ip6OptionPrefixInfo:
2190 NetbufCopy (Packet, Offset, sizeof (IP6_PREFIX_INFO_OPTION), (UINT8 *)&PrefixOption);
2191
2192 //
2193 // Option size validity ensured by Ip6IsNDOptionValid().
2194 //
2195 ASSERT (PrefixOption.Length == 4);
2196 ASSERT (Offset + (UINT32)PrefixOption.Length * 8 <= (UINT32)Head->PayloadLength);
2197
2198 PrefixOption.ValidLifetime = NTOHL (PrefixOption.ValidLifetime);
2199 PrefixOption.PreferredLifetime = NTOHL (PrefixOption.PreferredLifetime);
2200
2201 //
2202 // Get L and A flag, recorded in the lower 2 bits of Reserved1
2203 //
2204 OnLink = FALSE;
2205 if ((PrefixOption.Reserved1 & IP6_ON_LINK_FLAG) == IP6_ON_LINK_FLAG) {
2206 OnLink = TRUE;
2207 }
2208
2209 Autonomous = FALSE;
2210 if ((PrefixOption.Reserved1 & IP6_AUTO_CONFIG_FLAG) == IP6_AUTO_CONFIG_FLAG) {
2211 Autonomous = TRUE;
2212 }
2213
2214 //
2215 // If the prefix is the link-local prefix, silently ignore the prefix option.
2216 //
2217 if ((PrefixOption.PrefixLength == IP6_LINK_LOCAL_PREFIX_LENGTH) &&
2218 NetIp6IsLinkLocalAddr (&PrefixOption.Prefix)
2219 )
2220 {
2221 Offset += sizeof (IP6_PREFIX_INFO_OPTION);
2222 break;
2223 }
2224
2225 //
2226 // Do following if on-link flag is set according to RFC4861.
2227 //
2228 if (OnLink) {
2229 PrefixList = Ip6FindPrefixListEntry (
2230 IpSb,
2231 TRUE,
2232 PrefixOption.PrefixLength,
2233 &PrefixOption.Prefix
2234 );
2235 //
2236 // Create a new entry for the prefix, if the ValidLifetime is zero,
2237 // silently ignore the prefix option.
2238 //
2239 if ((PrefixList == NULL) && (PrefixOption.ValidLifetime != 0)) {
2240 PrefixList = Ip6CreatePrefixListEntry (
2241 IpSb,
2242 TRUE,
2243 PrefixOption.ValidLifetime,
2244 PrefixOption.PreferredLifetime,
2245 PrefixOption.PrefixLength,
2246 &PrefixOption.Prefix
2247 );
2248 if (PrefixList == NULL) {
2249 Status = EFI_OUT_OF_RESOURCES;
2250 goto Exit;
2251 }
2252 } else if (PrefixList != NULL) {
2253 if (PrefixOption.ValidLifetime != 0) {
2254 PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
2255 } else {
2256 //
2257 // If the prefix exists and incoming ValidLifetime is zero, immediately
2258 // remove the prefix.
2259 Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
2260 }
2261 }
2262 }
2263
2264 //
2265 // Do following if Autonomous flag is set according to RFC4862.
2266 //
2267 if (Autonomous && (PrefixOption.PreferredLifetime <= PrefixOption.ValidLifetime)) {
2268 PrefixList = Ip6FindPrefixListEntry (
2269 IpSb,
2270 FALSE,
2271 PrefixOption.PrefixLength,
2272 &PrefixOption.Prefix
2273 );
2274 //
2275 // Create a new entry for the prefix, and form an address by prefix + interface id
2276 // If the sum of the prefix length and interface identifier length
2277 // does not equal 128 bits, the Prefix Information option MUST be ignored.
2278 //
2279 if ((PrefixList == NULL) &&
2280 (PrefixOption.ValidLifetime != 0) &&
2281 (PrefixOption.PrefixLength + IpSb->InterfaceIdLen * 8 == 128)
2282 )
2283 {
2284 //
2285 // Form the address in network order.
2286 //
2287 CopyMem (&StatelessAddress, &PrefixOption.Prefix, sizeof (UINT64));
2288 CopyMem (&StatelessAddress.Addr[8], IpSb->InterfaceId, sizeof (UINT64));
2289
2290 //
2291 // If the address is not yet in the assigned address list, adds it into.
2292 //
2293 if (!Ip6IsOneOfSetAddress (IpSb, &StatelessAddress, NULL, NULL)) {
2294 //
2295 // And also not in the DAD process, check its uniqueness firstly.
2296 //
2297 if (Ip6FindDADEntry (IpSb, &StatelessAddress, NULL) == NULL) {
2298 Status = Ip6SetAddress (
2299 IpSb->DefaultInterface,
2300 &StatelessAddress,
2301 FALSE,
2302 PrefixOption.PrefixLength,
2303 PrefixOption.ValidLifetime,
2304 PrefixOption.PreferredLifetime,
2305 NULL,
2306 NULL
2307 );
2308 if (EFI_ERROR (Status)) {
2309 goto Exit;
2310 }
2311 }
2312 }
2313
2314 //
2315 // Adds the prefix option to stateless prefix option list.
2316 //
2317 PrefixList = Ip6CreatePrefixListEntry (
2318 IpSb,
2319 FALSE,
2320 PrefixOption.ValidLifetime,
2321 PrefixOption.PreferredLifetime,
2322 PrefixOption.PrefixLength,
2323 &PrefixOption.Prefix
2324 );
2325 if (PrefixList == NULL) {
2326 Status = EFI_OUT_OF_RESOURCES;
2327 goto Exit;
2328 }
2329 } else if (PrefixList != NULL) {
2330 //
2331 // Reset the preferred lifetime of the address if the advertised prefix exists.
2332 // Perform specific action to valid lifetime together.
2333 //
2334 PrefixList->PreferredLifetime = PrefixOption.PreferredLifetime;
2335 if ((PrefixOption.ValidLifetime > 7200) ||
2336 (PrefixOption.ValidLifetime > PrefixList->ValidLifetime))
2337 {
2338 //
2339 // If the received Valid Lifetime is greater than 2 hours or
2340 // greater than RemainingLifetime, set the valid lifetime of the
2341 // corresponding address to the advertised Valid Lifetime.
2342 //
2343 PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
2344 } else if (PrefixList->ValidLifetime <= 7200) {
2345 //
2346 // If RemainingLifetime is less than or equals to 2 hours, ignore the
2347 // Prefix Information option with regards to the valid lifetime.
2348 // TODO: If this option has been authenticated, set the valid lifetime.
2349 //
2350 } else {
2351 //
2352 // Otherwise, reset the valid lifetime of the corresponding
2353 // address to 2 hours.
2354 //
2355 PrefixList->ValidLifetime = 7200;
2356 }
2357 }
2358 }
2359
2360 Offset += sizeof (IP6_PREFIX_INFO_OPTION);
2361 break;
2362 case Ip6OptionMtu:
2363 NetbufCopy (Packet, Offset, sizeof (IP6_MTU_OPTION), (UINT8 *)&MTUOption);
2364
2365 //
2366 // Option size validity ensured by Ip6IsNDOptionValid().
2367 //
2368 ASSERT (MTUOption.Length == 1);
2369 ASSERT (Offset + (UINT32)MTUOption.Length * 8 <= (UINT32)Head->PayloadLength);
2370
2371 //
2372 // Use IPv6 minimum link MTU 1280 bytes as the maximum packet size in order
2373 // to omit implementation of Path MTU Discovery. Thus ignore the MTU option
2374 // in Router Advertisement.
2375 //
2376
2377 Offset += sizeof (IP6_MTU_OPTION);
2378 break;
2379 default:
2380 //
2381 // Silently ignore unrecognized options
2382 //
2383 NetbufCopy (Packet, Offset + sizeof (UINT8), sizeof (UINT8), &Length);
2384
2385 ASSERT (Length != 0);
2386
2387 Offset += (UINT32)Length * 8;
2388 break;
2389 }
2390 }
2391
2392 Status = EFI_SUCCESS;
2393
2394Exit:
2395 NetbufFree (Packet);
2396 return Status;
2397}
2398
2417 IN IP6_SERVICE *IpSb,
2418 IN EFI_IP6_HEADER *Head,
2419 IN NET_BUF *Packet
2420 )
2421{
2423 EFI_IPv6_ADDRESS *Target;
2424 EFI_IPv6_ADDRESS *IcmpDest;
2425 UINT8 *Option;
2426 UINT16 OptionLen;
2427 IP6_ROUTE_ENTRY *RouteEntry;
2428 IP6_ROUTE_CACHE_ENTRY *RouteCache;
2429 IP6_NEIGHBOR_ENTRY *NeighborCache;
2430 INT32 Length;
2431 UINT8 OptLen;
2432 IP6_ETHER_ADDR_OPTION *LinkLayerOption;
2433 EFI_MAC_ADDRESS Mac;
2434 UINT32 Index;
2435 BOOLEAN IsRouter;
2436 EFI_STATUS Status;
2437 INTN Result;
2438
2439 Status = EFI_INVALID_PARAMETER;
2440
2441 Icmp = (IP6_ICMP_INFORMATION_HEAD *)NetbufGetByte (Packet, 0, NULL);
2442 if (Icmp == NULL) {
2443 goto Exit;
2444 }
2445
2446 //
2447 // Validate the incoming Redirect message
2448 //
2449
2450 //
2451 // The IP Hop Limit field has a value of 255, i.e. the packet
2452 // could not possibly have been forwarded by a router.
2453 // ICMP Code is 0.
2454 // ICMP length (derived from the IP length) is 40 or more octets.
2455 //
2456 if ((Head->HopLimit != IP6_HOP_LIMIT) || (Icmp->Head.Code != 0) ||
2457 (Head->PayloadLength < IP6_REDITECT_LENGTH))
2458 {
2459 goto Exit;
2460 }
2461
2462 //
2463 // The IP source address must be a link-local address
2464 //
2465 if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
2466 goto Exit;
2467 }
2468
2469 //
2470 // The dest of this ICMP redirect message is not us.
2471 //
2472 if (!Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
2473 goto Exit;
2474 }
2475
2476 //
2477 // All included options have a length that is greater than zero.
2478 //
2479 OptionLen = (UINT16)(Head->PayloadLength - IP6_REDITECT_LENGTH);
2480 if (OptionLen != 0) {
2481 Option = NetbufGetByte (Packet, IP6_REDITECT_LENGTH, NULL);
2482 ASSERT (Option != NULL);
2483
2484 if (!Ip6IsNDOptionValid (Option, OptionLen)) {
2485 goto Exit;
2486 }
2487 }
2488
2489 Target = (EFI_IPv6_ADDRESS *)(Icmp + 1);
2490 IcmpDest = Target + 1;
2491
2492 //
2493 // The ICMP Destination Address field in the redirect message does not contain
2494 // a multicast address.
2495 //
2496 if (IP6_IS_MULTICAST (IcmpDest)) {
2497 goto Exit;
2498 }
2499
2500 //
2501 // The ICMP Target Address is either a link-local address (when redirected to
2502 // a router) or the same as the ICMP Destination Address (when redirected to
2503 // the on-link destination).
2504 //
2505 IsRouter = (BOOLEAN) !EFI_IP6_EQUAL (Target, IcmpDest);
2506 if (!NetIp6IsLinkLocalAddr (Target) && IsRouter) {
2507 goto Exit;
2508 }
2509
2510 //
2511 // Check the options. The only interested option here is the target-link layer
2512 // address option.
2513 //
2514 Length = Packet->TotalSize - 40;
2515 Option = (UINT8 *)(IcmpDest + 1);
2516 LinkLayerOption = NULL;
2517 while (Length > 0) {
2518 switch (*Option) {
2519 case Ip6OptionEtherTarget:
2520
2521 LinkLayerOption = (IP6_ETHER_ADDR_OPTION *)Option;
2522 OptLen = LinkLayerOption->Length;
2523 if (OptLen != 1) {
2524 //
2525 // For ethernet, the length must be 1.
2526 //
2527 goto Exit;
2528 }
2529
2530 break;
2531
2532 default:
2533
2534 OptLen = *(Option + 1);
2535 if (OptLen == 0) {
2536 //
2537 // A length of 0 is invalid.
2538 //
2539 goto Exit;
2540 }
2541
2542 break;
2543 }
2544
2545 Length -= 8 * OptLen;
2546 Option += 8 * OptLen;
2547 }
2548
2549 if (Length != 0) {
2550 goto Exit;
2551 }
2552
2553 //
2554 // The IP source address of the Redirect is the same as the current
2555 // first-hop router for the specified ICMP Destination Address.
2556 //
2557 RouteCache = Ip6FindRouteCache (IpSb->RouteTable, IcmpDest, &Head->DestinationAddress);
2558 if (RouteCache != NULL) {
2559 if (!EFI_IP6_EQUAL (&RouteCache->NextHop, &Head->SourceAddress)) {
2560 //
2561 // The source of this Redirect message must match the NextHop of the
2562 // corresponding route cache entry.
2563 //
2564 goto Exit;
2565 }
2566
2567 //
2568 // Update the NextHop.
2569 //
2570 IP6_COPY_ADDRESS (&RouteCache->NextHop, Target);
2571
2572 if (!IsRouter) {
2573 RouteEntry = (IP6_ROUTE_ENTRY *)RouteCache->Tag;
2574 RouteEntry->Flag = RouteEntry->Flag | IP6_DIRECT_ROUTE;
2575 }
2576 } else {
2577 //
2578 // Get the Route Entry.
2579 //
2580 RouteEntry = Ip6FindRouteEntry (IpSb->RouteTable, IcmpDest, NULL);
2581 if (RouteEntry == NULL) {
2582 RouteEntry = Ip6CreateRouteEntry (IcmpDest, 0, NULL);
2583 if (RouteEntry == NULL) {
2584 Status = EFI_OUT_OF_RESOURCES;
2585 goto Exit;
2586 }
2587 }
2588
2589 if (!IsRouter) {
2590 RouteEntry->Flag = IP6_DIRECT_ROUTE;
2591 }
2592
2593 //
2594 // Create a route cache for this.
2595 //
2596 RouteCache = Ip6CreateRouteCacheEntry (
2597 IcmpDest,
2598 &Head->DestinationAddress,
2599 Target,
2600 (UINTN)RouteEntry
2601 );
2602 if (RouteCache == NULL) {
2603 Status = EFI_OUT_OF_RESOURCES;
2604 goto Exit;
2605 }
2606
2607 //
2608 // Insert the newly created route cache entry.
2609 //
2610 Index = IP6_ROUTE_CACHE_HASH (IcmpDest, &Head->DestinationAddress);
2611 InsertHeadList (&IpSb->RouteTable->Cache.CacheBucket[Index], &RouteCache->Link);
2612 }
2613
2614 //
2615 // Try to locate the neighbor cache for the Target.
2616 //
2617 NeighborCache = Ip6FindNeighborEntry (IpSb, Target);
2618
2619 if (LinkLayerOption != NULL) {
2620 if (NeighborCache == NULL) {
2621 //
2622 // Create a neighbor cache for the Target.
2623 //
2624 ZeroMem (&Mac, sizeof (EFI_MAC_ADDRESS));
2625 CopyMem (&Mac, LinkLayerOption->EtherAddr, 6);
2626 NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, Target, &Mac);
2627 if (NeighborCache == NULL) {
2628 //
2629 // Just report a success here. The neighbor cache can be created in
2630 // some other place.
2631 //
2632 Status = EFI_SUCCESS;
2633 goto Exit;
2634 }
2635
2636 NeighborCache->State = EfiNeighborStale;
2637 NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
2638 } else {
2639 Result = CompareMem (LinkLayerOption->EtherAddr, &NeighborCache->LinkAddress, 6);
2640
2641 //
2642 // If the link-local address is the same as that already in the cache,
2643 // the cache entry's state remains unchanged. Otherwise update the
2644 // reachability state to STALE.
2645 //
2646 if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
2647 CopyMem (&NeighborCache->LinkAddress, LinkLayerOption->EtherAddr, 6);
2648
2649 NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
2650
2651 if (NeighborCache->State == EfiNeighborInComplete) {
2652 //
2653 // Send queued packets if exist.
2654 //
2655 NeighborCache->State = EfiNeighborStale;
2656 NeighborCache->CallBack ((VOID *)NeighborCache);
2657 } else {
2658 NeighborCache->State = EfiNeighborStale;
2659 }
2660 }
2661 }
2662 }
2663
2664 if ((NeighborCache != NULL) && IsRouter) {
2665 //
2666 // The Target is a router, set IsRouter to TRUE.
2667 //
2668 NeighborCache->IsRouter = TRUE;
2669 }
2670
2671 Status = EFI_SUCCESS;
2672
2673Exit:
2674 NetbufFree (Packet);
2675 return Status;
2676}
2677
2704 IN IP6_SERVICE *IpSb,
2705 IN EFI_IPv6_ADDRESS *TargetIp6Address,
2706 IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
2707 IN UINT32 Timeout,
2708 IN BOOLEAN Override
2709 )
2710{
2711 IP6_NEIGHBOR_ENTRY *Neighbor;
2712
2713 Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
2714 if (Neighbor != NULL) {
2715 if (!Override) {
2716 return EFI_ACCESS_DENIED;
2717 } else {
2718 if (TargetLinkAddress != NULL) {
2719 IP6_COPY_LINK_ADDRESS (&Neighbor->LinkAddress, TargetLinkAddress);
2720 }
2721 }
2722 } else {
2723 if (TargetLinkAddress == NULL) {
2724 return EFI_NOT_FOUND;
2725 }
2726
2727 Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, TargetLinkAddress);
2728 if (Neighbor == NULL) {
2729 return EFI_OUT_OF_RESOURCES;
2730 }
2731 }
2732
2733 Neighbor->State = EfiNeighborReachable;
2734
2735 if (Timeout != 0) {
2736 Neighbor->Ticks = IP6_GET_TICKS (Timeout / TICKS_PER_MS);
2737 Neighbor->Dynamic = TRUE;
2738 } else {
2739 Neighbor->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
2740 }
2741
2742 return EFI_SUCCESS;
2743}
2744
2766 IN IP6_SERVICE *IpSb,
2767 IN EFI_IPv6_ADDRESS *TargetIp6Address,
2768 IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
2769 IN UINT32 Timeout,
2770 IN BOOLEAN Override
2771 )
2772{
2773 IP6_NEIGHBOR_ENTRY *Neighbor;
2774
2775 Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
2776 if (Neighbor == NULL) {
2777 return EFI_NOT_FOUND;
2778 }
2779
2780 RemoveEntryList (&Neighbor->Link);
2781 FreePool (Neighbor);
2782
2783 return EFI_SUCCESS;
2784}
2785
2795VOID
2796EFIAPI
2798 IN EFI_EVENT Event,
2799 IN VOID *Context
2800 )
2801{
2802 LIST_ENTRY *Entry;
2803 LIST_ENTRY *Next;
2804 LIST_ENTRY *Entry2;
2805 IP6_INTERFACE *IpIf;
2806 IP6_DELAY_JOIN_LIST *DelayNode;
2807 EFI_IPv6_ADDRESS Source;
2808 IP6_DAD_ENTRY *DupAddrDetect;
2809 EFI_STATUS Status;
2810 IP6_NEIGHBOR_ENTRY *NeighborCache;
2811 EFI_IPv6_ADDRESS Destination;
2812 IP6_SERVICE *IpSb;
2813 BOOLEAN Flag;
2814
2815 IpSb = (IP6_SERVICE *)Context;
2816 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
2817
2818 ZeroMem (&Source, sizeof (EFI_IPv6_ADDRESS));
2819
2820 //
2821 // A host SHOULD transmit up to MAX_RTR_SOLICITATIONS (3) Router
2822 // Solicitation messages, each separated by at least
2823 // RTR_SOLICITATION_INTERVAL (4) seconds.
2824 //
2825 if ((IpSb->Ip6ConfigInstance.Policy == Ip6ConfigPolicyAutomatic) &&
2826 !IpSb->RouterAdvertiseReceived &&
2827 (IpSb->SolicitTimer > 0)
2828 )
2829 {
2830 if ((IpSb->Ticks == 0) || (--IpSb->Ticks == 0)) {
2831 Status = Ip6SendRouterSolicit (IpSb, NULL, NULL, NULL, NULL);
2832 if (!EFI_ERROR (Status)) {
2833 IpSb->SolicitTimer--;
2834 IpSb->Ticks = (UINT32)IP6_GET_TICKS (IP6_RTR_SOLICITATION_INTERVAL);
2835 }
2836 }
2837 }
2838
2839 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
2840 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
2841
2842 //
2843 // Process the delay list to join the solicited-node multicast address.
2844 //
2845 NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
2846 DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
2847 if ((DelayNode->DelayTime == 0) || (--DelayNode->DelayTime == 0)) {
2848 //
2849 // The timer expires, init the duplicate address detection.
2850 //
2852 DelayNode->Interface,
2853 DelayNode->AddressInfo,
2854 DelayNode->DadCallback,
2855 DelayNode->Context
2856 );
2857
2858 //
2859 // Remove the delay node
2860 //
2861 RemoveEntryList (&DelayNode->Link);
2862 FreePool (DelayNode);
2863 }
2864 }
2865
2866 //
2867 // Process the duplicate address detection list.
2868 //
2869 NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
2870 DupAddrDetect = NET_LIST_USER_STRUCT (Entry2, IP6_DAD_ENTRY, Link);
2871
2872 if ((DupAddrDetect->RetransTick == 0) || (--DupAddrDetect->RetransTick == 0)) {
2873 //
2874 // The timer expires, check the remaining transmit counts.
2875 //
2876 if (DupAddrDetect->Transmit < DupAddrDetect->MaxTransmit) {
2877 //
2878 // Send the Neighbor Solicitation message with
2879 // Source - unspecified address, destination - solicited-node multicast address
2880 // Target - the address to be validated
2881 //
2882 Status = Ip6SendNeighborSolicit (
2883 IpSb,
2884 NULL,
2885 &DupAddrDetect->Destination,
2886 &DupAddrDetect->AddressInfo->Address,
2887 NULL
2888 );
2889 if (EFI_ERROR (Status)) {
2890 return;
2891 }
2892
2893 DupAddrDetect->Transmit++;
2894 DupAddrDetect->RetransTick = IP6_GET_TICKS (IpSb->RetransTimer);
2895 } else {
2896 //
2897 // All required solicitation has been sent out, and the RetransTime after the last
2898 // Neighbor Solicit is elapsed, finish the DAD process.
2899 //
2900 Flag = FALSE;
2901 if ((DupAddrDetect->Receive == 0) ||
2902 (DupAddrDetect->Transmit <= DupAddrDetect->Receive))
2903 {
2904 Flag = TRUE;
2905 }
2906
2907 Ip6OnDADFinished (Flag, IpIf, DupAddrDetect);
2908 }
2909 }
2910 }
2911 }
2912
2913 //
2914 // Polling the state of Neighbor cache
2915 //
2916 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
2917 NeighborCache = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
2918
2919 switch (NeighborCache->State) {
2921 if (NeighborCache->Ticks > 0) {
2922 --NeighborCache->Ticks;
2923 }
2924
2925 //
2926 // Retransmit Neighbor Solicitation messages approximately every
2927 // RetransTimer milliseconds while awaiting a response.
2928 //
2929 if (NeighborCache->Ticks == 0) {
2930 if (NeighborCache->Transmit > 1) {
2931 //
2932 // Send out multicast neighbor solicitation for address resolution.
2933 // After last neighbor solicitation message has been sent out, wait
2934 // for RetransTimer and then remove entry if no response is received.
2935 //
2936 Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
2937 Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
2938 if (EFI_ERROR (Status)) {
2939 return;
2940 }
2941
2942 Status = Ip6SendNeighborSolicit (
2943 IpSb,
2944 &Source,
2945 &Destination,
2946 &NeighborCache->Neighbor,
2947 &IpSb->SnpMode.CurrentAddress
2948 );
2949 if (EFI_ERROR (Status)) {
2950 return;
2951 }
2952 }
2953
2954 //
2955 // Update the retransmit times.
2956 //
2957 if (NeighborCache->Transmit > 0) {
2958 --NeighborCache->Transmit;
2959 NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
2960 }
2961 }
2962
2963 if (NeighborCache->Transmit == 0) {
2964 //
2965 // Timeout, send ICMP destination unreachable packet and then remove entry
2966 //
2967 Status = Ip6FreeNeighborEntry (
2968 IpSb,
2969 NeighborCache,
2970 TRUE,
2971 TRUE,
2972 EFI_ICMP_ERROR,
2973 NULL,
2974 NULL
2975 );
2976 if (EFI_ERROR (Status)) {
2977 return;
2978 }
2979 }
2980
2981 break;
2982
2984 //
2985 // This entry is inserted by EfiIp6Neighbors() as static entry
2986 // and will not timeout.
2987 //
2988 if (!NeighborCache->Dynamic && (NeighborCache->Ticks == IP6_INFINIT_LIFETIME)) {
2989 break;
2990 }
2991
2992 if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
2993 if (NeighborCache->Dynamic) {
2994 //
2995 // This entry is inserted by EfiIp6Neighbors() as dynamic entry
2996 // and will be deleted after timeout.
2997 //
2998 Status = Ip6FreeNeighborEntry (
2999 IpSb,
3000 NeighborCache,
3001 FALSE,
3002 TRUE,
3003 EFI_TIMEOUT,
3004 NULL,
3005 NULL
3006 );
3007 if (EFI_ERROR (Status)) {
3008 return;
3009 }
3010 } else {
3011 NeighborCache->State = EfiNeighborStale;
3012 NeighborCache->Ticks = (UINT32)IP6_INFINIT_LIFETIME;
3013 }
3014 }
3015
3016 break;
3017
3018 case EfiNeighborDelay:
3019 if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
3020 NeighborCache->State = EfiNeighborProbe;
3021 NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
3022 NeighborCache->Transmit = IP6_MAX_UNICAST_SOLICIT + 1;
3023 //
3024 // Send out unicast neighbor solicitation for Neighbor Unreachability Detection
3025 //
3026 Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
3027 if (EFI_ERROR (Status)) {
3028 return;
3029 }
3030
3031 Status = Ip6SendNeighborSolicit (
3032 IpSb,
3033 &Source,
3034 &NeighborCache->Neighbor,
3035 &NeighborCache->Neighbor,
3036 &IpSb->SnpMode.CurrentAddress
3037 );
3038 if (EFI_ERROR (Status)) {
3039 return;
3040 }
3041
3042 NeighborCache->Transmit--;
3043 }
3044
3045 break;
3046
3047 case EfiNeighborProbe:
3048 if (NeighborCache->Ticks > 0) {
3049 --NeighborCache->Ticks;
3050 }
3051
3052 //
3053 // Retransmit Neighbor Solicitation messages approximately every
3054 // RetransTimer milliseconds while awaiting a response.
3055 //
3056 if (NeighborCache->Ticks == 0) {
3057 if (NeighborCache->Transmit > 1) {
3058 //
3059 // Send out unicast neighbor solicitation for Neighbor Unreachability
3060 // Detection. After last neighbor solicitation message has been sent out,
3061 // wait for RetransTimer and then remove entry if no response is received.
3062 //
3063 Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
3064 if (EFI_ERROR (Status)) {
3065 return;
3066 }
3067
3068 Status = Ip6SendNeighborSolicit (
3069 IpSb,
3070 &Source,
3071 &NeighborCache->Neighbor,
3072 &NeighborCache->Neighbor,
3073 &IpSb->SnpMode.CurrentAddress
3074 );
3075 if (EFI_ERROR (Status)) {
3076 return;
3077 }
3078 }
3079
3080 //
3081 // Update the retransmit times.
3082 //
3083 if (NeighborCache->Transmit > 0) {
3084 --NeighborCache->Transmit;
3085 NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
3086 }
3087 }
3088
3089 if (NeighborCache->Transmit == 0) {
3090 //
3091 // Delete the neighbor entry.
3092 //
3093 Status = Ip6FreeNeighborEntry (
3094 IpSb,
3095 NeighborCache,
3096 FALSE,
3097 TRUE,
3098 EFI_TIMEOUT,
3099 NULL,
3100 NULL
3101 );
3102 if (EFI_ERROR (Status)) {
3103 return;
3104 }
3105 }
3106
3107 break;
3108
3109 default:
3110 break;
3111 }
3112 }
3113}
3114
3123VOID
3125 IN IP6_SERVICE *IpSb
3126 )
3127{
3128 LIST_ENTRY *Entry;
3129 LIST_ENTRY *Next;
3130 IP6_DEFAULT_ROUTER *DefaultRouter;
3131 IP6_PREFIX_LIST_ENTRY *PrefixOption;
3132 UINT8 Index;
3133 IP6_ROUTE_CACHE_ENTRY *RouteCache;
3134
3135 //
3136 // Decrease the lifetime of default router, if expires remove it from default router list.
3137 //
3138 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->DefaultRouterList) {
3139 DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
3140 if (DefaultRouter->Lifetime != IP6_INF_ROUTER_LIFETIME) {
3141 if ((DefaultRouter->Lifetime == 0) || (--DefaultRouter->Lifetime == 0)) {
3142 Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
3143 }
3144 }
3145 }
3146
3147 //
3148 // Decrease Valid lifetime and Preferred lifetime of Prefix options and corresponding addresses.
3149 //
3150 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->AutonomousPrefix) {
3151 PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
3152 if (PrefixOption->ValidLifetime != (UINT32)IP6_INFINIT_LIFETIME) {
3153 if ((PrefixOption->ValidLifetime > 0) && (--PrefixOption->ValidLifetime > 0)) {
3154 if ((PrefixOption->PreferredLifetime != (UINT32)IP6_INFINIT_LIFETIME) &&
3155 (PrefixOption->PreferredLifetime > 0)
3156 )
3157 {
3158 --PrefixOption->PreferredLifetime;
3159 }
3160 } else {
3161 Ip6DestroyPrefixListEntry (IpSb, PrefixOption, FALSE, TRUE);
3162 }
3163 }
3164 }
3165
3166 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->OnlinkPrefix) {
3167 PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
3168 if (PrefixOption->ValidLifetime != (UINT32)IP6_INFINIT_LIFETIME) {
3169 if ((PrefixOption->ValidLifetime == 0) || (--PrefixOption->ValidLifetime == 0)) {
3170 Ip6DestroyPrefixListEntry (IpSb, PrefixOption, TRUE, TRUE);
3171 }
3172 }
3173 }
3174
3175 //
3176 // Each bucket of route cache can contain at most IP6_ROUTE_CACHE_MAX entries.
3177 // Remove the entries at the tail of the bucket. These entries
3178 // are likely to be used least.
3179 // Reclaim frequency is set to 1 second.
3180 //
3181 for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
3182 while (IpSb->RouteTable->Cache.CacheNum[Index] > IP6_ROUTE_CACHE_MAX) {
3183 Entry = NetListRemoveTail (&IpSb->RouteTable->Cache.CacheBucket[Index]);
3184 if (Entry == NULL) {
3185 break;
3186 }
3187
3188 RouteCache = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
3189 Ip6FreeRouteCacheEntry (RouteCache);
3190 ASSERT (IpSb->RouteTable->Cache.CacheNum[Index] > 0);
3191 IpSb->RouteTable->Cache.CacheNum[Index]--;
3192 }
3193 }
3194}
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)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
@ EfiNeighborDelay
Definition: Ip6.h:272
@ EfiNeighborInComplete
Definition: Ip6.h:256
@ EfiNeighborProbe
Definition: Ip6.h:278
@ EfiNeighborReachable
Definition: Ip6.h:261
@ EfiNeighborStale
Definition: Ip6.h:267
#define ICMP_V6_DEST_UNREACHABLE
Definition: Ip6.h:80
VOID Ip6CreateSNMulticastAddr(IN EFI_IPv6_ADDRESS *Ip6Addr, OUT EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Common.c:291
EFI_STATUS Ip6SetToAllNodeMulticast(IN BOOLEAN Router, IN UINT8 Scope, OUT EFI_IPv6_ADDRESS *Ip6Addr)
Definition: Ip6Common.c:103
BOOLEAN Ip6IsSNMulticastAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: Ip6Common.c:471
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
VOID Ip6AddAddr(IN OUT IP6_INTERFACE *IpIf, IN IP6_ADDRESS_INFO *AddrInfo)
Definition: Ip6Common.c:316
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
@ Ip6ConfigPolicyAutomatic
Definition: Ip6Config.h:175
EFI_STATUS EFIAPI Ip6ConfigOnDhcp6Reply(IN EFI_DHCP6_PROTOCOL *This, IN VOID *Context, IN EFI_DHCP6_PACKET *Packet)
EFI_STATUS Ip6ConfigStartStatefulAutoConfig(IN IP6_CONFIG_INSTANCE *Instance, IN BOOLEAN OtherInfoOnly)
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 Ip6SetAddress(IN IP6_INTERFACE *Interface, IN EFI_IPv6_ADDRESS *Ip6Addr, IN BOOLEAN IsAnycast, IN UINT8 PrefixLength, IN UINT32 ValidLifetime, IN UINT32 PreferredLifetime, IN IP6_DAD_CALLBACK DadCallback OPTIONAL, IN VOID *Context OPTIONAL)
Definition: Ip6If.c:75
VOID Ip6FreeLinkTxToken(IN IP6_LINK_TX_TOKEN *Token)
Definition: Ip6If.c:432
EFI_STATUS Ip6LeaveGroup(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Address)
Definition: Ip6Mld.c:547
EFI_STATUS Ip6JoinGroup(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface, IN EFI_IPv6_ADDRESS *Address)
Definition: Ip6Mld.c:483
IP6_DEFAULT_ROUTER * Ip6CreateDefaultRouter(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Ip6Address, IN UINT16 RouterLifetime)
Definition: Ip6Nd.c:691
EFI_STATUS Ip6ProcessRedirect(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Nd.c:2416
VOID Ip6DestroyDefaultRouter(IN IP6_SERVICE *IpSb, IN IP6_DEFAULT_ROUTER *DefaultRouter)
Definition: Ip6Nd.c:738
VOID Ip6OnDADFinished(IN BOOLEAN IsDadPassed, IN IP6_INTERFACE *IpIf, IN IP6_DAD_ENTRY *DadEntry)
Definition: Ip6Nd.c:818
IP6_PREFIX_LIST_ENTRY * Ip6FindPrefixListEntry(IN IP6_SERVICE *IpSb, IN BOOLEAN OnLinkOrAuto, IN UINT8 PrefixLength, IN EFI_IPv6_ADDRESS *Prefix)
Definition: Ip6Nd.c:337
VOID Ip6CleanDefaultRouterList(IN IP6_SERVICE *IpSb)
Definition: Ip6Nd.c:765
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 Ip6CleanPrefixListTable(IN IP6_SERVICE *IpSb, IN LIST_ENTRY *ListHead)
Definition: Ip6Nd.c:391
EFI_STATUS Ip6UpdateReachableTime(IN OUT IP6_SERVICE *IpSb)
Definition: Ip6Nd.c:23
VOID Ip6DestroyPrefixListEntry(IN IP6_SERVICE *IpSb, IN IP6_PREFIX_LIST_ENTRY *PrefixEntry, IN BOOLEAN OnLinkOrAuto, IN BOOLEAN ImmediateDelete)
Definition: Ip6Nd.c:281
EFI_STATUS Ip6SendRouterSolicit(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface OPTIONAL, IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL, IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL)
Definition: Ip6Nd.c:1114
EFI_STATUS Ip6SendNeighborAdvertise(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *SourceAddress, IN EFI_IPv6_ADDRESS *DestinationAddress, IN EFI_IPv6_ADDRESS *TargetIp6Address, IN EFI_MAC_ADDRESS *TargetLinkAddress, IN BOOLEAN IsRouter, IN BOOLEAN Override, IN BOOLEAN Solicited)
Definition: Ip6Nd.c:1225
IP6_DEFAULT_ROUTER * Ip6FindDefaultRouter(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Ip6Address)
Definition: Ip6Nd.c:788
IP6_DAD_ENTRY * Ip6FindDADEntry(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Target, OUT IP6_INTERFACE **Interface OPTIONAL)
Definition: Ip6Nd.c:1064
EFI_STATUS Ip6AddNeighbor(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *TargetIp6Address, IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, IN UINT32 Timeout, IN BOOLEAN Override)
Definition: Ip6Nd.c:2703
EFI_STATUS Ip6ProcessNeighborAdvertise(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Nd.c:1708
VOID Ip6OnArpResolved(IN VOID *Context)
Definition: Ip6Nd.c:416
EFI_STATUS Ip6InitDADProcess(IN IP6_INTERFACE *IpIf, IN IP6_ADDRESS_INFO *AddressInfo, IN IP6_DAD_CALLBACK Callback OPTIONAL, IN VOID *Context OPTIONAL)
Definition: Ip6Nd.c:974
EFI_STATUS Ip6DelNeighbor(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *TargetIp6Address, IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, IN UINT32 Timeout, IN BOOLEAN Override)
Definition: Ip6Nd.c:2765
EFI_STATUS Ip6ProcessNeighborSolicit(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Nd.c:1476
VOID Ip6NdTimerTicking(IN IP6_SERVICE *IpSb)
Definition: Ip6Nd.c:3124
VOID EFIAPI Ip6NdFasterTimerTicking(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6Nd.c:2797
EFI_STATUS Ip6BuildPrefixTable(IN IP6_PROTOCOL *IpInstance, OUT UINT32 *PrefixCount, OUT EFI_IP6_ADDRESS_INFO **PrefixTable)
Definition: Ip6Nd.c:122
EFI_STATUS Ip6ProcessRouterAdvertise(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Nd.c:1943
IP6_PREFIX_LIST_ENTRY * Ip6CreatePrefixListEntry(IN IP6_SERVICE *IpSb, IN BOOLEAN OnLinkOrAuto, IN UINT32 ValidLifetime, IN UINT32 PreferredLifetime, IN UINT8 PrefixLength, IN EFI_IPv6_ADDRESS *Prefix)
Definition: Ip6Nd.c:191
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
EFI_STATUS Ip6BuildEfiNeighborCache(IN IP6_PROTOCOL *IpInstance, OUT UINT32 *NeighborCount, OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache)
Definition: Ip6Nd.c:56
IP6_NEIGHBOR_ENTRY * Ip6FindNeighborEntry(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Ip6Address)
Definition: Ip6Nd.c:566
@ IP6_MAX_RTR_SOLICITATION_DELAY
1000 milliseconds
Definition: Ip6Nd.h:18
BOOLEAN Ip6IsNDOptionValid(IN UINT8 *Option, IN UINT16 OptionLen)
Definition: Ip6Option.c:150
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
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 * Ip6CreateRouteEntry(IN EFI_IPv6_ADDRESS *Destination OPTIONAL, IN UINT8 PrefixLength, IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL)
Definition: Ip6Route.c:51
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 * Ip6FindRouteCache(IN IP6_ROUTE_TABLE *RtTable, IN EFI_IPv6_ADDRESS *Dest, IN EFI_IPv6_ADDRESS *Src)
Definition: Ip6Route.c:223
EFI_STATUS Ip6DelRoute(IN OUT IP6_ROUTE_TABLE *RtTable, IN EFI_IPv6_ADDRESS *Destination, IN UINT8 PrefixLength, IN EFI_IPv6_ADDRESS *GatewayAddress)
Definition: Ip6Route.c:506
IP6_ROUTE_CACHE_ENTRY * Ip6CreateRouteCacheEntry(IN EFI_IPv6_ADDRESS *Dst, IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *GateWay, IN UINTN Tag)
Definition: Ip6Route.c:167
#define IP6_ROUTE_CACHE_MAX
Definition: Ip6Route.h:20
#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 DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
VOID EFIAPI NetbufReserve(IN OUT NET_BUF *Nbuf, IN UINT32 Len)
Definition: NetBuffer.c:984
LIST_ENTRY *EFIAPI NetListRemoveTail(IN OUT LIST_ENTRY *Head)
Definition: DxeNetLib.c:1134
BOOLEAN EFIAPI NetIp6IsValidUnicast(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:725
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
BOOLEAN EFIAPI NetIp6IsNetEqual(EFI_IPv6_ADDRESS *Ip1, EFI_IPv6_ADDRESS *Ip2, UINT8 PrefixLength)
Definition: DxeNetLib.c:837
BOOLEAN EFIAPI NetIp6IsLinkLocalAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:796
NET_BUF *EFIAPI NetbufAlloc(IN UINT32 Len)
Definition: NetBuffer.c:89
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
EFI_STATUS EFIAPI PseudoRandomU32(OUT UINT32 *Output)
Definition: DxeNetLib.c:1011
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID EFIAPI NetListInsertBefore(IN OUT LIST_ENTRY *PostEntry, IN OUT LIST_ENTRY *NewEntry)
Definition: DxeNetLib.c:1199
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
IPv6_ADDRESS EFI_IPv6_ADDRESS
Definition: UefiBaseType.h:90
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
@ TimerCancel
Definition: UefiSpec.h:531
UINT32 DelayTime
in tick per 50 milliseconds
Definition: Ip6Nd.h:154
UINT8 PrefixLength
The length of the prefix associated with the Address.
Definition: Ip6.h:222
EFI_IPv6_ADDRESS Address
The IPv6 address.
Definition: Ip6.h:221
UINT32 DupAddrDetectTransmits
The number of consecutive Neighbor Solicitation messages sent.
Definition: Ip6Config.h:185
EFI_IP6_NEIGHBOR_STATE State
State of this neighbor cache entry.
Definition: Ip6.h:289
EFI_MAC_ADDRESS LinkAddress
Link-layer address of the neighbor.
Definition: Ip6.h:288
EFI_IPv6_ADDRESS Neighbor
The on-link unicast/anycast IP address of the neighbor.
Definition: Ip6.h:287
EFI_MAC_ADDRESS CurrentAddress