nfs_subs.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  1. /* $OpenBSD: nfs_subs.c,v 1.128 2015/06/16 11:09:40 mpi Exp $ */
  2. /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */
  3. /*
  4. * Copyright (c) 1989, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * This code is derived from software contributed to Berkeley by
  8. * Rick Macklem at The University of Guelph.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
  35. */
  36. /*
  37. * These functions support the macros and help fiddle mbuf chains for
  38. * the nfs op functions. They do things like create the rpc header and
  39. * copy data between mbuf chains and uio lists.
  40. */
  41. #include <sys/param.h>
  42. #include <sys/systm.h>
  43. #include <sys/kernel.h>
  44. #include <sys/mount.h>
  45. #include <sys/vnode.h>
  46. #include <sys/namei.h>
  47. #include <sys/mbuf.h>
  48. #include <sys/socket.h>
  49. #include <sys/socketvar.h>
  50. #include <sys/stat.h>
  51. #include <sys/pool.h>
  52. #include <sys/time.h>
  53. #include <nfs/rpcv2.h>
  54. #include <nfs/nfsproto.h>
  55. #include <nfs/nfsnode.h>
  56. #include <nfs/nfs.h>
  57. #include <nfs/xdr_subs.h>
  58. #include <nfs/nfsm_subs.h>
  59. #include <nfs/nfsmount.h>
  60. #include <nfs/nfs_var.h>
  61. #include <uvm/uvm_extern.h>
  62. #include <netinet/in.h>
  63. #include <crypto/idgen.h>
  64. int nfs_attrtimeo(struct nfsnode *np);
  65. /*
  66. * Data items converted to xdr at startup, since they are constant
  67. * This is kinda hokey, but may save a little time doing byte swaps
  68. */
  69. u_int32_t nfs_xdrneg1;
  70. u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
  71. rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
  72. u_int32_t nfs_prog, nfs_true, nfs_false;
  73. /* And other global data */
  74. nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
  75. NFCHR, NFNON };
  76. nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
  77. NFFIFO, NFNON };
  78. enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
  79. enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
  80. int nfs_ticks;
  81. struct nfsstats nfsstats;
  82. /*
  83. * Mapping of old NFS Version 2 RPC numbers to generic numbers.
  84. */
  85. int nfsv3_procid[NFS_NPROCS] = {
  86. NFSPROC_NULL,
  87. NFSPROC_GETATTR,
  88. NFSPROC_SETATTR,
  89. NFSPROC_NOOP,
  90. NFSPROC_LOOKUP,
  91. NFSPROC_READLINK,
  92. NFSPROC_READ,
  93. NFSPROC_NOOP,
  94. NFSPROC_WRITE,
  95. NFSPROC_CREATE,
  96. NFSPROC_REMOVE,
  97. NFSPROC_RENAME,
  98. NFSPROC_LINK,
  99. NFSPROC_SYMLINK,
  100. NFSPROC_MKDIR,
  101. NFSPROC_RMDIR,
  102. NFSPROC_READDIR,
  103. NFSPROC_FSSTAT,
  104. NFSPROC_NOOP,
  105. NFSPROC_NOOP,
  106. NFSPROC_NOOP,
  107. NFSPROC_NOOP,
  108. NFSPROC_NOOP
  109. };
  110. /*
  111. * and the reverse mapping from generic to Version 2 procedure numbers
  112. */
  113. int nfsv2_procid[NFS_NPROCS] = {
  114. NFSV2PROC_NULL,
  115. NFSV2PROC_GETATTR,
  116. NFSV2PROC_SETATTR,
  117. NFSV2PROC_LOOKUP,
  118. NFSV2PROC_NOOP,
  119. NFSV2PROC_READLINK,
  120. NFSV2PROC_READ,
  121. NFSV2PROC_WRITE,
  122. NFSV2PROC_CREATE,
  123. NFSV2PROC_MKDIR,
  124. NFSV2PROC_SYMLINK,
  125. NFSV2PROC_CREATE,
  126. NFSV2PROC_REMOVE,
  127. NFSV2PROC_RMDIR,
  128. NFSV2PROC_RENAME,
  129. NFSV2PROC_LINK,
  130. NFSV2PROC_READDIR,
  131. NFSV2PROC_NOOP,
  132. NFSV2PROC_STATFS,
  133. NFSV2PROC_NOOP,
  134. NFSV2PROC_NOOP,
  135. NFSV2PROC_NOOP,
  136. NFSV2PROC_NOOP
  137. };
  138. /*
  139. * Maps errno values to nfs error numbers.
  140. * Use NFSERR_IO as the catch all for ones not specifically defined in
  141. * RFC 1094.
  142. */
  143. static u_char nfsrv_v2errmap[] = {
  144. NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  145. NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  146. NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
  147. NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
  148. NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  149. NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
  150. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  151. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  152. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  153. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  154. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  155. NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
  156. NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
  157. NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE
  158. /* Everything after this maps to NFSERR_IO, so far */
  159. };
  160. /*
  161. * Maps errno values to nfs error numbers.
  162. * Although it is not obvious whether or not NFS clients really care if
  163. * a returned error value is in the specified list for the procedure, the
  164. * safest thing to do is filter them appropriately. For Version 2, the
  165. * X/Open XNFS document is the only specification that defines error values
  166. * for each RPC (The RFC simply lists all possible error values for all RPCs),
  167. * so I have decided to not do this for Version 2.
  168. * The first entry is the default error return and the rest are the valid
  169. * errors for that RPC in increasing numeric order.
  170. */
  171. static short nfsv3err_null[] = {
  172. 0,
  173. 0,
  174. };
  175. static short nfsv3err_getattr[] = {
  176. NFSERR_IO,
  177. NFSERR_IO,
  178. NFSERR_STALE,
  179. NFSERR_BADHANDLE,
  180. NFSERR_SERVERFAULT,
  181. 0,
  182. };
  183. static short nfsv3err_setattr[] = {
  184. NFSERR_IO,
  185. NFSERR_PERM,
  186. NFSERR_IO,
  187. NFSERR_ACCES,
  188. NFSERR_INVAL,
  189. NFSERR_NOSPC,
  190. NFSERR_ROFS,
  191. NFSERR_DQUOT,
  192. NFSERR_STALE,
  193. NFSERR_BADHANDLE,
  194. NFSERR_NOT_SYNC,
  195. NFSERR_SERVERFAULT,
  196. 0,
  197. };
  198. static short nfsv3err_lookup[] = {
  199. NFSERR_IO,
  200. NFSERR_NOENT,
  201. NFSERR_IO,
  202. NFSERR_ACCES,
  203. NFSERR_NOTDIR,
  204. NFSERR_NAMETOL,
  205. NFSERR_STALE,
  206. NFSERR_BADHANDLE,
  207. NFSERR_SERVERFAULT,
  208. 0,
  209. };
  210. static short nfsv3err_access[] = {
  211. NFSERR_IO,
  212. NFSERR_IO,
  213. NFSERR_STALE,
  214. NFSERR_BADHANDLE,
  215. NFSERR_SERVERFAULT,
  216. 0,
  217. };
  218. static short nfsv3err_readlink[] = {
  219. NFSERR_IO,
  220. NFSERR_IO,
  221. NFSERR_ACCES,
  222. NFSERR_INVAL,
  223. NFSERR_STALE,
  224. NFSERR_BADHANDLE,
  225. NFSERR_NOTSUPP,
  226. NFSERR_SERVERFAULT,
  227. 0,
  228. };
  229. static short nfsv3err_read[] = {
  230. NFSERR_IO,
  231. NFSERR_IO,
  232. NFSERR_NXIO,
  233. NFSERR_ACCES,
  234. NFSERR_INVAL,
  235. NFSERR_STALE,
  236. NFSERR_BADHANDLE,
  237. NFSERR_SERVERFAULT,
  238. 0,
  239. };
  240. static short nfsv3err_write[] = {
  241. NFSERR_IO,
  242. NFSERR_IO,
  243. NFSERR_ACCES,
  244. NFSERR_INVAL,
  245. NFSERR_FBIG,
  246. NFSERR_NOSPC,
  247. NFSERR_ROFS,
  248. NFSERR_DQUOT,
  249. NFSERR_STALE,
  250. NFSERR_BADHANDLE,
  251. NFSERR_SERVERFAULT,
  252. 0,
  253. };
  254. static short nfsv3err_create[] = {
  255. NFSERR_IO,
  256. NFSERR_IO,
  257. NFSERR_ACCES,
  258. NFSERR_EXIST,
  259. NFSERR_NOTDIR,
  260. NFSERR_NOSPC,
  261. NFSERR_ROFS,
  262. NFSERR_NAMETOL,
  263. NFSERR_DQUOT,
  264. NFSERR_STALE,
  265. NFSERR_BADHANDLE,
  266. NFSERR_NOTSUPP,
  267. NFSERR_SERVERFAULT,
  268. 0,
  269. };
  270. static short nfsv3err_mkdir[] = {
  271. NFSERR_IO,
  272. NFSERR_IO,
  273. NFSERR_ACCES,
  274. NFSERR_EXIST,
  275. NFSERR_NOTDIR,
  276. NFSERR_NOSPC,
  277. NFSERR_ROFS,
  278. NFSERR_NAMETOL,
  279. NFSERR_DQUOT,
  280. NFSERR_STALE,
  281. NFSERR_BADHANDLE,
  282. NFSERR_NOTSUPP,
  283. NFSERR_SERVERFAULT,
  284. 0,
  285. };
  286. static short nfsv3err_symlink[] = {
  287. NFSERR_IO,
  288. NFSERR_IO,
  289. NFSERR_ACCES,
  290. NFSERR_EXIST,
  291. NFSERR_NOTDIR,
  292. NFSERR_NOSPC,
  293. NFSERR_ROFS,
  294. NFSERR_NAMETOL,
  295. NFSERR_DQUOT,
  296. NFSERR_STALE,
  297. NFSERR_BADHANDLE,
  298. NFSERR_NOTSUPP,
  299. NFSERR_SERVERFAULT,
  300. 0,
  301. };
  302. static short nfsv3err_mknod[] = {
  303. NFSERR_IO,
  304. NFSERR_IO,
  305. NFSERR_ACCES,
  306. NFSERR_EXIST,
  307. NFSERR_NOTDIR,
  308. NFSERR_NOSPC,
  309. NFSERR_ROFS,
  310. NFSERR_NAMETOL,
  311. NFSERR_DQUOT,
  312. NFSERR_STALE,
  313. NFSERR_BADHANDLE,
  314. NFSERR_NOTSUPP,
  315. NFSERR_SERVERFAULT,
  316. NFSERR_BADTYPE,
  317. 0,
  318. };
  319. static short nfsv3err_remove[] = {
  320. NFSERR_IO,
  321. NFSERR_NOENT,
  322. NFSERR_IO,
  323. NFSERR_ACCES,
  324. NFSERR_NOTDIR,
  325. NFSERR_ROFS,
  326. NFSERR_NAMETOL,
  327. NFSERR_STALE,
  328. NFSERR_BADHANDLE,
  329. NFSERR_SERVERFAULT,
  330. 0,
  331. };
  332. static short nfsv3err_rmdir[] = {
  333. NFSERR_IO,
  334. NFSERR_NOENT,
  335. NFSERR_IO,
  336. NFSERR_ACCES,
  337. NFSERR_EXIST,
  338. NFSERR_NOTDIR,
  339. NFSERR_INVAL,
  340. NFSERR_ROFS,
  341. NFSERR_NAMETOL,
  342. NFSERR_NOTEMPTY,
  343. NFSERR_STALE,
  344. NFSERR_BADHANDLE,
  345. NFSERR_NOTSUPP,
  346. NFSERR_SERVERFAULT,
  347. 0,
  348. };
  349. static short nfsv3err_rename[] = {
  350. NFSERR_IO,
  351. NFSERR_NOENT,
  352. NFSERR_IO,
  353. NFSERR_ACCES,
  354. NFSERR_EXIST,
  355. NFSERR_XDEV,
  356. NFSERR_NOTDIR,
  357. NFSERR_ISDIR,
  358. NFSERR_INVAL,
  359. NFSERR_NOSPC,
  360. NFSERR_ROFS,
  361. NFSERR_MLINK,
  362. NFSERR_NAMETOL,
  363. NFSERR_NOTEMPTY,
  364. NFSERR_DQUOT,
  365. NFSERR_STALE,
  366. NFSERR_BADHANDLE,
  367. NFSERR_NOTSUPP,
  368. NFSERR_SERVERFAULT,
  369. 0,
  370. };
  371. static short nfsv3err_link[] = {
  372. NFSERR_IO,
  373. NFSERR_IO,
  374. NFSERR_ACCES,
  375. NFSERR_EXIST,
  376. NFSERR_XDEV,
  377. NFSERR_NOTDIR,
  378. NFSERR_INVAL,
  379. NFSERR_NOSPC,
  380. NFSERR_ROFS,
  381. NFSERR_MLINK,
  382. NFSERR_NAMETOL,
  383. NFSERR_DQUOT,
  384. NFSERR_STALE,
  385. NFSERR_BADHANDLE,
  386. NFSERR_NOTSUPP,
  387. NFSERR_SERVERFAULT,
  388. 0,
  389. };
  390. static short nfsv3err_readdir[] = {
  391. NFSERR_IO,
  392. NFSERR_IO,
  393. NFSERR_ACCES,
  394. NFSERR_NOTDIR,
  395. NFSERR_STALE,
  396. NFSERR_BADHANDLE,
  397. NFSERR_BAD_COOKIE,
  398. NFSERR_TOOSMALL,
  399. NFSERR_SERVERFAULT,
  400. 0,
  401. };
  402. static short nfsv3err_readdirplus[] = {
  403. NFSERR_IO,
  404. NFSERR_IO,
  405. NFSERR_ACCES,
  406. NFSERR_NOTDIR,
  407. NFSERR_STALE,
  408. NFSERR_BADHANDLE,
  409. NFSERR_BAD_COOKIE,
  410. NFSERR_NOTSUPP,
  411. NFSERR_TOOSMALL,
  412. NFSERR_SERVERFAULT,
  413. 0,
  414. };
  415. static short nfsv3err_fsstat[] = {
  416. NFSERR_IO,
  417. NFSERR_IO,
  418. NFSERR_STALE,
  419. NFSERR_BADHANDLE,
  420. NFSERR_SERVERFAULT,
  421. 0,
  422. };
  423. static short nfsv3err_fsinfo[] = {
  424. NFSERR_STALE,
  425. NFSERR_STALE,
  426. NFSERR_BADHANDLE,
  427. NFSERR_SERVERFAULT,
  428. 0,
  429. };
  430. static short nfsv3err_pathconf[] = {
  431. NFSERR_STALE,
  432. NFSERR_STALE,
  433. NFSERR_BADHANDLE,
  434. NFSERR_SERVERFAULT,
  435. 0,
  436. };
  437. static short nfsv3err_commit[] = {
  438. NFSERR_IO,
  439. NFSERR_IO,
  440. NFSERR_STALE,
  441. NFSERR_BADHANDLE,
  442. NFSERR_SERVERFAULT,
  443. 0,
  444. };
  445. static short *nfsrv_v3errmap[] = {
  446. nfsv3err_null,
  447. nfsv3err_getattr,
  448. nfsv3err_setattr,
  449. nfsv3err_lookup,
  450. nfsv3err_access,
  451. nfsv3err_readlink,
  452. nfsv3err_read,
  453. nfsv3err_write,
  454. nfsv3err_create,
  455. nfsv3err_mkdir,
  456. nfsv3err_symlink,
  457. nfsv3err_mknod,
  458. nfsv3err_remove,
  459. nfsv3err_rmdir,
  460. nfsv3err_rename,
  461. nfsv3err_link,
  462. nfsv3err_readdir,
  463. nfsv3err_readdirplus,
  464. nfsv3err_fsstat,
  465. nfsv3err_fsinfo,
  466. nfsv3err_pathconf,
  467. nfsv3err_commit,
  468. };
  469. struct pool nfsreqpl;
  470. /*
  471. * Create the header for an rpc request packet
  472. * The hsiz is the size of the rest of the nfs request header.
  473. * (just used to decide if a cluster is a good idea)
  474. */
  475. struct mbuf *
  476. nfsm_reqhead(int hsiz)
  477. {
  478. struct mbuf *mb;
  479. MGET(mb, M_WAIT, MT_DATA);
  480. if (hsiz > MLEN)
  481. MCLGET(mb, M_WAIT);
  482. mb->m_len = 0;
  483. /* Finally, return values */
  484. return (mb);
  485. }
  486. /*
  487. * Return an unpredictable XID in XDR form.
  488. */
  489. u_int32_t
  490. nfs_get_xid(void)
  491. {
  492. static struct idgen32_ctx nfs_xid_ctx;
  493. static int called = 0;
  494. if (!called) {
  495. called = 1;
  496. idgen32_init(&nfs_xid_ctx);
  497. }
  498. return (txdr_unsigned(idgen32(&nfs_xid_ctx)));
  499. }
  500. /*
  501. * Build the RPC header and fill in the authorization info.
  502. * Right now we are pretty centric around RPCAUTH_UNIX, in the
  503. * future, this function will need some love to be able to handle
  504. * other authorization methods, such as Kerberos.
  505. */
  506. void
  507. nfsm_rpchead(struct nfsreq *req, struct ucred *cr, int auth_type)
  508. {
  509. struct mbuf *mb;
  510. u_int32_t *tl;
  511. int i, authsiz, auth_len, ngroups;
  512. KASSERT(auth_type == RPCAUTH_UNIX);
  513. /*
  514. * RPCAUTH_UNIX fits in an hdr mbuf, in the future other
  515. * authorization methods need to figure out their own sizes
  516. * and allocate and chain mbuf's accorindgly.
  517. */
  518. mb = req->r_mreq;
  519. /*
  520. * We need to start out by finding how big the authorization cred
  521. * and verifer are for the auth_type, to be able to correctly
  522. * align the mbuf header/chain.
  523. */
  524. switch (auth_type) {
  525. case RPCAUTH_UNIX:
  526. /*
  527. * In the RPCAUTH_UNIX case, the size is the static
  528. * part as shown in RFC1831 + the number of groups,
  529. * RPCAUTH_UNIX has a zero verifer.
  530. */
  531. if (cr->cr_ngroups > req->r_nmp->nm_numgrps)
  532. ngroups = req->r_nmp->nm_numgrps;
  533. else
  534. ngroups = cr->cr_ngroups;
  535. auth_len = (ngroups << 2) + 5 * NFSX_UNSIGNED;
  536. authsiz = nfsm_rndup(auth_len);
  537. /* The authorization size + the size of the static part */
  538. MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
  539. break;
  540. }
  541. mb->m_len = 0;
  542. /* First the RPC header. */
  543. tl = nfsm_build(&mb, 6 * NFSX_UNSIGNED);
  544. /* Get a new (non-zero) xid */
  545. *tl++ = req->r_xid = nfs_get_xid();
  546. *tl++ = rpc_call;
  547. *tl++ = rpc_vers;
  548. *tl++ = nfs_prog;
  549. if (ISSET(req->r_nmp->nm_flag, NFSMNT_NFSV3)) {
  550. *tl++ = txdr_unsigned(NFS_VER3);
  551. *tl = txdr_unsigned(req->r_procnum);
  552. } else {
  553. *tl++ = txdr_unsigned(NFS_VER2);
  554. *tl = txdr_unsigned(nfsv2_procid[req->r_procnum]);
  555. }
  556. /* The Authorization cred and its verifier */
  557. switch (auth_type) {
  558. case RPCAUTH_UNIX:
  559. tl = nfsm_build(&mb, auth_len + 4 * NFSX_UNSIGNED);
  560. *tl++ = txdr_unsigned(RPCAUTH_UNIX);
  561. *tl++ = txdr_unsigned(authsiz);
  562. /* The authorization cred */
  563. *tl++ = 0; /* stamp */
  564. *tl++ = 0; /* NULL hostname */
  565. *tl++ = txdr_unsigned(cr->cr_uid);
  566. *tl++ = txdr_unsigned(cr->cr_gid);
  567. *tl++ = txdr_unsigned(ngroups);
  568. for (i = 0; i < ngroups; i++)
  569. *tl++ = txdr_unsigned(cr->cr_groups[i]);
  570. /* The authorization verifier */
  571. *tl++ = txdr_unsigned(RPCAUTH_NULL);
  572. *tl = 0;
  573. break;
  574. }
  575. mb->m_pkthdr.len += authsiz + 10 * NFSX_UNSIGNED;
  576. mb->m_pkthdr.ph_ifidx = 0;
  577. }
  578. /*
  579. * copies mbuf chain to the uio scatter/gather list
  580. */
  581. int
  582. nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
  583. {
  584. char *mbufcp, *uiocp;
  585. int xfer, left, len;
  586. struct mbuf *mp;
  587. long uiosiz, rem;
  588. int error = 0;
  589. mp = *mrep;
  590. mbufcp = *dpos;
  591. len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
  592. rem = nfsm_padlen(siz);
  593. while (siz > 0) {
  594. if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
  595. return (EFBIG);
  596. left = uiop->uio_iov->iov_len;
  597. uiocp = uiop->uio_iov->iov_base;
  598. if (left > siz)
  599. left = siz;
  600. uiosiz = left;
  601. while (left > 0) {
  602. while (len == 0) {
  603. mp = mp->m_next;
  604. if (mp == NULL)
  605. return (EBADRPC);
  606. mbufcp = mtod(mp, caddr_t);
  607. len = mp->m_len;
  608. }
  609. xfer = (left > len) ? len : left;
  610. if (uiop->uio_segflg == UIO_SYSSPACE)
  611. memcpy(uiocp, mbufcp, xfer);
  612. else
  613. copyout(mbufcp, uiocp, xfer);
  614. left -= xfer;
  615. len -= xfer;
  616. mbufcp += xfer;
  617. uiocp += xfer;
  618. uiop->uio_offset += xfer;
  619. uiop->uio_resid -= xfer;
  620. }
  621. if (uiop->uio_iov->iov_len <= siz) {
  622. uiop->uio_iovcnt--;
  623. uiop->uio_iov++;
  624. } else {
  625. uiop->uio_iov->iov_base =
  626. (char *)uiop->uio_iov->iov_base + uiosiz;
  627. uiop->uio_iov->iov_len -= uiosiz;
  628. }
  629. siz -= uiosiz;
  630. }
  631. *dpos = mbufcp;
  632. *mrep = mp;
  633. if (rem > 0) {
  634. if (len < rem)
  635. error = nfs_adv(mrep, dpos, rem, len);
  636. else
  637. *dpos += rem;
  638. }
  639. return (error);
  640. }
  641. /*
  642. * Copy a uio scatter/gather list to an mbuf chain.
  643. */
  644. void
  645. nfsm_uiotombuf(struct mbuf **mp, struct uio *uiop, size_t len)
  646. {
  647. struct mbuf *mb, *mb2;
  648. size_t xfer, pad;
  649. mb = *mp;
  650. pad = nfsm_padlen(len);
  651. /* XXX -- the following should be done by the caller */
  652. uiop->uio_resid = len;
  653. uiop->uio_rw = UIO_WRITE;
  654. while (len) {
  655. xfer = min(len, M_TRAILINGSPACE(mb));
  656. uiomovei(mb_offset(mb), xfer, uiop);
  657. mb->m_len += xfer;
  658. len -= xfer;
  659. if (len > 0) {
  660. MGET(mb2, M_WAIT, MT_DATA);
  661. if (len > MLEN)
  662. MCLGET(mb2, M_WAIT);
  663. mb2->m_len = 0;
  664. mb->m_next = mb2;
  665. mb = mb2;
  666. }
  667. }
  668. if (pad > 0) {
  669. if (pad > M_TRAILINGSPACE(mb)) {
  670. MGET(mb2, M_WAIT, MT_DATA);
  671. mb2->m_len = 0;
  672. mb->m_next = mb2;
  673. mb = mb2;
  674. }
  675. memset(mb_offset(mb), 0, pad);
  676. mb->m_len += pad;
  677. }
  678. *mp = mb;
  679. }
  680. /*
  681. * Copy a buffer to an mbuf chain
  682. */
  683. void
  684. nfsm_buftombuf(struct mbuf **mp, void *buf, size_t len)
  685. {
  686. struct iovec iov;
  687. struct uio io;
  688. iov.iov_base = buf;
  689. iov.iov_len = len;
  690. io.uio_iov = &iov;
  691. io.uio_iovcnt = 1;
  692. io.uio_resid = len;
  693. io.uio_segflg = UIO_SYSSPACE;
  694. io.uio_rw = UIO_WRITE;
  695. nfsm_uiotombuf(mp, &io, len);
  696. }
  697. /*
  698. * Copy a string to an mbuf chain
  699. */
  700. void
  701. nfsm_strtombuf(struct mbuf **mp, void *str, size_t len)
  702. {
  703. struct iovec iov[2];
  704. struct uio io;
  705. uint32_t strlen;
  706. strlen = txdr_unsigned(len);
  707. iov[0].iov_base = &strlen;
  708. iov[0].iov_len = sizeof(uint32_t);
  709. iov[1].iov_base = str;
  710. iov[1].iov_len = len;
  711. io.uio_iov = iov;
  712. io.uio_iovcnt = 2;
  713. io.uio_resid = sizeof(uint32_t) + len;
  714. io.uio_segflg = UIO_SYSSPACE;
  715. io.uio_rw = UIO_WRITE;
  716. nfsm_uiotombuf(mp, &io, io.uio_resid);
  717. }
  718. /*
  719. * Help break down an mbuf chain by setting the first siz bytes contiguous
  720. * pointed to by returned val.
  721. * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
  722. * cases. (The macros use the vars. dpos and dpos2)
  723. */
  724. int
  725. nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
  726. {
  727. struct mbuf *mp, *mp2;
  728. int siz2, xfer;
  729. caddr_t p;
  730. mp = *mdp;
  731. while (left == 0) {
  732. *mdp = mp = mp->m_next;
  733. if (mp == NULL)
  734. return (EBADRPC);
  735. left = mp->m_len;
  736. *dposp = mtod(mp, caddr_t);
  737. }
  738. if (left >= siz) {
  739. *cp2 = *dposp;
  740. *dposp += siz;
  741. } else if (mp->m_next == NULL) {
  742. return (EBADRPC);
  743. } else if (siz > MHLEN) {
  744. panic("nfs S too big");
  745. } else {
  746. MGET(mp2, M_WAIT, MT_DATA);
  747. mp2->m_next = mp->m_next;
  748. mp->m_next = mp2;
  749. mp->m_len -= left;
  750. mp = mp2;
  751. *cp2 = p = mtod(mp, caddr_t);
  752. bcopy(*dposp, p, left); /* Copy what was left */
  753. siz2 = siz-left;
  754. p += left;
  755. mp2 = mp->m_next;
  756. /* Loop around copying up the siz2 bytes */
  757. while (siz2 > 0) {
  758. if (mp2 == NULL)
  759. return (EBADRPC);
  760. xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
  761. if (xfer > 0) {
  762. bcopy(mtod(mp2, caddr_t), p, xfer);
  763. mp2->m_data += xfer;
  764. mp2->m_len -= xfer;
  765. p += xfer;
  766. siz2 -= xfer;
  767. }
  768. if (siz2 > 0)
  769. mp2 = mp2->m_next;
  770. }
  771. mp->m_len = siz;
  772. *mdp = mp2;
  773. *dposp = mtod(mp2, caddr_t);
  774. }
  775. return (0);
  776. }
  777. /*
  778. * Advance the position in the mbuf chain.
  779. */
  780. int
  781. nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
  782. {
  783. struct mbuf *m;
  784. int s;
  785. m = *mdp;
  786. s = left;
  787. while (s < offs) {
  788. offs -= s;
  789. m = m->m_next;
  790. if (m == NULL)
  791. return (EBADRPC);
  792. s = m->m_len;
  793. }
  794. *mdp = m;
  795. *dposp = mtod(m, caddr_t)+offs;
  796. return (0);
  797. }
  798. /*
  799. * Called once to initialize data structures...
  800. */
  801. void
  802. nfs_init(void)
  803. {
  804. rpc_vers = txdr_unsigned(RPC_VER2);
  805. rpc_call = txdr_unsigned(RPC_CALL);
  806. rpc_reply = txdr_unsigned(RPC_REPLY);
  807. rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
  808. rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
  809. rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
  810. rpc_autherr = txdr_unsigned(RPC_AUTHERR);
  811. rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
  812. nfs_prog = txdr_unsigned(NFS_PROG);
  813. nfs_true = txdr_unsigned(1);
  814. nfs_false = txdr_unsigned(0);
  815. nfs_xdrneg1 = txdr_unsigned(-1);
  816. nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
  817. if (nfs_ticks < 1)
  818. nfs_ticks = 1;
  819. #ifdef NFSSERVER
  820. nfsrv_init(0); /* Init server data structures */
  821. nfsrv_initcache(); /* Init the server request cache */
  822. #endif /* NFSSERVER */
  823. pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, 0, PR_WAITOK,
  824. "nfsreqpl", NULL);
  825. }
  826. #ifdef NFSCLIENT
  827. int
  828. nfs_vfs_init(struct vfsconf *vfsp)
  829. {
  830. extern struct pool nfs_node_pool;
  831. TAILQ_INIT(&nfs_bufq);
  832. pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, PR_WAITOK,
  833. "nfsnodepl", NULL);
  834. return (0);
  835. }
  836. /*
  837. * Attribute cache routines.
  838. * nfs_loadattrcache() - loads or updates the cache contents from attributes
  839. * that are on the mbuf list
  840. * nfs_getattrcache() - returns valid attributes if found in cache, returns
  841. * error otherwise
  842. */
  843. /*
  844. * Load the attribute cache (that lives in the nfsnode entry) with
  845. * the values on the mbuf list and
  846. * Iff vap not NULL
  847. * copy the attributes to *vaper
  848. */
  849. int
  850. nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
  851. struct vattr *vaper)
  852. {
  853. struct vnode *vp = *vpp;
  854. struct vattr *vap;
  855. struct nfs_fattr *fp;
  856. extern struct vops nfs_specvops;
  857. struct nfsnode *np;
  858. int32_t t1;
  859. caddr_t cp2;
  860. int error = 0;
  861. int32_t rdev;
  862. struct mbuf *md;
  863. enum vtype vtyp;
  864. mode_t vmode;
  865. struct timespec mtime;
  866. struct vnode *nvp;
  867. int v3 = NFS_ISV3(vp);
  868. uid_t uid;
  869. gid_t gid;
  870. md = *mdp;
  871. t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
  872. error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
  873. if (error)
  874. return (error);
  875. fp = (struct nfs_fattr *)cp2;
  876. if (v3) {
  877. vtyp = nfsv3tov_type(fp->fa_type);
  878. vmode = fxdr_unsigned(mode_t, fp->fa_mode);
  879. rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1),
  880. fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2));
  881. fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
  882. } else {
  883. vtyp = nfsv2tov_type(fp->fa_type);
  884. vmode = fxdr_unsigned(mode_t, fp->fa_mode);
  885. if (vtyp == VNON || vtyp == VREG)
  886. vtyp = IFTOVT(vmode);
  887. rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
  888. fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
  889. /*
  890. * Really ugly NFSv2 kludge.
  891. */
  892. if (vtyp == VCHR && rdev == 0xffffffff)
  893. vtyp = VFIFO;
  894. }
  895. /*
  896. * If v_type == VNON it is a new node, so fill in the v_type,
  897. * n_mtime fields. Check to see if it represents a special
  898. * device, and if so, check for a possible alias. Once the
  899. * correct vnode has been obtained, fill in the rest of the
  900. * information.
  901. */
  902. np = VTONFS(vp);
  903. if (vp->v_type != vtyp) {
  904. cache_purge(vp);
  905. vp->v_type = vtyp;
  906. if (vp->v_type == VFIFO) {
  907. #ifndef FIFO
  908. return (EOPNOTSUPP);
  909. #else
  910. extern struct vops nfs_fifovops;
  911. vp->v_op = &nfs_fifovops;
  912. #endif /* FIFO */
  913. }
  914. if (vp->v_type == VCHR || vp->v_type == VBLK) {
  915. vp->v_op = &nfs_specvops;
  916. nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
  917. if (nvp) {
  918. /*
  919. * Discard unneeded vnode, but save its nfsnode.
  920. * Since the nfsnode does not have a lock, its
  921. * vnode lock has to be carried over.
  922. */
  923. nvp->v_data = vp->v_data;
  924. vp->v_data = NULL;
  925. vp->v_op = &spec_vops;
  926. vrele(vp);
  927. vgone(vp);
  928. /*
  929. * Reinitialize aliased node.
  930. */
  931. np->n_vnode = nvp;
  932. *vpp = vp = nvp;
  933. }
  934. }
  935. np->n_mtime = mtime;
  936. }
  937. vap = &np->n_vattr;
  938. vap->va_type = vtyp;
  939. vap->va_rdev = (dev_t)rdev;
  940. vap->va_mtime = mtime;
  941. vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
  942. uid = fxdr_unsigned(uid_t, fp->fa_uid);
  943. gid = fxdr_unsigned(gid_t, fp->fa_gid);
  944. /* Invalidate access cache if uid, gid or mode changed. */
  945. if (np->n_accstamp != -1 &&
  946. (gid != vap->va_gid || uid != vap->va_uid ||
  947. (vmode & 07777) != vap->va_mode))
  948. np->n_accstamp = -1;
  949. vap->va_mode = (vmode & 07777);
  950. switch (vtyp) {
  951. case VBLK:
  952. vap->va_blocksize = BLKDEV_IOSIZE;
  953. break;
  954. case VCHR:
  955. vap->va_blocksize = MAXBSIZE;
  956. break;
  957. default:
  958. vap->va_blocksize = v3 ? vp->v_mount->mnt_stat.f_iosize :
  959. fxdr_unsigned(int32_t, fp->fa2_blocksize);
  960. break;
  961. }
  962. if (v3) {
  963. vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
  964. vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  965. vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  966. vap->va_size = fxdr_hyper(&fp->fa3_size);
  967. vap->va_bytes = fxdr_hyper(&fp->fa3_used);
  968. vap->va_fileid = fxdr_hyper(&fp->fa3_fileid);
  969. fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
  970. fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
  971. vap->va_flags = 0;
  972. vap->va_filerev = 0;
  973. } else {
  974. vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
  975. vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  976. vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  977. vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
  978. vap->va_bytes =
  979. (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
  980. NFS_FABLKSIZE;
  981. vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
  982. fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
  983. vap->va_flags = 0;
  984. vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
  985. fp->fa2_ctime.nfsv2_sec);
  986. vap->va_ctime.tv_nsec = 0;
  987. vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
  988. vap->va_filerev = 0;
  989. }
  990. if (vap->va_size != np->n_size) {
  991. if (vap->va_type == VREG) {
  992. if (np->n_flag & NMODIFIED) {
  993. if (vap->va_size < np->n_size)
  994. vap->va_size = np->n_size;
  995. else
  996. np->n_size = vap->va_size;
  997. } else
  998. np->n_size = vap->va_size;
  999. uvm_vnp_setsize(vp, np->n_size);
  1000. } else
  1001. np->n_size = vap->va_size;
  1002. }
  1003. np->n_attrstamp = time_second;
  1004. if (vaper != NULL) {
  1005. bcopy(vap, vaper, sizeof(*vap));
  1006. if (np->n_flag & NCHG) {
  1007. if (np->n_flag & NACC)
  1008. vaper->va_atime = np->n_atim;
  1009. if (np->n_flag & NUPD)
  1010. vaper->va_mtime = np->n_mtim;
  1011. }
  1012. }
  1013. return (0);
  1014. }
  1015. int
  1016. nfs_attrtimeo(struct nfsnode *np)
  1017. {
  1018. struct vnode *vp = np->n_vnode;
  1019. struct nfsmount *nmp = VFSTONFS(vp->v_mount);
  1020. int tenthage = (time_second - np->n_mtime.tv_sec) / 10;
  1021. int minto, maxto;
  1022. if (vp->v_type == VDIR) {
  1023. maxto = nmp->nm_acdirmax;
  1024. minto = nmp->nm_acdirmin;
  1025. }
  1026. else {
  1027. maxto = nmp->nm_acregmax;
  1028. minto = nmp->nm_acregmin;
  1029. }
  1030. if (np->n_flag & NMODIFIED || tenthage < minto)
  1031. return minto;
  1032. else if (tenthage < maxto)
  1033. return tenthage;
  1034. else
  1035. return maxto;
  1036. }
  1037. /*
  1038. * Check the time stamp
  1039. * If the cache is valid, copy contents to *vap and return 0
  1040. * otherwise return an error
  1041. */
  1042. int
  1043. nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
  1044. {
  1045. struct nfsnode *np = VTONFS(vp);
  1046. struct vattr *vap;
  1047. if (np->n_attrstamp == 0 ||
  1048. (time_second - np->n_attrstamp) >= nfs_attrtimeo(np)) {
  1049. nfsstats.attrcache_misses++;
  1050. return (ENOENT);
  1051. }
  1052. nfsstats.attrcache_hits++;
  1053. vap = &np->n_vattr;
  1054. if (vap->va_size != np->n_size) {
  1055. if (vap->va_type == VREG) {
  1056. if (np->n_flag & NMODIFIED) {
  1057. if (vap->va_size < np->n_size)
  1058. vap->va_size = np->n_size;
  1059. else
  1060. np->n_size = vap->va_size;
  1061. } else
  1062. np->n_size = vap->va_size;
  1063. uvm_vnp_setsize(vp, np->n_size);
  1064. } else
  1065. np->n_size = vap->va_size;
  1066. }
  1067. bcopy(vap, vaper, sizeof(struct vattr));
  1068. if (np->n_flag & NCHG) {
  1069. if (np->n_flag & NACC)
  1070. vaper->va_atime = np->n_atim;
  1071. if (np->n_flag & NUPD)
  1072. vaper->va_mtime = np->n_mtim;
  1073. }
  1074. return (0);
  1075. }
  1076. #endif /* NFSCLIENT */
  1077. /*
  1078. * Set up nameidata for a lookup() call and do it
  1079. */
  1080. int
  1081. nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
  1082. struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp,
  1083. caddr_t *dposp, struct vnode **retdirp, struct proc *p)
  1084. {
  1085. int i, rem;
  1086. struct mbuf *md;
  1087. char *fromcp, *tocp;
  1088. struct vnode *dp;
  1089. int error, rdonly;
  1090. struct componentname *cnp = &ndp->ni_cnd;
  1091. *retdirp = NULL;
  1092. cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
  1093. /*
  1094. * Copy the name from the mbuf list to ndp->ni_pnbuf
  1095. * and set the various ndp fields appropriately.
  1096. */
  1097. fromcp = *dposp;
  1098. tocp = cnp->cn_pnbuf;
  1099. md = *mdp;
  1100. rem = mtod(md, caddr_t) + md->m_len - fromcp;
  1101. for (i = 0; i < len; i++) {
  1102. while (rem == 0) {
  1103. md = md->m_next;
  1104. if (md == NULL) {
  1105. error = EBADRPC;
  1106. goto out;
  1107. }
  1108. fromcp = mtod(md, caddr_t);
  1109. rem = md->m_len;
  1110. }
  1111. if (*fromcp == '\0' || *fromcp == '/') {
  1112. error = EACCES;
  1113. goto out;
  1114. }
  1115. *tocp++ = *fromcp++;
  1116. rem--;
  1117. }
  1118. *tocp = '\0';
  1119. *mdp = md;
  1120. *dposp = fromcp;
  1121. len = nfsm_padlen(len);
  1122. if (len > 0) {
  1123. if (rem >= len)
  1124. *dposp += len;
  1125. else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
  1126. goto out;
  1127. }
  1128. ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
  1129. cnp->cn_nameptr = cnp->cn_pnbuf;
  1130. /*
  1131. * Extract and set starting directory.
  1132. */
  1133. error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp,
  1134. nam, &rdonly);
  1135. if (error)
  1136. goto out;
  1137. if (dp->v_type != VDIR) {
  1138. vrele(dp);
  1139. error = ENOTDIR;
  1140. goto out;
  1141. }
  1142. vref(dp);
  1143. *retdirp = dp;
  1144. ndp->ni_startdir = dp;
  1145. if (rdonly)
  1146. cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
  1147. else
  1148. cnp->cn_flags |= NOCROSSMOUNT;
  1149. /*
  1150. * And call lookup() to do the real work
  1151. */
  1152. cnp->cn_proc = p;
  1153. error = vfs_lookup(ndp);
  1154. if (error)
  1155. goto out;
  1156. /*
  1157. * Check for encountering a symbolic link
  1158. */
  1159. if (cnp->cn_flags & ISSYMLINK) {
  1160. if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
  1161. vput(ndp->ni_dvp);
  1162. else
  1163. vrele(ndp->ni_dvp);
  1164. vput(ndp->ni_vp);
  1165. ndp->ni_vp = NULL;
  1166. error = EINVAL;
  1167. goto out;
  1168. }
  1169. /*
  1170. * Check for saved name request
  1171. */
  1172. if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
  1173. cnp->cn_flags |= HASBUF;
  1174. return (0);
  1175. }
  1176. out:
  1177. pool_put(&namei_pool, cnp->cn_pnbuf);
  1178. return (error);
  1179. }
  1180. /*
  1181. * A fiddled version of m_adj() that ensures null fill to a long
  1182. * boundary and only trims off the back end
  1183. */
  1184. void
  1185. nfsm_adj(struct mbuf *mp, int len, int nul)
  1186. {
  1187. struct mbuf *m;
  1188. int count, i;
  1189. char *cp;
  1190. /*
  1191. * Trim from tail. Scan the mbuf chain,
  1192. * calculating its length and finding the last mbuf.
  1193. * If the adjustment only affects this mbuf, then just
  1194. * adjust and return. Otherwise, rescan and truncate
  1195. * after the remaining size.
  1196. */
  1197. count = 0;
  1198. m = mp;
  1199. for (;;) {
  1200. count += m->m_len;
  1201. if (m->m_next == NULL)
  1202. break;
  1203. m = m->m_next;
  1204. }
  1205. if (m->m_len > len) {
  1206. m->m_len -= len;
  1207. if (nul > 0) {
  1208. cp = mtod(m, caddr_t)+m->m_len-nul;
  1209. for (i = 0; i < nul; i++)
  1210. *cp++ = '\0';
  1211. }
  1212. return;
  1213. }
  1214. count -= len;
  1215. if (count < 0)
  1216. count = 0;
  1217. /*
  1218. * Correct length for chain is "count".
  1219. * Find the mbuf with last data, adjust its length,
  1220. * and toss data from remaining mbufs on chain.
  1221. */
  1222. for (m = mp; m; m = m->m_next) {
  1223. if (m->m_len >= count) {
  1224. m->m_len = count;
  1225. if (nul > 0) {
  1226. cp = mtod(m, caddr_t)+m->m_len-nul;
  1227. for (i = 0; i < nul; i++)
  1228. *cp++ = '\0';
  1229. }
  1230. break;
  1231. }
  1232. count -= m->m_len;
  1233. }
  1234. for (m = m->m_next;m;m = m->m_next)
  1235. m->m_len = 0;
  1236. }
  1237. /*
  1238. * Make these functions instead of macros, so that the kernel text size
  1239. * doesn't get too big...
  1240. */
  1241. void
  1242. nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
  1243. struct vattr *before_vap, int after_ret, struct vattr *after_vap,
  1244. struct nfsm_info *info)
  1245. {
  1246. u_int32_t *tl;
  1247. if (before_ret) {
  1248. tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED);
  1249. *tl = nfs_false;
  1250. } else {
  1251. tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED);
  1252. *tl++ = nfs_true;
  1253. txdr_hyper(before_vap->va_size, tl);
  1254. tl += 2;
  1255. txdr_nfsv3time(&(before_vap->va_mtime), tl);
  1256. tl += 2;
  1257. txdr_nfsv3time(&(before_vap->va_ctime), tl);
  1258. }
  1259. nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info);
  1260. }
  1261. void
  1262. nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret,
  1263. struct vattr *after_vap, struct nfsm_info *info)
  1264. {
  1265. u_int32_t *tl;
  1266. struct nfs_fattr *fp;
  1267. if (after_ret) {
  1268. tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED);
  1269. *tl = nfs_false;
  1270. } else {
  1271. tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR);
  1272. *tl++ = nfs_true;
  1273. fp = (struct nfs_fattr *)tl;
  1274. nfsm_srvfattr(nfsd, after_vap, fp);
  1275. }
  1276. }
  1277. void
  1278. nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
  1279. struct nfs_fattr *fp)
  1280. {
  1281. fp->fa_nlink = txdr_unsigned(vap->va_nlink);
  1282. fp->fa_uid = txdr_unsigned(vap->va_uid);
  1283. fp->fa_gid = txdr_unsigned(vap->va_gid);
  1284. if (nfsd->nd_flag & ND_NFSV3) {
  1285. fp->fa_type = vtonfsv3_type(vap->va_type);
  1286. fp->fa_mode = vtonfsv3_mode(vap->va_mode);
  1287. txdr_hyper(vap->va_size, &fp->fa3_size);
  1288. txdr_hyper(vap->va_bytes, &fp->fa3_used);
  1289. fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
  1290. fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
  1291. fp->fa3_fsid.nfsuquad[0] = 0;
  1292. fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
  1293. txdr_hyper(vap->va_fileid, &fp->fa3_fileid);
  1294. txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
  1295. txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
  1296. txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
  1297. } else {
  1298. fp->fa_type = vtonfsv2_type(vap->va_type);
  1299. fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
  1300. fp->fa2_size = txdr_unsigned(vap->va_size);
  1301. fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
  1302. if (vap->va_type == VFIFO)
  1303. fp->fa2_rdev = 0xffffffff;
  1304. else
  1305. fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
  1306. fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
  1307. fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
  1308. fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid);
  1309. txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
  1310. txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
  1311. txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
  1312. }
  1313. }
  1314. /*
  1315. * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
  1316. * - look up fsid in mount list (if not found ret error)
  1317. * - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP()
  1318. * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
  1319. * - if not lockflag unlock it with VOP_UNLOCK()
  1320. */
  1321. int
  1322. nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
  1323. struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam,
  1324. int *rdonlyp)
  1325. {
  1326. struct proc *p = curproc; /* XXX */
  1327. struct mount *mp;
  1328. int i;
  1329. struct ucred *credanon;
  1330. int error, exflags;
  1331. struct sockaddr_in *saddr;
  1332. *vpp = NULL;
  1333. mp = vfs_getvfs(&fhp->fh_fsid);
  1334. if (!mp)
  1335. return (ESTALE);
  1336. error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
  1337. if (error)
  1338. return (error);
  1339. error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
  1340. if (error)
  1341. return (error);
  1342. saddr = mtod(nam, struct sockaddr_in *);
  1343. if (saddr->sin_family == AF_INET &&
  1344. (ntohs(saddr->sin_port) >= IPPORT_RESERVED ||
  1345. (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) {
  1346. vput(*vpp);
  1347. return (NFSERR_AUTHERR | AUTH_TOOWEAK);
  1348. }
  1349. /* Check/setup credentials. */
  1350. if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
  1351. cred->cr_uid = credanon->cr_uid;
  1352. cred->cr_gid = credanon->cr_gid;
  1353. for (i = 0; i < credanon->cr_ngroups && i < NGROUPS_MAX; i++)
  1354. cred->cr_groups[i] = credanon->cr_groups[i];
  1355. cred->cr_ngroups = i;
  1356. }
  1357. if (exflags & MNT_EXRDONLY)
  1358. *rdonlyp = 1;
  1359. else
  1360. *rdonlyp = 0;
  1361. if (!lockflag)
  1362. VOP_UNLOCK(*vpp, 0, p);
  1363. return (0);
  1364. }
  1365. /*
  1366. * This function compares two net addresses by family and returns non zero
  1367. * if they are the same host, or if there is any doubt it returns 0.
  1368. * The AF_INET family is handled as a special case so that address mbufs
  1369. * don't need to be saved to store "struct in_addr", which is only 4 bytes.
  1370. */
  1371. int
  1372. netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam)
  1373. {
  1374. struct sockaddr_in *inetaddr;
  1375. switch (family) {
  1376. case AF_INET:
  1377. inetaddr = mtod(nam, struct sockaddr_in *);
  1378. if (inetaddr->sin_family == AF_INET &&
  1379. inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
  1380. return (1);
  1381. break;
  1382. default:
  1383. break;
  1384. };
  1385. return (0);
  1386. }
  1387. /*
  1388. * The write verifier has changed (probably due to a server reboot), so all
  1389. * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
  1390. * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
  1391. * flag. Once done the new write verifier can be set for the mount point.
  1392. */
  1393. void
  1394. nfs_clearcommit(struct mount *mp)
  1395. {
  1396. struct vnode *vp, *nvp;
  1397. struct buf *bp, *nbp;
  1398. int s;
  1399. s = splbio();
  1400. loop:
  1401. for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
  1402. if (vp->v_mount != mp) /* Paranoia */
  1403. goto loop;
  1404. nvp = LIST_NEXT(vp, v_mntvnodes);
  1405. for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
  1406. nbp = LIST_NEXT(bp, b_vnbufs);
  1407. if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
  1408. == (B_DELWRI | B_NEEDCOMMIT))
  1409. bp->b_flags &= ~B_NEEDCOMMIT;
  1410. }
  1411. }
  1412. splx(s);
  1413. }
  1414. void
  1415. nfs_merge_commit_ranges(struct vnode *vp)
  1416. {
  1417. struct nfsnode *np = VTONFS(vp);
  1418. if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
  1419. np->n_pushedlo = np->n_pushlo;
  1420. np->n_pushedhi = np->n_pushhi;
  1421. np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
  1422. } else {
  1423. if (np->n_pushlo < np->n_pushedlo)
  1424. np->n_pushedlo = np->n_pushlo;
  1425. if (np->n_pushhi > np->n_pushedhi)
  1426. np->n_pushedhi = np->n_pushhi;
  1427. }
  1428. np->n_pushlo = np->n_pushhi = 0;
  1429. np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID;
  1430. }
  1431. int
  1432. nfs_in_committed_range(struct vnode *vp, struct buf *bp)
  1433. {
  1434. struct nfsnode *np = VTONFS(vp);
  1435. off_t lo, hi;
  1436. if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
  1437. return 0;
  1438. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1439. hi = lo + bp->b_dirtyend;
  1440. return (lo >= np->n_pushedlo && hi <= np->n_pushedhi);
  1441. }
  1442. int
  1443. nfs_in_tobecommitted_range(struct vnode *vp, struct buf *bp)
  1444. {
  1445. struct nfsnode *np = VTONFS(vp);
  1446. off_t lo, hi;
  1447. if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
  1448. return 0;
  1449. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1450. hi = lo + bp->b_dirtyend;
  1451. return (lo >= np->n_pushlo && hi <= np->n_pushhi);
  1452. }
  1453. void
  1454. nfs_add_committed_range(struct vnode *vp, struct buf *bp)
  1455. {
  1456. struct nfsnode *np = VTONFS(vp);
  1457. off_t lo, hi;
  1458. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1459. hi = lo + bp->b_dirtyend;
  1460. if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
  1461. np->n_pushedlo = lo;
  1462. np->n_pushedhi = hi;
  1463. np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
  1464. } else {
  1465. if (hi > np->n_pushedhi)
  1466. np->n_pushedhi = hi;
  1467. if (lo < np->n_pushedlo)
  1468. np->n_pushedlo = lo;
  1469. }
  1470. }
  1471. void
  1472. nfs_del_committed_range(struct vnode *vp, struct buf *bp)
  1473. {
  1474. struct nfsnode *np = VTONFS(vp);
  1475. off_t lo, hi;
  1476. if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
  1477. return;
  1478. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1479. hi = lo + bp->b_dirtyend;
  1480. if (lo > np->n_pushedhi || hi < np->n_pushedlo)
  1481. return;
  1482. if (lo <= np->n_pushedlo)
  1483. np->n_pushedlo = hi;
  1484. else if (hi >= np->n_pushedhi)
  1485. np->n_pushedhi = lo;
  1486. else {
  1487. /*
  1488. * XXX There's only one range. If the deleted range
  1489. * is in the middle, pick the largest of the
  1490. * contiguous ranges that it leaves.
  1491. */
  1492. if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi))
  1493. np->n_pushedhi = lo;
  1494. else
  1495. np->n_pushedlo = hi;
  1496. }
  1497. }
  1498. void
  1499. nfs_add_tobecommitted_range(struct vnode *vp, struct buf *bp)
  1500. {
  1501. struct nfsnode *np = VTONFS(vp);
  1502. off_t lo, hi;
  1503. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1504. hi = lo + bp->b_dirtyend;
  1505. if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) {
  1506. np->n_pushlo = lo;
  1507. np->n_pushhi = hi;
  1508. np->n_commitflags |= NFS_COMMIT_PUSH_VALID;
  1509. } else {
  1510. if (lo < np->n_pushlo)
  1511. np->n_pushlo = lo;
  1512. if (hi > np->n_pushhi)
  1513. np->n_pushhi = hi;
  1514. }
  1515. }
  1516. void
  1517. nfs_del_tobecommitted_range(struct vnode *vp, struct buf *bp)
  1518. {
  1519. struct nfsnode *np = VTONFS(vp);
  1520. off_t lo, hi;
  1521. if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
  1522. return;
  1523. lo = (off_t)bp->b_blkno * DEV_BSIZE;
  1524. hi = lo + bp->b_dirtyend;
  1525. if (lo > np->n_pushhi || hi < np->n_pushlo)
  1526. return;
  1527. if (lo <= np->n_pushlo)
  1528. np->n_pushlo = hi;
  1529. else if (hi >= np->n_pushhi)
  1530. np->n_pushhi = lo;
  1531. else {
  1532. /*
  1533. * XXX There's only one range. If the deleted range
  1534. * is in the middle, pick the largest of the
  1535. * contiguous ranges that it leaves.
  1536. */
  1537. if ((np->n_pushlo - lo) > (hi - np->n_pushhi))
  1538. np->n_pushhi = lo;
  1539. else
  1540. np->n_pushlo = hi;
  1541. }
  1542. }
  1543. /*
  1544. * Map errnos to NFS error numbers. For Version 3 also filter out error
  1545. * numbers not specified for the associated procedure.
  1546. */
  1547. int
  1548. nfsrv_errmap(struct nfsrv_descript *nd, int err)
  1549. {
  1550. short *defaulterrp, *errp;
  1551. if (nd->nd_flag & ND_NFSV3) {
  1552. if (nd->nd_procnum <= NFSPROC_COMMIT) {
  1553. errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
  1554. while (*++errp) {
  1555. if (*errp == err)
  1556. return (err);
  1557. else if (*errp > err)
  1558. break;
  1559. }
  1560. return ((int)*defaulterrp);
  1561. } else
  1562. return (err & 0xffff);
  1563. }
  1564. if (err <= nitems(nfsrv_v2errmap))
  1565. return ((int)nfsrv_v2errmap[err - 1]);
  1566. return (NFSERR_IO);
  1567. }
  1568. /*
  1569. * If full is non zero, set all fields, otherwise just set mode and time fields
  1570. */
  1571. void
  1572. nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full)
  1573. {
  1574. struct mbuf *mb;
  1575. u_int32_t *tl;
  1576. mb = *mp;
  1577. if (a->va_mode != (mode_t)VNOVAL) {
  1578. tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
  1579. *tl++ = nfs_true;
  1580. *tl = txdr_unsigned(a->va_mode);
  1581. } else {
  1582. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1583. *tl = nfs_false;
  1584. }
  1585. if (full && a->va_uid != (uid_t)VNOVAL) {
  1586. tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
  1587. *tl++ = nfs_true;
  1588. *tl = txdr_unsigned(a->va_uid);
  1589. } else {
  1590. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1591. *tl = nfs_false;
  1592. }
  1593. if (full && a->va_gid != (gid_t)VNOVAL) {
  1594. tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
  1595. *tl++ = nfs_true;
  1596. *tl = txdr_unsigned((a)->va_gid);
  1597. } else {
  1598. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1599. *tl = nfs_false;
  1600. }
  1601. if (full && a->va_size != VNOVAL) {
  1602. tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
  1603. *tl++ = nfs_true;
  1604. txdr_hyper(a->va_size, tl);
  1605. } else {
  1606. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1607. *tl = nfs_false;
  1608. }
  1609. if (a->va_atime.tv_nsec != VNOVAL) {
  1610. if (a->va_atime.tv_sec != time_second) {
  1611. tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
  1612. *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
  1613. txdr_nfsv3time(&a->va_atime, tl);
  1614. } else {
  1615. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1616. *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
  1617. }
  1618. } else {
  1619. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1620. *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
  1621. }
  1622. if (a->va_mtime.tv_nsec != VNOVAL) {
  1623. if (a->va_mtime.tv_sec != time_second) {
  1624. tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
  1625. *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
  1626. txdr_nfsv3time(&a->va_mtime, tl);
  1627. } else {
  1628. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1629. *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
  1630. }
  1631. } else {
  1632. tl = nfsm_build(&mb, NFSX_UNSIGNED);
  1633. *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
  1634. }
  1635. *mp = mb;
  1636. }
  1637. /*
  1638. * Ensure a contiguous buffer len bytes long
  1639. */
  1640. void *
  1641. nfsm_build(struct mbuf **mp, u_int len)
  1642. {
  1643. struct mbuf *mb, *mb2;
  1644. caddr_t bpos;
  1645. mb = *mp;
  1646. bpos = mb_offset(mb);
  1647. if (len > M_TRAILINGSPACE(mb)) {
  1648. MGET(mb2, M_WAIT, MT_DATA);
  1649. if (len > MLEN)
  1650. panic("build > MLEN");
  1651. mb->m_next = mb2;
  1652. mb = mb2;
  1653. mb->m_len = 0;
  1654. bpos = mtod(mb, caddr_t);
  1655. }
  1656. mb->m_len += len;
  1657. *mp = mb;
  1658. return (bpos);
  1659. }
  1660. void
  1661. nfsm_fhtom(struct nfsm_info *info, struct vnode *v, int v3)
  1662. {
  1663. struct nfsnode *n = VTONFS(v);
  1664. if (v3) {
  1665. nfsm_strtombuf(&info->nmi_mb, n->n_fhp, n->n_fhsize);
  1666. } else {
  1667. nfsm_buftombuf(&info->nmi_mb, n->n_fhp, NFSX_V2FH);
  1668. }
  1669. }
  1670. void
  1671. nfsm_srvfhtom(struct mbuf **mp, fhandle_t *f, int v3)
  1672. {
  1673. if (v3) {
  1674. nfsm_strtombuf(mp, f, NFSX_V3FH);
  1675. } else {
  1676. nfsm_buftombuf(mp, f, NFSX_V2FH);
  1677. }
  1678. }
  1679. int
  1680. nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep,
  1681. caddr_t *dposp)
  1682. {
  1683. struct nfsm_info info;
  1684. uint32_t *tl, t1;
  1685. caddr_t cp2;
  1686. int error = 0;
  1687. info.nmi_md = *mp;
  1688. info.nmi_dpos = *dposp;
  1689. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1690. if (*tl == nfs_true) {
  1691. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1692. va->va_mode = nfstov_mode(*tl);
  1693. }
  1694. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1695. if (*tl == nfs_true) {
  1696. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1697. va->va_uid = fxdr_unsigned(uid_t, *tl);
  1698. }
  1699. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1700. if (*tl == nfs_true) {
  1701. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1702. va->va_gid = fxdr_unsigned(gid_t, *tl);
  1703. }
  1704. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1705. if (*tl == nfs_true) {
  1706. nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  1707. va->va_size = fxdr_hyper(tl);
  1708. }
  1709. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1710. switch (fxdr_unsigned(int, *tl)) {
  1711. case NFSV3SATTRTIME_TOCLIENT:
  1712. va->va_vaflags |= VA_UTIMES_CHANGE;
  1713. va->va_vaflags &= ~VA_UTIMES_NULL;
  1714. nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  1715. fxdr_nfsv3time(tl, &va->va_atime);
  1716. break;
  1717. case NFSV3SATTRTIME_TOSERVER:
  1718. va->va_vaflags |= VA_UTIMES_CHANGE;
  1719. getnanotime(&va->va_atime);
  1720. break;
  1721. };
  1722. nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  1723. switch (fxdr_unsigned(int, *tl)) {
  1724. case NFSV3SATTRTIME_TOCLIENT:
  1725. va->va_vaflags |= VA_UTIMES_CHANGE;
  1726. va->va_vaflags &= ~VA_UTIMES_NULL;
  1727. nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  1728. fxdr_nfsv3time(tl, &va->va_mtime);
  1729. break;
  1730. case NFSV3SATTRTIME_TOSERVER:
  1731. va->va_vaflags |= VA_UTIMES_CHANGE;
  1732. getnanotime(&va->va_mtime);
  1733. break;
  1734. };
  1735. *dposp = info.nmi_dpos;
  1736. *mp = info.nmi_md;
  1737. nfsmout:
  1738. return (error);
  1739. }
  1740. void
  1741. txdr_nfsv2time(const struct timespec *from, struct nfsv2_time *to)
  1742. {
  1743. if (from->tv_nsec == VNOVAL) {
  1744. to->nfsv2_sec = nfs_xdrneg1;
  1745. to->nfsv2_usec = nfs_xdrneg1;
  1746. } else if (from->tv_sec == -1) {
  1747. /*
  1748. * can't request a time of -1; send
  1749. * -1.000001 == {-2,999999} instead
  1750. */
  1751. to->nfsv2_sec = htonl(-2);
  1752. to->nfsv2_usec = htonl(999999);
  1753. } else {
  1754. to->nfsv2_sec = htonl(from->tv_sec);
  1755. to->nfsv2_usec = htonl(from->tv_nsec / 1000);
  1756. }
  1757. }