TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip6Mld.c
Go to the documentation of this file.
1
10#include "Ip6Impl.h"
11
24 IN OUT IP6_SERVICE *IpSb,
25 IN EFI_IPv6_ADDRESS *MulticastAddr,
26 IN UINT32 DelayTimer
27 )
28{
29 IP6_MLD_GROUP *Entry;
30
31 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
32 ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
33
34 Entry = AllocatePool (sizeof (IP6_MLD_GROUP));
35 if (Entry != NULL) {
36 Entry->RefCnt = 1;
37 Entry->DelayTimer = DelayTimer;
38 Entry->SendByUs = FALSE;
39 IP6_COPY_ADDRESS (&Entry->Address, MulticastAddr);
40 InsertTailList (&IpSb->MldCtrl.Groups, &Entry->Link);
41 }
42
43 return Entry;
44}
45
57 IN IP6_SERVICE *IpSb,
58 IN EFI_IPv6_ADDRESS *MulticastAddr
59 )
60{
61 LIST_ENTRY *Entry;
62 IP6_MLD_GROUP *Group;
63
64 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
65 ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
66
67 NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
68 Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
69 if (EFI_IP6_EQUAL (MulticastAddr, &Group->Address)) {
70 return Group;
71 }
72 }
73
74 return NULL;
75}
76
89INTN
91 IN IP6_MLD_SERVICE_DATA *MldCtrl,
93 )
94{
95 LIST_ENTRY *Entry;
96 IP6_MLD_GROUP *Group;
97 INTN Count;
98
99 Count = 0;
100
101 NET_LIST_FOR_EACH (Entry, &MldCtrl->Groups) {
102 Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
103
104 if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
105 Count++;
106 }
107 }
108
109 return Count;
110}
111
128 IN IP6_SERVICE *IpSb,
129 IN IP6_INTERFACE *Interface OPTIONAL,
130 IN EFI_IPv6_ADDRESS *MulticastAddr
131 )
132{
133 IP6_MLD_HEAD *MldHead;
134 NET_BUF *Packet;
135 EFI_IP6_HEADER Head;
136 UINT16 PayloadLen;
137 UINTN OptionLen;
138 UINT8 *Options;
139 EFI_STATUS Status;
140 UINT16 HeadChecksum;
141 UINT16 PseudoChecksum;
142
143 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
144 ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
145
146 //
147 // Generate the packet to be sent
148 // IPv6 basic header + Hop by Hop option + MLD message
149 //
150
151 OptionLen = 0;
152 Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
153 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
154
155 PayloadLen = (UINT16)(OptionLen + sizeof (IP6_MLD_HEAD));
156 Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
157 if (Packet == NULL) {
158 return EFI_OUT_OF_RESOURCES;
159 }
160
161 //
162 // Create the basic IPv6 header.
163 // RFC3590: Use link-local address as source address if it is available,
164 // otherwise use the unspecified address.
165 //
166 Head.FlowLabelL = 0;
167 Head.FlowLabelH = 0;
168 Head.PayloadLength = HTONS (PayloadLen);
169 Head.NextHeader = IP6_HOP_BY_HOP;
170 Head.HopLimit = 1;
171 IP6_COPY_ADDRESS (&Head.DestinationAddress, MulticastAddr);
172
173 //
174 // If Link-Local address is not ready, we use unspecified address.
175 //
176 IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
177
178 NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
179
180 //
181 // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
182 //
183 Options = NetbufAllocSpace (Packet, (UINT32)OptionLen, FALSE);
184 ASSERT (Options != NULL);
185 Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
186 if (EFI_ERROR (Status)) {
187 NetbufFree (Packet);
188 Packet = NULL;
189 return Status;
190 }
191
192 //
193 // Fill in MLD message - Report
194 //
195 MldHead = (IP6_MLD_HEAD *)NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
196 ASSERT (MldHead != NULL);
197 ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
198 MldHead->Head.Type = ICMP_V6_LISTENER_REPORT;
199 MldHead->Head.Code = 0;
200 IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
201
202 HeadChecksum = NetblockChecksum ((UINT8 *)MldHead, sizeof (IP6_MLD_HEAD));
203 PseudoChecksum = NetIp6PseudoHeadChecksum (
204 &Head.SourceAddress,
205 &Head.DestinationAddress,
206 IP6_ICMP,
207 sizeof (IP6_MLD_HEAD)
208 );
209
210 MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
211
212 //
213 // Transmit the packet
214 //
215 return Ip6Output (IpSb, Interface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
216}
217
232 IN IP6_SERVICE *IpSb,
233 IN EFI_IPv6_ADDRESS *MulticastAddr
234 )
235{
236 IP6_MLD_HEAD *MldHead;
237 NET_BUF *Packet;
238 EFI_IP6_HEADER Head;
239 UINT16 PayloadLen;
240 UINTN OptionLen;
241 UINT8 *Options;
242 EFI_STATUS Status;
243 EFI_IPv6_ADDRESS Destination;
244 UINT16 HeadChecksum;
245 UINT16 PseudoChecksum;
246
247 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
248 ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
249
250 //
251 // Generate the packet to be sent
252 // IPv6 basic header + Hop by Hop option + MLD message
253 //
254
255 OptionLen = 0;
256 Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
257 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
258
259 PayloadLen = (UINT16)(OptionLen + sizeof (IP6_MLD_HEAD));
260 Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32)PayloadLen);
261 if (Packet == NULL) {
262 return EFI_OUT_OF_RESOURCES;
263 }
264
265 //
266 // Create the basic IPv6 header.
267 //
268 Head.FlowLabelL = 0;
269 Head.FlowLabelH = 0;
270 Head.PayloadLength = HTONS (PayloadLen);
271 Head.NextHeader = IP6_HOP_BY_HOP;
272 Head.HopLimit = 1;
273
274 //
275 // If Link-Local address is not ready, we use unspecified address.
276 //
277 IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
278
279 Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Destination);
280 IP6_COPY_ADDRESS (&Head.DestinationAddress, &Destination);
281
282 NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
283
284 //
285 // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
286 //
287 Options = NetbufAllocSpace (Packet, (UINT32)OptionLen, FALSE);
288 ASSERT (Options != NULL);
289 Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
290 if (EFI_ERROR (Status)) {
291 NetbufFree (Packet);
292 Packet = NULL;
293 return Status;
294 }
295
296 //
297 // Fill in MLD message - Done
298 //
299 MldHead = (IP6_MLD_HEAD *)NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
300 ASSERT (MldHead != NULL);
301 ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
302 MldHead->Head.Type = ICMP_V6_LISTENER_DONE;
303 MldHead->Head.Code = 0;
304 IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
305
306 HeadChecksum = NetblockChecksum ((UINT8 *)MldHead, sizeof (IP6_MLD_HEAD));
307 PseudoChecksum = NetIp6PseudoHeadChecksum (
308 &Head.SourceAddress,
309 &Head.DestinationAddress,
310 IP6_ICMP,
311 sizeof (IP6_MLD_HEAD)
312 );
313
314 MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
315
316 //
317 // Transmit the packet
318 //
319 return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
320}
321
335 IN IP6_SERVICE *IpSb
336 )
337{
338 EFI_IPv6_ADDRESS AllNodes;
339 IP6_MLD_GROUP *Group;
340 EFI_STATUS Status;
341
342 //
343 // Join the link-scope all-nodes multicast address (FF02::1).
344 // This address is started in Idle Listener state and never transitions to
345 // another state, and never sends a Report or Done for that address.
346 //
347
348 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
349
350 Group = Ip6CreateMldEntry (IpSb, &AllNodes, (UINT32)IP6_INFINIT_LIFETIME);
351 if (Group == NULL) {
352 return EFI_OUT_OF_RESOURCES;
353 }
354
355 Status = Ip6GetMulticastMac (IpSb->Mnp, &AllNodes, &Group->Mac);
356 if (EFI_ERROR (Status)) {
357 goto ERROR;
358 }
359
360 //
361 // Configure MNP to receive all-nodes multicast
362 //
363 Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
364 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
365 goto ERROR;
366 }
367
368 return EFI_SUCCESS;
369
370ERROR:
371 RemoveEntryList (&Group->Link);
372 FreePool (Group);
373 return Status;
374}
375
391 IN OUT IP6_PROTOCOL *IpInstance,
392 IN EFI_IPv6_ADDRESS *Group
393 )
394{
395 EFI_IPv6_ADDRESS *GroupList;
396
397 NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
398 ASSERT (Group != NULL && IP6_IS_MULTICAST (Group));
399
400 IpInstance->GroupCount++;
401
402 GroupList = AllocatePool (IpInstance->GroupCount * sizeof (EFI_IPv6_ADDRESS));
403 if (GroupList == NULL) {
404 return EFI_OUT_OF_RESOURCES;
405 }
406
407 if (IpInstance->GroupCount > 1) {
408 ASSERT (IpInstance->GroupList != NULL);
409
410 CopyMem (
411 GroupList,
412 IpInstance->GroupList,
413 (IpInstance->GroupCount - 1) * sizeof (EFI_IPv6_ADDRESS)
414 );
415
416 FreePool (IpInstance->GroupList);
417 }
418
419 IP6_COPY_ADDRESS (GroupList + (IpInstance->GroupCount - 1), Group);
420
421 IpInstance->GroupList = GroupList;
422
423 return EFI_SUCCESS;
424}
425
440 IN OUT IP6_PROTOCOL *IpInstance,
441 IN EFI_IPv6_ADDRESS *Group
442 )
443{
444 UINT32 Index;
445 UINT32 Count;
446
447 Count = IpInstance->GroupCount;
448
449 for (Index = 0; Index < Count; Index++) {
450 if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, Group)) {
451 break;
452 }
453 }
454
455 if (Index == Count) {
456 return EFI_NOT_FOUND;
457 }
458
459 while (Index < Count - 1) {
460 IP6_COPY_ADDRESS (IpInstance->GroupList + Index, IpInstance->GroupList + Index + 1);
461 Index++;
462 }
463
464 ASSERT (IpInstance->GroupCount > 0);
465 IpInstance->GroupCount--;
466
467 return EFI_SUCCESS;
468}
469
484 IN IP6_SERVICE *IpSb,
485 IN IP6_INTERFACE *Interface,
486 IN EFI_IPv6_ADDRESS *Address
487 )
488{
489 IP6_MLD_GROUP *Group;
490 EFI_STATUS Status;
491
492 Group = Ip6FindMldEntry (IpSb, Address);
493 if (Group != NULL) {
494 Group->RefCnt++;
495 return EFI_SUCCESS;
496 }
497
498 //
499 // Repeat the report once or twice after short delays [Unsolicited Report Interval] (default:10s)
500 // Simulate this operation as a Multicast-Address-Specific Query was received for that address.
501 //
502 Group = Ip6CreateMldEntry (IpSb, Address, IP6_UNSOLICITED_REPORT_INTERVAL);
503 if (Group == NULL) {
504 return EFI_OUT_OF_RESOURCES;
505 }
506
507 Group->SendByUs = TRUE;
508
509 Status = Ip6GetMulticastMac (IpSb->Mnp, Address, &Group->Mac);
510 if (EFI_ERROR (Status)) {
511 return Status;
512 }
513
514 Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
515 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
516 goto ERROR;
517 }
518
519 //
520 // Send unsolicited report when a node starts listening to a multicast address
521 //
522 Status = Ip6SendMldReport (IpSb, Interface, Address);
523 if (EFI_ERROR (Status)) {
524 goto ERROR;
525 }
526
527 return EFI_SUCCESS;
528
529ERROR:
530 RemoveEntryList (&Group->Link);
531 FreePool (Group);
532 return Status;
533}
534
548 IN IP6_SERVICE *IpSb,
549 IN EFI_IPv6_ADDRESS *Address
550 )
551{
552 IP6_MLD_GROUP *Group;
553 EFI_STATUS Status;
554
555 Group = Ip6FindMldEntry (IpSb, Address);
556 if (Group == NULL) {
557 return EFI_NOT_FOUND;
558 }
559
560 //
561 // If more than one instance is in the group, decrease
562 // the RefCnt then return.
563 //
564 if ((Group->RefCnt > 0) && (--Group->RefCnt > 0)) {
565 return EFI_SUCCESS;
566 }
567
568 //
569 // If multiple IP6 group addresses are mapped to the same
570 // multicast MAC address, don't configure the MNP to leave
571 // the MAC.
572 //
573 if (Ip6FindMac (&IpSb->MldCtrl, &Group->Mac) == 1) {
574 Status = IpSb->Mnp->Groups (IpSb->Mnp, FALSE, &Group->Mac);
575 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
576 return Status;
577 }
578 }
579
580 //
581 // Send a leave report if we are the last node to report
582 //
583 if (Group->SendByUs) {
584 Status = Ip6SendMldDone (IpSb, Address);
585 if (EFI_ERROR (Status)) {
586 return Status;
587 }
588 }
589
590 RemoveEntryList (&Group->Link);
591 FreePool (Group);
592
593 return EFI_SUCCESS;
594}
595
614 IN IP6_PROTOCOL *IpInstance,
615 IN BOOLEAN JoinFlag,
616 IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
617 )
618{
619 EFI_STATUS Status;
620 IP6_SERVICE *IpSb;
621 UINT32 Index;
622 EFI_IPv6_ADDRESS *Group;
623
624 IpSb = IpInstance->Service;
625
626 if (JoinFlag) {
627 ASSERT (GroupAddress != NULL);
628
629 for (Index = 0; Index < IpInstance->GroupCount; Index++) {
630 if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, GroupAddress)) {
631 return EFI_ALREADY_STARTED;
632 }
633 }
634
635 Status = Ip6JoinGroup (IpSb, IpInstance->Interface, GroupAddress);
636 if (!EFI_ERROR (Status)) {
637 return Ip6CombineGroups (IpInstance, GroupAddress);
638 }
639
640 return Status;
641 }
642
643 //
644 // Leave the group. Leave all the groups if GroupAddress is NULL.
645 //
646 for (Index = IpInstance->GroupCount; Index > 0; Index--) {
647 Group = IpInstance->GroupList + (Index - 1);
648
649 if ((GroupAddress == NULL) || EFI_IP6_EQUAL (Group, GroupAddress)) {
650 Status = Ip6LeaveGroup (IpInstance->Service, Group);
651 if (EFI_ERROR (Status)) {
652 return Status;
653 }
654
655 Ip6RemoveGroup (IpInstance, Group);
656
657 if (IpInstance->GroupCount == 0) {
658 ASSERT (Index == 1);
659 FreePool (IpInstance->GroupList);
660 IpInstance->GroupList = NULL;
661 }
662
663 if (GroupAddress != NULL) {
664 return EFI_SUCCESS;
665 }
666 }
667 }
668
669 return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);
670}
671
693 IN IP6_SERVICE *IpSb,
694 IN UINT16 MaxRespDelay,
695 IN EFI_IPv6_ADDRESS *MulticastAddr,
696 IN OUT IP6_MLD_GROUP *Group
697 )
698{
699 UINT32 Delay;
700 EFI_STATUS Status;
701 UINT32 Random;
702
703 Status = PseudoRandomU32 (&Random);
704 if (EFI_ERROR (Status)) {
705 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
706 return Status;
707 }
708
709 //
710 // If the Query packet specifies a Maximum Response Delay of zero, perform timer
711 // expiration immediately.
712 //
713 if (MaxRespDelay == 0) {
714 Group->DelayTimer = 0;
715 return Ip6SendMldReport (IpSb, NULL, MulticastAddr);
716 }
717
718 Delay = (UINT32)(MaxRespDelay / 1000);
719
720 //
721 // Sets a delay timer to a random value selected from the range [0, Maximum Response Delay]
722 // If a timer is already running, resets it if the request Maximum Response Delay
723 // is less than the remaining value of the running timer.
724 //
725 if ((Group->DelayTimer == 0) || (Delay < Group->DelayTimer)) {
726 Group->DelayTimer = Delay / 4294967295UL * Random;
727 }
728
729 return EFI_SUCCESS;
730}
731
747 IN IP6_SERVICE *IpSb,
748 IN EFI_IP6_HEADER *Head,
749 IN NET_BUF *Packet
750 )
751{
752 EFI_IPv6_ADDRESS AllNodes;
753 IP6_MLD_GROUP *Group;
754 IP6_MLD_HEAD MldPacket;
755 LIST_ENTRY *Entry;
756 EFI_STATUS Status;
757
758 Status = EFI_INVALID_PARAMETER;
759
760 //
761 // Check the validity of the packet, generic query or specific query
762 //
763 if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
764 goto Exit;
765 }
766
767 if ((Head->HopLimit != 1) || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
768 goto Exit;
769 }
770
771 //
772 // The Packet points to MLD report raw data without Hop-By-Hop option.
773 //
774 NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *)&MldPacket);
775 MldPacket.MaxRespDelay = NTOHS (MldPacket.MaxRespDelay);
776
777 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
778 if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &AllNodes)) {
779 //
780 // Receives a Multicast-Address-Specific Query, check it firstly
781 //
782 if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
783 goto Exit;
784 }
785
786 //
787 // The node is not listening but it receives the specific query. Just return.
788 //
789 Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
790 if (Group == NULL) {
791 Status = EFI_SUCCESS;
792 goto Exit;
793 }
794
795 Status = Ip6UpdateDelayTimer (
796 IpSb,
797 MldPacket.MaxRespDelay,
798 &MldPacket.Group,
799 Group
800 );
801 goto Exit;
802 }
803
804 //
805 // Receives a General Query, sets a delay timer for each multicast address it is listening
806 //
807 NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
808 Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
809 Status = Ip6UpdateDelayTimer (IpSb, MldPacket.MaxRespDelay, &Group->Address, Group);
810 if (EFI_ERROR (Status)) {
811 goto Exit;
812 }
813 }
814
815 Status = EFI_SUCCESS;
816
817Exit:
818 NetbufFree (Packet);
819 return Status;
820}
821
836 IN IP6_SERVICE *IpSb,
837 IN EFI_IP6_HEADER *Head,
838 IN NET_BUF *Packet
839 )
840{
841 IP6_MLD_HEAD MldPacket;
842 IP6_MLD_GROUP *Group;
843 EFI_STATUS Status;
844
845 Status = EFI_INVALID_PARAMETER;
846
847 //
848 // Validate the incoming message, if invalid, drop it.
849 //
850 if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
851 goto Exit;
852 }
853
854 if ((Head->HopLimit != 1) || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
855 goto Exit;
856 }
857
858 //
859 // The Packet points to MLD report raw data without Hop-By-Hop option.
860 //
861 NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *)&MldPacket);
862 if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
863 goto Exit;
864 }
865
866 Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
867 if (Group == NULL) {
868 goto Exit;
869 }
870
871 //
872 // The report is sent by another node, stop its own timer relates to the multicast address and clear
873 //
874
875 if (!Group->SendByUs) {
876 Group->DelayTimer = 0;
877 }
878
879 Status = EFI_SUCCESS;
880
881Exit:
882 NetbufFree (Packet);
883 return Status;
884}
885
893VOID
895 IN IP6_SERVICE *IpSb
896 )
897{
898 IP6_MLD_GROUP *Group;
899 LIST_ENTRY *Entry;
900
901 //
902 // Send solicited report when timer expires
903 //
904 NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
905 Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
906 if ((Group->DelayTimer > 0) && (--Group->DelayTimer == 0)) {
907 Ip6SendMldReport (IpSb, NULL, &Group->Address);
908 }
909 }
910}
UINT64 UINTN
INT64 INTN
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS Ip6GetMulticastMac(IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp, IN EFI_IPv6_ADDRESS *Multicast, OUT EFI_MAC_ADDRESS *Mac)
Definition: Ip6Common.c:635
EFI_STATUS Ip6SetToAllNodeMulticast(IN BOOLEAN Router, IN UINT8 Scope, OUT EFI_IPv6_ADDRESS *Ip6Addr)
Definition: Ip6Common.c:103
EFI_STATUS Ip6LeaveGroup(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Address)
Definition: Ip6Mld.c:547
EFI_STATUS Ip6UpdateDelayTimer(IN IP6_SERVICE *IpSb, IN UINT16 MaxRespDelay, IN EFI_IPv6_ADDRESS *MulticastAddr, IN OUT IP6_MLD_GROUP *Group)
Definition: Ip6Mld.c:692
IP6_MLD_GROUP * Ip6CreateMldEntry(IN OUT IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *MulticastAddr, IN UINT32 DelayTimer)
Definition: Ip6Mld.c:23
EFI_STATUS Ip6SendMldDone(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Mld.c:231
EFI_STATUS Ip6ProcessMldReport(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Mld.c:835
EFI_STATUS Ip6InitMld(IN IP6_SERVICE *IpSb)
Definition: Ip6Mld.c:334
EFI_STATUS Ip6SendMldReport(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface OPTIONAL, IN EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Mld.c:127
EFI_STATUS Ip6Groups(IN IP6_PROTOCOL *IpInstance, IN BOOLEAN JoinFlag, IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL)
Definition: Ip6Mld.c:613
IP6_MLD_GROUP * Ip6FindMldEntry(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *MulticastAddr)
Definition: Ip6Mld.c:56
INTN Ip6FindMac(IN IP6_MLD_SERVICE_DATA *MldCtrl, IN EFI_MAC_ADDRESS *Mac)
Definition: Ip6Mld.c:90
VOID Ip6MldTimerTicking(IN IP6_SERVICE *IpSb)
Definition: Ip6Mld.c:894
EFI_STATUS Ip6ProcessMldQuery(IN IP6_SERVICE *IpSb, IN EFI_IP6_HEADER *Head, IN NET_BUF *Packet)
Definition: Ip6Mld.c:746
EFI_STATUS Ip6JoinGroup(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface, IN EFI_IPv6_ADDRESS *Address)
Definition: Ip6Mld.c:483
EFI_STATUS Ip6CombineGroups(IN OUT IP6_PROTOCOL *IpInstance, IN EFI_IPv6_ADDRESS *Group)
Definition: Ip6Mld.c:390
EFI_STATUS Ip6RemoveGroup(IN OUT IP6_PROTOCOL *IpInstance, IN EFI_IPv6_ADDRESS *Group)
Definition: Ip6Mld.c:439
EFI_STATUS Ip6FillHopByHop(OUT UINT8 *Buffer, IN OUT UINTN *BufferLen, IN UINT8 NextHeader)
Definition: Ip6Option.c:663
EFI_STATUS Ip6Output(IN IP6_SERVICE *IpSb, IN IP6_INTERFACE *Interface OPTIONAL, IN IP6_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN EFI_IP6_HEADER *Head, IN UINT8 *ExtHdrs, IN UINT32 ExtHdrsLen, IN IP6_FRAME_CALLBACK Callback, IN VOID *Context)
Definition: Ip6Output.c:476
VOID Ip6SysPacketSent(NET_BUF *Packet, EFI_STATUS IoStatus, UINT32 LinkFlag, VOID *Context)
Definition: Ip6Output.c:337
#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
UINT16 EFIAPI NetIp6PseudoHeadChecksum(IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *Dst, IN UINT8 NextHeader, IN UINT32 Len)
Definition: NetBuffer.c:1777
UINT16 EFIAPI NetblockChecksum(IN UINT8 *Bulk, IN UINT32 Len)
Definition: NetBuffer.c:1615
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
BOOLEAN EFIAPI NetIp6IsLinkLocalAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:796
UINT16 EFIAPI NetAddChecksum(IN UINT16 Checksum1, IN UINT16 Checksum2)
Definition: NetBuffer.c:1658
NET_BUF *EFIAPI 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
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112