EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

NetworkPkg/Ip6Dxe/Ip6Impl.c

Go to the documentation of this file.
00001 
00016 #include "Ip6Impl.h"
00017 
00018 EFI_IPSEC2_PROTOCOL    *mIpSec = NULL;
00019 
00020 EFI_IP6_PROTOCOL mEfiIp6ProtocolTemplete = {
00021   EfiIp6GetModeData,
00022   EfiIp6Configure,
00023   EfiIp6Groups,
00024   EfiIp6Routes,
00025   EfiIp6Neighbors,
00026   EfiIp6Transmit,
00027   EfiIp6Receive,
00028   EfiIp6Cancel,
00029   EfiIp6Poll
00030 };
00031 
00049 EFI_STATUS
00050 EFIAPI
00051 EfiIp6GetModeData (
00052   IN EFI_IP6_PROTOCOL                 *This,
00053   OUT EFI_IP6_MODE_DATA               *Ip6ModeData     OPTIONAL,
00054   OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData   OPTIONAL,
00055   OUT EFI_SIMPLE_NETWORK_MODE         *SnpModeData     OPTIONAL
00056   )
00057 {
00058   IP6_PROTOCOL              *IpInstance;
00059   IP6_SERVICE               *IpSb;
00060   IP6_INTERFACE             *IpIf;
00061   EFI_IP6_CONFIG_DATA       *Config;
00062   EFI_STATUS                Status;
00063   EFI_TPL                   OldTpl;
00064 
00065   if (This == NULL) {
00066     return EFI_INVALID_PARAMETER;
00067   }
00068 
00069   OldTpl     = gBS->RaiseTPL (TPL_CALLBACK);
00070   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
00071   IpSb       = IpInstance->Service;
00072   IpIf       = IpInstance->Interface;
00073 
00074   if (IpSb->LinkLocalDadFail) {
00075     return EFI_INVALID_PARAMETER;
00076   }
00077 
00078   if (Ip6ModeData != NULL) {
00079     //
00080     // IsStarted is "whether the EfiIp6Configure has been called".
00081     // IsConfigured is "whether the station address has been configured"
00082     //
00083     Ip6ModeData->IsStarted     = (BOOLEAN) (IpInstance->State == IP6_STATE_CONFIGED);
00084     Ip6ModeData->MaxPacketSize = IpSb->MaxPacketSize;
00085     CopyMem (&Ip6ModeData->ConfigData, &IpInstance->ConfigData, sizeof (EFI_IP6_CONFIG_DATA));
00086     Ip6ModeData->IsConfigured  = FALSE;
00087 
00088     Ip6ModeData->AddressCount  = 0;
00089     Ip6ModeData->AddressList   = NULL;
00090 
00091     Ip6ModeData->GroupCount    = IpInstance->GroupCount;
00092     Ip6ModeData->GroupTable    = NULL;
00093 
00094     Ip6ModeData->RouteCount    = 0;
00095     Ip6ModeData->RouteTable    = NULL;
00096 
00097     Ip6ModeData->NeighborCount = 0;
00098     Ip6ModeData->NeighborCache = NULL;
00099 
00100     Ip6ModeData->PrefixCount   = 0;
00101     Ip6ModeData->PrefixTable   = NULL;
00102 
00103     Ip6ModeData->IcmpTypeCount = 23;
00104     Ip6ModeData->IcmpTypeList  = AllocateCopyPool (
00105                                    Ip6ModeData->IcmpTypeCount * sizeof (EFI_IP6_ICMP_TYPE),
00106                                    mIp6SupportedIcmp
00107                                    );
00108     if (Ip6ModeData->IcmpTypeList == NULL) {
00109       Status = EFI_OUT_OF_RESOURCES;
00110       goto Error;
00111     }
00112 
00113     //
00114     // Return the currently configured IPv6 addresses and corresponding prefix lengths.
00115     //
00116     Status = Ip6BuildEfiAddressList (
00117                IpSb,
00118                &Ip6ModeData->AddressCount,
00119                &Ip6ModeData->AddressList
00120                );
00121     if (EFI_ERROR (Status)) {
00122       goto Error;
00123     }
00124 
00125     //
00126     // Return the current station address for this IP child.
00127     // If UseAnyStationAddress is set to TRUE, IP6 driver will
00128     // select a source address from its address list. Otherwise use the
00129     // StationAddress in config data.
00130     //
00131     if (Ip6ModeData->IsStarted) {
00132       Config = &Ip6ModeData->ConfigData;
00133 
00134       if (IpIf->Configured || NetIp6IsUnspecifiedAddr (&Config->DestinationAddress)) {
00135         Ip6ModeData->IsConfigured = TRUE;
00136       } else {
00137         Ip6ModeData->IsConfigured = FALSE;
00138       }
00139 
00140       //
00141       // Build a EFI route table for user from the internal route table.
00142       //
00143       Status = Ip6BuildEfiRouteTable (
00144                  IpSb->RouteTable,
00145                  &Ip6ModeData->RouteCount,
00146                  &Ip6ModeData->RouteTable
00147                  );
00148 
00149       if (EFI_ERROR (Status)) {
00150         goto Error;
00151       }
00152     }
00153 
00154     if (Ip6ModeData->IsConfigured) {
00155       //
00156       // Return the joined multicast group addresses.
00157       //
00158       if (IpInstance->GroupCount != 0) {
00159         Ip6ModeData->GroupTable = AllocateCopyPool (
00160                                     IpInstance->GroupCount * sizeof (EFI_IPv6_ADDRESS),
00161                                     IpInstance->GroupList
00162                                     );
00163         if (Ip6ModeData->GroupTable == NULL) {
00164           Status = EFI_OUT_OF_RESOURCES;
00165           goto Error;
00166         }
00167       }
00168       //
00169       // Return the neighbor cache entries
00170       //
00171       Status = Ip6BuildEfiNeighborCache (
00172                  IpInstance,
00173                  &Ip6ModeData->NeighborCount,
00174                  &Ip6ModeData->NeighborCache
00175                  );
00176       if (EFI_ERROR (Status)) {
00177         goto Error;
00178       }
00179 
00180       //
00181       // Return the prefix table entries
00182       //
00183       Status = Ip6BuildPrefixTable (
00184                  IpInstance,
00185                  &Ip6ModeData->PrefixCount,
00186                  &Ip6ModeData->PrefixTable
00187                  );
00188       if (EFI_ERROR (Status)) {
00189         goto Error;
00190       }
00191 
00192     }
00193   }
00194 
00195   //
00196   // Get fresh mode data from MNP, since underlying media status may change
00197   //
00198   Status = IpSb->Mnp->GetModeData (IpSb->Mnp, MnpConfigData, SnpModeData);
00199 
00200   goto Exit;
00201 
00202 Error:
00203   if (Ip6ModeData != NULL) {
00204     if (Ip6ModeData->AddressList != NULL) {
00205       FreePool (Ip6ModeData->AddressList);
00206     }
00207 
00208     if (Ip6ModeData->GroupTable != NULL) {
00209       FreePool (Ip6ModeData->GroupTable);
00210     }
00211 
00212     if (Ip6ModeData->RouteTable != NULL) {
00213       FreePool (Ip6ModeData->RouteTable);
00214     }
00215 
00216     if (Ip6ModeData->NeighborCache != NULL) {
00217       FreePool (Ip6ModeData->NeighborCache);
00218     }
00219 
00220     if (Ip6ModeData->PrefixTable != NULL) {
00221       FreePool (Ip6ModeData->PrefixTable);
00222     }
00223 
00224     if (Ip6ModeData->IcmpTypeList != NULL) {
00225       FreePool (Ip6ModeData->IcmpTypeList);
00226     }
00227   }
00228 
00229 Exit:
00230   gBS->RestoreTPL (OldTpl);
00231   return Status;
00232 }
00233 
00248 BOOLEAN
00249 Ip6IsValidAddress (
00250   IN IP6_SERVICE            *IpSb,
00251   IN EFI_IPv6_ADDRESS       *Ip,
00252   IN BOOLEAN                Flag
00253   )
00254 {
00255   if (!NetIp6IsUnspecifiedAddr (Ip)) {
00256     if (!NetIp6IsValidUnicast(Ip)) {
00257       return FALSE;
00258     }
00259     if (Ip6IsOneOfSetAddress (IpSb, Ip, NULL, NULL)) {
00260       return Flag;
00261     }
00262   } else {
00263     return Flag;
00264   }
00265 
00266   return (BOOLEAN) !Flag;
00267 }
00268 
00279 BOOLEAN
00280 Ip6IsIllegalProtocol (
00281   IN UINT8                  Protocol
00282   )
00283 {
00284   if (Protocol == IP6_HOP_BY_HOP || Protocol == EFI_IP_PROTO_ICMP || Protocol == IP4_PROTO_IGMP) {
00285     return TRUE;
00286   }
00287 
00288   if (Protocol == 41 || Protocol == 43 || Protocol == 44 || Protocol == 59 || Protocol == 60 || Protocol == 124) {
00289     return TRUE;
00290   }
00291 
00292   return FALSE;
00293 }
00294 
00302 VOID
00303 Ip6InitProtocol (
00304   IN IP6_SERVICE            *IpSb,
00305   IN OUT IP6_PROTOCOL       *IpInstance
00306   )
00307 {
00308   ASSERT ((IpSb != NULL) && (IpInstance != NULL));
00309 
00310   ZeroMem (IpInstance, sizeof (IP6_PROTOCOL));
00311 
00312   IpInstance->Signature = IP6_PROTOCOL_SIGNATURE;
00313   IpInstance->State     = IP6_STATE_UNCONFIGED;
00314   IpInstance->Service   = IpSb;
00315   IpInstance->GroupList = NULL;
00316   CopyMem (&IpInstance->Ip6Proto, &mEfiIp6ProtocolTemplete, sizeof (EFI_IP6_PROTOCOL));
00317 
00318   NetMapInit  (&IpInstance->RxTokens);
00319   NetMapInit  (&IpInstance->TxTokens);
00320   InitializeListHead (&IpInstance->Received);
00321   InitializeListHead (&IpInstance->Delivered);
00322 
00323   EfiInitializeLock (&IpInstance->RecycleLock, TPL_NOTIFY);
00324 }
00325 
00346 EFI_STATUS
00347 Ip6ConfigProtocol (
00348   IN OUT IP6_PROTOCOL        *IpInstance,
00349   IN     EFI_IP6_CONFIG_DATA *Config
00350   )
00351 {
00352   IP6_SERVICE               *IpSb;
00353   IP6_INTERFACE             *IpIf;
00354   EFI_STATUS                Status;
00355   EFI_IP6_CONFIG_DATA       *Current;
00356   IP6_ADDRESS_INFO          *AddressInfo;
00357   BOOLEAN                   StationZero;
00358   BOOLEAN                   DestZero;
00359   EFI_IPv6_ADDRESS          Source;
00360   BOOLEAN                   AddrOk;
00361 
00362   IpSb    = IpInstance->Service;
00363   Current = &IpInstance->ConfigData;
00364 
00365   //
00366   // User is changing packet filters. It must be stopped
00367   // before the station address can be changed.
00368   //
00369   if (IpInstance->State == IP6_STATE_CONFIGED) {
00370     //
00371     // Cancel all the pending transmit/receive from upper layer
00372     //
00373     Status = Ip6Cancel (IpInstance, NULL);
00374 
00375     if (EFI_ERROR (Status)) {
00376       return EFI_DEVICE_ERROR;
00377     }
00378 
00379     CopyMem (Current, Config, sizeof (EFI_IP6_CONFIG_DATA));
00380     return EFI_SUCCESS;
00381   }
00382 
00383   //
00384   // Set up the interface.
00385   //
00386   StationZero = NetIp6IsUnspecifiedAddr (&Config->StationAddress);
00387   DestZero    = NetIp6IsUnspecifiedAddr (&Config->DestinationAddress);
00388 
00389   if (StationZero && DestZero) {
00390     //
00391     // StationAddress is still zero.
00392     //
00393 
00394     NET_GET_REF (IpSb->DefaultInterface);
00395     IpInstance->Interface = IpSb->DefaultInterface;
00396     InsertTailList (&IpSb->DefaultInterface->IpInstances, &IpInstance->AddrLink);
00397 
00398     CopyMem (Current, Config, sizeof (EFI_IP6_CONFIG_DATA));
00399     IpInstance->State = IP6_STATE_CONFIGED;
00400 
00401     return EFI_SUCCESS;
00402   }
00403 
00404   if (StationZero && !DestZero) {
00405     Status = Ip6SelectSourceAddress (IpSb, &Config->DestinationAddress, &Source);
00406     if (EFI_ERROR (Status)) {
00407       return Status;
00408     }
00409   } else {
00410     IP6_COPY_ADDRESS (&Source, &Config->StationAddress);
00411   }
00412 
00413   AddrOk = Ip6IsOneOfSetAddress (IpSb, &Source, &IpIf, &AddressInfo);
00414   if (AddrOk) {
00415     if (AddressInfo != NULL) {
00416       IpInstance->PrefixLength = AddressInfo->PrefixLength;
00417     } else {
00418       IpInstance->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
00419     }
00420   } else {
00421     //
00422     // The specified source address is not one of the addresses IPv6 maintains.
00423     //
00424     return EFI_INVALID_PARAMETER;
00425   }
00426 
00427 
00428   NET_GET_REF (IpIf);
00429   IpInstance->Interface = IpIf;
00430   InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink);
00431 
00432   CopyMem (Current, Config, sizeof (EFI_IP6_CONFIG_DATA));
00433   IP6_COPY_ADDRESS (&Current->StationAddress, &Source);
00434   IpInstance->State = IP6_STATE_CONFIGED;
00435 
00436   return EFI_SUCCESS;
00437 }
00438 
00448 EFI_STATUS
00449 Ip6CleanProtocol (
00450   IN OUT IP6_PROTOCOL            *IpInstance
00451   )
00452 {
00453   if (EFI_ERROR (Ip6Cancel (IpInstance, NULL))) {
00454     return EFI_DEVICE_ERROR;
00455   }
00456 
00457   if (EFI_ERROR (Ip6Groups (IpInstance, FALSE, NULL))) {
00458     return EFI_DEVICE_ERROR;
00459   }
00460 
00461   //
00462   // Some packets haven't been recycled. It is because either the
00463   // user forgets to recycle the packets, or because the callback
00464   // hasn't been called. Just leave it alone.
00465   //
00466   if (!IsListEmpty (&IpInstance->Delivered)) {
00467     ;
00468   }
00469 
00470   if (IpInstance->Interface != NULL) {
00471     RemoveEntryList (&IpInstance->AddrLink);
00472     Ip6CleanInterface (IpInstance->Interface, IpInstance);
00473     IpInstance->Interface = NULL;
00474   }
00475 
00476   if (IpInstance->GroupList != NULL) {
00477     FreePool (IpInstance->GroupList);
00478     IpInstance->GroupList   = NULL;
00479     IpInstance->GroupCount  = 0;
00480   }
00481 
00482   NetMapClean (&IpInstance->TxTokens);
00483 
00484   NetMapClean (&IpInstance->RxTokens);
00485 
00486   return EFI_SUCCESS;
00487 }
00488 
00507 EFI_STATUS
00508 Ip6ServiceConfigMnp (
00509   IN IP6_SERVICE            *IpSb,
00510   IN BOOLEAN                Force
00511   )
00512 {
00513   LIST_ENTRY                *Entry;
00514   LIST_ENTRY                *ProtoEntry;
00515   IP6_INTERFACE             *IpIf;
00516   IP6_PROTOCOL              *IpInstance;
00517   BOOLEAN                   Reconfig;
00518   BOOLEAN                   PromiscReceive;
00519   EFI_STATUS                Status;
00520 
00521   Reconfig       = FALSE;
00522   PromiscReceive = FALSE;
00523 
00524   if (!Force) {
00525     //
00526     // Iterate through the IP children to check whether promiscuous
00527     // receive setting has been changed. Update the interface's receive
00528     // filter also.
00529     //
00530     NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
00531 
00532       IpIf              = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
00533       IpIf->PromiscRecv = FALSE;
00534 
00535       NET_LIST_FOR_EACH (ProtoEntry, &IpIf->IpInstances) {
00536         IpInstance = NET_LIST_USER_STRUCT (ProtoEntry, IP6_PROTOCOL, AddrLink);
00537 
00538         if (IpInstance->ConfigData.AcceptPromiscuous) {
00539           IpIf->PromiscRecv = TRUE;
00540           PromiscReceive    = TRUE;
00541         }
00542       }
00543     }
00544 
00545     //
00546     // If promiscuous receive isn't changed, it isn't necessary to reconfigure.
00547     //
00548     if (PromiscReceive == IpSb->MnpConfigData.EnablePromiscuousReceive) {
00549       return EFI_SUCCESS;
00550     }
00551 
00552     Reconfig  = TRUE;
00553     IpSb->MnpConfigData.EnablePromiscuousReceive = PromiscReceive;
00554   }
00555 
00556   Status = IpSb->Mnp->Configure (IpSb->Mnp, &IpSb->MnpConfigData);
00557 
00558   //
00559   // recover the original configuration if failed to set the configure.
00560   //
00561   if (EFI_ERROR (Status) && Reconfig) {
00562     IpSb->MnpConfigData.EnablePromiscuousReceive = (BOOLEAN) !PromiscReceive;
00563   }
00564 
00565   return Status;
00566 }
00567 
00615 EFI_STATUS
00616 EFIAPI
00617 EfiIp6Configure (
00618   IN EFI_IP6_PROTOCOL          *This,
00619   IN EFI_IP6_CONFIG_DATA       *Ip6ConfigData OPTIONAL
00620   )
00621 {
00622   IP6_PROTOCOL              *IpInstance;
00623   EFI_IP6_CONFIG_DATA       *Current;
00624   EFI_TPL                   OldTpl;
00625   EFI_STATUS                Status;
00626   IP6_SERVICE               *IpSb;
00627 
00628   //
00629   // First, validate the parameters
00630   //
00631   if (This == NULL) {
00632     return EFI_INVALID_PARAMETER;
00633   }
00634 
00635   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
00636   IpSb       = IpInstance->Service;
00637 
00638   if (IpSb->LinkLocalDadFail) {
00639     return EFI_DEVICE_ERROR;
00640   }
00641 
00642   OldTpl     = gBS->RaiseTPL (TPL_CALLBACK);
00643 
00644   Status     = EFI_INVALID_PARAMETER;
00645 
00646   //
00647   // Validate the configuration first.
00648   //
00649   if (Ip6ConfigData != NULL) {
00650     //
00651     // Check whether the station address is valid.
00652     //
00653     if (!Ip6IsValidAddress (IpSb, &Ip6ConfigData->StationAddress, TRUE)) {
00654        goto Exit;
00655     }
00656     //
00657     // Check whether the default protocol is valid.
00658     //
00659     if (Ip6IsIllegalProtocol (Ip6ConfigData->DefaultProtocol)) {
00660       goto Exit;
00661     }
00662 
00663     //
00664     // User can only update packet filters when already configured.
00665     // If it wants to change the station address, it must configure(NULL)
00666     // the instance firstly.
00667     //
00668     if (IpInstance->State == IP6_STATE_CONFIGED) {
00669       Current = &IpInstance->ConfigData;
00670 
00671       if (!EFI_IP6_EQUAL (&Current->StationAddress, &Ip6ConfigData->StationAddress)) {
00672         Status = EFI_ALREADY_STARTED;
00673         goto Exit;
00674       }
00675 
00676       if (NetIp6IsUnspecifiedAddr (&Current->StationAddress) && IP6_NO_MAPPING (IpInstance)) {
00677         Status = EFI_NO_MAPPING;
00678         goto Exit;
00679       }
00680     }
00681   }
00682 
00683   //
00684   // Configure the instance or clean it up.
00685   //
00686   if (Ip6ConfigData != NULL) {
00687     Status = Ip6ConfigProtocol (IpInstance, Ip6ConfigData);
00688   } else {
00689     Status = Ip6CleanProtocol (IpInstance);
00690 
00691     //
00692     // Don't change the state if it is DESTORY, consider the following
00693     // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,
00694     // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,
00695     // the unload fails miserably.
00696     //
00697     if (IpInstance->State == IP6_STATE_CONFIGED) {
00698       IpInstance->State = IP6_STATE_UNCONFIGED;
00699     }
00700   }
00701 
00702   //
00703   // Update the MNP's configure data. Ip6ServiceConfigMnp will check
00704   // whether it is necessary to reconfigure the MNP.
00705   //
00706   Ip6ServiceConfigMnp (IpInstance->Service, FALSE);
00707 
00708   //
00709   // Update the variable data.
00710   //
00711   Ip6SetVariableData (IpInstance->Service);
00712 
00713 Exit:
00714   gBS->RestoreTPL (OldTpl);
00715   return Status;
00716 }
00717 
00749 EFI_STATUS
00750 EFIAPI
00751 EfiIp6Groups (
00752   IN EFI_IP6_PROTOCOL  *This,
00753   IN BOOLEAN           JoinFlag,
00754   IN EFI_IPv6_ADDRESS  *GroupAddress  OPTIONAL
00755   )
00756 {
00757   EFI_TPL                   OldTpl;
00758   EFI_STATUS                Status;
00759   IP6_PROTOCOL              *IpInstance;
00760   IP6_SERVICE               *IpSb;
00761 
00762   if ((This == NULL) || (JoinFlag && GroupAddress == NULL)) {
00763     return EFI_INVALID_PARAMETER;
00764   }
00765 
00766   if (GroupAddress != NULL && !IP6_IS_MULTICAST (GroupAddress)) {
00767     return EFI_INVALID_PARAMETER;
00768   }
00769 
00770   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
00771   IpSb       = IpInstance->Service;
00772 
00773   if (IpSb->LinkLocalDadFail) {
00774     return EFI_DEVICE_ERROR;
00775   }
00776 
00777   OldTpl     = gBS->RaiseTPL (TPL_CALLBACK);
00778 
00779   if (IpInstance->State != IP6_STATE_CONFIGED) {
00780     Status = EFI_NOT_STARTED;
00781     goto ON_EXIT;
00782   }
00783 
00784   Status = Ip6Groups (IpInstance, JoinFlag, GroupAddress);
00785 
00786 ON_EXIT:
00787   gBS->RestoreTPL (OldTpl);
00788   return Status;
00789 }
00790 
00834 EFI_STATUS
00835 EFIAPI
00836 EfiIp6Routes (
00837   IN EFI_IP6_PROTOCOL    *This,
00838   IN BOOLEAN             DeleteRoute,
00839   IN EFI_IPv6_ADDRESS    *Destination    OPTIONAL,
00840   IN UINT8               PrefixLength,
00841   IN EFI_IPv6_ADDRESS    *GatewayAddress OPTIONAL
00842   )
00843 {
00844   IP6_PROTOCOL              *IpInstance;
00845   EFI_STATUS                Status;
00846   EFI_TPL                   OldTpl;
00847   IP6_SERVICE               *IpSb;
00848 
00849   if ((This == NULL) || (PrefixLength >= IP6_PREFIX_NUM)) {
00850     return EFI_INVALID_PARAMETER;
00851   }
00852 
00853   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
00854   IpSb       = IpInstance->Service;
00855 
00856   if (IpSb->LinkLocalDadFail) {
00857     return EFI_DEVICE_ERROR;
00858   }
00859 
00860   if (IpInstance->State != IP6_STATE_CONFIGED) {
00861     return EFI_NOT_STARTED;
00862   }
00863 
00864   if (DeleteRoute && (Destination == NULL) && (GatewayAddress == NULL)) {
00865     return EFI_INVALID_PARAMETER;
00866   }
00867 
00868   if (!DeleteRoute && (Destination == NULL || GatewayAddress == NULL)) {
00869     return EFI_INVALID_PARAMETER;
00870   }
00871 
00872   if (GatewayAddress != NULL) {
00873     if (!Ip6IsValidAddress (IpSb, GatewayAddress, FALSE)) {
00874       return EFI_INVALID_PARAMETER;
00875     }
00876 
00877     if (!NetIp6IsUnspecifiedAddr (GatewayAddress) &&
00878         !NetIp6IsNetEqual (GatewayAddress, &IpInstance->ConfigData.StationAddress, PrefixLength)
00879           ) {
00880       return EFI_INVALID_PARAMETER;
00881     }
00882   }
00883 
00884   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
00885 
00886   //
00887   // Update the route table
00888   //
00889   if (DeleteRoute) {
00890     Status = Ip6DelRoute (IpSb->RouteTable, Destination, PrefixLength, GatewayAddress);
00891   } else {
00892     Status = Ip6AddRoute (IpSb->RouteTable, Destination, PrefixLength, GatewayAddress);
00893   }
00894 
00895   gBS->RestoreTPL (OldTpl);
00896   return Status;
00897 }
00898 
00945 EFI_STATUS
00946 EFIAPI
00947 EfiIp6Neighbors (
00948   IN EFI_IP6_PROTOCOL          *This,
00949   IN BOOLEAN                   DeleteFlag,
00950   IN EFI_IPv6_ADDRESS          *TargetIp6Address,
00951   IN EFI_MAC_ADDRESS           *TargetLinkAddress OPTIONAL,
00952   IN UINT32                    Timeout,
00953   IN BOOLEAN                   Override
00954   )
00955 {
00956   EFI_TPL                   OldTpl;
00957   EFI_STATUS                Status;
00958   IP6_PROTOCOL              *IpInstance;
00959   IP6_SERVICE               *IpSb;
00960 
00961   if (This == NULL || TargetIp6Address == NULL) {
00962     return EFI_INVALID_PARAMETER;
00963   }
00964 
00965   if (NetIp6IsUnspecifiedAddr (TargetIp6Address)) {
00966     return EFI_INVALID_PARAMETER;
00967   }
00968 
00969   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
00970   IpSb       = IpInstance->Service;
00971 
00972   if (IpSb->LinkLocalDadFail) {
00973     return EFI_DEVICE_ERROR;
00974   }
00975 
00976   if (!Ip6IsValidAddress (IpSb, TargetIp6Address, FALSE)) {
00977     return EFI_INVALID_PARAMETER;
00978   }
00979 
00980   if (TargetLinkAddress != NULL) {
00981     if (!Ip6IsValidLinkAddress (IpSb, TargetLinkAddress)) {
00982       return EFI_INVALID_PARAMETER;
00983     }
00984   }
00985 
00986   if (Ip6IsOneOfSetAddress (IpSb, TargetIp6Address, NULL, NULL)) {
00987     return EFI_INVALID_PARAMETER;
00988   }
00989 
00990   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
00991   if (IpInstance->State != IP6_STATE_CONFIGED) {
00992     Status = EFI_NOT_STARTED;
00993     goto Exit;
00994   }
00995 
00996   if (DeleteFlag) {
00997     Status = Ip6DelNeighbor (IpInstance->Service, TargetIp6Address, TargetLinkAddress, Timeout, Override);
00998   } else {
00999     Status = Ip6AddNeighbor (IpInstance->Service, TargetIp6Address, TargetLinkAddress, Timeout, Override);
01000   }
01001 
01002 Exit:
01003   gBS->RestoreTPL (OldTpl);
01004   return Status;
01005 }
01006 
01021 EFI_STATUS
01022 EFIAPI
01023 Ip6TokenExist (
01024   IN NET_MAP                *Map,
01025   IN NET_MAP_ITEM           *Item,
01026   IN VOID                   *Context
01027   )
01028 {
01029   EFI_IP6_COMPLETION_TOKEN  *Token;
01030   EFI_IP6_COMPLETION_TOKEN  *TokenInItem;
01031 
01032   Token       = (EFI_IP6_COMPLETION_TOKEN *) Context;
01033   TokenInItem = (EFI_IP6_COMPLETION_TOKEN *) Item->Key;
01034 
01035   if (Token == TokenInItem || Token->Event == TokenInItem->Event) {
01036     return EFI_ACCESS_DENIED;
01037   }
01038 
01039   return EFI_SUCCESS;
01040 }
01041 
01052 EFI_STATUS
01053 Ip6TxTokenValid (
01054   IN EFI_IP6_COMPLETION_TOKEN   *Token
01055   )
01056 {
01057   EFI_IP6_TRANSMIT_DATA     *TxData;
01058   UINT32                    Index;
01059   UINT32                    DataLength;
01060 
01061   if (Token == NULL || Token->Event == NULL) {
01062     return EFI_INVALID_PARAMETER;
01063   }
01064 
01065   TxData = Token->Packet.TxData;
01066 
01067   if (TxData == NULL || (TxData->ExtHdrsLength != 0 && TxData->ExtHdrs == NULL)) {
01068     return EFI_INVALID_PARAMETER;
01069   }
01070 
01071   if (TxData->FragmentCount == 0 || TxData->DataLength == 0) {
01072     return EFI_INVALID_PARAMETER;
01073   }
01074 
01075   for (DataLength = 0, Index = 0; Index < TxData->FragmentCount; Index++) {
01076     if (TxData->FragmentTable[Index].FragmentLength == 0 || TxData->FragmentTable[Index].FragmentBuffer == NULL) {
01077       return EFI_INVALID_PARAMETER;
01078     }
01079 
01080     DataLength += TxData->FragmentTable[Index].FragmentLength;
01081   }
01082 
01083   if (TxData->DataLength != DataLength) {
01084     return EFI_INVALID_PARAMETER;
01085   }
01086 
01087   //
01088   // TODO: Token.Packet.TxData.DataLength is too short to transmit.
01089   // return EFI_BUFFER_TOO_SMALL;
01090   //
01091 
01092   //
01093   // If Token.Packet.TxData.DataLength is beyond the maximum that which can be
01094   // described through the Fragment Offset field in Fragment header when performing
01095   // fragmentation.
01096   //
01097   if (TxData->DataLength > 64 * 1024) {
01098     return EFI_BAD_BUFFER_SIZE;
01099   }
01100 
01101   return EFI_SUCCESS;
01102 }
01103 
01125 VOID
01126 EFIAPI
01127 Ip6FreeTxToken (
01128   IN VOID                   *Context
01129   )
01130 {
01131   IP6_TXTOKEN_WRAP          *Wrap;
01132   NET_MAP_ITEM              *Item;
01133 
01134   Wrap = (IP6_TXTOKEN_WRAP *) Context;
01135 
01136   //
01137   // Signal IpSecRecycleEvent to inform IPsec free the memory
01138   //
01139   if (Wrap->IpSecRecycleSignal != NULL) {
01140     gBS->SignalEvent (Wrap->IpSecRecycleSignal);
01141   }
01142 
01143   //
01144   // Find the token in the instance's map. EfiIp6Transmit put the
01145   // token to the map. If that failed, NetMapFindKey will return NULL.
01146   //
01147   Item = NetMapFindKey (&Wrap->IpInstance->TxTokens, Wrap->Token);
01148 
01149   if (Item != NULL) {
01150     NetMapRemoveItem (&Wrap->IpInstance->TxTokens, Item, NULL);
01151   }
01152 
01153   if (Wrap->Sent) {
01154     gBS->SignalEvent (Wrap->Token->Event);
01155 
01156     //
01157     // Dispatch the DPC queued by the NotifyFunction of Token->Event.
01158     //
01159     DispatchDpc ();
01160   }
01161 
01162   FreePool (Wrap);
01163 }
01164 
01165 
01175 VOID
01176 Ip6OnPacketSent (
01177   IN NET_BUF                   *Packet,
01178   IN EFI_STATUS                IoStatus,
01179   IN UINT32                    Flag,
01180   IN VOID                      *Context
01181   )
01182 {
01183   IP6_TXTOKEN_WRAP             *Wrap;
01184 
01185   //
01186   // This is the transmission request from upper layer,
01187   // not the IP6 driver itself.
01188   //
01189   Wrap                = (IP6_TXTOKEN_WRAP *) Context;
01190   Wrap->Token->Status = IoStatus;
01191 
01192   NetbufFree (Wrap->Packet);
01193 }
01194 
01247 EFI_STATUS
01248 EFIAPI
01249 EfiIp6Transmit (
01250   IN EFI_IP6_PROTOCOL          *This,
01251   IN EFI_IP6_COMPLETION_TOKEN  *Token
01252   )
01253 {
01254   IP6_SERVICE               *IpSb;
01255   IP6_PROTOCOL              *IpInstance;
01256   EFI_IP6_CONFIG_DATA       *Config;
01257   EFI_STATUS                Status;
01258   EFI_TPL                   OldTpl;
01259   EFI_IP6_HEADER            Head;
01260   EFI_IP6_TRANSMIT_DATA     *TxData;
01261   EFI_IP6_OVERRIDE_DATA     *Override;
01262   IP6_TXTOKEN_WRAP          *Wrap;
01263   UINT8                     *ExtHdrs;
01264 
01265   //
01266   // Check input parameters.
01267   //
01268   if (This == NULL) {
01269     return EFI_INVALID_PARAMETER;
01270   }
01271 
01272   ExtHdrs = NULL;
01273 
01274   Status = Ip6TxTokenValid (Token);
01275   if (EFI_ERROR (Status)) {
01276     return Status;
01277   }
01278 
01279   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
01280   IpSb       = IpInstance->Service;
01281 
01282   if (IpSb->LinkLocalDadFail) {
01283     return EFI_DEVICE_ERROR;
01284   }
01285 
01286   OldTpl     = gBS->RaiseTPL (TPL_CALLBACK);
01287 
01288   if (IpInstance->State != IP6_STATE_CONFIGED) {
01289     Status = EFI_NOT_STARTED;
01290     goto Exit;
01291   }
01292 
01293   Config = &IpInstance->ConfigData;
01294 
01295   //
01296   // Check whether the token or signal already existed.
01297   //
01298   if (EFI_ERROR (NetMapIterate (&IpInstance->TxTokens, Ip6TokenExist, Token))) {
01299     Status = EFI_ACCESS_DENIED;
01300     goto Exit;
01301   }
01302 
01303   //
01304   // Build the IP header, fill in the information from ConfigData or OverrideData
01305   //
01306   ZeroMem (&Head, sizeof(EFI_IP6_HEADER));
01307   TxData = Token->Packet.TxData;
01308   IP6_COPY_ADDRESS (&Head.SourceAddress, &Config->StationAddress);
01309   IP6_COPY_ADDRESS (&Head.DestinationAddress, &Config->DestinationAddress);
01310 
01311   Status = EFI_INVALID_PARAMETER;
01312 
01313   if (NetIp6IsUnspecifiedAddr (&TxData->DestinationAddress)) {
01314     if (NetIp6IsUnspecifiedAddr (&Config->DestinationAddress)) {
01315       goto Exit;
01316     }
01317 
01318     ASSERT (!NetIp6IsUnspecifiedAddr (&Config->StationAddress));
01319 
01320   } else {
01321     //
01322     // StationAddress is unspecified only when ConfigData.Dest is unspecified.
01323     // Use TxData.Dest to override the DestinationAddress.
01324     //
01325     if (!NetIp6IsUnspecifiedAddr (&Config->DestinationAddress)) {
01326       goto Exit;
01327     }
01328 
01329     if (NetIp6IsUnspecifiedAddr (&Config->StationAddress)) {
01330       Status = Ip6SelectSourceAddress (
01331                  IpSb,
01332                  &TxData->DestinationAddress,
01333                  &Head.SourceAddress
01334                  );
01335       if (EFI_ERROR (Status)) {
01336         goto Exit;
01337       }
01338     }
01339 
01340     IP6_COPY_ADDRESS (&Head.DestinationAddress, &TxData->DestinationAddress);
01341   }
01342 
01343   //
01344   // Fill in Head infos.
01345   //
01346   Head.NextHeader = Config->DefaultProtocol;
01347   if (TxData->ExtHdrsLength != 0) {
01348     Head.NextHeader = TxData->NextHeader;
01349   }
01350 
01351   if (TxData->OverrideData != NULL) {
01352     Override        = TxData->OverrideData;
01353     Head.NextHeader = Override->Protocol;
01354     Head.HopLimit   = Override->HopLimit;
01355     Head.FlowLabelL = HTONS ((UINT16) Override->FlowLabel);
01356     Head.FlowLabelH = (UINT8) ((Override->FlowLabel >> 16) & 0x0F);
01357   } else {
01358     Head.HopLimit   = Config->HopLimit;
01359     Head.FlowLabelL = HTONS ((UINT16) Config->FlowLabel);
01360     Head.FlowLabelH = (UINT8) ((Config->FlowLabel >> 16) & 0x0F);
01361   }
01362 
01363   Head.PayloadLength = HTONS ((UINT16) (TxData->ExtHdrsLength + TxData->DataLength));
01364 
01365   //
01366   // OK, it survives all the validation check. Wrap the token in
01367   // a IP6_TXTOKEN_WRAP and the data in a netbuf
01368   //
01369   Status = EFI_OUT_OF_RESOURCES;
01370   Wrap   = AllocateZeroPool (sizeof (IP6_TXTOKEN_WRAP));
01371   if (Wrap == NULL) {
01372     goto Exit;
01373   }
01374 
01375   Wrap->IpInstance  = IpInstance;
01376   Wrap->Token       = Token;
01377   Wrap->Sent        = FALSE;
01378   Wrap->Life        = IP6_US_TO_SEC (Config->TransmitTimeout);
01379   Wrap->Packet      = NetbufFromExt (
01380                         (NET_FRAGMENT *) TxData->FragmentTable,
01381                         TxData->FragmentCount,
01382                         IP6_MAX_HEADLEN,
01383                         0,
01384                         Ip6FreeTxToken,
01385                         Wrap
01386                         );
01387 
01388   if (Wrap->Packet == NULL) {
01389     FreePool (Wrap);
01390     goto Exit;
01391   }
01392 
01393   Token->Status = EFI_NOT_READY;
01394 
01395   Status = NetMapInsertTail (&IpInstance->TxTokens, Token, Wrap);
01396   if (EFI_ERROR (Status)) {
01397     //
01398     // NetbufFree will call Ip6FreeTxToken, which in turn will
01399     // free the IP6_TXTOKEN_WRAP. Now, the token wrap hasn't been
01400     // enqueued.
01401     //
01402     NetbufFree (Wrap->Packet);
01403     goto Exit;
01404   }
01405 
01406   //
01407   // Allocate a new buffer to store IPv6 extension headers to avoid updating
01408   // the original data in EFI_IP6_COMPLETION_TOKEN.
01409   //
01410   if (TxData->ExtHdrsLength != 0 && TxData->ExtHdrs != NULL) {
01411     ExtHdrs = (UINT8 *) AllocateCopyPool (TxData->ExtHdrsLength, TxData->ExtHdrs);
01412     if (ExtHdrs == NULL) {
01413       Status = EFI_OUT_OF_RESOURCES;
01414       goto Exit;
01415     }
01416   }
01417 
01418   //
01419   // Mark the packet sent before output it. Mark it not sent again if the
01420   // returned status is not EFI_SUCCESS;
01421   //
01422   Wrap->Sent = TRUE;
01423 
01424   Status = Ip6Output (
01425              IpSb,
01426              NULL,
01427              IpInstance,
01428              Wrap->Packet,
01429              &Head,
01430              ExtHdrs,
01431              TxData->ExtHdrsLength,
01432              Ip6OnPacketSent,
01433              Wrap
01434              );
01435   if (EFI_ERROR (Status)) {
01436     Wrap->Sent = FALSE;
01437     NetbufFree (Wrap->Packet);
01438   }
01439 
01440 Exit:
01441   gBS->RestoreTPL (OldTpl);
01442 
01443   if (ExtHdrs != NULL) {
01444     FreePool (ExtHdrs);
01445   }
01446 
01447   return Status;
01448 }
01449 
01491 EFI_STATUS
01492 EFIAPI
01493 EfiIp6Receive (
01494   IN EFI_IP6_PROTOCOL          *This,
01495   IN EFI_IP6_COMPLETION_TOKEN  *Token
01496   )
01497 {
01498   IP6_PROTOCOL              *IpInstance;
01499   EFI_STATUS                Status;
01500   EFI_TPL                   OldTpl;
01501   IP6_SERVICE               *IpSb;
01502 
01503   if (This == NULL || Token == NULL || Token->Event == NULL) {
01504     return EFI_INVALID_PARAMETER;
01505   }
01506 
01507   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
01508   IpSb       = IpInstance->Service;
01509 
01510   if (IpSb->LinkLocalDadFail) {
01511     return EFI_DEVICE_ERROR;
01512   }
01513 
01514   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
01515 
01516   if (IpInstance->State != IP6_STATE_CONFIGED) {
01517     Status = EFI_NOT_STARTED;
01518     goto Exit;
01519   }
01520 
01521   //
01522   // Check whether the toke is already on the receive queue.
01523   //
01524   Status = NetMapIterate (&IpInstance->RxTokens, Ip6TokenExist, Token);
01525 
01526   if (EFI_ERROR (Status)) {
01527     Status = EFI_ACCESS_DENIED;
01528     goto Exit;
01529   }
01530 
01531   //
01532   // Queue the token then check whether there is pending received packet.
01533   //
01534   Status = NetMapInsertTail (&IpInstance->RxTokens, Token, NULL);
01535 
01536   if (EFI_ERROR (Status)) {
01537     goto Exit;
01538   }
01539 
01540   Status = Ip6InstanceDeliverPacket (IpInstance);
01541 
01542   //
01543   // Dispatch the DPC queued by the NotifyFunction of this instane's receive
01544   // event.
01545   //
01546   DispatchDpc ();
01547 
01548 Exit:
01549   gBS->RestoreTPL (OldTpl);
01550   return Status;
01551 }
01552 
01553 
01571 EFI_STATUS
01572 EFIAPI
01573 Ip6CancelTxTokens (
01574   IN NET_MAP                *Map,
01575   IN NET_MAP_ITEM           *Item,
01576   IN VOID                   *Context
01577   )
01578 {
01579   EFI_IP6_COMPLETION_TOKEN  *Token;
01580   IP6_TXTOKEN_WRAP          *Wrap;
01581 
01582   Token = (EFI_IP6_COMPLETION_TOKEN *) Context;
01583 
01584   //
01585   // Return EFI_SUCCESS to check the next item in the map if
01586   // this one doesn't match.
01587   //
01588   if ((Token != NULL) && (Token != Item->Key)) {
01589     return EFI_SUCCESS;
01590   }
01591 
01592   Wrap = (IP6_TXTOKEN_WRAP *) Item->Value;
01593   ASSERT (Wrap != NULL);
01594 
01595   //
01596   // Don't access the Item, Wrap and Token's members after this point.
01597   // Item and wrap has been freed. And we no longer own the Token.
01598   //
01599   Ip6CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
01600 
01601   //
01602   // If only one item is to be cancel, return EFI_ABORTED to stop
01603   // iterating the map any more.
01604   //
01605   if (Token != NULL) {
01606     return EFI_ABORTED;
01607   }
01608 
01609   return EFI_SUCCESS;
01610 }
01611 
01612 
01628 EFI_STATUS
01629 EFIAPI
01630 Ip6CancelRxTokens (
01631   IN NET_MAP                *Map,
01632   IN NET_MAP_ITEM           *Item,
01633   IN VOID                   *Context
01634   )
01635 {
01636   EFI_IP6_COMPLETION_TOKEN  *Token;
01637   EFI_IP6_COMPLETION_TOKEN  *This;
01638 
01639   Token = (EFI_IP6_COMPLETION_TOKEN *) Context;
01640   This  = Item->Key;
01641 
01642   if ((Token != NULL) && (Token != This)) {
01643     return EFI_SUCCESS;
01644   }
01645 
01646   NetMapRemoveItem (Map, Item, NULL);
01647 
01648   This->Status        = EFI_ABORTED;
01649   This->Packet.RxData = NULL;
01650   gBS->SignalEvent (This->Event);
01651 
01652   if (Token != NULL) {
01653     return EFI_ABORTED;
01654   }
01655 
01656   return EFI_SUCCESS;
01657 }
01658 
01673 EFI_STATUS
01674 Ip6Cancel (
01675   IN IP6_PROTOCOL             *IpInstance,
01676   IN EFI_IP6_COMPLETION_TOKEN *Token          OPTIONAL
01677   )
01678 {
01679   EFI_STATUS                Status;
01680 
01681   //
01682   // First check the transmitted packet. Ip6CancelTxTokens returns
01683   // EFI_ABORTED to mean that the token has been cancelled when
01684   // token != NULL. So, return EFI_SUCCESS for this condition.
01685   //
01686   Status = NetMapIterate (&IpInstance->TxTokens, Ip6CancelTxTokens, Token);
01687   if (EFI_ERROR (Status)) {
01688     if ((Token != NULL) && (Status == EFI_ABORTED)) {
01689       return EFI_SUCCESS;
01690     }
01691 
01692     return Status;
01693   }
01694 
01695   //
01696   // Check the receive queue. Ip6CancelRxTokens also returns EFI_ABORT
01697   // for Token!=NULL and it is cancelled.
01698   //
01699   Status = NetMapIterate (&IpInstance->RxTokens, Ip6CancelRxTokens, Token);
01700   //
01701   // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
01702   // events.
01703   //
01704   DispatchDpc ();
01705   if (EFI_ERROR (Status)) {
01706     if ((Token != NULL) && (Status == EFI_ABORTED)) {
01707       return EFI_SUCCESS;
01708     }
01709 
01710     return Status;
01711   }
01712 
01713   //
01714   // OK, if the Token is found when Token != NULL, the NetMapIterate
01715   // will return EFI_ABORTED, which has been interrupted as EFI_SUCCESS.
01716   //
01717   if (Token != NULL) {
01718     return EFI_NOT_FOUND;
01719   }
01720 
01721   //
01722   // If Token == NULL, cancel all the tokens. return error if not
01723   // all of them are cancelled.
01724   //
01725   if (!NetMapIsEmpty (&IpInstance->TxTokens) || !NetMapIsEmpty (&IpInstance->RxTokens)) {
01726 
01727     return EFI_DEVICE_ERROR;
01728   }
01729 
01730   return EFI_SUCCESS;
01731 }
01732 
01761 EFI_STATUS
01762 EFIAPI
01763 EfiIp6Cancel (
01764   IN EFI_IP6_PROTOCOL          *This,
01765   IN EFI_IP6_COMPLETION_TOKEN  *Token    OPTIONAL
01766   )
01767 {
01768   IP6_PROTOCOL              *IpInstance;
01769   IP6_SERVICE               *IpSb;
01770   EFI_STATUS                Status;
01771   EFI_TPL                   OldTpl;
01772 
01773   if (This == NULL) {
01774     return EFI_INVALID_PARAMETER;
01775   }
01776 
01777   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
01778   IpSb       = IpInstance->Service;
01779 
01780   if (IpSb->LinkLocalDadFail) {
01781     return EFI_DEVICE_ERROR;
01782   }
01783 
01784   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
01785 
01786   if (IpInstance->State != IP6_STATE_CONFIGED) {
01787     Status = EFI_NOT_STARTED;
01788     goto Exit;
01789   }
01790 
01791   Status = Ip6Cancel (IpInstance, Token);
01792 
01793 Exit:
01794   gBS->RestoreTPL (OldTpl);
01795   return Status;
01796 }
01797 
01823 EFI_STATUS
01824 EFIAPI
01825 EfiIp6Poll (
01826   IN EFI_IP6_PROTOCOL          *This
01827   )
01828 {
01829   IP6_PROTOCOL                  *IpInstance;
01830   IP6_SERVICE                   *IpSb;
01831   EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;
01832 
01833   if (This == NULL) {
01834     return EFI_INVALID_PARAMETER;
01835   }
01836 
01837   IpInstance = IP6_INSTANCE_FROM_PROTOCOL (This);
01838   IpSb       = IpInstance->Service;
01839 
01840   if (IpSb->LinkLocalDadFail) {
01841     return EFI_DEVICE_ERROR;
01842   }
01843 
01844   if (IpInstance->State == IP6_STATE_UNCONFIGED) {
01845     return EFI_NOT_STARTED;
01846   }
01847 
01848   Mnp = IpInstance->Service->Mnp;
01849 
01850   //
01851   // Don't lock the Poll function to enable the deliver of
01852   // the packet polled up.
01853   //
01854   return Mnp->Poll (Mnp);
01855 
01856 }
01857 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines