TianoCore EDK2 master
Loading...
Searching...
No Matches
Dhcp6Impl.c
Go to the documentation of this file.
1
10#include "Dhcp6Impl.h"
11
12//
13// Well-known multi-cast address defined in section-24.1 of rfc-3315
14//
15// ALL_DHCP_Relay_Agents_and_Servers address: FF02::1:2
16//
17EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {
18 { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }
19};
20
21EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate = {
31};
32
64EFIAPI
67 )
68{
69 EFI_STATUS Status;
70 EFI_TPL OldTpl;
71 DHCP6_INSTANCE *Instance;
72 DHCP6_SERVICE *Service;
73 EFI_STATUS MediaStatus;
74
75 if (This == NULL) {
76 return EFI_INVALID_PARAMETER;
77 }
78
79 Instance = DHCP6_INSTANCE_FROM_THIS (This);
80 Service = Instance->Service;
81
82 //
83 // The instance hasn't been configured.
84 //
85 if (Instance->Config == NULL) {
86 return EFI_ACCESS_DENIED;
87 }
88
89 ASSERT (Instance->IaCb.Ia != NULL);
90
91 //
92 // The instance has already been started.
93 //
94 if (Instance->IaCb.Ia->State != Dhcp6Init) {
95 return EFI_ALREADY_STARTED;
96 }
97
98 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
99
100 //
101 // Check Media Status.
102 //
103 MediaStatus = EFI_SUCCESS;
104 NetLibDetectMediaWaitTimeout (Service->Controller, DHCP_CHECK_MEDIA_WAITING_TIME, &MediaStatus);
105 if (MediaStatus != EFI_SUCCESS) {
106 Status = EFI_NO_MEDIA;
107 goto ON_ERROR;
108 }
109
110 Instance->UdpSts = EFI_ALREADY_STARTED;
111
112 //
113 // Send the solicit message to start S.A.R.R process.
114 //
115 Status = Dhcp6SendSolicitMsg (Instance);
116
117 if (EFI_ERROR (Status)) {
118 goto ON_ERROR;
119 }
120
121 //
122 // Register receive callback for the stateful exchange process.
123 //
124 Status = UdpIoRecvDatagram (
125 Service->UdpIo,
127 Service,
128 0
129 );
130
131 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
132 goto ON_ERROR;
133 }
134
135 gBS->RestoreTPL (OldTpl);
136
137 //
138 // Poll udp out of the net tpl if synchronous call.
139 //
140 if (Instance->Config->IaInfoEvent == NULL) {
141 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
142 Service->UdpIo->Protocol.Udp6->Poll (Service->UdpIo->Protocol.Udp6);
143 }
144
145 return Instance->UdpSts;
146 }
147
148 return EFI_SUCCESS;
149
150ON_ERROR:
151
152 gBS->RestoreTPL (OldTpl);
153 return Status;
154}
155
172EFIAPI
175 )
176{
177 EFI_TPL OldTpl;
178 EFI_STATUS Status;
179 EFI_UDP6_PROTOCOL *Udp6;
180 DHCP6_INSTANCE *Instance;
181 DHCP6_SERVICE *Service;
182
183 if (This == NULL) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 Instance = DHCP6_INSTANCE_FROM_THIS (This);
188 Service = Instance->Service;
189 Udp6 = Service->UdpIo->Protocol.Udp6;
190 Status = EFI_SUCCESS;
191
192 //
193 // The instance hasn't been configured.
194 //
195 if (Instance->Config == NULL) {
196 return Status;
197 }
198
199 ASSERT (Instance->IaCb.Ia != NULL);
200
201 //
202 // No valid REPLY message received yet, cleanup this instance directly.
203 //
204 if ((Instance->IaCb.Ia->State == Dhcp6Init) ||
205 (Instance->IaCb.Ia->State == Dhcp6Selecting) ||
206 (Instance->IaCb.Ia->State == Dhcp6Requesting)
207 )
208 {
209 goto ON_EXIT;
210 }
211
212 //
213 // Release the current ready Ia.
214 //
215 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
216
217 Instance->UdpSts = EFI_ALREADY_STARTED;
218 Status = Dhcp6SendReleaseMsg (Instance, Instance->IaCb.Ia);
219 gBS->RestoreTPL (OldTpl);
220 if (EFI_ERROR (Status)) {
221 goto ON_EXIT;
222 }
223
224 //
225 // Poll udp out of the net tpl if synchronous call.
226 //
227 if (Instance->Config->IaInfoEvent == NULL) {
228 ASSERT (Udp6 != NULL);
229 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
230 Udp6->Poll (Udp6);
231 }
232
233 Status = Instance->UdpSts;
234 }
235
236ON_EXIT:
237 //
238 // Clean up the session data for the released Ia.
239 //
240 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
242 gBS->RestoreTPL (OldTpl);
243
244 return Status;
245}
246
263EFIAPI
266 OUT EFI_DHCP6_MODE_DATA *Dhcp6ModeData OPTIONAL,
267 OUT EFI_DHCP6_CONFIG_DATA *Dhcp6ConfigData OPTIONAL
268 )
269{
270 EFI_TPL OldTpl;
271 EFI_DHCP6_IA *Ia;
272 DHCP6_INSTANCE *Instance;
273 DHCP6_SERVICE *Service;
274 UINT32 IaSize;
275 UINT32 IdSize;
276
277 if ((This == NULL) || ((Dhcp6ModeData == NULL) && (Dhcp6ConfigData == NULL))) {
278 return EFI_INVALID_PARAMETER;
279 }
280
281 Instance = DHCP6_INSTANCE_FROM_THIS (This);
282 Service = Instance->Service;
283
284 if ((Instance->Config == NULL) && (Dhcp6ConfigData != NULL)) {
285 return EFI_ACCESS_DENIED;
286 }
287
288 ASSERT (Service->ClientId != NULL);
289
290 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
291
292 //
293 // User needs a copy of instance config data.
294 //
295 if (Dhcp6ConfigData != NULL) {
296 ZeroMem (Dhcp6ConfigData, sizeof (EFI_DHCP6_CONFIG_DATA));
297 //
298 // Duplicate config data, including all reference buffers.
299 //
300 if (EFI_ERROR (Dhcp6CopyConfigData (Dhcp6ConfigData, Instance->Config))) {
301 goto ON_ERROR;
302 }
303 }
304
305 //
306 // User need a copy of instance mode data.
307 //
308 if (Dhcp6ModeData != NULL) {
309 ZeroMem (Dhcp6ModeData, sizeof (EFI_DHCP6_MODE_DATA));
310 //
311 // Duplicate a copy of EFI_DHCP6_DUID for client Id.
312 //
313 IdSize = Service->ClientId->Length + sizeof (Service->ClientId->Length);
314
315 Dhcp6ModeData->ClientId = AllocateZeroPool (IdSize);
316 if (Dhcp6ModeData->ClientId == NULL) {
317 goto ON_ERROR;
318 }
319
320 CopyMem (
321 Dhcp6ModeData->ClientId,
322 Service->ClientId,
323 IdSize
324 );
325
326 Ia = Instance->IaCb.Ia;
327 if (Ia != NULL) {
328 //
329 // Duplicate a copy of EFI_DHCP6_IA for configured Ia.
330 //
331 IaSize = sizeof (EFI_DHCP6_IA) + (Ia->IaAddressCount -1) * sizeof (EFI_DHCP6_IA_ADDRESS);
332
333 Dhcp6ModeData->Ia = AllocateZeroPool (IaSize);
334 if (Dhcp6ModeData->Ia == NULL) {
335 goto ON_ERROR;
336 }
337
338 CopyMem (
339 Dhcp6ModeData->Ia,
340 Ia,
341 IaSize
342 );
343
344 //
345 // Duplicate a copy of reply packet if has.
346 //
347 if (Ia->ReplyPacket != NULL) {
348 Dhcp6ModeData->Ia->ReplyPacket = AllocateZeroPool (Ia->ReplyPacket->Size);
349 if (Dhcp6ModeData->Ia->ReplyPacket == NULL) {
350 goto ON_ERROR;
351 }
352
353 CopyMem (
354 Dhcp6ModeData->Ia->ReplyPacket,
355 Ia->ReplyPacket,
356 Ia->ReplyPacket->Size
357 );
358 }
359 }
360 }
361
362 gBS->RestoreTPL (OldTpl);
363
364 return EFI_SUCCESS;
365
366ON_ERROR:
367
368 if (Dhcp6ConfigData != NULL) {
369 Dhcp6CleanupConfigData (Dhcp6ConfigData);
370 }
371
372 if (Dhcp6ModeData != NULL) {
373 Dhcp6CleanupModeData (Dhcp6ModeData);
374 }
375
376 gBS->RestoreTPL (OldTpl);
377
378 return EFI_OUT_OF_RESOURCES;
379}
380
410EFIAPI
413 IN EFI_DHCP6_CONFIG_DATA *Dhcp6CfgData OPTIONAL
414 )
415{
416 EFI_TPL OldTpl;
417 EFI_STATUS Status;
418 LIST_ENTRY *Entry;
419 DHCP6_INSTANCE *Other;
420 DHCP6_INSTANCE *Instance;
421 DHCP6_SERVICE *Service;
422 UINTN Index;
423
424 if (This == NULL) {
425 return EFI_INVALID_PARAMETER;
426 }
427
428 Instance = DHCP6_INSTANCE_FROM_THIS (This);
429 Service = Instance->Service;
430
431 //
432 // Check the parameter of configure data.
433 //
434 if (Dhcp6CfgData != NULL) {
435 if ((Dhcp6CfgData->OptionCount > 0) && (Dhcp6CfgData->OptionList == NULL)) {
436 return EFI_INVALID_PARAMETER;
437 }
438
439 if (Dhcp6CfgData->OptionList != NULL) {
440 for (Index = 0; Index < Dhcp6CfgData->OptionCount; Index++) {
441 if ((Dhcp6CfgData->OptionList[Index]->OpCode == Dhcp6OptClientId) ||
442 (Dhcp6CfgData->OptionList[Index]->OpCode == Dhcp6OptRapidCommit) ||
443 (Dhcp6CfgData->OptionList[Index]->OpCode == Dhcp6OptReconfigureAccept) ||
444 (Dhcp6CfgData->OptionList[Index]->OpCode == Dhcp6OptIana) ||
445 (Dhcp6CfgData->OptionList[Index]->OpCode == Dhcp6OptIata)
446 )
447 {
448 return EFI_INVALID_PARAMETER;
449 }
450 }
451 }
452
453 if ((Dhcp6CfgData->IaDescriptor.Type != EFI_DHCP6_IA_TYPE_NA) &&
454 (Dhcp6CfgData->IaDescriptor.Type != EFI_DHCP6_IA_TYPE_TA)
455 )
456 {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 if ((Dhcp6CfgData->IaInfoEvent == NULL) && (Dhcp6CfgData->SolicitRetransmission == NULL)) {
461 return EFI_INVALID_PARAMETER;
462 }
463
464 if ((Dhcp6CfgData->SolicitRetransmission != NULL) &&
465 (Dhcp6CfgData->SolicitRetransmission->Mrc == 0) &&
466 (Dhcp6CfgData->SolicitRetransmission->Mrd == 0)
467 )
468 {
469 return EFI_INVALID_PARAMETER;
470 }
471
472 //
473 // Make sure the (IaId, IaType) is unique over all the instances.
474 //
475 NET_LIST_FOR_EACH (Entry, &Service->Child) {
476 Other = NET_LIST_USER_STRUCT (Entry, DHCP6_INSTANCE, Link);
477 if ((Other->IaCb.Ia != NULL) &&
478 (Other->IaCb.Ia->Descriptor.Type == Dhcp6CfgData->IaDescriptor.Type) &&
479 (Other->IaCb.Ia->Descriptor.IaId == Dhcp6CfgData->IaDescriptor.IaId)
480 )
481 {
482 return EFI_INVALID_PARAMETER;
483 }
484 }
485 }
486
487 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
488
489 if (Dhcp6CfgData != NULL) {
490 //
491 // It's not allowed to configure one instance twice without configure null.
492 //
493 if (Instance->Config != NULL) {
494 gBS->RestoreTPL (OldTpl);
495 return EFI_ACCESS_DENIED;
496 }
497
498 //
499 // Duplicate config data including all reference buffers.
500 //
501 Instance->Config = AllocateZeroPool (sizeof (EFI_DHCP6_CONFIG_DATA));
502 if (Instance->Config == NULL) {
503 gBS->RestoreTPL (OldTpl);
504 return EFI_OUT_OF_RESOURCES;
505 }
506
507 Status = Dhcp6CopyConfigData (Instance->Config, Dhcp6CfgData);
508 if (EFI_ERROR (Status)) {
509 FreePool (Instance->Config);
510 gBS->RestoreTPL (OldTpl);
511 return EFI_OUT_OF_RESOURCES;
512 }
513
514 //
515 // Initialize the Ia descriptor from the config data, and leave the other
516 // fields of the Ia as default value 0.
517 //
518 Instance->IaCb.Ia = AllocateZeroPool (sizeof (EFI_DHCP6_IA));
519 if (Instance->IaCb.Ia == NULL) {
520 Dhcp6CleanupConfigData (Instance->Config);
521 FreePool (Instance->Config);
522 gBS->RestoreTPL (OldTpl);
523 return EFI_OUT_OF_RESOURCES;
524 }
525
526 CopyMem (
527 &Instance->IaCb.Ia->Descriptor,
528 &Dhcp6CfgData->IaDescriptor,
530 );
531 } else {
532 if (Instance->Config == NULL) {
533 ASSERT (Instance->IaCb.Ia == NULL);
534 gBS->RestoreTPL (OldTpl);
535 return EFI_SUCCESS;
536 }
537
538 //
539 // It's not allowed to configure a started instance as null.
540 //
541 if (Instance->IaCb.Ia->State != Dhcp6Init) {
542 gBS->RestoreTPL (OldTpl);
543 return EFI_ACCESS_DENIED;
544 }
545
546 Dhcp6CleanupConfigData (Instance->Config);
547 FreePool (Instance->Config);
548 Instance->Config = NULL;
549
550 FreePool (Instance->IaCb.Ia);
551 Instance->IaCb.Ia = NULL;
552 }
553
554 gBS->RestoreTPL (OldTpl);
555
556 return EFI_SUCCESS;
557}
558
601EFIAPI
604 IN BOOLEAN SendClientId,
605 IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
606 IN UINT32 OptionCount,
607 IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL,
608 IN EFI_DHCP6_RETRANSMISSION *Retransmission,
609 IN EFI_EVENT TimeoutEvent OPTIONAL,
610 IN EFI_DHCP6_INFO_CALLBACK ReplyCallback,
611 IN VOID *CallbackContext OPTIONAL
612 )
613{
614 EFI_STATUS Status;
615 DHCP6_INSTANCE *Instance;
616 DHCP6_SERVICE *Service;
617 UINTN Index;
618 EFI_EVENT Timer;
619 EFI_STATUS TimerStatus;
620 UINTN GetMappingTimeOut;
621
622 if ((This == NULL) || (OptionRequest == NULL) || (Retransmission == NULL) || (ReplyCallback == NULL)) {
623 return EFI_INVALID_PARAMETER;
624 }
625
626 if ((Retransmission != NULL) && (Retransmission->Mrc == 0) && (Retransmission->Mrd == 0)) {
627 return EFI_INVALID_PARAMETER;
628 }
629
630 if ((OptionCount > 0) && (OptionList == NULL)) {
631 return EFI_INVALID_PARAMETER;
632 }
633
634 if (OptionList != NULL) {
635 for (Index = 0; Index < OptionCount; Index++) {
636 if ((OptionList[Index]->OpCode == Dhcp6OptClientId) || (OptionList[Index]->OpCode == Dhcp6OptRequestOption)) {
637 return EFI_INVALID_PARAMETER;
638 }
639 }
640 }
641
642 Instance = DHCP6_INSTANCE_FROM_THIS (This);
643 Service = Instance->Service;
644
645 Status = Dhcp6StartInfoRequest (
646 Instance,
647 SendClientId,
648 OptionRequest,
649 OptionCount,
650 OptionList,
651 Retransmission,
652 TimeoutEvent,
653 ReplyCallback,
654 CallbackContext
655 );
656 if (Status == EFI_NO_MAPPING) {
657 //
658 // The link local address is not ready, wait for some time and restart
659 // the DHCP6 information request process.
660 //
661 Status = Dhcp6GetMappingTimeOut (Service->Ip6Cfg, &GetMappingTimeOut);
662 if (EFI_ERROR (Status)) {
663 return Status;
664 }
665
666 Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
667 if (EFI_ERROR (Status)) {
668 return Status;
669 }
670
671 //
672 // Start the timer, wait for link local address DAD to finish.
673 //
674 Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);
675 if (EFI_ERROR (Status)) {
676 gBS->CloseEvent (Timer);
677 return Status;
678 }
679
680 do {
681 TimerStatus = gBS->CheckEvent (Timer);
682 if (!EFI_ERROR (TimerStatus)) {
683 Status = Dhcp6StartInfoRequest (
684 Instance,
685 SendClientId,
686 OptionRequest,
687 OptionCount,
688 OptionList,
689 Retransmission,
690 TimeoutEvent,
691 ReplyCallback,
692 CallbackContext
693 );
694 }
695 } while (TimerStatus == EFI_NOT_READY);
696
697 gBS->CloseEvent (Timer);
698 }
699
700 if (EFI_ERROR (Status)) {
701 return Status;
702 }
703
704 //
705 // Poll udp out of the net tpl if synchronous call.
706 //
707 if (TimeoutEvent == NULL) {
708 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
709 Service->UdpIo->Protocol.Udp6->Poll (Service->UdpIo->Protocol.Udp6);
710 }
711
712 return Instance->UdpSts;
713 }
714
715 return EFI_SUCCESS;
716}
717
764EFIAPI
767 IN BOOLEAN RebindRequest
768 )
769{
770 EFI_STATUS Status;
771 EFI_TPL OldTpl;
772 DHCP6_INSTANCE *Instance;
773 DHCP6_SERVICE *Service;
774
775 if (This == NULL) {
776 return EFI_INVALID_PARAMETER;
777 }
778
779 Instance = DHCP6_INSTANCE_FROM_THIS (This);
780 Service = Instance->Service;
781
782 //
783 // The instance hasn't been configured.
784 //
785 if (Instance->Config == NULL) {
786 return EFI_ACCESS_DENIED;
787 }
788
789 ASSERT (Instance->IaCb.Ia != NULL);
790
791 //
792 // The instance has already entered renewing or rebinding state.
793 //
794 if (((Instance->IaCb.Ia->State == Dhcp6Rebinding) && RebindRequest) ||
795 ((Instance->IaCb.Ia->State == Dhcp6Renewing) && !RebindRequest)
796 )
797 {
798 return EFI_ALREADY_STARTED;
799 }
800
801 if (Instance->IaCb.Ia->State != Dhcp6Bound) {
802 return EFI_ACCESS_DENIED;
803 }
804
805 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
806 Instance->UdpSts = EFI_ALREADY_STARTED;
807
808 //
809 // Send renew/rebind message to start exchange process.
810 //
811 Status = Dhcp6SendRenewRebindMsg (Instance, RebindRequest);
812
813 if (EFI_ERROR (Status)) {
814 goto ON_ERROR;
815 }
816
817 //
818 // Register receive callback for the stateful exchange process.
819 //
820 Status = UdpIoRecvDatagram (
821 Service->UdpIo,
823 Service,
824 0
825 );
826
827 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
828 goto ON_ERROR;
829 }
830
831 gBS->RestoreTPL (OldTpl);
832
833 //
834 // Poll udp out of the net tpl if synchronous call.
835 //
836 if (Instance->Config->IaInfoEvent == NULL) {
837 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
838 Service->UdpIo->Protocol.Udp6->Poll (Service->UdpIo->Protocol.Udp6);
839 }
840
841 return Instance->UdpSts;
842 }
843
844 return EFI_SUCCESS;
845
846ON_ERROR:
847
848 gBS->RestoreTPL (OldTpl);
849 return Status;
850}
851
885EFIAPI
888 IN UINT32 AddressCount,
889 IN EFI_IPv6_ADDRESS *Addresses
890 )
891{
892 EFI_STATUS Status;
893 EFI_TPL OldTpl;
894 EFI_DHCP6_IA *DecIa;
895 DHCP6_INSTANCE *Instance;
896 DHCP6_SERVICE *Service;
897
898 if ((This == NULL) || (AddressCount == 0) || (Addresses == NULL)) {
899 return EFI_INVALID_PARAMETER;
900 }
901
902 Instance = DHCP6_INSTANCE_FROM_THIS (This);
903 Service = Instance->Service;
904
905 //
906 // The instance hasn't been configured.
907 //
908 if (Instance->Config == NULL) {
909 return EFI_ACCESS_DENIED;
910 }
911
912 ASSERT (Instance->IaCb.Ia != NULL);
913
914 if (Instance->IaCb.Ia->State != Dhcp6Bound) {
915 return EFI_ACCESS_DENIED;
916 }
917
918 //
919 // Check whether all the declined addresses belongs to the configured Ia.
920 //
921 Status = Dhcp6CheckAddress (Instance->IaCb.Ia, AddressCount, Addresses);
922
923 if (EFI_ERROR (Status)) {
924 return Status;
925 }
926
927 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
928 Instance->UdpSts = EFI_ALREADY_STARTED;
929
930 //
931 // Deprive of all the declined addresses from the configured Ia, and create a
932 // DeclineIa used to create decline message.
933 //
934 DecIa = Dhcp6DepriveAddress (Instance->IaCb.Ia, AddressCount, Addresses);
935
936 if (DecIa == NULL) {
937 Status = EFI_OUT_OF_RESOURCES;
938 goto ON_ERROR;
939 }
940
941 //
942 // Send the decline message to start exchange process.
943 //
944 Status = Dhcp6SendDeclineMsg (Instance, DecIa);
945
946 if (EFI_ERROR (Status)) {
947 goto ON_ERROR;
948 }
949
950 //
951 // Register receive callback for the stateful exchange process.
952 //
953 Status = UdpIoRecvDatagram (
954 Service->UdpIo,
956 Service,
957 0
958 );
959
960 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
961 goto ON_ERROR;
962 }
963
964 FreePool (DecIa);
965 gBS->RestoreTPL (OldTpl);
966
967 //
968 // Poll udp out of the net tpl if synchronous call.
969 //
970 if (Instance->Config->IaInfoEvent == NULL) {
971 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
972 Service->UdpIo->Protocol.Udp6->Poll (Service->UdpIo->Protocol.Udp6);
973 }
974
975 return Instance->UdpSts;
976 }
977
978 return EFI_SUCCESS;
979
980ON_ERROR:
981
982 if (DecIa != NULL) {
983 FreePool (DecIa);
984 }
985
986 gBS->RestoreTPL (OldTpl);
987
988 return Status;
989}
990
1026EFIAPI
1028 IN EFI_DHCP6_PROTOCOL *This,
1029 IN UINT32 AddressCount,
1030 IN EFI_IPv6_ADDRESS *Addresses
1031 )
1032{
1033 EFI_STATUS Status;
1034 EFI_TPL OldTpl;
1035 EFI_DHCP6_IA *RelIa;
1036 DHCP6_INSTANCE *Instance;
1037 DHCP6_SERVICE *Service;
1038
1039 if ((This == NULL) || ((AddressCount != 0) && (Addresses == NULL))) {
1040 return EFI_INVALID_PARAMETER;
1041 }
1042
1043 Instance = DHCP6_INSTANCE_FROM_THIS (This);
1044 Service = Instance->Service;
1045
1046 //
1047 // The instance hasn't been configured.
1048 //
1049 if (Instance->Config == NULL) {
1050 return EFI_ACCESS_DENIED;
1051 }
1052
1053 ASSERT (Instance->IaCb.Ia != NULL);
1054
1055 if (Instance->IaCb.Ia->State != Dhcp6Bound) {
1056 return EFI_ACCESS_DENIED;
1057 }
1058
1059 //
1060 // Check whether all the released addresses belongs to the configured Ia.
1061 //
1062 Status = Dhcp6CheckAddress (Instance->IaCb.Ia, AddressCount, Addresses);
1063
1064 if (EFI_ERROR (Status)) {
1065 return Status;
1066 }
1067
1068 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1069 Instance->UdpSts = EFI_ALREADY_STARTED;
1070
1071 //
1072 // Deprive of all the released addresses from the configured Ia, and create a
1073 // ReleaseIa used to create release message.
1074 //
1075 RelIa = Dhcp6DepriveAddress (Instance->IaCb.Ia, AddressCount, Addresses);
1076
1077 if (RelIa == NULL) {
1078 Status = EFI_OUT_OF_RESOURCES;
1079 goto ON_ERROR;
1080 }
1081
1082 //
1083 // Send the release message to start exchange process.
1084 //
1085 Status = Dhcp6SendReleaseMsg (Instance, RelIa);
1086
1087 if (EFI_ERROR (Status)) {
1088 goto ON_ERROR;
1089 }
1090
1091 //
1092 // Register receive callback for the stateful exchange process.
1093 //
1094 Status = UdpIoRecvDatagram (
1095 Service->UdpIo,
1097 Service,
1098 0
1099 );
1100
1101 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
1102 goto ON_ERROR;
1103 }
1104
1105 FreePool (RelIa);
1106 gBS->RestoreTPL (OldTpl);
1107
1108 //
1109 // Poll udp out of the net tpl if synchronous call.
1110 //
1111 if (Instance->Config->IaInfoEvent == NULL) {
1112 while (Instance->UdpSts == EFI_ALREADY_STARTED) {
1113 Service->UdpIo->Protocol.Udp6->Poll (Service->UdpIo->Protocol.Udp6);
1114 }
1115
1116 return Instance->UdpSts;
1117 }
1118
1119 return EFI_SUCCESS;
1120
1121ON_ERROR:
1122
1123 if (RelIa != NULL) {
1124 FreePool (RelIa);
1125 }
1126
1127 gBS->RestoreTPL (OldTpl);
1128
1129 return Status;
1130}
1131
1149EFIAPI
1151 IN EFI_DHCP6_PROTOCOL *This,
1152 IN EFI_DHCP6_PACKET *Packet,
1153 IN OUT UINT32 *OptionCount,
1154 OUT EFI_DHCP6_PACKET_OPTION *PacketOptionList[] OPTIONAL
1155 )
1156{
1157 UINT32 OptCnt;
1158 UINT32 OptLen;
1159 UINT16 DataLen;
1160 UINT8 *Start;
1161 UINT8 *End;
1162
1163 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
1164 return EFI_INVALID_PARAMETER;
1165 }
1166
1167 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
1168 return EFI_INVALID_PARAMETER;
1169 }
1170
1171 if ((Packet->Length > Packet->Size) || (Packet->Length < sizeof (EFI_DHCP6_HEADER))) {
1172 return EFI_INVALID_PARAMETER;
1173 }
1174
1175 //
1176 // The format of Dhcp6 option:
1177 //
1178 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1179 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1180 // | option-code | option-len (option data) |
1181 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1182 // | option-data |
1183 // | (option-len octets) |
1184 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1185 //
1186
1187 OptCnt = 0;
1188 OptLen = Packet->Length - sizeof (EFI_DHCP6_HEADER);
1189 Start = Packet->Dhcp6.Option;
1190 End = Start + OptLen;
1191
1192 //
1193 // Calculate the number of option in the packet.
1194 //
1195 while (Start < End) {
1196 DataLen = ((EFI_DHCP6_PACKET_OPTION *)Start)->OpLen;
1197 Start += (NTOHS (DataLen) + 4);
1198 OptCnt++;
1199 }
1200
1201 //
1202 // It will return buffer too small if pass-in option count is smaller than the
1203 // actual count of options in the packet.
1204 //
1205 if (OptCnt > *OptionCount) {
1206 *OptionCount = OptCnt;
1207 return EFI_BUFFER_TOO_SMALL;
1208 }
1209
1210 ZeroMem (
1211 PacketOptionList,
1212 (*OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *))
1213 );
1214
1215 OptCnt = 0;
1216 Start = Packet->Dhcp6.Option;
1217
1218 while (Start < End) {
1219 PacketOptionList[OptCnt] = (EFI_DHCP6_PACKET_OPTION *)Start;
1220 DataLen = ((EFI_DHCP6_PACKET_OPTION *)Start)->OpLen;
1221 Start += (NTOHS (DataLen) + 4);
1222 OptCnt++;
1223 }
1224
1225 return EFI_SUCCESS;
1226}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define EFI_DHCP6_IA_TYPE_NA
Definition: Dhcp6.h:134
EFI_STATUS(EFIAPI * EFI_DHCP6_INFO_CALLBACK)(IN EFI_DHCP6_PROTOCOL *This, IN VOID *Context, IN EFI_DHCP6_PACKET *Packet)
Definition: Dhcp6.h:397
@ Dhcp6Requesting
Definition: Dhcp6.h:43
@ Dhcp6Bound
Definition: Dhcp6.h:63
@ Dhcp6Selecting
Definition: Dhcp6.h:38
@ Dhcp6Rebinding
Definition: Dhcp6.h:73
@ Dhcp6Renewing
Definition: Dhcp6.h:68
@ Dhcp6Init
Definition: Dhcp6.h:33
#define EFI_DHCP6_IA_TYPE_TA
Definition: Dhcp6.h:138
EFI_STATUS EFIAPI EfiDhcp6Release(IN EFI_DHCP6_PROTOCOL *This, IN UINT32 AddressCount, IN EFI_IPv6_ADDRESS *Addresses)
Definition: Dhcp6Impl.c:1027
EFI_STATUS EFIAPI EfiDhcp6Decline(IN EFI_DHCP6_PROTOCOL *This, IN UINT32 AddressCount, IN EFI_IPv6_ADDRESS *Addresses)
Definition: Dhcp6Impl.c:886
EFI_STATUS EFIAPI EfiDhcp6Parse(IN EFI_DHCP6_PROTOCOL *This, IN EFI_DHCP6_PACKET *Packet, IN OUT UINT32 *OptionCount, OUT EFI_DHCP6_PACKET_OPTION *PacketOptionList[] OPTIONAL)
Definition: Dhcp6Impl.c:1150
EFI_STATUS EFIAPI EfiDhcp6Configure(IN EFI_DHCP6_PROTOCOL *This, IN EFI_DHCP6_CONFIG_DATA *Dhcp6CfgData OPTIONAL)
Definition: Dhcp6Impl.c:411
EFI_STATUS EFIAPI EfiDhcp6InfoRequest(IN EFI_DHCP6_PROTOCOL *This, IN BOOLEAN SendClientId, IN EFI_DHCP6_PACKET_OPTION *OptionRequest, IN UINT32 OptionCount, IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL, IN EFI_DHCP6_RETRANSMISSION *Retransmission, IN EFI_EVENT TimeoutEvent OPTIONAL, IN EFI_DHCP6_INFO_CALLBACK ReplyCallback, IN VOID *CallbackContext OPTIONAL)
Definition: Dhcp6Impl.c:602
EFI_STATUS EFIAPI EfiDhcp6RenewRebind(IN EFI_DHCP6_PROTOCOL *This, IN BOOLEAN RebindRequest)
Definition: Dhcp6Impl.c:765
EFI_STATUS EFIAPI EfiDhcp6Start(IN EFI_DHCP6_PROTOCOL *This)
Definition: Dhcp6Impl.c:65
EFI_STATUS EFIAPI EfiDhcp6GetModeData(IN EFI_DHCP6_PROTOCOL *This, OUT EFI_DHCP6_MODE_DATA *Dhcp6ModeData OPTIONAL, OUT EFI_DHCP6_CONFIG_DATA *Dhcp6ConfigData OPTIONAL)
Definition: Dhcp6Impl.c:264
EFI_STATUS EFIAPI EfiDhcp6Stop(IN EFI_DHCP6_PROTOCOL *This)
Definition: Dhcp6Impl.c:173
EFI_STATUS Dhcp6SendReleaseMsg(IN DHCP6_INSTANCE *Instance, IN EFI_DHCP6_IA *RelIa)
Definition: Dhcp6Io.c:1527
VOID EFIAPI Dhcp6ReceivePacket(IN NET_BUF *Udp6Wrap, IN UDP_END_POINT *EndPoint, IN EFI_STATUS IoStatus, IN VOID *Context)
Definition: Dhcp6Io.c:3007
VOID Dhcp6CleanupSession(IN OUT DHCP6_INSTANCE *Instance, IN EFI_STATUS Status)
Definition: Dhcp6Io.c:387
EFI_STATUS Dhcp6StartInfoRequest(IN DHCP6_INSTANCE *Instance, IN BOOLEAN SendClientId, IN EFI_DHCP6_PACKET_OPTION *OptionRequest, IN UINT32 OptionCount, IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL, IN EFI_DHCP6_RETRANSMISSION *Retransmission, IN EFI_EVENT TimeoutEvent OPTIONAL, IN EFI_DHCP6_INFO_CALLBACK ReplyCallback, IN VOID *CallbackContext OPTIONAL)
Definition: Dhcp6Io.c:1889
EFI_STATUS Dhcp6SendDeclineMsg(IN DHCP6_INSTANCE *Instance, IN EFI_DHCP6_IA *DecIa)
Definition: Dhcp6Io.c:1367
EFI_STATUS Dhcp6SendSolicitMsg(IN DHCP6_INSTANCE *Instance)
Definition: Dhcp6Io.c:1005
EFI_STATUS Dhcp6SendRenewRebindMsg(IN DHCP6_INSTANCE *Instance, IN BOOLEAN RebindRequest)
Definition: Dhcp6Io.c:1683
EFI_STATUS Dhcp6CopyConfigData(IN EFI_DHCP6_CONFIG_DATA *DstCfg, IN EFI_DHCP6_CONFIG_DATA *SorCfg)
Definition: Dhcp6Utility.c:180
EFI_DHCP6_IA * Dhcp6DepriveAddress(IN EFI_DHCP6_IA *Ia, IN UINT32 AddressCount, IN EFI_IPv6_ADDRESS *Addresses)
Definition: Dhcp6Utility.c:465
VOID Dhcp6CleanupModeData(IN OUT EFI_DHCP6_MODE_DATA *ModeData)
Definition: Dhcp6Utility.c:286
EFI_STATUS Dhcp6CheckAddress(IN EFI_DHCP6_IA *Ia, IN UINT32 AddressCount, IN EFI_IPv6_ADDRESS *Addresses)
Definition: Dhcp6Utility.c:416
EFI_STATUS Dhcp6GetMappingTimeOut(IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg, OUT UINTN *TimeOut)
VOID Dhcp6CleanupConfigData(IN OUT EFI_DHCP6_CONFIG_DATA *CfgData)
Definition: Dhcp6Utility.c:251
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI NetLibDetectMediaWaitTimeout(IN EFI_HANDLE ServiceHandle, IN UINT64 Timeout, OUT EFI_STATUS *MediaState)
Definition: DxeNetLib.c:2683
EFI_STATUS EFIAPI UdpIoRecvDatagram(IN UDP_IO *UdpIo, IN UDP_IO_CALLBACK CallBack, IN VOID *Context, IN UINT32 HeadLen)
Definition: DxeUdpIoLib.c:1084
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ TimerRelative
Definition: UefiSpec.h:539
EFI_EVENT IaInfoEvent
Definition: Dhcp6.h:360
UINT16 Length
Definition: Dhcp6.h:209
UINT16 Type
Type for an IA.
Definition: Dhcp6.h:256
UINT32 IaId
The identifier for an IA.
Definition: Dhcp6.h:257
EFI_DHCP6_PACKET * ReplyPacket
Definition: Dhcp6.h:272
EFI_DHCP6_IA_DESCRIPTOR Descriptor
Definition: Dhcp6.h:264
EFI_DHCP6_STATE State
Definition: Dhcp6.h:268
UINT32 IaAddressCount
Definition: Dhcp6.h:276
UINT32 Size
Definition: Dhcp6.h:185