nfs.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /* $OpenBSD: nfs.c,v 1.12 2014/11/19 20:28:56 miod Exp $ */
  2. /* $NetBSD: nfs.c,v 1.19 1996/10/13 02:29:04 christos Exp $ */
  3. /*-
  4. * Copyright (c) 1993 John Brezak
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. The name of the author may not be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
  19. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  22. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  26. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <sys/param.h>
  31. #include <sys/time.h>
  32. #include <sys/socket.h>
  33. #include <sys/stat.h>
  34. #include <netinet/in.h>
  35. #include "rpcv2.h"
  36. #include "nfsv2.h"
  37. #include "stand.h"
  38. #include "saerrno.h"
  39. #include "net.h"
  40. #include "netif.h"
  41. #include "nfs.h"
  42. #include "rpc.h"
  43. /* Define our own NFS attributes without NQNFS stuff. */
  44. struct nfsv2_fattrs {
  45. u_int32_t fa_type;
  46. u_int32_t fa_mode;
  47. u_int32_t fa_nlink;
  48. u_int32_t fa_uid;
  49. u_int32_t fa_gid;
  50. u_int32_t fa_size;
  51. u_int32_t fa_blocksize;
  52. u_int32_t fa_rdev;
  53. u_int32_t fa_blocks;
  54. u_int32_t fa_fsid;
  55. u_int32_t fa_fileid;
  56. struct nfsv2_time fa_atime;
  57. struct nfsv2_time fa_mtime;
  58. struct nfsv2_time fa_ctime;
  59. };
  60. struct nfs_read_args {
  61. u_char fh[NFS_FHSIZE];
  62. u_int32_t off;
  63. u_int32_t len;
  64. u_int32_t xxx; /* XXX what's this for? */
  65. };
  66. /* Data part of nfs rpc reply (also the largest thing we receive) */
  67. #define NFSREAD_SIZE 1024
  68. struct nfs_read_repl {
  69. u_int32_t errno;
  70. struct nfsv2_fattrs fa;
  71. u_int32_t count;
  72. u_char data[NFSREAD_SIZE];
  73. };
  74. struct nfs_readlnk_repl {
  75. u_int32_t errno;
  76. u_int32_t len;
  77. char path[NFS_MAXPATHLEN];
  78. };
  79. struct nfs_iodesc {
  80. struct iodesc *iodesc;
  81. off_t off;
  82. u_char fh[NFS_FHSIZE];
  83. struct nfsv2_fattrs fa; /* all in network order */
  84. };
  85. struct nfs_iodesc nfs_root_node;
  86. /*
  87. * Fetch the root file handle (call mount daemon)
  88. * On error, return non-zero and set errno.
  89. */
  90. static int
  91. nfs_getrootfh(struct iodesc *d, const char *path, u_char *fhp)
  92. {
  93. int len;
  94. struct args {
  95. u_int32_t len;
  96. char path[FNAME_SIZE];
  97. } *args;
  98. struct repl {
  99. u_int32_t errno;
  100. u_char fh[NFS_FHSIZE];
  101. } *repl;
  102. struct {
  103. u_int32_t h[RPC_HEADER_WORDS];
  104. struct args d;
  105. } sdata;
  106. struct {
  107. u_int32_t h[RPC_HEADER_WORDS];
  108. struct repl d;
  109. } rdata;
  110. size_t cc;
  111. #ifdef NFS_DEBUG
  112. if (debug)
  113. printf("nfs_getrootfh: %s\n", path);
  114. #endif
  115. args = &sdata.d;
  116. repl = &rdata.d;
  117. bzero(args, sizeof(*args));
  118. len = strlen(path);
  119. if (len > sizeof(args->path))
  120. len = sizeof(args->path);
  121. args->len = htonl(len);
  122. bcopy(path, args->path, len);
  123. len = 4 + roundup(len, 4);
  124. cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
  125. args, len, repl, sizeof(*repl));
  126. if (cc == -1) {
  127. /* errno was set by rpc_call */
  128. return (-1);
  129. }
  130. if (cc < 4) {
  131. errno = EBADRPC;
  132. return (-1);
  133. }
  134. if (repl->errno) {
  135. errno = ntohl(repl->errno);
  136. return (-1);
  137. }
  138. bcopy(repl->fh, fhp, sizeof(repl->fh));
  139. return (0);
  140. }
  141. /*
  142. * Lookup a file. Store handle and attributes.
  143. * Return zero or error number.
  144. */
  145. static int
  146. nfs_lookupfh(struct nfs_iodesc *d, char *name, struct nfs_iodesc *newfd)
  147. {
  148. int len, rlen;
  149. struct args {
  150. u_char fh[NFS_FHSIZE];
  151. u_int32_t len;
  152. char name[FNAME_SIZE];
  153. } *args;
  154. struct repl {
  155. u_int32_t errno;
  156. u_char fh[NFS_FHSIZE];
  157. struct nfsv2_fattrs fa;
  158. } *repl;
  159. struct {
  160. u_int32_t h[RPC_HEADER_WORDS];
  161. struct args d;
  162. } sdata;
  163. struct {
  164. u_int32_t h[RPC_HEADER_WORDS];
  165. struct repl d;
  166. } rdata;
  167. ssize_t cc;
  168. #ifdef NFS_DEBUG
  169. if (debug)
  170. printf("lookupfh: called\n");
  171. #endif
  172. args = &sdata.d;
  173. repl = &rdata.d;
  174. bzero(args, sizeof(*args));
  175. bcopy(d->fh, args->fh, sizeof(args->fh));
  176. len = strlen(name);
  177. if (len > sizeof(args->name))
  178. len = sizeof(args->name);
  179. bcopy(name, args->name, len);
  180. args->len = htonl(len);
  181. len = 4 + roundup(len, 4);
  182. len += NFS_FHSIZE;
  183. rlen = sizeof(*repl);
  184. cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
  185. args, len, repl, rlen);
  186. if (cc == -1)
  187. return (errno); /* XXX - from rpc_call */
  188. if (cc < 4)
  189. return (EIO);
  190. if (repl->errno) {
  191. /* saerrno.h now matches NFS error numbers. */
  192. return (ntohl(repl->errno));
  193. }
  194. bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
  195. bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
  196. return (0);
  197. }
  198. /*
  199. * Get the destination of a symbolic link.
  200. */
  201. static int
  202. nfs_readlink(struct nfs_iodesc *d, char *buf)
  203. {
  204. struct {
  205. u_int32_t h[RPC_HEADER_WORDS];
  206. u_char fh[NFS_FHSIZE];
  207. } sdata;
  208. struct {
  209. u_int32_t h[RPC_HEADER_WORDS];
  210. struct nfs_readlnk_repl d;
  211. } rdata;
  212. ssize_t cc;
  213. #ifdef NFS_DEBUG
  214. if (debug)
  215. printf("readlink: called\n");
  216. #endif
  217. bcopy(d->fh, sdata.fh, NFS_FHSIZE);
  218. cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
  219. sdata.fh, NFS_FHSIZE,
  220. &rdata.d, sizeof(rdata.d));
  221. if (cc == -1)
  222. return (errno);
  223. if (cc < 4)
  224. return (EIO);
  225. if (rdata.d.errno)
  226. return (ntohl(rdata.d.errno));
  227. rdata.d.len = ntohl(rdata.d.len);
  228. if (rdata.d.len > NFS_MAXPATHLEN)
  229. return (ENAMETOOLONG);
  230. bcopy(rdata.d.path, buf, rdata.d.len);
  231. buf[rdata.d.len] = 0;
  232. return (0);
  233. }
  234. /*
  235. * Read data from a file.
  236. * Return transfer count or -1 (and set errno)
  237. */
  238. static ssize_t
  239. nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
  240. {
  241. struct nfs_read_args *args;
  242. struct nfs_read_repl *repl;
  243. struct {
  244. u_int32_t h[RPC_HEADER_WORDS];
  245. struct nfs_read_args d;
  246. } sdata;
  247. struct {
  248. u_int32_t h[RPC_HEADER_WORDS];
  249. struct nfs_read_repl d;
  250. } rdata;
  251. size_t cc;
  252. long x;
  253. int hlen, rlen;
  254. args = &sdata.d;
  255. repl = &rdata.d;
  256. bcopy(d->fh, args->fh, NFS_FHSIZE);
  257. args->off = htonl((u_int32_t)off);
  258. if (len > NFSREAD_SIZE)
  259. len = NFSREAD_SIZE;
  260. args->len = htonl((u_int32_t)len);
  261. args->xxx = htonl((u_int32_t)0);
  262. hlen = sizeof(*repl) - NFSREAD_SIZE;
  263. cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
  264. args, sizeof(*args),
  265. repl, sizeof(*repl));
  266. if (cc == -1) {
  267. /* errno was already set by rpc_call */
  268. return (-1);
  269. }
  270. if (cc < hlen) {
  271. errno = EBADRPC;
  272. return (-1);
  273. }
  274. if (repl->errno) {
  275. errno = ntohl(repl->errno);
  276. return (-1);
  277. }
  278. rlen = cc - hlen;
  279. x = ntohl(repl->count);
  280. if (rlen < x) {
  281. printf("nfsread: short packet, %d < %ld\n", rlen, x);
  282. errno = EBADRPC;
  283. return(-1);
  284. }
  285. bcopy(repl->data, addr, x);
  286. return (x);
  287. }
  288. /*
  289. * nfs_mount - mount this nfs filesystem to a host
  290. * On error, return non-zero and set errno.
  291. */
  292. int
  293. nfs_mount(int sock, struct in_addr ip, const char *path)
  294. {
  295. struct iodesc *desc;
  296. struct nfsv2_fattrs *fa;
  297. if (!(desc = socktodesc(sock))) {
  298. errno = EINVAL;
  299. return(-1);
  300. }
  301. /* Bind to a reserved port. */
  302. desc->myport = htons(--rpc_port);
  303. desc->destip = ip;
  304. if (nfs_getrootfh(desc, path, nfs_root_node.fh))
  305. return (-1);
  306. nfs_root_node.iodesc = desc;
  307. /* Fake up attributes for the root dir. */
  308. fa = &nfs_root_node.fa;
  309. fa->fa_type = htonl(NFDIR);
  310. fa->fa_mode = htonl(0755);
  311. fa->fa_nlink = htonl(2);
  312. #ifdef NFS_DEBUG
  313. if (debug)
  314. printf("nfs_mount: got fh for %s\n", path);
  315. #endif
  316. return(0);
  317. }
  318. /*
  319. * Open a file.
  320. * return zero or error number
  321. */
  322. int
  323. nfs_open(char *path, struct open_file *f)
  324. {
  325. struct nfs_iodesc *newfd, *currfd;
  326. char namebuf[NFS_MAXPATHLEN + 1], *cp, *ncp;
  327. char linkbuf[NFS_MAXPATHLEN + 1];
  328. int nlinks = 0, error = 0, c;
  329. #ifdef NFS_DEBUG
  330. if (debug)
  331. printf("nfs_open: %s\n", path);
  332. #endif
  333. if (nfs_root_node.iodesc == NULL) {
  334. printf("nfs_open: must mount first.\n");
  335. return (ENXIO);
  336. }
  337. currfd = &nfs_root_node;
  338. newfd = 0;
  339. cp = path;
  340. while (*cp) {
  341. /*
  342. * Remove extra separators
  343. */
  344. while (*cp == '/')
  345. cp++;
  346. if (*cp == '\0')
  347. break;
  348. /*
  349. * Check that current node is a directory.
  350. */
  351. if (currfd->fa.fa_type != htonl(NFDIR)) {
  352. error = ENOTDIR;
  353. goto out;
  354. }
  355. /* allocate file system specific data structure */
  356. newfd = alloc(sizeof(*newfd));
  357. newfd->iodesc = currfd->iodesc;
  358. newfd->off = 0;
  359. /*
  360. * Get next component of path name.
  361. */
  362. {
  363. int len = 0;
  364. ncp = cp;
  365. while ((c = *cp) != '\0' && c != '/') {
  366. if (++len > NFS_MAXNAMLEN) {
  367. error = ENOENT;
  368. goto out;
  369. }
  370. cp++;
  371. }
  372. *cp = '\0';
  373. }
  374. /* lookup a file handle */
  375. error = nfs_lookupfh(currfd, ncp, newfd);
  376. *cp = c;
  377. if (error)
  378. goto out;
  379. /*
  380. * Check for symbolic link
  381. */
  382. if (newfd->fa.fa_type == htonl(NFLNK)) {
  383. int link_len, len;
  384. error = nfs_readlink(newfd, linkbuf);
  385. if (error)
  386. goto out;
  387. link_len = strlen(linkbuf);
  388. len = strlen(cp);
  389. if (link_len + len > MAXPATHLEN ||
  390. ++nlinks > MAXSYMLINKS) {
  391. error = ENOENT;
  392. goto out;
  393. }
  394. bcopy(cp, &namebuf[link_len], len + 1);
  395. bcopy(linkbuf, namebuf, link_len);
  396. /*
  397. * If absolute pathname, restart at root.
  398. * If relative pathname, restart at parent directory.
  399. */
  400. cp = namebuf;
  401. if (*cp == '/') {
  402. if (currfd != &nfs_root_node)
  403. free(currfd, sizeof(*currfd));
  404. currfd = &nfs_root_node;
  405. }
  406. free(newfd, sizeof(*newfd));
  407. newfd = 0;
  408. continue;
  409. }
  410. if (currfd != &nfs_root_node)
  411. free(currfd, sizeof(*currfd));
  412. currfd = newfd;
  413. newfd = 0;
  414. }
  415. error = 0;
  416. out:
  417. if (!error) {
  418. f->f_fsdata = (void *)currfd;
  419. return (0);
  420. }
  421. #ifdef NFS_DEBUG
  422. if (debug)
  423. printf("nfs_open: %s lookupfh failed: %s\n",
  424. path, strerror(error));
  425. #endif
  426. if (currfd != &nfs_root_node)
  427. free(currfd, sizeof(*currfd));
  428. if (newfd)
  429. free(newfd, sizeof(*newfd));
  430. return (error);
  431. }
  432. int
  433. nfs_close(struct open_file *f)
  434. {
  435. struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
  436. #ifdef NFS_DEBUG
  437. if (debug)
  438. printf("nfs_close: fp=%p\n", fp);
  439. #endif
  440. if (fp)
  441. free(fp, sizeof(struct nfs_iodesc));
  442. f->f_fsdata = (void *)0;
  443. return (0);
  444. }
  445. /*
  446. * read a portion of a file
  447. */
  448. int
  449. nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
  450. {
  451. struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
  452. ssize_t cc;
  453. char *addr = buf;
  454. #ifdef NFS_DEBUG
  455. if (debug)
  456. printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
  457. #endif
  458. while ((int)size > 0) {
  459. twiddle();
  460. cc = nfs_readdata(fp, fp->off, (void *)addr, size);
  461. /* XXX maybe should retry on certain errors */
  462. if (cc == -1) {
  463. #ifdef NFS_DEBUG
  464. if (debug)
  465. printf("nfs_read: read: %s", strerror(errno));
  466. #endif
  467. return (errno); /* XXX - from nfs_readdata */
  468. }
  469. if (cc == 0) {
  470. if (debug)
  471. printf("nfs_read: hit EOF unexpectantly");
  472. goto ret;
  473. }
  474. fp->off += cc;
  475. addr += cc;
  476. size -= cc;
  477. }
  478. ret:
  479. if (resid)
  480. *resid = size;
  481. return (0);
  482. }
  483. /*
  484. * Not implemented.
  485. */
  486. int
  487. nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
  488. {
  489. return (EROFS);
  490. }
  491. off_t
  492. nfs_seek(struct open_file *f, off_t offset, int where)
  493. {
  494. struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
  495. u_int32_t size = ntohl(d->fa.fa_size);
  496. switch (where) {
  497. case SEEK_SET:
  498. d->off = offset;
  499. break;
  500. case SEEK_CUR:
  501. d->off += offset;
  502. break;
  503. case SEEK_END:
  504. d->off = size - offset;
  505. break;
  506. default:
  507. return (-1);
  508. }
  509. return (d->off);
  510. }
  511. /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
  512. const int nfs_stat_types[8] = {
  513. 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0
  514. };
  515. int
  516. nfs_stat(struct open_file *f, struct stat *sb)
  517. {
  518. struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
  519. u_int32_t ftype, mode;
  520. ftype = ntohl(fp->fa.fa_type);
  521. mode = ntohl(fp->fa.fa_mode);
  522. mode |= nfs_stat_types[ftype & 7];
  523. sb->st_mode = mode;
  524. sb->st_nlink = ntohl(fp->fa.fa_nlink);
  525. sb->st_uid = ntohl(fp->fa.fa_uid);
  526. sb->st_gid = ntohl(fp->fa.fa_gid);
  527. sb->st_size = ntohl(fp->fa.fa_size);
  528. return (0);
  529. }
  530. /*
  531. * Not implemented.
  532. */
  533. #ifndef NO_READDIR
  534. int
  535. nfs_readdir(struct open_file *f, char *name)
  536. {
  537. return (EROFS);
  538. }
  539. #endif