diff options
Diffstat (limited to 'fw/src/rules.c')
| -rw-r--r-- | fw/src/rules.c | 67 |
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 |
