cifssmb.c 131 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281
  1. /*
  2. * fs/cifs/cifssmb.c
  3. *
  4. * Copyright (C) International Business Machines Corp., 2002,2005
  5. * Author(s): Steve French (sfrench@us.ibm.com)
  6. *
  7. * Contains the routines for constructing the SMB PDUs themselves
  8. *
  9. * This library is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published
  11. * by the Free Software Foundation; either version 2.1 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  17. * the GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. */
  23. /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
  24. /* These are mostly routines that operate on a pathname, or on a tree id */
  25. /* (mounted volume), but there are eight handle based routines which must be */
  26. /* treated slightly different for reconnection purposes since we never want */
  27. /* to reuse a stale file handle and the caller knows the file handle */
  28. #include <linux/fs.h>
  29. #include <linux/kernel.h>
  30. #include <linux/vfs.h>
  31. #include <linux/posix_acl_xattr.h>
  32. #include <asm/uaccess.h>
  33. #include "cifspdu.h"
  34. #include "cifsglob.h"
  35. #include "cifsproto.h"
  36. #include "cifs_unicode.h"
  37. #include "cifs_debug.h"
  38. #ifdef CONFIG_CIFS_POSIX
  39. static struct {
  40. int index;
  41. char *name;
  42. } protocols[] = {
  43. {CIFS_PROT, "\2NT LM 0.12"},
  44. {CIFS_PROT, "\2POSIX 2"},
  45. {BAD_PROT, "\2"}
  46. };
  47. #else
  48. static struct {
  49. int index;
  50. char *name;
  51. } protocols[] = {
  52. {CIFS_PROT, "\2NT LM 0.12"},
  53. {BAD_PROT, "\2"}
  54. };
  55. #endif
  56. /* Mark as invalid, all open files on tree connections since they
  57. were closed when session to server was lost */
  58. static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
  59. {
  60. struct cifsFileInfo *open_file = NULL;
  61. struct list_head * tmp;
  62. struct list_head * tmp1;
  63. /* list all files open on tree connection and mark them invalid */
  64. write_lock(&GlobalSMBSeslock);
  65. list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
  66. open_file = list_entry(tmp,struct cifsFileInfo, tlist);
  67. if(open_file) {
  68. open_file->invalidHandle = TRUE;
  69. }
  70. }
  71. write_unlock(&GlobalSMBSeslock);
  72. /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
  73. to this tcon */
  74. }
  75. /* If the return code is zero, this function must fill in request_buf pointer */
  76. static int
  77. small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
  78. void **request_buf /* returned */)
  79. {
  80. int rc = 0;
  81. /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
  82. check for tcp and smb session status done differently
  83. for those three - in the calling routine */
  84. if(tcon) {
  85. if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
  86. (tcon->ses->server)){
  87. struct nls_table *nls_codepage;
  88. /* Give Demultiplex thread up to 10 seconds to
  89. reconnect, should be greater than cifs socket
  90. timeout which is 7 seconds */
  91. while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
  92. wait_event_interruptible_timeout(tcon->ses->server->response_q,
  93. (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
  94. if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
  95. /* on "soft" mounts we wait once */
  96. if((tcon->retry == FALSE) ||
  97. (tcon->ses->status == CifsExiting)) {
  98. cFYI(1,("gave up waiting on reconnect in smb_init"));
  99. return -EHOSTDOWN;
  100. } /* else "hard" mount - keep retrying
  101. until process is killed or server
  102. comes back on-line */
  103. } else /* TCP session is reestablished now */
  104. break;
  105. }
  106. nls_codepage = load_nls_default();
  107. /* need to prevent multiple threads trying to
  108. simultaneously reconnect the same SMB session */
  109. down(&tcon->ses->sesSem);
  110. if(tcon->ses->status == CifsNeedReconnect)
  111. rc = cifs_setup_session(0, tcon->ses,
  112. nls_codepage);
  113. if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
  114. mark_open_files_invalid(tcon);
  115. rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
  116. , nls_codepage);
  117. up(&tcon->ses->sesSem);
  118. if(rc == 0)
  119. atomic_inc(&tconInfoReconnectCount);
  120. cFYI(1, ("reconnect tcon rc = %d", rc));
  121. /* Removed call to reopen open files here -
  122. it is safer (and faster) to reopen files
  123. one at a time as needed in read and write */
  124. /* Check if handle based operation so we
  125. know whether we can continue or not without
  126. returning to caller to reset file handle */
  127. switch(smb_command) {
  128. case SMB_COM_READ_ANDX:
  129. case SMB_COM_WRITE_ANDX:
  130. case SMB_COM_CLOSE:
  131. case SMB_COM_FIND_CLOSE2:
  132. case SMB_COM_LOCKING_ANDX: {
  133. unload_nls(nls_codepage);
  134. return -EAGAIN;
  135. }
  136. }
  137. } else {
  138. up(&tcon->ses->sesSem);
  139. }
  140. unload_nls(nls_codepage);
  141. } else {
  142. return -EIO;
  143. }
  144. }
  145. if(rc)
  146. return rc;
  147. *request_buf = cifs_small_buf_get();
  148. if (*request_buf == NULL) {
  149. /* BB should we add a retry in here if not a writepage? */
  150. return -ENOMEM;
  151. }
  152. header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
  153. #ifdef CONFIG_CIFS_STATS
  154. if(tcon != NULL) {
  155. atomic_inc(&tcon->num_smbs_sent);
  156. }
  157. #endif /* CONFIG_CIFS_STATS */
  158. return rc;
  159. }
  160. /* If the return code is zero, this function must fill in request_buf pointer */
  161. static int
  162. smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
  163. void **request_buf /* returned */ ,
  164. void **response_buf /* returned */ )
  165. {
  166. int rc = 0;
  167. /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
  168. check for tcp and smb session status done differently
  169. for those three - in the calling routine */
  170. if(tcon) {
  171. if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
  172. (tcon->ses->server)){
  173. struct nls_table *nls_codepage;
  174. /* Give Demultiplex thread up to 10 seconds to
  175. reconnect, should be greater than cifs socket
  176. timeout which is 7 seconds */
  177. while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
  178. wait_event_interruptible_timeout(tcon->ses->server->response_q,
  179. (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
  180. if(tcon->ses->server->tcpStatus ==
  181. CifsNeedReconnect) {
  182. /* on "soft" mounts we wait once */
  183. if((tcon->retry == FALSE) ||
  184. (tcon->ses->status == CifsExiting)) {
  185. cFYI(1,("gave up waiting on reconnect in smb_init"));
  186. return -EHOSTDOWN;
  187. } /* else "hard" mount - keep retrying
  188. until process is killed or server
  189. comes on-line */
  190. } else /* TCP session is reestablished now */
  191. break;
  192. }
  193. nls_codepage = load_nls_default();
  194. /* need to prevent multiple threads trying to
  195. simultaneously reconnect the same SMB session */
  196. down(&tcon->ses->sesSem);
  197. if(tcon->ses->status == CifsNeedReconnect)
  198. rc = cifs_setup_session(0, tcon->ses,
  199. nls_codepage);
  200. if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
  201. mark_open_files_invalid(tcon);
  202. rc = CIFSTCon(0, tcon->ses, tcon->treeName,
  203. tcon, nls_codepage);
  204. up(&tcon->ses->sesSem);
  205. if(rc == 0)
  206. atomic_inc(&tconInfoReconnectCount);
  207. cFYI(1, ("reconnect tcon rc = %d", rc));
  208. /* Removed call to reopen open files here -
  209. it is safer (and faster) to reopen files
  210. one at a time as needed in read and write */
  211. /* Check if handle based operation so we
  212. know whether we can continue or not without
  213. returning to caller to reset file handle */
  214. switch(smb_command) {
  215. case SMB_COM_READ_ANDX:
  216. case SMB_COM_WRITE_ANDX:
  217. case SMB_COM_CLOSE:
  218. case SMB_COM_FIND_CLOSE2:
  219. case SMB_COM_LOCKING_ANDX: {
  220. unload_nls(nls_codepage);
  221. return -EAGAIN;
  222. }
  223. }
  224. } else {
  225. up(&tcon->ses->sesSem);
  226. }
  227. unload_nls(nls_codepage);
  228. } else {
  229. return -EIO;
  230. }
  231. }
  232. if(rc)
  233. return rc;
  234. *request_buf = cifs_buf_get();
  235. if (*request_buf == NULL) {
  236. /* BB should we add a retry in here if not a writepage? */
  237. return -ENOMEM;
  238. }
  239. /* Although the original thought was we needed the response buf for */
  240. /* potential retries of smb operations it turns out we can determine */
  241. /* from the mid flags when the request buffer can be resent without */
  242. /* having to use a second distinct buffer for the response */
  243. *response_buf = *request_buf;
  244. header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
  245. wct /*wct */ );
  246. #ifdef CONFIG_CIFS_STATS
  247. if(tcon != NULL) {
  248. atomic_inc(&tcon->num_smbs_sent);
  249. }
  250. #endif /* CONFIG_CIFS_STATS */
  251. return rc;
  252. }
  253. static int validate_t2(struct smb_t2_rsp * pSMB)
  254. {
  255. int rc = -EINVAL;
  256. int total_size;
  257. char * pBCC;
  258. /* check for plausible wct, bcc and t2 data and parm sizes */
  259. /* check for parm and data offset going beyond end of smb */
  260. if(pSMB->hdr.WordCount >= 10) {
  261. if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
  262. (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
  263. /* check that bcc is at least as big as parms + data */
  264. /* check that bcc is less than negotiated smb buffer */
  265. total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
  266. if(total_size < 512) {
  267. total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
  268. /* BCC le converted in SendReceive */
  269. pBCC = (pSMB->hdr.WordCount * 2) +
  270. sizeof(struct smb_hdr) +
  271. (char *)pSMB;
  272. if((total_size <= (*(u16 *)pBCC)) &&
  273. (total_size <
  274. CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
  275. return 0;
  276. }
  277. }
  278. }
  279. }
  280. cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
  281. sizeof(struct smb_t2_rsp) + 16);
  282. return rc;
  283. }
  284. int
  285. CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
  286. {
  287. NEGOTIATE_REQ *pSMB;
  288. NEGOTIATE_RSP *pSMBr;
  289. int rc = 0;
  290. int bytes_returned;
  291. struct TCP_Server_Info * server;
  292. u16 count;
  293. if(ses->server)
  294. server = ses->server;
  295. else {
  296. rc = -EIO;
  297. return rc;
  298. }
  299. rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
  300. (void **) &pSMB, (void **) &pSMBr);
  301. if (rc)
  302. return rc;
  303. pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  304. if (extended_security)
  305. pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
  306. count = strlen(protocols[0].name) + 1;
  307. strncpy(pSMB->DialectsArray, protocols[0].name, 30);
  308. /* null guaranteed to be at end of source and target buffers anyway */
  309. pSMB->hdr.smb_buf_length += count;
  310. pSMB->ByteCount = cpu_to_le16(count);
  311. rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  312. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  313. if (rc == 0) {
  314. server->secMode = pSMBr->SecurityMode;
  315. server->secType = NTLM; /* BB override default for
  316. NTLMv2 or kerberos v5 */
  317. /* one byte - no need to convert this or EncryptionKeyLen
  318. from little endian */
  319. server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
  320. /* probably no need to store and check maxvcs */
  321. server->maxBuf =
  322. min(le32_to_cpu(pSMBr->MaxBufferSize),
  323. (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
  324. server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
  325. cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
  326. GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
  327. server->capabilities = le32_to_cpu(pSMBr->Capabilities);
  328. server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
  329. /* BB with UTC do we ever need to be using srvr timezone? */
  330. if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
  331. memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
  332. CIFS_CRYPTO_KEY_SIZE);
  333. } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
  334. && (pSMBr->EncryptionKeyLength == 0)) {
  335. /* decode security blob */
  336. } else
  337. rc = -EIO;
  338. /* BB might be helpful to save off the domain of server here */
  339. if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
  340. (server->capabilities & CAP_EXTENDED_SECURITY)) {
  341. count = pSMBr->ByteCount;
  342. if (count < 16)
  343. rc = -EIO;
  344. else if (count == 16) {
  345. server->secType = RawNTLMSSP;
  346. if (server->socketUseCount.counter > 1) {
  347. if (memcmp
  348. (server->server_GUID,
  349. pSMBr->u.extended_response.
  350. GUID, 16) != 0) {
  351. cFYI(1,
  352. ("UID of server does not match previous connection to same ip address"));
  353. memcpy(server->
  354. server_GUID,
  355. pSMBr->u.
  356. extended_response.
  357. GUID, 16);
  358. }
  359. } else
  360. memcpy(server->server_GUID,
  361. pSMBr->u.extended_response.
  362. GUID, 16);
  363. } else {
  364. rc = decode_negTokenInit(pSMBr->u.
  365. extended_response.
  366. SecurityBlob,
  367. count - 16,
  368. &server->secType);
  369. if(rc == 1) {
  370. /* BB Need to fill struct for sessetup here */
  371. rc = -EOPNOTSUPP;
  372. } else {
  373. rc = -EINVAL;
  374. }
  375. }
  376. } else
  377. server->capabilities &= ~CAP_EXTENDED_SECURITY;
  378. if(sign_CIFS_PDUs == FALSE) {
  379. if(server->secMode & SECMODE_SIGN_REQUIRED)
  380. cERROR(1,
  381. ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
  382. server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
  383. } else if(sign_CIFS_PDUs == 1) {
  384. if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
  385. server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
  386. }
  387. }
  388. if (pSMB)
  389. cifs_buf_release(pSMB);
  390. return rc;
  391. }
  392. int
  393. CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
  394. {
  395. struct smb_hdr *smb_buffer;
  396. struct smb_hdr *smb_buffer_response; /* BB removeme BB */
  397. int rc = 0;
  398. int length;
  399. cFYI(1, ("In tree disconnect"));
  400. /*
  401. * If last user of the connection and
  402. * connection alive - disconnect it
  403. * If this is the last connection on the server session disconnect it
  404. * (and inside session disconnect we should check if tcp socket needs
  405. * to be freed and kernel thread woken up).
  406. */
  407. if (tcon)
  408. down(&tcon->tconSem);
  409. else
  410. return -EIO;
  411. atomic_dec(&tcon->useCount);
  412. if (atomic_read(&tcon->useCount) > 0) {
  413. up(&tcon->tconSem);
  414. return -EBUSY;
  415. }
  416. /* No need to return error on this operation if tid invalidated and
  417. closed on server already e.g. due to tcp session crashing */
  418. if(tcon->tidStatus == CifsNeedReconnect) {
  419. up(&tcon->tconSem);
  420. return 0;
  421. }
  422. if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
  423. up(&tcon->tconSem);
  424. return -EIO;
  425. }
  426. rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
  427. (void **)&smb_buffer);
  428. if (rc) {
  429. up(&tcon->tconSem);
  430. return rc;
  431. } else {
  432. smb_buffer_response = smb_buffer; /* BB removeme BB */
  433. }
  434. rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
  435. &length, 0);
  436. if (rc)
  437. cFYI(1, ("Tree disconnect failed %d", rc));
  438. if (smb_buffer)
  439. cifs_small_buf_release(smb_buffer);
  440. up(&tcon->tconSem);
  441. /* No need to return error on this operation if tid invalidated and
  442. closed on server already e.g. due to tcp session crashing */
  443. if (rc == -EAGAIN)
  444. rc = 0;
  445. return rc;
  446. }
  447. int
  448. CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
  449. {
  450. struct smb_hdr *smb_buffer_response;
  451. LOGOFF_ANDX_REQ *pSMB;
  452. int rc = 0;
  453. int length;
  454. cFYI(1, ("In SMBLogoff for session disconnect"));
  455. if (ses)
  456. down(&ses->sesSem);
  457. else
  458. return -EIO;
  459. atomic_dec(&ses->inUse);
  460. if (atomic_read(&ses->inUse) > 0) {
  461. up(&ses->sesSem);
  462. return -EBUSY;
  463. }
  464. rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
  465. if (rc) {
  466. up(&ses->sesSem);
  467. return rc;
  468. }
  469. smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
  470. if(ses->server) {
  471. if(ses->server->secMode &
  472. (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
  473. pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  474. }
  475. pSMB->hdr.Uid = ses->Suid;
  476. pSMB->AndXCommand = 0xFF;
  477. rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  478. smb_buffer_response, &length, 0);
  479. if (ses->server) {
  480. atomic_dec(&ses->server->socketUseCount);
  481. if (atomic_read(&ses->server->socketUseCount) == 0) {
  482. spin_lock(&GlobalMid_Lock);
  483. ses->server->tcpStatus = CifsExiting;
  484. spin_unlock(&GlobalMid_Lock);
  485. rc = -ESHUTDOWN;
  486. }
  487. }
  488. if (pSMB)
  489. cifs_small_buf_release(pSMB);
  490. up(&ses->sesSem);
  491. /* if session dead then we do not need to do ulogoff,
  492. since server closed smb session, no sense reporting
  493. error */
  494. if (rc == -EAGAIN)
  495. rc = 0;
  496. return rc;
  497. }
  498. int
  499. CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
  500. const struct nls_table *nls_codepage, int remap)
  501. {
  502. DELETE_FILE_REQ *pSMB = NULL;
  503. DELETE_FILE_RSP *pSMBr = NULL;
  504. int rc = 0;
  505. int bytes_returned;
  506. int name_len;
  507. DelFileRetry:
  508. rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
  509. (void **) &pSMBr);
  510. if (rc)
  511. return rc;
  512. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  513. name_len =
  514. cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
  515. PATH_MAX, nls_codepage, remap);
  516. name_len++; /* trailing null */
  517. name_len *= 2;
  518. } else { /* BB improve check for buffer overruns BB */
  519. name_len = strnlen(fileName, PATH_MAX);
  520. name_len++; /* trailing null */
  521. strncpy(pSMB->fileName, fileName, name_len);
  522. }
  523. pSMB->SearchAttributes =
  524. cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
  525. pSMB->BufferFormat = 0x04;
  526. pSMB->hdr.smb_buf_length += name_len + 1;
  527. pSMB->ByteCount = cpu_to_le16(name_len + 1);
  528. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  529. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  530. if (rc) {
  531. cFYI(1, ("Error in RMFile = %d", rc));
  532. }
  533. #ifdef CONFIG_CIFS_STATS
  534. else {
  535. atomic_inc(&tcon->num_deletes);
  536. }
  537. #endif
  538. cifs_buf_release(pSMB);
  539. if (rc == -EAGAIN)
  540. goto DelFileRetry;
  541. return rc;
  542. }
  543. int
  544. CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
  545. const struct nls_table *nls_codepage, int remap)
  546. {
  547. DELETE_DIRECTORY_REQ *pSMB = NULL;
  548. DELETE_DIRECTORY_RSP *pSMBr = NULL;
  549. int rc = 0;
  550. int bytes_returned;
  551. int name_len;
  552. cFYI(1, ("In CIFSSMBRmDir"));
  553. RmDirRetry:
  554. rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
  555. (void **) &pSMBr);
  556. if (rc)
  557. return rc;
  558. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  559. name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
  560. PATH_MAX, nls_codepage, remap);
  561. name_len++; /* trailing null */
  562. name_len *= 2;
  563. } else { /* BB improve check for buffer overruns BB */
  564. name_len = strnlen(dirName, PATH_MAX);
  565. name_len++; /* trailing null */
  566. strncpy(pSMB->DirName, dirName, name_len);
  567. }
  568. pSMB->BufferFormat = 0x04;
  569. pSMB->hdr.smb_buf_length += name_len + 1;
  570. pSMB->ByteCount = cpu_to_le16(name_len + 1);
  571. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  572. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  573. if (rc) {
  574. cFYI(1, ("Error in RMDir = %d", rc));
  575. }
  576. #ifdef CONFIG_CIFS_STATS
  577. else {
  578. atomic_inc(&tcon->num_rmdirs);
  579. }
  580. #endif
  581. cifs_buf_release(pSMB);
  582. if (rc == -EAGAIN)
  583. goto RmDirRetry;
  584. return rc;
  585. }
  586. int
  587. CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
  588. const char *name, const struct nls_table *nls_codepage, int remap)
  589. {
  590. int rc = 0;
  591. CREATE_DIRECTORY_REQ *pSMB = NULL;
  592. CREATE_DIRECTORY_RSP *pSMBr = NULL;
  593. int bytes_returned;
  594. int name_len;
  595. cFYI(1, ("In CIFSSMBMkDir"));
  596. MkDirRetry:
  597. rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
  598. (void **) &pSMBr);
  599. if (rc)
  600. return rc;
  601. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  602. name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
  603. PATH_MAX, nls_codepage, remap);
  604. name_len++; /* trailing null */
  605. name_len *= 2;
  606. } else { /* BB improve check for buffer overruns BB */
  607. name_len = strnlen(name, PATH_MAX);
  608. name_len++; /* trailing null */
  609. strncpy(pSMB->DirName, name, name_len);
  610. }
  611. pSMB->BufferFormat = 0x04;
  612. pSMB->hdr.smb_buf_length += name_len + 1;
  613. pSMB->ByteCount = cpu_to_le16(name_len + 1);
  614. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  615. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  616. if (rc) {
  617. cFYI(1, ("Error in Mkdir = %d", rc));
  618. }
  619. #ifdef CONFIG_CIFS_STATS
  620. else {
  621. atomic_inc(&tcon->num_mkdirs);
  622. }
  623. #endif
  624. cifs_buf_release(pSMB);
  625. if (rc == -EAGAIN)
  626. goto MkDirRetry;
  627. return rc;
  628. }
  629. int
  630. CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
  631. const char *fileName, const int openDisposition,
  632. const int access_flags, const int create_options, __u16 * netfid,
  633. int *pOplock, FILE_ALL_INFO * pfile_info,
  634. const struct nls_table *nls_codepage, int remap)
  635. {
  636. int rc = -EACCES;
  637. OPEN_REQ *pSMB = NULL;
  638. OPEN_RSP *pSMBr = NULL;
  639. int bytes_returned;
  640. int name_len;
  641. __u16 count;
  642. openRetry:
  643. rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
  644. (void **) &pSMBr);
  645. if (rc)
  646. return rc;
  647. pSMB->AndXCommand = 0xFF; /* none */
  648. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  649. count = 1; /* account for one byte pad to word boundary */
  650. name_len =
  651. cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
  652. fileName, PATH_MAX, nls_codepage, remap);
  653. name_len++; /* trailing null */
  654. name_len *= 2;
  655. pSMB->NameLength = cpu_to_le16(name_len);
  656. } else { /* BB improve check for buffer overruns BB */
  657. count = 0; /* no pad */
  658. name_len = strnlen(fileName, PATH_MAX);
  659. name_len++; /* trailing null */
  660. pSMB->NameLength = cpu_to_le16(name_len);
  661. strncpy(pSMB->fileName, fileName, name_len);
  662. }
  663. if (*pOplock & REQ_OPLOCK)
  664. pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
  665. else if (*pOplock & REQ_BATCHOPLOCK) {
  666. pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
  667. }
  668. pSMB->DesiredAccess = cpu_to_le32(access_flags);
  669. pSMB->AllocationSize = 0;
  670. pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
  671. /* XP does not handle ATTR_POSIX_SEMANTICS */
  672. /* but it helps speed up case sensitive checks for other
  673. servers such as Samba */
  674. if (tcon->ses->capabilities & CAP_UNIX)
  675. pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
  676. /* if ((omode & S_IWUGO) == 0)
  677. pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
  678. /* Above line causes problems due to vfs splitting create into two
  679. pieces - need to set mode after file created not while it is
  680. being created */
  681. pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
  682. pSMB->CreateDisposition = cpu_to_le32(openDisposition);
  683. pSMB->CreateOptions = cpu_to_le32(create_options);
  684. /* BB Expirement with various impersonation levels and verify */
  685. pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
  686. pSMB->SecurityFlags =
  687. SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
  688. count += name_len;
  689. pSMB->hdr.smb_buf_length += count;
  690. pSMB->ByteCount = cpu_to_le16(count);
  691. /* long_op set to 1 to allow for oplock break timeouts */
  692. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  693. (struct smb_hdr *) pSMBr, &bytes_returned, 1);
  694. if (rc) {
  695. cFYI(1, ("Error in Open = %d", rc));
  696. } else {
  697. *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
  698. *netfid = pSMBr->Fid; /* cifs fid stays in le */
  699. /* Let caller know file was created so we can set the mode. */
  700. /* Do we care about the CreateAction in any other cases? */
  701. if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
  702. *pOplock |= CIFS_CREATE_ACTION;
  703. if(pfile_info) {
  704. memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
  705. 36 /* CreationTime to Attributes */);
  706. /* the file_info buf is endian converted by caller */
  707. pfile_info->AllocationSize = pSMBr->AllocationSize;
  708. pfile_info->EndOfFile = pSMBr->EndOfFile;
  709. pfile_info->NumberOfLinks = cpu_to_le32(1);
  710. }
  711. #ifdef CONFIG_CIFS_STATS
  712. atomic_inc(&tcon->num_opens);
  713. #endif
  714. }
  715. cifs_buf_release(pSMB);
  716. if (rc == -EAGAIN)
  717. goto openRetry;
  718. return rc;
  719. }
  720. /* If no buffer passed in, then caller wants to do the copy
  721. as in the case of readpages so the SMB buffer must be
  722. freed by the caller */
  723. int
  724. CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
  725. const int netfid, const unsigned int count,
  726. const __u64 lseek, unsigned int *nbytes, char **buf)
  727. {
  728. int rc = -EACCES;
  729. READ_REQ *pSMB = NULL;
  730. READ_RSP *pSMBr = NULL;
  731. char *pReadData = NULL;
  732. int bytes_returned;
  733. cFYI(1,("Reading %d bytes on fid %d",count,netfid));
  734. *nbytes = 0;
  735. rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
  736. (void **) &pSMBr);
  737. if (rc)
  738. return rc;
  739. /* tcon and ses pointer are checked in smb_init */
  740. if (tcon->ses->server == NULL)
  741. return -ECONNABORTED;
  742. pSMB->AndXCommand = 0xFF; /* none */
  743. pSMB->Fid = netfid;
  744. pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
  745. pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
  746. pSMB->Remaining = 0;
  747. pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
  748. pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
  749. pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
  750. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  751. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  752. if (rc) {
  753. cERROR(1, ("Send error in read = %d", rc));
  754. } else {
  755. int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
  756. data_length = data_length << 16;
  757. data_length += le16_to_cpu(pSMBr->DataLength);
  758. *nbytes = data_length;
  759. /*check that DataLength would not go beyond end of SMB */
  760. if ((data_length > CIFSMaxBufSize)
  761. || (data_length > count)) {
  762. cFYI(1,("bad length %d for count %d",data_length,count));
  763. rc = -EIO;
  764. *nbytes = 0;
  765. } else {
  766. pReadData =
  767. (char *) (&pSMBr->hdr.Protocol) +
  768. le16_to_cpu(pSMBr->DataOffset);
  769. /* if(rc = copy_to_user(buf, pReadData, data_length)) {
  770. cERROR(1,("Faulting on read rc = %d",rc));
  771. rc = -EFAULT;
  772. }*/ /* can not use copy_to_user when using page cache*/
  773. if(*buf)
  774. memcpy(*buf,pReadData,data_length);
  775. }
  776. }
  777. if(*buf)
  778. cifs_buf_release(pSMB);
  779. else
  780. *buf = (char *)pSMB;
  781. /* Note: On -EAGAIN error only caller can retry on handle based calls
  782. since file handle passed in no longer valid */
  783. return rc;
  784. }
  785. int
  786. CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
  787. const int netfid, const unsigned int count,
  788. const __u64 offset, unsigned int *nbytes, const char *buf,
  789. const char __user * ubuf, const int long_op)
  790. {
  791. int rc = -EACCES;
  792. WRITE_REQ *pSMB = NULL;
  793. WRITE_RSP *pSMBr = NULL;
  794. int bytes_returned;
  795. __u32 bytes_sent;
  796. __u16 byte_count;
  797. /* cFYI(1,("write at %lld %d bytes",offset,count));*/
  798. rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
  799. (void **) &pSMBr);
  800. if (rc)
  801. return rc;
  802. /* tcon and ses pointer are checked in smb_init */
  803. if (tcon->ses->server == NULL)
  804. return -ECONNABORTED;
  805. pSMB->AndXCommand = 0xFF; /* none */
  806. pSMB->Fid = netfid;
  807. pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
  808. pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
  809. pSMB->Reserved = 0xFFFFFFFF;
  810. pSMB->WriteMode = 0;
  811. pSMB->Remaining = 0;
  812. /* Can increase buffer size if buffer is big enough in some cases - ie we
  813. can send more if LARGE_WRITE_X capability returned by the server and if
  814. our buffer is big enough or if we convert to iovecs on socket writes
  815. and eliminate the copy to the CIFS buffer */
  816. if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
  817. bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
  818. } else {
  819. bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
  820. & ~0xFF;
  821. }
  822. if (bytes_sent > count)
  823. bytes_sent = count;
  824. pSMB->DataOffset =
  825. cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
  826. if(buf)
  827. memcpy(pSMB->Data,buf,bytes_sent);
  828. else if(ubuf) {
  829. if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
  830. cifs_buf_release(pSMB);
  831. return -EFAULT;
  832. }
  833. } else {
  834. /* No buffer */
  835. cifs_buf_release(pSMB);
  836. return -EINVAL;
  837. }
  838. byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
  839. pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
  840. pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
  841. pSMB->hdr.smb_buf_length += bytes_sent+1;
  842. pSMB->ByteCount = cpu_to_le16(byte_count);
  843. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  844. (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
  845. if (rc) {
  846. cFYI(1, ("Send error in write = %d", rc));
  847. *nbytes = 0;
  848. } else {
  849. *nbytes = le16_to_cpu(pSMBr->CountHigh);
  850. *nbytes = (*nbytes) << 16;
  851. *nbytes += le16_to_cpu(pSMBr->Count);
  852. }
  853. cifs_buf_release(pSMB);
  854. /* Note: On -EAGAIN error only caller can retry on handle based calls
  855. since file handle passed in no longer valid */
  856. return rc;
  857. }
  858. #ifdef CONFIG_CIFS_EXPERIMENTAL
  859. int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
  860. const int netfid, const unsigned int count,
  861. const __u64 offset, unsigned int *nbytes, const char __user *buf,
  862. const int long_op)
  863. {
  864. int rc = -EACCES;
  865. WRITE_REQ *pSMB = NULL;
  866. WRITE_RSP *pSMBr = NULL;
  867. /*int bytes_returned;*/
  868. unsigned bytes_sent;
  869. __u16 byte_count;
  870. rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
  871. if (rc)
  872. return rc;
  873. pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
  874. /* tcon and ses pointer are checked in smb_init */
  875. if (tcon->ses->server == NULL)
  876. return -ECONNABORTED;
  877. pSMB->AndXCommand = 0xFF; /* none */
  878. pSMB->Fid = netfid;
  879. pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
  880. pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
  881. pSMB->Reserved = 0xFFFFFFFF;
  882. pSMB->WriteMode = 0;
  883. pSMB->Remaining = 0;
  884. bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
  885. if (bytes_sent > count)
  886. bytes_sent = count;
  887. pSMB->DataLengthHigh = 0;
  888. pSMB->DataOffset =
  889. cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
  890. byte_count = bytes_sent + 1 /* pad */ ;
  891. pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
  892. pSMB->DataLengthHigh = 0;
  893. pSMB->hdr.smb_buf_length += byte_count;
  894. pSMB->ByteCount = cpu_to_le16(byte_count);
  895. /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
  896. (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
  897. if (rc) {
  898. cFYI(1, ("Send error in write2 (large write) = %d", rc));
  899. *nbytes = 0;
  900. } else
  901. *nbytes = le16_to_cpu(pSMBr->Count);
  902. cifs_small_buf_release(pSMB);
  903. /* Note: On -EAGAIN error only caller can retry on handle based calls
  904. since file handle passed in no longer valid */
  905. return rc;
  906. }
  907. #endif /* CIFS_EXPERIMENTAL */
  908. int
  909. CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
  910. const __u16 smb_file_id, const __u64 len,
  911. const __u64 offset, const __u32 numUnlock,
  912. const __u32 numLock, const __u8 lockType, const int waitFlag)
  913. {
  914. int rc = 0;
  915. LOCK_REQ *pSMB = NULL;
  916. LOCK_RSP *pSMBr = NULL;
  917. int bytes_returned;
  918. int timeout = 0;
  919. __u16 count;
  920. cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
  921. rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
  922. if (rc)
  923. return rc;
  924. pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
  925. if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
  926. timeout = -1; /* no response expected */
  927. pSMB->Timeout = 0;
  928. } else if (waitFlag == TRUE) {
  929. timeout = 3; /* blocking operation, no timeout */
  930. pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
  931. } else {
  932. pSMB->Timeout = 0;
  933. }
  934. pSMB->NumberOfLocks = cpu_to_le16(numLock);
  935. pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
  936. pSMB->LockType = lockType;
  937. pSMB->AndXCommand = 0xFF; /* none */
  938. pSMB->Fid = smb_file_id; /* netfid stays le */
  939. if((numLock != 0) || (numUnlock != 0)) {
  940. pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
  941. /* BB where to store pid high? */
  942. pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
  943. pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
  944. pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
  945. pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
  946. count = sizeof(LOCKING_ANDX_RANGE);
  947. } else {
  948. /* oplock break */
  949. count = 0;
  950. }
  951. pSMB->hdr.smb_buf_length += count;
  952. pSMB->ByteCount = cpu_to_le16(count);
  953. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  954. (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
  955. if (rc) {
  956. cFYI(1, ("Send error in Lock = %d", rc));
  957. }
  958. cifs_small_buf_release(pSMB);
  959. /* Note: On -EAGAIN error only caller can retry on handle based calls
  960. since file handle passed in no longer valid */
  961. return rc;
  962. }
  963. int
  964. CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
  965. {
  966. int rc = 0;
  967. CLOSE_REQ *pSMB = NULL;
  968. CLOSE_RSP *pSMBr = NULL;
  969. int bytes_returned;
  970. cFYI(1, ("In CIFSSMBClose"));
  971. /* do not retry on dead session on close */
  972. rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
  973. if(rc == -EAGAIN)
  974. return 0;
  975. if (rc)
  976. return rc;
  977. pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
  978. pSMB->FileID = (__u16) smb_file_id;
  979. pSMB->LastWriteTime = 0;
  980. pSMB->ByteCount = 0;
  981. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  982. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  983. if (rc) {
  984. if(rc!=-EINTR) {
  985. /* EINTR is expected when user ctl-c to kill app */
  986. cERROR(1, ("Send error in Close = %d", rc));
  987. }
  988. }
  989. cifs_small_buf_release(pSMB);
  990. /* Since session is dead, file will be closed on server already */
  991. if(rc == -EAGAIN)
  992. rc = 0;
  993. return rc;
  994. }
  995. int
  996. CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
  997. const char *fromName, const char *toName,
  998. const struct nls_table *nls_codepage, int remap)
  999. {
  1000. int rc = 0;
  1001. RENAME_REQ *pSMB = NULL;
  1002. RENAME_RSP *pSMBr = NULL;
  1003. int bytes_returned;
  1004. int name_len, name_len2;
  1005. __u16 count;
  1006. cFYI(1, ("In CIFSSMBRename"));
  1007. renameRetry:
  1008. rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
  1009. (void **) &pSMBr);
  1010. if (rc)
  1011. return rc;
  1012. pSMB->BufferFormat = 0x04;
  1013. pSMB->SearchAttributes =
  1014. cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  1015. ATTR_DIRECTORY);
  1016. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1017. name_len =
  1018. cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
  1019. PATH_MAX, nls_codepage, remap);
  1020. name_len++; /* trailing null */
  1021. name_len *= 2;
  1022. pSMB->OldFileName[name_len] = 0x04; /* pad */
  1023. /* protocol requires ASCII signature byte on Unicode string */
  1024. pSMB->OldFileName[name_len + 1] = 0x00;
  1025. name_len2 =
  1026. cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
  1027. toName, PATH_MAX, nls_codepage, remap);
  1028. name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  1029. name_len2 *= 2; /* convert to bytes */
  1030. } else { /* BB improve the check for buffer overruns BB */
  1031. name_len = strnlen(fromName, PATH_MAX);
  1032. name_len++; /* trailing null */
  1033. strncpy(pSMB->OldFileName, fromName, name_len);
  1034. name_len2 = strnlen(toName, PATH_MAX);
  1035. name_len2++; /* trailing null */
  1036. pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  1037. strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  1038. name_len2++; /* trailing null */
  1039. name_len2++; /* signature byte */
  1040. }
  1041. count = 1 /* 1st signature byte */ + name_len + name_len2;
  1042. pSMB->hdr.smb_buf_length += count;
  1043. pSMB->ByteCount = cpu_to_le16(count);
  1044. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1045. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1046. if (rc) {
  1047. cFYI(1, ("Send error in rename = %d", rc));
  1048. }
  1049. #ifdef CONFIG_CIFS_STATS
  1050. else {
  1051. atomic_inc(&tcon->num_renames);
  1052. }
  1053. #endif
  1054. cifs_buf_release(pSMB);
  1055. if (rc == -EAGAIN)
  1056. goto renameRetry;
  1057. return rc;
  1058. }
  1059. int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
  1060. int netfid, char * target_name,
  1061. const struct nls_table * nls_codepage, int remap)
  1062. {
  1063. struct smb_com_transaction2_sfi_req *pSMB = NULL;
  1064. struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
  1065. struct set_file_rename * rename_info;
  1066. char *data_offset;
  1067. char dummy_string[30];
  1068. int rc = 0;
  1069. int bytes_returned = 0;
  1070. int len_of_str;
  1071. __u16 params, param_offset, offset, count, byte_count;
  1072. cFYI(1, ("Rename to File by handle"));
  1073. rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
  1074. (void **) &pSMBr);
  1075. if (rc)
  1076. return rc;
  1077. params = 6;
  1078. pSMB->MaxSetupCount = 0;
  1079. pSMB->Reserved = 0;
  1080. pSMB->Flags = 0;
  1081. pSMB->Timeout = 0;
  1082. pSMB->Reserved2 = 0;
  1083. param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  1084. offset = param_offset + params;
  1085. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  1086. rename_info = (struct set_file_rename *) data_offset;
  1087. pSMB->MaxParameterCount = cpu_to_le16(2);
  1088. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
  1089. pSMB->SetupCount = 1;
  1090. pSMB->Reserved3 = 0;
  1091. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  1092. byte_count = 3 /* pad */ + params;
  1093. pSMB->ParameterCount = cpu_to_le16(params);
  1094. pSMB->TotalParameterCount = pSMB->ParameterCount;
  1095. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  1096. pSMB->DataOffset = cpu_to_le16(offset);
  1097. /* construct random name ".cifs_tmp<inodenum><mid>" */
  1098. rename_info->overwrite = cpu_to_le32(1);
  1099. rename_info->root_fid = 0;
  1100. /* unicode only call */
  1101. if(target_name == NULL) {
  1102. sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
  1103. len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
  1104. dummy_string, 24, nls_codepage, remap);
  1105. } else {
  1106. len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
  1107. target_name, PATH_MAX, nls_codepage, remap);
  1108. }
  1109. rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
  1110. count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
  1111. byte_count += count;
  1112. pSMB->DataCount = cpu_to_le16(count);
  1113. pSMB->TotalDataCount = pSMB->DataCount;
  1114. pSMB->Fid = netfid;
  1115. pSMB->InformationLevel =
  1116. cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
  1117. pSMB->Reserved4 = 0;
  1118. pSMB->hdr.smb_buf_length += byte_count;
  1119. pSMB->ByteCount = cpu_to_le16(byte_count);
  1120. rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
  1121. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1122. if (rc) {
  1123. cFYI(1,("Send error in Rename (by file handle) = %d", rc));
  1124. }
  1125. #ifdef CONFIG_CIFS_STATS
  1126. else {
  1127. atomic_inc(&pTcon->num_t2renames);
  1128. }
  1129. #endif
  1130. cifs_buf_release(pSMB);
  1131. /* Note: On -EAGAIN error only caller can retry on handle based calls
  1132. since file handle passed in no longer valid */
  1133. return rc;
  1134. }
  1135. int
  1136. CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
  1137. const __u16 target_tid, const char *toName, const int flags,
  1138. const struct nls_table *nls_codepage, int remap)
  1139. {
  1140. int rc = 0;
  1141. COPY_REQ *pSMB = NULL;
  1142. COPY_RSP *pSMBr = NULL;
  1143. int bytes_returned;
  1144. int name_len, name_len2;
  1145. __u16 count;
  1146. cFYI(1, ("In CIFSSMBCopy"));
  1147. copyRetry:
  1148. rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
  1149. (void **) &pSMBr);
  1150. if (rc)
  1151. return rc;
  1152. pSMB->BufferFormat = 0x04;
  1153. pSMB->Tid2 = target_tid;
  1154. pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
  1155. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1156. name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
  1157. fromName, PATH_MAX, nls_codepage,
  1158. remap);
  1159. name_len++; /* trailing null */
  1160. name_len *= 2;
  1161. pSMB->OldFileName[name_len] = 0x04; /* pad */
  1162. /* protocol requires ASCII signature byte on Unicode string */
  1163. pSMB->OldFileName[name_len + 1] = 0x00;
  1164. name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
  1165. toName, PATH_MAX, nls_codepage, remap);
  1166. name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  1167. name_len2 *= 2; /* convert to bytes */
  1168. } else { /* BB improve the check for buffer overruns BB */
  1169. name_len = strnlen(fromName, PATH_MAX);
  1170. name_len++; /* trailing null */
  1171. strncpy(pSMB->OldFileName, fromName, name_len);
  1172. name_len2 = strnlen(toName, PATH_MAX);
  1173. name_len2++; /* trailing null */
  1174. pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  1175. strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  1176. name_len2++; /* trailing null */
  1177. name_len2++; /* signature byte */
  1178. }
  1179. count = 1 /* 1st signature byte */ + name_len + name_len2;
  1180. pSMB->hdr.smb_buf_length += count;
  1181. pSMB->ByteCount = cpu_to_le16(count);
  1182. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1183. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1184. if (rc) {
  1185. cFYI(1, ("Send error in copy = %d with %d files copied",
  1186. rc, le16_to_cpu(pSMBr->CopyCount)));
  1187. }
  1188. if (pSMB)
  1189. cifs_buf_release(pSMB);
  1190. if (rc == -EAGAIN)
  1191. goto copyRetry;
  1192. return rc;
  1193. }
  1194. int
  1195. CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
  1196. const char *fromName, const char *toName,
  1197. const struct nls_table *nls_codepage)
  1198. {
  1199. TRANSACTION2_SPI_REQ *pSMB = NULL;
  1200. TRANSACTION2_SPI_RSP *pSMBr = NULL;
  1201. char *data_offset;
  1202. int name_len;
  1203. int name_len_target;
  1204. int rc = 0;
  1205. int bytes_returned = 0;
  1206. __u16 params, param_offset, offset, byte_count;
  1207. cFYI(1, ("In Symlink Unix style"));
  1208. createSymLinkRetry:
  1209. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1210. (void **) &pSMBr);
  1211. if (rc)
  1212. return rc;
  1213. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1214. name_len =
  1215. cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
  1216. /* find define for this maxpathcomponent */
  1217. , nls_codepage);
  1218. name_len++; /* trailing null */
  1219. name_len *= 2;
  1220. } else { /* BB improve the check for buffer overruns BB */
  1221. name_len = strnlen(fromName, PATH_MAX);
  1222. name_len++; /* trailing null */
  1223. strncpy(pSMB->FileName, fromName, name_len);
  1224. }
  1225. params = 6 + name_len;
  1226. pSMB->MaxSetupCount = 0;
  1227. pSMB->Reserved = 0;
  1228. pSMB->Flags = 0;
  1229. pSMB->Timeout = 0;
  1230. pSMB->Reserved2 = 0;
  1231. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  1232. InformationLevel) - 4;
  1233. offset = param_offset + params;
  1234. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  1235. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1236. name_len_target =
  1237. cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
  1238. /* find define for this maxpathcomponent */
  1239. , nls_codepage);
  1240. name_len_target++; /* trailing null */
  1241. name_len_target *= 2;
  1242. } else { /* BB improve the check for buffer overruns BB */
  1243. name_len_target = strnlen(toName, PATH_MAX);
  1244. name_len_target++; /* trailing null */
  1245. strncpy(data_offset, toName, name_len_target);
  1246. }
  1247. pSMB->MaxParameterCount = cpu_to_le16(2);
  1248. /* BB find exact max on data count below from sess */
  1249. pSMB->MaxDataCount = cpu_to_le16(1000);
  1250. pSMB->SetupCount = 1;
  1251. pSMB->Reserved3 = 0;
  1252. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  1253. byte_count = 3 /* pad */ + params + name_len_target;
  1254. pSMB->DataCount = cpu_to_le16(name_len_target);
  1255. pSMB->ParameterCount = cpu_to_le16(params);
  1256. pSMB->TotalDataCount = pSMB->DataCount;
  1257. pSMB->TotalParameterCount = pSMB->ParameterCount;
  1258. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  1259. pSMB->DataOffset = cpu_to_le16(offset);
  1260. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
  1261. pSMB->Reserved4 = 0;
  1262. pSMB->hdr.smb_buf_length += byte_count;
  1263. pSMB->ByteCount = cpu_to_le16(byte_count);
  1264. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1265. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1266. if (rc) {
  1267. cFYI(1,
  1268. ("Send error in SetPathInfo (create symlink) = %d",
  1269. rc));
  1270. }
  1271. if (pSMB)
  1272. cifs_buf_release(pSMB);
  1273. if (rc == -EAGAIN)
  1274. goto createSymLinkRetry;
  1275. return rc;
  1276. }
  1277. int
  1278. CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
  1279. const char *fromName, const char *toName,
  1280. const struct nls_table *nls_codepage, int remap)
  1281. {
  1282. TRANSACTION2_SPI_REQ *pSMB = NULL;
  1283. TRANSACTION2_SPI_RSP *pSMBr = NULL;
  1284. char *data_offset;
  1285. int name_len;
  1286. int name_len_target;
  1287. int rc = 0;
  1288. int bytes_returned = 0;
  1289. __u16 params, param_offset, offset, byte_count;
  1290. cFYI(1, ("In Create Hard link Unix style"));
  1291. createHardLinkRetry:
  1292. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1293. (void **) &pSMBr);
  1294. if (rc)
  1295. return rc;
  1296. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1297. name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
  1298. PATH_MAX, nls_codepage, remap);
  1299. name_len++; /* trailing null */
  1300. name_len *= 2;
  1301. } else { /* BB improve the check for buffer overruns BB */
  1302. name_len = strnlen(toName, PATH_MAX);
  1303. name_len++; /* trailing null */
  1304. strncpy(pSMB->FileName, toName, name_len);
  1305. }
  1306. params = 6 + name_len;
  1307. pSMB->MaxSetupCount = 0;
  1308. pSMB->Reserved = 0;
  1309. pSMB->Flags = 0;
  1310. pSMB->Timeout = 0;
  1311. pSMB->Reserved2 = 0;
  1312. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  1313. InformationLevel) - 4;
  1314. offset = param_offset + params;
  1315. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  1316. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1317. name_len_target =
  1318. cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
  1319. nls_codepage, remap);
  1320. name_len_target++; /* trailing null */
  1321. name_len_target *= 2;
  1322. } else { /* BB improve the check for buffer overruns BB */
  1323. name_len_target = strnlen(fromName, PATH_MAX);
  1324. name_len_target++; /* trailing null */
  1325. strncpy(data_offset, fromName, name_len_target);
  1326. }
  1327. pSMB->MaxParameterCount = cpu_to_le16(2);
  1328. /* BB find exact max on data count below from sess*/
  1329. pSMB->MaxDataCount = cpu_to_le16(1000);
  1330. pSMB->SetupCount = 1;
  1331. pSMB->Reserved3 = 0;
  1332. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  1333. byte_count = 3 /* pad */ + params + name_len_target;
  1334. pSMB->ParameterCount = cpu_to_le16(params);
  1335. pSMB->TotalParameterCount = pSMB->ParameterCount;
  1336. pSMB->DataCount = cpu_to_le16(name_len_target);
  1337. pSMB->TotalDataCount = pSMB->DataCount;
  1338. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  1339. pSMB->DataOffset = cpu_to_le16(offset);
  1340. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
  1341. pSMB->Reserved4 = 0;
  1342. pSMB->hdr.smb_buf_length += byte_count;
  1343. pSMB->ByteCount = cpu_to_le16(byte_count);
  1344. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1345. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1346. if (rc) {
  1347. cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
  1348. }
  1349. cifs_buf_release(pSMB);
  1350. if (rc == -EAGAIN)
  1351. goto createHardLinkRetry;
  1352. return rc;
  1353. }
  1354. int
  1355. CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
  1356. const char *fromName, const char *toName,
  1357. const struct nls_table *nls_codepage, int remap)
  1358. {
  1359. int rc = 0;
  1360. NT_RENAME_REQ *pSMB = NULL;
  1361. RENAME_RSP *pSMBr = NULL;
  1362. int bytes_returned;
  1363. int name_len, name_len2;
  1364. __u16 count;
  1365. cFYI(1, ("In CIFSCreateHardLink"));
  1366. winCreateHardLinkRetry:
  1367. rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
  1368. (void **) &pSMBr);
  1369. if (rc)
  1370. return rc;
  1371. pSMB->SearchAttributes =
  1372. cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  1373. ATTR_DIRECTORY);
  1374. pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
  1375. pSMB->ClusterCount = 0;
  1376. pSMB->BufferFormat = 0x04;
  1377. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1378. name_len =
  1379. cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
  1380. PATH_MAX, nls_codepage, remap);
  1381. name_len++; /* trailing null */
  1382. name_len *= 2;
  1383. pSMB->OldFileName[name_len] = 0; /* pad */
  1384. pSMB->OldFileName[name_len + 1] = 0x04;
  1385. name_len2 =
  1386. cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
  1387. toName, PATH_MAX, nls_codepage, remap);
  1388. name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
  1389. name_len2 *= 2; /* convert to bytes */
  1390. } else { /* BB improve the check for buffer overruns BB */
  1391. name_len = strnlen(fromName, PATH_MAX);
  1392. name_len++; /* trailing null */
  1393. strncpy(pSMB->OldFileName, fromName, name_len);
  1394. name_len2 = strnlen(toName, PATH_MAX);
  1395. name_len2++; /* trailing null */
  1396. pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
  1397. strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
  1398. name_len2++; /* trailing null */
  1399. name_len2++; /* signature byte */
  1400. }
  1401. count = 1 /* string type byte */ + name_len + name_len2;
  1402. pSMB->hdr.smb_buf_length += count;
  1403. pSMB->ByteCount = cpu_to_le16(count);
  1404. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1405. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1406. if (rc) {
  1407. cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
  1408. }
  1409. cifs_buf_release(pSMB);
  1410. if (rc == -EAGAIN)
  1411. goto winCreateHardLinkRetry;
  1412. return rc;
  1413. }
  1414. int
  1415. CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
  1416. const unsigned char *searchName,
  1417. char *symlinkinfo, const int buflen,
  1418. const struct nls_table *nls_codepage)
  1419. {
  1420. /* SMB_QUERY_FILE_UNIX_LINK */
  1421. TRANSACTION2_QPI_REQ *pSMB = NULL;
  1422. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  1423. int rc = 0;
  1424. int bytes_returned;
  1425. int name_len;
  1426. __u16 params, byte_count;
  1427. cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
  1428. querySymLinkRetry:
  1429. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1430. (void **) &pSMBr);
  1431. if (rc)
  1432. return rc;
  1433. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1434. name_len =
  1435. cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
  1436. /* find define for this maxpathcomponent */
  1437. , nls_codepage);
  1438. name_len++; /* trailing null */
  1439. name_len *= 2;
  1440. } else { /* BB improve the check for buffer overruns BB */
  1441. name_len = strnlen(searchName, PATH_MAX);
  1442. name_len++; /* trailing null */
  1443. strncpy(pSMB->FileName, searchName, name_len);
  1444. }
  1445. params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
  1446. pSMB->TotalDataCount = 0;
  1447. pSMB->MaxParameterCount = cpu_to_le16(2);
  1448. /* BB find exact max data count below from sess structure BB */
  1449. pSMB->MaxDataCount = cpu_to_le16(4000);
  1450. pSMB->MaxSetupCount = 0;
  1451. pSMB->Reserved = 0;
  1452. pSMB->Flags = 0;
  1453. pSMB->Timeout = 0;
  1454. pSMB->Reserved2 = 0;
  1455. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  1456. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  1457. pSMB->DataCount = 0;
  1458. pSMB->DataOffset = 0;
  1459. pSMB->SetupCount = 1;
  1460. pSMB->Reserved3 = 0;
  1461. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  1462. byte_count = params + 1 /* pad */ ;
  1463. pSMB->TotalParameterCount = cpu_to_le16(params);
  1464. pSMB->ParameterCount = pSMB->TotalParameterCount;
  1465. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
  1466. pSMB->Reserved4 = 0;
  1467. pSMB->hdr.smb_buf_length += byte_count;
  1468. pSMB->ByteCount = cpu_to_le16(byte_count);
  1469. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1470. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1471. if (rc) {
  1472. cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
  1473. } else {
  1474. /* decode response */
  1475. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  1476. if (rc || (pSMBr->ByteCount < 2))
  1477. /* BB also check enough total bytes returned */
  1478. rc = -EIO; /* bad smb */
  1479. else {
  1480. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  1481. __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  1482. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  1483. name_len = UniStrnlen((wchar_t *) ((char *)
  1484. &pSMBr->hdr.Protocol +data_offset),
  1485. min_t(const int, buflen,count) / 2);
  1486. /* BB FIXME investigate remapping reserved chars here */
  1487. cifs_strfromUCS_le(symlinkinfo,
  1488. (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
  1489. data_offset),
  1490. name_len, nls_codepage);
  1491. } else {
  1492. strncpy(symlinkinfo,
  1493. (char *) &pSMBr->hdr.Protocol +
  1494. data_offset,
  1495. min_t(const int, buflen, count));
  1496. }
  1497. symlinkinfo[buflen] = 0;
  1498. /* just in case so calling code does not go off the end of buffer */
  1499. }
  1500. }
  1501. cifs_buf_release(pSMB);
  1502. if (rc == -EAGAIN)
  1503. goto querySymLinkRetry;
  1504. return rc;
  1505. }
  1506. int
  1507. CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
  1508. const unsigned char *searchName,
  1509. char *symlinkinfo, const int buflen,__u16 fid,
  1510. const struct nls_table *nls_codepage)
  1511. {
  1512. int rc = 0;
  1513. int bytes_returned;
  1514. int name_len;
  1515. struct smb_com_transaction_ioctl_req * pSMB;
  1516. struct smb_com_transaction_ioctl_rsp * pSMBr;
  1517. cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
  1518. rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  1519. (void **) &pSMBr);
  1520. if (rc)
  1521. return rc;
  1522. pSMB->TotalParameterCount = 0 ;
  1523. pSMB->TotalDataCount = 0;
  1524. pSMB->MaxParameterCount = cpu_to_le32(2);
  1525. /* BB find exact data count max from sess structure BB */
  1526. pSMB->MaxDataCount = cpu_to_le32(4000);
  1527. pSMB->MaxSetupCount = 4;
  1528. pSMB->Reserved = 0;
  1529. pSMB->ParameterOffset = 0;
  1530. pSMB->DataCount = 0;
  1531. pSMB->DataOffset = 0;
  1532. pSMB->SetupCount = 4;
  1533. pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
  1534. pSMB->ParameterCount = pSMB->TotalParameterCount;
  1535. pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
  1536. pSMB->IsFsctl = 1; /* FSCTL */
  1537. pSMB->IsRootFlag = 0;
  1538. pSMB->Fid = fid; /* file handle always le */
  1539. pSMB->ByteCount = 0;
  1540. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1541. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1542. if (rc) {
  1543. cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
  1544. } else { /* decode response */
  1545. __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
  1546. __u32 data_count = le32_to_cpu(pSMBr->DataCount);
  1547. if ((pSMBr->ByteCount < 2) || (data_offset > 512))
  1548. /* BB also check enough total bytes returned */
  1549. rc = -EIO; /* bad smb */
  1550. else {
  1551. if(data_count && (data_count < 2048)) {
  1552. char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
  1553. struct reparse_data * reparse_buf = (struct reparse_data *)
  1554. ((char *)&pSMBr->hdr.Protocol + data_offset);
  1555. if((char*)reparse_buf >= end_of_smb) {
  1556. rc = -EIO;
  1557. goto qreparse_out;
  1558. }
  1559. if((reparse_buf->LinkNamesBuf +
  1560. reparse_buf->TargetNameOffset +
  1561. reparse_buf->TargetNameLen) >
  1562. end_of_smb) {
  1563. cFYI(1,("reparse buf extended beyond SMB"));
  1564. rc = -EIO;
  1565. goto qreparse_out;
  1566. }
  1567. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  1568. name_len = UniStrnlen((wchar_t *)
  1569. (reparse_buf->LinkNamesBuf +
  1570. reparse_buf->TargetNameOffset),
  1571. min(buflen/2, reparse_buf->TargetNameLen / 2));
  1572. cifs_strfromUCS_le(symlinkinfo,
  1573. (wchar_t *) (reparse_buf->LinkNamesBuf +
  1574. reparse_buf->TargetNameOffset),
  1575. name_len, nls_codepage);
  1576. } else { /* ASCII names */
  1577. strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
  1578. reparse_buf->TargetNameOffset,
  1579. min_t(const int, buflen, reparse_buf->TargetNameLen));
  1580. }
  1581. } else {
  1582. rc = -EIO;
  1583. cFYI(1,("Invalid return data count on get reparse info ioctl"));
  1584. }
  1585. symlinkinfo[buflen] = 0; /* just in case so the caller
  1586. does not go off the end of the buffer */
  1587. cFYI(1,("readlink result - %s ",symlinkinfo));
  1588. }
  1589. }
  1590. qreparse_out:
  1591. if (pSMB)
  1592. cifs_buf_release(pSMB);
  1593. /* Note: On -EAGAIN error only caller can retry on handle based calls
  1594. since file handle passed in no longer valid */
  1595. return rc;
  1596. }
  1597. #ifdef CONFIG_CIFS_POSIX
  1598. /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
  1599. static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
  1600. {
  1601. /* u8 cifs fields do not need le conversion */
  1602. ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
  1603. ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
  1604. ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
  1605. /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
  1606. return;
  1607. }
  1608. /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
  1609. static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
  1610. const int acl_type,const int size_of_data_area)
  1611. {
  1612. int size = 0;
  1613. int i;
  1614. __u16 count;
  1615. struct cifs_posix_ace * pACE;
  1616. struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
  1617. posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
  1618. if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
  1619. return -EOPNOTSUPP;
  1620. if(acl_type & ACL_TYPE_ACCESS) {
  1621. count = le16_to_cpu(cifs_acl->access_entry_count);
  1622. pACE = &cifs_acl->ace_array[0];
  1623. size = sizeof(struct cifs_posix_acl);
  1624. size += sizeof(struct cifs_posix_ace) * count;
  1625. /* check if we would go beyond end of SMB */
  1626. if(size_of_data_area < size) {
  1627. cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
  1628. return -EINVAL;
  1629. }
  1630. } else if(acl_type & ACL_TYPE_DEFAULT) {
  1631. count = le16_to_cpu(cifs_acl->access_entry_count);
  1632. size = sizeof(struct cifs_posix_acl);
  1633. size += sizeof(struct cifs_posix_ace) * count;
  1634. /* skip past access ACEs to get to default ACEs */
  1635. pACE = &cifs_acl->ace_array[count];
  1636. count = le16_to_cpu(cifs_acl->default_entry_count);
  1637. size += sizeof(struct cifs_posix_ace) * count;
  1638. /* check if we would go beyond end of SMB */
  1639. if(size_of_data_area < size)
  1640. return -EINVAL;
  1641. } else {
  1642. /* illegal type */
  1643. return -EINVAL;
  1644. }
  1645. size = posix_acl_xattr_size(count);
  1646. if((buflen == 0) || (local_acl == NULL)) {
  1647. /* used to query ACL EA size */
  1648. } else if(size > buflen) {
  1649. return -ERANGE;
  1650. } else /* buffer big enough */ {
  1651. local_acl->a_version = POSIX_ACL_XATTR_VERSION;
  1652. for(i = 0;i < count ;i++) {
  1653. cifs_convert_ace(&local_acl->a_entries[i],pACE);
  1654. pACE ++;
  1655. }
  1656. }
  1657. return size;
  1658. }
  1659. static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
  1660. const posix_acl_xattr_entry * local_ace)
  1661. {
  1662. __u16 rc = 0; /* 0 = ACL converted ok */
  1663. cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
  1664. cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
  1665. /* BB is there a better way to handle the large uid? */
  1666. if(local_ace->e_id == -1) {
  1667. /* Probably no need to le convert -1 on any arch but can not hurt */
  1668. cifs_ace->cifs_uid = cpu_to_le64(-1);
  1669. } else
  1670. cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
  1671. /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
  1672. return rc;
  1673. }
  1674. /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
  1675. static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
  1676. const int acl_type)
  1677. {
  1678. __u16 rc = 0;
  1679. struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
  1680. posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
  1681. int count;
  1682. int i;
  1683. if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
  1684. return 0;
  1685. count = posix_acl_xattr_count((size_t)buflen);
  1686. cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
  1687. count,buflen,local_acl->a_version));
  1688. if(local_acl->a_version != 2) {
  1689. cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
  1690. return 0;
  1691. }
  1692. cifs_acl->version = cpu_to_le16(1);
  1693. if(acl_type == ACL_TYPE_ACCESS)
  1694. cifs_acl->access_entry_count = count;
  1695. else if(acl_type == ACL_TYPE_DEFAULT)
  1696. cifs_acl->default_entry_count = count;
  1697. else {
  1698. cFYI(1,("unknown ACL type %d",acl_type));
  1699. return 0;
  1700. }
  1701. for(i=0;i<count;i++) {
  1702. rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
  1703. &local_acl->a_entries[i]);
  1704. if(rc != 0) {
  1705. /* ACE not converted */
  1706. break;
  1707. }
  1708. }
  1709. if(rc == 0) {
  1710. rc = (__u16)(count * sizeof(struct cifs_posix_ace));
  1711. rc += sizeof(struct cifs_posix_acl);
  1712. /* BB add check to make sure ACL does not overflow SMB */
  1713. }
  1714. return rc;
  1715. }
  1716. int
  1717. CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
  1718. const unsigned char *searchName,
  1719. char *acl_inf, const int buflen, const int acl_type,
  1720. const struct nls_table *nls_codepage, int remap)
  1721. {
  1722. /* SMB_QUERY_POSIX_ACL */
  1723. TRANSACTION2_QPI_REQ *pSMB = NULL;
  1724. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  1725. int rc = 0;
  1726. int bytes_returned;
  1727. int name_len;
  1728. __u16 params, byte_count;
  1729. cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
  1730. queryAclRetry:
  1731. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1732. (void **) &pSMBr);
  1733. if (rc)
  1734. return rc;
  1735. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1736. name_len =
  1737. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  1738. PATH_MAX, nls_codepage, remap);
  1739. name_len++; /* trailing null */
  1740. name_len *= 2;
  1741. pSMB->FileName[name_len] = 0;
  1742. pSMB->FileName[name_len+1] = 0;
  1743. } else { /* BB improve the check for buffer overruns BB */
  1744. name_len = strnlen(searchName, PATH_MAX);
  1745. name_len++; /* trailing null */
  1746. strncpy(pSMB->FileName, searchName, name_len);
  1747. }
  1748. params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
  1749. pSMB->TotalDataCount = 0;
  1750. pSMB->MaxParameterCount = cpu_to_le16(2);
  1751. /* BB find exact max data count below from sess structure BB */
  1752. pSMB->MaxDataCount = cpu_to_le16(4000);
  1753. pSMB->MaxSetupCount = 0;
  1754. pSMB->Reserved = 0;
  1755. pSMB->Flags = 0;
  1756. pSMB->Timeout = 0;
  1757. pSMB->Reserved2 = 0;
  1758. pSMB->ParameterOffset = cpu_to_le16(
  1759. offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  1760. pSMB->DataCount = 0;
  1761. pSMB->DataOffset = 0;
  1762. pSMB->SetupCount = 1;
  1763. pSMB->Reserved3 = 0;
  1764. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  1765. byte_count = params + 1 /* pad */ ;
  1766. pSMB->TotalParameterCount = cpu_to_le16(params);
  1767. pSMB->ParameterCount = pSMB->TotalParameterCount;
  1768. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
  1769. pSMB->Reserved4 = 0;
  1770. pSMB->hdr.smb_buf_length += byte_count;
  1771. pSMB->ByteCount = cpu_to_le16(byte_count);
  1772. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1773. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1774. if (rc) {
  1775. cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
  1776. } else {
  1777. /* decode response */
  1778. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  1779. if (rc || (pSMBr->ByteCount < 2))
  1780. /* BB also check enough total bytes returned */
  1781. rc = -EIO; /* bad smb */
  1782. else {
  1783. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  1784. __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  1785. rc = cifs_copy_posix_acl(acl_inf,
  1786. (char *)&pSMBr->hdr.Protocol+data_offset,
  1787. buflen,acl_type,count);
  1788. }
  1789. }
  1790. cifs_buf_release(pSMB);
  1791. if (rc == -EAGAIN)
  1792. goto queryAclRetry;
  1793. return rc;
  1794. }
  1795. int
  1796. CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
  1797. const unsigned char *fileName,
  1798. const char *local_acl, const int buflen,
  1799. const int acl_type,
  1800. const struct nls_table *nls_codepage, int remap)
  1801. {
  1802. struct smb_com_transaction2_spi_req *pSMB = NULL;
  1803. struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  1804. char *parm_data;
  1805. int name_len;
  1806. int rc = 0;
  1807. int bytes_returned = 0;
  1808. __u16 params, byte_count, data_count, param_offset, offset;
  1809. cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
  1810. setAclRetry:
  1811. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1812. (void **) &pSMBr);
  1813. if (rc)
  1814. return rc;
  1815. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1816. name_len =
  1817. cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  1818. PATH_MAX, nls_codepage, remap);
  1819. name_len++; /* trailing null */
  1820. name_len *= 2;
  1821. } else { /* BB improve the check for buffer overruns BB */
  1822. name_len = strnlen(fileName, PATH_MAX);
  1823. name_len++; /* trailing null */
  1824. strncpy(pSMB->FileName, fileName, name_len);
  1825. }
  1826. params = 6 + name_len;
  1827. pSMB->MaxParameterCount = cpu_to_le16(2);
  1828. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
  1829. pSMB->MaxSetupCount = 0;
  1830. pSMB->Reserved = 0;
  1831. pSMB->Flags = 0;
  1832. pSMB->Timeout = 0;
  1833. pSMB->Reserved2 = 0;
  1834. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  1835. InformationLevel) - 4;
  1836. offset = param_offset + params;
  1837. parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
  1838. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  1839. /* convert to on the wire format for POSIX ACL */
  1840. data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
  1841. if(data_count == 0) {
  1842. rc = -EOPNOTSUPP;
  1843. goto setACLerrorExit;
  1844. }
  1845. pSMB->DataOffset = cpu_to_le16(offset);
  1846. pSMB->SetupCount = 1;
  1847. pSMB->Reserved3 = 0;
  1848. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  1849. pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
  1850. byte_count = 3 /* pad */ + params + data_count;
  1851. pSMB->DataCount = cpu_to_le16(data_count);
  1852. pSMB->TotalDataCount = pSMB->DataCount;
  1853. pSMB->ParameterCount = cpu_to_le16(params);
  1854. pSMB->TotalParameterCount = pSMB->ParameterCount;
  1855. pSMB->Reserved4 = 0;
  1856. pSMB->hdr.smb_buf_length += byte_count;
  1857. pSMB->ByteCount = cpu_to_le16(byte_count);
  1858. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1859. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1860. if (rc) {
  1861. cFYI(1, ("Set POSIX ACL returned %d", rc));
  1862. }
  1863. setACLerrorExit:
  1864. cifs_buf_release(pSMB);
  1865. if (rc == -EAGAIN)
  1866. goto setAclRetry;
  1867. return rc;
  1868. }
  1869. /* BB fix tabs in this function FIXME BB */
  1870. int
  1871. CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
  1872. const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
  1873. {
  1874. int rc = 0;
  1875. struct smb_t2_qfi_req *pSMB = NULL;
  1876. struct smb_t2_qfi_rsp *pSMBr = NULL;
  1877. int bytes_returned;
  1878. __u16 params, byte_count;
  1879. cFYI(1,("In GetExtAttr"));
  1880. if(tcon == NULL)
  1881. return -ENODEV;
  1882. GetExtAttrRetry:
  1883. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1884. (void **) &pSMBr);
  1885. if (rc)
  1886. return rc;
  1887. params = 2 /* level */ +2 /* fid */;
  1888. pSMB->t2.TotalDataCount = 0;
  1889. pSMB->t2.MaxParameterCount = cpu_to_le16(4);
  1890. /* BB find exact max data count below from sess structure BB */
  1891. pSMB->t2.MaxDataCount = cpu_to_le16(4000);
  1892. pSMB->t2.MaxSetupCount = 0;
  1893. pSMB->t2.Reserved = 0;
  1894. pSMB->t2.Flags = 0;
  1895. pSMB->t2.Timeout = 0;
  1896. pSMB->t2.Reserved2 = 0;
  1897. pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
  1898. Fid) - 4);
  1899. pSMB->t2.DataCount = 0;
  1900. pSMB->t2.DataOffset = 0;
  1901. pSMB->t2.SetupCount = 1;
  1902. pSMB->t2.Reserved3 = 0;
  1903. pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
  1904. byte_count = params + 1 /* pad */ ;
  1905. pSMB->t2.TotalParameterCount = cpu_to_le16(params);
  1906. pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
  1907. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
  1908. pSMB->Pad = 0;
  1909. pSMB->Fid = netfid;
  1910. pSMB->hdr.smb_buf_length += byte_count;
  1911. pSMB->t2.ByteCount = cpu_to_le16(byte_count);
  1912. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  1913. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  1914. if (rc) {
  1915. cFYI(1, ("error %d in GetExtAttr", rc));
  1916. } else {
  1917. /* decode response */
  1918. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  1919. if (rc || (pSMBr->ByteCount < 2))
  1920. /* BB also check enough total bytes returned */
  1921. /* If rc should we check for EOPNOSUPP and
  1922. disable the srvino flag? or in caller? */
  1923. rc = -EIO; /* bad smb */
  1924. else {
  1925. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  1926. __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  1927. struct file_chattr_info * pfinfo;
  1928. /* BB Do we need a cast or hash here ? */
  1929. if(count != 16) {
  1930. cFYI(1, ("Illegal size ret in GetExtAttr"));
  1931. rc = -EIO;
  1932. goto GetExtAttrOut;
  1933. }
  1934. pfinfo = (struct file_chattr_info *)
  1935. (data_offset + (char *) &pSMBr->hdr.Protocol);
  1936. *pExtAttrBits = le64_to_cpu(pfinfo->mode);
  1937. *pMask = le64_to_cpu(pfinfo->mask);
  1938. }
  1939. }
  1940. GetExtAttrOut:
  1941. cifs_buf_release(pSMB);
  1942. if (rc == -EAGAIN)
  1943. goto GetExtAttrRetry;
  1944. return rc;
  1945. }
  1946. #endif /* CONFIG_POSIX */
  1947. int
  1948. CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
  1949. const unsigned char *searchName,
  1950. FILE_ALL_INFO * pFindData,
  1951. const struct nls_table *nls_codepage, int remap)
  1952. {
  1953. /* level 263 SMB_QUERY_FILE_ALL_INFO */
  1954. TRANSACTION2_QPI_REQ *pSMB = NULL;
  1955. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  1956. int rc = 0;
  1957. int bytes_returned;
  1958. int name_len;
  1959. __u16 params, byte_count;
  1960. /* cFYI(1, ("In QPathInfo path %s", searchName)); */
  1961. QPathInfoRetry:
  1962. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  1963. (void **) &pSMBr);
  1964. if (rc)
  1965. return rc;
  1966. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  1967. name_len =
  1968. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  1969. PATH_MAX, nls_codepage, remap);
  1970. name_len++; /* trailing null */
  1971. name_len *= 2;
  1972. } else { /* BB improve the check for buffer overruns BB */
  1973. name_len = strnlen(searchName, PATH_MAX);
  1974. name_len++; /* trailing null */
  1975. strncpy(pSMB->FileName, searchName, name_len);
  1976. }
  1977. params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
  1978. pSMB->TotalDataCount = 0;
  1979. pSMB->MaxParameterCount = cpu_to_le16(2);
  1980. pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  1981. pSMB->MaxSetupCount = 0;
  1982. pSMB->Reserved = 0;
  1983. pSMB->Flags = 0;
  1984. pSMB->Timeout = 0;
  1985. pSMB->Reserved2 = 0;
  1986. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  1987. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  1988. pSMB->DataCount = 0;
  1989. pSMB->DataOffset = 0;
  1990. pSMB->SetupCount = 1;
  1991. pSMB->Reserved3 = 0;
  1992. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  1993. byte_count = params + 1 /* pad */ ;
  1994. pSMB->TotalParameterCount = cpu_to_le16(params);
  1995. pSMB->ParameterCount = pSMB->TotalParameterCount;
  1996. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
  1997. pSMB->Reserved4 = 0;
  1998. pSMB->hdr.smb_buf_length += byte_count;
  1999. pSMB->ByteCount = cpu_to_le16(byte_count);
  2000. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2001. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2002. if (rc) {
  2003. cFYI(1, ("Send error in QPathInfo = %d", rc));
  2004. } else { /* decode response */
  2005. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2006. if (rc || (pSMBr->ByteCount < 40))
  2007. rc = -EIO; /* bad smb */
  2008. else if (pFindData){
  2009. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2010. memcpy((char *) pFindData,
  2011. (char *) &pSMBr->hdr.Protocol +
  2012. data_offset, sizeof (FILE_ALL_INFO));
  2013. } else
  2014. rc = -ENOMEM;
  2015. }
  2016. cifs_buf_release(pSMB);
  2017. if (rc == -EAGAIN)
  2018. goto QPathInfoRetry;
  2019. return rc;
  2020. }
  2021. int
  2022. CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
  2023. const unsigned char *searchName,
  2024. FILE_UNIX_BASIC_INFO * pFindData,
  2025. const struct nls_table *nls_codepage, int remap)
  2026. {
  2027. /* SMB_QUERY_FILE_UNIX_BASIC */
  2028. TRANSACTION2_QPI_REQ *pSMB = NULL;
  2029. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  2030. int rc = 0;
  2031. int bytes_returned = 0;
  2032. int name_len;
  2033. __u16 params, byte_count;
  2034. cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
  2035. UnixQPathInfoRetry:
  2036. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2037. (void **) &pSMBr);
  2038. if (rc)
  2039. return rc;
  2040. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  2041. name_len =
  2042. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  2043. PATH_MAX, nls_codepage, remap);
  2044. name_len++; /* trailing null */
  2045. name_len *= 2;
  2046. } else { /* BB improve the check for buffer overruns BB */
  2047. name_len = strnlen(searchName, PATH_MAX);
  2048. name_len++; /* trailing null */
  2049. strncpy(pSMB->FileName, searchName, name_len);
  2050. }
  2051. params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
  2052. pSMB->TotalDataCount = 0;
  2053. pSMB->MaxParameterCount = cpu_to_le16(2);
  2054. /* BB find exact max SMB PDU from sess structure BB */
  2055. pSMB->MaxDataCount = cpu_to_le16(4000);
  2056. pSMB->MaxSetupCount = 0;
  2057. pSMB->Reserved = 0;
  2058. pSMB->Flags = 0;
  2059. pSMB->Timeout = 0;
  2060. pSMB->Reserved2 = 0;
  2061. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2062. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  2063. pSMB->DataCount = 0;
  2064. pSMB->DataOffset = 0;
  2065. pSMB->SetupCount = 1;
  2066. pSMB->Reserved3 = 0;
  2067. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  2068. byte_count = params + 1 /* pad */ ;
  2069. pSMB->TotalParameterCount = cpu_to_le16(params);
  2070. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2071. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
  2072. pSMB->Reserved4 = 0;
  2073. pSMB->hdr.smb_buf_length += byte_count;
  2074. pSMB->ByteCount = cpu_to_le16(byte_count);
  2075. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2076. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2077. if (rc) {
  2078. cFYI(1, ("Send error in QPathInfo = %d", rc));
  2079. } else { /* decode response */
  2080. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2081. if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
  2082. rc = -EIO; /* bad smb */
  2083. } else {
  2084. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2085. memcpy((char *) pFindData,
  2086. (char *) &pSMBr->hdr.Protocol +
  2087. data_offset,
  2088. sizeof (FILE_UNIX_BASIC_INFO));
  2089. }
  2090. }
  2091. cifs_buf_release(pSMB);
  2092. if (rc == -EAGAIN)
  2093. goto UnixQPathInfoRetry;
  2094. return rc;
  2095. }
  2096. #if 0 /* function unused at present */
  2097. int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
  2098. const char *searchName, FILE_ALL_INFO * findData,
  2099. const struct nls_table *nls_codepage)
  2100. {
  2101. /* level 257 SMB_ */
  2102. TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  2103. TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
  2104. int rc = 0;
  2105. int bytes_returned;
  2106. int name_len;
  2107. __u16 params, byte_count;
  2108. cFYI(1, ("In FindUnique"));
  2109. findUniqueRetry:
  2110. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2111. (void **) &pSMBr);
  2112. if (rc)
  2113. return rc;
  2114. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  2115. name_len =
  2116. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
  2117. /* find define for this maxpathcomponent */
  2118. , nls_codepage);
  2119. name_len++; /* trailing null */
  2120. name_len *= 2;
  2121. } else { /* BB improve the check for buffer overruns BB */
  2122. name_len = strnlen(searchName, PATH_MAX);
  2123. name_len++; /* trailing null */
  2124. strncpy(pSMB->FileName, searchName, name_len);
  2125. }
  2126. params = 12 + name_len /* includes null */ ;
  2127. pSMB->TotalDataCount = 0; /* no EAs */
  2128. pSMB->MaxParameterCount = cpu_to_le16(2);
  2129. pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  2130. pSMB->MaxSetupCount = 0;
  2131. pSMB->Reserved = 0;
  2132. pSMB->Flags = 0;
  2133. pSMB->Timeout = 0;
  2134. pSMB->Reserved2 = 0;
  2135. pSMB->ParameterOffset = cpu_to_le16(
  2136. offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
  2137. pSMB->DataCount = 0;
  2138. pSMB->DataOffset = 0;
  2139. pSMB->SetupCount = 1; /* one byte, no need to le convert */
  2140. pSMB->Reserved3 = 0;
  2141. pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
  2142. byte_count = params + 1 /* pad */ ;
  2143. pSMB->TotalParameterCount = cpu_to_le16(params);
  2144. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2145. pSMB->SearchAttributes =
  2146. cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  2147. ATTR_DIRECTORY);
  2148. pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
  2149. pSMB->SearchFlags = cpu_to_le16(1);
  2150. pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
  2151. pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
  2152. pSMB->hdr.smb_buf_length += byte_count;
  2153. pSMB->ByteCount = cpu_to_le16(byte_count);
  2154. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2155. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2156. if (rc) {
  2157. cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
  2158. } else { /* decode response */
  2159. /* BB fill in */
  2160. }
  2161. cifs_buf_release(pSMB);
  2162. if (rc == -EAGAIN)
  2163. goto findUniqueRetry;
  2164. return rc;
  2165. }
  2166. #endif /* end unused (temporarily) function */
  2167. /* xid, tcon, searchName and codepage are input parms, rest are returned */
  2168. int
  2169. CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
  2170. const char *searchName,
  2171. const struct nls_table *nls_codepage,
  2172. __u16 * pnetfid,
  2173. struct cifs_search_info * psrch_inf, int remap)
  2174. {
  2175. /* level 257 SMB_ */
  2176. TRANSACTION2_FFIRST_REQ *pSMB = NULL;
  2177. TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
  2178. T2_FFIRST_RSP_PARMS * parms;
  2179. int rc = 0;
  2180. int bytes_returned = 0;
  2181. int name_len;
  2182. __u16 params, byte_count;
  2183. cFYI(1, ("In FindFirst for %s",searchName));
  2184. findFirstRetry:
  2185. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2186. (void **) &pSMBr);
  2187. if (rc)
  2188. return rc;
  2189. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  2190. name_len =
  2191. cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
  2192. PATH_MAX, nls_codepage, remap);
  2193. /* We can not add the asterik earlier in case
  2194. it got remapped to 0xF03A as if it were part of the
  2195. directory name instead of a wildcard */
  2196. name_len *= 2;
  2197. pSMB->FileName[name_len] = '\\';
  2198. pSMB->FileName[name_len+1] = 0;
  2199. pSMB->FileName[name_len+2] = '*';
  2200. pSMB->FileName[name_len+3] = 0;
  2201. name_len += 4; /* now the trailing null */
  2202. pSMB->FileName[name_len] = 0; /* null terminate just in case */
  2203. pSMB->FileName[name_len+1] = 0;
  2204. name_len += 2;
  2205. } else { /* BB add check for overrun of SMB buf BB */
  2206. name_len = strnlen(searchName, PATH_MAX);
  2207. /* BB fix here and in unicode clause above ie
  2208. if(name_len > buffersize-header)
  2209. free buffer exit; BB */
  2210. strncpy(pSMB->FileName, searchName, name_len);
  2211. pSMB->FileName[name_len] = '\\';
  2212. pSMB->FileName[name_len+1] = '*';
  2213. pSMB->FileName[name_len+2] = 0;
  2214. name_len += 3;
  2215. }
  2216. params = 12 + name_len /* includes null */ ;
  2217. pSMB->TotalDataCount = 0; /* no EAs */
  2218. pSMB->MaxParameterCount = cpu_to_le16(10);
  2219. pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
  2220. MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
  2221. pSMB->MaxSetupCount = 0;
  2222. pSMB->Reserved = 0;
  2223. pSMB->Flags = 0;
  2224. pSMB->Timeout = 0;
  2225. pSMB->Reserved2 = 0;
  2226. byte_count = params + 1 /* pad */ ;
  2227. pSMB->TotalParameterCount = cpu_to_le16(params);
  2228. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2229. pSMB->ParameterOffset = cpu_to_le16(
  2230. offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
  2231. pSMB->DataCount = 0;
  2232. pSMB->DataOffset = 0;
  2233. pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
  2234. pSMB->Reserved3 = 0;
  2235. pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
  2236. pSMB->SearchAttributes =
  2237. cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
  2238. ATTR_DIRECTORY);
  2239. pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
  2240. pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
  2241. CIFS_SEARCH_RETURN_RESUME);
  2242. pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  2243. /* BB what should we set StorageType to? Does it matter? BB */
  2244. pSMB->SearchStorageType = 0;
  2245. pSMB->hdr.smb_buf_length += byte_count;
  2246. pSMB->ByteCount = cpu_to_le16(byte_count);
  2247. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2248. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2249. if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
  2250. /* BB Add code to handle unsupported level rc */
  2251. cFYI(1, ("Error in FindFirst = %d", rc));
  2252. if (pSMB)
  2253. cifs_buf_release(pSMB);
  2254. /* BB eventually could optimize out free and realloc of buf */
  2255. /* for this case */
  2256. if (rc == -EAGAIN)
  2257. goto findFirstRetry;
  2258. } else { /* decode response */
  2259. /* BB remember to free buffer if error BB */
  2260. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2261. if(rc == 0) {
  2262. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  2263. psrch_inf->unicode = TRUE;
  2264. else
  2265. psrch_inf->unicode = FALSE;
  2266. psrch_inf->ntwrk_buf_start = (char *)pSMBr;
  2267. psrch_inf->srch_entries_start =
  2268. (char *) &pSMBr->hdr.Protocol +
  2269. le16_to_cpu(pSMBr->t2.DataOffset);
  2270. parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
  2271. le16_to_cpu(pSMBr->t2.ParameterOffset));
  2272. if(parms->EndofSearch)
  2273. psrch_inf->endOfSearch = TRUE;
  2274. else
  2275. psrch_inf->endOfSearch = FALSE;
  2276. psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
  2277. psrch_inf->index_of_last_entry =
  2278. psrch_inf->entries_in_buffer;
  2279. *pnetfid = parms->SearchHandle;
  2280. } else {
  2281. cifs_buf_release(pSMB);
  2282. }
  2283. }
  2284. return rc;
  2285. }
  2286. int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
  2287. __u16 searchHandle, struct cifs_search_info * psrch_inf)
  2288. {
  2289. TRANSACTION2_FNEXT_REQ *pSMB = NULL;
  2290. TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
  2291. T2_FNEXT_RSP_PARMS * parms;
  2292. char *response_data;
  2293. int rc = 0;
  2294. int bytes_returned, name_len;
  2295. __u16 params, byte_count;
  2296. cFYI(1, ("In FindNext"));
  2297. if(psrch_inf->endOfSearch == TRUE)
  2298. return -ENOENT;
  2299. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2300. (void **) &pSMBr);
  2301. if (rc)
  2302. return rc;
  2303. params = 14; /* includes 2 bytes of null string, converted to LE below */
  2304. byte_count = 0;
  2305. pSMB->TotalDataCount = 0; /* no EAs */
  2306. pSMB->MaxParameterCount = cpu_to_le16(8);
  2307. pSMB->MaxDataCount =
  2308. cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
  2309. pSMB->MaxSetupCount = 0;
  2310. pSMB->Reserved = 0;
  2311. pSMB->Flags = 0;
  2312. pSMB->Timeout = 0;
  2313. pSMB->Reserved2 = 0;
  2314. pSMB->ParameterOffset = cpu_to_le16(
  2315. offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
  2316. pSMB->DataCount = 0;
  2317. pSMB->DataOffset = 0;
  2318. pSMB->SetupCount = 1;
  2319. pSMB->Reserved3 = 0;
  2320. pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
  2321. pSMB->SearchHandle = searchHandle; /* always kept as le */
  2322. pSMB->SearchCount =
  2323. cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
  2324. /* test for Unix extensions */
  2325. /* if (tcon->ses->capabilities & CAP_UNIX) {
  2326. pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
  2327. psrch_inf->info_level = SMB_FIND_FILE_UNIX;
  2328. } else {
  2329. pSMB->InformationLevel =
  2330. cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
  2331. psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
  2332. } */
  2333. pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
  2334. pSMB->ResumeKey = psrch_inf->resume_key;
  2335. pSMB->SearchFlags =
  2336. cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
  2337. name_len = psrch_inf->resume_name_len;
  2338. params += name_len;
  2339. if(name_len < PATH_MAX) {
  2340. memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
  2341. byte_count += name_len;
  2342. /* 14 byte parm len above enough for 2 byte null terminator */
  2343. pSMB->ResumeFileName[name_len] = 0;
  2344. pSMB->ResumeFileName[name_len+1] = 0;
  2345. } else {
  2346. rc = -EINVAL;
  2347. goto FNext2_err_exit;
  2348. }
  2349. byte_count = params + 1 /* pad */ ;
  2350. pSMB->TotalParameterCount = cpu_to_le16(params);
  2351. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2352. pSMB->hdr.smb_buf_length += byte_count;
  2353. pSMB->ByteCount = cpu_to_le16(byte_count);
  2354. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2355. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2356. if (rc) {
  2357. if (rc == -EBADF) {
  2358. psrch_inf->endOfSearch = TRUE;
  2359. rc = 0; /* search probably was closed at end of search above */
  2360. } else
  2361. cFYI(1, ("FindNext returned = %d", rc));
  2362. } else { /* decode response */
  2363. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2364. if(rc == 0) {
  2365. /* BB fixme add lock for file (srch_info) struct here */
  2366. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
  2367. psrch_inf->unicode = TRUE;
  2368. else
  2369. psrch_inf->unicode = FALSE;
  2370. response_data = (char *) &pSMBr->hdr.Protocol +
  2371. le16_to_cpu(pSMBr->t2.ParameterOffset);
  2372. parms = (T2_FNEXT_RSP_PARMS *)response_data;
  2373. response_data = (char *)&pSMBr->hdr.Protocol +
  2374. le16_to_cpu(pSMBr->t2.DataOffset);
  2375. cifs_buf_release(psrch_inf->ntwrk_buf_start);
  2376. psrch_inf->srch_entries_start = response_data;
  2377. psrch_inf->ntwrk_buf_start = (char *)pSMB;
  2378. if(parms->EndofSearch)
  2379. psrch_inf->endOfSearch = TRUE;
  2380. else
  2381. psrch_inf->endOfSearch = FALSE;
  2382. psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
  2383. psrch_inf->index_of_last_entry +=
  2384. psrch_inf->entries_in_buffer;
  2385. /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
  2386. /* BB fixme add unlock here */
  2387. }
  2388. }
  2389. /* BB On error, should we leave previous search buf (and count and
  2390. last entry fields) intact or free the previous one? */
  2391. /* Note: On -EAGAIN error only caller can retry on handle based calls
  2392. since file handle passed in no longer valid */
  2393. FNext2_err_exit:
  2394. if (rc != 0)
  2395. cifs_buf_release(pSMB);
  2396. return rc;
  2397. }
  2398. int
  2399. CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
  2400. {
  2401. int rc = 0;
  2402. FINDCLOSE_REQ *pSMB = NULL;
  2403. CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
  2404. int bytes_returned;
  2405. cFYI(1, ("In CIFSSMBFindClose"));
  2406. rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
  2407. /* no sense returning error if session restarted
  2408. as file handle has been closed */
  2409. if(rc == -EAGAIN)
  2410. return 0;
  2411. if (rc)
  2412. return rc;
  2413. pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
  2414. pSMB->FileID = searchHandle;
  2415. pSMB->ByteCount = 0;
  2416. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2417. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2418. if (rc) {
  2419. cERROR(1, ("Send error in FindClose = %d", rc));
  2420. }
  2421. cifs_small_buf_release(pSMB);
  2422. /* Since session is dead, search handle closed on server already */
  2423. if (rc == -EAGAIN)
  2424. rc = 0;
  2425. return rc;
  2426. }
  2427. #ifdef CONFIG_CIFS_EXPERIMENTAL
  2428. int
  2429. CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
  2430. const unsigned char *searchName,
  2431. __u64 * inode_number,
  2432. const struct nls_table *nls_codepage, int remap)
  2433. {
  2434. int rc = 0;
  2435. TRANSACTION2_QPI_REQ *pSMB = NULL;
  2436. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  2437. int name_len, bytes_returned;
  2438. __u16 params, byte_count;
  2439. cFYI(1,("In GetSrvInodeNum for %s",searchName));
  2440. if(tcon == NULL)
  2441. return -ENODEV;
  2442. GetInodeNumberRetry:
  2443. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2444. (void **) &pSMBr);
  2445. if (rc)
  2446. return rc;
  2447. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  2448. name_len =
  2449. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  2450. PATH_MAX,nls_codepage, remap);
  2451. name_len++; /* trailing null */
  2452. name_len *= 2;
  2453. } else { /* BB improve the check for buffer overruns BB */
  2454. name_len = strnlen(searchName, PATH_MAX);
  2455. name_len++; /* trailing null */
  2456. strncpy(pSMB->FileName, searchName, name_len);
  2457. }
  2458. params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
  2459. pSMB->TotalDataCount = 0;
  2460. pSMB->MaxParameterCount = cpu_to_le16(2);
  2461. /* BB find exact max data count below from sess structure BB */
  2462. pSMB->MaxDataCount = cpu_to_le16(4000);
  2463. pSMB->MaxSetupCount = 0;
  2464. pSMB->Reserved = 0;
  2465. pSMB->Flags = 0;
  2466. pSMB->Timeout = 0;
  2467. pSMB->Reserved2 = 0;
  2468. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2469. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  2470. pSMB->DataCount = 0;
  2471. pSMB->DataOffset = 0;
  2472. pSMB->SetupCount = 1;
  2473. pSMB->Reserved3 = 0;
  2474. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  2475. byte_count = params + 1 /* pad */ ;
  2476. pSMB->TotalParameterCount = cpu_to_le16(params);
  2477. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2478. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
  2479. pSMB->Reserved4 = 0;
  2480. pSMB->hdr.smb_buf_length += byte_count;
  2481. pSMB->ByteCount = cpu_to_le16(byte_count);
  2482. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2483. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2484. if (rc) {
  2485. cFYI(1, ("error %d in QueryInternalInfo", rc));
  2486. } else {
  2487. /* decode response */
  2488. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2489. if (rc || (pSMBr->ByteCount < 2))
  2490. /* BB also check enough total bytes returned */
  2491. /* If rc should we check for EOPNOSUPP and
  2492. disable the srvino flag? or in caller? */
  2493. rc = -EIO; /* bad smb */
  2494. else {
  2495. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2496. __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
  2497. struct file_internal_info * pfinfo;
  2498. /* BB Do we need a cast or hash here ? */
  2499. if(count < 8) {
  2500. cFYI(1, ("Illegal size ret in QryIntrnlInf"));
  2501. rc = -EIO;
  2502. goto GetInodeNumOut;
  2503. }
  2504. pfinfo = (struct file_internal_info *)
  2505. (data_offset + (char *) &pSMBr->hdr.Protocol);
  2506. *inode_number = pfinfo->UniqueId;
  2507. }
  2508. }
  2509. GetInodeNumOut:
  2510. cifs_buf_release(pSMB);
  2511. if (rc == -EAGAIN)
  2512. goto GetInodeNumberRetry;
  2513. return rc;
  2514. }
  2515. #endif /* CIFS_EXPERIMENTAL */
  2516. int
  2517. CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
  2518. const unsigned char *searchName,
  2519. unsigned char **targetUNCs,
  2520. unsigned int *number_of_UNC_in_array,
  2521. const struct nls_table *nls_codepage, int remap)
  2522. {
  2523. /* TRANS2_GET_DFS_REFERRAL */
  2524. TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
  2525. TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
  2526. struct dfs_referral_level_3 * referrals = NULL;
  2527. int rc = 0;
  2528. int bytes_returned;
  2529. int name_len;
  2530. unsigned int i;
  2531. char * temp;
  2532. __u16 params, byte_count;
  2533. *number_of_UNC_in_array = 0;
  2534. *targetUNCs = NULL;
  2535. cFYI(1, ("In GetDFSRefer the path %s", searchName));
  2536. if (ses == NULL)
  2537. return -ENODEV;
  2538. getDFSRetry:
  2539. rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
  2540. (void **) &pSMBr);
  2541. if (rc)
  2542. return rc;
  2543. pSMB->hdr.Tid = ses->ipc_tid;
  2544. pSMB->hdr.Uid = ses->Suid;
  2545. if (ses->capabilities & CAP_STATUS32) {
  2546. pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
  2547. }
  2548. if (ses->capabilities & CAP_DFS) {
  2549. pSMB->hdr.Flags2 |= SMBFLG2_DFS;
  2550. }
  2551. if (ses->capabilities & CAP_UNICODE) {
  2552. pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
  2553. name_len =
  2554. cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
  2555. searchName, PATH_MAX, nls_codepage, remap);
  2556. name_len++; /* trailing null */
  2557. name_len *= 2;
  2558. } else { /* BB improve the check for buffer overruns BB */
  2559. name_len = strnlen(searchName, PATH_MAX);
  2560. name_len++; /* trailing null */
  2561. strncpy(pSMB->RequestFileName, searchName, name_len);
  2562. }
  2563. params = 2 /* level */ + name_len /*includes null */ ;
  2564. pSMB->TotalDataCount = 0;
  2565. pSMB->DataCount = 0;
  2566. pSMB->DataOffset = 0;
  2567. pSMB->MaxParameterCount = 0;
  2568. pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  2569. pSMB->MaxSetupCount = 0;
  2570. pSMB->Reserved = 0;
  2571. pSMB->Flags = 0;
  2572. pSMB->Timeout = 0;
  2573. pSMB->Reserved2 = 0;
  2574. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2575. struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
  2576. pSMB->SetupCount = 1;
  2577. pSMB->Reserved3 = 0;
  2578. pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
  2579. byte_count = params + 3 /* pad */ ;
  2580. pSMB->ParameterCount = cpu_to_le16(params);
  2581. pSMB->TotalParameterCount = pSMB->ParameterCount;
  2582. pSMB->MaxReferralLevel = cpu_to_le16(3);
  2583. pSMB->hdr.smb_buf_length += byte_count;
  2584. pSMB->ByteCount = cpu_to_le16(byte_count);
  2585. rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
  2586. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2587. if (rc) {
  2588. cFYI(1, ("Send error in GetDFSRefer = %d", rc));
  2589. } else { /* decode response */
  2590. /* BB Add logic to parse referrals here */
  2591. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2592. if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
  2593. rc = -EIO; /* bad smb */
  2594. else {
  2595. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2596. __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
  2597. cFYI(1,
  2598. ("Decoding GetDFSRefer response. BCC: %d Offset %d",
  2599. pSMBr->ByteCount, data_offset));
  2600. referrals =
  2601. (struct dfs_referral_level_3 *)
  2602. (8 /* sizeof start of data block */ +
  2603. data_offset +
  2604. (char *) &pSMBr->hdr.Protocol);
  2605. 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",
  2606. le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
  2607. /* BB This field is actually two bytes in from start of
  2608. data block so we could do safety check that DataBlock
  2609. begins at address of pSMBr->NumberOfReferrals */
  2610. *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
  2611. /* BB Fix below so can return more than one referral */
  2612. if(*number_of_UNC_in_array > 1)
  2613. *number_of_UNC_in_array = 1;
  2614. /* get the length of the strings describing refs */
  2615. name_len = 0;
  2616. for(i=0;i<*number_of_UNC_in_array;i++) {
  2617. /* make sure that DfsPathOffset not past end */
  2618. __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
  2619. if (offset > data_count) {
  2620. /* if invalid referral, stop here and do
  2621. not try to copy any more */
  2622. *number_of_UNC_in_array = i;
  2623. break;
  2624. }
  2625. temp = ((char *)referrals) + offset;
  2626. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  2627. name_len += UniStrnlen((wchar_t *)temp,data_count);
  2628. } else {
  2629. name_len += strnlen(temp,data_count);
  2630. }
  2631. referrals++;
  2632. /* BB add check that referral pointer does not fall off end PDU */
  2633. }
  2634. /* BB add check for name_len bigger than bcc */
  2635. *targetUNCs =
  2636. kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
  2637. if(*targetUNCs == NULL) {
  2638. rc = -ENOMEM;
  2639. goto GetDFSRefExit;
  2640. }
  2641. /* copy the ref strings */
  2642. referrals =
  2643. (struct dfs_referral_level_3 *)
  2644. (8 /* sizeof data hdr */ +
  2645. data_offset +
  2646. (char *) &pSMBr->hdr.Protocol);
  2647. for(i=0;i<*number_of_UNC_in_array;i++) {
  2648. temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
  2649. if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
  2650. cifs_strfromUCS_le(*targetUNCs,
  2651. (wchar_t *) temp, name_len, nls_codepage);
  2652. } else {
  2653. strncpy(*targetUNCs,temp,name_len);
  2654. }
  2655. /* BB update target_uncs pointers */
  2656. referrals++;
  2657. }
  2658. temp = *targetUNCs;
  2659. temp[name_len] = 0;
  2660. }
  2661. }
  2662. GetDFSRefExit:
  2663. if (pSMB)
  2664. cifs_buf_release(pSMB);
  2665. if (rc == -EAGAIN)
  2666. goto getDFSRetry;
  2667. return rc;
  2668. }
  2669. int
  2670. CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
  2671. {
  2672. /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
  2673. TRANSACTION2_QFSI_REQ *pSMB = NULL;
  2674. TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  2675. FILE_SYSTEM_INFO *response_data;
  2676. int rc = 0;
  2677. int bytes_returned = 0;
  2678. __u16 params, byte_count;
  2679. cFYI(1, ("In QFSInfo"));
  2680. QFSInfoRetry:
  2681. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2682. (void **) &pSMBr);
  2683. if (rc)
  2684. return rc;
  2685. params = 2; /* level */
  2686. pSMB->TotalDataCount = 0;
  2687. pSMB->MaxParameterCount = cpu_to_le16(2);
  2688. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  2689. pSMB->MaxSetupCount = 0;
  2690. pSMB->Reserved = 0;
  2691. pSMB->Flags = 0;
  2692. pSMB->Timeout = 0;
  2693. pSMB->Reserved2 = 0;
  2694. byte_count = params + 1 /* pad */ ;
  2695. pSMB->TotalParameterCount = cpu_to_le16(params);
  2696. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2697. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2698. struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  2699. pSMB->DataCount = 0;
  2700. pSMB->DataOffset = 0;
  2701. pSMB->SetupCount = 1;
  2702. pSMB->Reserved3 = 0;
  2703. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  2704. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
  2705. pSMB->hdr.smb_buf_length += byte_count;
  2706. pSMB->ByteCount = cpu_to_le16(byte_count);
  2707. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2708. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2709. if (rc) {
  2710. cERROR(1, ("Send error in QFSInfo = %d", rc));
  2711. } else { /* decode response */
  2712. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2713. if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
  2714. rc = -EIO; /* bad smb */
  2715. else {
  2716. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2717. cFYI(1,
  2718. ("Decoding qfsinfo response. BCC: %d Offset %d",
  2719. pSMBr->ByteCount, data_offset));
  2720. response_data =
  2721. (FILE_SYSTEM_INFO
  2722. *) (((char *) &pSMBr->hdr.Protocol) +
  2723. data_offset);
  2724. FSData->f_bsize =
  2725. le32_to_cpu(response_data->BytesPerSector) *
  2726. le32_to_cpu(response_data->
  2727. SectorsPerAllocationUnit);
  2728. FSData->f_blocks =
  2729. le64_to_cpu(response_data->TotalAllocationUnits);
  2730. FSData->f_bfree = FSData->f_bavail =
  2731. le64_to_cpu(response_data->FreeAllocationUnits);
  2732. cFYI(1,
  2733. ("Blocks: %lld Free: %lld Block size %ld",
  2734. (unsigned long long)FSData->f_blocks,
  2735. (unsigned long long)FSData->f_bfree,
  2736. FSData->f_bsize));
  2737. }
  2738. }
  2739. cifs_buf_release(pSMB);
  2740. if (rc == -EAGAIN)
  2741. goto QFSInfoRetry;
  2742. return rc;
  2743. }
  2744. int
  2745. CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
  2746. {
  2747. /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
  2748. TRANSACTION2_QFSI_REQ *pSMB = NULL;
  2749. TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  2750. FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
  2751. int rc = 0;
  2752. int bytes_returned = 0;
  2753. __u16 params, byte_count;
  2754. cFYI(1, ("In QFSAttributeInfo"));
  2755. QFSAttributeRetry:
  2756. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2757. (void **) &pSMBr);
  2758. if (rc)
  2759. return rc;
  2760. params = 2; /* level */
  2761. pSMB->TotalDataCount = 0;
  2762. pSMB->MaxParameterCount = cpu_to_le16(2);
  2763. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  2764. pSMB->MaxSetupCount = 0;
  2765. pSMB->Reserved = 0;
  2766. pSMB->Flags = 0;
  2767. pSMB->Timeout = 0;
  2768. pSMB->Reserved2 = 0;
  2769. byte_count = params + 1 /* pad */ ;
  2770. pSMB->TotalParameterCount = cpu_to_le16(params);
  2771. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2772. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2773. struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  2774. pSMB->DataCount = 0;
  2775. pSMB->DataOffset = 0;
  2776. pSMB->SetupCount = 1;
  2777. pSMB->Reserved3 = 0;
  2778. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  2779. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
  2780. pSMB->hdr.smb_buf_length += byte_count;
  2781. pSMB->ByteCount = cpu_to_le16(byte_count);
  2782. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2783. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2784. if (rc) {
  2785. cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
  2786. } else { /* decode response */
  2787. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2788. if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
  2789. rc = -EIO; /* bad smb */
  2790. } else {
  2791. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2792. response_data =
  2793. (FILE_SYSTEM_ATTRIBUTE_INFO
  2794. *) (((char *) &pSMBr->hdr.Protocol) +
  2795. data_offset);
  2796. memcpy(&tcon->fsAttrInfo, response_data,
  2797. sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
  2798. }
  2799. }
  2800. cifs_buf_release(pSMB);
  2801. if (rc == -EAGAIN)
  2802. goto QFSAttributeRetry;
  2803. return rc;
  2804. }
  2805. int
  2806. CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
  2807. {
  2808. /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
  2809. TRANSACTION2_QFSI_REQ *pSMB = NULL;
  2810. TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  2811. FILE_SYSTEM_DEVICE_INFO *response_data;
  2812. int rc = 0;
  2813. int bytes_returned = 0;
  2814. __u16 params, byte_count;
  2815. cFYI(1, ("In QFSDeviceInfo"));
  2816. QFSDeviceRetry:
  2817. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2818. (void **) &pSMBr);
  2819. if (rc)
  2820. return rc;
  2821. params = 2; /* level */
  2822. pSMB->TotalDataCount = 0;
  2823. pSMB->MaxParameterCount = cpu_to_le16(2);
  2824. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  2825. pSMB->MaxSetupCount = 0;
  2826. pSMB->Reserved = 0;
  2827. pSMB->Flags = 0;
  2828. pSMB->Timeout = 0;
  2829. pSMB->Reserved2 = 0;
  2830. byte_count = params + 1 /* pad */ ;
  2831. pSMB->TotalParameterCount = cpu_to_le16(params);
  2832. pSMB->ParameterCount = pSMB->TotalParameterCount;
  2833. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  2834. struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  2835. pSMB->DataCount = 0;
  2836. pSMB->DataOffset = 0;
  2837. pSMB->SetupCount = 1;
  2838. pSMB->Reserved3 = 0;
  2839. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  2840. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
  2841. pSMB->hdr.smb_buf_length += byte_count;
  2842. pSMB->ByteCount = cpu_to_le16(byte_count);
  2843. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2844. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2845. if (rc) {
  2846. cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
  2847. } else { /* decode response */
  2848. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2849. if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
  2850. rc = -EIO; /* bad smb */
  2851. else {
  2852. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2853. response_data =
  2854. (FILE_SYSTEM_DEVICE_INFO *)
  2855. (((char *) &pSMBr->hdr.Protocol) +
  2856. data_offset);
  2857. memcpy(&tcon->fsDevInfo, response_data,
  2858. sizeof (FILE_SYSTEM_DEVICE_INFO));
  2859. }
  2860. }
  2861. cifs_buf_release(pSMB);
  2862. if (rc == -EAGAIN)
  2863. goto QFSDeviceRetry;
  2864. return rc;
  2865. }
  2866. int
  2867. CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
  2868. {
  2869. /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
  2870. TRANSACTION2_QFSI_REQ *pSMB = NULL;
  2871. TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  2872. FILE_SYSTEM_UNIX_INFO *response_data;
  2873. int rc = 0;
  2874. int bytes_returned = 0;
  2875. __u16 params, byte_count;
  2876. cFYI(1, ("In QFSUnixInfo"));
  2877. QFSUnixRetry:
  2878. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2879. (void **) &pSMBr);
  2880. if (rc)
  2881. return rc;
  2882. params = 2; /* level */
  2883. pSMB->TotalDataCount = 0;
  2884. pSMB->DataCount = 0;
  2885. pSMB->DataOffset = 0;
  2886. pSMB->MaxParameterCount = cpu_to_le16(2);
  2887. pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
  2888. pSMB->MaxSetupCount = 0;
  2889. pSMB->Reserved = 0;
  2890. pSMB->Flags = 0;
  2891. pSMB->Timeout = 0;
  2892. pSMB->Reserved2 = 0;
  2893. byte_count = params + 1 /* pad */ ;
  2894. pSMB->ParameterCount = cpu_to_le16(params);
  2895. pSMB->TotalParameterCount = pSMB->ParameterCount;
  2896. pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  2897. smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  2898. pSMB->SetupCount = 1;
  2899. pSMB->Reserved3 = 0;
  2900. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  2901. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
  2902. pSMB->hdr.smb_buf_length += byte_count;
  2903. pSMB->ByteCount = cpu_to_le16(byte_count);
  2904. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2905. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2906. if (rc) {
  2907. cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
  2908. } else { /* decode response */
  2909. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2910. if (rc || (pSMBr->ByteCount < 13)) {
  2911. rc = -EIO; /* bad smb */
  2912. } else {
  2913. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2914. response_data =
  2915. (FILE_SYSTEM_UNIX_INFO
  2916. *) (((char *) &pSMBr->hdr.Protocol) +
  2917. data_offset);
  2918. memcpy(&tcon->fsUnixInfo, response_data,
  2919. sizeof (FILE_SYSTEM_UNIX_INFO));
  2920. }
  2921. }
  2922. cifs_buf_release(pSMB);
  2923. if (rc == -EAGAIN)
  2924. goto QFSUnixRetry;
  2925. return rc;
  2926. }
  2927. int
  2928. CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
  2929. struct kstatfs *FSData)
  2930. {
  2931. /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
  2932. TRANSACTION2_QFSI_REQ *pSMB = NULL;
  2933. TRANSACTION2_QFSI_RSP *pSMBr = NULL;
  2934. FILE_SYSTEM_POSIX_INFO *response_data;
  2935. int rc = 0;
  2936. int bytes_returned = 0;
  2937. __u16 params, byte_count;
  2938. cFYI(1, ("In QFSPosixInfo"));
  2939. QFSPosixRetry:
  2940. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  2941. (void **) &pSMBr);
  2942. if (rc)
  2943. return rc;
  2944. params = 2; /* level */
  2945. pSMB->TotalDataCount = 0;
  2946. pSMB->DataCount = 0;
  2947. pSMB->DataOffset = 0;
  2948. pSMB->MaxParameterCount = cpu_to_le16(2);
  2949. pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
  2950. pSMB->MaxSetupCount = 0;
  2951. pSMB->Reserved = 0;
  2952. pSMB->Flags = 0;
  2953. pSMB->Timeout = 0;
  2954. pSMB->Reserved2 = 0;
  2955. byte_count = params + 1 /* pad */ ;
  2956. pSMB->ParameterCount = cpu_to_le16(params);
  2957. pSMB->TotalParameterCount = pSMB->ParameterCount;
  2958. pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
  2959. smb_com_transaction2_qfsi_req, InformationLevel) - 4);
  2960. pSMB->SetupCount = 1;
  2961. pSMB->Reserved3 = 0;
  2962. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
  2963. pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
  2964. pSMB->hdr.smb_buf_length += byte_count;
  2965. pSMB->ByteCount = cpu_to_le16(byte_count);
  2966. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  2967. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  2968. if (rc) {
  2969. cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
  2970. } else { /* decode response */
  2971. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  2972. if (rc || (pSMBr->ByteCount < 13)) {
  2973. rc = -EIO; /* bad smb */
  2974. } else {
  2975. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  2976. response_data =
  2977. (FILE_SYSTEM_POSIX_INFO
  2978. *) (((char *) &pSMBr->hdr.Protocol) +
  2979. data_offset);
  2980. FSData->f_bsize =
  2981. le32_to_cpu(response_data->BlockSize);
  2982. FSData->f_blocks =
  2983. le64_to_cpu(response_data->TotalBlocks);
  2984. FSData->f_bfree =
  2985. le64_to_cpu(response_data->BlocksAvail);
  2986. if(response_data->UserBlocksAvail == -1) {
  2987. FSData->f_bavail = FSData->f_bfree;
  2988. } else {
  2989. FSData->f_bavail =
  2990. le64_to_cpu(response_data->UserBlocksAvail);
  2991. }
  2992. if(response_data->TotalFileNodes != -1)
  2993. FSData->f_files =
  2994. le64_to_cpu(response_data->TotalFileNodes);
  2995. if(response_data->FreeFileNodes != -1)
  2996. FSData->f_ffree =
  2997. le64_to_cpu(response_data->FreeFileNodes);
  2998. }
  2999. }
  3000. cifs_buf_release(pSMB);
  3001. if (rc == -EAGAIN)
  3002. goto QFSPosixRetry;
  3003. return rc;
  3004. }
  3005. /* We can not use write of zero bytes trick to
  3006. set file size due to need for large file support. Also note that
  3007. this SetPathInfo is preferred to SetFileInfo based method in next
  3008. routine which is only needed to work around a sharing violation bug
  3009. in Samba which this routine can run into */
  3010. int
  3011. CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
  3012. __u64 size, int SetAllocation,
  3013. const struct nls_table *nls_codepage, int remap)
  3014. {
  3015. struct smb_com_transaction2_spi_req *pSMB = NULL;
  3016. struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  3017. struct file_end_of_file_info *parm_data;
  3018. int name_len;
  3019. int rc = 0;
  3020. int bytes_returned = 0;
  3021. __u16 params, byte_count, data_count, param_offset, offset;
  3022. cFYI(1, ("In SetEOF"));
  3023. SetEOFRetry:
  3024. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3025. (void **) &pSMBr);
  3026. if (rc)
  3027. return rc;
  3028. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3029. name_len =
  3030. cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  3031. PATH_MAX, nls_codepage, remap);
  3032. name_len++; /* trailing null */
  3033. name_len *= 2;
  3034. } else { /* BB improve the check for buffer overruns BB */
  3035. name_len = strnlen(fileName, PATH_MAX);
  3036. name_len++; /* trailing null */
  3037. strncpy(pSMB->FileName, fileName, name_len);
  3038. }
  3039. params = 6 + name_len;
  3040. data_count = sizeof (struct file_end_of_file_info);
  3041. pSMB->MaxParameterCount = cpu_to_le16(2);
  3042. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
  3043. pSMB->MaxSetupCount = 0;
  3044. pSMB->Reserved = 0;
  3045. pSMB->Flags = 0;
  3046. pSMB->Timeout = 0;
  3047. pSMB->Reserved2 = 0;
  3048. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  3049. InformationLevel) - 4;
  3050. offset = param_offset + params;
  3051. if(SetAllocation) {
  3052. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3053. pSMB->InformationLevel =
  3054. cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  3055. else
  3056. pSMB->InformationLevel =
  3057. cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
  3058. } else /* Set File Size */ {
  3059. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3060. pSMB->InformationLevel =
  3061. cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
  3062. else
  3063. pSMB->InformationLevel =
  3064. cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
  3065. }
  3066. parm_data =
  3067. (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
  3068. offset);
  3069. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3070. pSMB->DataOffset = cpu_to_le16(offset);
  3071. pSMB->SetupCount = 1;
  3072. pSMB->Reserved3 = 0;
  3073. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  3074. byte_count = 3 /* pad */ + params + data_count;
  3075. pSMB->DataCount = cpu_to_le16(data_count);
  3076. pSMB->TotalDataCount = pSMB->DataCount;
  3077. pSMB->ParameterCount = cpu_to_le16(params);
  3078. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3079. pSMB->Reserved4 = 0;
  3080. pSMB->hdr.smb_buf_length += byte_count;
  3081. parm_data->FileSize = cpu_to_le64(size);
  3082. pSMB->ByteCount = cpu_to_le16(byte_count);
  3083. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3084. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3085. if (rc) {
  3086. cFYI(1, ("SetPathInfo (file size) returned %d", rc));
  3087. }
  3088. cifs_buf_release(pSMB);
  3089. if (rc == -EAGAIN)
  3090. goto SetEOFRetry;
  3091. return rc;
  3092. }
  3093. int
  3094. CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
  3095. __u16 fid, __u32 pid_of_opener, int SetAllocation)
  3096. {
  3097. struct smb_com_transaction2_sfi_req *pSMB = NULL;
  3098. struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
  3099. char *data_offset;
  3100. struct file_end_of_file_info *parm_data;
  3101. int rc = 0;
  3102. int bytes_returned = 0;
  3103. __u16 params, param_offset, offset, byte_count, count;
  3104. cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
  3105. (long long)size));
  3106. rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
  3107. if (rc)
  3108. return rc;
  3109. pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
  3110. pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
  3111. pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
  3112. params = 6;
  3113. pSMB->MaxSetupCount = 0;
  3114. pSMB->Reserved = 0;
  3115. pSMB->Flags = 0;
  3116. pSMB->Timeout = 0;
  3117. pSMB->Reserved2 = 0;
  3118. param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  3119. offset = param_offset + params;
  3120. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  3121. count = sizeof(struct file_end_of_file_info);
  3122. pSMB->MaxParameterCount = cpu_to_le16(2);
  3123. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
  3124. pSMB->SetupCount = 1;
  3125. pSMB->Reserved3 = 0;
  3126. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  3127. byte_count = 3 /* pad */ + params + count;
  3128. pSMB->DataCount = cpu_to_le16(count);
  3129. pSMB->ParameterCount = cpu_to_le16(params);
  3130. pSMB->TotalDataCount = pSMB->DataCount;
  3131. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3132. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3133. parm_data =
  3134. (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
  3135. offset);
  3136. pSMB->DataOffset = cpu_to_le16(offset);
  3137. parm_data->FileSize = cpu_to_le64(size);
  3138. pSMB->Fid = fid;
  3139. if(SetAllocation) {
  3140. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3141. pSMB->InformationLevel =
  3142. cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
  3143. else
  3144. pSMB->InformationLevel =
  3145. cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
  3146. } else /* Set File Size */ {
  3147. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3148. pSMB->InformationLevel =
  3149. cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
  3150. else
  3151. pSMB->InformationLevel =
  3152. cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
  3153. }
  3154. pSMB->Reserved4 = 0;
  3155. pSMB->hdr.smb_buf_length += byte_count;
  3156. pSMB->ByteCount = cpu_to_le16(byte_count);
  3157. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3158. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3159. if (rc) {
  3160. cFYI(1,
  3161. ("Send error in SetFileInfo (SetFileSize) = %d",
  3162. rc));
  3163. }
  3164. if (pSMB)
  3165. cifs_small_buf_release(pSMB);
  3166. /* Note: On -EAGAIN error only caller can retry on handle based calls
  3167. since file handle passed in no longer valid */
  3168. return rc;
  3169. }
  3170. /* Some legacy servers such as NT4 require that the file times be set on
  3171. an open handle, rather than by pathname - this is awkward due to
  3172. potential access conflicts on the open, but it is unavoidable for these
  3173. old servers since the only other choice is to go from 100 nanosecond DCE
  3174. time and resort to the original setpathinfo level which takes the ancient
  3175. DOS time format with 2 second granularity */
  3176. int
  3177. CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
  3178. __u16 fid)
  3179. {
  3180. struct smb_com_transaction2_sfi_req *pSMB = NULL;
  3181. struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
  3182. char *data_offset;
  3183. int rc = 0;
  3184. int bytes_returned = 0;
  3185. __u16 params, param_offset, offset, byte_count, count;
  3186. cFYI(1, ("Set Times (via SetFileInfo)"));
  3187. rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
  3188. if (rc)
  3189. return rc;
  3190. pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
  3191. /* At this point there is no need to override the current pid
  3192. with the pid of the opener, but that could change if we someday
  3193. use an existing handle (rather than opening one on the fly) */
  3194. /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
  3195. pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
  3196. params = 6;
  3197. pSMB->MaxSetupCount = 0;
  3198. pSMB->Reserved = 0;
  3199. pSMB->Flags = 0;
  3200. pSMB->Timeout = 0;
  3201. pSMB->Reserved2 = 0;
  3202. param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
  3203. offset = param_offset + params;
  3204. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  3205. count = sizeof (FILE_BASIC_INFO);
  3206. pSMB->MaxParameterCount = cpu_to_le16(2);
  3207. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
  3208. pSMB->SetupCount = 1;
  3209. pSMB->Reserved3 = 0;
  3210. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
  3211. byte_count = 3 /* pad */ + params + count;
  3212. pSMB->DataCount = cpu_to_le16(count);
  3213. pSMB->ParameterCount = cpu_to_le16(params);
  3214. pSMB->TotalDataCount = pSMB->DataCount;
  3215. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3216. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3217. pSMB->DataOffset = cpu_to_le16(offset);
  3218. pSMB->Fid = fid;
  3219. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3220. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
  3221. else
  3222. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
  3223. pSMB->Reserved4 = 0;
  3224. pSMB->hdr.smb_buf_length += byte_count;
  3225. pSMB->ByteCount = cpu_to_le16(byte_count);
  3226. memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
  3227. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3228. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3229. if (rc) {
  3230. cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
  3231. }
  3232. cifs_small_buf_release(pSMB);
  3233. /* Note: On -EAGAIN error only caller can retry on handle based calls
  3234. since file handle passed in no longer valid */
  3235. return rc;
  3236. }
  3237. int
  3238. CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
  3239. const FILE_BASIC_INFO * data,
  3240. const struct nls_table *nls_codepage, int remap)
  3241. {
  3242. TRANSACTION2_SPI_REQ *pSMB = NULL;
  3243. TRANSACTION2_SPI_RSP *pSMBr = NULL;
  3244. int name_len;
  3245. int rc = 0;
  3246. int bytes_returned = 0;
  3247. char *data_offset;
  3248. __u16 params, param_offset, offset, byte_count, count;
  3249. cFYI(1, ("In SetTimes"));
  3250. SetTimesRetry:
  3251. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3252. (void **) &pSMBr);
  3253. if (rc)
  3254. return rc;
  3255. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3256. name_len =
  3257. cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  3258. PATH_MAX, nls_codepage, remap);
  3259. name_len++; /* trailing null */
  3260. name_len *= 2;
  3261. } else { /* BB improve the check for buffer overruns BB */
  3262. name_len = strnlen(fileName, PATH_MAX);
  3263. name_len++; /* trailing null */
  3264. strncpy(pSMB->FileName, fileName, name_len);
  3265. }
  3266. params = 6 + name_len;
  3267. count = sizeof (FILE_BASIC_INFO);
  3268. pSMB->MaxParameterCount = cpu_to_le16(2);
  3269. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  3270. pSMB->MaxSetupCount = 0;
  3271. pSMB->Reserved = 0;
  3272. pSMB->Flags = 0;
  3273. pSMB->Timeout = 0;
  3274. pSMB->Reserved2 = 0;
  3275. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  3276. InformationLevel) - 4;
  3277. offset = param_offset + params;
  3278. data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
  3279. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3280. pSMB->DataOffset = cpu_to_le16(offset);
  3281. pSMB->SetupCount = 1;
  3282. pSMB->Reserved3 = 0;
  3283. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  3284. byte_count = 3 /* pad */ + params + count;
  3285. pSMB->DataCount = cpu_to_le16(count);
  3286. pSMB->ParameterCount = cpu_to_le16(params);
  3287. pSMB->TotalDataCount = pSMB->DataCount;
  3288. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3289. if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
  3290. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
  3291. else
  3292. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
  3293. pSMB->Reserved4 = 0;
  3294. pSMB->hdr.smb_buf_length += byte_count;
  3295. memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
  3296. pSMB->ByteCount = cpu_to_le16(byte_count);
  3297. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3298. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3299. if (rc) {
  3300. cFYI(1, ("SetPathInfo (times) returned %d", rc));
  3301. }
  3302. cifs_buf_release(pSMB);
  3303. if (rc == -EAGAIN)
  3304. goto SetTimesRetry;
  3305. return rc;
  3306. }
  3307. /* Can not be used to set time stamps yet (due to old DOS time format) */
  3308. /* Can be used to set attributes */
  3309. #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
  3310. handling it anyway and NT4 was what we thought it would be needed for
  3311. Do not delete it until we prove whether needed for Win9x though */
  3312. int
  3313. CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
  3314. __u16 dos_attrs, const struct nls_table *nls_codepage)
  3315. {
  3316. SETATTR_REQ *pSMB = NULL;
  3317. SETATTR_RSP *pSMBr = NULL;
  3318. int rc = 0;
  3319. int bytes_returned;
  3320. int name_len;
  3321. cFYI(1, ("In SetAttrLegacy"));
  3322. SetAttrLgcyRetry:
  3323. rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
  3324. (void **) &pSMBr);
  3325. if (rc)
  3326. return rc;
  3327. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3328. name_len =
  3329. ConvertToUCS((__le16 *) pSMB->fileName, fileName,
  3330. PATH_MAX, nls_codepage);
  3331. name_len++; /* trailing null */
  3332. name_len *= 2;
  3333. } else { /* BB improve the check for buffer overruns BB */
  3334. name_len = strnlen(fileName, PATH_MAX);
  3335. name_len++; /* trailing null */
  3336. strncpy(pSMB->fileName, fileName, name_len);
  3337. }
  3338. pSMB->attr = cpu_to_le16(dos_attrs);
  3339. pSMB->BufferFormat = 0x04;
  3340. pSMB->hdr.smb_buf_length += name_len + 1;
  3341. pSMB->ByteCount = cpu_to_le16(name_len + 1);
  3342. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3343. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3344. if (rc) {
  3345. cFYI(1, ("Error in LegacySetAttr = %d", rc));
  3346. }
  3347. cifs_buf_release(pSMB);
  3348. if (rc == -EAGAIN)
  3349. goto SetAttrLgcyRetry;
  3350. return rc;
  3351. }
  3352. #endif /* temporarily unneeded SetAttr legacy function */
  3353. int
  3354. CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
  3355. char *fileName, __u64 mode, __u64 uid, __u64 gid,
  3356. dev_t device, const struct nls_table *nls_codepage,
  3357. int remap)
  3358. {
  3359. TRANSACTION2_SPI_REQ *pSMB = NULL;
  3360. TRANSACTION2_SPI_RSP *pSMBr = NULL;
  3361. int name_len;
  3362. int rc = 0;
  3363. int bytes_returned = 0;
  3364. FILE_UNIX_BASIC_INFO *data_offset;
  3365. __u16 params, param_offset, offset, count, byte_count;
  3366. cFYI(1, ("In SetUID/GID/Mode"));
  3367. setPermsRetry:
  3368. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3369. (void **) &pSMBr);
  3370. if (rc)
  3371. return rc;
  3372. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3373. name_len =
  3374. cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  3375. PATH_MAX, nls_codepage, remap);
  3376. name_len++; /* trailing null */
  3377. name_len *= 2;
  3378. } else { /* BB improve the check for buffer overruns BB */
  3379. name_len = strnlen(fileName, PATH_MAX);
  3380. name_len++; /* trailing null */
  3381. strncpy(pSMB->FileName, fileName, name_len);
  3382. }
  3383. params = 6 + name_len;
  3384. count = sizeof (FILE_UNIX_BASIC_INFO);
  3385. pSMB->MaxParameterCount = cpu_to_le16(2);
  3386. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
  3387. pSMB->MaxSetupCount = 0;
  3388. pSMB->Reserved = 0;
  3389. pSMB->Flags = 0;
  3390. pSMB->Timeout = 0;
  3391. pSMB->Reserved2 = 0;
  3392. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  3393. InformationLevel) - 4;
  3394. offset = param_offset + params;
  3395. data_offset =
  3396. (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
  3397. offset);
  3398. memset(data_offset, 0, count);
  3399. pSMB->DataOffset = cpu_to_le16(offset);
  3400. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3401. pSMB->SetupCount = 1;
  3402. pSMB->Reserved3 = 0;
  3403. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  3404. byte_count = 3 /* pad */ + params + count;
  3405. pSMB->ParameterCount = cpu_to_le16(params);
  3406. pSMB->DataCount = cpu_to_le16(count);
  3407. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3408. pSMB->TotalDataCount = pSMB->DataCount;
  3409. pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
  3410. pSMB->Reserved4 = 0;
  3411. pSMB->hdr.smb_buf_length += byte_count;
  3412. data_offset->Uid = cpu_to_le64(uid);
  3413. data_offset->Gid = cpu_to_le64(gid);
  3414. /* better to leave device as zero when it is */
  3415. data_offset->DevMajor = cpu_to_le64(MAJOR(device));
  3416. data_offset->DevMinor = cpu_to_le64(MINOR(device));
  3417. data_offset->Permissions = cpu_to_le64(mode);
  3418. if(S_ISREG(mode))
  3419. data_offset->Type = cpu_to_le32(UNIX_FILE);
  3420. else if(S_ISDIR(mode))
  3421. data_offset->Type = cpu_to_le32(UNIX_DIR);
  3422. else if(S_ISLNK(mode))
  3423. data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
  3424. else if(S_ISCHR(mode))
  3425. data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
  3426. else if(S_ISBLK(mode))
  3427. data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
  3428. else if(S_ISFIFO(mode))
  3429. data_offset->Type = cpu_to_le32(UNIX_FIFO);
  3430. else if(S_ISSOCK(mode))
  3431. data_offset->Type = cpu_to_le32(UNIX_SOCKET);
  3432. pSMB->ByteCount = cpu_to_le16(byte_count);
  3433. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3434. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3435. if (rc) {
  3436. cFYI(1, ("SetPathInfo (perms) returned %d", rc));
  3437. }
  3438. if (pSMB)
  3439. cifs_buf_release(pSMB);
  3440. if (rc == -EAGAIN)
  3441. goto setPermsRetry;
  3442. return rc;
  3443. }
  3444. int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
  3445. const int notify_subdirs, const __u16 netfid,
  3446. __u32 filter, const struct nls_table *nls_codepage)
  3447. {
  3448. int rc = 0;
  3449. struct smb_com_transaction_change_notify_req * pSMB = NULL;
  3450. struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
  3451. int bytes_returned;
  3452. cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
  3453. rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
  3454. (void **) &pSMBr);
  3455. if (rc)
  3456. return rc;
  3457. pSMB->TotalParameterCount = 0 ;
  3458. pSMB->TotalDataCount = 0;
  3459. pSMB->MaxParameterCount = cpu_to_le32(2);
  3460. /* BB find exact data count max from sess structure BB */
  3461. pSMB->MaxDataCount = 0; /* same in little endian or be */
  3462. pSMB->MaxSetupCount = 4;
  3463. pSMB->Reserved = 0;
  3464. pSMB->ParameterOffset = 0;
  3465. pSMB->DataCount = 0;
  3466. pSMB->DataOffset = 0;
  3467. pSMB->SetupCount = 4; /* single byte does not need le conversion */
  3468. pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
  3469. pSMB->ParameterCount = pSMB->TotalParameterCount;
  3470. if(notify_subdirs)
  3471. pSMB->WatchTree = 1; /* one byte - no le conversion needed */
  3472. pSMB->Reserved2 = 0;
  3473. pSMB->CompletionFilter = cpu_to_le32(filter);
  3474. pSMB->Fid = netfid; /* file handle always le */
  3475. pSMB->ByteCount = 0;
  3476. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3477. (struct smb_hdr *) pSMBr, &bytes_returned, -1);
  3478. if (rc) {
  3479. cFYI(1, ("Error in Notify = %d", rc));
  3480. }
  3481. cifs_buf_release(pSMB);
  3482. return rc;
  3483. }
  3484. #ifdef CONFIG_CIFS_XATTR
  3485. ssize_t
  3486. CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
  3487. const unsigned char *searchName,
  3488. char * EAData, size_t buf_size,
  3489. const struct nls_table *nls_codepage, int remap)
  3490. {
  3491. /* BB assumes one setup word */
  3492. TRANSACTION2_QPI_REQ *pSMB = NULL;
  3493. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  3494. int rc = 0;
  3495. int bytes_returned;
  3496. int name_len;
  3497. struct fea * temp_fea;
  3498. char * temp_ptr;
  3499. __u16 params, byte_count;
  3500. cFYI(1, ("In Query All EAs path %s", searchName));
  3501. QAllEAsRetry:
  3502. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3503. (void **) &pSMBr);
  3504. if (rc)
  3505. return rc;
  3506. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3507. name_len =
  3508. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  3509. PATH_MAX, nls_codepage, remap);
  3510. name_len++; /* trailing null */
  3511. name_len *= 2;
  3512. } else { /* BB improve the check for buffer overruns BB */
  3513. name_len = strnlen(searchName, PATH_MAX);
  3514. name_len++; /* trailing null */
  3515. strncpy(pSMB->FileName, searchName, name_len);
  3516. }
  3517. params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
  3518. pSMB->TotalDataCount = 0;
  3519. pSMB->MaxParameterCount = cpu_to_le16(2);
  3520. pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  3521. pSMB->MaxSetupCount = 0;
  3522. pSMB->Reserved = 0;
  3523. pSMB->Flags = 0;
  3524. pSMB->Timeout = 0;
  3525. pSMB->Reserved2 = 0;
  3526. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  3527. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  3528. pSMB->DataCount = 0;
  3529. pSMB->DataOffset = 0;
  3530. pSMB->SetupCount = 1;
  3531. pSMB->Reserved3 = 0;
  3532. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  3533. byte_count = params + 1 /* pad */ ;
  3534. pSMB->TotalParameterCount = cpu_to_le16(params);
  3535. pSMB->ParameterCount = pSMB->TotalParameterCount;
  3536. pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
  3537. pSMB->Reserved4 = 0;
  3538. pSMB->hdr.smb_buf_length += byte_count;
  3539. pSMB->ByteCount = cpu_to_le16(byte_count);
  3540. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3541. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3542. if (rc) {
  3543. cFYI(1, ("Send error in QueryAllEAs = %d", rc));
  3544. } else { /* decode response */
  3545. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  3546. /* BB also check enough total bytes returned */
  3547. /* BB we need to improve the validity checking
  3548. of these trans2 responses */
  3549. if (rc || (pSMBr->ByteCount < 4))
  3550. rc = -EIO; /* bad smb */
  3551. /* else if (pFindData){
  3552. memcpy((char *) pFindData,
  3553. (char *) &pSMBr->hdr.Protocol +
  3554. data_offset, kl);
  3555. }*/ else {
  3556. /* check that length of list is not more than bcc */
  3557. /* check that each entry does not go beyond length
  3558. of list */
  3559. /* check that each element of each entry does not
  3560. go beyond end of list */
  3561. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  3562. struct fealist * ea_response_data;
  3563. rc = 0;
  3564. /* validate_trans2_offsets() */
  3565. /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
  3566. ea_response_data = (struct fealist *)
  3567. (((char *) &pSMBr->hdr.Protocol) +
  3568. data_offset);
  3569. name_len = le32_to_cpu(ea_response_data->list_len);
  3570. cFYI(1,("ea length %d", name_len));
  3571. if(name_len <= 8) {
  3572. /* returned EA size zeroed at top of function */
  3573. cFYI(1,("empty EA list returned from server"));
  3574. } else {
  3575. /* account for ea list len */
  3576. name_len -= 4;
  3577. temp_fea = ea_response_data->list;
  3578. temp_ptr = (char *)temp_fea;
  3579. while(name_len > 0) {
  3580. __u16 value_len;
  3581. name_len -= 4;
  3582. temp_ptr += 4;
  3583. rc += temp_fea->name_len;
  3584. /* account for prefix user. and trailing null */
  3585. rc = rc + 5 + 1;
  3586. if(rc<(int)buf_size) {
  3587. memcpy(EAData,"user.",5);
  3588. EAData+=5;
  3589. memcpy(EAData,temp_ptr,temp_fea->name_len);
  3590. EAData+=temp_fea->name_len;
  3591. /* null terminate name */
  3592. *EAData = 0;
  3593. EAData = EAData + 1;
  3594. } else if(buf_size == 0) {
  3595. /* skip copy - calc size only */
  3596. } else {
  3597. /* stop before overrun buffer */
  3598. rc = -ERANGE;
  3599. break;
  3600. }
  3601. name_len -= temp_fea->name_len;
  3602. temp_ptr += temp_fea->name_len;
  3603. /* account for trailing null */
  3604. name_len--;
  3605. temp_ptr++;
  3606. value_len = le16_to_cpu(temp_fea->value_len);
  3607. name_len -= value_len;
  3608. temp_ptr += value_len;
  3609. /* BB check that temp_ptr is still within smb BB*/
  3610. /* no trailing null to account for in value len */
  3611. /* go on to next EA */
  3612. temp_fea = (struct fea *)temp_ptr;
  3613. }
  3614. }
  3615. }
  3616. }
  3617. if (pSMB)
  3618. cifs_buf_release(pSMB);
  3619. if (rc == -EAGAIN)
  3620. goto QAllEAsRetry;
  3621. return (ssize_t)rc;
  3622. }
  3623. ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
  3624. const unsigned char * searchName,const unsigned char * ea_name,
  3625. unsigned char * ea_value, size_t buf_size,
  3626. const struct nls_table *nls_codepage, int remap)
  3627. {
  3628. TRANSACTION2_QPI_REQ *pSMB = NULL;
  3629. TRANSACTION2_QPI_RSP *pSMBr = NULL;
  3630. int rc = 0;
  3631. int bytes_returned;
  3632. int name_len;
  3633. struct fea * temp_fea;
  3634. char * temp_ptr;
  3635. __u16 params, byte_count;
  3636. cFYI(1, ("In Query EA path %s", searchName));
  3637. QEARetry:
  3638. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3639. (void **) &pSMBr);
  3640. if (rc)
  3641. return rc;
  3642. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3643. name_len =
  3644. cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
  3645. PATH_MAX, nls_codepage, remap);
  3646. name_len++; /* trailing null */
  3647. name_len *= 2;
  3648. } else { /* BB improve the check for buffer overruns BB */
  3649. name_len = strnlen(searchName, PATH_MAX);
  3650. name_len++; /* trailing null */
  3651. strncpy(pSMB->FileName, searchName, name_len);
  3652. }
  3653. params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
  3654. pSMB->TotalDataCount = 0;
  3655. pSMB->MaxParameterCount = cpu_to_le16(2);
  3656. pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
  3657. pSMB->MaxSetupCount = 0;
  3658. pSMB->Reserved = 0;
  3659. pSMB->Flags = 0;
  3660. pSMB->Timeout = 0;
  3661. pSMB->Reserved2 = 0;
  3662. pSMB->ParameterOffset = cpu_to_le16(offsetof(
  3663. struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
  3664. pSMB->DataCount = 0;
  3665. pSMB->DataOffset = 0;
  3666. pSMB->SetupCount = 1;
  3667. pSMB->Reserved3 = 0;
  3668. pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
  3669. byte_count = params + 1 /* pad */ ;
  3670. pSMB->TotalParameterCount = cpu_to_le16(params);
  3671. pSMB->ParameterCount = pSMB->TotalParameterCount;
  3672. pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
  3673. pSMB->Reserved4 = 0;
  3674. pSMB->hdr.smb_buf_length += byte_count;
  3675. pSMB->ByteCount = cpu_to_le16(byte_count);
  3676. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3677. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3678. if (rc) {
  3679. cFYI(1, ("Send error in Query EA = %d", rc));
  3680. } else { /* decode response */
  3681. rc = validate_t2((struct smb_t2_rsp *)pSMBr);
  3682. /* BB also check enough total bytes returned */
  3683. /* BB we need to improve the validity checking
  3684. of these trans2 responses */
  3685. if (rc || (pSMBr->ByteCount < 4))
  3686. rc = -EIO; /* bad smb */
  3687. /* else if (pFindData){
  3688. memcpy((char *) pFindData,
  3689. (char *) &pSMBr->hdr.Protocol +
  3690. data_offset, kl);
  3691. }*/ else {
  3692. /* check that length of list is not more than bcc */
  3693. /* check that each entry does not go beyond length
  3694. of list */
  3695. /* check that each element of each entry does not
  3696. go beyond end of list */
  3697. __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
  3698. struct fealist * ea_response_data;
  3699. rc = -ENODATA;
  3700. /* validate_trans2_offsets() */
  3701. /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
  3702. ea_response_data = (struct fealist *)
  3703. (((char *) &pSMBr->hdr.Protocol) +
  3704. data_offset);
  3705. name_len = le32_to_cpu(ea_response_data->list_len);
  3706. cFYI(1,("ea length %d", name_len));
  3707. if(name_len <= 8) {
  3708. /* returned EA size zeroed at top of function */
  3709. cFYI(1,("empty EA list returned from server"));
  3710. } else {
  3711. /* account for ea list len */
  3712. name_len -= 4;
  3713. temp_fea = ea_response_data->list;
  3714. temp_ptr = (char *)temp_fea;
  3715. /* loop through checking if we have a matching
  3716. name and then return the associated value */
  3717. while(name_len > 0) {
  3718. __u16 value_len;
  3719. name_len -= 4;
  3720. temp_ptr += 4;
  3721. value_len = le16_to_cpu(temp_fea->value_len);
  3722. /* BB validate that value_len falls within SMB,
  3723. even though maximum for name_len is 255 */
  3724. if(memcmp(temp_fea->name,ea_name,
  3725. temp_fea->name_len) == 0) {
  3726. /* found a match */
  3727. rc = value_len;
  3728. /* account for prefix user. and trailing null */
  3729. if(rc<=(int)buf_size) {
  3730. memcpy(ea_value,
  3731. temp_fea->name+temp_fea->name_len+1,
  3732. rc);
  3733. /* ea values, unlike ea names,
  3734. are not null terminated */
  3735. } else if(buf_size == 0) {
  3736. /* skip copy - calc size only */
  3737. } else {
  3738. /* stop before overrun buffer */
  3739. rc = -ERANGE;
  3740. }
  3741. break;
  3742. }
  3743. name_len -= temp_fea->name_len;
  3744. temp_ptr += temp_fea->name_len;
  3745. /* account for trailing null */
  3746. name_len--;
  3747. temp_ptr++;
  3748. name_len -= value_len;
  3749. temp_ptr += value_len;
  3750. /* no trailing null to account for in value len */
  3751. /* go on to next EA */
  3752. temp_fea = (struct fea *)temp_ptr;
  3753. }
  3754. }
  3755. }
  3756. }
  3757. if (pSMB)
  3758. cifs_buf_release(pSMB);
  3759. if (rc == -EAGAIN)
  3760. goto QEARetry;
  3761. return (ssize_t)rc;
  3762. }
  3763. int
  3764. CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
  3765. const char * ea_name, const void * ea_value,
  3766. const __u16 ea_value_len, const struct nls_table *nls_codepage,
  3767. int remap)
  3768. {
  3769. struct smb_com_transaction2_spi_req *pSMB = NULL;
  3770. struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
  3771. struct fealist *parm_data;
  3772. int name_len;
  3773. int rc = 0;
  3774. int bytes_returned = 0;
  3775. __u16 params, param_offset, byte_count, offset, count;
  3776. cFYI(1, ("In SetEA"));
  3777. SetEARetry:
  3778. rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
  3779. (void **) &pSMBr);
  3780. if (rc)
  3781. return rc;
  3782. if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
  3783. name_len =
  3784. cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
  3785. PATH_MAX, nls_codepage, remap);
  3786. name_len++; /* trailing null */
  3787. name_len *= 2;
  3788. } else { /* BB improve the check for buffer overruns BB */
  3789. name_len = strnlen(fileName, PATH_MAX);
  3790. name_len++; /* trailing null */
  3791. strncpy(pSMB->FileName, fileName, name_len);
  3792. }
  3793. params = 6 + name_len;
  3794. /* done calculating parms using name_len of file name,
  3795. now use name_len to calculate length of ea name
  3796. we are going to create in the inode xattrs */
  3797. if(ea_name == NULL)
  3798. name_len = 0;
  3799. else
  3800. name_len = strnlen(ea_name,255);
  3801. count = sizeof(*parm_data) + ea_value_len + name_len + 1;
  3802. pSMB->MaxParameterCount = cpu_to_le16(2);
  3803. pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
  3804. pSMB->MaxSetupCount = 0;
  3805. pSMB->Reserved = 0;
  3806. pSMB->Flags = 0;
  3807. pSMB->Timeout = 0;
  3808. pSMB->Reserved2 = 0;
  3809. param_offset = offsetof(struct smb_com_transaction2_spi_req,
  3810. InformationLevel) - 4;
  3811. offset = param_offset + params;
  3812. pSMB->InformationLevel =
  3813. cpu_to_le16(SMB_SET_FILE_EA);
  3814. parm_data =
  3815. (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
  3816. offset);
  3817. pSMB->ParameterOffset = cpu_to_le16(param_offset);
  3818. pSMB->DataOffset = cpu_to_le16(offset);
  3819. pSMB->SetupCount = 1;
  3820. pSMB->Reserved3 = 0;
  3821. pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
  3822. byte_count = 3 /* pad */ + params + count;
  3823. pSMB->DataCount = cpu_to_le16(count);
  3824. parm_data->list_len = cpu_to_le32(count);
  3825. parm_data->list[0].EA_flags = 0;
  3826. /* we checked above that name len is less than 255 */
  3827. parm_data->list[0].name_len = (__u8)name_len;;
  3828. /* EA names are always ASCII */
  3829. if(ea_name)
  3830. strncpy(parm_data->list[0].name,ea_name,name_len);
  3831. parm_data->list[0].name[name_len] = 0;
  3832. parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
  3833. /* caller ensures that ea_value_len is less than 64K but
  3834. we need to ensure that it fits within the smb */
  3835. /*BB add length check that it would fit in negotiated SMB buffer size BB */
  3836. /* if(ea_value_len > buffer_size - 512 (enough for header)) */
  3837. if(ea_value_len)
  3838. memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
  3839. pSMB->TotalDataCount = pSMB->DataCount;
  3840. pSMB->ParameterCount = cpu_to_le16(params);
  3841. pSMB->TotalParameterCount = pSMB->ParameterCount;
  3842. pSMB->Reserved4 = 0;
  3843. pSMB->hdr.smb_buf_length += byte_count;
  3844. pSMB->ByteCount = cpu_to_le16(byte_count);
  3845. rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
  3846. (struct smb_hdr *) pSMBr, &bytes_returned, 0);
  3847. if (rc) {
  3848. cFYI(1, ("SetPathInfo (EA) returned %d", rc));
  3849. }
  3850. cifs_buf_release(pSMB);
  3851. if (rc == -EAGAIN)
  3852. goto SetEARetry;
  3853. return rc;
  3854. }
  3855. #endif