1/* -*- coding: utf-8 -*- 2 * ---------------------------------------------------------------------- 3 * Copyright © 2009-2012, RedJack, LLC. 4 * All rights reserved. 5 * 6 * Please see the LICENSE.txt file in this distribution for license 7 * details. 8 * ---------------------------------------------------------------------- 9 */ 10 11#include <libcork/core.h> 12 13#include "ipset/bdd/nodes.h" 14#include "ipset/bits.h" 15#include "ipset/errors.h" 16#include "ipset/ipset.h" 17 18 19/** 20 * Given a BDD variable number, return the index of the corresponding 21 * bit in an IP address. IPv4 addresses use variables 1-32; IPv6 22 * addresses use 1-128. (Variable 0 is used to identify the kind of 23 * address — TRUE for IPv4, FALSE for IPv6.) 24 */ 25 26static unsigned int 27IPMAP_NAME(bit_for_var)(ipset_variable var) 28{ 29 return (var - 1); 30} 31 32 33/** 34 * An assignment function that can be used to evaluate an IP map BDD. 35 */ 36 37static bool 38IPMAP_NAME(assignment)(const void *addr, ipset_variable var) 39{ 40 if (var == 0) { 41 return IP_DISCRIMINATOR_VALUE; 42 } else { 43 unsigned int bit = IPMAP_NAME(bit_for_var)(var); 44 return IPSET_BIT_GET(addr, bit); 45 } 46} 47 48 49int 50IPMAP_NAME(get)(struct ip_map *map, CORK_IP *elem) 51{ 52 return ipset_node_evaluate 53 (map->cache, map->map_bdd, IPMAP_NAME(assignment), elem); 54} 55 56 57void 58IPMAP_NAME(set_network)(struct ip_map *map, CORK_IP *elem, 59 unsigned int cidr_prefix, int value) 60{ 61 /* Special case — the BDD for a netmask that's out of range never 62 * evaluates to true. */ 63 if (cidr_prefix > IP_BIT_SIZE) { 64 cork_error_set 65 (IPSET_ERROR, IPSET_PARSE_ERROR, 66 "CIDR block %u out of range [0..%u]", cidr_prefix, IP_BIT_SIZE); 67 return; 68 } 69 70 ipset_node_id new_bdd = 71 ipset_node_insert 72 (map->cache, map->map_bdd, 73 IPMAP_NAME(assignment), elem, cidr_prefix + 1, value); 74 ipset_node_decref(map->cache, map->map_bdd); 75 map->map_bdd = new_bdd; 76} 77 78 79void 80IPMAP_NAME(set)(struct ip_map *map, CORK_IP *elem, int value) 81{ 82 ipset_node_id new_bdd = 83 ipset_node_insert 84 (map->cache, map->map_bdd, 85 IPMAP_NAME(assignment), elem, IP_BIT_SIZE + 1, value); 86 ipset_node_decref(map->cache, map->map_bdd); 87 map->map_bdd = new_bdd; 88} 89