typedef struct xtc_handle iptc_handle_t;
typedef struct ipt_entry iptc_rule_t;
+typedef struct iptables_comment {
+ // Comment String
+ char comment[XT_MAX_COMMENT_LEN];
+
+ // Counters
+ uint64_t packets;
+ uint64_t bytes;
+} iptables_comment;
+
+static int find_comment(iptables_comment** ret,
+ iptables_comment** comments, unsigned int* num_comments, const char* s) {
+ iptables_comment* comment = NULL;
+ iptables_comment* c = *comments;
+ iptables_comment* p = NULL;
+ int r;
+
+ // Return any matching comments
+ for (unsigned int i = 0; i < (*num_comments); i++) {
+ if (td_string_equals(c[i].comment, s)) {
+ *ret = &c[i];
+ return 0;
+ }
+ }
+
+ // No comment found, let's increase the length of the array
+ p = reallocarray(c, (*num_comments) + 1, sizeof(*p));
+ if (!p)
+ return -errno;
+
+ // Update the pointer
+ *comments = p;
+
+ // Pointer to the new comment
+ comment = &p[*num_comments];
+
+ // Store the comment string
+ r = td_string_set(comment->comment, s);
+ if (r < 0)
+ return r;
+
+ // Initialize the counters
+ comment->packets = comment->bytes = 0;
+
+ // The array is now longer
+ (*num_comments)++;
+
+ // Return the comment
+ *ret = comment;
+
+ return 0;
+}
+
static int skip_comment(const char* comment) {
// Skip empty comments
if (!*comment)
return 0;
}
-static int iptables_iterate_matches(td_ctx* ctx, td_source* source, const iptc_rule_t* rule) {
+static int iptables_iterate_matches(td_ctx* ctx, td_source* source,
+ const iptc_rule_t* rule, iptables_comment** comments, unsigned int* num_comments) {
const struct xt_comment_info* comment = NULL;
const struct xt_entry_match* match = NULL;
+ iptables_comment* c = NULL;
int r;
// Start with the first match and determine the end
if (skip_comment(comment->comment))
continue;
- // Submit metrics
- r = td_source_submit_values(source, comment->comment, VALUES(
- VALUE_UINT64("packets", &rule->counters.pcnt),
- VALUE_UINT64("bytes", &rule->counters.bcnt)
- ));
+ // Find the comment
+ r = find_comment(&c, comments, num_comments, comment->comment);
if (r < 0)
return r;
+
+ // Increment counters
+ c->packets += rule->counters.pcnt;
+ c->bytes += rule->counters.bcnt;
}
return 0;
}
-static int iptables_iterate_chain(td_ctx* ctx, td_source* source,
- iptc_handle_t* handle, const char* chain) {
+static int iptables_iterate_chain(td_ctx* ctx, td_source* source, iptc_handle_t* handle,
+ const char* chain, iptables_comment** comments, unsigned int* num_comments) {
const iptc_rule_t* rule = NULL;
int r = 0;
// Iterate over all rules
for (rule = iptc_first_rule(chain, handle); rule; rule = iptc_next_rule(rule, handle)) {
- r = iptables_iterate_matches(ctx, source, rule);
+ r = iptables_iterate_matches(ctx, source, rule, comments, num_comments);
if (r < 0)
return r;
}
return 0;
}
-static int iptables_iterate_table(td_ctx* ctx, td_source* source, const char* table) {
+static int iptables_iterate_table(td_ctx* ctx, td_source* source, const char* table,
+ iptables_comment** comments, unsigned int* num_comments) {
iptc_handle_t* handle = NULL;
const char* chain = NULL;
int r;
// Iterate through all chains
for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle)) {
- r = iptables_iterate_chain(ctx, source, handle, chain);
+ r = iptables_iterate_chain(ctx, source, handle, chain, comments, num_comments);
if (r < 0)
goto ERROR;
}
iptc_free(handle);
return r;
-
}
static int iptables_heartbeat(td_ctx* ctx, td_source* source) {
+ iptables_comment* comments = NULL;
+ unsigned int num_comments = 0;
int r = 0;
const char* tables[] = {
// Walk through all known tables
for (const char** table = tables; *table; table++) {
- r = iptables_iterate_table(ctx, source, *table);
+ r = iptables_iterate_table(ctx, source, *table, &comments, &num_comments);
if (r < 0)
- return r;
+ goto ERROR;
}
- return 0;
+ // Submit all comments
+ for (unsigned int i = 0; i < num_comments; i++) {
+ r = td_source_submit_values(source, comments[i].comment, VALUES(
+ VALUE_UINT64("packets", &comments[i].packets),
+ VALUE_UINT64("bytes", &comments[i].bytes)
+ ));
+ if (r < 0)
+ goto ERROR;
+ }
+
+ERROR:
+ if (comments)
+ free(comments);
+
+ return r;
}
const td_source_impl iptables_source = {