/* * Copyright 2021 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include "logger.h" #include "xalloc.h" #define NUM_VALUES 0xFFFFFFFF #define PAGE_SIZE_IN_BITS 0x10000 #define PAGE_SIZE_IN_BYTES (PAGE_SIZE_IN_BITS / 8) #define NUM_PAGES 0x10000 #define PAGE_MASK 0xFFFF uint8_t **pbm_init(void) { uint8_t **retv = xcalloc(NUM_PAGES, sizeof(void *)); return retv; } uint8_t *bm_init(void) { uint8_t *bm = xmalloc(PAGE_SIZE_IN_BYTES); memset(bm, 0, PAGE_SIZE_IN_BYTES); return bm; } int bm_check(uint8_t *bm, uint16_t v) { uint16_t page_idx = (v >> 3); uint8_t bit_idx = (uint8_t)(v & 0x07); return bm[page_idx] & (1 << bit_idx); } void bm_set(uint8_t *bm, uint16_t v) { uint16_t page_idx = (v >> 3); uint8_t bit_idx = (uint8_t)(v & 0x07); bm[page_idx] |= (1 << bit_idx); } int pbm_check(uint8_t **b, uint32_t v) { uint32_t top = v >> 16; uint32_t bottom = v & PAGE_MASK; return b[top] && bm_check(b[top], bottom); } void pbm_set(uint8_t **b, uint32_t v) { uint16_t top = (uint16_t)(v >> 16); uint16_t bottom = (uint16_t)(v & PAGE_MASK); if (!b[top]) { b[top] = bm_init(); } bm_set(b[top], bottom); } uint32_t pbm_load_from_file(uint8_t **b, char *file) { if (!b) { log_fatal("pbm", "load_from_file called with NULL PBM"); } if (!file) { log_fatal("pbm", "load_from_file called with NULL filename"); } FILE *fp = fopen(file, "r"); if (fp == NULL) { log_fatal("pbm", "unable to open file: %s: %s", file, strerror(errno)); } char line[1000]; uint32_t count = 0; while (fgets(line, sizeof(line), fp)) { char *comment = strchr(line, '#'); if (comment) { *comment = '\0'; } struct in_addr addr; if (inet_aton(line, &addr) != 1) { log_fatal("pbm", "unable to parse IP address: %s", line); } pbm_set(b, addr.s_addr); ++count; } fclose(fp); return count; }