#include <auth.h>
#include <bio.h>
#include <ip.h>
-#include <ndb.h>
enum
{
Maxpath= 128,
- Maxerr= 256,
Debug= 0,
void ack(int, ushort);
void clrcon(void);
void setuser(void);
-char* sunkernel(char*);
void remoteaddr(char*, char*, int);
void doserve(int);
char bigbuf[32768];
char raddr[64];
-char *dir = "/lib/tftpd";
char *dirsl;
int dirsllen;
+char *homedir = "/";
char flog[] = "ipboot";
char net[Maxpath];
dbg++;
break;
case 'h':
- dir = EARGF(usage());
+ homedir = EARGF(usage());
break;
case 'r':
restricted = 1;
usage();
}ARGEND
- snprint(buf, sizeof buf, "%s/", dir);
- dirsl = strdup(buf);
- dirsllen = strlen(dirsl);
+ dirsllen = strlen(homedir);
+ while(dirsllen > 0 && homedir[dirsllen-1] == '/')
+ dirsllen--;
+ dirsl = smprint("%.*s/", utfnlen(homedir, dirsllen), homedir);
fmtinstall('E', eipfmt);
fmtinstall('I', eipfmt);
* "cd /usr/$user", so call setuser before chdir.
*/
setuser();
- if(chdir(dir) < 0)
- sysfatal("can't get to directory %s: %r", dir);
+ if(chdir(homedir) < 0)
+ sysfatal("can't get to directory %s: %r", homedir);
if(!dbg)
switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
break;
dlen -= vallen;
- nopts++;
olen = 0;
op = handleopt(fd, p, val);
if (op == nil)
continue;
+ nopts++;
+
/* append OACK response to buf */
nmlen = emits(p, bp, ep); /* option name */
if (nmlen < 0)
if (nopts == 0)
return 0; /* no options actually seen */
- if (bp + 3 >= ep)
- return -1;
-
if (write(fd, buf, bp - buf) < bp - buf) {
syslog(dbg, flog, "tftpd network write error on oack to %s: %r",
raddr);
if (Debug)
syslog(dbg, flog, "tftpd %d read ack of %d bytes "
"for block %d", pid, al, ackblock);
- if(ackblock == block)
+ if(ackblock == (block & 0xffff))
return Ackok; /* for block just sent */
- else if(ackblock == block + 1) /* intel pxe eof bug */
+ else if(ackblock == (block + 1 & 0xffff)) /* intel pxe eof bug */
return Ackok;
else if(ackblock == 0xffff)
return Ackrexmit;
{
int file, block, ret, rexmit, n, txtry;
uchar buf[Maxsegsize+Hdrsize];
- char errbuf[Maxerr];
+ char errbuf[ERRMAX];
- file = -1;
syslog(dbg, flog, "tftpd %d send file '%s' %s to %s",
pid, name, mode, raddr);
- name = sunkernel(name);
- if(name == 0){
- nak(fd, 0, "not in our database");
- goto error;
- }
notify(catcher);
{
ushort op, block, inblock;
uchar buf[Maxsegsize+8];
- char errbuf[Maxerr];
+ char errbuf[ERRMAX];
int n, ret, file;
syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr);
if(file < 0) {
errstr(errbuf, sizeof errbuf);
nak(fd, 0, errbuf);
- syslog(dbg, flog, "can't create %s: %r", name);
+ syslog(dbg, flog, "can't create %s: %s", name, errbuf);
return;
}
char buf[128];
int n;
+ n = 5 + strlen(msg);
+ if(n > sizeof(buf))
+ n = sizeof(buf);
buf[0] = 0;
buf[1] = Tftp_ERROR;
buf[2] = 0;
buf[3] = code;
- strcpy(buf+4, msg);
- n = strlen(msg) + 4 + 1;
- if(write(fd, buf, n) < n)
+ memmove(buf+4, msg, n - 5);
+ buf[n-1] = 0;
+ if(write(fd, buf, n) != n)
sysfatal("write nak: %r");
}
sysfatal("can't build namespace: %r");
}
-char*
-lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
-{
- static Ndb *db;
- char *attrs[1];
- Ndbtuple *t;
-
- if(db == nil)
- db = ndbopen(0);
- if(db == nil)
- return nil;
-
- if(sattr == nil)
- sattr = ipattr(sval);
-
- attrs[0] = tattr;
- t = ndbipinfo(db, sattr, sval, attrs, 1);
- if(t == nil)
- return nil;
- strncpy(tval, t->val, len);
- tval[len-1] = 0;
- ndbfree(t);
- return tval;
-}
-
-/*
- * for sun kernel boots, replace the requested file name with
- * a one from our database. If the database doesn't specify a file,
- * don't answer.
- */
-char*
-sunkernel(char *name)
-{
- ulong addr;
- uchar v4[IPv4addrlen];
- uchar v6[IPaddrlen];
- char buf[256];
- char ipbuf[128];
- char *suffix;
-
- addr = strtoul(name, &suffix, 16);
- if(suffix-name != 8 || (strcmp(suffix, "") != 0 && strcmp(suffix, ".SUN") != 0))
- return name;
-
- v4[0] = addr>>24;
- v4[1] = addr>>16;
- v4[2] = addr>>8;
- v4[3] = addr;
- v4tov6(v6, v4);
- sprint(ipbuf, "%I", v6);
- return lookup("ip", ipbuf, "bootf", buf, sizeof buf);
-}
-
void
remoteaddr(char *dir, char *raddr, int len)
{