diff options
Diffstat (limited to 'fw/src/netfs.c')
| -rw-r--r-- | fw/src/netfs.c | 72 |
1 files changed, 43 insertions, 29 deletions
diff --git a/fw/src/netfs.c b/fw/src/netfs.c index f44b089..1300717 100644 --- a/fw/src/netfs.c +++ b/fw/src/netfs.c @@ -345,14 +345,16 @@ static char *okverbs[] = { * a bare port, or addr!port with addr often "*". */ static char* -checkctl(char *proto, char *msg, long n) +checkctl(Match *m, char *proto, char *msg, long n) { - char buf[512], *f[8], *a[4], *addr, *e; - static char err[128]; + char buf[512], dest[128], *f[8], *a[4], *addr; uchar ip[IPaddrlen], mask[IPaddrlen]; - Rule *rule; - int nf, na, verb, anyip, port, lport, i; + int nf, na, i; + memset(m, 0, sizeof *m); + m->count = 1; + m->proto = proto; + m->ip = ip; if(n <= 0) return nil; if(n >= sizeof buf) @@ -363,9 +365,9 @@ checkctl(char *proto, char *msg, long n) if((nf = tokenize(buf, f, nelem(f))) < 1) return nil; if(strcmp(f[0], "connect") == 0) - verb = Vout; + m->verb = Vout; else if(strcmp(f[0], "announce") == 0) - verb = Vin; + m->verb = Vin; else{ /* * Anything else is refused unless it is known to be @@ -387,22 +389,29 @@ checkctl(char *proto, char *msg, long n) return nil; syslog(0, "fw", "deny %s %s: control message not permitted", proto, f[0]); - snprint(err, sizeof err, + snprint(m->err, sizeof m->err, "fw: %s: not a permitted control message", f[0]); - return err; + return m->err; } if(nf < 2) return nil; /* malformed; let the kernel say so */ + /* + * Keep the address before splitting it: getfields writes over the + * separators, so f[1] afterwards is only what precedes the first + * one, and the log said "connect 127.0.0.2" for a connection to a + * port it never named. + */ + snprint(dest, sizeof dest, "%s", f[1]); na = getfields(f[1], a, nelem(a), 0, "!"); if(na < 1) return nil; if(na == 1){ addr = "*"; /* announce 17019 */ - port = atoi(a[0]); + m->port = atoi(a[0]); }else{ addr = a[0]; - port = strcmp(a[1], "*") == 0 ? -1 : atoi(a[1]); + m->port = strcmp(a[1], "*") == 0 ? -1 : atoi(a[1]); } /* @@ -418,27 +427,30 @@ checkctl(char *proto, char *msg, long n) * peer therefore cannot apply to an announce, which is right: * at this point there is no peer to name. */ - if(verb == Vin){ - lport = port; - port = -1; - anyip = 1; + if(m->verb == Vin){ + m->lport = m->port; + m->port = -1; + m->anyip = 1; }else{ - lport = -1; - anyip = strcmp(addr, "*") == 0; - if(!anyip && parseipandmask(ip, mask, addr, nil) == -1){ + m->lport = -1; + m->anyip = strcmp(addr, "*") == 0; + if(!m->anyip && parseipandmask(ip, mask, addr, nil) == -1){ syslog(0, "fw", "deny %s %s %s: unparseable address", - proto, f[0], f[1]); - return "fw: unparseable address"; + proto, f[0], dest); + snprint(m->err, sizeof m->err, "fw: unparseable address"); + return m->err; } } - if((e = matchrule(verb, proto, ip, anyip, port, lport, &rule)) != nil){ - if(rule != nil && rule->log) - syslog(0, "fw", "deny %s %s %s: %s", proto, f[0], f[1], e); - snprint(err, sizeof err, "fw: %s", e); - return err; + if(!matchrule(m)){ + if(m->log) + syslog(0, "fw", "deny %s %s %s: %s", + proto, f[0], dest, m->err); + snprint(buf, sizeof buf, "fw: %s", m->err); + snprint(m->err, sizeof m->err, "%s", buf); + return m->err; } - if(rule != nil && rule->log) - syslog(0, "fw", "allow %s %s %s", proto, f[0], f[1]); + if(m->log) + syslog(0, "fw", "allow %s %s %s", proto, f[0], dest); return nil; } @@ -646,10 +658,12 @@ fswrite(Req *r) return; } if((proto = ctlproto(f->path)) != nil){ - e = checkctl(proto, r->ifcall.data, r->ifcall.count); + Match m; + + e = checkctl(&m, proto, r->ifcall.data, r->ifcall.count); free(proto); if(e != nil){ - respond(r, e); + respond(r, e); /* m outlives the respond, which packs it */ return; } } |
