diff options
Diffstat (limited to 'src/ban.c')
-rw-r--r-- | src/ban.c | 189 |
1 files changed, 188 insertions, 1 deletions
@@ -16,6 +16,7 @@ */ #include "varnish_mib.h" +#include <ctype.h> static int send_ban_cmd(vcli_conn_t *conn, const char *expr) @@ -50,7 +51,7 @@ varnish_ban(netsnmp_agent_request_info *reqinfo, } memcpy(expr, requests->requestvb->val.string, len); expr[len] = 0; - DEBUGMSGTL(("vcli_mib", "ban %s\n", expr)); + DEBUGMSGTL(("varnish_ban", "setting ban %s\n", expr)); rc = vcli_connect(vd, &conn); if (rc == SNMP_ERR_NOERROR) { rc = send_ban_cmd(&conn, expr); @@ -60,3 +61,189 @@ varnish_ban(netsnmp_agent_request_info *reqinfo, return rc ? SNMP_ERR_GENERR : SNMP_ERR_NOERROR; } +unsigned banTable_timeout = 60; + +/* + * create a new row in the table + */ +static struct banTable_entry * +create_entry(netsnmp_tdata *table_data, long idx, struct banTable_entry *ent) +{ + struct banTable_entry *entry; + netsnmp_tdata_row *row; + + entry = SNMP_MALLOC_TYPEDEF(struct banTable_entry); + if (!entry) + return NULL; + + row = netsnmp_tdata_create_row(); + if (!row) { + SNMP_FREE(entry); + return NULL; + } + row->data = entry; + *entry = *ent; + + entry->banIndex = idx; + netsnmp_tdata_row_add_index(row, ASN_INTEGER, + &entry->banIndex, + sizeof(entry->banIndex)); + if (table_data) + netsnmp_tdata_add_row(table_data, row); + return entry; +} + +#define TMSEC(t) (((t)->tm_hour * 60 + (t)->tm_min) * 60 + (t)->tm_sec) + +static int +utc_offset (void) +{ + time_t t = time (NULL); + struct tm ltm = *localtime (&t); + struct tm gtm = *gmtime (&t); + int d = TMSEC (<m) - TMSEC (>m); + if (!(ltm.tm_year = gtm.tm_year && ltm.tm_mon == gtm.tm_mon)) + d += 86400; + return d / 60; +} + +/* Refill the ban table */ +int +banTable_load(netsnmp_cache *cache, void *vmagic) +{ + netsnmp_tdata *table = (netsnmp_tdata *) vmagic; + long idx = 0; + int rc; + struct vcli_conn conn; + char *p; + struct VSM_data *vd; + + DEBUGMSGTL(("varnish_ban", "reloading ban table")); + vd = varnish_get_vsm_data(); + rc = vcli_connect(vd, &conn); + if (rc != SNMP_ERR_NOERROR) + return rc; + + if (vcli_asprintf(&conn, "ban.list\n") || vcli_write(&conn)) + return SNMP_ERR_GENERR; + + if (vcli_read_response(&conn)) + return SNMP_ERR_GENERR; + + if (conn.resp != CLIS_OK) { + snmp_log(LOG_ERR, "ban.list command rejected: %u %s\n", + conn.resp, conn.base); + return SNMP_ERR_GENERR; + } + + p = conn.base; + while (p < conn.base + conn.bufsize) { + char *q; + struct banTable_entry e; + struct tm *tm; + time_t t; + int n; + + if (*p == '\n') { + ++p; + continue; + } + e.banIndex = idx; + t = strtoul(p, &q, 10); + if (*q != '.') { + p = strchr(p, '\n'); + if (!p) + break; + continue; + } + ++q; + + e.banTime_len = 11; + e.banTime = malloc(e.banTime_len + 1); + if (!e.banTime) { + vcli_disconnect(&conn); + snmp_log(LOG_ERR, "out of memory\n"); + return SNMP_ERR_GENERR; + } + tm = localtime(&t); + /* A date-time specification. + + field octets contents range + ----- ------ -------- ----- + 1 1-2 year* 0..65536 + 2 3 month 1..12 + 3 4 day 1..31 + 4 5 hour 0..23 + 5 6 minutes 0..59 + 6 7 seconds 0..60 + (use 60 for leap-second) + 7 8 deci-seconds 0..9 + 8 9 direction from UTC '+' / '-' + 9 10 hours from UTC* 0..13 + 10 11 minutes from UTC 0..59 + + * Notes: + - the value of year is in network-byte order + */ + n = tm->tm_year % 100; + e.banTime[0] = n >> 8; + e.banTime[1] = n & 0xff; + e.banTime[2] = tm->tm_mon + 1; + e.banTime[3] = tm->tm_mday; + e.banTime[4] = tm->tm_hour; + e.banTime[5] = tm->tm_min; + e.banTime[6] = tm->tm_sec; + e.banTime[7] = *q - '0'; + n = utc_offset(); + if (n < 0) { + e.banTime[8] = '-'; + n = - n; + } else + e.banTime[8] = '+'; + e.banTime[9] = n / 60; + e.banTime[10] = n % 60; + + while (*q && isdigit(*q)) + ++q; + while (*q && isspace(*q)) + ++q; + e.banRefCount = strtoul(q, &q, 10); + + while (*q && isspace(*q)) + ++q; + + e.banExpression_len = strcspn(q, "\n"); + e.banExpression = malloc(e.banExpression_len); + if (!e.banExpression) { + vcli_disconnect(&conn); + free(e.banTime); + snmp_log(LOG_ERR, "out of memory\n"); + return SNMP_ERR_GENERR; + } + memcpy(e.banExpression, q, e.banExpression_len); + + create_entry(table, idx, &e); + ++idx; + q += e.banExpression_len; + p = q; + } + vcli_disconnect(&conn); + DEBUGMSGTL(("varnish_ban", "loaded %ld ban entries", idx)); + return 0; +} + +void +banTable_free(netsnmp_cache *cache, void *vmagic) +{ + netsnmp_tdata *table = (netsnmp_tdata *) vmagic; + netsnmp_tdata_row *row; + + DEBUGMSGTL(("varnish_ban", "freeing ban table")); + while ((row = netsnmp_tdata_row_first(table))) { + struct banTable_entry *entry = row->data; + free(entry->banExpression); + free(entry->banTime); + SNMP_FREE(entry); + netsnmp_tdata_remove_and_delete_row(table, row); + } +} |