123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983 |
- /** @file
- Udp6 driver's whole implementation.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Udp6Impl.h"
- UINT16 mUdp6RandomPort;
- /**
- This function checks and timeouts the I/O datagrams holding by the corresponding
- service context.
- @param[in] Event The event this function is registered to.
- @param[in] Context The context data registered during the creation of
- the Event.
- **/
- VOID
- EFIAPI
- Udp6CheckTimeout (
- 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 IPv6 address.
- @param[in] Port The udp port number.
- @retval TRUE The specified <Address, Port> pair is found.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp6FindInstanceByPort (
- IN LIST_ENTRY *InstanceList,
- IN EFI_IPv6_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 the IpIo layer completes
- transmitting of the udp datagram.
- If Context is NULL, then ASSERT().
- If NotifyData is NULL, then ASSERT().
- @param[in] Status The completion status of the output udp datagram.
- @param[in] Context Pointer to the context data.
- @param[in] Sender Specify a EFI_IP6_PROTOCOL for sending.
- @param[in] NotifyData Pointer to the notify data.
- **/
- VOID
- EFIAPI
- Udp6DgramSent (
- 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.
- If NetSession is NULL, then ASSERT().
- If Packet is NULL, then ASSERT().
- If Context is NULL, then ASSERT().
- @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
- Udp6DgramRcvd (
- IN EFI_STATUS Status,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet,
- IN VOID *Context
- );
- /**
- This function cancel the token specified by Arg in the Map.
- @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, all
- the tokens in this Map will be cancelled.
- This parameter is optional and may be NULL.
- @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
- Udp6CancelTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- );
- /**
- This function check if the received udp datagram matches with the Instance.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] Udp6Session Pointer to the EFI_UDP6_SESSION_DATA abstracted
- from the received udp datagram.
- @retval TRUE The udp datagram matches the receiving requirements of the Instance.
- @retval FALSE The udp datagram doe not match the receiving requirements of the Instance.
- **/
- BOOLEAN
- Udp6MatchDgram (
- IN UDP6_INSTANCE_DATA *Instance,
- IN EFI_UDP6_SESSION_DATA *Udp6Session
- );
- /**
- This function removes the Wrap specified by Context and releases relevant resources.
- @param[in] Event The Event this notify function is registered to.
- @param[in] Context Pointer to the context data.
- **/
- VOID
- EFIAPI
- Udp6RecycleRxDataWrap (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
- /**
- This function wraps the Packet into 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_UDP6_RECEIVE_DATA of this
- datagram.
- @return Pointer to the structure wrapping the RxData and the Packet. NULL will
- be returned if any error occurs.
- **/
- UDP6_RXDATA_WRAP *
- Udp6WrapRxData (
- IN UDP6_INSTANCE_DATA *Instance,
- IN NET_BUF *Packet,
- IN EFI_UDP6_RECEIVE_DATA *RxData
- );
- /**
- This function enqueues the received datagram into the instances' receiving queues.
- @param[in] Udp6Service 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_UDP6_RECEIVE_DATA of this
- datagram.
- @return The times this datagram is enqueued.
- **/
- UINTN
- Udp6EnqueueDgram (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN NET_BUF *Packet,
- IN EFI_UDP6_RECEIVE_DATA *RxData
- );
- /**
- This function delivers the datagrams enqueued in the instances.
- @param[in] Udp6Service Pointer to the udp service context data.
- **/
- VOID
- Udp6DeliverDgram (
- IN UDP6_SERVICE_DATA *Udp6Service
- );
- /**
- This function demultiplexes the received udp datagram to the appropriate instances.
- @param[in] Udp6Service 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
- Udp6Demultiplex (
- IN UDP6_SERVICE_DATA *Udp6Service,
- 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] Udp6Service 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, out] Packet Pointer to the Icmp Error packet.
- **/
- VOID
- Udp6IcmpHandler (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN OUT 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] Udp6Header Pointer to the udp header of the datagram causes
- this icmp error message.
- **/
- VOID
- Udp6SendPortUnreach (
- IN IP_IO *IpIo,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN VOID *Udp6Header
- );
- /**
- Find the key in the netmap
- @param[in] Map The netmap to search within.
- @param[in] Key The key to search.
- @return The point to the item contains the Key, or NULL if Key isn't in the map.
- **/
- NET_MAP_ITEM *
- Udp6MapMultiCastAddr (
- IN NET_MAP *Map,
- IN VOID *Key
- );
- /**
- Create the Udp service context data.
- @param[in] Udp6Service Pointer to the UDP6_SERVICE_DATA.
- @param[in] ImageHandle The image handle of this udp6 driver.
- @param[in] ControllerHandle The controller handle this udp6 driver binds on.
- @retval EFI_SUCCESS The udp6 service context data was created and
- initialized.
- @retval EFI_OUT_OF_RESOURCES Cannot allocate memory.
- @retval Others An error condition occurred.
- **/
- EFI_STATUS
- Udp6CreateService (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN EFI_HANDLE ImageHandle,
- IN EFI_HANDLE ControllerHandle
- )
- {
- EFI_STATUS Status;
- IP_IO_OPEN_DATA OpenData;
- ZeroMem (Udp6Service, sizeof (UDP6_SERVICE_DATA));
- Udp6Service->Signature = UDP6_SERVICE_DATA_SIGNATURE;
- Udp6Service->ServiceBinding = mUdp6ServiceBinding;
- Udp6Service->ImageHandle = ImageHandle;
- Udp6Service->ControllerHandle = ControllerHandle;
- Udp6Service->ChildrenNumber = 0;
- InitializeListHead (&Udp6Service->ChildrenList);
- //
- // Create the IpIo for this service context.
- //
- Udp6Service->IpIo = IpIoCreate (ImageHandle, ControllerHandle, IP_VERSION_6);
- if (Udp6Service->IpIo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Set the OpenData used to open the IpIo.
- //
- CopyMem (
- &OpenData.IpConfigData.Ip6CfgData,
- &mIp6IoDefaultIpConfigData,
- sizeof (EFI_IP6_CONFIG_DATA)
- );
- OpenData.RcvdContext = (VOID *)Udp6Service;
- OpenData.SndContext = NULL;
- OpenData.PktRcvdNotify = Udp6DgramRcvd;
- OpenData.PktSentNotify = Udp6DgramSent;
- //
- // Configure and start the IpIo.
- //
- Status = IpIoOpen (Udp6Service->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,
- Udp6CheckTimeout,
- Udp6Service,
- &Udp6Service->TimeoutEvent
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Start the timeout timer event.
- //
- Status = gBS->SetTimer (
- Udp6Service->TimeoutEvent,
- TimerPeriodic,
- UDP6_TIMEOUT_INTERVAL
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- return EFI_SUCCESS;
- ON_ERROR:
- if (Udp6Service->TimeoutEvent != NULL) {
- gBS->CloseEvent (Udp6Service->TimeoutEvent);
- }
- IpIoDestroy (Udp6Service->IpIo);
- Udp6Service->IpIo = NULL;
- return Status;
- }
- /**
- Clean the Udp service context data.
- @param[in, out] Udp6Service Pointer to the UDP6_SERVICE_DATA.
- **/
- VOID
- Udp6CleanService (
- IN OUT UDP6_SERVICE_DATA *Udp6Service
- )
- {
- //
- // Close the TimeoutEvent timer.
- //
- gBS->CloseEvent (Udp6Service->TimeoutEvent);
- //
- // Destroy the IpIo.
- //
- IpIoDestroy (Udp6Service->IpIo);
- Udp6Service->IpIo = NULL;
- ZeroMem (Udp6Service, sizeof (UDP6_SERVICE_DATA));
- }
- /**
- This function checks and times out the I/O datagrams listed in the
- UDP6_SERVICE_DATA which is specified by the input parameter 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
- Udp6CheckTimeout (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UDP6_SERVICE_DATA *Udp6Service;
- LIST_ENTRY *Entry;
- UDP6_INSTANCE_DATA *Instance;
- LIST_ENTRY *WrapEntry;
- LIST_ENTRY *NextEntry;
- UDP6_RXDATA_WRAP *Wrap;
- Udp6Service = (UDP6_SERVICE_DATA *)Context;
- NET_CHECK_SIGNATURE (Udp6Service, UDP6_SERVICE_DATA_SIGNATURE);
- NET_LIST_FOR_EACH (Entry, &Udp6Service->ChildrenList) {
- //
- // Iterate all the instances belonging to this service context.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP6_INSTANCE_DATA, Link);
- NET_CHECK_SIGNATURE (Instance, UDP6_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, UDP6_RXDATA_WRAP, Link);
- if (Wrap->TimeoutTick < UDP6_TIMEOUT_INTERVAL / 10) {
- //
- // Remove this RxData if it timeouts.
- //
- Udp6RecycleRxDataWrap (NULL, (VOID *)Wrap);
- } else {
- Wrap->TimeoutTick -= UDP6_TIMEOUT_INTERVAL / 10;
- }
- }
- }
- }
- /**
- This function initializes the new created udp instance.
- @param[in] Udp6Service Pointer to the UDP6_SERVICE_DATA.
- @param[in, out] Instance Pointer to the un-initialized UDP6_INSTANCE_DATA.
- **/
- VOID
- Udp6InitInstance (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN OUT UDP6_INSTANCE_DATA *Instance
- )
- {
- //
- // Set the signature.
- //
- Instance->Signature = UDP6_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 UDP6_SERVICE_DATA, and initialize other members.
- //
- Instance->Udp6Service = Udp6Service;
- CopyMem (&Instance->Udp6Proto, &mUdp6Protocol, sizeof (EFI_UDP6_PROTOCOL));
- Instance->IcmpError = EFI_SUCCESS;
- Instance->Configured = FALSE;
- Instance->IsNoMapping = FALSE;
- Instance->InDestroy = FALSE;
- }
- /**
- This function cleans the udp instance.
- @param[in, out] Instance Pointer to the UDP6_INSTANCE_DATA to clean.
- **/
- VOID
- Udp6CleanInstance (
- IN OUT UDP6_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 IPv6 address.
- @param[in] Port The udp port number.
- @retval TRUE The specified <Address, Port> pair is found.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp6FindInstanceByPort (
- IN LIST_ENTRY *InstanceList,
- IN EFI_IPv6_ADDRESS *Address,
- IN UINT16 Port
- )
- {
- LIST_ENTRY *Entry;
- UDP6_INSTANCE_DATA *Instance;
- EFI_UDP6_CONFIG_DATA *ConfigData;
- NET_LIST_FOR_EACH (Entry, InstanceList) {
- //
- // Iterate all the udp instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP6_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_IP6_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] ConfigData Pointer to the ConfigData of the instance to be
- bound.
- @retval EFI_SUCCESS The bound operation 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
- Udp6Bind (
- IN LIST_ENTRY *InstanceList,
- IN EFI_UDP6_CONFIG_DATA *ConfigData
- )
- {
- EFI_IPv6_ADDRESS *StationAddress;
- UINT16 StartPort;
- if (ConfigData->AcceptAnyPort) {
- return EFI_SUCCESS;
- }
- StationAddress = &ConfigData->StationAddress;
- if (ConfigData->StationPort != 0) {
- if (!ConfigData->AllowDuplicatePort &&
- Udp6FindInstanceByPort (InstanceList, StationAddress, ConfigData->StationPort)
- )
- {
- //
- // Do not allow duplicate ports 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 = mUdp6RandomPort;
- } else {
- StartPort = mUdp6RandomPort;
- while (Udp6FindInstanceByPort (InstanceList, StationAddress, mUdp6RandomPort)) {
- mUdp6RandomPort++;
- if (mUdp6RandomPort == 0) {
- mUdp6RandomPort = UDP6_PORT_KNOWN;
- }
- if (mUdp6RandomPort == StartPort) {
- //
- // No available port.
- //
- return EFI_OUT_OF_RESOURCES;
- }
- }
- ConfigData->StationPort = mUdp6RandomPort;
- }
- mUdp6RandomPort++;
- if (mUdp6RandomPort == 0) {
- mUdp6RandomPort = UDP6_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 according to the NewConfigData.
- @retval FALSE Otherwise.
- **/
- BOOLEAN
- Udp6IsReconfigurable (
- IN EFI_UDP6_CONFIG_DATA *OldConfigData,
- IN EFI_UDP6_CONFIG_DATA *NewConfigData
- )
- {
- if ((NewConfigData->AcceptAnyPort != OldConfigData->AcceptAnyPort) ||
- (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 (!EFI_IP6_EQUAL (&NewConfigData->StationAddress, &OldConfigData->StationAddress)) {
- //
- // The StationAddress is not the same.
- //
- return FALSE;
- }
- if (!EFI_IP6_EQUAL (&NewConfigData->RemoteAddress, &OldConfigData->RemoteAddress)) {
- //
- // The remoteaddress is not the same.
- //
- return FALSE;
- }
- if (!NetIp6IsUnspecifiedAddr (&NewConfigData->RemoteAddress) &&
- (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 Ip6 configdata from the Udp6ConfigData.
- @param[in] Udp6ConfigData Pointer to the EFI_UDP6_CONFIG_DATA.
- @param[in, out] Ip6ConfigData Pointer to the EFI_IP6_CONFIG_DATA.
- **/
- VOID
- Udp6BuildIp6ConfigData (
- IN EFI_UDP6_CONFIG_DATA *Udp6ConfigData,
- IN OUT EFI_IP6_CONFIG_DATA *Ip6ConfigData
- )
- {
- CopyMem (
- Ip6ConfigData,
- &mIp6IoDefaultIpConfigData,
- sizeof (EFI_IP6_CONFIG_DATA)
- );
- Ip6ConfigData->DefaultProtocol = EFI_IP_PROTO_UDP;
- Ip6ConfigData->AcceptPromiscuous = Udp6ConfigData->AcceptPromiscuous;
- IP6_COPY_ADDRESS (&Ip6ConfigData->StationAddress, &Udp6ConfigData->StationAddress);
- IP6_COPY_ADDRESS (&Ip6ConfigData->DestinationAddress, &Udp6ConfigData->RemoteAddress);
- //
- // Use the -1 magic number to disable the receiving process of the ip instance.
- //
- Ip6ConfigData->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:
- 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;
- UdpSessionData.DestinationAddress are not valid
- unicast IPv6 addresses if the UdpSessionData is
- not NULL;
- UdpSessionData.DestinationPort and
- ConfigData.RemotePort are all zero if the
- UdpSessionData is not NULL.
- @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP
- packet size.
- **/
- EFI_STATUS
- Udp6ValidateTxToken (
- IN UDP6_INSTANCE_DATA *Instance,
- IN EFI_UDP6_COMPLETION_TOKEN *TxToken
- )
- {
- EFI_UDP6_TRANSMIT_DATA *TxData;
- UINT32 Index;
- UINT32 TotalLen;
- EFI_UDP6_CONFIG_DATA *ConfigData;
- EFI_UDP6_SESSION_DATA *UdpSessionData;
- 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;
- }
- ConfigData = &Instance->ConfigData;
- UdpSessionData = TxData->UdpSessionData;
- if (UdpSessionData != NULL) {
- if ((UdpSessionData->DestinationPort == 0) && (ConfigData->RemotePort == 0)) {
- //
- // Ambiguous; no available DestinationPort for this token.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (NetIp6IsUnspecifiedAddr (&UdpSessionData->DestinationAddress) &&
- NetIp6IsUnspecifiedAddr (&ConfigData->RemoteAddress)
- )
- {
- //
- // The DestinationAddress is not specified.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (!NetIp6IsUnspecifiedAddr (&UdpSessionData->DestinationAddress) &&
- !NetIp6IsUnspecifiedAddr (&ConfigData->RemoteAddress)
- )
- {
- //
- // The ConfigData.RemoteAddress is not zero and the UdpSessionData.DestinationAddress
- // is not zero too.
- //
- return EFI_INVALID_PARAMETER;
- }
- } else if (NetIp6IsUnspecifiedAddr (&ConfigData->RemoteAddress)) {
- //
- // The configured RemoteAddress is all zero, and the user doesn't override the
- // destination address.
- //
- return EFI_INVALID_PARAMETER;
- }
- if (TxData->DataLength > UDP6_MAX_DATA_SIZE) {
- return EFI_BAD_BUFFER_SIZE;
- }
- return EFI_SUCCESS;
- }
- /**
- This function checks whether the specified Token duplicates 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
- Udp6TokenExist (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- EFI_UDP6_COMPLETION_TOKEN *Token;
- EFI_UDP6_COMPLETION_TOKEN *TokenInItem;
- Token = (EFI_UDP6_COMPLETION_TOKEN *)Context;
- TokenInItem = (EFI_UDP6_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.
- @return The 16-bit checksum of this udp datagram.
- **/
- UINT16
- Udp6Checksum (
- IN NET_BUF *Packet,
- IN UINT16 HeadSum
- )
- {
- UINT16 Checksum;
- Checksum = NetbufChecksum (Packet);
- Checksum = NetAddChecksum (Checksum, HeadSum);
- Checksum = NetAddChecksum (Checksum, HTONS ((UINT16)Packet->TotalSize));
- Checksum = (UINT16)(~Checksum);
- return Checksum;
- }
- /**
- This function removes the specified Token from the TokenMap.
- @param[in] 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
- Udp6RemoveToken (
- IN NET_MAP *TokenMap,
- IN EFI_UDP6_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.
- If Context is NULL, then ASSERT().
- If NotifyData is NULL, then ASSERT().
- @param[in] Status The completion status of the output udp datagram.
- @param[in] Context Pointer to the context data.
- @param[in] Sender Specify a EFI_IP6_PROTOCOL for sending.
- @param[in] NotifyData Pointer to the notify data.
- **/
- VOID
- EFIAPI
- Udp6DgramSent (
- IN EFI_STATUS Status,
- IN VOID *Context,
- IN IP_IO_IP_PROTOCOL Sender,
- IN VOID *NotifyData
- )
- {
- UDP6_INSTANCE_DATA *Instance;
- EFI_UDP6_COMPLETION_TOKEN *Token;
- ASSERT (Context != NULL && NotifyData != NULL);
- Instance = (UDP6_INSTANCE_DATA *)Context;
- Token = (EFI_UDP6_COMPLETION_TOKEN *)NotifyData;
- if (Udp6RemoveToken (&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.
- If NetSession is NULL, then ASSERT().
- If Packet is NULL, then ASSERT().
- If Context is NULL, then ASSERT().
- @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
- Udp6DgramRcvd (
- IN EFI_STATUS Status,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet,
- IN VOID *Context
- )
- {
- ASSERT (NetSession != NULL && Packet != NULL && Context != NULL);
- 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.
- //
- Udp6Demultiplex ((UDP6_SERVICE_DATA *)Context, NetSession, Packet);
- } else {
- //
- // Handle the ICMP6 Error packet.
- //
- Udp6IcmpHandler ((UDP6_SERVICE_DATA *)Context, IcmpError, NetSession, Packet);
- }
- //
- // Dispatch the DPC queued by the NotifyFunction of the rx token's events
- // that are signaled with received data.
- //
- DispatchDpc ();
- }
- /**
- This function removes the multicast group specified by Arg from the Map.
- @param[in] 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 IPv6 Address. This parameter is
- optional and may be NULL.
- @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
- Udp6LeaveGroup (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- )
- {
- EFI_IPv6_ADDRESS *McastIp;
- McastIp = Arg;
- if ((McastIp != NULL) &&
- !EFI_IP6_EQUAL (McastIp, ((EFI_IPv6_ADDRESS *)Item->Key))
- )
- {
- //
- // McastIp is not NULL and the multicast address contained in the Item
- // is not the same as McastIp.
- //
- return EFI_SUCCESS;
- }
- FreePool (Item->Key);
- //
- // 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 cancel the token specified by Arg in the Map.
- @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, all
- the tokens in this Map will be cancelled.
- This parameter is optional and may be NULL.
- @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
- Udp6CancelTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Arg OPTIONAL
- )
- {
- EFI_UDP6_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 Udp6DgramSent, 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_UDP6_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 Udp6 Instance.
- **/
- VOID
- Udp6FlushRcvdDgram (
- IN UDP6_INSTANCE_DATA *Instance
- )
- {
- UDP6_RXDATA_WRAP *Wrap;
- while (!IsListEmpty (&Instance->RcvdDgramQue)) {
- //
- // Iterate all the Wraps in the RcvdDgramQue.
- //
- Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP6_RXDATA_WRAP, Link);
- //
- // The Wrap will be removed from the RcvdDgramQue by this function call.
- //
- Udp6RecycleRxDataWrap (NULL, (VOID *)Wrap);
- }
- }
- /**
- Cancel Udp6 tokens from the Udp6 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.
- This parameter is optional and may be NULL.
- @retval EFI_SUCCESS The Token is cancelled.
- @retval EFI_NOT_FOUND The Token is not found.
- **/
- EFI_STATUS
- Udp6InstanceCancelToken (
- IN UDP6_INSTANCE_DATA *Instance,
- IN EFI_UDP6_COMPLETION_TOKEN *Token OPTIONAL
- )
- {
- EFI_STATUS Status;
- //
- // Cancel this token from the TxTokens map.
- //
- Status = NetMapIterate (&Instance->TxTokens, Udp6CancelTokens, Token);
- if ((Token != NULL) && (Status == EFI_ABORTED)) {
- //
- // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
- // the TxTokens and returns 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, Udp6CancelTokens, 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 checks if the received udp datagram matches with the Instance.
- @param[in] Instance Pointer to the udp instance context data.
- @param[in] Udp6Session Pointer to the EFI_UDP6_SESSION_DATA abstracted
- from the received udp datagram.
- @retval TRUE The udp datagram matches the receiving requirements of the Instance.
- @retval FALSE The udp datagram does not match the receiving requirements of the Instance.
- **/
- BOOLEAN
- Udp6MatchDgram (
- IN UDP6_INSTANCE_DATA *Instance,
- IN EFI_UDP6_SESSION_DATA *Udp6Session
- )
- {
- EFI_UDP6_CONFIG_DATA *ConfigData;
- EFI_IPv6_ADDRESS Destination;
- ConfigData = &Instance->ConfigData;
- if (ConfigData->AcceptPromiscuous) {
- //
- // Always matches if this instance is in the promiscuous state.
- //
- return TRUE;
- }
- if ((!ConfigData->AcceptAnyPort && (Udp6Session->DestinationPort != ConfigData->StationPort)) ||
- ((ConfigData->RemotePort != 0) && (Udp6Session->SourcePort != ConfigData->RemotePort))
- )
- {
- //
- // The local port or the remote port doesn't match.
- //
- return FALSE;
- }
- if (!NetIp6IsUnspecifiedAddr (&ConfigData->RemoteAddress) &&
- !EFI_IP6_EQUAL (&ConfigData->RemoteAddress, &Udp6Session->SourceAddress)
- )
- {
- //
- // This datagram doesn't come from the instance's specified sender.
- //
- return FALSE;
- }
- if (NetIp6IsUnspecifiedAddr (&ConfigData->StationAddress) ||
- EFI_IP6_EQUAL (&Udp6Session->DestinationAddress, &ConfigData->StationAddress)
- )
- {
- //
- // The instance is configured to receive datagrams destinated to any station IP or
- // the destination address of this datagram matches the configured station IP.
- //
- return TRUE;
- }
- IP6_COPY_ADDRESS (&Destination, &Udp6Session->DestinationAddress);
- if (IP6_IS_MULTICAST (&Destination) &&
- (NULL != Udp6MapMultiCastAddr (&Instance->McastIps, &Destination))
- )
- {
- //
- // 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
- Udp6RecycleRxDataWrap (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UDP6_RXDATA_WRAP *Wrap;
- Wrap = (UDP6_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 into 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_UDP6_RECEIVE_DATA of this
- datagram.
- @return Pointer to the structure wrapping the RxData and the Packet. NULL will
- be returned if any error occurs.
- **/
- UDP6_RXDATA_WRAP *
- Udp6WrapRxData (
- IN UDP6_INSTANCE_DATA *Instance,
- IN NET_BUF *Packet,
- IN EFI_UDP6_RECEIVE_DATA *RxData
- )
- {
- EFI_STATUS Status;
- UDP6_RXDATA_WRAP *Wrap;
- //
- // Allocate buffer for the Wrap.
- //
- Wrap = AllocateZeroPool (
- sizeof (UDP6_RXDATA_WRAP) +
- (Packet->BlockOpNum - 1) * sizeof (EFI_UDP6_FRAGMENT_DATA)
- );
- if (Wrap == NULL) {
- return NULL;
- }
- InitializeListHead (&Wrap->Link);
- CopyMem (&Wrap->RxData, RxData, sizeof (EFI_UDP6_RECEIVE_DATA));
- //
- // Create the Recycle event.
- //
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- Udp6RecycleRxDataWrap,
- 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] Udp6Service 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_UDP6_RECEIVE_DATA of this
- datagram.
- @return The times this datagram is enqueued.
- **/
- UINTN
- Udp6EnqueueDgram (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN NET_BUF *Packet,
- IN EFI_UDP6_RECEIVE_DATA *RxData
- )
- {
- LIST_ENTRY *Entry;
- UDP6_INSTANCE_DATA *Instance;
- UDP6_RXDATA_WRAP *Wrap;
- UINTN Enqueued;
- Enqueued = 0;
- NET_LIST_FOR_EACH (Entry, &Udp6Service->ChildrenList) {
- //
- // Iterate the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP6_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- if (Udp6MatchDgram (Instance, &RxData->UdpSession)) {
- //
- // Wrap the RxData and put this Wrap into the instances RcvdDgramQue.
- //
- Wrap = Udp6WrapRxData (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 to the specified instance.
- @param[in] Instance Pointer to the instance context data.
- **/
- VOID
- Udp6InstanceDeliverDgram (
- IN UDP6_INSTANCE_DATA *Instance
- )
- {
- UDP6_RXDATA_WRAP *Wrap;
- EFI_UDP6_COMPLETION_TOKEN *Token;
- NET_BUF *Dup;
- EFI_UDP6_RECEIVE_DATA *RxData;
- EFI_TPL OldTpl;
- if (!IsListEmpty (&Instance->RcvdDgramQue) &&
- !NetMapIsEmpty (&Instance->RxTokens)
- )
- {
- Wrap = NET_LIST_HEAD (&Instance->RcvdDgramQue, UDP6_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_UDP6_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] Udp6Service Pointer to the udp service context data.
- **/
- VOID
- Udp6DeliverDgram (
- IN UDP6_SERVICE_DATA *Udp6Service
- )
- {
- LIST_ENTRY *Entry;
- UDP6_INSTANCE_DATA *Instance;
- NET_LIST_FOR_EACH (Entry, &Udp6Service->ChildrenList) {
- //
- // Iterate the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP6_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- //
- // Deliver the datagrams of this instance.
- //
- Udp6InstanceDeliverDgram (Instance);
- }
- }
- /**
- This function demultiplexes the received udp datagram to the appropriate instances.
- @param[in] Udp6Service 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
- Udp6Demultiplex (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN NET_BUF *Packet
- )
- {
- EFI_UDP_HEADER *Udp6Header;
- UINT16 HeadSum;
- EFI_UDP6_RECEIVE_DATA RxData;
- EFI_UDP6_SESSION_DATA *Udp6Session;
- UINTN Enqueued;
- if (Packet->TotalSize < UDP6_HEADER_SIZE) {
- NetbufFree (Packet);
- return;
- }
- //
- // Get the datagram header from the packet buffer.
- //
- Udp6Header = (EFI_UDP_HEADER *)NetbufGetByte (Packet, 0, NULL);
- ASSERT (Udp6Header != NULL);
- if (Udp6Header == NULL) {
- NetbufFree (Packet);
- return;
- }
- if (Udp6Header->Checksum != 0) {
- //
- // check the checksum.
- //
- HeadSum = NetIp6PseudoHeadChecksum (
- &NetSession->Source.v6,
- &NetSession->Dest.v6,
- EFI_IP_PROTO_UDP,
- 0
- );
- if (Udp6Checksum (Packet, HeadSum) != 0) {
- //
- // Wrong checksum.
- //
- NetbufFree (Packet);
- return;
- }
- }
- Udp6Session = &RxData.UdpSession;
- Udp6Session->SourcePort = NTOHS (Udp6Header->SrcPort);
- Udp6Session->DestinationPort = NTOHS (Udp6Header->DstPort);
- IP6_COPY_ADDRESS (&Udp6Session->SourceAddress, &NetSession->Source);
- IP6_COPY_ADDRESS (&Udp6Session->DestinationAddress, &NetSession->Dest);
- //
- // Trim the UDP header.
- //
- NetbufTrim (Packet, UDP6_HEADER_SIZE, TRUE);
- RxData.DataLength = (UINT32)Packet->TotalSize;
- //
- // Try to enqueue this datagram into the instances.
- //
- Enqueued = Udp6EnqueueDgram (Udp6Service, Packet, &RxData);
- if (Enqueued == 0) {
- //
- // Send the port unreachable ICMP packet before we free this NET_BUF
- //
- Udp6SendPortUnreach (Udp6Service->IpIo, NetSession, Udp6Header);
- }
- //
- // Try to free the packet before deliver it.
- //
- NetbufFree (Packet);
- if (Enqueued > 0) {
- //
- // Deliver the datagram.
- //
- Udp6DeliverDgram (Udp6Service);
- }
- }
- /**
- 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] Udp6Header Pointer to the udp header of the datagram causes
- this icmp error message.
- **/
- VOID
- Udp6SendPortUnreach (
- IN IP_IO *IpIo,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN VOID *Udp6Header
- )
- {
- NET_BUF *Packet;
- UINT32 Len;
- IP6_ICMP_ERROR_HEAD *IcmpErrHdr;
- UINT8 *Ptr;
- IP_IO_OVERRIDE Override;
- IP_IO_IP_INFO *IpSender;
- EFI_IP6_MODE_DATA *Ip6ModeData;
- EFI_STATUS Status;
- EFI_IP6_PROTOCOL *Ip6Protocol;
- Ip6ModeData = NULL;
- //
- // An ICMPv6 error message MUST NOT be originated as A packet destined to
- // 1) an IPv6 multicast address 2) The IPv6 Unspecified Address
- //
- if (NetSession->IpVersion == IP_VERSION_6) {
- if (NetIp6IsUnspecifiedAddr (&NetSession->Dest.v6) ||
- IP6_IS_MULTICAST (&NetSession->Dest.v6)
- )
- {
- goto EXIT;
- }
- }
- IpSender = IpIoFindSender (&IpIo, NetSession->IpVersion, &NetSession->Dest);
- //
- // Get the Ipv6 Mode Data.
- //
- Ip6ModeData = AllocateZeroPool (sizeof (EFI_IP6_MODE_DATA));
- ASSERT (Ip6ModeData != NULL);
- if (Ip6ModeData == NULL) {
- goto EXIT;
- }
- //
- // If not finding the related IpSender use the default IpIo to send out
- // the port unreachable ICMP message.
- //
- if (IpSender == NULL) {
- Ip6Protocol = IpIo->Ip.Ip6;
- } else {
- Ip6Protocol = IpSender->Ip.Ip6;
- }
- Status = Ip6Protocol->GetModeData (
- Ip6Protocol,
- Ip6ModeData,
- NULL,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
- //
- // The ICMP6 packet length, includes whole invoking packet and ICMP6 error header.
- //
- Len = NetSession->IpHdrLen +
- NTOHS (((EFI_UDP_HEADER *)Udp6Header)->Length) +
- sizeof (IP6_ICMP_ERROR_HEAD);
- //
- // If the ICMP6 packet length larger than IP MTU, adjust its length to MTU.
- //
- if (Ip6ModeData->MaxPacketSize < Len) {
- Len = Ip6ModeData->MaxPacketSize;
- }
- //
- // Allocate buffer for the icmp error message.
- //
- Packet = NetbufAlloc (Len);
- if (Packet == NULL) {
- goto EXIT;
- }
- //
- // Allocate space for the IP6_ICMP_ERROR_HEAD.
- //
- IcmpErrHdr = (IP6_ICMP_ERROR_HEAD *)NetbufAllocSpace (Packet, Len, FALSE);
- ASSERT (IcmpErrHdr != NULL);
- if (IcmpErrHdr == NULL) {
- goto EXIT;
- }
- //
- // Set the required fields for the icmp port unreachable message.
- //
- IcmpErrHdr->Head.Type = ICMP_V6_DEST_UNREACHABLE;
- IcmpErrHdr->Head.Code = ICMP_V6_PORT_UNREACHABLE;
- IcmpErrHdr->Head.Checksum = 0;
- IcmpErrHdr->Fourth = 0;
- //
- // Copy as much of invoking Packet as possible without the ICMPv6 packet
- // exceeding the minimum Ipv6 MTU. The length of IP6_ICMP_ERROR_HEAD contains
- // the length of EFI_IP6_HEADER, so when using the length of IP6_ICMP_ERROR_HEAD
- // for pointer movement that fact should be considered.
- //
- Ptr = (VOID *)&IcmpErrHdr->Head;
- Ptr = (UINT8 *)(UINTN)((UINTN)Ptr + sizeof (IP6_ICMP_ERROR_HEAD) - sizeof (EFI_IP6_HEADER));
- CopyMem (Ptr, NetSession->IpHdr.Ip6Hdr, NetSession->IpHdrLen);
- CopyMem (
- Ptr + NetSession->IpHdrLen,
- Udp6Header,
- Len - NetSession->IpHdrLen - sizeof (IP6_ICMP_ERROR_HEAD) + sizeof (EFI_IP6_HEADER)
- );
- //
- // Set the checksum as zero, and IP6 driver will calculate it with pseudo header.
- //
- IcmpErrHdr->Head.Checksum = 0;
- //
- // Fill the override data.
- //
- Override.Ip6OverrideData.FlowLabel = 0;
- Override.Ip6OverrideData.HopLimit = 255;
- Override.Ip6OverrideData.Protocol = IP6_ICMP;
- //
- // Send out this icmp packet.
- //
- IpIoSend (IpIo, Packet, IpSender, NULL, NULL, &NetSession->Source, &Override);
- NetbufFree (Packet);
- EXIT:
- if (Ip6ModeData != NULL) {
- FreePool (Ip6ModeData);
- }
- }
- /**
- This function handles the received Icmp Error message and de-multiplexes it to the
- instance.
- @param[in] Udp6Service 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, out] Packet Pointer to the Icmp Error packet.
- **/
- VOID
- Udp6IcmpHandler (
- IN UDP6_SERVICE_DATA *Udp6Service,
- IN UINT8 IcmpError,
- IN EFI_NET_SESSION_DATA *NetSession,
- IN OUT NET_BUF *Packet
- )
- {
- EFI_UDP_HEADER *Udp6Header;
- EFI_UDP6_SESSION_DATA Udp6Session;
- LIST_ENTRY *Entry;
- UDP6_INSTANCE_DATA *Instance;
- if (Packet->TotalSize < UDP6_HEADER_SIZE) {
- NetbufFree (Packet);
- return;
- }
- Udp6Header = (EFI_UDP_HEADER *)NetbufGetByte (Packet, 0, NULL);
- ASSERT (Udp6Header != NULL);
- if (Udp6Header == NULL) {
- NetbufFree (Packet);
- return;
- }
- IP6_COPY_ADDRESS (&Udp6Session.SourceAddress, &NetSession->Source);
- IP6_COPY_ADDRESS (&Udp6Session.DestinationAddress, &NetSession->Dest);
- Udp6Session.SourcePort = NTOHS (Udp6Header->DstPort);
- Udp6Session.DestinationPort = NTOHS (Udp6Header->SrcPort);
- NET_LIST_FOR_EACH (Entry, &Udp6Service->ChildrenList) {
- //
- // Iterate all the instances.
- //
- Instance = NET_LIST_USER_STRUCT (Entry, UDP6_INSTANCE_DATA, Link);
- if (!Instance->Configured) {
- continue;
- }
- if (Udp6MatchDgram (Instance, &Udp6Session)) {
- //
- // Translate the Icmp Error code according to the udp spec.
- //
- Instance->IcmpError = IpIoGetIcmpErrStatus (IcmpError, IP_VERSION_6, NULL, NULL);
- if (IcmpError > ICMP_ERR_UNREACH_PORT) {
- Instance->IcmpError = EFI_ICMP_ERROR;
- }
- //
- // Notify the instance with the received Icmp Error.
- //
- Udp6ReportIcmpError (Instance);
- break;
- }
- }
- NetbufFree (Packet);
- }
- /**
- This function reports the received ICMP error.
- @param[in] Instance Pointer to the udp instance context data.
- **/
- VOID
- Udp6ReportIcmpError (
- IN UDP6_INSTANCE_DATA *Instance
- )
- {
- EFI_UDP6_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_UDP6_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
- Udp6NetVectorExtFree (
- IN VOID *Context
- )
- {
- }
- /**
- Find the key in the netmap.
- @param[in] Map The netmap to search within.
- @param[in] Key The key to search.
- @return The point to the item contains the Key, or NULL, if Key isn't in the map.
- **/
- NET_MAP_ITEM *
- Udp6MapMultiCastAddr (
- IN NET_MAP *Map,
- IN VOID *Key
- )
- {
- LIST_ENTRY *Entry;
- NET_MAP_ITEM *Item;
- EFI_IPv6_ADDRESS *Addr;
- ASSERT (Map != NULL);
- NET_LIST_FOR_EACH (Entry, &Map->Used) {
- Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
- Addr = (EFI_IPv6_ADDRESS *)Item->Key;
- if (EFI_IP6_EQUAL (Addr, Key)) {
- return Item;
- }
- }
- return NULL;
- }
|