|
|
/* -*- coding: utf-8 -*- * ---------------------------------------------------------------------- * Copyright © 2012, RedJack, LLC. * All rights reserved. * * Please see the LICENSE.txt file in this distribution for license * details. * ---------------------------------------------------------------------- */
#include <libcork/core.h>
#include "ipset/bdd/nodes.h" #include "ipset/bits.h" #include "ipset/errors.h" #include "ipset/ipset.h"
/** * Given a BDD variable number, return the index of the corresponding * bit in an IP address. IPv4 addresses use variables 1-32; IPv6 * addresses use 1-128. (Variable 0 is used to identify the kind of * address — TRUE for IPv4, FALSE for IPv6.) */
static unsigned int IPSET_NAME(bit_for_var)(ipset_variable var) { return (var - 1); }
/** * An assignment function that can be used to evaluate an IP set BDD. */
static bool IPSET_NAME(assignment)(const void *addr, ipset_variable var) { if (var == 0) { return IP_DISCRIMINATOR_VALUE; } else { unsigned int bit = IPSET_NAME(bit_for_var)(var); return IPSET_BIT_GET(addr, bit); } }
bool IPSET_PRENAME(contains)(const struct ip_set *set, CORK_IP *elem) { return ipset_node_evaluate (set->cache, set->set_bdd, IPSET_NAME(assignment), elem); }
bool IPSET_NAME(add_network)(struct ip_set *set, CORK_IP *elem, unsigned int cidr_prefix) { /* Special case — the BDD for a netmask that's out of range never * evaluates to true. */ if (cidr_prefix > IP_BIT_SIZE) { cork_error_set (IPSET_ERROR, IPSET_PARSE_ERROR, "CIDR block %u out of range [0..%u]", cidr_prefix, IP_BIT_SIZE); return false; }
ipset_node_id new_bdd = ipset_node_insert (set->cache, set->set_bdd, IPSET_NAME(assignment), elem, cidr_prefix + 1, 1); bool result = (new_bdd == set->set_bdd); ipset_node_decref(set->cache, set->set_bdd); set->set_bdd = new_bdd; return result; }
bool IPSET_NAME(add)(struct ip_set *set, CORK_IP *elem) { ipset_node_id new_bdd = ipset_node_insert (set->cache, set->set_bdd, IPSET_NAME(assignment), elem, IP_BIT_SIZE + 1, 1); bool result = (new_bdd == set->set_bdd); ipset_node_decref(set->cache, set->set_bdd); set->set_bdd = new_bdd; return result; }
bool IPSET_NAME(remove)(struct ip_set *set, CORK_IP *elem) { ipset_node_id new_bdd = ipset_node_insert (set->cache, set->set_bdd, IPSET_NAME(assignment), elem, IP_BIT_SIZE + 1, 0); bool result = (new_bdd == set->set_bdd); ipset_node_decref(set->cache, set->set_bdd); set->set_bdd = new_bdd; return result; }
bool IPSET_NAME(remove_network)(struct ip_set *set, CORK_IP *elem, unsigned int cidr_prefix) { /* Special case — the BDD for a netmask that's out of range never * evaluates to true. */ if (cidr_prefix > IP_BIT_SIZE) { cork_error_set (IPSET_ERROR, IPSET_PARSE_ERROR, "CIDR block %u out of range [0..%u]", cidr_prefix, IP_BIT_SIZE); return false; }
ipset_node_id new_bdd = ipset_node_insert (set->cache, set->set_bdd, IPSET_NAME(assignment), elem, cidr_prefix + 1, 0); bool result = (new_bdd == set->set_bdd); ipset_node_decref(set->cache, set->set_bdd); set->set_bdd = new_bdd; return result; }
|