diff options
author | Bart De Schuymer <bdschuym@pandora.be> | 2005-02-14 20:20:03 +0000 |
---|---|---|
committer | Bart De Schuymer <bdschuym@pandora.be> | 2005-02-14 20:20:03 +0000 |
commit | ab611e28d2ee6b12670494bb4212679b8c63ce22 (patch) | |
tree | 2c6c13e091f186accd0c0dbc379073d6a1a813bc /libebtc.c | |
parent | ff587205009a0d49e2d086765de87dc619b028bb (diff) | |
download | ebtables-ab611e28d2ee6b12670494bb4212679b8c63ce22.tar.gz |
complete -c and -C implementation
Diffstat (limited to 'libebtc.c')
-rw-r--r-- | libebtc.c | 53 |
1 files changed, 37 insertions, 16 deletions
@@ -170,7 +170,7 @@ void ebt_initialize_entry(struct ebt_u_entry *e) e->w_list = NULL; e->t = (struct ebt_entry_target *)ebt_find_target(EBT_STANDARD_TARGET); ebt_find_target(EBT_STANDARD_TARGET)->used = 1; - e->cnt.pcnt = e->cnt.bcnt = 0; + e->cnt.pcnt = e->cnt.bcnt = e->cnt_surplus.pcnt = e->cnt_surplus.bcnt = 0; if (!e->t) ebt_print_bug("Couldn't load standard target"); @@ -580,6 +580,7 @@ letscontinue: entries->entries = NULL; } +#define OPT_COUNT 0x1000 /* This value is also defined in ebtables.c */ /* Returns the rule number on success (starting from 0), -1 on failure * * This function expects the ebt_{match,watcher,target} members of new_entry @@ -621,6 +622,9 @@ int ebt_check_rule_exists(struct ebt_u_replace *replace, if (new_entry->bitmask != u_e->bitmask || new_entry->invflags != u_e->invflags) continue; + if (replace->flags & OPT_COUNT && (new_entry->cnt.pcnt != + u_e->cnt.pcnt || new_entry->cnt.bcnt != u_e->cnt.bcnt)) + continue; /* Compare all matches */ m_l = new_entry->m_list; j = 0; @@ -895,6 +899,8 @@ void ebt_delete_rule(struct ebt_u_replace *replace, } } +#define OPT_CNT_INCR 0x2000 /* This value is also defined in ebtables.c */ +#define OPT_CNT_DECR 0x4000 /* This value is also defined in ebtables.c */ /* Change the counters of a rule or rules * begin == end == 0: change counters of the rule corresponding to new_entry * @@ -909,7 +915,6 @@ void ebt_change_counters(struct ebt_u_replace *replace, struct ebt_u_entry *u_e; struct ebt_u_entries *entries = ebt_to_chain(replace); struct ebt_cntchanges *cc = replace->counterchanges; - struct ebt_cntchanges **prev_cc = &(replace->counterchanges); if (check_and_change_rule_number(replace, new_entry, &begin, &end)) return; @@ -921,7 +926,6 @@ void ebt_change_counters(struct ebt_u_replace *replace, while (j) { if (cc->type != CNT_DEL) j--; - prev_cc = &(cc->next); cc = cc->next; } } @@ -929,28 +933,45 @@ void ebt_change_counters(struct ebt_u_replace *replace, while (i) { if (cc->type != CNT_DEL) i--; - prev_cc = &(cc->next); cc = cc->next; } + u_e = entries->entries; + for (i = 0; i < begin; i++) + u_e = u_e->next; i = end - begin + 1; while (i) { if (cc->type != CNT_DEL) { i--; - /* A -C after a -A remains a -A */ - if (cc->type != CNT_ADD && cc->type != CNT_OWRITE) - cc->type = CNT_CHANGE; + if (cc->type != CNT_ADD && cc->type != CNT_OWRITE) { + /* In daemon mode, we want to make sure we don't lose + * any counted packets/bytes (the kernel is still counting + * while we are changing things in userspace). Therefore, + * we need to add the amount to the counters in the kernel, + * not the counters copied earlier from the kernel. */ + u_e->cnt_surplus = *cnt; + if (replace->flags & OPT_CNT_INCR) { + cc->type = CNT_INCR; + } else if (replace->flags & OPT_CNT_DECR) + cc->type = CNT_DECR; + else { + cc->type = CNT_CHANGE; + u_e->cnt = *cnt; + u_e->cnt_surplus.pcnt = u_e->cnt_surplus.bcnt = 0; + } + } else { /* A -C after a -A remains a -A */ + if (replace->flags & OPT_CNT_INCR) { + u_e->cnt.pcnt += cnt->pcnt; + u_e->cnt.bcnt += cnt->bcnt; + } else if (replace->flags & OPT_CNT_DECR) { + u_e->cnt.pcnt -= cnt->pcnt; + u_e->cnt.bcnt -= cnt->bcnt; + } else + u_e->cnt = *cnt; + } + u_e = u_e->next; } - prev_cc = &(cc->next); cc = cc->next; } - u_e = entries->entries; - for (i = 0; i < begin; i++) - u_e = u_e->next; - i = end - begin + 1; - while(i--) { - u_e->cnt = *cnt; - u_e = u_e->next; - } } /* Selected_chain == -1 : zero all counters |