2 * tftpd - tftp service, see /lib/rfc/rfc783 (now rfc1350 + 234[789])
18 Opsize= sizeof(short),
19 Blksize= sizeof(short),
20 Hdrsize= Opsize + Blksize,
32 Tftp_OACK = 6, /* option acknowledge */
34 Errnotdef = 0, /* see textual error instead */
42 Errbadopt = 8, /* really bad option value */
45 Maxsegsize = 65464, /* from rfc2348 */
48 * bandt (viaduct) tunnels use smaller mtu than ether's
49 * (1400 bytes for tcp mss of 1300 bytes).
53 * maximum size of block's data content, excludes hdrs,
54 * notably IP/UDP and TFTP, using worst-case (IPv6) sizes.
56 Bandtblksz = Bandtmtu - 40 - 8,
59 typedef struct Opt Opt;
62 int *valp; /* set to client's value if within bounds */
72 int blksize = Defsegsize; /* excluding 4-byte header */
73 int timeout = 5; /* seconds */
75 static Opt option[] = {
76 "timeout", &timeout, 1, 255,
77 /* see "hack" below */
78 "blksize", &blksize, 8, Maxsegsize,
79 "tsize", &tsize, 0, ~0UL >> 1,
82 void sendfile(int, char*, char*, int);
83 void recvfile(int, char*, char*);
84 void nak(int, int, char*);
85 void ack(int, ushort);
88 char* sunkernel(char*);
89 void remoteaddr(char*, char*, int);
95 char *dir = "/lib/tftpd";
98 char flog[] = "ipboot";
101 static char *opnames[] = {
103 [Tftp_WRITE] "write",
106 [Tftp_ERROR] "error",
113 fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt]\n",
119 main(int argc, char **argv)
122 char adir[64], ldir[64];
126 setnetmtpt(net, sizeof net, nil);
132 dir = EARGF(usage());
138 svc = EARGF(usage());
141 setnetmtpt(net, sizeof net, EARGF(usage()));
147 snprint(buf, sizeof buf, "%s/", dir);
149 dirsllen = strlen(dirsl);
151 fmtinstall('E', eipfmt);
152 fmtinstall('I', eipfmt);
155 * setuser calls newns, and typical /lib/namespace files contain
156 * "cd /usr/$user", so call setuser before chdir.
160 sysfatal("can't get to directory %s: %r", dir);
163 switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
165 sysfatal("fork: %r");
172 snprint(buf, sizeof buf, "%s/udp!*!%s", net, svc);
173 cfd = announce(buf, adir);
175 sysfatal("announcing on %s: %r", buf);
176 syslog(dbg, flog, "tftpd started on %s dir %s", buf, adir);
179 lcfd = listen(adir, ldir);
181 sysfatal("listening on %s: %r", adir);
185 sysfatal("fork: %r");
187 dfd = accept(lcfd, ldir);
190 remoteaddr(ldir, raddr, sizeof(raddr));
192 syslog(0, flog, "tftp %d connection from %s dir %s",
205 handleopt(int fd, char *name, char *val)
210 for (op = option; op < option + nelem(option); op++)
211 if(cistrcmp(name, op->name) == 0) {
212 n = strtol(val, nil, 10);
213 if (n < op->min || n > op->max) {
214 nak(fd, Errbadopt, "option value out of range");
215 syslog(dbg, flog, "tftp bad option value from "
216 "client: %s %s", name, val);
217 sysfatal("bad option value from client: %s %s",
221 syslog(dbg, flog, "tftpd %d setting %s to %d",
243 options(int fd, char *buf, char *file, ushort oper, char *p, int dlen)
245 int nmlen, vallen, nopts;
254 while (dlen > 0 && *p != '\0') {
255 nmlen = strlen(p) + 1; /* include NUL */
260 if (dlen <= 0 || *val == '\0')
263 vallen = strlen(val) + 1;
269 op = handleopt(fd, p, val);
271 /* append OACK response to buf */
274 if (oper == Tftp_READ && cistrcmp(p, "tsize") == 0) {
275 size = filesize(file);
276 sprint(bp, "%lld", size);
277 syslog(dbg, flog, "tftpd %d %s tsize is %,lld",
281 * hack: bandt (viaducts) uses smaller mtu than ether's
282 * (1400 bytes for tcp mss of 1300 bytes),
283 * so offer at most bandt's mtu minus headers,
284 * to avoid failure of pxe booting via viaduct.
286 else if (oper == Tftp_READ &&
287 cistrcmp(p, "blksize") == 0 &&
288 blksize > Bandtblksz) {
289 blksize = Bandtblksz;
290 sprint(bp, "%d", blksize);
292 "tftpd %d overriding blksize to %d",
295 strcpy(bp, val); /* use requested value */
296 bp += strlen(bp) + 1;
301 return 0; /* no options actually seen */
303 *bp++ = '\0'; /* overkill */
305 if (write(fd, buf, bp - buf) < bp - buf) {
306 syslog(dbg, flog, "tftpd network write error on oack to %s: %r",
308 sysfatal("tftpd: network write error: %r");
311 syslog(dbg, flog, "tftpd oack: options to %s", raddr);
315 /* this doesn't stop the cavium from barging ahead */
317 //sendnoopts(int fd, char *name)
321 // memset(buf, 0, sizeof buf);
323 // buf[1] = Tftp_OACK;
325 // if(write(fd, buf, sizeof buf) < sizeof buf) {
326 // syslog(dbg, flog, "tftpd network write error on %s oack to %s: %r",
328 // sysfatal("tftpd: network write error: %r");
331 // syslog(dbg, flog, "tftpd oack: no options to %s", raddr);
335 optlog(char *bytes, char *p, int dlen)
340 sprint(bp, "tftpd %d option bytes: ", dlen);
342 for (; dlen > 0; dlen--, p++)
345 syslog(dbg, flog, "%s", bytes);
352 char *mode, *p, *file;
355 dlen = read(fd, bigbuf, sizeof(bigbuf)-1);
357 sysfatal("listen read: %r");
360 op = (bigbuf[0]<<8) | bigbuf[1];
362 mode = file = bigbuf + Opsize;
363 while(*mode != '\0' && dlen--)
370 nak(fd, 0, "bad tftpmode");
372 syslog(dbg, flog, "tftpd %d bad mode %s for file %s from %s",
373 pid, mode, file, raddr);
377 if(op != Tftp_READ && op != Tftp_WRITE) {
378 nak(fd, Errbadop, "Illegal TFTP operation");
380 syslog(dbg, flog, "tftpd %d bad request %d %s", pid, op, raddr);
385 if(file[0] == '#' || strncmp(file, "../", 3) == 0 ||
386 strstr(file, "/../") != nil ||
387 (file[0] == '/' && strncmp(file, dirsl, dirsllen) != 0)){
388 nak(fd, Errnoaccess, "Permission denied");
390 syslog(dbg, flog, "tftpd %d bad request %d from %s file %s",
391 pid, op, raddr, file);
397 * options are supposed to be negotiated, but the cavium board's
398 * u-boot really wants us to use a block size of 1432 bytes and won't
399 * take `no' for an answer.
401 p++; /* skip NUL after mode */
404 if(dlen > 0) { /* might have options */
408 optlog(bytes, p, dlen);
409 opts = options(fd, bytes, file, op, p, dlen);
412 sendfile(fd, file, mode, opts);
414 recvfile(fd, file, mode);
418 catcher(void *junk, char *msg)
422 if(strncmp(msg, "exit", 4) == 0)
428 awaitack(int fd, int block)
430 int ackblock, al, rxl;
434 for(rxl = 0; rxl < 10; rxl++) {
435 memset(ack, 0, Hdrsize);
437 al = read(fd, ack, sizeof(ack));
441 syslog(dbg, flog, "tftpd %d timed out "
442 "waiting for ack from %s", pid, raddr);
445 op = ack[0]<<8|ack[1];
446 if(op == Tftp_ERROR) {
448 syslog(dbg, flog, "tftpd %d got error "
449 "waiting for ack from %s", pid, raddr);
451 } else if(op != Tftp_ACK) {
452 syslog(dbg, flog, "tftpd %d rcvd %s op from %s", pid,
453 (op < nelem(opnames)? opnames[op]: "gok"),
457 ackblock = ack[2]<<8|ack[3];
459 syslog(dbg, flog, "tftpd %d read ack of %d bytes "
460 "for block %d", pid, al, ackblock);
461 if(ackblock == block)
462 return Ackok; /* for block just sent */
463 else if(ackblock == block + 1) /* intel pxe eof bug */
465 else if(ackblock == 0xffff)
468 /* ack is for some other block; ignore it, try again */
469 syslog(dbg, flog, "tftpd %d expected ack for block %d, "
470 "got %d", pid, block, ackblock);
476 sendfile(int fd, char *name, char *mode, int opts)
478 int file, block, ret, rexmit, n, txtry;
479 uchar buf[Maxsegsize+Hdrsize];
482 syslog(dbg, flog, "tftpd %d send file '%s' %s to %s",
483 pid, name, mode, raddr);
484 name = sunkernel(name);
486 nak(fd, 0, "not in our database");
492 file = open(name, OREAD);
494 errstr(errbuf, sizeof errbuf);
502 * if we sent an oack previously, wait for the client's ack or error.
503 * if we get no ack for our oack, it could be that we returned
504 * a tsize that the client can't handle, or it could be intel
505 * pxe just read-with-tsize to get size, couldn't be bothered to
506 * ack our oack and has just gone ahead and issued another read.
508 if(opts && awaitack(fd, 0) != Ackok)
511 for(txtry = 0; txtry < timeout;) {
512 if(rexmit == Ackok) {
518 n = read(file, buf+Hdrsize, blksize);
520 errstr(errbuf, sizeof errbuf);
527 syslog(dbg, flog, "tftpd %d rexmit %d %s:%d to %s",
528 pid, Hdrsize+n, name, block, raddr);
532 ret = write(fd, buf, Hdrsize+n);
533 if(ret < Hdrsize+n) {
535 "tftpd network write error on %s to %s: %r",
537 sysfatal("tftpd: network write error: %r");
540 syslog(dbg, flog, "tftpd %d sent block %d", pid, block);
542 rexmit = awaitack(fd, block);
543 if (rexmit == Ackerr)
545 if(ret != blksize+Hdrsize && rexmit == Ackok)
554 recvfile(int fd, char *name, char *mode)
556 ushort op, block, inblock;
557 uchar buf[Maxsegsize+8];
561 syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr);
563 file = create(name, OWRITE, 0666);
565 errstr(errbuf, sizeof errbuf);
567 syslog(dbg, flog, "can't create %s: %r", name);
577 n = read(fd, buf, blksize+8);
580 syslog(dbg, flog, "tftpd: network error reading %s: %r",
586 "tftpd: short read from network, reading %s",
590 op = buf[0]<<8|buf[1];
591 if(op == Tftp_ERROR) {
592 syslog(dbg, flog, "tftpd: tftp error reading %s", name);
597 inblock = buf[2]<<8|buf[3];
598 if(op == Tftp_DATA) {
599 if(inblock == block) {
600 ret = write(file, buf+Hdrsize, n);
602 errstr(errbuf, sizeof errbuf);
605 "tftpd: error writing %s: %s",
612 ack(fd, 0xffff); /* tell him to resend */
620 ack(int fd, ushort block)
630 n = write(fd, ack, 4);
632 sysfatal("network write: %r");
636 nak(int fd, int code, char *msg)
646 n = strlen(msg) + 4 + 1;
647 if(write(fd, buf, n) < n)
648 sysfatal("write nak: %r");
656 fd = open("#c/user", OWRITE);
657 if(fd < 0 || write(fd, "none", strlen("none")) < 0)
658 sysfatal("can't become none: %r");
660 if(newns("none", nil) < 0)
661 sysfatal("can't build namespace: %r");
665 lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
677 sattr = ipattr(sval);
680 t = ndbipinfo(db, sattr, sval, attrs, 1);
683 strncpy(tval, t->val, len);
690 * for sun kernel boots, replace the requested file name with
691 * a one from our database. If the database doesn't specify a file,
695 sunkernel(char *name)
698 uchar v4[IPv4addrlen];
704 addr = strtoul(name, &suffix, 16);
705 if(suffix-name != 8 || (strcmp(suffix, "") != 0 && strcmp(suffix, ".SUN") != 0))
713 sprint(ipbuf, "%I", v6);
714 return lookup("ip", ipbuf, "bootf", buf, sizeof buf);
718 remoteaddr(char *dir, char *raddr, int len)
723 snprint(buf, sizeof(buf), "%s/remote", dir);
724 fd = open(buf, OREAD);
726 snprint(raddr, sizeof(raddr), "unknown");
729 n = read(fd, raddr, len-1);
732 snprint(raddr, sizeof(raddr), "unknown");