TianoCore EDK2 master
Loading...
Searching...
No Matches
Dhcp4Io.c
Go to the documentation of this file.
1
9#include "Dhcp4Impl.h"
10
11UINT32 mDhcp4DefaultTimeout[4] = { 4, 8, 16, 32 };
12
25 IN DHCP_SERVICE *DhcpSb
26 )
27{
28 EFI_STATUS Status;
29
30 ASSERT ((DhcpSb->DhcpState == Dhcp4Init) || (DhcpSb->DhcpState == Dhcp4InitReboot));
31
32 //
33 // Clear initial time to make sure that elapsed-time is set to 0 for first Discover or REQUEST message.
34 //
35 DhcpSb->ActiveChild->ElaspedTime = 0;
36
37 if (DhcpSb->DhcpState == Dhcp4Init) {
39 Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_DISCOVER, NULL);
40
41 if (EFI_ERROR (Status)) {
42 DhcpSb->DhcpState = Dhcp4Init;
43 return Status;
44 }
45 } else {
47 Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_REQUEST, NULL);
48
49 if (EFI_ERROR (Status)) {
50 DhcpSb->DhcpState = Dhcp4InitReboot;
51 return Status;
52 }
53 }
54
55 return EFI_SUCCESS;
56}
57
76 IN DHCP_SERVICE *DhcpSb,
77 IN EFI_DHCP4_EVENT Event,
78 IN EFI_DHCP4_PACKET *Packet OPTIONAL,
79 OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL
80 )
81{
83 EFI_STATUS Status;
84
85 if (NewPacket != NULL) {
86 *NewPacket = NULL;
87 }
88
89 //
90 // If user doesn't provide the call back function, return the value
91 // that directs the client to continue the normal process.
92 // In Dhcp4Selecting EFI_SUCCESS tells the client to stop collecting
93 // the offers and select a offer, EFI_NOT_READY tells the client to
94 // collect more offers.
95 //
96 Config = &DhcpSb->ActiveConfig;
97
98 if (Config->Dhcp4Callback == NULL) {
99 if (Event == Dhcp4RcvdOffer) {
100 return EFI_NOT_READY;
101 }
102
103 return EFI_SUCCESS;
104 }
105
106 Status = Config->Dhcp4Callback (
107 &DhcpSb->ActiveChild->Dhcp4Protocol,
108 Config->CallbackContext,
109 (EFI_DHCP4_STATE)DhcpSb->DhcpState,
110 Event,
111 Packet,
112 NewPacket
113 );
114
115 //
116 // User's callback should only return EFI_SUCCESS, EFI_NOT_READY,
117 // and EFI_ABORTED. If it returns values other than those, assume
118 // it to be EFI_ABORTED.
119 //
120 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_READY)) {
121 return Status;
122 }
123
124 return EFI_ABORTED;
125}
126
134VOID
136 IN DHCP_SERVICE *DhcpSb,
137 IN INTN Which
138 )
139{
141
142 if ((Child = DhcpSb->ActiveChild) == NULL) {
143 return;
144 }
145
146 if ((Child->CompletionEvent != NULL) &&
147 ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL))
148 )
149 {
150 gBS->SignalEvent (Child->CompletionEvent);
151 Child->CompletionEvent = NULL;
152 }
153
154 if ((Child->RenewRebindEvent != NULL) &&
155 ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL))
156 )
157 {
158 gBS->SignalEvent (Child->RenewRebindEvent);
159 Child->RenewRebindEvent = NULL;
160 }
161}
162
180 IN OUT DHCP_SERVICE *DhcpSb,
181 IN INTN State,
182 IN BOOLEAN CallUser
183 )
184{
185 EFI_STATUS Status;
186
187 if (CallUser) {
188 Status = EFI_SUCCESS;
189
190 if (State == Dhcp4Renewing) {
191 Status = DhcpCallUser (DhcpSb, Dhcp4EnterRenewing, NULL, NULL);
192 } else if (State == Dhcp4Rebinding) {
193 Status = DhcpCallUser (DhcpSb, Dhcp4EnterRebinding, NULL, NULL);
194 } else if (State == Dhcp4Bound) {
195 Status = DhcpCallUser (DhcpSb, Dhcp4BoundCompleted, NULL, NULL);
196 }
197
198 if (EFI_ERROR (Status)) {
199 return Status;
200 }
201 }
202
203 //
204 // Update the retransmission timer during the state transition.
205 // This will clear the retry count. This is also why the rule
206 // first transit the state, then send packets.
207 //
208 if (State == Dhcp4Selecting) {
209 DhcpSb->MaxRetries = DhcpSb->ActiveConfig.DiscoverTryCount;
210 } else {
211 DhcpSb->MaxRetries = DhcpSb->ActiveConfig.RequestTryCount;
212 }
213
214 if (DhcpSb->MaxRetries == 0) {
215 DhcpSb->MaxRetries = 4;
216 }
217
218 DhcpSb->CurRetry = 0;
219 DhcpSb->PacketToLive = 0;
220 DhcpSb->LastTimeout = 0;
221 DhcpSb->DhcpState = State;
222 return EFI_SUCCESS;
223}
224
232VOID
234 IN OUT DHCP_SERVICE *DhcpSb
235 )
236{
237 UINT32 *Times;
238
239 ASSERT (DhcpSb->MaxRetries > DhcpSb->CurRetry);
240
241 if (DhcpSb->DhcpState == Dhcp4Selecting) {
242 Times = DhcpSb->ActiveConfig.DiscoverTimeout;
243 } else {
244 Times = DhcpSb->ActiveConfig.RequestTimeout;
245 }
246
247 if (Times == NULL) {
248 Times = mDhcp4DefaultTimeout;
249 }
250
251 DhcpSb->PacketToLive = Times[DhcpSb->CurRetry];
252 DhcpSb->LastTimeout = DhcpSb->PacketToLive;
253
254 return;
255}
256
266VOID
268 IN OUT DHCP_SERVICE *DhcpSb,
269 IN DHCP_PARAMETER *Para
270 )
271{
272 ASSERT (Para != NULL);
273
274 DhcpSb->Lease = Para->Lease;
275 DhcpSb->T2 = Para->T2;
276 DhcpSb->T1 = Para->T1;
277
278 if (DhcpSb->Lease == 0) {
279 DhcpSb->Lease = DHCP_DEFAULT_LEASE;
280 }
281
282 if ((DhcpSb->T2 == 0) || (DhcpSb->T2 >= Para->Lease)) {
283 DhcpSb->T2 = Para->Lease - (Para->Lease >> 3);
284 }
285
286 if ((DhcpSb->T1 == 0) || (DhcpSb->T1 >= Para->T2)) {
287 DhcpSb->T1 = DhcpSb->Lease >> 1;
288 }
289}
290
304EFIAPI
306 IN UDP_IO *UdpIo,
307 IN VOID *Context
308 )
309{
310 EFI_UDP4_CONFIG_DATA UdpConfigData;
311 EFI_IPv4_ADDRESS Subnet;
312 EFI_IPv4_ADDRESS Gateway;
313 DHCP_SERVICE *DhcpSb;
314 EFI_STATUS Status;
315 IP4_ADDR Ip;
316
317 DhcpSb = (DHCP_SERVICE *)Context;
318
319 UdpConfigData.AcceptBroadcast = FALSE;
320 UdpConfigData.AcceptPromiscuous = FALSE;
321 UdpConfigData.AcceptAnyPort = FALSE;
322 UdpConfigData.AllowDuplicatePort = TRUE;
323 UdpConfigData.TypeOfService = 0;
324 UdpConfigData.TimeToLive = 64;
325 UdpConfigData.DoNotFragment = FALSE;
326 UdpConfigData.ReceiveTimeout = 1;
327 UdpConfigData.TransmitTimeout = 0;
328
329 UdpConfigData.UseDefaultAddress = FALSE;
330 UdpConfigData.StationPort = DHCP_CLIENT_PORT;
331 UdpConfigData.RemotePort = DHCP_SERVER_PORT;
332
333 Ip = HTONL (DhcpSb->ClientAddr);
334 CopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
335
336 Ip = HTONL (DhcpSb->Netmask);
337 CopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
338
339 ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
340
341 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);
342
343 if (EFI_ERROR (Status)) {
344 return Status;
345 }
346
347 //
348 // Add a default route if received from the server.
349 //
350 if ((DhcpSb->Para != NULL) && (DhcpSb->Para->Router != 0)) {
351 ZeroMem (&Subnet, sizeof (EFI_IPv4_ADDRESS));
352
353 Ip = HTONL (DhcpSb->Para->Router);
354 CopyMem (&Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));
355
356 UdpIo->Protocol.Udp4->Routes (UdpIo->Protocol.Udp4, FALSE, &Subnet, &Subnet, &Gateway);
357 }
358
359 return EFI_SUCCESS;
360}
361
375 IN OUT DHCP_SERVICE *DhcpSb
376 )
377{
378 DhcpSb->ClientAddr = EFI_NTOHL (DhcpSb->Selected->Dhcp4.Header.YourAddr);
379
380 if (DhcpSb->Para != NULL) {
381 DhcpSb->Netmask = DhcpSb->Para->NetMask;
382 DhcpSb->ServerAddr = DhcpSb->Para->ServerId;
383 }
384
385 if (DhcpSb->Netmask == 0) {
386 return EFI_ABORTED;
387 }
388
389 if (DhcpSb->LeaseIoPort != NULL) {
390 UdpIoFreeIo (DhcpSb->LeaseIoPort);
391 }
392
393 //
394 // Create a UDP/IP child to provide ARP service for the Leased IP,
395 // and transmit unicast packet with it as source address. Don't
396 // start receive on this port, the queued packet will be timeout.
397 //
398 DhcpSb->LeaseIoPort = UdpIoCreateIo (
399 DhcpSb->Controller,
400 DhcpSb->Image,
402 UDP_IO_UDP4_VERSION,
403 DhcpSb
404 );
405
406 if (DhcpSb->LeaseIoPort == NULL) {
407 return EFI_OUT_OF_RESOURCES;
408 }
409
410 if (!DHCP_IS_BOOTP (DhcpSb->Para)) {
411 DhcpComputeLease (DhcpSb, DhcpSb->Para);
412 }
413
414 return DhcpSetState (DhcpSb, Dhcp4Bound, TRUE);
415}
416
423VOID
425 IN DHCP_SERVICE *DhcpSb
426 )
427{
428 DhcpSb->DhcpState = Dhcp4Init;
429 DhcpSb->Xid = DhcpSb->Xid + 1;
430 DhcpSb->ClientAddr = 0;
431 DhcpSb->Netmask = 0;
432 DhcpSb->ServerAddr = 0;
433
434 if (DhcpSb->LastOffer != NULL) {
435 FreePool (DhcpSb->LastOffer);
436 DhcpSb->LastOffer = NULL;
437 }
438
439 if (DhcpSb->Selected != NULL) {
440 FreePool (DhcpSb->Selected);
441 DhcpSb->Selected = NULL;
442 }
443
444 if (DhcpSb->Para != NULL) {
445 FreePool (DhcpSb->Para);
446 DhcpSb->Para = NULL;
447 }
448
449 DhcpSb->Lease = 0;
450 DhcpSb->T1 = 0;
451 DhcpSb->T2 = 0;
452 DhcpSb->ExtraRefresh = FALSE;
453
454 if (DhcpSb->LeaseIoPort != NULL) {
455 UdpIoFreeIo (DhcpSb->LeaseIoPort);
456 DhcpSb->LeaseIoPort = NULL;
457 }
458
459 if (DhcpSb->LastPacket != NULL) {
460 FreePool (DhcpSb->LastPacket);
461 DhcpSb->LastPacket = NULL;
462 }
463
464 DhcpSb->PacketToLive = 0;
465 DhcpSb->LastTimeout = 0;
466 DhcpSb->CurRetry = 0;
467 DhcpSb->MaxRetries = 0;
468 DhcpSb->LeaseLife = 0;
469
470 //
471 // Clean active config data.
472 //
473 DhcpCleanConfigure (&DhcpSb->ActiveConfig);
474}
475
488 IN DHCP_SERVICE *DhcpSb
489 )
490{
491 EFI_DHCP4_PACKET *Selected;
492 EFI_DHCP4_PACKET *NewPacket;
493 EFI_DHCP4_PACKET *TempPacket;
494 EFI_STATUS Status;
495
496 ASSERT (DhcpSb->LastOffer != NULL);
497
498 //
499 // User will cache previous offers if he wants to select
500 // from multiple offers. If user provides an invalid packet,
501 // use the last offer, otherwise use the provided packet.
502 //
503 NewPacket = NULL;
504 Status = DhcpCallUser (DhcpSb, Dhcp4SelectOffer, DhcpSb->LastOffer, &NewPacket);
505
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509
510 Selected = DhcpSb->LastOffer;
511
512 if ((NewPacket != NULL) && !EFI_ERROR (DhcpValidateOptions (NewPacket, NULL))) {
513 TempPacket = (EFI_DHCP4_PACKET *)AllocatePool (NewPacket->Size);
514 if (TempPacket != NULL) {
515 CopyMem (TempPacket, NewPacket, NewPacket->Size);
516 FreePool (Selected);
517 Selected = TempPacket;
518 }
519 }
520
521 DhcpSb->Selected = Selected;
522 DhcpSb->LastOffer = NULL;
523 DhcpSb->Para = NULL;
524 DhcpValidateOptions (Selected, &DhcpSb->Para);
525
526 //
527 // A bootp offer has been selected, save the lease status,
528 // enter bound state then notify the user.
529 //
530 if (DHCP_IS_BOOTP (DhcpSb->Para)) {
531 Status = DhcpLeaseAcquired (DhcpSb);
532
533 if (EFI_ERROR (Status)) {
534 return Status;
535 }
536
537 DhcpSb->IoStatus = EFI_SUCCESS;
538 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_ALL);
539 return EFI_SUCCESS;
540 }
541
542 //
543 // Send a DHCP requests
544 //
545 Status = DhcpSetState (DhcpSb, Dhcp4Requesting, TRUE);
546
547 if (EFI_ERROR (Status)) {
548 return Status;
549 }
550
551 return DhcpSendMessage (DhcpSb, Selected, DhcpSb->Para, DHCP_MSG_REQUEST, NULL);
552}
553
564VOID
566 IN DHCP_SERVICE *DhcpSb,
567 IN EFI_STATUS Status
568 )
569{
570 if (DHCP_CONNECTED (DhcpSb->DhcpState)) {
572 } else {
573 DhcpCallUser (DhcpSb, Dhcp4Fail, NULL, NULL);
574 }
575
576 DhcpCleanLease (DhcpSb);
577
578 DhcpSb->IoStatus = Status;
579 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_ALL);
580}
581
596 IN DHCP_SERVICE *DhcpSb,
597 IN EFI_DHCP4_PACKET *Packet,
598 IN DHCP_PARAMETER *Para
599 )
600{
601 EFI_STATUS Status;
602
603 Status = EFI_SUCCESS;
604
605 //
606 // First validate the message:
607 // 1. the offer is a unicast
608 // 2. if it is a DHCP message, it must contains a server ID.
609 // Don't return a error for these two case otherwise the session is ended.
610 //
611 if (!DHCP_IS_BOOTP (Para) &&
612 ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0))
613 )
614 {
615 goto ON_EXIT;
616 }
617
618 //
619 // Call the user's callback. The action according to the return is as:
620 // 1. EFI_SUCCESS: stop waiting for more offers, select the offer now
621 // 2. EFI_NOT_READY: wait for more offers
622 // 3. EFI_ABORTED: abort the address acquiring.
623 //
624 Status = DhcpCallUser (DhcpSb, Dhcp4RcvdOffer, Packet, NULL);
625
626 if (Status == EFI_SUCCESS) {
627 if (DhcpSb->LastOffer != NULL) {
628 FreePool (DhcpSb->LastOffer);
629 }
630
631 DhcpSb->LastOffer = Packet;
632
633 return DhcpChooseOffer (DhcpSb);
634 } else if (Status == EFI_NOT_READY) {
635 if (DhcpSb->LastOffer != NULL) {
636 FreePool (DhcpSb->LastOffer);
637 }
638
639 DhcpSb->LastOffer = Packet;
640 } else if (Status == EFI_ABORTED) {
641 //
642 // DhcpInput will end the session upon error return. Remember
643 // only to call DhcpEndSession at the top level call.
644 //
645 goto ON_EXIT;
646 }
647
648 return EFI_SUCCESS;
649
650ON_EXIT:
651 FreePool (Packet);
652 return Status;
653}
654
669 IN DHCP_SERVICE *DhcpSb,
670 IN EFI_DHCP4_PACKET *Packet,
671 IN DHCP_PARAMETER *Para
672 )
673{
674 EFI_DHCP4_HEADER *Head;
675 EFI_DHCP4_HEADER *Selected;
676 EFI_STATUS Status;
677 UINT8 *Message;
678
679 ASSERT (!DHCP_IS_BOOTP (DhcpSb->Para));
680
681 Head = &Packet->Dhcp4.Header;
682 Selected = &DhcpSb->Selected->Dhcp4.Header;
683
684 //
685 // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK.
686 //
687 if (DHCP_IS_BOOTP (Para) ||
688 (Para->ServerId != DhcpSb->Para->ServerId) ||
689 ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))
690 )
691 {
692 Status = EFI_SUCCESS;
693 goto ON_EXIT;
694 }
695
696 //
697 // Received a NAK, end the session no matter what the user returns
698 //
699 Status = EFI_DEVICE_ERROR;
700
701 if (Para->DhcpType == DHCP_MSG_NAK) {
702 DhcpCallUser (DhcpSb, Dhcp4RcvdNak, Packet, NULL);
703 goto ON_EXIT;
704 }
705
706 //
707 // Check whether the ACK matches the selected offer
708 //
709 Message = NULL;
710
711 if (!EFI_IP4_EQUAL (&Head->YourAddr, &Selected->YourAddr)) {
712 Message = (UINT8 *)"Lease confirmed isn't the same as that in the offer";
713 goto REJECT;
714 }
715
716 Status = DhcpCallUser (DhcpSb, Dhcp4RcvdAck, Packet, NULL);
717
718 if (EFI_ERROR (Status)) {
719 Message = (UINT8 *)"Lease is denied upon received ACK";
720 goto REJECT;
721 }
722
723 //
724 // Record the lease, transit to BOUND state, then notify the user
725 //
726 Status = DhcpLeaseAcquired (DhcpSb);
727
728 if (EFI_ERROR (Status)) {
729 Message = (UINT8 *)"Lease is denied upon entering bound";
730 goto REJECT;
731 }
732
733 DhcpSb->IoStatus = EFI_SUCCESS;
734 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_COMPLETION);
735
736 FreePool (Packet);
737 return EFI_SUCCESS;
738
739REJECT:
740 DhcpSendMessage (DhcpSb, DhcpSb->Selected, DhcpSb->Para, DHCP_MSG_DECLINE, Message);
741
742ON_EXIT:
743 FreePool (Packet);
744 return Status;
745}
746
761 IN DHCP_SERVICE *DhcpSb,
762 IN EFI_DHCP4_PACKET *Packet,
763 IN DHCP_PARAMETER *Para
764 )
765{
766 EFI_DHCP4_HEADER *Head;
767 EFI_DHCP4_HEADER *Selected;
768 EFI_STATUS Status;
769
770 ASSERT (!DHCP_IS_BOOTP (DhcpSb->Para));
771
772 Head = &Packet->Dhcp4.Header;
773 Selected = &DhcpSb->Selected->Dhcp4.Header;
774
775 //
776 // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK
777 //
778 if (DHCP_IS_BOOTP (Para) ||
779 (Para->ServerId != DhcpSb->Para->ServerId) ||
780 ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))
781 )
782 {
783 Status = EFI_SUCCESS;
784 goto ON_EXIT;
785 }
786
787 //
788 // Received a NAK, ignore the user's return then terminate the process
789 //
790 Status = EFI_DEVICE_ERROR;
791
792 if (Para->DhcpType == DHCP_MSG_NAK) {
793 DhcpCallUser (DhcpSb, Dhcp4RcvdNak, Packet, NULL);
794 goto ON_EXIT;
795 }
796
797 //
798 // The lease is different from the selected. Don't send a DECLINE
799 // since it isn't existed in the client's FSM.
800 //
801 if (!EFI_IP4_EQUAL (&Head->YourAddr, &Selected->YourAddr)) {
802 goto ON_EXIT;
803 }
804
805 Status = DhcpCallUser (DhcpSb, Dhcp4RcvdAck, Packet, NULL);
806
807 if (EFI_ERROR (Status)) {
808 goto ON_EXIT;
809 }
810
811 //
812 // Record the lease, start timer for T1 and T2,
813 //
814 DhcpComputeLease (DhcpSb, Para);
815 DhcpSb->LeaseLife = 0;
816 DhcpSetState (DhcpSb, Dhcp4Bound, TRUE);
817
818 if (DhcpSb->ExtraRefresh != 0) {
819 DhcpSb->ExtraRefresh = FALSE;
820
821 DhcpSb->IoStatus = EFI_SUCCESS;
822 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_RENEWREBIND);
823 }
824
825ON_EXIT:
826 FreePool (Packet);
827 return Status;
828}
829
844 IN DHCP_SERVICE *DhcpSb,
845 IN EFI_DHCP4_PACKET *Packet,
846 IN DHCP_PARAMETER *Para
847 )
848{
849 EFI_DHCP4_HEADER *Head;
850 EFI_STATUS Status;
851
852 Head = &Packet->Dhcp4.Header;
853
854 //
855 // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK
856 //
857 if (DHCP_IS_BOOTP (Para) ||
858 ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))
859 )
860 {
861 Status = EFI_SUCCESS;
862 goto ON_EXIT;
863 }
864
865 //
866 // If a NAK is received, transit to INIT and try again.
867 //
868 if (Para->DhcpType == DHCP_MSG_NAK) {
869 DhcpCallUser (DhcpSb, Dhcp4RcvdNak, Packet, NULL);
870
871 DhcpSb->ClientAddr = 0;
872 DhcpSb->DhcpState = Dhcp4Init;
873
874 Status = DhcpInitRequest (DhcpSb);
875 goto ON_EXIT;
876 }
877
878 //
879 // Check whether the ACK matches the selected offer
880 //
881 if (EFI_NTOHL (Head->YourAddr) != DhcpSb->ClientAddr) {
882 Status = EFI_DEVICE_ERROR;
883 goto ON_EXIT;
884 }
885
886 Status = DhcpCallUser (DhcpSb, Dhcp4RcvdAck, Packet, NULL);
887 if (EFI_ERROR (Status)) {
888 goto ON_EXIT;
889 }
890
891 //
892 // OK, get the parameter from server, record the lease
893 //
894 DhcpSb->Para = AllocateCopyPool (sizeof (DHCP_PARAMETER), Para);
895 if (DhcpSb->Para == NULL) {
896 Status = EFI_OUT_OF_RESOURCES;
897 goto ON_EXIT;
898 }
899
900 DhcpSb->Selected = Packet;
901 Status = DhcpLeaseAcquired (DhcpSb);
902 if (EFI_ERROR (Status)) {
903 return Status;
904 }
905
906 DhcpSb->IoStatus = EFI_SUCCESS;
907 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_COMPLETION);
908 return EFI_SUCCESS;
909
910ON_EXIT:
911 FreePool (Packet);
912 return Status;
913}
914
925VOID
926EFIAPI
928 NET_BUF *UdpPacket,
929 UDP_END_POINT *EndPoint,
930 EFI_STATUS IoStatus,
931 VOID *Context
932 )
933{
934 DHCP_SERVICE *DhcpSb;
935 EFI_DHCP4_HEADER *Head;
936 EFI_DHCP4_PACKET *Packet;
937 DHCP_PARAMETER *Para;
938 EFI_STATUS Status;
939 UINT32 Len;
940
941 Packet = NULL;
942 DhcpSb = (DHCP_SERVICE *)Context;
943
944 //
945 // Don't restart receive if error occurs or DHCP is destroyed.
946 //
947 if (EFI_ERROR (IoStatus)) {
948 return;
949 } else if (DhcpSb->ServiceState == DHCP_DESTROY) {
950 NetbufFree (UdpPacket);
951 return;
952 }
953
954 ASSERT (UdpPacket != NULL);
955
956 if (DhcpSb->DhcpState == Dhcp4Stopped) {
957 goto RESTART;
958 }
959
960 //
961 // Validate the packet received
962 //
963 if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {
964 goto RESTART;
965 }
966
967 //
968 // Copy the DHCP message to a continuous memory block
969 //
970 Len = sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER);
971 Packet = (EFI_DHCP4_PACKET *)AllocatePool (Len);
972
973 if (Packet == NULL) {
974 goto RESTART;
975 }
976
977 Packet->Size = Len;
978 Head = &Packet->Dhcp4.Header;
979 Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *)Head);
980
981 if (Packet->Length != UdpPacket->TotalSize) {
982 goto RESTART;
983 }
984
985 //
986 // Is this packet the answer to our packet?
987 //
988 if ((Head->OpCode != BOOTP_REPLY) ||
989 (NTOHL (Head->Xid) != DhcpSb->Xid) ||
990 (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0))
991 {
992 goto RESTART;
993 }
994
995 //
996 // Validate the options and retrieve the interested options
997 //
998 Para = NULL;
999 if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&
1000 (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&
1001 EFI_ERROR (DhcpValidateOptions (Packet, &Para)))
1002 {
1003 goto RESTART;
1004 }
1005
1006 //
1007 // Call the handler for each state. The handler should return
1008 // EFI_SUCCESS if the process can go on no matter whether the
1009 // packet is ignored or not. If the return is EFI_ERROR, the
1010 // session will be terminated. Packet's ownership is handled
1011 // over to the handlers. If operation succeeds, the handler
1012 // must notify the user. It isn't necessary to do if EFI_ERROR
1013 // is returned because the DhcpEndSession will notify the user.
1014 //
1015 Status = EFI_SUCCESS;
1016
1017 switch (DhcpSb->DhcpState) {
1018 case Dhcp4Selecting:
1019 Status = DhcpHandleSelect (DhcpSb, Packet, Para);
1020 break;
1021
1022 case Dhcp4Requesting:
1023 Status = DhcpHandleRequest (DhcpSb, Packet, Para);
1024 break;
1025
1026 case Dhcp4InitReboot:
1027 case Dhcp4Init:
1028 case Dhcp4Bound:
1029 //
1030 // Ignore the packet in INITREBOOT, INIT and BOUND states
1031 //
1032 FreePool (Packet);
1033 Status = EFI_SUCCESS;
1034 break;
1035
1036 case Dhcp4Renewing:
1037 case Dhcp4Rebinding:
1038 Status = DhcpHandleRenewRebind (DhcpSb, Packet, Para);
1039 break;
1040
1041 case Dhcp4Rebooting:
1042 Status = DhcpHandleReboot (DhcpSb, Packet, Para);
1043 break;
1044 }
1045
1046 if (Para != NULL) {
1047 FreePool (Para);
1048 }
1049
1050 Packet = NULL;
1051
1052 if (EFI_ERROR (Status)) {
1053 NetbufFree (UdpPacket);
1054 UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
1055 DhcpEndSession (DhcpSb, Status);
1056 return;
1057 }
1058
1059RESTART:
1060 NetbufFree (UdpPacket);
1061
1062 if (Packet != NULL) {
1063 FreePool (Packet);
1064 }
1065
1066 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
1067
1068 if (EFI_ERROR (Status)) {
1069 DhcpEndSession (DhcpSb, EFI_DEVICE_ERROR);
1070 }
1071}
1072
1082VOID
1083EFIAPI
1085 NET_BUF *Packet,
1086 UDP_END_POINT *EndPoint,
1087 EFI_STATUS IoStatus,
1088 VOID *Context
1089 )
1090{
1091 NetbufFree (Packet);
1092}
1093
1115 IN DHCP_SERVICE *DhcpSb,
1116 IN EFI_DHCP4_PACKET *Seed,
1117 IN DHCP_PARAMETER *Para,
1118 IN UINT8 Type,
1119 IN UINT8 *Msg
1120 )
1121{
1122 EFI_DHCP4_CONFIG_DATA *Config;
1123 EFI_DHCP4_PACKET *Packet;
1124 EFI_DHCP4_PACKET *NewPacket;
1125 EFI_DHCP4_HEADER *Head;
1126 EFI_DHCP4_HEADER *SeedHead;
1127 UDP_IO *UdpIo;
1128 UDP_END_POINT EndPoint;
1129 NET_BUF *Wrap;
1130 NET_FRAGMENT Frag;
1131 EFI_STATUS Status;
1132 IP4_ADDR IpAddr;
1133 UINT8 *Buf;
1134 UINT16 MaxMsg;
1135 UINT32 Len;
1136 UINT32 Index;
1137
1138 //
1139 // Allocate a big enough memory block to hold the DHCP packet
1140 //
1141 Len = sizeof (EFI_DHCP4_PACKET) + 128 + DhcpSb->UserOptionLen;
1142
1143 if (Msg != NULL) {
1144 Len += (UINT32)AsciiStrLen ((CHAR8 *)Msg);
1145 }
1146
1147 Packet = AllocatePool (Len);
1148
1149 if (Packet == NULL) {
1150 return EFI_OUT_OF_RESOURCES;
1151 }
1152
1153 Packet->Size = Len;
1154 Packet->Length = sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32);
1155
1156 //
1157 // Fill in the DHCP header fields
1158 //
1159 Config = &DhcpSb->ActiveConfig;
1160 SeedHead = NULL;
1161
1162 if (Seed != NULL) {
1163 SeedHead = &Seed->Dhcp4.Header;
1164 }
1165
1166 Head = &Packet->Dhcp4.Header;
1167 ZeroMem (Head, sizeof (EFI_DHCP4_HEADER));
1168
1169 Head->OpCode = BOOTP_REQUEST;
1170 Head->HwType = DhcpSb->HwType;
1171 Head->HwAddrLen = DhcpSb->HwLen;
1172 Head->Xid = HTONL (DhcpSb->Xid);
1173 Head->Reserved = HTONS (0x8000); // Server, broadcast the message please.
1174
1175 EFI_IP4 (Head->ClientAddr) = HTONL (DhcpSb->ClientAddr);
1176 CopyMem (Head->ClientHwAddr, DhcpSb->Mac.Addr, DhcpSb->HwLen);
1177
1178 if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE)) {
1179 Head->Seconds = 0;
1180 } else if ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting)) {
1181 //
1182 // Use the same value as the original DHCPDISCOVER message.
1183 //
1184 Head->Seconds = DhcpSb->LastPacket->Dhcp4.Header.Seconds;
1185 } else {
1186 SetElapsedTime (&Head->Seconds, DhcpSb->ActiveChild);
1187 }
1188
1189 //
1190 // Append the DHCP message type
1191 //
1192 Packet->Dhcp4.Magik = DHCP_OPTION_MAGIC;
1193 Buf = Packet->Dhcp4.Option;
1194 Buf = DhcpAppendOption (Buf, DHCP4_TAG_MSG_TYPE, 1, &Type);
1195
1196 //
1197 // Append the serverid option if necessary:
1198 // 1. DHCP decline message
1199 // 2. DHCP release message
1200 // 3. DHCP request to confirm one lease.
1201 //
1202 if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE) ||
1203 ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting))
1204 )
1205 {
1206 ASSERT ((Para != NULL) && (Para->ServerId != 0));
1207
1208 IpAddr = HTONL (Para->ServerId);
1209 Buf = DhcpAppendOption (Buf, DHCP4_TAG_SERVER_ID, 4, (UINT8 *)&IpAddr);
1210 }
1211
1212 //
1213 // Append the requested IP option if necessary:
1214 // 1. DHCP request to use the previously allocated address
1215 // 2. DHCP request to confirm one lease
1216 // 3. DHCP decline to decline one lease
1217 //
1218 IpAddr = 0;
1219
1220 if (Type == DHCP_MSG_REQUEST) {
1221 if (DhcpSb->DhcpState == Dhcp4Rebooting) {
1222 IpAddr = EFI_IP4 (Config->ClientAddress);
1223 } else if (DhcpSb->DhcpState == Dhcp4Requesting) {
1224 ASSERT (SeedHead != NULL);
1225 IpAddr = EFI_IP4 (SeedHead->YourAddr);
1226 }
1227 } else if (Type == DHCP_MSG_DECLINE) {
1228 ASSERT (SeedHead != NULL);
1229 IpAddr = EFI_IP4 (SeedHead->YourAddr);
1230 }
1231
1232 if (IpAddr != 0) {
1233 Buf = DhcpAppendOption (Buf, DHCP4_TAG_REQUEST_IP, 4, (UINT8 *)&IpAddr);
1234 }
1235
1236 //
1237 // Append the Max Message Length option if it isn't a DECLINE
1238 // or RELEASE to direct the server use large messages instead of
1239 // override the BOOTFILE and SERVER fields in the message head.
1240 //
1241 if ((Type != DHCP_MSG_DECLINE) && (Type != DHCP_MSG_RELEASE)) {
1242 MaxMsg = HTONS (0xFF00);
1243 Buf = DhcpAppendOption (Buf, DHCP4_TAG_MAXMSG, 2, (UINT8 *)&MaxMsg);
1244 }
1245
1246 //
1247 // Append the user's message if it isn't NULL
1248 //
1249 if (Msg != NULL) {
1250 Len = MIN ((UINT32)AsciiStrLen ((CHAR8 *)Msg), 255);
1251 Buf = DhcpAppendOption (Buf, DHCP4_TAG_MESSAGE, (UINT16)Len, Msg);
1252 }
1253
1254 //
1255 // Append the user configured options
1256 //
1257 if (DhcpSb->UserOptionLen != 0) {
1258 for (Index = 0; Index < Config->OptionCount; Index++) {
1259 //
1260 // We can't use any option other than the client ID from user
1261 // if it is a DHCP decline or DHCP release .
1262 //
1263 if (((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE)) &&
1264 (Config->OptionList[Index]->OpCode != DHCP4_TAG_CLIENT_ID))
1265 {
1266 continue;
1267 }
1268
1269 Buf = DhcpAppendOption (
1270 Buf,
1271 Config->OptionList[Index]->OpCode,
1272 Config->OptionList[Index]->Length,
1273 Config->OptionList[Index]->Data
1274 );
1275 }
1276 }
1277
1278 *(Buf++) = DHCP4_TAG_EOP;
1279 Packet->Length += (UINT32)(Buf - Packet->Dhcp4.Option);
1280
1281 //
1282 // OK, the message is built, call the user to override it.
1283 //
1284 Status = EFI_SUCCESS;
1285 NewPacket = NULL;
1286
1287 if (Type == DHCP_MSG_DISCOVER) {
1288 Status = DhcpCallUser (DhcpSb, Dhcp4SendDiscover, Packet, &NewPacket);
1289 } else if (Type == DHCP_MSG_REQUEST) {
1290 Status = DhcpCallUser (DhcpSb, Dhcp4SendRequest, Packet, &NewPacket);
1291 } else if (Type == DHCP_MSG_DECLINE) {
1292 Status = DhcpCallUser (DhcpSb, Dhcp4SendDecline, Packet, &NewPacket);
1293 }
1294
1295 if (EFI_ERROR (Status)) {
1296 FreePool (Packet);
1297 return Status;
1298 }
1299
1300 if (NewPacket != NULL) {
1301 FreePool (Packet);
1302 Packet = NewPacket;
1303 }
1304
1305 //
1306 // Save the Client Address will be sent out
1307 //
1308 CopyMem (
1309 &DhcpSb->ClientAddressSendOut[0],
1310 &Packet->Dhcp4.Header.ClientHwAddr[0],
1311 Packet->Dhcp4.Header.HwAddrLen
1312 );
1313
1314 //
1315 // Wrap it into a netbuf then send it.
1316 //
1317 Frag.Bulk = (UINT8 *)&Packet->Dhcp4.Header;
1318 Frag.Len = Packet->Length;
1319 Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);
1320
1321 if (Wrap == NULL) {
1322 FreePool (Packet);
1323 return EFI_OUT_OF_RESOURCES;
1324 }
1325
1326 //
1327 // Save it as the last sent packet for retransmission
1328 //
1329 if (DhcpSb->LastPacket != NULL) {
1330 FreePool (DhcpSb->LastPacket);
1331 }
1332
1333 DhcpSb->LastPacket = Packet;
1334 DhcpSetTransmitTimer (DhcpSb);
1335
1336 //
1337 // Broadcast the message, unless we know the server address.
1338 // Use the lease UdpIo port to send the unicast packet.
1339 //
1340 EndPoint.RemoteAddr.Addr[0] = 0xffffffff;
1341 EndPoint.LocalAddr.Addr[0] = 0;
1342 EndPoint.RemotePort = DHCP_SERVER_PORT;
1343 EndPoint.LocalPort = DHCP_CLIENT_PORT;
1344 UdpIo = DhcpSb->UdpIo;
1345
1346 if ((DhcpSb->DhcpState == Dhcp4Renewing) || (Type == DHCP_MSG_RELEASE)) {
1347 EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr;
1348 EndPoint.LocalAddr.Addr[0] = DhcpSb->ClientAddr;
1349 UdpIo = DhcpSb->LeaseIoPort;
1350 }
1351
1352 ASSERT (UdpIo != NULL);
1353
1354 Status = UdpIoSendDatagram (
1355 UdpIo,
1356 Wrap,
1357 &EndPoint,
1358 NULL,
1360 DhcpSb
1361 );
1362
1363 if (EFI_ERROR (Status)) {
1364 NetbufFree (Wrap);
1365 return EFI_ACCESS_DENIED;
1366 }
1367
1368 return EFI_SUCCESS;
1369}
1370
1383 IN DHCP_SERVICE *DhcpSb
1384 )
1385{
1386 UDP_IO *UdpIo;
1387 UDP_END_POINT EndPoint;
1388 NET_BUF *Wrap;
1389 NET_FRAGMENT Frag;
1390 EFI_STATUS Status;
1391
1392 ASSERT (DhcpSb->LastPacket != NULL);
1393
1394 //
1395 // For REQUEST message in Dhcp4Requesting state, do not change the secs fields.
1396 //
1397 if (DhcpSb->DhcpState != Dhcp4Requesting) {
1398 SetElapsedTime (&DhcpSb->LastPacket->Dhcp4.Header.Seconds, DhcpSb->ActiveChild);
1399 }
1400
1401 //
1402 // Wrap it into a netbuf then send it.
1403 //
1404 Frag.Bulk = (UINT8 *)&DhcpSb->LastPacket->Dhcp4.Header;
1405 Frag.Len = DhcpSb->LastPacket->Length;
1406 Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);
1407
1408 if (Wrap == NULL) {
1409 return EFI_OUT_OF_RESOURCES;
1410 }
1411
1412 //
1413 // Broadcast the message, unless we know the server address.
1414 //
1415 EndPoint.RemotePort = DHCP_SERVER_PORT;
1416 EndPoint.LocalPort = DHCP_CLIENT_PORT;
1417 EndPoint.RemoteAddr.Addr[0] = 0xffffffff;
1418 EndPoint.LocalAddr.Addr[0] = 0;
1419 UdpIo = DhcpSb->UdpIo;
1420
1421 if (DhcpSb->DhcpState == Dhcp4Renewing) {
1422 EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr;
1423 EndPoint.LocalAddr.Addr[0] = DhcpSb->ClientAddr;
1424 UdpIo = DhcpSb->LeaseIoPort;
1425 }
1426
1427 ASSERT (UdpIo != NULL);
1428
1429 Status = UdpIoSendDatagram (
1430 UdpIo,
1431 Wrap,
1432 &EndPoint,
1433 NULL,
1435 DhcpSb
1436 );
1437
1438 if (EFI_ERROR (Status)) {
1439 NetbufFree (Wrap);
1440 return EFI_ACCESS_DENIED;
1441 }
1442
1443 return EFI_SUCCESS;
1444}
1445
1457VOID
1458EFIAPI
1460 IN EFI_EVENT Event,
1461 IN VOID *Context
1462 )
1463{
1464 LIST_ENTRY *Entry;
1465 LIST_ENTRY *Next;
1466 DHCP_SERVICE *DhcpSb;
1467 DHCP_PROTOCOL *Instance;
1468 EFI_STATUS Status;
1469
1470 DhcpSb = (DHCP_SERVICE *)Context;
1471 Instance = DhcpSb->ActiveChild;
1472
1473 //
1474 // 0xffff is the maximum supported value for elapsed time according to RFC.
1475 //
1476 if ((Instance != NULL) && (Instance->ElaspedTime < 0xffff)) {
1477 Instance->ElaspedTime++;
1478 }
1479
1480 //
1481 // Check the retransmit timer
1482 //
1483 if ((DhcpSb->PacketToLive > 0) && (--DhcpSb->PacketToLive == 0)) {
1484 //
1485 // Select offer at each timeout if any offer received.
1486 //
1487 if ((DhcpSb->DhcpState == Dhcp4Selecting) && (DhcpSb->LastOffer != NULL)) {
1488 Status = DhcpChooseOffer (DhcpSb);
1489
1490 if (EFI_ERROR (Status)) {
1491 if (DhcpSb->LastOffer != NULL) {
1492 FreePool (DhcpSb->LastOffer);
1493 DhcpSb->LastOffer = NULL;
1494 }
1495 } else {
1496 goto ON_EXIT;
1497 }
1498 }
1499
1500 if (++DhcpSb->CurRetry < DhcpSb->MaxRetries) {
1501 //
1502 // Still has another try
1503 //
1504 DhcpRetransmit (DhcpSb);
1505 DhcpSetTransmitTimer (DhcpSb);
1506 } else if (DHCP_CONNECTED (DhcpSb->DhcpState)) {
1507 //
1508 // Retransmission failed, if the DHCP request is initiated by
1509 // user, adjust the current state according to the lease life.
1510 // Otherwise do nothing to wait the lease to timeout
1511 //
1512 if (DhcpSb->ExtraRefresh != 0) {
1513 Status = EFI_SUCCESS;
1514
1515 if (DhcpSb->LeaseLife < DhcpSb->T1) {
1516 Status = DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
1517 } else if (DhcpSb->LeaseLife < DhcpSb->T2) {
1518 Status = DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
1519 } else if (DhcpSb->LeaseLife < DhcpSb->Lease) {
1520 Status = DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
1521 } else {
1522 goto END_SESSION;
1523 }
1524
1525 DhcpSb->IoStatus = EFI_TIMEOUT;
1526 DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_RENEWREBIND);
1527 }
1528 } else {
1529 goto END_SESSION;
1530 }
1531 }
1532
1533 //
1534 // If an address has been acquired, check whether need to
1535 // refresh or whether it has expired.
1536 //
1537 if (DHCP_CONNECTED (DhcpSb->DhcpState)) {
1538 DhcpSb->LeaseLife++;
1539
1540 //
1541 // Don't timeout the lease, only count the life if user is
1542 // requesting extra renew/rebind. Adjust the state after that.
1543 //
1544 if (DhcpSb->ExtraRefresh != 0) {
1545 return;
1546 }
1547
1548 if (DhcpSb->LeaseLife == DhcpSb->Lease) {
1549 //
1550 // Lease expires, end the session
1551 //
1552 goto END_SESSION;
1553 } else if (DhcpSb->LeaseLife == DhcpSb->T2) {
1554 //
1555 // T2 expires, transit to rebinding then send a REQUEST to any server
1556 //
1557 if (EFI_ERROR (DhcpSetState (DhcpSb, Dhcp4Rebinding, TRUE))) {
1558 goto END_SESSION;
1559 }
1560
1561 if (Instance != NULL) {
1562 Instance->ElaspedTime = 0;
1563 }
1564
1565 Status = DhcpSendMessage (
1566 DhcpSb,
1567 DhcpSb->Selected,
1568 DhcpSb->Para,
1569 DHCP_MSG_REQUEST,
1570 NULL
1571 );
1572
1573 if (EFI_ERROR (Status)) {
1574 goto END_SESSION;
1575 }
1576 } else if (DhcpSb->LeaseLife == DhcpSb->T1) {
1577 //
1578 // T1 expires, transit to renewing, then send a REQUEST to the server
1579 //
1580 if (EFI_ERROR (DhcpSetState (DhcpSb, Dhcp4Renewing, TRUE))) {
1581 goto END_SESSION;
1582 }
1583
1584 if (Instance != NULL) {
1585 Instance->ElaspedTime = 0;
1586 }
1587
1588 Status = DhcpSendMessage (
1589 DhcpSb,
1590 DhcpSb->Selected,
1591 DhcpSb->Para,
1592 DHCP_MSG_REQUEST,
1593 NULL
1594 );
1595
1596 if (EFI_ERROR (Status)) {
1597 goto END_SESSION;
1598 }
1599 }
1600 }
1601
1602ON_EXIT:
1603 //
1604 // Iterate through all the DhcpSb Children.
1605 //
1606 NET_LIST_FOR_EACH_SAFE (Entry, Next, &DhcpSb->Children) {
1607 Instance = NET_LIST_USER_STRUCT (Entry, DHCP_PROTOCOL, Link);
1608 Instance->Timeout--;
1609 if ((Instance->Timeout == 0) && (Instance->Token != NULL)) {
1610 PxeDhcpDone (Instance);
1611 }
1612 }
1613
1614 return;
1615
1616END_SESSION:
1617 DhcpEndSession (DhcpSb, EFI_TIMEOUT);
1618
1619 return;
1620}
INT64 INTN
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
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)
NODE Child(IN NODE LoopVar6, IN UINT8 LoopVar5)
Definition: Compress.c:265
EFI_DHCP4_STATE
Definition: Dhcp4.h:98
@ Dhcp4Stopped
Definition: Dhcp4.h:102
@ Dhcp4Init
Definition: Dhcp4.h:106
@ Dhcp4Bound
Definition: Dhcp4.h:118
@ Dhcp4Rebooting
Definition: Dhcp4.h:138
@ Dhcp4Requesting
Definition: Dhcp4.h:114
@ Dhcp4InitReboot
Definition: Dhcp4.h:133
@ Dhcp4Rebinding
Definition: Dhcp4.h:128
@ Dhcp4Selecting
Definition: Dhcp4.h:110
@ Dhcp4Renewing
Definition: Dhcp4.h:123
EFI_DHCP4_EVENT
Definition: Dhcp4.h:141
@ Dhcp4RcvdNak
Definition: Dhcp4.h:165
@ Dhcp4Fail
Definition: Dhcp4.h:195
@ Dhcp4SendDecline
Definition: Dhcp4.h:169
@ Dhcp4RcvdAck
Definition: Dhcp4.h:161
@ Dhcp4SendRequest
Definition: Dhcp4.h:157
@ Dhcp4SelectOffer
Definition: Dhcp4.h:153
@ Dhcp4EnterRebinding
Definition: Dhcp4.h:183
@ Dhcp4BoundCompleted
Definition: Dhcp4.h:173
@ Dhcp4RcvdOffer
Definition: Dhcp4.h:149
@ Dhcp4SendDiscover
Definition: Dhcp4.h:145
@ Dhcp4EnterRenewing
Definition: Dhcp4.h:178
@ Dhcp4AddressLost
Definition: Dhcp4.h:189
VOID EFIAPI DhcpDummyExtFree(IN VOID *Arg)
Definition: Dhcp4Impl.c:1296
VOID DhcpCleanConfigure(IN OUT EFI_DHCP4_CONFIG_DATA *Config)
Definition: Dhcp4Impl.c:415
VOID PxeDhcpDone(IN DHCP_PROTOCOL *Instance)
Definition: Dhcp4Impl.c:1419
VOID SetElapsedTime(IN UINT16 *Elapsed, IN DHCP_PROTOCOL *Instance)
Definition: Dhcp4Impl.c:1783
EFI_STATUS DhcpLeaseAcquired(IN OUT DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:374
EFI_STATUS DhcpHandleReboot(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_PACKET *Packet, IN DHCP_PARAMETER *Para)
Definition: Dhcp4Io.c:843
EFI_STATUS DhcpInitRequest(IN DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:24
EFI_STATUS DhcpHandleRequest(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_PACKET *Packet, IN DHCP_PARAMETER *Para)
Definition: Dhcp4Io.c:668
EFI_STATUS DhcpHandleSelect(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_PACKET *Packet, IN DHCP_PARAMETER *Para)
Definition: Dhcp4Io.c:595
EFI_STATUS DhcpHandleRenewRebind(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_PACKET *Packet, IN DHCP_PARAMETER *Para)
Definition: Dhcp4Io.c:760
VOID DhcpComputeLease(IN OUT DHCP_SERVICE *DhcpSb, IN DHCP_PARAMETER *Para)
Definition: Dhcp4Io.c:267
EFI_STATUS DhcpSendMessage(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_PACKET *Seed, IN DHCP_PARAMETER *Para, IN UINT8 Type, IN UINT8 *Msg)
Definition: Dhcp4Io.c:1114
EFI_STATUS EFIAPI DhcpConfigLeaseIoPort(IN UDP_IO *UdpIo, IN VOID *Context)
Definition: Dhcp4Io.c:305
EFI_STATUS DhcpSetState(IN OUT DHCP_SERVICE *DhcpSb, IN INTN State, IN BOOLEAN CallUser)
Definition: Dhcp4Io.c:179
VOID DhcpEndSession(IN DHCP_SERVICE *DhcpSb, IN EFI_STATUS Status)
Definition: Dhcp4Io.c:565
VOID DhcpCleanLease(IN DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:424
EFI_STATUS DhcpCallUser(IN DHCP_SERVICE *DhcpSb, IN EFI_DHCP4_EVENT Event, IN EFI_DHCP4_PACKET *Packet OPTIONAL, OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL)
Definition: Dhcp4Io.c:75
EFI_STATUS DhcpChooseOffer(IN DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:487
VOID DhcpSetTransmitTimer(IN OUT DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:233
EFI_STATUS DhcpRetransmit(IN DHCP_SERVICE *DhcpSb)
Definition: Dhcp4Io.c:1382
VOID EFIAPI DhcpOnPacketSent(NET_BUF *Packet, UDP_END_POINT *EndPoint, EFI_STATUS IoStatus, VOID *Context)
Definition: Dhcp4Io.c:1084
VOID EFIAPI DhcpOnTimerTick(IN EFI_EVENT Event, IN VOID *Context)
Definition: Dhcp4Io.c:1459
VOID EFIAPI DhcpInput(NET_BUF *UdpPacket, UDP_END_POINT *EndPoint, EFI_STATUS IoStatus, VOID *Context)
Definition: Dhcp4Io.c:927
VOID DhcpNotifyUser(IN DHCP_SERVICE *DhcpSb, IN INTN Which)
Definition: Dhcp4Io.c:135
EFI_STATUS DhcpValidateOptions(IN EFI_DHCP4_PACKET *Packet, OUT DHCP_PARAMETER **Para OPTIONAL)
Definition: Dhcp4Option.c:641
UINT8 * DhcpAppendOption(OUT UINT8 *Buf, IN UINT8 Tag, IN UINT16 DataLen, IN UINT8 *Data)
Definition: Dhcp4Option.c:727
#define DHCP_OPTION_MAGIC
Definition: Dhcp4Option.h:16
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
NET_BUF *EFIAPI NetbufFromExt(IN NET_FRAGMENT *ExtFragment, IN UINT32 ExtNum, IN UINT32 HeadSpace, IN UINT32 HeadLen, IN NET_VECTOR_EXT_FREE ExtFree, IN VOID *Arg OPTIONAL)
Definition: NetBuffer.c:693
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS EFIAPI UdpIoRecvDatagram(IN UDP_IO *UdpIo, IN UDP_IO_CALLBACK CallBack, IN VOID *Context, IN UINT32 HeadLen)
Definition: DxeUdpIoLib.c:1084
EFI_STATUS EFIAPI UdpIoSendDatagram(IN UDP_IO *UdpIo, IN NET_BUF *Packet, IN UDP_END_POINT *EndPoint OPTIONAL, IN EFI_IP_ADDRESS *Gateway OPTIONAL, IN UDP_IO_CALLBACK CallBack, IN VOID *Context)
Definition: DxeUdpIoLib.c:971
EFI_STATUS EFIAPI UdpIoFreeIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:809
UDP_IO *EFIAPI UdpIoCreateIo(IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle, IN UDP_IO_CONFIG Configure, IN UINT8 UdpVersion, IN VOID *Context)
Definition: DxeUdpIoLib.c:602
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
VOID * CallbackContext
Definition: Dhcp4.h:282
EFI_DHCP4_PACKET_OPTION ** OptionList
Definition: Dhcp4.h:294
EFI_IPv4_ADDRESS ClientAddress
Definition: Dhcp4.h:273
UINT32 OptionCount
Definition: Dhcp4.h:286
EFI_DHCP4_CALLBACK Dhcp4Callback
Definition: Dhcp4.h:278
EFI_IPv4_ADDRESS ClientAddr
Client IP address from client.
Definition: Dhcp4.h:59
UINT8 ClientHwAddr[16]
Client hardware address.
Definition: Dhcp4.h:63
EFI_IPv4_ADDRESS YourAddr
Client IP address from server.
Definition: Dhcp4.h:60
UINT8 Option[1]
Definition: Dhcp4.h:93
UINT32 Length
Definition: Dhcp4.h:79
EFI_DHCP4_HEADER Header
Definition: Dhcp4.h:85
UINT32 Size
Definition: Dhcp4.h:74
UINT32 Magik
Definition: Dhcp4.h:89