summaryrefslogtreecommitdiff
path: root/fw/src/netfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/src/netfs.c')
-rw-r--r--fw/src/netfs.c72
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;
}
}