zmap-mark-ii/lib/pbm.c

112 lines
2.5 KiB
C

/*
* 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 <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#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;
}