tftpd.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * tftpd - tftp service, see /lib/rfc/rfc783 (now rfc1350 + 234[789])
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <auth.h>
  15. #include <bio.h>
  16. #include <ip.h>
  17. #include <ndb.h>
  18. enum
  19. {
  20. Maxpath= 128,
  21. Maxerr= 256,
  22. Debug= 0,
  23. Opsize= sizeof(int16_t),
  24. Blksize= sizeof(int16_t),
  25. Hdrsize= Opsize + Blksize,
  26. Ackerr= -1,
  27. Ackok= 0,
  28. Ackrexmit= 1,
  29. /* op codes */
  30. Tftp_READ = 1,
  31. Tftp_WRITE = 2,
  32. Tftp_DATA = 3,
  33. Tftp_ACK = 4,
  34. Tftp_ERROR = 5,
  35. Tftp_OACK = 6, /* option acknowledge */
  36. Errnotdef = 0, /* see textual error instead */
  37. Errnotfound = 1,
  38. Errnoaccess = 2,
  39. Errdiskfull = 3,
  40. Errbadop = 4,
  41. Errbadtid = 5,
  42. Errexists = 6,
  43. Errnouser = 7,
  44. Errbadopt = 8, /* really bad option value */
  45. Defsegsize = 512,
  46. Maxsegsize = 65464, /* from rfc2348 */
  47. /*
  48. * bandt (viaduct) tunnels use smaller mtu than ether's
  49. * (1400 bytes for tcp mss of 1300 bytes).
  50. */
  51. Bandtmtu = 1400,
  52. /*
  53. * maximum size of block's data content, excludes hdrs,
  54. * notably IP/UDP and TFTP, using worst-case (IPv6) sizes.
  55. */
  56. Bandtblksz = Bandtmtu - 40 - 8,
  57. Bcavium = 1432, /* cavium's u-boot demands this size */
  58. };
  59. typedef struct Opt Opt;
  60. struct Opt {
  61. char *name;
  62. int *valp; /* set to client's value if within bounds */
  63. int min;
  64. int max;
  65. };
  66. int dbg;
  67. int restricted;
  68. int pid;
  69. /* options */
  70. int blksize = Defsegsize; /* excluding 4-byte header */
  71. int timeout = 5; /* seconds */
  72. int tsize;
  73. static Opt option[] = {
  74. "timeout", &timeout, 1, 255,
  75. /* see "hack" below */
  76. "blksize", &blksize, 8, Maxsegsize,
  77. "tsize", &tsize, 0, (~0UL >> 1)&0xFF,
  78. };
  79. void sendfile(int, char*, char*, int);
  80. void recvfile(int, char*, char*);
  81. void nak(int, int, char*);
  82. void ack(int, uint16_t);
  83. void clrcon(void);
  84. void setuser(void);
  85. char* sunkernel(char*);
  86. void remoteaddr(char*, char*, int);
  87. void doserve(int);
  88. char bigbuf[32768];
  89. char raddr[64];
  90. char *dir = "/lib/tftpd";
  91. char *dirsl;
  92. int dirsllen;
  93. char flog[] = "ipboot";
  94. char net[Maxpath];
  95. static char *opnames[] = {
  96. [Tftp_READ] "read",
  97. [Tftp_WRITE] "write",
  98. [Tftp_DATA] "data",
  99. [Tftp_ACK] "ack",
  100. [Tftp_ERROR] "error",
  101. [Tftp_OACK] "oack",
  102. };
  103. void
  104. usage(void)
  105. {
  106. fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt]\n",
  107. argv0);
  108. exits("usage");
  109. }
  110. void
  111. main(int argc, char **argv)
  112. {
  113. char buf[64];
  114. char adir[64], ldir[64];
  115. int cfd, lcfd, dfd;
  116. char *svc = "69";
  117. setnetmtpt(net, sizeof net, nil);
  118. ARGBEGIN{
  119. case 'd':
  120. dbg++;
  121. break;
  122. case 'h':
  123. dir = EARGF(usage());
  124. break;
  125. case 'r':
  126. restricted = 1;
  127. break;
  128. case 's':
  129. svc = EARGF(usage());
  130. break;
  131. case 'x':
  132. setnetmtpt(net, sizeof net, EARGF(usage()));
  133. break;
  134. default:
  135. usage();
  136. }ARGEND
  137. snprint(buf, sizeof buf, "%s/", dir);
  138. dirsl = strdup(buf);
  139. dirsllen = strlen(dirsl);
  140. fmtinstall('E', eipfmt);
  141. fmtinstall('I', eipfmt);
  142. /*
  143. * setuser calls newns, and typical /lib/namespace files contain
  144. * "cd /usr/$user", so call setuser before chdir.
  145. */
  146. setuser();
  147. if(chdir(dir) < 0)
  148. sysfatal("can't get to directory %s: %r", dir);
  149. if(!dbg)
  150. switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
  151. case -1:
  152. sysfatal("fork: %r");
  153. case 0:
  154. break;
  155. default:
  156. exits(0);
  157. }
  158. snprint(buf, sizeof buf, "%s/udp!*!%s", net, svc);
  159. cfd = announce(buf, adir);
  160. if (cfd < 0)
  161. sysfatal("announcing on %s: %r", buf);
  162. syslog(dbg, flog, "tftpd started on %s dir %s", buf, adir);
  163. // setuser();
  164. for(;;) {
  165. lcfd = listen(adir, ldir);
  166. if(lcfd < 0)
  167. sysfatal("listening on %s: %r", adir);
  168. switch(fork()) {
  169. case -1:
  170. sysfatal("fork: %r");
  171. case 0:
  172. dfd = accept(lcfd, ldir);
  173. if(dfd < 0)
  174. exits(0);
  175. remoteaddr(ldir, raddr, sizeof(raddr));
  176. pid = getpid();
  177. syslog(0, flog, "tftp %d connection from %s dir %s",
  178. pid, raddr, ldir);
  179. doserve(dfd);
  180. exits("done");
  181. break;
  182. default:
  183. close(lcfd);
  184. continue;
  185. }
  186. }
  187. }
  188. static Opt *
  189. handleopt(int fd, char *name, char *val)
  190. {
  191. int n;
  192. Opt *op;
  193. for (op = option; op < option + nelem(option); op++)
  194. if(cistrcmp(name, op->name) == 0) {
  195. n = strtol(val, nil, 10);
  196. if (n < op->min || n > op->max) {
  197. nak(fd, Errbadopt, "option value out of range");
  198. syslog(dbg, flog, "tftp bad option value from "
  199. "client: %s %s", name, val);
  200. sysfatal("bad option value from client: %s %s",
  201. name, val);
  202. }
  203. *op->valp = n;
  204. /* incoming 0 for tsize is uninteresting */
  205. if(cistrcmp("tsize", op->name) != 0)
  206. syslog(dbg, flog, "tftpd %d setting %s to client's %d",
  207. pid, name, n);
  208. return op;
  209. }
  210. return nil;
  211. }
  212. static int64_t
  213. filesize(char *file)
  214. {
  215. int64_t size;
  216. Dir *dp;
  217. dp = dirstat(file);
  218. if (dp == nil)
  219. return -1;
  220. size = dp->length;
  221. free(dp);
  222. return size;
  223. }
  224. /* copy word into bp iff it fits before ep, returns bytes to advance bp. */
  225. static int
  226. emits(char *word, char *bp, char *ep)
  227. {
  228. int len;
  229. len = strlen(word) + 1;
  230. if (bp + len >= ep)
  231. return -1;
  232. strcpy(bp, word);
  233. return len;
  234. }
  235. /* format number into bp iff it fits before ep. */
  236. static int
  237. emitn(int64_t n, char *bp, char *ep)
  238. {
  239. char numb[32];
  240. snprint(numb, sizeof numb, "%lld", n);
  241. return emits(numb, bp, ep);
  242. }
  243. /*
  244. * send an OACK packet to respond to options. bail early with -1 on error.
  245. * p is the packet containing the options.
  246. *
  247. * hack: bandt (viaducts) uses smaller mtu than ether's
  248. * (1400 bytes for tcp mss of 1300 bytes),
  249. * so offer at most bandt's mtu minus headers,
  250. * to avoid failure of pxe booting via viaduct.
  251. * there's an exception for the cavium's u-boot.
  252. */
  253. static int
  254. options(int fd, char *buf, int bufsz, char *file, uint16_t oper,
  255. char *p,
  256. int dlen)
  257. {
  258. int nmlen, vallen, olen, nopts;
  259. int64_t size;
  260. char *val, *bp, *ep;
  261. Opt *op;
  262. buf[0] = 0;
  263. buf[1] = Tftp_OACK;
  264. bp = buf + Opsize;
  265. ep = buf + bufsz;
  266. nopts = 0;
  267. for (; dlen > 0 && *p != '\0'; p = val + vallen, bp += olen) {
  268. nmlen = strlen(p) + 1; /* include NUL */
  269. if (nmlen > dlen)
  270. break;
  271. dlen -= nmlen;
  272. val = p + nmlen;
  273. if (dlen <= 0 || *val == '\0')
  274. break;
  275. vallen = strlen(val) + 1;
  276. if (vallen > dlen)
  277. break;
  278. dlen -= vallen;
  279. nopts++;
  280. olen = 0;
  281. op = handleopt(fd, p, val);
  282. if (op == nil)
  283. continue;
  284. /* append OACK response to buf */
  285. nmlen = emits(p, bp, ep); /* option name */
  286. if (nmlen < 0)
  287. return -1;
  288. bp += nmlen;
  289. if (oper == Tftp_READ && cistrcmp(p, "tsize") == 0) {
  290. size = filesize(file);
  291. if (size == -1) {
  292. nak(fd, Errnotfound, "no such file");
  293. syslog(dbg, flog, "tftpd tsize for "
  294. "non-existent file %s", file);
  295. // *op->valp = 0;
  296. // olen = emits("0", bp, ep);
  297. return -1;
  298. }
  299. *op->valp = size;
  300. olen = emitn(size, bp, ep);
  301. syslog(dbg, flog, "tftpd %d %s tsize is %,lld",
  302. pid, file, size);
  303. } else if (oper == Tftp_READ && cistrcmp(p, "blksize") == 0 &&
  304. blksize > Bandtblksz && blksize != Bcavium) {
  305. *op->valp = blksize = Bandtblksz;
  306. olen = emitn(blksize, bp, ep);
  307. syslog(dbg, flog, "tftpd %d overriding blksize to %d",
  308. pid, blksize);
  309. } else
  310. olen = emits(val, bp, ep); /* use requested value */
  311. }
  312. if (nopts == 0)
  313. return 0; /* no options actually seen */
  314. if (write(fd, buf, bp - buf) < bp - buf) {
  315. syslog(dbg, flog, "tftpd network write error on oack to %s: %r",
  316. raddr);
  317. sysfatal("tftpd: network write error: %r");
  318. }
  319. if(Debug)
  320. syslog(dbg, flog, "tftpd oack: options to %s", raddr);
  321. return nopts;
  322. }
  323. static void
  324. optlog(char *bytes, char *p, int dlen)
  325. {
  326. char *bp;
  327. bp = bytes;
  328. sprint(bp, "tftpd %d option bytes: ", dlen);
  329. bp += strlen(bp);
  330. for (; dlen > 0; dlen--, p++)
  331. *bp++ = *p? *p: ' ';
  332. *bp = '\0';
  333. syslog(dbg, flog, "%s", bytes);
  334. }
  335. /*
  336. * replace one occurrence of %[ICE] with ip, cfgpxe name, or ether mac, resp.
  337. * we can't easily use $ because u-boot has stranger quoting rules than sh.
  338. */
  339. char *
  340. mapname(char *file)
  341. {
  342. int nf;
  343. char *p, *newnm, *cur, *arpf, *ln, *remip, *bang;
  344. char *fields[4];
  345. Biobuf *arp;
  346. p = strchr(file, '%');
  347. if (p == nil || p[1] == '\0')
  348. return strdup(file);
  349. remip = strdup(raddr);
  350. newnm = mallocz(strlen(file) + Maxpath, 1);
  351. if (remip == nil || newnm == nil)
  352. sysfatal("out of memory");
  353. bang = strchr(remip, '!');
  354. if (bang)
  355. *bang = '\0'; /* remove !port */
  356. memmove(newnm, file, p - file); /* copy up to % */
  357. cur = newnm + strlen(newnm);
  358. switch(p[1]) {
  359. case 'I':
  360. strcpy(cur, remip); /* remote's IP */
  361. break;
  362. case 'C':
  363. strcpy(cur, "/cfg/pxe/");
  364. cur += strlen(cur);
  365. /* fall through */
  366. case 'E':
  367. /* look up remote's IP in /net/arp to get mac. */
  368. arpf = smprint("%s/arp", net);
  369. arp = Bopen(arpf, OREAD);
  370. free(arpf);
  371. if (arp == nil)
  372. break;
  373. /* read lines looking for remip in 3rd field of 4 */
  374. while ((ln = Brdline(arp, '\n')) != nil) {
  375. ln[Blinelen(arp)-1] = 0;
  376. nf = tokenize(ln, fields, nelem(fields));
  377. if (nf >= 4 && strcmp(fields[2], remip) == 0) {
  378. strcpy(cur, fields[3]);
  379. break;
  380. }
  381. }
  382. Bterm(arp);
  383. break;
  384. }
  385. strcat(newnm, p + 2); /* tail following %x */
  386. free(remip);
  387. return newnm;
  388. }
  389. void
  390. doserve(int fd)
  391. {
  392. int dlen, opts;
  393. char *mode, *p, *file;
  394. int16_t op;
  395. dlen = read(fd, bigbuf, sizeof(bigbuf)-1);
  396. if(dlen < 0)
  397. sysfatal("listen read: %r");
  398. bigbuf[dlen] = '\0';
  399. op = (bigbuf[0]<<8) | bigbuf[1];
  400. dlen -= Opsize;
  401. mode = file = bigbuf + Opsize;
  402. while(*mode != '\0' && dlen--)
  403. mode++;
  404. mode++;
  405. p = mode;
  406. while(*p && dlen--)
  407. p++;
  408. file = mapname(file); /* we don't free the result; minor leak */
  409. if(dlen == 0) {
  410. nak(fd, 0, "bad tftpmode");
  411. close(fd);
  412. syslog(dbg, flog, "tftpd %d bad mode %s for file %s from %s",
  413. pid, mode, file, raddr);
  414. return;
  415. }
  416. if(op != Tftp_READ && op != Tftp_WRITE) {
  417. nak(fd, Errbadop, "Illegal TFTP operation");
  418. close(fd);
  419. syslog(dbg, flog, "tftpd %d bad request %d (%s) %s", pid, op,
  420. (op < nelem(opnames)? opnames[op]: "gok"), raddr);
  421. return;
  422. }
  423. if(restricted){
  424. if(file[0] == '#' || strncmp(file, "../", 3) == 0 ||
  425. strstr(file, "/../") != nil ||
  426. (file[0] == '/' && strncmp(file, dirsl, dirsllen) != 0)){
  427. nak(fd, Errnoaccess, "Permission denied");
  428. close(fd);
  429. syslog(dbg, flog, "tftpd %d bad request %d from %s file %s",
  430. pid, op, raddr, file);
  431. return;
  432. }
  433. }
  434. /*
  435. * options are supposed to be negotiated, but the cavium board's
  436. * u-boot really wants us to use a block size of 1432 bytes and won't
  437. * take `no' for an answer.
  438. */
  439. p++; /* skip NUL after mode */
  440. dlen--;
  441. opts = 0;
  442. if(dlen > 0) { /* might have options */
  443. char bytes[32*1024];
  444. if(Debug)
  445. optlog(bytes, p, dlen);
  446. opts = options(fd, bytes, sizeof bytes, file, op, p, dlen);
  447. if (opts < 0)
  448. return;
  449. }
  450. if(op == Tftp_READ)
  451. sendfile(fd, file, mode, opts);
  452. else
  453. recvfile(fd, file, mode);
  454. }
  455. void
  456. catcher(void *junk, char *msg)
  457. {
  458. USED(junk);
  459. if(strncmp(msg, "exit", 4) == 0)
  460. noted(NDFLT);
  461. noted(NCONT);
  462. }
  463. static int
  464. awaitack(int net, int block)
  465. {
  466. int ackblock, al, rxl;
  467. uint16_t op;
  468. uint8_t ack[1024];
  469. for(rxl = 0; rxl < 10; rxl++) {
  470. memset(ack, 0, Hdrsize);
  471. alarm(1000);
  472. al = read(net, ack, sizeof(ack));
  473. alarm(0);
  474. if(al < 0) {
  475. if (Debug)
  476. syslog(dbg, flog, "tftpd %d timed out "
  477. "waiting for ack from %s", pid, raddr);
  478. return Ackrexmit;
  479. }
  480. op = ack[0]<<8|ack[1];
  481. if(op == Tftp_ERROR) {
  482. if (Debug)
  483. syslog(dbg, flog, "tftpd %d got error "
  484. "waiting for ack from %s", pid, raddr);
  485. return Ackerr;
  486. } else if(op != Tftp_ACK) {
  487. syslog(dbg, flog, "tftpd %d rcvd %s op from %s", pid,
  488. (op < nelem(opnames)? opnames[op]: "gok"),
  489. raddr);
  490. return Ackerr;
  491. }
  492. ackblock = ack[2]<<8|ack[3];
  493. if (Debug)
  494. syslog(dbg, flog, "tftpd %d read ack of %d bytes "
  495. "for block %d", pid, al, ackblock);
  496. if(ackblock == block)
  497. return Ackok; /* for block just sent */
  498. else if(ackblock == block + 1) /* intel pxe eof bug */
  499. return Ackok;
  500. else if(ackblock == 0xffff)
  501. return Ackrexmit;
  502. else
  503. /* ack is for some other block; ignore it, try again */
  504. syslog(dbg, flog, "tftpd %d expected ack for block %d, "
  505. "got %d", pid, block, ackblock);
  506. }
  507. return Ackrexmit;
  508. }
  509. void
  510. sendfile(int net, char *name, char *mode, int opts)
  511. {
  512. int file, block, ret, rexmit, n, txtry, failed;
  513. uint8_t buf[Maxsegsize+Hdrsize];
  514. char errbuf[Maxerr];
  515. file = -1;
  516. failed = 1;
  517. syslog(dbg, flog, "tftpd %d send file '%s' %s to %s",
  518. pid, name, mode, raddr);
  519. name = sunkernel(name);
  520. if(name == 0){
  521. nak(net, 0, "not in our database");
  522. goto error;
  523. }
  524. notify(catcher);
  525. file = open(name, OREAD);
  526. if(file < 0) {
  527. errstr(errbuf, sizeof errbuf);
  528. nak(net, 0, errbuf);
  529. goto error;
  530. }
  531. block = 0;
  532. rexmit = Ackok;
  533. n = 0;
  534. /*
  535. * if we sent an oack previously, wait for the client's ack or error.
  536. * if we get no ack for our oack, it could be that we returned
  537. * a tsize that the client can't handle, or it could be intel
  538. * pxe just read-with-tsize to get size, couldn't be bothered to
  539. * ack our oack and has just gone ahead and issued another read.
  540. */
  541. if(opts && awaitack(net, 0) != Ackok)
  542. goto error;
  543. for(txtry = 0; txtry < timeout;) {
  544. if(rexmit == Ackok) {
  545. /* block number wraparound for enormous hogs */
  546. if (block >= 65536)
  547. block = 0;
  548. block++;
  549. buf[0] = 0;
  550. buf[1] = Tftp_DATA;
  551. buf[2] = block>>8;
  552. buf[3] = block;
  553. n = read(file, buf+Hdrsize, blksize);
  554. if(n < 0) {
  555. errstr(errbuf, sizeof errbuf);
  556. nak(net, 0, errbuf);
  557. goto error;
  558. }
  559. txtry = 0;
  560. }
  561. else {
  562. syslog(dbg, flog, "tftpd %d rexmit %d %s:%d to %s",
  563. pid, Hdrsize+n, name, block, raddr);
  564. txtry++;
  565. }
  566. ret = write(net, buf, Hdrsize+n);
  567. if(ret < Hdrsize+n) {
  568. syslog(dbg, flog,
  569. "tftpd network write error on %s to %s: %r",
  570. name, raddr);
  571. sysfatal("tftpd: network write error: %r");
  572. }
  573. if (Debug)
  574. syslog(dbg, flog, "tftpd %d sent block %d", pid, block);
  575. rexmit = awaitack(net, block);
  576. if (rexmit == Ackerr)
  577. break;
  578. if(ret != blksize+Hdrsize && rexmit == Ackok) {
  579. failed = 0;
  580. break;
  581. }
  582. }
  583. error:
  584. syslog(dbg, flog, "tftpd %d %s file '%s' %s to %s",
  585. pid, (failed? "failed to send": "sent"), name, mode, raddr);
  586. close(net);
  587. close(file);
  588. }
  589. void
  590. recvfile(int net, char *name, char *mode)
  591. {
  592. uint16_t op, block, inblock;
  593. uint8_t buf[Maxsegsize+8];
  594. char errbuf[Maxerr];
  595. int n, ret, file;
  596. syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr);
  597. file = create(name, OWRITE, 0666);
  598. if(file < 0) {
  599. errstr(errbuf, sizeof errbuf);
  600. nak(net, 0, errbuf);
  601. syslog(dbg, flog, "can't create %s: %r", name);
  602. return;
  603. }
  604. block = 0;
  605. ack(net, block);
  606. block++;
  607. for (;;) {
  608. alarm(15000);
  609. n = read(net, buf, blksize+8);
  610. alarm(0);
  611. if(n < 0) {
  612. syslog(dbg, flog, "tftpd: network error reading %s: %r",
  613. name);
  614. goto error;
  615. }
  616. /*
  617. * NB: not `<='; just a header is legal and happens when
  618. * file being read is a multiple of segment-size bytes long.
  619. */
  620. if(n < Hdrsize) {
  621. syslog(dbg, flog,
  622. "tftpd: short read from network, reading %s",
  623. name);
  624. goto error;
  625. }
  626. op = buf[0]<<8|buf[1];
  627. if(op == Tftp_ERROR) {
  628. syslog(dbg, flog, "tftpd: tftp error reading %s", name);
  629. goto error;
  630. }
  631. n -= Hdrsize;
  632. inblock = buf[2]<<8|buf[3];
  633. if(op == Tftp_DATA) {
  634. if(inblock == block) {
  635. ret = write(file, buf+Hdrsize, n);
  636. if(ret != n) {
  637. errstr(errbuf, sizeof errbuf);
  638. nak(net, 0, errbuf);
  639. syslog(dbg, flog,
  640. "tftpd: error writing %s: %s",
  641. name, errbuf);
  642. goto error;
  643. }
  644. ack(net, block);
  645. block++;
  646. } else
  647. ack(net, 0xffff); /* tell him to resend */
  648. }
  649. }
  650. error:
  651. close(file);
  652. }
  653. void
  654. ack(int fd, uint16_t block)
  655. {
  656. uint8_t ack[4];
  657. int n;
  658. ack[0] = 0;
  659. ack[1] = Tftp_ACK;
  660. ack[2] = block>>8;
  661. ack[3] = block;
  662. n = write(fd, ack, 4);
  663. if(n < 4)
  664. sysfatal("network write: %r");
  665. }
  666. void
  667. nak(int fd, int code, char *msg)
  668. {
  669. char buf[128];
  670. int n;
  671. buf[0] = 0;
  672. buf[1] = Tftp_ERROR;
  673. buf[2] = 0;
  674. buf[3] = code;
  675. strcpy(buf+4, msg);
  676. n = strlen(msg) + 4 + 1;
  677. if(write(fd, buf, n) < n)
  678. sysfatal("write nak: %r");
  679. }
  680. void
  681. setuser(void)
  682. {
  683. int fd;
  684. fd = open("#c/user", OWRITE);
  685. if(fd < 0 || write(fd, "none", strlen("none")) < 0)
  686. sysfatal("can't become none: %r");
  687. close(fd);
  688. if(newns("none", nil) < 0)
  689. sysfatal("can't build namespace: %r");
  690. }
  691. char*
  692. lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
  693. {
  694. static Ndb *db;
  695. char *attrs[1];
  696. Ndbtuple *t;
  697. if(db == nil)
  698. db = ndbopen(0);
  699. if(db == nil)
  700. return nil;
  701. if(sattr == nil)
  702. sattr = ipattr(sval);
  703. attrs[0] = tattr;
  704. t = ndbipinfo(db, sattr, sval, attrs, 1);
  705. if(t == nil)
  706. return nil;
  707. strncpy(tval, t->val, len);
  708. tval[len-1] = 0;
  709. ndbfree(t);
  710. return tval;
  711. }
  712. /*
  713. * for sun kernel boots, replace the requested file name with
  714. * a one from our database. If the database doesn't specify a file,
  715. * don't answer.
  716. */
  717. char*
  718. sunkernel(char *name)
  719. {
  720. uint32_t addr;
  721. uint8_t v4[IPv4addrlen];
  722. uint8_t v6[IPaddrlen];
  723. char buf[256];
  724. char ipbuf[128];
  725. char *suffix;
  726. addr = strtoul(name, &suffix, 16);
  727. if(suffix-name != 8 || (strcmp(suffix, "") != 0 && strcmp(suffix, ".SUN") != 0))
  728. return name;
  729. v4[0] = addr>>24;
  730. v4[1] = addr>>16;
  731. v4[2] = addr>>8;
  732. v4[3] = addr;
  733. v4tov6(v6, v4);
  734. sprint(ipbuf, "%I", v6);
  735. return lookup("ip", ipbuf, "bootf", buf, sizeof buf);
  736. }
  737. void
  738. remoteaddr(char *dir, char *raddr, int len)
  739. {
  740. char buf[64];
  741. int fd, n;
  742. snprint(buf, sizeof(buf), "%s/remote", dir);
  743. fd = open(buf, OREAD);
  744. if(fd < 0){
  745. snprint(raddr, sizeof(raddr), "unknown");
  746. return;
  747. }
  748. n = read(fd, raddr, len-1);
  749. close(fd);
  750. if(n <= 0){
  751. snprint(raddr, sizeof(raddr), "unknown");
  752. return;
  753. }
  754. if(n > 0)
  755. n--;
  756. raddr[n] = 0;
  757. }