1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136 |
- /** @file
- Dhcp6 internal functions implementation.
- (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Dhcp6Impl.h"
- /**
- Enqueue the packet into the retry list in case of timeout.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to the Dhcp6 packet to retry.
- @param[in] Elapsed The pointer to the elapsed time value in the packet.
- @param[in] RetryCtl The pointer to the transmission control of the packet.
- This parameter is optional and may be NULL.
- @retval EFI_SUCCESS Successfully enqueued the packet into the retry list according
- to its message type.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected message type.
- **/
- EFI_STATUS
- Dhcp6EnqueueRetry (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet,
- IN UINT16 *Elapsed,
- IN EFI_DHCP6_RETRANSMISSION *RetryCtl OPTIONAL
- )
- {
- DHCP6_TX_CB *TxCb;
- DHCP6_IA_CB *IaCb;
- ASSERT (Packet != NULL);
- IaCb = &Instance->IaCb;
- TxCb = AllocateZeroPool (sizeof (DHCP6_TX_CB));
- if (TxCb == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Save tx packet pointer, and it will be destroyed when reply received.
- //
- TxCb->TxPacket = Packet;
- TxCb->Xid = Packet->Dhcp6.Header.TransactionId;
- //
- // Save pointer to elapsed-time value so we can update it on retransmits.
- //
- TxCb->Elapsed = Elapsed;
- //
- // Calculate the retransmission according to the message type.
- //
- switch (Packet->Dhcp6.Header.MessageType) {
- case Dhcp6MsgSolicit:
- //
- // Calculate the retransmission threshold value for solicit packet.
- // Use the default value by rfc-3315 if user doesn't configure.
- //
- if (RetryCtl == NULL) {
- TxCb->RetryCtl.Irt = DHCP6_SOL_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_SOL_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_SOL_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_SOL_MRD;
- } else {
- TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_SOL_IRT;
- TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_SOL_MRC;
- TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_SOL_MRT;
- TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_SOL_MRD;
- }
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- FALSE
- );
- break;
- case Dhcp6MsgRequest:
- //
- // Calculate the retransmission threshold value for request packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_REQ_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_REQ_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_REQ_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_REQ_MRD;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgConfirm:
- //
- // Calculate the retransmission threshold value for confirm packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_CNF_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_CNF_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_CNF_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_CNF_MRD;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgRenew:
- //
- // Calculate the retransmission threshold value for renew packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_REB_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_REB_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_REB_MRT;
- TxCb->RetryCtl.Mrd = IaCb->T2 - IaCb->T1;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgRebind:
- //
- // Calculate the retransmission threshold value for rebind packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_REN_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_REN_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_REN_MRT;
- TxCb->RetryCtl.Mrd = IaCb->AllExpireTime - IaCb->T2;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgDecline:
- //
- // Calculate the retransmission threshold value for decline packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_DEC_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_DEC_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_DEC_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_DEC_MRD;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgRelease:
- //
- // Calculate the retransmission threshold value for release packet.
- //
- TxCb->RetryCtl.Irt = DHCP6_REL_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_REL_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_REL_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_REL_MRD;
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- case Dhcp6MsgInfoRequest:
- //
- // Calculate the retransmission threshold value for info-request packet.
- // Use the default value by rfc-3315 if user doesn't configure.
- //
- if (RetryCtl == NULL) {
- TxCb->RetryCtl.Irt = DHCP6_INF_IRT;
- TxCb->RetryCtl.Mrc = DHCP6_INF_MRC;
- TxCb->RetryCtl.Mrt = DHCP6_INF_MRT;
- TxCb->RetryCtl.Mrd = DHCP6_INF_MRD;
- } else {
- TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_INF_IRT;
- TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_INF_MRC;
- TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_INF_MRT;
- TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_INF_MRD;
- }
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Irt,
- TRUE,
- TRUE
- );
- break;
- default:
- //
- // Unexpected message type.
- //
- FreePool (TxCb);
- return EFI_DEVICE_ERROR;
- }
- //
- // Insert into the retransmit list of the instance.
- //
- InsertTailList (&Instance->TxList, &TxCb->Link);
- return EFI_SUCCESS;
- }
- /**
- Dequeue the packet from retry list if reply received or timeout at last.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] PacketXid The packet transaction id to match.
- @param[in] NeedSignal If TRUE, then an timeout event need be signaled when it is existed.
- Otherwise, this parameter is ignored.
- @retval EFI_SUCCESS Successfully dequeued the packet into retry list .
- @retval EFI_NOT_FOUND There is no xid matched in retry list.
- **/
- EFI_STATUS
- Dhcp6DequeueRetry (
- IN DHCP6_INSTANCE *Instance,
- IN UINT32 PacketXid,
- IN BOOLEAN NeedSignal
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *NextEntry;
- DHCP6_TX_CB *TxCb;
- DHCP6_INF_CB *InfCb;
- //
- // Seek the retransmit node in the retransmit list by packet xid.
- //
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) {
- TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link);
- ASSERT (TxCb->TxPacket);
- if (TxCb->Xid == PacketXid) {
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) {
- //
- // Seek the info-request node in the info-request list by packet xid.
- //
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->InfList) {
- InfCb = NET_LIST_USER_STRUCT (Entry, DHCP6_INF_CB, Link);
- if (InfCb->Xid == PacketXid) {
- //
- // Remove the info-request node, and signal the event if timeout.
- //
- if ((InfCb->TimeoutEvent != NULL) && NeedSignal) {
- gBS->SignalEvent (InfCb->TimeoutEvent);
- }
- RemoveEntryList (&InfCb->Link);
- FreePool (InfCb);
- }
- }
- }
- //
- // Remove the retransmit node.
- //
- RemoveEntryList (&TxCb->Link);
- ASSERT (TxCb->TxPacket);
- FreePool (TxCb->TxPacket);
- FreePool (TxCb);
- return EFI_SUCCESS;
- }
- }
- return EFI_NOT_FOUND;
- }
- /**
- Clean up the specific nodes in the retry list.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Scope The scope of cleanup nodes.
- **/
- VOID
- Dhcp6CleanupRetry (
- IN DHCP6_INSTANCE *Instance,
- IN UINT32 Scope
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *NextEntry;
- DHCP6_TX_CB *TxCb;
- DHCP6_INF_CB *InfCb;
- //
- // Clean up all the stateful messages from the retransmit list.
- //
- if ((Scope == DHCP6_PACKET_STATEFUL) || (Scope == DHCP6_PACKET_ALL)) {
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) {
- TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link);
- ASSERT (TxCb->TxPacket);
- if (TxCb->TxPacket->Dhcp6.Header.MessageType != Dhcp6MsgInfoRequest) {
- RemoveEntryList (&TxCb->Link);
- FreePool (TxCb->TxPacket);
- FreePool (TxCb);
- }
- }
- }
- //
- // Clean up all the stateless messages from the retransmit list.
- //
- if ((Scope == DHCP6_PACKET_STATELESS) || (Scope == DHCP6_PACKET_ALL)) {
- //
- // Clean up all the retransmit list for stateless messages.
- //
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) {
- TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link);
- ASSERT (TxCb->TxPacket);
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) {
- RemoveEntryList (&TxCb->Link);
- FreePool (TxCb->TxPacket);
- FreePool (TxCb);
- }
- }
- //
- // Clean up all the info-request messages list.
- //
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->InfList) {
- InfCb = NET_LIST_USER_STRUCT (Entry, DHCP6_INF_CB, Link);
- if (InfCb->TimeoutEvent != NULL) {
- gBS->SignalEvent (InfCb->TimeoutEvent);
- }
- RemoveEntryList (&InfCb->Link);
- FreePool (InfCb);
- }
- }
- }
- /**
- Check whether the TxCb is still a valid control block in the instance's retry list.
- @param[in] Instance The pointer to DHCP6_INSTANCE.
- @param[in] TxCb The control block for a transmitted message.
- @retval TRUE The control block is in Instance's retry list.
- @retval FALSE The control block is NOT in Instance's retry list.
- **/
- BOOLEAN
- Dhcp6IsValidTxCb (
- IN DHCP6_INSTANCE *Instance,
- IN DHCP6_TX_CB *TxCb
- )
- {
- LIST_ENTRY *Entry;
- NET_LIST_FOR_EACH (Entry, &Instance->TxList) {
- if (TxCb == NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link)) {
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- Clean up the session of the instance stateful exchange.
- @param[in, out] Instance The pointer to the Dhcp6 instance.
- @param[in] Status The return status from udp.
- **/
- VOID
- Dhcp6CleanupSession (
- IN OUT DHCP6_INSTANCE *Instance,
- IN EFI_STATUS Status
- )
- {
- UINTN Index;
- EFI_DHCP6_IA *Ia;
- ASSERT (Instance->Config);
- ASSERT (Instance->IaCb.Ia);
- //
- // Clean up the retransmit list for stateful messages.
- //
- Dhcp6CleanupRetry (Instance, DHCP6_PACKET_STATEFUL);
- if (Instance->Unicast != NULL) {
- FreePool (Instance->Unicast);
- }
- if (Instance->AdSelect != NULL) {
- FreePool (Instance->AdSelect);
- }
- if (Instance->IaCb.Ia->ReplyPacket != NULL) {
- FreePool (Instance->IaCb.Ia->ReplyPacket);
- }
- //
- // Reinitialize the Ia fields of the instance.
- //
- Instance->UdpSts = Status;
- Instance->AdSelect = NULL;
- Instance->AdPref = 0;
- Instance->Unicast = NULL;
- Instance->IaCb.T1 = 0;
- Instance->IaCb.T2 = 0;
- Instance->IaCb.AllExpireTime = 0;
- Instance->IaCb.LeaseTime = 0;
- //
- // Clear start time
- //
- Instance->StartTime = 0;
- Ia = Instance->IaCb.Ia;
- Ia->State = Dhcp6Init;
- Ia->ReplyPacket = NULL;
- //
- // Set the addresses as zero lifetime, and then the notify
- // function in Ip6Config will remove these timeout address.
- //
- for (Index = 0; Index < Ia->IaAddressCount; Index++) {
- Ia->IaAddress[Index].PreferredLifetime = 0;
- Ia->IaAddress[Index].ValidLifetime = 0;
- }
- //
- //
- // Signal the Ia information updated event to informal user.
- //
- if (Instance->Config->IaInfoEvent != NULL) {
- gBS->SignalEvent (Instance->Config->IaInfoEvent);
- }
- }
- /**
- Callback to user when Dhcp6 transmit/receive occurs.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Event The current Dhcp6 event.
- @param[in, out] Packet The pointer to the packet sending or received.
- @retval EFI_SUCCESS The user function returns success.
- @retval EFI_NOT_READY Direct the caller to continue collecting the offer.
- @retval EFI_ABORTED The user function ask it to abort.
- **/
- EFI_STATUS
- EFIAPI
- Dhcp6CallbackUser (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_EVENT Event,
- IN OUT EFI_DHCP6_PACKET **Packet
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *NewPacket;
- EFI_DHCP6_CALLBACK Callback;
- VOID *Context;
- ASSERT (Packet != NULL);
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- NewPacket = NULL;
- Status = EFI_SUCCESS;
- Callback = Instance->Config->Dhcp6Callback;
- Context = Instance->Config->CallbackContext;
- //
- // Callback to user with the new message if has.
- //
- if (Callback != NULL) {
- Status = Callback (
- &Instance->Dhcp6,
- Context,
- Instance->IaCb.Ia->State,
- Event,
- *Packet,
- &NewPacket
- );
- //
- // Updated the new packet from user to replace the original one.
- //
- if (NewPacket != NULL) {
- ASSERT (*Packet != NULL);
- FreePool (*Packet);
- *Packet = NewPacket;
- }
- }
- return Status;
- }
- /**
- Update Ia according to the new reply message.
- @param[in, out] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to reply messages.
- @retval EFI_SUCCESS Updated the Ia information successfully.
- @retval EFI_DEVICE_ERROR An unexpected error.
- **/
- EFI_STATUS
- Dhcp6UpdateIaInfo (
- IN OUT DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet
- )
- {
- EFI_STATUS Status;
- UINT8 *Option;
- UINT8 *IaInnerOpt;
- UINT16 IaInnerLen;
- UINT16 StsCode;
- UINT32 T1;
- UINT32 T2;
- ASSERT (Instance->Config != NULL);
- //
- // If the reply was received in response to a solicit with rapid commit option,
- // request, renew or rebind message, the client updates the information it has
- // recorded about IAs from the IA options contained in the reply message:
- // 1. record the T1 and T2 times
- // 2. add any new addresses in the IA
- // 3. discard any addresses from the IA, that have a valid lifetime of 0
- // 4. update lifetimes for any addresses that already recorded
- // 5. leave unchanged any information about addresses
- //
- // See details in the section-18.1.8 of rfc-3315.
- //
- Option = Dhcp6SeekIaOption (
- Packet->Dhcp6.Option,
- Packet->Length - sizeof (EFI_DHCP6_HEADER),
- &Instance->Config->IaDescriptor
- );
- if (Option == NULL) {
- return EFI_DEVICE_ERROR;
- }
- //
- // The format of the IA_NA option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_IA_NA | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | IAID (4 octets) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | T1 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | T2 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // . IA_NA-options .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- // The format of the IA_TA option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_IA_TA | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | IAID (4 octets) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // . IA_TA-options .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- //
- // sizeof (option-code + option-len + IaId) = 8
- // sizeof (option-code + option-len + IaId + T1) = 12
- // sizeof (option-code + option-len + IaId + T1 + T2) = 16
- //
- // The inner options still start with 2 bytes option-code and 2 bytes option-len.
- //
- if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
- T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8)));
- T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12)));
- //
- // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,
- // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes
- // the remainder of the message as though the server had not included the invalid IA_NA option.
- //
- if ((T1 > T2) && (T2 > 0)) {
- return EFI_DEVICE_ERROR;
- }
- IaInnerOpt = Option + 16;
- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 12);
- } else {
- T1 = 0;
- T2 = 0;
- IaInnerOpt = Option + 8;
- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4);
- }
- //
- // The format of the Status Code option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_STATUS_CODE | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | status-code | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // . .
- // . status-message .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- //
- // sizeof (option-code + option-len) = 4
- //
- StsCode = Dhcp6StsSuccess;
- Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
- if (Option != NULL) {
- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
- if (StsCode != Dhcp6StsSuccess) {
- return EFI_DEVICE_ERROR;
- }
- }
- //
- // Generate control block for the Ia.
- //
- Status = Dhcp6GenerateIaCb (
- Instance,
- IaInnerOpt,
- IaInnerLen,
- T1,
- T2
- );
- return Status;
- }
- /**
- Seek StatusCode Option in package. A Status Code option may appear in the
- options field of a DHCP message and/or in the options field of another option.
- See details in section 22.13, RFC3315.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to reply messages.
- @param[out] Option The pointer to status code option.
- @retval EFI_SUCCESS Seek status code option successfully.
- @retval EFI_DEVICE_ERROR An unexpected error.
- **/
- EFI_STATUS
- Dhcp6SeekStsOption (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet,
- OUT UINT8 **Option
- )
- {
- UINT8 *IaInnerOpt;
- UINT16 IaInnerLen;
- UINT16 StsCode;
- //
- // Seek StatusCode option directly in DHCP message body. That is, search in
- // non-encapsulated option fields.
- //
- *Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptStatusCode
- );
- if (*Option != NULL) {
- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
- if (StsCode != Dhcp6StsSuccess) {
- return EFI_DEVICE_ERROR;
- }
- }
- //
- // Seek in encapsulated options, IA_NA and IA_TA.
- //
- *Option = Dhcp6SeekIaOption (
- Packet->Dhcp6.Option,
- Packet->Length - sizeof (EFI_DHCP6_HEADER),
- &Instance->Config->IaDescriptor
- );
- if (*Option == NULL) {
- return EFI_SUCCESS;
- }
- //
- // The format of the IA_NA option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_IA_NA | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | IAID (4 octets) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | T1 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | T2 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // . IA_NA-options .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- // The format of the IA_TA option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_IA_TA | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | IAID (4 octets) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // . IA_TA-options .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- //
- // sizeof (option-code + option-len + IaId) = 8
- // sizeof (option-code + option-len + IaId + T1) = 12
- // sizeof (option-code + option-len + IaId + T1 + T2) = 16
- //
- // The inner options still start with 2 bytes option-code and 2 bytes option-len.
- //
- if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
- IaInnerOpt = *Option + 16;
- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12);
- } else {
- IaInnerOpt = *Option + 8;
- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4);
- }
- //
- // The format of the Status Code option is:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | OPTION_STATUS_CODE | option-len |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | status-code | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // . .
- // . status-message .
- // . .
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- //
- // sizeof (option-code + option-len) = 4
- //
- *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
- if (*Option != NULL) {
- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
- if (StsCode != Dhcp6StsSuccess) {
- return EFI_DEVICE_ERROR;
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Transmit Dhcp6 message by udpio.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to transmit message.
- @param[in] Elapsed The pointer to the elapsed time value to fill in.
- @retval EFI_SUCCESS Successfully transmitted the packet.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Failed to transmit the packet.
- **/
- EFI_STATUS
- Dhcp6TransmitPacket (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet,
- IN UINT16 *Elapsed
- )
- {
- EFI_STATUS Status;
- NET_BUF *Wrap;
- NET_FRAGMENT Frag;
- UDP_END_POINT EndPt;
- DHCP6_SERVICE *Service;
- Service = Instance->Service;
- //
- // Wrap it into a netbuf then send it.
- //
- Frag.Bulk = (UINT8 *)&Packet->Dhcp6.Header;
- Frag.Len = Packet->Length;
- //
- // Do not register free packet here, which will be handled in retry list.
- //
- Wrap = NetbufFromExt (&Frag, 1, 0, 0, Dhcp6DummyExtFree, NULL);
- if (Wrap == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Multicast the Dhcp6 message, unless get the unicast server address by option.
- //
- ZeroMem (&EndPt, sizeof (UDP_END_POINT));
- if (Instance->Unicast != NULL) {
- CopyMem (
- &EndPt.RemoteAddr,
- Instance->Unicast,
- sizeof (EFI_IPv6_ADDRESS)
- );
- } else {
- CopyMem (
- &EndPt.RemoteAddr,
- &mAllDhcpRelayAndServersAddress,
- sizeof (EFI_IPv6_ADDRESS)
- );
- }
- EndPt.RemotePort = DHCP6_PORT_SERVER;
- EndPt.LocalPort = DHCP6_PORT_CLIENT;
- //
- // Update the elapsed time value.
- //
- if (Elapsed != NULL) {
- SetElapsedTime (Elapsed, Instance);
- }
- //
- // Send out the message by the configured Udp6Io.
- //
- Status = UdpIoSendDatagram (
- Service->UdpIo,
- Wrap,
- &EndPt,
- NULL,
- Dhcp6OnTransmitted,
- NULL
- );
- if (EFI_ERROR (Status)) {
- NetbufFree (Wrap);
- return Status;
- }
- return EFI_SUCCESS;
- }
- /**
- Create the solicit message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @retval EFI_SUCCESS Created and sent the solicit message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Failed to send the solicit message.
- **/
- EFI_STATUS
- Dhcp6SendSolicitMsg (
- IN DHCP6_INSTANCE *Instance
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET_OPTION *UserOpt;
- EFI_DHCP6_DUID *ClientId;
- DHCP6_SERVICE *Service;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT32 UserLen;
- UINTN Index;
- UINT16 Length;
- Service = Instance->Service;
- ClientId = Service->ClientId;
- UserLen = 0;
- ASSERT (Service->ClientId != NULL);
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- //
- // Calculate the added length of customized option list.
- //
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
- }
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgSolicit;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for solicit message.
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendIaOption (
- Cursor,
- Instance->IaCb.Ia,
- Instance->IaCb.T1,
- Instance->IaCb.T2,
- Packet->Dhcp6.Header.MessageType
- );
- //
- // Append user-defined when configurate Dhcp6 service.
- //
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserOpt = Instance->Config->OptionList[Index];
- Cursor = Dhcp6AppendOption (
- Cursor,
- UserOpt->OpCode,
- UserOpt->OpLen,
- UserOpt->Data
- );
- }
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send solicit packet with the state transition from Dhcp6init to
- // Dhcp6selecting.
- //
- Instance->IaCb.Ia->State = Dhcp6Selecting;
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (
- Instance,
- Packet,
- Elapsed,
- Instance->Config->SolicitRetransmission
- );
- }
- /**
- Configure some parameter to initiate SolicitMsg.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @retval EFI_SUCCESS Created and sent the solicit message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Failed to send the solicit message.
- **/
- EFI_STATUS
- Dhcp6InitSolicitMsg (
- IN DHCP6_INSTANCE *Instance
- )
- {
- Instance->IaCb.T1 = 0;
- Instance->IaCb.T2 = 0;
- Instance->IaCb.Ia->IaAddressCount = 0;
- return Dhcp6SendSolicitMsg (Instance);
- }
- /**
- Create the request message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @retval EFI_SUCCESS Created and sent the request message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to send the request message.
- **/
- EFI_STATUS
- Dhcp6SendRequestMsg (
- IN DHCP6_INSTANCE *Instance
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET_OPTION *UserOpt;
- EFI_DHCP6_DUID *ClientId;
- EFI_DHCP6_DUID *ServerId;
- DHCP6_SERVICE *Service;
- UINT8 *Option;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT32 UserLen;
- UINTN Index;
- UINT16 Length;
- ASSERT (Instance->AdSelect != NULL);
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- ASSERT (Instance->Service != NULL);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- ASSERT (ClientId != NULL);
- //
- // Get the server Id from the selected advertisement message.
- //
- Option = Dhcp6SeekOption (
- Instance->AdSelect->Dhcp6.Option,
- Instance->AdSelect->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- return EFI_DEVICE_ERROR;
- }
- ServerId = (EFI_DHCP6_DUID *)(Option + 2);
- //
- // Calculate the added length of customized option list.
- //
- UserLen = 0;
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
- }
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgRequest;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for request message.
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptServerId),
- ServerId->Length,
- ServerId->Duid
- );
- Cursor = Dhcp6AppendIaOption (
- Cursor,
- Instance->IaCb.Ia,
- Instance->IaCb.T1,
- Instance->IaCb.T2,
- Packet->Dhcp6.Header.MessageType
- );
- //
- // Append user-defined when configurate Dhcp6 service.
- //
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserOpt = Instance->Config->OptionList[Index];
- Cursor = Dhcp6AppendOption (
- Cursor,
- UserOpt->OpCode,
- UserOpt->OpLen,
- UserOpt->Data
- );
- }
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send request packet with the state transition from Dhcp6selecting to
- // Dhcp6requesting.
- //
- Instance->IaCb.Ia->State = Dhcp6Requesting;
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
- }
- /**
- Create the decline message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] DecIa The pointer to the decline Ia.
- @retval EFI_SUCCESS Created and sent the decline message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to send the decline message.
- **/
- EFI_STATUS
- Dhcp6SendDeclineMsg (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_IA *DecIa
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET *LastReply;
- EFI_DHCP6_DUID *ClientId;
- EFI_DHCP6_DUID *ServerId;
- DHCP6_SERVICE *Service;
- UINT8 *Option;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT16 Length;
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- ASSERT (Instance->Service != NULL);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- LastReply = Instance->IaCb.Ia->ReplyPacket;
- ASSERT (ClientId != NULL);
- ASSERT (LastReply != NULL);
- //
- // Get the server Id from the last reply message.
- //
- Option = Dhcp6SeekOption (
- LastReply->Dhcp6.Option,
- LastReply->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- return EFI_DEVICE_ERROR;
- }
- //
- // EFI_DHCP6_DUID contains a length field of 2 bytes.
- //
- ServerId = (EFI_DHCP6_DUID *)(Option + 2);
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgDecline;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for rebind/renew message.
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptServerId),
- ServerId->Length,
- ServerId->Duid
- );
- Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send decline packet with the state transition from Dhcp6bound to
- // Dhcp6declining.
- //
- Instance->IaCb.Ia->State = Dhcp6Declining;
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
- }
- /**
- Create the release message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] RelIa The pointer to the release Ia.
- @retval EFI_SUCCESS Created and sent the release message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to send the release message.
- **/
- EFI_STATUS
- Dhcp6SendReleaseMsg (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_IA *RelIa
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET *LastReply;
- EFI_DHCP6_DUID *ClientId;
- EFI_DHCP6_DUID *ServerId;
- DHCP6_SERVICE *Service;
- UINT8 *Option;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT16 Length;
- ASSERT (Instance->Config);
- ASSERT (Instance->IaCb.Ia);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- LastReply = Instance->IaCb.Ia->ReplyPacket;
- ASSERT (ClientId);
- ASSERT (LastReply);
- //
- // Get the server Id from the last reply message.
- //
- Option = Dhcp6SeekOption (
- LastReply->Dhcp6.Option,
- LastReply->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- return EFI_DEVICE_ERROR;
- }
- ServerId = (EFI_DHCP6_DUID *)(Option + 2);
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgRelease;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for rebind/renew message
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- //
- // ServerId is extracted from packet, it's network order.
- //
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptServerId),
- ServerId->Length,
- ServerId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);
- //
- // Determine the size/length of packet
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send release packet with the state transition from Dhcp6bound to
- // Dhcp6releasing.
- //
- Instance->IaCb.Ia->State = Dhcp6Releasing;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
- }
- /**
- Create the renew/rebind message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] RebindRequest If TRUE, it is a Rebind type message.
- Otherwise, it is a Renew type message.
- @retval EFI_SUCCESS Created and sent the renew/rebind message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to send the renew/rebind message.
- **/
- EFI_STATUS
- Dhcp6SendRenewRebindMsg (
- IN DHCP6_INSTANCE *Instance,
- IN BOOLEAN RebindRequest
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET *LastReply;
- EFI_DHCP6_PACKET_OPTION *UserOpt;
- EFI_DHCP6_DUID *ClientId;
- EFI_DHCP6_DUID *ServerId;
- EFI_DHCP6_STATE State;
- EFI_DHCP6_EVENT Event;
- DHCP6_SERVICE *Service;
- UINT8 *Option;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT32 UserLen;
- UINTN Index;
- UINT16 Length;
- ASSERT (Instance->Config);
- ASSERT (Instance->IaCb.Ia);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- ASSERT (ClientId);
- //
- // Calculate the added length of customized option list.
- //
- UserLen = 0;
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
- }
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = RebindRequest ? Dhcp6MsgRebind : Dhcp6MsgRenew;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for rebind/renew message.
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendIaOption (
- Cursor,
- Instance->IaCb.Ia,
- Instance->IaCb.T1,
- Instance->IaCb.T2,
- Packet->Dhcp6.Header.MessageType
- );
- if (!RebindRequest) {
- //
- // Get the server Id from the last reply message and
- // insert it for rebind request.
- //
- LastReply = Instance->IaCb.Ia->ReplyPacket;
- ASSERT (LastReply);
- Option = Dhcp6SeekOption (
- LastReply->Dhcp6.Option,
- LastReply->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- FreePool (Packet);
- return EFI_DEVICE_ERROR;
- }
- ServerId = (EFI_DHCP6_DUID *)(Option + 2);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptServerId),
- ServerId->Length,
- ServerId->Duid
- );
- }
- //
- // Append user-defined when configurate Dhcp6 service.
- //
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserOpt = Instance->Config->OptionList[Index];
- Cursor = Dhcp6AppendOption (
- Cursor,
- UserOpt->OpCode,
- UserOpt->OpLen,
- UserOpt->Data
- );
- }
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- State = (RebindRequest) ? Dhcp6Rebinding : Dhcp6Renewing;
- Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;
- Status = Dhcp6CallbackUser (Instance, Event, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send renew/rebind packet with the state transition from Dhcp6bound to
- // Dhcp6renew/rebind.
- // And sync the lease time when send renew/rebind, in case that user send
- // renew/rebind actively.
- //
- Instance->IaCb.Ia->State = State;
- Instance->IaCb.LeaseTime = (RebindRequest) ? Instance->IaCb.T2 : Instance->IaCb.T1;
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
- }
- /**
- Start the information request process.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] SendClientId If TRUE, the client identifier option will be included in
- information request message. Otherwise, the client identifier
- option will not be included.
- @param[in] OptionRequest The pointer to the option request option.
- @param[in] OptionCount The number options in the OptionList.
- @param[in] OptionList The array pointers to the appended options.
- @param[in] Retransmission The pointer to the retransmission control.
- @param[in] TimeoutEvent The event of timeout.
- @param[in] ReplyCallback The callback function when the reply was received.
- @param[in] CallbackContext The pointer to the parameter passed to the callback.
- @retval EFI_SUCCESS Start the info-request process successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_NO_MAPPING No source address is available for use.
- @retval Others Failed to start the info-request process.
- **/
- EFI_STATUS
- Dhcp6StartInfoRequest (
- IN DHCP6_INSTANCE *Instance,
- IN BOOLEAN SendClientId,
- IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
- IN UINT32 OptionCount,
- IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL,
- IN EFI_DHCP6_RETRANSMISSION *Retransmission,
- IN EFI_EVENT TimeoutEvent OPTIONAL,
- IN EFI_DHCP6_INFO_CALLBACK ReplyCallback,
- IN VOID *CallbackContext OPTIONAL
- )
- {
- EFI_STATUS Status;
- DHCP6_INF_CB *InfCb;
- DHCP6_SERVICE *Service;
- EFI_TPL OldTpl;
- Service = Instance->Service;
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- Instance->UdpSts = EFI_ALREADY_STARTED;
- //
- // Create and initialize the control block for the info-request.
- //
- InfCb = AllocateZeroPool (sizeof (DHCP6_INF_CB));
- if (InfCb == NULL) {
- gBS->RestoreTPL (OldTpl);
- return EFI_OUT_OF_RESOURCES;
- }
- InfCb->ReplyCallback = ReplyCallback;
- InfCb->CallbackContext = CallbackContext;
- InfCb->TimeoutEvent = TimeoutEvent;
- InsertTailList (&Instance->InfList, &InfCb->Link);
- //
- // Send the info-request message to start exchange process.
- //
- Status = Dhcp6SendInfoRequestMsg (
- Instance,
- InfCb,
- SendClientId,
- OptionRequest,
- OptionCount,
- OptionList,
- Retransmission
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Register receive callback for the stateless exchange process.
- //
- Status = UdpIoRecvDatagram (
- Service->UdpIo,
- Dhcp6ReceivePacket,
- Service,
- 0
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- goto ON_ERROR;
- }
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- ON_ERROR:
- gBS->RestoreTPL (OldTpl);
- RemoveEntryList (&InfCb->Link);
- FreePool (InfCb);
- return Status;
- }
- /**
- Create the information request message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] InfCb The pointer to the information request control block.
- @param[in] SendClientId If TRUE, the client identifier option will be included in
- information request message. Otherwise, the client identifier
- option will not be included.
- @param[in] OptionRequest The pointer to the option request option.
- @param[in] OptionCount The number options in the OptionList.
- @param[in] OptionList The array pointers to the appended options.
- @param[in] Retransmission The pointer to the retransmission control.
- @retval EFI_SUCCESS Created and sent the info-request message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Failed to send the info-request message.
- **/
- EFI_STATUS
- Dhcp6SendInfoRequestMsg (
- IN DHCP6_INSTANCE *Instance,
- IN DHCP6_INF_CB *InfCb,
- IN BOOLEAN SendClientId,
- IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
- IN UINT32 OptionCount,
- IN EFI_DHCP6_PACKET_OPTION *OptionList[],
- IN EFI_DHCP6_RETRANSMISSION *Retransmission
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET_OPTION *UserOpt;
- EFI_DHCP6_DUID *ClientId;
- DHCP6_SERVICE *Service;
- UINT8 *Cursor;
- UINT16 *Elapsed;
- UINT32 UserLen;
- UINTN Index;
- UINT16 Length;
- ASSERT (OptionRequest);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- UserLen = NTOHS (OptionRequest->OpLen) + 4;
- ASSERT (ClientId);
- //
- // Calculate the added length of customized option list.
- //
- for (Index = 0; Index < OptionCount; Index++) {
- UserLen += (NTOHS (OptionList[Index]->OpLen) + 4);
- }
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgInfoRequest;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- InfCb->Xid = Packet->Dhcp6.Header.TransactionId;
- //
- // Assembly Dhcp6 options for info-request message.
- //
- Cursor = Packet->Dhcp6.Option;
- if (SendClientId) {
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- }
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendOption (
- Cursor,
- OptionRequest->OpCode,
- OptionRequest->OpLen,
- OptionRequest->Data
- );
- //
- // Append user-defined when configurate Dhcp6 service.
- //
- for (Index = 0; Index < OptionCount; Index++) {
- UserOpt = OptionList[Index];
- Cursor = Dhcp6AppendOption (
- Cursor,
- UserOpt->OpCode,
- UserOpt->OpLen,
- UserOpt->Data
- );
- }
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- //
- // Send info-request packet with no state.
- //
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);
- }
- /**
- Create the Confirm message and send it.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @retval EFI_SUCCESS Created and sent the confirm message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to send the confirm message.
- **/
- EFI_STATUS
- Dhcp6SendConfirmMsg (
- IN DHCP6_INSTANCE *Instance
- )
- {
- UINT8 *Cursor;
- UINTN Index;
- UINT16 Length;
- UINT32 UserLen;
- EFI_STATUS Status;
- DHCP6_SERVICE *Service;
- EFI_DHCP6_DUID *ClientId;
- EFI_DHCP6_PACKET *Packet;
- EFI_DHCP6_PACKET_OPTION *UserOpt;
- UINT16 *Elapsed;
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- ASSERT (Instance->Service != NULL);
- Service = Instance->Service;
- ClientId = Service->ClientId;
- ASSERT (ClientId != NULL);
- //
- // Calculate the added length of customized option list.
- //
- UserLen = 0;
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
- }
- //
- // Create the Dhcp6 packet and initialize common fields.
- //
- Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
- if (Packet == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
- Packet->Length = sizeof (EFI_DHCP6_HEADER);
- Packet->Dhcp6.Header.MessageType = Dhcp6MsgConfirm;
- Packet->Dhcp6.Header.TransactionId = Service->Xid++;
- //
- // Assembly Dhcp6 options for solicit message.
- //
- Cursor = Packet->Dhcp6.Option;
- Length = HTONS (ClientId->Length);
- Cursor = Dhcp6AppendOption (
- Cursor,
- HTONS (Dhcp6OptClientId),
- Length,
- ClientId->Duid
- );
- Cursor = Dhcp6AppendETOption (
- Cursor,
- Instance,
- &Elapsed
- );
- Cursor = Dhcp6AppendIaOption (
- Cursor,
- Instance->IaCb.Ia,
- Instance->IaCb.T1,
- Instance->IaCb.T2,
- Packet->Dhcp6.Header.MessageType
- );
- //
- // Append user-defined when configurate Dhcp6 service.
- //
- for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
- UserOpt = Instance->Config->OptionList[Index];
- Cursor = Dhcp6AppendOption (
- Cursor,
- UserOpt->OpCode,
- UserOpt->OpLen,
- UserOpt->Data
- );
- }
- //
- // Determine the size/length of packet.
- //
- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
- ASSERT (Packet->Size > Packet->Length + 8);
- //
- // Callback to user with the packet to be sent and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Send confirm packet with the state transition from Dhcp6Bound to
- // Dhcp6Confirming.
- //
- Instance->IaCb.Ia->State = Dhcp6Confirming;
- //
- // Clear initial time for current transaction.
- //
- Instance->StartTime = 0;
- Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
- if (EFI_ERROR (Status)) {
- FreePool (Packet);
- return Status;
- }
- //
- // Enqueue the sent packet for the retransmission in case reply timeout.
- //
- return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
- }
- /**
- Handle with the Dhcp6 reply message.
- @param[in] Instance The pointer to Dhcp6 instance.
- @param[in] Packet The pointer to the Dhcp6 reply message.
- @retval EFI_SUCCESS Processed the reply message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to process the reply message.
- **/
- EFI_STATUS
- Dhcp6HandleReplyMsg (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet
- )
- {
- EFI_STATUS Status;
- UINT8 *Option;
- UINT16 StsCode;
- ASSERT (Instance->Config != NULL);
- ASSERT (Instance->IaCb.Ia != NULL);
- ASSERT (Packet != NULL);
- Status = EFI_SUCCESS;
- if (Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply) {
- return EFI_DEVICE_ERROR;
- }
- //
- // If the client subsequently receives a valid reply message that includes a
- // rapid commit option since send a solicit with rapid commit option before,
- // preocess the reply message and discard any reply messages received in
- // response to the request message.
- // See details in the section-17.1.4 of rfc-3315.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptRapidCommit
- );
- if (((Option != NULL) && !Instance->Config->RapidCommit) || ((Option == NULL) && Instance->Config->RapidCommit)) {
- return EFI_DEVICE_ERROR;
- }
- //
- // As to a valid reply packet in response to a request/renew/rebind packet,
- // ignore the packet if not contains the Ia option
- //
- if ((Instance->IaCb.Ia->State == Dhcp6Requesting) ||
- (Instance->IaCb.Ia->State == Dhcp6Renewing) ||
- (Instance->IaCb.Ia->State == Dhcp6Rebinding)
- )
- {
- Option = Dhcp6SeekIaOption (
- Packet->Dhcp6.Option,
- Packet->Length,
- &Instance->Config->IaDescriptor
- );
- if (Option == NULL) {
- return EFI_SUCCESS;
- }
- }
- //
- // Callback to user with the received packet and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6RcvdReply, &Packet);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // When receive a valid reply packet in response to a decline/release packet,
- // the client considers the decline/release event completed regardless of the
- // status code.
- //
- if ((Instance->IaCb.Ia->State == Dhcp6Declining) || (Instance->IaCb.Ia->State == Dhcp6Releasing)) {
- if (Instance->IaCb.Ia->IaAddressCount != 0) {
- Instance->IaCb.Ia->State = Dhcp6Bound;
- } else {
- ASSERT (Instance->IaCb.Ia->ReplyPacket);
- FreePool (Instance->IaCb.Ia->ReplyPacket);
- Instance->IaCb.Ia->ReplyPacket = NULL;
- Instance->IaCb.Ia->State = Dhcp6Init;
- }
- //
- // For sync, set the success flag out of polling in decline/release.
- //
- Instance->UdpSts = EFI_SUCCESS;
- //
- // For async, signal the Ia event to inform Ia information update.
- //
- if (Instance->Config->IaInfoEvent != NULL) {
- gBS->SignalEvent (Instance->Config->IaInfoEvent);
- }
- //
- // Reset start time for next exchange.
- //
- Instance->StartTime = 0;
- Status = EFI_SUCCESS;
- goto ON_EXIT;
- }
- //
- // Upon the receipt of a valid reply packet in response to a solicit, request,
- // confirm, renew and rebind, the behavior depends on the status code option.
- // See the details in the section-18.1.8 of rfc-3315.
- //
- Option = NULL;
- Status = Dhcp6SeekStsOption (
- Instance,
- Packet,
- &Option
- );
- if (!EFI_ERROR (Status)) {
- //
- // No status code or no error status code means succeed to reply.
- //
- Status = Dhcp6UpdateIaInfo (Instance, Packet);
- if (!EFI_ERROR (Status)) {
- //
- // Reset start time for next exchange.
- //
- Instance->StartTime = 0;
- //
- // Set bound state and store the reply packet.
- //
- if (Instance->IaCb.Ia->ReplyPacket != NULL) {
- FreePool (Instance->IaCb.Ia->ReplyPacket);
- }
- Instance->IaCb.Ia->ReplyPacket = AllocateZeroPool (Packet->Size);
- if (Instance->IaCb.Ia->ReplyPacket == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
- CopyMem (Instance->IaCb.Ia->ReplyPacket, Packet, Packet->Size);
- Instance->IaCb.Ia->State = Dhcp6Bound;
- //
- // For sync, set the success flag out of polling in start/renewrebind.
- //
- Instance->UdpSts = EFI_SUCCESS;
- //
- // Maybe this is a new round DHCP process due to some reason, such as NotOnLink
- // ReplyMsg for ConfirmMsg should trigger new round to acquire new address. In that
- // case, clear old address.ValidLifetime and append to new address. Therefore, DHCP
- // consumers can be notified to flush old address.
- //
- Dhcp6AppendCacheIa (Instance);
- //
- // For async, signal the Ia event to inform Ia information update.
- //
- if (Instance->Config->IaInfoEvent != NULL) {
- gBS->SignalEvent (Instance->Config->IaInfoEvent);
- }
- } else if (Status == EFI_NOT_FOUND) {
- //
- // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message,
- // the client sends a Renew or Rebind if the IA is not in the Reply message.
- // Return EFI_SUCCESS so we can continue to restart the Renew/Rebind process.
- //
- return EFI_SUCCESS;
- }
- goto ON_EXIT;
- } else if (Option != NULL) {
- //
- // Any error status code option is found.
- //
- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
- switch (StsCode) {
- case Dhcp6StsUnspecFail:
- //
- // It indicates the server is unable to process the message due to an
- // unspecified failure condition, so just retry if possible.
- //
- break;
- case Dhcp6StsUseMulticast:
- //
- // It indicates the server receives a message via unicast from a client
- // to which the server has not sent a unicast option, so retry it by
- // multi-cast address.
- //
- if (Instance->Unicast != NULL) {
- FreePool (Instance->Unicast);
- Instance->Unicast = NULL;
- }
- break;
- case Dhcp6StsNotOnLink:
- if (Instance->IaCb.Ia->State == Dhcp6Confirming) {
- //
- // Before initiate new round DHCP, cache the current IA.
- //
- Status = Dhcp6CacheIa (Instance);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Restart S.A.R.R process to acquire new address.
- //
- Status = Dhcp6InitSolicitMsg (Instance);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- break;
- case Dhcp6StsNoBinding:
- if ((Instance->IaCb.Ia->State == Dhcp6Renewing) || (Instance->IaCb.Ia->State == Dhcp6Rebinding)) {
- //
- // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client
- // sends a Request message if the IA contained a Status Code option with the NoBinding status.
- //
- Status = Dhcp6SendRequestMsg (Instance);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- break;
- default:
- //
- // The other status code, just restart solicitation.
- //
- break;
- }
- }
- return EFI_SUCCESS;
- ON_EXIT:
- if (!EFI_ERROR (Status)) {
- Status = Dhcp6DequeueRetry (
- Instance,
- Packet->Dhcp6.Header.TransactionId,
- FALSE
- );
- }
- return Status;
- }
- /**
- Select the appointed Dhcp6 advertisement message.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] AdSelect The pointer to the selected Dhcp6 advertisement message.
- @retval EFI_SUCCESS Selected the right advertisement message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Failed to select the advertise message.
- **/
- EFI_STATUS
- Dhcp6SelectAdvertiseMsg (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *AdSelect
- )
- {
- EFI_STATUS Status;
- UINT8 *Option;
- ASSERT (AdSelect != NULL);
- //
- // Callback to user with the selected advertisement packet, and the user
- // might overwrite it.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6SelectAdvertise, &AdSelect);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Instance->AdSelect = AdSelect;
- //
- // Dequeue the sent packet for the retransmission since advertisement selected.
- //
- Status = Dhcp6DequeueRetry (
- Instance,
- AdSelect->Dhcp6.Header.TransactionId,
- FALSE
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Check whether there is server unicast option in the selected advertise
- // packet, and update it.
- //
- Option = Dhcp6SeekOption (
- AdSelect->Dhcp6.Option,
- AdSelect->Length - 4,
- Dhcp6OptServerUnicast
- );
- if (Option != NULL) {
- Instance->Unicast = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
- if (Instance->Unicast == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS));
- }
- //
- // Update the information of the Ia by the selected advertisement message.
- //
- Status = Dhcp6UpdateIaInfo (Instance, AdSelect);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Send the request message to continue the S.A.R.R. process.
- //
- return Dhcp6SendRequestMsg (Instance);
- }
- /**
- Handle with the Dhcp6 advertisement message.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to the Dhcp6 advertisement message.
- @retval EFI_SUCCESS Processed the advertisement message successfully.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected error.
- @retval Others Failed to process the advertise message.
- **/
- EFI_STATUS
- Dhcp6HandleAdvertiseMsg (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet
- )
- {
- EFI_STATUS Status;
- UINT8 *Option;
- BOOLEAN Timeout;
- ASSERT (Instance->Config);
- ASSERT (Instance->IaCb.Ia);
- Timeout = FALSE;
- //
- // If the client does receives a valid reply message that includes a rapid
- // commit option since a solicit with rapid commit option sent before, select
- // this reply message. Or else, process the advertise messages as normal.
- // See details in the section-17.1.4 of rfc-3315.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptRapidCommit
- );
- if ((Option != NULL) && Instance->Config->RapidCommit && (Packet->Dhcp6.Header.MessageType == Dhcp6MsgReply)) {
- return Dhcp6HandleReplyMsg (Instance, Packet);
- }
- if (Packet->Dhcp6.Header.MessageType != Dhcp6MsgAdvertise) {
- return EFI_DEVICE_ERROR;
- }
- //
- // Client must ignore any advertise message that includes a status code option
- // containing the value noaddrsavail, with the exception that the client may
- // display the associated status message to the user.
- // See the details in the section-17.1.3 of rfc-3315.
- //
- Status = Dhcp6SeekStsOption (
- Instance,
- Packet,
- &Option
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- //
- // Callback to user with the received packet and check the user's feedback.
- //
- Status = Dhcp6CallbackUser (Instance, Dhcp6RcvdAdvertise, &Packet);
- if (!EFI_ERROR (Status)) {
- //
- // Success means user choose the current advertisement packet.
- //
- if (Instance->AdSelect != NULL) {
- FreePool (Instance->AdSelect);
- }
- //
- // Store the selected advertisement packet and set a flag.
- //
- Instance->AdSelect = AllocateZeroPool (Packet->Size);
- if (Instance->AdSelect == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (Instance->AdSelect, Packet, Packet->Size);
- Instance->AdPref = 0xff;
- } else if (Status == EFI_NOT_READY) {
- //
- // Not_ready means user wants to continue to receive more advertise packets.
- //
- if ((Instance->AdPref == 0xff) && (Instance->AdSelect == NULL)) {
- //
- // It's a tricky point. The timer routine set adpref as 0xff if the first
- // rt timeout and no advertisement received, which means any advertisement
- // received will be selected after the first rt.
- //
- Timeout = TRUE;
- }
- //
- // Check whether the current packet has a 255 preference option or not.
- // Take non-preference option as 0 value.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptPreference
- );
- if ((Instance->AdSelect == NULL) || ((Option != NULL) && (*(Option + 4) > Instance->AdPref))) {
- //
- // No advertisements received before or preference is more than other
- // advertisements received before. Then store the new packet and the
- // preference value.
- //
- if (Instance->AdSelect != NULL) {
- FreePool (Instance->AdSelect);
- }
- Instance->AdSelect = AllocateZeroPool (Packet->Size);
- if (Instance->AdSelect == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (Instance->AdSelect, Packet, Packet->Size);
- if (Option != NULL) {
- Instance->AdPref = *(Option + 4);
- }
- } else {
- //
- // Non-preference and other advertisements received before or current
- // preference is less than other advertisements received before.
- // Leave the packet alone.
- }
- } else {
- //
- // Other error status means termination.
- //
- return Status;
- }
- //
- // Client must collect advertise messages as more as possible until the first
- // RT has elapsed, or get a highest preference 255 advertise.
- // See details in the section-17.1.2 of rfc-3315.
- //
- if ((Instance->AdPref == 0xff) || Timeout) {
- Status = Dhcp6SelectAdvertiseMsg (Instance, Instance->AdSelect);
- }
- return Status;
- }
- /**
- The Dhcp6 stateful exchange process routine.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to the received Dhcp6 message.
- **/
- VOID
- Dhcp6HandleStateful (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet
- )
- {
- EFI_STATUS Status;
- EFI_DHCP6_DUID *ClientId;
- DHCP6_SERVICE *Service;
- UINT8 *Option;
- Service = Instance->Service;
- ClientId = Service->ClientId;
- Status = EFI_SUCCESS;
- if (Instance->Config == NULL) {
- goto ON_CONTINUE;
- }
- ASSERT (ClientId);
- ASSERT (Instance->Config);
- ASSERT (Instance->IaCb.Ia);
- //
- // Discard the packet if not advertisement or reply packet.
- //
- if ((Packet->Dhcp6.Header.MessageType != Dhcp6MsgAdvertise) && (Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply)) {
- goto ON_CONTINUE;
- }
- //
- // Check whether include client Id or not.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptClientId
- );
- if ((Option == NULL) || (CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0)) {
- goto ON_CONTINUE;
- }
- //
- // Check whether include server Id or not.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- goto ON_CONTINUE;
- }
- switch (Instance->IaCb.Ia->State) {
- case Dhcp6Selecting:
- //
- // Handle the advertisement message when in the Dhcp6Selecting state.
- // Do not need check return status, if failed, just continue to the next.
- //
- Dhcp6HandleAdvertiseMsg (Instance, Packet);
- break;
- case Dhcp6Requesting:
- case Dhcp6Confirming:
- case Dhcp6Renewing:
- case Dhcp6Rebinding:
- case Dhcp6Releasing:
- case Dhcp6Declining:
- //
- // Handle the reply message when in the Dhcp6Requesting, Dhcp6Renewing
- // Dhcp6Rebinding, Dhcp6Releasing and Dhcp6Declining state.
- // If failed here, it should reset the current session.
- //
- Status = Dhcp6HandleReplyMsg (Instance, Packet);
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- break;
- default:
- //
- // Other state has not supported yet.
- //
- break;
- }
- ON_CONTINUE:
- //
- // Continue to receive the following Dhcp6 message.
- //
- Status = UdpIoRecvDatagram (
- Service->UdpIo,
- Dhcp6ReceivePacket,
- Service,
- 0
- );
- ON_EXIT:
- if (EFI_ERROR (Status)) {
- Dhcp6CleanupSession (Instance, Status);
- }
- }
- /**
- The Dhcp6 stateless exchange process routine.
- @param[in] Instance The pointer to the Dhcp6 instance.
- @param[in] Packet The pointer to the received Dhcp6 message.
- **/
- VOID
- Dhcp6HandleStateless (
- IN DHCP6_INSTANCE *Instance,
- IN EFI_DHCP6_PACKET *Packet
- )
- {
- EFI_STATUS Status;
- DHCP6_SERVICE *Service;
- DHCP6_INF_CB *InfCb;
- UINT8 *Option;
- BOOLEAN IsMatched;
- Service = Instance->Service;
- Status = EFI_SUCCESS;
- IsMatched = FALSE;
- InfCb = NULL;
- if (Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply) {
- goto ON_EXIT;
- }
- //
- // Check whether it's a desired Info-request message by Xid.
- //
- while (!IsListEmpty (&Instance->InfList)) {
- InfCb = NET_LIST_HEAD (&Instance->InfList, DHCP6_INF_CB, Link);
- if (InfCb->Xid == Packet->Dhcp6.Header.TransactionId) {
- IsMatched = TRUE;
- break;
- }
- }
- if (!IsMatched) {
- goto ON_EXIT;
- }
- //
- // Check whether include server Id or not.
- //
- Option = Dhcp6SeekOption (
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptServerId
- );
- if (Option == NULL) {
- goto ON_EXIT;
- }
- //
- // Callback to user with the received packet and check the user's feedback.
- //
- Status = InfCb->ReplyCallback (
- &Instance->Dhcp6,
- InfCb->CallbackContext,
- Packet
- );
- if (Status == EFI_NOT_READY) {
- //
- // Success or aborted will both stop this info-request exchange process,
- // but not ready means user wants to continue to receive reply.
- //
- goto ON_EXIT;
- }
- //
- // Dequeue the sent packet from the txlist if the xid matched, and ignore
- // if no xid matched.
- //
- Dhcp6DequeueRetry (
- Instance,
- Packet->Dhcp6.Header.TransactionId,
- FALSE
- );
- //
- // For sync, set the status out of polling for info-request.
- //
- Instance->UdpSts = Status;
- ON_EXIT:
- Status = UdpIoRecvDatagram (
- Service->UdpIo,
- Dhcp6ReceivePacket,
- Service,
- 0
- );
- if (EFI_ERROR (Status)) {
- Dhcp6CleanupRetry (Instance, DHCP6_PACKET_STATELESS);
- }
- }
- /**
- The receive callback function for Dhcp6 exchange process.
- @param[in] Udp6Wrap The pointer to the received net buffer.
- @param[in] EndPoint The pointer to the udp end point.
- @param[in] IoStatus The return status from udp io.
- @param[in] Context The opaque parameter to the function.
- **/
- VOID
- EFIAPI
- Dhcp6ReceivePacket (
- IN NET_BUF *Udp6Wrap,
- IN UDP_END_POINT *EndPoint,
- IN EFI_STATUS IoStatus,
- IN VOID *Context
- )
- {
- EFI_DHCP6_HEADER *Head;
- EFI_DHCP6_PACKET *Packet;
- DHCP6_SERVICE *Service;
- DHCP6_INSTANCE *Instance;
- DHCP6_TX_CB *TxCb;
- UINT32 Size;
- BOOLEAN IsDispatched;
- BOOLEAN IsStateless;
- LIST_ENTRY *Entry1;
- LIST_ENTRY *Next1;
- LIST_ENTRY *Entry2;
- LIST_ENTRY *Next2;
- EFI_STATUS Status;
- ASSERT (Udp6Wrap != NULL);
- ASSERT (Context != NULL);
- Service = (DHCP6_SERVICE *)Context;
- Instance = NULL;
- Packet = NULL;
- IsDispatched = FALSE;
- IsStateless = FALSE;
- if (EFI_ERROR (IoStatus)) {
- return;
- }
- if (Udp6Wrap->TotalSize < sizeof (EFI_DHCP6_HEADER)) {
- goto ON_CONTINUE;
- }
- //
- // Copy the net buffer received from upd6 to a Dhcp6 packet.
- //
- Size = sizeof (EFI_DHCP6_PACKET) + Udp6Wrap->TotalSize;
- Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (Size);
- if (Packet == NULL) {
- goto ON_CONTINUE;
- }
- Packet->Size = Size;
- Head = &Packet->Dhcp6.Header;
- Packet->Length = NetbufCopy (Udp6Wrap, 0, Udp6Wrap->TotalSize, (UINT8 *)Head);
- if (Packet->Length == 0) {
- goto ON_CONTINUE;
- }
- //
- // Dispatch packet to right instance by transaction id.
- //
- NET_LIST_FOR_EACH_SAFE (Entry1, Next1, &Service->Child) {
- Instance = NET_LIST_USER_STRUCT (Entry1, DHCP6_INSTANCE, Link);
- NET_LIST_FOR_EACH_SAFE (Entry2, Next2, &Instance->TxList) {
- TxCb = NET_LIST_USER_STRUCT (Entry2, DHCP6_TX_CB, Link);
- if (Packet->Dhcp6.Header.TransactionId == TxCb->Xid) {
- //
- // Find the corresponding packet in tx list, and check it whether belongs
- // to stateful exchange process.
- //
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) {
- IsStateless = TRUE;
- }
- IsDispatched = TRUE;
- break;
- }
- }
- if (IsDispatched) {
- break;
- }
- }
- //
- // Skip this packet if not dispatched to any instance.
- //
- if (!IsDispatched) {
- goto ON_CONTINUE;
- }
- //
- // Dispatch the received packet ot the right instance.
- //
- if (IsStateless) {
- Dhcp6HandleStateless (Instance, Packet);
- } else {
- Dhcp6HandleStateful (Instance, Packet);
- }
- ON_CONTINUE:
- if (!IsDispatched) {
- Status = UdpIoRecvDatagram (
- Service->UdpIo,
- Dhcp6ReceivePacket,
- Service,
- 0
- );
- if (EFI_ERROR (Status)) {
- NET_LIST_FOR_EACH_SAFE (Entry1, Next1, &Service->Child) {
- Instance = NET_LIST_USER_STRUCT (Entry1, DHCP6_INSTANCE, Link);
- Dhcp6CleanupRetry (Instance, DHCP6_PACKET_ALL);
- }
- }
- }
- NetbufFree (Udp6Wrap);
- if (Packet != NULL) {
- FreePool (Packet);
- }
- }
- /**
- Detect Link movement for specified network device.
- This routine will try to invoke Snp->GetStatus() to get the media status.
- If media present status switches from unpresent to present, a link movement
- is detected. Note that the underlying UNDI driver may not support reporting
- media status from GET_STATUS command. If that, fail to detect link movement.
- @param[in] Instance The pointer to DHCP6_INSTANCE.
- @retval TRUE A link movement is detected.
- @retval FALSE A link movement is not detected.
- **/
- BOOLEAN
- Dhcp6LinkMovDetect (
- IN DHCP6_INSTANCE *Instance
- )
- {
- UINT32 InterruptStatus;
- BOOLEAN MediaPresent;
- EFI_STATUS Status;
- EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
- ASSERT (Instance != NULL);
- Snp = Instance->Service->Snp;
- MediaPresent = Instance->MediaPresent;
- //
- // Check whether SNP support media detection
- //
- if (!Snp->Mode->MediaPresentSupported) {
- return FALSE;
- }
- //
- // Invoke Snp->GetStatus() to refresh MediaPresent field in SNP mode data
- //
- Status = Snp->GetStatus (Snp, &InterruptStatus, NULL);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- Instance->MediaPresent = Snp->Mode->MediaPresent;
- //
- // Media transimit Unpresent to Present means new link movement is detected.
- //
- if (!MediaPresent && Instance->MediaPresent) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- The timer routine of the Dhcp6 instance for each second.
- @param[in] Event The timer event.
- @param[in] Context The opaque parameter to the function.
- **/
- VOID
- EFIAPI
- Dhcp6OnTimerTick (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *NextEntry;
- DHCP6_INSTANCE *Instance;
- DHCP6_TX_CB *TxCb;
- DHCP6_IA_CB *IaCb;
- UINT32 LossTime;
- EFI_STATUS Status;
- ASSERT (Context != NULL);
- Instance = (DHCP6_INSTANCE *)Context;
- //
- // 1. Loop the tx list, count live time of every tx packet to check whether
- // need re-transmit or not.
- //
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) {
- TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link);
- TxCb->TickTime++;
- if (TxCb->TickTime > TxCb->RetryExp) {
- //
- // Handle the first rt in the transmission of solicit specially.
- //
- if (((TxCb->RetryCnt == 0) || TxCb->SolicitRetry) && (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit)) {
- if (Instance->AdSelect == NULL) {
- //
- // Set adpref as 0xff here to indicate select any advertisement
- // afterwards.
- //
- Instance->AdPref = 0xff;
- } else {
- //
- // Select the advertisement received before.
- //
- Status = Dhcp6SelectAdvertiseMsg (Instance, Instance->AdSelect);
- if (Status == EFI_ABORTED) {
- goto ON_CLOSE;
- } else if (EFI_ERROR (Status)) {
- TxCb->RetryCnt++;
- }
- return;
- }
- }
- //
- // Increase the retry count for the packet and add up the total loss time.
- //
- TxCb->RetryCnt++;
- TxCb->RetryLos += TxCb->RetryExp;
- //
- // Check whether overflow the max retry count limit for this packet
- //
- if ((TxCb->RetryCtl.Mrc != 0) && (TxCb->RetryCtl.Mrc < TxCb->RetryCnt)) {
- Status = EFI_NO_RESPONSE;
- goto ON_CLOSE;
- }
- //
- // Check whether overflow the max retry duration for this packet
- //
- if ((TxCb->RetryCtl.Mrd != 0) && (TxCb->RetryCtl.Mrd <= TxCb->RetryLos)) {
- Status = EFI_NO_RESPONSE;
- goto ON_CLOSE;
- }
- //
- // Re-calculate retry expire timeout for the next time.
- //
- // Firstly, Check the new calculated time whether overflow the max retry
- // expire time.
- //
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryExp,
- FALSE,
- TRUE
- );
- if ((TxCb->RetryCtl.Mrt != 0) && (TxCb->RetryCtl.Mrt < TxCb->RetryExp)) {
- TxCb->RetryExp = Dhcp6CalculateExpireTime (
- TxCb->RetryCtl.Mrt,
- TRUE,
- TRUE
- );
- }
- //
- // Secondly, Check the new calculated time whether overflow the max retry
- // duration time.
- //
- LossTime = TxCb->RetryLos + TxCb->RetryExp;
- if ((TxCb->RetryCtl.Mrd != 0) && (TxCb->RetryCtl.Mrd < LossTime)) {
- TxCb->RetryExp = TxCb->RetryCtl.Mrd - TxCb->RetryLos;
- }
- //
- // Reset the tick time for the next retransmission
- //
- TxCb->TickTime = 0;
- //
- // Retransmit the last sent packet again.
- //
- Dhcp6TransmitPacket (Instance, TxCb->TxPacket, TxCb->Elapsed);
- TxCb->SolicitRetry = FALSE;
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit) {
- TxCb->SolicitRetry = TRUE;
- }
- }
- }
- //
- // 2. Check the configured Ia, count lease time of every valid Ia to check
- // whether need to renew or rebind this Ia.
- //
- IaCb = &Instance->IaCb;
- if ((Instance->Config == NULL) || (IaCb->Ia == NULL)) {
- return;
- }
- if ((IaCb->Ia->State == Dhcp6Bound) || (IaCb->Ia->State == Dhcp6Renewing) || (IaCb->Ia->State == Dhcp6Rebinding)) {
- IaCb->LeaseTime++;
- if ((IaCb->LeaseTime > IaCb->T2) && (IaCb->Ia->State == Dhcp6Bound)) {
- //
- // Exceed t2, send rebind packet to extend the Ia lease.
- //
- Dhcp6SendRenewRebindMsg (Instance, TRUE);
- } else if ((IaCb->LeaseTime > IaCb->T1) && (IaCb->Ia->State == Dhcp6Bound)) {
- //
- // Exceed t1, send renew packet to extend the Ia lease.
- //
- Dhcp6SendRenewRebindMsg (Instance, FALSE);
- }
- }
- //
- // 3. In any situation when a client may have moved to a new link, the
- // client MUST initiate a Confirm/Reply message exchange.
- //
- if (Dhcp6LinkMovDetect (Instance) && (IaCb->Ia->State == Dhcp6Bound)) {
- Dhcp6SendConfirmMsg (Instance);
- }
- return;
- ON_CLOSE:
- if (Dhcp6IsValidTxCb (Instance, TxCb) &&
- (TxCb->TxPacket != NULL) &&
- ((TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) ||
- (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew) ||
- (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm))
- )
- {
- //
- // The failure of renew/Confirm will still switch to the bound state.
- //
- if ((TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew) ||
- (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm))
- {
- ASSERT (Instance->IaCb.Ia);
- Instance->IaCb.Ia->State = Dhcp6Bound;
- }
- //
- // The failure of info-request will return no response.
- //
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) {
- Instance->UdpSts = EFI_NO_RESPONSE;
- }
- Dhcp6DequeueRetry (
- Instance,
- TxCb->Xid,
- TRUE
- );
- } else {
- //
- // The failure of the others will terminate current state machine if timeout.
- //
- Dhcp6CleanupSession (Instance, Status);
- }
- }
|