Hi, This diff adds an option for client IP address path prefixes to the tftpd(8). First, I used the -r rewrite socket for this, but...
If you use the rewrite socket feature, the tftpd(8) will exit with an error when the rewrite socket is closed. A reopen of the socket is not possible, if its outside of the chroot directory. And a privilege separated tftpd(8) is a bit overkill for a stable per client path rewrite feature. This story led me to this change here. Any suggestions or objections are welcome. :-) Bye, Jan Index: tftpd.8 =================================================================== RCS file: /mount/openbsd/cvs/src/usr.sbin/tftpd/tftpd.8,v retrieving revision 1.5 diff -u -p -r1.5 tftpd.8 --- tftpd.8 18 Jul 2015 05:32:56 -0000 1.5 +++ tftpd.8 18 Oct 2017 19:58:40 -0000 @@ -40,7 +40,7 @@ .Op Fl 46cdv .Op Fl l Ar address .Op Fl p Ar port -.Op Fl r Ar socket +.Op Fl i | Fl r Ar socket .Ar directory .Sh DESCRIPTION .Nm @@ -113,6 +113,12 @@ listens on the port indicated in the .Ql tftp service description; see .Xr services 5 . +.It Fl i +.Nm +will use the clients IP address as subdirectory prefix for all requested +filenames. +This option can not be combined with +.Fl r . .It Fl r Ar socket Issue filename rewrite requests to the specified UNIX domain socket. .Nm @@ -126,6 +132,8 @@ before the TFTP request will continue. By default .Nm does not use filename rewriting. +This option can not be combined with +.Fl i . .It Fl v Log the client IP, type of request, and filename. .It Ar directory Index: tftpd.c =================================================================== RCS file: /mount/openbsd/cvs/src/usr.sbin/tftpd/tftpd.c,v retrieving revision 1.39 diff -u -p -r1.39 tftpd.c --- tftpd.c 26 May 2017 17:38:46 -0000 1.39 +++ tftpd.c 18 Oct 2017 19:59:40 -0000 @@ -282,14 +282,15 @@ __dead void usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port] [-r socket]" - " directory\n", __progname); + fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port]" + " [-i | -r socket] directory\n", __progname); exit(1); } int cancreate = 0; int verbose = 0; int debug = 0; +int iflag = 0; int main(int argc, char *argv[]) @@ -307,7 +308,7 @@ main(int argc, char *argv[]) int family = AF_UNSPEC; int devnull = -1; - while ((c = getopt(argc, argv, "46cdl:p:r:v")) != -1) { + while ((c = getopt(argc, argv, "46cdil:p:r:v")) != -1) { switch (c) { case '4': family = AF_INET; @@ -321,6 +322,11 @@ main(int argc, char *argv[]) case 'd': verbose = debug = 1; break; + case 'i': + if (rewrite != NULL) + usage(); + iflag = 1; + break; case 'l': addr = optarg; break; @@ -328,6 +334,8 @@ main(int argc, char *argv[]) port = optarg; break; case 'r': + if (iflag) + usage(); rewrite = optarg; break; case 'v': @@ -903,7 +911,13 @@ again: if (rwmap != NULL) rewrite_map(client, filename); - else + else if (iflag) { + char nfilename[PATH_MAX]; + + snprintf(nfilename, sizeof nfilename, "%s/%s", + getip(&client->ss), filename); + tftp_open(client, nfilename); + } else tftp_open(client, filename); return;