ip/tftpd: add -m argument for name substitution using regular expressions
This allows mapping incoming filenames to a different name using regular expressions, followed by subtitutions of the %[ICE] format strings. I needed this to have individual cmdline.txt files for netbooted raspberry pi's. In this example, i map cmdline.txt to %C, which gets substituted for /cfg/pxe/$ether of the client.
This commit is contained in:
parent
dc72530159
commit
e4f30c89f4
2 changed files with 106 additions and 6 deletions
|
@ -43,7 +43,9 @@ dhcpd, dhcp6d, dhcpleases, rarpd, tftpd \- Internet booting
|
|||
.RB [ -x
|
||||
.IR netmtpt ]
|
||||
.RB [ -n
|
||||
.IR namespace-file ]
|
||||
.IR nsfile ]
|
||||
.RB [ -m
|
||||
.IR mapfile ]
|
||||
.SH DESCRIPTION
|
||||
These programs support booting over the Internet.
|
||||
They should all be run on the same server to
|
||||
|
@ -323,6 +325,26 @@ Restricts access to only those files rooted in the
|
|||
.TP
|
||||
.B n
|
||||
Sets the namespace file (default /lib/namespace).
|
||||
.TP
|
||||
.B m
|
||||
Loads name substitutions from
|
||||
.IR mapfile .
|
||||
The format is a space or tab separated two-column text
|
||||
with the first column being a regular expression
|
||||
(see
|
||||
.IR regexp (6))
|
||||
that is matched against the requested file name
|
||||
and the second column contains a subsitution.
|
||||
Lines starting with
|
||||
.B #
|
||||
are ignored.
|
||||
Occurances in the resulting filename of
|
||||
.BR %I ,
|
||||
.B %C
|
||||
or
|
||||
.B %E
|
||||
are replaced with the ip, cfgpxe name or ether MAC of
|
||||
of the client.
|
||||
.PD
|
||||
.SH FILES
|
||||
.BR /lib/ndb/dhcp " directory of dynamic address files
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <auth.h>
|
||||
#include <bio.h>
|
||||
#include <ip.h>
|
||||
#include <regexp.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -63,6 +64,13 @@ struct Opt {
|
|||
int max;
|
||||
};
|
||||
|
||||
typedef struct Map Map;
|
||||
struct Map {
|
||||
Reprog *re;
|
||||
char *sub;
|
||||
Map *next;
|
||||
};
|
||||
|
||||
int dbg;
|
||||
int restricted;
|
||||
int pid;
|
||||
|
@ -85,6 +93,7 @@ void ack(int, ushort);
|
|||
void clrcon(void);
|
||||
void setuser(void);
|
||||
void remoteaddr(char*, char*, int);
|
||||
void readmapfile(char*);
|
||||
void doserve(int);
|
||||
|
||||
char bigbuf[32768];
|
||||
|
@ -94,6 +103,7 @@ char *dirsl;
|
|||
int dirsllen;
|
||||
char *homedir = "/";
|
||||
char *nsfile = nil;
|
||||
Map *namemap = nil;
|
||||
char flog[] = "ipboot";
|
||||
char net[Maxpath];
|
||||
|
||||
|
@ -109,7 +119,7 @@ static char *opnames[] = {
|
|||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt]\n",
|
||||
fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt] [-n nsfile] [-m mapfile]\n",
|
||||
argv0);
|
||||
exits("usage");
|
||||
}
|
||||
|
@ -142,6 +152,9 @@ main(int argc, char **argv)
|
|||
case 'n':
|
||||
nsfile = EARGF(usage());
|
||||
break;
|
||||
case 'm':
|
||||
readmapfile(EARGF(usage()));
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
@ -177,7 +190,6 @@ main(int argc, char **argv)
|
|||
if (cfd < 0)
|
||||
sysfatal("announcing on %s: %r", buf);
|
||||
syslog(dbg, flog, "tftpd started on %s dir %s", buf, adir);
|
||||
// setuser();
|
||||
for(;;) {
|
||||
lcfd = listen(adir, ldir);
|
||||
if(lcfd < 0)
|
||||
|
@ -368,16 +380,27 @@ optlog(char *bytes, char *p, int dlen)
|
|||
}
|
||||
|
||||
/*
|
||||
* substitute name from namemap file and
|
||||
* replace one occurrence of %[ICE] with ip, cfgpxe name, or ether mac, resp.
|
||||
* we can't easily use $ because u-boot has stranger quoting rules than sh.
|
||||
*/
|
||||
char *
|
||||
mapname(char *file)
|
||||
{
|
||||
int nf;
|
||||
char *p, *newnm, *cur, *arpf, *ln, *remip, *bang;
|
||||
char *fields[4];
|
||||
char sub[1024], *p, *newnm, *cur, *arpf, *ln, *remip, *bang;
|
||||
Biobuf *arp;
|
||||
Map *map;
|
||||
|
||||
for(map = namemap; map != nil; map = map->next){
|
||||
Resub subs[16];
|
||||
|
||||
memset(subs, 0, sizeof(subs));
|
||||
if(regexec(map->re, file, subs, nelem(subs))){
|
||||
regsub(map->sub, sub, sizeof(sub), subs, nelem(subs));
|
||||
file = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p = strchr(file, '%');
|
||||
if (p == nil || p[1] == '\0')
|
||||
|
@ -411,6 +434,9 @@ mapname(char *file)
|
|||
break;
|
||||
/* read lines looking for remip in 3rd field of 4 */
|
||||
while ((ln = Brdline(arp, '\n')) != nil) {
|
||||
char *fields[4];
|
||||
int nf;
|
||||
|
||||
ln[Blinelen(arp)-1] = 0;
|
||||
nf = tokenize(ln, fields, nelem(fields));
|
||||
if (nf >= 4 && strcmp(fields[2], remip) == 0) {
|
||||
|
@ -448,8 +474,12 @@ doserve(int fd)
|
|||
while(*p && dlen--)
|
||||
p++;
|
||||
|
||||
syslog(dbg, flog, "tftpd %d mode %s file %s", pid, mode, file);
|
||||
|
||||
file = mapname(file); /* we don't free the result; minor leak */
|
||||
|
||||
syslog(dbg, flog, "tftpd %d file -> %s", pid, file);
|
||||
|
||||
if(dlen == 0) {
|
||||
nak(fd, 0, "bad tftpmode");
|
||||
close(fd);
|
||||
|
@ -772,3 +802,51 @@ remoteaddr(char *dir, char *raddr, int len)
|
|||
n--;
|
||||
raddr[n] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
readmapfile(char *file)
|
||||
{
|
||||
Map **link, *map;
|
||||
Biobuf *bio;
|
||||
char *s, *p, *d;
|
||||
int line;
|
||||
|
||||
/* go to last entry */
|
||||
for(link = &namemap; *link; link = &(*link)->next)
|
||||
;
|
||||
|
||||
if((bio = Bopen(file, OREAD)) == nil)
|
||||
sysfatal("open: %r");
|
||||
|
||||
for(line = 1; (s = Brdstr(bio, '\n', 1)) != nil; free(s), line++){
|
||||
p = s;
|
||||
while(strchr("\t ", *p))
|
||||
p++;
|
||||
|
||||
if(*p == '#')
|
||||
continue;
|
||||
|
||||
if(d = strchr(p, '\t'))
|
||||
*d++ = '\0';
|
||||
else if(d = strchr(p, ' '))
|
||||
*d++ = '\0';
|
||||
else {
|
||||
fprint(2, "%s:%d: ignored: %s\n", file, line, p);
|
||||
continue;
|
||||
}
|
||||
while(strchr("\t ", *d))
|
||||
d++;
|
||||
map = malloc(sizeof(Map));
|
||||
map->re = regcomp(p);
|
||||
if(map->re == nil){
|
||||
fprint(2, "%s:%d: syntax error: %s\n", file, line, p);
|
||||
free(map);
|
||||
continue;
|
||||
}
|
||||
map->sub = strdup(d);
|
||||
map->next = nil;
|
||||
*link = map;
|
||||
link = &map->next;
|
||||
}
|
||||
Bterm(bio);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue