107-cifs.patch 715 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977
  1. --- a/Documentation/Configure.help
  2. +++ b/Documentation/Configure.help
  3. @@ -18007,6 +18007,34 @@ CONFIG_UNIXWARE_DISKLABEL
  4. If you don't know what all this is about, say N.
  5. +CIFS (Common Internet File System) support
  6. +CONFIG_CIFS
  7. + This is the client VFS module for the Common Internet File System
  8. + (CIFS) protocol which is the successor to the Server Message Block
  9. + (SMB) protocol, the native file sharing mechanism for most early
  10. + PC operating systems. CIFS is fully supported by current network
  11. + file servers such as Windows 2000, Windows 2003 (including
  12. + Windows XP) as well by Samba (which provides excellent CIFS
  13. + server support for Linux and many other operating systems).
  14. + The smbfs module should be used instead of this cifs module for
  15. + mounting to older SMB servers such as OS/2. The smbfs and cifs
  16. + modules can coexist and do not conflict.
  17. +
  18. + The intent of this module is to provide the most advanced network
  19. + file system function for CIFS compliant servers, including better
  20. + POSIX compliance, secure per-user session establishment, high
  21. + performance safe distributed caching (oplock), optional packet
  22. + signing, Unicode support and other internationalization improvements
  23. + For more information see the project page at
  24. + http://us1.samba.org/samba/Linux_CIFS_client.html
  25. +
  26. +CIFS Debugging
  27. +CONFIG_CIFS_DEBUG
  28. + If you are experiencing any problems with the CIFS filesystem, say
  29. + Y here. This will result in additional debugging messages to be
  30. + written to the system log. Under normal circumstances, this
  31. + results in very little overhead.
  32. +
  33. SMB file system support (to mount Windows shares etc.)
  34. CONFIG_SMB_FS
  35. SMB (Server Message Block) is the protocol Windows for Workgroups
  36. --- a/Documentation/filesystems/00-INDEX
  37. +++ b/Documentation/filesystems/00-INDEX
  38. @@ -10,6 +10,8 @@ befs.txt
  39. - info for the BeOS file system (BFS)
  40. bfs.txt
  41. - info for the SCO UnixWare Boot Filesystem (BFS).
  42. +cifs.txt
  43. + - info on the Common Internet File System (CIFS)
  44. coda.txt
  45. - description of the CODA filesystem.
  46. cramfs.txt
  47. --- /dev/null
  48. +++ b/Documentation/filesystems/cifs.txt
  49. @@ -0,0 +1,51 @@
  50. + This is the client VFS module for the Common Internet File System
  51. + (CIFS) protocol which is the successor to the Server Message Block
  52. + (SMB) protocol, the native file sharing mechanism for most early
  53. + PC operating systems. CIFS is fully supported by current network
  54. + file servers such as Windows 2000, Windows 2003 (including
  55. + Windows XP) as well by Samba (which provides excellent CIFS
  56. + server support for Linux and many other operating systems), so
  57. + this network filesystem client can mount to a wide variety of
  58. + servers. The smbfs module should be used instead of this cifs module
  59. + for mounting to older SMB servers such as OS/2. The smbfs and cifs
  60. + modules can coexist and do not conflict. The CIFS VFS filesystem
  61. + module is designed to work well with servers that implement the
  62. + newer versions (dialects) of the SMB/CIFS protocol such as Samba,
  63. + the program written by Andrew Tridgell that turns any Unix host
  64. + into a SMB/CIFS file server.
  65. +
  66. + The intent of this module is to provide the most advanced network
  67. + file system function for CIFS compliant servers, including better
  68. + POSIX compliance, secure per-user session establishment, high
  69. + performance safe distributed caching (oplock), optional packet
  70. + signing, large files, Unicode support and other internationalization
  71. + improvements. Since both Samba server and this filesystem client support
  72. + the CIFS Unix extensions, the combination can provide a reasonable
  73. + alternative to NFSv4 for fileserving in some Linux to Linux environments,
  74. + not just in Linux to Windows environments.
  75. +
  76. + This filesystem has an optional mount utility (mount.cifs) that can
  77. + be obtained from the project page and installed in the path in the same
  78. + directory with the other mount helpers (such as mount.smbfs).
  79. + Mounting using the cifs filesystem without installing the mount helper
  80. + requires specifying the server's ip address.
  81. +
  82. + For Linux 2.4:
  83. + mount //anything/here /mnt_target -o
  84. + user=username,pass=password,unc=//ip_address_of_server/sharename
  85. +
  86. + For Linux 2.5:
  87. + mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
  88. +
  89. +
  90. + For more information on the module see the project page at
  91. +
  92. + http://us1.samba.org/samba/Linux_CIFS_client.html
  93. +
  94. + For more information on CIFS see:
  95. +
  96. + http://www.snia.org/tech_activities/CIFS
  97. +
  98. + or the Samba site:
  99. +
  100. + http://www.samba.org
  101. --- /dev/null
  102. +++ b/fs/cifs/asn1.c
  103. @@ -0,0 +1,614 @@
  104. +/*
  105. + * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
  106. + * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
  107. + *
  108. + * Copyright (c) 2000 RP Internet (www.rpi.net.au).
  109. + *
  110. + * This program is free software; you can redistribute it and/or modify
  111. + * it under the terms of the GNU General Public License as published by
  112. + * the Free Software Foundation; either version 2 of the License, or
  113. + * (at your option) any later version.
  114. + * This program is distributed in the hope that it will be useful,
  115. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  116. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  117. + * GNU General Public License for more details.
  118. + * You should have received a copy of the GNU General Public License
  119. + * along with this program; if not, write to the Free Software
  120. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  121. + */
  122. +
  123. +#include <linux/config.h>
  124. +#include <linux/module.h>
  125. +#include <linux/types.h>
  126. +#include <linux/kernel.h>
  127. +#include <linux/mm.h>
  128. +#include <linux/slab.h>
  129. +#include "cifspdu.h"
  130. +#include "cifsglob.h"
  131. +#include "cifs_debug.h"
  132. +
  133. +/*****************************************************************************
  134. + *
  135. + * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
  136. + *
  137. + *****************************************************************************/
  138. +
  139. +/* Class */
  140. +#define ASN1_UNI 0 /* Universal */
  141. +#define ASN1_APL 1 /* Application */
  142. +#define ASN1_CTX 2 /* Context */
  143. +#define ASN1_PRV 3 /* Private */
  144. +
  145. +/* Tag */
  146. +#define ASN1_EOC 0 /* End Of Contents or N/A */
  147. +#define ASN1_BOL 1 /* Boolean */
  148. +#define ASN1_INT 2 /* Integer */
  149. +#define ASN1_BTS 3 /* Bit String */
  150. +#define ASN1_OTS 4 /* Octet String */
  151. +#define ASN1_NUL 5 /* Null */
  152. +#define ASN1_OJI 6 /* Object Identifier */
  153. +#define ASN1_OJD 7 /* Object Description */
  154. +#define ASN1_EXT 8 /* External */
  155. +#define ASN1_SEQ 16 /* Sequence */
  156. +#define ASN1_SET 17 /* Set */
  157. +#define ASN1_NUMSTR 18 /* Numerical String */
  158. +#define ASN1_PRNSTR 19 /* Printable String */
  159. +#define ASN1_TEXSTR 20 /* Teletext String */
  160. +#define ASN1_VIDSTR 21 /* Video String */
  161. +#define ASN1_IA5STR 22 /* IA5 String */
  162. +#define ASN1_UNITIM 23 /* Universal Time */
  163. +#define ASN1_GENTIM 24 /* General Time */
  164. +#define ASN1_GRASTR 25 /* Graphical String */
  165. +#define ASN1_VISSTR 26 /* Visible String */
  166. +#define ASN1_GENSTR 27 /* General String */
  167. +
  168. +/* Primitive / Constructed methods*/
  169. +#define ASN1_PRI 0 /* Primitive */
  170. +#define ASN1_CON 1 /* Constructed */
  171. +
  172. +/*
  173. + * Error codes.
  174. + */
  175. +#define ASN1_ERR_NOERROR 0
  176. +#define ASN1_ERR_DEC_EMPTY 2
  177. +#define ASN1_ERR_DEC_EOC_MISMATCH 3
  178. +#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
  179. +#define ASN1_ERR_DEC_BADVALUE 5
  180. +
  181. +#define SPNEGO_OID_LEN 7
  182. +#define NTLMSSP_OID_LEN 10
  183. +unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
  184. +unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
  185. +
  186. +/*
  187. + * ASN.1 context.
  188. + */
  189. +struct asn1_ctx {
  190. + int error; /* Error condition */
  191. + unsigned char *pointer; /* Octet just to be decoded */
  192. + unsigned char *begin; /* First octet */
  193. + unsigned char *end; /* Octet after last octet */
  194. +};
  195. +
  196. +/*
  197. + * Octet string (not null terminated)
  198. + */
  199. +struct asn1_octstr {
  200. + unsigned char *data;
  201. + unsigned int len;
  202. +};
  203. +
  204. +static void
  205. +asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
  206. +{
  207. + ctx->begin = buf;
  208. + ctx->end = buf + len;
  209. + ctx->pointer = buf;
  210. + ctx->error = ASN1_ERR_NOERROR;
  211. +}
  212. +
  213. +static unsigned char
  214. +asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
  215. +{
  216. + if (ctx->pointer >= ctx->end) {
  217. + ctx->error = ASN1_ERR_DEC_EMPTY;
  218. + return 0;
  219. + }
  220. + *ch = *(ctx->pointer)++;
  221. + return 1;
  222. +}
  223. +
  224. +static unsigned char
  225. +asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
  226. +{
  227. + unsigned char ch;
  228. +
  229. + *tag = 0;
  230. +
  231. + do {
  232. + if (!asn1_octet_decode(ctx, &ch))
  233. + return 0;
  234. + *tag <<= 7;
  235. + *tag |= ch & 0x7F;
  236. + } while ((ch & 0x80) == 0x80);
  237. + return 1;
  238. +}
  239. +
  240. +static unsigned char
  241. +asn1_id_decode(struct asn1_ctx *ctx,
  242. + unsigned int *cls, unsigned int *con, unsigned int *tag)
  243. +{
  244. + unsigned char ch;
  245. +
  246. + if (!asn1_octet_decode(ctx, &ch))
  247. + return 0;
  248. +
  249. + *cls = (ch & 0xC0) >> 6;
  250. + *con = (ch & 0x20) >> 5;
  251. + *tag = (ch & 0x1F);
  252. +
  253. + if (*tag == 0x1F) {
  254. + if (!asn1_tag_decode(ctx, tag))
  255. + return 0;
  256. + }
  257. + return 1;
  258. +}
  259. +
  260. +static unsigned char
  261. +asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
  262. +{
  263. + unsigned char ch, cnt;
  264. +
  265. + if (!asn1_octet_decode(ctx, &ch))
  266. + return 0;
  267. +
  268. + if (ch == 0x80)
  269. + *def = 0;
  270. + else {
  271. + *def = 1;
  272. +
  273. + if (ch < 0x80)
  274. + *len = ch;
  275. + else {
  276. + cnt = (unsigned char) (ch & 0x7F);
  277. + *len = 0;
  278. +
  279. + while (cnt > 0) {
  280. + if (!asn1_octet_decode(ctx, &ch))
  281. + return 0;
  282. + *len <<= 8;
  283. + *len |= ch;
  284. + cnt--;
  285. + }
  286. + }
  287. + }
  288. + return 1;
  289. +}
  290. +
  291. +static unsigned char
  292. +asn1_header_decode(struct asn1_ctx *ctx,
  293. + unsigned char **eoc,
  294. + unsigned int *cls, unsigned int *con, unsigned int *tag)
  295. +{
  296. + unsigned int def, len;
  297. +
  298. + if (!asn1_id_decode(ctx, cls, con, tag))
  299. + return 0;
  300. +
  301. + if (!asn1_length_decode(ctx, &def, &len))
  302. + return 0;
  303. +
  304. + if (def)
  305. + *eoc = ctx->pointer + len;
  306. + else
  307. + *eoc = NULL;
  308. + return 1;
  309. +}
  310. +
  311. +static unsigned char
  312. +asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
  313. +{
  314. + unsigned char ch;
  315. +
  316. + if (eoc == 0) {
  317. + if (!asn1_octet_decode(ctx, &ch))
  318. + return 0;
  319. +
  320. + if (ch != 0x00) {
  321. + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
  322. + return 0;
  323. + }
  324. +
  325. + if (!asn1_octet_decode(ctx, &ch))
  326. + return 0;
  327. +
  328. + if (ch != 0x00) {
  329. + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
  330. + return 0;
  331. + }
  332. + return 1;
  333. + } else {
  334. + if (ctx->pointer != eoc) {
  335. + ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
  336. + return 0;
  337. + }
  338. + return 1;
  339. + }
  340. +}
  341. +
  342. +/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
  343. + unsigned char *eoc)
  344. +{
  345. + ctx->pointer = eoc;
  346. + return 1;
  347. +}
  348. +
  349. +static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
  350. + unsigned char *eoc, long *integer)
  351. +{
  352. + unsigned char ch;
  353. + unsigned int len;
  354. +
  355. + if (!asn1_octet_decode(ctx, &ch))
  356. + return 0;
  357. +
  358. + *integer = (signed char) ch;
  359. + len = 1;
  360. +
  361. + while (ctx->pointer < eoc) {
  362. + if (++len > sizeof(long)) {
  363. + ctx->error = ASN1_ERR_DEC_BADVALUE;
  364. + return 0;
  365. + }
  366. +
  367. + if (!asn1_octet_decode(ctx, &ch))
  368. + return 0;
  369. +
  370. + *integer <<= 8;
  371. + *integer |= ch;
  372. + }
  373. + return 1;
  374. +}
  375. +
  376. +static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
  377. + unsigned char *eoc,
  378. + unsigned int *integer)
  379. +{
  380. + unsigned char ch;
  381. + unsigned int len;
  382. +
  383. + if (!asn1_octet_decode(ctx, &ch))
  384. + return 0;
  385. +
  386. + *integer = ch;
  387. + if (ch == 0)
  388. + len = 0;
  389. + else
  390. + len = 1;
  391. +
  392. + while (ctx->pointer < eoc) {
  393. + if (++len > sizeof(unsigned int)) {
  394. + ctx->error = ASN1_ERR_DEC_BADVALUE;
  395. + return 0;
  396. + }
  397. +
  398. + if (!asn1_octet_decode(ctx, &ch))
  399. + return 0;
  400. +
  401. + *integer <<= 8;
  402. + *integer |= ch;
  403. + }
  404. + return 1;
  405. +}
  406. +
  407. +static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
  408. + unsigned char *eoc,
  409. + unsigned long *integer)
  410. +{
  411. + unsigned char ch;
  412. + unsigned int len;
  413. +
  414. + if (!asn1_octet_decode(ctx, &ch))
  415. + return 0;
  416. +
  417. + *integer = ch;
  418. + if (ch == 0)
  419. + len = 0;
  420. + else
  421. + len = 1;
  422. +
  423. + while (ctx->pointer < eoc) {
  424. + if (++len > sizeof(unsigned long)) {
  425. + ctx->error = ASN1_ERR_DEC_BADVALUE;
  426. + return 0;
  427. + }
  428. +
  429. + if (!asn1_octet_decode(ctx, &ch))
  430. + return 0;
  431. +
  432. + *integer <<= 8;
  433. + *integer |= ch;
  434. + }
  435. + return 1;
  436. +}
  437. +
  438. +static unsigned char
  439. +asn1_octets_decode(struct asn1_ctx *ctx,
  440. + unsigned char *eoc,
  441. + unsigned char **octets, unsigned int *len)
  442. +{
  443. + unsigned char *ptr;
  444. +
  445. + *len = 0;
  446. +
  447. + *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
  448. + if (*octets == NULL) {
  449. + return 0;
  450. + }
  451. +
  452. + ptr = *octets;
  453. + while (ctx->pointer < eoc) {
  454. + if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
  455. + kfree(*octets);
  456. + *octets = NULL;
  457. + return 0;
  458. + }
  459. + (*len)++;
  460. + }
  461. + return 1;
  462. +} */
  463. +
  464. +static unsigned char
  465. +asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
  466. +{
  467. + unsigned char ch;
  468. +
  469. + *subid = 0;
  470. +
  471. + do {
  472. + if (!asn1_octet_decode(ctx, &ch))
  473. + return 0;
  474. +
  475. + *subid <<= 7;
  476. + *subid |= ch & 0x7F;
  477. + } while ((ch & 0x80) == 0x80);
  478. + return 1;
  479. +}
  480. +
  481. +static unsigned char
  482. +asn1_oid_decode(struct asn1_ctx *ctx,
  483. + unsigned char *eoc, unsigned long **oid, unsigned int *len)
  484. +{
  485. + unsigned long subid;
  486. + unsigned int size;
  487. + unsigned long *optr;
  488. +
  489. + size = eoc - ctx->pointer + 1;
  490. + *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
  491. + if (*oid == NULL) {
  492. + return 0;
  493. + }
  494. +
  495. + optr = *oid;
  496. +
  497. + if (!asn1_subid_decode(ctx, &subid)) {
  498. + kfree(*oid);
  499. + *oid = NULL;
  500. + return 0;
  501. + }
  502. +
  503. + if (subid < 40) {
  504. + optr[0] = 0;
  505. + optr[1] = subid;
  506. + } else if (subid < 80) {
  507. + optr[0] = 1;
  508. + optr[1] = subid - 40;
  509. + } else {
  510. + optr[0] = 2;
  511. + optr[1] = subid - 80;
  512. + }
  513. +
  514. + *len = 2;
  515. + optr += 2;
  516. +
  517. + while (ctx->pointer < eoc) {
  518. + if (++(*len) > size) {
  519. + ctx->error = ASN1_ERR_DEC_BADVALUE;
  520. + kfree(*oid);
  521. + *oid = NULL;
  522. + return 0;
  523. + }
  524. +
  525. + if (!asn1_subid_decode(ctx, optr++)) {
  526. + kfree(*oid);
  527. + *oid = NULL;
  528. + return 0;
  529. + }
  530. + }
  531. + return 1;
  532. +}
  533. +
  534. +static int
  535. +compare_oid(unsigned long *oid1, unsigned int oid1len,
  536. + unsigned long *oid2, unsigned int oid2len)
  537. +{
  538. + unsigned int i;
  539. +
  540. + if (oid1len != oid2len)
  541. + return 0;
  542. + else {
  543. + for (i = 0; i < oid1len; i++) {
  544. + if (oid1[i] != oid2[i])
  545. + return 0;
  546. + }
  547. + return 1;
  548. + }
  549. +}
  550. +
  551. + /* BB check for endian conversion issues here */
  552. +
  553. +int
  554. +decode_negTokenInit(unsigned char *security_blob, int length,
  555. + enum securityEnum *secType)
  556. +{
  557. + struct asn1_ctx ctx;
  558. + unsigned char *end;
  559. + unsigned char *sequence_end;
  560. + unsigned long *oid;
  561. + unsigned int cls, con, tag, oidlen, rc;
  562. + int use_ntlmssp = FALSE;
  563. +
  564. + *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
  565. +
  566. + /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
  567. +
  568. + asn1_open(&ctx, security_blob, length);
  569. +
  570. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  571. + cFYI(1, ("Error decoding negTokenInit header "));
  572. + return 0;
  573. + } else if ((cls != ASN1_APL) || (con != ASN1_CON)
  574. + || (tag != ASN1_EOC)) {
  575. + cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
  576. + return 0;
  577. + } else {
  578. + /* remember to free obj->oid */
  579. + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
  580. + if (rc) {
  581. + if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
  582. + rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
  583. + if (rc) {
  584. + rc = compare_oid(oid, oidlen,
  585. + SPNEGO_OID,
  586. + SPNEGO_OID_LEN);
  587. + kfree(oid);
  588. + }
  589. + } else
  590. + rc = 0;
  591. + }
  592. +
  593. + if (!rc) {
  594. + cFYI(1, ("Error decoding negTokenInit header"));
  595. + return 0;
  596. + }
  597. +
  598. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  599. + cFYI(1, ("Error decoding negTokenInit "));
  600. + return 0;
  601. + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
  602. + || (tag != ASN1_EOC)) {
  603. + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
  604. + cls, con, tag, end, *end));
  605. + return 0;
  606. + }
  607. +
  608. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  609. + cFYI(1, ("Error decoding negTokenInit "));
  610. + return 0;
  611. + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
  612. + || (tag != ASN1_SEQ)) {
  613. + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
  614. + cls, con, tag, end, *end));
  615. + return 0;
  616. + }
  617. +
  618. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  619. + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
  620. + return 0;
  621. + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
  622. + || (tag != ASN1_EOC)) {
  623. + cFYI(1,
  624. + ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
  625. + cls, con, tag, end, *end));
  626. + return 0;
  627. + }
  628. +
  629. + if (asn1_header_decode
  630. + (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
  631. + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
  632. + return 0;
  633. + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
  634. + || (tag != ASN1_SEQ)) {
  635. + cFYI(1,
  636. + ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
  637. + cls, con, tag, end, *end));
  638. + return 0;
  639. + }
  640. +
  641. + while (!asn1_eoc_decode(&ctx, sequence_end)) {
  642. + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
  643. + if (!rc) {
  644. + cFYI(1,
  645. + ("Error 1 decoding negTokenInit header exit 2"));
  646. + return 0;
  647. + }
  648. + if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
  649. + asn1_oid_decode(&ctx, end, &oid, &oidlen);
  650. + cFYI(1,
  651. + ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
  652. + oidlen, *oid, *(oid + 1), *(oid + 2),
  653. + *(oid + 3)));
  654. + rc = compare_oid(oid, oidlen, NTLMSSP_OID,
  655. + NTLMSSP_OID_LEN);
  656. + kfree(oid);
  657. + if (rc)
  658. + use_ntlmssp = TRUE;
  659. + } else {
  660. + cFYI(1,("This should be an oid what is going on? "));
  661. + }
  662. + }
  663. +
  664. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  665. + cFYI(1,
  666. + ("Error decoding last part of negTokenInit exit 3"));
  667. + return 0;
  668. + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
  669. + cFYI(1,
  670. + ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
  671. + cls, con, tag, end, *end));
  672. + return 0;
  673. + }
  674. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  675. + cFYI(1,
  676. + ("Error decoding last part of negTokenInit exit 5"));
  677. + return 0;
  678. + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
  679. + || (tag != ASN1_SEQ)) {
  680. + cFYI(1,
  681. + ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
  682. + cls, con, tag, end, *end));
  683. + }
  684. +
  685. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  686. + cFYI(1,
  687. + ("Error decoding last part of negTokenInit exit 7"));
  688. + return 0;
  689. + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
  690. + cFYI(1,
  691. + ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
  692. + cls, con, tag, end, *end));
  693. + return 0;
  694. + }
  695. + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
  696. + cFYI(1,
  697. + ("Error decoding last part of negTokenInit exit 9"));
  698. + return 0;
  699. + } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
  700. + || (tag != ASN1_GENSTR)) {
  701. + cFYI(1,
  702. + ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
  703. + cls, con, tag, end, *end));
  704. + return 0;
  705. + }
  706. + cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
  707. + }
  708. +
  709. + /* if (use_kerberos)
  710. + *secType = Kerberos
  711. + else */
  712. + if (use_ntlmssp) {
  713. + *secType = NTLMSSP;
  714. + }
  715. +
  716. + return 1;
  717. +}
  718. --- /dev/null
  719. +++ b/fs/cifs/AUTHORS
  720. @@ -0,0 +1,37 @@
  721. +Original Author
  722. +===============
  723. +Steve French ([email protected])
  724. +
  725. +The author wishes to express his appreciation and thanks to:
  726. +Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
  727. +improvements. Thanks to IBM for allowing me the time and test resources to pursue
  728. +this project. Jim McDonough from IBM (and the Samba Team) for his help.
  729. +The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
  730. +Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
  731. +for proving years ago that a very good smb/cifs client could be done on a Unix like
  732. +operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
  733. +and others for their work on the Linux smbfs module over the years. Thanks to
  734. +the other members of the Storage Network Industry Association CIFS Technical
  735. +Workgroup for their work specifying this highly complex protocol and finally
  736. +thanks to the Samba team for their technical advice and encouragement.
  737. +
  738. +Patch Contributors
  739. +------------------
  740. +Zwane Mwaikambo
  741. +Andi Kleen
  742. +Amrut Joshi
  743. +Shobhit Dayal
  744. +Sergey Vlasov
  745. +Richard Hughes
  746. +Yury Umanets
  747. +
  748. +Test case and Bug Report contributors
  749. +-------------------------------------
  750. +Thanks to those in the community who have submitted detailed bug reports
  751. +and debug of problems they have found: Jochen Dolze, David Blaine,
  752. +Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
  753. +Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
  754. +Olaf Kirch, Kieron Briggs, Nick Millington and others.
  755. +
  756. +And thanks to the IBM LTC and Power test teams and SuSE testers for
  757. +finding multiple bugs during excellent stress test runs.
  758. --- /dev/null
  759. +++ b/fs/cifs/CHANGES
  760. @@ -0,0 +1,572 @@
  761. +Version 1.20
  762. +------------
  763. +Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
  764. +info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
  765. +(in build_wildcard_path_from_dentry). Fix mknod to pass type field
  766. +(block/char/fifo) properly. Remove spurious mount warning log entry when
  767. +credentials passed as mount argument. Set major/minor device number in
  768. +inode for block and char devices when unix extensions enabled.
  769. +
  770. +Version 1.19
  771. +------------
  772. +Fix /proc/fs/cifs/Stats and DebugData display to handle larger
  773. +amounts of return data. Properly limit requests to MAX_REQ (50
  774. +is the usual maximum active multiplex SMB/CIFS requests per server).
  775. +Do not kill cifsd (and thus hurt the other SMB session) when more than one
  776. +session to the same server (but with different userids) exists and one
  777. +of the two user's smb sessions is being removed while leaving the other.
  778. +Do not loop reconnecting in cifsd demultiplex thread when admin
  779. +kills the thread without going through unmount.
  780. +
  781. +Version 1.18
  782. +------------
  783. +Do not rename hardlinked files (since that should be a noop). Flush
  784. +cached write behind data when reopening a file after session abend,
  785. +except when already in write. Grab per socket sem during reconnect
  786. +to avoid oops in sendmsg if overlapping with reconnect. Do not
  787. +reset cached inode file size on readdir for files open for write on
  788. +client.
  789. +
  790. +
  791. +Version 1.17
  792. +------------
  793. +Update number of blocks in file so du command is happier (in Linux a fake
  794. +blocksize of 512 is required for calculating number of blocks in inode).
  795. +Fix prepare write of partial pages to read in data from server if possible.
  796. +Fix race on tcpStatus field between unmount and reconnection code, causing
  797. +cifsd process sometimes to hang around forever. Improve out of memory
  798. +checks in cifs_filldir
  799. +
  800. +Version 1.16
  801. +------------
  802. +Fix incorrect file size in file handle based setattr on big endian hardware.
  803. +Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
  804. +and closing file structs in writepage/partialpagewrite. Add statistics
  805. +for each mounted share (new menuconfig option). Fix endianness problem in
  806. +volume information displayed in /proc/fs/cifs/DebugData (only affects
  807. +affects big endian architectures). Prevent renames while constructing
  808. +path names for open, mkdir and rmdir.
  809. +
  810. +Version 1.15
  811. +------------
  812. +Change to mempools for alloc smb request buffers and multiplex structs
  813. +to better handle low memory problems (and potential deadlocks).
  814. +
  815. +Version 1.14
  816. +------------
  817. +Fix incomplete listings of large directories on Samba servers when Unix
  818. +extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
  819. +rename deadlock when writing out dirty pages at same time.
  820. +
  821. +Version 1.13
  822. +------------
  823. +Fix open of files in which O_CREATE can cause the mode to change in
  824. +some cases. Fix case in which retry of write overlaps file close.
  825. +Fix PPC64 build error. Reduce excessive stack usage in smb password
  826. +hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
  827. +
  828. +Version 1.12
  829. +------------
  830. +Fixes for large file copy, signal handling, socket retry, buffer
  831. +allocation and low memory situations.
  832. +
  833. +Version 1.11
  834. +------------
  835. +Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
  836. +also now allowing support for specifying client netbiosname. NT4 support added.
  837. +
  838. +Version 1.10
  839. +------------
  840. +Fix reconnection (and certain failed mounts) to properly wake up the
  841. +blocked users thread so it does not seem hung (in some cases was blocked
  842. +until the cifs receive timeout expired). Fix spurious error logging
  843. +to kernel log when application with open network files killed.
  844. +
  845. +Version 1.09
  846. +------------
  847. +Fix /proc/fs module unload warning message (that could be logged
  848. +to the kernel log). Fix intermittent failure in connectathon
  849. +test7 (hardlink count not immediately refreshed in case in which
  850. +inode metadata can be incorrectly kept cached when time near zero)
  851. +
  852. +Version 1.08
  853. +------------
  854. +Allow file_mode and dir_mode (specified at mount time) to be enforced
  855. +locally (the server already enforced its own ACLs too) for servers
  856. +that do not report the correct mode (do not support the
  857. +CIFS Unix Extensions).
  858. +
  859. +Version 1.07
  860. +------------
  861. +Fix some small memory leaks in some unmount error paths. Fix major leak
  862. +of cache pages in readpages causing multiple read oriented stress
  863. +testcases (including fsx, and even large file copy) to fail over time.
  864. +
  865. +Version 1.06
  866. +------------
  867. +Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
  868. +This allows files that differ only in case and improves performance of file
  869. +creation and file open to such servers. Fix semaphore conflict which causes
  870. +slow delete of open file to Samba (which unfortunately can cause an oplock
  871. +break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
  872. +
  873. +Version 1.05
  874. +------------
  875. +fixes to cifs_readpages for fsx test case
  876. +
  877. +Version 1.04
  878. +------------
  879. +Fix caching data integrity bug when extending file size especially when no
  880. +oplock on file. Fix spurious logging of valid already parsed mount options
  881. +that are parsed outside of the cifs vfs such as nosuid.
  882. +
  883. +
  884. +Version 1.03
  885. +------------
  886. +Connect to server when port number override not specified, and tcp port
  887. +unitialized. Reset search to restart at correct file when kernel routine
  888. +filldir returns error during large directory searches (readdir).
  889. +
  890. +Version 1.02
  891. +------------
  892. +Fix caching problem when files opened by multiple clients in which
  893. +page cache could contain stale data, and write through did
  894. +not occur often enough while file was still open when read ahead
  895. +(read oplock) not allowed. Treat "sep=" when first mount option
  896. +as an overrride of comma as the default separator between mount
  897. +options.
  898. +
  899. +Version 1.01
  900. +------------
  901. +Allow passwords longer than 16 bytes. Allow null password string.
  902. +
  903. +Version 1.00
  904. +------------
  905. +Gracefully clean up failed mounts when attempting to mount to servers such as
  906. +Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
  907. +embedded commas in mount parsing of passwords.
  908. +
  909. +Version 0.99
  910. +------------
  911. +Invalidate local inode cached pages on oplock break and when last file
  912. +instance is closed so that the client does not continue using stale local
  913. +copy rather than later modified server copy of file. Do not reconnect
  914. +when server drops the tcp session prematurely before negotiate
  915. +protocol response. Fix oops in roepen_file when dentry freed. Allow
  916. +the support for CIFS Unix Extensions to be disabled via proc interface.
  917. +
  918. +Version 0.98
  919. +------------
  920. +Fix hang in commit_write during reconnection of open files under heavy load.
  921. +Fix unload_nls oops in a mount failure path. Serialize writes to same socket
  922. +which also fixes any possible races when cifs signatures are enabled in SMBs
  923. +being sent out of signature sequence number order.
  924. +
  925. +Version 0.97
  926. +------------
  927. +Fix byte range locking bug (endian problem) causing bad offset and
  928. +length.
  929. +
  930. +Version 0.96
  931. +------------
  932. +Fix oops (in send_sig) caused by CIFS unmount code trying to
  933. +wake up the demultiplex thread after it had exited. Do not log
  934. +error on harmless oplock release of closed handle.
  935. +
  936. +Version 0.95
  937. +------------
  938. +Fix unsafe global variable usage and password hash failure on gcc 3.3.1
  939. +Fix problem reconnecting secondary mounts to same server after session
  940. +failure. Fix invalid dentry - race in mkdir when directory gets created
  941. +by another client between the lookup and mkdir.
  942. +
  943. +Version 0.94
  944. +------------
  945. +Fix to list processing in reopen_files. Fix reconnection when server hung
  946. +but tcpip session still alive. Set proper timeout on socket read.
  947. +
  948. +Version 0.93
  949. +------------
  950. +Add missing mount options including iocharset. SMP fixes in write and open.
  951. +Fix errors in reconnecting after TCP session failure. Fix module unloading
  952. +of default nls codepage
  953. +
  954. +Version 0.92
  955. +------------
  956. +Active smb transactions should never go negative (fix double FreeXid). Fix
  957. +list processing in file routines. Check return code on kmalloc in open.
  958. +Fix spinlock usage for SMP.
  959. +
  960. +Version 0.91
  961. +------------
  962. +Fix oops in reopen_files when invalid dentry. drop dentry on server rename
  963. +and on revalidate errors. Fix cases where pid is now tgid. Fix return code
  964. +on create hard link when server does not support them.
  965. +
  966. +Version 0.90
  967. +------------
  968. +Fix scheduling while atomic error in getting inode info on newly created file.
  969. +Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
  970. +
  971. +Version 0.89
  972. +------------
  973. +Fix oops on write to dead tcp session. Remove error log write for case when file open
  974. +O_CREAT but not O_EXCL
  975. +
  976. +Version 0.88
  977. +------------
  978. +Fix non-POSIX behavior on rename of open file and delete of open file by taking
  979. +advantage of trans2 SetFileInfo rename facility if available on target server.
  980. +Retry on ENOSPC and EAGAIN socket errors.
  981. +
  982. +Version 0.87
  983. +------------
  984. +Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
  985. +allocation size miscalculation. After oplock token lost do not read through
  986. +cache.
  987. +
  988. +Version 0.86
  989. +------------
  990. +Fix oops on empty file readahead. Fix for file size handling for locally cached files.
  991. +
  992. +Version 0.85
  993. +------------
  994. +Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
  995. +during auto reconnection to server after server recovered from failure.
  996. +
  997. +Version 0.84
  998. +------------
  999. +Finish support for Linux 2.5 open/create changes, which removes the
  1000. +redundant NTCreate/QPathInfo/close that was sent during file create.
  1001. +Enable oplock by default. Enable packet signing by default (needed to
  1002. +access many recent Windows servers)
  1003. +
  1004. +Version 0.83
  1005. +------------
  1006. +Fix oops when mounting to long server names caused by inverted parms to kmalloc.
  1007. +Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
  1008. +we will choose a cifs user session (smb uid) that better matches the local
  1009. +uid if a) the mount uid does not match the current uid and b) we have another
  1010. +session to the same server (ip address) for a different mount which
  1011. +matches the current local uid.
  1012. +
  1013. +Version 0.82
  1014. +------------
  1015. +Add support for mknod of block or character devices. Fix oplock
  1016. +code (distributed caching) to properly send response to oplock
  1017. +break from server.
  1018. +
  1019. +Version 0.81
  1020. +------------
  1021. +Finish up CIFS packet digital signing for the default
  1022. +NTLM security case. This should help Windows 2003
  1023. +network interoperability since it is common for
  1024. +packet signing to be required now. Fix statfs (stat -f)
  1025. +which recently started returning errors due to
  1026. +invalid value (-1 instead of 0) being set in the
  1027. +struct kstatfs f_ffiles field.
  1028. +
  1029. +Version 0.80
  1030. +-----------
  1031. +Fix oops on stopping oplock thread when removing cifs when
  1032. +built as module.
  1033. +
  1034. +Version 0.79
  1035. +------------
  1036. +Fix mount options for ro (readonly), uid, gid and file and directory mode.
  1037. +
  1038. +Version 0.78
  1039. +------------
  1040. +Fix errors displayed on failed mounts to be more understandable.
  1041. +Fixed various incorrect or misleading smb to posix error code mappings.
  1042. +
  1043. +Version 0.77
  1044. +------------
  1045. +Fix display of NTFS DFS junctions to display as symlinks.
  1046. +They are the network equivalent. Fix oops in
  1047. +cifs_partialpagewrite caused by missing spinlock protection
  1048. +of openfile linked list. Allow writebehind caching errors to
  1049. +be returned to the application at file close.
  1050. +
  1051. +Version 0.76
  1052. +------------
  1053. +Clean up options displayed in /proc/mounts by show_options to
  1054. +be more consistent with other filesystems.
  1055. +
  1056. +Version 0.75
  1057. +------------
  1058. +Fix delete of readonly file to Windows servers. Reflect
  1059. +presence or absence of read only dos attribute in mode
  1060. +bits for servers that do not support CIFS Unix extensions.
  1061. +Fix shortened results on readdir of large directories to
  1062. +servers supporting CIFS Unix extensions (caused by
  1063. +incorrect resume key).
  1064. +
  1065. +Version 0.74
  1066. +------------
  1067. +Fix truncate bug (set file size) that could cause hangs e.g. running fsx
  1068. +
  1069. +Version 0.73
  1070. +------------
  1071. +unload nls if mount fails.
  1072. +
  1073. +Version 0.72
  1074. +------------
  1075. +Add resume key support to search (readdir) code to workaround
  1076. +Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
  1077. +allows disabling caching of attribute information for
  1078. +lookups.
  1079. +
  1080. +Version 0.71
  1081. +------------
  1082. +Add more oplock handling (distributed caching code). Remove
  1083. +dead code. Remove excessive stack space utilization from
  1084. +symlink routines.
  1085. +
  1086. +Version 0.70
  1087. +------------
  1088. +Fix oops in get dfs referral (triggered when null path sent in to
  1089. +mount). Add support for overriding rsize at mount time.
  1090. +
  1091. +Version 0.69
  1092. +------------
  1093. +Fix buffer overrun in readdir which caused intermittent kernel oopses.
  1094. +Fix writepage code to release kmap on write data. Allow "-ip=" new
  1095. +mount option to be passed in on parameter distinct from the first part
  1096. +(server name portion of) the UNC name. Allow override of the
  1097. +tcp port of the target server via new mount option "-port="
  1098. +
  1099. +Version 0.68
  1100. +------------
  1101. +Fix search handle leak on rewind. Fix setuid and gid so that they are
  1102. +reflected in the local inode immediately. Cleanup of whitespace
  1103. +to make 2.4 and 2.5 versions more consistent.
  1104. +
  1105. +
  1106. +Version 0.67
  1107. +------------
  1108. +Fix signal sending so that captive thread (cifsd) exits on umount
  1109. +(which was causing the warning in kmem_cache_free of the request buffers
  1110. +at rmmod time). This had broken as a sideeffect of the recent global
  1111. +kernel change to daemonize. Fix memory leak in readdir code which
  1112. +showed up in "ls -R" (and applications that did search rewinding).
  1113. +
  1114. +Version 0.66
  1115. +------------
  1116. +Reconnect tids and fids after session reconnection (still do not
  1117. +reconnect byte range locks though). Fix problem caching
  1118. +lookup information for directory inodes, improving performance,
  1119. +especially in deep directory trees. Fix various build warnings.
  1120. +
  1121. +Version 0.65
  1122. +------------
  1123. +Finish fixes to commit write for caching/readahead consistency. fsx
  1124. +now works to Samba servers. Fix oops caused when readahead
  1125. +was interrupted by a signal.
  1126. +
  1127. +Version 0.64
  1128. +------------
  1129. +Fix data corruption (in partial page after truncate) that caused fsx to
  1130. +fail to Windows servers. Cleaned up some extraneous error logging in
  1131. +common error paths. Add generic sendfile support.
  1132. +
  1133. +Version 0.63
  1134. +------------
  1135. +Fix memory leak in AllocMidQEntry.
  1136. +Finish reconnection logic, so connection with server can be dropped
  1137. +(or server rebooted) and the cifs client will reconnect.
  1138. +
  1139. +Version 0.62
  1140. +------------
  1141. +Fix temporary socket leak when bad userid or password specified
  1142. +(or other SMBSessSetup failure). Increase maximum buffer size to slightly
  1143. +over 16K to allow negotiation of up to Samba and Windows server default read
  1144. +sizes. Add support for readpages
  1145. +
  1146. +Version 0.61
  1147. +------------
  1148. +Fix oops when username not passed in on mount. Extensive fixes and improvements
  1149. +to error logging (strip redundant newlines, change debug macros to ensure newline
  1150. +passed in and to be more consistent). Fix writepage wrong file handle problem,
  1151. +a readonly file handle could be incorrectly used to attempt to write out
  1152. +file updates through the page cache to multiply open files. This could cause
  1153. +the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
  1154. +shares to the same Windows server when using different usernames
  1155. +(doing this to Samba servers worked but Windows was rejecting it) - now it is
  1156. +possible to use different userids when connecting to the same server from a
  1157. +Linux client. Fix oops when treeDisconnect called during unmount on
  1158. +previously freed socket.
  1159. +
  1160. +Version 0.60
  1161. +------------
  1162. +Fix oops in readpages caused by not setting address space operations in inode in
  1163. +rare code path.
  1164. +
  1165. +Version 0.59
  1166. +------------
  1167. +Includes support for deleting of open files and renaming over existing files (per POSIX
  1168. +requirement). Add readlink support for Windows junction points (directory symlinks).
  1169. +
  1170. +Version 0.58
  1171. +------------
  1172. +Changed read and write to go through pagecache. Added additional address space operations.
  1173. +Memory mapped operations now working.
  1174. +
  1175. +Version 0.57
  1176. +------------
  1177. +Added writepage code for additional memory mapping support. Fixed leak in xids causing
  1178. +the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
  1179. +every stat call. Additional formatting cleanup.
  1180. +
  1181. +Version 0.56
  1182. +------------
  1183. +Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
  1184. +
  1185. +Version 0.55
  1186. +------------
  1187. +Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
  1188. +Also included a modified version of his fix to protect global list manipulation of
  1189. +the smb session and tree connection and mid related global variables.
  1190. +
  1191. +Version 0.54
  1192. +------------
  1193. +Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
  1194. +changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
  1195. +buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
  1196. +
  1197. +Version 0.53
  1198. +------------
  1199. +More stylistic updates to better match kernel style. Add additional statistics
  1200. +for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
  1201. +and CIFS Packet Signing enablement.
  1202. +
  1203. +Version 0.52
  1204. +------------
  1205. +Replace call to sleep_on with safer wait_on_event.
  1206. +Make stylistic changes to better match kernel style recommendations.
  1207. +Remove most typedef usage (except for the PDUs themselves).
  1208. +
  1209. +Version 0.51
  1210. +------------
  1211. +Update mount so the -unc mount option is no longer required (the ip address can be specified
  1212. +in a UNC style device name. Implementation of readpage/writepage started.
  1213. +
  1214. +Version 0.50
  1215. +------------
  1216. +Fix intermittent problem with incorrect smb header checking on badly
  1217. +fragmented tcp responses
  1218. +
  1219. +Version 0.49
  1220. +------------
  1221. +Fixes to setting of allocation size and file size.
  1222. +
  1223. +Version 0.48
  1224. +------------
  1225. +Various 2.5.38 fixes. Now works on 2.5.38
  1226. +
  1227. +Version 0.47
  1228. +------------
  1229. +Prepare for 2.5 kernel merge. Remove ifdefs.
  1230. +
  1231. +Version 0.46
  1232. +------------
  1233. +Socket buffer management fixes. Fix dual free.
  1234. +
  1235. +Version 0.45
  1236. +------------
  1237. +Various big endian fixes for hardlinks and symlinks and also for dfs.
  1238. +
  1239. +Version 0.44
  1240. +------------
  1241. +Various big endian fixes for servers with Unix extensions such as Samba
  1242. +
  1243. +Version 0.43
  1244. +------------
  1245. +Various FindNext fixes for incorrect filenames on large directory searches on big endian
  1246. +clients. basic posix file i/o tests now work on big endian machines, not just le
  1247. +
  1248. +Version 0.42
  1249. +------------
  1250. +SessionSetup and NegotiateProtocol now work from Big Endian machines.
  1251. +Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
  1252. +versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
  1253. +
  1254. +Version 0.41
  1255. +------------
  1256. +Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
  1257. +files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
  1258. +
  1259. +Version 0.40
  1260. +------------
  1261. +Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
  1262. +session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
  1263. +Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
  1264. +(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
  1265. +
  1266. +Version 0.38
  1267. +------------
  1268. +Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
  1269. +it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
  1270. +
  1271. +Version 0.37
  1272. +------------
  1273. +Rewrote much of connection and mount/unmount logic to handle bugs with
  1274. +multiple uses to same share, multiple users to same server etc.
  1275. +
  1276. +Version 0.36
  1277. +------------
  1278. +Fixed major problem with dentry corruption (missing call to dput)
  1279. +
  1280. +Version 0.35
  1281. +------------
  1282. +Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
  1283. +Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
  1284. +although corresponding function not fully implemented in the vfs yet
  1285. +
  1286. +Version 0.34
  1287. +------------
  1288. +Fixed dentry caching bug, misc. cleanup
  1289. +
  1290. +Version 0.33
  1291. +------------
  1292. +Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
  1293. +on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
  1294. +Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
  1295. +
  1296. +Version 0.32
  1297. +------------
  1298. +Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
  1299. +and tested against Samba 2.2.5
  1300. +
  1301. +
  1302. +Version 0.31
  1303. +------------
  1304. +1) Fixed lockrange to be correct (it was one byte too short)
  1305. +
  1306. +2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
  1307. +show range as locked when there is a conflict with an existing lock.
  1308. +
  1309. +3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
  1310. +in most cases. Eventually will offer optional ability to query server for the correct perms.
  1311. +
  1312. +3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
  1313. +but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
  1314. +session)
  1315. +
  1316. +4) Fixed error logging of valid mount options
  1317. +
  1318. +5) Removed logging of password field.
  1319. +
  1320. +6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
  1321. +and cleaned them up and made them more consistent with other cifs functions.
  1322. +
  1323. +7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
  1324. +(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
  1325. +nor is the symlink support using the Unix extensions
  1326. +
  1327. +8) Started adding the readlink and follow_link code
  1328. +
  1329. +Version 0.3
  1330. +-----------
  1331. +Initial drop
  1332. +
  1333. --- /dev/null
  1334. +++ b/fs/cifs/cifs_debug.c
  1335. @@ -0,0 +1,797 @@
  1336. +/*
  1337. + * fs/cifs_debug.c
  1338. + *
  1339. + * Copyright (C) International Business Machines Corp., 2000,2003
  1340. + *
  1341. + * Modified by Steve French ([email protected])
  1342. + *
  1343. + * This program is free software; you can redistribute it and/or modify
  1344. + * it under the terms of the GNU General Public License as published by
  1345. + * the Free Software Foundation; either version 2 of the License, or
  1346. + * (at your option) any later version.
  1347. + *
  1348. + * This program is distributed in the hope that it will be useful,
  1349. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1350. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  1351. + * the GNU General Public License for more details.
  1352. + *
  1353. + * You should have received a copy of the GNU General Public License
  1354. + * along with this program; if not, write to the Free Software
  1355. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  1356. + */
  1357. +#include <linux/fs.h>
  1358. +#include <linux/string.h>
  1359. +#include <linux/ctype.h>
  1360. +#include <linux/module.h>
  1361. +#include <linux/proc_fs.h>
  1362. +#include <asm/uaccess.h>
  1363. +#include "cifspdu.h"
  1364. +#include "cifsglob.h"
  1365. +#include "cifsproto.h"
  1366. +#include "cifs_debug.h"
  1367. +
  1368. +void
  1369. +cifs_dump_mem(char *label, void *data, int length)
  1370. +{
  1371. + int i, j;
  1372. + int *intptr = data;
  1373. + char *charptr = data;
  1374. + char buf[10], line[80];
  1375. +
  1376. + printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
  1377. + label, length, data);
  1378. + for (i = 0; i < length; i += 16) {
  1379. + line[0] = 0;
  1380. + for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
  1381. + sprintf(buf, " %08x", intptr[i / 4 + j]);
  1382. + strcat(line, buf);
  1383. + }
  1384. + buf[0] = ' ';
  1385. + buf[2] = 0;
  1386. + for (j = 0; (j < 16) && (i + j < length); j++) {
  1387. + buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
  1388. + strcat(line, buf);
  1389. + }
  1390. + printk(KERN_DEBUG "%s\n", line);
  1391. + }
  1392. +}
  1393. +
  1394. +#ifdef CONFIG_PROC_FS
  1395. +int
  1396. +cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
  1397. + int count, int *eof, void *data)
  1398. +{
  1399. + struct list_head *tmp;
  1400. + struct list_head *tmp1;
  1401. + struct mid_q_entry * mid_entry;
  1402. + struct cifsSesInfo *ses;
  1403. + struct cifsTconInfo *tcon;
  1404. + int i;
  1405. + int length = 0;
  1406. + char * original_buf = buf;
  1407. +
  1408. + *beginBuffer = buf + offset;
  1409. +
  1410. +
  1411. + length =
  1412. + sprintf(buf,
  1413. + "Display Internal CIFS Data Structures for Debugging\n"
  1414. + "---------------------------------------------------\n");
  1415. + buf += length;
  1416. +
  1417. + length = sprintf(buf, "Servers:\n");
  1418. + buf += length;
  1419. +
  1420. + i = 0;
  1421. + read_lock(&GlobalSMBSeslock);
  1422. + list_for_each(tmp, &GlobalSMBSessionList) {
  1423. + i++;
  1424. + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
  1425. + length =
  1426. + sprintf(buf,
  1427. + "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
  1428. + i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
  1429. + ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
  1430. + buf += length;
  1431. + if(ses->server) {
  1432. + buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
  1433. + atomic_read(&ses->server->socketUseCount),
  1434. + ses->server->secMode,
  1435. + atomic_read(&ses->server->inFlight));
  1436. +
  1437. + length = sprintf(buf, "\nMIDs: \n");
  1438. + buf += length;
  1439. +
  1440. + spin_lock(&GlobalMid_Lock);
  1441. + list_for_each(tmp1, &ses->server->pending_mid_q) {
  1442. + mid_entry = list_entry(tmp1, struct
  1443. + mid_q_entry,
  1444. + qhead);
  1445. + if(mid_entry) {
  1446. + length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
  1447. + buf += length;
  1448. + }
  1449. + }
  1450. + spin_unlock(&GlobalMid_Lock);
  1451. + }
  1452. +
  1453. + }
  1454. + read_unlock(&GlobalSMBSeslock);
  1455. + sprintf(buf, "\n");
  1456. + buf++;
  1457. +
  1458. + length = sprintf(buf, "\nShares:\n");
  1459. + buf += length;
  1460. +
  1461. + i = 0;
  1462. + read_lock(&GlobalSMBSeslock);
  1463. + list_for_each(tmp, &GlobalTreeConnectionList) {
  1464. + i++;
  1465. + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
  1466. + length =
  1467. + sprintf(buf,
  1468. + "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
  1469. + i, tcon->treeName,
  1470. + atomic_read(&tcon->useCount),
  1471. + tcon->nativeFileSystem,
  1472. + tcon->fsDevInfo.DeviceCharacteristics,
  1473. + tcon->fsAttrInfo.Attributes,
  1474. + tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
  1475. + buf += length;
  1476. + if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
  1477. + length = sprintf(buf, " type: DISK ");
  1478. + else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
  1479. + length = sprintf(buf, " type: CDROM ");
  1480. + else
  1481. + length =
  1482. + sprintf(buf, " type: %d ",
  1483. + tcon->fsDevInfo.DeviceType);
  1484. + buf += length;
  1485. + if(tcon->tidStatus == CifsNeedReconnect) {
  1486. + buf += sprintf(buf, "\tDISCONNECTED ");
  1487. + length += 14;
  1488. + }
  1489. + }
  1490. + read_unlock(&GlobalSMBSeslock);
  1491. +
  1492. + length = sprintf(buf, "\n");
  1493. + buf += length;
  1494. +
  1495. + /* BB add code to dump additional info such as TCP session info now */
  1496. + /* Now calculate total size of returned data */
  1497. + length = buf - original_buf;
  1498. +
  1499. + if(offset + count >= length)
  1500. + *eof = 1;
  1501. + if(length < offset) {
  1502. + *eof = 1;
  1503. + return 0;
  1504. + } else {
  1505. + length = length - offset;
  1506. + }
  1507. + if (length > count)
  1508. + length = count;
  1509. +
  1510. + return length;
  1511. +}
  1512. +
  1513. +#ifdef CONFIG_CIFS_STATS
  1514. +int
  1515. +cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
  1516. + int count, int *eof, void *data)
  1517. +{
  1518. + int item_length,i,length;
  1519. + struct list_head *tmp;
  1520. + struct cifsTconInfo *tcon;
  1521. +
  1522. + *beginBuffer = buf + offset;
  1523. +
  1524. + length = sprintf(buf,
  1525. + "Resources in use\nCIFS Session: %d\n",
  1526. + sesInfoAllocCount.counter);
  1527. + buf += length;
  1528. + item_length =
  1529. + sprintf(buf,"Share (unique mount targets): %d\n",
  1530. + tconInfoAllocCount.counter);
  1531. + length += item_length;
  1532. + buf += item_length;
  1533. + item_length =
  1534. + sprintf(buf,"SMB Request/Response Buffer: %d\n",
  1535. + bufAllocCount.counter);
  1536. + length += item_length;
  1537. + buf += item_length;
  1538. + item_length =
  1539. + sprintf(buf,"Operations (MIDs): %d\n",
  1540. + midCount.counter);
  1541. + length += item_length;
  1542. + buf += item_length;
  1543. + item_length = sprintf(buf,
  1544. + "\n%d session %d share reconnects\n",
  1545. + tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
  1546. + length += item_length;
  1547. + buf += item_length;
  1548. +
  1549. + item_length = sprintf(buf,
  1550. + "Total vfs operations: %d maximum at one time: %d\n",
  1551. + GlobalCurrentXid,GlobalMaxActiveXid);
  1552. + length += item_length;
  1553. + buf += item_length;
  1554. +
  1555. + i = 0;
  1556. + read_lock(&GlobalSMBSeslock);
  1557. + list_for_each(tmp, &GlobalTreeConnectionList) {
  1558. + i++;
  1559. + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
  1560. + item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
  1561. + buf += item_length;
  1562. + length += item_length;
  1563. + if(tcon->tidStatus == CifsNeedReconnect) {
  1564. + buf += sprintf(buf, "\tDISCONNECTED ");
  1565. + length += 14;
  1566. + }
  1567. + item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
  1568. + atomic_read(&tcon->num_smbs_sent),
  1569. + atomic_read(&tcon->num_oplock_brks));
  1570. + buf += item_length;
  1571. + length += item_length;
  1572. + item_length = sprintf(buf,"\nReads: %d Bytes %lld",
  1573. + atomic_read(&tcon->num_reads),
  1574. + (long long)(tcon->bytes_read));
  1575. + buf += item_length;
  1576. + length += item_length;
  1577. + item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
  1578. + atomic_read(&tcon->num_writes),
  1579. + (long long)(tcon->bytes_written));
  1580. + buf += item_length;
  1581. + length += item_length;
  1582. + item_length = sprintf(buf,
  1583. + "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
  1584. + atomic_read(&tcon->num_opens),
  1585. + atomic_read(&tcon->num_deletes),
  1586. + atomic_read(&tcon->num_mkdirs),
  1587. + atomic_read(&tcon->num_rmdirs));
  1588. + buf += item_length;
  1589. + length += item_length;
  1590. + item_length = sprintf(buf,
  1591. + "\nRenames: %d T2 Renames %d",
  1592. + atomic_read(&tcon->num_renames),
  1593. + atomic_read(&tcon->num_t2renames));
  1594. + buf += item_length;
  1595. + length += item_length;
  1596. + }
  1597. + read_unlock(&GlobalSMBSeslock);
  1598. +
  1599. + buf += sprintf(buf,"\n");
  1600. + length++;
  1601. +
  1602. + if(offset + count >= length)
  1603. + *eof = 1;
  1604. + if(length < offset) {
  1605. + *eof = 1;
  1606. + return 0;
  1607. + } else {
  1608. + length = length - offset;
  1609. + }
  1610. + if (length > count)
  1611. + length = count;
  1612. +
  1613. + return length;
  1614. +}
  1615. +#endif
  1616. +
  1617. +struct proc_dir_entry *proc_fs_cifs;
  1618. +read_proc_t cifs_txanchor_read;
  1619. +static read_proc_t cifsFYI_read;
  1620. +static write_proc_t cifsFYI_write;
  1621. +static read_proc_t oplockEnabled_read;
  1622. +static write_proc_t oplockEnabled_write;
  1623. +static read_proc_t lookupFlag_read;
  1624. +static write_proc_t lookupFlag_write;
  1625. +static read_proc_t traceSMB_read;
  1626. +static write_proc_t traceSMB_write;
  1627. +static read_proc_t multiuser_mount_read;
  1628. +static write_proc_t multiuser_mount_write;
  1629. +static read_proc_t extended_security_read;
  1630. +static write_proc_t extended_security_write;
  1631. +static read_proc_t ntlmv2_enabled_read;
  1632. +static write_proc_t ntlmv2_enabled_write;
  1633. +static read_proc_t packet_signing_enabled_read;
  1634. +static write_proc_t packet_signing_enabled_write;
  1635. +static read_proc_t quotaEnabled_read;
  1636. +static write_proc_t quotaEnabled_write;
  1637. +static read_proc_t linuxExtensionsEnabled_read;
  1638. +static write_proc_t linuxExtensionsEnabled_write;
  1639. +
  1640. +void
  1641. +cifs_proc_init(void)
  1642. +{
  1643. + struct proc_dir_entry *pde;
  1644. +
  1645. + proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
  1646. + if (proc_fs_cifs == NULL)
  1647. + return;
  1648. +
  1649. + proc_fs_cifs->owner = THIS_MODULE;
  1650. + create_proc_read_entry("DebugData", 0, proc_fs_cifs,
  1651. + cifs_debug_data_read, NULL);
  1652. +
  1653. +#ifdef CONFIG_CIFS_STATS
  1654. + create_proc_read_entry("Stats", 0, proc_fs_cifs,
  1655. + cifs_stats_read, NULL);
  1656. +#endif
  1657. + pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
  1658. + cifsFYI_read, NULL);
  1659. + if (pde)
  1660. + pde->write_proc = cifsFYI_write;
  1661. +
  1662. + pde =
  1663. + create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
  1664. + traceSMB_read, NULL);
  1665. + if (pde)
  1666. + pde->write_proc = traceSMB_write;
  1667. +
  1668. + pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
  1669. + oplockEnabled_read, NULL);
  1670. + if (pde)
  1671. + pde->write_proc = oplockEnabled_write;
  1672. +
  1673. + pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
  1674. + quotaEnabled_read, NULL);
  1675. + if (pde)
  1676. + pde->write_proc = quotaEnabled_write;
  1677. +
  1678. + pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
  1679. + linuxExtensionsEnabled_read, NULL);
  1680. + if (pde)
  1681. + pde->write_proc = linuxExtensionsEnabled_write;
  1682. +
  1683. + pde =
  1684. + create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
  1685. + multiuser_mount_read, NULL);
  1686. + if (pde)
  1687. + pde->write_proc = multiuser_mount_write;
  1688. +
  1689. + pde =
  1690. + create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
  1691. + extended_security_read, NULL);
  1692. + if (pde)
  1693. + pde->write_proc = extended_security_write;
  1694. +
  1695. + pde =
  1696. + create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
  1697. + lookupFlag_read, NULL);
  1698. + if (pde)
  1699. + pde->write_proc = lookupFlag_write;
  1700. +
  1701. + pde =
  1702. + create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
  1703. + ntlmv2_enabled_read, NULL);
  1704. + if (pde)
  1705. + pde->write_proc = ntlmv2_enabled_write;
  1706. +
  1707. + pde =
  1708. + create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
  1709. + packet_signing_enabled_read, NULL);
  1710. + if (pde)
  1711. + pde->write_proc = packet_signing_enabled_write;
  1712. +}
  1713. +
  1714. +void
  1715. +cifs_proc_clean(void)
  1716. +{
  1717. + if (proc_fs_cifs == NULL)
  1718. + return;
  1719. +
  1720. + remove_proc_entry("DebugData", proc_fs_cifs);
  1721. + remove_proc_entry("cifsFYI", proc_fs_cifs);
  1722. + remove_proc_entry("traceSMB", proc_fs_cifs);
  1723. +#ifdef CONFIG_CIFS_STATS
  1724. + remove_proc_entry("Stats", proc_fs_cifs);
  1725. +#endif
  1726. + remove_proc_entry("MultiuserMount", proc_fs_cifs);
  1727. + remove_proc_entry("OplockEnabled", proc_fs_cifs);
  1728. + remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
  1729. + remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
  1730. + remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
  1731. + remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
  1732. + remove_proc_entry("QuotaEnabled",proc_fs_cifs);
  1733. + remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
  1734. + remove_proc_entry("cifs", proc_root_fs);
  1735. +}
  1736. +
  1737. +static int
  1738. +cifsFYI_read(char *page, char **start, off_t off, int count,
  1739. + int *eof, void *data)
  1740. +{
  1741. + int len;
  1742. +
  1743. + len = sprintf(page, "%d\n", cifsFYI);
  1744. +
  1745. + len -= off;
  1746. + *start = page + off;
  1747. +
  1748. + if (len > count)
  1749. + len = count;
  1750. + else
  1751. + *eof = 1;
  1752. +
  1753. + if (len < 0)
  1754. + len = 0;
  1755. +
  1756. + return len;
  1757. +}
  1758. +static int
  1759. +cifsFYI_write(struct file *file, const char *buffer,
  1760. + unsigned long count, void *data)
  1761. +{
  1762. + char c;
  1763. + int rc;
  1764. +
  1765. + rc = get_user(c, buffer);
  1766. + if (rc)
  1767. + return rc;
  1768. + if (c == '0' || c == 'n' || c == 'N')
  1769. + cifsFYI = 0;
  1770. + else if (c == '1' || c == 'y' || c == 'Y')
  1771. + cifsFYI = 1;
  1772. +
  1773. + return count;
  1774. +}
  1775. +
  1776. +static int
  1777. +oplockEnabled_read(char *page, char **start, off_t off,
  1778. + int count, int *eof, void *data)
  1779. +{
  1780. + int len;
  1781. +
  1782. + len = sprintf(page, "%d\n", oplockEnabled);
  1783. +
  1784. + len -= off;
  1785. + *start = page + off;
  1786. +
  1787. + if (len > count)
  1788. + len = count;
  1789. + else
  1790. + *eof = 1;
  1791. +
  1792. + if (len < 0)
  1793. + len = 0;
  1794. +
  1795. + return len;
  1796. +}
  1797. +static int
  1798. +oplockEnabled_write(struct file *file, const char *buffer,
  1799. + unsigned long count, void *data)
  1800. +{
  1801. + char c;
  1802. + int rc;
  1803. +
  1804. + rc = get_user(c, buffer);
  1805. + if (rc)
  1806. + return rc;
  1807. + if (c == '0' || c == 'n' || c == 'N')
  1808. + oplockEnabled = 0;
  1809. + else if (c == '1' || c == 'y' || c == 'Y')
  1810. + oplockEnabled = 1;
  1811. +
  1812. + return count;
  1813. +}
  1814. +
  1815. +static int
  1816. +quotaEnabled_read(char *page, char **start, off_t off,
  1817. + int count, int *eof, void *data)
  1818. +{
  1819. + int len;
  1820. +
  1821. + len = sprintf(page, "%d\n", quotaEnabled);
  1822. +/* could also check if quotas are enabled in kernel
  1823. + as a whole first */
  1824. + len -= off;
  1825. + *start = page + off;
  1826. +
  1827. + if (len > count)
  1828. + len = count;
  1829. + else
  1830. + *eof = 1;
  1831. +
  1832. + if (len < 0)
  1833. + len = 0;
  1834. +
  1835. + return len;
  1836. +}
  1837. +static int
  1838. +quotaEnabled_write(struct file *file, const char *buffer,
  1839. + unsigned long count, void *data)
  1840. +{
  1841. + char c;
  1842. + int rc;
  1843. +
  1844. + rc = get_user(c, buffer);
  1845. + if (rc)
  1846. + return rc;
  1847. + if (c == '0' || c == 'n' || c == 'N')
  1848. + quotaEnabled = 0;
  1849. + else if (c == '1' || c == 'y' || c == 'Y')
  1850. + quotaEnabled = 1;
  1851. +
  1852. + return count;
  1853. +}
  1854. +
  1855. +static int
  1856. +linuxExtensionsEnabled_read(char *page, char **start, off_t off,
  1857. + int count, int *eof, void *data)
  1858. +{
  1859. + int len;
  1860. +
  1861. + len = sprintf(page, "%d\n", linuxExtEnabled);
  1862. +/* could also check if quotas are enabled in kernel
  1863. + as a whole first */
  1864. + len -= off;
  1865. + *start = page + off;
  1866. +
  1867. + if (len > count)
  1868. + len = count;
  1869. + else
  1870. + *eof = 1;
  1871. +
  1872. + if (len < 0)
  1873. + len = 0;
  1874. +
  1875. + return len;
  1876. +}
  1877. +static int
  1878. +linuxExtensionsEnabled_write(struct file *file, const char *buffer,
  1879. + unsigned long count, void *data)
  1880. +{
  1881. + char c;
  1882. + int rc;
  1883. +
  1884. + rc = get_user(c, buffer);
  1885. + if (rc)
  1886. + return rc;
  1887. + if (c == '0' || c == 'n' || c == 'N')
  1888. + linuxExtEnabled = 0;
  1889. + else if (c == '1' || c == 'y' || c == 'Y')
  1890. + linuxExtEnabled = 1;
  1891. +
  1892. + return count;
  1893. +}
  1894. +
  1895. +
  1896. +static int
  1897. +lookupFlag_read(char *page, char **start, off_t off,
  1898. + int count, int *eof, void *data)
  1899. +{
  1900. + int len;
  1901. +
  1902. + len = sprintf(page, "%d\n", lookupCacheEnabled);
  1903. +
  1904. + len -= off;
  1905. + *start = page + off;
  1906. +
  1907. + if (len > count)
  1908. + len = count;
  1909. + else
  1910. + *eof = 1;
  1911. +
  1912. + if (len < 0)
  1913. + len = 0;
  1914. +
  1915. + return len;
  1916. +}
  1917. +static int
  1918. +lookupFlag_write(struct file *file, const char *buffer,
  1919. + unsigned long count, void *data)
  1920. +{
  1921. + char c;
  1922. + int rc;
  1923. +
  1924. + rc = get_user(c, buffer);
  1925. + if (rc)
  1926. + return rc;
  1927. + if (c == '0' || c == 'n' || c == 'N')
  1928. + lookupCacheEnabled = 0;
  1929. + else if (c == '1' || c == 'y' || c == 'Y')
  1930. + lookupCacheEnabled = 1;
  1931. +
  1932. + return count;
  1933. +}
  1934. +static int
  1935. +traceSMB_read(char *page, char **start, off_t off, int count,
  1936. + int *eof, void *data)
  1937. +{
  1938. + int len;
  1939. +
  1940. + len = sprintf(page, "%d\n", traceSMB);
  1941. +
  1942. + len -= off;
  1943. + *start = page + off;
  1944. +
  1945. + if (len > count)
  1946. + len = count;
  1947. + else
  1948. + *eof = 1;
  1949. +
  1950. + if (len < 0)
  1951. + len = 0;
  1952. +
  1953. + return len;
  1954. +}
  1955. +static int
  1956. +traceSMB_write(struct file *file, const char *buffer,
  1957. + unsigned long count, void *data)
  1958. +{
  1959. + char c;
  1960. + int rc;
  1961. +
  1962. + rc = get_user(c, buffer);
  1963. + if (rc)
  1964. + return rc;
  1965. + if (c == '0' || c == 'n' || c == 'N')
  1966. + traceSMB = 0;
  1967. + else if (c == '1' || c == 'y' || c == 'Y')
  1968. + traceSMB = 1;
  1969. +
  1970. + return count;
  1971. +}
  1972. +
  1973. +static int
  1974. +multiuser_mount_read(char *page, char **start, off_t off,
  1975. + int count, int *eof, void *data)
  1976. +{
  1977. + int len;
  1978. +
  1979. + len = sprintf(page, "%d\n", multiuser_mount);
  1980. +
  1981. + len -= off;
  1982. + *start = page + off;
  1983. +
  1984. + if (len > count)
  1985. + len = count;
  1986. + else
  1987. + *eof = 1;
  1988. +
  1989. + if (len < 0)
  1990. + len = 0;
  1991. +
  1992. + return len;
  1993. +}
  1994. +static int
  1995. +multiuser_mount_write(struct file *file, const char *buffer,
  1996. + unsigned long count, void *data)
  1997. +{
  1998. + char c;
  1999. + int rc;
  2000. +
  2001. + rc = get_user(c, buffer);
  2002. + if (rc)
  2003. + return rc;
  2004. + if (c == '0' || c == 'n' || c == 'N')
  2005. + multiuser_mount = 0;
  2006. + else if (c == '1' || c == 'y' || c == 'Y')
  2007. + multiuser_mount = 1;
  2008. +
  2009. + return count;
  2010. +}
  2011. +
  2012. +static int
  2013. +extended_security_read(char *page, char **start, off_t off,
  2014. + int count, int *eof, void *data)
  2015. +{
  2016. + int len;
  2017. +
  2018. + len = sprintf(page, "%d\n", extended_security);
  2019. +
  2020. + len -= off;
  2021. + *start = page + off;
  2022. +
  2023. + if (len > count)
  2024. + len = count;
  2025. + else
  2026. + *eof = 1;
  2027. +
  2028. + if (len < 0)
  2029. + len = 0;
  2030. +
  2031. + return len;
  2032. +}
  2033. +static int
  2034. +extended_security_write(struct file *file, const char *buffer,
  2035. + unsigned long count, void *data)
  2036. +{
  2037. + char c;
  2038. + int rc;
  2039. +
  2040. + rc = get_user(c, buffer);
  2041. + if (rc)
  2042. + return rc;
  2043. + if (c == '0' || c == 'n' || c == 'N')
  2044. + extended_security = 0;
  2045. + else if (c == '1' || c == 'y' || c == 'Y')
  2046. + extended_security = 1;
  2047. +
  2048. + return count;
  2049. +}
  2050. +
  2051. +static int
  2052. +ntlmv2_enabled_read(char *page, char **start, off_t off,
  2053. + int count, int *eof, void *data)
  2054. +{
  2055. + int len;
  2056. +
  2057. + len = sprintf(page, "%d\n", ntlmv2_support);
  2058. +
  2059. + len -= off;
  2060. + *start = page + off;
  2061. +
  2062. + if (len > count)
  2063. + len = count;
  2064. + else
  2065. + *eof = 1;
  2066. +
  2067. + if (len < 0)
  2068. + len = 0;
  2069. +
  2070. + return len;
  2071. +}
  2072. +static int
  2073. +ntlmv2_enabled_write(struct file *file, const char *buffer,
  2074. + unsigned long count, void *data)
  2075. +{
  2076. + char c;
  2077. + int rc;
  2078. +
  2079. + rc = get_user(c, buffer);
  2080. + if (rc)
  2081. + return rc;
  2082. + if (c == '0' || c == 'n' || c == 'N')
  2083. + ntlmv2_support = 0;
  2084. + else if (c == '1' || c == 'y' || c == 'Y')
  2085. + ntlmv2_support = 1;
  2086. +
  2087. + return count;
  2088. +}
  2089. +
  2090. +static int
  2091. +packet_signing_enabled_read(char *page, char **start, off_t off,
  2092. + int count, int *eof, void *data)
  2093. +{
  2094. + int len;
  2095. +
  2096. + len = sprintf(page, "%d\n", sign_CIFS_PDUs);
  2097. +
  2098. + len -= off;
  2099. + *start = page + off;
  2100. +
  2101. + if (len > count)
  2102. + len = count;
  2103. + else
  2104. + *eof = 1;
  2105. +
  2106. + if (len < 0)
  2107. + len = 0;
  2108. +
  2109. + return len;
  2110. +}
  2111. +static int
  2112. +packet_signing_enabled_write(struct file *file, const char *buffer,
  2113. + unsigned long count, void *data)
  2114. +{
  2115. + char c;
  2116. + int rc;
  2117. +
  2118. + rc = get_user(c, buffer);
  2119. + if (rc)
  2120. + return rc;
  2121. + if (c == '0' || c == 'n' || c == 'N')
  2122. + sign_CIFS_PDUs = 0;
  2123. + else if (c == '1' || c == 'y' || c == 'Y')
  2124. + sign_CIFS_PDUs = 1;
  2125. + else if (c == '2')
  2126. + sign_CIFS_PDUs = 2;
  2127. +
  2128. + return count;
  2129. +}
  2130. +
  2131. +
  2132. +#endif
  2133. --- /dev/null
  2134. +++ b/fs/cifs/cifs_debug.h
  2135. @@ -0,0 +1,66 @@
  2136. +/*
  2137. + *
  2138. + * Copyright (c) International Business Machines Corp., 2000,2002
  2139. + * Modified by Steve French ([email protected])
  2140. + *
  2141. + * This program is free software; you can redistribute it and/or modify
  2142. + * it under the terms of the GNU General Public License as published by
  2143. + * the Free Software Foundation; either version 2 of the License, or
  2144. + * (at your option) any later version.
  2145. + *
  2146. + * This program is distributed in the hope that it will be useful,
  2147. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2148. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  2149. + * the GNU General Public License for more details.
  2150. + *
  2151. + * You should have received a copy of the GNU General Public License
  2152. + * along with this program; if not, write to the Free Software
  2153. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  2154. + *
  2155. +*/
  2156. +#define CIFS_DEBUG /* BB temporary */
  2157. +
  2158. +#ifndef _H_CIFS_DEBUG
  2159. +#define _H_CIFS_DEBUG
  2160. +
  2161. +void cifs_dump_mem(char *label, void *data, int length);
  2162. +extern int traceSMB; /* flag which enables the function below */
  2163. +void dump_smb(struct smb_hdr *, int);
  2164. +
  2165. +/*
  2166. + * debug ON
  2167. + * --------
  2168. + */
  2169. +#ifdef CIFS_DEBUG
  2170. +
  2171. +
  2172. +/* information message: e.g., configuration, major event */
  2173. +extern int cifsFYI;
  2174. +#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
  2175. +
  2176. +#define cFYI(button,prspec) if (button) cifsfyi prspec
  2177. +
  2178. +#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
  2179. +
  2180. +/* debug event message: */
  2181. +extern int cifsERROR;
  2182. +
  2183. +#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
  2184. +
  2185. +/* error event message: e.g., i/o error */
  2186. +#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
  2187. +
  2188. +#define cERROR(button, prspec) if (button) cifserror prspec
  2189. +
  2190. +/*
  2191. + * debug OFF
  2192. + * ---------
  2193. + */
  2194. +#else /* _CIFS_DEBUG */
  2195. +#define cERROR(button,prspec)
  2196. +#define cEVENT(format,arg...)
  2197. +#define cFYI(button, prspec)
  2198. +#define cifserror(format,arg...)
  2199. +#endif /* _CIFS_DEBUG */
  2200. +
  2201. +#endif /* _H_CIFS_DEBUG */
  2202. --- /dev/null
  2203. +++ b/fs/cifs/cifsencrypt.c
  2204. @@ -0,0 +1,204 @@
  2205. +/*
  2206. + * fs/cifs/cifsencrypt.c
  2207. + *
  2208. + * Copyright (C) International Business Machines Corp., 2003
  2209. + * Author(s): Steve French ([email protected])
  2210. + *
  2211. + * This library is free software; you can redistribute it and/or modify
  2212. + * it under the terms of the GNU Lesser General Public License as published
  2213. + * by the Free Software Foundation; either version 2.1 of the License, or
  2214. + * (at your option) any later version.
  2215. + *
  2216. + * This library is distributed in the hope that it will be useful,
  2217. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2218. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  2219. + * the GNU Lesser General Public License for more details.
  2220. + *
  2221. + * You should have received a copy of the GNU Lesser General Public License
  2222. + * along with this library; if not, write to the Free Software
  2223. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  2224. + */
  2225. +
  2226. +#include <linux/fs.h>
  2227. +#include "cifspdu.h"
  2228. +#include "cifsglob.h"
  2229. +#include "cifs_debug.h"
  2230. +#include "md5.h"
  2231. +#include "cifs_unicode.h"
  2232. +
  2233. +/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
  2234. +/* the 16 byte signature must be allocated by the caller */
  2235. +/* Note we only use the 1st eight bytes */
  2236. +/* Note that the smb header signature field on input contains the
  2237. + sequence number before this function is called */
  2238. +
  2239. +extern void mdfour(unsigned char *out, unsigned char *in, int n);
  2240. +extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
  2241. +
  2242. +static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
  2243. +{
  2244. + struct MD5Context context;
  2245. +
  2246. + if((cifs_pdu == NULL) || (signature == NULL))
  2247. + return -EINVAL;
  2248. +
  2249. + MD5Init(&context);
  2250. + MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
  2251. + MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
  2252. + MD5Final(signature,&context);
  2253. + return 0;
  2254. +}
  2255. +
  2256. +int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
  2257. + __u32 * pexpected_response_sequence_number)
  2258. +{
  2259. + int rc = 0;
  2260. + char smb_signature[20];
  2261. +
  2262. + /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
  2263. + /* BB remember to add code to save expected sequence number in midQ entry BB */
  2264. +
  2265. + if((cifs_pdu == NULL) || (ses == NULL))
  2266. + return -EINVAL;
  2267. +
  2268. + if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
  2269. + return rc;
  2270. +
  2271. + spin_lock(&GlobalMid_Lock);
  2272. + cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
  2273. + cifs_pdu->Signature.Sequence.Reserved = 0;
  2274. +
  2275. + *pexpected_response_sequence_number = ses->sequence_number++;
  2276. + ses->sequence_number++;
  2277. + spin_unlock(&GlobalMid_Lock);
  2278. +
  2279. + rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
  2280. + if(rc)
  2281. + memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
  2282. + else
  2283. + memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
  2284. +
  2285. + return rc;
  2286. +}
  2287. +
  2288. +int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
  2289. + __u32 expected_sequence_number)
  2290. +{
  2291. + unsigned int rc;
  2292. + char server_response_sig[8];
  2293. + char what_we_think_sig_should_be[20];
  2294. +
  2295. + if((cifs_pdu == NULL) || (mac_key == NULL))
  2296. + return -EINVAL;
  2297. +
  2298. + if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
  2299. + return 0;
  2300. +
  2301. + if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
  2302. + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
  2303. + if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
  2304. + return 0;
  2305. + }
  2306. +
  2307. + /* BB what if signatures are supposed to be on for session but server does not
  2308. + send one? BB */
  2309. +
  2310. + /* Do not need to verify session setups with signature "BSRSPYL " */
  2311. + if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
  2312. + cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
  2313. +
  2314. + expected_sequence_number = cpu_to_le32(expected_sequence_number);
  2315. +
  2316. + /* save off the origiginal signature so we can modify the smb and check
  2317. + its signature against what the server sent */
  2318. + memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
  2319. +
  2320. + cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
  2321. + cifs_pdu->Signature.Sequence.Reserved = 0;
  2322. +
  2323. + rc = cifs_calculate_signature(cifs_pdu, mac_key,
  2324. + what_we_think_sig_should_be);
  2325. +
  2326. + if(rc)
  2327. + return rc;
  2328. +
  2329. +
  2330. +/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
  2331. +
  2332. + if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
  2333. + return -EACCES;
  2334. + else
  2335. + return 0;
  2336. +
  2337. +}
  2338. +
  2339. +/* We fill in key by putting in 40 byte array which was allocated by caller */
  2340. +int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
  2341. +{
  2342. + char temp_key[16];
  2343. + if ((key == NULL) || (rn == NULL))
  2344. + return -EINVAL;
  2345. +
  2346. + E_md4hash(password, temp_key);
  2347. + mdfour(key,temp_key,16);
  2348. + memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
  2349. + return 0;
  2350. +}
  2351. +
  2352. +int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
  2353. +{
  2354. + char temp_hash[16];
  2355. + struct HMACMD5Context ctx;
  2356. + char * ucase_buf;
  2357. + wchar_t * unicode_buf;
  2358. + unsigned int i,user_name_len,dom_name_len;
  2359. +
  2360. + if(ses)
  2361. + return -EINVAL;
  2362. +
  2363. + E_md4hash(ses->password, temp_hash);
  2364. +
  2365. + hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
  2366. + user_name_len = strlen(ses->userName);
  2367. + if(user_name_len > MAX_USERNAME_SIZE)
  2368. + return -EINVAL;
  2369. + dom_name_len = strlen(ses->domainName);
  2370. + if(dom_name_len > MAX_USERNAME_SIZE)
  2371. + return -EINVAL;
  2372. +
  2373. + ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
  2374. + unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
  2375. +
  2376. + for(i=0;i<user_name_len;i++)
  2377. + ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
  2378. + ucase_buf[i] = 0;
  2379. + user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
  2380. + unicode_buf[user_name_len] = 0;
  2381. + user_name_len++;
  2382. +
  2383. + for(i=0;i<dom_name_len;i++)
  2384. + ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
  2385. + ucase_buf[i] = 0;
  2386. + dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
  2387. +
  2388. + unicode_buf[user_name_len + dom_name_len] = 0;
  2389. + hmac_md5_update((const unsigned char *) unicode_buf,
  2390. + (user_name_len+dom_name_len)*2,&ctx);
  2391. +
  2392. + hmac_md5_final(ses->mac_signing_key,&ctx);
  2393. + kfree(ucase_buf);
  2394. + kfree(unicode_buf);
  2395. + return 0;
  2396. +}
  2397. +void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
  2398. +{
  2399. + struct HMACMD5Context context;
  2400. + memcpy(v2_session_response + 8, ses->server->cryptKey,8);
  2401. + /* gen_blob(v2_session_response + 16); */
  2402. + hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
  2403. +
  2404. + hmac_md5_update(ses->server->cryptKey,8,&context);
  2405. +/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
  2406. +
  2407. + hmac_md5_final(v2_session_response,&context);
  2408. +}
  2409. --- /dev/null
  2410. +++ b/fs/cifs/cifserr.c
  2411. @@ -0,0 +1,70 @@
  2412. +/*
  2413. + * fs/cifserr.c
  2414. + *
  2415. + * Copyright (c) International Business Machines Corp., 2002
  2416. + * Author(s): Steve French ([email protected])
  2417. + *
  2418. + * This library is free software; you can redistribute it and/or modify
  2419. + * it under the terms of the GNU Lesser General Public License as published
  2420. + * by the Free Software Foundation; either version 2.1 of the License, or
  2421. + * (at your option) any later version.
  2422. + *
  2423. + * This library is distributed in the hope that it will be useful,
  2424. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2425. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  2426. + * the GNU Lesser General Public License for more details.
  2427. + *
  2428. + * You should have received a copy of the GNU Lesser General Public License
  2429. + * along with this library; if not, write to the Free Software
  2430. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  2431. + */
  2432. +
  2433. +#include <linux/errno.h>
  2434. +#include <linux/fs.h>
  2435. +#include <linux/smbno.h>
  2436. +#include "cifsfs.h"
  2437. +
  2438. +int map_cifs_error(int error_class, int error_code,
  2439. + int status_codes_negotiated)
  2440. +{
  2441. +
  2442. +
  2443. + if (status_codes_negotiated) {
  2444. + switch (error_code) {
  2445. + default:
  2446. + return EIO;
  2447. + }
  2448. + } else
  2449. + switch (error_class) {
  2450. + case SUCCESS:
  2451. + return 0;
  2452. +
  2453. + case ERRDOS:
  2454. + switch (error_code) {
  2455. + case ERRbadfunc:
  2456. + return EINVAL;
  2457. + default:
  2458. + return EIO;
  2459. + }
  2460. +
  2461. + case ERRSRV:
  2462. + switch (error_code) {
  2463. + default:
  2464. + return EIO;
  2465. + }
  2466. +
  2467. + case ERRHRD:
  2468. + switch (error_code) {
  2469. + default:
  2470. + return EIO;
  2471. + }
  2472. + default:
  2473. + return EIO;
  2474. + }
  2475. + return 0;
  2476. +}
  2477. +
  2478. +int map_smb_error(int error_class, int error_code)
  2479. +{
  2480. + return map_cifs_error(error_class, error_code, FALSE);
  2481. +}
  2482. --- /dev/null
  2483. +++ b/fs/cifs/cifsfs.c
  2484. @@ -0,0 +1,769 @@
  2485. +/*
  2486. + * fs/cifs/cifsfs.c
  2487. + *
  2488. + * Copyright (C) International Business Machines Corp., 2002,2004
  2489. + * Author(s): Steve French ([email protected])
  2490. + *
  2491. + * Common Internet FileSystem (CIFS) client
  2492. + *
  2493. + * This library is free software; you can redistribute it and/or modify
  2494. + * it under the terms of the GNU Lesser General Public License as published
  2495. + * by the Free Software Foundation; either version 2.1 of the License, or
  2496. + * (at your option) any later version.
  2497. + *
  2498. + * This library is distributed in the hope that it will be useful,
  2499. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2500. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  2501. + * the GNU Lesser General Public License for more details.
  2502. + *
  2503. + * You should have received a copy of the GNU Lesser General Public License
  2504. + * along with this library; if not, write to the Free Software
  2505. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  2506. + */
  2507. +
  2508. +/* Note that BB means BUGBUG (ie something to fix eventually) */
  2509. +
  2510. +#include <linux/module.h>
  2511. +#include <linux/fs.h>
  2512. +#include <linux/mount.h>
  2513. +#include <linux/slab.h>
  2514. +#include <linux/init.h>
  2515. +#include <linux/version.h>
  2516. +#include <linux/list.h>
  2517. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  2518. +#include <linux/seq_file.h>
  2519. +#endif
  2520. +#include <linux/vfs.h>
  2521. +#include "cifsfs.h"
  2522. +#include "cifspdu.h"
  2523. +#define DECLARE_GLOBALS_HERE
  2524. +#include "cifsglob.h"
  2525. +#include "cifsproto.h"
  2526. +#include "cifs_debug.h"
  2527. +#include "cifs_fs_sb.h"
  2528. +#include <linux/mm.h>
  2529. +#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
  2530. +/* BB when mempool_resize is added back in, we will resize pool on new mount */
  2531. +#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
  2532. +
  2533. +#ifdef CONFIG_CIFS_QUOTA
  2534. +static struct quotactl_ops cifs_quotactl_ops;
  2535. +#endif
  2536. +
  2537. +extern struct file_system_type cifs_fs_type;
  2538. +
  2539. +int cifsFYI = 0;
  2540. +int cifsERROR = 1;
  2541. +int traceSMB = 0;
  2542. +unsigned int oplockEnabled = 1;
  2543. +unsigned int quotaEnabled = 0;
  2544. +unsigned int linuxExtEnabled = 1;
  2545. +unsigned int lookupCacheEnabled = 1;
  2546. +unsigned int multiuser_mount = 0;
  2547. +unsigned int extended_security = 0;
  2548. +unsigned int ntlmv2_support = 0;
  2549. +unsigned int sign_CIFS_PDUs = 1;
  2550. +unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
  2551. +struct task_struct * oplockThread = NULL;
  2552. +
  2553. +extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
  2554. + const char *);
  2555. +extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
  2556. +void cifs_proc_init(void);
  2557. +void cifs_proc_clean(void);
  2558. +
  2559. +static DECLARE_COMPLETION(cifs_oplock_exited);
  2560. +
  2561. +
  2562. +struct super_block *
  2563. +cifs_read_super(struct super_block *sb, void *data, int silent)
  2564. +{
  2565. + struct inode *inode;
  2566. + struct cifs_sb_info *cifs_sb;
  2567. + int rc = 0;
  2568. +
  2569. + sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
  2570. + cifs_sb = CIFS_SB(sb);
  2571. + if(cifs_sb == NULL)
  2572. + return 0;
  2573. + else
  2574. + memset(cifs_sb,0,sizeof(struct cifs_sb_info));
  2575. +
  2576. +
  2577. + rc = cifs_mount(sb, cifs_sb, data, NULL);
  2578. +
  2579. + if (rc) {
  2580. + if (!silent)
  2581. + cERROR(1,
  2582. + ("cifs_mount failed w/return code = %d", rc));
  2583. + goto out_mount_failed;
  2584. + }
  2585. +
  2586. + sb->s_magic = CIFS_MAGIC_NUMBER;
  2587. + sb->s_op = &cifs_super_ops;
  2588. +/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
  2589. + sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
  2590. +#ifdef CONFIG_CIFS_QUOTA
  2591. + sb->s_qcop = &cifs_quotactl_ops;
  2592. +#endif
  2593. + sb->s_blocksize = CIFS_MAX_MSGSIZE;
  2594. + sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
  2595. + inode = iget(sb, ROOT_I);
  2596. +
  2597. + if (!inode) {
  2598. + goto out_no_root;
  2599. + }
  2600. +
  2601. + sb->s_root = d_alloc_root(inode);
  2602. +
  2603. + if (!sb->s_root) {
  2604. + goto out_no_root;
  2605. + }
  2606. +
  2607. + return sb;
  2608. +
  2609. +out_no_root:
  2610. + cERROR(1, ("cifs_read_super: get root inode failed"));
  2611. + if (inode)
  2612. + iput(inode);
  2613. +
  2614. +out_mount_failed:
  2615. + if(cifs_sb->local_nls)
  2616. + unload_nls(cifs_sb->local_nls);
  2617. + sb->s_dev = 0;
  2618. + return 0;
  2619. +}
  2620. +
  2621. +static void
  2622. +cifs_put_super(struct super_block *sb)
  2623. +{
  2624. + int rc = 0;
  2625. + struct cifs_sb_info *cifs_sb;
  2626. +
  2627. + cFYI(1, ("In cifs_put_super"));
  2628. + cifs_sb = CIFS_SB(sb);
  2629. + if(cifs_sb == NULL) {
  2630. + cFYI(1,("Empty cifs superblock info passed to unmount"));
  2631. + return;
  2632. + }
  2633. + rc = cifs_umount(sb, cifs_sb);
  2634. + if (rc) {
  2635. + cERROR(1, ("cifs_umount failed with return code %d", rc));
  2636. + }
  2637. + unload_nls(cifs_sb->local_nls);
  2638. + return;
  2639. +}
  2640. +
  2641. +static int
  2642. +cifs_statfs(struct super_block *sb, struct statfs *buf)
  2643. +{
  2644. + int xid, rc;
  2645. + struct cifs_sb_info *cifs_sb;
  2646. + struct cifsTconInfo *pTcon;
  2647. +
  2648. + xid = GetXid();
  2649. +
  2650. + cifs_sb = CIFS_SB(sb);
  2651. + pTcon = cifs_sb->tcon;
  2652. +
  2653. + buf->f_type = CIFS_MAGIC_NUMBER;
  2654. +
  2655. + /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
  2656. + buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
  2657. + be length of total path, note that some servers may be
  2658. + able to support more than this, but best to be safe
  2659. + since Win2k and others can not handle very long filenames */
  2660. + buf->f_files = 0; /* undefined */
  2661. + buf->f_ffree = 0; /* unlimited */
  2662. +
  2663. + rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
  2664. +
  2665. + /*
  2666. + int f_type;
  2667. + __fsid_t f_fsid;
  2668. + int f_namelen; */
  2669. + /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
  2670. + FreeXid(xid);
  2671. + return 0; /* always return success? what if volume is no longer available? */
  2672. +}
  2673. +
  2674. +static int cifs_permission(struct inode * inode, int mask)
  2675. +{
  2676. + /* the server does permission checks, we do not need to do it here */
  2677. + return 0;
  2678. +}
  2679. +
  2680. +kmem_cache_t *cifs_req_cachep;
  2681. +kmem_cache_t *cifs_mid_cachep;
  2682. +kmem_cache_t *cifs_oplock_cachep;
  2683. +
  2684. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
  2685. +static struct inode *
  2686. +cifs_alloc_inode(struct super_block *sb)
  2687. +{
  2688. + struct cifsInodeInfo *cifs_inode;
  2689. + cifs_inode =
  2690. + (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
  2691. + SLAB_KERNEL);
  2692. + if (!cifs_inode)
  2693. + return NULL;
  2694. + cifs_inode->cifsAttrs = 0x20; /* default */
  2695. + atomic_set(&cifs_inode->inUse, 0);
  2696. + cifs_inode->time = 0;
  2697. + /* Until the file is open and we have gotten oplock
  2698. + info back from the server, can not assume caching of
  2699. + file data or metadata */
  2700. + cifs_inode->clientCanCacheRead = FALSE;
  2701. + cifs_inode->clientCanCacheAll = FALSE;
  2702. + INIT_LIST_HEAD(&cifs_inode->openFileList);
  2703. + return &cifs_inode->vfs_inode;
  2704. +}
  2705. +
  2706. +static void
  2707. +cifs_destroy_inode(struct inode *inode)
  2708. +{
  2709. + kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
  2710. +}
  2711. +#endif
  2712. +
  2713. +/*
  2714. + * cifs_show_options() is for displaying mount options in /proc/mounts.
  2715. + * Not all settable options are displayed but most of the important
  2716. + * ones are.
  2717. + */
  2718. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  2719. +static int
  2720. +cifs_show_options(struct seq_file *s, struct vfsmount *m)
  2721. +{
  2722. + struct cifs_sb_info *cifs_sb;
  2723. +
  2724. + cifs_sb = CIFS_SB(m->mnt_sb);
  2725. +
  2726. + if (cifs_sb) {
  2727. + if (cifs_sb->tcon) {
  2728. + seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
  2729. + if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
  2730. + seq_printf(s, ",username=%s",
  2731. + cifs_sb->tcon->ses->userName);
  2732. + if(cifs_sb->tcon->ses->domainName)
  2733. + seq_printf(s, ",domain=%s",
  2734. + cifs_sb->tcon->ses->domainName);
  2735. + }
  2736. + seq_printf(s, ",rsize=%d",cifs_sb->rsize);
  2737. + seq_printf(s, ",wsize=%d",cifs_sb->wsize);
  2738. + }
  2739. + return 0;
  2740. +}
  2741. +#endif
  2742. +
  2743. +#ifdef CONFIG_CIFS_QUOTA
  2744. +int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
  2745. + struct fs_disk_quota * pdquota)
  2746. +{
  2747. + int xid;
  2748. + int rc = 0;
  2749. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  2750. + struct cifsTconInfo *pTcon;
  2751. +
  2752. + if(cifs_sb)
  2753. + pTcon = cifs_sb->tcon;
  2754. + else
  2755. + return -EIO;
  2756. +
  2757. +
  2758. + xid = GetXid();
  2759. + if(pTcon) {
  2760. + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
  2761. + } else {
  2762. + return -EIO;
  2763. + }
  2764. +
  2765. + FreeXid(xid);
  2766. + return rc;
  2767. +}
  2768. +
  2769. +int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
  2770. + struct fs_disk_quota * pdquota)
  2771. +{
  2772. + int xid;
  2773. + int rc = 0;
  2774. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  2775. + struct cifsTconInfo *pTcon;
  2776. +
  2777. + if(cifs_sb)
  2778. + pTcon = cifs_sb->tcon;
  2779. + else
  2780. + return -EIO;
  2781. +
  2782. + xid = GetXid();
  2783. + if(pTcon) {
  2784. + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
  2785. + } else {
  2786. + rc = -EIO;
  2787. + }
  2788. +
  2789. + FreeXid(xid);
  2790. + return rc;
  2791. +}
  2792. +
  2793. +int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
  2794. +{
  2795. + int xid;
  2796. + int rc = 0;
  2797. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  2798. + struct cifsTconInfo *pTcon;
  2799. +
  2800. + if(cifs_sb)
  2801. + pTcon = cifs_sb->tcon;
  2802. + else
  2803. + return -EIO;
  2804. +
  2805. + xid = GetXid();
  2806. + if(pTcon) {
  2807. + cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
  2808. + } else {
  2809. + rc = -EIO;
  2810. + }
  2811. +
  2812. + FreeXid(xid);
  2813. + return rc;
  2814. +}
  2815. +
  2816. +int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
  2817. +{
  2818. + int xid;
  2819. + int rc = 0;
  2820. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  2821. + struct cifsTconInfo *pTcon;
  2822. +
  2823. + if(cifs_sb) {
  2824. + pTcon = cifs_sb->tcon;
  2825. + } else {
  2826. + return -EIO;
  2827. + }
  2828. + xid = GetXid();
  2829. + if(pTcon) {
  2830. + cFYI(1,("pqstats %p",qstats));
  2831. + } else {
  2832. + rc = -EIO;
  2833. + }
  2834. +
  2835. + FreeXid(xid);
  2836. + return rc;
  2837. +}
  2838. +
  2839. +static struct quotactl_ops cifs_quotactl_ops = {
  2840. + .set_xquota = cifs_xquota_set,
  2841. + .get_xquota = cifs_xquota_set,
  2842. + .set_xstate = cifs_xstate_set,
  2843. + .get_xstate = cifs_xstate_get,
  2844. +};
  2845. +#endif
  2846. +
  2847. +static int cifs_remount(struct super_block *sb, int *flags, char *data)
  2848. +{
  2849. + *flags |= MS_NODIRATIME;
  2850. + return 0;
  2851. +}
  2852. +
  2853. +struct super_operations cifs_super_ops = {
  2854. + .read_inode = cifs_read_inode,
  2855. + .put_super = cifs_put_super,
  2856. + .statfs = cifs_statfs,
  2857. +/* .alloc_inode = cifs_alloc_inode,
  2858. + .destroy_inode = cifs_destroy_inode, */
  2859. +/* .drop_inode = generic_delete_inode,
  2860. + .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
  2861. + unless later we add lazy close of inodes or unless the kernel forgets to call
  2862. + us with the same number of releases (closes) as opens */
  2863. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  2864. + .show_options = cifs_show_options,
  2865. +#endif
  2866. +/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
  2867. +};
  2868. +
  2869. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
  2870. +static struct super_block *
  2871. +cifs_get_sb(struct file_system_type *fs_type,
  2872. + int flags, const char *dev_name, void *data)
  2873. +{
  2874. + int rc;
  2875. + struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
  2876. +
  2877. + cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
  2878. +
  2879. + if (IS_ERR(sb))
  2880. + return sb;
  2881. +
  2882. + sb->s_flags = flags;
  2883. +
  2884. + rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
  2885. + if (rc) {
  2886. + up_write(&sb->s_umount);
  2887. + deactivate_super(sb);
  2888. + return ERR_PTR(rc);
  2889. + }
  2890. + sb->s_flags |= MS_ACTIVE;
  2891. + return sb;
  2892. +}
  2893. +#endif
  2894. +
  2895. +static ssize_t
  2896. +cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
  2897. + loff_t * poffset)
  2898. +{
  2899. + if(file == NULL)
  2900. + return -EIO;
  2901. + else if(file->f_dentry == NULL)
  2902. + return -EIO;
  2903. + else if(file->f_dentry->d_inode == NULL)
  2904. + return -EIO;
  2905. +
  2906. + if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
  2907. + return generic_file_read(file,read_data,read_size,poffset);
  2908. + } else {
  2909. + /* BB do we need to lock inode from here until after invalidate? */
  2910. +/* if(file->f_dentry->d_inode->i_mapping) {
  2911. + filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
  2912. + filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
  2913. + }*/
  2914. +/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
  2915. +
  2916. + /* BB we should make timer configurable - perhaps
  2917. + by simply calling cifs_revalidate here */
  2918. + /* invalidate_remote_inode(file->f_dentry->d_inode);*/
  2919. + return generic_file_read(file,read_data,read_size,poffset);
  2920. + }
  2921. +}
  2922. +
  2923. +static ssize_t
  2924. +cifs_write_wrapper(struct file * file, const char *write_data,
  2925. + size_t write_size, loff_t * poffset)
  2926. +{
  2927. + ssize_t written;
  2928. +
  2929. + if(file == NULL)
  2930. + return -EIO;
  2931. + else if(file->f_dentry == NULL)
  2932. + return -EIO;
  2933. + else if(file->f_dentry->d_inode == NULL)
  2934. + return -EIO;
  2935. +
  2936. + /* check whether we can cache writes locally */
  2937. + written = generic_file_write(file,write_data,write_size,poffset);
  2938. + if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
  2939. + if(file->f_dentry->d_inode->i_mapping) {
  2940. + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
  2941. + }
  2942. + }
  2943. + return written;
  2944. +}
  2945. +
  2946. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
  2947. +static struct file_system_type cifs_fs_type = {
  2948. + .owner = THIS_MODULE,
  2949. + .name = "cifs",
  2950. + .get_sb = cifs_get_sb,
  2951. + .kill_sb = kill_anon_super,
  2952. + /* .fs_flags */
  2953. +};
  2954. +#endif
  2955. +
  2956. +static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
  2957. +
  2958. +
  2959. +struct inode_operations cifs_dir_inode_ops = {
  2960. + .create = cifs_create,
  2961. + .lookup = cifs_lookup,
  2962. + .unlink = cifs_unlink,
  2963. + .link = cifs_hardlink,
  2964. + .mkdir = cifs_mkdir,
  2965. + .rmdir = cifs_rmdir,
  2966. + .rename = cifs_rename,
  2967. + .permission = cifs_permission,
  2968. + .revalidate = cifs_revalidate,
  2969. + .setattr = cifs_setattr,
  2970. + .symlink = cifs_symlink,
  2971. + .mknod = cifs_mknod,
  2972. +};
  2973. +
  2974. +struct inode_operations cifs_file_inode_ops = {
  2975. + .revalidate = cifs_revalidate,
  2976. + .setattr = cifs_setattr,
  2977. +/* .getattr = cifs_getattr,*/
  2978. + .rename = cifs_rename,
  2979. + .permission = cifs_permission,
  2980. +#ifdef CONFIG_CIFS_XATTR
  2981. + .setxattr = cifs_setxattr,
  2982. + .getxattr = cifs_getxattr,
  2983. + .listxattr = cifs_listxattr,
  2984. + .removexattr = cifs_removexattr,
  2985. +#endif
  2986. +};
  2987. +
  2988. +struct inode_operations cifs_symlink_inode_ops = {
  2989. + .readlink = cifs_readlink,
  2990. + .follow_link = cifs_follow_link,
  2991. + .permission = cifs_permission,
  2992. + /* BB add the following two eventually */
  2993. + /* revalidate: cifs_revalidate,
  2994. + setattr: cifs_notify_change, *//* BB do we need notify change */
  2995. +#ifdef CONFIG_CIFS_XATTR
  2996. + .setxattr = cifs_setxattr,
  2997. + .getxattr = cifs_getxattr,
  2998. + .listxattr = cifs_listxattr,
  2999. + .removexattr = cifs_removexattr,
  3000. +#endif
  3001. +};
  3002. +
  3003. +struct file_operations cifs_file_ops = {
  3004. + .read = cifs_read_wrapper,
  3005. + .write = cifs_write_wrapper,
  3006. + .open = cifs_open,
  3007. + .release = cifs_close,
  3008. + .lock = cifs_lock,
  3009. + .fsync = cifs_fsync,
  3010. + .flush = cifs_flush,
  3011. + .mmap = cifs_file_mmap,
  3012. +/* .sendfile = generic_file_sendfile,*/
  3013. +#ifdef CONFIG_CIFS_FCNTL
  3014. + .fcntl = cifs_fcntl,
  3015. +#endif
  3016. +};
  3017. +
  3018. +struct file_operations cifs_dir_ops = {
  3019. + .readdir = cifs_readdir,
  3020. + .release = cifs_closedir,
  3021. + .read = generic_read_dir,
  3022. +#ifdef CONFIG_CIFS_FCNTL
  3023. + .fcntl = cifs_fcntl,
  3024. +#endif
  3025. +};
  3026. +/*
  3027. +static void
  3028. +cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
  3029. +{
  3030. + struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
  3031. +
  3032. + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
  3033. + SLAB_CTOR_CONSTRUCTOR) {
  3034. + inode_init_once(&cifsi->vfs_inode);
  3035. + INIT_LIST_HEAD(&cifsi->lockList);
  3036. + }
  3037. +}
  3038. +
  3039. +static int
  3040. +cifs_init_inodecache(void)
  3041. +{
  3042. + cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
  3043. + sizeof (struct cifsInodeInfo),
  3044. + 0, SLAB_HWCACHE_ALIGN,
  3045. + cifs_init_once, NULL);
  3046. + if (cifs_inode_cachep == NULL)
  3047. + return -ENOMEM;
  3048. +
  3049. +
  3050. + return 0;
  3051. +}
  3052. +
  3053. +static void
  3054. +cifs_destroy_inodecache(void)
  3055. +{
  3056. + if (kmem_cache_destroy(cifs_inode_cachep))
  3057. + printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
  3058. +} */
  3059. +
  3060. +static int
  3061. +cifs_init_request_bufs(void)
  3062. +{
  3063. + cifs_req_cachep = kmem_cache_create("cifs_request",
  3064. + CIFS_MAX_MSGSIZE +
  3065. + MAX_CIFS_HDR_SIZE, 0,
  3066. + SLAB_HWCACHE_ALIGN, NULL, NULL);
  3067. + if (cifs_req_cachep == NULL)
  3068. + return -ENOMEM;
  3069. +
  3070. + return 0;
  3071. +}
  3072. +
  3073. +static void
  3074. +cifs_destroy_request_bufs(void)
  3075. +{
  3076. + if (kmem_cache_destroy(cifs_req_cachep))
  3077. + printk(KERN_WARNING
  3078. + "cifs_destroy_request_cache: error not all structures were freed\n");
  3079. +}
  3080. +
  3081. +static int
  3082. +cifs_init_mids(void)
  3083. +{
  3084. + cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
  3085. + sizeof (struct mid_q_entry), 0,
  3086. + SLAB_HWCACHE_ALIGN, NULL, NULL);
  3087. + if (cifs_mid_cachep == NULL)
  3088. + return -ENOMEM;
  3089. + cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
  3090. + sizeof (struct oplock_q_entry), 0,
  3091. + SLAB_HWCACHE_ALIGN, NULL, NULL);
  3092. + if (cifs_oplock_cachep == NULL) {
  3093. + kmem_cache_destroy(cifs_mid_cachep);
  3094. + return -ENOMEM;
  3095. + }
  3096. +
  3097. + return 0;
  3098. +}
  3099. +
  3100. +static void
  3101. +cifs_destroy_mids(void)
  3102. +{
  3103. + if (kmem_cache_destroy(cifs_mid_cachep))
  3104. + printk(KERN_WARNING
  3105. + "cifs_destroy_mids: error not all structures were freed\n");
  3106. + if (kmem_cache_destroy(cifs_oplock_cachep))
  3107. + printk(KERN_WARNING
  3108. + "error not all oplock structures were freed\n");
  3109. +}
  3110. +
  3111. +static int cifs_oplock_thread(void * dummyarg)
  3112. +{
  3113. + struct oplock_q_entry * oplock_item;
  3114. + struct cifsTconInfo *pTcon;
  3115. + struct inode * inode;
  3116. + __u16 netfid;
  3117. + int rc = 0;
  3118. +
  3119. + daemonize();
  3120. + sprintf(current->comm,"cifsoplockd");
  3121. +
  3122. + oplockThread = current;
  3123. + do {
  3124. + set_current_state(TASK_INTERRUPTIBLE);
  3125. +
  3126. + schedule_timeout(1*HZ);
  3127. + spin_lock(&GlobalMid_Lock);
  3128. + if(list_empty(&GlobalOplock_Q)) {
  3129. + spin_unlock(&GlobalMid_Lock);
  3130. + set_current_state(TASK_INTERRUPTIBLE);
  3131. + schedule_timeout(39*HZ);
  3132. + } else {
  3133. + oplock_item = list_entry(GlobalOplock_Q.next,
  3134. + struct oplock_q_entry, qhead);
  3135. + if(oplock_item) {
  3136. + cFYI(1,("found oplock item to write out"));
  3137. + pTcon = oplock_item->tcon;
  3138. + inode = oplock_item->pinode;
  3139. + netfid = oplock_item->netfid;
  3140. + spin_unlock(&GlobalMid_Lock);
  3141. + DeleteOplockQEntry(oplock_item);
  3142. + /* can not grab inode sem here since it would
  3143. + deadlock when oplock received on delete
  3144. + since vfs_unlink holds the i_sem across
  3145. + the call */
  3146. + /* down(&inode->i_sem);*/
  3147. + if (S_ISREG(inode->i_mode)) {
  3148. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
  3149. + rc = filemap_fdatasync(inode->i_mapping);
  3150. + if(rc)
  3151. + CIFS_I(inode)->write_behind_rc = rc;
  3152. +#else
  3153. + filemap_fdatasync(inode->i_mapping);
  3154. +#endif
  3155. + if(CIFS_I(inode)->clientCanCacheRead == 0)
  3156. + invalidate_inode_pages(inode);
  3157. + } else
  3158. + rc = 0;
  3159. + /* releasing a stale oplock after recent reconnection
  3160. + of smb session using a now incorrect file
  3161. + handle is not a data integrity issue but do
  3162. + not bother sending an oplock release if session
  3163. + to server still is disconnected since oplock
  3164. + already released by the server in that case */
  3165. + if(pTcon->tidStatus != CifsNeedReconnect) {
  3166. + rc = CIFSSMBLock(0, pTcon,
  3167. + netfid,
  3168. + 0 /* len */ , 0 /* offset */, 0,
  3169. + 0, LOCKING_ANDX_OPLOCK_RELEASE,
  3170. + 0 /* wait flag */);
  3171. + cFYI(1,("Oplock release rc = %d ",rc));
  3172. + }
  3173. + } else
  3174. + spin_unlock(&GlobalMid_Lock);
  3175. + }
  3176. + } while(!signal_pending(current));
  3177. + complete_and_exit (&cifs_oplock_exited, 0);
  3178. +}
  3179. +
  3180. +static int __init
  3181. +init_cifs(void)
  3182. +{
  3183. + int rc = 0;
  3184. +#if CONFIG_PROC_FS
  3185. + cifs_proc_init();
  3186. +#endif
  3187. + INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
  3188. + INIT_LIST_HEAD(&GlobalSMBSessionList);
  3189. + INIT_LIST_HEAD(&GlobalTreeConnectionList);
  3190. + INIT_LIST_HEAD(&GlobalOplock_Q);
  3191. +/*
  3192. + * Initialize Global counters
  3193. + */
  3194. + atomic_set(&sesInfoAllocCount, 0);
  3195. + atomic_set(&tconInfoAllocCount, 0);
  3196. + atomic_set(&tcpSesReconnectCount, 0);
  3197. + atomic_set(&tconInfoReconnectCount, 0);
  3198. +
  3199. + atomic_set(&bufAllocCount, 0);
  3200. + atomic_set(&midCount, 0);
  3201. + GlobalCurrentXid = 0;
  3202. + GlobalTotalActiveXid = 0;
  3203. + GlobalMaxActiveXid = 0;
  3204. + GlobalSMBSeslock = RW_LOCK_UNLOCKED;
  3205. + GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
  3206. +
  3207. +/* rc = cifs_init_inodecache();*/
  3208. + if (!rc) {
  3209. + rc = cifs_init_mids();
  3210. + if (!rc) {
  3211. + rc = cifs_init_request_bufs();
  3212. + if (!rc) {
  3213. + rc = register_filesystem(&cifs_fs_type);
  3214. + if (!rc) {
  3215. + kernel_thread(cifs_oplock_thread, NULL,
  3216. + CLONE_FS | CLONE_FILES | CLONE_VM);
  3217. + return rc; /* Success */
  3218. + } else
  3219. + cifs_destroy_request_bufs();
  3220. + }
  3221. + cifs_destroy_mids();
  3222. + }
  3223. +/* cifs_destroy_inodecache(); */
  3224. + }
  3225. +#if CONFIG_PROC_FS
  3226. + cifs_proc_clean();
  3227. +#endif
  3228. + return rc;
  3229. +}
  3230. +
  3231. +static void __exit
  3232. +exit_cifs(void)
  3233. +{
  3234. + cFYI(0, ("In unregister ie exit_cifs"));
  3235. +#if CONFIG_PROC_FS
  3236. + cifs_proc_clean();
  3237. +#endif
  3238. + unregister_filesystem(&cifs_fs_type);
  3239. +/* cifs_destroy_inodecache();*/
  3240. + cifs_destroy_mids();
  3241. + cifs_destroy_request_bufs();
  3242. + if(oplockThread) {
  3243. + send_sig(SIGTERM, oplockThread, 1);
  3244. + wait_for_completion(&cifs_oplock_exited);
  3245. + }
  3246. +}
  3247. +
  3248. +MODULE_AUTHOR("Steve French <[email protected]>");
  3249. +MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
  3250. +MODULE_DESCRIPTION
  3251. + ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
  3252. +module_init(init_cifs)
  3253. +module_exit(exit_cifs)
  3254. --- /dev/null
  3255. +++ b/fs/cifs/cifsfs.h
  3256. @@ -0,0 +1,97 @@
  3257. +/*
  3258. + * fs/cifs/cifsfs.h
  3259. + *
  3260. + * Copyright (c) International Business Machines Corp., 2002
  3261. + * Author(s): Steve French ([email protected])
  3262. + *
  3263. + * This library is free software; you can redistribute it and/or modify
  3264. + * it under the terms of the GNU Lesser General Public License as published
  3265. + * by the Free Software Foundation; either version 2.1 of the License, or
  3266. + * (at your option) any later version.
  3267. + *
  3268. + * This library is distributed in the hope that it will be useful,
  3269. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3270. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  3271. + * the GNU Lesser General Public License for more details.
  3272. + *
  3273. + * You should have received a copy of the GNU Lesser General Public License
  3274. + * along with this library; if not, write to the Free Software
  3275. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  3276. + */
  3277. +
  3278. +#ifndef _CIFSFS_H
  3279. +#define _CIFSFS_H
  3280. +
  3281. +#define ROOT_I 2
  3282. +
  3283. +#ifndef FALSE
  3284. +#define FALSE 0
  3285. +#endif
  3286. +
  3287. +#ifndef TRUE
  3288. +#define TRUE 1
  3289. +#endif
  3290. +
  3291. +extern int map_cifs_error(int error_class, int error_code,
  3292. + int status_codes_negotiated);
  3293. +
  3294. +extern struct address_space_operations cifs_addr_ops;
  3295. +
  3296. +/* Functions related to super block operations */
  3297. +extern struct super_operations cifs_super_ops;
  3298. +extern void cifs_put_inode(struct inode *);
  3299. +extern void cifs_read_inode(struct inode *);
  3300. +extern void cifs_delete_inode(struct inode *);
  3301. +/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
  3302. +
  3303. +/* Functions related to inodes */
  3304. +extern struct inode_operations cifs_dir_inode_ops;
  3305. +extern int cifs_create(struct inode *, struct dentry *, int);
  3306. +extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
  3307. +extern int cifs_unlink(struct inode *, struct dentry *);
  3308. +extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
  3309. +extern int cifs_mknod(struct inode *, struct dentry *, int, int);
  3310. +extern int cifs_mkdir(struct inode *, struct dentry *, int);
  3311. +extern int cifs_rmdir(struct inode *, struct dentry *);
  3312. +extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
  3313. + struct dentry *);
  3314. +extern int cifs_revalidate(struct dentry *);
  3315. +extern int cifs_setattr(struct dentry *, struct iattr *);
  3316. +
  3317. +extern struct inode_operations cifs_file_inode_ops;
  3318. +extern void cifs_truncate_file(struct inode *);
  3319. +extern struct inode_operations cifs_symlink_inode_ops;
  3320. +
  3321. +/* Functions related to files and directories */
  3322. +extern struct file_operations cifs_file_ops;
  3323. +extern int cifs_open(struct inode *inode, struct file *file);
  3324. +extern int cifs_close(struct inode *inode, struct file *file);
  3325. +extern int cifs_closedir(struct inode *inode, struct file *file);
  3326. +extern ssize_t cifs_read(struct file *file, char *read_data,
  3327. + size_t read_size, loff_t * poffset);
  3328. +extern ssize_t cifs_write(struct file *file, const char *write_data,
  3329. + size_t write_size, loff_t * poffset);
  3330. +extern int cifs_lock(struct file *, int, struct file_lock *);
  3331. +extern int cifs_fsync(struct file *, struct dentry *, int);
  3332. +extern int cifs_flush(struct file *);
  3333. +extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
  3334. +extern struct file_operations cifs_dir_ops;
  3335. +extern int cifs_dir_open(struct inode *inode, struct file *file);
  3336. +extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
  3337. +extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
  3338. +
  3339. +/* Functions related to dir entries */
  3340. +extern struct dentry_operations cifs_dentry_ops;
  3341. +
  3342. +/* Functions related to symlinks */
  3343. +extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
  3344. +extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
  3345. +extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
  3346. + const char *symname);
  3347. +extern int cifs_removexattr(struct dentry *, const char *);
  3348. +extern int cifs_setxattr(struct dentry *, const char *, const void *,
  3349. + size_t, int);
  3350. +extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
  3351. +extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
  3352. +#define CIFS_VERSION "1.20"
  3353. +#endif /* _CIFSFS_H */
  3354. --- /dev/null
  3355. +++ b/fs/cifs/cifs_fs_sb.h
  3356. @@ -0,0 +1,32 @@
  3357. +/*
  3358. + * fs/cifs/cifs_fs_sb.h
  3359. + *
  3360. + * Copyright (c) International Business Machines Corp., 2002
  3361. + * Author(s): Steve French ([email protected])
  3362. + *
  3363. + * This library is free software; you can redistribute it and/or modify
  3364. + * it under the terms of the GNU Lesser General Public License as published
  3365. + * by the Free Software Foundation; either version 2.1 of the License, or
  3366. + * (at your option) any later version.
  3367. + *
  3368. + * This library is distributed in the hope that it will be useful,
  3369. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3370. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  3371. + * the GNU Lesser General Public License for more details.
  3372. + *
  3373. + */
  3374. +#ifndef _CIFS_FS_SB_H
  3375. +#define _CIFS_FS_SB_H
  3376. +
  3377. +struct cifs_sb_info {
  3378. + struct cifsTconInfo *tcon; /* primary mount */
  3379. + struct list_head nested_tcon_q;
  3380. + struct nls_table *local_nls;
  3381. + unsigned int rsize;
  3382. + unsigned int wsize;
  3383. + uid_t mnt_uid;
  3384. + gid_t mnt_gid;
  3385. + mode_t mnt_file_mode;
  3386. + mode_t mnt_dir_mode;
  3387. +};
  3388. +#endif /* _CIFS_FS_SB_H */
  3389. --- /dev/null
  3390. +++ b/fs/cifs/cifsglob.h
  3391. @@ -0,0 +1,413 @@
  3392. +/*
  3393. + * fs/cifs/cifsglob.h
  3394. + *
  3395. + * Copyright (C) International Business Machines Corp., 2002,2003
  3396. + * Author(s): Steve French ([email protected])
  3397. + *
  3398. + * This library is free software; you can redistribute it and/or modify
  3399. + * it under the terms of the GNU Lesser General Public License as published
  3400. + * by the Free Software Foundation; either version 2.1 of the License, or
  3401. + * (at your option) any later version.
  3402. + *
  3403. + * This library is distributed in the hope that it will be useful,
  3404. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3405. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  3406. + * the GNU Lesser General Public License for more details.
  3407. + *
  3408. + */
  3409. +#include <linux/in.h>
  3410. +#include <linux/in6.h>
  3411. +#include "cifs_fs_sb.h"
  3412. +/*
  3413. + * The sizes of various internal tables and strings
  3414. + */
  3415. +#define MAX_UID_INFO 16
  3416. +#define MAX_SES_INFO 2
  3417. +#define MAX_TCON_INFO 4
  3418. +
  3419. +#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
  3420. +#define MAX_SERVER_SIZE 15
  3421. +#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
  3422. +#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
  3423. + termination then *2 for unicode versions */
  3424. +#define MAX_PASSWORD_SIZE 16
  3425. +
  3426. +/*
  3427. + * MAX_REQ is the maximum number of requests that WE will send
  3428. + * on one socket concurently. It also matches the most common
  3429. + * value of max multiplex returned by servers. We may
  3430. + * eventually want to use the negotiated value (in case
  3431. + * future servers can handle more) when we are more confident that
  3432. + * we will not have problems oveloading the socket with pending
  3433. + * write data.
  3434. + */
  3435. +#define CIFS_MAX_REQ 50
  3436. +
  3437. +#define SERVER_NAME_LENGTH 15
  3438. +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
  3439. +
  3440. +/* used to define string lengths for reversing unicode strings */
  3441. +/* (256+1)*2 = 514 */
  3442. +/* (max path length + 1 for null) * 2 for unicode */
  3443. +#define MAX_NAME 514
  3444. +
  3445. +#include "cifspdu.h"
  3446. +
  3447. +#ifndef FALSE
  3448. +#define FALSE 0
  3449. +#endif
  3450. +
  3451. +#ifndef TRUE
  3452. +#define TRUE 1
  3453. +#endif
  3454. +
  3455. +#ifndef XATTR_DOS_ATTRIB
  3456. +#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
  3457. +#endif
  3458. +
  3459. +/*
  3460. + * This information is kept on every Server we know about.
  3461. + *
  3462. + * Some things to note:
  3463. + *
  3464. + */
  3465. +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
  3466. +
  3467. +/*
  3468. + * CIFS vfs client Status information (based on what we know.)
  3469. + */
  3470. +
  3471. + /* associated with each tcp and smb session */
  3472. +enum statusEnum {
  3473. + CifsNew = 0,
  3474. + CifsGood,
  3475. + CifsExiting,
  3476. + CifsNeedReconnect
  3477. +};
  3478. +
  3479. +enum securityEnum {
  3480. + NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
  3481. + NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
  3482. + RawNTLMSSP, /* NTLMSSP without SPNEGO */
  3483. + NTLMSSP, /* NTLMSSP via SPNEGO */
  3484. + Kerberos /* Kerberos via SPNEGO */
  3485. +};
  3486. +
  3487. +enum protocolEnum {
  3488. + IPV4 = 0,
  3489. + IPV6,
  3490. + SCTP
  3491. + /* Netbios frames protocol not supported at this time */
  3492. +};
  3493. +
  3494. +/*
  3495. + *****************************************************************
  3496. + * Except the CIFS PDUs themselves all the
  3497. + * globally interesting structs should go here
  3498. + *****************************************************************
  3499. + */
  3500. +
  3501. +struct TCP_Server_Info {
  3502. + char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
  3503. + char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
  3504. + struct socket *ssocket;
  3505. + union {
  3506. + struct sockaddr_in sockAddr;
  3507. + struct sockaddr_in6 sockAddr6;
  3508. + } addr;
  3509. + wait_queue_head_t response_q;
  3510. + wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
  3511. + struct list_head pending_mid_q;
  3512. + void *Server_NlsInfo; /* BB - placeholder for future NLS info */
  3513. + unsigned short server_codepage; /* codepage for the server */
  3514. + unsigned long ip_address; /* IP addr for the server if known */
  3515. + enum protocolEnum protocolType;
  3516. + char versionMajor;
  3517. + char versionMinor;
  3518. + int svlocal:1; /* local server or remote */
  3519. + atomic_t socketUseCount; /* number of open cifs sessions on socket */
  3520. + atomic_t inFlight; /* number of requests on the wire to server */
  3521. + enum statusEnum tcpStatus; /* what we think the status is */
  3522. + struct semaphore tcpSem;
  3523. + struct task_struct *tsk;
  3524. + char server_GUID[16];
  3525. + char secMode;
  3526. + enum securityEnum secType;
  3527. + unsigned int maxReq; /* Clients should submit no more */
  3528. + /* than maxReq distinct unanswered SMBs to the server when using */
  3529. + /* multiplexed reads or writes */
  3530. + unsigned int maxBuf; /* maxBuf specifies the maximum */
  3531. + /* message size the server can send or receive for non-raw SMBs */
  3532. + unsigned int maxRw; /* maxRw specifies the maximum */
  3533. + /* message size the server can send or receive for */
  3534. + /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
  3535. + char sessid[4]; /* unique token id for this session */
  3536. + /* (returned on Negotiate */
  3537. + int capabilities; /* allow selective disabling of caps by smb sess */
  3538. + __u16 timeZone;
  3539. + char cryptKey[CIFS_CRYPTO_KEY_SIZE];
  3540. + char workstation_RFC1001_name[16]; /* 16th byte is always zero */
  3541. +};
  3542. +
  3543. +/*
  3544. + * The following is our shortcut to user information. We surface the uid,
  3545. + * and name. We always get the password on the fly in case it
  3546. + * has changed. We also hang a list of sessions owned by this user off here.
  3547. + */
  3548. +struct cifsUidInfo {
  3549. + struct list_head userList;
  3550. + struct list_head sessionList; /* SMB sessions for this user */
  3551. + uid_t linux_uid;
  3552. + char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
  3553. + /* BB may need ptr or callback for PAM or WinBind info */
  3554. +};
  3555. +
  3556. +/*
  3557. + * Session structure. One of these for each uid session with a particular host
  3558. + */
  3559. +struct cifsSesInfo {
  3560. + struct list_head cifsSessionList;
  3561. + struct semaphore sesSem;
  3562. + struct cifsUidInfo *uidInfo; /* pointer to user info */
  3563. + struct TCP_Server_Info *server; /* pointer to server info */
  3564. + atomic_t inUse; /* # of mounts (tree connections) on this ses */
  3565. + enum statusEnum status;
  3566. + __u32 sequence_number; /* needed for CIFS PDU signature */
  3567. + __u16 ipc_tid; /* special tid for connection to IPC share */
  3568. + char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
  3569. + char *serverOS; /* name of operating system underlying the server */
  3570. + char *serverNOS; /* name of network operating system that the server is running */
  3571. + char *serverDomain; /* security realm of server */
  3572. + int Suid; /* remote smb uid */
  3573. + uid_t linux_uid; /* local Linux uid */
  3574. + int capabilities;
  3575. + char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
  3576. + char userName[MAX_USERNAME_SIZE + 1];
  3577. + char domainName[MAX_USERNAME_SIZE + 1];
  3578. + char * password;
  3579. +};
  3580. +
  3581. +/*
  3582. + * there is one of these for each connection to a resource on a particular
  3583. + * session
  3584. + */
  3585. +struct cifsTconInfo {
  3586. + struct list_head cifsConnectionList;
  3587. + struct list_head openFileList;
  3588. + struct semaphore tconSem;
  3589. + struct cifsSesInfo *ses; /* pointer to session associated with */
  3590. + char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
  3591. + char *nativeFileSystem;
  3592. + __u16 tid; /* The 2 byte tree id */
  3593. + __u16 Flags; /* optional support bits */
  3594. + enum statusEnum tidStatus;
  3595. + atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
  3596. +#ifdef CONFIG_CIFS_STATS
  3597. + atomic_t num_smbs_sent;
  3598. + atomic_t num_writes;
  3599. + atomic_t num_reads;
  3600. + atomic_t num_oplock_brks;
  3601. + atomic_t num_opens;
  3602. + atomic_t num_deletes;
  3603. + atomic_t num_mkdirs;
  3604. + atomic_t num_rmdirs;
  3605. + atomic_t num_renames;
  3606. + atomic_t num_t2renames;
  3607. + __u64 bytes_read;
  3608. + __u64 bytes_written;
  3609. + spinlock_t stat_lock;
  3610. +#endif
  3611. + FILE_SYSTEM_DEVICE_INFO fsDevInfo;
  3612. + FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
  3613. + FILE_SYSTEM_UNIX_INFO fsUnixInfo;
  3614. + int retry:1;
  3615. + /* BB add field for back pointer to sb struct? */
  3616. +};
  3617. +
  3618. +/*
  3619. + * This info hangs off the cifsFileInfo structure. This is used to track
  3620. + * byte stream locks on the file
  3621. + */
  3622. +struct cifsLockInfo {
  3623. + struct cifsLockInfo *next;
  3624. + int start;
  3625. + int length;
  3626. + int type;
  3627. +};
  3628. +
  3629. +/*
  3630. + * One of these for each open instance of a file
  3631. + */
  3632. +struct cifsFileInfo {
  3633. + struct list_head tlist; /* pointer to next fid owned by tcon */
  3634. + struct list_head flist; /* next fid (file instance) for this inode */
  3635. + unsigned int uid; /* allows finding which FileInfo structure */
  3636. + __u32 pid; /* process id who opened file */
  3637. + __u16 netfid; /* file id from remote */
  3638. + /* BB add lock scope info here if needed */ ;
  3639. + /* lock scope id (0 if none) */
  3640. + struct file * pfile; /* needed for writepage */
  3641. + struct inode * pInode; /* needed for oplock break */
  3642. + int endOfSearch:1; /* we have reached end of search */
  3643. + int closePend:1; /* file is marked to close */
  3644. + int emptyDir:1;
  3645. + int invalidHandle:1; /* file closed via session abend */
  3646. + struct semaphore fh_sem; /* prevents reopen race after dead ses*/
  3647. + char * search_resume_name;
  3648. + unsigned int resume_name_length;
  3649. + __u32 resume_key;
  3650. +};
  3651. +
  3652. +/*
  3653. + * One of these for each file inode
  3654. + */
  3655. +
  3656. +struct cifsInodeInfo {
  3657. + struct list_head lockList;
  3658. + /* BB add in lists for dirty pages - i.e. write caching info for oplock */
  3659. + struct list_head openFileList;
  3660. + int write_behind_rc;
  3661. + __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
  3662. + atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
  3663. + unsigned long time; /* jiffies of last update/check of inode */
  3664. + int clientCanCacheRead:1; /* read oplock */
  3665. + int clientCanCacheAll:1; /* read and writebehind oplock */
  3666. + int oplockPending:1;
  3667. + struct inode vfs_inode;
  3668. +};
  3669. +
  3670. +static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
  3671. +{
  3672. + return (struct cifsInodeInfo *)&(inode->u);
  3673. +}
  3674. +
  3675. +static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
  3676. +{
  3677. + return (struct cifs_sb_info *) &(sb->u);
  3678. +}
  3679. +
  3680. +
  3681. +/* one of these for every pending CIFS request to the server */
  3682. +struct mid_q_entry {
  3683. + struct list_head qhead; /* mids waiting on reply from this server */
  3684. + __u16 mid; /* multiplex id */
  3685. + __u16 pid; /* process id */
  3686. + __u32 sequence_number; /* for CIFS signing */
  3687. + __u16 command; /* smb command code */
  3688. + struct timeval when_sent; /* time when smb sent */
  3689. + struct cifsSesInfo *ses; /* smb was sent to this server */
  3690. + struct task_struct *tsk; /* task waiting for response */
  3691. + struct smb_hdr *resp_buf; /* response buffer */
  3692. + int midState; /* wish this were enum but can not pass to wait_event */
  3693. +};
  3694. +
  3695. +struct oplock_q_entry {
  3696. + struct list_head qhead;
  3697. + struct inode * pinode;
  3698. + struct cifsTconInfo * tcon;
  3699. + __u16 netfid;
  3700. +};
  3701. +
  3702. +#define MID_FREE 0
  3703. +#define MID_REQUEST_ALLOCATED 1
  3704. +#define MID_REQUEST_SUBMITTED 2
  3705. +#define MID_RESPONSE_RECEIVED 4
  3706. +#define MID_RETRY_NEEDED 8 /* session closed while this request out */
  3707. +
  3708. +/*
  3709. + *****************************************************************
  3710. + * All constants go here
  3711. + *****************************************************************
  3712. + */
  3713. +
  3714. +#define UID_HASH (16)
  3715. +
  3716. +/*
  3717. + * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
  3718. + * following to be declared.
  3719. + */
  3720. +
  3721. +/****************************************************************************
  3722. + * Locking notes. All updates to global variables and lists should be
  3723. + * protected by spinlocks or semaphores.
  3724. + *
  3725. + * Spinlocks
  3726. + * ---------
  3727. + * GlobalMid_Lock protects:
  3728. + * list operations on pending_mid_q and oplockQ
  3729. + * updates to XID counters, multiplex id and SMB sequence numbers
  3730. + * GlobalSMBSesLock protects:
  3731. + * list operations on tcp and SMB session lists and tCon lists
  3732. + * f_owner.lock protects certain per file struct operations
  3733. + * mapping->page_lock protects certain per page operations
  3734. + *
  3735. + * Semaphores
  3736. + * ----------
  3737. + * sesSem operations on smb session
  3738. + * tconSem operations on tree connection
  3739. + * fh_sem file handle reconnection operations
  3740. + *
  3741. + ****************************************************************************/
  3742. +
  3743. +#ifdef DECLARE_GLOBALS_HERE
  3744. +#define GLOBAL_EXTERN
  3745. +#else
  3746. +#define GLOBAL_EXTERN extern
  3747. +#endif
  3748. +
  3749. +/*
  3750. + * The list of servers that did not respond with NT LM 0.12.
  3751. + * This list helps improve performance and eliminate the messages indicating
  3752. + * that we had a communications error talking to the server in this list.
  3753. + */
  3754. +GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
  3755. +
  3756. +/*
  3757. + * The following is a hash table of all the users we know about.
  3758. + */
  3759. +GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
  3760. +
  3761. +GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
  3762. +GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
  3763. +GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
  3764. +GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
  3765. +
  3766. +GLOBAL_EXTERN struct list_head GlobalOplock_Q;
  3767. +
  3768. +/*
  3769. + * Global transaction id (XID) information
  3770. + */
  3771. +GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
  3772. +GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
  3773. +GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
  3774. +GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
  3775. + /* on midQ entries */
  3776. +GLOBAL_EXTERN char Local_System_Name[15];
  3777. +
  3778. +/*
  3779. + * Global counters, updated atomically
  3780. + */
  3781. +GLOBAL_EXTERN atomic_t sesInfoAllocCount;
  3782. +GLOBAL_EXTERN atomic_t tconInfoAllocCount;
  3783. +
  3784. +GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
  3785. +GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
  3786. +
  3787. +/* Various Debug counters to remove someday (BB) */
  3788. +GLOBAL_EXTERN atomic_t bufAllocCount;
  3789. +GLOBAL_EXTERN atomic_t midCount;
  3790. +
  3791. +/* Misc globals */
  3792. +GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
  3793. + to be established on existing mount if we
  3794. + have the uid/password or Kerberos credential
  3795. + or equivalent for current user */
  3796. +GLOBAL_EXTERN unsigned int oplockEnabled;
  3797. +GLOBAL_EXTERN unsigned int quotaEnabled;
  3798. +GLOBAL_EXTERN unsigned int lookupCacheEnabled;
  3799. +GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
  3800. + with more secure ntlmssp2 challenge/resp */
  3801. +GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
  3802. +GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
  3803. +GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
  3804. +
  3805. --- /dev/null
  3806. +++ b/fs/cifs/cifspdu.h
  3807. @@ -0,0 +1,1793 @@
  3808. +/*
  3809. + * fs/cifs/cifspdu.h
  3810. + *
  3811. + * Copyright (c) International Business Machines Corp., 2002
  3812. + * Author(s): Steve French ([email protected])
  3813. + *
  3814. + * This library is free software; you can redistribute it and/or modify
  3815. + * it under the terms of the GNU Lesser General Public License as published
  3816. + * by the Free Software Foundation; either version 2.1 of the License, or
  3817. + * (at your option) any later version.
  3818. + *
  3819. + * This library is distributed in the hope that it will be useful,
  3820. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3821. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  3822. + * the GNU Lesser General Public License for more details.
  3823. + *
  3824. + * You should have received a copy of the GNU Lesser General Public License
  3825. + * along with this library; if not, write to the Free Software
  3826. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  3827. + */
  3828. +
  3829. +#ifndef _CIFSPDU_H
  3830. +#define _CIFSPDU_H
  3831. +
  3832. +#include <net/sock.h>
  3833. +
  3834. +#define CIFS_PROT 0
  3835. +#define BAD_PROT CIFS_PROT+1
  3836. +
  3837. +/* SMB command codes */
  3838. +#define SMB_COM_CREATE_DIRECTORY 0x00
  3839. +#define SMB_COM_DELETE_DIRECTORY 0x01
  3840. +#define SMB_COM_CLOSE 0x04
  3841. +#define SMB_COM_DELETE 0x06
  3842. +#define SMB_COM_RENAME 0x07
  3843. +#define SMB_COM_LOCKING_ANDX 0x24
  3844. +#define SMB_COM_COPY 0x29
  3845. +#define SMB_COM_READ_ANDX 0x2E
  3846. +#define SMB_COM_WRITE_ANDX 0x2F
  3847. +#define SMB_COM_TRANSACTION2 0x32
  3848. +#define SMB_COM_TRANSACTION2_SECONDARY 0x33
  3849. +#define SMB_COM_FIND_CLOSE2 0x34
  3850. +#define SMB_COM_TREE_DISCONNECT 0x71
  3851. +#define SMB_COM_NEGOTIATE 0x72
  3852. +#define SMB_COM_SESSION_SETUP_ANDX 0x73
  3853. +#define SMB_COM_LOGOFF_ANDX 0x74
  3854. +#define SMB_COM_TREE_CONNECT_ANDX 0x75
  3855. +#define SMB_COM_NT_TRANSACT 0xA0
  3856. +#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
  3857. +#define SMB_COM_NT_CREATE_ANDX 0xA2
  3858. +#define SMB_COM_NT_RENAME 0xA5
  3859. +
  3860. +/* Transact2 subcommand codes */
  3861. +#define TRANS2_OPEN 0x00
  3862. +#define TRANS2_FIND_FIRST 0x01
  3863. +#define TRANS2_FIND_NEXT 0x02
  3864. +#define TRANS2_QUERY_FS_INFORMATION 0x03
  3865. +#define TRANS2_QUERY_PATH_INFORMATION 0x05
  3866. +#define TRANS2_SET_PATH_INFORMATION 0x06
  3867. +#define TRANS2_QUERY_FILE_INFORMATION 0x07
  3868. +#define TRANS2_SET_FILE_INFORMATION 0x08
  3869. +#define TRANS2_GET_DFS_REFERRAL 0x10
  3870. +#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
  3871. +
  3872. +/* NT Transact subcommand codes */
  3873. +#define NT_TRANSACT_CREATE 0x01
  3874. +#define NT_TRANSACT_IOCTL 0x02
  3875. +#define NT_TRANSACT_SET_SECURITY_DESC 0x03
  3876. +#define NT_TRANSACT_NOTIFY_CHANGE 0x04
  3877. +#define NT_TRANSACT_RENAME 0x05
  3878. +#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
  3879. +#define NT_TRANSACT_GET_USER_QUOTA 0x07
  3880. +#define NT_TRANSACT_SET_USER_QUOTA 0x08
  3881. +
  3882. +#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
  3883. +
  3884. +/* internal cifs vfs structures */
  3885. +/*****************************************************************
  3886. + * All constants go here
  3887. + *****************************************************************
  3888. + */
  3889. +
  3890. +/*
  3891. + * Starting value for maximum SMB size negotiation
  3892. + */
  3893. +#define CIFS_MAX_MSGSIZE (4*4096)
  3894. +
  3895. +/*
  3896. + * Size of encrypted user password in bytes
  3897. + */
  3898. +#define CIFS_ENCPWD_SIZE (16)
  3899. +
  3900. +/*
  3901. + * Size of the crypto key returned on the negotiate SMB in bytes
  3902. + */
  3903. +#define CIFS_CRYPTO_KEY_SIZE (8)
  3904. +
  3905. +/*
  3906. + * Size of the session key (crypto key encrypted with the password
  3907. + */
  3908. +#define CIFS_SESSION_KEY_SIZE (24)
  3909. +
  3910. +/*
  3911. + * Maximum user name length
  3912. + */
  3913. +#define CIFS_UNLEN (20)
  3914. +
  3915. +/*
  3916. + * Flags on SMB open
  3917. + */
  3918. +#define SMBOPEN_WRITE_THROUGH 0x4000
  3919. +#define SMBOPEN_DENY_ALL 0x0010
  3920. +#define SMBOPEN_DENY_WRITE 0x0020
  3921. +#define SMBOPEN_DENY_READ 0x0030
  3922. +#define SMBOPEN_DENY_NONE 0x0040
  3923. +#define SMBOPEN_READ 0x0000
  3924. +#define SMBOPEN_WRITE 0x0001
  3925. +#define SMBOPEN_READWRITE 0x0002
  3926. +#define SMBOPEN_EXECUTE 0x0003
  3927. +
  3928. +#define SMBOPEN_OCREATE 0x0010
  3929. +#define SMBOPEN_OTRUNC 0x0002
  3930. +#define SMBOPEN_OAPPEND 0x0001
  3931. +
  3932. +/*
  3933. + * SMB flag definitions
  3934. + */
  3935. +#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
  3936. +#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
  3937. +#define SMBFLG_RSVD 0x04
  3938. +#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
  3939. +#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
  3940. +#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
  3941. +#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
  3942. +#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
  3943. +
  3944. +/*
  3945. + * SMB flag2 definitions
  3946. + */
  3947. +#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
  3948. +#define SMBFLG2_KNOWS_EAS 0x0002
  3949. +#define SMBFLG2_SECURITY_SIGNATURE 0x0004
  3950. +#define SMBFLG2_IS_LONG_NAME 0x0040
  3951. +#define SMBFLG2_EXT_SEC 0x0800
  3952. +#define SMBFLG2_DFS 0x1000
  3953. +#define SMBFLG2_PAGING_IO 0x2000
  3954. +#define SMBFLG2_ERR_STATUS 0x4000
  3955. +#define SMBFLG2_UNICODE 0x8000
  3956. +
  3957. +/*
  3958. + * These are the file access permission bits defined in CIFS for the
  3959. + * NTCreateAndX as well as the level 0x107
  3960. + * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
  3961. + * responds with the AccessFlags.
  3962. + * The AccessFlags specifies the access permissions a caller has to the
  3963. + * file and can have any suitable combination of the following values:
  3964. + */
  3965. +
  3966. +#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
  3967. +#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
  3968. +#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
  3969. +#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
  3970. + /* with the file can be read */
  3971. +#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
  3972. + /* with the file can be written */
  3973. +#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
  3974. + /* the file using system paging I/O */
  3975. +#define FILE_DELETE_CHILD 0x00000040
  3976. +#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
  3977. + /* file can be read */
  3978. +#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
  3979. + /* file can be written */
  3980. +#define DELETE 0x00010000 /* The file can be deleted */
  3981. +#define READ_CONTROL 0x00020000 /* The access control list and */
  3982. + /* ownership associated with the */
  3983. + /* file can be read */
  3984. +#define WRITE_DAC 0x00040000 /* The access control list and */
  3985. + /* ownership associated with the */
  3986. + /* file can be written. */
  3987. +#define WRITE_OWNER 0x00080000 /* Ownership information associated */
  3988. + /* with the file can be written */
  3989. +#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
  3990. + /* synchronize with the completion */
  3991. + /* of an input/output request */
  3992. +#define GENERIC_ALL 0x10000000
  3993. +#define GENERIC_EXECUTE 0x20000000
  3994. +#define GENERIC_WRITE 0x40000000
  3995. +#define GENERIC_READ 0x80000000
  3996. + /* In summary - Relevant file */
  3997. + /* access flags from CIFS are */
  3998. + /* file_read_data, file_write_data */
  3999. + /* file_execute, file_read_attributes */
  4000. + /* write_dac, and delete. */
  4001. +
  4002. +/*
  4003. + * Invalid readdir handle
  4004. + */
  4005. +#define CIFS_NO_HANDLE 0xFFFF
  4006. +
  4007. +/* IPC$ in ASCII */
  4008. +#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
  4009. +
  4010. +/* IPC$ in Unicode */
  4011. +#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
  4012. +
  4013. +/* Unicode Null terminate 2 bytes of 0 */
  4014. +#define UNICODE_NULL "\x00\x00"
  4015. +#define ASCII_NULL 0x00
  4016. +
  4017. +/*
  4018. + * Server type values (returned on EnumServer API
  4019. + */
  4020. +#define CIFS_SV_TYPE_DC 0x00000008
  4021. +#define CIFS_SV_TYPE_BACKDC 0x00000010
  4022. +
  4023. +/*
  4024. + * Alias type flags (From EnumAlias API call
  4025. + */
  4026. +#define CIFS_ALIAS_TYPE_FILE 0x0001
  4027. +#define CIFS_SHARE_TYPE_FILE 0x0000
  4028. +
  4029. +/*
  4030. + * File Attribute flags
  4031. + */
  4032. +#define ATTR_READONLY 0x0001
  4033. +#define ATTR_HIDDEN 0x0002
  4034. +#define ATTR_SYSTEM 0x0004
  4035. +#define ATTR_VOLUME 0x0008
  4036. +#define ATTR_DIRECTORY 0x0010
  4037. +#define ATTR_ARCHIVE 0x0020
  4038. +#define ATTR_DEVICE 0x0040
  4039. +#define ATTR_NORMAL 0x0080
  4040. +#define ATTR_TEMPORARY 0x0100
  4041. +#define ATTR_SPARSE 0x0200
  4042. +#define ATTR_REPARSE 0x0400
  4043. +#define ATTR_COMPRESSED 0x0800
  4044. +#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
  4045. +#define ATTR_NOT_CONTENT_INDEXED 0x2000
  4046. +#define ATTR_ENCRYPTED 0x4000
  4047. +#define ATTR_POSIX_SEMANTICS 0x01000000
  4048. +#define ATTR_BACKUP_SEMANTICS 0x02000000
  4049. +#define ATTR_DELETE_ON_CLOSE 0x04000000
  4050. +#define ATTR_SEQUENTIAL_SCAN 0x08000000
  4051. +#define ATTR_RANDOM_ACCESS 0x10000000
  4052. +#define ATTR_NO_BUFFERING 0x20000000
  4053. +#define ATTR_WRITE_THROUGH 0x80000000
  4054. +
  4055. +/* ShareAccess flags */
  4056. +#define FILE_NO_SHARE 0x00000000
  4057. +#define FILE_SHARE_READ 0x00000001
  4058. +#define FILE_SHARE_WRITE 0x00000002
  4059. +#define FILE_SHARE_DELETE 0x00000004
  4060. +#define FILE_SHARE_ALL 0x00000007
  4061. +
  4062. +/* CreateDisposition flags */
  4063. +#define FILE_SUPERSEDE 0x00000000
  4064. +#define FILE_OPEN 0x00000001
  4065. +#define FILE_CREATE 0x00000002
  4066. +#define FILE_OPEN_IF 0x00000003
  4067. +#define FILE_OVERWRITE 0x00000004
  4068. +#define FILE_OVERWRITE_IF 0x00000005
  4069. +
  4070. +/* CreateOptions */
  4071. +#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
  4072. +#define CREATE_WRITE_THROUGH 0x00000002
  4073. +#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
  4074. +#define CREATE_RANDOM_ACCESS 0x00000800
  4075. +#define CREATE_DELETE_ON_CLOSE 0x00001000
  4076. +#define OPEN_REPARSE_POINT 0x00200000
  4077. +
  4078. +/* ImpersonationLevel flags */
  4079. +#define SECURITY_ANONYMOUS 0
  4080. +#define SECURITY_IDENTIFICATION 1
  4081. +#define SECURITY_IMPERSONATION 2
  4082. +#define SECURITY_DELEGATION 3
  4083. +
  4084. +/* SecurityFlags */
  4085. +#define SECURITY_CONTEXT_TRACKING 0x01
  4086. +#define SECURITY_EFFECTIVE_ONLY 0x02
  4087. +
  4088. +/*
  4089. + * Default PID value, used in all SMBs where the PID is not important
  4090. + */
  4091. +#define CIFS_DFT_PID 0x1234
  4092. +
  4093. +/*
  4094. + * We use the same routine for Copy and Move SMBs. This flag is used to
  4095. + * distinguish
  4096. + */
  4097. +#define CIFS_COPY_OP 1
  4098. +#define CIFS_RENAME_OP 2
  4099. +
  4100. +#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
  4101. +#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
  4102. +
  4103. +#pragma pack(1)
  4104. +
  4105. +struct smb_hdr {
  4106. + __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
  4107. + __u8 Protocol[4];
  4108. + __u8 Command;
  4109. + union {
  4110. + struct {
  4111. + __u8 ErrorClass;
  4112. + __u8 Reserved;
  4113. + __u16 Error; /* note: treated as little endian (le) on wire */
  4114. + } DosError;
  4115. + __u32 CifsError; /* note: le */
  4116. + } Status;
  4117. + __u8 Flags;
  4118. + __u16 Flags2; /* note: le */
  4119. + __u16 PidHigh; /* note: le */
  4120. + union {
  4121. + struct {
  4122. + __u32 SequenceNumber; /* le */
  4123. + __u32 Reserved; /* zero */
  4124. + } Sequence;
  4125. + __u8 SecuritySignature[8]; /* le */
  4126. + } Signature;
  4127. + __u8 pad[2];
  4128. + __u16 Tid;
  4129. + __u16 Pid; /* note: le */
  4130. + __u16 Uid;
  4131. + __u16 Mid;
  4132. + __u8 WordCount;
  4133. +};
  4134. +/* given a pointer to an smb_hdr retrieve the value of byte count */
  4135. +#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
  4136. +
  4137. +/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
  4138. +#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
  4139. +
  4140. +/*
  4141. + * Computer Name Length
  4142. + */
  4143. +#define CNLEN 15
  4144. +
  4145. +/*
  4146. + * Share Name Length @S8A
  4147. + * Note: This length is limited by the SMB used to get @S8A
  4148. + * the Share info. NetShareEnum only returns 13 @S8A
  4149. + * chars, including the null termination. @S8A
  4150. + */
  4151. +#define SNLEN 12 /*@S8A */
  4152. +
  4153. +/*
  4154. + * Comment Length
  4155. + */
  4156. +#define MAXCOMMENTLEN 40
  4157. +
  4158. +/*
  4159. + * The OS/2 maximum path name
  4160. + */
  4161. +#define MAX_PATHCONF 256
  4162. +
  4163. +/*
  4164. + * SMB frame definitions (following must be packed structs)
  4165. + * See the SNIA CIFS Specification for details.
  4166. + *
  4167. + * The Naming convention is the lower case version of the
  4168. + * smb command code name for the struct and this is typedef to the
  4169. + * uppercase version of the same name with the prefix SMB_ removed
  4170. + * for brevity. Although typedefs are not commonly used for
  4171. + * structure definitions in the Linux kernel, their use in the
  4172. + * CIFS standards document, which this code is based on, may
  4173. + * make this one of the cases where typedefs for structures make
  4174. + * sense to improve readability for readers of the standards doc.
  4175. + * Typedefs can always be removed later if they are too distracting
  4176. + * and they are only used for the CIFSs PDUs themselves, not
  4177. + * internal cifs vfs structures
  4178. + *
  4179. + */
  4180. +
  4181. +typedef struct negotiate_req {
  4182. + struct smb_hdr hdr; /* wct = 0 */
  4183. + __u16 ByteCount;
  4184. + unsigned char DialectsArray[1];
  4185. +} NEGOTIATE_REQ;
  4186. +
  4187. +typedef struct negotiate_rsp {
  4188. + struct smb_hdr hdr; /* wct = 17 */
  4189. + __u16 DialectIndex;
  4190. + __u8 SecurityMode;
  4191. + __u16 MaxMpxCount;
  4192. + __u16 MaxNumberVcs;
  4193. + __u32 MaxBufferSize;
  4194. + __u32 MaxRawSize;
  4195. + __u32 SessionKey;
  4196. + __u32 Capabilities; /* see below */
  4197. + __u32 SystemTimeLow;
  4198. + __u32 SystemTimeHigh;
  4199. + __u16 ServerTimeZone;
  4200. + __u8 EncryptionKeyLength;
  4201. + __u16 ByteCount;
  4202. + union {
  4203. + unsigned char EncryptionKey[1]; /* if cap extended security is off */
  4204. + /* followed by Domain name - if extended security is off */
  4205. + /* followed by 16 bytes of server GUID */
  4206. + /* followed by security blob if cap_extended_security negotiated */
  4207. + struct {
  4208. + unsigned char GUID[16];
  4209. + unsigned char SecurityBlob[1];
  4210. + } extended_response;
  4211. + } u;
  4212. +} NEGOTIATE_RSP;
  4213. +
  4214. +/* SecurityMode bits */
  4215. +#define SECMODE_USER 0x01 /* off indicates share level security */
  4216. +#define SECMODE_PW_ENCRYPT 0x02
  4217. +#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
  4218. +#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
  4219. +
  4220. +/* Negotiate response Capabilities */
  4221. +#define CAP_RAW_MODE 0x00000001
  4222. +#define CAP_MPX_MODE 0x00000002
  4223. +#define CAP_UNICODE 0x00000004
  4224. +#define CAP_LARGE_FILES 0x00000008
  4225. +#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
  4226. +#define CAP_RPC_REMOTE_APIS 0x00000020
  4227. +#define CAP_STATUS32 0x00000040
  4228. +#define CAP_LEVEL_II_OPLOCKS 0x00000080
  4229. +#define CAP_LOCK_AND_READ 0x00000100
  4230. +#define CAP_NT_FIND 0x00000200
  4231. +#define CAP_DFS 0x00001000
  4232. +#define CAP_INFOLEVEL_PASSTHRU 0x00002000
  4233. +#define CAP_LARGE_READ_X 0x00004000
  4234. +#define CAP_LARGE_WRITE_X 0x00008000
  4235. +#define CAP_UNIX 0x00800000
  4236. +#define CAP_RESERVED 0x02000000
  4237. +#define CAP_BULK_TRANSFER 0x20000000
  4238. +#define CAP_COMPRESSED_DATA 0x40000000
  4239. +#define CAP_EXTENDED_SECURITY 0x80000000
  4240. +
  4241. +typedef union smb_com_session_setup_andx {
  4242. + struct { /* request format */
  4243. + struct smb_hdr hdr; /* wct = 12 */
  4244. + __u8 AndXCommand;
  4245. + __u8 AndXReserved;
  4246. + __u16 AndXOffset;
  4247. + __u16 MaxBufferSize;
  4248. + __u16 MaxMpxCount;
  4249. + __u16 VcNumber;
  4250. + __u32 SessionKey;
  4251. + __u16 SecurityBlobLength;
  4252. + __u32 Reserved;
  4253. + __u32 Capabilities; /* see below */
  4254. + __u16 ByteCount;
  4255. + unsigned char SecurityBlob[1]; /* followed by */
  4256. + /* STRING NativeOS */
  4257. + /* STRING NativeLanMan */
  4258. + } req; /* NTLM request format (with extended security */
  4259. +
  4260. + struct { /* request format */
  4261. + struct smb_hdr hdr; /* wct = 13 */
  4262. + __u8 AndXCommand;
  4263. + __u8 AndXReserved;
  4264. + __u16 AndXOffset;
  4265. + __u16 MaxBufferSize;
  4266. + __u16 MaxMpxCount;
  4267. + __u16 VcNumber;
  4268. + __u32 SessionKey;
  4269. + __u16 CaseInsensitivePasswordLength; /* ASCII password length */
  4270. + __u16 CaseSensitivePasswordLength; /* Unicode password length */
  4271. + __u32 Reserved; /* see below */
  4272. + __u32 Capabilities;
  4273. + __u16 ByteCount;
  4274. + unsigned char CaseInsensitivePassword[1]; /* followed by: */
  4275. + /* unsigned char * CaseSensitivePassword; */
  4276. + /* STRING AccountName */
  4277. + /* STRING PrimaryDomain */
  4278. + /* STRING NativeOS */
  4279. + /* STRING NativeLanMan */
  4280. + } req_no_secext; /* NTLM request format (without extended security */
  4281. +
  4282. + struct { /* default (NTLM) response format */
  4283. + struct smb_hdr hdr; /* wct = 4 */
  4284. + __u8 AndXCommand;
  4285. + __u8 AndXReserved;
  4286. + __u16 AndXOffset;
  4287. + __u16 Action; /* see below */
  4288. + __u16 SecurityBlobLength;
  4289. + __u16 ByteCount;
  4290. + unsigned char SecurityBlob[1]; /* followed by */
  4291. +/* unsigned char * NativeOS; */
  4292. +/* unsigned char * NativeLanMan; */
  4293. +/* unsigned char * PrimaryDomain; */
  4294. + } resp; /* NTLM response format (with or without extended security */
  4295. +
  4296. + struct { /* request format */
  4297. + struct smb_hdr hdr; /* wct = 10 */
  4298. + __u8 AndXCommand;
  4299. + __u8 AndXReserved;
  4300. + __u16 AndXOffset;
  4301. + __u16 MaxBufferSize;
  4302. + __u16 MaxMpxCount;
  4303. + __u16 VcNumber;
  4304. + __u32 SessionKey;
  4305. + __u16 PassswordLength;
  4306. + __u32 Reserved;
  4307. + __u16 ByteCount;
  4308. + unsigned char AccountPassword[1]; /* followed by */
  4309. + /* STRING AccountName */
  4310. + /* STRING PrimaryDomain */
  4311. + /* STRING NativeOS */
  4312. + /* STRING NativeLanMan */
  4313. + } old_req; /* pre-NTLM (LANMAN2.1) request format */
  4314. +
  4315. + struct { /* default (NTLM) response format */
  4316. + struct smb_hdr hdr; /* wct = 3 */
  4317. + __u8 AndXCommand;
  4318. + __u8 AndXReserved;
  4319. + __u16 AndXOffset;
  4320. + __u16 Action; /* see below */
  4321. + __u16 ByteCount;
  4322. + unsigned char NativeOS[1]; /* followed by */
  4323. +/* unsigned char * NativeLanMan; */
  4324. +/* unsigned char * PrimaryDomain; */
  4325. + } old_resp; /* pre-NTLM (LANMAN2.1) response format */
  4326. +} SESSION_SETUP_ANDX;
  4327. +
  4328. +#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
  4329. +
  4330. +/* Capabilities bits (for NTLM SessSetup request) */
  4331. +#define CAP_UNICODE 0x00000004
  4332. +#define CAP_LARGE_FILES 0x00000008
  4333. +#define CAP_NT_SMBS 0x00000010
  4334. +#define CAP_STATUS32 0x00000040
  4335. +#define CAP_LEVEL_II_OPLOCKS 0x00000080
  4336. +#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
  4337. +#define CAP_BULK_TRANSFER 0x20000000
  4338. +#define CAP_EXTENDED_SECURITY 0x80000000
  4339. +
  4340. +/* Action bits */
  4341. +#define GUEST_LOGIN 1
  4342. +
  4343. +typedef struct smb_com_tconx_req {
  4344. + struct smb_hdr hdr; /* wct = 4 */
  4345. + __u8 AndXCommand;
  4346. + __u8 AndXReserved;
  4347. + __u16 AndXOffset;
  4348. + __u16 Flags; /* see below */
  4349. + __u16 PasswordLength;
  4350. + __u16 ByteCount;
  4351. + unsigned char Password[1]; /* followed by */
  4352. +/* STRING Path *//* \\server\share name */
  4353. + /* STRING Service */
  4354. +} TCONX_REQ;
  4355. +
  4356. +typedef struct smb_com_tconx_rsp {
  4357. + struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
  4358. + __u8 AndXCommand;
  4359. + __u8 AndXReserved;
  4360. + __u16 AndXOffset;
  4361. + __u16 OptionalSupport; /* see below */
  4362. + __u16 ByteCount;
  4363. + unsigned char Service[1]; /* always ASCII, not Unicode */
  4364. + /* STRING NativeFileSystem */
  4365. +} TCONX_RSP;
  4366. +
  4367. +/* tree connect Flags */
  4368. +#define DISCONNECT_TID 0x0001
  4369. +#define TCON_EXTENDED_SECINFO 0x0008
  4370. +/* OptionalSupport bits */
  4371. +#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
  4372. +#define SMB_SHARE_IS_IN_DFS 0x0002
  4373. +
  4374. +typedef struct smb_com_logoff_andx_req {
  4375. +
  4376. + struct smb_hdr hdr; /* wct = 2 */
  4377. + __u8 AndXCommand;
  4378. + __u8 AndXReserved;
  4379. + __u16 AndXOffset;
  4380. + __u16 ByteCount;
  4381. +} LOGOFF_ANDX_REQ;
  4382. +
  4383. +typedef struct smb_com_logoff_andx_rsp {
  4384. + struct smb_hdr hdr; /* wct = 2 */
  4385. + __u8 AndXCommand;
  4386. + __u8 AndXReserved;
  4387. + __u16 AndXOffset;
  4388. + __u16 ByteCount;
  4389. +} LOGOFF_ANDX_RSP;
  4390. +
  4391. +typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
  4392. + struct {
  4393. + struct smb_hdr hdr; /* wct = 0 */
  4394. + __u16 ByteCount; /* bcc = 0 */
  4395. + } req;
  4396. + struct {
  4397. + struct smb_hdr hdr; /* wct = 0 */
  4398. + __u16 ByteCount; /* bcc = 0 */
  4399. + } resp;
  4400. +} TREE_DISCONNECT;
  4401. +
  4402. +typedef struct smb_com_close_req {
  4403. + struct smb_hdr hdr; /* wct = 3 */
  4404. + __u16 FileID;
  4405. + __u32 LastWriteTime; /* should be zero */
  4406. + __u16 ByteCount; /* 0 */
  4407. +} CLOSE_REQ;
  4408. +
  4409. +typedef struct smb_com_close_rsp {
  4410. + struct smb_hdr hdr; /* wct = 0 */
  4411. + __u16 ByteCount; /* bct = 0 */
  4412. +} CLOSE_RSP;
  4413. +
  4414. +typedef struct smb_com_findclose_req {
  4415. + struct smb_hdr hdr; /* wct = 1 */
  4416. + __u16 FileID;
  4417. + __u16 ByteCount; /* 0 */
  4418. +} FINDCLOSE_REQ;
  4419. +
  4420. +/* OpenFlags */
  4421. +#define REQ_OPLOCK 0x00000002
  4422. +#define REQ_BATCHOPLOCK 0x00000004
  4423. +#define REQ_OPENDIRONLY 0x00000008
  4424. +
  4425. +typedef struct smb_com_open_req { /* also handles create */
  4426. + struct smb_hdr hdr; /* wct = 24 */
  4427. + __u8 AndXCommand;
  4428. + __u8 AndXReserved;
  4429. + __u16 AndXOffset;
  4430. + __u8 Reserved; /* Must Be Zero */
  4431. + __u16 NameLength;
  4432. + __u32 OpenFlags;
  4433. + __u32 RootDirectoryFid;
  4434. + __u32 DesiredAccess;
  4435. + __u64 AllocationSize;
  4436. + __u32 FileAttributes;
  4437. + __u32 ShareAccess;
  4438. + __u32 CreateDisposition;
  4439. + __u32 CreateOptions;
  4440. + __u32 ImpersonationLevel;
  4441. + __u8 SecurityFlags;
  4442. + __u16 ByteCount;
  4443. + char fileName[1];
  4444. +} OPEN_REQ;
  4445. +
  4446. +/* open response: oplock levels */
  4447. +#define OPLOCK_NONE 0
  4448. +#define OPLOCK_EXCLUSIVE 1
  4449. +#define OPLOCK_BATCH 2
  4450. +#define OPLOCK_READ 3 /* level 2 oplock */
  4451. +
  4452. +/* open response for CreateAction shifted left */
  4453. +#define CIFS_CREATE_ACTION 0x20000 /* file created */
  4454. +
  4455. +typedef struct smb_com_open_rsp {
  4456. + struct smb_hdr hdr; /* wct = 34 BB */
  4457. + __u8 AndXCommand;
  4458. + __u8 AndXReserved;
  4459. + __u16 AndXOffset;
  4460. + __u8 OplockLevel;
  4461. + __u16 Fid;
  4462. + __u32 CreateAction;
  4463. + __u64 CreationTime;
  4464. + __u64 LastAccessTime;
  4465. + __u64 LastWriteTime;
  4466. + __u64 ChangeTime;
  4467. + __u32 FileAttributes;
  4468. + __u64 AllocationSize;
  4469. + __u64 EndOfFile;
  4470. + __u16 FileType;
  4471. + __u16 DeviceState;
  4472. + __u8 DirectoryFlag;
  4473. + __u16 ByteCount; /* bct = 0 */
  4474. +} OPEN_RSP;
  4475. +
  4476. +typedef struct smb_com_write_req {
  4477. + struct smb_hdr hdr; /* wct = 14 */
  4478. + __u8 AndXCommand;
  4479. + __u8 AndXReserved;
  4480. + __u16 AndXOffset;
  4481. + __u16 Fid;
  4482. + __u32 OffsetLow;
  4483. + __u32 Reserved;
  4484. + __u16 WriteMode;
  4485. + __u16 Remaining;
  4486. + __u16 DataLengthHigh;
  4487. + __u16 DataLengthLow;
  4488. + __u16 DataOffset;
  4489. + __u32 OffsetHigh;
  4490. + __u16 ByteCount;
  4491. + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
  4492. + char Data[1];
  4493. +} WRITE_REQ;
  4494. +
  4495. +typedef struct smb_com_write_rsp {
  4496. + struct smb_hdr hdr; /* wct = 6 */
  4497. + __u8 AndXCommand;
  4498. + __u8 AndXReserved;
  4499. + __u16 AndXOffset;
  4500. + __u16 Count;
  4501. + __u16 Remaining;
  4502. + __u32 Reserved;
  4503. + __u16 ByteCount;
  4504. +} WRITE_RSP;
  4505. +
  4506. +typedef struct smb_com_read_req {
  4507. + struct smb_hdr hdr; /* wct = 12 */
  4508. + __u8 AndXCommand;
  4509. + __u8 AndXReserved;
  4510. + __u16 AndXOffset;
  4511. + __u16 Fid;
  4512. + __u32 OffsetLow;
  4513. + __u16 MaxCount;
  4514. + __u16 MinCount; /* obsolete */
  4515. + __u32 MaxCountHigh;
  4516. + __u16 Remaining;
  4517. + __u32 OffsetHigh;
  4518. + __u16 ByteCount;
  4519. +} READ_REQ;
  4520. +
  4521. +typedef struct smb_com_read_rsp {
  4522. + struct smb_hdr hdr; /* wct = 12 */
  4523. + __u8 AndXCommand;
  4524. + __u8 AndXReserved;
  4525. + __u16 AndXOffset;
  4526. + __u16 Remaining;
  4527. + __u16 DataCompactionMode;
  4528. + __u16 Reserved;
  4529. + __u16 DataLength;
  4530. + __u16 DataOffset;
  4531. + __u16 DataLengthHigh;
  4532. + __u64 Reserved2;
  4533. + __u16 ByteCount;
  4534. + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
  4535. + char Data[1];
  4536. +} READ_RSP;
  4537. +
  4538. +typedef struct locking_andx_range {
  4539. + __u16 Pid;
  4540. + __u16 Pad;
  4541. + __u32 OffsetHigh;
  4542. + __u32 OffsetLow;
  4543. + __u32 LengthHigh;
  4544. + __u32 LengthLow;
  4545. +} LOCKING_ANDX_RANGE;
  4546. +
  4547. +#define LOCKING_ANDX_SHARED_LOCK 0x01
  4548. +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
  4549. +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
  4550. +#define LOCKING_ANDX_CANCEL_LOCK 0x08
  4551. +#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
  4552. +
  4553. +typedef struct smb_com_lock_req {
  4554. + struct smb_hdr hdr; /* wct = 8 */
  4555. + __u8 AndXCommand;
  4556. + __u8 AndXReserved;
  4557. + __u16 AndXOffset;
  4558. + __u16 Fid;
  4559. + __u8 LockType;
  4560. + __u8 OplockLevel;
  4561. + __u32 Timeout;
  4562. + __u16 NumberOfUnlocks;
  4563. + __u16 NumberOfLocks;
  4564. + __u16 ByteCount;
  4565. + LOCKING_ANDX_RANGE Locks[1];
  4566. +} LOCK_REQ;
  4567. +
  4568. +typedef struct smb_com_lock_rsp {
  4569. + struct smb_hdr hdr; /* wct = 2 */
  4570. + __u8 AndXCommand;
  4571. + __u8 AndXReserved;
  4572. + __u16 AndXOffset;
  4573. + __u16 ByteCount;
  4574. +} LOCK_RSP;
  4575. +
  4576. +typedef struct smb_com_rename_req {
  4577. + struct smb_hdr hdr; /* wct = 1 */
  4578. + __u16 SearchAttributes; /* target file attributes */
  4579. + __u16 ByteCount;
  4580. + __u8 BufferFormat; /* 4 = ASCII or Unicode */
  4581. + unsigned char OldFileName[1];
  4582. + /* followed by __u8 BufferFormat2 */
  4583. + /* followed by NewFileName */
  4584. +} RENAME_REQ;
  4585. +
  4586. + /* copy request flags */
  4587. +#define COPY_MUST_BE_FILE 0x0001
  4588. +#define COPY_MUST_BE_DIR 0x0002
  4589. +#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
  4590. +#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
  4591. +#define COPY_VERIFY_WRITES 0x0010
  4592. +#define COPY_TREE 0x0020
  4593. +
  4594. +typedef struct smb_com_copy_req {
  4595. + struct smb_hdr hdr; /* wct = 3 */
  4596. + __u16 Tid2;
  4597. + __u16 OpenFunction;
  4598. + __u16 Flags;
  4599. + __u16 ByteCount;
  4600. + __u8 BufferFormat; /* 4 = ASCII or Unicode */
  4601. + unsigned char OldFileName[1];
  4602. + /* followed by __u8 BufferFormat2 */
  4603. + /* followed by NewFileName string */
  4604. +} COPY_REQ;
  4605. +
  4606. +typedef struct smb_com_copy_rsp {
  4607. + struct smb_hdr hdr; /* wct = 1 */
  4608. + __u16 CopyCount; /* number of files copied */
  4609. + __u16 ByteCount; /* may be zero */
  4610. + __u8 BufferFormat; /* 0x04 - only present if errored file follows */
  4611. + unsigned char ErrorFileName[1]; /* only present if error in copy */
  4612. +} COPY_RSP;
  4613. +
  4614. +#define CREATE_HARD_LINK 0x103
  4615. +#define MOVEFILE_COPY_ALLOWED 0x0002
  4616. +#define MOVEFILE_REPLACE_EXISTING 0x0001
  4617. +
  4618. +typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
  4619. + struct smb_hdr hdr; /* wct = 4 */
  4620. + __u16 SearchAttributes; /* target file attributes */
  4621. + __u16 Flags; /* spec says Information Level */
  4622. + __u32 ClusterCount;
  4623. + __u16 ByteCount;
  4624. + __u8 BufferFormat; /* 4 = ASCII or Unicode */
  4625. + unsigned char OldFileName[1];
  4626. + /* followed by __u8 BufferFormat2 */
  4627. + /* followed by NewFileName */
  4628. +} NT_RENAME_REQ;
  4629. +
  4630. +typedef struct smb_com_rename_rsp {
  4631. + struct smb_hdr hdr; /* wct = 0 */
  4632. + __u16 ByteCount; /* bct = 0 */
  4633. +} RENAME_RSP;
  4634. +
  4635. +typedef struct smb_com_delete_file_req {
  4636. + struct smb_hdr hdr; /* wct = 1 */
  4637. + __u16 SearchAttributes;
  4638. + __u16 ByteCount;
  4639. + __u8 BufferFormat; /* 4 = ASCII */
  4640. + unsigned char fileName[1];
  4641. +} DELETE_FILE_REQ;
  4642. +
  4643. +typedef struct smb_com_delete_file_rsp {
  4644. + struct smb_hdr hdr; /* wct = 0 */
  4645. + __u16 ByteCount; /* bct = 0 */
  4646. +} DELETE_FILE_RSP;
  4647. +
  4648. +typedef struct smb_com_delete_directory_req {
  4649. + struct smb_hdr hdr; /* wct = 0 */
  4650. + __u16 ByteCount;
  4651. + __u8 BufferFormat; /* 4 = ASCII */
  4652. + unsigned char DirName[1];
  4653. +} DELETE_DIRECTORY_REQ;
  4654. +
  4655. +typedef struct smb_com_delete_directory_rsp {
  4656. + struct smb_hdr hdr; /* wct = 0 */
  4657. + __u16 ByteCount; /* bct = 0 */
  4658. +} DELETE_DIRECTORY_RSP;
  4659. +
  4660. +typedef struct smb_com_create_directory_req {
  4661. + struct smb_hdr hdr; /* wct = 0 */
  4662. + __u16 ByteCount;
  4663. + __u8 BufferFormat; /* 4 = ASCII */
  4664. + unsigned char DirName[1];
  4665. +} CREATE_DIRECTORY_REQ;
  4666. +
  4667. +typedef struct smb_com_create_directory_rsp {
  4668. + struct smb_hdr hdr; /* wct = 0 */
  4669. + __u16 ByteCount; /* bct = 0 */
  4670. +} CREATE_DIRECTORY_RSP;
  4671. +
  4672. +/***************************************************/
  4673. +/* NT Transact structure defintions follow */
  4674. +/* Currently only ioctl and notify are implemented */
  4675. +/***************************************************/
  4676. +typedef struct smb_com_transaction_ioctl_req {
  4677. + struct smb_hdr hdr; /* wct = 23 */
  4678. + __u8 MaxSetupCount;
  4679. + __u16 Reserved;
  4680. + __u32 TotalParameterCount;
  4681. + __u32 TotalDataCount;
  4682. + __u32 MaxParameterCount;
  4683. + __u32 MaxDataCount;
  4684. + __u32 ParameterCount;
  4685. + __u32 ParameterOffset;
  4686. + __u32 DataCount;
  4687. + __u32 DataOffset;
  4688. + __u8 SetupCount; /* four setup words follow subcommand */
  4689. + /* SNIA spec incorrectly included spurious pad here */
  4690. + __u16 SubCommand;/* 2 = IOCTL/FSCTL */
  4691. + __u32 FunctionCode;
  4692. + __u16 Fid;
  4693. + __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
  4694. + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
  4695. + __u16 ByteCount;
  4696. + __u8 Pad[3];
  4697. + __u8 Data[1];
  4698. +} TRANSACT_IOCTL_REQ;
  4699. +
  4700. +typedef struct smb_com_transaction_ioctl_rsp {
  4701. + struct smb_hdr hdr; /* wct = 19 */
  4702. + __u8 Reserved[3];
  4703. + __u32 TotalParameterCount;
  4704. + __u32 TotalDataCount;
  4705. + __u32 ParameterCount;
  4706. + __u32 ParameterOffset;
  4707. + __u32 ParameterDisplacement;
  4708. + __u32 DataCount;
  4709. + __u32 DataOffset;
  4710. + __u32 DataDisplacement;
  4711. + __u8 SetupCount; /* 1 */
  4712. + __u16 ReturnedDataLen;
  4713. + __u16 ByteCount;
  4714. + __u8 Pad[3];
  4715. +} TRANSACT_IOCTL_RSP;
  4716. +
  4717. +typedef struct smb_com_transaction_change_notify_req {
  4718. + struct smb_hdr hdr; /* wct = 23 */
  4719. + __u8 MaxSetupCount;
  4720. + __u16 Reserved;
  4721. + __u32 TotalParameterCount;
  4722. + __u32 TotalDataCount;
  4723. + __u32 MaxParameterCount;
  4724. + __u32 MaxDataCount;
  4725. + __u32 ParameterCount;
  4726. + __u32 ParameterOffset;
  4727. + __u32 DataCount;
  4728. + __u32 DataOffset;
  4729. + __u8 SetupCount; /* four setup words follow subcommand */
  4730. + /* SNIA spec incorrectly included spurious pad here */
  4731. + __u16 SubCommand;/* 4 = Change Notify */
  4732. + __u32 CompletionFilter; /* operation to monitor */
  4733. + __u16 Fid;
  4734. + __u8 WatchTree; /* 1 = Monitor subdirectories */
  4735. + __u8 Reserved2;
  4736. + __u16 ByteCount;
  4737. +/* __u8 Pad[3];*/
  4738. +/* __u8 Data[1];*/
  4739. +} TRANSACT_CHANGE_NOTIFY_REQ;
  4740. +
  4741. +typedef struct smb_com_transaction_change_notify_rsp {
  4742. + struct smb_hdr hdr; /* wct = 18 */
  4743. + __u8 Reserved[3];
  4744. + __u32 TotalParameterCount;
  4745. + __u32 TotalDataCount;
  4746. + __u32 ParameterCount;
  4747. + __u32 ParameterOffset;
  4748. + __u32 ParameterDisplacement;
  4749. + __u32 DataCount;
  4750. + __u32 DataOffset;
  4751. + __u32 DataDisplacement;
  4752. + __u8 SetupCount; /* 0 */
  4753. + __u16 ByteCount;
  4754. + /* __u8 Pad[3]; */
  4755. +} TRANSACT_CHANGE_NOTIFY_RSP;
  4756. +/* Completion Filter flags for Notify */
  4757. +#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
  4758. +#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
  4759. +#define FILE_NOTIFY_CHANGE_NAME 0x00000003
  4760. +#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
  4761. +#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
  4762. +#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
  4763. +#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
  4764. +#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
  4765. +#define FILE_NOTIFY_CHANGE_EA 0x00000080
  4766. +#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
  4767. +#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
  4768. +#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
  4769. +#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
  4770. +
  4771. +#define FILE_ACTION_ADDED 0x00000001
  4772. +#define FILE_ACTION_REMOVED 0x00000002
  4773. +#define FILE_ACTION_MODIFIED 0x00000003
  4774. +#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
  4775. +#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
  4776. +#define FILE_ACTION_ADDED_STREAM 0x00000006
  4777. +#define FILE_ACTION_REMOVED_STREAM 0x00000007
  4778. +#define FILE_ACTION_MODIFIED_STREAM 0x00000008
  4779. +
  4780. +/* response contains array of the following structures */
  4781. +struct file_notify_information {
  4782. + __u32 NextEntryOffset;
  4783. + __u32 Action;
  4784. + __u32 FileNameLength;
  4785. + __u8 FileName[1];
  4786. +};
  4787. +
  4788. +struct reparse_data {
  4789. + __u32 ReparseTag;
  4790. + __u16 ReparseDataLength;
  4791. + __u16 Reserved;
  4792. + __u16 AltNameOffset;
  4793. + __u16 AltNameLen;
  4794. + __u16 TargetNameOffset;
  4795. + __u16 TargetNameLen;
  4796. + char LinkNamesBuf[1];
  4797. +};
  4798. +
  4799. +struct cifs_quota_data {
  4800. + __u32 rsrvd1; /* 0 */
  4801. + __u32 sid_size;
  4802. + __u64 rsrvd2; /* 0 */
  4803. + __u64 space_used;
  4804. + __u64 soft_limit;
  4805. + __u64 hard_limit;
  4806. + char sid[1]; /* variable size? */
  4807. +};
  4808. +
  4809. +/* quota sub commands */
  4810. +#define QUOTA_LIST_CONTINUE 0
  4811. +#define QUOTA_LIST_START 0x100
  4812. +#define QUOTA_FOR_SID 0x101
  4813. +
  4814. +typedef union smb_com_transaction2 {
  4815. + struct {
  4816. + struct smb_hdr hdr; /* wct = 14+ */
  4817. + __u16 TotalParameterCount;
  4818. + __u16 TotalDataCount;
  4819. + __u16 MaxParameterCount;
  4820. + __u16 MaxDataCount;
  4821. + __u8 MaxSetupCount;
  4822. + __u8 Reserved;
  4823. + __u16 Flags;
  4824. + __u32 Timeout;
  4825. + __u16 Reserved2;
  4826. + __u16 ParameterCount;
  4827. + __u16 ParameterOffset;
  4828. + __u16 DataCount;
  4829. + __u16 DataOffset;
  4830. + __u8 SetupCount;
  4831. + __u8 Reserved3;
  4832. + __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
  4833. + __u16 ByteCount; /* careful - setupcount is not always one */
  4834. + } req;
  4835. + struct {
  4836. + struct smb_hdr hdr; /* wct = 0 */
  4837. + __u16 TotalParameterCount;
  4838. + __u16 TotalDataCount;
  4839. + __u16 Reserved;
  4840. + __u16 ParameterCount;
  4841. + __u16 ParamterOffset;
  4842. + __u16 ParameterDisplacement;
  4843. + __u16 DataCount;
  4844. + __u16 DataOffset;
  4845. + __u16 DataDisplacement;
  4846. + __u8 SetupCount;
  4847. + __u8 Reserved1; /* should be zero setup words following */
  4848. + __u16 ByteCount;
  4849. + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
  4850. + /* data area follows */
  4851. + } resp;
  4852. +} TRANSACTION2;
  4853. +
  4854. +/* PathInfo/FileInfo infolevels */
  4855. +#define SMB_INFO_STANDARD 1
  4856. +#define SMB_INFO_QUERY_EAS_FROM_LIST 3
  4857. +#define SMB_INFO_QUERY_ALL_EAS 4
  4858. +#define SMB_INFO_IS_NAME_VALID 6
  4859. +#define SMB_QUERY_FILE_BASIC_INFO 0x101
  4860. +#define SMB_QUERY_FILE_STANDARD_INFO 0x102
  4861. +#define SMB_QUERY_FILE_EA_INFO 0x103
  4862. +#define SMB_QUERY_FILE_NAME_INFO 0x104
  4863. +#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
  4864. +#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
  4865. +#define SMB_QUERY_FILE_ALL_INFO 0x107
  4866. +#define SMB_QUERY_ALT_NAME_INFO 0x108
  4867. +#define SMB_QUERY_FILE_STREAM_INFO 0x109
  4868. +#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
  4869. +#define SMB_QUERY_FILE_UNIX_BASIC 0x200
  4870. +#define SMB_QUERY_FILE_UNIX_LINK 0x201
  4871. +
  4872. +#define SMB_SET_FILE_BASIC_INFO 0x101
  4873. +#define SMB_SET_FILE_DISPOSITION_INFO 0x102
  4874. +#define SMB_SET_FILE_ALLOCATION_INFO 0x103
  4875. +#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
  4876. +#define SMB_SET_FILE_UNIX_BASIC 0x200
  4877. +#define SMB_SET_FILE_UNIX_LINK 0x201
  4878. +#define SMB_SET_FILE_UNIX_HLINK 0x203
  4879. +#define SMB_SET_FILE_BASIC_INFO2 0x3ec
  4880. +#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
  4881. +#define SMB_FILE_ALL_INFO2 0x3fa
  4882. +#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
  4883. +#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
  4884. +#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
  4885. +#define SMB_FILE_QUOTA_INFO 0x408
  4886. +#define SMB_FILE_REPARSEPOINT_INFO 0x409
  4887. +#define SMB_FILE_MAXIMUM_INFO 0x40d
  4888. +
  4889. +/* Find File infolevels */
  4890. +#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
  4891. +#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
  4892. +#define SMB_FIND_FILE_NAMES_INFO 0x103
  4893. +#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
  4894. +#define SMB_FIND_FILE_UNIX 0x202
  4895. +
  4896. +typedef struct smb_com_transaction2_qpi_req {
  4897. + struct smb_hdr hdr; /* wct = 14+ */
  4898. + __u16 TotalParameterCount;
  4899. + __u16 TotalDataCount;
  4900. + __u16 MaxParameterCount;
  4901. + __u16 MaxDataCount;
  4902. + __u8 MaxSetupCount;
  4903. + __u8 Reserved;
  4904. + __u16 Flags;
  4905. + __u32 Timeout;
  4906. + __u16 Reserved2;
  4907. + __u16 ParameterCount;
  4908. + __u16 ParameterOffset;
  4909. + __u16 DataCount;
  4910. + __u16 DataOffset;
  4911. + __u8 SetupCount;
  4912. + __u8 Reserved3;
  4913. + __u16 SubCommand; /* one setup word */
  4914. + __u16 ByteCount;
  4915. + __u8 Pad;
  4916. + __u16 InformationLevel;
  4917. + __u32 Reserved4;
  4918. + char FileName[1];
  4919. +} TRANSACTION2_QPI_REQ;
  4920. +
  4921. +typedef struct smb_com_transaction2_qpi_rsp {
  4922. + struct smb_hdr hdr; /* wct = 10 + SetupCount */
  4923. + __u16 TotalParameterCount;
  4924. + __u16 TotalDataCount;
  4925. + __u16 Reserved;
  4926. + __u16 ParameterCount;
  4927. + __u16 ParameterOffset;
  4928. + __u16 ParameterDisplacement;
  4929. + __u16 DataCount;
  4930. + __u16 DataOffset;
  4931. + __u16 DataDisplacement;
  4932. + __u8 SetupCount;
  4933. + __u8 Reserved1; /* should be zero setup words following */
  4934. + __u16 ByteCount;
  4935. + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
  4936. +} TRANSACTION2_QPI_RSP;
  4937. +
  4938. +typedef struct smb_com_transaction2_spi_req {
  4939. + struct smb_hdr hdr; /* wct = 15 */
  4940. + __u16 TotalParameterCount;
  4941. + __u16 TotalDataCount;
  4942. + __u16 MaxParameterCount;
  4943. + __u16 MaxDataCount;
  4944. + __u8 MaxSetupCount;
  4945. + __u8 Reserved;
  4946. + __u16 Flags;
  4947. + __u32 Timeout;
  4948. + __u16 Reserved2;
  4949. + __u16 ParameterCount;
  4950. + __u16 ParameterOffset;
  4951. + __u16 DataCount;
  4952. + __u16 DataOffset;
  4953. + __u8 SetupCount;
  4954. + __u8 Reserved3;
  4955. + __u16 SubCommand; /* one setup word */
  4956. + __u16 ByteCount;
  4957. + __u8 Pad;
  4958. + __u16 Pad1;
  4959. + __u16 InformationLevel;
  4960. + __u32 Reserved4;
  4961. + char FileName[1];
  4962. +} TRANSACTION2_SPI_REQ;
  4963. +
  4964. +typedef struct smb_com_transaction2_spi_rsp {
  4965. + struct smb_hdr hdr; /* wct = 10 + SetupCount */
  4966. + __u16 TotalParameterCount;
  4967. + __u16 TotalDataCount;
  4968. + __u16 Reserved;
  4969. + __u16 ParameterCount;
  4970. + __u16 ParameterOffset;
  4971. + __u16 ParameterDisplacement;
  4972. + __u16 DataCount;
  4973. + __u16 DataOffset;
  4974. + __u16 DataDisplacement;
  4975. + __u8 SetupCount;
  4976. + __u8 Reserved1; /* should be zero setup words following */
  4977. + __u16 ByteCount;
  4978. + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
  4979. +} TRANSACTION2_SPI_RSP;
  4980. +
  4981. +struct set_file_rename {
  4982. + __u32 overwrite; /* 1 = overwrite dest */
  4983. + __u32 root_fid; /* zero */
  4984. + __u32 target_name_len;
  4985. + char target_name[0]; /* Must be unicode */
  4986. +};
  4987. +
  4988. +struct smb_com_transaction2_sfi_req {
  4989. + struct smb_hdr hdr; /* wct = 15 */
  4990. + __u16 TotalParameterCount;
  4991. + __u16 TotalDataCount;
  4992. + __u16 MaxParameterCount;
  4993. + __u16 MaxDataCount;
  4994. + __u8 MaxSetupCount;
  4995. + __u8 Reserved;
  4996. + __u16 Flags;
  4997. + __u32 Timeout;
  4998. + __u16 Reserved2;
  4999. + __u16 ParameterCount;
  5000. + __u16 ParameterOffset;
  5001. + __u16 DataCount;
  5002. + __u16 DataOffset;
  5003. + __u8 SetupCount;
  5004. + __u8 Reserved3;
  5005. + __u16 SubCommand; /* one setup word */
  5006. + __u16 ByteCount;
  5007. + __u8 Pad;
  5008. + __u16 Pad1;
  5009. + __u16 Fid;
  5010. + __u16 InformationLevel;
  5011. + __u16 Reserved4;
  5012. +};
  5013. +
  5014. +struct smb_com_transaction2_sfi_rsp {
  5015. + struct smb_hdr hdr; /* wct = 10 + SetupCount */
  5016. + __u16 TotalParameterCount;
  5017. + __u16 TotalDataCount;
  5018. + __u16 Reserved;
  5019. + __u16 ParameterCount;
  5020. + __u16 ParameterOffset;
  5021. + __u16 ParameterDisplacement;
  5022. + __u16 DataCount;
  5023. + __u16 DataOffset;
  5024. + __u16 DataDisplacement;
  5025. + __u8 SetupCount;
  5026. + __u8 Reserved1; /* should be zero setup words following */
  5027. + __u16 ByteCount;
  5028. + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
  5029. +};
  5030. +
  5031. +
  5032. +/*
  5033. + * Flags on T2 FINDFIRST and FINDNEXT
  5034. + */
  5035. +#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
  5036. +#define CIFS_SEARCH_CLOSE_AT_END 0x0002
  5037. +#define CIFS_SEARCH_RETURN_RESUME 0x0004
  5038. +#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
  5039. +#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
  5040. +
  5041. +/*
  5042. + * Size of the resume key on FINDFIRST and FINDNEXT calls
  5043. + */
  5044. +#define CIFS_SMB_RESUME_KEY_SIZE 4
  5045. +
  5046. +typedef struct smb_com_transaction2_ffirst_req {
  5047. + struct smb_hdr hdr; /* wct = 15 */
  5048. + __u16 TotalParameterCount;
  5049. + __u16 TotalDataCount;
  5050. + __u16 MaxParameterCount;
  5051. + __u16 MaxDataCount;
  5052. + __u8 MaxSetupCount;
  5053. + __u8 Reserved;
  5054. + __u16 Flags;
  5055. + __u32 Timeout;
  5056. + __u16 Reserved2;
  5057. + __u16 ParameterCount;
  5058. + __u16 ParameterOffset;
  5059. + __u16 DataCount;
  5060. + __u16 DataOffset;
  5061. + __u8 SetupCount; /* one */
  5062. + __u8 Reserved3;
  5063. + __u16 SubCommand; /* TRANS2_FIND_FIRST */
  5064. + __u16 ByteCount;
  5065. + __u8 Pad;
  5066. + __u16 SearchAttributes;
  5067. + __u16 SearchCount;
  5068. + __u16 SearchFlags;
  5069. + __u16 InformationLevel;
  5070. + __u32 SearchStorageType;
  5071. + char FileName[1];
  5072. +} TRANSACTION2_FFIRST_REQ;
  5073. +
  5074. +typedef struct smb_com_transaction2_ffirst_rsp {
  5075. + struct smb_hdr hdr; /* wct = 10 */
  5076. + __u16 TotalParameterCount;
  5077. + __u16 TotalDataCount;
  5078. + __u16 Reserved;
  5079. + __u16 ParameterCount;
  5080. + __u16 ParameterOffset;
  5081. + __u16 ParameterDisplacement;
  5082. + __u16 DataCount;
  5083. + __u16 DataOffset;
  5084. + __u16 DataDisplacement;
  5085. + __u8 SetupCount;
  5086. + __u8 Reserved1; /* should be zero setup words following */
  5087. + __u16 ByteCount;
  5088. +} TRANSACTION2_FFIRST_RSP;
  5089. +
  5090. +typedef struct smb_com_transaction2_ffirst_rsp_parms {
  5091. + __u16 SearchHandle;
  5092. + __u16 SearchCount;
  5093. + __u16 EndofSearch;
  5094. + __u16 EAErrorOffset;
  5095. + __u16 LastNameOffset;
  5096. +} T2_FFIRST_RSP_PARMS;
  5097. +
  5098. +typedef struct smb_com_transaction2_fnext_req {
  5099. + struct smb_hdr hdr; /* wct = 15 */
  5100. + __u16 TotalParameterCount;
  5101. + __u16 TotalDataCount;
  5102. + __u16 MaxParameterCount;
  5103. + __u16 MaxDataCount;
  5104. + __u8 MaxSetupCount;
  5105. + __u8 Reserved;
  5106. + __u16 Flags;
  5107. + __u32 Timeout;
  5108. + __u16 Reserved2;
  5109. + __u16 ParameterCount;
  5110. + __u16 ParameterOffset;
  5111. + __u16 DataCount;
  5112. + __u16 DataOffset;
  5113. + __u8 SetupCount; /* one */
  5114. + __u8 Reserved3;
  5115. + __u16 SubCommand; /* TRANS2_FIND_NEXT */
  5116. + __u16 ByteCount;
  5117. + __u8 Pad;
  5118. + __u16 SearchHandle;
  5119. + __u16 SearchCount;
  5120. + __u16 InformationLevel;
  5121. + __u32 ResumeKey;
  5122. + __u16 SearchFlags;
  5123. + char ResumeFileName[1];
  5124. +} TRANSACTION2_FNEXT_REQ;
  5125. +
  5126. +typedef struct smb_com_transaction2_fnext_rsp {
  5127. + struct smb_hdr hdr; /* wct = 10 */
  5128. + __u16 TotalParameterCount;
  5129. + __u16 TotalDataCount;
  5130. + __u16 Reserved;
  5131. + __u16 ParameterCount;
  5132. + __u16 ParameterOffset;
  5133. + __u16 ParameterDisplacement;
  5134. + __u16 DataCount;
  5135. + __u16 DataOffset;
  5136. + __u16 DataDisplacement;
  5137. + __u8 SetupCount;
  5138. + __u8 Reserved1; /* should be zero setup words following */
  5139. + __u16 ByteCount;
  5140. +} TRANSACTION2_FNEXT_RSP;
  5141. +
  5142. +typedef struct smb_com_transaction2_fnext_rsp_parms {
  5143. + __u16 SearchCount;
  5144. + __u16 EndofSearch;
  5145. + __u16 EAErrorOffset;
  5146. + __u16 LastNameOffset;
  5147. +} T2_FNEXT_RSP_PARMS;
  5148. +
  5149. +/* QFSInfo Levels */
  5150. +#define SMB_INFO_ALLOCATION 1
  5151. +#define SMB_INFO_VOLUME 2
  5152. +#define SMB_QUERY_FS_VOLUME_INFO 0x102
  5153. +#define SMB_QUERY_FS_SIZE_INFO 0x103
  5154. +#define SMB_QUERY_FS_DEVICE_INFO 0x104
  5155. +#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
  5156. +#define SMB_QUERY_CIFS_UNIX_INFO 0x200
  5157. +#define SMB_QUERY_LABEL_INFO 0x3ea
  5158. +#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
  5159. +
  5160. +typedef struct smb_com_transaction2_qfsi_req {
  5161. + struct smb_hdr hdr; /* wct = 14+ */
  5162. + __u16 TotalParameterCount;
  5163. + __u16 TotalDataCount;
  5164. + __u16 MaxParameterCount;
  5165. + __u16 MaxDataCount;
  5166. + __u8 MaxSetupCount;
  5167. + __u8 Reserved;
  5168. + __u16 Flags;
  5169. + __u32 Timeout;
  5170. + __u16 Reserved2;
  5171. + __u16 ParameterCount;
  5172. + __u16 ParameterOffset;
  5173. + __u16 DataCount;
  5174. + __u16 DataOffset;
  5175. + __u8 SetupCount;
  5176. + __u8 Reserved3;
  5177. + __u16 SubCommand; /* one setup word */
  5178. + __u16 ByteCount;
  5179. + __u8 Pad;
  5180. + __u16 InformationLevel;
  5181. +} TRANSACTION2_QFSI_REQ;
  5182. +
  5183. +typedef struct smb_com_transaction_qfsi_rsp {
  5184. + struct smb_hdr hdr; /* wct = 10 + SetupCount */
  5185. + __u16 TotalParameterCount;
  5186. + __u16 TotalDataCount;
  5187. + __u16 Reserved;
  5188. + __u16 ParameterCount;
  5189. + __u16 ParameterOffset;
  5190. + __u16 ParameterDisplacement;
  5191. + __u16 DataCount;
  5192. + __u16 DataOffset;
  5193. + __u16 DataDisplacement;
  5194. + __u8 SetupCount;
  5195. + __u8 Reserved1; /* should be zero setup words following */
  5196. + __u16 ByteCount;
  5197. + __u8 Pad; /* may be three bytes *//* followed by data area */
  5198. +} TRANSACTION2_QFSI_RSP;
  5199. +
  5200. +typedef struct smb_com_transaction2_get_dfs_refer_req {
  5201. + struct smb_hdr hdr; /* wct = 15 */
  5202. + __u16 TotalParameterCount;
  5203. + __u16 TotalDataCount;
  5204. + __u16 MaxParameterCount;
  5205. + __u16 MaxDataCount;
  5206. + __u8 MaxSetupCount;
  5207. + __u8 Reserved;
  5208. + __u16 Flags;
  5209. + __u32 Timeout;
  5210. + __u16 Reserved2;
  5211. + __u16 ParameterCount;
  5212. + __u16 ParameterOffset;
  5213. + __u16 DataCount;
  5214. + __u16 DataOffset;
  5215. + __u8 SetupCount;
  5216. + __u8 Reserved3;
  5217. + __u16 SubCommand; /* one setup word */
  5218. + __u16 ByteCount;
  5219. + __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
  5220. + __u16 MaxReferralLevel;
  5221. + char RequestFileName[1];
  5222. +} TRANSACTION2_GET_DFS_REFER_REQ;
  5223. +
  5224. +typedef struct dfs_referral_level_3 {
  5225. + __u16 VersionNumber;
  5226. + __u16 ReferralSize;
  5227. + __u16 ServerType; /* 0x0001 = CIFS server */
  5228. + __u16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
  5229. + __u16 TimeToLive;
  5230. + __u16 Proximity;
  5231. + __u16 DfsPathOffset;
  5232. + __u16 DfsAlternatePathOffset;
  5233. + __u16 NetworkAddressOffset;
  5234. +} REFERRAL3;
  5235. +
  5236. +typedef struct smb_com_transaction_get_dfs_refer_rsp {
  5237. + struct smb_hdr hdr; /* wct = 10 */
  5238. + __u16 TotalParameterCount;
  5239. + __u16 TotalDataCount;
  5240. + __u16 Reserved;
  5241. + __u16 ParameterCount;
  5242. + __u16 ParameterOffset;
  5243. + __u16 ParameterDisplacement;
  5244. + __u16 DataCount;
  5245. + __u16 DataOffset;
  5246. + __u16 DataDisplacement;
  5247. + __u8 SetupCount;
  5248. + __u8 Reserved1; /* zero setup words following */
  5249. + __u16 ByteCount;
  5250. + __u8 Pad;
  5251. + __u16 PathConsumed;
  5252. + __u16 NumberOfReferrals;
  5253. + __u16 DFSFlags;
  5254. + __u16 Pad2;
  5255. + REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
  5256. + /* followed by the strings pointed to by the referral structures */
  5257. +} TRANSACTION2_GET_DFS_REFER_RSP;
  5258. +
  5259. +/* DFS Flags */
  5260. +#define DFSREF_REFERRAL_SERVER 0x0001
  5261. +#define DFSREF_STORAGE_SERVER 0x0002
  5262. +
  5263. +/* IOCTL information */
  5264. +/* List of ioctl function codes that look to be of interest to remote clients like this. */
  5265. +/* Need to do some experimentation to make sure they all work remotely. */
  5266. +/* Some of the following such as the encryption/compression ones would be */
  5267. +/* invoked from tools via a specialized hook into the VFS rather than via the */
  5268. +/* standard vfs entry points */
  5269. +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
  5270. +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
  5271. +#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
  5272. +#define FSCTL_LOCK_VOLUME 0x00090018
  5273. +#define FSCTL_UNLOCK_VOLUME 0x0009001C
  5274. +#define FSCTL_GET_COMPRESSION 0x0009003C
  5275. +#define FSCTL_SET_COMPRESSION 0x0009C040
  5276. +#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
  5277. +#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
  5278. +#define FSCTL_SET_REPARSE_POINT 0x000900A4
  5279. +#define FSCTL_GET_REPARSE_POINT 0x000900A8
  5280. +#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
  5281. +#define FSCTL_SET_SPARSE 0x000900C4
  5282. +#define FSCTL_SET_ZERO_DATA 0x000900C8
  5283. +#define FSCTL_SET_ENCRYPTION 0x000900D7
  5284. +#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
  5285. +#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
  5286. +#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
  5287. +#define FSCTL_SIS_COPYFILE 0x00090100
  5288. +#define FSCTL_SIS_LINK_FILES 0x0009C104
  5289. +
  5290. +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
  5291. +#define IO_REPARSE_TAG_HSM 0xC0000004
  5292. +#define IO_REPARSE_TAG_SIS 0x80000007
  5293. +
  5294. +/*
  5295. + ************************************************************************
  5296. + * All structs for everything above the SMB PDUs themselves
  5297. + * (such as the T2 level specific data) go here
  5298. + ************************************************************************
  5299. + */
  5300. +
  5301. +/*
  5302. + * Information on a server
  5303. + */
  5304. +
  5305. +struct serverInfo {
  5306. + char name[16];
  5307. + unsigned char versionMajor;
  5308. + unsigned char versionMinor;
  5309. + unsigned long type;
  5310. + unsigned int commentOffset;
  5311. +};
  5312. +
  5313. +/*
  5314. + * The following structure is the format of the data returned on a NetShareEnum
  5315. + * with level "90" (x5A)
  5316. + */
  5317. +
  5318. +struct shareInfo {
  5319. + char shareName[13];
  5320. + char pad;
  5321. + unsigned short type;
  5322. + unsigned int commentOffset;
  5323. +};
  5324. +
  5325. +struct aliasInfo {
  5326. + char aliasName[9];
  5327. + char pad;
  5328. + unsigned int commentOffset;
  5329. + unsigned char type[2];
  5330. +};
  5331. +
  5332. +struct aliasInfo92 {
  5333. + int aliasNameOffset;
  5334. + int serverNameOffset;
  5335. + int shareNameOffset;
  5336. +};
  5337. +
  5338. +typedef struct {
  5339. + __u64 TotalAllocationUnits;
  5340. + __u64 FreeAllocationUnits;
  5341. + __u32 SectorsPerAllocationUnit;
  5342. + __u32 BytesPerSector;
  5343. +} FILE_SYSTEM_INFO; /* size info, level 0x103 */
  5344. +
  5345. +typedef struct {
  5346. + __u16 MajorVersionNumber;
  5347. + __u16 MinorVersionNumber;
  5348. + __u64 Capability;
  5349. +} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
  5350. +/* Linux/Unix extensions capability flags */
  5351. +#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
  5352. +#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
  5353. +
  5354. +/* DeviceType Flags */
  5355. +#define FILE_DEVICE_CD_ROM 0x00000002
  5356. +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
  5357. +#define FILE_DEVICE_DFS 0x00000006
  5358. +#define FILE_DEVICE_DISK 0x00000007
  5359. +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
  5360. +#define FILE_DEVICE_FILE_SYSTEM 0x00000009
  5361. +#define FILE_DEVICE_NAMED_PIPE 0x00000011
  5362. +#define FILE_DEVICE_NETWORK 0x00000012
  5363. +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
  5364. +#define FILE_DEVICE_NULL 0x00000015
  5365. +#define FILE_DEVICE_PARALLEL_PORT 0x00000016
  5366. +#define FILE_DEVICE_PRINTER 0x00000018
  5367. +#define FILE_DEVICE_SERIAL_PORT 0x0000001b
  5368. +#define FILE_DEVICE_STREAMS 0x0000001e
  5369. +#define FILE_DEVICE_TAPE 0x0000001f
  5370. +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
  5371. +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
  5372. +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
  5373. +
  5374. +typedef struct {
  5375. + __u32 DeviceType;
  5376. + __u32 DeviceCharacteristics;
  5377. +} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
  5378. +
  5379. +typedef struct {
  5380. + __u32 Attributes;
  5381. + __u32 MaxPathNameComponentLength;
  5382. + __u32 FileSystemNameLen;
  5383. + char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
  5384. +} FILE_SYSTEM_ATTRIBUTE_INFO;
  5385. +
  5386. +typedef struct { /* data block encoding of response to level 263 QPathInfo */
  5387. + __u64 CreationTime;
  5388. + __u64 LastAccessTime;
  5389. + __u64 LastWriteTime;
  5390. + __u64 ChangeTime;
  5391. + __u32 Attributes;
  5392. + __u32 Pad1;
  5393. + __u64 AllocationSize;
  5394. + __u64 EndOfFile; /* size ie offset to first free byte in file */
  5395. + __u32 NumberOfLinks; /* hard links */
  5396. + __u8 DeletePending;
  5397. + __u8 Directory;
  5398. + __u16 Pad2;
  5399. + __u64 IndexNumber;
  5400. + __u32 EASize;
  5401. + __u32 AccessFlags;
  5402. + __u64 IndexNumber1;
  5403. + __u64 CurrentByteOffset;
  5404. + __u32 Mode;
  5405. + __u32 AlignmentRequirement;
  5406. + __u32 FileNameLength;
  5407. + char FileName[1];
  5408. +} FILE_ALL_INFO; /* level 263 QPathInfo */
  5409. +
  5410. +typedef struct {
  5411. + __u64 EndOfFile;
  5412. + __u64 NumOfBytes;
  5413. + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
  5414. + __u64 LastAccessTime;
  5415. + __u64 LastModificationTime;
  5416. + __u64 Uid;
  5417. + __u64 Gid;
  5418. + __u32 Type;
  5419. + __u64 DevMajor;
  5420. + __u64 DevMinor;
  5421. + __u64 UniqueId;
  5422. + __u64 Permissions;
  5423. + __u64 Nlinks;
  5424. +} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
  5425. +
  5426. +typedef struct {
  5427. + char LinkDest[1];
  5428. +} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
  5429. +
  5430. +/* defines for enumerating possible values of the Unix type field below */
  5431. +#define UNIX_FILE 0
  5432. +#define UNIX_DIR 1
  5433. +#define UNIX_SYMLINK 2
  5434. +#define UNIX_CHARDEV 3
  5435. +#define UNIX_BLOCKDEV 4
  5436. +#define UNIX_FIFO 5
  5437. +#define UNIX_SOCKET 6
  5438. +
  5439. +typedef struct {
  5440. + __u32 NextEntryOffset;
  5441. + __u32 ResumeKey;
  5442. + __u64 EndOfFile;
  5443. + __u64 NumOfBytes;
  5444. + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
  5445. + __u64 LastAccessTime;
  5446. + __u64 LastModificationTime;
  5447. + __u64 Uid;
  5448. + __u64 Gid;
  5449. + __u32 Type;
  5450. + __u64 DevMajor;
  5451. + __u64 DevMinor;
  5452. + __u64 UniqueId;
  5453. + __u64 Permissions;
  5454. + __u64 Nlinks;
  5455. + char FileName[1];
  5456. +} FILE_UNIX_INFO;
  5457. +
  5458. +typedef struct {
  5459. + __u64 CreationTime;
  5460. + __u64 LastAccessTime;
  5461. + __u64 LastWriteTime;
  5462. + __u64 ChangeTime;
  5463. + __u32 Attributes;
  5464. + __u32 Pad;
  5465. +} FILE_BASIC_INFO; /* size info, level 0x101 */
  5466. +
  5467. +struct file_allocation_info {
  5468. + __u64 AllocationSize;
  5469. +}; /* size info, level 0x103 */
  5470. +
  5471. +struct file_end_of_file_info {
  5472. + __u64 FileSize; /* offset to end of file */
  5473. +}; /* size info, level 0x104 */
  5474. +
  5475. +typedef struct {
  5476. + __u32 NextEntryOffset;
  5477. + __u32 FileIndex;
  5478. + __u64 CreationTime;
  5479. + __u64 LastAccessTime;
  5480. + __u64 LastWriteTime;
  5481. + __u64 ChangeTime;
  5482. + __u64 EndOfFile;
  5483. + __u64 AllocationSize;
  5484. + __u32 ExtFileAttributes;
  5485. + __u32 FileNameLength;
  5486. + char FileName[1];
  5487. +} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
  5488. +
  5489. +struct gea {
  5490. + unsigned char cbName;
  5491. + char szName[1];
  5492. +};
  5493. +
  5494. +struct gealist {
  5495. + unsigned long cbList;
  5496. + struct gea list[1];
  5497. +};
  5498. +
  5499. +struct fea {
  5500. + unsigned char EA_flags;
  5501. + __u8 name_len;
  5502. + __u16 value_len;
  5503. + char szName[1];
  5504. + /* optionally followed by value */
  5505. +};
  5506. +/* flags for _FEA.fEA */
  5507. +#define FEA_NEEDEA 0x80 /* need EA bit */
  5508. +
  5509. +struct fealist {
  5510. + __u32 list_len;
  5511. + struct fea list[1];
  5512. +};
  5513. +
  5514. +/* used to hold an arbitrary blob of data */
  5515. +struct data_blob {
  5516. + __u8 *data;
  5517. + size_t length;
  5518. + void (*free) (struct data_blob * data_blob);
  5519. +};
  5520. +
  5521. +#ifdef CONFIG_CIFS_POSIX
  5522. +/*
  5523. + For better POSIX semantics from Linux client, (even better
  5524. + than the existing CIFS Unix Extensions) we need updated PDUs for:
  5525. +
  5526. + 1) PosixCreateX - to set and return the mode, inode#, device info and
  5527. + perhaps add a CreateDevice - to create Pipes and other special .inodes
  5528. + Also note POSIX open flags
  5529. + 2) Close - to return the last write time to do cache across close more safely
  5530. + 3) PosixQFSInfo - to return statfs info
  5531. + 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
  5532. + 5) Mkdir - set mode
  5533. +
  5534. + And under consideration:
  5535. + 6) FindClose2 (return nanosecond timestamp ??)
  5536. + 7) Use nanosecond timestamps throughout all time fields if
  5537. + corresponding attribute flag is set
  5538. + 8) sendfile - handle based copy
  5539. + 9) Direct i/o
  5540. + 10) "POSIX ACL" support
  5541. + 11) Misc fcntls?
  5542. +
  5543. + what about fixing 64 bit alignment
  5544. +
  5545. + There are also various legacy SMB/CIFS requests used as is
  5546. +
  5547. + From existing Lanman and NTLM dialects:
  5548. + --------------------------------------
  5549. + NEGOTIATE
  5550. + SESSION_SETUP_ANDX (BB which?)
  5551. + TREE_CONNECT_ANDX (BB which wct?)
  5552. + TREE_DISCONNECT (BB add volume timestamp on response)
  5553. + LOGOFF_ANDX
  5554. + DELETE (note delete open file behavior)
  5555. + DELETE_DIRECTORY
  5556. + READ_AND_X
  5557. + WRITE_AND_X
  5558. + LOCKING_AND_X (note posix lock semantics)
  5559. + RENAME (note rename across dirs and open file rename posix behaviors)
  5560. + NT_RENAME (for hardlinks) Is this good enough for all features?
  5561. + FIND_CLOSE2
  5562. + TRANSACTION2 (18 cases)
  5563. + SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
  5564. + (BB verify that never need to set allocation size)
  5565. + SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
  5566. +
  5567. + COPY (note support for copy across directories) - FUTURE, OPTIONAL
  5568. + setting/getting OS/2 EAs - FUTURE (BB can this handle
  5569. + setting Linux xattrs perfectly) - OPTIONAL
  5570. + dnotify - FUTURE, OPTIONAL
  5571. + quota - FUTURE, OPTIONAL
  5572. +
  5573. + Note that various requests implemented for NT interop such as
  5574. + NT_TRANSACT (IOCTL) QueryReparseInfo
  5575. + are unneeded to servers compliant with the CIFS POSIX extensions
  5576. +
  5577. + From CIFS Unix Extensions:
  5578. + -------------------------
  5579. + T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
  5580. + T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
  5581. + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
  5582. + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
  5583. + Actually need QUERY_FILE_UNIX_INFO since has inode num
  5584. + BB what about a) blksize/blkbits/blocks
  5585. + b) i_version
  5586. + c) i_rdev
  5587. + d) notify mask?
  5588. + e) generation
  5589. + f) size_seqcount
  5590. + T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
  5591. + TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
  5592. + T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
  5593. +
  5594. +
  5595. + */
  5596. +#endif
  5597. +
  5598. +#pragma pack() /* resume default structure packing */
  5599. +
  5600. +#endif /* _CIFSPDU_H */
  5601. --- /dev/null
  5602. +++ b/fs/cifs/cifsproto.h
  5603. @@ -0,0 +1,254 @@
  5604. +/*
  5605. + * fs/cifs/cifsproto.h
  5606. + *
  5607. + * Copyright (c) International Business Machines Corp., 2002
  5608. + * Author(s): Steve French ([email protected])
  5609. + *
  5610. + * This library is free software; you can redistribute it and/or modify
  5611. + * it under the terms of the GNU Lesser General Public License as published
  5612. + * by the Free Software Foundation; either version 2.1 of the License, or
  5613. + * (at your option) any later version.
  5614. + *
  5615. + * This library is distributed in the hope that it will be useful,
  5616. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5617. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  5618. + * the GNU Lesser General Public License for more details.
  5619. + *
  5620. + * You should have received a copy of the GNU Lesser General Public License
  5621. + * along with this library; if not, write to the Free Software
  5622. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  5623. + */
  5624. +#ifndef _CIFSPROTO_H
  5625. +#define _CIFSPROTO_H
  5626. +#include <linux/nls.h>
  5627. +
  5628. +struct statfs;
  5629. +
  5630. +/*
  5631. + *****************************************************************
  5632. + * All Prototypes
  5633. + *****************************************************************
  5634. + */
  5635. +
  5636. +extern struct smb_hdr *cifs_buf_get(void);
  5637. +extern void cifs_buf_release(void *);
  5638. +extern int smb_send(struct socket *, struct smb_hdr *,
  5639. + unsigned int /* length */ , struct sockaddr *);
  5640. +extern unsigned int _GetXid(void);
  5641. +extern void _FreeXid(unsigned int);
  5642. +#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
  5643. +#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
  5644. +extern char *build_path_from_dentry(struct dentry *);
  5645. +extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
  5646. +extern void renew_parental_timestamps(struct dentry *direntry);
  5647. +extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
  5648. + struct smb_hdr * /* input */ ,
  5649. + struct smb_hdr * /* out */ ,
  5650. + int * /* bytes returned */ , const int long_op);
  5651. +extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
  5652. +extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
  5653. +extern int is_valid_oplock_break(struct smb_hdr *smb);
  5654. +extern unsigned int smbCalcSize(struct smb_hdr *ptr);
  5655. +extern int decode_negTokenInit(unsigned char *security_blob, int length,
  5656. + enum securityEnum *secType);
  5657. +extern int map_smb_to_linux_error(struct smb_hdr *smb);
  5658. +extern void header_assemble(struct smb_hdr *, char /* command */ ,
  5659. + const struct cifsTconInfo *, int
  5660. + /* length of fixed section (word count) in two byte units */
  5661. + );
  5662. +struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
  5663. +void DeleteOplockQEntry(struct oplock_q_entry *);
  5664. +extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
  5665. +extern u64 cifs_UnixTimeToNT(time_t);
  5666. +extern int cifs_get_inode_info(struct inode **pinode,
  5667. + const unsigned char *search_path,
  5668. + FILE_ALL_INFO * pfile_info,
  5669. + struct super_block *sb, int xid);
  5670. +extern int cifs_get_inode_info_unix(struct inode **pinode,
  5671. + const unsigned char *search_path,
  5672. + struct super_block *sb,int xid);
  5673. +
  5674. +extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
  5675. + struct nls_table * nls_info);
  5676. +extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
  5677. +
  5678. +extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
  5679. + const char *tree, struct cifsTconInfo *tcon,
  5680. + const struct nls_table *);
  5681. +
  5682. +extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
  5683. + const char *searchName,
  5684. + FILE_DIRECTORY_INFO * findData,
  5685. + T2_FFIRST_RSP_PARMS * findParms,
  5686. + const struct nls_table *nls_codepage,
  5687. + int *pUnicodeFlag,
  5688. + int *pUnixFlag /* if Unix extensions used */ );
  5689. +extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
  5690. + FILE_DIRECTORY_INFO * findData,
  5691. + T2_FNEXT_RSP_PARMS * findParms,
  5692. + const __u16 searchHandle, char * resume_name,
  5693. + int name_length, __u32 resume_key,
  5694. + int *UnicodeFlag, int *pUnixFlag);
  5695. +
  5696. +extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
  5697. + const __u16 search_handle);
  5698. +
  5699. +extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
  5700. + const unsigned char *searchName,
  5701. + FILE_ALL_INFO * findData,
  5702. + const struct nls_table *nls_codepage);
  5703. +
  5704. +extern int CIFSSMBUnixQPathInfo(const int xid,
  5705. + struct cifsTconInfo *tcon,
  5706. + const unsigned char *searchName,
  5707. + FILE_UNIX_BASIC_INFO * pFindData,
  5708. + const struct nls_table *nls_codepage);
  5709. +
  5710. +extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
  5711. + const unsigned char *searchName,
  5712. + unsigned char **targetUNCs,
  5713. + unsigned int *number_of_UNC_in_array,
  5714. + const struct nls_table *nls_codepage);
  5715. +
  5716. +extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
  5717. + const char *old_path,
  5718. + const struct nls_table *nls_codepage);
  5719. +extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
  5720. + const char *old_path, const struct nls_table *nls_codepage,
  5721. + unsigned int *pnum_referrals, unsigned char ** preferrals);
  5722. +extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
  5723. + struct statfs *FSData,
  5724. + const struct nls_table *nls_codepage);
  5725. +extern int CIFSSMBQFSAttributeInfo(const int xid,
  5726. + struct cifsTconInfo *tcon,
  5727. + const struct nls_table *nls_codepage);
  5728. +extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
  5729. + const struct nls_table *nls_codepage);
  5730. +extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
  5731. + const struct nls_table *nls_codepage);
  5732. +
  5733. +extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
  5734. + char *fileName, FILE_BASIC_INFO * data,
  5735. + const struct nls_table *nls_codepage);
  5736. +extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
  5737. + char *fileName, __u64 size,int setAllocationSizeFlag,
  5738. + const struct nls_table *nls_codepage);
  5739. +extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
  5740. + __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
  5741. +extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
  5742. + char *full_path, __u64 mode, __u64 uid,
  5743. + __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
  5744. +
  5745. +extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
  5746. + const char *newName,
  5747. + const struct nls_table *nls_codepage);
  5748. +extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
  5749. + const char *name, const struct nls_table *nls_codepage);
  5750. +
  5751. +extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
  5752. + const char *name,
  5753. + const struct nls_table *nls_codepage);
  5754. +extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
  5755. + const char *fromName, const char *toName,
  5756. + const struct nls_table *nls_codepage);
  5757. +extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
  5758. + int netfid, char * target_name, const struct nls_table *nls_codepage);
  5759. +extern int CIFSCreateHardLink(const int xid,
  5760. + struct cifsTconInfo *tcon,
  5761. + const char *fromName, const char *toName,
  5762. + const struct nls_table *nls_codepage);
  5763. +extern int CIFSUnixCreateHardLink(const int xid,
  5764. + struct cifsTconInfo *tcon,
  5765. + const char *fromName, const char *toName,
  5766. + const struct nls_table *nls_codepage);
  5767. +extern int CIFSUnixCreateSymLink(const int xid,
  5768. + struct cifsTconInfo *tcon,
  5769. + const char *fromName, const char *toName,
  5770. + const struct nls_table *nls_codepage);
  5771. +extern int CIFSSMBUnixQuerySymLink(const int xid,
  5772. + struct cifsTconInfo *tcon,
  5773. + const unsigned char *searchName,
  5774. + char *syminfo, const int buflen,
  5775. + const struct nls_table *nls_codepage);
  5776. +extern int CIFSSMBQueryReparseLinkInfo(const int xid,
  5777. + struct cifsTconInfo *tcon,
  5778. + const unsigned char *searchName,
  5779. + char *symlinkinfo, const int buflen, __u16 fid,
  5780. + const struct nls_table *nls_codepage);
  5781. +
  5782. +extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
  5783. + const char *fileName, const int disposition,
  5784. + const int access_flags, const int omode,
  5785. + __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
  5786. + const struct nls_table *nls_codepage);
  5787. +extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
  5788. + const int smb_file_id);
  5789. +
  5790. +extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
  5791. + const int netfid, unsigned int count,
  5792. + const __u64 lseek, unsigned int *nbytes, char **buf);
  5793. +extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
  5794. + const int netfid, const unsigned int count,
  5795. + const __u64 lseek, unsigned int *nbytes,
  5796. + const char *buf, const int long_op);
  5797. +extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
  5798. + const __u16 netfid, const __u64 len,
  5799. + const __u64 offset, const __u32 numUnlock,
  5800. + const __u32 numLock, const __u8 lockType,
  5801. + const int waitFlag);
  5802. +
  5803. +extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
  5804. +extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
  5805. +
  5806. +extern struct cifsSesInfo *sesInfoAlloc(void);
  5807. +extern void sesInfoFree(struct cifsSesInfo *);
  5808. +extern struct cifsTconInfo *tconInfoAlloc(void);
  5809. +extern void tconInfoFree(struct cifsTconInfo *);
  5810. +
  5811. +extern int cifs_reconnect(struct TCP_Server_Info *server);
  5812. +
  5813. +extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
  5814. +extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
  5815. + __u32 expected_sequence_number);
  5816. +extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
  5817. +extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
  5818. +extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
  5819. +
  5820. +extern int CIFSBuildServerList(int xid, char *serverBufferList,
  5821. + int recordlength, int *entries,
  5822. + int *totalEntries, int *topoChangedFlag);
  5823. +extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
  5824. + struct shareInfo *shareList, int bufferLen,
  5825. + int *entries, int *totalEntries);
  5826. +extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
  5827. + struct aliasInfo *aliasList, int bufferLen,
  5828. + int *entries, int *totalEntries);
  5829. +extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
  5830. + char *aliasName, char *serverName,
  5831. + char *shareName, char *comment);
  5832. +extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
  5833. + char *share, char *comment);
  5834. +extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
  5835. + char *userName, char *searchName, int *perms);
  5836. +extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
  5837. +
  5838. +extern int CIFSSMBSeek(int xid,
  5839. + struct cifsTconInfo *tcon,
  5840. + int netfid,
  5841. + int pid,
  5842. + int whence, unsigned long offset, long long *newoffset);
  5843. +
  5844. +extern int CIFSSMBCopy(int xid,
  5845. + struct cifsTconInfo *source_tcon,
  5846. + const char *fromName,
  5847. + const __u16 target_tid,
  5848. + const char *toName, const int flags,
  5849. + const struct nls_table *nls_codepage);
  5850. +extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
  5851. + const int notify_subdirs,const __u16 netfid,__u32 filter,
  5852. + const struct nls_table *nls_codepage);
  5853. +extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
  5854. + const unsigned char *searchName,
  5855. + char * EAData, size_t size,
  5856. + const struct nls_table *nls_codepage);
  5857. +#endif /* _CIFSPROTO_H */
  5858. --- /dev/null
  5859. +++ b/fs/cifs/cifssmb.c
  5860. @@ -0,0 +1,3016 @@
  5861. +/*
  5862. + * fs/cifs/cifssmb.c
  5863. + *
  5864. + * Copyright (C) International Business Machines Corp., 2002,2003
  5865. + * Author(s): Steve French ([email protected])
  5866. + *
  5867. + * Contains the routines for constructing the SMB PDUs themselves
  5868. + *
  5869. + * This library is free software; you can redistribute it and/or modify
  5870. + * it under the terms of the GNU Lesser General Public License as published
  5871. + * by the Free Software Foundation; either version 2.1 of the License, or
  5872. + * (at your option) any later version.
  5873. + *
  5874. + * This library is distributed in the hope that it will be useful,
  5875. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5876. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  5877. + * the GNU Lesser General Public License for more details.
  5878. + *
  5879. + * You should have received a copy of the GNU Lesser General Public License
  5880. + * along with this library; if not, write to the Free Software
  5881. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  5882. + */
  5883. +
  5884. + /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
  5885. + /* These are mostly routines that operate on a pathname, or on a tree id */
  5886. + /* (mounted volume), but there are eight handle based routines which must be */
  5887. + /* treated slightly different for reconnection purposes since we never want */
  5888. + /* to reuse a stale file handle and the caller knows the file handle */
  5889. +
  5890. +#include <linux/fs.h>
  5891. +#include <linux/kernel.h>
  5892. +#include <linux/vfs.h>
  5893. +#include <asm/uaccess.h>
  5894. +#include "cifspdu.h"
  5895. +#include "cifsglob.h"
  5896. +#include "cifsproto.h"
  5897. +#include "cifs_unicode.h"
  5898. +#include "cifs_debug.h"
  5899. +
  5900. +#ifdef CONFIG_CIFS_POSIX
  5901. +static struct {
  5902. + int index;
  5903. + char *name;
  5904. +} protocols[] = {
  5905. + {CIFS_PROT, "\2NT LM 0.12"},
  5906. + {CIFS_PROT, "\2POSIX 2"},
  5907. + {BAD_PROT, "\2"}
  5908. +};
  5909. +#else
  5910. +static struct {
  5911. + int index;
  5912. + char *name;
  5913. +} protocols[] = {
  5914. + {CIFS_PROT, "\2NT LM 0.12"},
  5915. + {BAD_PROT, "\2"}
  5916. +};
  5917. +#endif
  5918. +
  5919. +
  5920. +/* Mark as invalid, all open files on tree connections since they
  5921. + were closed when session to server was lost */
  5922. +static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
  5923. +{
  5924. + struct cifsFileInfo *open_file = NULL;
  5925. + struct list_head * tmp;
  5926. + struct list_head * tmp1;
  5927. +
  5928. +/* list all files open on tree connection and mark them invalid */
  5929. + write_lock(&GlobalSMBSeslock);
  5930. + list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
  5931. + open_file = list_entry(tmp,struct cifsFileInfo, tlist);
  5932. + if(open_file) {
  5933. + open_file->invalidHandle = TRUE;
  5934. + }
  5935. + }
  5936. + write_unlock(&GlobalSMBSeslock);
  5937. + /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
  5938. +}
  5939. +
  5940. +static int
  5941. +smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
  5942. + void **request_buf /* returned */ ,
  5943. + void **response_buf /* returned */ )
  5944. +{
  5945. + int rc = 0;
  5946. + int timeout = 10 * HZ;
  5947. +
  5948. + /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
  5949. + check for tcp and smb session status done differently
  5950. + for those three - in the calling routine */
  5951. + if(tcon) {
  5952. + if((tcon->ses) && (tcon->ses->server)){
  5953. + struct nls_table *nls_codepage;
  5954. + /* Give Demultiplex thread up to 10 seconds to
  5955. + reconnect, should be greater than cifs socket
  5956. + timeout which is 7 seconds */
  5957. + while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
  5958. + while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
  5959. + timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
  5960. + }
  5961. + if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
  5962. + /* on "soft" mounts we wait once */
  5963. + if((tcon->retry == FALSE) ||
  5964. + (tcon->ses->status == CifsExiting)) {
  5965. + cFYI(1,("gave up waiting on reconnect in smb_init"));
  5966. + return -EHOSTDOWN;
  5967. + } /* else "hard" mount - keep retrying until
  5968. + process is killed or server comes back up */
  5969. + } else /* TCP session is reestablished now */
  5970. + break;
  5971. +
  5972. + }
  5973. +
  5974. + nls_codepage = load_nls_default();
  5975. + /* need to prevent multiple threads trying to
  5976. + simultaneously reconnect the same SMB session */
  5977. + down(&tcon->ses->sesSem);
  5978. + if(tcon->ses->status == CifsNeedReconnect)
  5979. + rc = cifs_setup_session(0, tcon->ses, nls_codepage);
  5980. + if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
  5981. + mark_open_files_invalid(tcon);
  5982. + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
  5983. + nls_codepage);
  5984. + up(&tcon->ses->sesSem);
  5985. + if(rc == 0)
  5986. + atomic_inc(&tconInfoReconnectCount);
  5987. +
  5988. + cFYI(1, ("reconnect tcon rc = %d", rc));
  5989. + /* Removed call to reopen open files here -
  5990. + it is safer (and faster) to reopen files
  5991. + one at a time as needed in read and write */
  5992. +
  5993. + /* Check if handle based operation so we
  5994. + know whether we can continue or not without
  5995. + returning to caller to reset file handle */
  5996. + switch(smb_command) {
  5997. + case SMB_COM_READ_ANDX:
  5998. + case SMB_COM_WRITE_ANDX:
  5999. + case SMB_COM_CLOSE:
  6000. + case SMB_COM_FIND_CLOSE2:
  6001. + case SMB_COM_LOCKING_ANDX: {
  6002. + unload_nls(nls_codepage);
  6003. + return -EAGAIN;
  6004. + }
  6005. + }
  6006. + } else {
  6007. + up(&tcon->ses->sesSem);
  6008. + }
  6009. + unload_nls(nls_codepage);
  6010. +
  6011. + } else {
  6012. + return -EIO;
  6013. + }
  6014. + }
  6015. + if(rc)
  6016. + return rc;
  6017. +
  6018. + *request_buf = cifs_buf_get();
  6019. + if (*request_buf == 0) {
  6020. + /* BB should we add a retry in here if not a writepage? */
  6021. + return -ENOMEM;
  6022. + }
  6023. + /* Although the original thought was we needed the response buf for */
  6024. + /* potential retries of smb operations it turns out we can determine */
  6025. + /* from the mid flags when the request buffer can be resent without */
  6026. + /* having to use a second distinct buffer for the response */
  6027. + *response_buf = *request_buf;
  6028. +
  6029. + header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
  6030. + wct /*wct */ );
  6031. +
  6032. +#ifdef CONFIG_CIFS_STATS
  6033. + if(tcon != NULL) {
  6034. + atomic_inc(&tcon->num_smbs_sent);
  6035. + }
  6036. +#endif
  6037. + return rc;
  6038. +}
  6039. +
  6040. +int
  6041. +CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
  6042. +{
  6043. + NEGOTIATE_REQ *pSMB;
  6044. + NEGOTIATE_RSP *pSMBr;
  6045. + int rc = 0;
  6046. + int bytes_returned;
  6047. + struct TCP_Server_Info * server;
  6048. +
  6049. + if(ses->server)
  6050. + server = ses->server;
  6051. + else {
  6052. + rc = -EIO;
  6053. + return rc;
  6054. + }
  6055. + rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
  6056. + (void **) &pSMB, (void **) &pSMBr);
  6057. + if (rc)
  6058. + return rc;
  6059. +
  6060. + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  6061. + if (extended_security)
  6062. + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
  6063. +
  6064. + pSMB->ByteCount = strlen(protocols[0].name) + 1;
  6065. + strncpy(pSMB->DialectsArray, protocols[0].name, 30);
  6066. + /* null guaranteed to be at end of source and target buffers anyway */
  6067. +
  6068. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6069. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6070. +
  6071. + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  6072. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6073. + if (rc == 0) {
  6074. + server->secMode = pSMBr->SecurityMode;
  6075. + server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
  6076. + /* one byte - no need to convert this or EncryptionKeyLen from le,*/
  6077. + server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
  6078. + /* probably no need to store and check maxvcs */
  6079. + server->maxBuf =
  6080. + min(le32_to_cpu(pSMBr->MaxBufferSize),
  6081. + (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
  6082. + server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
  6083. + cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
  6084. + GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
  6085. + server->capabilities = le32_to_cpu(pSMBr->Capabilities);
  6086. + server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
  6087. + /* BB with UTC do we ever need to be using srvr timezone? */
  6088. + if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
  6089. + memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
  6090. + CIFS_CRYPTO_KEY_SIZE);
  6091. + } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
  6092. + && (pSMBr->EncryptionKeyLength == 0)) {
  6093. + /* decode security blob */
  6094. + } else
  6095. + rc = -EIO;
  6096. +
  6097. + /* BB might be helpful to save off the domain of server here */
  6098. +
  6099. + if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
  6100. + if (pSMBr->ByteCount < 16)
  6101. + rc = -EIO;
  6102. + else if (pSMBr->ByteCount == 16) {
  6103. + server->secType = RawNTLMSSP;
  6104. + if (server->socketUseCount.counter > 1) {
  6105. + if (memcmp
  6106. + (server->server_GUID,
  6107. + pSMBr->u.extended_response.
  6108. + GUID, 16) != 0) {
  6109. + cFYI(1,
  6110. + ("UID of server does not match previous connection to same ip address"));
  6111. + memcpy(server->
  6112. + server_GUID,
  6113. + pSMBr->u.
  6114. + extended_response.
  6115. + GUID, 16);
  6116. + }
  6117. + } else
  6118. + memcpy(server->server_GUID,
  6119. + pSMBr->u.extended_response.
  6120. + GUID, 16);
  6121. + } else {
  6122. + rc = decode_negTokenInit(pSMBr->u.
  6123. + extended_response.
  6124. + SecurityBlob,
  6125. + pSMBr->ByteCount -
  6126. + 16, &server->secType);
  6127. + }
  6128. + } else
  6129. + server->capabilities &= ~CAP_EXTENDED_SECURITY;
  6130. + if(sign_CIFS_PDUs == FALSE) {
  6131. + if(server->secMode & SECMODE_SIGN_REQUIRED)
  6132. + cERROR(1,
  6133. + ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
  6134. + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
  6135. + } else if(sign_CIFS_PDUs == 1) {
  6136. + if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
  6137. + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
  6138. + }
  6139. +
  6140. + }
  6141. + if (pSMB)
  6142. + cifs_buf_release(pSMB);
  6143. + return rc;
  6144. +}
  6145. +
  6146. +int
  6147. +CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
  6148. +{
  6149. + struct smb_hdr *smb_buffer;
  6150. + struct smb_hdr *smb_buffer_response;
  6151. + int rc = 0;
  6152. + int length;
  6153. +
  6154. + cFYI(1, ("In tree disconnect"));
  6155. + /*
  6156. + * If last user of the connection and
  6157. + * connection alive - disconnect it
  6158. + * If this is the last connection on the server session disconnect it
  6159. + * (and inside session disconnect we should check if tcp socket needs
  6160. + * to be freed and kernel thread woken up).
  6161. + */
  6162. + if (tcon)
  6163. + down(&tcon->tconSem);
  6164. + else
  6165. + return -EIO;
  6166. +
  6167. + atomic_dec(&tcon->useCount);
  6168. + if (atomic_read(&tcon->useCount) > 0) {
  6169. + up(&tcon->tconSem);
  6170. + return -EBUSY;
  6171. + }
  6172. +
  6173. + /* No need to return error on this operation if tid invalidated and
  6174. + closed on server already e.g. due to tcp session crashing */
  6175. + if(tcon->tidStatus == CifsNeedReconnect) {
  6176. + up(&tcon->tconSem);
  6177. + return 0;
  6178. + }
  6179. +
  6180. + if((tcon->ses == 0) || (tcon->ses->server == 0)) {
  6181. + up(&tcon->tconSem);
  6182. + return -EIO;
  6183. + }
  6184. +
  6185. + rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
  6186. + (void **) &smb_buffer, (void **) &smb_buffer_response);
  6187. + if (rc) {
  6188. + up(&tcon->tconSem);
  6189. + return rc;
  6190. + }
  6191. + rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
  6192. + &length, 0);
  6193. + if (rc)
  6194. + cFYI(1, (" Tree disconnect failed %d", rc));
  6195. +
  6196. + if (smb_buffer)
  6197. + cifs_buf_release(smb_buffer);
  6198. + up(&tcon->tconSem);
  6199. +
  6200. + /* No need to return error on this operation if tid invalidated and
  6201. + closed on server already e.g. due to tcp session crashing */
  6202. + if (rc == -EAGAIN)
  6203. + rc = 0;
  6204. +
  6205. + return rc;
  6206. +}
  6207. +
  6208. +int
  6209. +CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
  6210. +{
  6211. + struct smb_hdr *smb_buffer_response;
  6212. + LOGOFF_ANDX_REQ *pSMB;
  6213. + int rc = 0;
  6214. + int length;
  6215. +
  6216. + cFYI(1, ("In SMBLogoff for session disconnect"));
  6217. + if (ses)
  6218. + down(&ses->sesSem);
  6219. + else
  6220. + return -EIO;
  6221. +
  6222. + atomic_dec(&ses->inUse);
  6223. + if (atomic_read(&ses->inUse) > 0) {
  6224. + up(&ses->sesSem);
  6225. + return -EBUSY;
  6226. + }
  6227. +
  6228. + rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
  6229. + (void **) &pSMB, (void **) &smb_buffer_response);
  6230. +
  6231. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  6232. + pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  6233. +
  6234. + if (rc) {
  6235. + up(&ses->sesSem);
  6236. + return rc;
  6237. + }
  6238. +
  6239. + pSMB->hdr.Uid = ses->Suid;
  6240. +
  6241. + pSMB->AndXCommand = 0xFF;
  6242. + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  6243. + smb_buffer_response, &length, 0);
  6244. + if (ses->server) {
  6245. + atomic_dec(&ses->server->socketUseCount);
  6246. + if (atomic_read(&ses->server->socketUseCount) == 0) {
  6247. + spin_lock(&GlobalMid_Lock);
  6248. + ses->server->tcpStatus = CifsExiting;
  6249. + spin_unlock(&GlobalMid_Lock);
  6250. + rc = -ESHUTDOWN;
  6251. + }
  6252. + }
  6253. + if (pSMB)
  6254. + cifs_buf_release(pSMB);
  6255. + up(&ses->sesSem);
  6256. +
  6257. + /* if session dead then we do not need to do ulogoff,
  6258. + since server closed smb session, no sense reporting
  6259. + error */
  6260. + if (rc == -EAGAIN)
  6261. + rc = 0;
  6262. + return rc;
  6263. +}
  6264. +
  6265. +int
  6266. +CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
  6267. + const char *fileName, const struct nls_table *nls_codepage)
  6268. +{
  6269. + DELETE_FILE_REQ *pSMB = NULL;
  6270. + DELETE_FILE_RSP *pSMBr = NULL;
  6271. + int rc = 0;
  6272. + int bytes_returned;
  6273. + int name_len;
  6274. +
  6275. +DelFileRetry:
  6276. + rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
  6277. + (void **) &pSMBr);
  6278. + if (rc)
  6279. + return rc;
  6280. +
  6281. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6282. + name_len =
  6283. + cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
  6284. + /* find define for this maxpathcomponent */
  6285. + , nls_codepage);
  6286. + name_len++; /* trailing null */
  6287. + name_len *= 2;
  6288. + } else { /* BB improve the check for buffer overruns BB */
  6289. + name_len = strnlen(fileName, 530);
  6290. + name_len++; /* trailing null */
  6291. + strncpy(pSMB->fileName, fileName, name_len);
  6292. + }
  6293. + pSMB->SearchAttributes =
  6294. + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
  6295. + pSMB->ByteCount = name_len + 1;
  6296. + pSMB->BufferFormat = 0x04;
  6297. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6298. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6299. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6300. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6301. + if (rc) {
  6302. + cFYI(1, ("Error in RMFile = %d", rc));
  6303. + }
  6304. +#ifdef CONFIG_CIFS_STATS
  6305. + else {
  6306. + atomic_inc(&tcon->num_deletes);
  6307. + }
  6308. +#endif
  6309. +
  6310. + if (pSMB)
  6311. + cifs_buf_release(pSMB);
  6312. + if (rc == -EAGAIN)
  6313. + goto DelFileRetry;
  6314. +
  6315. + return rc;
  6316. +}
  6317. +
  6318. +int
  6319. +CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
  6320. + const char *dirName, const struct nls_table *nls_codepage)
  6321. +{
  6322. + DELETE_DIRECTORY_REQ *pSMB = NULL;
  6323. + DELETE_DIRECTORY_RSP *pSMBr = NULL;
  6324. + int rc = 0;
  6325. + int bytes_returned;
  6326. + int name_len;
  6327. +
  6328. + cFYI(1, ("In CIFSSMBRmDir"));
  6329. +RmDirRetry:
  6330. + rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
  6331. + (void **) &pSMBr);
  6332. + if (rc)
  6333. + return rc;
  6334. +
  6335. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6336. + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
  6337. + /* find define for this maxpathcomponent */
  6338. + , nls_codepage);
  6339. + name_len++; /* trailing null */
  6340. + name_len *= 2;
  6341. + } else { /* BB improve the check for buffer overruns BB */
  6342. + name_len = strnlen(dirName, 530);
  6343. + name_len++; /* trailing null */
  6344. + strncpy(pSMB->DirName, dirName, name_len);
  6345. + }
  6346. +
  6347. + pSMB->ByteCount = name_len + 1;
  6348. + pSMB->BufferFormat = 0x04;
  6349. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6350. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6351. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6352. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6353. + if (rc) {
  6354. + cFYI(1, ("Error in RMDir = %d", rc));
  6355. + }
  6356. +#ifdef CONFIG_CIFS_STATS
  6357. + else {
  6358. + atomic_inc(&tcon->num_rmdirs);
  6359. + }
  6360. +#endif
  6361. +
  6362. + if (pSMB)
  6363. + cifs_buf_release(pSMB);
  6364. + if (rc == -EAGAIN)
  6365. + goto RmDirRetry;
  6366. + return rc;
  6367. +}
  6368. +
  6369. +int
  6370. +CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
  6371. + const char *name, const struct nls_table *nls_codepage)
  6372. +{
  6373. + int rc = 0;
  6374. + CREATE_DIRECTORY_REQ *pSMB = NULL;
  6375. + CREATE_DIRECTORY_RSP *pSMBr = NULL;
  6376. + int bytes_returned;
  6377. + int name_len;
  6378. +
  6379. + cFYI(1, ("In CIFSSMBMkDir"));
  6380. +MkDirRetry:
  6381. + rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
  6382. + (void **) &pSMBr);
  6383. + if (rc)
  6384. + return rc;
  6385. +
  6386. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6387. + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
  6388. + /* find define for this maxpathcomponent */
  6389. + , nls_codepage);
  6390. + name_len++; /* trailing null */
  6391. + name_len *= 2;
  6392. + } else { /* BB improve the check for buffer overruns BB */
  6393. + name_len = strnlen(name, 530);
  6394. + name_len++; /* trailing null */
  6395. + strncpy(pSMB->DirName, name, name_len);
  6396. + }
  6397. +
  6398. + pSMB->ByteCount = name_len + 1 /* for buf format */ ;
  6399. + pSMB->BufferFormat = 0x04;
  6400. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6401. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6402. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6403. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6404. + if (rc) {
  6405. + cFYI(1, ("Error in Mkdir = %d", rc));
  6406. + }
  6407. +#ifdef CONFIG_CIFS_STATS
  6408. + else {
  6409. + atomic_inc(&tcon->num_mkdirs);
  6410. + }
  6411. +#endif
  6412. + if (pSMB)
  6413. + cifs_buf_release(pSMB);
  6414. + if (rc == -EAGAIN)
  6415. + goto MkDirRetry;
  6416. + return rc;
  6417. +}
  6418. +
  6419. +int
  6420. +CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
  6421. + const char *fileName, const int openDisposition,
  6422. + const int access_flags, const int create_options, __u16 * netfid,
  6423. + int *pOplock, FILE_ALL_INFO * pfile_info,
  6424. + const struct nls_table *nls_codepage)
  6425. +{
  6426. + int rc = -EACCES;
  6427. + OPEN_REQ *pSMB = NULL;
  6428. + OPEN_RSP *pSMBr = NULL;
  6429. + int bytes_returned;
  6430. + int name_len;
  6431. +
  6432. +openRetry:
  6433. + rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
  6434. + (void **) &pSMBr);
  6435. + if (rc)
  6436. + return rc;
  6437. +
  6438. + pSMB->AndXCommand = 0xFF; /* none */
  6439. +
  6440. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6441. + pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
  6442. + name_len =
  6443. + cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
  6444. + fileName, 530
  6445. + /* find define for this maxpathcomponent */
  6446. + , nls_codepage);
  6447. + name_len++; /* trailing null */
  6448. + name_len *= 2;
  6449. + pSMB->NameLength = cpu_to_le16(name_len);
  6450. + } else { /* BB improve the check for buffer overruns BB */
  6451. + pSMB->ByteCount = 0; /* no pad */
  6452. + name_len = strnlen(fileName, 530);
  6453. + name_len++; /* trailing null */
  6454. + pSMB->NameLength = cpu_to_le16(name_len);
  6455. + strncpy(pSMB->fileName, fileName, name_len);
  6456. + }
  6457. + if (*pOplock & REQ_OPLOCK)
  6458. + pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
  6459. + else if (*pOplock & REQ_BATCHOPLOCK) {
  6460. + pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
  6461. + }
  6462. + pSMB->DesiredAccess = cpu_to_le32(access_flags);
  6463. + pSMB->AllocationSize = 0;
  6464. + pSMB->FileAttributes = ATTR_NORMAL;
  6465. + /* XP does not handle ATTR_POSIX_SEMANTICS */
  6466. + /* but it helps speed up case sensitive checks for other
  6467. + servers such as Samba */
  6468. + if (tcon->ses->capabilities & CAP_UNIX)
  6469. + pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
  6470. +
  6471. + /* if ((omode & S_IWUGO) == 0)
  6472. + pSMB->FileAttributes |= ATTR_READONLY;*/
  6473. + /* Above line causes problems due to vfs splitting create into two
  6474. + pieces - need to set mode after file created not while it is
  6475. + being created */
  6476. + pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
  6477. + pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
  6478. + pSMB->CreateDisposition = cpu_to_le32(openDisposition);
  6479. + pSMB->CreateOptions = cpu_to_le32(create_options);
  6480. + pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
  6481. + pSMB->SecurityFlags =
  6482. + cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
  6483. +
  6484. + pSMB->ByteCount += name_len;
  6485. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6486. +
  6487. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6488. + /* long_op set to 1 to allow for oplock break timeouts */
  6489. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6490. + (struct smb_hdr *) pSMBr, &bytes_returned, 1);
  6491. + if (rc) {
  6492. + cFYI(1, ("Error in Open = %d", rc));
  6493. + } else {
  6494. + *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
  6495. + *netfid = pSMBr->Fid; /* cifs fid stays in le */
  6496. + /* Let caller know file was created so we can set the mode. */
  6497. + /* Do we care about the CreateAction in any other cases? */
  6498. + if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
  6499. + *pOplock |= CIFS_CREATE_ACTION;
  6500. + if(pfile_info) {
  6501. + memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
  6502. + 36 /* CreationTime to Attributes */);
  6503. + /* the file_info buf is endian converted by caller */
  6504. + pfile_info->AllocationSize = pSMBr->AllocationSize;
  6505. + pfile_info->EndOfFile = pSMBr->EndOfFile;
  6506. + pfile_info->NumberOfLinks = cpu_to_le32(1);
  6507. + }
  6508. +
  6509. +#ifdef CONFIG_CIFS_STATS
  6510. + atomic_inc(&tcon->num_opens);
  6511. +#endif
  6512. + }
  6513. + if (pSMB)
  6514. + cifs_buf_release(pSMB);
  6515. + if (rc == -EAGAIN)
  6516. + goto openRetry;
  6517. + return rc;
  6518. +}
  6519. +
  6520. +/* If no buffer passed in, then caller wants to do the copy
  6521. + as in the case of readpages so the SMB buffer must be
  6522. + freed by the caller */
  6523. +
  6524. +int
  6525. +CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
  6526. + const int netfid, const unsigned int count,
  6527. + const __u64 lseek, unsigned int *nbytes, char **buf)
  6528. +{
  6529. + int rc = -EACCES;
  6530. + READ_REQ *pSMB = NULL;
  6531. + READ_RSP *pSMBr = NULL;
  6532. + char *pReadData = NULL;
  6533. + int bytes_returned;
  6534. +
  6535. + *nbytes = 0;
  6536. + rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
  6537. + (void **) &pSMBr);
  6538. + if (rc)
  6539. + return rc;
  6540. +
  6541. + /* tcon and ses pointer are checked in smb_init */
  6542. + if (tcon->ses->server == NULL)
  6543. + return -ECONNABORTED;
  6544. +
  6545. + pSMB->AndXCommand = 0xFF; /* none */
  6546. + pSMB->Fid = netfid;
  6547. + pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
  6548. + pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
  6549. + pSMB->Remaining = 0;
  6550. + pSMB->MaxCount = cpu_to_le16(count);
  6551. + pSMB->MaxCountHigh = 0;
  6552. + pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
  6553. +
  6554. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6555. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6556. + if (rc) {
  6557. + cERROR(1, ("Send error in read = %d", rc));
  6558. + } else {
  6559. + pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
  6560. + *nbytes = pSMBr->DataLength;
  6561. + /*check that DataLength would not go beyond end of SMB */
  6562. + if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
  6563. + || (pSMBr->DataLength > count)) {
  6564. + cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
  6565. + rc = -EIO;
  6566. + *nbytes = 0;
  6567. + } else {
  6568. + pReadData =
  6569. + (char *) (&pSMBr->hdr.Protocol) +
  6570. + le16_to_cpu(pSMBr->DataOffset);
  6571. +/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
  6572. + cERROR(1,("Faulting on read rc = %d",rc));
  6573. + rc = -EFAULT;
  6574. + }*/ /* can not use copy_to_user when using page cache*/
  6575. + if(*buf)
  6576. + memcpy(*buf,pReadData,pSMBr->DataLength);
  6577. + }
  6578. + }
  6579. + if (pSMB) {
  6580. + if(*buf)
  6581. + cifs_buf_release(pSMB);
  6582. + else
  6583. + *buf = (char *)pSMB;
  6584. + }
  6585. +
  6586. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  6587. + since file handle passed in no longer valid */
  6588. + return rc;
  6589. +}
  6590. +
  6591. +int
  6592. +CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
  6593. + const int netfid, const unsigned int count,
  6594. + const __u64 offset, unsigned int *nbytes, const char *buf,
  6595. + const int long_op)
  6596. +{
  6597. + int rc = -EACCES;
  6598. + WRITE_REQ *pSMB = NULL;
  6599. + WRITE_RSP *pSMBr = NULL;
  6600. + int bytes_returned;
  6601. +
  6602. + rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
  6603. + (void **) &pSMBr);
  6604. + if (rc)
  6605. + return rc;
  6606. + /* tcon and ses pointer are checked in smb_init */
  6607. + if (tcon->ses->server == NULL)
  6608. + return -ECONNABORTED;
  6609. +
  6610. + pSMB->AndXCommand = 0xFF; /* none */
  6611. + pSMB->Fid = netfid;
  6612. + pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
  6613. + pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
  6614. + pSMB->Remaining = 0;
  6615. + if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
  6616. + pSMB->DataLengthLow =
  6617. + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
  6618. + else
  6619. + pSMB->DataLengthLow = count;
  6620. + pSMB->DataLengthHigh = 0;
  6621. + pSMB->DataOffset =
  6622. + cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
  6623. +
  6624. + memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
  6625. +
  6626. + pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
  6627. + pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
  6628. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6629. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6630. +
  6631. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6632. + (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
  6633. + if (rc) {
  6634. + cFYI(1, ("Send error in write = %d", rc));
  6635. + *nbytes = 0;
  6636. + } else
  6637. + *nbytes = le16_to_cpu(pSMBr->Count);
  6638. +
  6639. + if (pSMB)
  6640. + cifs_buf_release(pSMB);
  6641. +
  6642. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  6643. + since file handle passed in no longer valid */
  6644. +
  6645. + return rc;
  6646. +}
  6647. +
  6648. +int
  6649. +CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
  6650. + const __u16 smb_file_id, const __u64 len,
  6651. + const __u64 offset, const __u32 numUnlock,
  6652. + const __u32 numLock, const __u8 lockType, const int waitFlag)
  6653. +{
  6654. + int rc = 0;
  6655. + LOCK_REQ *pSMB = NULL;
  6656. + LOCK_RSP *pSMBr = NULL;
  6657. + int bytes_returned;
  6658. + int timeout = 0;
  6659. + __u64 temp;
  6660. +
  6661. + cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
  6662. + rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
  6663. + (void **) &pSMBr);
  6664. + if (rc)
  6665. + return rc;
  6666. +
  6667. + if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
  6668. + timeout = -1; /* no response expected */
  6669. + pSMB->Timeout = 0;
  6670. + } else if (waitFlag == TRUE) {
  6671. + timeout = 3; /* blocking operation, no timeout */
  6672. + pSMB->Timeout = -1; /* blocking - do not time out */
  6673. + } else {
  6674. + pSMB->Timeout = 0;
  6675. + }
  6676. +
  6677. + pSMB->NumberOfLocks = cpu_to_le32(numLock);
  6678. + pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
  6679. + pSMB->LockType = lockType;
  6680. + pSMB->AndXCommand = 0xFF; /* none */
  6681. + pSMB->Fid = smb_file_id; /* netfid stays le */
  6682. +
  6683. + if(numLock != 0) {
  6684. + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
  6685. + /* BB where to store pid high? */
  6686. + temp = cpu_to_le64(len);
  6687. + pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
  6688. + pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
  6689. + temp = cpu_to_le64(offset);
  6690. + pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
  6691. + pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
  6692. + pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
  6693. + } else {
  6694. + /* oplock break */
  6695. + pSMB->ByteCount = 0;
  6696. + }
  6697. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6698. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6699. +
  6700. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6701. + (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
  6702. +
  6703. + if (rc) {
  6704. + cFYI(1, ("Send error in Lock = %d", rc));
  6705. + }
  6706. + if (pSMB)
  6707. + cifs_buf_release(pSMB);
  6708. +
  6709. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  6710. + since file handle passed in no longer valid */
  6711. + return rc;
  6712. +}
  6713. +
  6714. +int
  6715. +CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
  6716. +{
  6717. + int rc = 0;
  6718. + CLOSE_REQ *pSMB = NULL;
  6719. + CLOSE_RSP *pSMBr = NULL;
  6720. + int bytes_returned;
  6721. + cFYI(1, ("In CIFSSMBClose"));
  6722. +
  6723. +/* do not retry on dead session on close */
  6724. + rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
  6725. + (void **) &pSMBr);
  6726. + if(rc == -EAGAIN)
  6727. + return 0;
  6728. + if (rc)
  6729. + return rc;
  6730. +
  6731. + pSMB->FileID = (__u16) smb_file_id;
  6732. + pSMB->LastWriteTime = 0;
  6733. + pSMB->ByteCount = 0;
  6734. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6735. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6736. + if (rc) {
  6737. + if(rc!=-EINTR) {
  6738. + /* EINTR is expected when user ctl-c to kill app */
  6739. + cERROR(1, ("Send error in Close = %d", rc));
  6740. + }
  6741. + }
  6742. + if (pSMB)
  6743. + cifs_buf_release(pSMB);
  6744. +
  6745. + /* Since session is dead, file will be closed on server already */
  6746. + if(rc == -EAGAIN)
  6747. + rc = 0;
  6748. +
  6749. + return rc;
  6750. +}
  6751. +
  6752. +int
  6753. +CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
  6754. + const char *fromName, const char *toName,
  6755. + const struct nls_table *nls_codepage)
  6756. +{
  6757. + int rc = 0;
  6758. + RENAME_REQ *pSMB = NULL;
  6759. + RENAME_RSP *pSMBr = NULL;
  6760. + int bytes_returned;
  6761. + int name_len, name_len2;
  6762. +
  6763. + cFYI(1, ("In CIFSSMBRename"));
  6764. +renameRetry:
  6765. + rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
  6766. + (void **) &pSMBr);
  6767. + if (rc)
  6768. + return rc;
  6769. +
  6770. + pSMB->BufferFormat = 0x04;
  6771. + pSMB->SearchAttributes =
  6772. + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  6773. + ATTR_DIRECTORY);
  6774. +
  6775. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6776. + name_len =
  6777. + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
  6778. + /* find define for this maxpathcomponent */
  6779. + , nls_codepage);
  6780. + name_len++; /* trailing null */
  6781. + name_len *= 2;
  6782. + pSMB->OldFileName[name_len] = 0x04; /* pad */
  6783. + /* protocol requires ASCII signature byte on Unicode string */
  6784. + pSMB->OldFileName[name_len + 1] = 0x00;
  6785. + name_len2 =
  6786. + cifs_strtoUCS((wchar_t *) & pSMB->
  6787. + OldFileName[name_len + 2], toName, 530,
  6788. + nls_codepage);
  6789. + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  6790. + name_len2 *= 2; /* convert to bytes */
  6791. + } else { /* BB improve the check for buffer overruns BB */
  6792. + name_len = strnlen(fromName, 530);
  6793. + name_len++; /* trailing null */
  6794. + strncpy(pSMB->OldFileName, fromName, name_len);
  6795. + name_len2 = strnlen(toName, 530);
  6796. + name_len2++; /* trailing null */
  6797. + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  6798. + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  6799. + name_len2++; /* trailing null */
  6800. + name_len2++; /* signature byte */
  6801. + }
  6802. +
  6803. + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
  6804. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6805. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6806. +
  6807. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6808. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6809. + if (rc) {
  6810. + cFYI(1, ("Send error in rename = %d", rc));
  6811. + }
  6812. +
  6813. +#ifdef CONFIG_CIFS_STATS
  6814. + else {
  6815. + atomic_inc(&tcon->num_renames);
  6816. + }
  6817. +#endif
  6818. +
  6819. + if (pSMB)
  6820. + cifs_buf_release(pSMB);
  6821. +
  6822. + if (rc == -EAGAIN)
  6823. + goto renameRetry;
  6824. +
  6825. + return rc;
  6826. +}
  6827. +
  6828. +int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
  6829. + int netfid, char * target_name, const struct nls_table * nls_codepage)
  6830. +{
  6831. + struct smb_com_transaction2_sfi_req *pSMB = NULL;
  6832. + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
  6833. + struct set_file_rename * rename_info;
  6834. + char *data_offset;
  6835. + char dummy_string[30];
  6836. + int rc = 0;
  6837. + int bytes_returned = 0;
  6838. + int len_of_str;
  6839. +
  6840. + cFYI(1, ("Rename to File by handle"));
  6841. + rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
  6842. + (void **) &pSMBr);
  6843. + if (rc)
  6844. + return rc;
  6845. +
  6846. + pSMB->ParameterCount = 6;
  6847. + pSMB->MaxSetupCount = 0;
  6848. + pSMB->Reserved = 0;
  6849. + pSMB->Flags = 0;
  6850. + pSMB->Timeout = 0;
  6851. + pSMB->Reserved2 = 0;
  6852. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
  6853. + Fid) - 4;
  6854. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  6855. +
  6856. + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
  6857. + rename_info = (struct set_file_rename *) data_offset;
  6858. + pSMB->MaxParameterCount = cpu_to_le16(2);
  6859. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
  6860. + pSMB->SetupCount = 1;
  6861. + pSMB->Reserved3 = 0;
  6862. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  6863. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
  6864. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  6865. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  6866. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  6867. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  6868. + /* construct random name ".cifs_tmp<inodenum><mid>" */
  6869. + rename_info->overwrite = cpu_to_le32(1);
  6870. + rename_info->root_fid = 0;
  6871. + /* unicode only call */
  6872. + if(target_name == NULL) {
  6873. + sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
  6874. + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
  6875. + } else {
  6876. + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
  6877. + }
  6878. + rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
  6879. + pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
  6880. + pSMB->ByteCount += pSMB->DataCount;
  6881. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  6882. + pSMB->TotalDataCount = pSMB->DataCount;
  6883. + pSMB->Fid = netfid;
  6884. + pSMB->InformationLevel =
  6885. + cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
  6886. + pSMB->Reserved4 = 0;
  6887. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6888. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6889. + rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
  6890. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6891. + if (rc) {
  6892. + cFYI(1,("Send error in Rename (by file handle) = %d", rc));
  6893. + }
  6894. +#ifdef CONFIG_CIFS_STATS
  6895. + else {
  6896. + atomic_inc(&pTcon->num_t2renames);
  6897. + }
  6898. +#endif
  6899. + if (pSMB)
  6900. + cifs_buf_release(pSMB);
  6901. +
  6902. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  6903. + since file handle passed in no longer valid */
  6904. +
  6905. + return rc;
  6906. +}
  6907. +
  6908. +int
  6909. +CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
  6910. + const __u16 target_tid, const char *toName, const int flags,
  6911. + const struct nls_table *nls_codepage)
  6912. +{
  6913. + int rc = 0;
  6914. + COPY_REQ *pSMB = NULL;
  6915. + COPY_RSP *pSMBr = NULL;
  6916. + int bytes_returned;
  6917. + int name_len, name_len2;
  6918. +
  6919. + cFYI(1, ("In CIFSSMBCopy"));
  6920. +copyRetry:
  6921. + rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
  6922. + (void **) &pSMBr);
  6923. + if (rc)
  6924. + return rc;
  6925. +
  6926. + pSMB->BufferFormat = 0x04;
  6927. + pSMB->Tid2 = target_tid;
  6928. +
  6929. + if(flags & COPY_TREE)
  6930. + pSMB->Flags |= COPY_TREE;
  6931. + pSMB->Flags = cpu_to_le16(pSMB->Flags);
  6932. +
  6933. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  6934. + name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
  6935. + fromName,
  6936. + 530 /* find define for this maxpathcomponent */,
  6937. + nls_codepage);
  6938. + name_len++; /* trailing null */
  6939. + name_len *= 2;
  6940. + pSMB->OldFileName[name_len] = 0x04; /* pad */
  6941. + /* protocol requires ASCII signature byte on Unicode string */
  6942. + pSMB->OldFileName[name_len + 1] = 0x00;
  6943. + name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
  6944. + OldFileName[name_len + 2], toName, 530,
  6945. + nls_codepage);
  6946. + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  6947. + name_len2 *= 2; /* convert to bytes */
  6948. + } else { /* BB improve the check for buffer overruns BB */
  6949. + name_len = strnlen(fromName, 530);
  6950. + name_len++; /* trailing null */
  6951. + strncpy(pSMB->OldFileName, fromName, name_len);
  6952. + name_len2 = strnlen(toName, 530);
  6953. + name_len2++; /* trailing null */
  6954. + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  6955. + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  6956. + name_len2++; /* trailing null */
  6957. + name_len2++; /* signature byte */
  6958. + }
  6959. +
  6960. + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
  6961. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  6962. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  6963. +
  6964. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  6965. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  6966. + if (rc) {
  6967. + cFYI(1, ("Send error in copy = %d with %d files copied",
  6968. + rc, pSMBr->CopyCount));
  6969. + }
  6970. + if (pSMB)
  6971. + cifs_buf_release(pSMB);
  6972. +
  6973. + if (rc == -EAGAIN)
  6974. + goto copyRetry;
  6975. +
  6976. + return rc;
  6977. +}
  6978. +
  6979. +int
  6980. +CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
  6981. + const char *fromName, const char *toName,
  6982. + const struct nls_table *nls_codepage)
  6983. +{
  6984. + TRANSACTION2_SPI_REQ *pSMB = NULL;
  6985. + TRANSACTION2_SPI_RSP *pSMBr = NULL;
  6986. + char *data_offset;
  6987. + int name_len;
  6988. + int name_len_target;
  6989. + int rc = 0;
  6990. + int bytes_returned = 0;
  6991. +
  6992. + cFYI(1, ("In Symlink Unix style"));
  6993. +createSymLinkRetry:
  6994. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  6995. + (void **) &pSMBr);
  6996. + if (rc)
  6997. + return rc;
  6998. +
  6999. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7000. + name_len =
  7001. + cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
  7002. + /* find define for this maxpathcomponent */
  7003. + , nls_codepage);
  7004. + name_len++; /* trailing null */
  7005. + name_len *= 2;
  7006. +
  7007. + } else { /* BB improve the check for buffer overruns BB */
  7008. + name_len = strnlen(fromName, 530);
  7009. + name_len++; /* trailing null */
  7010. + strncpy(pSMB->FileName, fromName, name_len);
  7011. + }
  7012. + pSMB->ParameterCount = 6 + name_len;
  7013. + pSMB->MaxSetupCount = 0;
  7014. + pSMB->Reserved = 0;
  7015. + pSMB->Flags = 0;
  7016. + pSMB->Timeout = 0;
  7017. + pSMB->Reserved2 = 0;
  7018. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
  7019. + InformationLevel) - 4;
  7020. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  7021. +
  7022. + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
  7023. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7024. + name_len_target =
  7025. + cifs_strtoUCS((wchar_t *) data_offset, toName, 530
  7026. + /* find define for this maxpathcomponent */
  7027. + , nls_codepage);
  7028. + name_len_target++; /* trailing null */
  7029. + name_len_target *= 2;
  7030. + } else { /* BB improve the check for buffer overruns BB */
  7031. + name_len_target = strnlen(toName, 530);
  7032. + name_len_target++; /* trailing null */
  7033. + strncpy(data_offset, toName, name_len_target);
  7034. + }
  7035. +
  7036. + pSMB->DataCount = name_len_target;
  7037. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7038. + /* BB find exact max on data count below from sess */
  7039. + pSMB->MaxDataCount = cpu_to_le16(1000);
  7040. + pSMB->SetupCount = 1;
  7041. + pSMB->Reserved3 = 0;
  7042. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  7043. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  7044. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  7045. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  7046. + pSMB->TotalDataCount = pSMB->DataCount;
  7047. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  7048. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  7049. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  7050. + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
  7051. + pSMB->Reserved4 = 0;
  7052. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7053. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7054. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7055. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7056. + if (rc) {
  7057. + cFYI(1,
  7058. + ("Send error in SetPathInfo (create symlink) = %d",
  7059. + rc));
  7060. + }
  7061. +
  7062. + if (pSMB)
  7063. + cifs_buf_release(pSMB);
  7064. +
  7065. + if (rc == -EAGAIN)
  7066. + goto createSymLinkRetry;
  7067. +
  7068. + return rc;
  7069. +}
  7070. +
  7071. +int
  7072. +CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
  7073. + const char *fromName, const char *toName,
  7074. + const struct nls_table *nls_codepage)
  7075. +{
  7076. + TRANSACTION2_SPI_REQ *pSMB = NULL;
  7077. + TRANSACTION2_SPI_RSP *pSMBr = NULL;
  7078. + char *data_offset;
  7079. + int name_len;
  7080. + int name_len_target;
  7081. + int rc = 0;
  7082. + int bytes_returned = 0;
  7083. +
  7084. + cFYI(1, ("In Create Hard link Unix style"));
  7085. +createHardLinkRetry:
  7086. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7087. + (void **) &pSMBr);
  7088. + if (rc)
  7089. + return rc;
  7090. +
  7091. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7092. + name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
  7093. + /* find define for this maxpathcomponent */
  7094. + , nls_codepage);
  7095. + name_len++; /* trailing null */
  7096. + name_len *= 2;
  7097. +
  7098. + } else { /* BB improve the check for buffer overruns BB */
  7099. + name_len = strnlen(toName, 530);
  7100. + name_len++; /* trailing null */
  7101. + strncpy(pSMB->FileName, toName, name_len);
  7102. + }
  7103. + pSMB->ParameterCount = 6 + name_len;
  7104. + pSMB->MaxSetupCount = 0;
  7105. + pSMB->Reserved = 0;
  7106. + pSMB->Flags = 0;
  7107. + pSMB->Timeout = 0;
  7108. + pSMB->Reserved2 = 0;
  7109. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
  7110. + InformationLevel) - 4;
  7111. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  7112. +
  7113. + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
  7114. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7115. + name_len_target =
  7116. + cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
  7117. + /* find define for this maxpathcomponent */
  7118. + , nls_codepage);
  7119. + name_len_target++; /* trailing null */
  7120. + name_len_target *= 2;
  7121. + } else { /* BB improve the check for buffer overruns BB */
  7122. + name_len_target = strnlen(fromName, 530);
  7123. + name_len_target++; /* trailing null */
  7124. + strncpy(data_offset, fromName, name_len_target);
  7125. + }
  7126. +
  7127. + pSMB->DataCount = name_len_target;
  7128. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7129. + /* BB find exact max on data count below from sess*/
  7130. + pSMB->MaxDataCount = cpu_to_le16(1000);
  7131. + pSMB->SetupCount = 1;
  7132. + pSMB->Reserved3 = 0;
  7133. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  7134. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  7135. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  7136. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  7137. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  7138. + pSMB->TotalDataCount = pSMB->DataCount;
  7139. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  7140. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  7141. + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
  7142. + pSMB->Reserved4 = 0;
  7143. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7144. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7145. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7146. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7147. + if (rc) {
  7148. + cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
  7149. + }
  7150. +
  7151. + if (pSMB)
  7152. + cifs_buf_release(pSMB);
  7153. + if (rc == -EAGAIN)
  7154. + goto createHardLinkRetry;
  7155. +
  7156. + return rc;
  7157. +}
  7158. +
  7159. +int
  7160. +CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
  7161. + const char *fromName, const char *toName,
  7162. + const struct nls_table *nls_codepage)
  7163. +{
  7164. + int rc = 0;
  7165. + NT_RENAME_REQ *pSMB = NULL;
  7166. + RENAME_RSP *pSMBr = NULL;
  7167. + int bytes_returned;
  7168. + int name_len, name_len2;
  7169. +
  7170. + cFYI(1, ("In CIFSCreateHardLink"));
  7171. +winCreateHardLinkRetry:
  7172. +
  7173. + rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
  7174. + (void **) &pSMBr);
  7175. + if (rc)
  7176. + return rc;
  7177. +
  7178. + pSMB->SearchAttributes =
  7179. + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  7180. + ATTR_DIRECTORY);
  7181. + pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
  7182. + pSMB->ClusterCount = 0;
  7183. +
  7184. + pSMB->BufferFormat = 0x04;
  7185. +
  7186. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7187. + name_len =
  7188. + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
  7189. + /* find define for this maxpathcomponent */
  7190. + , nls_codepage);
  7191. + name_len++; /* trailing null */
  7192. + name_len *= 2;
  7193. + pSMB->OldFileName[name_len] = 0; /* pad */
  7194. + pSMB->OldFileName[name_len + 1] = 0x04;
  7195. + name_len2 =
  7196. + cifs_strtoUCS((wchar_t *) & pSMB->
  7197. + OldFileName[name_len + 2], toName, 530,
  7198. + nls_codepage);
  7199. + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  7200. + name_len2 *= 2; /* convert to bytes */
  7201. + } else { /* BB improve the check for buffer overruns BB */
  7202. + name_len = strnlen(fromName, 530);
  7203. + name_len++; /* trailing null */
  7204. + strncpy(pSMB->OldFileName, fromName, name_len);
  7205. + name_len2 = strnlen(toName, 530);
  7206. + name_len2++; /* trailing null */
  7207. + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  7208. + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  7209. + name_len2++; /* trailing null */
  7210. + name_len2++; /* signature byte */
  7211. + }
  7212. +
  7213. + pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
  7214. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7215. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7216. +
  7217. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7218. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7219. + if (rc) {
  7220. + cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
  7221. + }
  7222. + if (pSMB)
  7223. + cifs_buf_release(pSMB);
  7224. + if (rc == -EAGAIN)
  7225. + goto winCreateHardLinkRetry;
  7226. +
  7227. + return rc;
  7228. +}
  7229. +
  7230. +int
  7231. +CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
  7232. + const unsigned char *searchName,
  7233. + char *symlinkinfo, const int buflen,
  7234. + const struct nls_table *nls_codepage)
  7235. +{
  7236. +/* SMB_QUERY_FILE_UNIX_LINK */
  7237. + TRANSACTION2_QPI_REQ *pSMB = NULL;
  7238. + TRANSACTION2_QPI_RSP *pSMBr = NULL;
  7239. + int rc = 0;
  7240. + int bytes_returned;
  7241. + int name_len;
  7242. +
  7243. + cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
  7244. +
  7245. +querySymLinkRetry:
  7246. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7247. + (void **) &pSMBr);
  7248. + if (rc)
  7249. + return rc;
  7250. +
  7251. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7252. + name_len =
  7253. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  7254. + /* find define for this maxpathcomponent */
  7255. + , nls_codepage);
  7256. + name_len++; /* trailing null */
  7257. + name_len *= 2;
  7258. + } else { /* BB improve the check for buffer overruns BB */
  7259. + name_len = strnlen(searchName, 530);
  7260. + name_len++; /* trailing null */
  7261. + strncpy(pSMB->FileName, searchName, name_len);
  7262. + }
  7263. +
  7264. + pSMB->TotalParameterCount =
  7265. + 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
  7266. + pSMB->TotalDataCount = 0;
  7267. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7268. + /* BB find exact max data count below from sess structure BB */
  7269. + pSMB->MaxDataCount = cpu_to_le16(4000);
  7270. + pSMB->MaxSetupCount = 0;
  7271. + pSMB->Reserved = 0;
  7272. + pSMB->Flags = 0;
  7273. + pSMB->Timeout = 0;
  7274. + pSMB->Reserved2 = 0;
  7275. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  7276. + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  7277. + pSMB->DataCount = 0;
  7278. + pSMB->DataOffset = 0;
  7279. + pSMB->SetupCount = 1;
  7280. + pSMB->Reserved3 = 0;
  7281. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  7282. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7283. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  7284. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7285. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
  7286. + pSMB->Reserved4 = 0;
  7287. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7288. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7289. +
  7290. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7291. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7292. + if (rc) {
  7293. + cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
  7294. + } else { /* decode response */
  7295. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  7296. + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
  7297. + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
  7298. + /* BB also check enough total bytes returned */
  7299. + rc = -EIO; /* bad smb */
  7300. + else {
  7301. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  7302. + name_len = UniStrnlen((wchar_t *) ((char *)
  7303. + &pSMBr->hdr.Protocol +pSMBr->DataOffset),
  7304. + min_t(const int, buflen,pSMBr->DataCount) / 2);
  7305. + cifs_strfromUCS_le(symlinkinfo,
  7306. + (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
  7307. + pSMBr->DataOffset),
  7308. + name_len, nls_codepage);
  7309. + } else {
  7310. + strncpy(symlinkinfo,
  7311. + (char *) &pSMBr->hdr.Protocol +
  7312. + pSMBr->DataOffset,
  7313. + min_t(const int, buflen, pSMBr->DataCount));
  7314. + }
  7315. + symlinkinfo[buflen] = 0;
  7316. + /* just in case so calling code does not go off the end of buffer */
  7317. + }
  7318. + }
  7319. + if (pSMB)
  7320. + cifs_buf_release(pSMB);
  7321. + if (rc == -EAGAIN)
  7322. + goto querySymLinkRetry;
  7323. + return rc;
  7324. +}
  7325. +
  7326. +
  7327. +
  7328. +int
  7329. +CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
  7330. + const unsigned char *searchName,
  7331. + char *symlinkinfo, const int buflen,__u16 fid,
  7332. + const struct nls_table *nls_codepage)
  7333. +{
  7334. + int rc = 0;
  7335. + int bytes_returned;
  7336. + int name_len;
  7337. + struct smb_com_transaction_ioctl_req * pSMB;
  7338. + struct smb_com_transaction_ioctl_rsp * pSMBr;
  7339. +
  7340. + cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
  7341. + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  7342. + (void **) &pSMBr);
  7343. + if (rc)
  7344. + return rc;
  7345. +
  7346. + pSMB->TotalParameterCount = 0 ;
  7347. + pSMB->TotalDataCount = 0;
  7348. + pSMB->MaxParameterCount = cpu_to_le32(2);
  7349. + /* BB find exact data count max from sess structure BB */
  7350. + pSMB->MaxDataCount = cpu_to_le32(4000);
  7351. + pSMB->MaxSetupCount = 4;
  7352. + pSMB->Reserved = 0;
  7353. + pSMB->ParameterOffset = 0;
  7354. + pSMB->DataCount = 0;
  7355. + pSMB->DataOffset = 0;
  7356. + pSMB->SetupCount = 4;
  7357. + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
  7358. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7359. + pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
  7360. + pSMB->IsFsctl = 1; /* FSCTL */
  7361. + pSMB->IsRootFlag = 0;
  7362. + pSMB->Fid = fid; /* file handle always le */
  7363. + pSMB->ByteCount = 0;
  7364. +
  7365. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7366. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7367. + if (rc) {
  7368. + cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
  7369. + } else { /* decode response */
  7370. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  7371. + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
  7372. + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
  7373. + /* BB also check enough total bytes returned */
  7374. + rc = -EIO; /* bad smb */
  7375. + else {
  7376. + if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
  7377. + /* could also validate reparse tag && better check name length */
  7378. + struct reparse_data * reparse_buf = (struct reparse_data *)
  7379. + ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
  7380. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  7381. + name_len = UniStrnlen((wchar_t *)
  7382. + (reparse_buf->LinkNamesBuf +
  7383. + reparse_buf->TargetNameOffset),
  7384. + min(buflen/2, reparse_buf->TargetNameLen / 2));
  7385. + cifs_strfromUCS_le(symlinkinfo,
  7386. + (wchar_t *) (reparse_buf->LinkNamesBuf +
  7387. + reparse_buf->TargetNameOffset),
  7388. + name_len, nls_codepage);
  7389. + } else { /* ASCII names */
  7390. + strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
  7391. + reparse_buf->TargetNameOffset,
  7392. + min_t(const int, buflen, reparse_buf->TargetNameLen));
  7393. + }
  7394. + } else {
  7395. + rc = -EIO;
  7396. + cFYI(1,("Invalid return data count on get reparse info ioctl"));
  7397. + }
  7398. + symlinkinfo[buflen] = 0; /* just in case so the caller
  7399. + does not go off the end of the buffer */
  7400. + cFYI(1,("readlink result - %s ",symlinkinfo));
  7401. + }
  7402. + }
  7403. + if (pSMB)
  7404. + cifs_buf_release(pSMB);
  7405. +
  7406. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  7407. + since file handle passed in no longer valid */
  7408. +
  7409. + return rc;
  7410. +}
  7411. +
  7412. +int
  7413. +CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
  7414. + const unsigned char *searchName,
  7415. + FILE_ALL_INFO * pFindData,
  7416. + const struct nls_table *nls_codepage)
  7417. +{
  7418. +/* level 263 SMB_QUERY_FILE_ALL_INFO */
  7419. + TRANSACTION2_QPI_REQ *pSMB = NULL;
  7420. + TRANSACTION2_QPI_RSP *pSMBr = NULL;
  7421. + int rc = 0;
  7422. + int bytes_returned;
  7423. + int name_len;
  7424. +
  7425. + cFYI(1, ("In QPathInfo path %s", searchName));
  7426. +QPathInfoRetry:
  7427. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7428. + (void **) &pSMBr);
  7429. + if (rc)
  7430. + return rc;
  7431. +
  7432. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7433. + name_len =
  7434. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  7435. + /* find define for this maxpathcomponent */
  7436. + , nls_codepage);
  7437. + name_len++; /* trailing null */
  7438. + name_len *= 2;
  7439. + } else { /* BB improve the check for buffer overruns BB */
  7440. + name_len = strnlen(searchName, 530);
  7441. + name_len++; /* trailing null */
  7442. + strncpy(pSMB->FileName, searchName, name_len);
  7443. + }
  7444. +
  7445. + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
  7446. + name_len /* includes null */ ;
  7447. + pSMB->TotalDataCount = 0;
  7448. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7449. + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  7450. + pSMB->MaxSetupCount = 0;
  7451. + pSMB->Reserved = 0;
  7452. + pSMB->Flags = 0;
  7453. + pSMB->Timeout = 0;
  7454. + pSMB->Reserved2 = 0;
  7455. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  7456. + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  7457. + pSMB->DataCount = 0;
  7458. + pSMB->DataOffset = 0;
  7459. + pSMB->SetupCount = 1;
  7460. + pSMB->Reserved3 = 0;
  7461. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  7462. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7463. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  7464. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7465. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
  7466. + pSMB->Reserved4 = 0;
  7467. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7468. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7469. +
  7470. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7471. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7472. + if (rc) {
  7473. + cFYI(1, ("Send error in QPathInfo = %d", rc));
  7474. + } else { /* decode response */
  7475. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  7476. + /* BB also check enough total bytes returned */
  7477. + /* BB we need to improve the validity checking
  7478. + of these trans2 responses */
  7479. + if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
  7480. + rc = -EIO; /* bad smb */
  7481. + else if (pFindData){
  7482. + memcpy((char *) pFindData,
  7483. + (char *) &pSMBr->hdr.Protocol +
  7484. + pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
  7485. + } else
  7486. + rc = -ENOMEM;
  7487. + }
  7488. + if (pSMB)
  7489. + cifs_buf_release(pSMB);
  7490. + if (rc == -EAGAIN)
  7491. + goto QPathInfoRetry;
  7492. +
  7493. + return rc;
  7494. +}
  7495. +
  7496. +int
  7497. +CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
  7498. + const unsigned char *searchName,
  7499. + FILE_UNIX_BASIC_INFO * pFindData,
  7500. + const struct nls_table *nls_codepage)
  7501. +{
  7502. +/* SMB_QUERY_FILE_UNIX_BASIC */
  7503. + TRANSACTION2_QPI_REQ *pSMB = NULL;
  7504. + TRANSACTION2_QPI_RSP *pSMBr = NULL;
  7505. + int rc = 0;
  7506. + int bytes_returned = 0;
  7507. + int name_len;
  7508. +
  7509. + cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
  7510. +UnixQPathInfoRetry:
  7511. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7512. + (void **) &pSMBr);
  7513. + if (rc)
  7514. + return rc;
  7515. +
  7516. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7517. + name_len =
  7518. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  7519. + /* find define for this maxpathcomponent */
  7520. + , nls_codepage);
  7521. + name_len++; /* trailing null */
  7522. + name_len *= 2;
  7523. + } else { /* BB improve the check for buffer overruns BB */
  7524. + name_len = strnlen(searchName, 530);
  7525. + name_len++; /* trailing null */
  7526. + strncpy(pSMB->FileName, searchName, name_len);
  7527. + }
  7528. +
  7529. + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
  7530. + name_len /* includes null */ ;
  7531. + pSMB->TotalDataCount = 0;
  7532. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7533. + /* BB find exact max SMB PDU from sess structure BB */
  7534. + pSMB->MaxDataCount = cpu_to_le16(4000);
  7535. + pSMB->MaxSetupCount = 0;
  7536. + pSMB->Reserved = 0;
  7537. + pSMB->Flags = 0;
  7538. + pSMB->Timeout = 0;
  7539. + pSMB->Reserved2 = 0;
  7540. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  7541. + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  7542. + pSMB->DataCount = 0;
  7543. + pSMB->DataOffset = 0;
  7544. + pSMB->SetupCount = 1;
  7545. + pSMB->Reserved3 = 0;
  7546. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  7547. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7548. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  7549. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7550. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
  7551. + pSMB->Reserved4 = 0;
  7552. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7553. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7554. +
  7555. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7556. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7557. + if (rc) {
  7558. + cFYI(1, ("Send error in QPathInfo = %d", rc));
  7559. + } else { /* decode response */
  7560. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  7561. + /* BB also check if enough total bytes returned */
  7562. + if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
  7563. + (pSMBr->DataOffset > 512) ||
  7564. + (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
  7565. + cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
  7566. + (int)pSMBr->DataOffset,bytes_returned));
  7567. + rc = -EIO; /* bad smb */
  7568. + } else {
  7569. + memcpy((char *) pFindData,
  7570. + (char *) &pSMBr->hdr.Protocol +
  7571. + pSMBr->DataOffset,
  7572. + sizeof (FILE_UNIX_BASIC_INFO));
  7573. + }
  7574. + }
  7575. + if (pSMB)
  7576. + cifs_buf_release(pSMB);
  7577. + if (rc == -EAGAIN)
  7578. + goto UnixQPathInfoRetry;
  7579. +
  7580. + return rc;
  7581. +}
  7582. +
  7583. +int
  7584. +CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
  7585. + const char *searchName, FILE_ALL_INFO * findData,
  7586. + const struct nls_table *nls_codepage)
  7587. +{
  7588. +/* level 257 SMB_ */
  7589. + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  7590. + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
  7591. + int rc = 0;
  7592. + int bytes_returned;
  7593. + int name_len;
  7594. +
  7595. + cFYI(1, ("In FindUnique"));
  7596. +findUniqueRetry:
  7597. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7598. + (void **) &pSMBr);
  7599. + if (rc)
  7600. + return rc;
  7601. +
  7602. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7603. + name_len =
  7604. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  7605. + /* find define for this maxpathcomponent */
  7606. + , nls_codepage);
  7607. + name_len++; /* trailing null */
  7608. + name_len *= 2;
  7609. + } else { /* BB improve the check for buffer overruns BB */
  7610. + name_len = strnlen(searchName, 530);
  7611. + name_len++; /* trailing null */
  7612. + strncpy(pSMB->FileName, searchName, name_len);
  7613. + }
  7614. +
  7615. + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
  7616. + pSMB->TotalDataCount = 0; /* no EAs */
  7617. + pSMB->MaxParameterCount = cpu_to_le16(2);
  7618. + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  7619. + pSMB->MaxSetupCount = 0;
  7620. + pSMB->Reserved = 0;
  7621. + pSMB->Flags = 0;
  7622. + pSMB->Timeout = 0;
  7623. + pSMB->Reserved2 = 0;
  7624. + pSMB->ParameterOffset = cpu_to_le16(
  7625. + offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
  7626. + pSMB->DataCount = 0;
  7627. + pSMB->DataOffset = 0;
  7628. + pSMB->SetupCount = 1; /* one byte, no need to le convert */
  7629. + pSMB->Reserved3 = 0;
  7630. + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
  7631. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7632. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
  7633. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7634. + pSMB->SearchAttributes =
  7635. + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  7636. + ATTR_DIRECTORY);
  7637. + pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
  7638. + pSMB->SearchFlags = cpu_to_le16(1);
  7639. + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
  7640. + pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
  7641. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7642. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7643. +
  7644. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7645. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7646. +
  7647. + if (rc) {
  7648. + cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
  7649. + } else { /* decode response */
  7650. +
  7651. + /* BB fill in */
  7652. + }
  7653. + if (pSMB)
  7654. + cifs_buf_release(pSMB);
  7655. + if (rc == -EAGAIN)
  7656. + goto findUniqueRetry;
  7657. +
  7658. + return rc;
  7659. +}
  7660. +
  7661. +int
  7662. +CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
  7663. + const char *searchName, FILE_DIRECTORY_INFO * findData,
  7664. + T2_FFIRST_RSP_PARMS * findParms,
  7665. + const struct nls_table *nls_codepage, int *pUnicodeFlag,
  7666. + int *pUnixFlag)
  7667. +{
  7668. +/* level 257 SMB_ */
  7669. + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  7670. + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
  7671. + char *response_data;
  7672. + int rc = 0;
  7673. + int bytes_returned;
  7674. + int name_len;
  7675. +
  7676. + cFYI(1, ("In FindFirst"));
  7677. +findFirstRetry:
  7678. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7679. + (void **) &pSMBr);
  7680. + if (rc)
  7681. + return rc;
  7682. +
  7683. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  7684. + name_len =
  7685. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  7686. + /* find define for this maxpathcomponent */
  7687. + , nls_codepage);
  7688. + name_len++; /* trailing null */
  7689. + name_len *= 2;
  7690. + } else { /* BB improve the check for buffer overruns BB */
  7691. + name_len = strnlen(searchName, 530);
  7692. + name_len++; /* trailing null */
  7693. + strncpy(pSMB->FileName, searchName, name_len);
  7694. + }
  7695. +
  7696. + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
  7697. + pSMB->TotalDataCount = 0; /* no EAs */
  7698. + pSMB->MaxParameterCount = cpu_to_le16(10);
  7699. + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
  7700. + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
  7701. + pSMB->MaxSetupCount = 0;
  7702. + pSMB->Reserved = 0;
  7703. + pSMB->Flags = 0;
  7704. + pSMB->Timeout = 0;
  7705. + pSMB->Reserved2 = 0;
  7706. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7707. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  7708. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7709. + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  7710. + smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
  7711. + pSMB->DataCount = 0;
  7712. + pSMB->DataOffset = 0;
  7713. + pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
  7714. + pSMB->Reserved3 = 0;
  7715. + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
  7716. + pSMB->SearchAttributes =
  7717. + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  7718. + ATTR_DIRECTORY);
  7719. + pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
  7720. + pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
  7721. +
  7722. + /* test for Unix extensions */
  7723. + if (tcon->ses->capabilities & CAP_UNIX) {
  7724. + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
  7725. + *pUnixFlag = TRUE;
  7726. + } else {
  7727. + pSMB->InformationLevel =
  7728. + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
  7729. + *pUnixFlag = FALSE;
  7730. + }
  7731. + pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
  7732. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7733. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7734. +
  7735. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7736. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7737. +
  7738. + if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
  7739. + cFYI(1, ("Error in FindFirst = %d", rc));
  7740. + } else { /* decode response */
  7741. + /* BB add safety checks for these memcpys */
  7742. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  7743. + *pUnicodeFlag = TRUE;
  7744. + else
  7745. + *pUnicodeFlag = FALSE;
  7746. + memcpy(findParms,
  7747. + (char *) &pSMBr->hdr.Protocol +
  7748. + le16_to_cpu(pSMBr->ParameterOffset),
  7749. + sizeof (T2_FFIRST_RSP_PARMS));
  7750. + /* search handle can stay LE and EAoffset not needed so not converted */
  7751. + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
  7752. + findParms->LastNameOffset =
  7753. + le16_to_cpu(findParms->LastNameOffset);
  7754. + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
  7755. + response_data =
  7756. + (char *) &pSMBr->hdr.Protocol +
  7757. + le16_to_cpu(pSMBr->DataOffset);
  7758. + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
  7759. + }
  7760. + if (pSMB)
  7761. + cifs_buf_release(pSMB);
  7762. +
  7763. + if (rc == -EAGAIN)
  7764. + goto findFirstRetry;
  7765. +
  7766. + return rc;
  7767. +}
  7768. +
  7769. +int
  7770. +CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
  7771. + FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
  7772. + const __u16 searchHandle, char * resume_file_name, int name_len,
  7773. + __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
  7774. +{
  7775. +/* level 257 SMB_ */
  7776. + TRANSACTION2_FNEXT_REQ *pSMB = NULL;
  7777. + TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
  7778. + char *response_data;
  7779. + int rc = 0;
  7780. + int bytes_returned;
  7781. +
  7782. + cFYI(1, ("In FindNext"));
  7783. +
  7784. + if(resume_file_name == NULL) {
  7785. + return -EIO;
  7786. + }
  7787. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  7788. + (void **) &pSMBr);
  7789. + if (rc)
  7790. + return rc;
  7791. +
  7792. + pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
  7793. + pSMB->TotalDataCount = 0; /* no EAs */
  7794. + pSMB->MaxParameterCount = cpu_to_le16(8);
  7795. + pSMB->MaxDataCount =
  7796. + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
  7797. + pSMB->MaxSetupCount = 0;
  7798. + pSMB->Reserved = 0;
  7799. + pSMB->Flags = 0;
  7800. + pSMB->Timeout = 0;
  7801. + pSMB->Reserved2 = 0;
  7802. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  7803. + struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
  7804. + pSMB->DataCount = 0;
  7805. + pSMB->DataOffset = 0;
  7806. + pSMB->SetupCount = 1;
  7807. + pSMB->Reserved3 = 0;
  7808. + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
  7809. + pSMB->SearchHandle = searchHandle; /* always kept as le */
  7810. + findParms->SearchCount = 0; /* set to zero in case of error */
  7811. + pSMB->SearchCount =
  7812. + cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
  7813. + /* test for Unix extensions */
  7814. + if (tcon->ses->capabilities & CAP_UNIX) {
  7815. + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
  7816. + *pUnixFlag = TRUE;
  7817. + } else {
  7818. + pSMB->InformationLevel =
  7819. + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
  7820. + *pUnixFlag = FALSE;
  7821. + }
  7822. + pSMB->ResumeKey = resume_key;
  7823. + pSMB->SearchFlags =
  7824. + cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
  7825. + /* BB add check to make sure we do not cross end of smb */
  7826. + if(name_len < CIFS_MAX_MSGSIZE) {
  7827. + memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
  7828. + pSMB->ByteCount += name_len;
  7829. + }
  7830. + pSMB->TotalParameterCount += name_len;
  7831. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  7832. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  7833. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  7834. + /* BB improve error handling here */
  7835. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7836. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7837. +
  7838. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7839. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7840. +
  7841. + if (rc) {
  7842. + if (rc == -EBADF)
  7843. + rc = 0; /* search probably was closed at end of search above */
  7844. + else
  7845. + cFYI(1, ("FindNext returned = %d", rc));
  7846. + } else { /* decode response */
  7847. + /* BB add safety checks for these memcpys */
  7848. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  7849. + *pUnicodeFlag = TRUE;
  7850. + else
  7851. + *pUnicodeFlag = FALSE;
  7852. + memcpy(findParms,
  7853. + (char *) &pSMBr->hdr.Protocol +
  7854. + le16_to_cpu(pSMBr->ParameterOffset),
  7855. + sizeof (T2_FNEXT_RSP_PARMS));
  7856. + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
  7857. + findParms->LastNameOffset =
  7858. + le16_to_cpu(findParms->LastNameOffset);
  7859. + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
  7860. + response_data =
  7861. + (char *) &pSMBr->hdr.Protocol +
  7862. + le16_to_cpu(pSMBr->DataOffset);
  7863. + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
  7864. + }
  7865. + if (pSMB)
  7866. + cifs_buf_release(pSMB);
  7867. +
  7868. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  7869. + since file handle passed in no longer valid */
  7870. +
  7871. + return rc;
  7872. +}
  7873. +
  7874. +int
  7875. +CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
  7876. +{
  7877. + int rc = 0;
  7878. + FINDCLOSE_REQ *pSMB = NULL;
  7879. + CLOSE_RSP *pSMBr = NULL;
  7880. + int bytes_returned;
  7881. +
  7882. + cFYI(1, ("In CIFSSMBFindClose"));
  7883. + rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
  7884. + (void **) &pSMBr);
  7885. + /* no sense returning error if session restarted
  7886. + file handle has been closed */
  7887. + if(rc == -EAGAIN)
  7888. + return 0;
  7889. + if (rc)
  7890. + return rc;
  7891. +
  7892. + pSMB->FileID = searchHandle;
  7893. + pSMB->ByteCount = 0;
  7894. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  7895. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7896. + if (rc) {
  7897. + cERROR(1, ("Send error in FindClose = %d", rc));
  7898. + }
  7899. + if (pSMB)
  7900. + cifs_buf_release(pSMB);
  7901. +
  7902. + /* Since session is dead, search handle closed on server already */
  7903. + if (rc == -EAGAIN)
  7904. + rc = 0;
  7905. +
  7906. + return rc;
  7907. +}
  7908. +
  7909. +int
  7910. +CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
  7911. + const unsigned char *searchName,
  7912. + unsigned char **targetUNCs,
  7913. + unsigned int *number_of_UNC_in_array,
  7914. + const struct nls_table *nls_codepage)
  7915. +{
  7916. +/* TRANS2_GET_DFS_REFERRAL */
  7917. + TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
  7918. + TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
  7919. + struct dfs_referral_level_3 * referrals = NULL;
  7920. + int rc = 0;
  7921. + int bytes_returned;
  7922. + int name_len;
  7923. + unsigned int i;
  7924. + char * temp;
  7925. + *number_of_UNC_in_array = 0;
  7926. + *targetUNCs = NULL;
  7927. +
  7928. + cFYI(1, ("In GetDFSRefer the path %s", searchName));
  7929. + if (ses == NULL)
  7930. + return -ENODEV;
  7931. +getDFSRetry:
  7932. + rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
  7933. + (void **) &pSMBr);
  7934. + if (rc)
  7935. + return rc;
  7936. +
  7937. + pSMB->hdr.Tid = ses->ipc_tid;
  7938. + pSMB->hdr.Uid = ses->Suid;
  7939. + if (ses->capabilities & CAP_STATUS32) {
  7940. + pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
  7941. + }
  7942. + if (ses->capabilities & CAP_DFS) {
  7943. + pSMB->hdr.Flags2 |= SMBFLG2_DFS;
  7944. + }
  7945. +
  7946. + if (ses->capabilities & CAP_UNICODE) {
  7947. + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  7948. + name_len =
  7949. + cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
  7950. + searchName, 530
  7951. + /* find define for this maxpathcomponent */
  7952. + , nls_codepage);
  7953. + name_len++; /* trailing null */
  7954. + name_len *= 2;
  7955. + } else { /* BB improve the check for buffer overruns BB */
  7956. + name_len = strnlen(searchName, 530);
  7957. + name_len++; /* trailing null */
  7958. + strncpy(pSMB->RequestFileName, searchName, name_len);
  7959. + }
  7960. +
  7961. + pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
  7962. + pSMB->TotalDataCount = 0;
  7963. + pSMB->DataCount = 0;
  7964. + pSMB->DataOffset = 0;
  7965. + pSMB->MaxParameterCount = 0;
  7966. + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  7967. + pSMB->MaxSetupCount = 0;
  7968. + pSMB->Reserved = 0;
  7969. + pSMB->Flags = 0;
  7970. + pSMB->Timeout = 0;
  7971. + pSMB->Reserved2 = 0;
  7972. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  7973. + struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
  7974. + pSMB->SetupCount = 1;
  7975. + pSMB->Reserved3 = 0;
  7976. + pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
  7977. + pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
  7978. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  7979. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  7980. + pSMB->MaxReferralLevel = cpu_to_le16(3);
  7981. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  7982. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  7983. +
  7984. + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  7985. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  7986. + if (rc) {
  7987. + cFYI(1, ("Send error in GetDFSRefer = %d", rc));
  7988. + } else { /* decode response */
  7989. +/* BB Add logic to parse referrals here */
  7990. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  7991. + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
  7992. + cFYI(1,
  7993. + ("Decoding GetDFSRefer response. BCC: %d Offset %d",
  7994. + pSMBr->ByteCount, pSMBr->DataOffset));
  7995. + if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
  7996. + rc = -EIO; /* bad smb */
  7997. + else {
  7998. + referrals =
  7999. + (struct dfs_referral_level_3 *)
  8000. + (8 /* sizeof start of data block */ +
  8001. + pSMBr->DataOffset +
  8002. + (char *) &pSMBr->hdr.Protocol);
  8003. + cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
  8004. + /* BB This field is actually two bytes in from start of
  8005. + data block so we could do safety check that DataBlock
  8006. + begins at address of pSMBr->NumberOfReferrals */
  8007. + *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
  8008. +
  8009. + /* BB Fix below so can return more than one referral */
  8010. + if(*number_of_UNC_in_array > 1)
  8011. + *number_of_UNC_in_array = 1;
  8012. +
  8013. + /* get the length of the strings describing refs */
  8014. + name_len = 0;
  8015. + for(i=0;i<*number_of_UNC_in_array;i++) {
  8016. + /* make sure that DfsPathOffset not past end */
  8017. + referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
  8018. + if(referrals->DfsPathOffset > pSMBr->DataCount) {
  8019. + /* if invalid referral, stop here and do
  8020. + not try to copy any more */
  8021. + *number_of_UNC_in_array = i;
  8022. + break;
  8023. + }
  8024. + temp = ((char *)referrals) + referrals->DfsPathOffset;
  8025. +
  8026. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  8027. + name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
  8028. + } else {
  8029. + name_len += strnlen(temp,pSMBr->DataCount);
  8030. + }
  8031. + referrals++;
  8032. + /* BB add check that referral pointer does not fall off end PDU */
  8033. +
  8034. + }
  8035. + /* BB add check for name_len bigger than bcc */
  8036. + *targetUNCs =
  8037. + kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
  8038. + /* copy the ref strings */
  8039. + referrals =
  8040. + (struct dfs_referral_level_3 *)
  8041. + (8 /* sizeof data hdr */ +
  8042. + pSMBr->DataOffset +
  8043. + (char *) &pSMBr->hdr.Protocol);
  8044. +
  8045. + for(i=0;i<*number_of_UNC_in_array;i++) {
  8046. + temp = ((char *)referrals) + referrals->DfsPathOffset;
  8047. + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  8048. + cifs_strfromUCS_le(*targetUNCs,
  8049. + (wchar_t *) temp, name_len, nls_codepage);
  8050. + } else {
  8051. + strncpy(*targetUNCs,temp,name_len);
  8052. + }
  8053. + /* BB update target_uncs pointers */
  8054. + referrals++;
  8055. + }
  8056. + temp = *targetUNCs;
  8057. + temp[name_len] = 0;
  8058. + }
  8059. +
  8060. + }
  8061. + if (pSMB)
  8062. + cifs_buf_release(pSMB);
  8063. +
  8064. + if (rc == -EAGAIN)
  8065. + goto getDFSRetry;
  8066. +
  8067. + return rc;
  8068. +}
  8069. +
  8070. +int
  8071. +CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
  8072. + struct statfs *FSData, const struct nls_table *nls_codepage)
  8073. +{
  8074. +/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
  8075. + TRANSACTION2_QFSI_REQ *pSMB = NULL;
  8076. + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  8077. + FILE_SYSTEM_INFO *response_data;
  8078. + int rc = 0;
  8079. + int bytes_returned = 0;
  8080. +
  8081. + cFYI(1, ("In QFSInfo"));
  8082. +QFSInfoRetry:
  8083. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8084. + (void **) &pSMBr);
  8085. + if (rc)
  8086. + return rc;
  8087. +
  8088. + pSMB->TotalParameterCount = 2; /* level */
  8089. + pSMB->TotalDataCount = 0;
  8090. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8091. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  8092. + pSMB->MaxSetupCount = 0;
  8093. + pSMB->Reserved = 0;
  8094. + pSMB->Flags = 0;
  8095. + pSMB->Timeout = 0;
  8096. + pSMB->Reserved2 = 0;
  8097. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  8098. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  8099. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  8100. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  8101. + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  8102. + pSMB->DataCount = 0;
  8103. + pSMB->DataOffset = 0;
  8104. + pSMB->SetupCount = 1;
  8105. + pSMB->Reserved3 = 0;
  8106. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  8107. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
  8108. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8109. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8110. +
  8111. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8112. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8113. + if (rc) {
  8114. + cERROR(1, ("Send error in QFSInfo = %d", rc));
  8115. + } else { /* decode response */
  8116. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  8117. + cFYI(1,
  8118. + ("Decoding qfsinfo response. BCC: %d Offset %d",
  8119. + pSMBr->ByteCount, pSMBr->DataOffset));
  8120. + if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
  8121. + rc = -EIO; /* bad smb */
  8122. + else {
  8123. + response_data =
  8124. + (FILE_SYSTEM_INFO
  8125. + *) (((char *) &pSMBr->hdr.Protocol) +
  8126. + pSMBr->DataOffset);
  8127. + FSData->f_bsize =
  8128. + le32_to_cpu(response_data->BytesPerSector) *
  8129. + le32_to_cpu(response_data->
  8130. + SectorsPerAllocationUnit);
  8131. + FSData->f_blocks =
  8132. + le64_to_cpu(response_data->TotalAllocationUnits);
  8133. + FSData->f_bfree = FSData->f_bavail =
  8134. + le64_to_cpu(response_data->FreeAllocationUnits);
  8135. + cFYI(1,
  8136. + ("Blocks: %lld Free: %lld Block size %ld",
  8137. + (unsigned long long)FSData->f_blocks,
  8138. + (unsigned long long)FSData->f_bfree,
  8139. + FSData->f_bsize));
  8140. + }
  8141. + }
  8142. + if (pSMB)
  8143. + cifs_buf_release(pSMB);
  8144. +
  8145. + if (rc == -EAGAIN)
  8146. + goto QFSInfoRetry;
  8147. +
  8148. + return rc;
  8149. +}
  8150. +
  8151. +int
  8152. +CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
  8153. + const struct nls_table *nls_codepage)
  8154. +{
  8155. +/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
  8156. + TRANSACTION2_QFSI_REQ *pSMB = NULL;
  8157. + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  8158. + FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
  8159. + int rc = 0;
  8160. + int bytes_returned = 0;
  8161. +
  8162. + cFYI(1, ("In QFSAttributeInfo"));
  8163. +QFSAttributeRetry:
  8164. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8165. + (void **) &pSMBr);
  8166. + if (rc)
  8167. + return rc;
  8168. +
  8169. + pSMB->TotalParameterCount = 2; /* level */
  8170. + pSMB->TotalDataCount = 0;
  8171. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8172. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  8173. + pSMB->MaxSetupCount = 0;
  8174. + pSMB->Reserved = 0;
  8175. + pSMB->Flags = 0;
  8176. + pSMB->Timeout = 0;
  8177. + pSMB->Reserved2 = 0;
  8178. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  8179. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  8180. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  8181. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  8182. + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  8183. + pSMB->DataCount = 0;
  8184. + pSMB->DataOffset = 0;
  8185. + pSMB->SetupCount = 1;
  8186. + pSMB->Reserved3 = 0;
  8187. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  8188. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
  8189. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8190. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8191. +
  8192. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8193. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8194. + if (rc) {
  8195. + cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
  8196. + } else { /* decode response */
  8197. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  8198. + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
  8199. + rc = -EIO; /* bad smb */
  8200. + } else {
  8201. + response_data =
  8202. + (FILE_SYSTEM_ATTRIBUTE_INFO
  8203. + *) (((char *) &pSMBr->hdr.Protocol) +
  8204. + pSMBr->DataOffset);
  8205. + response_data->Attributes = le32_to_cpu(response_data->Attributes);
  8206. + response_data->MaxPathNameComponentLength =
  8207. + le32_to_cpu(response_data->MaxPathNameComponentLength);
  8208. + response_data->FileSystemNameLen =
  8209. + le32_to_cpu(response_data->FileSystemNameLen);
  8210. + memcpy(&tcon->fsAttrInfo, response_data,
  8211. + sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
  8212. + }
  8213. + }
  8214. + if (pSMB)
  8215. + cifs_buf_release(pSMB);
  8216. +
  8217. + if (rc == -EAGAIN)
  8218. + goto QFSAttributeRetry;
  8219. +
  8220. + return rc;
  8221. +}
  8222. +
  8223. +int
  8224. +CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
  8225. + const struct nls_table *nls_codepage)
  8226. +{
  8227. +/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
  8228. + TRANSACTION2_QFSI_REQ *pSMB = NULL;
  8229. + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  8230. + FILE_SYSTEM_DEVICE_INFO *response_data;
  8231. + int rc = 0;
  8232. + int bytes_returned = 0;
  8233. +
  8234. + cFYI(1, ("In QFSDeviceInfo"));
  8235. +QFSDeviceRetry:
  8236. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8237. + (void **) &pSMBr);
  8238. + if (rc)
  8239. + return rc;
  8240. +
  8241. + pSMB->TotalParameterCount = 2; /* level */
  8242. + pSMB->TotalDataCount = 0;
  8243. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8244. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  8245. + pSMB->MaxSetupCount = 0;
  8246. + pSMB->Reserved = 0;
  8247. + pSMB->Flags = 0;
  8248. + pSMB->Timeout = 0;
  8249. + pSMB->Reserved2 = 0;
  8250. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  8251. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  8252. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  8253. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  8254. + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  8255. +
  8256. + pSMB->DataCount = 0;
  8257. + pSMB->DataOffset = 0;
  8258. + pSMB->SetupCount = 1;
  8259. + pSMB->Reserved3 = 0;
  8260. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  8261. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
  8262. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8263. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8264. +
  8265. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8266. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8267. + if (rc) {
  8268. + cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
  8269. + } else { /* decode response */
  8270. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  8271. + if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
  8272. + || (pSMBr->DataOffset > 512))
  8273. + rc = -EIO; /* bad smb */
  8274. + else {
  8275. + response_data =
  8276. + (FILE_SYSTEM_DEVICE_INFO
  8277. + *) (((char *) &pSMBr->hdr.Protocol) +
  8278. + pSMBr->DataOffset);
  8279. + response_data->DeviceType =
  8280. + le32_to_cpu(response_data->DeviceType);
  8281. + response_data->DeviceCharacteristics =
  8282. + le32_to_cpu(response_data->DeviceCharacteristics);
  8283. + memcpy(&tcon->fsDevInfo, response_data,
  8284. + sizeof (FILE_SYSTEM_DEVICE_INFO));
  8285. + }
  8286. + }
  8287. + if (pSMB)
  8288. + cifs_buf_release(pSMB);
  8289. +
  8290. + if (rc == -EAGAIN)
  8291. + goto QFSDeviceRetry;
  8292. +
  8293. + return rc;
  8294. +}
  8295. +
  8296. +int
  8297. +CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
  8298. + const struct nls_table *nls_codepage)
  8299. +{
  8300. +/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
  8301. + TRANSACTION2_QFSI_REQ *pSMB = NULL;
  8302. + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  8303. + FILE_SYSTEM_UNIX_INFO *response_data;
  8304. + int rc = 0;
  8305. + int bytes_returned = 0;
  8306. +
  8307. + cFYI(1, ("In QFSUnixInfo"));
  8308. +QFSUnixRetry:
  8309. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8310. + (void **) &pSMBr);
  8311. + if (rc)
  8312. + return rc;
  8313. +
  8314. + pSMB->ParameterCount = 2; /* level */
  8315. + pSMB->TotalDataCount = 0;
  8316. + pSMB->DataCount = 0;
  8317. + pSMB->DataOffset = 0;
  8318. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8319. + pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
  8320. + pSMB->MaxSetupCount = 0;
  8321. + pSMB->Reserved = 0;
  8322. + pSMB->Flags = 0;
  8323. + pSMB->Timeout = 0;
  8324. + pSMB->Reserved2 = 0;
  8325. + pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
  8326. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  8327. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  8328. + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  8329. + smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  8330. + pSMB->SetupCount = 1;
  8331. + pSMB->Reserved3 = 0;
  8332. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  8333. + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
  8334. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8335. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8336. +
  8337. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8338. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8339. + if (rc) {
  8340. + cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
  8341. + } else { /* decode response */
  8342. + pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
  8343. + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
  8344. + rc = -EIO; /* bad smb */
  8345. + } else {
  8346. + response_data =
  8347. + (FILE_SYSTEM_UNIX_INFO
  8348. + *) (((char *) &pSMBr->hdr.Protocol) +
  8349. + pSMBr->DataOffset);
  8350. + response_data->MajorVersionNumber =
  8351. + le16_to_cpu(response_data->MajorVersionNumber);
  8352. + response_data->MinorVersionNumber =
  8353. + le16_to_cpu(response_data->MinorVersionNumber);
  8354. + response_data->Capability =
  8355. + le64_to_cpu(response_data->Capability);
  8356. + memcpy(&tcon->fsUnixInfo, response_data,
  8357. + sizeof (FILE_SYSTEM_UNIX_INFO));
  8358. + }
  8359. + }
  8360. + if (pSMB)
  8361. + cifs_buf_release(pSMB);
  8362. +
  8363. + if (rc == -EAGAIN)
  8364. + goto QFSUnixRetry;
  8365. +
  8366. +
  8367. + return rc;
  8368. +}
  8369. +
  8370. +/* We can not use write of zero bytes trick to
  8371. + set file size due to need for large file support. Also note that
  8372. + this SetPathInfo is preferred to SetFileInfo based method in next
  8373. + routine which is only needed to work around a sharing violation bug
  8374. + in Samba which this routine can run into */
  8375. +
  8376. +int
  8377. +CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
  8378. + __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
  8379. +{
  8380. + struct smb_com_transaction2_spi_req *pSMB = NULL;
  8381. + struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  8382. + struct file_end_of_file_info *parm_data;
  8383. + int name_len;
  8384. + int rc = 0;
  8385. + int bytes_returned = 0;
  8386. +
  8387. + cFYI(1, ("In SetEOF"));
  8388. +SetEOFRetry:
  8389. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8390. + (void **) &pSMBr);
  8391. + if (rc)
  8392. + return rc;
  8393. +
  8394. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  8395. + name_len =
  8396. + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
  8397. + /* find define for this maxpathcomponent */
  8398. + , nls_codepage);
  8399. + name_len++; /* trailing null */
  8400. + name_len *= 2;
  8401. + } else { /* BB improve the check for buffer overruns BB */
  8402. + name_len = strnlen(fileName, 530);
  8403. + name_len++; /* trailing null */
  8404. + strncpy(pSMB->FileName, fileName, name_len);
  8405. + }
  8406. + pSMB->ParameterCount = 6 + name_len;
  8407. + pSMB->DataCount = sizeof (struct file_end_of_file_info);
  8408. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8409. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
  8410. + pSMB->MaxSetupCount = 0;
  8411. + pSMB->Reserved = 0;
  8412. + pSMB->Flags = 0;
  8413. + pSMB->Timeout = 0;
  8414. + pSMB->Reserved2 = 0;
  8415. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
  8416. + InformationLevel) - 4;
  8417. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  8418. + if(SetAllocation) {
  8419. + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  8420. + pSMB->InformationLevel =
  8421. + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  8422. + else
  8423. + pSMB->InformationLevel =
  8424. + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
  8425. + } else /* Set File Size */ {
  8426. + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  8427. + pSMB->InformationLevel =
  8428. + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
  8429. + else
  8430. + pSMB->InformationLevel =
  8431. + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
  8432. + }
  8433. +
  8434. + parm_data =
  8435. + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
  8436. + pSMB->DataOffset);
  8437. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  8438. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  8439. + pSMB->SetupCount = 1;
  8440. + pSMB->Reserved3 = 0;
  8441. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  8442. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  8443. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  8444. + pSMB->TotalDataCount = pSMB->DataCount;
  8445. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  8446. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  8447. + pSMB->Reserved4 = 0;
  8448. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8449. + parm_data->FileSize = cpu_to_le64(size);
  8450. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8451. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8452. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8453. + if (rc) {
  8454. + cFYI(1, ("SetPathInfo (file size) returned %d", rc));
  8455. + }
  8456. +
  8457. + if (pSMB)
  8458. + cifs_buf_release(pSMB);
  8459. +
  8460. + if (rc == -EAGAIN)
  8461. + goto SetEOFRetry;
  8462. +
  8463. + return rc;
  8464. +}
  8465. +
  8466. +int
  8467. +CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
  8468. + __u16 fid, __u32 pid_of_opener, int SetAllocation)
  8469. +{
  8470. + struct smb_com_transaction2_sfi_req *pSMB = NULL;
  8471. + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
  8472. + char *data_offset;
  8473. + struct file_end_of_file_info *parm_data;
  8474. + int rc = 0;
  8475. + int bytes_returned = 0;
  8476. + __u32 tmp;
  8477. +
  8478. + cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
  8479. + (long long)size));
  8480. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8481. + (void **) &pSMBr);
  8482. + if (rc)
  8483. + return rc;
  8484. +
  8485. + tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
  8486. + so network fid will be valid */
  8487. + pSMB->hdr.Pid = tmp & 0xFFFF;
  8488. + tmp >>= 16;
  8489. + pSMB->hdr.PidHigh = tmp & 0xFFFF;
  8490. +
  8491. + pSMB->ParameterCount = 6;
  8492. + pSMB->MaxSetupCount = 0;
  8493. + pSMB->Reserved = 0;
  8494. + pSMB->Flags = 0;
  8495. + pSMB->Timeout = 0;
  8496. + pSMB->Reserved2 = 0;
  8497. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
  8498. + Fid) - 4;
  8499. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  8500. +
  8501. + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
  8502. +
  8503. + pSMB->DataCount = sizeof(struct file_end_of_file_info);
  8504. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8505. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
  8506. + pSMB->SetupCount = 1;
  8507. + pSMB->Reserved3 = 0;
  8508. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  8509. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  8510. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  8511. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  8512. + pSMB->TotalDataCount = pSMB->DataCount;
  8513. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  8514. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  8515. + parm_data =
  8516. + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
  8517. + pSMB->DataOffset);
  8518. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
  8519. + parm_data->FileSize = cpu_to_le64(size);
  8520. + pSMB->Fid = fid;
  8521. + if(SetAllocation) {
  8522. + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  8523. + pSMB->InformationLevel =
  8524. + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  8525. + else
  8526. + pSMB->InformationLevel =
  8527. + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
  8528. + } else /* Set File Size */ {
  8529. + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  8530. + pSMB->InformationLevel =
  8531. + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
  8532. + else
  8533. + pSMB->InformationLevel =
  8534. + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
  8535. + }
  8536. + pSMB->Reserved4 = 0;
  8537. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8538. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8539. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8540. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8541. + if (rc) {
  8542. + cFYI(1,
  8543. + ("Send error in SetFileInfo (SetFileSize) = %d",
  8544. + rc));
  8545. + }
  8546. +
  8547. + if (pSMB)
  8548. + cifs_buf_release(pSMB);
  8549. +
  8550. + /* Note: On -EAGAIN error only caller can retry on handle based calls
  8551. + since file handle passed in no longer valid */
  8552. +
  8553. + return rc;
  8554. +}
  8555. +
  8556. +int
  8557. +CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
  8558. + FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
  8559. +{
  8560. + TRANSACTION2_SPI_REQ *pSMB = NULL;
  8561. + TRANSACTION2_SPI_RSP *pSMBr = NULL;
  8562. + int name_len;
  8563. + int rc = 0;
  8564. + int bytes_returned = 0;
  8565. + char *data_offset;
  8566. +
  8567. + cFYI(1, ("In SetTimes"));
  8568. +
  8569. +SetTimesRetry:
  8570. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8571. + (void **) &pSMBr);
  8572. + if (rc)
  8573. + return rc;
  8574. +
  8575. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  8576. + name_len =
  8577. + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
  8578. + /* find define for this maxpathcomponent */
  8579. + , nls_codepage);
  8580. + name_len++; /* trailing null */
  8581. + name_len *= 2;
  8582. + } else { /* BB improve the check for buffer overruns BB */
  8583. + name_len = strnlen(fileName, 530);
  8584. + name_len++; /* trailing null */
  8585. + strncpy(pSMB->FileName, fileName, name_len);
  8586. + }
  8587. +
  8588. + pSMB->ParameterCount = 6 + name_len;
  8589. + pSMB->DataCount = sizeof (FILE_BASIC_INFO);
  8590. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8591. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  8592. + pSMB->MaxSetupCount = 0;
  8593. + pSMB->Reserved = 0;
  8594. + pSMB->Flags = 0;
  8595. + pSMB->Timeout = 0;
  8596. + pSMB->Reserved2 = 0;
  8597. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
  8598. + InformationLevel) - 4;
  8599. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  8600. + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
  8601. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  8602. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  8603. + pSMB->SetupCount = 1;
  8604. + pSMB->Reserved3 = 0;
  8605. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  8606. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  8607. +
  8608. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  8609. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  8610. + pSMB->TotalDataCount = pSMB->DataCount;
  8611. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  8612. + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  8613. + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
  8614. + else
  8615. + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
  8616. + pSMB->Reserved4 = 0;
  8617. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8618. + memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
  8619. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8620. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8621. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8622. + if (rc) {
  8623. + cFYI(1, ("SetPathInfo (times) returned %d", rc));
  8624. + }
  8625. +
  8626. + if (pSMB)
  8627. + cifs_buf_release(pSMB);
  8628. +
  8629. + if (rc == -EAGAIN)
  8630. + goto SetTimesRetry;
  8631. +
  8632. + return rc;
  8633. +}
  8634. +
  8635. +int
  8636. +CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
  8637. + char *fileName, __u64 mode, __u64 uid, __u64 gid,
  8638. + dev_t device, const struct nls_table *nls_codepage)
  8639. +{
  8640. + TRANSACTION2_SPI_REQ *pSMB = NULL;
  8641. + TRANSACTION2_SPI_RSP *pSMBr = NULL;
  8642. + int name_len;
  8643. + int rc = 0;
  8644. + int bytes_returned = 0;
  8645. + FILE_UNIX_BASIC_INFO *data_offset;
  8646. +
  8647. + cFYI(1, ("In SetUID/GID/Mode"));
  8648. +setPermsRetry:
  8649. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8650. + (void **) &pSMBr);
  8651. + if (rc)
  8652. + return rc;
  8653. +
  8654. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  8655. + name_len =
  8656. + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
  8657. + /* find define for this maxpathcomponent */
  8658. + , nls_codepage);
  8659. + name_len++; /* trailing null */
  8660. + name_len *= 2;
  8661. + } else { /* BB improve the check for buffer overruns BB */
  8662. + name_len = strnlen(fileName, 530);
  8663. + name_len++; /* trailing null */
  8664. + strncpy(pSMB->FileName, fileName, name_len);
  8665. + }
  8666. +
  8667. + pSMB->ParameterCount = 6 + name_len;
  8668. + pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
  8669. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8670. + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  8671. + pSMB->MaxSetupCount = 0;
  8672. + pSMB->Reserved = 0;
  8673. + pSMB->Flags = 0;
  8674. + pSMB->Timeout = 0;
  8675. + pSMB->Reserved2 = 0;
  8676. + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
  8677. + InformationLevel) - 4;
  8678. + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
  8679. + data_offset =
  8680. + (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
  8681. + pSMB->DataOffset);
  8682. + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
  8683. + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
  8684. + pSMB->SetupCount = 1;
  8685. + pSMB->Reserved3 = 0;
  8686. + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  8687. + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
  8688. + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
  8689. + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
  8690. + pSMB->TotalParameterCount = pSMB->ParameterCount;
  8691. + pSMB->TotalDataCount = pSMB->DataCount;
  8692. + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
  8693. + pSMB->Reserved4 = 0;
  8694. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8695. + data_offset->Uid = cpu_to_le64(uid);
  8696. + data_offset->Gid = cpu_to_le64(gid);
  8697. + /* better to leave device as zero when it is */
  8698. + data_offset->DevMajor = cpu_to_le64(MAJOR(device));
  8699. + data_offset->DevMinor = cpu_to_le64(MINOR(device));
  8700. + data_offset->Permissions = cpu_to_le64(mode);
  8701. +
  8702. + if(S_ISREG(mode))
  8703. + data_offset->Type = cpu_to_le32(UNIX_FILE);
  8704. + else if(S_ISDIR(mode))
  8705. + data_offset->Type = cpu_to_le32(UNIX_DIR);
  8706. + else if(S_ISLNK(mode))
  8707. + data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
  8708. + else if(S_ISCHR(mode))
  8709. + data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
  8710. + else if(S_ISBLK(mode))
  8711. + data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
  8712. + else if(S_ISFIFO(mode))
  8713. + data_offset->Type = cpu_to_le32(UNIX_FIFO);
  8714. + else if(S_ISSOCK(mode))
  8715. + data_offset->Type = cpu_to_le32(UNIX_SOCKET);
  8716. +
  8717. +
  8718. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8719. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8720. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8721. + if (rc) {
  8722. + cFYI(1, ("SetPathInfo (perms) returned %d", rc));
  8723. + }
  8724. +
  8725. + if (pSMB)
  8726. + cifs_buf_release(pSMB);
  8727. + if (rc == -EAGAIN)
  8728. + goto setPermsRetry;
  8729. + return rc;
  8730. +}
  8731. +
  8732. +int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
  8733. + const int notify_subdirs, const __u16 netfid,
  8734. + __u32 filter, const struct nls_table *nls_codepage)
  8735. +{
  8736. + int rc = 0;
  8737. + struct smb_com_transaction_change_notify_req * pSMB = NULL;
  8738. + struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
  8739. + int bytes_returned;
  8740. +
  8741. + cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
  8742. + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  8743. + (void **) &pSMBr);
  8744. + if (rc)
  8745. + return rc;
  8746. +
  8747. + pSMB->TotalParameterCount = 0 ;
  8748. + pSMB->TotalDataCount = 0;
  8749. + pSMB->MaxParameterCount = cpu_to_le32(2);
  8750. + /* BB find exact data count max from sess structure BB */
  8751. + pSMB->MaxDataCount = 0; /* same in little endian or be */
  8752. + pSMB->MaxSetupCount = 4;
  8753. + pSMB->Reserved = 0;
  8754. + pSMB->ParameterOffset = 0;
  8755. + pSMB->DataCount = 0;
  8756. + pSMB->DataOffset = 0;
  8757. + pSMB->SetupCount = 4; /* single byte does not need le conversion */
  8758. + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
  8759. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  8760. + if(notify_subdirs)
  8761. + pSMB->WatchTree = 1; /* one byte - no le conversion needed */
  8762. + pSMB->Reserved2 = 0;
  8763. + pSMB->CompletionFilter = cpu_to_le32(filter);
  8764. + pSMB->Fid = netfid; /* file handle always le */
  8765. + pSMB->ByteCount = 0;
  8766. +
  8767. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8768. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8769. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8770. + if (rc) {
  8771. + cFYI(1, ("Error in Notify = %d", rc));
  8772. + }
  8773. + if (pSMB)
  8774. + cifs_buf_release(pSMB);
  8775. +/* if (rc == -EAGAIN)
  8776. + goto NotifyRetry; */
  8777. + return rc;
  8778. +}
  8779. +#ifdef CONFIG_CIFS_XATTR
  8780. +int
  8781. +CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
  8782. + const unsigned char *searchName,
  8783. + char * EAData, size_t size,
  8784. + const struct nls_table *nls_codepage)
  8785. +{
  8786. + /* BB assumes one setup word */
  8787. + TRANSACTION2_QPI_REQ *pSMB = NULL;
  8788. + TRANSACTION2_QPI_RSP *pSMBr = NULL;
  8789. + int rc = 0;
  8790. + int bytes_returned;
  8791. + int name_len;
  8792. +
  8793. + cFYI(1, ("In Query All EAs path %s", searchName));
  8794. +QAllEAsRetry:
  8795. + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  8796. + (void **) &pSMBr);
  8797. + if (rc)
  8798. + return rc;
  8799. +
  8800. + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  8801. + name_len =
  8802. + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
  8803. + /* find define for this maxpathcomponent */
  8804. + , nls_codepage);
  8805. + name_len++; /* trailing null */
  8806. + name_len *= 2;
  8807. + } else { /* BB improve the check for buffer overruns BB */
  8808. + name_len = strnlen(searchName, 530);
  8809. + name_len++; /* trailing null */
  8810. + strncpy(pSMB->FileName, searchName, name_len);
  8811. + }
  8812. +
  8813. + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
  8814. + name_len /* includes null */ ;
  8815. + pSMB->TotalDataCount = 0;
  8816. + pSMB->MaxParameterCount = cpu_to_le16(2);
  8817. + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  8818. + pSMB->MaxSetupCount = 0;
  8819. + pSMB->Reserved = 0;
  8820. + pSMB->Flags = 0;
  8821. + pSMB->Timeout = 0;
  8822. + pSMB->Reserved2 = 0;
  8823. + pSMB->ParameterOffset = cpu_to_le16(offsetof(
  8824. + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  8825. + pSMB->DataCount = 0;
  8826. + pSMB->DataOffset = 0;
  8827. + pSMB->SetupCount = 1;
  8828. + pSMB->Reserved3 = 0;
  8829. + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  8830. + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
  8831. + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
  8832. + pSMB->ParameterCount = pSMB->TotalParameterCount;
  8833. + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
  8834. + pSMB->Reserved4 = 0;
  8835. + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
  8836. + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
  8837. +
  8838. + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  8839. + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  8840. + if (rc) {
  8841. + cFYI(1, ("Send error in QueryAllEAs = %d", rc));
  8842. + } else { /* decode response */
  8843. + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
  8844. + /* BB also check enough total bytes returned */
  8845. + /* BB we need to improve the validity checking
  8846. + of these trans2 responses */
  8847. + if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
  8848. + rc = -EIO; /* bad smb */
  8849. + /* else if (pFindData){
  8850. + memcpy((char *) pFindData,
  8851. + (char *) &pSMBr->hdr.Protocol +
  8852. + pSMBr->DataOffset, kl);
  8853. + }*/ else {
  8854. + /* check that length of list is not more than bcc */
  8855. + /* check that each entry does not go beyond length
  8856. + of list */
  8857. + /* check that each element of each entry does not
  8858. + go beyond end of list */
  8859. + struct fealist * ea_response_data;
  8860. + rc = 0;
  8861. + /* validate_trans2_offsets() */
  8862. + /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
  8863. + ea_response_data = (struct fealist *)
  8864. + (((char *) &pSMBr->hdr.Protocol) +
  8865. + pSMBr->DataOffset);
  8866. + cFYI(1,("ea length %d",ea_response_data->list_len));
  8867. + }
  8868. + }
  8869. + if (pSMB)
  8870. + cifs_buf_release(pSMB);
  8871. + if (rc == -EAGAIN)
  8872. + goto QAllEAsRetry;
  8873. +
  8874. + return rc;
  8875. +}
  8876. +#endif
  8877. --- /dev/null
  8878. +++ b/fs/cifs/cifs_unicode.c
  8879. @@ -0,0 +1,87 @@
  8880. +/*
  8881. + * fs/cifs/cifs_unicode.c
  8882. + *
  8883. + * Copyright (c) International Business Machines Corp., 2000,2002
  8884. + * Modified by Steve French ([email protected])
  8885. + *
  8886. + * This program is free software; you can redistribute it and/or modify
  8887. + * it under the terms of the GNU General Public License as published by
  8888. + * the Free Software Foundation; either version 2 of the License, or
  8889. + * (at your option) any later version.
  8890. + *
  8891. + * This program is distributed in the hope that it will be useful,
  8892. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8893. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  8894. + * the GNU General Public License for more details.
  8895. + *
  8896. + * You should have received a copy of the GNU General Public License
  8897. + * along with this program; if not, write to the Free Software
  8898. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  8899. + */
  8900. +#include <linux/fs.h>
  8901. +#include "cifs_unicode.h"
  8902. +#include "cifs_uniupr.h"
  8903. +#include "cifspdu.h"
  8904. +#include "cifs_debug.h"
  8905. +
  8906. +/*
  8907. + * NAME: cifs_strfromUCS()
  8908. + *
  8909. + * FUNCTION: Convert little-endian unicode string to character string
  8910. + *
  8911. + */
  8912. +int
  8913. +cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
  8914. + int len, const struct nls_table *codepage)
  8915. +{
  8916. + int i;
  8917. + int outlen = 0;
  8918. +
  8919. + for (i = 0; (i < len) && from[i]; i++) {
  8920. + int charlen;
  8921. + /* 2.4.0 kernel or greater */
  8922. + charlen =
  8923. + codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
  8924. + NLS_MAX_CHARSET_SIZE);
  8925. + if (charlen > 0) {
  8926. + outlen += charlen;
  8927. + } else {
  8928. + to[outlen++] = '?';
  8929. + }
  8930. + }
  8931. + to[outlen] = 0;
  8932. + return outlen;
  8933. +}
  8934. +
  8935. +/*
  8936. + * NAME: cifs_strtoUCS()
  8937. + *
  8938. + * FUNCTION: Convert character string to unicode string
  8939. + *
  8940. + */
  8941. +int
  8942. +cifs_strtoUCS(wchar_t * to, const char *from, int len,
  8943. + const struct nls_table *codepage)
  8944. +{
  8945. + int charlen;
  8946. + int i;
  8947. +
  8948. + for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
  8949. +
  8950. + /* works for 2.4.0 kernel or later */
  8951. + charlen = codepage->char2uni(from, len, &to[i]);
  8952. + if (charlen < 1) {
  8953. + cERROR(1,
  8954. + ("cifs_strtoUCS: char2uni returned %d",
  8955. + charlen));
  8956. + to[i] = cpu_to_le16(0x003f); /* a question mark */
  8957. + charlen = 1;
  8958. + }
  8959. + to[i] = cpu_to_le16(to[i]);
  8960. +
  8961. + }
  8962. +
  8963. + to[i] = 0;
  8964. + return i;
  8965. +}
  8966. +
  8967. --- /dev/null
  8968. +++ b/fs/cifs/cifs_unicode.h
  8969. @@ -0,0 +1,353 @@
  8970. +/*
  8971. + * cifs_unicode: Unicode kernel case support
  8972. + *
  8973. + * Function:
  8974. + * Convert a unicode character to upper or lower case using
  8975. + * compressed tables.
  8976. + *
  8977. + * Copyright (c) International Business Machines Corp., 2000,2002
  8978. + *
  8979. + * This program is free software; you can redistribute it and/or modify
  8980. + * it under the terms of the GNU General Public License as published by
  8981. + * the Free Software Foundation; either version 2 of the License, or
  8982. + * (at your option) any later version.
  8983. + *
  8984. + * This program is distributed in the hope that it will be useful,
  8985. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8986. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  8987. + * the GNU General Public License for more details.
  8988. + *
  8989. + * You should have received a copy of the GNU General Public License
  8990. + * along with this program; if not, write to the Free Software
  8991. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  8992. + *
  8993. + *
  8994. + * Notes:
  8995. + * These APIs are based on the C library functions. The semantics
  8996. + * should match the C functions but with expanded size operands.
  8997. + *
  8998. + * The upper/lower functions are based on a table created by mkupr.
  8999. + * This is a compressed table of upper and lower case conversion.
  9000. + *
  9001. + */
  9002. +
  9003. +#include <asm/byteorder.h>
  9004. +#include <linux/types.h>
  9005. +#include <linux/nls.h>
  9006. +
  9007. +#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
  9008. +
  9009. +/* Just define what we want from uniupr.h. We don't want to define the tables
  9010. + * in each source file.
  9011. + */
  9012. +#ifndef UNICASERANGE_DEFINED
  9013. +struct UniCaseRange {
  9014. + wchar_t start;
  9015. + wchar_t end;
  9016. + signed char *table;
  9017. +};
  9018. +#endif /* UNICASERANGE_DEFINED */
  9019. +
  9020. +#ifndef UNIUPR_NOUPPER
  9021. +extern signed char CifsUniUpperTable[512];
  9022. +extern const struct UniCaseRange CifsUniUpperRange[];
  9023. +#endif /* UNIUPR_NOUPPER */
  9024. +
  9025. +#ifndef UNIUPR_NOLOWER
  9026. +extern signed char UniLowerTable[512];
  9027. +extern struct UniCaseRange UniLowerRange[];
  9028. +#endif /* UNIUPR_NOLOWER */
  9029. +
  9030. +#ifdef __KERNEL__
  9031. +int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
  9032. +int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
  9033. +#endif
  9034. +
  9035. +/*
  9036. + * UniStrcat: Concatenate the second string to the first
  9037. + *
  9038. + * Returns:
  9039. + * Address of the first string
  9040. + */
  9041. +static inline wchar_t *
  9042. +UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
  9043. +{
  9044. + wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
  9045. +
  9046. + while (*ucs1++) ; /* To end of first string */
  9047. + ucs1--; /* Return to the null */
  9048. + while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
  9049. + return anchor;
  9050. +}
  9051. +
  9052. +/*
  9053. + * UniStrchr: Find a character in a string
  9054. + *
  9055. + * Returns:
  9056. + * Address of first occurrence of character in string
  9057. + * or NULL if the character is not in the string
  9058. + */
  9059. +static inline wchar_t *
  9060. +UniStrchr(const wchar_t * ucs, wchar_t uc)
  9061. +{
  9062. + while ((*ucs != uc) && *ucs)
  9063. + ucs++;
  9064. +
  9065. + if (*ucs == uc)
  9066. + return (wchar_t *) ucs;
  9067. + return NULL;
  9068. +}
  9069. +
  9070. +/*
  9071. + * UniStrcmp: Compare two strings
  9072. + *
  9073. + * Returns:
  9074. + * < 0: First string is less than second
  9075. + * = 0: Strings are equal
  9076. + * > 0: First string is greater than second
  9077. + */
  9078. +static inline int
  9079. +UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
  9080. +{
  9081. + while ((*ucs1 == *ucs2) && *ucs1) {
  9082. + ucs1++;
  9083. + ucs2++;
  9084. + }
  9085. + return (int) *ucs1 - (int) *ucs2;
  9086. +}
  9087. +
  9088. +/*
  9089. + * UniStrcpy: Copy a string
  9090. + */
  9091. +static inline wchar_t *
  9092. +UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
  9093. +{
  9094. + wchar_t *anchor = ucs1; /* save the start of result string */
  9095. +
  9096. + while ((*ucs1++ = *ucs2++)) ;
  9097. + return anchor;
  9098. +}
  9099. +
  9100. +/*
  9101. + * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
  9102. + */
  9103. +static inline size_t
  9104. +UniStrlen(const wchar_t * ucs1)
  9105. +{
  9106. + int i = 0;
  9107. +
  9108. + while (*ucs1++)
  9109. + i++;
  9110. + return i;
  9111. +}
  9112. +
  9113. +/*
  9114. + * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
  9115. + */
  9116. +static inline size_t
  9117. +UniStrnlen(const wchar_t * ucs1, int maxlen)
  9118. +{
  9119. + int i = 0;
  9120. +
  9121. + while (*ucs1++) {
  9122. + i++;
  9123. + if (i >= maxlen)
  9124. + break;
  9125. + }
  9126. + return i;
  9127. +}
  9128. +
  9129. +/*
  9130. + * UniStrncat: Concatenate length limited string
  9131. + */
  9132. +static inline wchar_t *
  9133. +UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
  9134. +{
  9135. + wchar_t *anchor = ucs1; /* save pointer to string 1 */
  9136. +
  9137. + while (*ucs1++) ;
  9138. + ucs1--; /* point to null terminator of s1 */
  9139. + while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
  9140. + ucs1++;
  9141. + ucs2++;
  9142. + }
  9143. + *ucs1 = 0; /* Null terminate the result */
  9144. + return (anchor);
  9145. +}
  9146. +
  9147. +/*
  9148. + * UniStrncmp: Compare length limited string
  9149. + */
  9150. +static inline int
  9151. +UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
  9152. +{
  9153. + if (!n)
  9154. + return 0; /* Null strings are equal */
  9155. + while ((*ucs1 == *ucs2) && *ucs1 && --n) {
  9156. + ucs1++;
  9157. + ucs2++;
  9158. + }
  9159. + return (int) *ucs1 - (int) *ucs2;
  9160. +}
  9161. +
  9162. +/*
  9163. + * UniStrncmp_le: Compare length limited string - native to little-endian
  9164. + */
  9165. +static inline int
  9166. +UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
  9167. +{
  9168. + if (!n)
  9169. + return 0; /* Null strings are equal */
  9170. + while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
  9171. + ucs1++;
  9172. + ucs2++;
  9173. + }
  9174. + return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
  9175. +}
  9176. +
  9177. +/*
  9178. + * UniStrncpy: Copy length limited string with pad
  9179. + */
  9180. +static inline wchar_t *
  9181. +UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
  9182. +{
  9183. + wchar_t *anchor = ucs1;
  9184. +
  9185. + while (n-- && *ucs2) /* Copy the strings */
  9186. + *ucs1++ = *ucs2++;
  9187. +
  9188. + n++;
  9189. + while (n--) /* Pad with nulls */
  9190. + *ucs1++ = 0;
  9191. + return anchor;
  9192. +}
  9193. +
  9194. +/*
  9195. + * UniStrncpy_le: Copy length limited string with pad to little-endian
  9196. + */
  9197. +static inline wchar_t *
  9198. +UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
  9199. +{
  9200. + wchar_t *anchor = ucs1;
  9201. +
  9202. + while (n-- && *ucs2) /* Copy the strings */
  9203. + *ucs1++ = __le16_to_cpu(*ucs2++);
  9204. +
  9205. + n++;
  9206. + while (n--) /* Pad with nulls */
  9207. + *ucs1++ = 0;
  9208. + return anchor;
  9209. +}
  9210. +
  9211. +/*
  9212. + * UniStrstr: Find a string in a string
  9213. + *
  9214. + * Returns:
  9215. + * Address of first match found
  9216. + * NULL if no matching string is found
  9217. + */
  9218. +static inline wchar_t *
  9219. +UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
  9220. +{
  9221. + const wchar_t *anchor1 = ucs1;
  9222. + const wchar_t *anchor2 = ucs2;
  9223. +
  9224. + while (*ucs1) {
  9225. + if (*ucs1 == *ucs2) { /* Partial match found */
  9226. + ucs1++;
  9227. + ucs2++;
  9228. + } else {
  9229. + if (!*ucs2) /* Match found */
  9230. + return (wchar_t *) anchor1;
  9231. + ucs1 = ++anchor1; /* No match */
  9232. + ucs2 = anchor2;
  9233. + }
  9234. + }
  9235. +
  9236. + if (!*ucs2) /* Both end together */
  9237. + return (wchar_t *) anchor1; /* Match found */
  9238. + return NULL; /* No match */
  9239. +}
  9240. +
  9241. +#ifndef UNIUPR_NOUPPER
  9242. +/*
  9243. + * UniToupper: Convert a unicode character to upper case
  9244. + */
  9245. +static inline wchar_t
  9246. +UniToupper(register wchar_t uc)
  9247. +{
  9248. + register const struct UniCaseRange *rp;
  9249. +
  9250. + if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
  9251. + return uc + CifsUniUpperTable[uc]; /* Use base tables */
  9252. + } else {
  9253. + rp = CifsUniUpperRange; /* Use range tables */
  9254. + while (rp->start) {
  9255. + if (uc < rp->start) /* Before start of range */
  9256. + return uc; /* Uppercase = input */
  9257. + if (uc <= rp->end) /* In range */
  9258. + return uc + rp->table[uc - rp->start];
  9259. + rp++; /* Try next range */
  9260. + }
  9261. + }
  9262. + return uc; /* Past last range */
  9263. +}
  9264. +
  9265. +/*
  9266. + * UniStrupr: Upper case a unicode string
  9267. + */
  9268. +static inline wchar_t *
  9269. +UniStrupr(register wchar_t * upin)
  9270. +{
  9271. + register wchar_t *up;
  9272. +
  9273. + up = upin;
  9274. + while (*up) { /* For all characters */
  9275. + *up = UniToupper(*up);
  9276. + up++;
  9277. + }
  9278. + return upin; /* Return input pointer */
  9279. +}
  9280. +#endif /* UNIUPR_NOUPPER */
  9281. +
  9282. +#ifndef UNIUPR_NOLOWER
  9283. +/*
  9284. + * UniTolower: Convert a unicode character to lower case
  9285. + */
  9286. +static inline wchar_t
  9287. +UniTolower(wchar_t uc)
  9288. +{
  9289. + register struct UniCaseRange *rp;
  9290. +
  9291. + if (uc < sizeof (UniLowerTable)) { /* Latin characters */
  9292. + return uc + UniLowerTable[uc]; /* Use base tables */
  9293. + } else {
  9294. + rp = UniLowerRange; /* Use range tables */
  9295. + while (rp->start) {
  9296. + if (uc < rp->start) /* Before start of range */
  9297. + return uc; /* Uppercase = input */
  9298. + if (uc <= rp->end) /* In range */
  9299. + return uc + rp->table[uc - rp->start];
  9300. + rp++; /* Try next range */
  9301. + }
  9302. + }
  9303. + return uc; /* Past last range */
  9304. +}
  9305. +
  9306. +/*
  9307. + * UniStrlwr: Lower case a unicode string
  9308. + */
  9309. +static inline wchar_t *
  9310. +UniStrlwr(register wchar_t * upin)
  9311. +{
  9312. + register wchar_t *up;
  9313. +
  9314. + up = upin;
  9315. + while (*up) { /* For all characters */
  9316. + *up = UniTolower(*up);
  9317. + up++;
  9318. + }
  9319. + return upin; /* Return input pointer */
  9320. +}
  9321. +
  9322. +#endif
  9323. --- /dev/null
  9324. +++ b/fs/cifs/cifs_uniupr.h
  9325. @@ -0,0 +1,253 @@
  9326. +/*
  9327. + * Copyright (c) International Business Machines Corp., 2000,2002
  9328. + *
  9329. + * This program is free software; you can redistribute it and/or modify
  9330. + * it under the terms of the GNU General Public License as published by
  9331. + * the Free Software Foundation; either version 2 of the License, or
  9332. + * (at your option) any later version.
  9333. + *
  9334. + * This program is distributed in the hope that it will be useful,
  9335. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9336. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  9337. + * the GNU General Public License for more details.
  9338. + *
  9339. + * You should have received a copy of the GNU General Public License
  9340. + * along with this program; if not, write to the Free Software
  9341. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  9342. + *
  9343. + * uniupr.h - Unicode compressed case ranges
  9344. + *
  9345. +*/
  9346. +
  9347. +#ifndef UNIUPR_NOUPPER
  9348. +/*
  9349. + * Latin upper case
  9350. + */
  9351. +signed char CifsUniUpperTable[512] = {
  9352. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
  9353. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
  9354. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
  9355. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
  9356. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
  9357. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
  9358. + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
  9359. + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
  9360. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
  9361. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
  9362. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
  9363. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
  9364. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
  9365. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
  9366. + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
  9367. + -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
  9368. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
  9369. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
  9370. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
  9371. + 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
  9372. + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
  9373. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
  9374. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
  9375. + 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
  9376. + 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
  9377. + 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
  9378. + 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
  9379. + -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
  9380. + 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
  9381. + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
  9382. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
  9383. + 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
  9384. +};
  9385. +
  9386. +/* Upper case range - Greek */
  9387. +static signed char UniCaseRangeU03a0[47] = {
  9388. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
  9389. + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
  9390. + -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
  9391. + -63, -63,
  9392. +};
  9393. +
  9394. +/* Upper case range - Cyrillic */
  9395. +static signed char UniCaseRangeU0430[48] = {
  9396. + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
  9397. + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
  9398. + 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
  9399. +};
  9400. +
  9401. +/* Upper case range - Extended cyrillic */
  9402. +static signed char UniCaseRangeU0490[61] = {
  9403. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
  9404. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
  9405. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
  9406. + 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
  9407. +};
  9408. +
  9409. +/* Upper case range - Extended latin and greek */
  9410. +static signed char UniCaseRangeU1e00[509] = {
  9411. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
  9412. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
  9413. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
  9414. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
  9415. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
  9416. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
  9417. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
  9418. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
  9419. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
  9420. + 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
  9421. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
  9422. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
  9423. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
  9424. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
  9425. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
  9426. + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
  9427. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
  9428. + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
  9429. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
  9430. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
  9431. + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
  9432. + 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
  9433. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
  9434. + 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
  9435. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
  9436. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
  9437. + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
  9438. + 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
  9439. + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
  9440. + 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
  9441. + 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
  9442. + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  9443. +};
  9444. +
  9445. +/* Upper case range - Wide latin */
  9446. +static signed char UniCaseRangeUff40[27] = {
  9447. + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
  9448. + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
  9449. +};
  9450. +
  9451. +/*
  9452. + * Upper Case Range
  9453. + */
  9454. +const struct UniCaseRange CifsUniUpperRange[] = {
  9455. + {0x03a0, 0x03ce, UniCaseRangeU03a0},
  9456. + {0x0430, 0x045f, UniCaseRangeU0430},
  9457. + {0x0490, 0x04cc, UniCaseRangeU0490},
  9458. + {0x1e00, 0x1ffc, UniCaseRangeU1e00},
  9459. + {0xff40, 0xff5a, UniCaseRangeUff40},
  9460. + {0, 0, NULL}
  9461. +};
  9462. +#endif
  9463. +
  9464. +#ifndef UNIUPR_NOLOWER
  9465. +/*
  9466. + * Latin lower case
  9467. + */
  9468. +static signed char CifsUniLowerTable[512] = {
  9469. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
  9470. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
  9471. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
  9472. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
  9473. + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
  9474. + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
  9475. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
  9476. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
  9477. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
  9478. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
  9479. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
  9480. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
  9481. + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
  9482. + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
  9483. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
  9484. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
  9485. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
  9486. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
  9487. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
  9488. + 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
  9489. + 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
  9490. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
  9491. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
  9492. + 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
  9493. + 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
  9494. + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
  9495. + 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
  9496. + 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
  9497. + 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
  9498. + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
  9499. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
  9500. + 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
  9501. +};
  9502. +
  9503. +/* Lower case range - Greek */
  9504. +static signed char UniCaseRangeL0380[44] = {
  9505. + 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
  9506. + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
  9507. + 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
  9508. +};
  9509. +
  9510. +/* Lower case range - Cyrillic */
  9511. +static signed char UniCaseRangeL0400[48] = {
  9512. + 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
  9513. + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
  9514. + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
  9515. +};
  9516. +
  9517. +/* Lower case range - Extended cyrillic */
  9518. +static signed char UniCaseRangeL0490[60] = {
  9519. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
  9520. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
  9521. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
  9522. + 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
  9523. +};
  9524. +
  9525. +/* Lower case range - Extended latin and greek */
  9526. +static signed char UniCaseRangeL1e00[504] = {
  9527. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
  9528. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
  9529. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
  9530. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
  9531. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
  9532. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
  9533. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
  9534. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
  9535. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
  9536. + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
  9537. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
  9538. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
  9539. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
  9540. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
  9541. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
  9542. + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
  9543. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
  9544. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
  9545. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
  9546. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
  9547. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
  9548. + 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
  9549. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
  9550. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
  9551. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
  9552. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
  9553. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
  9554. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
  9555. + 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
  9556. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
  9557. + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
  9558. + 0, 0, 0, 0, 0, 0, 0, 0,
  9559. +};
  9560. +
  9561. +/* Lower case range - Wide latin */
  9562. +static signed char UniCaseRangeLff20[27] = {
  9563. + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
  9564. + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
  9565. +};
  9566. +
  9567. +/*
  9568. + * Lower Case Range
  9569. + */
  9570. +const static struct UniCaseRange CifsUniLowerRange[] = {
  9571. + 0x0380, 0x03ab, UniCaseRangeL0380,
  9572. + 0x0400, 0x042f, UniCaseRangeL0400,
  9573. + 0x0490, 0x04cb, UniCaseRangeL0490,
  9574. + 0x1e00, 0x1ff7, UniCaseRangeL1e00,
  9575. + 0xff20, 0xff3a, UniCaseRangeLff20,
  9576. + 0, 0, 0
  9577. +};
  9578. +#endif
  9579. --- /dev/null
  9580. +++ b/fs/cifs/connect.c
  9581. @@ -0,0 +1,2924 @@
  9582. +/*
  9583. + * fs/cifs/connect.c
  9584. + *
  9585. + * Copyright (C) International Business Machines Corp., 2002,2004
  9586. + * Author(s): Steve French ([email protected])
  9587. + *
  9588. + * This library is free software; you can redistribute it and/or modify
  9589. + * it under the terms of the GNU Lesser General Public License as published
  9590. + * by the Free Software Foundation; either version 2.1 of the License, or
  9591. + * (at your option) any later version.
  9592. + *
  9593. + * This library is distributed in the hope that it will be useful,
  9594. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9595. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  9596. + * the GNU Lesser General Public License for more details.
  9597. + *
  9598. + * You should have received a copy of the GNU Lesser General Public License
  9599. + * along with this library; if not, write to the Free Software
  9600. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  9601. + */
  9602. +#include <linux/fs.h>
  9603. +#include <linux/net.h>
  9604. +#include <linux/string.h>
  9605. +#include <linux/list.h>
  9606. +#include <linux/wait.h>
  9607. +#include <linux/version.h>
  9608. +#include <linux/ipv6.h>
  9609. +#include <linux/pagemap.h>
  9610. +#include <linux/ctype.h>
  9611. +#include <linux/utsname.h>
  9612. +#include <asm/uaccess.h>
  9613. +#include <asm/processor.h>
  9614. +#include "cifspdu.h"
  9615. +#include "cifsglob.h"
  9616. +#include "cifsproto.h"
  9617. +#include "cifs_unicode.h"
  9618. +#include "cifs_debug.h"
  9619. +#include "cifs_fs_sb.h"
  9620. +#include "ntlmssp.h"
  9621. +#include "nterr.h"
  9622. +#include "rfc1002pdu.h"
  9623. +
  9624. +#define CIFS_PORT 445
  9625. +#define RFC1001_PORT 139
  9626. +
  9627. +extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
  9628. + unsigned char *p24);
  9629. +extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
  9630. + unsigned char *p24);
  9631. +extern int cifs_inet_pton(int, const char *, void *dst);
  9632. +
  9633. +struct smb_vol {
  9634. + char *username;
  9635. + char *password;
  9636. + char *domainname;
  9637. + char *UNC;
  9638. + char *UNCip;
  9639. + char *iocharset; /* local code page for mapping to and from Unicode */
  9640. + char source_rfc1001_name[16]; /* netbios name of client */
  9641. + uid_t linux_uid;
  9642. + gid_t linux_gid;
  9643. + mode_t file_mode;
  9644. + mode_t dir_mode;
  9645. + int rw:1;
  9646. + int retry:1;
  9647. + int intr:1;
  9648. + unsigned int rsize;
  9649. + unsigned int wsize;
  9650. + unsigned int sockopt;
  9651. + unsigned short int port;
  9652. +};
  9653. +
  9654. +static int ipv4_connect(struct sockaddr_in *psin_server,
  9655. + struct socket **csocket,
  9656. + char * netb_name);
  9657. +static int ipv6_connect(struct sockaddr_in6 *psin_server,
  9658. + struct socket **csocket);
  9659. +
  9660. +
  9661. + /*
  9662. + * cifs tcp session reconnection
  9663. + *
  9664. + * mark tcp session as reconnecting so temporarily locked
  9665. + * mark all smb sessions as reconnecting for tcp session
  9666. + * reconnect tcp session
  9667. + * wake up waiters on reconnection? - (not needed currently)
  9668. + */
  9669. +
  9670. +int
  9671. +cifs_reconnect(struct TCP_Server_Info *server)
  9672. +{
  9673. + int rc = 0;
  9674. + struct list_head *tmp;
  9675. + struct cifsSesInfo *ses;
  9676. + struct cifsTconInfo *tcon;
  9677. + struct mid_q_entry * mid_entry;
  9678. +
  9679. + spin_lock(&GlobalMid_Lock);
  9680. + if(server->tcpStatus == CifsExiting) {
  9681. + /* the demux thread will exit normally
  9682. + next time through the loop */
  9683. + spin_unlock(&GlobalMid_Lock);
  9684. + return rc;
  9685. + } else
  9686. + server->tcpStatus = CifsNeedReconnect;
  9687. + spin_unlock(&GlobalMid_Lock);
  9688. + server->maxBuf = 0;
  9689. +
  9690. + cFYI(1, ("Reconnecting tcp session "));
  9691. +
  9692. + /* before reconnecting the tcp session, mark the smb session (uid)
  9693. + and the tid bad so they are not used until reconnected */
  9694. + read_lock(&GlobalSMBSeslock);
  9695. + list_for_each(tmp, &GlobalSMBSessionList) {
  9696. + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
  9697. + if (ses->server) {
  9698. + if (ses->server == server) {
  9699. + ses->status = CifsNeedReconnect;
  9700. + ses->ipc_tid = 0;
  9701. + }
  9702. + }
  9703. + /* else tcp and smb sessions need reconnection */
  9704. + }
  9705. + list_for_each(tmp, &GlobalTreeConnectionList) {
  9706. + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
  9707. + if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
  9708. + tcon->tidStatus = CifsNeedReconnect;
  9709. + }
  9710. + }
  9711. + read_unlock(&GlobalSMBSeslock);
  9712. + /* do not want to be sending data on a socket we are freeing */
  9713. + down(&server->tcpSem);
  9714. + if(server->ssocket) {
  9715. + cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
  9716. + server->ssocket->flags));
  9717. + server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
  9718. + cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
  9719. + server->ssocket->flags));
  9720. + sock_release(server->ssocket);
  9721. + server->ssocket = NULL;
  9722. + }
  9723. +
  9724. + spin_lock(&GlobalMid_Lock);
  9725. + list_for_each(tmp, &server->pending_mid_q) {
  9726. + mid_entry = list_entry(tmp, struct
  9727. + mid_q_entry,
  9728. + qhead);
  9729. + if(mid_entry) {
  9730. + if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
  9731. + /* Mark other intransit requests as needing retry so
  9732. + we do not immediately mark the session bad again
  9733. + (ie after we reconnect below) as they timeout too */
  9734. + mid_entry->midState = MID_RETRY_NEEDED;
  9735. + }
  9736. + }
  9737. + }
  9738. + spin_unlock(&GlobalMid_Lock);
  9739. + up(&server->tcpSem);
  9740. +
  9741. + while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
  9742. + {
  9743. + if(server->protocolType == IPV6) {
  9744. + rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
  9745. + } else {
  9746. + rc = ipv4_connect(&server->addr.sockAddr,
  9747. + &server->ssocket,
  9748. + server->workstation_RFC1001_name);
  9749. + }
  9750. + if(rc) {
  9751. + set_current_state(TASK_INTERRUPTIBLE);
  9752. + schedule_timeout(3 * HZ);
  9753. + } else {
  9754. + atomic_inc(&tcpSesReconnectCount);
  9755. + spin_lock(&GlobalMid_Lock);
  9756. + if(server->tcpStatus != CifsExiting)
  9757. + server->tcpStatus = CifsGood;
  9758. + spin_unlock(&GlobalMid_Lock);
  9759. + /* atomic_set(&server->inFlight,0);*/
  9760. + wake_up(&server->response_q);
  9761. + }
  9762. + }
  9763. + return rc;
  9764. +}
  9765. +
  9766. +static int
  9767. +cifs_demultiplex_thread(struct TCP_Server_Info *server)
  9768. +{
  9769. + int length;
  9770. + unsigned int pdu_length, total_read;
  9771. + struct smb_hdr *smb_buffer = NULL;
  9772. + struct msghdr smb_msg;
  9773. + mm_segment_t temp_fs;
  9774. + struct iovec iov;
  9775. + struct socket *csocket = server->ssocket;
  9776. + struct list_head *tmp;
  9777. + struct cifsSesInfo *ses;
  9778. + struct task_struct *task_to_wake = NULL;
  9779. + struct mid_q_entry *mid_entry;
  9780. + char *temp;
  9781. +
  9782. + daemonize();
  9783. + sprintf(current->comm,"cifsd");
  9784. + /* allow_signal(SIGKILL);*/
  9785. + current->flags |= PF_MEMALLOC;
  9786. + server->tsk = current; /* save process info to wake at shutdown */
  9787. + cFYI(1, ("Demultiplex PID: %d", current->pid));
  9788. +
  9789. + temp_fs = get_fs(); /* we must turn off socket api parm checking */
  9790. + set_fs(get_ds());
  9791. +
  9792. + while (server->tcpStatus != CifsExiting) {
  9793. + if (smb_buffer == NULL)
  9794. + smb_buffer = cifs_buf_get();
  9795. + else
  9796. + memset(smb_buffer, 0, sizeof (struct smb_hdr));
  9797. +
  9798. + if (smb_buffer == NULL) {
  9799. + cERROR(1,("Can not get memory for SMB response"));
  9800. + set_current_state(TASK_INTERRUPTIBLE);
  9801. + schedule_timeout(HZ * 3); /* give system time to free memory */
  9802. + continue;
  9803. + }
  9804. + iov.iov_base = smb_buffer;
  9805. + iov.iov_len = sizeof (struct smb_hdr) - 1;
  9806. + /* 1 byte less above since wct is not always returned in error cases */
  9807. + smb_msg.msg_iov = &iov;
  9808. + smb_msg.msg_iovlen = 1;
  9809. + smb_msg.msg_control = NULL;
  9810. + smb_msg.msg_controllen = 0;
  9811. +
  9812. + length =
  9813. + sock_recvmsg(csocket, &smb_msg,
  9814. + sizeof (struct smb_hdr) -
  9815. + 1 /* RFC1001 header and SMB header */ ,
  9816. + MSG_PEEK /* flags see socket.h */ );
  9817. +
  9818. + if(server->tcpStatus == CifsExiting) {
  9819. + break;
  9820. + } else if (server->tcpStatus == CifsNeedReconnect) {
  9821. + cFYI(1,("Reconnecting after server stopped responding"));
  9822. + cifs_reconnect(server);
  9823. + cFYI(1,("call to reconnect done"));
  9824. + csocket = server->ssocket;
  9825. + continue;
  9826. + } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
  9827. + set_current_state(TASK_INTERRUPTIBLE);
  9828. + schedule_timeout(1); /* minimum sleep to prevent looping
  9829. + allowing socket to clear and app threads to set
  9830. + tcpStatus CifsNeedReconnect if server hung */
  9831. + continue;
  9832. + } else if (length <= 0) {
  9833. + if(server->tcpStatus == CifsNew) {
  9834. + cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
  9835. + /* some servers kill tcp session rather than returning
  9836. + smb negprot error in which case reconnecting here is
  9837. + not going to help - return error to mount */
  9838. + break;
  9839. + }
  9840. + if(length == -EINTR) {
  9841. + cFYI(1,("cifsd thread killed"));
  9842. + break;
  9843. + }
  9844. + cFYI(1,("Reconnecting after unexpected peek error %d",length));
  9845. + cifs_reconnect(server);
  9846. + csocket = server->ssocket;
  9847. + wake_up(&server->response_q);
  9848. + continue;
  9849. + }
  9850. +
  9851. + pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
  9852. + /* Ony read pdu_length after below checks for too short (due
  9853. + to e.g. int overflow) and too long ie beyond end of buf */
  9854. + cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
  9855. +
  9856. + temp = (char *) smb_buffer;
  9857. + if (length > 3) {
  9858. + if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
  9859. + iov.iov_base = smb_buffer;
  9860. + iov.iov_len = 4;
  9861. + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
  9862. + cFYI(0,("Received 4 byte keep alive packet"));
  9863. + } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
  9864. + iov.iov_base = smb_buffer;
  9865. + iov.iov_len = 4;
  9866. + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
  9867. + cFYI(1,("Good RFC 1002 session rsp"));
  9868. + } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
  9869. + && (length == 5)) {
  9870. + /* we get this from Windows 98 instead of error on SMB negprot response */
  9871. + cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
  9872. + if(server->tcpStatus == CifsNew) {
  9873. + /* if nack on negprot (rather than
  9874. + ret of smb negprot error) reconnecting
  9875. + not going to help, ret error to mount */
  9876. + break;
  9877. + } else {
  9878. + /* give server a second to
  9879. + clean up before reconnect attempt */
  9880. + set_current_state(TASK_INTERRUPTIBLE);
  9881. + schedule_timeout(HZ);
  9882. + /* always try 445 first on reconnect
  9883. + since we get NACK on some if we ever
  9884. + connected to port 139 (the NACK is
  9885. + since we do not begin with RFC1001
  9886. + session initialize frame) */
  9887. + server->addr.sockAddr.sin_port = CIFS_PORT;
  9888. + cifs_reconnect(server);
  9889. + csocket = server->ssocket;
  9890. + wake_up(&server->response_q);
  9891. + continue;
  9892. + }
  9893. + } else if (temp[0] != (char) 0) {
  9894. + cERROR(1,("Unknown RFC 1002 frame"));
  9895. + cifs_dump_mem(" Received Data: ", temp, length);
  9896. + cifs_reconnect(server);
  9897. + csocket = server->ssocket;
  9898. + continue;
  9899. + } else {
  9900. + if ((length != sizeof (struct smb_hdr) - 1)
  9901. + || (pdu_length >
  9902. + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
  9903. + || (pdu_length <
  9904. + sizeof (struct smb_hdr) - 1)
  9905. + ||
  9906. + (checkSMBhdr
  9907. + (smb_buffer, smb_buffer->Mid))) {
  9908. + cERROR(1,
  9909. + ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
  9910. + length, pdu_length));
  9911. + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
  9912. + /* could we fix this network corruption by finding next
  9913. + smb header (instead of killing the session) and
  9914. + restart reading from next valid SMB found? */
  9915. + cifs_reconnect(server);
  9916. + csocket = server->ssocket;
  9917. + continue;
  9918. + } else { /* length ok */
  9919. +
  9920. + length = 0;
  9921. + iov.iov_base = smb_buffer;
  9922. + iov.iov_len = pdu_length;
  9923. + for (total_read = 0;
  9924. + total_read < pdu_length;
  9925. + total_read += length) {
  9926. + length = sock_recvmsg(csocket, &smb_msg,
  9927. + pdu_length - total_read, 0);
  9928. + if (length == 0) {
  9929. + cERROR(1,
  9930. + ("Zero length receive when expecting %d ",
  9931. + pdu_length - total_read));
  9932. + cifs_reconnect(server);
  9933. + csocket = server->ssocket;
  9934. + continue;
  9935. + }
  9936. + }
  9937. + }
  9938. +
  9939. + dump_smb(smb_buffer, length);
  9940. + if (checkSMB
  9941. + (smb_buffer, smb_buffer->Mid, total_read)) {
  9942. + cERROR(1, ("Bad SMB Received "));
  9943. + continue;
  9944. + }
  9945. +
  9946. + task_to_wake = NULL;
  9947. + spin_lock(&GlobalMid_Lock);
  9948. + list_for_each(tmp, &server->pending_mid_q) {
  9949. + mid_entry = list_entry(tmp, struct
  9950. + mid_q_entry,
  9951. + qhead);
  9952. +
  9953. + if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
  9954. + cFYI(1,
  9955. + (" Mid 0x%x matched - waking up ",mid_entry->mid));
  9956. + task_to_wake = mid_entry->tsk;
  9957. + mid_entry->resp_buf =
  9958. + smb_buffer;
  9959. + mid_entry->midState =
  9960. + MID_RESPONSE_RECEIVED;
  9961. + }
  9962. + }
  9963. + spin_unlock(&GlobalMid_Lock);
  9964. + if (task_to_wake) {
  9965. + smb_buffer = NULL; /* will be freed by users thread after he is done */
  9966. + wake_up_process(task_to_wake);
  9967. + } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
  9968. + cERROR(1, ("No task to wake, unknown frame rcvd!"));
  9969. + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
  9970. + }
  9971. + }
  9972. + } else {
  9973. + cFYI(0,
  9974. + ("Frame less than four bytes received %d bytes long.",
  9975. + length));
  9976. + if (length > 0) {
  9977. + length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
  9978. + cFYI(1,
  9979. + (" with junk 0x%x in it ",
  9980. + *(__u32 *) smb_buffer));
  9981. + }
  9982. + }
  9983. + }
  9984. + spin_lock(&GlobalMid_Lock);
  9985. + server->tcpStatus = CifsExiting;
  9986. + server->tsk = NULL;
  9987. + atomic_set(&server->inFlight, 0);
  9988. + spin_unlock(&GlobalMid_Lock);
  9989. + /* Although there should not be any requests blocked on
  9990. + this queue it can not hurt to be paranoid and try to wake up requests
  9991. + that may haven been blocked when more than 50 at time were on the wire
  9992. + to the same server - they now will see the session is in exit state
  9993. + and get out of SendReceive. */
  9994. + wake_up_all(&server->request_q);
  9995. + /* give those requests time to exit */
  9996. + set_current_state(TASK_INTERRUPTIBLE);
  9997. + schedule_timeout(HZ/8);
  9998. +
  9999. + if(server->ssocket) {
  10000. + sock_release(csocket);
  10001. + server->ssocket = NULL;
  10002. + }
  10003. + set_fs(temp_fs);
  10004. + if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
  10005. + cifs_buf_release(smb_buffer);
  10006. +
  10007. + read_lock(&GlobalSMBSeslock);
  10008. + if (list_empty(&server->pending_mid_q)) {
  10009. + /* loop through server session structures attached to this and mark them dead */
  10010. + list_for_each(tmp, &GlobalSMBSessionList) {
  10011. + ses =
  10012. + list_entry(tmp, struct cifsSesInfo,
  10013. + cifsSessionList);
  10014. + if (ses->server == server) {
  10015. + ses->status = CifsExiting;
  10016. + ses->server = NULL;
  10017. + }
  10018. + }
  10019. + read_unlock(&GlobalSMBSeslock);
  10020. + } else {
  10021. + spin_lock(&GlobalMid_Lock);
  10022. + list_for_each(tmp, &server->pending_mid_q) {
  10023. + mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
  10024. + if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
  10025. + cFYI(1,
  10026. + (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
  10027. + task_to_wake = mid_entry->tsk;
  10028. + if(task_to_wake) {
  10029. + wake_up_process(task_to_wake);
  10030. + }
  10031. + }
  10032. + }
  10033. + spin_unlock(&GlobalMid_Lock);
  10034. + read_unlock(&GlobalSMBSeslock);
  10035. + set_current_state(TASK_INTERRUPTIBLE);
  10036. + /* 1/8th of sec is more than enough time for them to exit */
  10037. + schedule_timeout(HZ/8);
  10038. + }
  10039. +
  10040. + if (list_empty(&server->pending_mid_q)) {
  10041. + /* mpx threads have not exited yet give them
  10042. + at least the smb send timeout time for long ops */
  10043. + cFYI(1, ("Wait for exit from demultiplex thread"));
  10044. + set_current_state(TASK_INTERRUPTIBLE);
  10045. + schedule_timeout(46 * HZ);
  10046. + /* if threads still have not exited they are probably never
  10047. + coming home not much else we can do but free the memory */
  10048. + }
  10049. + kfree(server);
  10050. +
  10051. + set_current_state(TASK_INTERRUPTIBLE);
  10052. + schedule_timeout(HZ/4);
  10053. + return 0;
  10054. +}
  10055. +
  10056. +static void *
  10057. +cifs_kcalloc(size_t size, int type)
  10058. +{
  10059. + void *addr;
  10060. + addr = kmalloc(size, type);
  10061. + if (addr)
  10062. + memset(addr, 0, size);
  10063. + return addr;
  10064. +}
  10065. +
  10066. +static int
  10067. +cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
  10068. +{
  10069. + char *value;
  10070. + char *data;
  10071. + unsigned int temp_len, i, j;
  10072. + char separator[2];
  10073. +
  10074. + separator[0] = ',';
  10075. + separator[1] = 0;
  10076. +
  10077. + memset(vol->source_rfc1001_name,0x20,15);
  10078. + for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
  10079. + /* does not have to be a perfect mapping since the field is
  10080. + informational, only used for servers that do not support
  10081. + port 445 and it can be overridden at mount time */
  10082. + vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
  10083. + }
  10084. + vol->source_rfc1001_name[15] = 0;
  10085. +
  10086. + vol->linux_uid = current->uid; /* current->euid instead? */
  10087. + vol->linux_gid = current->gid;
  10088. + vol->dir_mode = S_IRWXUGO;
  10089. + /* 2767 perms indicate mandatory locking support */
  10090. + vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
  10091. +
  10092. + /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
  10093. + vol->rw = TRUE;
  10094. +
  10095. + if (!options)
  10096. + return 1;
  10097. +
  10098. + if(strncmp(options,"sep=",4) == 0) {
  10099. + if(options[4] != 0) {
  10100. + separator[0] = options[4];
  10101. + options += 5;
  10102. + } else {
  10103. + cFYI(1,("Null separator not allowed"));
  10104. + }
  10105. + }
  10106. +
  10107. + while ((data = strsep(&options, separator)) != NULL) {
  10108. + if (!*data)
  10109. + continue;
  10110. + if ((value = strchr(data, '=')) != NULL)
  10111. + *value++ = '\0';
  10112. + if (strnicmp(data, "user", 4) == 0) {
  10113. + if (!value || !*value) {
  10114. + printk(KERN_WARNING
  10115. + "CIFS: invalid or missing username\n");
  10116. + return 1; /* needs_arg; */
  10117. + }
  10118. + if (strnlen(value, 200) < 200) {
  10119. + vol->username = value;
  10120. + } else {
  10121. + printk(KERN_WARNING "CIFS: username too long\n");
  10122. + return 1;
  10123. + }
  10124. + } else if (strnicmp(data, "pass", 4) == 0) {
  10125. + if (!value || !*value) {
  10126. + vol->password = NULL;
  10127. + continue;
  10128. + }
  10129. + temp_len = strlen(value);
  10130. + /* removed password length check, NTLM passwords
  10131. + can be arbitrarily long */
  10132. +
  10133. + /* if comma in password, the string will be
  10134. + prematurely null terminated. Commas in password are
  10135. + specified across the cifs mount interface by a double
  10136. + comma ie ,, and a comma used as in other cases ie ','
  10137. + as a parameter delimiter/separator is single and due
  10138. + to the strsep above is temporarily zeroed. */
  10139. +
  10140. + /* NB: password legally can have multiple commas and
  10141. + the only illegal character in a password is null */
  10142. +
  10143. + if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
  10144. + /* reinsert comma */
  10145. + value[temp_len] = separator[0];
  10146. + temp_len+=2; /* move after the second comma */
  10147. + while(value[temp_len] != 0) {
  10148. + if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
  10149. + /* single comma indicating start of next parm */
  10150. + break;
  10151. + }
  10152. + temp_len++;
  10153. + }
  10154. + if(value[temp_len] == 0) {
  10155. + options = NULL;
  10156. + } else {
  10157. + value[temp_len] = 0;
  10158. + /* move options to point to start of next parm */
  10159. + options = value + temp_len + 1;
  10160. + }
  10161. + /* go from value to (value + temp_len) condensing double commas to singles */
  10162. + vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
  10163. + for(i=0,j=0;i<temp_len;i++,j++) {
  10164. + vol->password[j] = value[i];
  10165. + if(value[i] == separator[0] && value[i+1] == separator[0]) {
  10166. + /* skip second comma */
  10167. + i++;
  10168. + }
  10169. + }
  10170. + /* value[temp_len] is zeroed above so
  10171. + vol->password[temp_len] guaranteed to be null */
  10172. + } else {
  10173. + vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
  10174. + strcpy(vol->password, value);
  10175. + }
  10176. + } else if (strnicmp(data, "ip", 2) == 0) {
  10177. + if (!value || !*value) {
  10178. + vol->UNCip = NULL;
  10179. + } else if (strnlen(value, 35) < 35) {
  10180. + vol->UNCip = value;
  10181. + } else {
  10182. + printk(KERN_WARNING "CIFS: ip address too long\n");
  10183. + return 1;
  10184. + }
  10185. + } else if ((strnicmp(data, "unc", 3) == 0)
  10186. + || (strnicmp(data, "target", 6) == 0)
  10187. + || (strnicmp(data, "path", 4) == 0)) {
  10188. + if (!value || !*value) {
  10189. + printk(KERN_WARNING
  10190. + "CIFS: invalid path to network resource\n");
  10191. + return 1; /* needs_arg; */
  10192. + }
  10193. + if ((temp_len = strnlen(value, 300)) < 300) {
  10194. + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
  10195. + if(vol->UNC == NULL)
  10196. + return 1;
  10197. + strcpy(vol->UNC,value);
  10198. + if (strncmp(vol->UNC, "//", 2) == 0) {
  10199. + vol->UNC[0] = '\\';
  10200. + vol->UNC[1] = '\\';
  10201. + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
  10202. + printk(KERN_WARNING
  10203. + "CIFS: UNC Path does not begin with // or \\\\ \n");
  10204. + return 1;
  10205. + }
  10206. + } else {
  10207. + printk(KERN_WARNING "CIFS: UNC name too long\n");
  10208. + return 1;
  10209. + }
  10210. + } else if ((strnicmp(data, "domain", 3) == 0)
  10211. + || (strnicmp(data, "workgroup", 5) == 0)) {
  10212. + if (!value || !*value) {
  10213. + printk(KERN_WARNING "CIFS: invalid domain name\n");
  10214. + return 1; /* needs_arg; */
  10215. + }
  10216. + /* BB are there cases in which a comma can be valid in
  10217. + a domain name and need special handling? */
  10218. + if (strnlen(value, 65) < 65) {
  10219. + vol->domainname = value;
  10220. + cFYI(1, ("Domain name set"));
  10221. + } else {
  10222. + printk(KERN_WARNING "CIFS: domain name too long\n");
  10223. + return 1;
  10224. + }
  10225. + } else if (strnicmp(data, "iocharset", 9) == 0) {
  10226. + if (!value || !*value) {
  10227. + printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
  10228. + return 1; /* needs_arg; */
  10229. + }
  10230. + if (strnlen(value, 65) < 65) {
  10231. + if(strnicmp(value,"default",7))
  10232. + vol->iocharset = value;
  10233. + /* if iocharset not set load_nls_default used by caller */
  10234. + cFYI(1, ("iocharset set to %s",value));
  10235. + } else {
  10236. + printk(KERN_WARNING "CIFS: iocharset name too long.\n");
  10237. + return 1;
  10238. + }
  10239. + } else if (strnicmp(data, "uid", 3) == 0) {
  10240. + if (value && *value) {
  10241. + vol->linux_uid =
  10242. + simple_strtoul(value, &value, 0);
  10243. + }
  10244. + } else if (strnicmp(data, "gid", 3) == 0) {
  10245. + if (value && *value) {
  10246. + vol->linux_gid =
  10247. + simple_strtoul(value, &value, 0);
  10248. + }
  10249. + } else if (strnicmp(data, "file_mode", 4) == 0) {
  10250. + if (value && *value) {
  10251. + vol->file_mode =
  10252. + simple_strtoul(value, &value, 0);
  10253. + }
  10254. + } else if (strnicmp(data, "dir_mode", 3) == 0) {
  10255. + if (value && *value) {
  10256. + vol->dir_mode =
  10257. + simple_strtoul(value, &value, 0);
  10258. + }
  10259. + } else if (strnicmp(data, "port", 4) == 0) {
  10260. + if (value && *value) {
  10261. + vol->port =
  10262. + simple_strtoul(value, &value, 0);
  10263. + }
  10264. + } else if (strnicmp(data, "rsize", 5) == 0) {
  10265. + if (value && *value) {
  10266. + vol->rsize =
  10267. + simple_strtoul(value, &value, 0);
  10268. + }
  10269. + } else if (strnicmp(data, "wsize", 5) == 0) {
  10270. + if (value && *value) {
  10271. + vol->wsize =
  10272. + simple_strtoul(value, &value, 0);
  10273. + }
  10274. + } else if (strnicmp(data, "sockopt", 5) == 0) {
  10275. + if (value && *value) {
  10276. + vol->sockopt =
  10277. + simple_strtoul(value, &value, 0);
  10278. + }
  10279. + } else if (strnicmp(data, "netbiosname", 4) == 0) {
  10280. + if (!value || !*value || (*value == ' ')) {
  10281. + cFYI(1,("invalid (empty) netbiosname specified"));
  10282. + } else {
  10283. + memset(vol->source_rfc1001_name,0x20,15);
  10284. + for(i=0;i<15;i++) {
  10285. + /* BB are there cases in which a comma can be
  10286. + valid in this workstation netbios name (and need
  10287. + special handling)? */
  10288. +
  10289. + /* We do not uppercase netbiosname for user */
  10290. + if (value[i]==0)
  10291. + break;
  10292. + else
  10293. + vol->source_rfc1001_name[i] = value[i];
  10294. + }
  10295. + /* The string has 16th byte zero still from
  10296. + set at top of the function */
  10297. + if((i==15) && (value[i] != 0))
  10298. + printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
  10299. + }
  10300. + } else if (strnicmp(data, "credentials", 4) == 0) {
  10301. + /* ignore */
  10302. + } else if (strnicmp(data, "version", 3) == 0) {
  10303. + /* ignore */
  10304. + } else if (strnicmp(data, "rw", 2) == 0) {
  10305. + vol->rw = TRUE;
  10306. + } else if ((strnicmp(data, "suid", 4) == 0) ||
  10307. + (strnicmp(data, "nosuid", 6) == 0) ||
  10308. + (strnicmp(data, "exec", 4) == 0) ||
  10309. + (strnicmp(data, "noexec", 6) == 0) ||
  10310. + (strnicmp(data, "nodev", 5) == 0) ||
  10311. + (strnicmp(data, "noauto", 6) == 0) ||
  10312. + (strnicmp(data, "dev", 3) == 0)) {
  10313. + /* The mount tool or mount.cifs helper (if present)
  10314. + uses these opts to set flags, and the flags are read
  10315. + by the kernel vfs layer before we get here (ie
  10316. + before read super) so there is no point trying to
  10317. + parse these options again and set anything and it
  10318. + is ok to just ignore them */
  10319. + continue;
  10320. + } else if (strnicmp(data, "ro", 2) == 0) {
  10321. + vol->rw = FALSE;
  10322. + } else if (strnicmp(data, "hard", 4) == 0) {
  10323. + vol->retry = 1;
  10324. + } else if (strnicmp(data, "soft", 4) == 0) {
  10325. + vol->retry = 0;
  10326. + } else if (strnicmp(data, "nohard", 6) == 0) {
  10327. + vol->retry = 0;
  10328. + } else if (strnicmp(data, "nosoft", 6) == 0) {
  10329. + vol->retry = 1;
  10330. + } else if (strnicmp(data, "nointr", 6) == 0) {
  10331. + vol->intr = 0;
  10332. + } else if (strnicmp(data, "intr", 4) == 0) {
  10333. + vol->intr = 1;
  10334. + } else if (strnicmp(data, "noac", 4) == 0) {
  10335. + printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
  10336. + } else
  10337. + printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
  10338. + }
  10339. + if (vol->UNC == NULL) {
  10340. + if(devname == NULL) {
  10341. + printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
  10342. + return 1;
  10343. + }
  10344. + if ((temp_len = strnlen(devname, 300)) < 300) {
  10345. + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
  10346. + if(vol->UNC == NULL)
  10347. + return 1;
  10348. + strcpy(vol->UNC,devname);
  10349. + if (strncmp(vol->UNC, "//", 2) == 0) {
  10350. + vol->UNC[0] = '\\';
  10351. + vol->UNC[1] = '\\';
  10352. + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
  10353. + printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
  10354. + return 1;
  10355. + }
  10356. + } else {
  10357. + printk(KERN_WARNING "CIFS: UNC name too long\n");
  10358. + return 1;
  10359. + }
  10360. + }
  10361. + if(vol->UNCip == 0)
  10362. + vol->UNCip = &vol->UNC[2];
  10363. +
  10364. + return 0;
  10365. +}
  10366. +
  10367. +static struct cifsSesInfo *
  10368. +cifs_find_tcp_session(__u32 new_target_ip_addr,
  10369. + char *userName, struct TCP_Server_Info **psrvTcp)
  10370. +{
  10371. + struct list_head *tmp;
  10372. + struct cifsSesInfo *ses;
  10373. +
  10374. + *psrvTcp = NULL;
  10375. + read_lock(&GlobalSMBSeslock);
  10376. + list_for_each(tmp, &GlobalSMBSessionList) {
  10377. + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
  10378. + if (ses->server) {
  10379. + if (ses->server->addr.sockAddr.sin_addr.s_addr ==
  10380. + new_target_ip_addr) {
  10381. + /* BB lock server and tcp session and increment use count here?? */
  10382. + *psrvTcp = ses->server; /* found a match on the TCP session */
  10383. + /* BB check if reconnection needed */
  10384. + if (strncmp
  10385. + (ses->userName, userName,
  10386. + MAX_USERNAME_SIZE) == 0){
  10387. + read_unlock(&GlobalSMBSeslock);
  10388. + return ses; /* found exact match on both tcp and SMB sessions */
  10389. + }
  10390. + }
  10391. + }
  10392. + /* else tcp and smb sessions need reconnection */
  10393. + }
  10394. + read_unlock(&GlobalSMBSeslock);
  10395. + return NULL;
  10396. +}
  10397. +
  10398. +static struct cifsTconInfo *
  10399. +find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
  10400. +{
  10401. + struct list_head *tmp;
  10402. + struct cifsTconInfo *tcon;
  10403. +
  10404. + read_lock(&GlobalSMBSeslock);
  10405. + list_for_each(tmp, &GlobalTreeConnectionList) {
  10406. + cFYI(1, ("Next tcon - "));
  10407. + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
  10408. + if (tcon->ses) {
  10409. + if (tcon->ses->server) {
  10410. + cFYI(1,
  10411. + (" old ip addr: %x == new ip %x ?",
  10412. + tcon->ses->server->addr.sockAddr.sin_addr.
  10413. + s_addr, new_target_ip_addr));
  10414. + if (tcon->ses->server->addr.sockAddr.sin_addr.
  10415. + s_addr == new_target_ip_addr) {
  10416. + /* BB lock tcon and server and tcp session and increment use count here? */
  10417. + /* found a match on the TCP session */
  10418. + /* BB check if reconnection needed */
  10419. + cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
  10420. + tcon->treeName, uncName));
  10421. + if (strncmp
  10422. + (tcon->treeName, uncName,
  10423. + MAX_TREE_SIZE) == 0) {
  10424. + cFYI(1,
  10425. + ("Matched UNC, old user: %s == new: %s ?",
  10426. + tcon->treeName, uncName));
  10427. + if (strncmp
  10428. + (tcon->ses->userName,
  10429. + userName,
  10430. + MAX_USERNAME_SIZE) == 0) {
  10431. + read_unlock(&GlobalSMBSeslock);
  10432. + return tcon;/* also matched user (smb session)*/
  10433. + }
  10434. + }
  10435. + }
  10436. + }
  10437. + }
  10438. + }
  10439. + read_unlock(&GlobalSMBSeslock);
  10440. + return NULL;
  10441. +}
  10442. +
  10443. +int
  10444. +connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
  10445. + const char *old_path, const struct nls_table *nls_codepage)
  10446. +{
  10447. + unsigned char *referrals = NULL;
  10448. + unsigned int num_referrals;
  10449. + int rc = 0;
  10450. +
  10451. + rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
  10452. + &num_referrals, &referrals);
  10453. +
  10454. + /* BB Add in code to: if valid refrl, if not ip address contact
  10455. + the helper that resolves tcp names, mount to it, try to
  10456. + tcon to it unmount it if fail */
  10457. +
  10458. + if(referrals)
  10459. + kfree(referrals);
  10460. +
  10461. + return rc;
  10462. +}
  10463. +
  10464. +int
  10465. +get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
  10466. + const char *old_path, const struct nls_table *nls_codepage,
  10467. + unsigned int *pnum_referrals, unsigned char ** preferrals)
  10468. +{
  10469. + char *temp_unc;
  10470. + int rc = 0;
  10471. +
  10472. + *pnum_referrals = 0;
  10473. +
  10474. + if (pSesInfo->ipc_tid == 0) {
  10475. + temp_unc = kmalloc(2 /* for slashes */ +
  10476. + strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
  10477. + + 1 + 4 /* slash IPC$ */ + 2,
  10478. + GFP_KERNEL);
  10479. + if (temp_unc == NULL)
  10480. + return -ENOMEM;
  10481. + temp_unc[0] = '\\';
  10482. + temp_unc[1] = '\\';
  10483. + strcpy(temp_unc + 2, pSesInfo->serverName);
  10484. + strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
  10485. + rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
  10486. + cFYI(1,
  10487. + ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
  10488. + kfree(temp_unc);
  10489. + }
  10490. + if (rc == 0)
  10491. + rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
  10492. + pnum_referrals, nls_codepage);
  10493. +
  10494. + return rc;
  10495. +}
  10496. +
  10497. +/* See RFC1001 section 14 on representation of Netbios names */
  10498. +static void rfc1002mangle(char * target,char * source, unsigned int length)
  10499. +{
  10500. + unsigned int i,j;
  10501. +
  10502. + for(i=0,j=0;i<(length);i++) {
  10503. + /* mask a nibble at a time and encode */
  10504. + target[j] = 'A' + (0x0F & (source[i] >> 4));
  10505. + target[j+1] = 'A' + (0x0F & source[i]);
  10506. + j+=2;
  10507. + }
  10508. +
  10509. +}
  10510. +
  10511. +
  10512. +static int
  10513. +ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
  10514. + char * netbios_name)
  10515. +{
  10516. + int rc = 0;
  10517. + int connected = 0;
  10518. + unsigned short int orig_port = 0;
  10519. +
  10520. + if(*csocket == NULL) {
  10521. + rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
  10522. + if (rc < 0) {
  10523. + cERROR(1, ("Error %d creating socket",rc));
  10524. + *csocket = NULL;
  10525. + return rc;
  10526. + } else {
  10527. + /* BB other socket options to set KEEPALIVE, NODELAY? */
  10528. + cFYI(1,("Socket created"));
  10529. + (*csocket)->sk->allocation = GFP_NOFS;
  10530. + }
  10531. + }
  10532. +
  10533. + psin_server->sin_family = AF_INET;
  10534. + if(psin_server->sin_port) { /* user overrode default port */
  10535. + rc = (*csocket)->ops->connect(*csocket,
  10536. + (struct sockaddr *) psin_server,
  10537. + sizeof (struct sockaddr_in),0);
  10538. + if (rc >= 0)
  10539. + connected = 1;
  10540. + }
  10541. +
  10542. + if(!connected) {
  10543. + /* save original port so we can retry user specified port
  10544. + later if fall back ports fail this time */
  10545. + orig_port = psin_server->sin_port;
  10546. +
  10547. + /* do not retry on the same port we just failed on */
  10548. + if(psin_server->sin_port != htons(CIFS_PORT)) {
  10549. + psin_server->sin_port = htons(CIFS_PORT);
  10550. +
  10551. + rc = (*csocket)->ops->connect(*csocket,
  10552. + (struct sockaddr *) psin_server,
  10553. + sizeof (struct sockaddr_in),0);
  10554. + if (rc >= 0)
  10555. + connected = 1;
  10556. + }
  10557. + }
  10558. + if (!connected) {
  10559. + psin_server->sin_port = htons(RFC1001_PORT);
  10560. + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
  10561. + psin_server, sizeof (struct sockaddr_in),0);
  10562. + if (rc >= 0)
  10563. + connected = 1;
  10564. + }
  10565. +
  10566. + /* give up here - unless we want to retry on different
  10567. + protocol families some day */
  10568. + if (!connected) {
  10569. + if(orig_port)
  10570. + psin_server->sin_port = orig_port;
  10571. + cFYI(1,("Error %d connecting to server via ipv4",rc));
  10572. + sock_release(*csocket);
  10573. + *csocket = NULL;
  10574. + return rc;
  10575. + }
  10576. + /* Eventually check for other socket options to change from
  10577. + the default. sock_setsockopt not used because it expects
  10578. + user space buffer */
  10579. + (*csocket)->sk->rcvtimeo = 7 * HZ;
  10580. +
  10581. + /* send RFC1001 sessinit */
  10582. +
  10583. + if(psin_server->sin_port == htons(139)) {
  10584. + /* some servers require RFC1001 sessinit before sending
  10585. + negprot - BB check reconnection in case where second
  10586. + sessinit is sent but no second negprot */
  10587. + struct rfc1002_session_packet * ses_init_buf;
  10588. + struct smb_hdr * smb_buf;
  10589. + ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
  10590. + if(ses_init_buf) {
  10591. + ses_init_buf->trailer.session_req.called_len = 32;
  10592. + rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
  10593. + DEFAULT_CIFS_CALLED_NAME,16);
  10594. + ses_init_buf->trailer.session_req.calling_len = 32;
  10595. + /* calling name ends in null (byte 16) from old smb
  10596. + convention. */
  10597. + if(netbios_name && (netbios_name[0] !=0)) {
  10598. + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
  10599. + netbios_name,16);
  10600. + } else {
  10601. + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
  10602. + "LINUX_CIFS_CLNT",16);
  10603. + }
  10604. + ses_init_buf->trailer.session_req.scope1 = 0;
  10605. + ses_init_buf->trailer.session_req.scope2 = 0;
  10606. + smb_buf = (struct smb_hdr *)ses_init_buf;
  10607. + /* sizeof RFC1002_SESSION_REQUEST with no scope */
  10608. + smb_buf->smb_buf_length = 0x81000044;
  10609. + rc = smb_send(*csocket, smb_buf, 0x44,
  10610. + (struct sockaddr *)psin_server);
  10611. + kfree(ses_init_buf);
  10612. + }
  10613. + /* else the negprot may still work without this
  10614. + even though malloc failed */
  10615. +
  10616. + }
  10617. +
  10618. + return rc;
  10619. +}
  10620. +
  10621. +static int
  10622. +ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
  10623. +{
  10624. + int rc = 0;
  10625. + int connected = 0;
  10626. +
  10627. + if(*csocket == NULL) {
  10628. + rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
  10629. + if (rc < 0) {
  10630. + cERROR(1, ("Error %d creating ipv6 socket",rc));
  10631. + *csocket = NULL;
  10632. + return rc;
  10633. + } else {
  10634. + /* BB other socket options to set KEEPALIVE, NODELAY? */
  10635. + cFYI(1,("ipv6 Socket created"));
  10636. + (*csocket)->sk->allocation = GFP_NOFS;
  10637. + }
  10638. + }
  10639. +
  10640. + psin_server->sin6_family = AF_INET6;
  10641. +
  10642. + if(psin_server->sin6_port) { /* user overrode default port */
  10643. + rc = (*csocket)->ops->connect(*csocket,
  10644. + (struct sockaddr *) psin_server,
  10645. + sizeof (struct sockaddr_in6),0);
  10646. + if (rc >= 0)
  10647. + connected = 1;
  10648. + }
  10649. +
  10650. + if(!connected) {
  10651. + /* do not retry on the same port we just failed on */
  10652. + if(psin_server->sin6_port != htons(CIFS_PORT)) {
  10653. + psin_server->sin6_port = htons(CIFS_PORT);
  10654. +
  10655. + rc = (*csocket)->ops->connect(*csocket,
  10656. + (struct sockaddr *) psin_server,
  10657. + sizeof (struct sockaddr_in6),0);
  10658. + if (rc >= 0)
  10659. + connected = 1;
  10660. + }
  10661. + }
  10662. + if (!connected) {
  10663. + psin_server->sin6_port = htons(RFC1001_PORT);
  10664. + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
  10665. + psin_server, sizeof (struct sockaddr_in6),0);
  10666. + if (rc >= 0)
  10667. + connected = 1;
  10668. + }
  10669. +
  10670. + /* give up here - unless we want to retry on different
  10671. + protocol families some day */
  10672. + if (!connected) {
  10673. + cFYI(1,("Error %d connecting to server via ipv6",rc));
  10674. + sock_release(*csocket);
  10675. + *csocket = NULL;
  10676. + return rc;
  10677. + }
  10678. + /* Eventually check for other socket options to change from
  10679. + the default. sock_setsockopt not used because it expects
  10680. + user space buffer */
  10681. + (*csocket)->sk->rcvtimeo = 7 * HZ;
  10682. +
  10683. + return rc;
  10684. +}
  10685. +
  10686. +int
  10687. +cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
  10688. + char *mount_data, const char *devname)
  10689. +{
  10690. + int rc = 0;
  10691. + int xid;
  10692. + struct socket *csocket = NULL;
  10693. + struct sockaddr_in sin_server;
  10694. + struct sockaddr_in6 sin_server6;
  10695. + struct smb_vol volume_info;
  10696. + struct cifsSesInfo *pSesInfo = NULL;
  10697. + struct cifsSesInfo *existingCifsSes = NULL;
  10698. + struct cifsTconInfo *tcon = NULL;
  10699. + struct TCP_Server_Info *srvTcp = NULL;
  10700. +
  10701. + xid = GetXid();
  10702. +
  10703. + cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
  10704. +
  10705. + memset(&volume_info,0,sizeof(struct smb_vol));
  10706. + if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
  10707. + if(volume_info.UNC)
  10708. + kfree(volume_info.UNC);
  10709. + if(volume_info.password)
  10710. + kfree(volume_info.password);
  10711. + FreeXid(xid);
  10712. + return -EINVAL;
  10713. + }
  10714. +
  10715. + if (volume_info.username) {
  10716. + cFYI(1, ("Username: %s ", volume_info.username));
  10717. +
  10718. + } else {
  10719. + cifserror("No username specified ");
  10720. + /* In userspace mount helper we can get user name from alternate
  10721. + locations such as env variables and files on disk */
  10722. + if(volume_info.UNC)
  10723. + kfree(volume_info.UNC);
  10724. + if(volume_info.password)
  10725. + kfree(volume_info.password);
  10726. + FreeXid(xid);
  10727. + return -EINVAL;
  10728. + }
  10729. +
  10730. + if (volume_info.UNCip && volume_info.UNC) {
  10731. + rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
  10732. +
  10733. + if(rc == 0) {
  10734. + /* not ipv4 address, try ipv6 */
  10735. + rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
  10736. + }
  10737. +
  10738. + if(rc != 1) {
  10739. + /* we failed translating address */
  10740. + if(volume_info.UNC)
  10741. + kfree(volume_info.UNC);
  10742. + if(volume_info.password)
  10743. + kfree(volume_info.password);
  10744. + FreeXid(xid);
  10745. + return -EINVAL;
  10746. + }
  10747. +
  10748. + cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
  10749. + /* success */
  10750. + rc = 0;
  10751. + } else if (volume_info.UNCip){
  10752. + /* BB using ip addr as server name connect to the DFS root below */
  10753. + cERROR(1,("Connecting to DFS root not implemented yet"));
  10754. + if(volume_info.UNC)
  10755. + kfree(volume_info.UNC);
  10756. + if(volume_info.password)
  10757. + kfree(volume_info.password);
  10758. + FreeXid(xid);
  10759. + return -EINVAL;
  10760. + } else /* which servers DFS root would we conect to */ {
  10761. + cERROR(1,
  10762. + ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
  10763. + if(volume_info.UNC)
  10764. + kfree(volume_info.UNC);
  10765. + if(volume_info.password)
  10766. + kfree(volume_info.password);
  10767. + FreeXid(xid);
  10768. + return -EINVAL;
  10769. + }
  10770. +
  10771. + /* this is needed for ASCII cp to Unicode converts */
  10772. + if(volume_info.iocharset == NULL) {
  10773. + cifs_sb->local_nls = load_nls_default();
  10774. + /* load_nls_default can not return null */
  10775. + } else {
  10776. + cifs_sb->local_nls = load_nls(volume_info.iocharset);
  10777. + if(cifs_sb->local_nls == NULL) {
  10778. + cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
  10779. + if(volume_info.UNC)
  10780. + kfree(volume_info.UNC);
  10781. + if(volume_info.password)
  10782. + kfree(volume_info.password);
  10783. + FreeXid(xid);
  10784. + return -ELIBACC;
  10785. + }
  10786. + }
  10787. +
  10788. + existingCifsSes =
  10789. + cifs_find_tcp_session(sin_server.sin_addr.s_addr,
  10790. + volume_info.username, &srvTcp);
  10791. + if (srvTcp) {
  10792. + cFYI(1, ("Existing tcp session with server found "));
  10793. + } else { /* create socket */
  10794. + if(volume_info.port)
  10795. + sin_server.sin_port = htons(volume_info.port);
  10796. + else
  10797. + sin_server.sin_port = 0;
  10798. + rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
  10799. + if (rc < 0) {
  10800. + cERROR(1,
  10801. + ("Error connecting to IPv4 socket. Aborting operation"));
  10802. + if(csocket != NULL)
  10803. + sock_release(csocket);
  10804. + if(volume_info.UNC)
  10805. + kfree(volume_info.UNC);
  10806. + if(volume_info.password)
  10807. + kfree(volume_info.password);
  10808. + FreeXid(xid);
  10809. + return rc;
  10810. + }
  10811. +
  10812. + srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
  10813. + if (srvTcp == NULL) {
  10814. + rc = -ENOMEM;
  10815. + sock_release(csocket);
  10816. + if(volume_info.UNC)
  10817. + kfree(volume_info.UNC);
  10818. + if(volume_info.password)
  10819. + kfree(volume_info.password);
  10820. + FreeXid(xid);
  10821. + return rc;
  10822. + } else {
  10823. + memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
  10824. + memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
  10825. + atomic_set(&srvTcp->inFlight,0);
  10826. + /* BB Add code for ipv6 case too */
  10827. + srvTcp->ssocket = csocket;
  10828. + srvTcp->protocolType = IPV4;
  10829. + init_waitqueue_head(&srvTcp->response_q);
  10830. + init_waitqueue_head(&srvTcp->request_q);
  10831. + INIT_LIST_HEAD(&srvTcp->pending_mid_q);
  10832. + /* at this point we are the only ones with the pointer
  10833. + to the struct since the kernel thread not created yet
  10834. + so no need to spinlock this init of tcpStatus */
  10835. + srvTcp->tcpStatus = CifsNew;
  10836. + init_MUTEX(&srvTcp->tcpSem);
  10837. + kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
  10838. + CLONE_FS | CLONE_FILES | CLONE_VM);
  10839. + memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
  10840. + }
  10841. + }
  10842. +
  10843. + if (existingCifsSes) {
  10844. + pSesInfo = existingCifsSes;
  10845. + cFYI(1, ("Existing smb sess found "));
  10846. + if(volume_info.password)
  10847. + kfree(volume_info.password);
  10848. + /* volume_info.UNC freed at end of function */
  10849. + } else if (!rc) {
  10850. + cFYI(1, ("Existing smb sess not found "));
  10851. + pSesInfo = sesInfoAlloc();
  10852. + if (pSesInfo == NULL)
  10853. + rc = -ENOMEM;
  10854. + else {
  10855. + pSesInfo->server = srvTcp;
  10856. + sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
  10857. + NIPQUAD(sin_server.sin_addr.s_addr));
  10858. + }
  10859. +
  10860. + if (!rc){
  10861. + /* volume_info.password freed at unmount */
  10862. + if (volume_info.password)
  10863. + pSesInfo->password = volume_info.password;
  10864. + if (volume_info.username)
  10865. + strncpy(pSesInfo->userName,
  10866. + volume_info.username,MAX_USERNAME_SIZE);
  10867. + if (volume_info.domainname)
  10868. + strncpy(pSesInfo->domainName,
  10869. + volume_info.domainname,MAX_USERNAME_SIZE);
  10870. + pSesInfo->linux_uid = volume_info.linux_uid;
  10871. + down(&pSesInfo->sesSem);
  10872. + rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
  10873. + up(&pSesInfo->sesSem);
  10874. + if(!rc)
  10875. + atomic_inc(&srvTcp->socketUseCount);
  10876. + } else
  10877. + if(volume_info.password)
  10878. + kfree(volume_info.password);
  10879. + }
  10880. +
  10881. + /* search for existing tcon to this server share */
  10882. + if (!rc) {
  10883. + if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
  10884. + cifs_sb->rsize = volume_info.rsize;
  10885. + else
  10886. + cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
  10887. + if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
  10888. + cifs_sb->wsize = volume_info.wsize;
  10889. + else
  10890. + cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
  10891. + if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
  10892. + cifs_sb->rsize = PAGE_CACHE_SIZE;
  10893. + cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
  10894. + }
  10895. + cifs_sb->mnt_uid = volume_info.linux_uid;
  10896. + cifs_sb->mnt_gid = volume_info.linux_gid;
  10897. + cifs_sb->mnt_file_mode = volume_info.file_mode;
  10898. + cifs_sb->mnt_dir_mode = volume_info.dir_mode;
  10899. + cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
  10900. + tcon =
  10901. + find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
  10902. + volume_info.username);
  10903. + if (tcon) {
  10904. + cFYI(1, ("Found match on UNC path "));
  10905. + /* we can have only one retry value for a connection
  10906. + to a share so for resources mounted more than once
  10907. + to the same server share the last value passed in
  10908. + for the retry flag is used */
  10909. + tcon->retry = volume_info.retry;
  10910. + } else {
  10911. + tcon = tconInfoAlloc();
  10912. + if (tcon == NULL)
  10913. + rc = -ENOMEM;
  10914. + else {
  10915. + /* check for null share name ie connect to dfs root */
  10916. +
  10917. + /* BB check if this works for exactly length three strings */
  10918. + if ((strchr(volume_info.UNC + 3, '\\') == NULL)
  10919. + && (strchr(volume_info.UNC + 3, '/') ==
  10920. + NULL)) {
  10921. + rc = connect_to_dfs_path(xid,
  10922. + pSesInfo,
  10923. + "",
  10924. + cifs_sb->
  10925. + local_nls);
  10926. + if(volume_info.UNC)
  10927. + kfree(volume_info.UNC);
  10928. + FreeXid(xid);
  10929. + return -ENODEV;
  10930. + } else {
  10931. + rc = CIFSTCon(xid, pSesInfo,
  10932. + volume_info.UNC,
  10933. + tcon, cifs_sb->local_nls);
  10934. + cFYI(1, ("CIFS Tcon rc = %d", rc));
  10935. + }
  10936. + if (!rc) {
  10937. + atomic_inc(&pSesInfo->inUse);
  10938. + tcon->retry = volume_info.retry;
  10939. + }
  10940. + }
  10941. + }
  10942. + }
  10943. + if(pSesInfo) {
  10944. + if (pSesInfo->capabilities & CAP_LARGE_FILES) {
  10945. + sb->s_maxbytes = (u64) 1 << 63;
  10946. + } else
  10947. + sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
  10948. + }
  10949. +
  10950. +/* on error free sesinfo and tcon struct if needed */
  10951. + if (rc) {
  10952. + /* if session setup failed, use count is zero but
  10953. + we still need to free cifsd thread */
  10954. + if(atomic_read(&srvTcp->socketUseCount) == 0) {
  10955. + spin_lock(&GlobalMid_Lock);
  10956. + srvTcp->tcpStatus = CifsExiting;
  10957. + spin_unlock(&GlobalMid_Lock);
  10958. + if(srvTcp->tsk)
  10959. + send_sig(SIGKILL,srvTcp->tsk,1);
  10960. + }
  10961. + /* If find_unc succeeded then rc == 0 so we can not end */
  10962. + if (tcon) /* up accidently freeing someone elses tcon struct */
  10963. + tconInfoFree(tcon);
  10964. + if (existingCifsSes == 0) {
  10965. + if (pSesInfo) {
  10966. + if ((pSesInfo->server) &&
  10967. + (pSesInfo->status == CifsGood)) {
  10968. + int temp_rc;
  10969. + temp_rc = CIFSSMBLogoff(xid, pSesInfo);
  10970. + /* if the socketUseCount is now zero */
  10971. + if((temp_rc == -ESHUTDOWN) &&
  10972. + (pSesInfo->server->tsk))
  10973. + send_sig(SIGKILL,pSesInfo->server->tsk,1);
  10974. + } else
  10975. + cFYI(1, ("No session or bad tcon"));
  10976. + sesInfoFree(pSesInfo);
  10977. + /* pSesInfo = NULL; */
  10978. + }
  10979. + }
  10980. + } else {
  10981. + atomic_inc(&tcon->useCount);
  10982. + cifs_sb->tcon = tcon;
  10983. + tcon->ses = pSesInfo;
  10984. +
  10985. + /* do not care if following two calls succeed - informational only */
  10986. + CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
  10987. + CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
  10988. + if (tcon->ses->capabilities & CAP_UNIX)
  10989. + CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
  10990. + }
  10991. +
  10992. + /* volume_info.password is freed above when existing session found
  10993. + (in which case it is not needed anymore) but when new sesion is created
  10994. + the password ptr is put in the new session structure (in which case the
  10995. + password will be freed at unmount time) */
  10996. + if(volume_info.UNC)
  10997. + kfree(volume_info.UNC);
  10998. + FreeXid(xid);
  10999. + return rc;
  11000. +}
  11001. +
  11002. +static int
  11003. +CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
  11004. + char session_key[CIFS_SESSION_KEY_SIZE],
  11005. + const struct nls_table *nls_codepage)
  11006. +{
  11007. + struct smb_hdr *smb_buffer;
  11008. + struct smb_hdr *smb_buffer_response;
  11009. + SESSION_SETUP_ANDX *pSMB;
  11010. + SESSION_SETUP_ANDX *pSMBr;
  11011. + char *bcc_ptr;
  11012. + char *user = ses->userName;
  11013. + char *domain = ses->domainName;
  11014. + int rc = 0;
  11015. + int remaining_words = 0;
  11016. + int bytes_returned = 0;
  11017. + int len;
  11018. +
  11019. + cFYI(1, ("In sesssetup "));
  11020. +
  11021. + smb_buffer = cifs_buf_get();
  11022. + if (smb_buffer == 0) {
  11023. + return -ENOMEM;
  11024. + }
  11025. + smb_buffer_response = smb_buffer;
  11026. + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
  11027. +
  11028. + /* send SMBsessionSetup here */
  11029. + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
  11030. + NULL /* no tCon exists yet */ , 13 /* wct */ );
  11031. +
  11032. + pSMB->req_no_secext.AndXCommand = 0xFF;
  11033. + pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
  11034. + pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
  11035. +
  11036. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  11037. + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  11038. +
  11039. + pSMB->req_no_secext.Capabilities =
  11040. + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
  11041. + if (ses->capabilities & CAP_UNICODE) {
  11042. + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  11043. + pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
  11044. + }
  11045. + if (ses->capabilities & CAP_STATUS32) {
  11046. + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  11047. + pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
  11048. + }
  11049. + if (ses->capabilities & CAP_DFS) {
  11050. + smb_buffer->Flags2 |= SMBFLG2_DFS;
  11051. + pSMB->req_no_secext.Capabilities |= CAP_DFS;
  11052. + }
  11053. + pSMB->req_no_secext.Capabilities =
  11054. + cpu_to_le32(pSMB->req_no_secext.Capabilities);
  11055. + /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
  11056. + CIFS_SESSION_KEY_SIZE; */
  11057. + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
  11058. + pSMB->req_no_secext.CaseSensitivePasswordLength =
  11059. + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
  11060. + bcc_ptr = pByteArea(smb_buffer);
  11061. + /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
  11062. + bcc_ptr += CIFS_SESSION_KEY_SIZE; */
  11063. + memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
  11064. + bcc_ptr += CIFS_SESSION_KEY_SIZE;
  11065. +
  11066. + if (ses->capabilities & CAP_UNICODE) {
  11067. + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
  11068. + *bcc_ptr = 0;
  11069. + bcc_ptr++;
  11070. + }
  11071. + if(user == NULL)
  11072. + bytes_returned = 0; /* skill null user */
  11073. + else
  11074. + bytes_returned =
  11075. + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
  11076. + nls_codepage);
  11077. + bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
  11078. + bcc_ptr += 2; /* trailing null */
  11079. + if (domain == NULL)
  11080. + bytes_returned =
  11081. + cifs_strtoUCS((wchar_t *) bcc_ptr,
  11082. + "CIFS_LINUX_DOM", 32, nls_codepage);
  11083. + else
  11084. + bytes_returned =
  11085. + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
  11086. + nls_codepage);
  11087. + bcc_ptr += 2 * bytes_returned;
  11088. + bcc_ptr += 2;
  11089. + bytes_returned =
  11090. + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
  11091. + 32, nls_codepage);
  11092. + bcc_ptr += 2 * bytes_returned;
  11093. + bytes_returned =
  11094. + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
  11095. + nls_codepage);
  11096. + bcc_ptr += 2 * bytes_returned;
  11097. + bcc_ptr += 2;
  11098. + bytes_returned =
  11099. + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
  11100. + 64, nls_codepage);
  11101. + bcc_ptr += 2 * bytes_returned;
  11102. + bcc_ptr += 2;
  11103. + } else {
  11104. + if(user != NULL) {
  11105. + strncpy(bcc_ptr, user, 200);
  11106. + bcc_ptr += strnlen(user, 200);
  11107. + }
  11108. + *bcc_ptr = 0;
  11109. + bcc_ptr++;
  11110. + if (domain == NULL) {
  11111. + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
  11112. + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
  11113. + } else {
  11114. + strncpy(bcc_ptr, domain, 64);
  11115. + bcc_ptr += strnlen(domain, 64);
  11116. + *bcc_ptr = 0;
  11117. + bcc_ptr++;
  11118. + }
  11119. + strcpy(bcc_ptr, "Linux version ");
  11120. + bcc_ptr += strlen("Linux version ");
  11121. + strcpy(bcc_ptr, UTS_RELEASE);
  11122. + bcc_ptr += strlen(UTS_RELEASE) + 1;
  11123. + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
  11124. + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
  11125. + }
  11126. + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
  11127. + smb_buffer->smb_buf_length += BCC(smb_buffer);
  11128. + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
  11129. +
  11130. + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
  11131. + &bytes_returned, 1);
  11132. + if (rc) {
  11133. +/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
  11134. + } else if ((smb_buffer_response->WordCount == 3)
  11135. + || (smb_buffer_response->WordCount == 4)) {
  11136. + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
  11137. + if (pSMBr->resp.Action & GUEST_LOGIN)
  11138. + cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
  11139. + if (ses) {
  11140. + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
  11141. + cFYI(1, ("UID = %d ", ses->Suid));
  11142. + /* response can have either 3 or 4 word count - Samba sends 3 */
  11143. + bcc_ptr = pByteArea(smb_buffer_response);
  11144. + if ((pSMBr->resp.hdr.WordCount == 3)
  11145. + || ((pSMBr->resp.hdr.WordCount == 4)
  11146. + && (pSMBr->resp.SecurityBlobLength <
  11147. + pSMBr->resp.ByteCount))) {
  11148. + if (pSMBr->resp.hdr.WordCount == 4)
  11149. + bcc_ptr +=
  11150. + pSMBr->resp.SecurityBlobLength;
  11151. +
  11152. + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
  11153. + if ((long) (bcc_ptr) % 2) {
  11154. + remaining_words =
  11155. + (BCC(smb_buffer_response)
  11156. + - 1) / 2;
  11157. + bcc_ptr++; /* Unicode strings must be word aligned */
  11158. + } else {
  11159. + remaining_words =
  11160. + BCC
  11161. + (smb_buffer_response) / 2;
  11162. + }
  11163. + len =
  11164. + UniStrnlen((wchar_t *) bcc_ptr,
  11165. + remaining_words - 1);
  11166. +/* We look for obvious messed up bcc or strings in response so we do not go off
  11167. + the end since (at least) WIN2K and Windows XP have a major bug in not null
  11168. + terminating last Unicode string in response */
  11169. + ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
  11170. + cifs_strfromUCS_le(ses->serverOS,
  11171. + (wchar_t *)bcc_ptr, len,nls_codepage);
  11172. + bcc_ptr += 2 * (len + 1);
  11173. + remaining_words -= len + 1;
  11174. + ses->serverOS[2 * len] = 0;
  11175. + ses->serverOS[1 + (2 * len)] = 0;
  11176. + if (remaining_words > 0) {
  11177. + len = UniStrnlen((wchar_t *)bcc_ptr,
  11178. + remaining_words
  11179. + - 1);
  11180. + ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
  11181. + cifs_strfromUCS_le(ses->serverNOS,
  11182. + (wchar_t *)bcc_ptr,len,nls_codepage);
  11183. + bcc_ptr += 2 * (len + 1);
  11184. + ses->serverNOS[2 * len] = 0;
  11185. + ses->serverNOS[1 + (2 * len)] = 0;
  11186. + remaining_words -= len + 1;
  11187. + if (remaining_words > 0) {
  11188. + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
  11189. + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
  11190. + ses->serverDomain =
  11191. + cifs_kcalloc(2*(len+1),GFP_KERNEL);
  11192. + cifs_strfromUCS_le(ses->serverDomain,
  11193. + (wchar_t *)bcc_ptr,len,nls_codepage);
  11194. + bcc_ptr += 2 * (len + 1);
  11195. + ses->serverDomain[2*len] = 0;
  11196. + ses->serverDomain[1+(2*len)] = 0;
  11197. + } /* else no more room so create dummy domain string */
  11198. + else
  11199. + ses->serverDomain =
  11200. + cifs_kcalloc(2,
  11201. + GFP_KERNEL);
  11202. + } else { /* no room so create dummy domain and NOS string */
  11203. + ses->serverDomain =
  11204. + cifs_kcalloc(2, GFP_KERNEL);
  11205. + ses->serverNOS =
  11206. + cifs_kcalloc(2, GFP_KERNEL);
  11207. + }
  11208. + } else { /* ASCII */
  11209. + len = strnlen(bcc_ptr, 1024);
  11210. + if (((long) bcc_ptr + len) - (long)
  11211. + pByteArea(smb_buffer_response)
  11212. + <= BCC(smb_buffer_response)) {
  11213. + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
  11214. + strncpy(ses->serverOS,bcc_ptr, len);
  11215. +
  11216. + bcc_ptr += len;
  11217. + bcc_ptr[0] = 0; /* null terminate the string */
  11218. + bcc_ptr++;
  11219. +
  11220. + len = strnlen(bcc_ptr, 1024);
  11221. + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
  11222. + strncpy(ses->serverNOS, bcc_ptr, len);
  11223. + bcc_ptr += len;
  11224. + bcc_ptr[0] = 0;
  11225. + bcc_ptr++;
  11226. +
  11227. + len = strnlen(bcc_ptr, 1024);
  11228. + ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
  11229. + strncpy(ses->serverDomain, bcc_ptr, len);
  11230. + bcc_ptr += len;
  11231. + bcc_ptr[0] = 0;
  11232. + bcc_ptr++;
  11233. + } else
  11234. + cFYI(1,
  11235. + ("Variable field of length %d extends beyond end of smb ",
  11236. + len));
  11237. + }
  11238. + } else {
  11239. + cERROR(1,
  11240. + (" Security Blob Length extends beyond end of SMB"));
  11241. + }
  11242. + } else {
  11243. + cERROR(1, ("No session structure passed in."));
  11244. + }
  11245. + } else {
  11246. + cERROR(1,
  11247. + (" Invalid Word count %d: ",
  11248. + smb_buffer_response->WordCount));
  11249. + rc = -EIO;
  11250. + }
  11251. +
  11252. + if (smb_buffer)
  11253. + cifs_buf_release(smb_buffer);
  11254. +
  11255. + return rc;
  11256. +}
  11257. +
  11258. +static int
  11259. +CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
  11260. + char *SecurityBlob,int SecurityBlobLength,
  11261. + const struct nls_table *nls_codepage)
  11262. +{
  11263. + struct smb_hdr *smb_buffer;
  11264. + struct smb_hdr *smb_buffer_response;
  11265. + SESSION_SETUP_ANDX *pSMB;
  11266. + SESSION_SETUP_ANDX *pSMBr;
  11267. + char *bcc_ptr;
  11268. + char *user = ses->userName;
  11269. + char *domain = ses->domainName;
  11270. + int rc = 0;
  11271. + int remaining_words = 0;
  11272. + int bytes_returned = 0;
  11273. + int len;
  11274. +
  11275. + cFYI(1, ("In spnego sesssetup "));
  11276. +
  11277. + smb_buffer = cifs_buf_get();
  11278. + if (smb_buffer == 0) {
  11279. + return -ENOMEM;
  11280. + }
  11281. + smb_buffer_response = smb_buffer;
  11282. + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
  11283. +
  11284. + /* send SMBsessionSetup here */
  11285. + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
  11286. + NULL /* no tCon exists yet */ , 12 /* wct */ );
  11287. + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
  11288. + pSMB->req.AndXCommand = 0xFF;
  11289. + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
  11290. + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
  11291. +
  11292. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  11293. + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  11294. +
  11295. + pSMB->req.Capabilities =
  11296. + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
  11297. + CAP_EXTENDED_SECURITY;
  11298. + if (ses->capabilities & CAP_UNICODE) {
  11299. + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  11300. + pSMB->req.Capabilities |= CAP_UNICODE;
  11301. + }
  11302. + if (ses->capabilities & CAP_STATUS32) {
  11303. + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  11304. + pSMB->req.Capabilities |= CAP_STATUS32;
  11305. + }
  11306. + if (ses->capabilities & CAP_DFS) {
  11307. + smb_buffer->Flags2 |= SMBFLG2_DFS;
  11308. + pSMB->req.Capabilities |= CAP_DFS;
  11309. + }
  11310. + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
  11311. +
  11312. + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
  11313. + bcc_ptr = pByteArea(smb_buffer);
  11314. + memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
  11315. + bcc_ptr += SecurityBlobLength;
  11316. +
  11317. + if (ses->capabilities & CAP_UNICODE) {
  11318. + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
  11319. + *bcc_ptr = 0;
  11320. + bcc_ptr++;
  11321. + }
  11322. + bytes_returned =
  11323. + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
  11324. + bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
  11325. + bcc_ptr += 2; /* trailing null */
  11326. + if (domain == NULL)
  11327. + bytes_returned =
  11328. + cifs_strtoUCS((wchar_t *) bcc_ptr,
  11329. + "CIFS_LINUX_DOM", 32, nls_codepage);
  11330. + else
  11331. + bytes_returned =
  11332. + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
  11333. + nls_codepage);
  11334. + bcc_ptr += 2 * bytes_returned;
  11335. + bcc_ptr += 2;
  11336. + bytes_returned =
  11337. + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
  11338. + 32, nls_codepage);
  11339. + bcc_ptr += 2 * bytes_returned;
  11340. + bytes_returned =
  11341. + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
  11342. + nls_codepage);
  11343. + bcc_ptr += 2 * bytes_returned;
  11344. + bcc_ptr += 2;
  11345. + bytes_returned =
  11346. + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
  11347. + 64, nls_codepage);
  11348. + bcc_ptr += 2 * bytes_returned;
  11349. + bcc_ptr += 2;
  11350. + } else {
  11351. + strncpy(bcc_ptr, user, 200);
  11352. + bcc_ptr += strnlen(user, 200);
  11353. + *bcc_ptr = 0;
  11354. + bcc_ptr++;
  11355. + if (domain == NULL) {
  11356. + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
  11357. + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
  11358. + } else {
  11359. + strncpy(bcc_ptr, domain, 64);
  11360. + bcc_ptr += strnlen(domain, 64);
  11361. + *bcc_ptr = 0;
  11362. + bcc_ptr++;
  11363. + }
  11364. + strcpy(bcc_ptr, "Linux version ");
  11365. + bcc_ptr += strlen("Linux version ");
  11366. + strcpy(bcc_ptr, UTS_RELEASE);
  11367. + bcc_ptr += strlen(UTS_RELEASE) + 1;
  11368. + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
  11369. + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
  11370. + }
  11371. + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
  11372. + smb_buffer->smb_buf_length += BCC(smb_buffer);
  11373. + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
  11374. +
  11375. + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
  11376. + &bytes_returned, 1);
  11377. + if (rc) {
  11378. +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
  11379. + } else if ((smb_buffer_response->WordCount == 3)
  11380. + || (smb_buffer_response->WordCount == 4)) {
  11381. + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
  11382. + pSMBr->resp.SecurityBlobLength =
  11383. + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
  11384. + if (pSMBr->resp.Action & GUEST_LOGIN)
  11385. + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
  11386. + if (ses) {
  11387. + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
  11388. + cFYI(1, ("UID = %d ", ses->Suid));
  11389. + bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
  11390. +
  11391. + /* BB Fix below to make endian neutral !! */
  11392. +
  11393. + if ((pSMBr->resp.hdr.WordCount == 3)
  11394. + || ((pSMBr->resp.hdr.WordCount == 4)
  11395. + && (pSMBr->resp.SecurityBlobLength <
  11396. + pSMBr->resp.ByteCount))) {
  11397. + if (pSMBr->resp.hdr.WordCount == 4) {
  11398. + bcc_ptr +=
  11399. + pSMBr->resp.SecurityBlobLength;
  11400. + cFYI(1,
  11401. + ("Security Blob Length %d ",
  11402. + pSMBr->resp.SecurityBlobLength));
  11403. + }
  11404. +
  11405. + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
  11406. + if ((long) (bcc_ptr) % 2) {
  11407. + remaining_words =
  11408. + (BCC(smb_buffer_response)
  11409. + - 1) / 2;
  11410. + bcc_ptr++; /* Unicode strings must be word aligned */
  11411. + } else {
  11412. + remaining_words =
  11413. + BCC
  11414. + (smb_buffer_response) / 2;
  11415. + }
  11416. + len =
  11417. + UniStrnlen((wchar_t *) bcc_ptr,
  11418. + remaining_words - 1);
  11419. +/* We look for obvious messed up bcc or strings in response so we do not go off
  11420. + the end since (at least) WIN2K and Windows XP have a major bug in not null
  11421. + terminating last Unicode string in response */
  11422. + ses->serverOS =
  11423. + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
  11424. + cifs_strfromUCS_le(ses->serverOS,
  11425. + (wchar_t *)
  11426. + bcc_ptr, len,
  11427. + nls_codepage);
  11428. + bcc_ptr += 2 * (len + 1);
  11429. + remaining_words -= len + 1;
  11430. + ses->serverOS[2 * len] = 0;
  11431. + ses->serverOS[1 + (2 * len)] = 0;
  11432. + if (remaining_words > 0) {
  11433. + len = UniStrnlen((wchar_t *)bcc_ptr,
  11434. + remaining_words
  11435. + - 1);
  11436. + ses->serverNOS =
  11437. + cifs_kcalloc(2 * (len + 1),
  11438. + GFP_KERNEL);
  11439. + cifs_strfromUCS_le(ses->serverNOS,
  11440. + (wchar_t *)bcc_ptr,
  11441. + len,
  11442. + nls_codepage);
  11443. + bcc_ptr += 2 * (len + 1);
  11444. + ses->serverNOS[2 * len] = 0;
  11445. + ses->serverNOS[1 + (2 * len)] = 0;
  11446. + remaining_words -= len + 1;
  11447. + if (remaining_words > 0) {
  11448. + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
  11449. + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
  11450. + ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
  11451. + cifs_strfromUCS_le(ses->serverDomain,
  11452. + (wchar_t *)bcc_ptr,
  11453. + len,
  11454. + nls_codepage);
  11455. + bcc_ptr += 2*(len+1);
  11456. + ses->serverDomain[2*len] = 0;
  11457. + ses->serverDomain[1+(2*len)] = 0;
  11458. + } /* else no more room so create dummy domain string */
  11459. + else
  11460. + ses->serverDomain =
  11461. + cifs_kcalloc(2,GFP_KERNEL);
  11462. + } else { /* no room so create dummy domain and NOS string */
  11463. + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
  11464. + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
  11465. + }
  11466. + } else { /* ASCII */
  11467. +
  11468. + len = strnlen(bcc_ptr, 1024);
  11469. + if (((long) bcc_ptr + len) - (long)
  11470. + pByteArea(smb_buffer_response)
  11471. + <= BCC(smb_buffer_response)) {
  11472. + ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
  11473. + strncpy(ses->serverOS, bcc_ptr, len);
  11474. +
  11475. + bcc_ptr += len;
  11476. + bcc_ptr[0] = 0; /* null terminate the string */
  11477. + bcc_ptr++;
  11478. +
  11479. + len = strnlen(bcc_ptr, 1024);
  11480. + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
  11481. + strncpy(ses->serverNOS, bcc_ptr, len);
  11482. + bcc_ptr += len;
  11483. + bcc_ptr[0] = 0;
  11484. + bcc_ptr++;
  11485. +
  11486. + len = strnlen(bcc_ptr, 1024);
  11487. + ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
  11488. + strncpy(ses->serverDomain, bcc_ptr, len);
  11489. + bcc_ptr += len;
  11490. + bcc_ptr[0] = 0;
  11491. + bcc_ptr++;
  11492. + } else
  11493. + cFYI(1,
  11494. + ("Variable field of length %d extends beyond end of smb ",
  11495. + len));
  11496. + }
  11497. + } else {
  11498. + cERROR(1,
  11499. + (" Security Blob Length extends beyond end of SMB"));
  11500. + }
  11501. + } else {
  11502. + cERROR(1, ("No session structure passed in."));
  11503. + }
  11504. + } else {
  11505. + cERROR(1,
  11506. + (" Invalid Word count %d: ",
  11507. + smb_buffer_response->WordCount));
  11508. + rc = -EIO;
  11509. + }
  11510. +
  11511. + if (smb_buffer)
  11512. + cifs_buf_release(smb_buffer);
  11513. +
  11514. + return rc;
  11515. +}
  11516. +
  11517. +static int
  11518. +CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
  11519. + struct cifsSesInfo *ses, int * pNTLMv2_flag,
  11520. + const struct nls_table *nls_codepage)
  11521. +{
  11522. + struct smb_hdr *smb_buffer;
  11523. + struct smb_hdr *smb_buffer_response;
  11524. + SESSION_SETUP_ANDX *pSMB;
  11525. + SESSION_SETUP_ANDX *pSMBr;
  11526. + char *bcc_ptr;
  11527. + char *domain = ses->domainName;
  11528. + int rc = 0;
  11529. + int remaining_words = 0;
  11530. + int bytes_returned = 0;
  11531. + int len;
  11532. + int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
  11533. + PNEGOTIATE_MESSAGE SecurityBlob;
  11534. + PCHALLENGE_MESSAGE SecurityBlob2;
  11535. +
  11536. + cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
  11537. + *pNTLMv2_flag = FALSE;
  11538. + smb_buffer = cifs_buf_get();
  11539. + if (smb_buffer == 0) {
  11540. + return -ENOMEM;
  11541. + }
  11542. + smb_buffer_response = smb_buffer;
  11543. + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
  11544. + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
  11545. +
  11546. + /* send SMBsessionSetup here */
  11547. + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
  11548. + NULL /* no tCon exists yet */ , 12 /* wct */ );
  11549. + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
  11550. + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
  11551. +
  11552. + pSMB->req.AndXCommand = 0xFF;
  11553. + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
  11554. + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
  11555. +
  11556. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  11557. + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  11558. +
  11559. + pSMB->req.Capabilities =
  11560. + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
  11561. + CAP_EXTENDED_SECURITY;
  11562. + if (ses->capabilities & CAP_UNICODE) {
  11563. + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  11564. + pSMB->req.Capabilities |= CAP_UNICODE;
  11565. + }
  11566. + if (ses->capabilities & CAP_STATUS32) {
  11567. + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  11568. + pSMB->req.Capabilities |= CAP_STATUS32;
  11569. + }
  11570. + if (ses->capabilities & CAP_DFS) {
  11571. + smb_buffer->Flags2 |= SMBFLG2_DFS;
  11572. + pSMB->req.Capabilities |= CAP_DFS;
  11573. + }
  11574. + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
  11575. +
  11576. + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
  11577. + SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
  11578. + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
  11579. + SecurityBlob->MessageType = NtLmNegotiate;
  11580. + SecurityBlob->NegotiateFlags =
  11581. + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
  11582. + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
  11583. + /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
  11584. + if(sign_CIFS_PDUs)
  11585. + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
  11586. + if(ntlmv2_support)
  11587. + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
  11588. + /* setup pointers to domain name and workstation name */
  11589. + bcc_ptr += SecurityBlobLength;
  11590. +
  11591. + SecurityBlob->WorkstationName.Buffer = 0;
  11592. + SecurityBlob->WorkstationName.Length = 0;
  11593. + SecurityBlob->WorkstationName.MaximumLength = 0;
  11594. +
  11595. + if (domain == NULL) {
  11596. + SecurityBlob->DomainName.Buffer = 0;
  11597. + SecurityBlob->DomainName.Length = 0;
  11598. + SecurityBlob->DomainName.MaximumLength = 0;
  11599. + } else {
  11600. + SecurityBlob->NegotiateFlags |=
  11601. + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
  11602. + strncpy(bcc_ptr, domain, 63);
  11603. + SecurityBlob->DomainName.Length = strnlen(domain, 64);
  11604. + SecurityBlob->DomainName.MaximumLength =
  11605. + cpu_to_le16(SecurityBlob->DomainName.Length);
  11606. + SecurityBlob->DomainName.Buffer =
  11607. + cpu_to_le32((long) &SecurityBlob->
  11608. + DomainString -
  11609. + (long) &SecurityBlob->Signature);
  11610. + bcc_ptr += SecurityBlob->DomainName.Length;
  11611. + SecurityBlobLength += SecurityBlob->DomainName.Length;
  11612. + SecurityBlob->DomainName.Length =
  11613. + cpu_to_le16(SecurityBlob->DomainName.Length);
  11614. + }
  11615. + if (ses->capabilities & CAP_UNICODE) {
  11616. + if ((long) bcc_ptr % 2) {
  11617. + *bcc_ptr = 0;
  11618. + bcc_ptr++;
  11619. + }
  11620. +
  11621. + bytes_returned =
  11622. + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
  11623. + 32, nls_codepage);
  11624. + bcc_ptr += 2 * bytes_returned;
  11625. + bytes_returned =
  11626. + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
  11627. + nls_codepage);
  11628. + bcc_ptr += 2 * bytes_returned;
  11629. + bcc_ptr += 2; /* null terminate Linux version */
  11630. + bytes_returned =
  11631. + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
  11632. + 64, nls_codepage);
  11633. + bcc_ptr += 2 * bytes_returned;
  11634. + *(bcc_ptr + 1) = 0;
  11635. + *(bcc_ptr + 2) = 0;
  11636. + bcc_ptr += 2; /* null terminate network opsys string */
  11637. + *(bcc_ptr + 1) = 0;
  11638. + *(bcc_ptr + 2) = 0;
  11639. + bcc_ptr += 2; /* null domain */
  11640. + } else { /* ASCII */
  11641. + strcpy(bcc_ptr, "Linux version ");
  11642. + bcc_ptr += strlen("Linux version ");
  11643. + strcpy(bcc_ptr, UTS_RELEASE);
  11644. + bcc_ptr += strlen(UTS_RELEASE) + 1;
  11645. + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
  11646. + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
  11647. + bcc_ptr++; /* empty domain field */
  11648. + *bcc_ptr = 0;
  11649. + }
  11650. + SecurityBlob->NegotiateFlags =
  11651. + cpu_to_le32(SecurityBlob->NegotiateFlags);
  11652. + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
  11653. + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
  11654. + smb_buffer->smb_buf_length += BCC(smb_buffer);
  11655. + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
  11656. +
  11657. + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
  11658. + &bytes_returned, 1);
  11659. +
  11660. + if (smb_buffer_response->Status.CifsError ==
  11661. + (NT_STATUS_MORE_PROCESSING_REQUIRED))
  11662. + rc = 0;
  11663. +
  11664. + if (rc) {
  11665. +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
  11666. + } else if ((smb_buffer_response->WordCount == 3)
  11667. + || (smb_buffer_response->WordCount == 4)) {
  11668. + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
  11669. + pSMBr->resp.SecurityBlobLength =
  11670. + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
  11671. + if (pSMBr->resp.Action & GUEST_LOGIN)
  11672. + cFYI(1, (" Guest login"));
  11673. + /* Do we want to set anything in SesInfo struct when guest login? */
  11674. +
  11675. + bcc_ptr = pByteArea(smb_buffer_response);
  11676. + /* response can have either 3 or 4 word count - Samba sends 3 */
  11677. +
  11678. + SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
  11679. + if (SecurityBlob2->MessageType != NtLmChallenge) {
  11680. + cFYI(1,
  11681. + ("Unexpected NTLMSSP message type received %d",
  11682. + SecurityBlob2->MessageType));
  11683. + } else if (ses) {
  11684. + ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
  11685. + cFYI(1, ("UID = %d ", ses->Suid));
  11686. + if ((pSMBr->resp.hdr.WordCount == 3)
  11687. + || ((pSMBr->resp.hdr.WordCount == 4)
  11688. + && (pSMBr->resp.SecurityBlobLength <
  11689. + pSMBr->resp.ByteCount))) {
  11690. + if (pSMBr->resp.hdr.WordCount == 4) {
  11691. + bcc_ptr +=
  11692. + pSMBr->resp.SecurityBlobLength;
  11693. + cFYI(1,
  11694. + ("Security Blob Length %d ",
  11695. + pSMBr->resp.SecurityBlobLength));
  11696. + }
  11697. +
  11698. + cFYI(1, ("NTLMSSP Challenge rcvd "));
  11699. +
  11700. + memcpy(ses->server->cryptKey,
  11701. + SecurityBlob2->Challenge,
  11702. + CIFS_CRYPTO_KEY_SIZE);
  11703. + if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
  11704. + *pNTLMv2_flag = TRUE;
  11705. +
  11706. + if((SecurityBlob2->NegotiateFlags &
  11707. + NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
  11708. + || (sign_CIFS_PDUs > 1))
  11709. + ses->server->secMode |=
  11710. + SECMODE_SIGN_REQUIRED;
  11711. + if ((SecurityBlob2->NegotiateFlags &
  11712. + NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
  11713. + ses->server->secMode |=
  11714. + SECMODE_SIGN_ENABLED;
  11715. +
  11716. + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
  11717. + if ((long) (bcc_ptr) % 2) {
  11718. + remaining_words =
  11719. + (BCC(smb_buffer_response)
  11720. + - 1) / 2;
  11721. + bcc_ptr++; /* Unicode strings must be word aligned */
  11722. + } else {
  11723. + remaining_words =
  11724. + BCC
  11725. + (smb_buffer_response) / 2;
  11726. + }
  11727. + len =
  11728. + UniStrnlen((wchar_t *) bcc_ptr,
  11729. + remaining_words - 1);
  11730. +/* We look for obvious messed up bcc or strings in response so we do not go off
  11731. + the end since (at least) WIN2K and Windows XP have a major bug in not null
  11732. + terminating last Unicode string in response */
  11733. + ses->serverOS =
  11734. + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
  11735. + cifs_strfromUCS_le(ses->serverOS,
  11736. + (wchar_t *)
  11737. + bcc_ptr, len,
  11738. + nls_codepage);
  11739. + bcc_ptr += 2 * (len + 1);
  11740. + remaining_words -= len + 1;
  11741. + ses->serverOS[2 * len] = 0;
  11742. + ses->serverOS[1 + (2 * len)] = 0;
  11743. + if (remaining_words > 0) {
  11744. + len = UniStrnlen((wchar_t *)
  11745. + bcc_ptr,
  11746. + remaining_words
  11747. + - 1);
  11748. + ses->serverNOS =
  11749. + cifs_kcalloc(2 * (len + 1),
  11750. + GFP_KERNEL);
  11751. + cifs_strfromUCS_le(ses->
  11752. + serverNOS,
  11753. + (wchar_t *)
  11754. + bcc_ptr,
  11755. + len,
  11756. + nls_codepage);
  11757. + bcc_ptr += 2 * (len + 1);
  11758. + ses->serverNOS[2 * len] = 0;
  11759. + ses->serverNOS[1 +
  11760. + (2 * len)] = 0;
  11761. + remaining_words -= len + 1;
  11762. + if (remaining_words > 0) {
  11763. + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
  11764. + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
  11765. + ses->serverDomain =
  11766. + cifs_kcalloc(2 *
  11767. + (len +
  11768. + 1),
  11769. + GFP_KERNEL);
  11770. + cifs_strfromUCS_le
  11771. + (ses->
  11772. + serverDomain,
  11773. + (wchar_t *)
  11774. + bcc_ptr, len,
  11775. + nls_codepage);
  11776. + bcc_ptr +=
  11777. + 2 * (len + 1);
  11778. + ses->
  11779. + serverDomain[2
  11780. + * len]
  11781. + = 0;
  11782. + ses->
  11783. + serverDomain[1
  11784. + +
  11785. + (2
  11786. + *
  11787. + len)]
  11788. + = 0;
  11789. + } /* else no more room so create dummy domain string */
  11790. + else
  11791. + ses->serverDomain =
  11792. + cifs_kcalloc(2,
  11793. + GFP_KERNEL);
  11794. + } else { /* no room so create dummy domain and NOS string */
  11795. + ses->serverDomain =
  11796. + cifs_kcalloc(2, GFP_KERNEL);
  11797. + ses->serverNOS =
  11798. + cifs_kcalloc(2, GFP_KERNEL);
  11799. + }
  11800. + } else { /* ASCII */
  11801. + len = strnlen(bcc_ptr, 1024);
  11802. + if (((long) bcc_ptr + len) - (long)
  11803. + pByteArea(smb_buffer_response)
  11804. + <= BCC(smb_buffer_response)) {
  11805. + ses->serverOS =
  11806. + cifs_kcalloc(len + 1,
  11807. + GFP_KERNEL);
  11808. + strncpy(ses->serverOS,
  11809. + bcc_ptr, len);
  11810. +
  11811. + bcc_ptr += len;
  11812. + bcc_ptr[0] = 0; /* null terminate string */
  11813. + bcc_ptr++;
  11814. +
  11815. + len = strnlen(bcc_ptr, 1024);
  11816. + ses->serverNOS =
  11817. + cifs_kcalloc(len + 1,
  11818. + GFP_KERNEL);
  11819. + strncpy(ses->serverNOS, bcc_ptr, len);
  11820. + bcc_ptr += len;
  11821. + bcc_ptr[0] = 0;
  11822. + bcc_ptr++;
  11823. +
  11824. + len = strnlen(bcc_ptr, 1024);
  11825. + ses->serverDomain =
  11826. + cifs_kcalloc(len + 1,
  11827. + GFP_KERNEL);
  11828. + strncpy(ses->serverDomain, bcc_ptr, len);
  11829. + bcc_ptr += len;
  11830. + bcc_ptr[0] = 0;
  11831. + bcc_ptr++;
  11832. + } else
  11833. + cFYI(1,
  11834. + ("Variable field of length %d extends beyond end of smb ",
  11835. + len));
  11836. + }
  11837. + } else {
  11838. + cERROR(1,
  11839. + (" Security Blob Length extends beyond end of SMB"));
  11840. + }
  11841. + } else {
  11842. + cERROR(1, ("No session structure passed in."));
  11843. + }
  11844. + } else {
  11845. + cERROR(1,
  11846. + (" Invalid Word count %d: ",
  11847. + smb_buffer_response->WordCount));
  11848. + rc = -EIO;
  11849. + }
  11850. +
  11851. + if (smb_buffer)
  11852. + cifs_buf_release(smb_buffer);
  11853. +
  11854. + return rc;
  11855. +}
  11856. +
  11857. +static int
  11858. +CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
  11859. + char *ntlm_session_key, int ntlmv2_flag,
  11860. + const struct nls_table *nls_codepage)
  11861. +{
  11862. + struct smb_hdr *smb_buffer;
  11863. + struct smb_hdr *smb_buffer_response;
  11864. + SESSION_SETUP_ANDX *pSMB;
  11865. + SESSION_SETUP_ANDX *pSMBr;
  11866. + char *bcc_ptr;
  11867. + char *user = ses->userName;
  11868. + char *domain = ses->domainName;
  11869. + int rc = 0;
  11870. + int remaining_words = 0;
  11871. + int bytes_returned = 0;
  11872. + int len;
  11873. + int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
  11874. + PAUTHENTICATE_MESSAGE SecurityBlob;
  11875. +
  11876. + cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
  11877. +
  11878. + smb_buffer = cifs_buf_get();
  11879. + if (smb_buffer == 0) {
  11880. + return -ENOMEM;
  11881. + }
  11882. + smb_buffer_response = smb_buffer;
  11883. + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
  11884. + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
  11885. +
  11886. + /* send SMBsessionSetup here */
  11887. + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
  11888. + NULL /* no tCon exists yet */ , 12 /* wct */ );
  11889. + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
  11890. + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
  11891. + pSMB->req.AndXCommand = 0xFF;
  11892. + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
  11893. + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
  11894. +
  11895. + pSMB->req.hdr.Uid = ses->Suid;
  11896. +
  11897. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  11898. + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  11899. +
  11900. + pSMB->req.Capabilities =
  11901. + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
  11902. + CAP_EXTENDED_SECURITY;
  11903. + if (ses->capabilities & CAP_UNICODE) {
  11904. + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  11905. + pSMB->req.Capabilities |= CAP_UNICODE;
  11906. + }
  11907. + if (ses->capabilities & CAP_STATUS32) {
  11908. + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  11909. + pSMB->req.Capabilities |= CAP_STATUS32;
  11910. + }
  11911. + if (ses->capabilities & CAP_DFS) {
  11912. + smb_buffer->Flags2 |= SMBFLG2_DFS;
  11913. + pSMB->req.Capabilities |= CAP_DFS;
  11914. + }
  11915. + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
  11916. +
  11917. + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
  11918. + SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
  11919. + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
  11920. + SecurityBlob->MessageType = NtLmAuthenticate;
  11921. + bcc_ptr += SecurityBlobLength;
  11922. + SecurityBlob->NegotiateFlags =
  11923. + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
  11924. + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
  11925. + 0x80000000 | NTLMSSP_NEGOTIATE_128;
  11926. + if(sign_CIFS_PDUs)
  11927. + SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
  11928. + if(ntlmv2_flag)
  11929. + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
  11930. +
  11931. +/* setup pointers to domain name and workstation name */
  11932. +
  11933. + SecurityBlob->WorkstationName.Buffer = 0;
  11934. + SecurityBlob->WorkstationName.Length = 0;
  11935. + SecurityBlob->WorkstationName.MaximumLength = 0;
  11936. + SecurityBlob->SessionKey.Length = 0;
  11937. + SecurityBlob->SessionKey.MaximumLength = 0;
  11938. + SecurityBlob->SessionKey.Buffer = 0;
  11939. +
  11940. + SecurityBlob->LmChallengeResponse.Length = 0;
  11941. + SecurityBlob->LmChallengeResponse.MaximumLength = 0;
  11942. + SecurityBlob->LmChallengeResponse.Buffer = 0;
  11943. +
  11944. + SecurityBlob->NtChallengeResponse.Length =
  11945. + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
  11946. + SecurityBlob->NtChallengeResponse.MaximumLength =
  11947. + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
  11948. + memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
  11949. + SecurityBlob->NtChallengeResponse.Buffer =
  11950. + cpu_to_le32(SecurityBlobLength);
  11951. + SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
  11952. + bcc_ptr += CIFS_SESSION_KEY_SIZE;
  11953. +
  11954. + if (ses->capabilities & CAP_UNICODE) {
  11955. + if (domain == NULL) {
  11956. + SecurityBlob->DomainName.Buffer = 0;
  11957. + SecurityBlob->DomainName.Length = 0;
  11958. + SecurityBlob->DomainName.MaximumLength = 0;
  11959. + } else {
  11960. + SecurityBlob->DomainName.Length =
  11961. + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
  11962. + nls_codepage);
  11963. + SecurityBlob->DomainName.Length *= 2;
  11964. + SecurityBlob->DomainName.MaximumLength =
  11965. + cpu_to_le16(SecurityBlob->DomainName.Length);
  11966. + SecurityBlob->DomainName.Buffer =
  11967. + cpu_to_le32(SecurityBlobLength);
  11968. + bcc_ptr += SecurityBlob->DomainName.Length;
  11969. + SecurityBlobLength += SecurityBlob->DomainName.Length;
  11970. + SecurityBlob->DomainName.Length =
  11971. + cpu_to_le16(SecurityBlob->DomainName.Length);
  11972. + }
  11973. + if (user == NULL) {
  11974. + SecurityBlob->UserName.Buffer = 0;
  11975. + SecurityBlob->UserName.Length = 0;
  11976. + SecurityBlob->UserName.MaximumLength = 0;
  11977. + } else {
  11978. + SecurityBlob->UserName.Length =
  11979. + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
  11980. + nls_codepage);
  11981. + SecurityBlob->UserName.Length *= 2;
  11982. + SecurityBlob->UserName.MaximumLength =
  11983. + cpu_to_le16(SecurityBlob->UserName.Length);
  11984. + SecurityBlob->UserName.Buffer =
  11985. + cpu_to_le32(SecurityBlobLength);
  11986. + bcc_ptr += SecurityBlob->UserName.Length;
  11987. + SecurityBlobLength += SecurityBlob->UserName.Length;
  11988. + SecurityBlob->UserName.Length =
  11989. + cpu_to_le16(SecurityBlob->UserName.Length);
  11990. + }
  11991. +
  11992. + /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
  11993. + SecurityBlob->WorkstationName.Length *= 2;
  11994. + SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
  11995. + SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
  11996. + bcc_ptr += SecurityBlob->WorkstationName.Length;
  11997. + SecurityBlobLength += SecurityBlob->WorkstationName.Length;
  11998. + SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
  11999. +
  12000. + if ((long) bcc_ptr % 2) {
  12001. + *bcc_ptr = 0;
  12002. + bcc_ptr++;
  12003. + }
  12004. + bytes_returned =
  12005. + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
  12006. + 32, nls_codepage);
  12007. + bcc_ptr += 2 * bytes_returned;
  12008. + bytes_returned =
  12009. + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
  12010. + nls_codepage);
  12011. + bcc_ptr += 2 * bytes_returned;
  12012. + bcc_ptr += 2; /* null term version string */
  12013. + bytes_returned =
  12014. + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
  12015. + 64, nls_codepage);
  12016. + bcc_ptr += 2 * bytes_returned;
  12017. + *(bcc_ptr + 1) = 0;
  12018. + *(bcc_ptr + 2) = 0;
  12019. + bcc_ptr += 2; /* null terminate network opsys string */
  12020. + *(bcc_ptr + 1) = 0;
  12021. + *(bcc_ptr + 2) = 0;
  12022. + bcc_ptr += 2; /* null domain */
  12023. + } else { /* ASCII */
  12024. + if (domain == NULL) {
  12025. + SecurityBlob->DomainName.Buffer = 0;
  12026. + SecurityBlob->DomainName.Length = 0;
  12027. + SecurityBlob->DomainName.MaximumLength = 0;
  12028. + } else {
  12029. + SecurityBlob->NegotiateFlags |=
  12030. + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
  12031. + strncpy(bcc_ptr, domain, 63);
  12032. + SecurityBlob->DomainName.Length = strnlen(domain, 64);
  12033. + SecurityBlob->DomainName.MaximumLength =
  12034. + cpu_to_le16(SecurityBlob->DomainName.Length);
  12035. + SecurityBlob->DomainName.Buffer =
  12036. + cpu_to_le32(SecurityBlobLength);
  12037. + bcc_ptr += SecurityBlob->DomainName.Length;
  12038. + SecurityBlobLength += SecurityBlob->DomainName.Length;
  12039. + SecurityBlob->DomainName.Length =
  12040. + cpu_to_le16(SecurityBlob->DomainName.Length);
  12041. + }
  12042. + if (user == NULL) {
  12043. + SecurityBlob->UserName.Buffer = 0;
  12044. + SecurityBlob->UserName.Length = 0;
  12045. + SecurityBlob->UserName.MaximumLength = 0;
  12046. + } else {
  12047. + strncpy(bcc_ptr, user, 63);
  12048. + SecurityBlob->UserName.Length = strnlen(user, 64);
  12049. + SecurityBlob->UserName.MaximumLength =
  12050. + cpu_to_le16(SecurityBlob->UserName.Length);
  12051. + SecurityBlob->UserName.Buffer =
  12052. + cpu_to_le32(SecurityBlobLength);
  12053. + bcc_ptr += SecurityBlob->UserName.Length;
  12054. + SecurityBlobLength += SecurityBlob->UserName.Length;
  12055. + SecurityBlob->UserName.Length =
  12056. + cpu_to_le16(SecurityBlob->UserName.Length);
  12057. + }
  12058. + /* BB fill in our workstation name if known BB */
  12059. +
  12060. + strcpy(bcc_ptr, "Linux version ");
  12061. + bcc_ptr += strlen("Linux version ");
  12062. + strcpy(bcc_ptr, UTS_RELEASE);
  12063. + bcc_ptr += strlen(UTS_RELEASE) + 1;
  12064. + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
  12065. + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
  12066. + bcc_ptr++; /* null domain */
  12067. + *bcc_ptr = 0;
  12068. + }
  12069. + SecurityBlob->NegotiateFlags =
  12070. + cpu_to_le32(SecurityBlob->NegotiateFlags);
  12071. + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
  12072. + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
  12073. + smb_buffer->smb_buf_length += BCC(smb_buffer);
  12074. + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
  12075. +
  12076. + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
  12077. + &bytes_returned, 1);
  12078. + if (rc) {
  12079. +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
  12080. + } else if ((smb_buffer_response->WordCount == 3)
  12081. + || (smb_buffer_response->WordCount == 4)) {
  12082. + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
  12083. + pSMBr->resp.SecurityBlobLength =
  12084. + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
  12085. + if (pSMBr->resp.Action & GUEST_LOGIN)
  12086. + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
  12087. +/* if(SecurityBlob2->MessageType != NtLm??){
  12088. + cFYI("Unexpected message type on auth response is %d "));
  12089. + } */
  12090. + if (ses) {
  12091. + cFYI(1,
  12092. + ("Does UID on challenge %d match auth response UID %d ",
  12093. + ses->Suid, smb_buffer_response->Uid));
  12094. + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
  12095. + bcc_ptr = pByteArea(smb_buffer_response);
  12096. + /* response can have either 3 or 4 word count - Samba sends 3 */
  12097. + if ((pSMBr->resp.hdr.WordCount == 3)
  12098. + || ((pSMBr->resp.hdr.WordCount == 4)
  12099. + && (pSMBr->resp.SecurityBlobLength <
  12100. + pSMBr->resp.ByteCount))) {
  12101. + if (pSMBr->resp.hdr.WordCount == 4) {
  12102. + bcc_ptr +=
  12103. + pSMBr->resp.SecurityBlobLength;
  12104. + cFYI(1,
  12105. + ("Security Blob Length %d ",
  12106. + pSMBr->resp.SecurityBlobLength));
  12107. + }
  12108. +
  12109. + cFYI(1,
  12110. + ("NTLMSSP response to Authenticate "));
  12111. +
  12112. + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
  12113. + if ((long) (bcc_ptr) % 2) {
  12114. + remaining_words =
  12115. + (BCC(smb_buffer_response)
  12116. + - 1) / 2;
  12117. + bcc_ptr++; /* Unicode strings must be word aligned */
  12118. + } else {
  12119. + remaining_words = BCC(smb_buffer_response) / 2;
  12120. + }
  12121. + len =
  12122. + UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
  12123. +/* We look for obvious messed up bcc or strings in response so we do not go off
  12124. + the end since (at least) WIN2K and Windows XP have a major bug in not null
  12125. + terminating last Unicode string in response */
  12126. + ses->serverOS =
  12127. + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
  12128. + cifs_strfromUCS_le(ses->serverOS,
  12129. + (wchar_t *)
  12130. + bcc_ptr, len,
  12131. + nls_codepage);
  12132. + bcc_ptr += 2 * (len + 1);
  12133. + remaining_words -= len + 1;
  12134. + ses->serverOS[2 * len] = 0;
  12135. + ses->serverOS[1 + (2 * len)] = 0;
  12136. + if (remaining_words > 0) {
  12137. + len = UniStrnlen((wchar_t *)
  12138. + bcc_ptr,
  12139. + remaining_words
  12140. + - 1);
  12141. + ses->serverNOS =
  12142. + cifs_kcalloc(2 * (len + 1),
  12143. + GFP_KERNEL);
  12144. + cifs_strfromUCS_le(ses->
  12145. + serverNOS,
  12146. + (wchar_t *)
  12147. + bcc_ptr,
  12148. + len,
  12149. + nls_codepage);
  12150. + bcc_ptr += 2 * (len + 1);
  12151. + ses->serverNOS[2 * len] = 0;
  12152. + ses->serverNOS[1+(2*len)] = 0;
  12153. + remaining_words -= len + 1;
  12154. + if (remaining_words > 0) {
  12155. + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
  12156. + /* last string not always null terminated (e.g. for Windows XP & 2000) */
  12157. + ses->serverDomain =
  12158. + cifs_kcalloc(2 *
  12159. + (len +
  12160. + 1),
  12161. + GFP_KERNEL);
  12162. + cifs_strfromUCS_le
  12163. + (ses->
  12164. + serverDomain,
  12165. + (wchar_t *)
  12166. + bcc_ptr, len,
  12167. + nls_codepage);
  12168. + bcc_ptr +=
  12169. + 2 * (len + 1);
  12170. + ses->
  12171. + serverDomain[2
  12172. + * len]
  12173. + = 0;
  12174. + ses->
  12175. + serverDomain[1
  12176. + +
  12177. + (2
  12178. + *
  12179. + len)]
  12180. + = 0;
  12181. + } /* else no more room so create dummy domain string */
  12182. + else
  12183. + ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
  12184. + } else { /* no room so create dummy domain and NOS string */
  12185. + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
  12186. + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
  12187. + }
  12188. + } else { /* ASCII */
  12189. + len = strnlen(bcc_ptr, 1024);
  12190. + if (((long) bcc_ptr + len) -
  12191. + (long) pByteArea(smb_buffer_response)
  12192. + <= BCC(smb_buffer_response)) {
  12193. + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
  12194. + strncpy(ses->serverOS,bcc_ptr, len);
  12195. +
  12196. + bcc_ptr += len;
  12197. + bcc_ptr[0] = 0; /* null terminate the string */
  12198. + bcc_ptr++;
  12199. +
  12200. + len = strnlen(bcc_ptr, 1024);
  12201. + ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
  12202. + strncpy(ses->serverNOS, bcc_ptr, len);
  12203. + bcc_ptr += len;
  12204. + bcc_ptr[0] = 0;
  12205. + bcc_ptr++;
  12206. +
  12207. + len = strnlen(bcc_ptr, 1024);
  12208. + ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
  12209. + strncpy(ses->serverDomain, bcc_ptr, len);
  12210. + bcc_ptr += len;
  12211. + bcc_ptr[0] = 0;
  12212. + bcc_ptr++;
  12213. + } else
  12214. + cFYI(1,
  12215. + ("Variable field of length %d extends beyond end of smb ",
  12216. + len));
  12217. + }
  12218. + } else {
  12219. + cERROR(1,
  12220. + (" Security Blob Length extends beyond end of SMB"));
  12221. + }
  12222. + } else {
  12223. + cERROR(1, ("No session structure passed in."));
  12224. + }
  12225. + } else {
  12226. + cERROR(1,
  12227. + (" Invalid Word count %d: ",
  12228. + smb_buffer_response->WordCount));
  12229. + rc = -EIO;
  12230. + }
  12231. +
  12232. + if (smb_buffer)
  12233. + cifs_buf_release(smb_buffer);
  12234. +
  12235. + return rc;
  12236. +}
  12237. +
  12238. +int
  12239. +CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
  12240. + const char *tree, struct cifsTconInfo *tcon,
  12241. + const struct nls_table *nls_codepage)
  12242. +{
  12243. + struct smb_hdr *smb_buffer;
  12244. + struct smb_hdr *smb_buffer_response;
  12245. + TCONX_REQ *pSMB;
  12246. + TCONX_RSP *pSMBr;
  12247. + char *bcc_ptr;
  12248. + int rc = 0;
  12249. + int length;
  12250. +
  12251. + if (ses == NULL)
  12252. + return -EIO;
  12253. +
  12254. + smb_buffer = cifs_buf_get();
  12255. + if (smb_buffer == 0) {
  12256. + return -ENOMEM;
  12257. + }
  12258. + smb_buffer_response = smb_buffer;
  12259. +
  12260. + header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
  12261. + NULL /*no tid */ , 4 /*wct */ );
  12262. + smb_buffer->Uid = ses->Suid;
  12263. + pSMB = (TCONX_REQ *) smb_buffer;
  12264. + pSMBr = (TCONX_RSP *) smb_buffer_response;
  12265. +
  12266. + pSMB->AndXCommand = 0xFF;
  12267. + pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
  12268. + pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
  12269. + bcc_ptr = &(pSMB->Password[0]);
  12270. + bcc_ptr++; /* skip password */
  12271. +
  12272. + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  12273. + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  12274. +
  12275. + if (ses->capabilities & CAP_STATUS32) {
  12276. + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  12277. + }
  12278. + if (ses->capabilities & CAP_DFS) {
  12279. + smb_buffer->Flags2 |= SMBFLG2_DFS;
  12280. + }
  12281. + if (ses->capabilities & CAP_UNICODE) {
  12282. + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  12283. + length =
  12284. + cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
  12285. + bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
  12286. + bcc_ptr += 2; /* skip trailing null */
  12287. + } else { /* ASCII */
  12288. +
  12289. + strcpy(bcc_ptr, tree);
  12290. + bcc_ptr += strlen(tree) + 1;
  12291. + }
  12292. + strcpy(bcc_ptr, "?????");
  12293. + bcc_ptr += strlen("?????");
  12294. + bcc_ptr += 1;
  12295. + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
  12296. + smb_buffer->smb_buf_length += BCC(smb_buffer);
  12297. + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
  12298. +
  12299. + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
  12300. +
  12301. + /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
  12302. + /* above now done in SendReceive */
  12303. + if ((rc == 0) && (tcon != NULL)) {
  12304. + tcon->tidStatus = CifsGood;
  12305. + tcon->tid = smb_buffer_response->Tid;
  12306. + bcc_ptr = pByteArea(smb_buffer_response);
  12307. + length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
  12308. + /* skip service field (NB: this field is always ASCII) */
  12309. + bcc_ptr += length + 1;
  12310. + strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
  12311. + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
  12312. + length = UniStrnlen((wchar_t *) bcc_ptr, 512);
  12313. + if (((long) bcc_ptr + (2 * length)) -
  12314. + (long) pByteArea(smb_buffer_response) <=
  12315. + BCC(smb_buffer_response)) {
  12316. + if(tcon->nativeFileSystem)
  12317. + kfree(tcon->nativeFileSystem);
  12318. + tcon->nativeFileSystem =
  12319. + cifs_kcalloc(length + 2, GFP_KERNEL);
  12320. + cifs_strfromUCS_le(tcon->nativeFileSystem,
  12321. + (wchar_t *) bcc_ptr,
  12322. + length, nls_codepage);
  12323. + bcc_ptr += 2 * length;
  12324. + bcc_ptr[0] = 0; /* null terminate the string */
  12325. + bcc_ptr[1] = 0;
  12326. + bcc_ptr += 2;
  12327. + }
  12328. + /* else do not bother copying these informational fields */
  12329. + } else {
  12330. + length = strnlen(bcc_ptr, 1024);
  12331. + if (((long) bcc_ptr + length) -
  12332. + (long) pByteArea(smb_buffer_response) <=
  12333. + BCC(smb_buffer_response)) {
  12334. + if(tcon->nativeFileSystem)
  12335. + kfree(tcon->nativeFileSystem);
  12336. + tcon->nativeFileSystem =
  12337. + cifs_kcalloc(length + 1, GFP_KERNEL);
  12338. + strncpy(tcon->nativeFileSystem, bcc_ptr,
  12339. + length);
  12340. + }
  12341. + /* else do not bother copying these informational fields */
  12342. + }
  12343. + tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
  12344. + cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
  12345. + } else if ((rc == 0) && tcon == NULL) {
  12346. + /* all we need to save for IPC$ connection */
  12347. + ses->ipc_tid = smb_buffer_response->Tid;
  12348. + }
  12349. +
  12350. + if (smb_buffer)
  12351. + cifs_buf_release(smb_buffer);
  12352. + return rc;
  12353. +}
  12354. +
  12355. +int
  12356. +cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
  12357. +{
  12358. + int rc = 0;
  12359. + int xid;
  12360. + struct cifsSesInfo *ses = NULL;
  12361. + struct task_struct *cifsd_task;
  12362. +
  12363. + xid = GetXid();
  12364. +
  12365. + if (cifs_sb->tcon) {
  12366. + ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
  12367. + rc = CIFSSMBTDis(xid, cifs_sb->tcon);
  12368. + if (rc == -EBUSY) {
  12369. + FreeXid(xid);
  12370. + return 0;
  12371. + }
  12372. + tconInfoFree(cifs_sb->tcon);
  12373. + if ((ses) && (ses->server)) {
  12374. + /* save off task so we do not refer to ses later */
  12375. + cifsd_task = ses->server->tsk;
  12376. + cFYI(1, ("About to do SMBLogoff "));
  12377. + rc = CIFSSMBLogoff(xid, ses);
  12378. + if (rc == -EBUSY) {
  12379. + FreeXid(xid);
  12380. + return 0;
  12381. + } else if (rc == -ESHUTDOWN) {
  12382. + cFYI(1,("Waking up socket by sending it signal"));
  12383. + send_sig(SIGKILL,cifsd_task,1);
  12384. + rc = 0;
  12385. + } /* else - we have an smb session
  12386. + left on this socket do not kill cifsd */
  12387. + } else
  12388. + cFYI(1, ("No session or bad tcon"));
  12389. + }
  12390. +
  12391. + cifs_sb->tcon = NULL;
  12392. + if (ses) {
  12393. + set_current_state(TASK_INTERRUPTIBLE);
  12394. + schedule_timeout(HZ / 2);
  12395. + }
  12396. + if (ses)
  12397. + sesInfoFree(ses);
  12398. +
  12399. + FreeXid(xid);
  12400. + return rc; /* BB check if we should always return zero here */
  12401. +}
  12402. +
  12403. +int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
  12404. + struct nls_table * nls_info)
  12405. +{
  12406. + int rc = 0;
  12407. + char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
  12408. + int ntlmv2_flag = FALSE;
  12409. +
  12410. + /* what if server changes its buffer size after dropping the session? */
  12411. + if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
  12412. + rc = CIFSSMBNegotiate(xid, pSesInfo);
  12413. + if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
  12414. + rc = CIFSSMBNegotiate(xid, pSesInfo);
  12415. + if(rc == -EAGAIN)
  12416. + rc = -EHOSTDOWN;
  12417. + }
  12418. + if(rc == 0) {
  12419. + spin_lock(&GlobalMid_Lock);
  12420. + if(pSesInfo->server->tcpStatus != CifsExiting)
  12421. + pSesInfo->server->tcpStatus = CifsGood;
  12422. + else
  12423. + rc = -EHOSTDOWN;
  12424. + spin_unlock(&GlobalMid_Lock);
  12425. +
  12426. + }
  12427. + }
  12428. + if (!rc) {
  12429. + pSesInfo->capabilities = pSesInfo->server->capabilities;
  12430. + if(linuxExtEnabled == 0)
  12431. + pSesInfo->capabilities &= (~CAP_UNIX);
  12432. + pSesInfo->sequence_number = 0;
  12433. + cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
  12434. + pSesInfo->server->secMode,
  12435. + pSesInfo->server->capabilities,
  12436. + pSesInfo->server->timeZone));
  12437. + if (extended_security
  12438. + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
  12439. + && (pSesInfo->server->secType == NTLMSSP)) {
  12440. + cFYI(1, ("New style sesssetup "));
  12441. + rc = CIFSSpnegoSessSetup(xid, pSesInfo,
  12442. + NULL /* security blob */,
  12443. + 0 /* blob length */,
  12444. + nls_info);
  12445. + } else if (extended_security
  12446. + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
  12447. + && (pSesInfo->server->secType == RawNTLMSSP)) {
  12448. + cFYI(1, ("NTLMSSP sesssetup "));
  12449. + rc = CIFSNTLMSSPNegotiateSessSetup(xid,
  12450. + pSesInfo,
  12451. + &ntlmv2_flag,
  12452. + nls_info);
  12453. + if (!rc) {
  12454. + if(ntlmv2_flag) {
  12455. + char * v2_response;
  12456. + cFYI(1,("Can use more secure NTLM version 2 password hash"));
  12457. + CalcNTLMv2_partial_mac_key(pSesInfo,
  12458. + nls_info);
  12459. + v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
  12460. + if(v2_response) {
  12461. + CalcNTLMv2_response(pSesInfo,v2_response);
  12462. +/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
  12463. + kfree(v2_response);
  12464. + /* BB Put dummy sig in SessSetup PDU? */
  12465. + } else
  12466. + rc = -ENOMEM;
  12467. +
  12468. + } else {
  12469. + SMBNTencrypt(pSesInfo->password,
  12470. + pSesInfo->server->cryptKey,
  12471. + ntlm_session_key);
  12472. +
  12473. + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
  12474. + ntlm_session_key,
  12475. + pSesInfo->password);
  12476. + }
  12477. + /* for better security the weaker lanman hash not sent
  12478. + in AuthSessSetup so we no longer calculate it */
  12479. +
  12480. + rc = CIFSNTLMSSPAuthSessSetup(xid,
  12481. + pSesInfo,
  12482. + ntlm_session_key,
  12483. + ntlmv2_flag,
  12484. + nls_info);
  12485. + }
  12486. + } else { /* old style NTLM 0.12 session setup */
  12487. + SMBNTencrypt(pSesInfo->password,
  12488. + pSesInfo->server->cryptKey,
  12489. + ntlm_session_key);
  12490. +
  12491. + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
  12492. + ntlm_session_key, pSesInfo->password);
  12493. + rc = CIFSSessSetup(xid, pSesInfo,
  12494. + ntlm_session_key, nls_info);
  12495. + }
  12496. + if (rc) {
  12497. + cERROR(1,("Send error in SessSetup = %d",rc));
  12498. + } else {
  12499. + cFYI(1,("CIFS Session Established successfully"));
  12500. + pSesInfo->status = CifsGood;
  12501. + }
  12502. + }
  12503. + return rc;
  12504. +}
  12505. +
  12506. --- /dev/null
  12507. +++ b/fs/cifs/dir.c
  12508. @@ -0,0 +1,425 @@
  12509. +/*
  12510. + * fs/cifs/dir.c
  12511. + *
  12512. + * vfs operations that deal with dentries
  12513. + *
  12514. + * Copyright (C) International Business Machines Corp., 2002,2003
  12515. + * Author(s): Steve French ([email protected])
  12516. + *
  12517. + * This library is free software; you can redistribute it and/or modify
  12518. + * it under the terms of the GNU Lesser General Public License as published
  12519. + * by the Free Software Foundation; either version 2.1 of the License, or
  12520. + * (at your option) any later version.
  12521. + *
  12522. + * This library is distributed in the hope that it will be useful,
  12523. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12524. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  12525. + * the GNU Lesser General Public License for more details.
  12526. + *
  12527. + * You should have received a copy of the GNU Lesser General Public License
  12528. + * along with this library; if not, write to the Free Software
  12529. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  12530. + */
  12531. +#include <linux/fs.h>
  12532. +#include <linux/stat.h>
  12533. +#include <linux/slab.h>
  12534. +#include "cifsfs.h"
  12535. +#include "cifspdu.h"
  12536. +#include "cifsglob.h"
  12537. +#include "cifsproto.h"
  12538. +#include "cifs_debug.h"
  12539. +#include "cifs_fs_sb.h"
  12540. +
  12541. +void
  12542. +renew_parental_timestamps(struct dentry *direntry)
  12543. +{
  12544. + /* BB check if there is a way to get the kernel to do this or if we really need this */
  12545. + do {
  12546. + direntry->d_time = jiffies;
  12547. + direntry = direntry->d_parent;
  12548. + } while (!IS_ROOT(direntry));
  12549. +}
  12550. +
  12551. +/* Note: caller must free return buffer */
  12552. +char *
  12553. +build_path_from_dentry(struct dentry *direntry)
  12554. +{
  12555. + struct dentry *temp;
  12556. + int namelen = 0;
  12557. + char *full_path;
  12558. +
  12559. + if(direntry == NULL)
  12560. + return NULL; /* not much we can do if dentry is freed and
  12561. + we need to reopen the file after it was closed implicitly
  12562. + when the server crashed */
  12563. +
  12564. +cifs_bp_rename_retry:
  12565. + for (temp = direntry; !IS_ROOT(temp);) {
  12566. + namelen += (1 + temp->d_name.len);
  12567. + temp = temp->d_parent;
  12568. + if(temp == NULL) {
  12569. + cERROR(1,("corrupt dentry"));
  12570. + return NULL;
  12571. + }
  12572. + }
  12573. +
  12574. + full_path = kmalloc(namelen+1, GFP_KERNEL);
  12575. + if(full_path == NULL)
  12576. + return full_path;
  12577. + full_path[namelen] = 0; /* trailing null */
  12578. +
  12579. + for (temp = direntry; !IS_ROOT(temp);) {
  12580. + namelen -= 1 + temp->d_name.len;
  12581. + if (namelen < 0) {
  12582. + break;
  12583. + } else {
  12584. + full_path[namelen] = '\\';
  12585. + strncpy(full_path + namelen + 1, temp->d_name.name,
  12586. + temp->d_name.len);
  12587. + cFYI(0, (" name: %s ", full_path + namelen));
  12588. + }
  12589. + temp = temp->d_parent;
  12590. + if(temp == NULL) {
  12591. + cERROR(1,("corrupt dentry"));
  12592. + kfree(full_path);
  12593. + return NULL;
  12594. + }
  12595. + }
  12596. + if (namelen != 0) {
  12597. + cERROR(1,
  12598. + ("We did not end path lookup where we expected namelen is %d",
  12599. + namelen));
  12600. + /* presumably this is only possible if we were racing with a rename
  12601. + of one of the parent directories (we can not lock the dentries
  12602. + above us to prevent this, but retrying should be harmless) */
  12603. + kfree(full_path);
  12604. + namelen = 0;
  12605. + goto cifs_bp_rename_retry;
  12606. + }
  12607. +
  12608. + return full_path;
  12609. +}
  12610. +
  12611. +/* Note: caller must free return buffer */
  12612. +char *
  12613. +build_wildcard_path_from_dentry(struct dentry *direntry)
  12614. +{
  12615. + struct dentry *temp;
  12616. + int namelen = 0;
  12617. + char *full_path;
  12618. +
  12619. + if(direntry == NULL)
  12620. + return NULL; /* not much we can do if dentry is freed and
  12621. + we need to reopen the file after it was closed implicitly
  12622. + when the server crashed */
  12623. +
  12624. +cifs_bwp_rename_retry:
  12625. + for (temp = direntry; !IS_ROOT(temp);) {
  12626. + namelen += (1 + temp->d_name.len);
  12627. + temp = temp->d_parent;
  12628. + if(temp == NULL) {
  12629. + cERROR(1,("corrupt dentry"));
  12630. + return NULL;
  12631. + }
  12632. + }
  12633. +
  12634. + full_path = kmalloc(namelen+3, GFP_KERNEL);
  12635. + if(full_path == NULL)
  12636. + return full_path;
  12637. +
  12638. + full_path[namelen] = '\\';
  12639. + full_path[namelen+1] = '*';
  12640. + full_path[namelen+2] = 0; /* trailing null */
  12641. +
  12642. + for (temp = direntry; !IS_ROOT(temp);) {
  12643. + namelen -= 1 + temp->d_name.len;
  12644. + if (namelen < 0) {
  12645. + break;
  12646. + } else {
  12647. + full_path[namelen] = '\\';
  12648. + strncpy(full_path + namelen + 1, temp->d_name.name,
  12649. + temp->d_name.len);
  12650. + cFYI(0, (" name: %s ", full_path + namelen));
  12651. + }
  12652. + temp = temp->d_parent;
  12653. + if(temp == NULL) {
  12654. + cERROR(1,("corrupt dentry"));
  12655. + kfree(full_path);
  12656. + return NULL;
  12657. + }
  12658. + }
  12659. + if (namelen != 0) {
  12660. + cERROR(1,
  12661. + ("We did not end path lookup where we expected namelen is %d",
  12662. + namelen));
  12663. + /* presumably this is only possible if we were racing with a rename
  12664. + of one of the parent directories (we can not lock the dentries
  12665. + above us to prevent this, but retrying should be harmless) */
  12666. + kfree(full_path);
  12667. + namelen = 0;
  12668. + goto cifs_bwp_rename_retry;
  12669. + }
  12670. +
  12671. + return full_path;
  12672. +}
  12673. +
  12674. +/* Inode operations in similar order to how they appear in the Linux file fs.h */
  12675. +
  12676. +int
  12677. +cifs_create(struct inode *inode, struct dentry *direntry, int mode)
  12678. +{
  12679. + int rc = -ENOENT;
  12680. + int xid;
  12681. + int oplock = 0; /* no sense requested oplock if we are just going to
  12682. + immediately close the file */
  12683. + __u16 fileHandle;
  12684. + struct cifs_sb_info *cifs_sb;
  12685. + struct cifsTconInfo *pTcon;
  12686. + char *full_path = NULL;
  12687. + FILE_ALL_INFO * buf = NULL;
  12688. + struct inode *newinode = NULL;
  12689. +
  12690. + xid = GetXid();
  12691. +
  12692. + cifs_sb = CIFS_SB(inode->i_sb);
  12693. + pTcon = cifs_sb->tcon;
  12694. +
  12695. + down(&direntry->d_sb->s_vfs_rename_sem);
  12696. + full_path = build_path_from_dentry(direntry);
  12697. + up(&direntry->d_sb->s_vfs_rename_sem);
  12698. + if(full_path == NULL) {
  12699. + FreeXid(xid);
  12700. + return -ENOMEM;
  12701. + }
  12702. +
  12703. + /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
  12704. +
  12705. + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
  12706. + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
  12707. + GENERIC_WRITE, CREATE_NOT_DIR,
  12708. + &fileHandle, &oplock, buf, cifs_sb->local_nls);
  12709. + if (rc) {
  12710. + cFYI(1, ("cifs_create returned 0x%x ", rc));
  12711. + } else {
  12712. + /* BB for case of overwriting existing file can we use the inode that was
  12713. + passed in rather than creating new one?? */
  12714. + if (pTcon->ses->capabilities & CAP_UNIX)
  12715. + rc = cifs_get_inode_info_unix(&newinode, full_path,
  12716. + inode->i_sb,xid);
  12717. + else
  12718. + rc = cifs_get_inode_info(&newinode, full_path,
  12719. + buf, inode->i_sb,xid);
  12720. +
  12721. + if (rc != 0) {
  12722. + cFYI(1,("Create worked but get_inode_info failed with rc = %d",
  12723. + rc));
  12724. + } else {
  12725. + direntry->d_op = &cifs_dentry_ops;
  12726. + d_instantiate(direntry, newinode);
  12727. + }
  12728. + CIFSSMBClose(xid, pTcon, fileHandle);
  12729. +
  12730. + if(newinode) {
  12731. + newinode->i_mode = mode;
  12732. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  12733. + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
  12734. + (__u64)-1,
  12735. + (__u64)-1,
  12736. + 0 /* dev */,
  12737. + cifs_sb->local_nls);
  12738. + else { /* BB implement via Windows security descriptors */
  12739. + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
  12740. + /* in the meantime could set r/o dos attribute when perms are eg:
  12741. + mode & 0222 == 0 */
  12742. + }
  12743. + }
  12744. + }
  12745. +
  12746. + if (buf)
  12747. + kfree(buf);
  12748. + if (full_path)
  12749. + kfree(full_path);
  12750. + FreeXid(xid);
  12751. +
  12752. + return rc;
  12753. +}
  12754. +
  12755. +int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
  12756. +{
  12757. + int rc = -EPERM;
  12758. + int xid;
  12759. + struct cifs_sb_info *cifs_sb;
  12760. + struct cifsTconInfo *pTcon;
  12761. + char *full_path = NULL;
  12762. + struct inode * newinode = NULL;
  12763. +
  12764. + xid = GetXid();
  12765. +
  12766. + cifs_sb = CIFS_SB(inode->i_sb);
  12767. + pTcon = cifs_sb->tcon;
  12768. +
  12769. + down(&direntry->d_sb->s_vfs_rename_sem);
  12770. + full_path = build_path_from_dentry(direntry);
  12771. + up(&direntry->d_sb->s_vfs_rename_sem);
  12772. + if(full_path == NULL)
  12773. + rc = -ENOMEM;
  12774. +
  12775. + if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
  12776. + rc = CIFSSMBUnixSetPerms(xid, pTcon,
  12777. + full_path, mode, current->euid, current->egid,
  12778. + device_number, cifs_sb->local_nls);
  12779. + if(!rc) {
  12780. + rc = cifs_get_inode_info_unix(&newinode, full_path,
  12781. + inode->i_sb,xid);
  12782. + direntry->d_op = &cifs_dentry_ops;
  12783. + if(rc == 0)
  12784. + d_instantiate(direntry, newinode);
  12785. + }
  12786. + }
  12787. +
  12788. + if (full_path)
  12789. + kfree(full_path);
  12790. + FreeXid(xid);
  12791. +
  12792. + return rc;
  12793. +}
  12794. +
  12795. +
  12796. +struct dentry *
  12797. +cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
  12798. +{
  12799. + int xid;
  12800. + int rc = 0; /* to get around spurious gcc warning, set to zero here */
  12801. + struct cifs_sb_info *cifs_sb;
  12802. + struct cifsTconInfo *pTcon;
  12803. + struct inode *newInode = NULL;
  12804. + char *full_path = NULL;
  12805. +
  12806. + xid = GetXid();
  12807. +
  12808. + cFYI(1,
  12809. + (" parent inode = 0x%p name is: %s and dentry = 0x%p",
  12810. + parent_dir_inode, direntry->d_name.name, direntry));
  12811. +
  12812. + /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
  12813. +
  12814. + /* check whether path exists */
  12815. +
  12816. + cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
  12817. + pTcon = cifs_sb->tcon;
  12818. +
  12819. + /* can not grab the rename sem here since it would
  12820. + deadlock in the cases (beginning of sys_rename itself)
  12821. + in which we already have the sb rename sem */
  12822. + full_path = build_path_from_dentry(direntry);
  12823. + if(full_path == NULL) {
  12824. + FreeXid(xid);
  12825. + return ERR_PTR(-ENOMEM);
  12826. + }
  12827. +
  12828. + if (direntry->d_inode != NULL) {
  12829. + cFYI(1, (" non-NULL inode in lookup"));
  12830. + } else {
  12831. + cFYI(1, (" NULL inode in lookup"));
  12832. + }
  12833. + cFYI(1,
  12834. + (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
  12835. +
  12836. + if (pTcon->ses->capabilities & CAP_UNIX)
  12837. + rc = cifs_get_inode_info_unix(&newInode, full_path,
  12838. + parent_dir_inode->i_sb,xid);
  12839. + else
  12840. + rc = cifs_get_inode_info(&newInode, full_path, NULL,
  12841. + parent_dir_inode->i_sb,xid);
  12842. +
  12843. + if ((rc == 0) && (newInode != NULL)) {
  12844. + direntry->d_op = &cifs_dentry_ops;
  12845. + d_add(direntry, newInode);
  12846. +
  12847. + /* since paths are not looked up by component - the parent directories are presumed to be good here */
  12848. + renew_parental_timestamps(direntry);
  12849. +
  12850. + } else if (rc == -ENOENT) {
  12851. + rc = 0;
  12852. + d_add(direntry, NULL);
  12853. + } else {
  12854. + cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
  12855. + /* BB special case check for Access Denied - watch security
  12856. + exposure of returning dir info implicitly via different rc
  12857. + if file exists or not but no access BB */
  12858. + }
  12859. +
  12860. + if (full_path)
  12861. + kfree(full_path);
  12862. + FreeXid(xid);
  12863. + return ERR_PTR(rc);
  12864. +}
  12865. +
  12866. +int
  12867. +cifs_dir_open(struct inode *inode, struct file *file)
  12868. +{ /* NB: currently unused since searches are opened in readdir */
  12869. + int rc = 0;
  12870. + int xid;
  12871. + struct cifs_sb_info *cifs_sb;
  12872. + struct cifsTconInfo *pTcon;
  12873. + char *full_path = NULL;
  12874. +
  12875. + xid = GetXid();
  12876. +
  12877. + cifs_sb = CIFS_SB(inode->i_sb);
  12878. + pTcon = cifs_sb->tcon;
  12879. +
  12880. + if(file->f_dentry) {
  12881. + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
  12882. + full_path = build_wildcard_path_from_dentry(file->f_dentry);
  12883. + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
  12884. + } else {
  12885. + FreeXid(xid);
  12886. + return -EIO;
  12887. + }
  12888. +
  12889. + cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
  12890. +
  12891. + if (full_path)
  12892. + kfree(full_path);
  12893. + FreeXid(xid);
  12894. + return rc;
  12895. +}
  12896. +
  12897. +static int
  12898. +cifs_d_revalidate(struct dentry *direntry, int flags)
  12899. +{
  12900. + int isValid = 1;
  12901. +
  12902. +/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
  12903. +
  12904. + if (direntry->d_inode) {
  12905. + if (cifs_revalidate(direntry)) {
  12906. + /* unlock_kernel(); */
  12907. + return 0;
  12908. + }
  12909. + } else {
  12910. + cFYI(1,
  12911. + ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
  12912. + direntry->d_name.name, direntry));
  12913. + }
  12914. +
  12915. +/* unlock_kernel(); */
  12916. +
  12917. + return isValid;
  12918. +}
  12919. +
  12920. +/* static int cifs_d_delete(struct dentry *direntry)
  12921. +{
  12922. + int rc = 0;
  12923. +
  12924. + cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
  12925. +
  12926. + return rc;
  12927. +} */
  12928. +
  12929. +struct dentry_operations cifs_dentry_ops = {
  12930. + .d_revalidate = cifs_d_revalidate,
  12931. +/* d_delete: cifs_d_delete, *//* not needed except for debugging */
  12932. + /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
  12933. +};
  12934. --- /dev/null
  12935. +++ b/fs/cifs/file.c
  12936. @@ -0,0 +1,2185 @@
  12937. +/*
  12938. + * fs/cifs/file.c
  12939. + *
  12940. + * vfs operations that deal with files
  12941. + *
  12942. + * Copyright (C) International Business Machines Corp., 2002,2003
  12943. + * Author(s): Steve French ([email protected])
  12944. + *
  12945. + * This library is free software; you can redistribute it and/or modify
  12946. + * it under the terms of the GNU Lesser General Public License as published
  12947. + * by the Free Software Foundation; either version 2.1 of the License, or
  12948. + * (at your option) any later version.
  12949. + *
  12950. + * This library is distributed in the hope that it will be useful,
  12951. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12952. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  12953. + * the GNU Lesser General Public License for more details.
  12954. + *
  12955. + * You should have received a copy of the GNU Lesser General Public License
  12956. + * along with this library; if not, write to the Free Software
  12957. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  12958. + */
  12959. +#include <linux/fs.h>
  12960. +#include <linux/stat.h>
  12961. +#include <linux/fcntl.h>
  12962. +#include <linux/version.h>
  12963. +#include <linux/pagemap.h>
  12964. +#include <linux/smp_lock.h>
  12965. +#include <linux/list.h>
  12966. +#include <asm/div64.h>
  12967. +#include <linux/mm.h>
  12968. +#include <linux/types.h>
  12969. +#include "cifsfs.h"
  12970. +#include "cifspdu.h"
  12971. +#include "cifsglob.h"
  12972. +#include "cifsproto.h"
  12973. +#include "cifs_unicode.h"
  12974. +#include "cifs_debug.h"
  12975. +#include "cifs_fs_sb.h"
  12976. +
  12977. +int
  12978. +cifs_open(struct inode *inode, struct file *file)
  12979. +{
  12980. + int rc = -EACCES;
  12981. + int xid, oplock;
  12982. + struct cifs_sb_info *cifs_sb;
  12983. + struct cifsTconInfo *pTcon;
  12984. + struct cifsFileInfo *pCifsFile;
  12985. + struct cifsInodeInfo *pCifsInode;
  12986. + char *full_path = NULL;
  12987. + int desiredAccess = 0x20197;
  12988. + int disposition;
  12989. + __u16 netfid;
  12990. + FILE_ALL_INFO * buf = NULL;
  12991. + time_t temp;
  12992. +
  12993. + xid = GetXid();
  12994. +
  12995. + cifs_sb = CIFS_SB(inode->i_sb);
  12996. + pTcon = cifs_sb->tcon;
  12997. +
  12998. + down(&inode->i_sb->s_vfs_rename_sem);
  12999. + full_path = build_path_from_dentry(file->f_dentry);
  13000. + up(&inode->i_sb->s_vfs_rename_sem);
  13001. + if(full_path == NULL) {
  13002. + FreeXid(xid);
  13003. + return -ENOMEM;
  13004. + }
  13005. +
  13006. + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
  13007. + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
  13008. + desiredAccess = GENERIC_READ;
  13009. + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
  13010. + desiredAccess = GENERIC_WRITE;
  13011. + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
  13012. + /* GENERIC_ALL is too much permission to request */
  13013. + /* can cause unnecessary access denied on create */
  13014. + /* desiredAccess = GENERIC_ALL; */
  13015. + desiredAccess = GENERIC_READ | GENERIC_WRITE;
  13016. + }
  13017. +
  13018. +/*********************************************************************
  13019. + * open flag mapping table:
  13020. + *
  13021. + * POSIX Flag CIFS Disposition
  13022. + * ---------- ----------------
  13023. + * O_CREAT FILE_OPEN_IF
  13024. + * O_CREAT | O_EXCL FILE_CREATE
  13025. + * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
  13026. + * O_TRUNC FILE_OVERWRITE
  13027. + * none of the above FILE_OPEN
  13028. + *
  13029. + * Note that there is not a direct match between disposition
  13030. + * FILE_SUPERSEDE (ie create whether or not file exists although
  13031. + * O_CREAT | O_TRUNC is similar but truncates the existing
  13032. + * file rather than creating a new file as FILE_SUPERSEDE does
  13033. + * (which uses the attributes / metadata passed in on open call)
  13034. + *?
  13035. + *? O_SYNC is a reasonable match to CIFS writethrough flag
  13036. + *? and the read write flags match reasonably. O_LARGEFILE
  13037. + *? is irrelevant because largefile support is always used
  13038. + *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
  13039. + * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
  13040. + *********************************************************************/
  13041. +
  13042. + /* For 2.4 case, file was already checked for existence
  13043. + before create by vfs lookup and created in create
  13044. + entry point, we are now just opening the newly
  13045. + created file with the right desiredAccess flags */
  13046. +
  13047. + if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
  13048. + disposition = FILE_OPEN_IF;
  13049. + else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
  13050. + disposition = FILE_OVERWRITE_IF;
  13051. + else if((file->f_flags & O_CREAT) == O_CREAT)
  13052. + disposition = FILE_OPEN_IF;
  13053. + else
  13054. + disposition = FILE_OPEN;
  13055. +
  13056. + if (oplockEnabled)
  13057. + oplock = REQ_OPLOCK;
  13058. + else
  13059. + oplock = FALSE;
  13060. +
  13061. + /* BB pass O_SYNC flag through on file attributes .. BB */
  13062. +
  13063. + /* Also refresh inode by passing in file_info buf returned by SMBOpen
  13064. + and calling get_inode_info with returned buf (at least
  13065. + helps non-Unix server case */
  13066. +
  13067. + /* BB we can not do this if this is the second open of a file
  13068. + and the first handle has writebehind data, we might be
  13069. + able to simply do a filemap_fdatawrite/filemap_fdatawait first */
  13070. + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
  13071. + if(buf==0) {
  13072. + if (full_path)
  13073. + kfree(full_path);
  13074. + FreeXid(xid);
  13075. + return -ENOMEM;
  13076. + }
  13077. + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
  13078. + CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
  13079. + if (rc) {
  13080. + cFYI(1, ("cifs_open returned 0x%x ", rc));
  13081. + cFYI(1, ("oplock: %d ", oplock));
  13082. + } else {
  13083. + file->private_data =
  13084. + kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
  13085. + if (file->private_data) {
  13086. + memset(file->private_data, 0, sizeof(struct cifsFileInfo));
  13087. + pCifsFile = (struct cifsFileInfo *) file->private_data;
  13088. + pCifsFile->netfid = netfid;
  13089. + pCifsFile->pid = current->pid;
  13090. + init_MUTEX(&pCifsFile->fh_sem);
  13091. + pCifsFile->pfile = file; /* needed for writepage */
  13092. + pCifsFile->pInode = inode;
  13093. + pCifsFile->invalidHandle = FALSE;
  13094. + pCifsFile->closePend = FALSE;
  13095. + write_lock(&GlobalSMBSeslock);
  13096. + spin_lock(&files_lock);
  13097. + list_add(&pCifsFile->tlist,&pTcon->openFileList);
  13098. + pCifsInode = CIFS_I(file->f_dentry->d_inode);
  13099. + if(pCifsInode) {
  13100. + /* want handles we can use to read with first */
  13101. + /* in the list so we do not have to walk the */
  13102. + /* list to search for one in prepare_write */
  13103. + if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
  13104. + list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
  13105. + } else {
  13106. + list_add(&pCifsFile->flist,&pCifsInode->openFileList);
  13107. + }
  13108. + spin_unlock(&files_lock);
  13109. + write_unlock(&GlobalSMBSeslock);
  13110. + if(pCifsInode->clientCanCacheRead) {
  13111. + /* we have the inode open somewhere else
  13112. + no need to discard cache data */
  13113. + } else {
  13114. + if(buf) {
  13115. + /* BB need same check in cifs_create too? */
  13116. +
  13117. + /* if not oplocked, invalidate inode pages if mtime
  13118. + or file size changed */
  13119. + temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
  13120. + if((file->f_dentry->d_inode->i_mtime == temp) &&
  13121. + (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
  13122. + cFYI(1,("inode unchanged on server"));
  13123. + } else {
  13124. + if(file->f_dentry->d_inode->i_mapping) {
  13125. + /* BB no need to lock inode until after invalidate*/
  13126. + /* since namei code should already have it locked?*/
  13127. + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
  13128. + }
  13129. + cFYI(1,("invalidating remote inode since open detected it changed"));
  13130. + invalidate_inode_pages(file->f_dentry->d_inode);
  13131. + }
  13132. + }
  13133. + }
  13134. + if (pTcon->ses->capabilities & CAP_UNIX)
  13135. + rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
  13136. + full_path, inode->i_sb,xid);
  13137. + else
  13138. + rc = cifs_get_inode_info(&file->f_dentry->d_inode,
  13139. + full_path, buf, inode->i_sb,xid);
  13140. +
  13141. + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
  13142. + pCifsInode->clientCanCacheAll = TRUE;
  13143. + pCifsInode->clientCanCacheRead = TRUE;
  13144. + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
  13145. + } else if((oplock & 0xF) == OPLOCK_READ)
  13146. + pCifsInode->clientCanCacheRead = TRUE;
  13147. + } else {
  13148. + spin_unlock(&files_lock);
  13149. + write_unlock(&GlobalSMBSeslock);
  13150. + }
  13151. + if(oplock & CIFS_CREATE_ACTION) {
  13152. + /* time to set mode which we can not set earlier due
  13153. + to problems creating new read-only files */
  13154. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  13155. + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
  13156. + (__u64)-1,
  13157. + (__u64)-1,
  13158. + 0 /* dev */,
  13159. + cifs_sb->local_nls);
  13160. + else {/* BB implement via Windows security descriptors */
  13161. + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
  13162. + /* in the meantime could set r/o dos attribute when perms are eg:
  13163. + mode & 0222 == 0 */
  13164. + }
  13165. + }
  13166. + }
  13167. + }
  13168. +
  13169. + if (buf)
  13170. + kfree(buf);
  13171. + if (full_path)
  13172. + kfree(full_path);
  13173. + FreeXid(xid);
  13174. + return rc;
  13175. +}
  13176. +
  13177. +/* Try to reaquire byte range locks that were released when session */
  13178. +/* to server was lost */
  13179. +static int cifs_relock_file(struct cifsFileInfo * cifsFile)
  13180. +{
  13181. + int rc = 0;
  13182. +
  13183. +/* BB list all locks open on this file and relock */
  13184. +
  13185. + return rc;
  13186. +}
  13187. +
  13188. +static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
  13189. +{
  13190. + int rc = -EACCES;
  13191. + int xid, oplock;
  13192. + struct cifs_sb_info *cifs_sb;
  13193. + struct cifsTconInfo *pTcon;
  13194. + struct cifsFileInfo *pCifsFile;
  13195. + struct cifsInodeInfo *pCifsInode;
  13196. + char *full_path = NULL;
  13197. + int desiredAccess = 0x20197;
  13198. + int disposition = FILE_OPEN;
  13199. + __u16 netfid;
  13200. +
  13201. + if(inode == NULL)
  13202. + return -EBADF;
  13203. + if (file->private_data) {
  13204. + pCifsFile = (struct cifsFileInfo *) file->private_data;
  13205. + } else
  13206. + return -EBADF;
  13207. +
  13208. + xid = GetXid();
  13209. + down(&pCifsFile->fh_sem);
  13210. + if(pCifsFile->invalidHandle == FALSE) {
  13211. + up(&pCifsFile->fh_sem);
  13212. + FreeXid(xid);
  13213. + return 0;
  13214. + }
  13215. +
  13216. + if(file->f_dentry == NULL) {
  13217. + up(&pCifsFile->fh_sem);
  13218. + cFYI(1,("failed file reopen, no valid name if dentry freed"));
  13219. + FreeXid(xid);
  13220. + return -EBADF;
  13221. + }
  13222. + cifs_sb = CIFS_SB(inode->i_sb);
  13223. + pTcon = cifs_sb->tcon;
  13224. +/* can not grab rename sem here because various ops, including
  13225. +those that already have the rename sem can end up causing writepage
  13226. +to get called and if the server was down that means we end up here,
  13227. +and we can never tell if the caller already has the rename_sem */
  13228. + full_path = build_path_from_dentry(file->f_dentry);
  13229. + if(full_path == NULL) {
  13230. + up(&pCifsFile->fh_sem);
  13231. + FreeXid(xid);
  13232. + return -ENOMEM;
  13233. + }
  13234. +
  13235. + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
  13236. + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
  13237. + desiredAccess = GENERIC_READ;
  13238. + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
  13239. + desiredAccess = GENERIC_WRITE;
  13240. + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
  13241. + /* GENERIC_ALL is too much permission to request */
  13242. + /* can cause unnecessary access denied on create */
  13243. + /* desiredAccess = GENERIC_ALL; */
  13244. + desiredAccess = GENERIC_READ | GENERIC_WRITE;
  13245. + }
  13246. +
  13247. + if (oplockEnabled)
  13248. + oplock = REQ_OPLOCK;
  13249. + else
  13250. + oplock = FALSE;
  13251. +
  13252. +
  13253. + /* Can not refresh inode by passing in file_info buf to be returned
  13254. + by SMBOpen and then calling get_inode_info with returned buf
  13255. + since file might have write behind data that needs to be flushed
  13256. + and server version of file size can be stale. If we
  13257. + knew for sure that inode was not dirty locally we could do this */
  13258. +
  13259. +/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
  13260. + if(buf==0) {
  13261. + up(&pCifsFile->fh_sem);
  13262. + if (full_path)
  13263. + kfree(full_path);
  13264. + FreeXid(xid);
  13265. + return -ENOMEM;
  13266. + }*/
  13267. + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
  13268. + CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
  13269. + if (rc) {
  13270. + up(&pCifsFile->fh_sem);
  13271. + cFYI(1, ("cifs_open returned 0x%x ", rc));
  13272. + cFYI(1, ("oplock: %d ", oplock));
  13273. + } else {
  13274. + pCifsFile->netfid = netfid;
  13275. + pCifsFile->invalidHandle = FALSE;
  13276. + up(&pCifsFile->fh_sem);
  13277. + pCifsInode = CIFS_I(inode);
  13278. + if(pCifsInode) {
  13279. + if(can_flush) {
  13280. + filemap_fdatasync(inode->i_mapping);
  13281. + filemap_fdatawait(inode->i_mapping);
  13282. + /* temporarily disable caching while we
  13283. + go to server to get inode info */
  13284. + pCifsInode->clientCanCacheAll = FALSE;
  13285. + pCifsInode->clientCanCacheRead = FALSE;
  13286. + if (pTcon->ses->capabilities & CAP_UNIX)
  13287. + rc = cifs_get_inode_info_unix(&inode,
  13288. + full_path, inode->i_sb,xid);
  13289. + else
  13290. + rc = cifs_get_inode_info(&inode,
  13291. + full_path, NULL, inode->i_sb,xid);
  13292. + } /* else we are writing out data to server already
  13293. + and could deadlock if we tried to flush data, and
  13294. + since we do not know if we have data that would
  13295. + invalidate the current end of file on the server
  13296. + we can not go to the server to get the new
  13297. + inod info */
  13298. + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
  13299. + pCifsInode->clientCanCacheAll = TRUE;
  13300. + pCifsInode->clientCanCacheRead = TRUE;
  13301. + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
  13302. + } else if((oplock & 0xF) == OPLOCK_READ) {
  13303. + pCifsInode->clientCanCacheRead = TRUE;
  13304. + pCifsInode->clientCanCacheAll = FALSE;
  13305. + } else {
  13306. + pCifsInode->clientCanCacheRead = FALSE;
  13307. + pCifsInode->clientCanCacheAll = FALSE;
  13308. + }
  13309. + cifs_relock_file(pCifsFile);
  13310. + }
  13311. + }
  13312. +
  13313. + if (full_path)
  13314. + kfree(full_path);
  13315. + FreeXid(xid);
  13316. + return rc;
  13317. +}
  13318. +
  13319. +int
  13320. +cifs_close(struct inode *inode, struct file *file)
  13321. +{
  13322. + int rc = 0;
  13323. + int xid;
  13324. + struct cifs_sb_info *cifs_sb;
  13325. + struct cifsTconInfo *pTcon;
  13326. + struct cifsFileInfo *pSMBFile =
  13327. + (struct cifsFileInfo *) file->private_data;
  13328. +
  13329. + xid = GetXid();
  13330. +
  13331. + cifs_sb = CIFS_SB(inode->i_sb);
  13332. + pTcon = cifs_sb->tcon;
  13333. + if (pSMBFile) {
  13334. + pSMBFile->closePend = TRUE;
  13335. + spin_lock(&files_lock);
  13336. + if(pTcon) {
  13337. + /* no sense reconnecting to close a file that is
  13338. + already closed */
  13339. + if (pTcon->tidStatus != CifsNeedReconnect) {
  13340. + spin_unlock(&files_lock);
  13341. + rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
  13342. + spin_lock(&files_lock);
  13343. + }
  13344. + }
  13345. + list_del(&pSMBFile->flist);
  13346. + list_del(&pSMBFile->tlist);
  13347. + spin_unlock(&files_lock);
  13348. + if(pSMBFile->search_resume_name)
  13349. + kfree(pSMBFile->search_resume_name);
  13350. + kfree(file->private_data);
  13351. + file->private_data = NULL;
  13352. + } else
  13353. + rc = -EBADF;
  13354. +
  13355. + if(list_empty(&(CIFS_I(inode)->openFileList))) {
  13356. + cFYI(1,("closing last open instance for inode %p",inode));
  13357. + /* if the file is not open we do not know if we can cache
  13358. + info on this inode, much less write behind and read ahead */
  13359. + CIFS_I(inode)->clientCanCacheRead = FALSE;
  13360. + CIFS_I(inode)->clientCanCacheAll = FALSE;
  13361. + }
  13362. + if((rc ==0) && CIFS_I(inode)->write_behind_rc)
  13363. + rc = CIFS_I(inode)->write_behind_rc;
  13364. + FreeXid(xid);
  13365. + return rc;
  13366. +}
  13367. +
  13368. +int
  13369. +cifs_closedir(struct inode *inode, struct file *file)
  13370. +{
  13371. + int rc = 0;
  13372. + int xid;
  13373. + struct cifsFileInfo *pSMBFileStruct =
  13374. + (struct cifsFileInfo *) file->private_data;
  13375. +
  13376. + cFYI(1, ("Closedir inode = 0x%p with ", inode));
  13377. +
  13378. + xid = GetXid();
  13379. +
  13380. + if (pSMBFileStruct) {
  13381. + cFYI(1, ("Freeing private data in close dir"));
  13382. + kfree(file->private_data);
  13383. + file->private_data = NULL;
  13384. + }
  13385. + FreeXid(xid);
  13386. + return rc;
  13387. +}
  13388. +
  13389. +int
  13390. +cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
  13391. +{
  13392. + int rc, xid;
  13393. + __u32 lockType = LOCKING_ANDX_LARGE_FILES;
  13394. + __u32 numLock = 0;
  13395. + __u32 numUnlock = 0;
  13396. + __u64 length;
  13397. + int wait_flag = FALSE;
  13398. + struct cifs_sb_info *cifs_sb;
  13399. + struct cifsTconInfo *pTcon;
  13400. + length = 1 + pfLock->fl_end - pfLock->fl_start;
  13401. +
  13402. + rc = -EACCES;
  13403. +
  13404. + xid = GetXid();
  13405. +
  13406. + cFYI(1,
  13407. + ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
  13408. + cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
  13409. + pfLock->fl_end));
  13410. +
  13411. + if (pfLock->fl_flags & FL_POSIX)
  13412. + cFYI(1, ("Posix "));
  13413. + if (pfLock->fl_flags & FL_FLOCK)
  13414. + cFYI(1, ("Flock "));
  13415. +/* if (pfLock->fl_flags & FL_SLEEP) {
  13416. + cFYI(1, ("Blocking lock "));
  13417. + wait_flag = TRUE;
  13418. + } */
  13419. + if (pfLock->fl_flags & FL_ACCESS)
  13420. + cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
  13421. + if (pfLock->fl_flags & FL_LEASE)
  13422. + cFYI(1, ("Lease on file - not implemented yet"));
  13423. + if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
  13424. + cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
  13425. +
  13426. + if (pfLock->fl_type == F_WRLCK) {
  13427. + cFYI(1, ("F_WRLCK "));
  13428. + numLock = 1;
  13429. + } else if (pfLock->fl_type == F_UNLCK) {
  13430. + cFYI(1, ("F_UNLCK "));
  13431. + numUnlock = 1;
  13432. + } else if (pfLock->fl_type == F_RDLCK) {
  13433. + cFYI(1, ("F_RDLCK "));
  13434. + lockType |= LOCKING_ANDX_SHARED_LOCK;
  13435. + numLock = 1;
  13436. + } else if (pfLock->fl_type == F_EXLCK) {
  13437. + cFYI(1, ("F_EXLCK "));
  13438. + numLock = 1;
  13439. + } else if (pfLock->fl_type == F_SHLCK) {
  13440. + cFYI(1, ("F_SHLCK "));
  13441. + lockType |= LOCKING_ANDX_SHARED_LOCK;
  13442. + numLock = 1;
  13443. + } else
  13444. + cFYI(1, ("Unknown type of lock "));
  13445. +
  13446. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  13447. + pTcon = cifs_sb->tcon;
  13448. +
  13449. + if (file->private_data == NULL) {
  13450. + FreeXid(xid);
  13451. + return -EBADF;
  13452. + }
  13453. +
  13454. + if (IS_GETLK(cmd)) {
  13455. + rc = CIFSSMBLock(xid, pTcon,
  13456. + ((struct cifsFileInfo *) file->
  13457. + private_data)->netfid,
  13458. + length,
  13459. + pfLock->fl_start, 0, 1, lockType,
  13460. + 0 /* wait flag */ );
  13461. + if (rc == 0) {
  13462. + rc = CIFSSMBLock(xid, pTcon,
  13463. + ((struct cifsFileInfo *) file->
  13464. + private_data)->netfid,
  13465. + length,
  13466. + pfLock->fl_start, 1 /* numUnlock */ ,
  13467. + 0 /* numLock */ , lockType,
  13468. + 0 /* wait flag */ );
  13469. + pfLock->fl_type = F_UNLCK;
  13470. + if (rc != 0)
  13471. + cERROR(1,
  13472. + ("Error unlocking previously locked range %d during test of lock ",
  13473. + rc));
  13474. + rc = 0;
  13475. +
  13476. + } else {
  13477. + /* if rc == ERR_SHARING_VIOLATION ? */
  13478. + rc = 0; /* do not change lock type to unlock since range in use */
  13479. + }
  13480. +
  13481. + FreeXid(xid);
  13482. + return rc;
  13483. + }
  13484. +
  13485. + rc = CIFSSMBLock(xid, pTcon,
  13486. + ((struct cifsFileInfo *) file->private_data)->
  13487. + netfid, length,
  13488. + pfLock->fl_start, numUnlock, numLock, lockType,
  13489. + wait_flag);
  13490. + FreeXid(xid);
  13491. + return rc;
  13492. +}
  13493. +
  13494. +ssize_t
  13495. +cifs_write(struct file * file, const char *write_data,
  13496. + size_t write_size, loff_t * poffset)
  13497. +{
  13498. + int rc = 0;
  13499. + unsigned int bytes_written = 0;
  13500. + unsigned int total_written;
  13501. + struct cifs_sb_info *cifs_sb;
  13502. + struct cifsTconInfo *pTcon;
  13503. + int xid, long_op;
  13504. + struct cifsFileInfo * open_file;
  13505. +
  13506. + if(file->f_dentry == NULL)
  13507. + return -EBADF;
  13508. +
  13509. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  13510. + if(cifs_sb == NULL) {
  13511. + return -EBADF;
  13512. + }
  13513. + pTcon = cifs_sb->tcon;
  13514. +
  13515. + /*cFYI(1,
  13516. + (" write %d bytes to offset %lld of %s", write_size,
  13517. + *poffset, file->f_dentry->d_name.name)); */
  13518. +
  13519. + if (file->private_data == NULL) {
  13520. + return -EBADF;
  13521. + } else {
  13522. + open_file = (struct cifsFileInfo *) file->private_data;
  13523. + }
  13524. +
  13525. + xid = GetXid();
  13526. + if(file->f_dentry->d_inode == NULL) {
  13527. + FreeXid(xid);
  13528. + return -EBADF;
  13529. + }
  13530. +
  13531. + if (*poffset > file->f_dentry->d_inode->i_size)
  13532. + long_op = 2; /* writes past end of file can take a long time */
  13533. + else
  13534. + long_op = 1;
  13535. +
  13536. + for (total_written = 0; write_size > total_written;
  13537. + total_written += bytes_written) {
  13538. + rc = -EAGAIN;
  13539. + while(rc == -EAGAIN) {
  13540. + if(file->private_data == NULL) {
  13541. + /* file has been closed on us */
  13542. + FreeXid(xid);
  13543. + /* if we have gotten here we have written some data
  13544. + and blocked, and the file has been freed on us
  13545. + while we blocked so return what we managed to write */
  13546. + return total_written;
  13547. + }
  13548. + if(open_file->closePend) {
  13549. + FreeXid(xid);
  13550. + if(total_written)
  13551. + return total_written;
  13552. + else
  13553. + return -EBADF;
  13554. + }
  13555. + if (open_file->invalidHandle) {
  13556. + if((file->f_dentry == NULL) ||
  13557. + (file->f_dentry->d_inode == NULL)) {
  13558. + FreeXid(xid);
  13559. + return total_written;
  13560. + }
  13561. + /* we could deadlock if we called
  13562. + filemap_fdatawait from here so tell
  13563. + reopen_file not to flush data to server now */
  13564. + rc = cifs_reopen_file(file->f_dentry->d_inode,
  13565. + file,FALSE);
  13566. + if(rc != 0)
  13567. + break;
  13568. + }
  13569. +
  13570. + rc = CIFSSMBWrite(xid, pTcon,
  13571. + open_file->netfid,
  13572. + write_size - total_written, *poffset,
  13573. + &bytes_written,
  13574. + write_data + total_written, long_op);
  13575. + }
  13576. + if (rc || (bytes_written == 0)) {
  13577. + if (total_written)
  13578. + break;
  13579. + else {
  13580. + FreeXid(xid);
  13581. + return rc;
  13582. + }
  13583. + } else
  13584. + *poffset += bytes_written;
  13585. + long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
  13586. + }
  13587. +
  13588. +#ifdef CONFIG_CIFS_STATS
  13589. + if(total_written > 0) {
  13590. + atomic_inc(&pTcon->num_writes);
  13591. + spin_lock(&pTcon->stat_lock);
  13592. + pTcon->bytes_written += total_written;
  13593. + spin_unlock(&pTcon->stat_lock);
  13594. + }
  13595. +#endif
  13596. +
  13597. + /* since the write may have blocked check these pointers again */
  13598. + if(file->f_dentry) {
  13599. + if(file->f_dentry->d_inode) {
  13600. + file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
  13601. + CURRENT_TIME;
  13602. + if (total_written > 0) {
  13603. + if (*poffset > file->f_dentry->d_inode->i_size)
  13604. + file->f_dentry->d_inode->i_size = *poffset;
  13605. + }
  13606. + mark_inode_dirty_sync(file->f_dentry->d_inode);
  13607. + }
  13608. + }
  13609. + FreeXid(xid);
  13610. + return total_written;
  13611. +}
  13612. +
  13613. +static int
  13614. +cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
  13615. +{
  13616. + struct address_space *mapping = page->mapping;
  13617. + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
  13618. + char * write_data;
  13619. + int rc = -EFAULT;
  13620. + int bytes_written = 0;
  13621. + struct cifs_sb_info *cifs_sb;
  13622. + struct cifsTconInfo *pTcon;
  13623. + struct inode *inode;
  13624. + struct cifsInodeInfo *cifsInode;
  13625. + struct cifsFileInfo *open_file = NULL;
  13626. + struct list_head *tmp;
  13627. + struct list_head *tmp1;
  13628. +
  13629. + if (!mapping) {
  13630. + return -EFAULT;
  13631. + } else if(!mapping->host) {
  13632. + return -EFAULT;
  13633. + }
  13634. +
  13635. + inode = page->mapping->host;
  13636. + cifs_sb = CIFS_SB(inode->i_sb);
  13637. + pTcon = cifs_sb->tcon;
  13638. +
  13639. + offset += (loff_t)from;
  13640. + write_data = kmap(page);
  13641. + write_data += from;
  13642. +
  13643. + if((to > PAGE_CACHE_SIZE) || (from > to)) {
  13644. + kunmap(page);
  13645. + return -EIO;
  13646. + }
  13647. +
  13648. + /* racing with truncate? */
  13649. + if(offset > mapping->host->i_size) {
  13650. + kunmap(page);
  13651. + return 0; /* don't care */
  13652. + }
  13653. +
  13654. + /* check to make sure that we are not extending the file */
  13655. + if(mapping->host->i_size - offset < (loff_t)to)
  13656. + to = (unsigned)(mapping->host->i_size - offset);
  13657. +
  13658. +
  13659. + cifsInode = CIFS_I(mapping->host);
  13660. + read_lock(&GlobalSMBSeslock);
  13661. + /* BB we should start at the end */
  13662. + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
  13663. + open_file = list_entry(tmp,struct cifsFileInfo, flist);
  13664. + if(open_file->closePend)
  13665. + continue;
  13666. + /* We check if file is open for writing first */
  13667. + if((open_file->pfile) &&
  13668. + ((open_file->pfile->f_flags & O_RDWR) ||
  13669. + (open_file->pfile->f_flags & O_WRONLY))) {
  13670. + read_unlock(&GlobalSMBSeslock);
  13671. + bytes_written = cifs_write(open_file->pfile, write_data,
  13672. + to-from, &offset);
  13673. + read_lock(&GlobalSMBSeslock);
  13674. + /* Does mm or vfs already set times? */
  13675. + inode->i_atime = inode->i_mtime = CURRENT_TIME;
  13676. + if ((bytes_written > 0) && (offset)) {
  13677. + rc = 0;
  13678. + } else if(bytes_written < 0) {
  13679. + if(rc == -EBADF) {
  13680. + /* have seen a case in which
  13681. + kernel seemed to have closed/freed a file
  13682. + even with writes active so we might as well
  13683. + see if there are other file structs to try
  13684. + for the same inode before giving up */
  13685. + continue;
  13686. + } else
  13687. + rc = bytes_written;
  13688. + }
  13689. + break; /* now that we found a valid file handle
  13690. + and tried to write to it we are done, no
  13691. + sense continuing to loop looking for another */
  13692. + }
  13693. + if(tmp->next == NULL) {
  13694. + cFYI(1,("File instance %p removed",tmp));
  13695. + break;
  13696. + }
  13697. + }
  13698. + read_unlock(&GlobalSMBSeslock);
  13699. + if(open_file == NULL) {
  13700. + cFYI(1,("No writeable filehandles for inode"));
  13701. + rc = -EIO;
  13702. + }
  13703. +
  13704. + kunmap(page);
  13705. + return rc;
  13706. +}
  13707. +
  13708. +#if 0
  13709. +static int
  13710. +cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
  13711. +{
  13712. + int rc = -EFAULT;
  13713. + int xid;
  13714. +
  13715. + xid = GetXid();
  13716. +/* call 16K write then Setpageuptodate */
  13717. + FreeXid(xid);
  13718. + return rc;
  13719. +}
  13720. +#endif
  13721. +
  13722. +static int
  13723. +cifs_writepage(struct page* page)
  13724. +{
  13725. + int rc = -EFAULT;
  13726. + int xid;
  13727. +
  13728. + xid = GetXid();
  13729. +/* BB add check for wbc flags */
  13730. + page_cache_get(page);
  13731. + if (!Page_Uptodate(page)) {
  13732. + cFYI(1,("ppw - page not up to date"));
  13733. + }
  13734. +
  13735. + rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
  13736. + SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
  13737. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
  13738. + unlock_page(page);
  13739. +#else
  13740. + UnlockPage(page);
  13741. +#endif
  13742. + page_cache_release(page);
  13743. + FreeXid(xid);
  13744. + return rc;
  13745. +}
  13746. +
  13747. +static int
  13748. +cifs_commit_write(struct file *file, struct page *page, unsigned offset,
  13749. + unsigned to)
  13750. +{
  13751. + int xid;
  13752. + int rc = 0;
  13753. + struct inode *inode = page->mapping->host;
  13754. + loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
  13755. + char * page_data;
  13756. +
  13757. + xid = GetXid();
  13758. + cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
  13759. + if (position > inode->i_size){
  13760. + inode->i_size = position;
  13761. + /*if (file->private_data == NULL) {
  13762. + rc = -EBADF;
  13763. + } else {
  13764. + open_file = (struct cifsFileInfo *)file->private_data;
  13765. + cifs_sb = CIFS_SB(inode->i_sb);
  13766. + rc = -EAGAIN;
  13767. + while(rc == -EAGAIN) {
  13768. + if((open_file->invalidHandle) &&
  13769. + (!open_file->closePend)) {
  13770. + rc = cifs_reopen_file(file->f_dentry->d_inode,file);
  13771. + if(rc != 0)
  13772. + break;
  13773. + }
  13774. + if(!open_file->closePend) {
  13775. + rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
  13776. + position, open_file->netfid,
  13777. + open_file->pid,FALSE);
  13778. + } else {
  13779. + rc = -EBADF;
  13780. + break;
  13781. + }
  13782. + }
  13783. + cFYI(1,(" SetEOF (commit write) rc = %d",rc));
  13784. + }*/
  13785. + }
  13786. + if (!Page_Uptodate(page)) {
  13787. + position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
  13788. + /* can not rely on (or let) writepage write this data */
  13789. + if(to < offset) {
  13790. + cFYI(1,("Illegal offsets, can not copy from %d to %d",
  13791. + offset,to));
  13792. + FreeXid(xid);
  13793. + return rc;
  13794. + }
  13795. + /* this is probably better than directly calling
  13796. + partialpage_write since in this function
  13797. + the file handle is known which we might as well
  13798. + leverage */
  13799. + /* BB check if anything else missing out of ppw */
  13800. + /* such as updating last write time */
  13801. + page_data = kmap(page);
  13802. + rc = cifs_write(file, page_data+offset,to-offset,
  13803. + &position);
  13804. + if(rc > 0)
  13805. + rc = 0;
  13806. + /* else if rc < 0 should we set writebehind rc? */
  13807. + kunmap(page);
  13808. + } else {
  13809. + set_page_dirty(page);
  13810. + }
  13811. +
  13812. + FreeXid(xid);
  13813. + return rc;
  13814. +}
  13815. +
  13816. +int
  13817. +cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
  13818. +{
  13819. + int xid;
  13820. + int rc = 0;
  13821. + struct inode * inode = file->f_dentry->d_inode;
  13822. +
  13823. + xid = GetXid();
  13824. +
  13825. + cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
  13826. + dentry->d_name.name, datasync));
  13827. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
  13828. + rc = filemap_fdatasync(inode->i_mapping);
  13829. +#else
  13830. + filemap_fdatasync(inode->i_mapping);
  13831. +#endif
  13832. + if(rc == 0)
  13833. + CIFS_I(inode)->write_behind_rc = 0;
  13834. + FreeXid(xid);
  13835. + return rc;
  13836. +}
  13837. +
  13838. +static int
  13839. +cifs_sync_page(struct page *page)
  13840. +{
  13841. + struct address_space *mapping;
  13842. + struct inode *inode;
  13843. + unsigned long index = page->index;
  13844. + unsigned int rpages = 0;
  13845. + int rc = 0;
  13846. +
  13847. + cFYI(1,("sync page %p",page));
  13848. + mapping = page->mapping;
  13849. + if (!mapping)
  13850. + return 0;
  13851. + inode = mapping->host;
  13852. + if (!inode)
  13853. + return 0;
  13854. +
  13855. +/* fill in rpages then
  13856. + result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
  13857. +
  13858. + cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
  13859. +
  13860. + if (rc < 0)
  13861. + return rc;
  13862. + return 0;
  13863. +}
  13864. +
  13865. +/*
  13866. + * As file closes, flush all cached write data for this inode checking
  13867. + * for write behind errors.
  13868. + *
  13869. + */
  13870. +int cifs_flush(struct file *file)
  13871. +{
  13872. + struct inode * inode = file->f_dentry->d_inode;
  13873. + int rc = 0;
  13874. +
  13875. + /* Rather than do the steps manually: */
  13876. + /* lock the inode for writing */
  13877. + /* loop through pages looking for write behind data (dirty pages) */
  13878. + /* coalesce into contiguous 16K (or smaller) chunks to write to server */
  13879. + /* send to server (prefer in parallel) */
  13880. + /* deal with writebehind errors */
  13881. + /* unlock inode for writing */
  13882. + /* filemapfdatawrite appears easier for the time being */
  13883. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
  13884. + rc = filemap_fdatasync(inode->i_mapping);
  13885. +#else
  13886. + filemap_fdatasync(inode->i_mapping);
  13887. +#endif
  13888. + if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
  13889. + CIFS_I(inode)->write_behind_rc = 0;
  13890. +
  13891. + cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
  13892. +
  13893. + return rc;
  13894. +}
  13895. +
  13896. +
  13897. +ssize_t
  13898. +cifs_read(struct file * file, char *read_data, size_t read_size,
  13899. + loff_t * poffset)
  13900. +{
  13901. + int rc = -EACCES;
  13902. + unsigned int bytes_read = 0;
  13903. + unsigned int total_read;
  13904. + unsigned int current_read_size;
  13905. + struct cifs_sb_info *cifs_sb;
  13906. + struct cifsTconInfo *pTcon;
  13907. + int xid;
  13908. + char * current_offset;
  13909. + struct cifsFileInfo * open_file;
  13910. +
  13911. + xid = GetXid();
  13912. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  13913. + pTcon = cifs_sb->tcon;
  13914. +
  13915. + if (file->private_data == NULL) {
  13916. + FreeXid(xid);
  13917. + return -EBADF;
  13918. + }
  13919. + open_file = (struct cifsFileInfo *)file->private_data;
  13920. +
  13921. + if((file->f_flags & O_ACCMODE) == O_WRONLY) {
  13922. + cFYI(1,("attempting read on write only file instance"));
  13923. + }
  13924. +
  13925. + for (total_read = 0,current_offset=read_data; read_size > total_read;
  13926. + total_read += bytes_read,current_offset+=bytes_read) {
  13927. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  13928. + current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
  13929. +#else
  13930. + current_read_size = min(read_size - total_read,cifs_sb->rsize);
  13931. +#endif
  13932. + rc = -EAGAIN;
  13933. + while(rc == -EAGAIN) {
  13934. + if ((open_file->invalidHandle) && (!open_file->closePend)) {
  13935. + rc = cifs_reopen_file(file->f_dentry->d_inode,
  13936. + file,TRUE);
  13937. + if(rc != 0)
  13938. + break;
  13939. + }
  13940. +
  13941. + rc = CIFSSMBRead(xid, pTcon,
  13942. + open_file->netfid,
  13943. + current_read_size, *poffset,
  13944. + &bytes_read, &current_offset);
  13945. + }
  13946. + if (rc || (bytes_read == 0)) {
  13947. + if (total_read) {
  13948. + break;
  13949. + } else {
  13950. + FreeXid(xid);
  13951. + return rc;
  13952. + }
  13953. + } else {
  13954. +#ifdef CONFIG_CIFS_STATS
  13955. + atomic_inc(&pTcon->num_reads);
  13956. + spin_lock(&pTcon->stat_lock);
  13957. + pTcon->bytes_read += total_read;
  13958. + spin_unlock(&pTcon->stat_lock);
  13959. +#endif
  13960. + *poffset += bytes_read;
  13961. + }
  13962. + }
  13963. + FreeXid(xid);
  13964. + return total_read;
  13965. +}
  13966. +
  13967. +int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
  13968. +{
  13969. + struct dentry * dentry = file->f_dentry;
  13970. + int rc, xid;
  13971. +
  13972. + xid = GetXid();
  13973. + rc = cifs_revalidate(dentry);
  13974. + if (rc) {
  13975. + cFYI(1,("Validation prior to mmap failed, error=%d", rc));
  13976. + FreeXid(xid);
  13977. + return rc;
  13978. + }
  13979. + rc = generic_file_mmap(file, vma);
  13980. + FreeXid(xid);
  13981. + return rc;
  13982. +}
  13983. +
  13984. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
  13985. +static void cifs_copy_cache_pages(struct address_space *mapping,
  13986. + struct list_head *pages, int bytes_read,
  13987. + char *data,struct pagevec * plru_pvec)
  13988. +{
  13989. + struct page *page;
  13990. + char * target;
  13991. +
  13992. + while (bytes_read > 0) {
  13993. + if(list_empty(pages))
  13994. + break;
  13995. +
  13996. + page = list_entry(pages->prev, struct page, lru);
  13997. + list_del(&page->lru);
  13998. +
  13999. + if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
  14000. + page_cache_release(page);
  14001. + cFYI(1,("Add page cache failed"));
  14002. + continue;
  14003. + }
  14004. +
  14005. + target = kmap_atomic(page,KM_USER0);
  14006. +
  14007. + if(PAGE_CACHE_SIZE > bytes_read) {
  14008. + memcpy(target,data,bytes_read);
  14009. + /* zero the tail end of this partial page */
  14010. + memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
  14011. + bytes_read = 0;
  14012. + } else {
  14013. + memcpy(target,data,PAGE_CACHE_SIZE);
  14014. + bytes_read -= PAGE_CACHE_SIZE;
  14015. + }
  14016. + kunmap_atomic(target,KM_USER0);
  14017. +
  14018. + flush_dcache_page(page);
  14019. + SetPageUptodate(page);
  14020. + unlock_page(page);
  14021. + if (!pagevec_add(plru_pvec, page))
  14022. + __pagevec_lru_add(plru_pvec);
  14023. + data += PAGE_CACHE_SIZE;
  14024. + }
  14025. + return;
  14026. +}
  14027. +
  14028. +
  14029. +static int
  14030. +cifs_readpages(struct file *file, struct address_space *mapping,
  14031. + struct list_head *page_list, unsigned num_pages)
  14032. +{
  14033. + int rc = -EACCES;
  14034. + int xid;
  14035. + loff_t offset;
  14036. + struct page * page;
  14037. + struct cifs_sb_info *cifs_sb;
  14038. + struct cifsTconInfo *pTcon;
  14039. + int bytes_read = 0;
  14040. + unsigned int read_size,i;
  14041. + char * smb_read_data = NULL;
  14042. + struct smb_com_read_rsp * pSMBr;
  14043. + struct pagevec lru_pvec;
  14044. + struct cifsFileInfo * open_file;
  14045. +
  14046. + xid = GetXid();
  14047. + if (file->private_data == NULL) {
  14048. + FreeXid(xid);
  14049. + return -EBADF;
  14050. + }
  14051. + open_file = (struct cifsFileInfo *)file->private_data;
  14052. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  14053. + pTcon = cifs_sb->tcon;
  14054. +
  14055. + pagevec_init(&lru_pvec, 0);
  14056. +
  14057. + for(i = 0;i<num_pages;) {
  14058. + unsigned contig_pages;
  14059. + struct page * tmp_page;
  14060. + unsigned long expected_index;
  14061. +
  14062. + if(list_empty(page_list)) {
  14063. + break;
  14064. + }
  14065. + page = list_entry(page_list->prev, struct page, lru);
  14066. + offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
  14067. +
  14068. + /* count adjacent pages that we will read into */
  14069. + contig_pages = 0;
  14070. + expected_index = list_entry(page_list->prev,struct page,lru)->index;
  14071. + list_for_each_entry_reverse(tmp_page,page_list,lru) {
  14072. + if(tmp_page->index == expected_index) {
  14073. + contig_pages++;
  14074. + expected_index++;
  14075. + } else {
  14076. + break;
  14077. + }
  14078. + }
  14079. + if(contig_pages + i > num_pages) {
  14080. + contig_pages = num_pages - i;
  14081. + }
  14082. +
  14083. + /* for reads over a certain size could initiate async read ahead */
  14084. +
  14085. + read_size = contig_pages * PAGE_CACHE_SIZE;
  14086. + /* Read size needs to be in multiples of one page */
  14087. + read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
  14088. +
  14089. + rc = -EAGAIN;
  14090. + while(rc == -EAGAIN) {
  14091. + if ((open_file->invalidHandle) && (!open_file->closePend)) {
  14092. + rc = cifs_reopen_file(file->f_dentry->d_inode,
  14093. + file, TRUE);
  14094. + if(rc != 0)
  14095. + break;
  14096. + }
  14097. +
  14098. + rc = CIFSSMBRead(xid, pTcon,
  14099. + open_file->netfid,
  14100. + read_size, offset,
  14101. + &bytes_read, &smb_read_data);
  14102. + /* BB need to check return code here */
  14103. + if(rc== -EAGAIN) {
  14104. + if(smb_read_data) {
  14105. + cifs_buf_release(smb_read_data);
  14106. + smb_read_data = NULL;
  14107. + }
  14108. + }
  14109. + }
  14110. + if ((rc < 0) || (smb_read_data == NULL)) {
  14111. + cFYI(1,("Read error in readpages: %d",rc));
  14112. + /* clean up remaing pages off list */
  14113. + while (!list_empty(page_list) && (i < num_pages)) {
  14114. + page = list_entry(page_list->prev, struct page, lru);
  14115. + list_del(&page->lru);
  14116. + page_cache_release(page);
  14117. + }
  14118. + break;
  14119. + } else if (bytes_read > 0) {
  14120. + pSMBr = (struct smb_com_read_rsp *)smb_read_data;
  14121. + cifs_copy_cache_pages(mapping, page_list, bytes_read,
  14122. + smb_read_data + 4 /* RFC1001 hdr */ +
  14123. + le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
  14124. +
  14125. + i += bytes_read >> PAGE_CACHE_SHIFT;
  14126. +#ifdef CONFIG_CIFS_STATS
  14127. + atomic_inc(&pTcon->num_reads);
  14128. + spin_lock(&pTcon->stat_lock);
  14129. + pTcon->bytes_read += bytes_read;
  14130. + spin_unlock(&pTcon->stat_lock);
  14131. +#endif
  14132. + if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
  14133. + cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
  14134. +
  14135. + i++; /* account for partial page */
  14136. +
  14137. + /* server copy of file can have smaller size than client */
  14138. + /* BB do we need to verify this common case ? this case is ok -
  14139. + if we are at server EOF we will hit it on next read */
  14140. +
  14141. + /* while(!list_empty(page_list) && (i < num_pages)) {
  14142. + page = list_entry(page_list->prev,struct page, list);
  14143. + list_del(&page->list);
  14144. + page_cache_release(page);
  14145. + }
  14146. + break; */
  14147. + }
  14148. + } else {
  14149. + cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
  14150. + /* BB turn off caching and do new lookup on file size at server? */
  14151. + while (!list_empty(page_list) && (i < num_pages)) {
  14152. + page = list_entry(page_list->prev, struct page, lru);
  14153. + list_del(&page->lru);
  14154. + page_cache_release(page); /* BB removeme - replace with zero of page? */
  14155. + }
  14156. + break;
  14157. + }
  14158. + if(smb_read_data) {
  14159. + cifs_buf_release(smb_read_data);
  14160. + smb_read_data = NULL;
  14161. + }
  14162. + bytes_read = 0;
  14163. + }
  14164. +
  14165. + pagevec_lru_add(&lru_pvec);
  14166. +
  14167. +/* need to free smb_read_data buf before exit */
  14168. + if(smb_read_data) {
  14169. + cifs_buf_release(smb_read_data);
  14170. + smb_read_data = NULL;
  14171. + }
  14172. +
  14173. + FreeXid(xid);
  14174. + return rc;
  14175. +}
  14176. +#endif
  14177. +
  14178. +static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
  14179. +{
  14180. + char * read_data;
  14181. + int rc;
  14182. +
  14183. + page_cache_get(page);
  14184. + read_data = kmap(page);
  14185. + /* for reads over a certain size could initiate async read ahead */
  14186. +
  14187. + rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
  14188. +
  14189. + if (rc < 0)
  14190. + goto io_error;
  14191. + else {
  14192. + cFYI(1,("Bytes read %d ",rc));
  14193. + }
  14194. +
  14195. + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  14196. +
  14197. + if(PAGE_CACHE_SIZE > rc) {
  14198. + memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
  14199. + }
  14200. + flush_dcache_page(page);
  14201. + SetPageUptodate(page);
  14202. + rc = 0;
  14203. +
  14204. +io_error:
  14205. + kunmap(page);
  14206. + page_cache_release(page);
  14207. + return rc;
  14208. +}
  14209. +
  14210. +static int
  14211. +cifs_readpage(struct file *file, struct page *page)
  14212. +{
  14213. + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
  14214. + int rc = -EACCES;
  14215. + int xid;
  14216. +
  14217. + xid = GetXid();
  14218. +
  14219. + if (file->private_data == NULL) {
  14220. + FreeXid(xid);
  14221. + return -EBADF;
  14222. + }
  14223. +
  14224. + cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
  14225. +
  14226. + rc = cifs_readpage_worker(file,page,&offset);
  14227. +
  14228. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
  14229. + unlock_page(page);
  14230. +#else
  14231. + UnlockPage(page);
  14232. +#endif
  14233. +
  14234. + FreeXid(xid);
  14235. + return rc;
  14236. +}
  14237. +
  14238. +/* We do not want to update the file size from server for inodes
  14239. + open for write - to avoid races with writepage extending
  14240. + the file - in the future we could consider allowing
  14241. + refreshing the inode only on increases in the file size
  14242. + but this is tricky to do without racing with writebehind
  14243. + page caching in the current Linux kernel design */
  14244. +
  14245. +int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
  14246. +{
  14247. + struct list_head *tmp;
  14248. + struct list_head *tmp1;
  14249. + struct cifsFileInfo *open_file = NULL;
  14250. + int rc = TRUE;
  14251. +
  14252. + if(cifsInode == NULL)
  14253. + return rc;
  14254. +
  14255. + read_lock(&GlobalSMBSeslock);
  14256. + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
  14257. + open_file = list_entry(tmp,struct cifsFileInfo, flist);
  14258. + if(open_file == NULL)
  14259. + break;
  14260. + if(open_file->closePend)
  14261. + continue;
  14262. + /* We check if file is open for writing,
  14263. + BB we could supplement this with a check to see if file size
  14264. + changes have been flushed to server - ie inode metadata dirty */
  14265. + if((open_file->pfile) &&
  14266. + ((open_file->pfile->f_flags & O_RDWR) ||
  14267. + (open_file->pfile->f_flags & O_WRONLY))) {
  14268. + rc = FALSE;
  14269. + break;
  14270. + }
  14271. + if(tmp->next == NULL) {
  14272. + cFYI(1,("File instance %p removed",tmp));
  14273. + break;
  14274. + }
  14275. + }
  14276. + read_unlock(&GlobalSMBSeslock);
  14277. + return rc;
  14278. +}
  14279. +
  14280. +
  14281. +void
  14282. +fill_in_inode(struct inode *tmp_inode,
  14283. + FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
  14284. +{
  14285. + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
  14286. + struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
  14287. +
  14288. + pfindData->ExtFileAttributes =
  14289. + le32_to_cpu(pfindData->ExtFileAttributes);
  14290. + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
  14291. + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
  14292. + cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
  14293. + cifsInfo->time = jiffies;
  14294. +
  14295. + /* Linux can not store file creation time unfortunately so ignore it */
  14296. + tmp_inode->i_atime =
  14297. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
  14298. + tmp_inode->i_mtime =
  14299. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
  14300. + tmp_inode->i_ctime =
  14301. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
  14302. + /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
  14303. + /* 2767 perms - indicate mandatory locking */
  14304. + /* BB fill in uid and gid here? with help from winbind?
  14305. + or retrieve from NTFS stream extended attribute */
  14306. + if(atomic_read(&cifsInfo->inUse) == 0) {
  14307. + tmp_inode->i_uid = cifs_sb->mnt_uid;
  14308. + tmp_inode->i_gid = cifs_sb->mnt_gid;
  14309. + /* set default mode. will override for dirs below */
  14310. + tmp_inode->i_mode = cifs_sb->mnt_file_mode;
  14311. + }
  14312. +
  14313. + cFYI(0,
  14314. + ("CIFS FFIRST: Attributes came in as 0x%x",
  14315. + pfindData->ExtFileAttributes));
  14316. + if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
  14317. + *pobject_type = DT_LNK;
  14318. + /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
  14319. + tmp_inode->i_mode |= S_IFLNK;
  14320. + } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
  14321. + *pobject_type = DT_DIR;
  14322. + /* override default perms since we do not lock dirs */
  14323. + if(atomic_read(&cifsInfo->inUse) == 0) {
  14324. + tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
  14325. + }
  14326. + tmp_inode->i_mode |= S_IFDIR;
  14327. + } else {
  14328. + *pobject_type = DT_REG;
  14329. + tmp_inode->i_mode |= S_IFREG;
  14330. + if(pfindData->ExtFileAttributes & ATTR_READONLY)
  14331. + tmp_inode->i_mode &= ~(S_IWUGO);
  14332. +
  14333. + }/* could add code here - to validate if device or weird share type? */
  14334. +
  14335. + /* can not fill in nlink here as in qpathinfo version and Unx search */
  14336. + if(atomic_read(&cifsInfo->inUse) == 0) {
  14337. + atomic_set(&cifsInfo->inUse,1);
  14338. + }
  14339. + if(is_size_safe_to_change(cifsInfo)) {
  14340. + /* can not safely change the file size here if the
  14341. + client is writing to it due to potential races */
  14342. + tmp_inode->i_size = pfindData->EndOfFile;
  14343. +
  14344. + /* 512 bytes (2**9) is the fake blocksize that must be used */
  14345. + /* for this calculation, even though the reported blocksize is larger */
  14346. + tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
  14347. + }
  14348. +
  14349. + if (pfindData->AllocationSize < pfindData->EndOfFile)
  14350. + cFYI(1, ("Possible sparse file: allocation size less than end of file "));
  14351. + cFYI(1,
  14352. + ("File Size %ld and blocks %ld and blocksize %ld",
  14353. + (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
  14354. + tmp_inode->i_blksize));
  14355. + if (S_ISREG(tmp_inode->i_mode)) {
  14356. + cFYI(1, (" File inode "));
  14357. + tmp_inode->i_op = &cifs_file_inode_ops;
  14358. + tmp_inode->i_fop = &cifs_file_ops;
  14359. + tmp_inode->i_data.a_ops = &cifs_addr_ops;
  14360. + } else if (S_ISDIR(tmp_inode->i_mode)) {
  14361. + cFYI(1, (" Directory inode"));
  14362. + tmp_inode->i_op = &cifs_dir_inode_ops;
  14363. + tmp_inode->i_fop = &cifs_dir_ops;
  14364. + } else if (S_ISLNK(tmp_inode->i_mode)) {
  14365. + cFYI(1, (" Symbolic Link inode "));
  14366. + tmp_inode->i_op = &cifs_symlink_inode_ops;
  14367. + } else {
  14368. + cFYI(1, (" Init special inode "));
  14369. + init_special_inode(tmp_inode, tmp_inode->i_mode,
  14370. + kdev_t_to_nr(tmp_inode->i_rdev));
  14371. + }
  14372. +}
  14373. +
  14374. +void
  14375. +unix_fill_in_inode(struct inode *tmp_inode,
  14376. + FILE_UNIX_INFO * pfindData, int *pobject_type)
  14377. +{
  14378. + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
  14379. + cifsInfo->time = jiffies;
  14380. + atomic_inc(&cifsInfo->inUse);
  14381. +
  14382. + tmp_inode->i_atime =
  14383. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
  14384. + tmp_inode->i_mtime =
  14385. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
  14386. + tmp_inode->i_ctime =
  14387. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
  14388. +
  14389. + tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
  14390. + pfindData->Type = le32_to_cpu(pfindData->Type);
  14391. + if (pfindData->Type == UNIX_FILE) {
  14392. + *pobject_type = DT_REG;
  14393. + tmp_inode->i_mode |= S_IFREG;
  14394. + } else if (pfindData->Type == UNIX_SYMLINK) {
  14395. + *pobject_type = DT_LNK;
  14396. + tmp_inode->i_mode |= S_IFLNK;
  14397. + } else if (pfindData->Type == UNIX_DIR) {
  14398. + *pobject_type = DT_DIR;
  14399. + tmp_inode->i_mode |= S_IFDIR;
  14400. + } else if (pfindData->Type == UNIX_CHARDEV) {
  14401. + *pobject_type = DT_CHR;
  14402. + tmp_inode->i_mode |= S_IFCHR;
  14403. + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
  14404. + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
  14405. + } else if (pfindData->Type == UNIX_BLOCKDEV) {
  14406. + *pobject_type = DT_BLK;
  14407. + tmp_inode->i_mode |= S_IFBLK;
  14408. + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
  14409. + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
  14410. + } else if (pfindData->Type == UNIX_FIFO) {
  14411. + *pobject_type = DT_FIFO;
  14412. + tmp_inode->i_mode |= S_IFIFO;
  14413. + } else if (pfindData->Type == UNIX_SOCKET) {
  14414. + *pobject_type = DT_SOCK;
  14415. + tmp_inode->i_mode |= S_IFSOCK;
  14416. + }
  14417. +
  14418. + tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
  14419. + tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
  14420. + tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
  14421. +
  14422. + pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
  14423. + if(is_size_safe_to_change(cifsInfo)) {
  14424. + /* can not safely change the file size here if the
  14425. + client is writing to it due to potential races */
  14426. + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
  14427. + tmp_inode->i_size = pfindData->EndOfFile;
  14428. +
  14429. + /* 512 bytes (2**9) is the fake blocksize that must be used */
  14430. + /* for this calculation, not the real blocksize */
  14431. + tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
  14432. + }
  14433. +
  14434. + if (S_ISREG(tmp_inode->i_mode)) {
  14435. + cFYI(1, ("File inode"));
  14436. + tmp_inode->i_op = &cifs_file_inode_ops;
  14437. + tmp_inode->i_fop = &cifs_file_ops;
  14438. + tmp_inode->i_data.a_ops = &cifs_addr_ops;
  14439. + } else if (S_ISDIR(tmp_inode->i_mode)) {
  14440. + cFYI(1, ("Directory inode"));
  14441. + tmp_inode->i_op = &cifs_dir_inode_ops;
  14442. + tmp_inode->i_fop = &cifs_dir_ops;
  14443. + } else if (S_ISLNK(tmp_inode->i_mode)) {
  14444. + cFYI(1, ("Symbolic Link inode"));
  14445. + tmp_inode->i_op = &cifs_symlink_inode_ops;
  14446. +/* tmp_inode->i_fop = *//* do not need to set to anything */
  14447. + } else {
  14448. + cFYI(1, ("Special inode"));
  14449. + init_special_inode(tmp_inode, tmp_inode->i_mode,
  14450. + kdev_t_to_nr(tmp_inode->i_rdev));
  14451. + }
  14452. +}
  14453. +
  14454. +static void
  14455. +construct_dentry(struct qstr *qstring, struct file *file,
  14456. + struct inode **ptmp_inode, struct dentry **pnew_dentry)
  14457. +{
  14458. + struct dentry *tmp_dentry;
  14459. + struct cifs_sb_info *cifs_sb;
  14460. + struct cifsTconInfo *pTcon;
  14461. + struct cifsInodeInfo *pCifsI;
  14462. +
  14463. + cFYI(1, ("For %s ", qstring->name));
  14464. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  14465. + pTcon = cifs_sb->tcon;
  14466. +
  14467. + qstring->hash = full_name_hash(qstring->name, qstring->len);
  14468. + tmp_dentry = d_lookup(file->f_dentry, qstring);
  14469. + if (tmp_dentry) {
  14470. + cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
  14471. + *ptmp_inode = tmp_dentry->d_inode;
  14472. + /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
  14473. + if(*ptmp_inode == NULL) {
  14474. + *ptmp_inode = new_inode(file->f_dentry->d_sb);
  14475. + if(*ptmp_inode == NULL)
  14476. + return;
  14477. + d_instantiate(tmp_dentry, *ptmp_inode);
  14478. + insert_inode_hash(*ptmp_inode);
  14479. + pCifsI = CIFS_I(*ptmp_inode);
  14480. + INIT_LIST_HEAD(&pCifsI->openFileList);
  14481. + /* can not enable caching for this inode
  14482. + until a file instance is open and we
  14483. + can check the oplock flag on the open
  14484. + response */
  14485. + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
  14486. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  14487. + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
  14488. +#endif
  14489. + pCifsI->clientCanCacheRead = FALSE;
  14490. + pCifsI->clientCanCacheAll = FALSE;
  14491. + pCifsI->time = 0;
  14492. + /* do not need to set cifs Attrs since
  14493. + they are about to be overwritten
  14494. + in fill_in_inode */
  14495. + atomic_set(&pCifsI->inUse, 0);
  14496. + }
  14497. + } else {
  14498. + tmp_dentry = d_alloc(file->f_dentry, qstring);
  14499. + if(tmp_dentry == NULL) {
  14500. + cERROR(1,("Failed allocating dentry"));
  14501. + return;
  14502. + }
  14503. +
  14504. + if(ptmp_inode) {
  14505. + *ptmp_inode = new_inode(file->f_dentry->d_sb);
  14506. + if(*ptmp_inode == NULL)
  14507. + return;
  14508. + pCifsI = CIFS_I(*ptmp_inode);
  14509. + insert_inode_hash(*ptmp_inode);
  14510. + INIT_LIST_HEAD(&pCifsI->openFileList);
  14511. + /* can not enable caching for this inode
  14512. + until a file instance is open and we
  14513. + can check the oplock flag on the open
  14514. + response */
  14515. + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
  14516. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  14517. + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
  14518. +#endif
  14519. + pCifsI->clientCanCacheRead = FALSE;
  14520. + pCifsI->clientCanCacheAll = FALSE;
  14521. + pCifsI->time = 0;
  14522. + /* do not need to set cifs Attrs since
  14523. + they are about to be overwritten
  14524. + in fill_in_inode */
  14525. + atomic_set(&pCifsI->inUse, 0);
  14526. + }
  14527. + tmp_dentry->d_op = &cifs_dentry_ops;
  14528. + d_instantiate(tmp_dentry, *ptmp_inode);
  14529. + d_rehash(tmp_dentry);
  14530. + }
  14531. +
  14532. + tmp_dentry->d_time = jiffies;
  14533. + *pnew_dentry = tmp_dentry;
  14534. +}
  14535. +
  14536. +static void reset_resume_key(struct file * dir_file,
  14537. + unsigned char * filename,
  14538. + unsigned int len,int Unicode,struct nls_table * nls_tab) {
  14539. + struct cifsFileInfo *cifsFile;
  14540. +
  14541. + cifsFile = (struct cifsFileInfo *)dir_file->private_data;
  14542. + if(cifsFile == NULL)
  14543. + return;
  14544. + if(cifsFile->search_resume_name) {
  14545. + kfree(cifsFile->search_resume_name);
  14546. + }
  14547. +
  14548. + if(Unicode)
  14549. + len *= 2;
  14550. + cifsFile->resume_name_length = len;
  14551. +
  14552. + cifsFile->search_resume_name =
  14553. + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
  14554. +
  14555. + if(cifsFile->search_resume_name == NULL) {
  14556. + cERROR(1,("failed new resume key allocate, length %d",
  14557. + cifsFile->resume_name_length));
  14558. + return;
  14559. + }
  14560. + if(Unicode)
  14561. + cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
  14562. + filename, len, nls_tab);
  14563. + else
  14564. + memcpy(cifsFile->search_resume_name, filename,
  14565. + cifsFile->resume_name_length);
  14566. + cFYI(1,("Reset resume key to: %s with len %d",filename,len));
  14567. + return;
  14568. +}
  14569. +
  14570. +
  14571. +
  14572. +static int
  14573. +cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
  14574. + struct file *file, filldir_t filldir, void *direntry)
  14575. +{
  14576. + struct inode *tmp_inode;
  14577. + struct dentry *tmp_dentry;
  14578. + int object_type,rc;
  14579. +
  14580. + pqstring->name = pfindData->FileName;
  14581. + pqstring->len = pfindData->FileNameLength;
  14582. +
  14583. + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
  14584. + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
  14585. + return -ENOMEM;
  14586. + }
  14587. + fill_in_inode(tmp_inode, pfindData, &object_type);
  14588. + rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
  14589. + tmp_inode->i_ino, object_type);
  14590. + if(rc) {
  14591. + /* due to readdir error we need to recalculate resume
  14592. + key so next readdir will restart on right entry */
  14593. + cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
  14594. + }
  14595. + dput(tmp_dentry);
  14596. + return rc;
  14597. +}
  14598. +
  14599. +static int
  14600. +cifs_filldir_unix(struct qstr *pqstring,
  14601. + FILE_UNIX_INFO * pUnixFindData, struct file *file,
  14602. + filldir_t filldir, void *direntry)
  14603. +{
  14604. + struct inode *tmp_inode;
  14605. + struct dentry *tmp_dentry;
  14606. + int object_type, rc;
  14607. +
  14608. + pqstring->name = pUnixFindData->FileName;
  14609. + pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
  14610. +
  14611. + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
  14612. + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
  14613. + return -ENOMEM;
  14614. + }
  14615. +
  14616. + unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
  14617. + rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
  14618. + file->f_pos, tmp_inode->i_ino, object_type);
  14619. + if(rc) {
  14620. + /* due to readdir error we need to recalculate resume
  14621. + key so next readdir will restart on right entry */
  14622. + cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
  14623. + }
  14624. + dput(tmp_dentry);
  14625. + return rc;
  14626. +}
  14627. +
  14628. +int
  14629. +cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
  14630. +{
  14631. + int rc = 0;
  14632. + int xid;
  14633. + int Unicode = FALSE;
  14634. + int UnixSearch = FALSE;
  14635. + unsigned int bufsize, i;
  14636. + __u16 searchHandle;
  14637. + struct cifs_sb_info *cifs_sb;
  14638. + struct cifsTconInfo *pTcon;
  14639. + struct cifsFileInfo *cifsFile = NULL;
  14640. + char *full_path = NULL;
  14641. + char *data;
  14642. + struct qstr qstring;
  14643. + T2_FFIRST_RSP_PARMS findParms;
  14644. + T2_FNEXT_RSP_PARMS findNextParms;
  14645. + FILE_DIRECTORY_INFO *pfindData;
  14646. + FILE_DIRECTORY_INFO *lastFindData;
  14647. + FILE_UNIX_INFO *pfindDataUnix;
  14648. +
  14649. + xid = GetXid();
  14650. +
  14651. + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
  14652. + pTcon = cifs_sb->tcon;
  14653. + bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
  14654. + if(bufsize > CIFS_MAX_MSGSIZE) {
  14655. + FreeXid(xid);
  14656. + return -EIO;
  14657. + }
  14658. + data = kmalloc(bufsize, GFP_KERNEL);
  14659. + pfindData = (FILE_DIRECTORY_INFO *) data;
  14660. +
  14661. + if(file->f_dentry == NULL) {
  14662. + FreeXid(xid);
  14663. + return -EIO;
  14664. + }
  14665. + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
  14666. + full_path = build_wildcard_path_from_dentry(file->f_dentry);
  14667. + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
  14668. +
  14669. +
  14670. + cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
  14671. +
  14672. + switch ((int) file->f_pos) {
  14673. + case 0:
  14674. + if (filldir(direntry, ".", 1, file->f_pos,
  14675. + file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
  14676. + cERROR(1, ("Filldir for current dir failed "));
  14677. + break;
  14678. + }
  14679. + file->f_pos++;
  14680. + /* fallthrough */
  14681. + case 1:
  14682. + if (filldir(direntry, "..", 2, file->f_pos,
  14683. + file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
  14684. + cERROR(1, ("Filldir for parent dir failed "));
  14685. + break;
  14686. + }
  14687. + file->f_pos++;
  14688. + /* fallthrough */
  14689. + case 2:
  14690. + if (file->private_data != NULL) {
  14691. + cifsFile =
  14692. + (struct cifsFileInfo *) file->private_data;
  14693. + if (cifsFile->endOfSearch) {
  14694. + if(cifsFile->emptyDir) {
  14695. + cFYI(1, ("End of search, empty dir"));
  14696. + rc = 0;
  14697. + break;
  14698. + }
  14699. + } else {
  14700. + cifsFile->invalidHandle = TRUE;
  14701. + CIFSFindClose(xid, pTcon, cifsFile->netfid);
  14702. + }
  14703. + if(cifsFile->search_resume_name) {
  14704. + kfree(cifsFile->search_resume_name);
  14705. + cifsFile->search_resume_name = NULL;
  14706. + }
  14707. + }
  14708. + rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
  14709. + &findParms, cifs_sb->local_nls,
  14710. + &Unicode, &UnixSearch);
  14711. + cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
  14712. + findParms.EndofSearch));
  14713. +
  14714. + if (rc == 0) {
  14715. + searchHandle = findParms.SearchHandle;
  14716. + if(file->private_data == NULL)
  14717. + file->private_data =
  14718. + kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
  14719. + if (file->private_data) {
  14720. + memset(file->private_data, 0,
  14721. + sizeof (struct cifsFileInfo));
  14722. + cifsFile =
  14723. + (struct cifsFileInfo *) file->private_data;
  14724. + cifsFile->netfid = searchHandle;
  14725. + cifsFile->invalidHandle = FALSE;
  14726. + init_MUTEX(&cifsFile->fh_sem);
  14727. + } else {
  14728. + rc = -ENOMEM;
  14729. + break;
  14730. + }
  14731. +
  14732. + renew_parental_timestamps(file->f_dentry);
  14733. + lastFindData =
  14734. + (FILE_DIRECTORY_INFO *) ((char *) pfindData +
  14735. + findParms.LastNameOffset);
  14736. + if((char *)lastFindData > (char *)pfindData + bufsize) {
  14737. + cFYI(1,("last search entry past end of packet"));
  14738. + rc = -EIO;
  14739. + break;
  14740. + }
  14741. + /* Offset of resume key same for levels 257 and 514 */
  14742. + cifsFile->resume_key = lastFindData->FileIndex;
  14743. + if(UnixSearch == FALSE) {
  14744. + cifsFile->resume_name_length =
  14745. + le32_to_cpu(lastFindData->FileNameLength);
  14746. + if(cifsFile->resume_name_length > bufsize - 64) {
  14747. + cFYI(1,("Illegal resume file name length %d",
  14748. + cifsFile->resume_name_length));
  14749. + rc = -ENOMEM;
  14750. + break;
  14751. + }
  14752. + cifsFile->search_resume_name =
  14753. + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
  14754. + cFYI(1,("Last file: %s with name %d bytes long",
  14755. + lastFindData->FileName,
  14756. + cifsFile->resume_name_length));
  14757. + memcpy(cifsFile->search_resume_name,
  14758. + lastFindData->FileName,
  14759. + cifsFile->resume_name_length);
  14760. + } else {
  14761. + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
  14762. + if (Unicode == TRUE) {
  14763. + for(i=0;(pfindDataUnix->FileName[i]
  14764. + | pfindDataUnix->FileName[i+1]);
  14765. + i+=2) {
  14766. + if(i > bufsize-64)
  14767. + break;
  14768. + }
  14769. + cifsFile->resume_name_length = i + 2;
  14770. + } else {
  14771. + cifsFile->resume_name_length =
  14772. + strnlen(pfindDataUnix->FileName,
  14773. + bufsize-63);
  14774. + }
  14775. + if(cifsFile->resume_name_length > bufsize - 64) {
  14776. + cFYI(1,("Illegal resume file name length %d",
  14777. + cifsFile->resume_name_length));
  14778. + rc = -ENOMEM;
  14779. + break;
  14780. + }
  14781. + cifsFile->search_resume_name =
  14782. + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
  14783. + cFYI(1,("Last file: %s with name %d bytes long",
  14784. + pfindDataUnix->FileName,
  14785. + cifsFile->resume_name_length));
  14786. + memcpy(cifsFile->search_resume_name,
  14787. + pfindDataUnix->FileName,
  14788. + cifsFile->resume_name_length);
  14789. + }
  14790. + for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
  14791. + if (UnixSearch == FALSE) {
  14792. + pfindData->FileNameLength =
  14793. + le32_to_cpu(pfindData->FileNameLength);
  14794. + if (Unicode == TRUE)
  14795. + pfindData->FileNameLength =
  14796. + cifs_strfromUCS_le
  14797. + (pfindData->FileName,
  14798. + (wchar_t *)
  14799. + pfindData->FileName,
  14800. + (pfindData->
  14801. + FileNameLength) / 2,
  14802. + cifs_sb->local_nls);
  14803. + qstring.len = pfindData->FileNameLength;
  14804. + if (((qstring.len != 1)
  14805. + || (pfindData->FileName[0] != '.'))
  14806. + && ((qstring.len != 2)
  14807. + || (pfindData->
  14808. + FileName[0] != '.')
  14809. + || (pfindData->
  14810. + FileName[1] != '.'))) {
  14811. + if(cifs_filldir(&qstring,
  14812. + pfindData,
  14813. + file, filldir,
  14814. + direntry)) {
  14815. + /* do not end search if
  14816. + kernel not ready to take
  14817. + remaining entries yet */
  14818. + reset_resume_key(file, pfindData->FileName,qstring.len,
  14819. + Unicode, cifs_sb->local_nls);
  14820. + findParms.EndofSearch = 0;
  14821. + break;
  14822. + }
  14823. + file->f_pos++;
  14824. + }
  14825. + } else { /* UnixSearch */
  14826. + pfindDataUnix =
  14827. + (FILE_UNIX_INFO *) pfindData;
  14828. + if (Unicode == TRUE)
  14829. + qstring.len =
  14830. + cifs_strfromUCS_le
  14831. + (pfindDataUnix->FileName,
  14832. + (wchar_t *)
  14833. + pfindDataUnix->FileName,
  14834. + MAX_PATHCONF,
  14835. + cifs_sb->local_nls);
  14836. + else
  14837. + qstring.len =
  14838. + strnlen(pfindDataUnix->
  14839. + FileName,
  14840. + MAX_PATHCONF);
  14841. + if (((qstring.len != 1)
  14842. + || (pfindDataUnix->
  14843. + FileName[0] != '.'))
  14844. + && ((qstring.len != 2)
  14845. + || (pfindDataUnix->
  14846. + FileName[0] != '.')
  14847. + || (pfindDataUnix->
  14848. + FileName[1] != '.'))) {
  14849. + if(cifs_filldir_unix(&qstring,
  14850. + pfindDataUnix,
  14851. + file,
  14852. + filldir,
  14853. + direntry)) {
  14854. + /* do not end search if
  14855. + kernel not ready to take
  14856. + remaining entries yet */
  14857. + findParms.EndofSearch = 0;
  14858. + reset_resume_key(file, pfindDataUnix->FileName,
  14859. + qstring.len,Unicode,cifs_sb->local_nls);
  14860. + break;
  14861. + }
  14862. + file->f_pos++;
  14863. + }
  14864. + }
  14865. + /* works also for Unix ff struct since first field of both */
  14866. + pfindData =
  14867. + (FILE_DIRECTORY_INFO *) ((char *) pfindData
  14868. + + le32_to_cpu(pfindData->NextEntryOffset));
  14869. + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
  14870. + /* if(pfindData > lastFindData) rc = -EIO; break; */
  14871. + } /* end for loop */
  14872. + if ((findParms.EndofSearch != 0) && cifsFile) {
  14873. + cifsFile->endOfSearch = TRUE;
  14874. + if(findParms.SearchCount == 2)
  14875. + cifsFile->emptyDir = TRUE;
  14876. + }
  14877. + } else {
  14878. + if (cifsFile)
  14879. + cifsFile->endOfSearch = TRUE;
  14880. + /* unless parent directory gone do not return error */
  14881. + rc = 0;
  14882. + }
  14883. + break;
  14884. + default:
  14885. + if (file->private_data == NULL) {
  14886. + rc = -EBADF;
  14887. + cFYI(1,
  14888. + ("Readdir on closed srch, pos = %lld",
  14889. + file->f_pos));
  14890. + } else {
  14891. + cifsFile = (struct cifsFileInfo *) file->private_data;
  14892. + if (cifsFile->endOfSearch) {
  14893. + rc = 0;
  14894. + cFYI(1, ("End of search "));
  14895. + break;
  14896. + }
  14897. + searchHandle = cifsFile->netfid;
  14898. + rc = CIFSFindNext(xid, pTcon, pfindData,
  14899. + &findNextParms, searchHandle,
  14900. + cifsFile->search_resume_name,
  14901. + cifsFile->resume_name_length,
  14902. + cifsFile->resume_key,
  14903. + &Unicode, &UnixSearch);
  14904. + cFYI(1,("Count: %d End: %d ",
  14905. + findNextParms.SearchCount,
  14906. + findNextParms.EndofSearch));
  14907. + if ((rc == 0) && (findNextParms.SearchCount != 0)) {
  14908. + /* BB save off resume key, key name and name length */
  14909. + lastFindData =
  14910. + (FILE_DIRECTORY_INFO *) ((char *) pfindData
  14911. + + findNextParms.LastNameOffset);
  14912. + if((char *)lastFindData > (char *)pfindData + bufsize) {
  14913. + cFYI(1,("last search entry past end of packet"));
  14914. + rc = -EIO;
  14915. + break;
  14916. + }
  14917. + /* Offset of resume key same for levels 257 and 514 */
  14918. + cifsFile->resume_key = lastFindData->FileIndex;
  14919. +
  14920. + if(UnixSearch == FALSE) {
  14921. + cifsFile->resume_name_length =
  14922. + le32_to_cpu(lastFindData->FileNameLength);
  14923. + if(cifsFile->resume_name_length > bufsize - 64) {
  14924. + cFYI(1,("Illegal resume file name length %d",
  14925. + cifsFile->resume_name_length));
  14926. + rc = -ENOMEM;
  14927. + break;
  14928. + }
  14929. + /* Free the memory allocated by previous findfirst
  14930. + or findnext call - we can not reuse the memory since
  14931. + the resume name may not be same string length */
  14932. + if(cifsFile->search_resume_name)
  14933. + kfree(cifsFile->search_resume_name);
  14934. + cifsFile->search_resume_name =
  14935. + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
  14936. + cFYI(1,("Last file: %s with name %d bytes long",
  14937. + lastFindData->FileName,
  14938. + cifsFile->resume_name_length));
  14939. + memcpy(cifsFile->search_resume_name,
  14940. + lastFindData->FileName,
  14941. + cifsFile->resume_name_length);
  14942. + } else {
  14943. + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
  14944. + if (Unicode == TRUE) {
  14945. + for(i=0;(pfindDataUnix->FileName[i]
  14946. + | pfindDataUnix->FileName[i+1]);
  14947. + i+=2) {
  14948. + if(i > bufsize-64)
  14949. + break;
  14950. + }
  14951. + cifsFile->resume_name_length = i + 2;
  14952. + } else {
  14953. + cifsFile->resume_name_length =
  14954. + strnlen(pfindDataUnix->
  14955. + FileName,
  14956. + MAX_PATHCONF);
  14957. + }
  14958. + if(cifsFile->resume_name_length > bufsize - 64) {
  14959. + cFYI(1,("Illegal resume file name length %d",
  14960. + cifsFile->resume_name_length));
  14961. + rc = -ENOMEM;
  14962. + break;
  14963. + }
  14964. + /* Free the memory allocated by previous findfirst
  14965. + or findnext call - we can not reuse the memory since
  14966. + the resume name may not be same string length */
  14967. + if(cifsFile->search_resume_name)
  14968. + kfree(cifsFile->search_resume_name);
  14969. + cifsFile->search_resume_name =
  14970. + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
  14971. + cFYI(1,("fnext last file: %s with name %d bytes long",
  14972. + pfindDataUnix->FileName,
  14973. + cifsFile->resume_name_length));
  14974. + memcpy(cifsFile->search_resume_name,
  14975. + pfindDataUnix->FileName,
  14976. + cifsFile->resume_name_length);
  14977. + }
  14978. +
  14979. + for (i = 0; i < findNextParms.SearchCount; i++) {
  14980. + pfindData->FileNameLength =
  14981. + le32_to_cpu(pfindData->
  14982. + FileNameLength);
  14983. + if (UnixSearch == FALSE) {
  14984. + if (Unicode == TRUE)
  14985. + pfindData->FileNameLength =
  14986. + cifs_strfromUCS_le
  14987. + (pfindData->FileName,
  14988. + (wchar_t *)
  14989. + pfindData->FileName,
  14990. + (pfindData->FileNameLength)/ 2,
  14991. + cifs_sb->local_nls);
  14992. + qstring.len =
  14993. + pfindData->FileNameLength;
  14994. + if (((qstring.len != 1)
  14995. + || (pfindData->FileName[0] != '.'))
  14996. + && ((qstring.len != 2)
  14997. + || (pfindData->FileName[0] != '.')
  14998. + || (pfindData->FileName[1] !=
  14999. + '.'))) {
  15000. + if(cifs_filldir
  15001. + (&qstring,
  15002. + pfindData,
  15003. + file, filldir,
  15004. + direntry)) {
  15005. + /* do not end search if
  15006. + kernel not ready to take
  15007. + remaining entries yet */
  15008. + findNextParms.EndofSearch = 0;
  15009. + reset_resume_key(file, pfindData->FileName,qstring.len,
  15010. + Unicode,cifs_sb->local_nls);
  15011. + break;
  15012. + }
  15013. + file->f_pos++;
  15014. + }
  15015. + } else { /* UnixSearch */
  15016. + pfindDataUnix =
  15017. + (FILE_UNIX_INFO *)
  15018. + pfindData;
  15019. + if (Unicode == TRUE)
  15020. + qstring.len =
  15021. + cifs_strfromUCS_le
  15022. + (pfindDataUnix->FileName,
  15023. + (wchar_t *)
  15024. + pfindDataUnix->FileName,
  15025. + MAX_PATHCONF,
  15026. + cifs_sb->local_nls);
  15027. + else
  15028. + qstring.len =
  15029. + strnlen
  15030. + (pfindDataUnix->
  15031. + FileName,
  15032. + MAX_PATHCONF);
  15033. + if (((qstring.len != 1)
  15034. + || (pfindDataUnix->
  15035. + FileName[0] != '.'))
  15036. + && ((qstring.len != 2)
  15037. + || (pfindDataUnix->
  15038. + FileName[0] != '.')
  15039. + || (pfindDataUnix->
  15040. + FileName[1] !=
  15041. + '.'))) {
  15042. + if(cifs_filldir_unix
  15043. + (&qstring,
  15044. + pfindDataUnix,
  15045. + file, filldir,
  15046. + direntry)) {
  15047. + /* do not end search if
  15048. + kernel not ready to take
  15049. + remaining entries yet */
  15050. + findNextParms.EndofSearch = 0;
  15051. + reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
  15052. + Unicode,cifs_sb->local_nls);
  15053. + break;
  15054. + }
  15055. + file->f_pos++;
  15056. + }
  15057. + }
  15058. + pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */
  15059. + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
  15060. + } /* end for loop */
  15061. + if (findNextParms.EndofSearch != 0) {
  15062. + cifsFile->endOfSearch = TRUE;
  15063. + }
  15064. + } else {
  15065. + cifsFile->endOfSearch = TRUE;
  15066. + rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
  15067. + }
  15068. + }
  15069. + } /* end switch */
  15070. + if (data)
  15071. + kfree(data);
  15072. + if (full_path)
  15073. + kfree(full_path);
  15074. + FreeXid(xid);
  15075. +
  15076. + return rc;
  15077. +}
  15078. +int cifs_prepare_write(struct file *file, struct page *page,
  15079. + unsigned from, unsigned to)
  15080. +{
  15081. + int rc = 0;
  15082. + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
  15083. + cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
  15084. + if (!Page_Uptodate(page)) {
  15085. + /* if (to - from != PAGE_CACHE_SIZE) {
  15086. + void *kaddr = kmap_atomic(page, KM_USER0);
  15087. + memset(kaddr, 0, from);
  15088. + memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
  15089. + flush_dcache_page(page);
  15090. + kunmap_atomic(kaddr, KM_USER0);
  15091. + } */
  15092. + /* If we are writing a full page it will be up to date,
  15093. + no need to read from the server */
  15094. + if((to==PAGE_CACHE_SIZE) && (from == 0))
  15095. + SetPageUptodate(page);
  15096. +
  15097. + /* might as well read a page, it is fast enough */
  15098. + if((file->f_flags & O_ACCMODE) != O_WRONLY) {
  15099. + rc = cifs_readpage_worker(file,page,&offset);
  15100. + } else {
  15101. + /* should we try using another
  15102. + file handle if there is one - how would we lock it
  15103. + to prevent close of that handle racing with this read? */
  15104. + /* In any case this will be written out by commit_write */
  15105. + }
  15106. + }
  15107. +
  15108. + /* BB should we pass any errors back? e.g. if we do not have read access to the file */
  15109. + return 0;
  15110. +}
  15111. +
  15112. +
  15113. +struct address_space_operations cifs_addr_ops = {
  15114. + .readpage = cifs_readpage,
  15115. +/* .readpages = cifs_readpages, */
  15116. + .writepage = cifs_writepage,
  15117. + .prepare_write = cifs_prepare_write,
  15118. + .commit_write = cifs_commit_write,
  15119. + .sync_page = cifs_sync_page,
  15120. + /*.direct_IO = */
  15121. +};
  15122. --- /dev/null
  15123. +++ b/fs/cifs/inode.c
  15124. @@ -0,0 +1,1079 @@
  15125. +/*
  15126. + * fs/cifs/inode.c
  15127. + *
  15128. + * Copyright (C) International Business Machines Corp., 2002,2003
  15129. + * Author(s): Steve French ([email protected])
  15130. + *
  15131. + * This library is free software; you can redistribute it and/or modify
  15132. + * it under the terms of the GNU Lesser General Public License as published
  15133. + * by the Free Software Foundation; either version 2.1 of the License, or
  15134. + * (at your option) any later version.
  15135. + *
  15136. + * This library is distributed in the hope that it will be useful,
  15137. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15138. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  15139. + * the GNU Lesser General Public License for more details.
  15140. + *
  15141. + * You should have received a copy of the GNU Lesser General Public License
  15142. + * along with this library; if not, write to the Free Software
  15143. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15144. + */
  15145. +#include <linux/fs.h>
  15146. +#include <linux/stat.h>
  15147. +#include <linux/pagemap.h>
  15148. +#include <linux/version.h>
  15149. +#include <asm/div64.h>
  15150. +#include "cifsfs.h"
  15151. +#include "cifspdu.h"
  15152. +#include "cifsglob.h"
  15153. +#include "cifsproto.h"
  15154. +#include "cifs_debug.h"
  15155. +#include "cifs_fs_sb.h"
  15156. +
  15157. +extern int is_size_safe_to_change(struct cifsInodeInfo *);
  15158. +
  15159. +struct inode * get_cifs_inode(struct super_block * sb)
  15160. +{
  15161. + struct inode * newinode;
  15162. + newinode = new_inode(sb);
  15163. + cFYI(1,("got new inode %p",newinode));
  15164. + if(newinode) {
  15165. + struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
  15166. + cifsInfo->clientCanCacheRead = FALSE;
  15167. + cifsInfo->clientCanCacheAll = FALSE;
  15168. + INIT_LIST_HEAD(&cifsInfo->openFileList);
  15169. + cifsInfo->cifsAttrs = 0x20; /* default */
  15170. + newinode->i_blksize = CIFS_MAX_MSGSIZE;
  15171. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
  15172. + newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
  15173. +#endif
  15174. + atomic_set(&cifsInfo->inUse, 0);
  15175. + cifsInfo->time = 0;
  15176. + insert_inode_hash(newinode);
  15177. + }
  15178. + return newinode;
  15179. +
  15180. +}
  15181. +
  15182. +int
  15183. +cifs_get_inode_info_unix(struct inode **pinode,
  15184. + const unsigned char *search_path,
  15185. + struct super_block *sb,int xid)
  15186. +{
  15187. + int rc = 0;
  15188. + FILE_UNIX_BASIC_INFO findData;
  15189. + struct cifsTconInfo *pTcon;
  15190. + struct inode *inode;
  15191. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  15192. + char *tmp_path;
  15193. +
  15194. + pTcon = cifs_sb->tcon;
  15195. + cFYI(1, (" Getting info on %s ", search_path));
  15196. + /* we could have done a find first instead but this returns more info */
  15197. + rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
  15198. + cifs_sb->local_nls);
  15199. + /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
  15200. + if (rc) {
  15201. + if (rc == -EREMOTE) {
  15202. + tmp_path =
  15203. + kmalloc(strnlen
  15204. + (pTcon->treeName,
  15205. + MAX_TREE_SIZE + 1) +
  15206. + strnlen(search_path, MAX_PATHCONF) + 1,
  15207. + GFP_KERNEL);
  15208. + if (tmp_path == NULL) {
  15209. + return -ENOMEM;
  15210. + }
  15211. + /* have to skip first of the double backslash of UNC name */
  15212. + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
  15213. + strncat(tmp_path, search_path, MAX_PATHCONF);
  15214. + rc = connect_to_dfs_path(xid, pTcon->ses,
  15215. + /* treename + */ tmp_path,
  15216. + cifs_sb->local_nls);
  15217. + kfree(tmp_path);
  15218. +
  15219. + /* BB fix up inode etc. */
  15220. + } else if (rc) {
  15221. + return rc;
  15222. + }
  15223. +
  15224. + } else {
  15225. + struct cifsInodeInfo *cifsInfo;
  15226. +
  15227. + /* get new inode */
  15228. + if (*pinode == NULL) {
  15229. + *pinode = get_cifs_inode(sb);
  15230. + }
  15231. + if(*pinode == NULL) {
  15232. + return -ENOMEM;
  15233. + }
  15234. +
  15235. + inode = *pinode;
  15236. + cifsInfo = CIFS_I(inode);
  15237. +
  15238. + cFYI(1, (" Old time %ld ", cifsInfo->time));
  15239. + cifsInfo->time = jiffies;
  15240. + cFYI(1, (" New time %ld ", cifsInfo->time));
  15241. + atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
  15242. +
  15243. + inode->i_atime =
  15244. + cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
  15245. + inode->i_mtime =
  15246. + cifs_NTtimeToUnix(le64_to_cpu
  15247. + (findData.LastModificationTime));
  15248. + inode->i_ctime =
  15249. + cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
  15250. + inode->i_mode = le64_to_cpu(findData.Permissions);
  15251. + findData.Type = le32_to_cpu(findData.Type);
  15252. + if (findData.Type == UNIX_FILE) {
  15253. + inode->i_mode |= S_IFREG;
  15254. + } else if (findData.Type == UNIX_SYMLINK) {
  15255. + inode->i_mode |= S_IFLNK;
  15256. + } else if (findData.Type == UNIX_DIR) {
  15257. + inode->i_mode |= S_IFDIR;
  15258. + } else if (findData.Type == UNIX_CHARDEV) {
  15259. + inode->i_mode |= S_IFCHR;
  15260. + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
  15261. + le64_to_cpu(findData.DevMinor) & MINORMASK);
  15262. + } else if (findData.Type == UNIX_BLOCKDEV) {
  15263. + inode->i_mode |= S_IFBLK;
  15264. + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
  15265. + le64_to_cpu(findData.DevMinor) & MINORMASK);
  15266. + } else if (findData.Type == UNIX_FIFO) {
  15267. + inode->i_mode |= S_IFIFO;
  15268. + } else if (findData.Type == UNIX_SOCKET) {
  15269. + inode->i_mode |= S_IFSOCK;
  15270. + }
  15271. + inode->i_uid = le64_to_cpu(findData.Uid);
  15272. + inode->i_gid = le64_to_cpu(findData.Gid);
  15273. + inode->i_nlink = le64_to_cpu(findData.Nlinks);
  15274. + findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
  15275. + findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
  15276. +
  15277. + if(is_size_safe_to_change(cifsInfo)) {
  15278. + /* can not safely change the file size here if the
  15279. + client is writing to it due to potential races */
  15280. + inode->i_size = findData.EndOfFile;
  15281. +/* blksize needs to be multiple of two. So safer to default to blksize
  15282. + and blkbits set in superblock so 2**blkbits and blksize will match */
  15283. +/* inode->i_blksize =
  15284. + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
  15285. +
  15286. + /* This seems incredibly stupid but it turns out that
  15287. + i_blocks is not related to (i_size / i_blksize), instead a
  15288. + size of 512 is required to be used for calculating num blocks */
  15289. +
  15290. +
  15291. +/* inode->i_blocks =
  15292. + (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
  15293. +
  15294. + /* 512 bytes (2**9) is the fake blocksize that must be used */
  15295. + /* for this calculation */
  15296. + inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
  15297. + }
  15298. +
  15299. + if (findData.NumOfBytes < findData.EndOfFile)
  15300. + cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
  15301. + cFYI(1,
  15302. + ("Size %ld and blocks %ld ",
  15303. + (unsigned long) inode->i_size, inode->i_blocks));
  15304. + if (S_ISREG(inode->i_mode)) {
  15305. + cFYI(1, (" File inode "));
  15306. + inode->i_op = &cifs_file_inode_ops;
  15307. + inode->i_fop = &cifs_file_ops;
  15308. + inode->i_data.a_ops = &cifs_addr_ops;
  15309. + } else if (S_ISDIR(inode->i_mode)) {
  15310. + cFYI(1, (" Directory inode"));
  15311. + inode->i_op = &cifs_dir_inode_ops;
  15312. + inode->i_fop = &cifs_dir_ops;
  15313. + } else if (S_ISLNK(inode->i_mode)) {
  15314. + cFYI(1, (" Symbolic Link inode "));
  15315. + inode->i_op = &cifs_symlink_inode_ops;
  15316. +/* tmp_inode->i_fop = *//* do not need to set to anything */
  15317. + } else {
  15318. + cFYI(1, (" Init special inode "));
  15319. + init_special_inode(inode, inode->i_mode,
  15320. + kdev_t_to_nr(inode->i_rdev));
  15321. + }
  15322. + }
  15323. + return rc;
  15324. +}
  15325. +
  15326. +int
  15327. +cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
  15328. + FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
  15329. +{
  15330. + int rc = 0;
  15331. + struct cifsTconInfo *pTcon;
  15332. + struct inode *inode;
  15333. + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  15334. + char *tmp_path;
  15335. + char *buf = NULL;
  15336. +
  15337. + pTcon = cifs_sb->tcon;
  15338. + cFYI(1,("Getting info on %s ", search_path));
  15339. +
  15340. + if((pfindData == NULL) && (*pinode != NULL)) {
  15341. + if(CIFS_I(*pinode)->clientCanCacheRead) {
  15342. + cFYI(1,("No need to revalidate inode sizes on cached file "));
  15343. + return rc;
  15344. + }
  15345. + }
  15346. +
  15347. + /* if file info not passed in then get it from server */
  15348. + if(pfindData == NULL) {
  15349. + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
  15350. + pfindData = (FILE_ALL_INFO *)buf;
  15351. + /* could do find first instead but this returns more info */
  15352. + rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
  15353. + cifs_sb->local_nls);
  15354. + }
  15355. + /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
  15356. + if (rc) {
  15357. + if (rc == -EREMOTE) {
  15358. + tmp_path =
  15359. + kmalloc(strnlen
  15360. + (pTcon->treeName,
  15361. + MAX_TREE_SIZE + 1) +
  15362. + strnlen(search_path, MAX_PATHCONF) + 1,
  15363. + GFP_KERNEL);
  15364. + if (tmp_path == NULL) {
  15365. + if(buf)
  15366. + kfree(buf);
  15367. + return -ENOMEM;
  15368. + }
  15369. +
  15370. + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
  15371. + strncat(tmp_path, search_path, MAX_PATHCONF);
  15372. + rc = connect_to_dfs_path(xid, pTcon->ses,
  15373. + /* treename + */ tmp_path,
  15374. + cifs_sb->local_nls);
  15375. + kfree(tmp_path);
  15376. + /* BB fix up inode etc. */
  15377. + } else if (rc) {
  15378. + if(buf)
  15379. + kfree(buf);
  15380. + return rc;
  15381. + }
  15382. + } else {
  15383. + struct cifsInodeInfo *cifsInfo;
  15384. +
  15385. + /* get new inode */
  15386. + if (*pinode == NULL) {
  15387. + *pinode = get_cifs_inode(sb);
  15388. + }
  15389. + if(*pinode == NULL)
  15390. + return -ENOMEM;
  15391. + inode = *pinode;
  15392. + cifsInfo = CIFS_I(inode);
  15393. + pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
  15394. + cifsInfo->cifsAttrs = pfindData->Attributes;
  15395. + cFYI(1, (" Old time %ld ", cifsInfo->time));
  15396. + cifsInfo->time = jiffies;
  15397. + cFYI(1, (" New time %ld ", cifsInfo->time));
  15398. +
  15399. +/* blksize needs to be multiple of two. So safer to default to blksize
  15400. + and blkbits set in superblock so 2**blkbits and blksize will match */
  15401. +/* inode->i_blksize =
  15402. + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
  15403. +
  15404. + /* Linux can not store file creation time unfortunately so we ignore it */
  15405. + inode->i_atime =
  15406. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
  15407. + inode->i_mtime =
  15408. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
  15409. + inode->i_ctime =
  15410. + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
  15411. + cFYI(0,
  15412. + (" Attributes came in as 0x%x ", pfindData->Attributes));
  15413. +
  15414. + /* set default mode. will override for dirs below */
  15415. + if(atomic_read(&cifsInfo->inUse) == 0)
  15416. + /* new inode, can safely set these fields */
  15417. + inode->i_mode = cifs_sb->mnt_file_mode;
  15418. +
  15419. + if (pfindData->Attributes & ATTR_REPARSE) {
  15420. + /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
  15421. + inode->i_mode |= S_IFLNK;
  15422. + } else if (pfindData->Attributes & ATTR_DIRECTORY) {
  15423. + /* override default perms since we do not do byte range locking on dirs */
  15424. + inode->i_mode = cifs_sb->mnt_dir_mode;
  15425. + inode->i_mode |= S_IFDIR;
  15426. + } else {
  15427. + inode->i_mode |= S_IFREG;
  15428. + /* treat the dos attribute of read-only as read-only mode e.g. 555 */
  15429. + if(cifsInfo->cifsAttrs & ATTR_READONLY)
  15430. + inode->i_mode &= ~(S_IWUGO);
  15431. + /* BB add code here - validate if device or weird share or device type? */
  15432. + }
  15433. + if(is_size_safe_to_change(cifsInfo)) {
  15434. + /* can not safely change the file size here if the
  15435. + client is writing to it due to potential races */
  15436. + inode->i_size = le64_to_cpu(pfindData->EndOfFile);
  15437. +
  15438. + /* 512 bytes (2**9) is the fake blocksize that must be used */
  15439. + /* for this calculation */
  15440. + inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
  15441. + >> 9;
  15442. + }
  15443. + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
  15444. +
  15445. + cFYI(1,
  15446. + (" Size %ld and blocks %ld ",
  15447. + (unsigned long) inode->i_size, inode->i_blocks));
  15448. + inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
  15449. +
  15450. + /* BB fill in uid and gid here? with help from winbind?
  15451. + or retrieve from NTFS stream extended attribute */
  15452. + if(atomic_read(&cifsInfo->inUse) == 0) {
  15453. + inode->i_uid = cifs_sb->mnt_uid;
  15454. + inode->i_gid = cifs_sb->mnt_gid;
  15455. + /* set so we do not keep refreshing these fields with
  15456. + bad data after user has changed them in memory */
  15457. + atomic_set(&cifsInfo->inUse,1);
  15458. + }
  15459. +
  15460. + if (S_ISREG(inode->i_mode)) {
  15461. + cFYI(1, (" File inode "));
  15462. + inode->i_op = &cifs_file_inode_ops;
  15463. + inode->i_fop = &cifs_file_ops;
  15464. + inode->i_data.a_ops = &cifs_addr_ops;
  15465. + } else if (S_ISDIR(inode->i_mode)) {
  15466. + cFYI(1, (" Directory inode "));
  15467. + inode->i_op = &cifs_dir_inode_ops;
  15468. + inode->i_fop = &cifs_dir_ops;
  15469. + } else if (S_ISLNK(inode->i_mode)) {
  15470. + cFYI(1, (" Symbolic Link inode "));
  15471. + inode->i_op = &cifs_symlink_inode_ops;
  15472. + } else {
  15473. + init_special_inode(inode, inode->i_mode,
  15474. + kdev_t_to_nr(inode->i_rdev));
  15475. + }
  15476. + }
  15477. + if(buf)
  15478. + kfree(buf);
  15479. + return rc;
  15480. +}
  15481. +
  15482. +void
  15483. +cifs_read_inode(struct inode *inode)
  15484. +{ /* gets root inode */
  15485. + int xid;
  15486. + struct cifs_sb_info *cifs_sb;
  15487. + struct cifsInodeInfo *cifs_inode;
  15488. +
  15489. + cifs_sb = CIFS_SB(inode->i_sb);
  15490. + xid = GetXid();
  15491. +
  15492. + cifs_inode = CIFS_I(inode);
  15493. + cifs_inode->cifsAttrs = ATTR_DIRECTORY;
  15494. + atomic_set(&cifs_inode->inUse, 0);
  15495. + cifs_inode->time = 0;
  15496. + inode->i_blksize = CIFS_MAX_MSGSIZE;
  15497. + inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
  15498. +
  15499. + INIT_LIST_HEAD(&cifs_inode->openFileList);
  15500. +
  15501. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  15502. + cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
  15503. + else
  15504. + cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
  15505. + /* can not call macro FreeXid here since in a void func */
  15506. + _FreeXid(xid);
  15507. +}
  15508. +
  15509. +int
  15510. +cifs_unlink(struct inode *inode, struct dentry *direntry)
  15511. +{
  15512. + int rc = 0;
  15513. + int xid;
  15514. + struct cifs_sb_info *cifs_sb;
  15515. + struct cifsTconInfo *pTcon;
  15516. + char *full_path = NULL;
  15517. + struct cifsInodeInfo *cifsInode;
  15518. + FILE_BASIC_INFO * pinfo_buf;
  15519. +
  15520. + cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
  15521. +
  15522. + xid = GetXid();
  15523. +
  15524. + cifs_sb = CIFS_SB(inode->i_sb);
  15525. + pTcon = cifs_sb->tcon;
  15526. +
  15527. +/* Unlink can be called from rename so we can not grab
  15528. + the sem here since we deadlock otherwise */
  15529. +/* down(&direntry->d_sb->s_vfs_rename_sem);*/
  15530. + full_path = build_path_from_dentry(direntry);
  15531. +/* up(&direntry->d_sb->s_vfs_rename_sem);*/
  15532. + if(full_path == NULL) {
  15533. + FreeXid(xid);
  15534. + return -ENOMEM;
  15535. + }
  15536. + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
  15537. +
  15538. + if (!rc) {
  15539. + direntry->d_inode->i_nlink--;
  15540. + } else if (rc == -ENOENT) {
  15541. + d_drop(direntry);
  15542. + } else if (rc == -ETXTBSY) {
  15543. + int oplock = FALSE;
  15544. + __u16 netfid;
  15545. +
  15546. + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
  15547. + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
  15548. + &netfid, &oplock, NULL, cifs_sb->local_nls);
  15549. + if(rc==0) {
  15550. + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
  15551. + NULL, cifs_sb->local_nls);
  15552. + CIFSSMBClose(xid, pTcon, netfid);
  15553. + direntry->d_inode->i_nlink--;
  15554. + }
  15555. + } else if (rc == -EACCES) {
  15556. + /* try only if r/o attribute set in local lookup data? */
  15557. + pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
  15558. + if(pinfo_buf) {
  15559. + memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
  15560. + /* ATTRS set to normal clears r/o bit */
  15561. + pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
  15562. + rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
  15563. + cifs_sb->local_nls);
  15564. + kfree(pinfo_buf);
  15565. + }
  15566. + if(rc==0) {
  15567. + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
  15568. + if (!rc) {
  15569. + direntry->d_inode->i_nlink--;
  15570. + } else if (rc == -ETXTBSY) {
  15571. + int oplock = FALSE;
  15572. + __u16 netfid;
  15573. +
  15574. + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
  15575. + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
  15576. + &netfid, &oplock, NULL, cifs_sb->local_nls);
  15577. + if(rc==0) {
  15578. + CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
  15579. + CIFSSMBClose(xid, pTcon, netfid);
  15580. + direntry->d_inode->i_nlink--;
  15581. + }
  15582. + /* BB if rc = -ETXTBUSY goto the rename logic BB */
  15583. + }
  15584. + }
  15585. + }
  15586. + cifsInode = CIFS_I(direntry->d_inode);
  15587. + cifsInode->time = 0; /* will force revalidate to get info when needed */
  15588. + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
  15589. + CURRENT_TIME;
  15590. + cifsInode = CIFS_I(inode);
  15591. + cifsInode->time = 0; /* force revalidate of dir as well */
  15592. +
  15593. + if (full_path)
  15594. + kfree(full_path);
  15595. + FreeXid(xid);
  15596. + return rc;
  15597. +}
  15598. +
  15599. +int
  15600. +cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
  15601. +{
  15602. + int rc = 0;
  15603. + int xid;
  15604. + struct cifs_sb_info *cifs_sb;
  15605. + struct cifsTconInfo *pTcon;
  15606. + char *full_path = NULL;
  15607. + struct inode *newinode = NULL;
  15608. +
  15609. + cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
  15610. +
  15611. + xid = GetXid();
  15612. +
  15613. + cifs_sb = CIFS_SB(inode->i_sb);
  15614. + pTcon = cifs_sb->tcon;
  15615. +
  15616. + down(&inode->i_sb->s_vfs_rename_sem);
  15617. + full_path = build_path_from_dentry(direntry);
  15618. + up(&inode->i_sb->s_vfs_rename_sem);
  15619. + if(full_path == NULL) {
  15620. + FreeXid(xid);
  15621. + return -ENOMEM;
  15622. + }
  15623. + /* BB add setting the equivalent of mode via CreateX w/ACLs */
  15624. + rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
  15625. + if (rc) {
  15626. + cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
  15627. + d_drop(direntry);
  15628. + } else {
  15629. + inode->i_nlink++;
  15630. + if (pTcon->ses->capabilities & CAP_UNIX)
  15631. + rc = cifs_get_inode_info_unix(&newinode, full_path,
  15632. + inode->i_sb,xid);
  15633. + else
  15634. + rc = cifs_get_inode_info(&newinode, full_path,NULL,
  15635. + inode->i_sb,xid);
  15636. +
  15637. + direntry->d_op = &cifs_dentry_ops;
  15638. + d_instantiate(direntry, newinode);
  15639. + if(direntry->d_inode)
  15640. + direntry->d_inode->i_nlink = 2;
  15641. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  15642. + CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
  15643. + (__u64)-1,
  15644. + (__u64)-1,
  15645. + 0 /* dev_t */,
  15646. + cifs_sb->local_nls);
  15647. + else { /* BB to be implemented via Windows secrty descriptors*/
  15648. + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
  15649. + }
  15650. + }
  15651. + if (full_path)
  15652. + kfree(full_path);
  15653. + FreeXid(xid);
  15654. +
  15655. + return rc;
  15656. +}
  15657. +
  15658. +int
  15659. +cifs_rmdir(struct inode *inode, struct dentry *direntry)
  15660. +{
  15661. + int rc = 0;
  15662. + int xid;
  15663. + struct cifs_sb_info *cifs_sb;
  15664. + struct cifsTconInfo *pTcon;
  15665. + char *full_path = NULL;
  15666. + struct cifsInodeInfo *cifsInode;
  15667. +
  15668. + cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
  15669. +
  15670. + xid = GetXid();
  15671. +
  15672. + cifs_sb = CIFS_SB(inode->i_sb);
  15673. + pTcon = cifs_sb->tcon;
  15674. +
  15675. + down(&inode->i_sb->s_vfs_rename_sem);
  15676. + full_path = build_path_from_dentry(direntry);
  15677. + up(&inode->i_sb->s_vfs_rename_sem);
  15678. + if(full_path == NULL) {
  15679. + FreeXid(xid);
  15680. + return -ENOMEM;
  15681. + }
  15682. +
  15683. + rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
  15684. +
  15685. + if (!rc) {
  15686. + inode->i_nlink--;
  15687. + direntry->d_inode->i_size = 0;
  15688. + direntry->d_inode->i_nlink = 0;
  15689. + }
  15690. +
  15691. + cifsInode = CIFS_I(direntry->d_inode);
  15692. + cifsInode->time = 0; /* force revalidate to go get info when needed */
  15693. + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
  15694. + CURRENT_TIME;
  15695. +
  15696. + if (full_path)
  15697. + kfree(full_path);
  15698. + FreeXid(xid);
  15699. + return rc;
  15700. +}
  15701. +
  15702. +int
  15703. +cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
  15704. + struct inode *target_inode, struct dentry *target_direntry)
  15705. +{
  15706. + char *fromName;
  15707. + char *toName;
  15708. + struct cifs_sb_info *cifs_sb_source;
  15709. + struct cifs_sb_info *cifs_sb_target;
  15710. + struct cifsTconInfo *pTcon;
  15711. + int xid;
  15712. + int rc = 0;
  15713. +
  15714. + xid = GetXid();
  15715. +
  15716. + cifs_sb_target = CIFS_SB(target_inode->i_sb);
  15717. + cifs_sb_source = CIFS_SB(source_inode->i_sb);
  15718. + pTcon = cifs_sb_source->tcon;
  15719. +
  15720. + if (pTcon != cifs_sb_target->tcon) {
  15721. + FreeXid(xid);
  15722. + return -EXDEV; /* BB actually could be allowed if same server, but
  15723. + different share. Might eventually add support for this */
  15724. + }
  15725. +
  15726. + /* we already have the rename sem so we do not need
  15727. + to grab it again here to protect the path integrity */
  15728. + fromName = build_path_from_dentry(source_direntry);
  15729. + toName = build_path_from_dentry(target_direntry);
  15730. + if((fromName == NULL) || (toName == NULL)) {
  15731. + rc = -ENOMEM;
  15732. + goto cifs_rename_exit;
  15733. + }
  15734. +
  15735. + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
  15736. + cifs_sb_source->local_nls);
  15737. + if(rc == -EEXIST) {
  15738. + /* check if they are the same file
  15739. + because rename of hardlinked files is a noop */
  15740. + FILE_UNIX_BASIC_INFO * info_buf_source;
  15741. + FILE_UNIX_BASIC_INFO * info_buf_target;
  15742. +
  15743. + info_buf_source =
  15744. + kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
  15745. + if(info_buf_source != NULL) {
  15746. + info_buf_target = info_buf_source+1;
  15747. + rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
  15748. + info_buf_source, cifs_sb_source->local_nls);
  15749. + if(rc == 0) {
  15750. + rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
  15751. + info_buf_target,
  15752. + cifs_sb_target->local_nls);
  15753. + }
  15754. + if((rc == 0) &&
  15755. + (info_buf_source->UniqueId ==
  15756. + info_buf_target->UniqueId)) {
  15757. + /* do not rename since the files are hardlinked
  15758. + which is a noop */
  15759. + } else {
  15760. + /* we either can not tell the files are hardlinked
  15761. + (as with Windows servers) or files are not hardlinked
  15762. + so delete the target manually before renaming to
  15763. + follow POSIX rather than Windows semantics */
  15764. + cifs_unlink(target_inode, target_direntry);
  15765. + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
  15766. + cifs_sb_source->local_nls);
  15767. + }
  15768. + kfree(info_buf_source);
  15769. + } /* if we can not get memory just leave rc as EEXIST */
  15770. + }
  15771. +
  15772. + if((rc == -EIO)||(rc == -EEXIST)) {
  15773. + int oplock = FALSE;
  15774. + __u16 netfid;
  15775. +
  15776. + rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
  15777. + CREATE_NOT_DIR,
  15778. + &netfid, &oplock, NULL, cifs_sb_source->local_nls);
  15779. + if(rc==0) {
  15780. + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
  15781. + toName, cifs_sb_source->local_nls);
  15782. + CIFSSMBClose(xid, pTcon, netfid);
  15783. + }
  15784. + }
  15785. +
  15786. +cifs_rename_exit:
  15787. + if (fromName)
  15788. + kfree(fromName);
  15789. + if (toName)
  15790. + kfree(toName);
  15791. +
  15792. + FreeXid(xid);
  15793. + return rc;
  15794. +}
  15795. +
  15796. +int
  15797. +cifs_revalidate(struct dentry *direntry)
  15798. +{
  15799. + int xid;
  15800. + int rc = 0;
  15801. + char *full_path;
  15802. + struct cifs_sb_info *cifs_sb;
  15803. + struct cifsInodeInfo *cifsInode;
  15804. + loff_t local_size;
  15805. + time_t local_mtime;
  15806. + int invalidate_inode = FALSE;
  15807. +
  15808. + if(direntry->d_inode == NULL)
  15809. + return -ENOENT;
  15810. +
  15811. + cifsInode = CIFS_I(direntry->d_inode);
  15812. +
  15813. + if(cifsInode == NULL)
  15814. + return -ENOENT;
  15815. +
  15816. + /* no sense revalidating inode info on file that no one can write */
  15817. + if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
  15818. + return rc;
  15819. +
  15820. + xid = GetXid();
  15821. +
  15822. + cifs_sb = CIFS_SB(direntry->d_sb);
  15823. +
  15824. + /* can not safely grab the rename sem here if
  15825. + rename calls revalidate since that would deadlock */
  15826. + full_path = build_path_from_dentry(direntry);
  15827. + if(full_path == NULL) {
  15828. + FreeXid(xid);
  15829. + return -ENOMEM;
  15830. + }
  15831. + cFYI(1,
  15832. + ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
  15833. + full_path, direntry->d_inode,
  15834. + direntry->d_inode->i_count.counter, direntry,
  15835. + direntry->d_time, jiffies));
  15836. +
  15837. + if (cifsInode->time == 0){
  15838. + /* was set to zero previously to force revalidate */
  15839. + } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
  15840. + if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
  15841. + (direntry->d_inode->i_nlink == 1)) {
  15842. + if (full_path)
  15843. + kfree(full_path);
  15844. + FreeXid(xid);
  15845. + return rc;
  15846. + } else {
  15847. + cFYI(1,("Have to revalidate file due to hardlinks"));
  15848. + }
  15849. + }
  15850. +
  15851. + /* save mtime and size */
  15852. + local_mtime = direntry->d_inode->i_mtime;
  15853. + local_size = direntry->d_inode->i_size;
  15854. +
  15855. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
  15856. + rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
  15857. + direntry->d_sb,xid);
  15858. + if(rc) {
  15859. + cFYI(1,("error on getting revalidate info %d",rc));
  15860. +/* if(rc != -ENOENT)
  15861. + rc = 0; */ /* BB should we cache info on certain errors? */
  15862. + }
  15863. + } else {
  15864. + rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
  15865. + direntry->d_sb,xid);
  15866. + if(rc) {
  15867. + cFYI(1,("error on getting revalidate info %d",rc));
  15868. +/* if(rc != -ENOENT)
  15869. + rc = 0; */ /* BB should we cache info on certain errors? */
  15870. + }
  15871. + }
  15872. + /* should we remap certain errors, access denied?, to zero */
  15873. +
  15874. + /* if not oplocked, we invalidate inode pages if mtime
  15875. + or file size had changed on server */
  15876. +
  15877. + if((local_mtime == direntry->d_inode->i_mtime) &&
  15878. + (local_size == direntry->d_inode->i_size)) {
  15879. + cFYI(1,("cifs_revalidate - inode unchanged"));
  15880. + } else {
  15881. + /* file may have changed on server */
  15882. + if(cifsInode->clientCanCacheRead) {
  15883. + /* no need to invalidate inode pages since we were
  15884. + the only ones who could have modified the file and
  15885. + the server copy is staler than ours */
  15886. + } else {
  15887. + invalidate_inode = TRUE;
  15888. + }
  15889. + }
  15890. +
  15891. + /* can not grab this sem since kernel filesys locking
  15892. + documentation indicates i_sem may be taken by the kernel
  15893. + on lookup and rename which could deadlock if we grab
  15894. + the i_sem here as well */
  15895. +/* down(&direntry->d_inode->i_sem);*/
  15896. + /* need to write out dirty pages here */
  15897. + if(direntry->d_inode->i_mapping) {
  15898. + /* do we need to lock inode until after invalidate completes below? */
  15899. + filemap_fdatasync(direntry->d_inode->i_mapping);
  15900. + }
  15901. + if(invalidate_inode) {
  15902. + filemap_fdatawait(direntry->d_inode->i_mapping);
  15903. + /* may eventually have to do this for open files too */
  15904. + if(list_empty(&(cifsInode->openFileList))) {
  15905. + /* Has changed on server - flush read ahead pages */
  15906. + cFYI(1,("Invalidating read ahead data on closed file"));
  15907. + invalidate_inode_pages(direntry->d_inode);
  15908. + }
  15909. + }
  15910. +/* up(&direntry->d_inode->i_sem);*/
  15911. +
  15912. + if (full_path)
  15913. + kfree(full_path);
  15914. + FreeXid(xid);
  15915. +
  15916. + return rc;
  15917. +}
  15918. +
  15919. +/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  15920. +{
  15921. + int err = cifs_revalidate(dentry);
  15922. + if (!err)
  15923. + generic_fillattr(dentry->d_inode, stat);
  15924. + return err;
  15925. +} */
  15926. +
  15927. +void
  15928. +cifs_truncate_file(struct inode *inode)
  15929. +{ /* BB remove - may not need this function after all BB */
  15930. + int xid;
  15931. + int rc = -EIO;
  15932. + int found = FALSE;
  15933. + struct cifsFileInfo *open_file = NULL;
  15934. + struct cifs_sb_info *cifs_sb;
  15935. + struct cifsTconInfo *pTcon;
  15936. + struct cifsInodeInfo *cifsInode;
  15937. + struct dentry *dirent;
  15938. + struct list_head * tmp;
  15939. + char *full_path = NULL;
  15940. +
  15941. + xid = GetXid();
  15942. +
  15943. + cifs_sb = CIFS_SB(inode->i_sb);
  15944. + pTcon = cifs_sb->tcon;
  15945. +
  15946. + /* To avoid spurious oplock breaks from server, in the case
  15947. + of inodes that we already have open, avoid doing path
  15948. + based setting of file size if we can do it by handle.
  15949. + This keeps our caching token (oplock) and avoids
  15950. + timeouts when the local oplock break takes longer to flush
  15951. + writebehind data than the SMB timeout for the SetPathInfo
  15952. + request would allow */
  15953. + read_lock(&GlobalSMBSeslock);
  15954. + cifsInode = CIFS_I(inode);
  15955. + list_for_each(tmp, &cifsInode->openFileList) {
  15956. + open_file = list_entry(tmp,struct cifsFileInfo, flist);
  15957. + /* We check if file is open for writing first */
  15958. + if((open_file->pfile) && (!open_file->invalidHandle) &&
  15959. + ((open_file->pfile->f_flags & O_RDWR) ||
  15960. + (open_file->pfile->f_flags & O_WRONLY))) {
  15961. + read_unlock(&GlobalSMBSeslock);
  15962. + found = TRUE;
  15963. + rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
  15964. + open_file->netfid,open_file->pid,FALSE);
  15965. + if(rc == 0) {
  15966. + FreeXid(xid);
  15967. + return;
  15968. + }
  15969. + /* Do not need reopen and retry on EAGAIN since we will
  15970. + retry by pathname below */
  15971. + if(rc == -EAGAIN)
  15972. + rc = -EHOSTDOWN;
  15973. +
  15974. + break; /* now that we found one valid file handle no
  15975. + sense continuing to loop trying others */
  15976. + }
  15977. + }
  15978. + if(found == FALSE)
  15979. + read_unlock(&GlobalSMBSeslock);
  15980. +
  15981. + if (list_empty(&inode->i_dentry)) {
  15982. + cERROR(1,
  15983. + ("Can not get pathname from empty dentry in inode 0x%p ",
  15984. + inode));
  15985. + FreeXid(xid);
  15986. + return;
  15987. + }
  15988. +
  15989. + dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
  15990. + if (dirent) {
  15991. + full_path = build_path_from_dentry(dirent);
  15992. + rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
  15993. + cifs_sb->local_nls);
  15994. + cFYI(1,(" SetEOF (truncate) rc = %d",rc));
  15995. + if (!rc)
  15996. + CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
  15997. + /* allocation size setting seems optional so ignore return code */
  15998. + }
  15999. + if (full_path)
  16000. + kfree(full_path);
  16001. + FreeXid(xid);
  16002. + return;
  16003. +}
  16004. +
  16005. +static int cifs_truncate_page(struct address_space *mapping, loff_t from)
  16006. +{
  16007. + unsigned long index = from >> PAGE_CACHE_SHIFT;
  16008. + unsigned offset = from & (PAGE_CACHE_SIZE-1);
  16009. + struct page *page;
  16010. + char *kaddr;
  16011. + int rc = 0;
  16012. +
  16013. + page = grab_cache_page(mapping, index);
  16014. + if (!page)
  16015. + return -ENOMEM;
  16016. +
  16017. + kaddr = kmap_atomic(page, KM_USER0);
  16018. + memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
  16019. + flush_dcache_page(page);
  16020. + kunmap_atomic(kaddr, KM_USER0);
  16021. + unlock_page(page);
  16022. + page_cache_release(page);
  16023. + return rc;
  16024. +}
  16025. +
  16026. +int
  16027. +cifs_setattr(struct dentry *direntry, struct iattr *attrs)
  16028. +{
  16029. + int xid;
  16030. + struct cifs_sb_info *cifs_sb;
  16031. + struct cifsTconInfo *pTcon;
  16032. + char *full_path = NULL;
  16033. + int rc = -EACCES;
  16034. + int found = FALSE;
  16035. + struct cifsFileInfo *open_file = NULL;
  16036. + FILE_BASIC_INFO time_buf;
  16037. + int set_time = FALSE;
  16038. + __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
  16039. + __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
  16040. + __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
  16041. + struct cifsInodeInfo *cifsInode;
  16042. + struct list_head * tmp;
  16043. +
  16044. + xid = GetXid();
  16045. +
  16046. + cFYI(1,
  16047. + (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
  16048. + direntry->d_name.name, attrs->ia_valid));
  16049. + cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
  16050. + pTcon = cifs_sb->tcon;
  16051. +
  16052. + down(&direntry->d_sb->s_vfs_rename_sem);
  16053. + full_path = build_path_from_dentry(direntry);
  16054. + up(&direntry->d_sb->s_vfs_rename_sem);
  16055. + if(full_path == NULL) {
  16056. + FreeXid(xid);
  16057. + return -ENOMEM;
  16058. + }
  16059. + cifsInode = CIFS_I(direntry->d_inode);
  16060. +
  16061. + /* BB check if we need to refresh inode from server now ? BB */
  16062. +
  16063. + /* need to flush data before changing file size on server */
  16064. + filemap_fdatasync(direntry->d_inode->i_mapping);
  16065. +
  16066. + if (attrs->ia_valid & ATTR_SIZE) {
  16067. + read_lock(&GlobalSMBSeslock);
  16068. + /* To avoid spurious oplock breaks from server, in the case
  16069. + of inodes that we already have open, avoid doing path
  16070. + based setting of file size if we can do it by handle.
  16071. + This keeps our caching token (oplock) and avoids
  16072. + timeouts when the local oplock break takes longer to flush
  16073. + writebehind data than the SMB timeout for the SetPathInfo
  16074. + request would allow */
  16075. + list_for_each(tmp, &cifsInode->openFileList) {
  16076. + open_file = list_entry(tmp,struct cifsFileInfo, flist);
  16077. + /* We check if file is open for writing first */
  16078. + if((open_file->pfile) &&
  16079. + ((open_file->pfile->f_flags & O_RDWR) ||
  16080. + (open_file->pfile->f_flags & O_WRONLY))) {
  16081. + if(open_file->invalidHandle == FALSE) {
  16082. + /* we found a valid, writeable network file
  16083. + handle to use to try to set the file size */
  16084. + __u16 nfid = open_file->netfid;
  16085. + __u32 npid = open_file->pid;
  16086. + read_unlock(&GlobalSMBSeslock);
  16087. + found = TRUE;
  16088. + rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
  16089. + nfid,npid,FALSE);
  16090. + cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
  16091. + /* Do not need reopen and retry on EAGAIN since we will
  16092. + retry by pathname below */
  16093. +
  16094. + break; /* now that we found one valid file handle no
  16095. + sense continuing to loop trying others */
  16096. + }
  16097. + }
  16098. + }
  16099. + if(found == FALSE) {
  16100. + read_unlock(&GlobalSMBSeslock);
  16101. + }
  16102. +
  16103. +
  16104. + if(rc != 0) {
  16105. + /* Set file size by pathname rather than by handle either
  16106. + because no valid, writeable file handle for it was found or
  16107. + because there was an error setting it by handle */
  16108. + rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
  16109. + cifs_sb->local_nls);
  16110. + cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
  16111. + }
  16112. +
  16113. + /* Server is ok setting allocation size implicitly - no need to call: */
  16114. + /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
  16115. +
  16116. + if (rc == 0) {
  16117. + rc = vmtruncate(direntry->d_inode, attrs->ia_size);
  16118. + cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
  16119. + }
  16120. + }
  16121. + if (attrs->ia_valid & ATTR_UID) {
  16122. + cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
  16123. + uid = attrs->ia_uid;
  16124. + /* entry->uid = cpu_to_le16(attr->ia_uid); */
  16125. + }
  16126. + if (attrs->ia_valid & ATTR_GID) {
  16127. + cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
  16128. + gid = attrs->ia_gid;
  16129. + /* entry->gid = cpu_to_le16(attr->ia_gid); */
  16130. + }
  16131. +
  16132. + time_buf.Attributes = 0;
  16133. + if (attrs->ia_valid & ATTR_MODE) {
  16134. + cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
  16135. + mode = attrs->ia_mode;
  16136. + /* entry->mode = cpu_to_le16(attr->ia_mode); */
  16137. + }
  16138. +
  16139. + if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  16140. + && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
  16141. + rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
  16142. + 0 /* dev_t */, cifs_sb->local_nls);
  16143. + else if (attrs->ia_valid & ATTR_MODE) {
  16144. + if((mode & S_IWUGO) == 0) /* not writeable */ {
  16145. + if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
  16146. + time_buf.Attributes =
  16147. + cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
  16148. + } else if((mode & S_IWUGO) == S_IWUGO) {
  16149. + if(cifsInode->cifsAttrs & ATTR_READONLY)
  16150. + time_buf.Attributes =
  16151. + cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
  16152. + }
  16153. + /* BB to be implemented - via Windows security descriptors or streams */
  16154. + /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
  16155. + }
  16156. +
  16157. + if (attrs->ia_valid & ATTR_ATIME) {
  16158. + set_time = TRUE;
  16159. + time_buf.LastAccessTime =
  16160. + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
  16161. + } else
  16162. + time_buf.LastAccessTime = 0;
  16163. +
  16164. + if (attrs->ia_valid & ATTR_MTIME) {
  16165. + set_time = TRUE;
  16166. + time_buf.LastWriteTime =
  16167. + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
  16168. + } else
  16169. + time_buf.LastWriteTime = 0;
  16170. +
  16171. + if (attrs->ia_valid & ATTR_CTIME) {
  16172. + set_time = TRUE;
  16173. + time_buf.ChangeTime =
  16174. + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
  16175. + } else
  16176. + time_buf.ChangeTime = 0;
  16177. +
  16178. + if (set_time | time_buf.Attributes) {
  16179. + /* BB what if setting one attribute fails
  16180. + (such as size) but time setting works */
  16181. + time_buf.CreationTime = 0; /* do not change */
  16182. + /* In the future we should experiment - try setting timestamps
  16183. + via Handle (SetFileInfo) instead of by path */
  16184. + rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
  16185. + cifs_sb->local_nls);
  16186. + }
  16187. +
  16188. + /* do not need local check to inode_check_ok since the server does that */
  16189. + if (!rc)
  16190. + rc = inode_setattr(direntry->d_inode, attrs);
  16191. + if (full_path)
  16192. + kfree(full_path);
  16193. + FreeXid(xid);
  16194. + return rc;
  16195. +}
  16196. +
  16197. +void
  16198. +cifs_delete_inode(struct inode *inode)
  16199. +{
  16200. + cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
  16201. + /* may have to add back in if and when safe distributed caching of
  16202. + directories added e.g. via FindNotify */
  16203. +}
  16204. --- /dev/null
  16205. +++ b/fs/cifs/link.c
  16206. @@ -0,0 +1,328 @@
  16207. +/*
  16208. + * fs/cifs/link.c
  16209. + *
  16210. + * Copyright (C) International Business Machines Corp., 2002,2003
  16211. + * Author(s): Steve French ([email protected])
  16212. + *
  16213. + * This library is free software; you can redistribute it and/or modify
  16214. + * it under the terms of the GNU Lesser General Public License as published
  16215. + * by the Free Software Foundation; either version 2.1 of the License, or
  16216. + * (at your option) any later version.
  16217. + *
  16218. + * This library is distributed in the hope that it will be useful,
  16219. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16220. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  16221. + * the GNU Lesser General Public License for more details.
  16222. + *
  16223. + * You should have received a copy of the GNU Lesser General Public License
  16224. + * along with this library; if not, write to the Free Software
  16225. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16226. + */
  16227. +#include <linux/fs.h>
  16228. +#include <linux/stat.h>
  16229. +#include "cifsfs.h"
  16230. +#include "cifspdu.h"
  16231. +#include "cifsglob.h"
  16232. +#include "cifsproto.h"
  16233. +#include "cifs_debug.h"
  16234. +#include "cifs_fs_sb.h"
  16235. +
  16236. +int
  16237. +cifs_hardlink(struct dentry *old_file, struct inode *inode,
  16238. + struct dentry *direntry)
  16239. +{
  16240. + int rc = -EACCES;
  16241. + int xid;
  16242. + char *fromName = NULL;
  16243. + char *toName = NULL;
  16244. + struct cifs_sb_info *cifs_sb_target;
  16245. + struct cifsTconInfo *pTcon;
  16246. + struct cifsInodeInfo *cifsInode;
  16247. +
  16248. + xid = GetXid();
  16249. +
  16250. + cifs_sb_target = CIFS_SB(inode->i_sb);
  16251. + pTcon = cifs_sb_target->tcon;
  16252. +
  16253. +/* No need to check for cross device links since server will do that
  16254. + BB note DFS case in future though (when we may have to check) */
  16255. +
  16256. + down(&inode->i_sb->s_vfs_rename_sem);
  16257. + fromName = build_path_from_dentry(old_file);
  16258. + toName = build_path_from_dentry(direntry);
  16259. + up(&inode->i_sb->s_vfs_rename_sem);
  16260. + if((fromName == NULL) || (toName == NULL)) {
  16261. + rc = -ENOMEM;
  16262. + goto cifs_hl_exit;
  16263. + }
  16264. +
  16265. + if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
  16266. + rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
  16267. + cifs_sb_target->local_nls);
  16268. + else {
  16269. + rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
  16270. + cifs_sb_target->local_nls);
  16271. + if(rc == -EIO)
  16272. + rc = -EOPNOTSUPP;
  16273. + }
  16274. +
  16275. +/* if (!rc) */
  16276. + {
  16277. + /* renew_parental_timestamps(old_file);
  16278. + inode->i_nlink++;
  16279. + mark_inode_dirty(inode);
  16280. + d_instantiate(direntry, inode); */
  16281. + /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
  16282. + }
  16283. + d_drop(direntry); /* force new lookup from server */
  16284. + cifsInode = CIFS_I(old_file->d_inode);
  16285. + cifsInode->time = 0; /* will force revalidate to go get info when needed */
  16286. +
  16287. +cifs_hl_exit:
  16288. + if (fromName)
  16289. + kfree(fromName);
  16290. + if (toName)
  16291. + kfree(toName);
  16292. + FreeXid(xid);
  16293. + return rc;
  16294. +}
  16295. +
  16296. +int
  16297. +cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
  16298. +{
  16299. + struct inode *inode = direntry->d_inode;
  16300. + int rc = -EACCES;
  16301. + int xid;
  16302. + char *full_path = NULL;
  16303. + char * target_path;
  16304. + struct cifs_sb_info *cifs_sb;
  16305. + struct cifsTconInfo *pTcon;
  16306. +
  16307. + xid = GetXid();
  16308. +
  16309. + down(&direntry->d_sb->s_vfs_rename_sem);
  16310. + full_path = build_path_from_dentry(direntry);
  16311. + up(&direntry->d_sb->s_vfs_rename_sem);
  16312. +
  16313. + if(full_path == NULL) {
  16314. + FreeXid(xid);
  16315. + return -ENOMEM;
  16316. + }
  16317. + cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
  16318. + cifs_sb = CIFS_SB(inode->i_sb);
  16319. + pTcon = cifs_sb->tcon;
  16320. + target_path = kmalloc(PATH_MAX, GFP_KERNEL);
  16321. + if(target_path == NULL) {
  16322. + if (full_path)
  16323. + kfree(full_path);
  16324. + FreeXid(xid);
  16325. + return -ENOMEM;
  16326. + }
  16327. + /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
  16328. + /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
  16329. +
  16330. +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
  16331. + if (pTcon->ses->capabilities & CAP_UNIX)
  16332. + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
  16333. + target_path,
  16334. + PATH_MAX-1,
  16335. + cifs_sb->local_nls);
  16336. + else {
  16337. + /* rc = CIFSSMBQueryReparseLinkInfo */
  16338. + /* BB Add code to Query ReparsePoint info */
  16339. + }
  16340. + /* BB Anything else to do to handle recursive links? */
  16341. + /* BB Should we be using page symlink ops here? */
  16342. +
  16343. + if (rc == 0) {
  16344. +
  16345. +/* BB Add special case check for Samba DFS symlinks */
  16346. +
  16347. + target_path[PATH_MAX-1] = 0;
  16348. + rc = vfs_follow_link(nd, target_path);
  16349. + }
  16350. + /* else EACCESS */
  16351. +
  16352. + if (target_path)
  16353. + kfree(target_path);
  16354. + if (full_path)
  16355. + kfree(full_path);
  16356. + FreeXid(xid);
  16357. + return rc;
  16358. +}
  16359. +
  16360. +int
  16361. +cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
  16362. +{
  16363. + int rc = -EOPNOTSUPP;
  16364. + int xid;
  16365. + struct cifs_sb_info *cifs_sb;
  16366. + struct cifsTconInfo *pTcon;
  16367. + char *full_path = NULL;
  16368. + struct inode *newinode = NULL;
  16369. +
  16370. + xid = GetXid();
  16371. +
  16372. + cifs_sb = CIFS_SB(inode->i_sb);
  16373. + pTcon = cifs_sb->tcon;
  16374. +
  16375. + down(&inode->i_sb->s_vfs_rename_sem);
  16376. + full_path = build_path_from_dentry(direntry);
  16377. + up(&inode->i_sb->s_vfs_rename_sem);
  16378. +
  16379. + if(full_path == NULL) {
  16380. + FreeXid(xid);
  16381. + return -ENOMEM;
  16382. + }
  16383. +
  16384. + cFYI(1, ("Full path: %s ", full_path));
  16385. + cFYI(1, ("symname is %s", symname));
  16386. +
  16387. + /* BB what if DFS and this volume is on different share? BB */
  16388. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  16389. + rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
  16390. + cifs_sb->local_nls);
  16391. + /* else
  16392. + rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
  16393. +
  16394. + if (rc == 0) {
  16395. + if (pTcon->ses->capabilities & CAP_UNIX)
  16396. + rc = cifs_get_inode_info_unix(&newinode, full_path,
  16397. + inode->i_sb,xid);
  16398. + else
  16399. + rc = cifs_get_inode_info(&newinode, full_path, NULL,
  16400. + inode->i_sb,xid);
  16401. +
  16402. + if (rc != 0) {
  16403. + cFYI(1,
  16404. + ("Create symlink worked but get_inode_info failed with rc = %d ",
  16405. + rc));
  16406. + } else {
  16407. + direntry->d_op = &cifs_dentry_ops;
  16408. + d_instantiate(direntry, newinode);
  16409. + }
  16410. + }
  16411. +
  16412. + if (full_path)
  16413. + kfree(full_path);
  16414. + FreeXid(xid);
  16415. + return rc;
  16416. +}
  16417. +
  16418. +int
  16419. +cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
  16420. +{
  16421. + struct inode *inode = direntry->d_inode;
  16422. + int rc = -EACCES;
  16423. + int xid;
  16424. + int oplock = FALSE;
  16425. + struct cifs_sb_info *cifs_sb;
  16426. + struct cifsTconInfo *pTcon;
  16427. + char *full_path = NULL;
  16428. + char *tmp_path = NULL;
  16429. + char * tmpbuffer;
  16430. + unsigned char * referrals = NULL;
  16431. + int num_referrals = 0;
  16432. + int len;
  16433. + __u16 fid;
  16434. +
  16435. + xid = GetXid();
  16436. + cifs_sb = CIFS_SB(inode->i_sb);
  16437. + pTcon = cifs_sb->tcon;
  16438. +
  16439. +/* BB would it be safe against deadlock to grab this sem
  16440. + even though rename itself grabs the sem and calls lookup? */
  16441. +/* down(&inode->i_sb->s_vfs_rename_sem);*/
  16442. + full_path = build_path_from_dentry(direntry);
  16443. +/* up(&inode->i_sb->s_vfs_rename_sem);*/
  16444. +
  16445. + if(full_path == NULL) {
  16446. + FreeXid(xid);
  16447. + return -ENOMEM;
  16448. + }
  16449. +
  16450. + cFYI(1,
  16451. + ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
  16452. + full_path, inode, pBuffer, buflen));
  16453. + if(buflen > PATH_MAX)
  16454. + len = PATH_MAX;
  16455. + else
  16456. + len = buflen;
  16457. + tmpbuffer = kmalloc(len,GFP_KERNEL);
  16458. + if(tmpbuffer == NULL) {
  16459. + if (full_path)
  16460. + kfree(full_path);
  16461. + FreeXid(xid);
  16462. + return -ENOMEM;
  16463. + }
  16464. +
  16465. +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
  16466. + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
  16467. + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
  16468. + tmpbuffer,
  16469. + len - 1,
  16470. + cifs_sb->local_nls);
  16471. + else {
  16472. + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
  16473. + OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
  16474. + if(!rc) {
  16475. + rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
  16476. + tmpbuffer,
  16477. + len - 1,
  16478. + fid,
  16479. + cifs_sb->local_nls);
  16480. + if(CIFSSMBClose(xid, pTcon, fid)) {
  16481. + cFYI(1,("Error closing junction point (open for ioctl)"));
  16482. + }
  16483. + if(rc == -EIO) {
  16484. + /* Query if DFS Junction */
  16485. + tmp_path =
  16486. + kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
  16487. + GFP_KERNEL);
  16488. + if (tmp_path) {
  16489. + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
  16490. + strncat(tmp_path, full_path, MAX_PATHCONF);
  16491. + rc = get_dfs_path(xid, pTcon->ses, tmp_path,
  16492. + cifs_sb->local_nls, &num_referrals, &referrals);
  16493. + cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
  16494. + if((num_referrals == 0) && (rc == 0))
  16495. + rc = -EACCES;
  16496. + else {
  16497. + cFYI(1,("num referral: %d",num_referrals));
  16498. + if(referrals) {
  16499. + cFYI(1,("referral string: %s ",referrals));
  16500. + strncpy(tmpbuffer, referrals, len-1);
  16501. + }
  16502. + }
  16503. + if(referrals)
  16504. + kfree(referrals);
  16505. + kfree(tmp_path);
  16506. + if(referrals) {
  16507. + kfree(referrals);
  16508. + }
  16509. + }
  16510. + /* BB add code like else decode referrals then memcpy to
  16511. + tmpbuffer and free referrals string array BB */
  16512. + }
  16513. + }
  16514. + }
  16515. + /* BB Anything else to do to handle recursive links? */
  16516. + /* BB Should we be using page ops here? */
  16517. +
  16518. + /* BB null terminate returned string in pBuffer? BB */
  16519. + if (rc == 0) {
  16520. + rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
  16521. + cFYI(1,
  16522. + ("vfs_readlink called from cifs_readlink returned %d",
  16523. + rc));
  16524. + }
  16525. +
  16526. + if (tmpbuffer) {
  16527. + kfree(tmpbuffer);
  16528. + }
  16529. + if (full_path) {
  16530. + kfree(full_path);
  16531. + }
  16532. + FreeXid(xid);
  16533. + return rc;
  16534. +}
  16535. --- /dev/null
  16536. +++ b/fs/cifs/Makefile
  16537. @@ -0,0 +1,10 @@
  16538. +#
  16539. +# Makefile for Linux CIFS VFS client
  16540. +#
  16541. +O_TARGET := cifs.o
  16542. +
  16543. +obj-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o cifsencrypt.o
  16544. +
  16545. +obj-m := $(O_TARGET)
  16546. +
  16547. +include $(TOPDIR)/Rules.make
  16548. --- /dev/null
  16549. +++ b/fs/cifs/md4.c
  16550. @@ -0,0 +1,203 @@
  16551. +/*
  16552. + Unix SMB/Netbios implementation.
  16553. + Version 1.9.
  16554. + a implementation of MD4 designed for use in the SMB authentication protocol
  16555. + Copyright (C) Andrew Tridgell 1997-1998.
  16556. + Modified by Steve French ([email protected]) 2002-2003
  16557. +
  16558. + This program is free software; you can redistribute it and/or modify
  16559. + it under the terms of the GNU General Public License as published by
  16560. + the Free Software Foundation; either version 2 of the License, or
  16561. + (at your option) any later version.
  16562. +
  16563. + This program is distributed in the hope that it will be useful,
  16564. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  16565. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16566. + GNU General Public License for more details.
  16567. +
  16568. + You should have received a copy of the GNU General Public License
  16569. + along with this program; if not, write to the Free Software
  16570. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16571. +*/
  16572. +#include <linux/module.h>
  16573. +#include <linux/fs.h>
  16574. +/* NOTE: This code makes no attempt to be fast! */
  16575. +
  16576. +static __u32
  16577. +F(__u32 X, __u32 Y, __u32 Z)
  16578. +{
  16579. + return (X & Y) | ((~X) & Z);
  16580. +}
  16581. +
  16582. +static __u32
  16583. +G(__u32 X, __u32 Y, __u32 Z)
  16584. +{
  16585. + return (X & Y) | (X & Z) | (Y & Z);
  16586. +}
  16587. +
  16588. +static __u32
  16589. +H(__u32 X, __u32 Y, __u32 Z)
  16590. +{
  16591. + return X ^ Y ^ Z;
  16592. +}
  16593. +
  16594. +static __u32
  16595. +lshift(__u32 x, int s)
  16596. +{
  16597. + x &= 0xFFFFFFFF;
  16598. + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
  16599. +}
  16600. +
  16601. +#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
  16602. +#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
  16603. +#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
  16604. +
  16605. +/* this applies md4 to 64 byte chunks */
  16606. +static void
  16607. +mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
  16608. +{
  16609. + int j;
  16610. + __u32 AA, BB, CC, DD;
  16611. + __u32 X[16];
  16612. +
  16613. +
  16614. + for (j = 0; j < 16; j++)
  16615. + X[j] = M[j];
  16616. +
  16617. + AA = *A;
  16618. + BB = *B;
  16619. + CC = *C;
  16620. + DD = *D;
  16621. +
  16622. + ROUND1(A, B, C, D, 0, 3);
  16623. + ROUND1(D, A, B, C, 1, 7);
  16624. + ROUND1(C, D, A, B, 2, 11);
  16625. + ROUND1(B, C, D, A, 3, 19);
  16626. + ROUND1(A, B, C, D, 4, 3);
  16627. + ROUND1(D, A, B, C, 5, 7);
  16628. + ROUND1(C, D, A, B, 6, 11);
  16629. + ROUND1(B, C, D, A, 7, 19);
  16630. + ROUND1(A, B, C, D, 8, 3);
  16631. + ROUND1(D, A, B, C, 9, 7);
  16632. + ROUND1(C, D, A, B, 10, 11);
  16633. + ROUND1(B, C, D, A, 11, 19);
  16634. + ROUND1(A, B, C, D, 12, 3);
  16635. + ROUND1(D, A, B, C, 13, 7);
  16636. + ROUND1(C, D, A, B, 14, 11);
  16637. + ROUND1(B, C, D, A, 15, 19);
  16638. +
  16639. + ROUND2(A, B, C, D, 0, 3);
  16640. + ROUND2(D, A, B, C, 4, 5);
  16641. + ROUND2(C, D, A, B, 8, 9);
  16642. + ROUND2(B, C, D, A, 12, 13);
  16643. + ROUND2(A, B, C, D, 1, 3);
  16644. + ROUND2(D, A, B, C, 5, 5);
  16645. + ROUND2(C, D, A, B, 9, 9);
  16646. + ROUND2(B, C, D, A, 13, 13);
  16647. + ROUND2(A, B, C, D, 2, 3);
  16648. + ROUND2(D, A, B, C, 6, 5);
  16649. + ROUND2(C, D, A, B, 10, 9);
  16650. + ROUND2(B, C, D, A, 14, 13);
  16651. + ROUND2(A, B, C, D, 3, 3);
  16652. + ROUND2(D, A, B, C, 7, 5);
  16653. + ROUND2(C, D, A, B, 11, 9);
  16654. + ROUND2(B, C, D, A, 15, 13);
  16655. +
  16656. + ROUND3(A, B, C, D, 0, 3);
  16657. + ROUND3(D, A, B, C, 8, 9);
  16658. + ROUND3(C, D, A, B, 4, 11);
  16659. + ROUND3(B, C, D, A, 12, 15);
  16660. + ROUND3(A, B, C, D, 2, 3);
  16661. + ROUND3(D, A, B, C, 10, 9);
  16662. + ROUND3(C, D, A, B, 6, 11);
  16663. + ROUND3(B, C, D, A, 14, 15);
  16664. + ROUND3(A, B, C, D, 1, 3);
  16665. + ROUND3(D, A, B, C, 9, 9);
  16666. + ROUND3(C, D, A, B, 5, 11);
  16667. + ROUND3(B, C, D, A, 13, 15);
  16668. + ROUND3(A, B, C, D, 3, 3);
  16669. + ROUND3(D, A, B, C, 11, 9);
  16670. + ROUND3(C, D, A, B, 7, 11);
  16671. + ROUND3(B, C, D, A, 15, 15);
  16672. +
  16673. + *A += AA;
  16674. + *B += BB;
  16675. + *C += CC;
  16676. + *D += DD;
  16677. +
  16678. + *A &= 0xFFFFFFFF;
  16679. + *B &= 0xFFFFFFFF;
  16680. + *C &= 0xFFFFFFFF;
  16681. + *D &= 0xFFFFFFFF;
  16682. +
  16683. + for (j = 0; j < 16; j++)
  16684. + X[j] = 0;
  16685. +}
  16686. +
  16687. +static void
  16688. +copy64(__u32 * M, unsigned char *in)
  16689. +{
  16690. + int i;
  16691. +
  16692. + for (i = 0; i < 16; i++)
  16693. + M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
  16694. + (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
  16695. +}
  16696. +
  16697. +static void
  16698. +copy4(unsigned char *out, __u32 x)
  16699. +{
  16700. + out[0] = x & 0xFF;
  16701. + out[1] = (x >> 8) & 0xFF;
  16702. + out[2] = (x >> 16) & 0xFF;
  16703. + out[3] = (x >> 24) & 0xFF;
  16704. +}
  16705. +
  16706. +/* produce a md4 message digest from data of length n bytes */
  16707. +void
  16708. +mdfour(unsigned char *out, unsigned char *in, int n)
  16709. +{
  16710. + unsigned char buf[128];
  16711. + __u32 M[16];
  16712. + __u32 b = n * 8;
  16713. + int i;
  16714. + __u32 A = 0x67452301;
  16715. + __u32 B = 0xefcdab89;
  16716. + __u32 C = 0x98badcfe;
  16717. + __u32 D = 0x10325476;
  16718. +
  16719. + while (n > 64) {
  16720. + copy64(M, in);
  16721. + mdfour64(M,&A,&B, &C, &D);
  16722. + in += 64;
  16723. + n -= 64;
  16724. + }
  16725. +
  16726. + for (i = 0; i < 128; i++)
  16727. + buf[i] = 0;
  16728. + memcpy(buf, in, n);
  16729. + buf[n] = 0x80;
  16730. +
  16731. + if (n <= 55) {
  16732. + copy4(buf + 56, b);
  16733. + copy64(M, buf);
  16734. + mdfour64(M, &A, &B, &C, &D);
  16735. + } else {
  16736. + copy4(buf + 120, b);
  16737. + copy64(M, buf);
  16738. + mdfour64(M, &A, &B, &C, &D);
  16739. + copy64(M, buf + 64);
  16740. + mdfour64(M, &A, &B, &C, &D);
  16741. + }
  16742. +
  16743. + for (i = 0; i < 128; i++)
  16744. + buf[i] = 0;
  16745. + copy64(M, buf);
  16746. +
  16747. + copy4(out, A);
  16748. + copy4(out + 4, B);
  16749. + copy4(out + 8, C);
  16750. + copy4(out + 12, D);
  16751. +
  16752. + A = B = C = D = 0;
  16753. +}
  16754. --- /dev/null
  16755. +++ b/fs/cifs/md5.c
  16756. @@ -0,0 +1,363 @@
  16757. +/*
  16758. + * This code implements the MD5 message-digest algorithm.
  16759. + * The algorithm is due to Ron Rivest. This code was
  16760. + * written by Colin Plumb in 1993, no copyright is claimed.
  16761. + * This code is in the public domain; do with it what you wish.
  16762. + *
  16763. + * Equivalent code is available from RSA Data Security, Inc.
  16764. + * This code has been tested against that, and is equivalent,
  16765. + * except that you don't need to include two pages of legalese
  16766. + * with every copy.
  16767. + *
  16768. + * To compute the message digest of a chunk of bytes, declare an
  16769. + * MD5Context structure, pass it to MD5Init, call MD5Update as
  16770. + * needed on buffers full of bytes, and then call MD5Final, which
  16771. + * will fill a supplied 16-byte array with the digest.
  16772. + */
  16773. +
  16774. +/* This code slightly modified to fit into Samba by
  16775. + [email protected] Jun 2001
  16776. + and to fit the cifs vfs by
  16777. + Steve French [email protected] */
  16778. +
  16779. +#include <linux/string.h>
  16780. +#include "md5.h"
  16781. +
  16782. +static void MD5Transform(__u32 buf[4], __u32 const in[16]);
  16783. +
  16784. +/*
  16785. + * Note: this code is harmless on little-endian machines.
  16786. + */
  16787. +static void
  16788. +byteReverse(unsigned char *buf, unsigned longs)
  16789. +{
  16790. + __u32 t;
  16791. + do {
  16792. + t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
  16793. + ((unsigned) buf[1] << 8 | buf[0]);
  16794. + *(__u32 *) buf = t;
  16795. + buf += 4;
  16796. + } while (--longs);
  16797. +}
  16798. +
  16799. +/*
  16800. + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
  16801. + * initialization constants.
  16802. + */
  16803. +void
  16804. +MD5Init(struct MD5Context *ctx)
  16805. +{
  16806. + ctx->buf[0] = 0x67452301;
  16807. + ctx->buf[1] = 0xefcdab89;
  16808. + ctx->buf[2] = 0x98badcfe;
  16809. + ctx->buf[3] = 0x10325476;
  16810. +
  16811. + ctx->bits[0] = 0;
  16812. + ctx->bits[1] = 0;
  16813. +}
  16814. +
  16815. +/*
  16816. + * Update context to reflect the concatenation of another buffer full
  16817. + * of bytes.
  16818. + */
  16819. +void
  16820. +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
  16821. +{
  16822. + register __u32 t;
  16823. +
  16824. + /* Update bitcount */
  16825. +
  16826. + t = ctx->bits[0];
  16827. + if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
  16828. + ctx->bits[1]++; /* Carry from low to high */
  16829. + ctx->bits[1] += len >> 29;
  16830. +
  16831. + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
  16832. +
  16833. + /* Handle any leading odd-sized chunks */
  16834. +
  16835. + if (t) {
  16836. + unsigned char *p = (unsigned char *) ctx->in + t;
  16837. +
  16838. + t = 64 - t;
  16839. + if (len < t) {
  16840. + memmove(p, buf, len);
  16841. + return;
  16842. + }
  16843. + memmove(p, buf, t);
  16844. + byteReverse(ctx->in, 16);
  16845. + MD5Transform(ctx->buf, (__u32 *) ctx->in);
  16846. + buf += t;
  16847. + len -= t;
  16848. + }
  16849. + /* Process data in 64-byte chunks */
  16850. +
  16851. + while (len >= 64) {
  16852. + memmove(ctx->in, buf, 64);
  16853. + byteReverse(ctx->in, 16);
  16854. + MD5Transform(ctx->buf, (__u32 *) ctx->in);
  16855. + buf += 64;
  16856. + len -= 64;
  16857. + }
  16858. +
  16859. + /* Handle any remaining bytes of data. */
  16860. +
  16861. + memmove(ctx->in, buf, len);
  16862. +}
  16863. +
  16864. +/*
  16865. + * Final wrapup - pad to 64-byte boundary with the bit pattern
  16866. + * 1 0* (64-bit count of bits processed, MSB-first)
  16867. + */
  16868. +void
  16869. +MD5Final(unsigned char digest[16], struct MD5Context *ctx)
  16870. +{
  16871. + unsigned int count;
  16872. + unsigned char *p;
  16873. +
  16874. + /* Compute number of bytes mod 64 */
  16875. + count = (ctx->bits[0] >> 3) & 0x3F;
  16876. +
  16877. + /* Set the first char of padding to 0x80. This is safe since there is
  16878. + always at least one byte free */
  16879. + p = ctx->in + count;
  16880. + *p++ = 0x80;
  16881. +
  16882. + /* Bytes of padding needed to make 64 bytes */
  16883. + count = 64 - 1 - count;
  16884. +
  16885. + /* Pad out to 56 mod 64 */
  16886. + if (count < 8) {
  16887. + /* Two lots of padding: Pad the first block to 64 bytes */
  16888. + memset(p, 0, count);
  16889. + byteReverse(ctx->in, 16);
  16890. + MD5Transform(ctx->buf, (__u32 *) ctx->in);
  16891. +
  16892. + /* Now fill the next block with 56 bytes */
  16893. + memset(ctx->in, 0, 56);
  16894. + } else {
  16895. + /* Pad block to 56 bytes */
  16896. + memset(p, 0, count - 8);
  16897. + }
  16898. + byteReverse(ctx->in, 14);
  16899. +
  16900. + /* Append length in bits and transform */
  16901. + ((__u32 *) ctx->in)[14] = ctx->bits[0];
  16902. + ((__u32 *) ctx->in)[15] = ctx->bits[1];
  16903. +
  16904. + MD5Transform(ctx->buf, (__u32 *) ctx->in);
  16905. + byteReverse((unsigned char *) ctx->buf, 4);
  16906. + memmove(digest, ctx->buf, 16);
  16907. + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
  16908. +}
  16909. +
  16910. +/* The four core functions - F1 is optimized somewhat */
  16911. +
  16912. +/* #define F1(x, y, z) (x & y | ~x & z) */
  16913. +#define F1(x, y, z) (z ^ (x & (y ^ z)))
  16914. +#define F2(x, y, z) F1(z, x, y)
  16915. +#define F3(x, y, z) (x ^ y ^ z)
  16916. +#define F4(x, y, z) (y ^ (x | ~z))
  16917. +
  16918. +/* This is the central step in the MD5 algorithm. */
  16919. +#define MD5STEP(f, w, x, y, z, data, s) \
  16920. + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
  16921. +
  16922. +/*
  16923. + * The core of the MD5 algorithm, this alters an existing MD5 hash to
  16924. + * reflect the addition of 16 longwords of new data. MD5Update blocks
  16925. + * the data and converts bytes into longwords for this routine.
  16926. + */
  16927. +static void
  16928. +MD5Transform(__u32 buf[4], __u32 const in[16])
  16929. +{
  16930. + register __u32 a, b, c, d;
  16931. +
  16932. + a = buf[0];
  16933. + b = buf[1];
  16934. + c = buf[2];
  16935. + d = buf[3];
  16936. +
  16937. + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
  16938. + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
  16939. + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
  16940. + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
  16941. + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
  16942. + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
  16943. + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
  16944. + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
  16945. + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
  16946. + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
  16947. + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
  16948. + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
  16949. + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
  16950. + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
  16951. + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
  16952. + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
  16953. +
  16954. + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
  16955. + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
  16956. + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
  16957. + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
  16958. + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
  16959. + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
  16960. + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
  16961. + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
  16962. + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
  16963. + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
  16964. + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
  16965. + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
  16966. + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
  16967. + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
  16968. + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
  16969. + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
  16970. +
  16971. + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
  16972. + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
  16973. + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
  16974. + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
  16975. + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
  16976. + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
  16977. + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
  16978. + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
  16979. + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
  16980. + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
  16981. + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
  16982. + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
  16983. + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
  16984. + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
  16985. + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
  16986. + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
  16987. +
  16988. + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
  16989. + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
  16990. + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
  16991. + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
  16992. + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
  16993. + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
  16994. + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
  16995. + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
  16996. + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
  16997. + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
  16998. + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
  16999. + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
  17000. + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
  17001. + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
  17002. + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
  17003. + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
  17004. +
  17005. + buf[0] += a;
  17006. + buf[1] += b;
  17007. + buf[2] += c;
  17008. + buf[3] += d;
  17009. +}
  17010. +
  17011. +/***********************************************************************
  17012. + the rfc 2104 version of hmac_md5 initialisation.
  17013. +***********************************************************************/
  17014. +void
  17015. +hmac_md5_init_rfc2104(unsigned char *key, int key_len,
  17016. + struct HMACMD5Context *ctx)
  17017. +{
  17018. + int i;
  17019. +
  17020. + /* if key is longer than 64 bytes reset it to key=MD5(key) */
  17021. + if (key_len > 64) {
  17022. + unsigned char tk[16];
  17023. + struct MD5Context tctx;
  17024. +
  17025. + MD5Init(&tctx);
  17026. + MD5Update(&tctx, key, key_len);
  17027. + MD5Final(tk, &tctx);
  17028. +
  17029. + key = tk;
  17030. + key_len = 16;
  17031. + }
  17032. +
  17033. + /* start out by storing key in pads */
  17034. + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
  17035. + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
  17036. + memcpy(ctx->k_ipad, key, key_len);
  17037. + memcpy(ctx->k_opad, key, key_len);
  17038. +
  17039. + /* XOR key with ipad and opad values */
  17040. + for (i = 0; i < 64; i++) {
  17041. + ctx->k_ipad[i] ^= 0x36;
  17042. + ctx->k_opad[i] ^= 0x5c;
  17043. + }
  17044. +
  17045. + MD5Init(&ctx->ctx);
  17046. + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
  17047. +}
  17048. +
  17049. +/***********************************************************************
  17050. + the microsoft version of hmac_md5 initialisation.
  17051. +***********************************************************************/
  17052. +void
  17053. +hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
  17054. + struct HMACMD5Context *ctx)
  17055. +{
  17056. + int i;
  17057. +
  17058. + /* if key is longer than 64 bytes truncate it */
  17059. + if (key_len > 64) {
  17060. + key_len = 64;
  17061. + }
  17062. +
  17063. + /* start out by storing key in pads */
  17064. + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
  17065. + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
  17066. + memcpy(ctx->k_ipad, key, key_len);
  17067. + memcpy(ctx->k_opad, key, key_len);
  17068. +
  17069. + /* XOR key with ipad and opad values */
  17070. + for (i = 0; i < 64; i++) {
  17071. + ctx->k_ipad[i] ^= 0x36;
  17072. + ctx->k_opad[i] ^= 0x5c;
  17073. + }
  17074. +
  17075. + MD5Init(&ctx->ctx);
  17076. + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
  17077. +}
  17078. +
  17079. +/***********************************************************************
  17080. + update hmac_md5 "inner" buffer
  17081. +***********************************************************************/
  17082. +void
  17083. +hmac_md5_update(const unsigned char *text, int text_len,
  17084. + struct HMACMD5Context *ctx)
  17085. +{
  17086. + MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
  17087. +}
  17088. +
  17089. +/***********************************************************************
  17090. + finish off hmac_md5 "inner" buffer and generate outer one.
  17091. +***********************************************************************/
  17092. +void
  17093. +hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
  17094. +{
  17095. + struct MD5Context ctx_o;
  17096. +
  17097. + MD5Final(digest, &ctx->ctx);
  17098. +
  17099. + MD5Init(&ctx_o);
  17100. + MD5Update(&ctx_o, ctx->k_opad, 64);
  17101. + MD5Update(&ctx_o, digest, 16);
  17102. + MD5Final(digest, &ctx_o);
  17103. +}
  17104. +
  17105. +/***********************************************************
  17106. + single function to calculate an HMAC MD5 digest from data.
  17107. + use the microsoft hmacmd5 init method because the key is 16 bytes.
  17108. +************************************************************/
  17109. +void
  17110. +hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
  17111. + unsigned char *digest)
  17112. +{
  17113. + struct HMACMD5Context ctx;
  17114. + hmac_md5_init_limK_to_64(key, 16, &ctx);
  17115. + if (data_len != 0) {
  17116. + hmac_md5_update(data, data_len, &ctx);
  17117. + }
  17118. + hmac_md5_final(digest, &ctx);
  17119. +}
  17120. --- /dev/null
  17121. +++ b/fs/cifs/md5.h
  17122. @@ -0,0 +1,38 @@
  17123. +#ifndef MD5_H
  17124. +#define MD5_H
  17125. +#ifndef HEADER_MD5_H
  17126. +/* Try to avoid clashes with OpenSSL */
  17127. +#define HEADER_MD5_H
  17128. +#endif
  17129. +
  17130. +struct MD5Context {
  17131. + __u32 buf[4];
  17132. + __u32 bits[2];
  17133. + unsigned char in[64];
  17134. +};
  17135. +#endif /* !MD5_H */
  17136. +
  17137. +#ifndef _HMAC_MD5_H
  17138. +struct HMACMD5Context {
  17139. + struct MD5Context ctx;
  17140. + unsigned char k_ipad[65];
  17141. + unsigned char k_opad[65];
  17142. +};
  17143. +#endif /* _HMAC_MD5_H */
  17144. +
  17145. +void MD5Init(struct MD5Context *context);
  17146. +void MD5Update(struct MD5Context *context, unsigned char const *buf,
  17147. + unsigned len);
  17148. +void MD5Final(unsigned char digest[16], struct MD5Context *context);
  17149. +
  17150. +/* The following definitions come from lib/hmacmd5.c */
  17151. +
  17152. +void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
  17153. + struct HMACMD5Context *ctx);
  17154. +void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
  17155. + struct HMACMD5Context *ctx);
  17156. +void hmac_md5_update(const unsigned char *text, int text_len,
  17157. + struct HMACMD5Context *ctx);
  17158. +void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
  17159. +void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
  17160. + unsigned char *digest);
  17161. --- /dev/null
  17162. +++ b/fs/cifs/misc.c
  17163. @@ -0,0 +1,463 @@
  17164. +/*
  17165. + * fs/cifs/misc.c
  17166. + *
  17167. + * Copyright (C) International Business Machines Corp., 2002,2003
  17168. + * Author(s): Steve French ([email protected])
  17169. + *
  17170. + * This library is free software; you can redistribute it and/or modify
  17171. + * it under the terms of the GNU Lesser General Public License as published
  17172. + * by the Free Software Foundation; either version 2.1 of the License, or
  17173. + * (at your option) any later version.
  17174. + *
  17175. + * This library is distributed in the hope that it will be useful,
  17176. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17177. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  17178. + * the GNU Lesser General Public License for more details.
  17179. + *
  17180. + * You should have received a copy of the GNU Lesser General Public License
  17181. + * along with this library; if not, write to the Free Software
  17182. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17183. + */
  17184. +
  17185. +#include <linux/slab.h>
  17186. +#include <linux/ctype.h>
  17187. +#include "cifspdu.h"
  17188. +#include "cifsglob.h"
  17189. +#include "cifsproto.h"
  17190. +#include "cifs_debug.h"
  17191. +#include "smberr.h"
  17192. +#include "nterr.h"
  17193. +
  17194. +extern kmem_cache_t *cifs_req_cachep;
  17195. +extern struct task_struct * oplockThread;
  17196. +
  17197. +__u16 GlobalMid; /* multiplex id - rotating counter */
  17198. +
  17199. +/* The xid serves as a useful identifier for each incoming vfs request,
  17200. + in a similar way to the mid which is useful to track each sent smb,
  17201. + and CurrentXid can also provide a running counter (although it
  17202. + will eventually wrap past zero) of the total vfs operations handled
  17203. + since the cifs fs was mounted */
  17204. +
  17205. +unsigned int
  17206. +_GetXid(void)
  17207. +{
  17208. + unsigned int xid;
  17209. +
  17210. + spin_lock(&GlobalMid_Lock);
  17211. + GlobalTotalActiveXid++;
  17212. + if (GlobalTotalActiveXid > GlobalMaxActiveXid)
  17213. + GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
  17214. + xid = GlobalCurrentXid++;
  17215. + spin_unlock(&GlobalMid_Lock);
  17216. + return xid;
  17217. +}
  17218. +
  17219. +void
  17220. +_FreeXid(unsigned int xid)
  17221. +{
  17222. + spin_lock(&GlobalMid_Lock);
  17223. + /* if(GlobalTotalActiveXid == 0)
  17224. + BUG(); */
  17225. + GlobalTotalActiveXid--;
  17226. + spin_unlock(&GlobalMid_Lock);
  17227. +}
  17228. +
  17229. +struct cifsSesInfo *
  17230. +sesInfoAlloc(void)
  17231. +{
  17232. + struct cifsSesInfo *ret_buf;
  17233. +
  17234. + ret_buf =
  17235. + (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
  17236. + GFP_KERNEL);
  17237. + if (ret_buf) {
  17238. + memset(ret_buf, 0, sizeof (struct cifsSesInfo));
  17239. + write_lock(&GlobalSMBSeslock);
  17240. + atomic_inc(&sesInfoAllocCount);
  17241. + ret_buf->status = CifsNew;
  17242. + list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
  17243. + init_MUTEX(&ret_buf->sesSem);
  17244. + write_unlock(&GlobalSMBSeslock);
  17245. + }
  17246. + return ret_buf;
  17247. +}
  17248. +
  17249. +void
  17250. +sesInfoFree(struct cifsSesInfo *buf_to_free)
  17251. +{
  17252. + if (buf_to_free == NULL) {
  17253. + cFYI(1, ("Null buffer passed to sesInfoFree"));
  17254. + return;
  17255. + }
  17256. +
  17257. + write_lock(&GlobalSMBSeslock);
  17258. + atomic_dec(&sesInfoAllocCount);
  17259. + list_del(&buf_to_free->cifsSessionList);
  17260. + write_unlock(&GlobalSMBSeslock);
  17261. + if (buf_to_free->serverOS)
  17262. + kfree(buf_to_free->serverOS);
  17263. + if (buf_to_free->serverDomain)
  17264. + kfree(buf_to_free->serverDomain);
  17265. + if (buf_to_free->serverNOS)
  17266. + kfree(buf_to_free->serverNOS);
  17267. + if (buf_to_free->password)
  17268. + kfree(buf_to_free->password);
  17269. + kfree(buf_to_free);
  17270. +}
  17271. +
  17272. +struct cifsTconInfo *
  17273. +tconInfoAlloc(void)
  17274. +{
  17275. + struct cifsTconInfo *ret_buf;
  17276. + ret_buf =
  17277. + (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
  17278. + GFP_KERNEL);
  17279. + if (ret_buf) {
  17280. + memset(ret_buf, 0, sizeof (struct cifsTconInfo));
  17281. + write_lock(&GlobalSMBSeslock);
  17282. + atomic_inc(&tconInfoAllocCount);
  17283. + list_add(&ret_buf->cifsConnectionList,
  17284. + &GlobalTreeConnectionList);
  17285. + ret_buf->tidStatus = CifsNew;
  17286. + INIT_LIST_HEAD(&ret_buf->openFileList);
  17287. + init_MUTEX(&ret_buf->tconSem);
  17288. +#ifdef CONFIG_CIFS_STATS
  17289. + ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
  17290. +#endif
  17291. + write_unlock(&GlobalSMBSeslock);
  17292. + }
  17293. + return ret_buf;
  17294. +}
  17295. +
  17296. +void
  17297. +tconInfoFree(struct cifsTconInfo *buf_to_free)
  17298. +{
  17299. + if (buf_to_free == NULL) {
  17300. + cFYI(1, ("Null buffer passed to tconInfoFree"));
  17301. + return;
  17302. + }
  17303. + write_lock(&GlobalSMBSeslock);
  17304. + atomic_dec(&tconInfoAllocCount);
  17305. + list_del(&buf_to_free->cifsConnectionList);
  17306. + write_unlock(&GlobalSMBSeslock);
  17307. + if (buf_to_free->nativeFileSystem)
  17308. + kfree(buf_to_free->nativeFileSystem);
  17309. + kfree(buf_to_free);
  17310. +}
  17311. +
  17312. +struct smb_hdr *
  17313. +cifs_buf_get(void)
  17314. +{
  17315. + struct smb_hdr *ret_buf = NULL;
  17316. +
  17317. +/* We could use negotiated size instead of max_msgsize -
  17318. + but it may be more efficient to always alloc same size
  17319. + albeit slightly larger than necessary and maxbuffersize
  17320. + defaults to this and can not be bigger */
  17321. + ret_buf =
  17322. + (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
  17323. +
  17324. + /* clear the first few header bytes */
  17325. + if (ret_buf) {
  17326. + memset(ret_buf, 0, sizeof (struct smb_hdr));
  17327. + atomic_inc(&bufAllocCount);
  17328. + }
  17329. +
  17330. + return ret_buf;
  17331. +}
  17332. +
  17333. +void
  17334. +cifs_buf_release(void *buf_to_free)
  17335. +{
  17336. +
  17337. + if (buf_to_free == NULL) {
  17338. + cFYI(1, ("Null buffer passed to cifs_buf_release"));
  17339. + return;
  17340. + }
  17341. + kmem_cache_free(cifs_req_cachep, buf_to_free);
  17342. +
  17343. + atomic_dec(&bufAllocCount);
  17344. + return;
  17345. +}
  17346. +
  17347. +void
  17348. +header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
  17349. + const struct cifsTconInfo *treeCon, int word_count
  17350. + /* length of fixed section (word count) in two byte units */
  17351. + )
  17352. +{
  17353. + int i;
  17354. + __u32 tmp;
  17355. + struct list_head* temp_item;
  17356. + struct cifsSesInfo * ses;
  17357. + char *temp = (char *) buffer;
  17358. +
  17359. + for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
  17360. + temp[i] = 0; /* BB is this needed ?? */
  17361. + }
  17362. +
  17363. + buffer->smb_buf_length =
  17364. + (2 * word_count) + sizeof (struct smb_hdr) -
  17365. + 4 /* RFC 1001 length field does not count */ +
  17366. + 2 /* for bcc field itself */ ;
  17367. + /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
  17368. +
  17369. + buffer->Protocol[0] = 0xFF;
  17370. + buffer->Protocol[1] = 'S';
  17371. + buffer->Protocol[2] = 'M';
  17372. + buffer->Protocol[3] = 'B';
  17373. + buffer->Command = smb_command;
  17374. + buffer->Flags = 0x00; /* case sensitive */
  17375. + buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
  17376. + tmp = cpu_to_le32(current->pid);
  17377. + buffer->Pid = tmp & 0xFFFF;
  17378. + tmp >>= 16;
  17379. + buffer->PidHigh = tmp & 0xFFFF;
  17380. + spin_lock(&GlobalMid_Lock);
  17381. + GlobalMid++;
  17382. + buffer->Mid = GlobalMid;
  17383. + spin_unlock(&GlobalMid_Lock);
  17384. + if (treeCon) {
  17385. + buffer->Tid = treeCon->tid;
  17386. + if (treeCon->ses) {
  17387. + if (treeCon->ses->capabilities & CAP_UNICODE)
  17388. + buffer->Flags2 |= SMBFLG2_UNICODE;
  17389. + if (treeCon->ses->capabilities & CAP_STATUS32) {
  17390. + buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  17391. + }
  17392. +
  17393. + buffer->Uid = treeCon->ses->Suid; /* always in LE format */
  17394. + if(multiuser_mount != 0) {
  17395. + /* For the multiuser case, there are few obvious technically */
  17396. + /* possible mechanisms to match the local linux user (uid) */
  17397. + /* to a valid remote smb user (smb_uid): */
  17398. + /* 1) Query Winbind (or other local pam/nss daemon */
  17399. + /* for userid/password/logon_domain or credential */
  17400. + /* 2) Query Winbind for uid to sid to username mapping */
  17401. + /* and see if we have a matching password for existing*/
  17402. + /* session for that user perhas getting password by */
  17403. + /* adding a new pam_cifs module that stores passwords */
  17404. + /* so that the cifs vfs can get at that for all logged*/
  17405. + /* on users */
  17406. + /* 3) (Which is the mechanism we have chosen) */
  17407. + /* Search through sessions to the same server for a */
  17408. + /* a match on the uid that was passed in on mount */
  17409. + /* with the current processes uid (or euid?) and use */
  17410. + /* that smb uid. If no existing smb session for */
  17411. + /* that uid found, use the default smb session ie */
  17412. + /* the smb session for the volume mounted which is */
  17413. + /* the same as would be used if the multiuser mount */
  17414. + /* flag were disabled. */
  17415. +
  17416. + /* BB Add support for establishing new tCon and SMB Session */
  17417. + /* with userid/password pairs found on the smb session */
  17418. + /* for other target tcp/ip addresses BB */
  17419. + if(current->uid != treeCon->ses->linux_uid) {
  17420. + cFYI(1,("Multiuser mode and UID did not match tcon uid "));
  17421. + read_lock(&GlobalSMBSeslock);
  17422. + list_for_each(temp_item, &GlobalSMBSessionList) {
  17423. + ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
  17424. + if(ses->linux_uid == current->uid) {
  17425. + if(ses->server == treeCon->ses->server) {
  17426. + cFYI(1,("found matching uid substitute right smb_uid"));
  17427. + buffer->Uid = ses->Suid;
  17428. + break;
  17429. + } else {
  17430. + /* BB eventually call cifs_setup_session here */
  17431. + cFYI(1,("local UID found but smb sess with this server does not exist"));
  17432. + }
  17433. + }
  17434. + }
  17435. + read_unlock(&GlobalSMBSeslock);
  17436. + }
  17437. + }
  17438. + }
  17439. + if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
  17440. + buffer->Flags2 |= SMBFLG2_DFS;
  17441. + if(treeCon->ses->server)
  17442. + if(treeCon->ses->server->secMode &
  17443. + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  17444. + buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  17445. + }
  17446. +
  17447. +/* endian conversion of flags is now done just before sending */
  17448. + buffer->WordCount = (char) word_count;
  17449. + return;
  17450. +}
  17451. +
  17452. +int
  17453. +checkSMBhdr(struct smb_hdr *smb, __u16 mid)
  17454. +{
  17455. + /* Make sure that this really is an SMB, that it is a response,
  17456. + and that the message ids match */
  17457. + if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
  17458. + (mid == smb->Mid)) {
  17459. + if(smb->Flags & SMBFLG_RESPONSE)
  17460. + return 0;
  17461. + else {
  17462. + /* only one valid case where server sends us request */
  17463. + if(smb->Command == SMB_COM_LOCKING_ANDX)
  17464. + return 0;
  17465. + else
  17466. + cERROR(1, ("Rcvd Request not response "));
  17467. + }
  17468. + } else { /* bad signature or mid */
  17469. + if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
  17470. + cERROR(1,
  17471. + ("Bad protocol string signature header %x ",
  17472. + *(unsigned int *) smb->Protocol));
  17473. + if (mid != smb->Mid)
  17474. + cERROR(1, ("Mids do not match"));
  17475. + }
  17476. + cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
  17477. + return 1;
  17478. +}
  17479. +
  17480. +int
  17481. +checkSMB(struct smb_hdr *smb, __u16 mid, int length)
  17482. +{
  17483. + cFYI(0,
  17484. + ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
  17485. + length, ntohl(smb->smb_buf_length)));
  17486. + if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
  17487. + || (ntohl(smb->smb_buf_length) >
  17488. + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
  17489. + if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
  17490. + cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
  17491. + if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
  17492. + && (smb->Status.CifsError != 0))
  17493. + return 0; /* some error cases do not return wct and bcc */
  17494. +
  17495. + }
  17496. + if (ntohl(smb->smb_buf_length) >
  17497. + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
  17498. + cERROR(1,
  17499. + ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
  17500. + cERROR(1,
  17501. + ("bad smb detected. Illegal length. The mid=%d",
  17502. + smb->Mid));
  17503. + return 1;
  17504. + }
  17505. +
  17506. + if (checkSMBhdr(smb, mid))
  17507. + return 1;
  17508. +
  17509. + if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
  17510. + || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
  17511. + return 0;
  17512. + } else {
  17513. + cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
  17514. + cERROR(1,
  17515. + ("bad smb size detected. The Mid=%d", smb->Mid));
  17516. + return 1;
  17517. + }
  17518. +}
  17519. +int
  17520. +is_valid_oplock_break(struct smb_hdr *buf)
  17521. +{
  17522. + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
  17523. + struct list_head *tmp;
  17524. + struct list_head *tmp1;
  17525. + struct cifsTconInfo *tcon;
  17526. + struct cifsFileInfo *netfile;
  17527. +
  17528. + /* could add check for smb response flag 0x80 */
  17529. + cFYI(1,("Checking for oplock break"));
  17530. + if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
  17531. + return FALSE;
  17532. + if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
  17533. + /* no sense logging error on invalid handle on oplock
  17534. + break - harmless race between close request and oplock
  17535. + break response is expected from time to time writing out
  17536. + large dirty files cached on the client */
  17537. + if ((NT_STATUS_INVALID_HANDLE) ==
  17538. + le32_to_cpu(pSMB->hdr.Status.CifsError)) {
  17539. + cFYI(1,("invalid handle on oplock break"));
  17540. + return TRUE;
  17541. + } else if (ERRbadfid ==
  17542. + le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
  17543. + return TRUE;
  17544. + } else {
  17545. + return FALSE; /* on valid oplock brk we get "request" */
  17546. + }
  17547. + }
  17548. + if(pSMB->hdr.WordCount != 8)
  17549. + return FALSE;
  17550. +
  17551. + cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
  17552. + if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
  17553. + return FALSE;
  17554. +
  17555. + /* look up tcon based on tid & uid */
  17556. + read_lock(&GlobalSMBSeslock);
  17557. + list_for_each(tmp, &GlobalTreeConnectionList) {
  17558. + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
  17559. + if (tcon->tid == buf->Tid) {
  17560. +#ifdef CONFIG_CIFS_STATS
  17561. + atomic_inc(&tcon->num_oplock_brks);
  17562. +#endif
  17563. + list_for_each(tmp1,&tcon->openFileList){
  17564. + netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
  17565. + if(pSMB->Fid == netfile->netfid) {
  17566. + struct cifsInodeInfo *pCifsInode;
  17567. + read_unlock(&GlobalSMBSeslock);
  17568. + cFYI(1,("Matching file id, processing oplock break"));
  17569. + pCifsInode =
  17570. + CIFS_I(netfile->pInode);
  17571. + pCifsInode->clientCanCacheAll = FALSE;
  17572. + if(pSMB->OplockLevel == 0)
  17573. + pCifsInode->clientCanCacheRead = FALSE;
  17574. + pCifsInode->oplockPending = TRUE;
  17575. + AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
  17576. + cFYI(1,("about to wake up oplock thd"));
  17577. + wake_up_process(oplockThread);
  17578. + return TRUE;
  17579. + }
  17580. + }
  17581. + read_unlock(&GlobalSMBSeslock);
  17582. + cFYI(1,("No matching file for oplock break on connection"));
  17583. + return TRUE;
  17584. + }
  17585. + }
  17586. + read_unlock(&GlobalSMBSeslock);
  17587. + cFYI(1,("Can not process oplock break for non-existent connection"));
  17588. + return TRUE;
  17589. +}
  17590. +
  17591. +void
  17592. +dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
  17593. +{
  17594. + int i, j;
  17595. + char debug_line[17];
  17596. + unsigned char *buffer;
  17597. +
  17598. + if (traceSMB == 0)
  17599. + return;
  17600. +
  17601. + buffer = (unsigned char *) smb_buf;
  17602. + for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
  17603. + if (i % 8 == 0) { /* we have reached the beginning of line */
  17604. + printk(KERN_DEBUG "| ");
  17605. + j = 0;
  17606. + }
  17607. + printk("%0#4x ", buffer[i]);
  17608. + debug_line[2 * j] = ' ';
  17609. + if (isprint(buffer[i]))
  17610. + debug_line[1 + (2 * j)] = buffer[i];
  17611. + else
  17612. + debug_line[1 + (2 * j)] = '_';
  17613. +
  17614. + if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
  17615. + debug_line[16] = 0;
  17616. + printk(" | %s\n", debug_line);
  17617. + }
  17618. + }
  17619. + for (; j < 8; j++) {
  17620. + printk(" ");
  17621. + debug_line[2 * j] = ' ';
  17622. + debug_line[1 + (2 * j)] = ' ';
  17623. + }
  17624. + printk( " | %s\n", debug_line);
  17625. + return;
  17626. +}
  17627. --- /dev/null
  17628. +++ b/fs/cifs/netmisc.c
  17629. @@ -0,0 +1,905 @@
  17630. +/*
  17631. + * fs/cifs/netmisc.c
  17632. + *
  17633. + * Copyright (c) International Business Machines Corp., 2002
  17634. + * Author(s): Steve French ([email protected])
  17635. + *
  17636. + * Error mapping routines from Samba libsmb/errormap.c
  17637. + * Copyright (C) Andrew Tridgell 2001
  17638. + *
  17639. + *
  17640. + * This program is free software; you can redistribute it and/or modify
  17641. + * it under the terms of the GNU General Public License as published by
  17642. + * the Free Software Foundation; either version 2 of the License, or
  17643. + * (at your option) any later version.
  17644. + *
  17645. + * This program is distributed in the hope that it will be useful,
  17646. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17647. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  17648. + * the GNU General Public License for more details.
  17649. + *
  17650. + * You should have received a copy of the GNU General Public License
  17651. + * along with this program; if not, write to the Free Software
  17652. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17653. + */
  17654. +
  17655. +#include <linux/net.h>
  17656. +#include <linux/string.h>
  17657. +#include <linux/in.h>
  17658. +#include <linux/ctype.h>
  17659. +#include <linux/fs.h>
  17660. +#include <asm/div64.h>
  17661. +#include <asm/byteorder.h>
  17662. +#include "cifsfs.h"
  17663. +#include "cifspdu.h"
  17664. +#include "cifsglob.h"
  17665. +#include "cifsproto.h"
  17666. +#include "smberr.h"
  17667. +#include "cifs_debug.h"
  17668. +#include "nterr.h"
  17669. +
  17670. +struct smb_to_posix_error {
  17671. + __u16 smb_err;
  17672. + int posix_code;
  17673. +};
  17674. +
  17675. +const struct smb_to_posix_error mapping_table_ERRDOS[] = {
  17676. + {ERRbadfunc, -EINVAL},
  17677. + {ERRbadfile, -ENOENT},
  17678. + {ERRbadpath, -ENOTDIR},
  17679. + {ERRnofids, -EMFILE},
  17680. + {ERRnoaccess, -EACCES},
  17681. + {ERRbadfid, -EBADF},
  17682. + {ERRbadmcb, -EIO},
  17683. + {ERRnomem, -ENOMEM},
  17684. + {ERRbadmem, -EFAULT},
  17685. + {ERRbadenv, -EFAULT},
  17686. + {ERRbadformat, -EINVAL},
  17687. + {ERRbadaccess, -EACCES},
  17688. + {ERRbaddata, -EIO},
  17689. + {ERRbaddrive, -ENXIO},
  17690. + {ERRremcd, -EACCES},
  17691. + {ERRdiffdevice, -EXDEV},
  17692. + {ERRnofiles, -ENOENT},
  17693. + {ERRbadshare, -ETXTBSY},
  17694. + {ERRlock, -EACCES},
  17695. + {ERRunsup, -EINVAL},
  17696. + {ERRnosuchshare,-ENXIO},
  17697. + {ERRfilexists, -EEXIST},
  17698. + {ERRinvparm, -EINVAL},
  17699. + {ERRdiskfull, -ENOSPC},
  17700. + {ERRinvname, -ENOENT},
  17701. + {ERRdirnotempty, -ENOTEMPTY},
  17702. + {ERRnotlocked, -ENOLCK},
  17703. + {ERRalreadyexists, -EEXIST},
  17704. + {ERRmoredata, -EOVERFLOW},
  17705. + {ErrQuota, -EDQUOT},
  17706. + {ErrNotALink, -ENOLINK},
  17707. + {ERRnetlogonNotStarted,-ENOPROTOOPT},
  17708. + {0, 0}
  17709. +};
  17710. +
  17711. +const struct smb_to_posix_error mapping_table_ERRSRV[] = {
  17712. + {ERRerror, -EIO},
  17713. + {ERRbadpw, -EPERM},
  17714. + {ERRbadtype, -EREMOTE},
  17715. + {ERRaccess, -EACCES},
  17716. + {ERRinvtid, -ENXIO},
  17717. + {ERRinvnetname, -ENODEV},
  17718. + {ERRinvdevice, -ENXIO},
  17719. + {ERRqfull, -ENOSPC},
  17720. + {ERRqtoobig, -ENOSPC},
  17721. + {ERRqeof, -EIO},
  17722. + {ERRinvpfid, -EBADF},
  17723. + {ERRsmbcmd, -EBADRQC},
  17724. + {ERRsrverror, -EIO},
  17725. + {ERRbadBID, -EIO},
  17726. + {ERRfilespecs, -EINVAL},
  17727. + {ERRbadLink, -EIO},
  17728. + {ERRbadpermits, -EINVAL},
  17729. + {ERRbadPID, -ESRCH},
  17730. + {ERRsetattrmode, -EINVAL},
  17731. + {ERRpaused, -EHOSTDOWN},
  17732. + {ERRmsgoff, -EHOSTDOWN},
  17733. + {ERRnoroom, -ENOSPC},
  17734. + {ERRrmuns, -EUSERS},
  17735. + {ERRtimeout, -ETIME},
  17736. + {ERRnoresource, -ENOBUFS},
  17737. + {ERRtoomanyuids, -EUSERS},
  17738. + {ERRbaduid, -EACCES},
  17739. + {ERRusempx, -EIO},
  17740. + {ERRusestd, -EIO},
  17741. + {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
  17742. + {ERRaccountexpired, -EACCES},
  17743. + {ERRbadclient, -EACCES},
  17744. + {ERRbadLogonTime, -EACCES},
  17745. + {ERRpasswordExpired, -EACCES},
  17746. + {ERRnosupport, -EINVAL},
  17747. + {0, 0}
  17748. +};
  17749. +
  17750. +const struct smb_to_posix_error mapping_table_ERRHRD[] = {
  17751. + {0, 0}
  17752. +};
  17753. +
  17754. +/* Convert string containing dotted ip address to binary form */
  17755. +/* returns 0 if invalid address */
  17756. +
  17757. +/* BB add address family, change rc to status flag and return union or for ipv6 */
  17758. +/* will need parent to call something like inet_pton to convert ipv6 address BB */
  17759. +int
  17760. +cifs_inet_pton(int address_family, char *cp,void *dst)
  17761. +{
  17762. + struct in_addr address;
  17763. + int value;
  17764. + int digit;
  17765. + int i;
  17766. + char temp;
  17767. + char bytes[4];
  17768. + char *end = bytes;
  17769. + static const int addr_class_max[4] =
  17770. + { 0xffffffff, 0xffffff, 0xffff, 0xff };
  17771. +
  17772. + if(address_family != AF_INET)
  17773. + return -EAFNOSUPPORT;
  17774. +
  17775. + for (i = 0; i < 4; i++) {
  17776. + bytes[i] = 0;
  17777. + }
  17778. +
  17779. + temp = *cp;
  17780. +
  17781. + while (TRUE) {
  17782. + if (!isdigit(temp))
  17783. + return 0;
  17784. +
  17785. + value = 0;
  17786. + digit = 0;
  17787. + for (;;) {
  17788. + if (isascii(temp) && isdigit(temp)) {
  17789. + value = (value * 10) + temp - '0';
  17790. + temp = *++cp;
  17791. + digit = 1;
  17792. + } else
  17793. + break;
  17794. + }
  17795. +
  17796. + if (temp == '.') {
  17797. + if ((end > bytes + 2) || (value > 255))
  17798. + return 0;
  17799. + *end++ = value;
  17800. + temp = *++cp;
  17801. + } else if (temp == ':') {
  17802. + cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
  17803. + return -1;
  17804. + } else
  17805. + break;
  17806. + }
  17807. +
  17808. + /* check for last characters */
  17809. + if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
  17810. + if (temp != '\\') {
  17811. + if (temp != '/')
  17812. + return 0;
  17813. + else
  17814. + (*cp = '\\'); /* switch the slash the expected way */
  17815. + }
  17816. + if (value > addr_class_max[end - bytes])
  17817. + return 0;
  17818. +
  17819. + address.s_addr = *((int *) bytes) | htonl(value);
  17820. + *((int *)dst) = address.s_addr;
  17821. + return 1; /* success */
  17822. +}
  17823. +
  17824. +/*****************************************************************************
  17825. +convert a NT status code to a dos class/code
  17826. + *****************************************************************************/
  17827. +/* NT status -> dos error map */
  17828. +static const struct {
  17829. + __u8 dos_class;
  17830. + __u16 dos_code;
  17831. + __u32 ntstatus;
  17832. +} ntstatus_to_dos_map[] = {
  17833. + {
  17834. + ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
  17835. + ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
  17836. + ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
  17837. + ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
  17838. + ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
  17839. + ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
  17840. + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
  17841. + ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
  17842. + ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
  17843. + ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
  17844. + ERRDOS, 87, NT_STATUS_INVALID_CID}, {
  17845. + ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
  17846. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
  17847. + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
  17848. + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
  17849. + ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
  17850. + ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
  17851. + ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
  17852. + ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
  17853. + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
  17854. + ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
  17855. +/* { This NT error code was 'sqashed'
  17856. + from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
  17857. + during the session setup } */
  17858. + {
  17859. + ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
  17860. + ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
  17861. + ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
  17862. + ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
  17863. + ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
  17864. + ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
  17865. + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
  17866. + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
  17867. + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
  17868. + ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
  17869. + ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
  17870. +/* { This NT error code was 'sqashed'
  17871. + from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
  17872. + during the session setup } */
  17873. + {
  17874. + ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
  17875. + ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
  17876. + ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
  17877. + ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
  17878. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
  17879. + ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
  17880. + ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
  17881. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
  17882. + ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
  17883. + ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
  17884. + ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
  17885. + ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
  17886. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
  17887. + ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
  17888. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
  17889. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
  17890. + ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
  17891. + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
  17892. + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
  17893. + ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
  17894. + ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
  17895. + ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
  17896. + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
  17897. + ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
  17898. + ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
  17899. + ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
  17900. + ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
  17901. + ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
  17902. + ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
  17903. + ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
  17904. + ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
  17905. + ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
  17906. + ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
  17907. + ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
  17908. + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
  17909. + ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
  17910. + ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
  17911. + ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
  17912. + ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
  17913. + ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
  17914. + ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
  17915. + ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
  17916. + ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
  17917. + ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
  17918. + ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
  17919. + ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
  17920. + ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
  17921. + ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
  17922. + ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
  17923. + ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
  17924. + ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
  17925. + ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
  17926. + ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
  17927. + ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
  17928. + ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
  17929. + ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
  17930. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
  17931. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
  17932. + ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
  17933. + ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
  17934. + ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
  17935. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
  17936. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
  17937. + ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
  17938. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
  17939. + ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
  17940. +/* { This NT error code was 'sqashed'
  17941. + from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
  17942. + during the session setup } */
  17943. + {
  17944. + ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
  17945. + ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
  17946. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
  17947. + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
  17948. + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
  17949. + ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
  17950. +/* { This NT error code was 'sqashed'
  17951. + from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
  17952. + during the session setup } */
  17953. + {
  17954. + ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
  17955. + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
  17956. + ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
  17957. + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
  17958. + ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
  17959. + ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
  17960. + ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
  17961. + ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
  17962. + ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
  17963. + ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
  17964. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
  17965. + ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
  17966. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
  17967. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
  17968. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
  17969. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
  17970. + ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
  17971. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
  17972. + ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
  17973. + ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
  17974. + ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
  17975. + ERRDOS, 112, NT_STATUS_DISK_FULL}, {
  17976. + ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
  17977. + ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
  17978. + ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
  17979. + ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
  17980. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
  17981. + ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
  17982. + ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
  17983. + ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
  17984. + ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
  17985. + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
  17986. + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
  17987. + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
  17988. + ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
  17989. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
  17990. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
  17991. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
  17992. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
  17993. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
  17994. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
  17995. + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
  17996. + ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
  17997. + ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
  17998. + ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
  17999. + ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
  18000. + ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
  18001. + ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
  18002. +/* { This NT error code was 'sqashed'
  18003. + from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
  18004. + during the session setup } */
  18005. + {
  18006. + ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
  18007. + ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
  18008. + ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
  18009. + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
  18010. + ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
  18011. + ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
  18012. + ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
  18013. + ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
  18014. + ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
  18015. + ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
  18016. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
  18017. + ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
  18018. + ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
  18019. + ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
  18020. + ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
  18021. + ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
  18022. + ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
  18023. + ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
  18024. + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
  18025. + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
  18026. + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
  18027. + ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
  18028. + ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
  18029. + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
  18030. + ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
  18031. + ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
  18032. + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
  18033. + ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
  18034. + ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
  18035. + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
  18036. + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
  18037. + ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
  18038. + ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
  18039. + ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
  18040. + ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
  18041. + ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
  18042. + ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
  18043. + ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
  18044. + ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
  18045. + ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
  18046. + ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
  18047. + ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
  18048. + ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
  18049. + ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
  18050. + ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
  18051. + ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
  18052. + ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
  18053. + ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
  18054. + ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
  18055. + ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
  18056. + ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
  18057. + ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
  18058. + ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
  18059. + ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
  18060. + ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
  18061. + ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
  18062. + ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
  18063. + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
  18064. + ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
  18065. + ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
  18066. + ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
  18067. + ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
  18068. + ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
  18069. + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
  18070. + ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
  18071. + ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
  18072. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
  18073. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
  18074. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
  18075. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
  18076. + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
  18077. + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
  18078. + ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
  18079. + ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
  18080. + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
  18081. + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
  18082. + ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
  18083. + ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
  18084. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
  18085. + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
  18086. + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
  18087. + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
  18088. + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
  18089. + ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
  18090. + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
  18091. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
  18092. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
  18093. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
  18094. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
  18095. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
  18096. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
  18097. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
  18098. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
  18099. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
  18100. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
  18101. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
  18102. + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
  18103. + ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
  18104. + ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
  18105. + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
  18106. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
  18107. + ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
  18108. + ERRDOS, 203, 0xc0000100}, {
  18109. + ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
  18110. + ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
  18111. + ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
  18112. + ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
  18113. + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
  18114. + ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
  18115. + ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
  18116. + ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
  18117. + ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
  18118. + ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
  18119. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
  18120. + ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
  18121. + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
  18122. + ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
  18123. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
  18124. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
  18125. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
  18126. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
  18127. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
  18128. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
  18129. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
  18130. + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
  18131. + ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
  18132. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
  18133. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
  18134. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
  18135. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
  18136. + ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
  18137. + ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
  18138. + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
  18139. + ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
  18140. + ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
  18141. + ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
  18142. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
  18143. + ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
  18144. + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
  18145. + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
  18146. + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
  18147. + ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
  18148. + ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
  18149. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
  18150. + ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
  18151. + ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
  18152. + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
  18153. + ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
  18154. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
  18155. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
  18156. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
  18157. + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
  18158. + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
  18159. + ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
  18160. + ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
  18161. + ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
  18162. + ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
  18163. + ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
  18164. + ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
  18165. + ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
  18166. + ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
  18167. + ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
  18168. + ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
  18169. + ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
  18170. + ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
  18171. + ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
  18172. + ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
  18173. + ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
  18174. + ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
  18175. + ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
  18176. + ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
  18177. + ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
  18178. + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
  18179. + ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
  18180. + ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
  18181. + ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
  18182. + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
  18183. + ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
  18184. + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
  18185. + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
  18186. + ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
  18187. + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
  18188. + ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
  18189. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
  18190. + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
  18191. + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
  18192. + ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
  18193. + ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
  18194. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
  18195. + ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
  18196. + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
  18197. + ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
  18198. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
  18199. + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
  18200. + ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
  18201. + ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
  18202. + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
  18203. + ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
  18204. + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
  18205. + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
  18206. + ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
  18207. + ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
  18208. + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
  18209. + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
  18210. + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
  18211. + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
  18212. + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
  18213. + ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
  18214. + ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
  18215. + ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
  18216. + ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
  18217. + ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
  18218. + ERRHRD, ERRgeneral, 0xc000016e}, {
  18219. + ERRHRD, ERRgeneral, 0xc000016f}, {
  18220. + ERRHRD, ERRgeneral, 0xc0000170}, {
  18221. + ERRHRD, ERRgeneral, 0xc0000171}, {
  18222. + ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
  18223. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
  18224. + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
  18225. + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
  18226. + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
  18227. + ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
  18228. + ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
  18229. + ERRHRD, ERRgeneral, 0xc0000179}, {
  18230. + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
  18231. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
  18232. + ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
  18233. + ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
  18234. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
  18235. + ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
  18236. + ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
  18237. + ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
  18238. + ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
  18239. + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
  18240. + ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
  18241. + ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
  18242. + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
  18243. + ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
  18244. + ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
  18245. + ERRDOS, 19, NT_STATUS_TOO_LATE}, {
  18246. + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
  18247. +/* { This NT error code was 'sqashed'
  18248. + from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
  18249. + during the session setup } */
  18250. + {
  18251. + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
  18252. + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
  18253. + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
  18254. + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
  18255. + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
  18256. + ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
  18257. + ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
  18258. + ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
  18259. + ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
  18260. + ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
  18261. + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
  18262. + ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
  18263. + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
  18264. + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
  18265. + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
  18266. + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
  18267. +/* { This NT error code was 'sqashed'
  18268. + from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
  18269. + during the session setup } */
  18270. + {
  18271. + ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
  18272. + ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
  18273. + ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
  18274. + ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
  18275. + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
  18276. + ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
  18277. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
  18278. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
  18279. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
  18280. + ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
  18281. + ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
  18282. + ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
  18283. + ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
  18284. + ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
  18285. + ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
  18286. + ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
  18287. + ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
  18288. + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
  18289. + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
  18290. + ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
  18291. + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
  18292. + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
  18293. + ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
  18294. + ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
  18295. + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
  18296. + ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
  18297. + ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
  18298. + ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
  18299. + ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
  18300. + ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
  18301. + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
  18302. + ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
  18303. + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
  18304. + ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
  18305. + ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
  18306. + ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
  18307. + ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
  18308. + ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
  18309. + ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
  18310. + ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
  18311. + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
  18312. + ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
  18313. + ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
  18314. + ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
  18315. + ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
  18316. + ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
  18317. + ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
  18318. + ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
  18319. + ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
  18320. + ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
  18321. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
  18322. + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
  18323. + ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
  18324. + ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
  18325. + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
  18326. + ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
  18327. + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
  18328. + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
  18329. + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
  18330. + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
  18331. + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
  18332. + ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
  18333. + ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
  18334. + ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
  18335. + ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
  18336. + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
  18337. + ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
  18338. + ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
  18339. + ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
  18340. + ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
  18341. + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
  18342. + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
  18343. + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
  18344. + ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
  18345. + ERRHRD, ERRgeneral, 0xc000024a}, {
  18346. + ERRHRD, ERRgeneral, 0xc000024b}, {
  18347. + ERRHRD, ERRgeneral, 0xc000024c}, {
  18348. + ERRHRD, ERRgeneral, 0xc000024d}, {
  18349. + ERRHRD, ERRgeneral, 0xc000024e}, {
  18350. + ERRHRD, ERRgeneral, 0xc000024f}, {
  18351. + ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
  18352. + ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
  18353. + ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
  18354. + ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
  18355. + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
  18356. + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
  18357. + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
  18358. + ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
  18359. + ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
  18360. + ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
  18361. + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
  18362. + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
  18363. + ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
  18364. + ERRHRD, ERRgeneral, 0xc000025d}, {
  18365. + ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
  18366. + ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
  18367. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
  18368. + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
  18369. + ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
  18370. + ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
  18371. + ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
  18372. + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
  18373. + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
  18374. + ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
  18375. + ERRDOS, 21, 0xc000026e}, {
  18376. + ERRDOS, 161, 0xc0000281}, {
  18377. + ERRDOS, ERRnoaccess, 0xc000028a}, {
  18378. + ERRDOS, ERRnoaccess, 0xc000028b}, {
  18379. + ERRHRD, ERRgeneral, 0xc000028c}, {
  18380. + ERRDOS, ERRnoaccess, 0xc000028d}, {
  18381. + ERRDOS, ERRnoaccess, 0xc000028e}, {
  18382. + ERRDOS, ERRnoaccess, 0xc000028f}, {
  18383. + ERRDOS, ERRnoaccess, 0xc0000290}, {
  18384. +ERRDOS, ERRbadfunc, 0xc000029c},};
  18385. +
  18386. +/*****************************************************************************
  18387. + Print an error message from the status code
  18388. + *****************************************************************************/
  18389. +static void
  18390. +cifs_print_status(__u32 status_code)
  18391. +{
  18392. + int idx = 0;
  18393. +
  18394. + while (nt_errs[idx].nt_errstr != NULL) {
  18395. + if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
  18396. + (status_code & 0xFFFFFF)) {
  18397. + printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
  18398. + status_code,nt_errs[idx].nt_errstr);
  18399. + }
  18400. + idx++;
  18401. + }
  18402. + return;
  18403. +}
  18404. +
  18405. +
  18406. +static void
  18407. +ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
  18408. +{
  18409. + int i;
  18410. + if (ntstatus == 0) {
  18411. + *eclass = 0;
  18412. + *ecode = 0;
  18413. + return;
  18414. + }
  18415. + for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
  18416. + if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
  18417. + *eclass = ntstatus_to_dos_map[i].dos_class;
  18418. + *ecode = ntstatus_to_dos_map[i].dos_code;
  18419. + return;
  18420. + }
  18421. + }
  18422. + *eclass = ERRHRD;
  18423. + *ecode = ERRgeneral;
  18424. +}
  18425. +
  18426. +int
  18427. +map_smb_to_linux_error(struct smb_hdr *smb)
  18428. +{
  18429. + unsigned int i;
  18430. + int rc = -EIO; /* if transport error smb error may not be set */
  18431. + __u8 smberrclass;
  18432. + __u16 smberrcode;
  18433. +
  18434. + /* BB if NT Status codes - map NT BB */
  18435. +
  18436. + /* old style smb error codes */
  18437. + if (smb->Status.CifsError == 0)
  18438. + return 0;
  18439. +
  18440. + if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
  18441. + /* translate the newer STATUS codes to old style errors and then to POSIX errors */
  18442. + smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
  18443. + if(cifsFYI)
  18444. + cifs_print_status(smb->Status.CifsError);
  18445. + ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
  18446. + &smberrcode);
  18447. + } else {
  18448. + smberrclass = smb->Status.DosError.ErrorClass;
  18449. + smb->Status.DosError.Error =
  18450. + le16_to_cpu(smb->Status.DosError.Error);
  18451. + smberrcode = smb->Status.DosError.Error;
  18452. + }
  18453. +
  18454. + /* old style errors */
  18455. +
  18456. + /* DOS class smb error codes - map DOS */
  18457. + if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
  18458. + for (i = 0;
  18459. + i <
  18460. + sizeof (mapping_table_ERRDOS) /
  18461. + sizeof (struct smb_to_posix_error); i++) {
  18462. + if (mapping_table_ERRDOS[i].smb_err == 0)
  18463. + break;
  18464. + else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
  18465. + rc = mapping_table_ERRDOS[i].posix_code;
  18466. + break;
  18467. + }
  18468. + /* else try the next error mapping one to see if it will match */
  18469. + }
  18470. + } else if (smberrclass == ERRSRV) { /* server class of error codes */
  18471. + for (i = 0;
  18472. + i <
  18473. + sizeof (mapping_table_ERRSRV) /
  18474. + sizeof (struct smb_to_posix_error); i++) {
  18475. + if (mapping_table_ERRSRV[i].smb_err == 0)
  18476. + break;
  18477. + else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
  18478. + rc = mapping_table_ERRSRV[i].posix_code;
  18479. + break;
  18480. + }
  18481. + /* else try the next error mapping one to see if it will match */
  18482. + }
  18483. + }
  18484. + /* else ERRHRD class errors or junk - return EIO */
  18485. +
  18486. + cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
  18487. +
  18488. + /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
  18489. +
  18490. + return rc;
  18491. +}
  18492. +
  18493. +/*
  18494. + * calculate the size of the SMB message based on the fixed header
  18495. + * portion, the number of word parameters and the data portion of the message
  18496. + */
  18497. +unsigned int
  18498. +smbCalcSize(struct smb_hdr *ptr)
  18499. +{
  18500. + return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
  18501. + BCC(ptr));
  18502. +}
  18503. +
  18504. +/* The following are taken from fs/ntfs/util.c */
  18505. +
  18506. +#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
  18507. +
  18508. + /*
  18509. + * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
  18510. + * into Unix UTC (based 1970-01-01, in seconds).
  18511. + */
  18512. +time_t
  18513. +cifs_NTtimeToUnix(__u64 ntutc)
  18514. +{
  18515. + /* BB what about the timezone? BB */
  18516. +
  18517. + /* Subtract the NTFS time offset, then convert to 1s intervals. */
  18518. + u64 t;
  18519. +
  18520. + t = ntutc - NTFS_TIME_OFFSET;
  18521. + do_div(t, 10000000);
  18522. + return (time_t)t;
  18523. +}
  18524. +
  18525. +/* Convert the Unix UTC into NT UTC. */
  18526. +__u64
  18527. +cifs_UnixTimeToNT(time_t t)
  18528. +{
  18529. + __u64 dce_time;
  18530. + /* Convert to 100ns intervals and then add the NTFS time offset. */
  18531. + dce_time = (__u64) t * 10000000;
  18532. + dce_time += NTFS_TIME_OFFSET;
  18533. + return dce_time;
  18534. +}
  18535. --- /dev/null
  18536. +++ b/fs/cifs/nterr.c
  18537. @@ -0,0 +1,687 @@
  18538. +/*
  18539. + * Unix SMB/Netbios implementation.
  18540. + * Version 1.9.
  18541. + * RPC Pipe client / server routines
  18542. + * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
  18543. + *
  18544. + * This program is free software; you can redistribute it and/or modify
  18545. + * it under the terms of the GNU General Public License as published by
  18546. + * the Free Software Foundation; either version 2 of the License, or
  18547. + * (at your option) any later version.
  18548. + *
  18549. + * This program is distributed in the hope that it will be useful,
  18550. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18551. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18552. + * GNU General Public License for more details.
  18553. + *
  18554. + * You should have received a copy of the GNU General Public License
  18555. + * along with this program; if not, write to the Free Software
  18556. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18557. + */
  18558. +
  18559. +/* NT error codes - see nterr.h */
  18560. +#include <linux/types.h>
  18561. +#include <linux/fs.h>
  18562. +#include "nterr.h"
  18563. +
  18564. +const struct nt_err_code_struct nt_errs[] = {
  18565. + {"NT_STATUS_OK", NT_STATUS_OK},
  18566. + {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
  18567. + {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
  18568. + {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
  18569. + {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
  18570. + {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
  18571. + {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
  18572. + {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
  18573. + {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
  18574. + {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
  18575. + {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
  18576. + {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
  18577. + {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
  18578. + {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
  18579. + {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
  18580. + {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
  18581. + {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
  18582. + {"NT_STATUS_INVALID_DEVICE_REQUEST",
  18583. + NT_STATUS_INVALID_DEVICE_REQUEST},
  18584. + {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
  18585. + {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
  18586. + {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
  18587. + {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
  18588. + {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
  18589. + {"NT_STATUS_MORE_PROCESSING_REQUIRED",
  18590. + NT_STATUS_MORE_PROCESSING_REQUIRED},
  18591. + {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
  18592. + {"NT_STATUS_CONFLICTING_ADDRESSES",
  18593. + NT_STATUS_CONFLICTING_ADDRESSES},
  18594. + {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
  18595. + {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
  18596. + {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
  18597. + NT_STATUS_UNABLE_TO_DELETE_SECTION},
  18598. + {"NT_STATUS_INVALID_SYSTEM_SERVICE",
  18599. + NT_STATUS_INVALID_SYSTEM_SERVICE},
  18600. + {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
  18601. + {"NT_STATUS_INVALID_LOCK_SEQUENCE",
  18602. + NT_STATUS_INVALID_LOCK_SEQUENCE},
  18603. + {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
  18604. + {"NT_STATUS_INVALID_FILE_FOR_SECTION",
  18605. + NT_STATUS_INVALID_FILE_FOR_SECTION},
  18606. + {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
  18607. + {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
  18608. + {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
  18609. + {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
  18610. + {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
  18611. + NT_STATUS_NONCONTINUABLE_EXCEPTION},
  18612. + {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
  18613. + {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
  18614. + {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
  18615. + {"NT_STATUS_INVALID_UNWIND_TARGET",
  18616. + NT_STATUS_INVALID_UNWIND_TARGET},
  18617. + {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
  18618. + {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
  18619. + {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
  18620. + NT_STATUS_UNABLE_TO_DECOMMIT_VM},
  18621. + {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
  18622. + {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
  18623. + NT_STATUS_INVALID_PORT_ATTRIBUTES},
  18624. + {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
  18625. + NT_STATUS_PORT_MESSAGE_TOO_LONG},
  18626. + {"NT_STATUS_INVALID_PARAMETER_MIX",
  18627. + NT_STATUS_INVALID_PARAMETER_MIX},
  18628. + {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
  18629. + {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
  18630. + {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
  18631. + {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
  18632. + NT_STATUS_OBJECT_NAME_NOT_FOUND},
  18633. + {"NT_STATUS_OBJECT_NAME_COLLISION",
  18634. + NT_STATUS_OBJECT_NAME_COLLISION},
  18635. + {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
  18636. + {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
  18637. + {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
  18638. + NT_STATUS_DEVICE_ALREADY_ATTACHED},
  18639. + {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
  18640. + {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
  18641. + NT_STATUS_OBJECT_PATH_NOT_FOUND},
  18642. + {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
  18643. + NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
  18644. + {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
  18645. + {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
  18646. + {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
  18647. + {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
  18648. + {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
  18649. + {"NT_STATUS_PORT_CONNECTION_REFUSED",
  18650. + NT_STATUS_PORT_CONNECTION_REFUSED},
  18651. + {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
  18652. + {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
  18653. + {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
  18654. + {"NT_STATUS_INVALID_PAGE_PROTECTION",
  18655. + NT_STATUS_INVALID_PAGE_PROTECTION},
  18656. + {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
  18657. + {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
  18658. + NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
  18659. + {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
  18660. + {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
  18661. + {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
  18662. + NT_STATUS_SUSPEND_COUNT_EXCEEDED},
  18663. + {"NT_STATUS_THREAD_IS_TERMINATING",
  18664. + NT_STATUS_THREAD_IS_TERMINATING},
  18665. + {"NT_STATUS_BAD_WORKING_SET_LIMIT",
  18666. + NT_STATUS_BAD_WORKING_SET_LIMIT},
  18667. + {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
  18668. + NT_STATUS_INCOMPATIBLE_FILE_MAP},
  18669. + {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
  18670. + {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
  18671. + {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
  18672. + {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
  18673. + {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
  18674. + {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
  18675. + {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
  18676. + {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
  18677. + {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
  18678. + {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
  18679. + NT_STATUS_CTL_FILE_NOT_SUPPORTED},
  18680. + {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
  18681. + {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
  18682. + {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
  18683. + {"NT_STATUS_INVALID_PRIMARY_GROUP",
  18684. + NT_STATUS_INVALID_PRIMARY_GROUP},
  18685. + {"NT_STATUS_NO_IMPERSONATION_TOKEN",
  18686. + NT_STATUS_NO_IMPERSONATION_TOKEN},
  18687. + {"NT_STATUS_CANT_DISABLE_MANDATORY",
  18688. + NT_STATUS_CANT_DISABLE_MANDATORY},
  18689. + {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
  18690. + {"NT_STATUS_NO_SUCH_LOGON_SESSION",
  18691. + NT_STATUS_NO_SUCH_LOGON_SESSION},
  18692. + {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
  18693. + {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
  18694. + {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
  18695. + {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
  18696. + {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
  18697. + {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
  18698. + {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
  18699. + {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
  18700. + {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
  18701. + {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
  18702. + {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
  18703. + {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
  18704. + {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
  18705. + {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
  18706. + {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
  18707. + {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
  18708. + {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
  18709. + {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
  18710. + {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
  18711. + {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
  18712. + {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
  18713. + NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
  18714. + {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
  18715. + {"NT_STATUS_INVALID_SUB_AUTHORITY",
  18716. + NT_STATUS_INVALID_SUB_AUTHORITY},
  18717. + {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
  18718. + {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
  18719. + {"NT_STATUS_INVALID_SECURITY_DESCR",
  18720. + NT_STATUS_INVALID_SECURITY_DESCR},
  18721. + {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
  18722. + {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
  18723. + {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
  18724. + {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
  18725. + {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
  18726. + {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
  18727. + {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
  18728. + {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
  18729. + {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
  18730. + NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
  18731. + {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
  18732. + {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
  18733. + {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
  18734. + {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
  18735. + {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
  18736. + {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
  18737. + {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
  18738. + NT_STATUS_RESOURCE_DATA_NOT_FOUND},
  18739. + {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
  18740. + NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
  18741. + {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
  18742. + NT_STATUS_RESOURCE_NAME_NOT_FOUND},
  18743. + {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
  18744. + NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
  18745. + {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
  18746. + NT_STATUS_FLOAT_DENORMAL_OPERAND},
  18747. + {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
  18748. + {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
  18749. + {"NT_STATUS_FLOAT_INVALID_OPERATION",
  18750. + NT_STATUS_FLOAT_INVALID_OPERATION},
  18751. + {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
  18752. + {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
  18753. + {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
  18754. + {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
  18755. + NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
  18756. + {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
  18757. + {"NT_STATUS_PRIVILEGED_INSTRUCTION",
  18758. + NT_STATUS_PRIVILEGED_INSTRUCTION},
  18759. + {"NT_STATUS_TOO_MANY_PAGING_FILES",
  18760. + NT_STATUS_TOO_MANY_PAGING_FILES},
  18761. + {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
  18762. + {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
  18763. + NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
  18764. + {"NT_STATUS_INSUFFICIENT_RESOURCES",
  18765. + NT_STATUS_INSUFFICIENT_RESOURCES},
  18766. + {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
  18767. + {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
  18768. + {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
  18769. + {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
  18770. + {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
  18771. + {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
  18772. + {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
  18773. + {"NT_STATUS_MEDIA_WRITE_PROTECTED",
  18774. + NT_STATUS_MEDIA_WRITE_PROTECTED},
  18775. + {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
  18776. + {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
  18777. + NT_STATUS_INVALID_GROUP_ATTRIBUTES},
  18778. + {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
  18779. + NT_STATUS_BAD_IMPERSONATION_LEVEL},
  18780. + {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
  18781. + {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
  18782. + {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
  18783. + {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
  18784. + NT_STATUS_BAD_MASTER_BOOT_RECORD},
  18785. + {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
  18786. + NT_STATUS_INSTRUCTION_MISALIGNMENT},
  18787. + {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
  18788. + NT_STATUS_INSTANCE_NOT_AVAILABLE},
  18789. + {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
  18790. + {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
  18791. + {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
  18792. + {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
  18793. + {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
  18794. + {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
  18795. + {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
  18796. + {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
  18797. + {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
  18798. + {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
  18799. + {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
  18800. + {"NT_STATUS_PROFILING_NOT_STARTED",
  18801. + NT_STATUS_PROFILING_NOT_STARTED},
  18802. + {"NT_STATUS_PROFILING_NOT_STOPPED",
  18803. + NT_STATUS_PROFILING_NOT_STOPPED},
  18804. + {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
  18805. + {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
  18806. + {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
  18807. + {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
  18808. + {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
  18809. + {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
  18810. + {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
  18811. + {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
  18812. + NT_STATUS_DEVICE_DOES_NOT_EXIST},
  18813. + {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
  18814. + {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
  18815. + NT_STATUS_ADAPTER_HARDWARE_ERROR},
  18816. + {"NT_STATUS_INVALID_NETWORK_RESPONSE",
  18817. + NT_STATUS_INVALID_NETWORK_RESPONSE},
  18818. + {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
  18819. + NT_STATUS_UNEXPECTED_NETWORK_ERROR},
  18820. + {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
  18821. + {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
  18822. + {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
  18823. + {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
  18824. + {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
  18825. + {"NT_STATUS_NETWORK_ACCESS_DENIED",
  18826. + NT_STATUS_NETWORK_ACCESS_DENIED},
  18827. + {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
  18828. + {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
  18829. + {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
  18830. + {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
  18831. + {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
  18832. + {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
  18833. + {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
  18834. + {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
  18835. + {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
  18836. + {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
  18837. + {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
  18838. + {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
  18839. + NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
  18840. + {"NT_STATUS_NO_SECURITY_ON_OBJECT",
  18841. + NT_STATUS_NO_SECURITY_ON_OBJECT},
  18842. + {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
  18843. + {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
  18844. + {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
  18845. + NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
  18846. + {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
  18847. + {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
  18848. + {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
  18849. + {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
  18850. + {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
  18851. + {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
  18852. + {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
  18853. + NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
  18854. + {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
  18855. + {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
  18856. + NT_STATUS_INVALID_OPLOCK_PROTOCOL},
  18857. + {"NT_STATUS_INTERNAL_DB_CORRUPTION",
  18858. + NT_STATUS_INTERNAL_DB_CORRUPTION},
  18859. + {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
  18860. + {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
  18861. + {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
  18862. + NT_STATUS_BAD_DESCRIPTOR_FORMAT},
  18863. + {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
  18864. + {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
  18865. + {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
  18866. + NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
  18867. + {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
  18868. + NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
  18869. + {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
  18870. + NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
  18871. + {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
  18872. + {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
  18873. + {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
  18874. + {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
  18875. + {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
  18876. + {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
  18877. + {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
  18878. + {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
  18879. + {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
  18880. + {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
  18881. + {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
  18882. + {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
  18883. + {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
  18884. + {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
  18885. + {"NT_STATUS_REDIRECTOR_NOT_STARTED",
  18886. + NT_STATUS_REDIRECTOR_NOT_STARTED},
  18887. + {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
  18888. + {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
  18889. + {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
  18890. + {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
  18891. + {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
  18892. + {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
  18893. + {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
  18894. + {"NT_STATUS_BAD_LOGON_SESSION_STATE",
  18895. + NT_STATUS_BAD_LOGON_SESSION_STATE},
  18896. + {"NT_STATUS_LOGON_SESSION_COLLISION",
  18897. + NT_STATUS_LOGON_SESSION_COLLISION},
  18898. + {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
  18899. + {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
  18900. + {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
  18901. + {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
  18902. + {"NT_STATUS_PROCESS_IS_TERMINATING",
  18903. + NT_STATUS_PROCESS_IS_TERMINATING},
  18904. + {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
  18905. + {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
  18906. + {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
  18907. + {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
  18908. + {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
  18909. + {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
  18910. + {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
  18911. + NT_STATUS_ABIOS_LID_ALREADY_OWNED},
  18912. + {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
  18913. + {"NT_STATUS_ABIOS_INVALID_COMMAND",
  18914. + NT_STATUS_ABIOS_INVALID_COMMAND},
  18915. + {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
  18916. + {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
  18917. + NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
  18918. + {"NT_STATUS_ABIOS_INVALID_SELECTOR",
  18919. + NT_STATUS_ABIOS_INVALID_SELECTOR},
  18920. + {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
  18921. + {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
  18922. + {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
  18923. + {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
  18924. + NT_STATUS_INVALID_LDT_DESCRIPTOR},
  18925. + {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
  18926. + NT_STATUS_INVALID_IMAGE_NE_FORMAT},
  18927. + {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
  18928. + {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
  18929. + {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
  18930. + NT_STATUS_MAPPED_FILE_SIZE_ZERO},
  18931. + {"NT_STATUS_TOO_MANY_OPENED_FILES",
  18932. + NT_STATUS_TOO_MANY_OPENED_FILES},
  18933. + {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
  18934. + {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
  18935. + {"NT_STATUS_INVALID_COMPUTER_NAME",
  18936. + NT_STATUS_INVALID_COMPUTER_NAME},
  18937. + {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
  18938. + {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
  18939. + {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
  18940. + {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
  18941. + {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
  18942. + NT_STATUS_MEMBERS_PRIMARY_GROUP},
  18943. + {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
  18944. + {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
  18945. + {"NT_STATUS_THREAD_NOT_IN_PROCESS",
  18946. + NT_STATUS_THREAD_NOT_IN_PROCESS},
  18947. + {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
  18948. + {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
  18949. + NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
  18950. + {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
  18951. + {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
  18952. + NT_STATUS_INVALID_IMAGE_LE_FORMAT},
  18953. + {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
  18954. + {"NT_STATUS_INVALID_IMAGE_PROTECT",
  18955. + NT_STATUS_INVALID_IMAGE_PROTECT},
  18956. + {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
  18957. + {"NT_STATUS_LOGON_SERVER_CONFLICT",
  18958. + NT_STATUS_LOGON_SERVER_CONFLICT},
  18959. + {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
  18960. + NT_STATUS_TIME_DIFFERENCE_AT_DC},
  18961. + {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
  18962. + NT_STATUS_SYNCHRONIZATION_REQUIRED},
  18963. + {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
  18964. + {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
  18965. + {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
  18966. + {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
  18967. + {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
  18968. + {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
  18969. + {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
  18970. + {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
  18971. + {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
  18972. + {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
  18973. + {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
  18974. + {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
  18975. + {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
  18976. + {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
  18977. + {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
  18978. + {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
  18979. + {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
  18980. + {"NT_STATUS_PAGEFILE_CREATE_FAILED",
  18981. + NT_STATUS_PAGEFILE_CREATE_FAILED},
  18982. + {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
  18983. + {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
  18984. + {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
  18985. + {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
  18986. + NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
  18987. + {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
  18988. + {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
  18989. + {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
  18990. + {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
  18991. + {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
  18992. + {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
  18993. + NT_STATUS_SERIAL_NO_DEVICE_INITED},
  18994. + {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
  18995. + {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
  18996. + {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
  18997. + {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
  18998. + {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
  18999. + {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
  19000. + {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
  19001. + {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
  19002. + {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
  19003. + {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
  19004. + {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
  19005. + NT_STATUS_LOGON_TYPE_NOT_GRANTED},
  19006. + {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
  19007. + {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
  19008. + NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
  19009. + {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
  19010. + NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
  19011. + {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
  19012. + {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
  19013. + NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
  19014. + {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
  19015. + {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
  19016. + {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
  19017. + {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
  19018. + {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
  19019. + NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
  19020. + {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
  19021. + NT_STATUS_FLOPPY_WRONG_CYLINDER},
  19022. + {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
  19023. + {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
  19024. + {"NT_STATUS_DISK_RECALIBRATE_FAILED",
  19025. + NT_STATUS_DISK_RECALIBRATE_FAILED},
  19026. + {"NT_STATUS_DISK_OPERATION_FAILED",
  19027. + NT_STATUS_DISK_OPERATION_FAILED},
  19028. + {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
  19029. + {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
  19030. + {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
  19031. + {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
  19032. + {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
  19033. + {"NT_STATUS_DEVICE_NOT_PARTITIONED",
  19034. + NT_STATUS_DEVICE_NOT_PARTITIONED},
  19035. + {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
  19036. + {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
  19037. + NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
  19038. + {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
  19039. + {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
  19040. + {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
  19041. + {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
  19042. + {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
  19043. + {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
  19044. + {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
  19045. + {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
  19046. + NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
  19047. + {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
  19048. + {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
  19049. + NT_STATUS_CHILD_MUST_BE_VOLATILE},
  19050. + {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
  19051. + NT_STATUS_DEVICE_CONFIGURATION_ERROR},
  19052. + {"NT_STATUS_DRIVER_INTERNAL_ERROR",
  19053. + NT_STATUS_DRIVER_INTERNAL_ERROR},
  19054. + {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
  19055. + {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
  19056. + {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
  19057. + NT_STATUS_DEVICE_PROTOCOL_ERROR},
  19058. + {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
  19059. + {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
  19060. + {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
  19061. + {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
  19062. + {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
  19063. + {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
  19064. + NT_STATUS_TRUSTED_DOMAIN_FAILURE},
  19065. + {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
  19066. + NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
  19067. + {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
  19068. + NT_STATUS_EVENTLOG_FILE_CORRUPT},
  19069. + {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
  19070. + {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
  19071. + {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
  19072. + NT_STATUS_MUTANT_LIMIT_EXCEEDED},
  19073. + {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
  19074. + {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
  19075. + {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
  19076. + {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
  19077. + NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
  19078. + {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
  19079. + {"NT_STATUS_EVENTLOG_FILE_CHANGED",
  19080. + NT_STATUS_EVENTLOG_FILE_CHANGED},
  19081. + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
  19082. + NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
  19083. + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
  19084. + NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
  19085. + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
  19086. + NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
  19087. + {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
  19088. + NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
  19089. + {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
  19090. + {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
  19091. + {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
  19092. + {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
  19093. + NT_STATUS_RESOURCE_LANG_NOT_FOUND},
  19094. + {"NT_STATUS_INSUFF_SERVER_RESOURCES",
  19095. + NT_STATUS_INSUFF_SERVER_RESOURCES},
  19096. + {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
  19097. + {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
  19098. + NT_STATUS_INVALID_ADDRESS_COMPONENT},
  19099. + {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
  19100. + NT_STATUS_INVALID_ADDRESS_WILDCARD},
  19101. + {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
  19102. + {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
  19103. + NT_STATUS_ADDRESS_ALREADY_EXISTS},
  19104. + {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
  19105. + {"NT_STATUS_CONNECTION_DISCONNECTED",
  19106. + NT_STATUS_CONNECTION_DISCONNECTED},
  19107. + {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
  19108. + {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
  19109. + {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
  19110. + {"NT_STATUS_TRANSACTION_TIMED_OUT",
  19111. + NT_STATUS_TRANSACTION_TIMED_OUT},
  19112. + {"NT_STATUS_TRANSACTION_NO_RELEASE",
  19113. + NT_STATUS_TRANSACTION_NO_RELEASE},
  19114. + {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
  19115. + {"NT_STATUS_TRANSACTION_RESPONDED",
  19116. + NT_STATUS_TRANSACTION_RESPONDED},
  19117. + {"NT_STATUS_TRANSACTION_INVALID_ID",
  19118. + NT_STATUS_TRANSACTION_INVALID_ID},
  19119. + {"NT_STATUS_TRANSACTION_INVALID_TYPE",
  19120. + NT_STATUS_TRANSACTION_INVALID_TYPE},
  19121. + {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
  19122. + {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
  19123. + {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
  19124. + NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
  19125. + {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
  19126. + {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
  19127. + NT_STATUS_SYSTEM_PROCESS_TERMINATED},
  19128. + {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
  19129. + {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
  19130. + NT_STATUS_NO_BROWSER_SERVERS_FOUND},
  19131. + {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
  19132. + {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
  19133. + NT_STATUS_DRIVER_CANCEL_TIMEOUT},
  19134. + {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
  19135. + NT_STATUS_REPLY_MESSAGE_MISMATCH},
  19136. + {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
  19137. + {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
  19138. + NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
  19139. + {"NT_STATUS_LOST_WRITEBEHIND_DATA",
  19140. + NT_STATUS_LOST_WRITEBEHIND_DATA},
  19141. + {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
  19142. + NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
  19143. + {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
  19144. + {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
  19145. + {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
  19146. + {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
  19147. + {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
  19148. + {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
  19149. + {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
  19150. + {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
  19151. + {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
  19152. + {"NT_STATUS_RETRY", NT_STATUS_RETRY},
  19153. + {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
  19154. + {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
  19155. + {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
  19156. + {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
  19157. + {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
  19158. + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
  19159. + NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
  19160. + {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
  19161. + {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
  19162. + {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
  19163. + {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
  19164. + {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
  19165. + NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
  19166. + {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
  19167. + NT_STATUS_ADDRESS_NOT_ASSOCIATED},
  19168. + {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
  19169. + {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
  19170. + {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
  19171. + {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
  19172. + {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
  19173. + {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
  19174. + {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
  19175. + {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
  19176. + {"NT_STATUS_BAD_COMPRESSION_BUFFER",
  19177. + NT_STATUS_BAD_COMPRESSION_BUFFER},
  19178. + {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
  19179. + {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
  19180. + {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
  19181. + NT_STATUS_TIMER_RESOLUTION_NOT_SET},
  19182. + {"NT_STATUS_CONNECTION_COUNT_LIMIT",
  19183. + NT_STATUS_CONNECTION_COUNT_LIMIT},
  19184. + {"NT_STATUS_LOGIN_TIME_RESTRICTION",
  19185. + NT_STATUS_LOGIN_TIME_RESTRICTION},
  19186. + {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
  19187. + NT_STATUS_LOGIN_WKSTA_RESTRICTION},
  19188. + {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
  19189. + {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
  19190. + NT_STATUS_INSUFFICIENT_LOGON_INFO},
  19191. + {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
  19192. + {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
  19193. + NT_STATUS_BAD_SERVICE_ENTRYPOINT},
  19194. + {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
  19195. + {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
  19196. + {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
  19197. + {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
  19198. + {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
  19199. + {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
  19200. + {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
  19201. + NT_STATUS_LICENSE_QUOTA_EXCEEDED},
  19202. + {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
  19203. + {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
  19204. + {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
  19205. + {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
  19206. + {"NT_STATUS_UNSUPPORTED_COMPRESSION",
  19207. + NT_STATUS_UNSUPPORTED_COMPRESSION},
  19208. + {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
  19209. + {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
  19210. + NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
  19211. + {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
  19212. + NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
  19213. + {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
  19214. + NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
  19215. + {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
  19216. + {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
  19217. + {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
  19218. + NT_STATUS_QUOTA_LIST_INCONSISTENT},
  19219. + {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
  19220. + {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
  19221. + {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
  19222. + {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
  19223. + {NULL, 0}
  19224. +};
  19225. --- /dev/null
  19226. +++ b/fs/cifs/nterr.h
  19227. @@ -0,0 +1,556 @@
  19228. +/*
  19229. + Unix SMB/Netbios implementation.
  19230. + Version 1.9.
  19231. + NT error code constants
  19232. + Copyright (C) Andrew Tridgell 1992-2000
  19233. + Copyright (C) John H Terpstra 1996-2000
  19234. + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
  19235. + Copyright (C) Paul Ashton 1998-2000
  19236. +
  19237. + This program is free software; you can redistribute it and/or modify
  19238. + it under the terms of the GNU General Public License as published by
  19239. + the Free Software Foundation; either version 2 of the License, or
  19240. + (at your option) any later version.
  19241. +
  19242. + This program is distributed in the hope that it will be useful,
  19243. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  19244. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19245. + GNU General Public License for more details.
  19246. +
  19247. + You should have received a copy of the GNU General Public License
  19248. + along with this program; if not, write to the Free Software
  19249. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19250. +*/
  19251. +
  19252. +
  19253. +
  19254. +#ifndef _NTERR_H
  19255. +#define _NTERR_H
  19256. +
  19257. +struct nt_err_code_struct {
  19258. + char *nt_errstr;
  19259. + __u32 nt_errcode;
  19260. +};
  19261. +
  19262. +extern const struct nt_err_code_struct nt_errs[];
  19263. +
  19264. +/* Win32 Status codes. */
  19265. +
  19266. +#define STATUS_BUFFER_OVERFLOW 0x80000005
  19267. +#define STATUS_MORE_ENTRIES 0x0105
  19268. +#define ERROR_INVALID_PARAMETER 0x0057
  19269. +#define ERROR_INSUFFICIENT_BUFFER 0x007a
  19270. +#define STATUS_1804 0x070c
  19271. +#define STATUS_NOTIFY_ENUM_DIR 0x010c
  19272. +
  19273. +/* Win32 Error codes extracted using a loop in smbclient then printing a
  19274. + netmon sniff to a file. */
  19275. +
  19276. +#define NT_STATUS_OK 0x0000
  19277. +#define STATUS_SOME_UNMAPPED 0x0107
  19278. +#define STATUS_BUFFER_OVERFLOW 0x80000005
  19279. +#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
  19280. +#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
  19281. +#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
  19282. +#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
  19283. +#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
  19284. +#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
  19285. +#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
  19286. +#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
  19287. +#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
  19288. +#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
  19289. +#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
  19290. +#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
  19291. +#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
  19292. +#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
  19293. +#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
  19294. +#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
  19295. +#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
  19296. +#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
  19297. +#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
  19298. +#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
  19299. +#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
  19300. +#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
  19301. +#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
  19302. +#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
  19303. +#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
  19304. +#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
  19305. +#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
  19306. +#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
  19307. +#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
  19308. +#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
  19309. +#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
  19310. +#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
  19311. +#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
  19312. +#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
  19313. +#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
  19314. +#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
  19315. +#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
  19316. +#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
  19317. +#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
  19318. +#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
  19319. +#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
  19320. +#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
  19321. +#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
  19322. +#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
  19323. +#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
  19324. +#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
  19325. +#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
  19326. +#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
  19327. +#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
  19328. +#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
  19329. +#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
  19330. +#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
  19331. +#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
  19332. +#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
  19333. +#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
  19334. +#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
  19335. +#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
  19336. +#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
  19337. +#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
  19338. +#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
  19339. +#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
  19340. +#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
  19341. +#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
  19342. +#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
  19343. +#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
  19344. +#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
  19345. +#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
  19346. +#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
  19347. +#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
  19348. +#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
  19349. +#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
  19350. +#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
  19351. +#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
  19352. +#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
  19353. +#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
  19354. +#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
  19355. +#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
  19356. +#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
  19357. +#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
  19358. +#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
  19359. +#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
  19360. +#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
  19361. +#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
  19362. +#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
  19363. +#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
  19364. +#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
  19365. +#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
  19366. +#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
  19367. +#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
  19368. +#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
  19369. +#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
  19370. +#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
  19371. +#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
  19372. +#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
  19373. +#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
  19374. +#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
  19375. +#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
  19376. +#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
  19377. +#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
  19378. +#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
  19379. +#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
  19380. +#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
  19381. +#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
  19382. +#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
  19383. +#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
  19384. +#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
  19385. +#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
  19386. +#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
  19387. +#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
  19388. +#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
  19389. +#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
  19390. +#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
  19391. +#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
  19392. +#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
  19393. +#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
  19394. +#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
  19395. +#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
  19396. +#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
  19397. +#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
  19398. +#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
  19399. +#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
  19400. +#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
  19401. +#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
  19402. +#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
  19403. +#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
  19404. +#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
  19405. +#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
  19406. +#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
  19407. +#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
  19408. +#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
  19409. +#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
  19410. +#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
  19411. +#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
  19412. +#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
  19413. +#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
  19414. +#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
  19415. +#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
  19416. +#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
  19417. +#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
  19418. +#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
  19419. +#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
  19420. +#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
  19421. +#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
  19422. +#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
  19423. +#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
  19424. +#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
  19425. +#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
  19426. +#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
  19427. +#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
  19428. +#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
  19429. +#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
  19430. +#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
  19431. +#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
  19432. +#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
  19433. +#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
  19434. +#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
  19435. +#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
  19436. +#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
  19437. +#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
  19438. +#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
  19439. +#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
  19440. +#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
  19441. +#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
  19442. +#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
  19443. +#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
  19444. +#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
  19445. +#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
  19446. +#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
  19447. +#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
  19448. +#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
  19449. +#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
  19450. +#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
  19451. +#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
  19452. +#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
  19453. +#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
  19454. +#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
  19455. +#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
  19456. +#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
  19457. +#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
  19458. +#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
  19459. +#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
  19460. +#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
  19461. +#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
  19462. +#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
  19463. +#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
  19464. +#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
  19465. +#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
  19466. +#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
  19467. +#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
  19468. +#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
  19469. +#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
  19470. +#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
  19471. +#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
  19472. +#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
  19473. +#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
  19474. +#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
  19475. +#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
  19476. +#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
  19477. +#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
  19478. +#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
  19479. +#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
  19480. +#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
  19481. +#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
  19482. +#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
  19483. +#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
  19484. +#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
  19485. +#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
  19486. +#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
  19487. +#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
  19488. +#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
  19489. +#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
  19490. +#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
  19491. +#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
  19492. +#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
  19493. +#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
  19494. +#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
  19495. +#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
  19496. +#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
  19497. +#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
  19498. +#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
  19499. +#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
  19500. +#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
  19501. +#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
  19502. +#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
  19503. +#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
  19504. +#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
  19505. +#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
  19506. +#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
  19507. +#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
  19508. +#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
  19509. +#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
  19510. +#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
  19511. +#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
  19512. +#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
  19513. +#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
  19514. +#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
  19515. +#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
  19516. +#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
  19517. +#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
  19518. +#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
  19519. +#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
  19520. +#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
  19521. +#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
  19522. +#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
  19523. +#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
  19524. +#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
  19525. +#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
  19526. +#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
  19527. +#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
  19528. +#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
  19529. +#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
  19530. +#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
  19531. +#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
  19532. +#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
  19533. +#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
  19534. +#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
  19535. +#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
  19536. +#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
  19537. +#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
  19538. +#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
  19539. +#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
  19540. +#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
  19541. +#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
  19542. +#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
  19543. +#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
  19544. +#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
  19545. +#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
  19546. +#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
  19547. +#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
  19548. +#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
  19549. +#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
  19550. +#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
  19551. +#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
  19552. +#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
  19553. +#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
  19554. +#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
  19555. +#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
  19556. +#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
  19557. +#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
  19558. +#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
  19559. +#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
  19560. +#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
  19561. +#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
  19562. +#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
  19563. +#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
  19564. +#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
  19565. +#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
  19566. +#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
  19567. +#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
  19568. +#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
  19569. +#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
  19570. +#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
  19571. +#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
  19572. +#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
  19573. +#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
  19574. +#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
  19575. +#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
  19576. +#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
  19577. +#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
  19578. +#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
  19579. +#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
  19580. +#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
  19581. +#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
  19582. +#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
  19583. +#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
  19584. +#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
  19585. +#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
  19586. +#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
  19587. +#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
  19588. +#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
  19589. +#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
  19590. +#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
  19591. +#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
  19592. +#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
  19593. +#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
  19594. +#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
  19595. +#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
  19596. +#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
  19597. +#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
  19598. +#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
  19599. +#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
  19600. +#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
  19601. +#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
  19602. +#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
  19603. +#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
  19604. +#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
  19605. +#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
  19606. +#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
  19607. +#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
  19608. +#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
  19609. +#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
  19610. +#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
  19611. +#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
  19612. +#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
  19613. +#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
  19614. +#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
  19615. +#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
  19616. +#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
  19617. +#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
  19618. +#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
  19619. +#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
  19620. +#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
  19621. +#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
  19622. +#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
  19623. +#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
  19624. +#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
  19625. +#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
  19626. +#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
  19627. +#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
  19628. +#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
  19629. +#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
  19630. +#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
  19631. +#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
  19632. +#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
  19633. +#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
  19634. +#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
  19635. +#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
  19636. +#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
  19637. +#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
  19638. +#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
  19639. +#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
  19640. +#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
  19641. +#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
  19642. +#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
  19643. +#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
  19644. +#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
  19645. +#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
  19646. +#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
  19647. +#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
  19648. +#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
  19649. +#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
  19650. +#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
  19651. +#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
  19652. +#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
  19653. +#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
  19654. +#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
  19655. +#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
  19656. +#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
  19657. +#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
  19658. +#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
  19659. +#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
  19660. +#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
  19661. +#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
  19662. +#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
  19663. +#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
  19664. +#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
  19665. +#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
  19666. +#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
  19667. +#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
  19668. +#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
  19669. +#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
  19670. +#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
  19671. +#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
  19672. +#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
  19673. +#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
  19674. +#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
  19675. +#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
  19676. +#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
  19677. +#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
  19678. +#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
  19679. +#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
  19680. +#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
  19681. +#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
  19682. +#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
  19683. +#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
  19684. +#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
  19685. +#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
  19686. +#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
  19687. +#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
  19688. +#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
  19689. +#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
  19690. +#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
  19691. +#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
  19692. +#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
  19693. +#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
  19694. +#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
  19695. +#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
  19696. +#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
  19697. +#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
  19698. +#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
  19699. +#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
  19700. +#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
  19701. +#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
  19702. +#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
  19703. +#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
  19704. +#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
  19705. +#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
  19706. +#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
  19707. +#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
  19708. +#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
  19709. +#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
  19710. +#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
  19711. +#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
  19712. +#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
  19713. +#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
  19714. +#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
  19715. +#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
  19716. +#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
  19717. +#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
  19718. +#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
  19719. +#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
  19720. +#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
  19721. +#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
  19722. +#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
  19723. +#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
  19724. +#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
  19725. +#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
  19726. +#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
  19727. +#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
  19728. +#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
  19729. +#define NT_STATUS_RETRY 0xC0000000 | 0x022d
  19730. +#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
  19731. +#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
  19732. +#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
  19733. +#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
  19734. +#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
  19735. +#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
  19736. +#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
  19737. +#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
  19738. +#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
  19739. +#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
  19740. +#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
  19741. +#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
  19742. +#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
  19743. +#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
  19744. +#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
  19745. +#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
  19746. +#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
  19747. +#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
  19748. +#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
  19749. +#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
  19750. +#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
  19751. +#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
  19752. +#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
  19753. +#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
  19754. +#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
  19755. +#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
  19756. +#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
  19757. +#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
  19758. +#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
  19759. +#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
  19760. +#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
  19761. +#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
  19762. +#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
  19763. +#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
  19764. +#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
  19765. +#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
  19766. +#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
  19767. +#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
  19768. +#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
  19769. +#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
  19770. +#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
  19771. +#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
  19772. +#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
  19773. +#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
  19774. +#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
  19775. +#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
  19776. +#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
  19777. +#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
  19778. +#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
  19779. +#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
  19780. +#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
  19781. +#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
  19782. +
  19783. +#endif /* _NTERR_H */
  19784. --- /dev/null
  19785. +++ b/fs/cifs/ntlmssp.h
  19786. @@ -0,0 +1,101 @@
  19787. +/*
  19788. + * fs/cifs/ntlmssp.h
  19789. + *
  19790. + * Copyright (c) International Business Machines Corp., 2002
  19791. + * Author(s): Steve French ([email protected])
  19792. + *
  19793. + * This library is free software; you can redistribute it and/or modify
  19794. + * it under the terms of the GNU Lesser General Public License as published
  19795. + * by the Free Software Foundation; either version 2.1 of the License, or
  19796. + * (at your option) any later version.
  19797. + *
  19798. + * This library is distributed in the hope that it will be useful,
  19799. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19800. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  19801. + * the GNU Lesser General Public License for more details.
  19802. + *
  19803. + * You should have received a copy of the GNU Lesser General Public License
  19804. + * along with this library; if not, write to the Free Software
  19805. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19806. + */
  19807. +
  19808. +#pragma pack(1)
  19809. +
  19810. +#define NTLMSSP_SIGNATURE "NTLMSSP"
  19811. +/* Message Types */
  19812. +#define NtLmNegotiate 1
  19813. +#define NtLmChallenge 2
  19814. +#define NtLmAuthenticate 3
  19815. +#define UnknownMessage 8
  19816. +
  19817. +/* Negotiate Flags */
  19818. +#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
  19819. +#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
  19820. +#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
  19821. +#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
  19822. +#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
  19823. +#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
  19824. +#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
  19825. +#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
  19826. +#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
  19827. +#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
  19828. +#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
  19829. +#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
  19830. +#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
  19831. +#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
  19832. +#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
  19833. +#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
  19834. +#define NTLMSSP_REQUEST_INIT_RESP 0x100000
  19835. +#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
  19836. +#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
  19837. +#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
  19838. +#define NTLMSSP_NEGOTIATE_128 0x20000000
  19839. +#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
  19840. +#define NTLMSSP_NEGOTIATE_56 0x80000000
  19841. +
  19842. +/* Although typedefs are not commonly used for structure definitions */
  19843. +/* in the Linux kernel, in this particular case they are useful */
  19844. +/* to more closely match the standards document for NTLMSSP from */
  19845. +/* OpenGroup and to make the code more closely match the standard in */
  19846. +/* appearance */
  19847. +
  19848. +typedef struct _SECURITY_BUFFER {
  19849. + __u16 Length;
  19850. + __u16 MaximumLength;
  19851. + __u32 Buffer; /* offset to buffer */
  19852. +} SECURITY_BUFFER;
  19853. +
  19854. +typedef struct _NEGOTIATE_MESSAGE {
  19855. + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
  19856. + __u32 MessageType; /* 1 */
  19857. + __u32 NegotiateFlags;
  19858. + SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
  19859. + SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
  19860. + char DomainString[0];
  19861. + /* followed by WorkstationString */
  19862. +} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
  19863. +
  19864. +typedef struct _CHALLENGE_MESSAGE {
  19865. + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
  19866. + __u32 MessageType; /* 2 */
  19867. + SECURITY_BUFFER TargetName;
  19868. + __u32 NegotiateFlags;
  19869. + __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
  19870. + __u8 Reserved[8];
  19871. + SECURITY_BUFFER TargetInfoArray;
  19872. +} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
  19873. +
  19874. +typedef struct _AUTHENTICATE_MESSAGE {
  19875. + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
  19876. + __u32 MessageType; /* 3 */
  19877. + SECURITY_BUFFER LmChallengeResponse;
  19878. + SECURITY_BUFFER NtChallengeResponse;
  19879. + SECURITY_BUFFER DomainName;
  19880. + SECURITY_BUFFER UserName;
  19881. + SECURITY_BUFFER WorkstationName;
  19882. + SECURITY_BUFFER SessionKey;
  19883. + __u32 NegotiateFlags;
  19884. + char UserString[0];
  19885. +} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
  19886. +
  19887. +#pragma pack() /* resume default structure packing */
  19888. --- /dev/null
  19889. +++ b/fs/cifs/README
  19890. @@ -0,0 +1,356 @@
  19891. +The CIFS VFS support for Linux supports many advanced network filesystem
  19892. +features such as heirarchical dfs like namespace, hardlinks, locking and more.
  19893. +It was designed to comply with the SNIA CIFS Technical Reference (which
  19894. +supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
  19895. +practical interoperability with Windows 2000, Windows XP, Samba and equivalent
  19896. +servers.
  19897. +
  19898. +For questions or bug reports please contact:
  19899. + [email protected] ([email protected])
  19900. +
  19901. +Build instructions:
  19902. +==================
  19903. +For Linux 2.4:
  19904. +1) Get the kernel source (e.g.from http://www.kernel.org)
  19905. +and download the cifs vfs source (see the project page
  19906. +at http://us1.samba.org/samba/Linux_CIFS_client.html)
  19907. +and change directory into the top of the kernel directory
  19908. +then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
  19909. +to add the cifs vfs to your kernel configure options if
  19910. +it has not already been added (e.g. current SuSE and UL
  19911. +users do not need to apply the cifs_24.patch since the cifs vfs is
  19912. +already in the kernel configure menu) and then
  19913. +mkdir linux/fs/cifs and then copy the current cifs vfs files from
  19914. +the cifs download to your kernel build directory e.g.
  19915. +
  19916. + cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
  19917. +
  19918. +2) make menuconfig (or make xconfig)
  19919. +3) select cifs from within the network filesystem choices
  19920. +4) save and exit
  19921. +5) make dep
  19922. +6) make modules (or "make" if CIFS VFS not to be built as a module)
  19923. +
  19924. +For Linux 2.5:
  19925. +1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
  19926. +at bk://linux.bkbits.net/linux-2.5) and change directory into the top
  19927. +of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
  19928. +2) make menuconfig (or make xconfig)
  19929. +3) select cifs from within the network filesystem choices
  19930. +4) save and exit
  19931. +5) make
  19932. +
  19933. +
  19934. +Installation instructions:
  19935. +=========================
  19936. +If you have built the CIFS vfs as module (successfully) simply
  19937. +type "make modules_install" (or if you prefer, manually copy the file to
  19938. +the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
  19939. +
  19940. +If you have built the CIFS vfs into the kernel itself, follow the instructions
  19941. +for your distribution on how to install a new kernel (usually you
  19942. +would simply type "make install").
  19943. +
  19944. +If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
  19945. +the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
  19946. +similar files reside (usually /sbin). Although the helper software is not
  19947. +required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
  19948. +"net" may also be helpful since it may someday provide easier mount syntax for
  19949. +users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
  19950. +Note that running the Winbind pam/nss module (logon service) on all of your
  19951. +Linux clients is useful in mapping Uids and Gids consistently across the
  19952. +domain to the proper network user. The mount.cifs mount helper can be
  19953. +trivially built from Samba 3.0 or later source e.g. by executing:
  19954. +
  19955. + gcc samba/source/client/mount.cifs.c -o mount.cifs
  19956. +
  19957. +Note that when the mount.cifs utility is run suid (allowing user mounts),
  19958. +in order to reduce risks, the "nosuid" mount flag is passed in on mount to
  19959. +disallow execution of an suid program mounted on the remote target.
  19960. +When mount is executed as root, nosuid is not passed in by default,
  19961. +and execution of suid programs on the remote target would be enabled
  19962. +by default. This can be changed, as with nfs and other filesystems,
  19963. +by simply specifying "nosuid" among the mount options. For user mounts
  19964. +though to be able to pass the suid flag to mount requires rebuilding
  19965. +mount.cifs with the following flag:
  19966. +
  19967. + gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
  19968. +
  19969. +There is a corresponding manual page for cifs mounting in the Samba 3.0 and
  19970. +later source tree in docs/manpages/mount.cifs.8
  19971. +
  19972. +Samba Considerations
  19973. +====================
  19974. +To get the maximum benefit from the CIFS VFS, we recommend using a server that
  19975. +supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
  19976. +Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
  19977. +Note that uid, gid and file permissions will display default values if you do
  19978. +not have a server that supports the Unix extensions for CIFS (such as Samba
  19979. +2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
  19980. +the line:
  19981. +
  19982. + unix extensions = yes
  19983. +
  19984. +to your smb.conf file on the server. Note that the following smb.conf settings
  19985. +are also useful (on the Samba server) when the majority of clients are Unix or
  19986. +Linux:
  19987. +
  19988. + case sensitive = yes
  19989. + delete readonly = yes
  19990. + ea support = yes
  19991. +
  19992. +Note that ea support is required for supporting Linux xattrs.
  19993. +Some administrators also change the "map archive" and the "create mask"
  19994. +parameters from their default values. Creating special devices (mknod)
  19995. +remotely may require specifying a mkdev function to Samba if you are not using
  19996. +Samba 3.0.5 or later. For more information on these see the manual pages
  19997. +("man smb.conf") on the Samba server system. Note that the cifs vfs,
  19998. +unlike the smbfs vfs, does not read the smb.conf on the client system
  19999. +(the few optional settings are passed in on mount via -o parameters instead).
  20000. +Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
  20001. +open files (required for strict POSIX compliance). Windows Servers already
  20002. +supported this feature. Samba server does not allow symlinks that refer to files
  20003. +outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
  20004. +files with absolute paths (ie beginning with slash) such as:
  20005. + ln -s /mnt/foo bar
  20006. +would be forbidden. Samba 3.0.5 server or later includes the ability to create
  20007. +such symlinks safely by converting unsafe symlinks (ie symlinks to server
  20008. +files that are outside of the share) to a samba specific format on the server
  20009. +that is ignored by local server applications and non-cifs clients and that will
  20010. +not be traversed by the Samba server). This is opaque to the Linux client
  20011. +application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
  20012. +later, but only for remote clients using the CIFS Unix extensions, and will
  20013. +be invisbile to Windows clients and typically will not affect local
  20014. +applications running on the same server as Samba.
  20015. +
  20016. +Use instructions:
  20017. +================
  20018. +Once the CIFS VFS support is built into the kernel or installed as a module
  20019. +(cifs.o), you can use mount syntax like the following to access Samba or Windows
  20020. +servers:
  20021. +
  20022. + mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
  20023. +
  20024. +Before -o the option -v may be specified to make the mount.cifs
  20025. +mount helper display the mount steps more verbosely.
  20026. +After -o the following commonly used cifs vfs specific options
  20027. +are supported:
  20028. +
  20029. + user=<username>
  20030. + pass=<password>
  20031. + domain=<domain name>
  20032. +
  20033. +Other cifs mount options are described below. Use of TCP names (in addition to
  20034. +ip addresses) is available if the mount helper (mount.cifs) is installed. If
  20035. +you do not trust the server to which are mounted, or if you do not have
  20036. +cifs signing enabled (and the physical network is insecure), consider use
  20037. +of the standard mount options "noexec" and "nosuid" to reduce the risk of
  20038. +running an altered binary on your local system (downloaded from a hostile server
  20039. +or altered by a hostile router).
  20040. +
  20041. +When using the mount helper mount.cifs, passwords may be specified via alternate
  20042. +mechanisms, instead of specifying it after -o using the normal "pass=" syntax
  20043. +on the command line:
  20044. +1) By including it in a credential file. Specify credentials=filename as one
  20045. +of the mount options. Credential files contain two lines
  20046. + username=someuser
  20047. + password=your_password
  20048. +2) By specifying the password in the PASSWD environment variable (similarly
  20049. +the user name can be taken from the USER environment variable).
  20050. +3) By specifying the password in a file by name via PASSWD_FILE
  20051. +4) By specifying the password in a file by file descriptor via PASSWD_FD
  20052. +
  20053. +If no password is provided, mount.cifs will prompt for password entry
  20054. +
  20055. +Restrictions
  20056. +============
  20057. +Servers must support the NTLM SMB dialect (which is the most recent, supported
  20058. +by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
  20059. +Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
  20060. +1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
  20061. +problem as most servers support this. IPv6 support is planned for the future.
  20062. +
  20063. +CIFS VFS Mount Options
  20064. +======================
  20065. +A partial list of the supported mount options follows:
  20066. + user The user name to use when trying to establish
  20067. + the CIFS session.
  20068. + password The user password. If the mount helper is
  20069. + installed, the user will be prompted for password
  20070. + if it is not supplied.
  20071. + ip The ip address of the target server
  20072. + unc The target server Universal Network Name (export) to
  20073. + mount.
  20074. + domain Set the SMB/CIFS workgroup name prepended to the
  20075. + username during CIFS session establishment
  20076. + uid If CIFS Unix extensions are not supported by the server
  20077. + this overrides the default uid for inodes. For mounts to
  20078. + servers which do support the CIFS Unix extensions, such
  20079. + as a properly configured Samba server, the server provides
  20080. + the uid, gid and mode. For servers which do not support
  20081. + the Unix extensions, the default uid (and gid) returned on
  20082. + lookup of existing files is the uid (gid) of the person
  20083. + who executed the mount (root, except when mount.cifs
  20084. + is configured setuid for user mounts) unless the "uid="
  20085. + (gid) mount option is specified. For the uid (gid) of newly
  20086. + created files and directories, ie files created since
  20087. + the last mount of the server share, the expected uid
  20088. + (gid) is cached as as long as the inode remains in
  20089. + memory on the client. Also note that permission
  20090. + checks (authorization checks) on accesses to a file occur
  20091. + at the server, but there are cases in which an administrator
  20092. + may want to restrict at the client as well. For those
  20093. + servers which do not report a uid/gid owner
  20094. + (such as Windows), permissions can also be checked at the
  20095. + client, and a crude form of client side permission checking
  20096. + can be enabled by specifying file_mode and dir_mode on
  20097. + the client
  20098. + gid If CIFS Unix extensions are not supported by the server
  20099. + this overrides the default gid for inodes.
  20100. + file_mode If CIFS Unix extensions are not supported by the server
  20101. + this overrides the default mode for file inodes.
  20102. + dir_mode If CIFS Unix extensions are not supported by the server
  20103. + this overrides the default mode for directory inodes.
  20104. + port attempt to contact the server on this tcp port, before
  20105. + trying the usual ports (port 445, then 139).
  20106. + iocharset Codepage used to convert local path names to and from
  20107. + Unicode. Unicode is used by default for network path
  20108. + names if the server supports it. If iocharset is
  20109. + not specified then the nls_default specified
  20110. + during the local client kernel build will be used.
  20111. + If server does not support Unicode, this parameter is
  20112. + unused.
  20113. + rsize default read size
  20114. + wsize default write size
  20115. + rw mount the network share read-write (note that the
  20116. + server may still consider the share read-only)
  20117. + ro mount network share read-only
  20118. + version used to distinguish different versions of the
  20119. + mount helper utility (not typically needed)
  20120. + sep if first mount option (after the -o), overrides
  20121. + the comma as the separator between the mount
  20122. + parms. e.g.
  20123. + -o user=myname,password=mypassword,domain=mydom
  20124. + could be passed instead with period as the separator by
  20125. + -o sep=.user=myname.password=mypassword.domain=mydom
  20126. + this might be useful when comma is contained within username
  20127. + or password or domain. This option is less important
  20128. + when the cifs mount helper cifs.mount (version 1.1 or later)
  20129. + is used.
  20130. + nosuid Do not allow remote executables with the suid bit
  20131. + program to be executed. This is only meaningful for mounts
  20132. + to servers such as Samba which support the CIFS Unix Extensions.
  20133. + If you do not trust the servers in your network (your mount
  20134. + targets) it is recommended that you specify this option for
  20135. + greater security.
  20136. + suid Allow remote files on this mountpoint with suid enabled to
  20137. + be executed (default for mounts when executed as root,
  20138. + nosuid is default for user mounts).
  20139. + credentials Although ignored by the cifs kernel component, it is used by
  20140. + the mount helper, mount.cifs. When mount.cifs is installed it
  20141. + opens and reads the credential file specified in order
  20142. + to obtain the userid and password arguments which are passed to
  20143. + the cifs vfs.
  20144. + guest Although ignored by the kernel component, the mount.cifs
  20145. + mount helper will not prompt the user for a password
  20146. + if guest is specified on the mount options. If no
  20147. + password is specified a null password will be used.
  20148. +
  20149. +The mount.cifs mount helper also accepts a few mount options before -o
  20150. +including:
  20151. +
  20152. + -S take password from stdin (equivalent to setting the environment
  20153. + variable "PASSWD_FD=0"
  20154. + -V print mount.cifs version
  20155. + -? display simple usage information
  20156. +
  20157. +With recent 2.6 kernel versions of modutils, the version of the cifs kernel
  20158. +module can be displayed via modinfo.
  20159. +
  20160. +Misc /proc/fs/cifs Flags and Debug Info
  20161. +=======================================
  20162. +Informational pseudo-files:
  20163. +DebugData Displays information about active CIFS sessions
  20164. + and shares.
  20165. +Stats Lists summary resource usage information as well as per
  20166. + share statistics, if CONFIG_CIFS_STATS in enabled
  20167. + in the kernel configuration.
  20168. +
  20169. +Configuration pseudo-files:
  20170. +MultiuserMount If set to one, more than one CIFS session to
  20171. + the same server ip address can be established
  20172. + if more than one uid accesses the same mount
  20173. + point and if the uids user/password mapping
  20174. + information is available. (default is 0)
  20175. +PacketSigningEnabled If set to one, cifs packet signing is enabled
  20176. + and will be used if the server requires
  20177. + it. If set to two, cifs packet signing is
  20178. + required even if the server considers packet
  20179. + signing optional. (default 1)
  20180. +cifsFYI If set to one, additional debug information is
  20181. + logged to the system error log. (default 0)
  20182. +ExtendedSecurity If set to one, SPNEGO session establishment
  20183. + is allowed which enables more advanced
  20184. + secure CIFS session establishment (default 0)
  20185. +NTLMV2Enabled If set to one, more secure password hashes
  20186. + are used when the server supports them and
  20187. + when kerberos is not negotiated (default 0)
  20188. +traceSMB If set to one, debug information is logged to the
  20189. + system error log with the start of smb requests
  20190. + and responses (default 0)
  20191. +LookupCacheEnable If set to one, inode information is kept cached
  20192. + for one second improving performance of lookups
  20193. + (default 1)
  20194. +OplockEnabled If set to one, safe distributed caching enabled.
  20195. + (default 1)
  20196. +LinuxExtensionsEnabled If set to one then the client will attempt to
  20197. + use the CIFS "UNIX" extensions which are optional
  20198. + protocol enhancements that allow CIFS servers
  20199. + to return accurate UID/GID information as well
  20200. + as support symbolic links. If you use servers
  20201. + such as Samba that support the CIFS Unix
  20202. + extensions but do not want to use symbolic link
  20203. + support and want to map the uid and gid fields
  20204. + to values supplied at mount (rather than the
  20205. + actual values, then set this to zero. (default 1)
  20206. +
  20207. +These experimental features and tracing can be enabled by changing flags in
  20208. +/proc/fs/cifs (after the cifs module has been installed or built into the
  20209. +kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
  20210. +tracing to the kernel message log type:
  20211. +
  20212. + echo 1 > /proc/fs/cifs/cifsFYI
  20213. +
  20214. +and for more extensive tracing including the start of smb requests and responses
  20215. +
  20216. + echo 1 > /proc/fs/cifs/traceSMB
  20217. +
  20218. +Three other experimental features are under development and to test
  20219. +require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
  20220. +
  20221. + CONFIG_CIFS_QUOTA
  20222. +
  20223. + CONFIG_CIFS_XATTR
  20224. +
  20225. + CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
  20226. + notification and perhaps later for file leases)
  20227. +
  20228. +Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
  20229. +if the kernel was configured with cifs statistics enabled. The statistics
  20230. +represent the number of successful (ie non-zero return code from the server)
  20231. +SMB responses to some of the more common commands (open, delete, mkdir etc.).
  20232. +Also recorded is the total bytes read and bytes written to the server for
  20233. +that share. Note that due to client caching effects this can be less than the
  20234. +number of bytes read and written by the application running on the client.
  20235. +The statistics for the number of total SMBs and oplock breaks are different in
  20236. +that they represent all for that share, not just those for which the server
  20237. +returned success.
  20238. +
  20239. +Also note that "cat /proc/fs/cifs/DebugData" will display information about
  20240. +the active sessions and the shares that are mounted. Note: NTLMv2 enablement
  20241. +will not work since they its implementation is not quite complete yet.
  20242. +Do not alter these configuration values unless you are doing specific testing.
  20243. +Enabling extended security works to Windows 2000 Workstations and XP but not to
  20244. +Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
  20245. +(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
  20246. +complete in the CIFS VFS yet).
  20247. --- /dev/null
  20248. +++ b/fs/cifs/rfc1002pdu.h
  20249. @@ -0,0 +1,79 @@
  20250. +/*
  20251. + * fs/cifs/rfc1002pdu.h
  20252. + *
  20253. + * Protocol Data Unit definitions for RFC 1001/1002 support
  20254. + *
  20255. + * Copyright (c) International Business Machines Corp., 2004
  20256. + * Author(s): Steve French ([email protected])
  20257. + *
  20258. + * This library is free software; you can redistribute it and/or modify
  20259. + * it under the terms of the GNU Lesser General Public License as published
  20260. + * by the Free Software Foundation; either version 2.1 of the License, or
  20261. + * (at your option) any later version.
  20262. + *
  20263. + * This library is distributed in the hope that it will be useful,
  20264. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20265. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  20266. + * the GNU Lesser General Public License for more details.
  20267. + *
  20268. + * You should have received a copy of the GNU Lesser General Public License
  20269. + * along with this library; if not, write to the Free Software
  20270. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20271. + */
  20272. +
  20273. +#pragma pack(1)
  20274. +
  20275. +/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
  20276. +
  20277. + /* RFC 1002 session packet types */
  20278. +#define RFC1002_SESSION_MESASAGE 0x00
  20279. +#define RFC1002_SESSION_REQUEST 0x81
  20280. +#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
  20281. +#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
  20282. +#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
  20283. +#define RFC1002_SESSION_KEEP_ALIVE 0x85
  20284. +
  20285. + /* RFC 1002 flags (only one defined */
  20286. +#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
  20287. +
  20288. +struct rfc1002_session_packet {
  20289. + __u8 type;
  20290. + __u8 flags;
  20291. + __u16 length;
  20292. + union {
  20293. + struct {
  20294. + __u8 called_len;
  20295. + __u8 called_name[32];
  20296. + __u8 scope1; /* null */
  20297. + __u8 calling_len;
  20298. + __u8 calling_name[32];
  20299. + __u8 scope2; /* null */
  20300. + } session_req;
  20301. + struct {
  20302. + __u32 retarget_ip_addr;
  20303. + __u16 port;
  20304. + } retarget_resp;
  20305. + __u8 neg_ses_resp_error_code;
  20306. + /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
  20307. + SESSION_KEEP_ALIVE packet also does not include a trailer.
  20308. + Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
  20309. + } trailer;
  20310. +};
  20311. +
  20312. +/* Negative Session Response error codes */
  20313. +#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
  20314. +#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
  20315. +#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
  20316. +#define RFC1002_INSUFFICIENT_RESOURCE 0x83
  20317. +#define RFC1002_UNSPECIFIED_ERROR 0x8F
  20318. +
  20319. +/* RFC 1002 Datagram service packets are not defined here as they
  20320. +are not needed for the network filesystem client unless we plan on
  20321. +implementing broadcast resolution of the server ip address (from
  20322. +server netbios name). Currently server names are resolved only via DNS
  20323. +(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
  20324. +
  20325. +#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
  20326. +
  20327. +#pragma pack() /* resume default structure packing */
  20328. +
  20329. --- /dev/null
  20330. +++ b/fs/cifs/smbdes.c
  20331. @@ -0,0 +1,408 @@
  20332. +/*
  20333. + Unix SMB/Netbios implementation.
  20334. + Version 1.9.
  20335. +
  20336. + a partial implementation of DES designed for use in the
  20337. + SMB authentication protocol
  20338. +
  20339. + Copyright (C) Andrew Tridgell 1998
  20340. + Modified by Steve French ([email protected]) 2002,2004
  20341. +
  20342. + This program is free software; you can redistribute it and/or modify
  20343. + it under the terms of the GNU General Public License as published by
  20344. + the Free Software Foundation; either version 2 of the License, or
  20345. + (at your option) any later version.
  20346. +
  20347. + This program is distributed in the hope that it will be useful,
  20348. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  20349. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20350. + GNU General Public License for more details.
  20351. +
  20352. + You should have received a copy of the GNU General Public License
  20353. + along with this program; if not, write to the Free Software
  20354. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20355. +*/
  20356. +
  20357. +/* NOTES:
  20358. +
  20359. + This code makes no attempt to be fast! In fact, it is a very
  20360. + slow implementation
  20361. +
  20362. + This code is NOT a complete DES implementation. It implements only
  20363. + the minimum necessary for SMB authentication, as used by all SMB
  20364. + products (including every copy of Microsoft Windows95 ever sold)
  20365. +
  20366. + In particular, it can only do a unchained forward DES pass. This
  20367. + means it is not possible to use this code for encryption/decryption
  20368. + of data, instead it is only useful as a "hash" algorithm.
  20369. +
  20370. + There is no entry point into this code that allows normal DES operation.
  20371. +
  20372. + I believe this means that this code does not come under ITAR
  20373. + regulations but this is NOT a legal opinion. If you are concerned
  20374. + about the applicability of ITAR regulations to this code then you
  20375. + should confirm it for yourself (and maybe let me know if you come
  20376. + up with a different answer to the one above)
  20377. +*/
  20378. +#include <linux/slab.h>
  20379. +#define uchar unsigned char
  20380. +
  20381. +static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
  20382. + 1, 58, 50, 42, 34, 26, 18,
  20383. + 10, 2, 59, 51, 43, 35, 27,
  20384. + 19, 11, 3, 60, 52, 44, 36,
  20385. + 63, 55, 47, 39, 31, 23, 15,
  20386. + 7, 62, 54, 46, 38, 30, 22,
  20387. + 14, 6, 61, 53, 45, 37, 29,
  20388. + 21, 13, 5, 28, 20, 12, 4
  20389. +};
  20390. +
  20391. +static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
  20392. + 3, 28, 15, 6, 21, 10,
  20393. + 23, 19, 12, 4, 26, 8,
  20394. + 16, 7, 27, 20, 13, 2,
  20395. + 41, 52, 31, 37, 47, 55,
  20396. + 30, 40, 51, 45, 33, 48,
  20397. + 44, 49, 39, 56, 34, 53,
  20398. + 46, 42, 50, 36, 29, 32
  20399. +};
  20400. +
  20401. +static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
  20402. + 60, 52, 44, 36, 28, 20, 12, 4,
  20403. + 62, 54, 46, 38, 30, 22, 14, 6,
  20404. + 64, 56, 48, 40, 32, 24, 16, 8,
  20405. + 57, 49, 41, 33, 25, 17, 9, 1,
  20406. + 59, 51, 43, 35, 27, 19, 11, 3,
  20407. + 61, 53, 45, 37, 29, 21, 13, 5,
  20408. + 63, 55, 47, 39, 31, 23, 15, 7
  20409. +};
  20410. +
  20411. +static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
  20412. + 4, 5, 6, 7, 8, 9,
  20413. + 8, 9, 10, 11, 12, 13,
  20414. + 12, 13, 14, 15, 16, 17,
  20415. + 16, 17, 18, 19, 20, 21,
  20416. + 20, 21, 22, 23, 24, 25,
  20417. + 24, 25, 26, 27, 28, 29,
  20418. + 28, 29, 30, 31, 32, 1
  20419. +};
  20420. +
  20421. +static uchar perm5[32] = { 16, 7, 20, 21,
  20422. + 29, 12, 28, 17,
  20423. + 1, 15, 23, 26,
  20424. + 5, 18, 31, 10,
  20425. + 2, 8, 24, 14,
  20426. + 32, 27, 3, 9,
  20427. + 19, 13, 30, 6,
  20428. + 22, 11, 4, 25
  20429. +};
  20430. +
  20431. +static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
  20432. + 39, 7, 47, 15, 55, 23, 63, 31,
  20433. + 38, 6, 46, 14, 54, 22, 62, 30,
  20434. + 37, 5, 45, 13, 53, 21, 61, 29,
  20435. + 36, 4, 44, 12, 52, 20, 60, 28,
  20436. + 35, 3, 43, 11, 51, 19, 59, 27,
  20437. + 34, 2, 42, 10, 50, 18, 58, 26,
  20438. + 33, 1, 41, 9, 49, 17, 57, 25
  20439. +};
  20440. +
  20441. +static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
  20442. +
  20443. +static uchar sbox[8][4][16] = {
  20444. + {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
  20445. + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
  20446. + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
  20447. + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
  20448. +
  20449. + {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
  20450. + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
  20451. + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
  20452. + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
  20453. +
  20454. + {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
  20455. + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
  20456. + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
  20457. + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
  20458. +
  20459. + {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
  20460. + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
  20461. + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
  20462. + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
  20463. +
  20464. + {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
  20465. + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
  20466. + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
  20467. + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
  20468. +
  20469. + {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
  20470. + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
  20471. + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
  20472. + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
  20473. +
  20474. + {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
  20475. + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
  20476. + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
  20477. + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
  20478. +
  20479. + {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
  20480. + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
  20481. + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
  20482. + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
  20483. +};
  20484. +
  20485. +static void
  20486. +permute(char *out, char *in, uchar * p, int n)
  20487. +{
  20488. + int i;
  20489. + for (i = 0; i < n; i++)
  20490. + out[i] = in[p[i] - 1];
  20491. +}
  20492. +
  20493. +static void
  20494. +lshift(char *d, int count, int n)
  20495. +{
  20496. + char out[64];
  20497. + int i;
  20498. + for (i = 0; i < n; i++)
  20499. + out[i] = d[(i + count) % n];
  20500. + for (i = 0; i < n; i++)
  20501. + d[i] = out[i];
  20502. +}
  20503. +
  20504. +static void
  20505. +concat(char *out, char *in1, char *in2, int l1, int l2)
  20506. +{
  20507. + while (l1--)
  20508. + *out++ = *in1++;
  20509. + while (l2--)
  20510. + *out++ = *in2++;
  20511. +}
  20512. +
  20513. +static void
  20514. +xor(char *out, char *in1, char *in2, int n)
  20515. +{
  20516. + int i;
  20517. + for (i = 0; i < n; i++)
  20518. + out[i] = in1[i] ^ in2[i];
  20519. +}
  20520. +
  20521. +static void
  20522. +dohash(char *out, char *in, char *key, int forw)
  20523. +{
  20524. + int i, j, k;
  20525. + char *pk1;
  20526. + char c[28];
  20527. + char d[28];
  20528. + char *cd;
  20529. + char ki[16][48];
  20530. + char *pd1;
  20531. + char l[32], r[32];
  20532. + char *rl;
  20533. +
  20534. + /* Have to reduce stack usage */
  20535. + pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
  20536. + if(pk1 == NULL)
  20537. + return;
  20538. +
  20539. + cd = pk1 + 56;
  20540. + pd1= cd + 56;
  20541. + rl = pd1 + 64;
  20542. +
  20543. + permute(pk1, key, perm1, 56);
  20544. +
  20545. + for (i = 0; i < 28; i++)
  20546. + c[i] = pk1[i];
  20547. + for (i = 0; i < 28; i++)
  20548. + d[i] = pk1[i + 28];
  20549. +
  20550. + for (i = 0; i < 16; i++) {
  20551. + lshift(c, sc[i], 28);
  20552. + lshift(d, sc[i], 28);
  20553. +
  20554. + concat(cd, c, d, 28, 28);
  20555. + permute(ki[i], cd, perm2, 48);
  20556. + }
  20557. +
  20558. + permute(pd1, in, perm3, 64);
  20559. +
  20560. + for (j = 0; j < 32; j++) {
  20561. + l[j] = pd1[j];
  20562. + r[j] = pd1[j + 32];
  20563. + }
  20564. +
  20565. + for (i = 0; i < 16; i++) {
  20566. + char *er; /* er[48] */
  20567. + char *erk; /* erk[48] */
  20568. + char b[8][6];
  20569. + char *cb; /* cb[32] */
  20570. + char *pcb; /* pcb[32] */
  20571. + char *r2; /* r2[32] */
  20572. +
  20573. + er = kmalloc(48+48+32+32+32, GFP_KERNEL);
  20574. + if(er == NULL) {
  20575. + kfree(pk1);
  20576. + return;
  20577. + }
  20578. + erk = er+48;
  20579. + cb = erk+48;
  20580. + pcb = cb+32;
  20581. + r2 = pcb+32;
  20582. +
  20583. + permute(er, r, perm4, 48);
  20584. +
  20585. + xor(erk, er, ki[forw ? i : 15 - i], 48);
  20586. +
  20587. + for (j = 0; j < 8; j++)
  20588. + for (k = 0; k < 6; k++)
  20589. + b[j][k] = erk[j * 6 + k];
  20590. +
  20591. + for (j = 0; j < 8; j++) {
  20592. + int m, n;
  20593. + m = (b[j][0] << 1) | b[j][5];
  20594. +
  20595. + n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
  20596. + 1) | b[j][4];
  20597. +
  20598. + for (k = 0; k < 4; k++)
  20599. + b[j][k] =
  20600. + (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
  20601. + }
  20602. +
  20603. + for (j = 0; j < 8; j++)
  20604. + for (k = 0; k < 4; k++)
  20605. + cb[j * 4 + k] = b[j][k];
  20606. + permute(pcb, cb, perm5, 32);
  20607. +
  20608. + xor(r2, l, pcb, 32);
  20609. +
  20610. + for (j = 0; j < 32; j++)
  20611. + l[j] = r[j];
  20612. +
  20613. + for (j = 0; j < 32; j++)
  20614. + r[j] = r2[j];
  20615. +
  20616. + kfree(er);
  20617. + }
  20618. +
  20619. + concat(rl, r, l, 32, 32);
  20620. +
  20621. + permute(out, rl, perm6, 64);
  20622. + kfree(pk1);
  20623. +}
  20624. +
  20625. +static void
  20626. +str_to_key(unsigned char *str, unsigned char *key)
  20627. +{
  20628. + int i;
  20629. +
  20630. + key[0] = str[0] >> 1;
  20631. + key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
  20632. + key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
  20633. + key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
  20634. + key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
  20635. + key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
  20636. + key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
  20637. + key[7] = str[6] & 0x7F;
  20638. + for (i = 0; i < 8; i++) {
  20639. + key[i] = (key[i] << 1);
  20640. + }
  20641. +}
  20642. +
  20643. +static void
  20644. +smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
  20645. +{
  20646. + int i;
  20647. + char *outb; /* outb[64] */
  20648. + char *inb; /* inb[64] */
  20649. + char *keyb; /* keyb[64] */
  20650. + unsigned char key2[8];
  20651. +
  20652. + outb = kmalloc(64 * 3,GFP_KERNEL);
  20653. + if(outb == NULL)
  20654. + return;
  20655. +
  20656. + inb = outb + 64;
  20657. + keyb = inb + 64;
  20658. +
  20659. + str_to_key(key, key2);
  20660. +
  20661. + for (i = 0; i < 64; i++) {
  20662. + inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
  20663. + keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
  20664. + outb[i] = 0;
  20665. + }
  20666. +
  20667. + dohash(outb, inb, keyb, forw);
  20668. +
  20669. + for (i = 0; i < 8; i++) {
  20670. + out[i] = 0;
  20671. + }
  20672. +
  20673. + for (i = 0; i < 64; i++) {
  20674. + if (outb[i])
  20675. + out[i / 8] |= (1 << (7 - (i % 8)));
  20676. + }
  20677. + kfree(outb);
  20678. +}
  20679. +
  20680. +void
  20681. +E_P16(unsigned char *p14, unsigned char *p16)
  20682. +{
  20683. + unsigned char sp8[8] =
  20684. + { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
  20685. + smbhash(p16, sp8, p14, 1);
  20686. + smbhash(p16 + 8, sp8, p14 + 7, 1);
  20687. +}
  20688. +
  20689. +void
  20690. +E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
  20691. +{
  20692. + smbhash(p24, c8, p21, 1);
  20693. + smbhash(p24 + 8, c8, p21 + 7, 1);
  20694. + smbhash(p24 + 16, c8, p21 + 14, 1);
  20695. +}
  20696. +
  20697. +void
  20698. +D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
  20699. +{
  20700. + smbhash(out, in, p14, 0);
  20701. + smbhash(out + 8, in + 8, p14 + 7, 0);
  20702. +}
  20703. +
  20704. +void
  20705. +E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
  20706. +{
  20707. + smbhash(out, in, p14, 1);
  20708. + smbhash(out + 8, in + 8, p14 + 7, 1);
  20709. +}
  20710. +
  20711. +void
  20712. +cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
  20713. +{
  20714. + unsigned char buf[8];
  20715. +
  20716. + smbhash(buf, in, key, 1);
  20717. + smbhash(out, buf, key + 9, 1);
  20718. +}
  20719. +
  20720. +void
  20721. +cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
  20722. +{
  20723. + unsigned char buf[8];
  20724. + static unsigned char key2[8];
  20725. +
  20726. + smbhash(buf, in, key, 1);
  20727. + key2[0] = key[7];
  20728. + smbhash(out, buf, key2, 1);
  20729. +}
  20730. +
  20731. +void
  20732. +cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
  20733. +{
  20734. + static unsigned char key2[8];
  20735. +
  20736. + smbhash(out, in, key, forw);
  20737. + key2[0] = key[7];
  20738. + smbhash(out + 8, in + 8, key2, forw);
  20739. +}
  20740. --- /dev/null
  20741. +++ b/fs/cifs/smbencrypt.c
  20742. @@ -0,0 +1,295 @@
  20743. +/*
  20744. + Unix SMB/Netbios implementation.
  20745. + Version 1.9.
  20746. + SMB parameters and setup
  20747. + Copyright (C) Andrew Tridgell 1992-2000
  20748. + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
  20749. + Modified by Jeremy Allison 1995.
  20750. + Copyright (C) Andrew Bartlett <[email protected]> 2002-2003
  20751. + Modified by Steve French ([email protected]) 2002-2003
  20752. +
  20753. + This program is free software; you can redistribute it and/or modify
  20754. + it under the terms of the GNU General Public License as published by
  20755. + the Free Software Foundation; either version 2 of the License, or
  20756. + (at your option) any later version.
  20757. +
  20758. + This program is distributed in the hope that it will be useful,
  20759. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  20760. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20761. + GNU General Public License for more details.
  20762. +
  20763. + You should have received a copy of the GNU General Public License
  20764. + along with this program; if not, write to the Free Software
  20765. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20766. +*/
  20767. +
  20768. +#include <linux/module.h>
  20769. +#include <linux/fs.h>
  20770. +#include <linux/string.h>
  20771. +#include <linux/kernel.h>
  20772. +#include <linux/random.h>
  20773. +#include "cifs_unicode.h"
  20774. +#include "cifspdu.h"
  20775. +#include "md5.h"
  20776. +#include "cifs_debug.h"
  20777. +
  20778. +#ifndef FALSE
  20779. +#define FALSE 0
  20780. +#endif
  20781. +#ifndef TRUE
  20782. +#define TRUE 1
  20783. +#endif
  20784. +
  20785. +/* following came from the other byteorder.h to avoid include conflicts */
  20786. +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
  20787. +#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
  20788. +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
  20789. +
  20790. +/*The following definitions come from lib/md4.c */
  20791. +
  20792. +void mdfour(unsigned char *out, unsigned char *in, int n);
  20793. +
  20794. +/*The following definitions come from libsmb/smbdes.c */
  20795. +
  20796. +void E_P16(unsigned char *p14, unsigned char *p16);
  20797. +void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
  20798. +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
  20799. +void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
  20800. +void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
  20801. +void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
  20802. +void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
  20803. + int forw);
  20804. +
  20805. +/*The following definitions come from libsmb/smbencrypt.c */
  20806. +
  20807. +void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
  20808. +void E_md4hash(const unsigned char *passwd, unsigned char *p16);
  20809. +void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
  20810. +void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
  20811. + unsigned char p24[24]);
  20812. +void NTLMSSPOWFencrypt(unsigned char passwd[8],
  20813. + unsigned char *ntlmchalresp, unsigned char p24[24]);
  20814. +void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
  20815. +int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
  20816. + int new_pwrd_size, __u32 * new_pw_len);
  20817. +
  20818. +/*
  20819. + This implements the X/Open SMB password encryption
  20820. + It takes a password, a 8 byte "crypt key" and puts 24 bytes of
  20821. + encrypted password into p24 */
  20822. +/* Note that password must be uppercased and null terminated */
  20823. +void
  20824. +SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
  20825. +{
  20826. + unsigned char p14[15], p21[21];
  20827. +
  20828. + memset(p21, '\0', 21);
  20829. + memset(p14, '\0', 14);
  20830. + strncpy((char *) p14, (char *) passwd, 14);
  20831. +
  20832. +/* strupper((char *)p14); *//* BB at least uppercase the easy range */
  20833. + E_P16(p14, p21);
  20834. +
  20835. + SMBOWFencrypt(p21, c8, p24);
  20836. +
  20837. + memset(p14,0,15);
  20838. + memset(p21,0,21);
  20839. +}
  20840. +
  20841. +/* Routines for Windows NT MD4 Hash functions. */
  20842. +static int
  20843. +_my_wcslen(__u16 * str)
  20844. +{
  20845. + int len = 0;
  20846. + while (*str++ != 0)
  20847. + len++;
  20848. + return len;
  20849. +}
  20850. +
  20851. +/*
  20852. + * Convert a string into an NT UNICODE string.
  20853. + * Note that regardless of processor type
  20854. + * this must be in intel (little-endian)
  20855. + * format.
  20856. + */
  20857. +
  20858. +static int
  20859. +_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
  20860. +{ /* not a very good conversion routine - change/fix */
  20861. + int i;
  20862. + __u16 val;
  20863. +
  20864. + for (i = 0; i < len; i++) {
  20865. + val = *src;
  20866. + SSVAL(dst, 0, val);
  20867. + dst++;
  20868. + src++;
  20869. + if (val == 0)
  20870. + break;
  20871. + }
  20872. + return i;
  20873. +}
  20874. +
  20875. +/*
  20876. + * Creates the MD4 Hash of the users password in NT UNICODE.
  20877. + */
  20878. +
  20879. +void
  20880. +E_md4hash(const unsigned char *passwd, unsigned char *p16)
  20881. +{
  20882. + int len;
  20883. + __u16 wpwd[129];
  20884. +
  20885. + /* Password cannot be longer than 128 characters */
  20886. + if(passwd) {
  20887. + len = strlen((char *) passwd);
  20888. + if (len > 128) {
  20889. + len = 128;
  20890. + }
  20891. + /* Password must be converted to NT unicode */
  20892. + _my_mbstowcs(wpwd, passwd, len);
  20893. + } else
  20894. + len = 0;
  20895. +
  20896. + wpwd[len] = 0; /* Ensure string is null terminated */
  20897. + /* Calculate length in bytes */
  20898. + len = _my_wcslen(wpwd) * sizeof (__u16);
  20899. +
  20900. + mdfour(p16, (unsigned char *) wpwd, len);
  20901. + memset(wpwd,0,129 * 2);
  20902. +}
  20903. +
  20904. +/* Does both the NT and LM owfs of a user's password */
  20905. +void
  20906. +nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
  20907. +{
  20908. + char passwd[514];
  20909. +
  20910. + memset(passwd, '\0', 514);
  20911. + if (strlen(pwd) < 513)
  20912. + strcpy(passwd, pwd);
  20913. + else
  20914. + memcpy(passwd, pwd, 512);
  20915. + /* Calculate the MD4 hash (NT compatible) of the password */
  20916. + memset(nt_p16, '\0', 16);
  20917. + E_md4hash(passwd, nt_p16);
  20918. +
  20919. + /* Mangle the passwords into Lanman format */
  20920. + passwd[14] = '\0';
  20921. +/* strupper(passwd); */
  20922. +
  20923. + /* Calculate the SMB (lanman) hash functions of the password */
  20924. +
  20925. + memset(p16, '\0', 16);
  20926. + E_P16((unsigned char *) passwd, (unsigned char *) p16);
  20927. +
  20928. + /* clear out local copy of user's password (just being paranoid). */
  20929. + memset(passwd, '\0', sizeof (passwd));
  20930. +}
  20931. +
  20932. +/* Does the NTLMv2 owfs of a user's password */
  20933. +void
  20934. +ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
  20935. + const char *domain_n, unsigned char kr_buf[16],
  20936. + const struct nls_table *nls_codepage)
  20937. +{
  20938. + wchar_t * user_u;
  20939. + wchar_t * dom_u;
  20940. + int user_l, domain_l;
  20941. + struct HMACMD5Context ctx;
  20942. +
  20943. + /* might as well do one alloc to hold both (user_u and dom_u) */
  20944. + user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
  20945. + if(user_u == NULL)
  20946. + return;
  20947. + dom_u = user_u + 1024;
  20948. +
  20949. + /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
  20950. + push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
  20951. +
  20952. + /* BB user and domain may need to be uppercased */
  20953. + user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
  20954. + domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
  20955. +
  20956. + user_l++; /* trailing null */
  20957. + domain_l++;
  20958. +
  20959. + hmac_md5_init_limK_to_64(owf, 16, &ctx);
  20960. + hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
  20961. + hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
  20962. + hmac_md5_final(kr_buf, &ctx);
  20963. +
  20964. + kfree(user_u);
  20965. +}
  20966. +
  20967. +/* Does the des encryption from the NT or LM MD4 hash. */
  20968. +void
  20969. +SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
  20970. + unsigned char p24[24])
  20971. +{
  20972. + unsigned char p21[21];
  20973. +
  20974. + memset(p21, '\0', 21);
  20975. +
  20976. + memcpy(p21, passwd, 16);
  20977. + E_P24(p21, c8, p24);
  20978. +}
  20979. +
  20980. +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
  20981. +void
  20982. +NTLMSSPOWFencrypt(unsigned char passwd[8],
  20983. + unsigned char *ntlmchalresp, unsigned char p24[24])
  20984. +{
  20985. + unsigned char p21[21];
  20986. +
  20987. + memset(p21, '\0', 21);
  20988. + memcpy(p21, passwd, 8);
  20989. + memset(p21 + 8, 0xbd, 8);
  20990. +
  20991. + E_P24(p21, ntlmchalresp, p24);
  20992. +}
  20993. +
  20994. +/* Does the NT MD4 hash then des encryption. */
  20995. +
  20996. +void
  20997. +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
  20998. +{
  20999. + unsigned char p21[21];
  21000. +
  21001. + memset(p21, '\0', 21);
  21002. +
  21003. + E_md4hash(passwd, p21);
  21004. + SMBOWFencrypt(p21, c8, p24);
  21005. +}
  21006. +
  21007. +/* Does the md5 encryption from the NT hash for NTLMv2. */
  21008. +void
  21009. +SMBOWFencrypt_ntv2(const unsigned char kr[16],
  21010. + const struct data_blob * srv_chal,
  21011. + const struct data_blob * cli_chal, unsigned char resp_buf[16])
  21012. +{
  21013. + struct HMACMD5Context ctx;
  21014. +
  21015. + hmac_md5_init_limK_to_64(kr, 16, &ctx);
  21016. + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
  21017. + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
  21018. + hmac_md5_final(resp_buf, &ctx);
  21019. +}
  21020. +
  21021. +void
  21022. +SMBsesskeygen_ntv2(const unsigned char kr[16],
  21023. + const unsigned char *nt_resp, __u8 sess_key[16])
  21024. +{
  21025. + struct HMACMD5Context ctx;
  21026. +
  21027. + hmac_md5_init_limK_to_64(kr, 16, &ctx);
  21028. + hmac_md5_update(nt_resp, 16, &ctx);
  21029. + hmac_md5_final((unsigned char *) sess_key, &ctx);
  21030. +}
  21031. +
  21032. +void
  21033. +SMBsesskeygen_ntv1(const unsigned char kr[16],
  21034. + const unsigned char *nt_resp, __u8 sess_key[16])
  21035. +{
  21036. + mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
  21037. +}
  21038. --- /dev/null
  21039. +++ b/fs/cifs/smberr.c
  21040. @@ -0,0 +1,240 @@
  21041. +/*
  21042. + Unix SMB/Netbios implementation.
  21043. + Version 1.9.
  21044. + Copyright (C) Andrew Tridgell 1998
  21045. + Copyright (C) Steve French ([email protected]) 2002
  21046. + This program is free software; you can redistribute it and/or modify
  21047. + it under the terms of the GNU General Public License as published by
  21048. + the Free Software Foundation; either version 2 of the License, or
  21049. + (at your option) any later version.
  21050. +
  21051. + This program is distributed in the hope that it will be useful,
  21052. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  21053. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21054. + GNU General Public License for more details.
  21055. +
  21056. + You should have received a copy of the GNU General Public License
  21057. + along with this program; if not, write to the Free Software
  21058. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21059. +*/
  21060. +include "smberr.h"
  21061. +#define NO_SYSLOG
  21062. +/* error code stuff - put together by Merik Karman
  21063. + [email protected] */
  21064. + typedef const struct {
  21065. + char *name;
  21066. + int code;
  21067. + char *message;
  21068. + int posix_code;
  21069. +} err_code_struct;
  21070. +
  21071. +/* Dos Error Messages */
  21072. +err_code_struct dos_msgs[] = {
  21073. + {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
  21074. + {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
  21075. + {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
  21076. + {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
  21077. + {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
  21078. + {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
  21079. + {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
  21080. + {"ERRnomem", ERRnomem,
  21081. + "Insufficient server memory to perform the requested function.",
  21082. + -ENOMEM},
  21083. + {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
  21084. + {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
  21085. + {"ERRbadformat", 11, "Invalid format.", -EINVAL},
  21086. + {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
  21087. + {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
  21088. + {"ERR", ERRres, "reserved.", -EIO},
  21089. + {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
  21090. + {"ERRremcd", ERRremcd,
  21091. + "A Delete Directory request attempted to remove the server's current directory.",
  21092. + -EIO},
  21093. + {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
  21094. + {"ERRnofiles", ERRnofiles, "A File Search command can find no more files matching the specified criteria.", -ENOENT}, /* Note: must map to zero manually in some places such as readdir */
  21095. + {"ERRbadshare", ERRbadshare,
  21096. + "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
  21097. + -EXTBSY},
  21098. + {"ERRlock", ERRlock,
  21099. + "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.",
  21100. + -EACCES},
  21101. + {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
  21102. + {"ERRnosuchshare", ERRnosuchshare,
  21103. + "You specified an invalid share name", -ENXIO},
  21104. + {"ERRfilexists", ERRfilexists,
  21105. + "The file named in a Create Directory, Make New File or Link request already exists.",
  21106. + -EEXIST},
  21107. + {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
  21108. + {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
  21109. +
  21110. + {"ERRmoredata", ERRmoredata,
  21111. + "There is more data to be returned.",},
  21112. + {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
  21113. + {NULL, -1, NULL, -EIO}
  21114. +};
  21115. +
  21116. +/* Server Error Messages */
  21117. +err_code_struct server_msgs[] = {
  21118. + {"ERRerror", 1, "Non-specific error code."},
  21119. + {"ERRbadpw", 2,
  21120. + "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
  21121. + {"ERRbadtype", 3, "reserved."},
  21122. + {"ERRaccess", 4,
  21123. + "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
  21124. + {"ERRinvnid", 5,
  21125. + "The tree ID (TID) specified in a command was invalid."},
  21126. + {"ERRinvnetname", 6, "Invalid network name in tree connect."},
  21127. + {"ERRinvdevice", 7,
  21128. + "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
  21129. + {"ERRqfull", 49,
  21130. + "Print queue full (files) -- returned by open print file."},
  21131. + {"ERRqtoobig", 50, "Print queue full -- no space."},
  21132. + {"ERRqeof", 51, "EOF on print queue dump."},
  21133. + {"ERRinvpfid", 52, "Invalid print file FID."},
  21134. + {"ERRsmbcmd", 64,
  21135. + "The server did not recognize the command received."},
  21136. + {"ERRsrverror", 65,
  21137. + "The server encountered an internal error, e.g., system file unavailable."},
  21138. + {"ERRfilespecs", 67,
  21139. + "The file handle (FID) and pathname parameters contained an invalid combination of values."},
  21140. + {"ERRreserved", 68, "reserved."},
  21141. + {"ERRbadpermits", 69,
  21142. + "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
  21143. + {"ERRreserved", 70, "reserved."},
  21144. + {"ERRsetattrmode", 71,
  21145. + "The attribute mode in the Set File Attribute request is invalid."},
  21146. + {"ERRpaused", 81, "Server is paused."},
  21147. + {"ERRmsgoff", 82, "Not receiving messages."},
  21148. + {"ERRnoroom", 83, "No room to buffer message."},
  21149. + {"ERRrmuns", 87, "Too many remote user names."},
  21150. + {"ERRtimeout", 88, "Operation timed out."},
  21151. + {"ERRnoresource", 89,
  21152. + "No resources currently available for request."},
  21153. + {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
  21154. + {"ERRbaduid", 91,
  21155. + "The UID is not known as a valid ID on this session."},
  21156. + {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
  21157. + {"ERRusestd", 251,
  21158. + "Temp unable to support Raw, use standard read/write."},
  21159. + {"ERRcontmpx", 252, "Continue in MPX mode."},
  21160. + {"ERRreserved", 253, "reserved."},
  21161. + {"ERRreserved", 254, "reserved."},
  21162. + {"ERRnosupport", 0xFFFF, "Function not supported."},
  21163. + {NULL, -1, NULL}
  21164. +};
  21165. +
  21166. +/* Hard Error Messages */
  21167. +err_code_struct hard_msgs[] = {
  21168. + {"ERRnowrite", 19,
  21169. + "Attempt to write on write-protected diskette."},
  21170. + {"ERRbadunit", 20, "Unknown unit."},
  21171. + {"ERRnotready", 21, "Drive not ready."},
  21172. + {"ERRbadcmd", 22, "Unknown command."},
  21173. + {"ERRdata", 23, "Data error (CRC)."},
  21174. + {"ERRbadreq", 24, "Bad request structure length."},
  21175. + {"ERRseek", 25, "Seek error."},
  21176. + {"ERRbadmedia", 26, "Unknown media type."},
  21177. + {"ERRbadsector", 27, "Sector not found."},
  21178. + {"ERRnopaper", 28, "Printer out of paper."},
  21179. + {"ERRwrite", 29, "Write fault."},
  21180. + {"ERRread", 30, "Read fault."},
  21181. + {"ERRgeneral", 31, "General failure."},
  21182. + {"ERRbadshare", 32, "An open conflicts with an existing open."},
  21183. + {"ERRlock", 33,
  21184. + "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
  21185. + {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
  21186. + {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
  21187. + {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
  21188. + {NULL, -1, NULL}
  21189. +};
  21190. +
  21191. +
  21192. +const struct {
  21193. + int code;
  21194. + char *class;
  21195. + err_code_struct *err_msgs;
  21196. +} err_classes[] = {
  21197. + {
  21198. + 0, "SUCCESS", NULL}, {
  21199. + 0x01, "ERRDOS", dos_msgs}, {
  21200. + 0x02, "ERRSRV", server_msgs}, {
  21201. + 0x03, "ERRHRD", hard_msgs}, {
  21202. + 0x04, "ERRXOS", NULL}, {
  21203. + 0xE1, "ERRRMX1", NULL}, {
  21204. + 0xE2, "ERRRMX2", NULL}, {
  21205. + 0xE3, "ERRRMX3", NULL}, {
  21206. + 0xFF, "ERRCMD", NULL}, {
  21207. +-1, NULL, NULL}};
  21208. +
  21209. +
  21210. +/****************************************************************************
  21211. +return a SMB error string from a SMB buffer
  21212. +****************************************************************************/
  21213. +char *smb_dos_errstr(char *inbuf)
  21214. +{
  21215. + static pstring ret;
  21216. + int class = CVAL(inbuf, smb_rcls);
  21217. + int num = SVAL(inbuf, smb_err);
  21218. + int i, j;
  21219. +
  21220. + for (i = 0; err_classes[i].class; i++)
  21221. + if (err_classes[i].code == class) {
  21222. + if (err_classes[i].err_msgs) {
  21223. + err_code_struct *err =
  21224. + err_classes[i].err_msgs;
  21225. + for (j = 0; err[j].name; j++)
  21226. + if (num == err[j].code) {
  21227. + if (DEBUGLEVEL > 0)
  21228. + slprintf(ret,
  21229. + sizeof
  21230. + (ret) - 1,
  21231. + "%s - %s (%s)",
  21232. + err_classes
  21233. + [i].class,
  21234. + err[j].
  21235. + name,
  21236. + err[j].
  21237. + message);
  21238. + else
  21239. + slprintf(ret,
  21240. + sizeof
  21241. + (ret) - 1,
  21242. + "%s - %s",
  21243. + err_classes
  21244. + [i].class,
  21245. + err[j].
  21246. + name);
  21247. + return ret;
  21248. + }
  21249. + }
  21250. +
  21251. + slprintf(ret, sizeof(ret) - 1, "%s - %d",
  21252. + err_classes[i].class, num);
  21253. + return ret;
  21254. + }
  21255. +
  21256. + slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
  21257. + class, num);
  21258. + return (ret);
  21259. +}
  21260. +
  21261. +
  21262. +/*****************************************************************************
  21263. + returns an WERROR error message.
  21264. + *****************************************************************************/
  21265. +char *werror_str(WERROR status)
  21266. +{
  21267. + static fstring msg;
  21268. + slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
  21269. + return msg;
  21270. +}
  21271. +
  21272. +
  21273. +/*****************************************************************************
  21274. +map a unix errno to a win32 error
  21275. + *****************************************************************************/
  21276. +WERROR map_werror_from_unix(int error)
  21277. +{
  21278. + NTSTATUS status = map_nt_error_from_unix(error);
  21279. + return ntstatus_to_werror(status);
  21280. +}
  21281. --- /dev/null
  21282. +++ b/fs/cifs/smberr.h
  21283. @@ -0,0 +1,113 @@
  21284. +/*
  21285. + * fs/cifs/smberr.h
  21286. + *
  21287. + * Copyright (c) International Business Machines Corp., 2002
  21288. + * Author(s): Steve French ([email protected])
  21289. + *
  21290. + * See Error Codes section of the SNIA CIFS Specification
  21291. + * for more information
  21292. + *
  21293. + * This library is free software; you can redistribute it and/or modify
  21294. + * it under the terms of the GNU Lesser General Public License as published
  21295. + * by the Free Software Foundation; either version 2.1 of the License, or
  21296. + * (at your option) any later version.
  21297. + *
  21298. + * This library is distributed in the hope that it will be useful,
  21299. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21300. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  21301. + * the GNU Lesser General Public License for more details.
  21302. + *
  21303. + * You should have received a copy of the GNU Lesser General Public License
  21304. + * along with this library; if not, write to the Free Software
  21305. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21306. + */
  21307. +
  21308. +#define SUCCESS 0 /* The request was successful. */
  21309. +#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
  21310. +#define ERRSRV 0x02 /* Error is generated by the file server daemon */
  21311. +#define ERRHRD 0x03 /* Error is a hardware error. */
  21312. +#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
  21313. +
  21314. +/* The following error codes may be generated with the SUCCESS error class.*/
  21315. +
  21316. +#define SUCCESS 0 /* The request was successful. */
  21317. +
  21318. +/* The following error codes may be generated with the ERRDOS error class.*/
  21319. +
  21320. +#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
  21321. +#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
  21322. +#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
  21323. +#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
  21324. +#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
  21325. +#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
  21326. +#define ERRbadmcb 7 /* Memory control blocks destroyed. */
  21327. +#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
  21328. +#define ERRbadmem 9 /* Invalid memory block address. */
  21329. +#define ERRbadenv 10 /* Invalid environment. */
  21330. +#define ERRbadformat 11 /* Invalid format. */
  21331. +#define ERRbadaccess 12 /* Invalid open mode. */
  21332. +#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
  21333. +#define ERRbaddrive 15 /* Invalid drive specified. */
  21334. +#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
  21335. +#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
  21336. +#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
  21337. +#define ERRgeneral 31
  21338. +#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
  21339. +#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
  21340. +#define ERRunsup 50
  21341. +#define ERRnosuchshare 67
  21342. +#define ERRfilexists 80 /* The file named in the request already exists. */
  21343. +#define ERRinvparm 87
  21344. +#define ERRdiskfull 112
  21345. +#define ERRinvname 123
  21346. +#define ERRdirnotempty 145
  21347. +#define ERRnotlocked 158
  21348. +#define ERRalreadyexists 183
  21349. +#define ERRbadpipe 230
  21350. +#define ERRpipebusy 231
  21351. +#define ERRpipeclosing 232
  21352. +#define ERRnotconnected 233
  21353. +#define ERRmoredata 234
  21354. +#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
  21355. +#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
  21356. + was not a link. */
  21357. +
  21358. +/* Following error codes may be generated with the ERRSRV error
  21359. +class.*/
  21360. +
  21361. +#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
  21362. +#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
  21363. +#define ERRbadtype 3 /* used for indicating DFS referral needed */
  21364. +#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
  21365. +#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
  21366. +#define ERRinvnetname 6 /* Invalid network name in tree connect. */
  21367. +#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
  21368. +#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
  21369. +#define ERRqtoobig 50 /* Print queue full -- no space. */
  21370. +#define ERRqeof 51 /* EOF on print queue dump */
  21371. +#define ERRinvpfid 52 /* Invalid print file FID. */
  21372. +#define ERRsmbcmd 64 /* The server did not recognize the command received. */
  21373. +#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
  21374. +#define ERRbadBID 66 /* (obsolete) */
  21375. +#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
  21376. +#define ERRbadLink 68 /* (obsolete) */
  21377. +#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
  21378. +#define ERRbadPID 70
  21379. +#define ERRsetattrmode 71 /* attribute (mode) is invalid */
  21380. +#define ERRpaused 81 /* Server is paused */
  21381. +#define ERRmsgoff 82 /* reserved - messaging off */
  21382. +#define ERRnoroom 83 /* reserved - no room for message */
  21383. +#define ERRrmuns 87 /* reserved - too many remote names */
  21384. +#define ERRtimeout 88 /* operation timed out */
  21385. +#define ERRnoresource 89 /* No resources available for request */
  21386. +#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
  21387. +#define ERRbaduid 91 /* The UID is not known as a valid user */
  21388. +#define ERRusempx 250 /* temporarily unable to use raw */
  21389. +#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
  21390. +#define ERR_NOTIFY_ENUM_DIR 1024
  21391. +#define ERRaccountexpired 2239
  21392. +#define ERRbadclient 2240
  21393. +#define ERRbadLogonTime 2241
  21394. +#define ERRpasswordExpired 2242
  21395. +#define ERRnetlogonNotStarted 2455
  21396. +#define ERRnosupport 0xFFFF
  21397. --- /dev/null
  21398. +++ b/fs/cifs/TODO
  21399. @@ -0,0 +1,106 @@
  21400. +version 1.16 May 27, 2004
  21401. +
  21402. +A Partial List of Missing Features
  21403. +==================================
  21404. +
  21405. +Contributions are welcome. There are plenty of opportunities
  21406. +for visible, important contributions to this module. Here
  21407. +is a partial list of the known problems and missing features:
  21408. +
  21409. +a) Support for SecurityDescriptors for chmod/chgrp/chown so
  21410. +these can be supported for Windows servers
  21411. +
  21412. +b) Better pam/winbind integration
  21413. +
  21414. +c) multi-user mounts - multiplexed sessionsetups over single vc
  21415. +(ie tcp session) - prettying up needed
  21416. +
  21417. +d) Kerberos/SPNEGO session setup support - (started)
  21418. +
  21419. +e) NTLMv2 authentication (mostly implemented)
  21420. +
  21421. +f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
  21422. +used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
  21423. +and raw NTLMSSP already. This is important when enabling
  21424. +extended security and mounting to Windows 2003 Servers
  21425. +
  21426. +f) Directory entry caching relies on a 1 second timer, rather than
  21427. +using FindNotify or equivalent. - (started)
  21428. +
  21429. +g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
  21430. +style byte range lock differences
  21431. +
  21432. +h) quota support
  21433. +
  21434. +i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
  21435. +which will allow us to expose dos attributes as well as real
  21436. +ACLs. This support has been started in the current code, but is
  21437. +ifdeffed out.
  21438. +
  21439. +k) finish writepages support (multi-page write behind for improved
  21440. +performance) and syncpage
  21441. +
  21442. +l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
  21443. +extra copy in/out of the socket buffers in some cases.
  21444. +
  21445. +m) finish support for IPv6. This is mostly complete but
  21446. +needs a simple inet_pton like function to convert ipv6
  21447. +addresses in string representation.
  21448. +
  21449. +o) Better optimize open (and pathbased setfilesize) to reduce the
  21450. +oplock breaks coming from windows srv. Piggyback identical file
  21451. +opens on top of each other by incrementing reference count rather
  21452. +than resending (helps reduce server resource utilization and avoid
  21453. +spurious oplock breaks).
  21454. +
  21455. +p) Improve performance of readpages by sending more than one read
  21456. +at a time when 8 pages or more are requested. Evaluate whether
  21457. +reads larger than 16K would be helpful.
  21458. +
  21459. +q) For support of Windows9x/98 we need to retry failed mounts
  21460. +to *SMBSERVER (default server name) with the uppercase hostname
  21461. +in the RFC1001 session_init request.
  21462. +
  21463. +r) Add Extended Attributed support (for storing UID/GID info
  21464. +to Windows servers)
  21465. +
  21466. +s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
  21467. +will autorefresh
  21468. +
  21469. +t) Add GUI tool to configure /proc/fs/cifs settings and for display of
  21470. +the CIFS statistics
  21471. +
  21472. +KNOWN BUGS (updated May 27, 2004)
  21473. +====================================
  21474. +1) existing symbolic links (Windows reparse points) are recognized but
  21475. +can not be created remotely. They are implemented for Samba and those that
  21476. +support the CIFS Unix extensions but Samba has a bug currently handling
  21477. +symlink text beginning with slash
  21478. +2) follow_link and readdir code does not follow dfs junctions
  21479. +but recognizes them
  21480. +3) create of new files to FAT partitions on Windows servers can
  21481. +succeed but still return access denied (appears to be Windows
  21482. +server not cifs client problem) and has not been reproduced recently.
  21483. +NTFS partitions do not have this problem.
  21484. +4) debug connectathon lock test case 10 which fails against
  21485. +Samba (may be unmappable due to POSIX to Windows lock model
  21486. +differences but worth investigating). Also debug Samba to
  21487. +see why lock test case 7 takes longer to complete to Samba
  21488. +than to Windows.
  21489. +
  21490. +Misc testing to do
  21491. +==================
  21492. +1) check out max path names and max path name components against various server
  21493. +types. Try nested symlinks. Return max path name in stat -f information
  21494. +
  21495. +2) Modify file portion of ltp so it can run against a mounted network
  21496. +share and run it against cifs vfs.
  21497. +
  21498. +3) Additional performance testing and optimization using iozone and similar -
  21499. +there are some easy changes that can be done to parallelize sequential writes,
  21500. +and when signing is disabled to request larger read sizes (larger than
  21501. +negotiated size) and send larger write sizes to modern servers.
  21502. +
  21503. +4) More exhaustively test the recently added NT4 support against various
  21504. +NT4 service pack levels.
  21505. +
  21506. --- /dev/null
  21507. +++ b/fs/cifs/transport.c
  21508. @@ -0,0 +1,434 @@
  21509. +/*
  21510. + * fs/cifs/transport.c
  21511. + *
  21512. + * Copyright (C) International Business Machines Corp., 2002,2004
  21513. + * Author(s): Steve French ([email protected])
  21514. + *
  21515. + * This library is free software; you can redistribute it and/or modify
  21516. + * it under the terms of the GNU Lesser General Public License as published
  21517. + * by the Free Software Foundation; either version 2.1 of the License, or
  21518. + * (at your option) any later version.
  21519. + *
  21520. + * This library is distributed in the hope that it will be useful,
  21521. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21522. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  21523. + * the GNU Lesser General Public License for more details.
  21524. + *
  21525. + * You should have received a copy of the GNU Lesser General Public License
  21526. + * along with this library; if not, write to the Free Software
  21527. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21528. + */
  21529. +
  21530. +#include <linux/fs.h>
  21531. +#include <linux/list.h>
  21532. +#include <linux/wait.h>
  21533. +#include <linux/net.h>
  21534. +#include <linux/version.h>
  21535. +#include <asm/uaccess.h>
  21536. +#include <asm/processor.h>
  21537. +#include "cifspdu.h"
  21538. +#include "cifsglob.h"
  21539. +#include "cifsproto.h"
  21540. +#include "cifs_debug.h"
  21541. +
  21542. +extern kmem_cache_t *cifs_mid_cachep;
  21543. +extern kmem_cache_t *cifs_oplock_cachep;
  21544. +
  21545. +struct mid_q_entry *
  21546. +AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
  21547. +{
  21548. + struct mid_q_entry *temp;
  21549. +
  21550. + if (ses == NULL) {
  21551. + cERROR(1, ("Null session passed in to AllocMidQEntry "));
  21552. + return NULL;
  21553. + }
  21554. + if (ses->server == NULL) {
  21555. + cERROR(1, ("Null TCP session in AllocMidQEntry"));
  21556. + return NULL;
  21557. + }
  21558. +
  21559. + temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
  21560. + SLAB_KERNEL);
  21561. + if (temp == NULL)
  21562. + return temp;
  21563. + else {
  21564. + memset(temp, 0, sizeof (struct mid_q_entry));
  21565. + temp->mid = smb_buffer->Mid; /* always LE */
  21566. + temp->pid = current->pid;
  21567. + temp->command = smb_buffer->Command;
  21568. + cFYI(1, ("For smb_command %d", temp->command));
  21569. + do_gettimeofday(&temp->when_sent);
  21570. + temp->ses = ses;
  21571. + temp->tsk = current;
  21572. + }
  21573. +
  21574. + spin_lock(&GlobalMid_Lock);
  21575. + list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
  21576. + atomic_inc(&midCount);
  21577. + temp->midState = MID_REQUEST_ALLOCATED;
  21578. + spin_unlock(&GlobalMid_Lock);
  21579. + return temp;
  21580. +}
  21581. +
  21582. +void
  21583. +DeleteMidQEntry(struct mid_q_entry *midEntry)
  21584. +{
  21585. + spin_lock(&GlobalMid_Lock);
  21586. + midEntry->midState = MID_FREE;
  21587. + list_del(&midEntry->qhead);
  21588. + atomic_dec(&midCount);
  21589. + spin_unlock(&GlobalMid_Lock);
  21590. + cifs_buf_release(midEntry->resp_buf);
  21591. + kmem_cache_free(cifs_mid_cachep, midEntry);
  21592. +}
  21593. +
  21594. +struct oplock_q_entry *
  21595. +AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
  21596. +{
  21597. + struct oplock_q_entry *temp;
  21598. + if ((pinode== NULL) || (tcon == NULL)) {
  21599. + cERROR(1, ("Null parms passed to AllocOplockQEntry"));
  21600. + return NULL;
  21601. + }
  21602. + temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
  21603. + SLAB_KERNEL);
  21604. + if (temp == NULL)
  21605. + return temp;
  21606. + else {
  21607. + temp->pinode = pinode;
  21608. + temp->tcon = tcon;
  21609. + temp->netfid = fid;
  21610. + spin_lock(&GlobalMid_Lock);
  21611. + list_add_tail(&temp->qhead, &GlobalOplock_Q);
  21612. + spin_unlock(&GlobalMid_Lock);
  21613. + }
  21614. + return temp;
  21615. +
  21616. +}
  21617. +
  21618. +void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
  21619. +{
  21620. + spin_lock(&GlobalMid_Lock);
  21621. + /* should we check if list empty first? */
  21622. + list_del(&oplockEntry->qhead);
  21623. + spin_unlock(&GlobalMid_Lock);
  21624. + kmem_cache_free(cifs_oplock_cachep, oplockEntry);
  21625. +}
  21626. +
  21627. +int
  21628. +smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
  21629. + unsigned int smb_buf_length, struct sockaddr *sin)
  21630. +{
  21631. + int rc = 0;
  21632. + int i = 0;
  21633. + struct msghdr smb_msg;
  21634. + struct iovec iov;
  21635. + mm_segment_t temp_fs;
  21636. +
  21637. + if(ssocket == NULL)
  21638. + return -ENOTSOCK; /* BB eventually add reconnect code here */
  21639. + iov.iov_base = smb_buffer;
  21640. + iov.iov_len = smb_buf_length + 4;
  21641. +
  21642. + smb_msg.msg_name = sin;
  21643. + smb_msg.msg_namelen = sizeof (struct sockaddr);
  21644. + smb_msg.msg_iov = &iov;
  21645. + smb_msg.msg_iovlen = 1;
  21646. + smb_msg.msg_control = NULL;
  21647. + smb_msg.msg_controllen = 0;
  21648. + smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
  21649. +
  21650. + /* smb header is converted in header_assemble. bcc and rest of SMB word
  21651. + area, and byte area if necessary, is converted to littleendian in
  21652. + cifssmb.c and RFC1001 len is converted to bigendian in smb_send
  21653. + Flags2 is converted in SendReceive */
  21654. +
  21655. + smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
  21656. + cFYI(1, ("Sending smb of length %d ", smb_buf_length));
  21657. + dump_smb(smb_buffer, smb_buf_length + 4);
  21658. +
  21659. + temp_fs = get_fs(); /* we must turn off socket api parm checking */
  21660. + set_fs(get_ds());
  21661. + while(iov.iov_len > 0) {
  21662. + rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
  21663. + if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
  21664. + i++;
  21665. + if(i > 60) {
  21666. + cERROR(1,
  21667. + ("sends on sock %p stuck for 30 seconds",
  21668. + ssocket));
  21669. + rc = -EAGAIN;
  21670. + break;
  21671. + }
  21672. + set_current_state(TASK_INTERRUPTIBLE);
  21673. + schedule_timeout(HZ/2);
  21674. + continue;
  21675. + }
  21676. + if (rc < 0)
  21677. + break;
  21678. + iov.iov_base += rc;
  21679. + iov.iov_len -= rc;
  21680. + }
  21681. + set_fs(temp_fs);
  21682. +
  21683. + if (rc < 0) {
  21684. + cERROR(1,("Error %d sending data on socket to server.", rc));
  21685. + } else {
  21686. + rc = 0;
  21687. + }
  21688. +
  21689. + return rc;
  21690. +}
  21691. +
  21692. +int
  21693. +SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
  21694. + struct smb_hdr *in_buf, struct smb_hdr *out_buf,
  21695. + int *pbytes_returned, const int long_op)
  21696. +{
  21697. + int rc = 0;
  21698. + unsigned int receive_len;
  21699. + long timeout;
  21700. + struct mid_q_entry *midQ;
  21701. +
  21702. + if (ses == NULL) {
  21703. + cERROR(1,("Null smb session"));
  21704. + return -EIO;
  21705. + }
  21706. + if(ses->server == NULL) {
  21707. + cERROR(1,("Null tcp session"));
  21708. + return -EIO;
  21709. + }
  21710. +
  21711. + /* Ensure that we do not send more than 50 overlapping requests
  21712. + to the same server. We may make this configurable later or
  21713. + use ses->maxReq */
  21714. + if(long_op == -1) {
  21715. + /* oplock breaks must not be held up */
  21716. + atomic_inc(&ses->server->inFlight);
  21717. + } else {
  21718. + spin_lock(&GlobalMid_Lock);
  21719. + while(1) {
  21720. + if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
  21721. + spin_unlock(&GlobalMid_Lock);
  21722. + wait_event(ses->server->request_q,
  21723. + atomic_read(&ses->server->inFlight)
  21724. + < CIFS_MAX_REQ);
  21725. + spin_lock(&GlobalMid_Lock);
  21726. + } else {
  21727. + if(ses->server->tcpStatus == CifsExiting) {
  21728. + spin_unlock(&GlobalMid_Lock);
  21729. + return -ENOENT;
  21730. + }
  21731. +
  21732. + /* can not count locking commands against total since
  21733. + they are allowed to block on server */
  21734. +
  21735. + if(long_op < 3) {
  21736. + /* update # of requests on the wire to server */
  21737. + atomic_inc(&ses->server->inFlight);
  21738. + }
  21739. + spin_unlock(&GlobalMid_Lock);
  21740. + break;
  21741. + }
  21742. + }
  21743. + }
  21744. + /* make sure that we sign in the same order that we send on this socket
  21745. + and avoid races inside tcp sendmsg code that could cause corruption
  21746. + of smb data */
  21747. +
  21748. + down(&ses->server->tcpSem);
  21749. +
  21750. + if (ses->server->tcpStatus == CifsExiting) {
  21751. + rc = -ENOENT;
  21752. + goto out_unlock;
  21753. + } else if (ses->server->tcpStatus == CifsNeedReconnect) {
  21754. + cFYI(1,("tcp session dead - return to caller to retry"));
  21755. + rc = -EAGAIN;
  21756. + goto out_unlock;
  21757. + } else if (ses->status != CifsGood) {
  21758. + /* check if SMB session is bad because we are setting it up */
  21759. + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
  21760. + (in_buf->Command != SMB_COM_NEGOTIATE)) {
  21761. + rc = -EAGAIN;
  21762. + goto out_unlock;
  21763. + } /* else ok - we are setting up session */
  21764. + }
  21765. + midQ = AllocMidQEntry(in_buf, ses);
  21766. + if (midQ == NULL) {
  21767. + up(&ses->server->tcpSem);
  21768. + /* If not lock req, update # of requests on wire to server */
  21769. + if(long_op < 3) {
  21770. + atomic_dec(&ses->server->inFlight);
  21771. + wake_up(&ses->server->request_q);
  21772. + }
  21773. + return -ENOMEM;
  21774. + }
  21775. +
  21776. + if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
  21777. + up(&ses->server->tcpSem);
  21778. + cERROR(1,
  21779. + ("Illegal length, greater than maximum frame, %d ",
  21780. + in_buf->smb_buf_length));
  21781. + DeleteMidQEntry(midQ);
  21782. + /* If not lock req, update # of requests on wire to server */
  21783. + if(long_op < 3) {
  21784. + atomic_dec(&ses->server->inFlight);
  21785. + wake_up(&ses->server->request_q);
  21786. + }
  21787. + return -EIO;
  21788. + }
  21789. +
  21790. + if (in_buf->smb_buf_length > 12)
  21791. + in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
  21792. +
  21793. + rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
  21794. +
  21795. + midQ->midState = MID_REQUEST_SUBMITTED;
  21796. + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
  21797. + (struct sockaddr *) &(ses->server->addr.sockAddr));
  21798. + if(rc < 0) {
  21799. + DeleteMidQEntry(midQ);
  21800. + up(&ses->server->tcpSem);
  21801. + /* If not lock req, update # of requests on wire to server */
  21802. + if(long_op < 3) {
  21803. + atomic_dec(&ses->server->inFlight);
  21804. + wake_up(&ses->server->request_q);
  21805. + }
  21806. + return rc;
  21807. + } else
  21808. + up(&ses->server->tcpSem);
  21809. + if (long_op == -1)
  21810. + goto cifs_no_response_exit;
  21811. + else if (long_op == 2) /* writes past end of file can take looooong time */
  21812. + timeout = 300 * HZ;
  21813. + else if (long_op == 1)
  21814. + timeout = 45 * HZ; /* should be greater than
  21815. + servers oplock break timeout (about 43 seconds) */
  21816. + else if (long_op > 2) {
  21817. + timeout = MAX_SCHEDULE_TIMEOUT;
  21818. + } else
  21819. + timeout = 15 * HZ;
  21820. + /* wait for 15 seconds or until woken up due to response arriving or
  21821. + due to last connection to this server being unmounted */
  21822. + if (signal_pending(current)) {
  21823. + /* if signal pending do not hold up user for full smb timeout
  21824. + but we still give response a change to complete */
  21825. + if(midQ->midState & MID_REQUEST_SUBMITTED) {
  21826. + set_current_state(TASK_UNINTERRUPTIBLE);
  21827. + timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
  21828. + }
  21829. + } else { /* using normal timeout */
  21830. + /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
  21831. + (midQ->midState & MID_RESPONSE_RECEIVED) ||
  21832. + ((ses->server->tcpStatus != CifsGood) &&
  21833. + (ses->server->tcpStatus != CifsNew)),
  21834. + timeout); */
  21835. + /* Can not allow user interrupts- wreaks havoc with performance */
  21836. + if(midQ->midState & MID_REQUEST_SUBMITTED) {
  21837. + set_current_state(TASK_UNINTERRUPTIBLE);
  21838. + timeout = sleep_on_timeout(&ses->server->response_q,timeout);
  21839. + }
  21840. + }
  21841. +
  21842. + spin_lock(&GlobalMid_Lock);
  21843. + if (midQ->resp_buf) {
  21844. + spin_unlock(&GlobalMid_Lock);
  21845. + receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
  21846. + } else {
  21847. + cERROR(1,("No response buffer"));
  21848. + if(midQ->midState == MID_REQUEST_SUBMITTED) {
  21849. + if(ses->server->tcpStatus == CifsExiting)
  21850. + rc = -EHOSTDOWN;
  21851. + else {
  21852. + ses->server->tcpStatus = CifsNeedReconnect;
  21853. + midQ->midState = MID_RETRY_NEEDED;
  21854. + }
  21855. + }
  21856. +
  21857. + if (rc != -EHOSTDOWN) {
  21858. + if(midQ->midState == MID_RETRY_NEEDED) {
  21859. + rc = -EAGAIN;
  21860. + cFYI(1,("marking request for retry"));
  21861. + } else {
  21862. + rc = -EIO;
  21863. + }
  21864. + }
  21865. + spin_unlock(&GlobalMid_Lock);
  21866. + DeleteMidQEntry(midQ);
  21867. + /* If not lock req, update # of requests on wire to server */
  21868. + if(long_op < 3) {
  21869. + atomic_dec(&ses->server->inFlight);
  21870. + wake_up(&ses->server->request_q);
  21871. + }
  21872. + return rc;
  21873. + }
  21874. +
  21875. + if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
  21876. + cERROR(1,
  21877. + ("Frame too large received. Length: %d Xid: %d",
  21878. + receive_len, xid));
  21879. + rc = -EIO;
  21880. + } else { /* rcvd frame is ok */
  21881. +
  21882. + if (midQ->resp_buf && out_buf
  21883. + && (midQ->midState == MID_RESPONSE_RECEIVED)) {
  21884. + memcpy(out_buf, midQ->resp_buf,
  21885. + receive_len +
  21886. + 4 /* include 4 byte RFC1001 header */ );
  21887. +
  21888. + dump_smb(out_buf, 92);
  21889. + /* convert the length into a more usable form */
  21890. + out_buf->smb_buf_length =
  21891. + be32_to_cpu(out_buf->smb_buf_length);
  21892. + if((out_buf->smb_buf_length > 24) &&
  21893. + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
  21894. + rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
  21895. + if(rc)
  21896. + cFYI(1,("Unexpected signature received from server"));
  21897. + }
  21898. +
  21899. + if (out_buf->smb_buf_length > 12)
  21900. + out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
  21901. + if (out_buf->smb_buf_length > 28)
  21902. + out_buf->Pid = le16_to_cpu(out_buf->Pid);
  21903. + if (out_buf->smb_buf_length > 28)
  21904. + out_buf->PidHigh =
  21905. + le16_to_cpu(out_buf->PidHigh);
  21906. +
  21907. + *pbytes_returned = out_buf->smb_buf_length;
  21908. +
  21909. + /* BB special case reconnect tid and reconnect uid here? */
  21910. + rc = map_smb_to_linux_error(out_buf);
  21911. +
  21912. + /* convert ByteCount if necessary */
  21913. + if (receive_len >=
  21914. + sizeof (struct smb_hdr) -
  21915. + 4 /* do not count RFC1001 header */ +
  21916. + (2 * out_buf->WordCount) + 2 /* bcc */ )
  21917. + BCC(out_buf) = le16_to_cpu(BCC(out_buf));
  21918. + } else {
  21919. + rc = -EIO;
  21920. + cFYI(1,("Bad MID state? "));
  21921. + }
  21922. + }
  21923. +cifs_no_response_exit:
  21924. + DeleteMidQEntry(midQ);
  21925. +
  21926. + if(long_op < 3) {
  21927. + atomic_dec(&ses->server->inFlight);
  21928. + wake_up(&ses->server->request_q);
  21929. + }
  21930. +
  21931. + return rc;
  21932. +
  21933. +out_unlock:
  21934. + up(&ses->server->tcpSem);
  21935. + /* If not lock req, update # of requests on wire to server */
  21936. + if(long_op < 3) {
  21937. + atomic_dec(&ses->server->inFlight);
  21938. + wake_up(&ses->server->request_q);
  21939. + }
  21940. +
  21941. + return rc;
  21942. +}
  21943. --- a/fs/Config.in
  21944. +++ b/fs/Config.in
  21945. @@ -153,6 +153,10 @@ if [ "$CONFIG_NET" = "y" ]; then
  21946. define_bool CONFIG_LOCKD_V4 y
  21947. fi
  21948. + dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
  21949. + dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
  21950. + dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
  21951. +
  21952. dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
  21953. if [ "$CONFIG_SMB_FS" != "n" ]; then
  21954. bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
  21955. --- a/fs/Makefile
  21956. +++ b/fs/Makefile
  21957. @@ -37,6 +37,7 @@ subdir-$(CONFIG_MSDOS_FS) += msdos
  21958. subdir-$(CONFIG_VFAT_FS) += vfat
  21959. subdir-$(CONFIG_BFS_FS) += bfs
  21960. subdir-$(CONFIG_ISO9660_FS) += isofs
  21961. +subdir-$(CONFIG_CIFS) += cifs
  21962. subdir-$(CONFIG_DEVFS_FS) += devfs
  21963. subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+
  21964. subdir-$(CONFIG_HFS_FS) += hfs
  21965. --- a/fs/nls/Config.in
  21966. +++ b/fs/nls/Config.in
  21967. @@ -11,6 +11,7 @@ fi
  21968. # msdos and Joliet want NLS
  21969. if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
  21970. + -o "$CONFIG_CIFS" != "n" \
  21971. -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
  21972. -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
  21973. -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then