]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip4Dxe/Ip4If.c
DynamicTablesPkg: Fix unaligned pointers usage
[mirror_edk2.git] / NetworkPkg / Ip4Dxe / Ip4If.c
1 /** @file
2 Implement IP4 pseudo interface.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "Ip4Impl.h"
10
11 //
12 // Mac address with all zero, used to determine whether the ARP
13 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
14 //
15 EFI_MAC_ADDRESS mZeroMacAddress;
16
17 /**
18 Callback function when frame transmission is finished. It will
19 call the frame owner's callback function to tell it the result.
20
21 @param[in] Context Context which is point to the token.
22
23 **/
24 VOID
25 EFIAPI
26 Ip4OnFrameSentDpc (
27 IN VOID *Context
28 );
29
30 /**
31 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
32
33 @param[in] Event The transmit token's event.
34 @param[in] Context Context which is point to the token.
35
36 **/
37 VOID
38 EFIAPI
39 Ip4OnFrameSent (
40 IN EFI_EVENT Event,
41 IN VOID *Context
42 );
43
44 /**
45 Callback function when ARP request are finished. It will cancelled
46 all the queued frame if the ARP requests failed. Or transmit them
47 if the request succeed.
48
49 @param[in] Context The context of the callback, a point to the ARP
50 queue
51
52 **/
53 VOID
54 EFIAPI
55 Ip4OnArpResolvedDpc (
56 IN VOID *Context
57 );
58
59 /**
60 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
61
62 @param Event The Arp request event.
63 @param Context The context of the callback, a point to the ARP
64 queue.
65
66 **/
67 VOID
68 EFIAPI
69 Ip4OnArpResolved (
70 IN EFI_EVENT Event,
71 IN VOID *Context
72 );
73
74 /**
75 Received a frame from MNP, wrap it in net buffer then deliver
76 it to IP's input function. The ownship of the packet also
77 transferred to IP. When Ip is finished with this packet, it
78 will call NetbufFree to release the packet, NetbufFree will
79 again call the Ip4RecycleFrame to signal MNP's event and free
80 the token used.
81
82 @param Context Context for the callback.
83
84 **/
85 VOID
86 EFIAPI
87 Ip4OnFrameReceivedDpc (
88 IN VOID *Context
89 );
90
91 /**
92 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
93
94 @param Event The receive event delivered to MNP for receive.
95 @param Context Context for the callback.
96
97 **/
98 VOID
99 EFIAPI
100 Ip4OnFrameReceived (
101 IN EFI_EVENT Event,
102 IN VOID *Context
103 );
104
105 /**
106 Remove all the frames on the ARP queue that pass the FrameToCancel,
107 that is, either FrameToCancel is NULL or it returns true for the frame.
108
109 @param[in] ArpQue ARP frame to remove the frames from.
110 @param[in] IoStatus The status returned to the cancelled frames'
111 callback function.
112 @param[in] FrameToCancel Function to select which frame to cancel.
113 @param[in] Context Opaque parameter to the FrameToCancel.
114
115 **/
116 VOID
117 Ip4CancelFrameArp (
118 IN IP4_ARP_QUE *ArpQue,
119 IN EFI_STATUS IoStatus,
120 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
121 IN VOID *Context
122 );
123
124
125 /**
126 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
127
128 @param[in] Interface The interface to send out to.
129 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
130 the packet is sent by the IP4 driver itself.
131 @param[in] Packet The packet to transmit
132 @param[in] CallBack Call back function to execute if transmission
133 finished.
134 @param[in] Context Opaque parameter to the call back.
135 @param[in] IpSb The pointer to the IP4 service binding instance.
136
137 @retval Token The wrapped token if succeed
138 @retval NULL The wrapped token if NULL
139
140 **/
141 IP4_LINK_TX_TOKEN *
142 Ip4WrapLinkTxToken (
143 IN IP4_INTERFACE *Interface,
144 IN IP4_PROTOCOL *IpInstance OPTIONAL,
145 IN NET_BUF *Packet,
146 IN IP4_FRAME_CALLBACK CallBack,
147 IN VOID *Context,
148 IN IP4_SERVICE *IpSb
149 )
150 {
151 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
152 EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
153 IP4_LINK_TX_TOKEN *Token;
154 EFI_STATUS Status;
155 UINT32 Count;
156
157 Token = AllocatePool (sizeof (IP4_LINK_TX_TOKEN) + \
158 (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));
159
160 if (Token == NULL) {
161 return NULL;
162 }
163
164 Token->Signature = IP4_FRAME_TX_SIGNATURE;
165 InitializeListHead (&Token->Link);
166
167 Token->Interface = Interface;
168 Token->IpInstance = IpInstance;
169 Token->IpSb = IpSb;
170 Token->CallBack = CallBack;
171 Token->Packet = Packet;
172 Token->Context = Context;
173 CopyMem (&Token->DstMac, &mZeroMacAddress, sizeof (Token->DstMac));
174 CopyMem (&Token->SrcMac, &Interface->Mac, sizeof (Token->SrcMac));
175
176 MnpToken = &(Token->MnpToken);
177 MnpToken->Status = EFI_NOT_READY;
178
179 Status = gBS->CreateEvent (
180 EVT_NOTIFY_SIGNAL,
181 TPL_NOTIFY,
182 Ip4OnFrameSent,
183 Token,
184 &MnpToken->Event
185 );
186
187 if (EFI_ERROR (Status)) {
188 FreePool (Token);
189 return NULL;
190 }
191
192 MnpTxData = &Token->MnpTxData;
193 MnpToken->Packet.TxData = MnpTxData;
194
195 MnpTxData->DestinationAddress = &Token->DstMac;
196 MnpTxData->SourceAddress = &Token->SrcMac;
197 MnpTxData->ProtocolType = IP4_ETHER_PROTO;
198 MnpTxData->DataLength = Packet->TotalSize;
199 MnpTxData->HeaderLength = 0;
200
201 Count = Packet->BlockOpNum;
202
203 NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
204 MnpTxData->FragmentCount = (UINT16)Count;
205
206 return Token;
207 }
208
209
210 /**
211 Free the link layer transmit token. It will close the event
212 then free the memory used.
213
214 @param[in] Token Token to free
215
216 **/
217 VOID
218 Ip4FreeLinkTxToken (
219 IN IP4_LINK_TX_TOKEN *Token
220 )
221 {
222 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);
223
224 gBS->CloseEvent (Token->MnpToken.Event);
225 FreePool (Token);
226 }
227
228
229 /**
230 Create an IP_ARP_QUE structure to request ARP service.
231
232 @param[in] Interface The interface to send ARP from.
233 @param[in] DestIp The destination IP (host byte order) to request MAC
234 for
235
236 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
237
238 **/
239 IP4_ARP_QUE *
240 Ip4CreateArpQue (
241 IN IP4_INTERFACE *Interface,
242 IN IP4_ADDR DestIp
243 )
244 {
245 IP4_ARP_QUE *ArpQue;
246 EFI_STATUS Status;
247
248 ArpQue = AllocatePool (sizeof (IP4_ARP_QUE));
249
250 if (ArpQue == NULL) {
251 return NULL;
252 }
253
254 ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;
255 InitializeListHead (&ArpQue->Link);
256
257 InitializeListHead (&ArpQue->Frames);
258 ArpQue->Interface = Interface;
259
260 Status = gBS->CreateEvent (
261 EVT_NOTIFY_SIGNAL,
262 TPL_NOTIFY,
263 Ip4OnArpResolved,
264 ArpQue,
265 &ArpQue->OnResolved
266 );
267
268 if (EFI_ERROR (Status)) {
269 FreePool (ArpQue);
270 return NULL;
271 }
272
273 ArpQue->Ip = DestIp;
274 CopyMem (&ArpQue->Mac, &mZeroMacAddress, sizeof (ArpQue->Mac));
275
276 return ArpQue;
277 }
278
279
280 /**
281 Remove all the transmit requests queued on the ARP queue, then free it.
282
283 @param[in] ArpQue Arp queue to free
284 @param[in] IoStatus The transmit status returned to transmit requests'
285 callback.
286
287 **/
288 VOID
289 Ip4FreeArpQue (
290 IN IP4_ARP_QUE *ArpQue,
291 IN EFI_STATUS IoStatus
292 )
293 {
294 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
295
296 //
297 // Remove all the frame waiting the ARP response
298 //
299 Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);
300
301 gBS->CloseEvent (ArpQue->OnResolved);
302 FreePool (ArpQue);
303 }
304
305
306 /**
307 Create a link layer receive token to wrap the receive request
308
309 @param[in] Interface The interface to receive from
310 @param[in] IpInstance The instance that request the receive (NULL for IP4
311 driver itself)
312 @param[in] CallBack Call back function to execute when finished.
313 @param[in] Context Opaque parameters to the callback
314
315 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
316
317 **/
318 IP4_LINK_RX_TOKEN *
319 Ip4CreateLinkRxToken (
320 IN IP4_INTERFACE *Interface,
321 IN IP4_PROTOCOL *IpInstance,
322 IN IP4_FRAME_CALLBACK CallBack,
323 IN VOID *Context
324 )
325 {
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
327 IP4_LINK_RX_TOKEN *Token;
328 EFI_STATUS Status;
329
330 Token = AllocatePool (sizeof (IP4_LINK_RX_TOKEN));
331 if (Token == NULL) {
332 return NULL;
333 }
334
335 Token->Signature = IP4_FRAME_RX_SIGNATURE;
336 Token->Interface = Interface;
337 Token->IpInstance = IpInstance;
338 Token->CallBack = CallBack;
339 Token->Context = Context;
340
341 MnpToken = &Token->MnpToken;
342 MnpToken->Status = EFI_NOT_READY;
343
344 Status = gBS->CreateEvent (
345 EVT_NOTIFY_SIGNAL,
346 TPL_NOTIFY,
347 Ip4OnFrameReceived,
348 Token,
349 &MnpToken->Event
350 );
351
352 if (EFI_ERROR (Status)) {
353 FreePool (Token);
354 return NULL;
355 }
356
357 MnpToken->Packet.RxData = NULL;
358 return Token;
359 }
360
361
362 /**
363 Free the link layer request token. It will close the event
364 then free the memory used.
365
366 @param[in] Token Request token to free.
367
368 **/
369 VOID
370 Ip4FreeFrameRxToken (
371 IN IP4_LINK_RX_TOKEN *Token
372 )
373 {
374
375 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
376
377 gBS->CloseEvent (Token->MnpToken.Event);
378 FreePool (Token);
379 }
380
381
382 /**
383 Remove all the frames on the ARP queue that pass the FrameToCancel,
384 that is, either FrameToCancel is NULL or it returns true for the frame.
385
386 @param[in] ArpQue ARP frame to remove the frames from.
387 @param[in] IoStatus The status returned to the cancelled frames'
388 callback function.
389 @param[in] FrameToCancel Function to select which frame to cancel.
390 @param[in] Context Opaque parameter to the FrameToCancel.
391
392 **/
393 VOID
394 Ip4CancelFrameArp (
395 IN IP4_ARP_QUE *ArpQue,
396 IN EFI_STATUS IoStatus,
397 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
398 IN VOID *Context
399 )
400 {
401 LIST_ENTRY *Entry;
402 LIST_ENTRY *Next;
403 IP4_LINK_TX_TOKEN *Token;
404
405 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
406 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
407
408 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
409 RemoveEntryList (Entry);
410
411 Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);
412 Ip4FreeLinkTxToken (Token);
413 }
414 }
415 }
416
417
418 /**
419 Remove all the frames on the interface that pass the FrameToCancel,
420 either queued on ARP queues or that have already been delivered to
421 MNP and not yet recycled.
422
423 @param[in] Interface Interface to remove the frames from.
424 @param[in] IoStatus The transmit status returned to the frames'
425 callback.
426 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
427 select all.
428 @param[in] Context Opaque parameters passed to FrameToCancel.
429
430 **/
431 VOID
432 Ip4CancelFrames (
433 IN IP4_INTERFACE *Interface,
434 IN EFI_STATUS IoStatus,
435 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
436 IN VOID *Context
437 )
438 {
439 LIST_ENTRY *Entry;
440 LIST_ENTRY *Next;
441 IP4_ARP_QUE *ArpQue;
442 IP4_LINK_TX_TOKEN *Token;
443
444 //
445 // Cancel all the pending frames on ARP requests
446 //
447 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
448 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
449
450 Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);
451
452 if (IsListEmpty (&ArpQue->Frames)) {
453 Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);
454 }
455 }
456
457 //
458 // Cancel all the frames that have been delivered to MNP
459 // but not yet recycled.
460 //
461 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
462 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
463
464 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
465 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
466 }
467 }
468 }
469
470
471 /**
472 Create an IP4_INTERFACE. Delay the creation of ARP instance until
473 the interface is configured.
474
475 @param[in] Mnp The shared MNP child of this IP4 service binding
476 instance.
477 @param[in] Controller The controller this IP4 service binding instance
478 is installed. Most like the UNDI handle.
479 @param[in] ImageHandle This driver's image handle.
480
481 @return Point to the created IP4_INTERFACE, otherwise NULL.
482
483 **/
484 IP4_INTERFACE *
485 Ip4CreateInterface (
486 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
487 IN EFI_HANDLE Controller,
488 IN EFI_HANDLE ImageHandle
489 )
490 {
491 IP4_INTERFACE *Interface;
492 EFI_SIMPLE_NETWORK_MODE SnpMode;
493
494 if (Mnp == NULL) {
495 return NULL;
496 }
497
498 Interface = AllocatePool (sizeof (IP4_INTERFACE));
499
500 if (Interface == NULL) {
501 return NULL;
502 }
503
504 Interface->Signature = IP4_INTERFACE_SIGNATURE;
505 InitializeListHead (&Interface->Link);
506 Interface->RefCnt = 1;
507
508 Interface->Ip = IP4_ALLZERO_ADDRESS;
509 Interface->SubnetMask = IP4_ALLZERO_ADDRESS;
510 Interface->Configured = FALSE;
511
512 Interface->Controller = Controller;
513 Interface->Image = ImageHandle;
514 Interface->Mnp = Mnp;
515 Interface->Arp = NULL;
516 Interface->ArpHandle = NULL;
517
518 InitializeListHead (&Interface->ArpQues);
519 InitializeListHead (&Interface->SentFrames);
520
521 Interface->RecvRequest = NULL;
522
523 //
524 // Get the interface's Mac address and broadcast mac address from SNP
525 //
526 if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {
527 FreePool (Interface);
528 return NULL;
529 }
530
531 CopyMem (&Interface->Mac, &SnpMode.CurrentAddress, sizeof (Interface->Mac));
532 CopyMem (&Interface->BroadcastMac, &SnpMode.BroadcastAddress, sizeof (Interface->BroadcastMac));
533 Interface->HwaddrLen = SnpMode.HwAddressSize;
534
535 InitializeListHead (&Interface->IpInstances);
536 Interface->PromiscRecv = FALSE;
537
538 return Interface;
539 }
540
541
542 /**
543 Set the interface's address, create and configure
544 the ARP child if necessary.
545
546 @param Interface The interface to set the address.
547 @param IpAddr The interface's IP address.
548 @param SubnetMask The interface's netmask.
549
550 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
551 and a ARP is created for it.
552 @retval Others Failed to set the interface's address.
553
554 **/
555 EFI_STATUS
556 Ip4SetAddress (
557 IN OUT IP4_INTERFACE *Interface,
558 IN IP4_ADDR IpAddr,
559 IN IP4_ADDR SubnetMask
560 )
561 {
562 EFI_ARP_CONFIG_DATA ArpConfig;
563 EFI_STATUS Status;
564
565 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
566
567 //
568 // Set the ip/netmask, then compute the subnet broadcast
569 // and network broadcast for easy access. When computing
570 // network broadcast, the subnet mask is most like longer
571 // than the default netmask (not subneted) as defined in
572 // RFC793. If that isn't the case, we are aggregating the
573 // networks, use the subnet's mask instead.
574 //
575 Interface->Ip = IpAddr;
576 Interface->SubnetMask = SubnetMask;
577 Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);
578 Interface->NetBrdcast = (IpAddr | ~SubnetMask);
579
580 //
581 // Do clean up for Arp child
582 //
583 if (Interface->ArpHandle != NULL) {
584 if (Interface->Arp != NULL) {
585 gBS->CloseProtocol (
586 Interface->ArpHandle,
587 &gEfiArpProtocolGuid,
588 Interface->Image,
589 Interface->Controller
590 );
591
592 Interface->Arp = NULL;
593 }
594
595 NetLibDestroyServiceChild (
596 Interface->Controller,
597 Interface->Image,
598 &gEfiArpServiceBindingProtocolGuid,
599 Interface->ArpHandle
600 );
601
602 Interface->ArpHandle = NULL;
603 }
604
605 //
606 // If the address is NOT all zero, create then configure an ARP child.
607 // Pay attention: DHCP configures its station address as 0.0.0.0/0
608 //
609 if (IpAddr != IP4_ALLZERO_ADDRESS) {
610 Status = NetLibCreateServiceChild (
611 Interface->Controller,
612 Interface->Image,
613 &gEfiArpServiceBindingProtocolGuid,
614 &Interface->ArpHandle
615 );
616
617 if (EFI_ERROR (Status)) {
618 return Status;
619 }
620
621 Status = gBS->OpenProtocol (
622 Interface->ArpHandle,
623 &gEfiArpProtocolGuid,
624 (VOID **) &Interface->Arp,
625 Interface->Image,
626 Interface->Controller,
627 EFI_OPEN_PROTOCOL_BY_DRIVER
628 );
629
630 if (EFI_ERROR (Status)) {
631 goto ON_ERROR;
632 }
633
634 IpAddr = HTONL (IpAddr);
635 ArpConfig.SwAddressType = IP4_ETHER_PROTO;
636 ArpConfig.SwAddressLength = 4;
637 ArpConfig.StationAddress = &IpAddr;
638 ArpConfig.EntryTimeOut = 0;
639 ArpConfig.RetryCount = 0;
640 ArpConfig.RetryTimeOut = 0;
641
642 Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);
643
644 if (EFI_ERROR (Status)) {
645 gBS->CloseProtocol (
646 Interface->ArpHandle,
647 &gEfiArpProtocolGuid,
648 Interface->Image,
649 Interface->Controller
650 );
651
652 goto ON_ERROR;
653 }
654 }
655
656 Interface->Configured = TRUE;
657 return EFI_SUCCESS;
658
659 ON_ERROR:
660 NetLibDestroyServiceChild (
661 Interface->Controller,
662 Interface->Image,
663 &gEfiArpServiceBindingProtocolGuid,
664 Interface->ArpHandle
665 );
666
667 return Status;
668 }
669
670
671 /**
672 Filter function to cancel all the frame related to an IP instance.
673
674 @param[in] Frame The transmit request to test whether to cancel
675 @param[in] Context The context which is the Ip instance that issued
676 the transmit.
677
678 @retval TRUE The frame belongs to this instance and is to be
679 removed
680 @retval FALSE The frame doesn't belong to this instance.
681
682 **/
683 BOOLEAN
684 Ip4CancelInstanceFrame (
685 IN IP4_LINK_TX_TOKEN *Frame,
686 IN VOID *Context
687 )
688 {
689 if (Frame->IpInstance == (IP4_PROTOCOL *) Context) {
690 return TRUE;
691 }
692
693 return FALSE;
694 }
695
696
697
698 /**
699 If there is a pending receive request, cancel it. Don't call
700 the receive request's callback because this function can be only
701 called if the instance or driver is tearing itself down. It
702 doesn't make sense to call it back. But it is necessary to call
703 the transmit token's callback to give it a chance to free the
704 packet and update the upper layer's transmit request status, say
705 that from the UDP.
706
707 @param[in] Interface The interface used by the IpInstance
708
709 **/
710 VOID
711 Ip4CancelReceive (
712 IN IP4_INTERFACE *Interface
713 )
714 {
715 EFI_TPL OldTpl;
716 IP4_LINK_RX_TOKEN *Token;
717
718 if ((Token = Interface->RecvRequest) != NULL) {
719 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
720
721 Interface->RecvRequest = NULL;
722 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
723
724 gBS->RestoreTPL (OldTpl);
725 }
726 }
727
728
729 /**
730 Free the interface used by IpInstance. All the IP instance with
731 the same Ip/Netmask pair share the same interface. It is reference
732 counted. All the frames haven't been sent will be cancelled.
733 Because the IpInstance is optional, the caller must remove
734 IpInstance from the interface's instance list itself.
735
736 @param[in] Interface The interface used by the IpInstance.
737 @param[in] IpInstance The Ip instance that free the interface. NULL if
738 the Ip driver is releasing the default interface.
739
740 @retval EFI_SUCCESS The interface use IpInstance is freed.
741
742 **/
743 EFI_STATUS
744 Ip4FreeInterface (
745 IN IP4_INTERFACE *Interface,
746 IN IP4_PROTOCOL *IpInstance OPTIONAL
747 )
748 {
749 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
750 ASSERT (Interface->RefCnt > 0);
751
752 //
753 // Remove all the pending transmit token related to this IP instance.
754 //
755 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
756
757 if (--Interface->RefCnt > 0) {
758 return EFI_SUCCESS;
759 }
760
761 //
762 // Destroy the interface if this is the last IP instance that
763 // has the address. Remove all the system transmitted packets
764 // from this interface, cancel the receive request if there is
765 // one, and destroy the ARP requests.
766 //
767 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
768 Ip4CancelReceive (Interface);
769
770 ASSERT (IsListEmpty (&Interface->IpInstances));
771 ASSERT (IsListEmpty (&Interface->ArpQues));
772 ASSERT (IsListEmpty (&Interface->SentFrames));
773
774 if (Interface->Arp != NULL) {
775 gBS->CloseProtocol (
776 Interface->ArpHandle,
777 &gEfiArpProtocolGuid,
778 Interface->Image,
779 Interface->Controller
780 );
781
782 NetLibDestroyServiceChild (
783 Interface->Controller,
784 Interface->Image,
785 &gEfiArpServiceBindingProtocolGuid,
786 Interface->ArpHandle
787 );
788 }
789
790 RemoveEntryList (&Interface->Link);
791 FreePool (Interface);
792
793 return EFI_SUCCESS;
794 }
795
796 /**
797 This function tries to send all the queued frames in ArpQue to the default gateway if
798 the ARP resolve for direct destination address is failed when using /32 subnet mask.
799
800 @param[in] ArpQue The ARP queue of a failed request.
801
802 @retval EFI_SUCCESS All the queued frames have been send to the default route.
803 @retval Others Failed to send the queued frames.
804
805 **/
806 EFI_STATUS
807 Ip4SendFrameToDefaultRoute (
808 IN IP4_ARP_QUE *ArpQue
809 )
810 {
811 LIST_ENTRY *Entry;
812 LIST_ENTRY *Next;
813 IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
814 IP4_LINK_TX_TOKEN *Token;
815 IP4_ADDR Gateway;
816 EFI_STATUS Status;
817 IP4_ROUTE_ENTRY *DefaultRoute;
818
819 //
820 // ARP resolve failed when using /32 subnet mask.
821 //
822 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
823 RemoveEntryList (Entry);
824 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
825 ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);
826 //
827 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
828 //
829 RtCacheEntry = NULL;
830 if (Token->IpInstance != NULL) {
831 RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
832 }
833 if (RtCacheEntry == NULL) {
834 RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
835 }
836 if (RtCacheEntry == NULL) {
837 Status= EFI_NO_MAPPING;
838 goto ON_ERROR;
839 }
840 DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;
841 if (DefaultRoute == NULL) {
842 Status= EFI_NO_MAPPING;
843 goto ON_ERROR;
844 }
845 //
846 // Try to send the frame to the default route.
847 //
848 Gateway = DefaultRoute->NextHop;
849 if (ArpQue->Ip == Gateway) {
850 //
851 // ARP resolve for the default route is failed, return error to caller.
852 //
853 Status= EFI_NO_MAPPING;
854 goto ON_ERROR;
855 }
856 RtCacheEntry->NextHop = Gateway;
857 Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);
858 if (EFI_ERROR (Status)) {
859 Status= EFI_NO_MAPPING;
860 goto ON_ERROR;
861 }
862 Ip4FreeRouteCacheEntry (RtCacheEntry);
863 }
864
865 return EFI_SUCCESS;
866
867 ON_ERROR:
868 if (RtCacheEntry != NULL) {
869 Ip4FreeRouteCacheEntry (RtCacheEntry);
870 }
871 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
872 Ip4FreeLinkTxToken (Token);
873 return Status;
874 }
875
876
877 /**
878 Callback function when ARP request are finished. It will cancel
879 all the queued frame if the ARP requests failed. Or transmit them
880 if the request succeed.
881
882 @param[in] Context The context of the callback, a point to the ARP
883 queue
884
885 **/
886 VOID
887 EFIAPI
888 Ip4OnArpResolvedDpc (
889 IN VOID *Context
890 )
891 {
892 LIST_ENTRY *Entry;
893 LIST_ENTRY *Next;
894 IP4_ARP_QUE *ArpQue;
895 IP4_INTERFACE *Interface;
896 IP4_LINK_TX_TOKEN *Token;
897 EFI_STATUS Status;
898 EFI_STATUS IoStatus;
899
900 ArpQue = (IP4_ARP_QUE *) Context;
901 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
902
903 RemoveEntryList (&ArpQue->Link);
904
905 //
906 // ARP resolve failed for some reason.
907 //
908 if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {
909 if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {
910 //
911 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
912 // owner back.
913 //
914 IoStatus = EFI_NO_MAPPING;
915 } else {
916 //
917 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
918 // default route.
919 //
920 IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);
921 }
922 goto ON_EXIT;
923 }
924
925 //
926 // ARP resolve succeeded, Transmit all the frame. Release the ARP
927 // queue. It isn't necessary for us to cache the ARP binding because
928 // we always check the ARP cache first before transmit.
929 //
930 IoStatus = EFI_SUCCESS;
931 Interface = ArpQue->Interface;
932
933 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
934 RemoveEntryList (Entry);
935
936 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
937 CopyMem (&Token->DstMac, &ArpQue->Mac, sizeof (Token->DstMac));
938
939 //
940 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
941 // may be called before Mnp->Transmit returns which will remove this tx
942 // token from the SentFrames list. Remove it from the list if the returned
943 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
944 // FrameSentDpc won't be queued.
945 //
946 InsertTailList (&Interface->SentFrames, &Token->Link);
947
948 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
949 if (EFI_ERROR (Status)) {
950 RemoveEntryList (&Token->Link);
951 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
952
953 Ip4FreeLinkTxToken (Token);
954 continue;
955 }
956 }
957
958 ON_EXIT:
959 Ip4FreeArpQue (ArpQue, IoStatus);
960 }
961
962 /**
963 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
964
965 @param Event The Arp request event.
966 @param Context The context of the callback, a point to the ARP
967 queue.
968
969 **/
970 VOID
971 EFIAPI
972 Ip4OnArpResolved (
973 IN EFI_EVENT Event,
974 IN VOID *Context
975 )
976 {
977 //
978 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
979 //
980 QueueDpc (TPL_CALLBACK, Ip4OnArpResolvedDpc, Context);
981 }
982
983
984
985 /**
986 Callback function when frame transmission is finished. It will
987 call the frame owner's callback function to tell it the result.
988
989 @param[in] Context Context which is point to the token.
990
991 **/
992 VOID
993 EFIAPI
994 Ip4OnFrameSentDpc (
995 IN VOID *Context
996 )
997 {
998 IP4_LINK_TX_TOKEN *Token;
999
1000 Token = (IP4_LINK_TX_TOKEN *) Context;
1001 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);
1002
1003 RemoveEntryList (&Token->Link);
1004
1005 Token->CallBack (
1006 Token->IpInstance,
1007 Token->Packet,
1008 Token->MnpToken.Status,
1009 0,
1010 Token->Context
1011 );
1012
1013 Ip4FreeLinkTxToken (Token);
1014 }
1015
1016 /**
1017 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1018
1019 @param[in] Event The transmit token's event.
1020 @param[in] Context Context which is point to the token.
1021
1022 **/
1023 VOID
1024 EFIAPI
1025 Ip4OnFrameSent (
1026 IN EFI_EVENT Event,
1027 IN VOID *Context
1028 )
1029 {
1030 //
1031 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1032 //
1033 QueueDpc (TPL_CALLBACK, Ip4OnFrameSentDpc, Context);
1034 }
1035
1036
1037
1038 /**
1039 Send a frame from the interface. If the next hop is broadcast or
1040 multicast address, it is transmitted immediately. If the next hop
1041 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1042 If some error happened, the CallBack won't be called. So, the caller
1043 must test the return value, and take action when there is an error.
1044
1045 @param[in] Interface The interface to send the frame from
1046 @param[in] IpInstance The IP child that request the transmission. NULL
1047 if it is the IP4 driver itself.
1048 @param[in] Packet The packet to transmit.
1049 @param[in] NextHop The immediate destination to transmit the packet
1050 to.
1051 @param[in] CallBack Function to call back when transmit finished.
1052 @param[in] Context Opaque parameter to the call back.
1053 @param[in] IpSb The pointer to the IP4 service binding instance.
1054
1055 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1056 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1057 @retval EFI_SUCCESS The packet is successfully transmitted.
1058 @retval other Other error occurs.
1059
1060 **/
1061 EFI_STATUS
1062 Ip4SendFrame (
1063 IN IP4_INTERFACE *Interface,
1064 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1065 IN NET_BUF *Packet,
1066 IN IP4_ADDR NextHop,
1067 IN IP4_FRAME_CALLBACK CallBack,
1068 IN VOID *Context,
1069 IN IP4_SERVICE *IpSb
1070 )
1071 {
1072 IP4_LINK_TX_TOKEN *Token;
1073 LIST_ENTRY *Entry;
1074 IP4_ARP_QUE *ArpQue;
1075 EFI_ARP_PROTOCOL *Arp;
1076 EFI_STATUS Status;
1077
1078 ASSERT (Interface->Configured);
1079
1080 Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);
1081
1082 if (Token == NULL) {
1083 return EFI_OUT_OF_RESOURCES;
1084 }
1085
1086 //
1087 // Get the destination MAC address for multicast and broadcasts.
1088 // Don't depend on ARP to solve the address since there maybe no
1089 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1090 // all the broadcasts.
1091 //
1092 if (NextHop == IP4_ALLONE_ADDRESS) {
1093 CopyMem (&Token->DstMac, &Interface->BroadcastMac, sizeof (Token->DstMac));
1094 goto SEND_NOW;
1095
1096 } else if (IP4_IS_MULTICAST (NextHop)) {
1097
1098 Status = Ip4GetMulticastMac (Interface->Mnp, NextHop, &Token->DstMac);
1099
1100 if (EFI_ERROR (Status)) {
1101 goto ON_ERROR;
1102 }
1103
1104 goto SEND_NOW;
1105 }
1106
1107 //
1108 // Can only send out multicast/broadcast if the IP address is zero
1109 //
1110 if ((Arp = Interface->Arp) == NULL) {
1111 Status = EFI_NO_MAPPING;
1112 goto ON_ERROR;
1113 }
1114
1115 //
1116 // First check whether this binding is in the ARP cache.
1117 //
1118 NextHop = HTONL (NextHop);
1119 Status = Arp->Request (Arp, &NextHop, NULL, &Token->DstMac);
1120
1121 if (Status == EFI_SUCCESS) {
1122 goto SEND_NOW;
1123
1124 } else if (Status != EFI_NOT_READY) {
1125 goto ON_ERROR;
1126 }
1127
1128 //
1129 // Have to do asynchronous ARP resolution. First check
1130 // whether there is already a pending request.
1131 //
1132 ArpQue = NULL;
1133
1134 NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
1135 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
1136
1137 if (ArpQue->Ip == NextHop) {
1138 break;
1139 }
1140 }
1141
1142 //
1143 // Found a pending ARP request, enqueue the frame then return
1144 //
1145 if (Entry != &Interface->ArpQues) {
1146 InsertTailList (&ArpQue->Frames, &Token->Link);
1147 return EFI_SUCCESS;
1148 }
1149
1150 //
1151 // First frame to NextHop, issue an asynchronous ARP requests
1152 //
1153 ArpQue = Ip4CreateArpQue (Interface, NextHop);
1154
1155 if (ArpQue == NULL) {
1156 Status = EFI_OUT_OF_RESOURCES;
1157 goto ON_ERROR;
1158 }
1159
1160 Status = Arp->Request (Arp, &ArpQue->Ip, ArpQue->OnResolved, ArpQue->Mac.Addr);
1161
1162 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
1163 Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);
1164 goto ON_ERROR;
1165 }
1166
1167 InsertHeadList (&ArpQue->Frames, &Token->Link);
1168 InsertHeadList (&Interface->ArpQues, &ArpQue->Link);
1169 return EFI_SUCCESS;
1170
1171 SEND_NOW:
1172 //
1173 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1174 // Remove it if the returned status is not EFI_SUCCESS.
1175 //
1176 InsertTailList (&Interface->SentFrames, &Token->Link);
1177 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
1178 if (EFI_ERROR (Status)) {
1179 RemoveEntryList (&Token->Link);
1180 goto ON_ERROR;
1181 }
1182
1183 return EFI_SUCCESS;
1184
1185 ON_ERROR:
1186 Ip4FreeLinkTxToken (Token);
1187 return Status;
1188 }
1189
1190
1191 /**
1192 Call back function when the received packet is freed.
1193 Check Ip4OnFrameReceived for information.
1194
1195 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1196
1197 **/
1198 VOID
1199 EFIAPI
1200 Ip4RecycleFrame (
1201 IN VOID *Context
1202 )
1203 {
1204 IP4_LINK_RX_TOKEN *Frame;
1205
1206 Frame = (IP4_LINK_RX_TOKEN *) Context;
1207 NET_CHECK_SIGNATURE (Frame, IP4_FRAME_RX_SIGNATURE);
1208
1209 gBS->SignalEvent (Frame->MnpToken.Packet.RxData->RecycleEvent);
1210 Ip4FreeFrameRxToken (Frame);
1211 }
1212
1213
1214 /**
1215 Received a frame from MNP, wrap it in net buffer then deliver
1216 it to IP's input function. The ownship of the packet also
1217 transferred to IP. When Ip is finished with this packet, it
1218 will call NetbufFree to release the packet, NetbufFree will
1219 again call the Ip4RecycleFrame to signal MNP's event and free
1220 the token used.
1221
1222 @param Context Context for the callback.
1223
1224 **/
1225 VOID
1226 EFIAPI
1227 Ip4OnFrameReceivedDpc (
1228 IN VOID *Context
1229 )
1230 {
1231 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
1232 EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
1233 IP4_LINK_RX_TOKEN *Token;
1234 NET_FRAGMENT Netfrag;
1235 NET_BUF *Packet;
1236 UINT32 Flag;
1237
1238 Token = (IP4_LINK_RX_TOKEN *) Context;
1239 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
1240
1241 //
1242 // First clear the interface's receive request in case the
1243 // caller wants to call Ip4ReceiveFrame in the callback.
1244 //
1245 Token->Interface->RecvRequest = NULL;
1246
1247 MnpToken = &Token->MnpToken;
1248 MnpRxData = MnpToken->Packet.RxData;
1249
1250 if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
1251 Token->CallBack (Token->IpInstance, NULL, MnpToken->Status, 0, Token->Context);
1252 Ip4FreeFrameRxToken (Token);
1253
1254 return ;
1255 }
1256
1257 //
1258 // Wrap the frame in a net buffer then deliver it to IP input.
1259 // IP will reassemble the packet, and deliver it to upper layer
1260 //
1261 Netfrag.Len = MnpRxData->DataLength;
1262 Netfrag.Bulk = MnpRxData->PacketData;
1263
1264 Packet = NetbufFromExt (&Netfrag, 1, 0, IP4_MAX_HEADLEN, Ip4RecycleFrame, Token);
1265
1266 if (Packet == NULL) {
1267 gBS->SignalEvent (MnpRxData->RecycleEvent);
1268
1269 Token->CallBack (Token->IpInstance, NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
1270 Ip4FreeFrameRxToken (Token);
1271
1272 return ;
1273 }
1274
1275 Flag = (MnpRxData->BroadcastFlag ? IP4_LINK_BROADCAST : 0);
1276 Flag |= (MnpRxData->MulticastFlag ? IP4_LINK_MULTICAST : 0);
1277 Flag |= (MnpRxData->PromiscuousFlag ? IP4_LINK_PROMISC : 0);
1278
1279 Token->CallBack (Token->IpInstance, Packet, EFI_SUCCESS, Flag, Token->Context);
1280 }
1281
1282 /**
1283 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1284
1285 @param Event The receive event delivered to MNP for receive.
1286 @param Context Context for the callback.
1287
1288 **/
1289 VOID
1290 EFIAPI
1291 Ip4OnFrameReceived (
1292 IN EFI_EVENT Event,
1293 IN VOID *Context
1294 )
1295 {
1296 //
1297 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1298 //
1299 QueueDpc (TPL_CALLBACK, Ip4OnFrameReceivedDpc, Context);
1300 }
1301
1302
1303 /**
1304 Request to receive the packet from the interface.
1305
1306 @param[in] Interface The interface to receive the frames from.
1307 @param[in] IpInstance The instance that requests the receive. NULL for
1308 the driver itself.
1309 @param[in] CallBack Function to call when receive finished.
1310 @param[in] Context Opaque parameter to the callback.
1311
1312 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1313 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1314 @retval EFI_SUCCESS The receive request has been started.
1315 @retval other Other error occurs.
1316
1317 **/
1318 EFI_STATUS
1319 Ip4ReceiveFrame (
1320 IN IP4_INTERFACE *Interface,
1321 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1322 IN IP4_FRAME_CALLBACK CallBack,
1323 IN VOID *Context
1324 )
1325 {
1326 IP4_LINK_RX_TOKEN *Token;
1327 EFI_STATUS Status;
1328
1329 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
1330
1331 if (Interface->RecvRequest != NULL) {
1332 return EFI_ALREADY_STARTED;
1333 }
1334
1335 Token = Ip4CreateLinkRxToken (Interface, IpInstance, CallBack, Context);
1336
1337 if (Token == NULL) {
1338 return EFI_OUT_OF_RESOURCES;
1339 }
1340
1341 Interface->RecvRequest = Token;
1342 Status = Interface->Mnp->Receive (Interface->Mnp, &Token->MnpToken);
1343 if (EFI_ERROR (Status)) {
1344 Interface->RecvRequest = NULL;
1345 Ip4FreeFrameRxToken (Token);
1346 return Status;
1347 }
1348 return EFI_SUCCESS;
1349 }