summaryrefslogtreecommitdiff
path: root/fw/src/rules.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/src/rules.c')
-rw-r--r--fw/src/rules.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/fw/src/rules.c b/fw/src/rules.c
index b5992b0..82a31a5 100644
--- a/fw/src/rules.c
+++ b/fw/src/rules.c
@@ -302,16 +302,47 @@ readrules(char *file)
/*
* The current set, written back out as ndb. What comes out here must
* parse back in unchanged; it is what gets persisted.
+ *
+ * Allocated to fit, not written into 64K and clipped. A rule set that
+ * outgrew the buffer used to come back short, and since prepend, append
+ * and delete all work by formatting the set out, editing the text and
+ * parsing it again, editing one rule past the limit deleted every rule
+ * after it. Silently.
*/
-long
-fmtrules(char *buf, long nbuf)
+static long
+rulesize(Rule *r)
+{
+ long n;
+
+ /*
+ * "allow=out" and the fixed part of every attribute, an address
+ * and a mask at their longest, two ports, log=yes, the tabs and
+ * the newline. Only the protocol is unbounded, and it is ndb's
+ * word rather than anything we choose.
+ */
+ n = 160;
+ if(r->proto != nil)
+ n += strlen(r->proto);
+ return n;
+}
+
+char*
+rulestext(void)
{
- char *p, *e;
+ char *buf, *p, *e;
+ long sz;
Rule *r;
- p = buf;
- e = buf + nbuf;
lock(&rulelock);
+ sz = 1;
+ for(r = rules; r != nil; r = r->next)
+ sz += rulesize(r);
+ if((buf = malloc(sz)) == nil){
+ unlock(&rulelock);
+ return nil;
+ }
+ p = buf;
+ e = buf + sz;
for(r = rules; r != nil; r = r->next){
p = seprint(p, e, "%s=%s", r->allow ? "allow" : "deny",
r->verb == Vin ? "in" : r->verb == Vout ? "out" : "*");
@@ -328,7 +359,8 @@ fmtrules(char *buf, long nbuf)
p = seprint(p, e, "\n");
}
unlock(&rulelock);
- return p - buf;
+ USED(p);
+ return buf;
}
/*
@@ -375,18 +407,26 @@ dumprules(void)
* The rules with a count of how often each has decided something. A
* rule that has never fired is either dead or protecting you from
* something that has not happened yet, and it is worth being able to
- * tell which. Kept out of fmtrules so that what "rules" prints stays
+ * tell which. Kept out of rulestext so that what "rules" prints stays
* a rule set that can be written straight back.
*/
-long
-fmthits(char *buf, long nbuf)
+char*
+hitstext(void)
{
- char *p, *e;
+ char *buf, *p, *e;
+ long sz;
Rule *r;
- p = buf;
- e = buf + nbuf;
lock(&rulelock);
+ sz = 1;
+ for(r = rules; r != nil; r = r->next)
+ sz += 64 + (r->proto != nil ? strlen(r->proto) : 0);
+ if((buf = malloc(sz)) == nil){
+ unlock(&rulelock);
+ return nil;
+ }
+ p = buf;
+ e = buf + sz;
for(r = rules; r != nil; r = r->next)
p = seprint(p, e, "%-8ld %s=%s%s%s\n", r->hits,
r->allow ? "allow" : "deny",
@@ -394,7 +434,8 @@ fmthits(char *buf, long nbuf)
r->proto != nil ? "\tproto=" : "",
r->proto != nil ? r->proto : "");
unlock(&rulelock);
- return p - buf;
+ USED(p);
+ return buf;
}
int