123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168 |
- /** @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 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.
- //
- 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 reponse 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 alread 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 commone 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 commone 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 commone 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 commone 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 commone 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 commone 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 infomation 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 triger 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 infomation 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 optioin 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);
- }
- }
|