mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-31 14:33:50 +00:00
add libipset
This commit is contained in:
@@ -0,0 +1,536 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ----------------------------------------------------------------------
|
||||
* Copyright © 2010-2013, RedJack, LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Please see the LICENSE.txt file in this distribution for license
|
||||
* details.
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef IPSET_BDD_NODES_H
|
||||
#define IPSET_BDD_NODES_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libcork/core.h>
|
||||
#include <libcork/ds.h>
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Preliminaries
|
||||
*/
|
||||
|
||||
/**
|
||||
* Each variable in a BDD is referred to by number.
|
||||
*/
|
||||
typedef unsigned int ipset_variable;
|
||||
|
||||
|
||||
/**
|
||||
* Each BDD terminal represents an integer value. The integer must be
|
||||
* non-negative, but must be within the range of the <i>signed</i>
|
||||
* integer type.
|
||||
*/
|
||||
typedef unsigned int ipset_value;
|
||||
|
||||
|
||||
/**
|
||||
* An identifier for each distinct node in a BDD.
|
||||
*
|
||||
* Internal implementation note. Since pointers are aligned to at
|
||||
* least two bytes, the ID of a terminal node has its LSB set to 1,
|
||||
* and has the terminal value stored in the remaining bits. The ID of
|
||||
* a nonterminal node is simply a pointer to the node struct.
|
||||
*/
|
||||
typedef unsigned int ipset_node_id;
|
||||
|
||||
|
||||
/**
|
||||
* Nodes can either be terminal or nonterminal.
|
||||
*/
|
||||
enum ipset_node_type {
|
||||
IPSET_NONTERMINAL_NODE = 0,
|
||||
IPSET_TERMINAL_NODE = 1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the type of node represented by a particular node ID.
|
||||
*/
|
||||
#define ipset_node_get_type(node_id) ((node_id) & 0x01)
|
||||
|
||||
#define IPSET_NODE_ID_FORMAT "%s%u"
|
||||
#define IPSET_NODE_ID_VALUES(node_id) \
|
||||
(ipset_node_get_type((node_id)) == IPSET_NONTERMINAL_NODE? "s": ""), \
|
||||
((node_id) >> 1)
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Terminal nodes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the value of a terminal node. The result is undefined if
|
||||
* the node ID represents a nonterminal.
|
||||
*/
|
||||
#define ipset_terminal_value(node_id) ((node_id) >> 1)
|
||||
|
||||
/**
|
||||
* Creates a terminal node ID from a terminal value.
|
||||
*/
|
||||
#define ipset_terminal_node_id(value) \
|
||||
(((value) << 1) | IPSET_TERMINAL_NODE)
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Nonterminal nodes
|
||||
*/
|
||||
|
||||
/**
|
||||
* A nonterminal BDD node. This is an inner node of the BDD tree.
|
||||
* The node represents one variable in an overall variable assignment.
|
||||
* The node has two children: a “low” child and a “high” child. The
|
||||
* low child is the subtree that applies when the node's variable is
|
||||
* false or 0; the high child is the subtree that applies when it's
|
||||
* true or 1.
|
||||
*
|
||||
* This type does not take care of ensuring that all BDD nodes are
|
||||
* reduced; that is handled by the node_cache class.
|
||||
*/
|
||||
struct ipset_node {
|
||||
/** The reference count for this node. */
|
||||
unsigned int refcount;
|
||||
/** The variable that this node represents. */
|
||||
ipset_variable variable;
|
||||
/** The subtree node for when the variable is false. */
|
||||
ipset_node_id low;
|
||||
/** The subtree node for when the variable is true. */
|
||||
ipset_node_id high;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the "value" of a nonterminal node. The value of a nonterminal
|
||||
* is the index into the node array of the cache that the node belongs
|
||||
* to.
|
||||
*/
|
||||
#define ipset_nonterminal_value(node_id) ((node_id) >> 1)
|
||||
|
||||
/**
|
||||
* Creates a nonterminal node ID from a nonterminal value.
|
||||
*/
|
||||
#define ipset_nonterminal_node_id(value) \
|
||||
(((value) << 1) | IPSET_NONTERMINAL_NODE)
|
||||
|
||||
/**
|
||||
* Print out a node object.
|
||||
*/
|
||||
void
|
||||
ipset_node_fprint(FILE *stream, struct ipset_node *node);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Node caches
|
||||
*/
|
||||
|
||||
/**
|
||||
* The log2 of the size of each chunk of BDD nodes.
|
||||
*/
|
||||
/* 16K elements per cache */
|
||||
#define IPSET_BDD_NODE_CACHE_BIT_SIZE 6
|
||||
#define IPSET_BDD_NODE_CACHE_SIZE (1 << IPSET_BDD_NODE_CACHE_BIT_SIZE)
|
||||
#define IPSET_BDD_NODE_CACHE_MASK (IPSET_BDD_NODE_CACHE_SIZE - 1)
|
||||
|
||||
/**
|
||||
* A cache for BDD nodes. By creating and retrieving nodes through
|
||||
* the cache, we ensure that a BDD is reduced.
|
||||
*/
|
||||
struct ipset_node_cache {
|
||||
/** The storage for the nodes managed by this cache. */
|
||||
cork_array(struct ipset_node *) chunks;
|
||||
/** The largest nonterminal index that has been handed out. */
|
||||
ipset_value largest_index;
|
||||
/** The index of the first node in the free list. */
|
||||
ipset_value free_list;
|
||||
/** A cache of the nonterminal nodes, keyed by their contents. */
|
||||
struct cork_hash_table *node_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the index of the chunk that the given nonterminal lives in.
|
||||
*/
|
||||
#define ipset_nonterminal_chunk_index(index) \
|
||||
((index) >> IPSET_BDD_NODE_CACHE_BIT_SIZE)
|
||||
|
||||
/**
|
||||
* Returns the offset of the given nonterminal within its chunk.
|
||||
*/
|
||||
#define ipset_nonterminal_chunk_offset(index) \
|
||||
((index) & IPSET_BDD_NODE_CACHE_MASK)
|
||||
|
||||
/**
|
||||
* Returns a pointer to the ipset_node for a given nonterminal index.
|
||||
*/
|
||||
#define ipset_node_cache_get_nonterminal_by_index(cache, index) \
|
||||
(&cork_array_at(&(cache)->chunks, ipset_nonterminal_chunk_index((index))) \
|
||||
[ipset_nonterminal_chunk_offset((index))])
|
||||
|
||||
/**
|
||||
* Returns the ipset_node for a given nonterminal node ID.
|
||||
*/
|
||||
#define ipset_node_cache_get_nonterminal(cache, node_id) \
|
||||
(ipset_node_cache_get_nonterminal_by_index \
|
||||
((cache), ipset_nonterminal_value((node_id))))
|
||||
|
||||
/**
|
||||
* Create a new node cache.
|
||||
*/
|
||||
struct ipset_node_cache *
|
||||
ipset_node_cache_new(void);
|
||||
|
||||
/**
|
||||
* Free a node cache.
|
||||
*/
|
||||
void
|
||||
ipset_node_cache_free(struct ipset_node_cache *cache);
|
||||
|
||||
/**
|
||||
* Create a new nonterminal node with the given contents, returning
|
||||
* its ID. This function ensures that there is only one node with the
|
||||
* given contents in this cache.
|
||||
*
|
||||
* Steals references to low and high.
|
||||
*/
|
||||
ipset_node_id
|
||||
ipset_node_cache_nonterminal(struct ipset_node_cache *cache,
|
||||
ipset_variable variable,
|
||||
ipset_node_id low, ipset_node_id high);
|
||||
|
||||
|
||||
/**
|
||||
* Increment the reference count of a nonterminal node. (This is a
|
||||
* no-op for terminal nodes.)
|
||||
*/
|
||||
ipset_node_id
|
||||
ipset_node_incref(struct ipset_node_cache *cache, ipset_node_id node);
|
||||
|
||||
/**
|
||||
* Decrement the reference count of a nonterminal node. If the
|
||||
* reference count reaches 0, the storage for the node will be
|
||||
* reclaimed. (This is a no-op for terminal nodes.)
|
||||
*/
|
||||
void
|
||||
ipset_node_decref(struct ipset_node_cache *cache, ipset_node_id node);
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of nodes that are reachable from the given node.
|
||||
* This does not include duplicates if a node is reachable via more
|
||||
* than one path.
|
||||
*/
|
||||
size_t
|
||||
ipset_node_reachable_count(const struct ipset_node_cache *cache,
|
||||
ipset_node_id node);
|
||||
|
||||
|
||||
/**
|
||||
* Return the amount of memory used by the nodes in the given BDD.
|
||||
*/
|
||||
size_t
|
||||
ipset_node_memory_size(const struct ipset_node_cache *cache,
|
||||
ipset_node_id node);
|
||||
|
||||
|
||||
/**
|
||||
* Load a BDD from an input stream. The error field is filled in with
|
||||
* an error condition is the BDD can't be read for any reason.
|
||||
*/
|
||||
ipset_node_id
|
||||
ipset_node_cache_load(FILE *stream, struct ipset_node_cache *cache);
|
||||
|
||||
|
||||
/**
|
||||
* Save a BDD to an output stream. This encodes the set using only
|
||||
* those nodes that are reachable from the BDD's root node.
|
||||
*/
|
||||
int
|
||||
ipset_node_cache_save(struct cork_stream_consumer *stream,
|
||||
struct ipset_node_cache *cache, ipset_node_id node);
|
||||
|
||||
|
||||
/**
|
||||
* Compare two BDD nodes, possibly from different caches, for equality.
|
||||
*/
|
||||
bool
|
||||
ipset_node_cache_nodes_equal(const struct ipset_node_cache *cache1,
|
||||
ipset_node_id node1,
|
||||
const struct ipset_node_cache *cache2,
|
||||
ipset_node_id node2);
|
||||
|
||||
|
||||
/**
|
||||
* Save a GraphViz dot graph for a BDD. The graph script is written
|
||||
* to the given output stream. This graph only includes those nodes
|
||||
* that are reachable from the BDD's root node.
|
||||
*/
|
||||
int
|
||||
ipset_node_cache_save_dot(struct cork_stream_consumer *stream,
|
||||
struct ipset_node_cache *cache, ipset_node_id node);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* BDD operators
|
||||
*/
|
||||
|
||||
/**
|
||||
* A function that provides the value for each variable in a BDD.
|
||||
*/
|
||||
typedef bool
|
||||
(*ipset_assignment_func)(const void *user_data,
|
||||
ipset_variable variable);
|
||||
|
||||
/**
|
||||
* An assignment function that gets the variable values from an array
|
||||
* of gbooleans.
|
||||
*/
|
||||
bool
|
||||
ipset_bool_array_assignment(const void *user_data,
|
||||
ipset_variable variable);
|
||||
|
||||
/**
|
||||
* An assignment function that gets the variable values from an array
|
||||
* of bits.
|
||||
*/
|
||||
bool
|
||||
ipset_bit_array_assignment(const void *user_data,
|
||||
ipset_variable variable);
|
||||
|
||||
/**
|
||||
* Evaluate a BDD given a particular assignment of variables.
|
||||
*/
|
||||
ipset_value
|
||||
ipset_node_evaluate(const struct ipset_node_cache *cache, ipset_node_id node,
|
||||
ipset_assignment_func assignment,
|
||||
const void *user_data);
|
||||
|
||||
/**
|
||||
* Add an assignment to the BDD.
|
||||
*/
|
||||
ipset_node_id
|
||||
ipset_node_insert(struct ipset_node_cache *cache, ipset_node_id node,
|
||||
ipset_assignment_func assignment,
|
||||
const void *user_data, ipset_variable variable_count,
|
||||
ipset_value value);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Variable assignments
|
||||
*/
|
||||
|
||||
/**
|
||||
* Each variable in the input to a Boolean function can be true or
|
||||
* false; it can also be EITHER, which means that the variable can be
|
||||
* either true or false in a particular assignment without affecting
|
||||
* the result of the function.
|
||||
*/
|
||||
enum ipset_tribool {
|
||||
IPSET_FALSE = 0,
|
||||
IPSET_TRUE = 1,
|
||||
IPSET_EITHER = 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An assignment is a mapping of variable numbers to Boolean values.
|
||||
* It represents an input to a Boolean function that maps to a
|
||||
* particular output value. Each variable in the input to a Boolean
|
||||
* function can be true or false; it can also be EITHER, which means
|
||||
* that the variable can be either true or false in a particular
|
||||
* assignment without affecting the result of the function.
|
||||
*/
|
||||
|
||||
struct ipset_assignment {
|
||||
/**
|
||||
* The underlying variable assignments are stored in a vector of
|
||||
* tribools. Every variable that has a true or false value must
|
||||
* appear in the vector. Variables that are EITHER only have to
|
||||
* appear to prevent gaps in the vector. Any variables outside
|
||||
* the range of the vector are assumed to be EITHER.
|
||||
*/
|
||||
cork_array(enum ipset_tribool) values;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a new assignment where all variables are indeterminite.
|
||||
*/
|
||||
struct ipset_assignment *
|
||||
ipset_assignment_new();
|
||||
|
||||
|
||||
/**
|
||||
* Free an assignment.
|
||||
*/
|
||||
void
|
||||
ipset_assignment_free(struct ipset_assignment *assignment);
|
||||
|
||||
|
||||
/**
|
||||
* Compare two assignments for equality.
|
||||
*/
|
||||
bool
|
||||
ipset_assignment_equal(const struct ipset_assignment *assignment1,
|
||||
const struct ipset_assignment *assignment2);
|
||||
|
||||
|
||||
/**
|
||||
* Set the given variable, and all higher variables, to the EITHER
|
||||
* value.
|
||||
*/
|
||||
void
|
||||
ipset_assignment_cut(struct ipset_assignment *assignment, ipset_variable var);
|
||||
|
||||
|
||||
/**
|
||||
* Clear the assignment, setting all variables to the EITHER value.
|
||||
*/
|
||||
void
|
||||
ipset_assignment_clear(struct ipset_assignment *assignment);
|
||||
|
||||
|
||||
/**
|
||||
* Return the value assigned to a particular variable.
|
||||
*/
|
||||
enum ipset_tribool
|
||||
ipset_assignment_get(struct ipset_assignment *assignment, ipset_variable var);
|
||||
|
||||
|
||||
/**
|
||||
* Set the value assigned to a particular variable.
|
||||
*/
|
||||
void
|
||||
ipset_assignment_set(struct ipset_assignment *assignment,
|
||||
ipset_variable var, enum ipset_tribool value);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Expanded assignments
|
||||
*/
|
||||
|
||||
/**
|
||||
* An iterator for expanding a variable assignment. For each EITHER
|
||||
* variable in the assignment, the iterator yields a result with both
|
||||
* values.
|
||||
*/
|
||||
struct ipset_expanded_assignment {
|
||||
/** Whether there are any more assignments in this iterator. */
|
||||
bool finished;
|
||||
|
||||
/**
|
||||
* The variable values in the current expanded assignment. Since
|
||||
* there won't be any EITHERs in the expanded assignment, we can
|
||||
* use a byte array, and represent each variable by a single bit.
|
||||
*/
|
||||
struct cork_buffer values;
|
||||
|
||||
/**
|
||||
* An array containing all of the variables that are EITHER in the
|
||||
* original assignment.
|
||||
*/
|
||||
cork_array(ipset_variable) eithers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return an iterator that expands a variable assignment. For each
|
||||
* variable that's EITHER in the assignment, the iterator yields a
|
||||
* result with both values. The iterator will ensure that the
|
||||
* specified number of variables are given concrete values.
|
||||
*/
|
||||
struct ipset_expanded_assignment *
|
||||
ipset_assignment_expand(const struct ipset_assignment *assignment,
|
||||
ipset_variable var_count);
|
||||
|
||||
|
||||
/**
|
||||
* Free an expanded assignment iterator.
|
||||
*/
|
||||
void
|
||||
ipset_expanded_assignment_free(struct ipset_expanded_assignment *exp);
|
||||
|
||||
|
||||
/**
|
||||
* Advance the iterator to the next assignment.
|
||||
*/
|
||||
void
|
||||
ipset_expanded_assignment_advance(struct ipset_expanded_assignment *exp);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* BDD iterators
|
||||
*/
|
||||
|
||||
/**
|
||||
* An iterator for walking through the assignments for a given BDD
|
||||
* node.
|
||||
*
|
||||
* The iterator walks through each path in the BDD tree, stopping at
|
||||
* each terminal node. Each time we reach a terminal node, we yield a
|
||||
* new ipset_assignment object representing the assignment of variables
|
||||
* along the current path.
|
||||
*
|
||||
* We maintain a stack of nodes leading to the current terminal, which
|
||||
* allows us to backtrack up the path to find the next terminal when
|
||||
* we increment the iterator.
|
||||
*/
|
||||
struct ipset_bdd_iterator {
|
||||
/** Whether there are any more assignments in this iterator. */
|
||||
bool finished;
|
||||
|
||||
/** The node cache that we're iterating through. */
|
||||
struct ipset_node_cache *cache;
|
||||
|
||||
/**
|
||||
* The sequence of nonterminal nodes leading to the current
|
||||
* terminal.
|
||||
*/
|
||||
cork_array(ipset_node_id) stack;
|
||||
|
||||
/** The current assignment. */
|
||||
struct ipset_assignment *assignment;
|
||||
|
||||
/**
|
||||
* The value of the BDD's function when applied to the current
|
||||
* assignment.
|
||||
*/
|
||||
ipset_value value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return an iterator that yields all of the assignments in the given
|
||||
* BDD. The iterator contains two items of interest. The first is an
|
||||
* ipset_assignment providing the value that each variable takes, while
|
||||
* the second is the terminal value that is the result of the BDD's
|
||||
* function when applied to that variable assignment.
|
||||
*/
|
||||
struct ipset_bdd_iterator *
|
||||
ipset_node_iterate(struct ipset_node_cache *cache, ipset_node_id root);
|
||||
|
||||
|
||||
/**
|
||||
* Free a BDD iterator.
|
||||
*/
|
||||
void
|
||||
ipset_bdd_iterator_free(struct ipset_bdd_iterator *iterator);
|
||||
|
||||
|
||||
/**
|
||||
* Advance the iterator to the next assignment.
|
||||
*/
|
||||
void
|
||||
ipset_bdd_iterator_advance(struct ipset_bdd_iterator *iterator);
|
||||
|
||||
|
||||
#endif /* IPSET_BDD_NODES_H */
|
||||
@@ -0,0 +1,58 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ----------------------------------------------------------------------
|
||||
* Copyright © 2012, RedJack, LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Please see the LICENSE.txt file in this distribution for license
|
||||
* details.
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef IPSET_BITS_H
|
||||
#define IPSET_BITS_H
|
||||
|
||||
#include <libcork/core.h>
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Bit arrays
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extract the byte that contains a particular bit in an array.
|
||||
*/
|
||||
#define IPSET_BIT_GET_BYTE(array, i) \
|
||||
(((uint8_t *) (array))[(i) / 8])
|
||||
|
||||
/**
|
||||
* Create a bit mask that extracts a particular bit from the byte that
|
||||
* it lives in.
|
||||
*/
|
||||
#define IPSET_BIT_ON_MASK(i) \
|
||||
(0x80 >> ((i) % 8))
|
||||
|
||||
/**
|
||||
* Create a bit mask that extracts everything except for a particular
|
||||
* bit from the byte that it lives in.
|
||||
*/
|
||||
#define IPSET_BIT_NEG_MASK(i) \
|
||||
(~IPSET_BIT_ON_MASK(i))
|
||||
|
||||
/**
|
||||
* Return whether a particular bit is set in a byte array. Bits are
|
||||
* numbered from 0, in a big-endian order.
|
||||
*/
|
||||
#define IPSET_BIT_GET(array, i) \
|
||||
((IPSET_BIT_GET_BYTE(array, i) & \
|
||||
IPSET_BIT_ON_MASK(i)) != 0)
|
||||
|
||||
/**
|
||||
* Set (or unset) a particular bit is set in a byte array. Bits are
|
||||
* numbered from 0, in a big-endian order.
|
||||
*/
|
||||
#define IPSET_BIT_SET(array, i, val) \
|
||||
(IPSET_BIT_GET_BYTE(array, i) = \
|
||||
(IPSET_BIT_GET_BYTE(array, i) & IPSET_BIT_NEG_MASK(i)) \
|
||||
| ((val)? IPSET_BIT_ON_MASK(i): 0))
|
||||
|
||||
|
||||
#endif /* IPSET_BITS_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ----------------------------------------------------------------------
|
||||
* Copyright © 2012, RedJack, LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Please see the LICENSE.txt file in this distribution for license
|
||||
* details.
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef IPSET_ERRORS_H
|
||||
#define IPSET_ERRORS_H
|
||||
|
||||
|
||||
#include <libcork/core.h>
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Error reporting
|
||||
*/
|
||||
|
||||
/* Hash of "ipset.h" */
|
||||
#define IPSET_ERROR 0xf2000181
|
||||
|
||||
enum ipset_error {
|
||||
IPSET_IO_ERROR,
|
||||
IPSET_PARSE_ERROR
|
||||
};
|
||||
|
||||
|
||||
#endif /* IPSET_ERRORS_H */
|
||||
@@ -0,0 +1,265 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ----------------------------------------------------------------------
|
||||
* Copyright © 2009-2012, RedJack, LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Please see the LICENSE.txt file in this distribution for license
|
||||
* details.
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef IPSET_IPSET_H
|
||||
#define IPSET_IPSET_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libcork/core.h>
|
||||
#include <libcork/ds.h>
|
||||
|
||||
#include <ipset/bdd/nodes.h>
|
||||
|
||||
|
||||
struct ip_set {
|
||||
struct ipset_node_cache *cache;
|
||||
ipset_node_id set_bdd;
|
||||
};
|
||||
|
||||
|
||||
struct ip_map {
|
||||
struct ipset_node_cache *cache;
|
||||
ipset_node_id map_bdd;
|
||||
ipset_node_id default_bdd;
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* General functions
|
||||
*/
|
||||
|
||||
int
|
||||
ipset_init_library(void);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* IP set functions
|
||||
*/
|
||||
|
||||
void
|
||||
ipset_init(struct ip_set *set);
|
||||
|
||||
void
|
||||
ipset_done(struct ip_set *set);
|
||||
|
||||
struct ip_set *
|
||||
ipset_new(void);
|
||||
|
||||
void
|
||||
ipset_free(struct ip_set *set);
|
||||
|
||||
bool
|
||||
ipset_is_empty(const struct ip_set *set);
|
||||
|
||||
bool
|
||||
ipset_is_equal(const struct ip_set *set1, const struct ip_set *set2);
|
||||
|
||||
size_t
|
||||
ipset_memory_size(const struct ip_set *set);
|
||||
|
||||
int
|
||||
ipset_save(FILE *stream, const struct ip_set *set);
|
||||
|
||||
int
|
||||
ipset_save_to_stream(struct cork_stream_consumer *stream,
|
||||
const struct ip_set *set);
|
||||
|
||||
int
|
||||
ipset_save_dot(FILE *stream, const struct ip_set *set);
|
||||
|
||||
struct ip_set *
|
||||
ipset_load(FILE *stream);
|
||||
|
||||
bool
|
||||
ipset_ipv4_add(struct ip_set *set, struct cork_ipv4 *elem);
|
||||
|
||||
bool
|
||||
ipset_ipv4_add_network(struct ip_set *set, struct cork_ipv4 *elem,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_ipv4_remove(struct ip_set *set, struct cork_ipv4 *elem);
|
||||
|
||||
bool
|
||||
ipset_ipv4_remove_network(struct ip_set *set, struct cork_ipv4 *elem,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_contains_ipv4(const struct ip_set *set, struct cork_ipv4 *elem);
|
||||
|
||||
bool
|
||||
ipset_ipv6_add(struct ip_set *set, struct cork_ipv6 *elem);
|
||||
|
||||
bool
|
||||
ipset_ipv6_add_network(struct ip_set *set, struct cork_ipv6 *elem,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_ipv6_remove(struct ip_set *set, struct cork_ipv6 *elem);
|
||||
|
||||
bool
|
||||
ipset_ipv6_remove_network(struct ip_set *set, struct cork_ipv6 *elem,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_contains_ipv6(const struct ip_set *set, struct cork_ipv6 *elem);
|
||||
|
||||
bool
|
||||
ipset_ip_add(struct ip_set *set, struct cork_ip *addr);
|
||||
|
||||
bool
|
||||
ipset_ip_add_network(struct ip_set *set, struct cork_ip *addr,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_ip_remove(struct ip_set *set, struct cork_ip *addr);
|
||||
|
||||
bool
|
||||
ipset_ip_remove_network(struct ip_set *set, struct cork_ip *addr,
|
||||
unsigned int cidr_prefix);
|
||||
|
||||
bool
|
||||
ipset_contains_ip(const struct ip_set *set, struct cork_ip *elem);
|
||||
|
||||
|
||||
/* An internal state type used by the ipset_iterator_multiple_expansion_state
|
||||
* field. */
|
||||
enum ipset_iterator_state {
|
||||
IPSET_ITERATOR_NORMAL = 0,
|
||||
IPSET_ITERATOR_MULTIPLE_IPV4,
|
||||
IPSET_ITERATOR_MULTIPLE_IPV6
|
||||
};
|
||||
|
||||
|
||||
/* An iterator that returns all of the IP addresses that have a given value in
|
||||
* an IP set or map. */
|
||||
struct ipset_iterator {
|
||||
/* The address of the current IP network in the iterator. */
|
||||
struct cork_ip addr;
|
||||
|
||||
/* The netmask of the current IP network in the iterator, given as a
|
||||
* CIDR prefix. For a single IP address, this will be 32 or 128. */
|
||||
unsigned int cidr_prefix;
|
||||
|
||||
/* Whether the current assignment needs to be expanded a second
|
||||
* time.
|
||||
*
|
||||
* We have to expand IPv4 and IPv6 assignments separately, since the
|
||||
* set of variables to turn into address bits is different.
|
||||
* Unfortunately, a BDD assignment can contain both IPv4 and IPv6
|
||||
* addresses, if variable 0 is EITHER. (This is trivially true for
|
||||
* the empty set, for instance.) In this case, we have to
|
||||
* explicitly set variable 0 to TRUE, expand it as IPv4, and then
|
||||
* set it to FALSE, and expand it as IPv6. This variable tells us
|
||||
* whether we're in an assignment that needs to be expanded twice,
|
||||
* and if so, which expansion we're currently in.
|
||||
*/
|
||||
enum ipset_iterator_state multiple_expansion_state;
|
||||
|
||||
/* An iterator for retrieving each assignment in the set's BDD. */
|
||||
struct ipset_bdd_iterator *bdd_iterator;
|
||||
|
||||
/* An iterator for expanding each assignment into individual IP
|
||||
* addresses. */
|
||||
struct ipset_expanded_assignment *assignment_iterator;
|
||||
|
||||
/* Whether there are any more IP addresses in this iterator. */
|
||||
bool finished;
|
||||
|
||||
/* The desired value for each IP address. */
|
||||
bool desired_value;
|
||||
|
||||
/* Whether to summarize the contents of the IP set as networks,
|
||||
* where possible. */
|
||||
bool summarize;
|
||||
};
|
||||
|
||||
|
||||
struct ipset_iterator *
|
||||
ipset_iterate(struct ip_set *set, bool desired_value);
|
||||
|
||||
struct ipset_iterator *
|
||||
ipset_iterate_networks(struct ip_set *set, bool desired_value);
|
||||
|
||||
void
|
||||
ipset_iterator_free(struct ipset_iterator *iterator);
|
||||
|
||||
void
|
||||
ipset_iterator_advance(struct ipset_iterator *iterator);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* IP map functions
|
||||
*/
|
||||
|
||||
void
|
||||
ipmap_init(struct ip_map *map, int default_value);
|
||||
|
||||
void
|
||||
ipmap_done(struct ip_map *map);
|
||||
|
||||
struct ip_map *
|
||||
ipmap_new(int default_value);
|
||||
|
||||
void
|
||||
ipmap_free(struct ip_map *map);
|
||||
|
||||
bool
|
||||
ipmap_is_empty(const struct ip_map *map);
|
||||
|
||||
bool
|
||||
ipmap_is_equal(const struct ip_map *map1, const struct ip_map *map2);
|
||||
|
||||
size_t
|
||||
ipmap_memory_size(const struct ip_map *map);
|
||||
|
||||
int
|
||||
ipmap_save(FILE *stream, const struct ip_map *map);
|
||||
|
||||
int
|
||||
ipmap_save_to_stream(struct cork_stream_consumer *stream,
|
||||
const struct ip_map *map);
|
||||
|
||||
struct ip_map *
|
||||
ipmap_load(FILE *stream);
|
||||
|
||||
void
|
||||
ipmap_ipv4_set(struct ip_map *map, struct cork_ipv4 *elem, int value);
|
||||
|
||||
void
|
||||
ipmap_ipv4_set_network(struct ip_map *map, struct cork_ipv4 *elem,
|
||||
unsigned int cidr_prefix, int value);
|
||||
|
||||
int
|
||||
ipmap_ipv4_get(struct ip_map *map, struct cork_ipv4 *elem);
|
||||
|
||||
void
|
||||
ipmap_ipv6_set(struct ip_map *map, struct cork_ipv6 *elem, int value);
|
||||
|
||||
void
|
||||
ipmap_ipv6_set_network(struct ip_map *map, struct cork_ipv6 *elem,
|
||||
unsigned int cidr_prefix, int value);
|
||||
|
||||
int
|
||||
ipmap_ipv6_get(struct ip_map *map, struct cork_ipv6 *elem);
|
||||
|
||||
void
|
||||
ipmap_ip_set(struct ip_map *map, struct cork_ip *addr, int value);
|
||||
|
||||
void
|
||||
ipmap_ip_set_network(struct ip_map *map, struct cork_ip *addr,
|
||||
unsigned int cidr_prefix, int value);
|
||||
|
||||
int
|
||||
ipmap_ip_get(struct ip_map *map, struct cork_ip *addr);
|
||||
|
||||
|
||||
#endif /* IPSET_IPSET_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ----------------------------------------------------------------------
|
||||
* Copyright © 2010-2012, RedJack, LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Please see the LICENSE.txt file in this distribution for license
|
||||
* details.
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef IPSET_LOGGING_H
|
||||
#define IPSET_LOGGING_H
|
||||
|
||||
|
||||
#if !defined(IPSET_DEBUG)
|
||||
#define IPSET_DEBUG 0
|
||||
#endif
|
||||
|
||||
#if IPSET_DEBUG
|
||||
#include <stdio.h>
|
||||
#define DEBUG(...) \
|
||||
do { \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG(...) /* no debug messages */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* IPSET_LOGGING_H */
|
||||
Reference in New Issue
Block a user