2 * tftpd - tftp service, see /lib/rfc/rfc783 (now rfc1350 + 234[789])
17 Opsize= sizeof(short),
18 Blksize= sizeof(short),
19 Hdrsize= Opsize + Blksize,
31 Tftp_OACK = 6, /* option acknowledge */
33 Errnotdef = 0, /* see textual error instead */
41 Errbadopt = 8, /* really bad option value */
44 Maxsegsize = 65464, /* from rfc2348 */
47 * bandt (viaduct) tunnels use smaller mtu than ether's
48 * (1400 bytes for tcp mss of 1300 bytes).
52 * maximum size of block's data content, excludes hdrs,
53 * notably IP/UDP and TFTP, using worst-case (IPv6) sizes.
55 Bandtblksz = Bandtmtu - 40 - 8,
56 Bcavium = 1432, /* cavium's u-boot demands this size */
57 Bci20 = 1468, /* ci20 u-boot */
60 typedef struct Opt Opt;
63 int *valp; /* set to client's value if within bounds */
73 int blksize = Defsegsize; /* excluding 4-byte header */
74 int timeout = 5; /* seconds */
76 static Opt option[] = {
77 "timeout", &timeout, 1, 255,
78 /* see "hack" below */
79 "blksize", &blksize, 8, Maxsegsize,
80 "tsize", &tsize, 0, ~0UL >> 1,
83 void sendfile(int, char*, char*, int);
84 void recvfile(int, char*, char*);
85 void nak(int, int, char*);
86 void ack(int, ushort);
89 char* sunkernel(char*);
90 void remoteaddr(char*, char*, int);
96 char *dir = "/lib/tftpd";
99 char flog[] = "ipboot";
102 static char *opnames[] = {
104 [Tftp_WRITE] "write",
107 [Tftp_ERROR] "error",
114 fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt]\n",
120 main(int argc, char **argv)
123 char adir[64], ldir[64];
127 setnetmtpt(net, sizeof net, nil);
133 dir = EARGF(usage());
139 svc = EARGF(usage());
142 setnetmtpt(net, sizeof net, EARGF(usage()));
148 snprint(buf, sizeof buf, "%s/", dir);
150 dirsllen = strlen(dirsl);
152 fmtinstall('E', eipfmt);
153 fmtinstall('I', eipfmt);
156 * setuser calls newns, and typical /lib/namespace files contain
157 * "cd /usr/$user", so call setuser before chdir.
161 sysfatal("can't get to directory %s: %r", dir);
164 switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
166 sysfatal("fork: %r");
173 snprint(buf, sizeof buf, "%s/udp!*!%s", net, svc);
174 cfd = announce(buf, adir);
176 sysfatal("announcing on %s: %r", buf);
177 syslog(dbg, flog, "tftpd started on %s dir %s", buf, adir);
180 lcfd = listen(adir, ldir);
182 sysfatal("listening on %s: %r", adir);
186 sysfatal("fork: %r");
188 dfd = accept(lcfd, ldir);
191 remoteaddr(ldir, raddr, sizeof(raddr));
193 syslog(0, flog, "tftp %d connection from %s dir %s",
206 handleopt(int fd, char *name, char *val)
211 for (op = option; op < option + nelem(option); op++)
212 if(cistrcmp(name, op->name) == 0) {
213 n = strtol(val, nil, 10);
214 if (n < op->min || n > op->max) {
215 nak(fd, Errbadopt, "option value out of range");
216 syslog(dbg, flog, "tftp bad option value from "
217 "client: %s %s", name, val);
218 sysfatal("bad option value from client: %s %s",
222 /* incoming 0 for tsize is uninteresting */
223 if(cistrcmp("tsize", op->name) != 0)
224 syslog(dbg, flog, "tftpd %d setting %s to client's %d",
245 /* copy word into bp iff it fits before ep, returns bytes to advance bp. */
247 emits(char *word, char *bp, char *ep)
251 len = strlen(word) + 1;
258 /* format number into bp iff it fits before ep. */
260 emitn(vlong n, char *bp, char *ep)
264 snprint(numb, sizeof numb, "%lld", n);
265 return emits(numb, bp, ep);
269 * send an OACK packet to respond to options. bail early with -1 on error.
270 * p is the packet containing the options.
272 * hack: bandt (viaducts) uses smaller mtu than ether's
273 * (1400 bytes for tcp mss of 1300 bytes),
274 * so offer at most bandt's mtu minus headers,
275 * to avoid failure of pxe booting via viaduct.
276 * there's an exception for the cavium's u-boot.
279 options(int fd, char *buf, int bufsz, char *file, ushort oper, char *p, int dlen)
281 int nmlen, vallen, olen, nopts;
291 for (; dlen > 0 && *p != '\0'; p = val + vallen, bp += olen) {
292 nmlen = strlen(p) + 1; /* include NUL */
297 if (dlen <= 0 || *val == '\0')
300 vallen = strlen(val) + 1;
306 op = handleopt(fd, p, val);
312 /* append OACK response to buf */
313 nmlen = emits(p, bp, ep); /* option name */
318 if (oper == Tftp_READ && cistrcmp(p, "tsize") == 0) {
319 size = filesize(file);
321 nak(fd, Errnotfound, "no such file");
322 syslog(dbg, flog, "tftpd tsize for "
323 "non-existent file %s", file);
325 // olen = emits("0", bp, ep);
329 olen = emitn(size, bp, ep);
330 syslog(dbg, flog, "tftpd %d %s tsize is %,lld",
332 } else if (oper == Tftp_READ && cistrcmp(p, "blksize") == 0 &&
333 blksize > Bandtblksz && blksize != Bcavium && blksize != Bci20) {
334 *op->valp = blksize = Bandtblksz;
335 olen = emitn(blksize, bp, ep);
336 syslog(dbg, flog, "tftpd %d overriding blksize to %d",
339 olen = emits(val, bp, ep); /* use requested value */
342 return 0; /* no options actually seen */
344 if (write(fd, buf, bp - buf) < bp - buf) {
345 syslog(dbg, flog, "tftpd network write error on oack to %s: %r",
347 sysfatal("tftpd: network write error: %r");
350 syslog(dbg, flog, "tftpd oack: options to %s", raddr);
355 optlog(char *bytes, char *p, int dlen)
360 sprint(bp, "tftpd %d option bytes: ", dlen);
362 for (; dlen > 0; dlen--, p++)
365 syslog(dbg, flog, "%s", bytes);
369 * replace one occurrence of %[ICE] with ip, cfgpxe name, or ether mac, resp.
370 * we can't easily use $ because u-boot has stranger quoting rules than sh.
376 char *p, *newnm, *cur, *arpf, *ln, *remip, *bang;
380 p = strchr(file, '%');
381 if (p == nil || p[1] == '\0')
384 remip = strdup(raddr);
385 newnm = mallocz(strlen(file) + Maxpath, 1);
386 if (remip == nil || newnm == nil)
387 sysfatal("out of memory");
389 bang = strchr(remip, '!');
391 *bang = '\0'; /* remove !port */
393 memmove(newnm, file, p - file); /* copy up to % */
394 cur = newnm + strlen(newnm);
397 strcpy(cur, remip); /* remote's IP */
400 strcpy(cur, "/cfg/pxe/");
404 /* look up remote's IP in /net/arp to get mac. */
405 arpf = smprint("%s/arp", net);
406 arp = Bopen(arpf, OREAD);
410 /* read lines looking for remip in 3rd field of 4 */
411 while ((ln = Brdline(arp, '\n')) != nil) {
412 ln[Blinelen(arp)-1] = 0;
413 nf = tokenize(ln, fields, nelem(fields));
414 if (nf >= 4 && strcmp(fields[2], remip) == 0) {
415 strcpy(cur, fields[3]);
422 strcat(newnm, p + 2); /* tail following %x */
431 char *mode, *p, *file;
434 dlen = read(fd, bigbuf, sizeof(bigbuf)-1);
436 sysfatal("listen read: %r");
439 op = (bigbuf[0]<<8) | bigbuf[1];
441 mode = file = bigbuf + Opsize;
442 while(*mode != '\0' && dlen--)
449 file = mapname(file); /* we don't free the result; minor leak */
452 nak(fd, 0, "bad tftpmode");
454 syslog(dbg, flog, "tftpd %d bad mode %s for file %s from %s",
455 pid, mode, file, raddr);
459 if(op != Tftp_READ && op != Tftp_WRITE) {
460 nak(fd, Errbadop, "Illegal TFTP operation");
462 syslog(dbg, flog, "tftpd %d bad request %d (%s) %s", pid, op,
463 (op < nelem(opnames)? opnames[op]: "gok"), raddr);
468 if(file[0] == '#' || strncmp(file, "../", 3) == 0 ||
469 strstr(file, "/../") != nil ||
470 (file[0] == '/' && strncmp(file, dirsl, dirsllen) != 0)){
471 nak(fd, Errnoaccess, "Permission denied");
473 syslog(dbg, flog, "tftpd %d bad request %d from %s file %s",
474 pid, op, raddr, file);
480 * options are supposed to be negotiated, but the cavium board's
481 * u-boot really wants us to use a block size of 1432 bytes and won't
482 * take `no' for an answer.
484 p++; /* skip NUL after mode */
487 if(dlen > 0) { /* might have options */
491 optlog(bytes, p, dlen);
492 opts = options(fd, bytes, sizeof bytes, file, op, p, dlen);
497 sendfile(fd, file, mode, opts);
499 recvfile(fd, file, mode);
503 catcher(void *junk, char *msg)
507 if(strncmp(msg, "exit", 4) == 0)
513 awaitack(int fd, int block)
515 int ackblock, al, rxl;
519 for(rxl = 0; rxl < 10; rxl++) {
520 memset(ack, 0, Hdrsize);
522 al = read(fd, ack, sizeof(ack));
526 syslog(dbg, flog, "tftpd %d timed out "
527 "waiting for ack from %s", pid, raddr);
530 op = ack[0]<<8|ack[1];
531 if(op == Tftp_ERROR) {
533 syslog(dbg, flog, "tftpd %d got error "
534 "waiting for ack from %s", pid, raddr);
536 } else if(op != Tftp_ACK) {
537 syslog(dbg, flog, "tftpd %d rcvd %s op from %s", pid,
538 (op < nelem(opnames)? opnames[op]: "gok"),
542 ackblock = ack[2]<<8|ack[3];
544 syslog(dbg, flog, "tftpd %d read ack of %d bytes "
545 "for block %d", pid, al, ackblock);
546 if(ackblock == block)
547 return Ackok; /* for block just sent */
548 else if(ackblock == block + 1) /* intel pxe eof bug */
550 else if(ackblock == 0xffff)
553 /* ack is for some other block; ignore it, try again */
554 syslog(dbg, flog, "tftpd %d expected ack for block %d, "
555 "got %d", pid, block, ackblock);
561 sendfile(int fd, char *name, char *mode, int opts)
563 int file, block, ret, rexmit, n, txtry;
564 uchar buf[Maxsegsize+Hdrsize];
568 syslog(dbg, flog, "tftpd %d send file '%s' %s to %s",
569 pid, name, mode, raddr);
570 name = sunkernel(name);
572 nak(fd, 0, "not in our database");
578 file = open(name, OREAD);
580 errstr(errbuf, sizeof errbuf);
588 * if we sent an oack previously, wait for the client's ack or error.
589 * if we get no ack for our oack, it could be that we returned
590 * a tsize that the client can't handle, or it could be intel
591 * pxe just read-with-tsize to get size, couldn't be bothered to
592 * ack our oack and has just gone ahead and issued another read.
594 if(opts && awaitack(fd, 0) != Ackok)
597 for(txtry = 0; txtry < timeout;) {
598 if(rexmit == Ackok) {
604 n = read(file, buf+Hdrsize, blksize);
606 errstr(errbuf, sizeof errbuf);
613 syslog(dbg, flog, "tftpd %d rexmit %d %s:%d to %s",
614 pid, Hdrsize+n, name, block, raddr);
618 ret = write(fd, buf, Hdrsize+n);
619 if(ret < Hdrsize+n) {
621 "tftpd network write error on %s to %s: %r",
623 sysfatal("tftpd: network write error: %r");
626 syslog(dbg, flog, "tftpd %d sent block %d", pid, block);
628 rexmit = awaitack(fd, block);
629 if (rexmit == Ackerr)
631 if(ret != blksize+Hdrsize && rexmit == Ackok)
634 syslog(dbg, flog, "tftpd %d done sending file '%s' %s to %s",
635 pid, name, mode, raddr);
642 recvfile(int fd, char *name, char *mode)
644 ushort op, block, inblock;
645 uchar buf[Maxsegsize+8];
649 syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr);
651 file = create(name, OWRITE, 0666);
653 errstr(errbuf, sizeof errbuf);
655 syslog(dbg, flog, "can't create %s: %s", name, errbuf);
665 n = read(fd, buf, blksize+8);
668 syslog(dbg, flog, "tftpd: network error reading %s: %r",
673 * NB: not `<='; just a header is legal and happens when
674 * file being read is a multiple of segment-size bytes long.
678 "tftpd: short read from network, reading %s",
682 op = buf[0]<<8|buf[1];
683 if(op == Tftp_ERROR) {
684 syslog(dbg, flog, "tftpd: tftp error reading %s", name);
689 inblock = buf[2]<<8|buf[3];
690 if(op == Tftp_DATA) {
691 if(inblock == block) {
692 ret = write(file, buf+Hdrsize, n);
694 errstr(errbuf, sizeof errbuf);
697 "tftpd: error writing %s: %s",
704 ack(fd, 0xffff); /* tell him to resend */
712 ack(int fd, ushort block)
722 n = write(fd, ack, 4);
724 sysfatal("network write: %r");
728 nak(int fd, int code, char *msg)
740 memmove(buf+4, msg, n - 5);
742 if(write(fd, buf, n) != n)
743 sysfatal("write nak: %r");
751 fd = open("#c/user", OWRITE);
752 if(fd < 0 || write(fd, "none", strlen("none")) < 0)
753 sysfatal("can't become none: %r");
755 if(newns("none", nil) < 0)
756 sysfatal("can't build namespace: %r");
760 lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
772 sattr = ipattr(sval);
775 t = ndbipinfo(db, sattr, sval, attrs, 1);
778 strncpy(tval, t->val, len);
785 * for sun kernel boots, replace the requested file name with
786 * a one from our database. If the database doesn't specify a file,
790 sunkernel(char *name)
793 uchar v4[IPv4addrlen];
799 addr = strtoul(name, &suffix, 16);
800 if(suffix-name != 8 || (strcmp(suffix, "") != 0 && strcmp(suffix, ".SUN") != 0))
808 sprint(ipbuf, "%I", v6);
809 return lookup("ip", ipbuf, "bootf", buf, sizeof buf);
813 remoteaddr(char *dir, char *raddr, int len)
818 snprint(buf, sizeof(buf), "%s/remote", dir);
819 fd = open(buf, OREAD);
821 snprint(raddr, sizeof(raddr), "unknown");
824 n = read(fd, raddr, len-1);
827 snprint(raddr, sizeof(raddr), "unknown");