+int Ban_getBanCount(void)
+{
+ return bancount;
+}
+
+message_t *Ban_getBanList(void)
+{
+ int i = 0;
+ struct dlist *itr;
+ ban_t *ban;
+ message_t *msg;
+ struct tm timespec;
+ char timestr[32];
+ char hexhash[41];
+ uint8_t address[16];
+
+ msg = Msg_banList_create(bancount);
+ list_iterate(itr, &banlist) {
+ ban = list_get_entry(itr, ban_t, node);
+ gmtime_r(&ban->time, ×pec);
+ strftime(timestr, 32, "%Y-%m-%dT%H:%M:%SZ", ×pec);
+ SSLi_hash2hex(ban->hash, hexhash);
+ memset(address, 0, 16);
+
+ if(ban->address.ss_family == AF_INET) {
+ memcpy(&address[12], &((struct sockaddr_in *)&ban->address)->sin_addr, 4);
+ memset(&address[10], 0xff, 2);
+ Msg_banList_addEntry(msg, i++, address, ban->mask + 96, ban->name, hexhash, ban->reason, timestr, ban->duration);
+ } else {
+ memcpy(&address, &((struct sockaddr_in6 *)&ban->address)->sin6_addr, 16);
+ Msg_banList_addEntry(msg, i++, address, ban->mask, ban->name, hexhash, ban->reason, timestr, ban->duration);
+ }
+
+ }
+ return msg;
+}
+
+void Ban_clearBanList(void)
+{
+ ban_t *ban;
+ struct dlist *itr, *save;
+ list_iterate_safe(itr, save, &banlist) {
+ ban = list_get_entry(itr, ban_t, node);
+ free(ban->name);
+ free(ban->reason);
+ list_del(&ban->node);
+ free(ban);
+ bancount--;
+ }
+}
+
+void Ban_putBanList(message_t *msg, int n_bans)
+{
+ int i = 0;
+ struct tm timespec;
+ ban_t *ban;
+ char *hexhash, *name, *reason, *start;
+ uint32_t duration, mask;
+ uint8_t *address;
+ char mappedBytes[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};
+ char *tz;
+
+ for (i = 0; i < n_bans; i++) {
+ Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
+ ban = Memory_safeMalloc(1, sizeof(ban_t));
+ SSLi_hex2hash(hexhash, ban->hash);
+
+ if(memcmp(address, mappedBytes, 12) == 0) {
+ memcpy(&((struct sockaddr_in *)&ban->address)->sin_addr, &address[12], 4);
+ ban->address.ss_family = AF_INET;
+ if (mask > 32) {
+ mask = 32;
+ }
+ } else {
+ memcpy(&((struct sockaddr_in6 *)&ban->address)->sin6_addr, address, 16);
+ ban->address.ss_family = AF_INET6;
+ }
+
+ ban->mask = mask;
+ ban->reason = strdup(reason);
+ ban->name = strdup(name);
+
+ /*
+ * Parse the timestring. We need to set TZ to UTC so that mktime() knows that the info in
+ * struct tm indeed is given in UTC. Otherwise it will use the current locale. There's
+ * apparently no other way to do this...
+ */
+ memset(×pec, 0, sizeof(struct tm));
+ strptime(start, "%Y-%m-%dT%H:%M:%S", ×pec);
+ tz = getenv("TZ");
+ setenv("TZ", "UTC", 1);
+ tzset();
+ ban->time = mktime(×pec);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+
+ ban->duration = duration;
+ list_add_tail(&ban->node, &banlist);
+ bancount++;
+ }
+ banlist_changed = true;
+ if(getBoolConf(SYNC_BANFILE))
+ Ban_saveBanFile();
+}
+
+static void Ban_saveBanFile(void)
+{
+ struct dlist *itr;
+ ban_t *ban;
+ char hexhash[41];
+ FILE *file;
+
+ if (!banlist_changed)
+ return;
+ file = fopen(getStrConf(BANFILE), "w");
+ if (file == NULL) {
+ Log_warn("Could not save banlist to file %s: %s", getStrConf(BANFILE), strerror(errno));
+ return;
+ }
+ list_iterate(itr, &banlist) {
+ ban = list_get_entry(itr, ban_t, node);
+ SSLi_hash2hex(ban->hash, hexhash);
+
+ char *addressString = Util_addressToString(&ban->address);
+ fprintf(file, "%s,%s,%d,%ld,%d,%s,%s\n", hexhash, addressString,ban->mask, (long int)ban->time, ban->duration, ban->name, ban->reason);
+ free(addressString);
+ }
+ fclose(file);
+ banlist_changed = false;
+ Log_info("Banlist file '%s': %d entries written", getStrConf(BANFILE), bancount);
+}
+
+static void Ban_readBanFile(void)
+{
+ ban_t *ban;
+ char line[1024], *hexhash, *address, *name, *reason;
+ uint32_t mask, duration;
+ time_t time;
+ char *p;
+ FILE *file;
+
+ file = fopen(getStrConf(BANFILE), "r");
+ if (file == NULL) {
+ Log_warn("Could not read banlist file %s: %s", getStrConf(BANFILE), strerror(errno));
+ return;
+ }
+ while (fgets(line, 1024, file) != NULL) {
+ p = strtok(line, ",");
+ hexhash = p;
+ p = strtok(NULL, ",");
+ if (p == NULL) break;
+ address = p;
+ p = strtok(NULL, ",");
+ if (p == NULL) break;
+ mask = strtoul(p, NULL, 0);
+ p = strtok(NULL, ",");
+ if (p == NULL) break;
+ time = strtoul(p, NULL, 0);
+ p = strtok(NULL, ",");
+ if (p == NULL) break;
+ duration = strtoul(p, NULL, 0);
+ p = strtok(NULL, ",");
+ if (p == NULL) break;
+ name = p;
+ p = strtok(NULL, "\n");
+ if (p == NULL) break;
+ reason = p;
+
+ ban = Memory_safeMalloc(1, sizeof(ban_t));
+ memset(ban, 0, sizeof(ban_t));
+ SSLi_hex2hash(hexhash, ban->hash);
+ if (inet_pton(AF_INET, address, &ban->address) == 0) {
+ if (inet_pton(AF_INET6, address, &ban->address) == 0) {
+ Log_warn("Address \"%s\" is illegal!", address);
+ } else {
+ ban->address.ss_family = AF_INET6;
+ }
+ } else {
+ ban->address.ss_family = AF_INET;
+ }
+ ban->name = strdup(name);
+ ban->reason = strdup(reason);
+ if (ban->name == NULL || ban->reason == NULL)
+ Log_fatal("Out of memory");
+ ban->time = time;
+ ban->duration = duration;
+ ban->mask = mask;
+ list_add_tail(&ban->node, &banlist);
+ bancount++;
+ Log_debug("Banfile: H = '%s' A = '%s' M = %d U = '%s' R = '%s'", hexhash, address, ban->mask, ban->name, ban->reason);
+ }
+ fclose(file);
+ Log_info("Banlist file '%s': %d entries read", getStrConf(BANFILE), bancount);
+}