/* $Id: ip_ranges.c,v 1.6 2006/09/18 22:59:38 maxim Exp $ * */ #include #include #include #include "configure.h" #include "settings.h" #include "str.h" #include "misc.h" #include "ip_ranges.h" #define MAX_NAMES 256 IPRanges* newIPRanges(char* name) { IPRanges* ranges; if (!(ranges = CALLOC(sizeof(IPRanges)))) return NULL; ranges->name = STRDUP(name); return ranges; } char loadIPRanges(IPRanges* ranges) { char filename[PATH_LEN]; char buf[SHORT_STR]; FILE* file; int i = 0; if (!ranges) return message(ERROR, "NULL ranges"); snprintf(filename, PATH_LEN, "conf/%s.ips", ranges->name); ranges->mtime = fileTime(filename); if (!fileSize(filename)) return FAILED; if (!(file = fopen(filename, "r"))) return message(SYS|ERROR, "cannot open %s", filename); while (fgets(buf, SHORT_STR, file)) i++; fseek(file, 0, SEEK_SET); ranges->ranges = CALLOC(i * sizeof(unsigned)); ranges->ids = CALLOC(i); i = 0; while (fgets(buf, SHORT_STR, file)) { unsigned ip = string2ip(buf); char* s = strchr(buf, ' '); if (s && ip != 0xFFFFFFFF) { ranges->ranges[i] = ip; ranges->ids[i++] = atol(s + 1); } } fclose(file); if (!i) { ranges->ranges = FREE(ranges->ranges); ranges->ids = FREE(ranges->ids); if (fileSize(filename)) message(ERROR, "no ranges found in %s", filename); return FAILED; } ranges->count = i; return OK; } void refreshRanges(IPRanges* ranges) { char filename[PATH_LEN]; if (!ranges) return; snprintf(filename, PATH_LEN, "conf/%s.ips", ranges->name); if (ranges->mtime != fileTime(filename)) { ranges->ranges = FREE(ranges->ranges); ranges->ids = FREE(ranges->ids); ranges->codes = FREE(ranges->codes); ranges->names = FREE(ranges->names); ranges->buffer = FREE(ranges->buffer); loadIPRanges(ranges); } } short ip2id(IPRanges* ranges, unsigned ip) { int start = 0; int midd = 0; int end = -1; if (!ranges) return 0; if (!ranges->ranges) { if (ranges->tried) return 0; ranges->tried = YES; if (!loadIPRanges(ranges)) return 0; } end = ranges->count; while (start < end) { unsigned current; midd = (start + end) >> 1; current = ranges->ranges[midd]; if (ip == current) return ranges->ids[midd]; else if (ip < current) end = midd; else if (midd + 1 == ranges->count || ip < ranges->ranges[midd + 1]) return ranges->ids[midd]; else start = midd + 1; } return 0; } char loadNames(IPRanges* ranges) { char filename[PATH_LEN]; char* s; snprintf(filename, PATH_LEN, "conf/%s", ranges->name); if (!(ranges->buffer = readFile(filename, NULL))) return FAILED; if (!(ranges->codes = (char**) CALLOC(MAX_NAMES * sizeof(char*)))) return FAILED; if (!(ranges->names = (char**) CALLOC(MAX_NAMES * sizeof(char*)))) return FAILED; s = ranges->buffer; while(s && *s) { int id = atol(s); if (id < 0 || id >= MAX_NAMES) break; while(*s && !isSpace(*s)) s++; while(*s && isSpace(*s)) s++; ranges->codes[id] = s; while(*s && !isSpace(*s)) s++; if (*s) *s++ = 0; while(*s && isSpace(*s)) s++; ranges->names[id] = s; while(*s && *s != '\n') s++; if (*s) *s++ = 0; } return OK; } char* id2name(IPRanges* ranges, short id) { if (!ranges) return ""; if (!ranges->names && !loadNames(ranges)) return ""; if (0 <= id && id < MAX_NAMES) return ranges->names[id]; return ""; } char* id2code(IPRanges* ranges, short id) { if (!ranges) return ""; if (!ranges->names && !loadNames(ranges)) return ""; if (0 <= id && id < MAX_NAMES) return ranges->codes[id]; return ""; } short code2id(IPRanges* ranges, char* code) { int id; if (!ranges) return -1; if (!ranges->names && !loadNames(ranges)) return -1; for (id = 0; id < MAX_NAMES; id++) if (ranges->codes[id] && !strcmp(ranges->codes[id], code)) return id; return -1; }