12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886 |
- /** @file
- The implementation of the Udp4 protocol.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Udp4Impl.h"
- UINT16 mUdp4RandomPort;
- /**
- This function checks and timeouts the I/O datagrams holding by the corresponding
- service context.
- @param[in] Event The event this function registered to.
- @param[in] Context The context data registered during the creation of
- the Event.
- **/
- VOID
- EFIAPI
- Udp4CheckTimeout (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
- /**
- This function finds the udp instance by the specified <Address, Port> pair.
- @param[in] InstanceList Pointer to the head of the list linking the udp
- instances.
- @param[in] Address Pointer to the specified IPv4 address.
- @param[in] Port The udp port number.
- @retval TRUE The specified <Address, Port> pair is found.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp4FindInstanceByPort (
- IN LIST_ENTRY *InstanceList,
- IN EFI_IPv4_ADDRESS *Address,
- IN UINT16 Port
- );
- /**
- This function is the packet transmitting notify function registered to the IpIo
- interface. It's called to signal the udp TxToken when IpIo layer completes the
- transmitting of the udp datagram.
- @param[in] Status The completion status of the output udp datagram.
- @param[in] Context Pointer to the context data.
- @param[in] Sender Specify a pointer of EFI_IP4_PROTOCOL for sending.
- @param[in] NotifyData Pointer to the notify data.
- **/
- VOID
- EFIAPI
- Udp4DgramSent (
- IN EFI_STATUS Status,
- IN VOID *Context,
- IN IP_IO_IP_PROTOCOL Sender,
- IN VOID *NotifyData
- );
- /**
- This function processes the received datagram passed up by the IpIo layer.
- @param[in] Status The status of this udp datagram.
- @param[in] IcmpError The IcmpError code, only available when Status is
- EFI_ICMP_ERROR.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA.
- @param[in] Packet Pointer to the NET_BUF containing the received udp
- datagram.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp4DgramRcvd (
- IN EFI_STATUS Status,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet,
- IN VOID *Context
- );
- /**
- This function cancels the token specified by Arg in the Map. This is a callback
- used by Udp4InstanceCancelToken().
- @param[in] Map Pointer to the NET_MAP.
- @param[in] Item Pointer to the NET_MAP_ITEM.
- @param[in] Arg Pointer to the token to be cancelled, if NULL,
- the token specified by Item is cancelled.
- @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token
- is not the same as that in the Item if Arg is not
- NULL.
- @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
- cancelled.
- **/
- EFI_STATUS
- EFIAPI
- Udp4CancelTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- );
- /**
- This function matches the received udp datagram with the Instance.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted
- from the received udp datagram.
- @retval TRUE The udp datagram matches the receiving requirements of the
- udp Instance.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp4MatchDgram (
- IN UDP4_INSTANCE_DATA *Instance,
- IN EFI_UDP4_SESSION_DATA *Udp4Session
- );
- /**
- This function removes the Wrap specified by Context and release relevant resources.
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp4RecycleRxDataWrap (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
- /**
- This function wraps the Packet and the RxData.
- @param[in] Instance Pointer to the instance context data.
- @param[in] Packet Pointer to the buffer containing the received
- datagram.
- @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
- datagram.
- @return Pointer to the structure wrapping the RxData and the Packet.
- **/
- UDP4_RXDATA_WRAP *
- Udp4WrapRxData (
- IN UDP4_INSTANCE_DATA *Instance,
- IN NET_BUF *Packet,
- IN EFI_UDP4_RECEIVE_DATA *RxData
- );
- /**
- This function enqueues the received datagram into the instances' receiving queues.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] Packet Pointer to the buffer containing the received
- datagram.
- @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
- datagram.
- @return The times this datagram is enqueued.
- **/
- UINTN
- Udp4EnqueueDgram (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN NET_BUF *Packet,
- IN EFI_UDP4_RECEIVE_DATA *RxData
- );
- /**
- This function delivers the datagrams enqueued in the instances.
- @param[in] Udp4Service Pointer to the udp service context data.
- **/
- VOID
- Udp4DeliverDgram (
- IN UDP4_SERVICE_DATA *Udp4Service
- );
- /**
- This function demultiplexes the received udp datagram to the appropriate instances.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted from
- the received datagram.
- @param[in] Packet Pointer to the buffer containing the received udp
- datagram.
- **/
- VOID
- Udp4Demultiplex (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet
- );
- /**
- This function handles the received Icmp Error message and demultiplexes it to the
- instance.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] IcmpError The icmp error code.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted
- from the received Icmp Error packet.
- @param[in] Packet Pointer to the Icmp Error packet.
- **/
- VOID
- Udp4IcmpHandler (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet
- );
- /**
- This function builds and sends out a icmp port unreachable message.
- @param[in] IpIo Pointer to the IP_IO instance.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA of the packet
- causes this icmp error message.
- @param[in] Udp4Header Pointer to the udp header of the datagram causes
- this icmp error message.
- **/
- VOID
- Udp4SendPortUnreach (
- IN IP_IO *IpIo,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN VOID *Udp4Header
- );
- /**
- Create the Udp service context data.
- @param[in, out] Udp4Service Pointer to the UDP4_SERVICE_DATA.
- @param[in] ImageHandle The image handle of this udp4 driver.
- @param[in] ControllerHandle The controller handle this udp4 driver binds on.
- @retval EFI_SUCCESS The udp4 service context data is created and
- initialized.
- @retval EFI_OUT_OF_RESOURCES Cannot allocate memory.
- @retval other Other error occurs.
- **/
- EFI_STATUS
- Udp4CreateService (
- IN OUT UDP4_SERVICE_DATA *Udp4Service,
- IN EFI_HANDLE ImageHandle,
- IN EFI_HANDLE ControllerHandle
- )
- {
- EFI_STATUS Status;
- IP_IO_OPEN_DATA OpenData;
- EFI_IP4_CONFIG_DATA *Ip4ConfigData;
- ZeroMem (Udp4Service, sizeof (UDP4_SERVICE_DATA));
- Udp4Service->Signature = UDP4_SERVICE_DATA_SIGNATURE;
- Udp4Service->ServiceBinding = mUdp4ServiceBinding;
- Udp4Service->ImageHandle = ImageHandle;
- Udp4Service->ControllerHandle = ControllerHandle;
- Udp4Service->ChildrenNumber = 0;
- InitializeListHead (&Udp4Service->ChildrenList);
- //
- // Create the IpIo for this service context.
- //
- Udp4Service->IpIo = IpIoCreate (ImageHandle, ControllerHandle, IP_VERSION_4);
- if (Udp4Service->IpIo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Set the OpenData used to open the IpIo.
- //
- Ip4ConfigData = &OpenData.IpConfigData.Ip4CfgData;
- CopyMem (Ip4ConfigData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));
- Ip4ConfigData->AcceptBroadcast = TRUE;
- OpenData.RcvdContext = (VOID *)Udp4Service;
- OpenData.SndContext = NULL;
- OpenData.PktRcvdNotify = Udp4DgramRcvd;
- OpenData.PktSentNotify = Udp4DgramSent;
- //
- // Configure and start the IpIo.
- //
- Status = IpIoOpen (Udp4Service->IpIo, &OpenData);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Create the event for Udp timeout checking.
- //
- Status = gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- Udp4CheckTimeout,
- Udp4Service,
- &Udp4Service->TimeoutEvent
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Start the timeout timer event.
- //
- Status = gBS->SetTimer (
- Udp4Service->TimeoutEvent,
- TimerPeriodic,
- UDP4_TIMEOUT_INTERVAL
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- return EFI_SUCCESS;
- ON_ERROR:
- if (Udp4Service->TimeoutEvent != NULL) {
- gBS->CloseEvent (Udp4Service->TimeoutEvent);
- }
- IpIoDestroy (Udp4Service->IpIo);
- return Status;
- }
- /**
- Clean the Udp service context data.
- @param[in] Udp4Service Pointer to the UDP4_SERVICE_DATA.
- **/
- VOID
- Udp4CleanService (
- IN UDP4_SERVICE_DATA *Udp4Service
- )
- {
- //
- // Cancel the TimeoutEvent timer.
- //
- gBS->SetTimer (Udp4Service->TimeoutEvent, TimerCancel, 0);
- //
- // Close the TimeoutEvent timer.
- //
- gBS->CloseEvent (Udp4Service->TimeoutEvent);
- //
- // Destroy the IpIo.
- //
- IpIoDestroy (Udp4Service->IpIo);
- }
- /**
- This function checks and timeouts the I/O datagrams holding by the corresponding
- service context.
- @param[in] Event The event this function registered to.
- @param[in] Context The context data registered during the creation of
- the Event.
- **/
- VOID
- EFIAPI
- Udp4CheckTimeout (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UDP4_SERVICE_DATA *Udp4Service;
- LIST_ENTRY *Entry;
- UDP4_INSTANCE_DATA *Instance;
- LIST_ENTRY *WrapEntry;
- LIST_ENTRY *NextEntry;
- UDP4_RXDATA_WRAP *Wrap;
- Udp4Service = (UDP4_SERVICE_DATA *)Context;
- NET_CHECK_SIGNATURE (Udp4Service, UDP4_SERVICE_DATA_SIGNATURE);
- NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {
- //
- // Iterate all the instances belonging to this service context.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);
- NET_CHECK_SIGNATURE (Instance, UDP4_INSTANCE_DATA_SIGNATURE);
- if (!Instance->Configured || (Instance->ConfigData.ReceiveTimeout == 0)) {
- //
- // Skip this instance if it's not configured or no receive timeout.
- //
- continue;
- }
- NET_LIST_FOR_EACH_SAFE (WrapEntry, NextEntry, &Instance->RcvdDgramQue) {
- //
- // Iterate all the rxdatas belonging to this udp instance.
- //
- Wrap = NET_LIST_USER_STRUCT (WrapEntry, UDP4_RXDATA_WRAP, Link);
- //
- // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
- //
- if (Wrap->TimeoutTick < (UDP4_TIMEOUT_INTERVAL / 10)) {
- //
- // Remove this RxData if it timeouts.
- //
- Udp4RecycleRxDataWrap (NULL, (VOID *)Wrap);
- } else {
- Wrap->TimeoutTick -= (UDP4_TIMEOUT_INTERVAL / 10);
- }
- }
- }
- }
- /**
- This function initializes the new created udp instance.
- @param[in] Udp4Service Pointer to the UDP4_SERVICE_DATA.
- @param[in, out] Instance Pointer to the un-initialized UDP4_INSTANCE_DATA.
- **/
- VOID
- Udp4InitInstance (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN OUT UDP4_INSTANCE_DATA *Instance
- )
- {
- //
- // Set the signature.
- //
- Instance->Signature = UDP4_INSTANCE_DATA_SIGNATURE;
- //
- // Init the lists.
- //
- InitializeListHead (&Instance->Link);
- InitializeListHead (&Instance->RcvdDgramQue);
- InitializeListHead (&Instance->DeliveredDgramQue);
- //
- // Init the NET_MAPs.
- //
- NetMapInit (&Instance->TxTokens);
- NetMapInit (&Instance->RxTokens);
- NetMapInit (&Instance->McastIps);
- //
- // Save the pointer to the UDP4_SERVICE_DATA, and initialize other members.
- //
- Instance->Udp4Service = Udp4Service;
- CopyMem (&Instance->Udp4Proto, &mUdp4Protocol, sizeof (Instance->Udp4Proto));
- Instance->IcmpError = EFI_SUCCESS;
- Instance->Configured = FALSE;
- Instance->IsNoMapping = FALSE;
- Instance->InDestroy = FALSE;
- }
- /**
- This function cleans the udp instance.
- @param[in] Instance Pointer to the UDP4_INSTANCE_DATA to clean.
- **/
- VOID
- Udp4CleanInstance (
- IN UDP4_INSTANCE_DATA *Instance
- )
- {
- NetMapClean (&Instance->McastIps);
- NetMapClean (&Instance->RxTokens);
- NetMapClean (&Instance->TxTokens);
- }
- /**
- This function finds the udp instance by the specified <Address, Port> pair.
- @param[in] InstanceList Pointer to the head of the list linking the udp
- instances.
- @param[in] Address Pointer to the specified IPv4 address.
- @param[in] Port The udp port number.
- @retval TRUE The specified <Address, Port> pair is found.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp4FindInstanceByPort (
- IN LIST_ENTRY *InstanceList,
- IN EFI_IPv4_ADDRESS *Address,
- IN UINT16 Port
- )
- {
- LIST_ENTRY *Entry;
- UDP4_INSTANCE_DATA *Instance;
- EFI_UDP4_CONFIG_DATA *ConfigData;
- NET_LIST_FOR_EACH (Entry, InstanceList) {
- //
- // Iterate all the udp instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);
- ConfigData = &Instance->ConfigData;
- if (!Instance->Configured || ConfigData->AcceptAnyPort) {
- //
- // If the instance is not configured or the configdata of the instance indicates
- // this instance accepts any port, skip it.
- //
- continue;
- }
- if (EFI_IP4_EQUAL (&ConfigData->StationAddress, Address) &&
- (ConfigData->StationPort == Port))
- {
- //
- // if both the address and the port are the same, return TRUE.
- //
- return TRUE;
- }
- }
- //
- // return FALSE when matching fails.
- //
- return FALSE;
- }
- /**
- This function tries to bind the udp instance according to the configured port
- allocation strategy.
- @param[in] InstanceList Pointer to the head of the list linking the udp
- instances.
- @param[in, out] ConfigData Pointer to the ConfigData of the instance to be
- bound. ConfigData->StationPort will be assigned
- with an available port value on success.
- @retval EFI_SUCCESS The bound operation is completed successfully.
- @retval EFI_ACCESS_DENIED The <Address, Port> specified by the ConfigData is
- already used by other instance.
- @retval EFI_OUT_OF_RESOURCES No available port resources.
- **/
- EFI_STATUS
- Udp4Bind (
- IN LIST_ENTRY *InstanceList,
- IN OUT EFI_UDP4_CONFIG_DATA *ConfigData
- )
- {
- EFI_IPv4_ADDRESS *StationAddress;
- UINT16 StartPort;
- if (ConfigData->AcceptAnyPort) {
- return EFI_SUCCESS;
- }
- StationAddress = &ConfigData->StationAddress;
- if (ConfigData->StationPort != 0) {
- if (!ConfigData->AllowDuplicatePort &&
- Udp4FindInstanceByPort (InstanceList, StationAddress, ConfigData->StationPort))
- {
- //
- // Do not allow duplicate port and the port is already used by other instance.
- //
- return EFI_ACCESS_DENIED;
- }
- } else {
- //
- // select a random port for this instance;
- //
- if (ConfigData->AllowDuplicatePort) {
- //
- // Just pick up the random port if the instance allows duplicate port.
- //
- ConfigData->StationPort = mUdp4RandomPort;
- } else {
- StartPort = mUdp4RandomPort;
- while (Udp4FindInstanceByPort (InstanceList, StationAddress, mUdp4RandomPort)) {
- mUdp4RandomPort++;
- if (mUdp4RandomPort == 0) {
- mUdp4RandomPort = UDP4_PORT_KNOWN;
- }
- if (mUdp4RandomPort == StartPort) {
- //
- // No available port.
- //
- return EFI_OUT_OF_RESOURCES;
- }
- }
- ConfigData->StationPort = mUdp4RandomPort;
- }
- mUdp4RandomPort++;
- if (mUdp4RandomPort == 0) {
- mUdp4RandomPort = UDP4_PORT_KNOWN;
- }
- }
- return EFI_SUCCESS;
- }
- /**
- This function is used to check whether the NewConfigData has any un-reconfigurable
- parameters changed compared to the OldConfigData.
- @param[in] OldConfigData Pointer to the current ConfigData the udp instance
- uses.
- @param[in] NewConfigData Pointer to the new ConfigData.
- @retval TRUE The instance is reconfigurable.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp4IsReconfigurable (
- IN EFI_UDP4_CONFIG_DATA *OldConfigData,
- IN EFI_UDP4_CONFIG_DATA *NewConfigData
- )
- {
- if ((NewConfigData->AcceptAnyPort != OldConfigData->AcceptAnyPort) ||
- (NewConfigData->AcceptBroadcast != OldConfigData->AcceptBroadcast) ||
- (NewConfigData->AcceptPromiscuous != OldConfigData->AcceptPromiscuous) ||
- (NewConfigData->AllowDuplicatePort != OldConfigData->AllowDuplicatePort)
- )
- {
- //
- // The receiving filter parameters cannot be changed.
- //
- return FALSE;
- }
- if ((!NewConfigData->AcceptAnyPort) &&
- (NewConfigData->StationPort != OldConfigData->StationPort)
- )
- {
- //
- // The port is not changeable.
- //
- return FALSE;
- }
- if (!NewConfigData->AcceptPromiscuous) {
- if (NewConfigData->UseDefaultAddress != OldConfigData->UseDefaultAddress) {
- //
- // The NewConfigData differs to the old one on the UseDefaultAddress.
- //
- return FALSE;
- }
- if (!NewConfigData->UseDefaultAddress &&
- (!EFI_IP4_EQUAL (&NewConfigData->StationAddress, &OldConfigData->StationAddress) ||
- !EFI_IP4_EQUAL (&NewConfigData->SubnetMask, &OldConfigData->SubnetMask))
- )
- {
- //
- // If the instance doesn't use the default address, and the new address or
- // new subnet mask is different from the old values.
- //
- return FALSE;
- }
- }
- if (!EFI_IP4_EQUAL (&NewConfigData->RemoteAddress, &OldConfigData->RemoteAddress)) {
- //
- // The remoteaddress is not the same.
- //
- return FALSE;
- }
- if (!EFI_IP4_EQUAL (&NewConfigData->RemoteAddress, &mZeroIp4Addr) &&
- (NewConfigData->RemotePort != OldConfigData->RemotePort)
- )
- {
- //
- // The RemotePort differs if it's designated in the configdata.
- //
- return FALSE;
- }
- //
- // All checks pass, return TRUE.
- //
- return TRUE;
- }
- /**
- This function builds the Ip4 configdata from the Udp4ConfigData.
- @param[in] Udp4ConfigData Pointer to the EFI_UDP4_CONFIG_DATA.
- @param[in, out] Ip4ConfigData Pointer to the EFI_IP4_CONFIG_DATA.
- **/
- VOID
- Udp4BuildIp4ConfigData (
- IN EFI_UDP4_CONFIG_DATA *Udp4ConfigData,
- IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData
- )
- {
- CopyMem (Ip4ConfigData, &mIp4IoDefaultIpConfigData, sizeof (*Ip4ConfigData));
- Ip4ConfigData->DefaultProtocol = EFI_IP_PROTO_UDP;
- Ip4ConfigData->AcceptBroadcast = Udp4ConfigData->AcceptBroadcast;
- Ip4ConfigData->AcceptPromiscuous = Udp4ConfigData->AcceptPromiscuous;
- Ip4ConfigData->UseDefaultAddress = Udp4ConfigData->UseDefaultAddress;
- CopyMem (&Ip4ConfigData->StationAddress, &Udp4ConfigData->StationAddress, sizeof (EFI_IPv4_ADDRESS));
- CopyMem (&Ip4ConfigData->SubnetMask, &Udp4ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
- //
- // use the -1 magic number to disable the receiving process of the ip instance.
- //
- Ip4ConfigData->ReceiveTimeout = (UINT32)(-1);
- }
- /**
- This function validates the TxToken, it returns the error code according to the spec.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] TxToken Pointer to the token to be checked.
- @retval EFI_SUCCESS The TxToken is valid.
- @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: This is
- NULL. Token is NULL. Token.Event is NULL.
- Token.Packet.TxData is NULL.
- Token.Packet.TxData.FragmentCount is zero.
- Token.Packet.TxData.DataLength is not equal to the
- sum of fragment lengths. One or more of the
- Token.Packet.TxData.FragmentTable[].
- FragmentLength fields is zero. One or more of the
- Token.Packet.TxData.FragmentTable[].
- FragmentBuffer fields is NULL.
- Token.Packet.TxData. GatewayAddress is not a
- unicast IPv4 address if it is not NULL. One or
- more IPv4 addresses in Token.Packet.TxData.
- UdpSessionData are not valid unicast IPv4
- addresses if the UdpSessionData is not NULL.
- @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP
- packet size.
- **/
- EFI_STATUS
- Udp4ValidateTxToken (
- IN UDP4_INSTANCE_DATA *Instance,
- IN EFI_UDP4_COMPLETION_TOKEN *TxToken
- )
- {
- EFI_UDP4_TRANSMIT_DATA *TxData;
- UINT32 Index;
- UINT32 TotalLen;
- EFI_UDP4_CONFIG_DATA *ConfigData;
- EFI_UDP4_SESSION_DATA *UdpSessionData;
- IP4_ADDR SourceAddress;
- IP4_ADDR GatewayAddress;
- if (TxToken->Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- TxData = TxToken->Packet.TxData;
- if ((TxData == NULL) || (TxData->FragmentCount == 0)) {
- return EFI_INVALID_PARAMETER;
- }
- TotalLen = 0;
- for (Index = 0; Index < TxData->FragmentCount; Index++) {
- if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||
- (TxData->FragmentTable[Index].FragmentLength == 0))
- {
- //
- // if the FragmentBuffer is NULL or the FragmentLeng is zero.
- //
- return EFI_INVALID_PARAMETER;
- }
- TotalLen += TxData->FragmentTable[Index].FragmentLength;
- }
- if (TotalLen != TxData->DataLength) {
- //
- // The TotalLen calculated by adding all the FragmentLeng doesn't equal to the
- // DataLength.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (TxData->GatewayAddress != NULL) {
- CopyMem (&GatewayAddress, TxData->GatewayAddress, sizeof (IP4_ADDR));
- if (!Instance->ConfigData.UseDefaultAddress &&
- (EFI_NTOHL (Instance->ConfigData.SubnetMask) != 0) &&
- !NetIp4IsUnicast (NTOHL (GatewayAddress), EFI_NTOHL (Instance->ConfigData.SubnetMask)))
- {
- //
- // The specified GatewayAddress is not a unicast IPv4 address while it's not 0.
- //
- return EFI_INVALID_PARAMETER;
- }
- }
- ConfigData = &Instance->ConfigData;
- UdpSessionData = TxData->UdpSessionData;
- if (UdpSessionData != NULL) {
- CopyMem (&SourceAddress, &UdpSessionData->SourceAddress, sizeof (IP4_ADDR));
- if ((SourceAddress != 0) &&
- !Instance->ConfigData.UseDefaultAddress &&
- (EFI_NTOHL (Instance->ConfigData.SubnetMask) != 0) &&
- !NetIp4IsUnicast (HTONL (SourceAddress), EFI_NTOHL (Instance->ConfigData.SubnetMask)))
- {
- //
- // Check whether SourceAddress is a valid IPv4 address in case it's not zero.
- // The configured station address is used if SourceAddress is zero.
- //
- return EFI_INVALID_PARAMETER;
- }
- if ((UdpSessionData->DestinationPort == 0) && (ConfigData->RemotePort == 0)) {
- //
- // Ambiguous, no available DestinationPort for this token.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (EFI_IP4_EQUAL (&UdpSessionData->DestinationAddress, &mZeroIp4Addr)) {
- //
- // The DestinationAddress specified in the UdpSessionData is 0.
- //
- return EFI_INVALID_PARAMETER;
- }
- } else if (EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &mZeroIp4Addr)) {
- //
- // the configured RemoteAddress is all zero, and the user doesn't override the
- // destination address.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (TxData->DataLength > UDP4_MAX_DATA_SIZE) {
- return EFI_BAD_BUFFER_SIZE;
- }
- return EFI_SUCCESS;
- }
- /**
- This function checks whether the specified Token duplicates with the one in the Map.
- @param[in] Map Pointer to the NET_MAP.
- @param[in] Item Pointer to the NET_MAP_ITEM contain the pointer to
- the Token.
- @param[in] Context Pointer to the Token to be checked.
- @retval EFI_SUCCESS The Token specified by Context differs from the
- one in the Item.
- @retval EFI_ACCESS_DENIED The Token duplicates with the one in the Item.
- **/
- EFI_STATUS
- EFIAPI
- Udp4TokenExist (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- EFI_UDP4_COMPLETION_TOKEN *Token;
- EFI_UDP4_COMPLETION_TOKEN *TokenInItem;
- Token = (EFI_UDP4_COMPLETION_TOKEN *)Context;
- TokenInItem = (EFI_UDP4_COMPLETION_TOKEN *)Item->Key;
- if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
- //
- // The Token duplicates with the TokenInItem in case either the two pointers are the
- // same or the Events of these two tokens are the same.
- //
- return EFI_ACCESS_DENIED;
- }
- return EFI_SUCCESS;
- }
- /**
- This function calculates the checksum for the Packet, utilizing the pre-calculated
- pseudo HeadSum to reduce some overhead.
- @param[in] Packet Pointer to the NET_BUF contains the udp datagram.
- @param[in] HeadSum Checksum of the pseudo header except the length
- field.
- @retval The 16-bit checksum of this udp datagram.
- **/
- UINT16
- Udp4Checksum (
- IN NET_BUF *Packet,
- IN UINT16 HeadSum
- )
- {
- UINT16 Checksum;
- Checksum = NetbufChecksum (Packet);
- Checksum = NetAddChecksum (Checksum, HeadSum);
- Checksum = NetAddChecksum (Checksum, HTONS ((UINT16)Packet->TotalSize));
- return (UINT16) ~Checksum;
- }
- /**
- This function removes the specified Token from the TokenMap.
- @param[in, out] TokenMap Pointer to the NET_MAP containing the tokens.
- @param[in] Token Pointer to the Token to be removed.
- @retval EFI_SUCCESS The specified Token is removed from the TokenMap.
- @retval EFI_NOT_FOUND The specified Token is not found in the TokenMap.
- **/
- EFI_STATUS
- Udp4RemoveToken (
- IN OUT NET_MAP *TokenMap,
- IN EFI_UDP4_COMPLETION_TOKEN *Token
- )
- {
- NET_MAP_ITEM *Item;
- //
- // Find the Token first.
- //
- Item = NetMapFindKey (TokenMap, (VOID *)Token);
- if (Item != NULL) {
- //
- // Remove the token if it's found in the map.
- //
- NetMapRemoveItem (TokenMap, Item, NULL);
- return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
- }
- /**
- This function is the packet transmitting notify function registered to the IpIo
- interface. It's called to signal the udp TxToken when IpIo layer completes the
- transmitting of the udp datagram.
- @param[in] Status The completion status of the output udp datagram.
- @param[in] Context Pointer to the context data.
- @param[in] Sender Specify a pointer of EFI_IP4_PROTOCOL for sending.
- @param[in] NotifyData Pointer to the notify data.
- **/
- VOID
- EFIAPI
- Udp4DgramSent (
- IN EFI_STATUS Status,
- IN VOID *Context,
- IN IP_IO_IP_PROTOCOL Sender,
- IN VOID *NotifyData
- )
- {
- UDP4_INSTANCE_DATA *Instance;
- EFI_UDP4_COMPLETION_TOKEN *Token;
- Instance = (UDP4_INSTANCE_DATA *)Context;
- Token = (EFI_UDP4_COMPLETION_TOKEN *)NotifyData;
- if (Udp4RemoveToken (&Instance->TxTokens, Token) == EFI_SUCCESS) {
- //
- // The token may be cancelled. Only signal it if the remove operation succeeds.
- //
- Token->Status = Status;
- gBS->SignalEvent (Token->Event);
- DispatchDpc ();
- }
- }
- /**
- This function processes the received datagram passed up by the IpIo layer.
- @param[in] Status The status of this udp datagram.
- @param[in] IcmpError The IcmpError code, only available when Status is
- EFI_ICMP_ERROR.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA.
- @param[in] Packet Pointer to the NET_BUF containing the received udp
- datagram.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp4DgramRcvd (
- IN EFI_STATUS Status,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet,
- IN VOID *Context
- )
- {
- NET_CHECK_SIGNATURE (Packet, NET_BUF_SIGNATURE);
- //
- // IpIo only passes received packets with Status EFI_SUCCESS or EFI_ICMP_ERROR.
- //
- if (Status == EFI_SUCCESS) {
- //
- // Demultiplex the received datagram.
- //
- Udp4Demultiplex ((UDP4_SERVICE_DATA *)Context, NetSession, Packet);
- } else {
- //
- // Handle the ICMP_ERROR packet.
- //
- Udp4IcmpHandler ((UDP4_SERVICE_DATA *)Context, IcmpError, NetSession, Packet);
- }
- //
- // Dispatch the DPC queued by the NotifyFunction of the rx token's events
- // which are signaled with received data.
- //
- DispatchDpc ();
- }
- /**
- This function removes the multicast group specified by Arg from the Map.
- @param[in, out] Map Pointer to the NET_MAP.
- @param[in] Item Pointer to the NET_MAP_ITEM.
- @param[in] Arg Pointer to the Arg, it's the pointer to a
- multicast IPv4 Address.
- @retval EFI_SUCCESS The multicast address is removed.
- @retval EFI_ABORTED The specified multicast address is removed and the
- Arg is not NULL.
- **/
- EFI_STATUS
- EFIAPI
- Udp4LeaveGroup (
- IN OUT NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- )
- {
- EFI_IPv4_ADDRESS *McastIp;
- McastIp = Arg;
- if ((McastIp != NULL) && (!EFI_IP4_EQUAL (McastIp, &(Item->Key)))) {
- //
- // McastIp is not NULL and the multicast address contained in the Item
- // is not the same as McastIp.
- //
- return EFI_SUCCESS;
- }
- //
- // Remove this Item.
- //
- NetMapRemoveItem (Map, Item, NULL);
- if (McastIp != NULL) {
- //
- // Return EFI_ABORTED in case McastIp is not NULL to terminate the iteration.
- //
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- /**
- This function cancels the token specified by Arg in the Map. This is a callback
- used by Udp4InstanceCancelToken().
- @param[in] Map Pointer to the NET_MAP.
- @param[in] Item Pointer to the NET_MAP_ITEM.
- @param[in] Arg Pointer to the token to be cancelled, if NULL,
- the token specified by Item is cancelled.
- @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token
- is not the same as that in the Item if Arg is not
- NULL.
- @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
- cancelled.
- **/
- EFI_STATUS
- EFIAPI
- Udp4CancelTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- )
- {
- EFI_UDP4_COMPLETION_TOKEN *TokenToCancel;
- NET_BUF *Packet;
- IP_IO *IpIo;
- if ((Arg != NULL) && (Item->Key != Arg)) {
- return EFI_SUCCESS;
- }
- if (Item->Value != NULL) {
- //
- // If the token is a transmit token, the corresponding Packet is recorded in
- // Item->Value, invoke IpIo to cancel this packet first. The IpIoCancelTxToken
- // will invoke Udp4DgramSent, the token will be signaled and this Item will
- // be removed from the Map there.
- //
- Packet = (NET_BUF *)(Item->Value);
- IpIo = (IP_IO *)(*((UINTN *)&Packet->ProtoData[0]));
- IpIoCancelTxToken (IpIo, Packet);
- } else {
- //
- // The token is a receive token. Abort it and remove it from the Map.
- //
- TokenToCancel = (EFI_UDP4_COMPLETION_TOKEN *)Item->Key;
- NetMapRemoveItem (Map, Item, NULL);
- TokenToCancel->Status = EFI_ABORTED;
- gBS->SignalEvent (TokenToCancel->Event);
- }
- if (Arg != NULL) {
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- /**
- This function removes all the Wrap datas in the RcvdDgramQue.
- @param[in] Instance Pointer to the udp instance context data.
- **/
- VOID
- Udp4FlushRcvdDgram (
- IN UDP4_INSTANCE_DATA *Instance
- )
- {
- UDP4_RXDATA_WRAP *Wrap;
- while (!IsListEmpty (&Instance->RcvdDgramQue)) {
- //
- // Iterate all the Wraps in the RcvdDgramQue.
- //
- Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP4_RXDATA_WRAP, Link);
- //
- // The Wrap will be removed from the RcvdDgramQue by this function call.
- //
- Udp4RecycleRxDataWrap (NULL, (VOID *)Wrap);
- }
- }
- /**
- Cancel Udp4 tokens from the Udp4 instance.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] Token Pointer to the token to be canceled, if NULL, all
- tokens in this instance will be cancelled.
- @retval EFI_SUCCESS The Token is cancelled.
- @retval EFI_NOT_FOUND The Token is not found.
- **/
- EFI_STATUS
- Udp4InstanceCancelToken (
- IN UDP4_INSTANCE_DATA *Instance,
- IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL
- )
- {
- EFI_STATUS Status;
- //
- // Cancel this token from the TxTokens map.
- //
- Status = NetMapIterate (&Instance->TxTokens, Udp4CancelTokens, Token);
- if ((Token != NULL) && (Status == EFI_ABORTED)) {
- //
- // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
- // the TxTokens, just return success.
- //
- return EFI_SUCCESS;
- }
- //
- // Try to cancel this token from the RxTokens map in condition either the Token
- // is NULL or the specified Token is not in TxTokens.
- //
- Status = NetMapIterate (&Instance->RxTokens, Udp4CancelTokens, Token);
- if ((Token != NULL) && (Status == EFI_SUCCESS)) {
- //
- // If Token isn't NULL and Status is EFI_SUCCESS, the token is neither in the
- // TxTokens nor the RxTokens, or say, it's not found.
- //
- return EFI_NOT_FOUND;
- }
- ASSERT (
- (Token != NULL) || ( (0 == NetMapGetCount (&Instance->TxTokens))
- && (0 == NetMapGetCount (&Instance->RxTokens)))
- );
- return EFI_SUCCESS;
- }
- /**
- This function matches the received udp datagram with the Instance.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted
- from the received udp datagram.
- @retval TRUE The udp datagram matches the receiving requirements of the
- udp Instance.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp4MatchDgram (
- IN UDP4_INSTANCE_DATA *Instance,
- IN EFI_UDP4_SESSION_DATA *Udp4Session
- )
- {
- EFI_UDP4_CONFIG_DATA *ConfigData;
- IP4_ADDR Destination;
- ConfigData = &Instance->ConfigData;
- if (ConfigData->AcceptPromiscuous) {
- //
- // Always matches if this instance is in the promiscuous state.
- //
- return TRUE;
- }
- if ((!ConfigData->AcceptAnyPort && (Udp4Session->DestinationPort != ConfigData->StationPort)) ||
- ((ConfigData->RemotePort != 0) && (Udp4Session->SourcePort != ConfigData->RemotePort))
- )
- {
- //
- // The local port or the remote port doesn't match.
- //
- return FALSE;
- }
- if (!EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &mZeroIp4Addr) &&
- !EFI_IP4_EQUAL (&ConfigData->RemoteAddress, &Udp4Session->SourceAddress)
- )
- {
- //
- // This datagram doesn't come from the instance's specified sender.
- //
- return FALSE;
- }
- if (EFI_IP4_EQUAL (&ConfigData->StationAddress, &mZeroIp4Addr) ||
- EFI_IP4_EQUAL (&Udp4Session->DestinationAddress, &ConfigData->StationAddress)
- )
- {
- //
- // The instance is configured to receive datagrams destined to any station IP or
- // the destination address of this datagram matches the configured station IP.
- //
- return TRUE;
- }
- CopyMem (&Destination, &Udp4Session->DestinationAddress, sizeof (IP4_ADDR));
- if (IP4_IS_LOCAL_BROADCAST (Destination) && ConfigData->AcceptBroadcast) {
- //
- // The instance is configured to receive broadcast and this is a broadcast packet.
- //
- return TRUE;
- }
- if (IP4_IS_MULTICAST (NTOHL (Destination)) &&
- (NetMapFindKey (&Instance->McastIps, (VOID *)(UINTN)Destination) != NULL)
- )
- {
- //
- // It's a multicast packet and the multicast address is accepted by this instance.
- //
- return TRUE;
- }
- return FALSE;
- }
- /**
- This function removes the Wrap specified by Context and release relevant resources.
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp4RecycleRxDataWrap (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UDP4_RXDATA_WRAP *Wrap;
- Wrap = (UDP4_RXDATA_WRAP *)Context;
- //
- // Remove the Wrap from the list it belongs to.
- //
- RemoveEntryList (&Wrap->Link);
- //
- // Free the Packet associated with this Wrap.
- //
- NetbufFree (Wrap->Packet);
- //
- // Close the event.
- //
- gBS->CloseEvent (Wrap->RxData.RecycleSignal);
- FreePool (Wrap);
- }
- /**
- This function wraps the Packet and the RxData.
- @param[in] Instance Pointer to the instance context data.
- @param[in] Packet Pointer to the buffer containing the received
- datagram.
- @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
- datagram.
- @return Pointer to the structure wrapping the RxData and the Packet.
- **/
- UDP4_RXDATA_WRAP *
- Udp4WrapRxData (
- IN UDP4_INSTANCE_DATA *Instance,
- IN NET_BUF *Packet,
- IN EFI_UDP4_RECEIVE_DATA *RxData
- )
- {
- EFI_STATUS Status;
- UDP4_RXDATA_WRAP *Wrap;
- //
- // Allocate buffer for the Wrap.
- //
- Wrap = AllocatePool (
- sizeof (UDP4_RXDATA_WRAP) +
- (Packet->BlockOpNum - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA)
- );
- if (Wrap == NULL) {
- return NULL;
- }
- InitializeListHead (&Wrap->Link);
- CopyMem (&Wrap->RxData, RxData, sizeof (Wrap->RxData));
- //
- // Create the Recycle event.
- //
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- Udp4RecycleRxDataWrap,
- Wrap,
- &Wrap->RxData.RecycleSignal
- );
- if (EFI_ERROR (Status)) {
- FreePool (Wrap);
- return NULL;
- }
- Wrap->Packet = Packet;
- Wrap->TimeoutTick = Instance->ConfigData.ReceiveTimeout;
- return Wrap;
- }
- /**
- This function enqueues the received datagram into the instances' receiving queues.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] Packet Pointer to the buffer containing the received
- datagram.
- @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
- datagram.
- @return The times this datagram is enqueued.
- **/
- UINTN
- Udp4EnqueueDgram (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN NET_BUF *Packet,
- IN EFI_UDP4_RECEIVE_DATA *RxData
- )
- {
- LIST_ENTRY *Entry;
- UDP4_INSTANCE_DATA *Instance;
- UDP4_RXDATA_WRAP *Wrap;
- UINTN Enqueued;
- Enqueued = 0;
- NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {
- //
- // Iterate the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- if (Udp4MatchDgram (Instance, &RxData->UdpSession)) {
- //
- // Wrap the RxData and put this Wrap into the instances RcvdDgramQue.
- //
- Wrap = Udp4WrapRxData (Instance, Packet, RxData);
- if (Wrap == NULL) {
- continue;
- }
- NET_GET_REF (Packet);
- InsertTailList (&Instance->RcvdDgramQue, &Wrap->Link);
- Enqueued++;
- }
- }
- return Enqueued;
- }
- /**
- This function delivers the received datagrams for the specified instance.
- @param[in] Instance Pointer to the instance context data.
- **/
- VOID
- Udp4InstanceDeliverDgram (
- IN UDP4_INSTANCE_DATA *Instance
- )
- {
- UDP4_RXDATA_WRAP *Wrap;
- EFI_UDP4_COMPLETION_TOKEN *Token;
- NET_BUF *Dup;
- EFI_UDP4_RECEIVE_DATA *RxData;
- EFI_TPL OldTpl;
- if (!IsListEmpty (&Instance->RcvdDgramQue) &&
- !NetMapIsEmpty (&Instance->RxTokens))
- {
- Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP4_RXDATA_WRAP, Link);
- if (NET_BUF_SHARED (Wrap->Packet)) {
- //
- // Duplicate the Packet if it is shared between instances.
- //
- Dup = NetbufDuplicate (Wrap->Packet, NULL, 0);
- if (Dup == NULL) {
- return;
- }
- NetbufFree (Wrap->Packet);
- Wrap->Packet = Dup;
- }
- NetListRemoveHead (&Instance->RcvdDgramQue);
- Token = (EFI_UDP4_COMPLETION_TOKEN *)NetMapRemoveHead (&Instance->RxTokens, NULL);
- //
- // Build the FragmentTable and set the FragmentCount in RxData.
- //
- RxData = &Wrap->RxData;
- RxData->FragmentCount = Wrap->Packet->BlockOpNum;
- NetbufBuildExt (
- Wrap->Packet,
- (NET_FRAGMENT *)RxData->FragmentTable,
- &RxData->FragmentCount
- );
- Token->Status = EFI_SUCCESS;
- Token->Packet.RxData = &Wrap->RxData;
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- InsertTailList (&Instance->DeliveredDgramQue, &Wrap->Link);
- gBS->RestoreTPL (OldTpl);
- gBS->SignalEvent (Token->Event);
- }
- }
- /**
- This function delivers the datagrams enqueued in the instances.
- @param[in] Udp4Service Pointer to the udp service context data.
- **/
- VOID
- Udp4DeliverDgram (
- IN UDP4_SERVICE_DATA *Udp4Service
- )
- {
- LIST_ENTRY *Entry;
- UDP4_INSTANCE_DATA *Instance;
- NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {
- //
- // Iterate the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- //
- // Deliver the datagrams of this instance.
- //
- Udp4InstanceDeliverDgram (Instance);
- }
- }
- /**
- This function demultiplexes the received udp datagram to the appropriate instances.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted from
- the received datagram.
- @param[in] Packet Pointer to the buffer containing the received udp
- datagram.
- **/
- VOID
- Udp4Demultiplex (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet
- )
- {
- EFI_UDP_HEADER *Udp4Header;
- UINT16 HeadSum;
- EFI_UDP4_RECEIVE_DATA RxData;
- EFI_UDP4_SESSION_DATA *Udp4Session;
- UINTN Enqueued;
- if (Packet->TotalSize < sizeof (EFI_UDP_HEADER)) {
- NetbufFree (Packet);
- return;
- }
- //
- // Get the datagram header from the packet buffer.
- //
- Udp4Header = (EFI_UDP_HEADER *)NetbufGetByte (Packet, 0, NULL);
- ASSERT (Udp4Header != NULL);
- if (Udp4Header->Checksum != 0) {
- //
- // check the checksum.
- //
- HeadSum = NetPseudoHeadChecksum (
- NetSession->Source.Addr[0],
- NetSession->Dest.Addr[0],
- EFI_IP_PROTO_UDP,
- 0
- );
- if (Udp4Checksum (Packet, HeadSum) != 0) {
- //
- // Wrong checksum.
- //
- NetbufFree (Packet);
- return;
- }
- }
- Udp4Session = &RxData.UdpSession;
- Udp4Session->SourcePort = NTOHS (Udp4Header->SrcPort);
- Udp4Session->DestinationPort = NTOHS (Udp4Header->DstPort);
- CopyMem (&Udp4Session->SourceAddress, &NetSession->Source, sizeof (EFI_IPv4_ADDRESS));
- CopyMem (&Udp4Session->DestinationAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));
- //
- // Trim the UDP header.
- //
- NetbufTrim (Packet, UDP4_HEADER_SIZE, TRUE);
- RxData.DataLength = (UINT32)Packet->TotalSize;
- //
- // Try to enqueue this datagram into the instances.
- //
- Enqueued = Udp4EnqueueDgram (Udp4Service, Packet, &RxData);
- if (Enqueued == 0) {
- //
- // Send the port unreachable ICMP packet before we free this NET_BUF
- //
- Udp4SendPortUnreach (Udp4Service->IpIo, NetSession, Udp4Header);
- }
- //
- // Try to free the packet before deliver it.
- //
- NetbufFree (Packet);
- if (Enqueued > 0) {
- //
- // Deliver the datagram.
- //
- Udp4DeliverDgram (Udp4Service);
- }
- }
- /**
- This function builds and sends out a icmp port unreachable message.
- @param[in] IpIo Pointer to the IP_IO instance.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA of the packet
- causes this icmp error message.
- @param[in] Udp4Header Pointer to the udp header of the datagram causes
- this icmp error message.
- **/
- VOID
- Udp4SendPortUnreach (
- IN IP_IO *IpIo,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN VOID *Udp4Header
- )
- {
- NET_BUF *Packet;
- UINT32 Len;
- IP4_ICMP_ERROR_HEAD *IcmpErrHdr;
- EFI_IP4_HEADER *IpHdr;
- UINT8 *Ptr;
- IP_IO_OVERRIDE Override;
- IP_IO_IP_INFO *IpSender;
- IpSender = IpIoFindSender (&IpIo, NetSession->IpVersion, &NetSession->Dest);
- if (IpSender == NULL) {
- //
- // No appropriate sender, since we cannot send out the ICMP message through
- // the default zero station address IP instance, abort.
- //
- return;
- }
- IpHdr = NetSession->IpHdr.Ip4Hdr;
- //
- // Calculate the required length of the icmp error message.
- //
- Len = sizeof (IP4_ICMP_ERROR_HEAD) + (EFI_IP4_HEADER_LEN (IpHdr) -
- sizeof (IP4_HEAD)) + ICMP_ERROR_PACKET_LENGTH;
- //
- // Allocate buffer for the icmp error message.
- //
- Packet = NetbufAlloc (Len);
- if (Packet == NULL) {
- return;
- }
- //
- // Allocate space for the IP4_ICMP_ERROR_HEAD.
- //
- IcmpErrHdr = (IP4_ICMP_ERROR_HEAD *)NetbufAllocSpace (Packet, Len, FALSE);
- ASSERT (IcmpErrHdr != NULL);
- //
- // Set the required fields for the icmp port unreachable message.
- //
- IcmpErrHdr->Head.Type = ICMP_TYPE_UNREACH;
- IcmpErrHdr->Head.Code = ICMP_CODE_UNREACH_PORT;
- IcmpErrHdr->Head.Checksum = 0;
- IcmpErrHdr->Fourth = 0;
- //
- // Copy the IP header of the datagram tragged the error.
- //
- CopyMem (&IcmpErrHdr->IpHead, IpHdr, EFI_IP4_HEADER_LEN (IpHdr));
- //
- // Copy the UDP header.
- //
- Ptr = (UINT8 *)&IcmpErrHdr->IpHead + EFI_IP4_HEADER_LEN (IpHdr);
- CopyMem (Ptr, Udp4Header, ICMP_ERROR_PACKET_LENGTH);
- //
- // Calculate the checksum.
- //
- IcmpErrHdr->Head.Checksum = (UINT16) ~(NetbufChecksum (Packet));
- //
- // Fill the override data.
- //
- Override.Ip4OverrideData.DoNotFragment = FALSE;
- Override.Ip4OverrideData.TypeOfService = 0;
- Override.Ip4OverrideData.TimeToLive = 255;
- Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_ICMP;
- CopyMem (&Override.Ip4OverrideData.SourceAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));
- ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
- //
- // Send out this icmp packet.
- //
- IpIoSend (IpIo, Packet, IpSender, NULL, NULL, &NetSession->Source, &Override);
- NetbufFree (Packet);
- }
- /**
- This function handles the received Icmp Error message and demultiplexes it to the
- instance.
- @param[in] Udp4Service Pointer to the udp service context data.
- @param[in] IcmpError The icmp error code.
- @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted
- from the received Icmp Error packet.
- @param[in] Packet Pointer to the Icmp Error packet.
- **/
- VOID
- Udp4IcmpHandler (
- IN UDP4_SERVICE_DATA *Udp4Service,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet
- )
- {
- EFI_UDP_HEADER *Udp4Header;
- EFI_UDP4_SESSION_DATA Udp4Session;
- LIST_ENTRY *Entry;
- UDP4_INSTANCE_DATA *Instance;
- if (Packet->TotalSize < sizeof (EFI_UDP_HEADER)) {
- NetbufFree (Packet);
- return;
- }
- Udp4Header = (EFI_UDP_HEADER *)NetbufGetByte (Packet, 0, NULL);
- ASSERT (Udp4Header != NULL);
- CopyMem (&Udp4Session.SourceAddress, &NetSession->Source, sizeof (EFI_IPv4_ADDRESS));
- CopyMem (&Udp4Session.DestinationAddress, &NetSession->Dest, sizeof (EFI_IPv4_ADDRESS));
- Udp4Session.SourcePort = NTOHS (Udp4Header->DstPort);
- Udp4Session.DestinationPort = NTOHS (Udp4Header->SrcPort);
- NET_LIST_FOR_EACH (Entry, &Udp4Service->ChildrenList) {
- //
- // Iterate all the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP4_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- if (Udp4MatchDgram (Instance, &Udp4Session)) {
- //
- // Translate the Icmp Error code according to the udp spec.
- //
- Instance->IcmpError = IpIoGetIcmpErrStatus (IcmpError, IP_VERSION_4, NULL, NULL);
- if (IcmpError > ICMP_ERR_UNREACH_PORT) {
- Instance->IcmpError = EFI_ICMP_ERROR;
- }
- //
- // Notify the instance with the received Icmp Error.
- //
- Udp4ReportIcmpError (Instance);
- break;
- }
- }
- NetbufFree (Packet);
- }
- /**
- This function reports the received ICMP error.
- @param[in] Instance Pointer to the udp instance context data.
- **/
- VOID
- Udp4ReportIcmpError (
- IN UDP4_INSTANCE_DATA *Instance
- )
- {
- EFI_UDP4_COMPLETION_TOKEN *Token;
- if (NetMapIsEmpty (&Instance->RxTokens)) {
- //
- // There are no receive tokens to deliver the ICMP error.
- //
- return;
- }
- if (EFI_ERROR (Instance->IcmpError)) {
- //
- // Try to get a RxToken from the RxTokens map.
- //
- Token = (EFI_UDP4_COMPLETION_TOKEN *)NetMapRemoveHead (&Instance->RxTokens, NULL);
- if (Token != NULL) {
- //
- // Report the error through the Token.
- //
- Token->Status = Instance->IcmpError;
- gBS->SignalEvent (Token->Event);
- //
- // Clear the IcmpError.
- //
- Instance->IcmpError = EFI_SUCCESS;
- }
- }
- }
- /**
- This function is a dummy ext-free function for the NET_BUF created for the output
- udp datagram.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp4NetVectorExtFree (
- VOID *Context
- )
- {
- }
|