X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fiplist.c;h=0fb6934a738df3b0ff50353b402f76d1700a936c;hb=HEAD;hp=c2b471b13ce01bc8b27e383309cf9f13478f7e5a;hpb=6deab7a7086ccb592daa0c41e12759ec0b9c7aa0;p=apps%2Fpfixtools.git diff --git a/postlicyd/iplist.c b/postlicyd/iplist.c index c2b471b..0fb6934 100644 --- a/postlicyd/iplist.c +++ b/postlicyd/iplist.c @@ -16,17 +16,20 @@ /* products derived from this software without specific prior written */ /* permission. */ /* */ -/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ -/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ -/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ -/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ -/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ -/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ -/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ -/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ -/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ -/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ -/* THE POSSIBILITY OF SUCH DAMAGE. */ +/* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */ +/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */ +/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */ +/* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */ +/* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */ +/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */ +/* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/* POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* Copyright (c) 2006-2008 the Authors */ +/* see AUTHORS and source files for details */ /******************************************************************************/ /* @@ -43,6 +46,7 @@ #include "str.h" #include "file.h" #include "array.h" +#include "resources.h" #include "rbl.h" #define IPv4_BITS 5 @@ -62,10 +66,25 @@ enum { }; struct rbldb_t { - A(uint16_t) ips[1 << 16]; + char *filename; + A(uint16_t) *ips; }; ARRAY(rbldb_t) +typedef struct rbldb_resource_t { + time_t mtime; + off_t size; + A(uint16_t) ips[1 << 16]; +} rbldb_resource_t; + +static void rbldb_resource_wipe(rbldb_resource_t *res) +{ + for (int i = 0 ; i < 1 << 16 ; ++i) { + array_wipe(res->ips[i]); + } + p_delete(&res); +} + static int get_o(const char *s, const char **out) { int res = 0; @@ -124,22 +143,38 @@ rbldb_t *rbldb_create(const char *file, bool lock) file_map_t map; const char *p, *end; uint32_t ips = 0; + time_t now = time(0); if (!file_map_open(&map, file, false)) { return NULL; } + rbldb_resource_t *res = resource_get("iplist", file); + if (res == NULL) { + res = p_new(rbldb_resource_t, 1); + resource_set("iplist", file, res, (resource_destructor_t)rbldb_resource_wipe); + } + + db = p_new(rbldb_t, 1); + db->filename = m_strdup(file); + db->ips = res->ips; + if (map.st.st_size == res->size && map.st.st_mtime == res->mtime) { + info("%s loaded: already up-to-date", file); + file_map_close(&map); + return db; + } + res->size = map.st.st_size; + res->mtime = map.st.st_mtime; + p = map.map; end = map.end; while (end > p && end[-1] != '\n') { --end; } if (end != map.end) { - warn("file %s miss a final \\n, ignoring last line", - file); + warn("%s: final \\n missing, ignoring last line", file); } - db = p_new(rbldb_t, 1); while (p < end) { uint32_t ip; @@ -149,7 +184,7 @@ rbldb_t *rbldb_create(const char *file, bool lock) if (parse_ipv4(p, &p, &ip) < 0) { p = (char *)memchr(p, '\n', end - p) + 1; } else { - array_add(db->ips[ip >> 16], ip & 0xffff); + array_add(res->ips[ip >> 16], ip & 0xffff); ++ips; } } @@ -158,28 +193,28 @@ rbldb_t *rbldb_create(const char *file, bool lock) /* Lookup may perform serveral I/O, so avoid swap. */ for (int i = 0 ; i < 1 << 16 ; ++i) { - array_adjust(db->ips[i]); - if (lock && !array_lock(db->ips[i])) { + array_adjust(res->ips[i]); + if (lock && !array_lock(res->ips[i])) { UNIXERR("mlock"); } - if (db->ips[i].len) { + if (res->ips[i].len) { # define QSORT_TYPE uint16_t -# define QSORT_BASE db->ips[i].data -# define QSORT_NELT db->ips[i].len +# define QSORT_BASE res->ips[i].data +# define QSORT_NELT res->ips[i].len # define QSORT_LT(a,b) *a < *b # include "qsort.c" } } - info("rbl %s loaded, %d IPs", file, ips); + info("%s loaded: done in %us, %u IPs", file, (uint32_t)(time(0) - now), ips); return db; } static void rbldb_wipe(rbldb_t *db) { - for (int i = 0 ; i < 1 << 16 ; ++i) { - array_wipe(db->ips[i]); - } + resource_release("iplist", db->filename); + p_delete(&db->filename); + db->ips = NULL; } void rbldb_delete(rbldb_t **db) @@ -414,7 +449,7 @@ static void iplist_filter_async(rbl_result_t *result, void *arg) --async->awaited; debug("got asynchronous request result for filter %s, rbl %d, still awaiting %d answers", - filter->name, result - array_ptr(async->results, 0), async->awaited); + filter->name, (int)(result - array_ptr(async->results, 0)), async->awaited); if (async->awaited == 0) { filter_result_t res = HTK_FAIL; @@ -455,9 +490,13 @@ static filter_result_t iplist_filter(const filter_t *filter, const query_t *quer const iplist_filter_t *data = filter->data; bool error = true; - if (parse_ipv4(query->client_address, &end, &ip) != 0) { + if (parse_ipv4(query->client_address.str, &end, &ip) != 0) { + if (strchr(query->client_address.str, ':')) { + /* iplist only works on IPv4 */ + return HTK_FAIL; + } warn("invalid client address: %s, expected ipv4", - query->client_address); + query->client_address.str); return HTK_ERROR; } for (uint32_t i = 0 ; i < data->rbls.len ; ++i) { @@ -509,6 +548,7 @@ static void *iplist_context_constructor(void) static void iplist_context_destructor(void *data) { iplist_async_data_t *ctx = data; + array_wipe(ctx->results); p_delete(&ctx); }