⛅ Sync 2026-08-05 21:58:21

This commit is contained in:
github-actions[bot] committed 2026-08-05 21:58:21 +08:00
1 parent 61841aa371
commit 6e0b600ecd
734 files changed
+225296 -28

No files matched your search

@@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------
# Copyright © 2011-2013, RedJack, LLC.
# All rights reserved.
#
# Please see the LICENSE.txt file in this distribution for license
# details.
# ----------------------------------------------------------------------
cmake_minimum_required(VERSION 2.6)
set(PROJECT_NAME ipset)
set(RELEASE_DATE 2013-12-11)
project(${PROJECT_NAME})
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(CTargets)
#-----------------------------------------------------------------------
# Retrieve the current version number
#-----------------------------------------------------------------------
# Check for building on Tilera
# If the Tilera environment is installed, then $TILERA_ROOT is defined
# as the path to the active MDE.
if(DEFINED ENV{TILERA_ROOT})
set(TILERA TRUE)
set(TILERA_ROOT $ENV{TILERA_ROOT})
message("-- Configuring for Tilera MDE ${TILERA_ROOT}")
set(ENV{PKG_CONFIG_PATH}
"${TILERA_ROOT}/tile/usr/lib/pkgconfig:${TILERA_ROOT}/tile/usr/local/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}"
)
set(CMAKE_SYSTEM_NAME "Tilera")
set(CMAKE_SYSTEM_PROCESSOR "tilegx")
set(CMAKE_C_COMPILER "${TILERA_ROOT}/bin/tile-gcc")
set(CMAKE_LINKER "${TILERA_ROOT}/bin/tile-ld")
set(TILERA_MONITOR "${TILERA_ROOT}/bin/tile-monitor")
#add_definitions(-std=gnu99)
set(CMAKE_FIND_ROOT_PATH "${TILERA_ROOT}/tile")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
#-----------------------------------------------------------------------
# Check for prerequisite libraries
include_directories(${libcork_include_dirs})
#-----------------------------------------------------------------------
# Set some options
if(APPLE)
if (NOT CMAKE_INSTALL_NAME_DIR)
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
endif (NOT CMAKE_INSTALL_NAME_DIR)
endif(APPLE)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
endif(NOT CMAKE_BUILD_TYPE)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
add_definitions(-Wall -Werror)
elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_definitions(-Wall -Werror)
elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel")
add_definitions(-Wall -Werror)
endif(CMAKE_C_COMPILER_ID STREQUAL "GNU")
#-----------------------------------------------------------------------
# Include our subdirectories
#add_subdirectory(src)
add_c_library(
libipset
OUTPUT_NAME ipset
PKGCONFIG_NAME libipset
VERSION 1.1.0
SOURCES
general.c
bdd/assignments.c
bdd/basics.c
bdd/bdd-iterator.c
bdd/expanded.c
bdd/reachable.c
bdd/read.c
bdd/write.c
map/allocation.c
map/inspection.c
map/ipv4_map.c
map/ipv6_map.c
map/storage.c
set/allocation.c
set/inspection.c
set/ipv4_set.c
set/ipv6_set.c
set/iterator.c
set/storage.c
LOCAL_LIBRARIES
libcork
)
set(libipset_include_dirs
${PROJECT_SOURCE_DIR}/include
${PROJECT_BINARY_DIR}/include
CACHE INTERNAL "libipset library" FORCE
)
@@ -0,0 +1,30 @@
Copyright © 2009-2013, RedJack, LLC.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
• Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
• Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
• Neither the name of RedJack Software, LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,13 @@
noinst_LTLIBRARIES = libipset.la
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
bdd/reachable.c bdd/read.c bdd/write.c
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
map/storage.c
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
set/iterator.c set/storage.c
libipset_la_SOURCES = general.c ${bdd_src} ${map_src} ${set_src}
libipset_la_CFLAGS = -I$(top_srcdir)/libipset/include -I$(top_srcdir)/libcork/include
libipset_la_LDFLAGS = -static
+852
View File
@@ -0,0 +1,852 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libipset
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/inet_ntop.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \
$(top_srcdir)/m4/polarssl.m4 \
$(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libipset_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_1 = bdd/libipset_la-assignments.lo \
bdd/libipset_la-basics.lo bdd/libipset_la-bdd-iterator.lo \
bdd/libipset_la-expanded.lo bdd/libipset_la-reachable.lo \
bdd/libipset_la-read.lo bdd/libipset_la-write.lo
am__objects_2 = map/libipset_la-allocation.lo \
map/libipset_la-inspection.lo map/libipset_la-ipv4_map.lo \
map/libipset_la-ipv6_map.lo map/libipset_la-storage.lo
am__objects_3 = set/libipset_la-allocation.lo \
set/libipset_la-inspection.lo set/libipset_la-ipv4_set.lo \
set/libipset_la-ipv6_set.lo set/libipset_la-iterator.lo \
set/libipset_la-storage.lo
am_libipset_la_OBJECTS = libipset_la-general.lo $(am__objects_1) \
$(am__objects_2) $(am__objects_3)
libipset_la_OBJECTS = $(am_libipset_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libipset_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libipset_la_CFLAGS) \
$(CFLAGS) $(libipset_la_LDFLAGS) $(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/auto/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libipset_la_SOURCES)
DIST_SOURCES = $(libipset_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/auto/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
GZIP = @GZIP@
INET_NTOP_LIB = @INET_NTOP_LIB@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPCRE = @LIBPCRE@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
MV = @MV@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PCRE_CONFIG = @PCRE_CONFIG@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XMLTO = @XMLTO@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pcre_pcreh = @pcre_pcreh@
pcreh = @pcreh@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = libipset.la
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
bdd/reachable.c bdd/read.c bdd/write.c
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
map/storage.c
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
set/iterator.c set/storage.c
libipset_la_SOURCES = general.c ${bdd_src} ${map_src} ${set_src}
libipset_la_CFLAGS = -I$(top_srcdir)/libipset/include -I$(top_srcdir)/libcork/include
libipset_la_LDFLAGS = -static
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libipset/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign libipset/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
bdd/$(am__dirstamp):
@$(MKDIR_P) bdd
@: > bdd/$(am__dirstamp)
bdd/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) bdd/$(DEPDIR)
@: > bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-assignments.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-basics.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-bdd-iterator.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-expanded.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-reachable.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-read.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
bdd/libipset_la-write.lo: bdd/$(am__dirstamp) \
bdd/$(DEPDIR)/$(am__dirstamp)
map/$(am__dirstamp):
@$(MKDIR_P) map
@: > map/$(am__dirstamp)
map/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) map/$(DEPDIR)
@: > map/$(DEPDIR)/$(am__dirstamp)
map/libipset_la-allocation.lo: map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/libipset_la-inspection.lo: map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/libipset_la-ipv4_map.lo: map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/libipset_la-ipv6_map.lo: map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/libipset_la-storage.lo: map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
set/$(am__dirstamp):
@$(MKDIR_P) set
@: > set/$(am__dirstamp)
set/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) set/$(DEPDIR)
@: > set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-allocation.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-inspection.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-ipv4_set.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-ipv6_set.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-iterator.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
set/libipset_la-storage.lo: set/$(am__dirstamp) \
set/$(DEPDIR)/$(am__dirstamp)
libipset.la: $(libipset_la_OBJECTS) $(libipset_la_DEPENDENCIES) $(EXTRA_libipset_la_DEPENDENCIES)
$(AM_V_CCLD)$(libipset_la_LINK) $(libipset_la_OBJECTS) $(libipset_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f bdd/*.$(OBJEXT)
-rm -f bdd/*.lo
-rm -f map/*.$(OBJEXT)
-rm -f map/*.lo
-rm -f set/*.$(OBJEXT)
-rm -f set/*.lo
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libipset_la-general.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-assignments.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-basics.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-bdd-iterator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-expanded.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-reachable.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-read.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-write.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@map/$(DEPDIR)/libipset_la-allocation.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@map/$(DEPDIR)/libipset_la-inspection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@map/$(DEPDIR)/libipset_la-ipv4_map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@map/$(DEPDIR)/libipset_la-ipv6_map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@map/$(DEPDIR)/libipset_la-storage.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-allocation.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-inspection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-ipv4_set.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-ipv6_set.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-iterator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@set/$(DEPDIR)/libipset_la-storage.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
libipset_la-general.lo: general.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT libipset_la-general.lo -MD -MP -MF $(DEPDIR)/libipset_la-general.Tpo -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libipset_la-general.Tpo $(DEPDIR)/libipset_la-general.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='general.c' object='libipset_la-general.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c
bdd/libipset_la-assignments.lo: bdd/assignments.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-assignments.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-assignments.Tpo -c -o bdd/libipset_la-assignments.lo `test -f 'bdd/assignments.c' || echo '$(srcdir)/'`bdd/assignments.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-assignments.Tpo bdd/$(DEPDIR)/libipset_la-assignments.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/assignments.c' object='bdd/libipset_la-assignments.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-assignments.lo `test -f 'bdd/assignments.c' || echo '$(srcdir)/'`bdd/assignments.c
bdd/libipset_la-basics.lo: bdd/basics.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-basics.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-basics.Tpo -c -o bdd/libipset_la-basics.lo `test -f 'bdd/basics.c' || echo '$(srcdir)/'`bdd/basics.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-basics.Tpo bdd/$(DEPDIR)/libipset_la-basics.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/basics.c' object='bdd/libipset_la-basics.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-basics.lo `test -f 'bdd/basics.c' || echo '$(srcdir)/'`bdd/basics.c
bdd/libipset_la-bdd-iterator.lo: bdd/bdd-iterator.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-bdd-iterator.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-bdd-iterator.Tpo -c -o bdd/libipset_la-bdd-iterator.lo `test -f 'bdd/bdd-iterator.c' || echo '$(srcdir)/'`bdd/bdd-iterator.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-bdd-iterator.Tpo bdd/$(DEPDIR)/libipset_la-bdd-iterator.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/bdd-iterator.c' object='bdd/libipset_la-bdd-iterator.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-bdd-iterator.lo `test -f 'bdd/bdd-iterator.c' || echo '$(srcdir)/'`bdd/bdd-iterator.c
bdd/libipset_la-expanded.lo: bdd/expanded.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-expanded.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-expanded.Tpo -c -o bdd/libipset_la-expanded.lo `test -f 'bdd/expanded.c' || echo '$(srcdir)/'`bdd/expanded.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-expanded.Tpo bdd/$(DEPDIR)/libipset_la-expanded.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/expanded.c' object='bdd/libipset_la-expanded.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-expanded.lo `test -f 'bdd/expanded.c' || echo '$(srcdir)/'`bdd/expanded.c
bdd/libipset_la-reachable.lo: bdd/reachable.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-reachable.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-reachable.Tpo -c -o bdd/libipset_la-reachable.lo `test -f 'bdd/reachable.c' || echo '$(srcdir)/'`bdd/reachable.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-reachable.Tpo bdd/$(DEPDIR)/libipset_la-reachable.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/reachable.c' object='bdd/libipset_la-reachable.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-reachable.lo `test -f 'bdd/reachable.c' || echo '$(srcdir)/'`bdd/reachable.c
bdd/libipset_la-read.lo: bdd/read.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-read.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-read.Tpo -c -o bdd/libipset_la-read.lo `test -f 'bdd/read.c' || echo '$(srcdir)/'`bdd/read.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-read.Tpo bdd/$(DEPDIR)/libipset_la-read.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/read.c' object='bdd/libipset_la-read.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-read.lo `test -f 'bdd/read.c' || echo '$(srcdir)/'`bdd/read.c
bdd/libipset_la-write.lo: bdd/write.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-write.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-write.Tpo -c -o bdd/libipset_la-write.lo `test -f 'bdd/write.c' || echo '$(srcdir)/'`bdd/write.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-write.Tpo bdd/$(DEPDIR)/libipset_la-write.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bdd/write.c' object='bdd/libipset_la-write.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o bdd/libipset_la-write.lo `test -f 'bdd/write.c' || echo '$(srcdir)/'`bdd/write.c
map/libipset_la-allocation.lo: map/allocation.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT map/libipset_la-allocation.lo -MD -MP -MF map/$(DEPDIR)/libipset_la-allocation.Tpo -c -o map/libipset_la-allocation.lo `test -f 'map/allocation.c' || echo '$(srcdir)/'`map/allocation.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/libipset_la-allocation.Tpo map/$(DEPDIR)/libipset_la-allocation.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map/allocation.c' object='map/libipset_la-allocation.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o map/libipset_la-allocation.lo `test -f 'map/allocation.c' || echo '$(srcdir)/'`map/allocation.c
map/libipset_la-inspection.lo: map/inspection.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT map/libipset_la-inspection.lo -MD -MP -MF map/$(DEPDIR)/libipset_la-inspection.Tpo -c -o map/libipset_la-inspection.lo `test -f 'map/inspection.c' || echo '$(srcdir)/'`map/inspection.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/libipset_la-inspection.Tpo map/$(DEPDIR)/libipset_la-inspection.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map/inspection.c' object='map/libipset_la-inspection.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o map/libipset_la-inspection.lo `test -f 'map/inspection.c' || echo '$(srcdir)/'`map/inspection.c
map/libipset_la-ipv4_map.lo: map/ipv4_map.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT map/libipset_la-ipv4_map.lo -MD -MP -MF map/$(DEPDIR)/libipset_la-ipv4_map.Tpo -c -o map/libipset_la-ipv4_map.lo `test -f 'map/ipv4_map.c' || echo '$(srcdir)/'`map/ipv4_map.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/libipset_la-ipv4_map.Tpo map/$(DEPDIR)/libipset_la-ipv4_map.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map/ipv4_map.c' object='map/libipset_la-ipv4_map.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o map/libipset_la-ipv4_map.lo `test -f 'map/ipv4_map.c' || echo '$(srcdir)/'`map/ipv4_map.c
map/libipset_la-ipv6_map.lo: map/ipv6_map.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT map/libipset_la-ipv6_map.lo -MD -MP -MF map/$(DEPDIR)/libipset_la-ipv6_map.Tpo -c -o map/libipset_la-ipv6_map.lo `test -f 'map/ipv6_map.c' || echo '$(srcdir)/'`map/ipv6_map.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/libipset_la-ipv6_map.Tpo map/$(DEPDIR)/libipset_la-ipv6_map.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map/ipv6_map.c' object='map/libipset_la-ipv6_map.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o map/libipset_la-ipv6_map.lo `test -f 'map/ipv6_map.c' || echo '$(srcdir)/'`map/ipv6_map.c
map/libipset_la-storage.lo: map/storage.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT map/libipset_la-storage.lo -MD -MP -MF map/$(DEPDIR)/libipset_la-storage.Tpo -c -o map/libipset_la-storage.lo `test -f 'map/storage.c' || echo '$(srcdir)/'`map/storage.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/libipset_la-storage.Tpo map/$(DEPDIR)/libipset_la-storage.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='map/storage.c' object='map/libipset_la-storage.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o map/libipset_la-storage.lo `test -f 'map/storage.c' || echo '$(srcdir)/'`map/storage.c
set/libipset_la-allocation.lo: set/allocation.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-allocation.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-allocation.Tpo -c -o set/libipset_la-allocation.lo `test -f 'set/allocation.c' || echo '$(srcdir)/'`set/allocation.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-allocation.Tpo set/$(DEPDIR)/libipset_la-allocation.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/allocation.c' object='set/libipset_la-allocation.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-allocation.lo `test -f 'set/allocation.c' || echo '$(srcdir)/'`set/allocation.c
set/libipset_la-inspection.lo: set/inspection.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-inspection.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-inspection.Tpo -c -o set/libipset_la-inspection.lo `test -f 'set/inspection.c' || echo '$(srcdir)/'`set/inspection.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-inspection.Tpo set/$(DEPDIR)/libipset_la-inspection.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/inspection.c' object='set/libipset_la-inspection.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-inspection.lo `test -f 'set/inspection.c' || echo '$(srcdir)/'`set/inspection.c
set/libipset_la-ipv4_set.lo: set/ipv4_set.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-ipv4_set.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-ipv4_set.Tpo -c -o set/libipset_la-ipv4_set.lo `test -f 'set/ipv4_set.c' || echo '$(srcdir)/'`set/ipv4_set.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-ipv4_set.Tpo set/$(DEPDIR)/libipset_la-ipv4_set.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/ipv4_set.c' object='set/libipset_la-ipv4_set.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-ipv4_set.lo `test -f 'set/ipv4_set.c' || echo '$(srcdir)/'`set/ipv4_set.c
set/libipset_la-ipv6_set.lo: set/ipv6_set.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-ipv6_set.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-ipv6_set.Tpo -c -o set/libipset_la-ipv6_set.lo `test -f 'set/ipv6_set.c' || echo '$(srcdir)/'`set/ipv6_set.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-ipv6_set.Tpo set/$(DEPDIR)/libipset_la-ipv6_set.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/ipv6_set.c' object='set/libipset_la-ipv6_set.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-ipv6_set.lo `test -f 'set/ipv6_set.c' || echo '$(srcdir)/'`set/ipv6_set.c
set/libipset_la-iterator.lo: set/iterator.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-iterator.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-iterator.Tpo -c -o set/libipset_la-iterator.lo `test -f 'set/iterator.c' || echo '$(srcdir)/'`set/iterator.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-iterator.Tpo set/$(DEPDIR)/libipset_la-iterator.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/iterator.c' object='set/libipset_la-iterator.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-iterator.lo `test -f 'set/iterator.c' || echo '$(srcdir)/'`set/iterator.c
set/libipset_la-storage.lo: set/storage.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT set/libipset_la-storage.lo -MD -MP -MF set/$(DEPDIR)/libipset_la-storage.Tpo -c -o set/libipset_la-storage.lo `test -f 'set/storage.c' || echo '$(srcdir)/'`set/storage.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) set/$(DEPDIR)/libipset_la-storage.Tpo set/$(DEPDIR)/libipset_la-storage.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set/storage.c' object='set/libipset_la-storage.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o set/libipset_la-storage.lo `test -f 'set/storage.c' || echo '$(srcdir)/'`set/storage.c
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf bdd/.libs bdd/_libs
-rm -rf map/.libs map/_libs
-rm -rf set/.libs set/_libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f bdd/$(DEPDIR)/$(am__dirstamp)
-rm -f bdd/$(am__dirstamp)
-rm -f map/$(DEPDIR)/$(am__dirstamp)
-rm -f map/$(am__dirstamp)
-rm -f set/$(DEPDIR)/$(am__dirstamp)
-rm -f set/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
@@ -0,0 +1,10 @@
# ipset
The ipset library provides C data types for storing sets of IP
addresses, and maps of IP addresses to integers. It supports both
IPv4 and IPv6 addresses. It's implemented using [Binary Decision
Diagrams](http://en.wikipedia.org/wiki/Binary_decision_diagram)
(BDDs), which (we hypothesize) makes it space efficient for large
sets.
Please see the INSTALL file for installation instructions.
@@ -0,0 +1,30 @@
# This file is part of libasyncns.
#
# Copyright 2005-2008 Lennart Poettering
#
# libasyncns is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 2.1 of the
# License, or (at your option) any later version.
#
# libasyncns is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with libasyncns. If not, see
# <http://www.gnu.org/licenses/>.
noinst_LTLIBRARIES = libipset.la
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
bdd/reachable.c bdd/read.c bdd/write.c
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
map/storage.c
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
set/iterator.c set/storage.c
libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src}
libipset_la_LDFLAGS = -static
Whitespace-only changes.
@@ -0,0 +1,134 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-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"
struct ipset_assignment *
ipset_assignment_new()
{
struct ipset_assignment *assignment = cork_new(struct ipset_assignment);
cork_array_init(&assignment->values);
return assignment;
}
void
ipset_assignment_free(struct ipset_assignment *assignment)
{
cork_array_done(&assignment->values);
free(assignment);
}
bool
ipset_assignment_equal(const struct ipset_assignment *assignment1,
const struct ipset_assignment *assignment2)
{
/* Identical pointers are trivially equal. */
if (assignment1 == assignment2) {
return true;
}
/* Otherwise we compare the assignments piecewise up through the end
* of the smaller vector. */
unsigned int size1 = cork_array_size(&assignment1->values);
unsigned int size2 = cork_array_size(&assignment2->values);
unsigned int smaller_size = (size1 < size2)? size1: size2;
unsigned int i;
for (i = 0; i < smaller_size; i++) {
if (cork_array_at(&assignment1->values, i) !=
cork_array_at(&assignment2->values, i)) {
return false;
}
}
/* If one of the assignment vectors is longer, any remaining
* elements must be indeterminate. */
if (size1 > smaller_size) {
for (i = smaller_size; i < size1; i++) {
if (cork_array_at(&assignment1->values, i) != IPSET_EITHER) {
return false;
}
}
}
if (size2 > smaller_size) {
for (i = smaller_size; i < size2; i++) {
if (cork_array_at(&assignment2->values, i) != IPSET_EITHER) {
return false;
}
}
}
/* If we make it through all of that, the two assignments are equal. */
return true;
}
void
ipset_assignment_cut(struct ipset_assignment *assignment,
ipset_variable var)
{
if (var < cork_array_size(&assignment->values)) {
assignment->values.size = var;
}
}
void
ipset_assignment_clear(struct ipset_assignment *assignment)
{
ipset_assignment_cut(assignment, 0);
}
enum ipset_tribool
ipset_assignment_get(struct ipset_assignment *assignment, ipset_variable var)
{
if (var < cork_array_size(&assignment->values)) {
/* If the requested variable is in the range of the values
* array, return whatever is stored there. */
return cork_array_at(&assignment->values, var);
} else {
/* Variables htat aren't in the values array are always EITHER. */
return IPSET_EITHER;
}
}
void
ipset_assignment_set(struct ipset_assignment *assignment,
ipset_variable var, enum ipset_tribool value)
{
/* Ensure that the vector is big enough to hold this variable
* assignment, inserting new EITHERs if needed. */
if (var >= cork_array_size(&assignment->values)) {
unsigned int old_len = cork_array_size(&assignment->values);
/* Expand the array. */
cork_array_ensure_size(&assignment->values, var+1);
assignment->values.size = var+1;
/* Fill in EITHERs in the newly allocated elements. */
if (var != old_len) {
unsigned int i;
for (i = old_len; i < var; i++) {
cork_array_at(&assignment->values, i) = IPSET_EITHER;
}
}
}
/* Assign the desired value. */
cork_array_at(&assignment->values, var) = value;
}
@@ -0,0 +1,467 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2013, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <stdio.h>
#include <string.h>
#include <libcork/core.h>
#include "ipset/bdd/nodes.h"
#include "ipset/bits.h"
#include "ipset/logging.h"
void
ipset_node_fprint(FILE *stream, struct ipset_node *node)
{
fprintf(stream,
"nonterminal(x%u? " IPSET_NODE_ID_FORMAT
": " IPSET_NODE_ID_FORMAT ")",
node->variable,
IPSET_NODE_ID_VALUES(node->high),
IPSET_NODE_ID_VALUES(node->low));
}
static cork_hash
ipset_node_hash(void *user_data, const void *key)
{
const struct ipset_node *node = key;
/* Hash of "ipset_node" */
cork_hash hash = 0xf3b7dc44;
hash = cork_hash_variable(hash, node->variable);
hash = cork_hash_variable(hash, node->low);
hash = cork_hash_variable(hash, node->high);
return hash;
}
static bool
ipset_node_equals(void *user_data, const void *key1, const void *key2)
{
const struct ipset_node *node1 = key1;
const struct ipset_node *node2 = key2;
if (node1 == node2) {
return true;
}
return
(node1->variable == node2->variable) &&
(node1->low == node2->low) &&
(node1->high == node2->high);
}
/* The free list in an ipset_node_cache is represented by a
* singly-linked list of indices into the chunk array. Since the
* ipset_node instance is unused for nodes in the free list, we reuse
* the refcount field to store the "next" index. */
#define IPSET_NULL_INDEX ((ipset_variable) -1)
struct ipset_node_cache *
ipset_node_cache_new()
{
struct ipset_node_cache *cache = cork_new(struct ipset_node_cache);
cork_array_init(&cache->chunks);
cache->largest_index = 0;
cache->free_list = IPSET_NULL_INDEX;
cache->node_cache = cork_hash_table_new(0, 0);
cork_hash_table_set_hash
(cache->node_cache, (cork_hash_f) ipset_node_hash);
cork_hash_table_set_equals
(cache->node_cache, (cork_equals_f) ipset_node_equals);
return cache;
}
void
ipset_node_cache_free(struct ipset_node_cache *cache)
{
size_t i;
for (i = 0; i < cork_array_size(&cache->chunks); i++) {
free(cork_array_at(&cache->chunks, i));
}
cork_array_done(&cache->chunks);
cork_hash_table_free(cache->node_cache);
free(cache);
}
/**
* Returns the index of a new ipset_node instance.
*/
static ipset_value
ipset_node_cache_alloc_node(struct ipset_node_cache *cache)
{
if (cache->free_list == IPSET_NULL_INDEX) {
/* Nothing in the free list; need to allocate a new node. */
ipset_value next_index = cache->largest_index++;
ipset_value chunk_index = next_index >> IPSET_BDD_NODE_CACHE_BIT_SIZE;
if (chunk_index >= cork_array_size(&cache->chunks)) {
/* We've filled up all of the existing chunks, and need to
* create a new one. */
DEBUG(" (allocating chunk %zu)",
cork_array_size(&cache->chunks));
struct ipset_node *new_chunk = cork_calloc
(IPSET_BDD_NODE_CACHE_SIZE, sizeof(struct ipset_node));
cork_array_append(&cache->chunks, new_chunk);
}
return next_index;
} else {
/* Reuse a recently freed node. */
ipset_value next_index = cache->free_list;
struct ipset_node *node =
ipset_node_cache_get_nonterminal_by_index(cache, next_index);
cache->free_list = node->refcount;
return next_index;
}
}
ipset_node_id
ipset_node_incref(struct ipset_node_cache *cache, ipset_node_id node_id)
{
if (ipset_node_get_type(node_id) == IPSET_NONTERMINAL_NODE) {
struct ipset_node *node =
ipset_node_cache_get_nonterminal(cache, node_id);
DEBUG(" [incref " IPSET_NODE_ID_FORMAT "]",
IPSET_NODE_ID_VALUES(node_id));
node->refcount++;
}
return node_id;
}
void
ipset_node_decref(struct ipset_node_cache *cache, ipset_node_id node_id)
{
if (ipset_node_get_type(node_id) == IPSET_NONTERMINAL_NODE) {
struct ipset_node *node =
ipset_node_cache_get_nonterminal(cache, node_id);
DEBUG(" [decref " IPSET_NODE_ID_FORMAT "]",
IPSET_NODE_ID_VALUES(node_id));
if (--node->refcount == 0) {
DEBUG(" [free " IPSET_NODE_ID_FORMAT "]",
IPSET_NODE_ID_VALUES(node_id));
ipset_node_decref(cache, node->low);
ipset_node_decref(cache, node->high);
cork_hash_table_delete(cache->node_cache, node, NULL, NULL);
/* Add the node to the free list */
node->refcount = cache->free_list;
cache->free_list = ipset_nonterminal_value(node_id);
}
}
}
bool
ipset_node_cache_nodes_equal(const struct ipset_node_cache *cache1,
ipset_node_id node_id1,
const struct ipset_node_cache *cache2,
ipset_node_id node_id2)
{
struct ipset_node *node1;
struct ipset_node *node2;
if (ipset_node_get_type(node_id1) != ipset_node_get_type(node_id2)) {
return false;
}
if (ipset_node_get_type(node_id1) == IPSET_TERMINAL_NODE) {
return node_id1 == node_id2;
}
node1 = ipset_node_cache_get_nonterminal(cache1, node_id1);
node2 = ipset_node_cache_get_nonterminal(cache2, node_id2);
return
(node1->variable == node2->variable) &&
ipset_node_cache_nodes_equal(cache1, node1->low, cache2, node2->low) &&
ipset_node_cache_nodes_equal(cache1, node1->high, cache2, node2->high);
}
ipset_node_id
ipset_node_cache_nonterminal(struct ipset_node_cache *cache,
ipset_variable variable,
ipset_node_id low, ipset_node_id high)
{
/* Don't allow any nonterminals whose low and high subtrees are the
* same, since the nonterminal would be redundant. */
if (CORK_UNLIKELY(low == high)) {
DEBUG(" [ SKIP nonterminal(x%u? "
IPSET_NODE_ID_FORMAT ": " IPSET_NODE_ID_FORMAT ")]",
variable, IPSET_NODE_ID_VALUES(high), IPSET_NODE_ID_VALUES(low));
ipset_node_decref(cache, high);
return low;
}
/* Check to see if there's already a nonterminal with these contents
* in the cache. */
DEBUG(" [search nonterminal(x%u? "
IPSET_NODE_ID_FORMAT ": " IPSET_NODE_ID_FORMAT ")]",
variable, IPSET_NODE_ID_VALUES(high), IPSET_NODE_ID_VALUES(low));
struct ipset_node search_node;
search_node.variable = variable;
search_node.low = low;
search_node.high = high;
bool is_new;
struct cork_hash_table_entry *entry =
cork_hash_table_get_or_create
(cache->node_cache, &search_node, &is_new);
if (!is_new) {
/* There's already a node with these contents, so return its ID. */
ipset_node_id node_id = (uintptr_t) entry->value;
DEBUG(" [reuse " IPSET_NODE_ID_FORMAT "]",
IPSET_NODE_ID_VALUES(node_id));
ipset_node_incref(cache, node_id);
ipset_node_decref(cache, low);
ipset_node_decref(cache, high);
return node_id;
} else {
/* This node doesn't exist yet. Allocate a permanent copy of
* the node, add it to the cache, and then return its ID. */
ipset_value new_index = ipset_node_cache_alloc_node(cache);
ipset_node_id new_node_id = ipset_nonterminal_node_id(new_index);
struct ipset_node *real_node =
ipset_node_cache_get_nonterminal_by_index(cache, new_index);
real_node->refcount = 1;
real_node->variable = variable;
real_node->low = low;
real_node->high = high;
entry->key = real_node;
entry->value = (void *) (uintptr_t) new_node_id;
DEBUG(" [new " IPSET_NODE_ID_FORMAT "]",
IPSET_NODE_ID_VALUES(new_node_id));
return new_node_id;
}
}
bool
ipset_bool_array_assignment(const void *user_data, ipset_variable variable)
{
const bool *bool_array = (const bool *) user_data;
return bool_array[variable];
}
bool
ipset_bit_array_assignment(const void *user_data, ipset_variable variable)
{
return IPSET_BIT_GET(user_data, variable);
}
ipset_value
ipset_node_evaluate(const struct ipset_node_cache *cache, ipset_node_id node_id,
ipset_assignment_func assignment, const void *user_data)
{
ipset_node_id curr_node_id = node_id;
DEBUG("Evaluating BDD node " IPSET_NODE_ID_FORMAT,
IPSET_NODE_ID_VALUES(node_id));
/* As long as the current node is a nonterminal, we have to check
* the value of the current variable. */
while (ipset_node_get_type(curr_node_id) == IPSET_NONTERMINAL_NODE) {
/* We have to look up this variable in the assignment. */
struct ipset_node *node =
ipset_node_cache_get_nonterminal(cache, curr_node_id);
bool this_value = assignment(user_data, node->variable);
DEBUG("[%3u] Nonterminal " IPSET_NODE_ID_FORMAT,
node->variable, IPSET_NODE_ID_VALUES(curr_node_id));
DEBUG("[%3u] x%u = %s",
node->variable, node->variable, this_value? "TRUE": "FALSE");
if (this_value) {
/* This node's variable is true in the assignment vector, so
* trace down the high subtree. */
curr_node_id = node->high;
} else {
/* This node's variable is false in the assignment vector,
* so trace down the low subtree. */
curr_node_id = node->low;
}
}
/* Once we find a terminal node, we've got the final result. */
DEBUG("Evaluated result is %u", ipset_terminal_value(curr_node_id));
return ipset_terminal_value(curr_node_id);
}
/* A “fake” BDD node given by an assignment. */
struct ipset_fake_node {
ipset_variable current_var;
ipset_variable var_count;
ipset_assignment_func assignment;
const void *user_data;
ipset_value value;
};
/* A fake BDD node representing the terminal 0 value. */
static struct ipset_fake_node fake_terminal_0 = { 0, 0, NULL, 0, 0 };
/* We set elements in a map using the if-then-else (ITE) operator:
*
* new_set = new_element? new_value: old_set
*
* The below is a straight copy of the standard trinary APPLY from the BDD
* literature, but without the caching of the results. And also with the
* wrinkle that the F argument to ITE (i.e., new_element) is given by an
* assignment, and not by a BDD node. (This lets us skip constructing the BDD
* for the assignment, saving us a few cycles.)
*/
static ipset_node_id
ipset_apply_ite(struct ipset_node_cache *cache, struct ipset_fake_node *f,
ipset_value g, ipset_node_id h)
{
ipset_node_id h_low;
ipset_node_id h_high;
ipset_node_id result_low;
ipset_node_id result_high;
/* If F is a terminal, then we're in one of the following two
* cases:
*
* 1? G: H == G
* 0? G: H == H
*/
if (f->current_var == f->var_count) {
ipset_node_id result;
DEBUG("[%3u] F is terminal (value %u)", f->current_var, f->value);
if (f->value == 0) {
DEBUG("[%3u] 0? " IPSET_NODE_ID_FORMAT ": " IPSET_NODE_ID_FORMAT
" = " IPSET_NODE_ID_FORMAT,
f->current_var,
IPSET_NODE_ID_VALUES(ipset_terminal_node_id(g)),
IPSET_NODE_ID_VALUES(h), IPSET_NODE_ID_VALUES(h));
result = ipset_node_incref(cache, h);
} else {
result = ipset_terminal_node_id(g);
DEBUG("[%3u] 1? " IPSET_NODE_ID_FORMAT ": " IPSET_NODE_ID_FORMAT
" = " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(result),
IPSET_NODE_ID_VALUES(h), IPSET_NODE_ID_VALUES(result));
}
return result;
}
/* F? G: G == G */
if (h == ipset_terminal_node_id(g)) {
DEBUG("[%3u] F? " IPSET_NODE_ID_FORMAT ": " IPSET_NODE_ID_FORMAT
" = " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(h),
IPSET_NODE_ID_VALUES(h), IPSET_NODE_ID_VALUES(h));
return h;
}
/* From here to the end of the function, we know that F is a
* nonterminal. */
DEBUG("[%3u] F is nonterminal", f->current_var);
/* We're going to do two recursive calls, a “low” one and a “high” one. For
* each nonterminal that has the minimum variable number, we use its low and
* high pointers in the respective recursive call. For all other
* nonterminals, and for all terminals, we use the operand itself. */
if (ipset_node_get_type(h) == IPSET_NONTERMINAL_NODE) {
struct ipset_node *h_node =
ipset_node_cache_get_nonterminal(cache, h);
DEBUG("[%3u] H is nonterminal (variable %u)",
f->current_var, h_node->variable);
if (h_node->variable < f->current_var) {
/* var(F) > var(H), so we only recurse down the H branches. */
DEBUG("[%3u] Recursing only down H", f->current_var);
DEBUG("[%3u] Recursing high", f->current_var);
result_high = ipset_apply_ite(cache, f, g, h_node->high);
DEBUG("[%3u] Back from high recursion", f->current_var);
DEBUG("[%3u] Recursing low", f->current_var);
result_low = ipset_apply_ite(cache, f, g, h_node->low);
DEBUG("[%3u] Back from low recursion", f->current_var);
return ipset_node_cache_nonterminal
(cache, h_node->variable, result_low, result_high);
} else if (h_node->variable == f->current_var) {
/* var(F) == var(H), so we recurse down both branches. */
DEBUG("[%3u] Recursing down both F and H", f->current_var);
h_low = h_node->low;
h_high = h_node->high;
} else {
/* var(F) < var(H), so we only recurse down the F branches. */
DEBUG("[%3u] Recursing only down F", f->current_var);
h_low = h;
h_high = h;
}
} else {
/* H in nonterminal, so we only recurse down the F branches. */
DEBUG("[%3u] H is terminal (value %u)",
f->current_var, ipset_terminal_value(h));
DEBUG("[%3u] Recursing only down F", f->current_var);
h_low = h;
h_high = h;
}
/* F is a “fake” nonterminal node, since it comes from our assignment. One
* of its branches will be the 0 terminal, and the other will be the fake
* nonterminal for the next variable in the assignment. (Which one is low
* and which one is high depends on the value of the current variable in the
* assignment.) */
if (f->assignment(f->user_data, f->current_var)) {
/* The current variable is set in F. The low branch is terminal 0; the
* high branch is the next variable in F. */
DEBUG("[%3u] x[%u] is set", f->current_var, f->current_var);
DEBUG("[%3u] Recursing high", f->current_var);
f->current_var++;
result_high = ipset_apply_ite(cache, f, g, h_high);
f->current_var--;
DEBUG("[%3u] Back from high recursion: " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(result_high));
DEBUG("[%3u] Recursing low", f->current_var);
fake_terminal_0.current_var = f->var_count;
fake_terminal_0.var_count = f->var_count;
result_low = ipset_apply_ite(cache, &fake_terminal_0, g, h_low);
DEBUG("[%3u] Back from low recursion: " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(result_low));
} else {
/* The current variable is NOT set in F. The high branch is terminal 0;
* the low branch is the next variable in F. */
DEBUG("[%3u] x[%u] is NOT set", f->current_var, f->current_var);
DEBUG("[%3u] Recursing high", f->current_var);
fake_terminal_0.current_var = f->var_count;
fake_terminal_0.var_count = f->var_count;
result_high = ipset_apply_ite(cache, &fake_terminal_0, g, h_high);
DEBUG("[%3u] Back from high recursion: " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(result_high));
DEBUG("[%3u] Recursing low", f->current_var);
f->current_var++;
result_low = ipset_apply_ite(cache, f, g, h_low);
f->current_var--;
DEBUG("[%3u] Back from low recursion: " IPSET_NODE_ID_FORMAT,
f->current_var, IPSET_NODE_ID_VALUES(result_low));
}
return ipset_node_cache_nonterminal
(cache, f->current_var, result_low, result_high);
}
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 var_count, ipset_value value)
{
struct ipset_fake_node f = { 0, var_count, assignment, user_data, 1 };
DEBUG("Inserting new element");
return ipset_apply_ite(cache, &f, value, node);
}
@@ -0,0 +1,129 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-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/logging.h"
/**
* Add the given node ID to the node stack, and trace down from it
* until we find a terminal node. Assign values to the variables for
* each nonterminal that encounter along the way. We check low edges
* first, so each new variable we encounter will be assigned FALSE.
* (The high edges will be checked eventually by a call to the
* ipset_bdd_iterator_advance() function.)
*/
static void
add_node(struct ipset_bdd_iterator *iterator, ipset_node_id node_id)
{
/* Keep tracing down low edges until we reach a terminal. */
while (ipset_node_get_type(node_id) == IPSET_NONTERMINAL_NODE) {
/* Add this nonterminal node to the stack, and trace down
* further into the tree. We check low edges first, so set the
* node's variable to FALSE in the assignment. */
struct ipset_node *node =
ipset_node_cache_get_nonterminal(iterator->cache, node_id);
cork_array_append(&iterator->stack, node_id);
ipset_assignment_set(iterator->assignment, node->variable, false);
node_id = node->low;
}
/* Once we find a terminal node, save it away in the iterator result
* and return. */
iterator->value = ipset_terminal_value(node_id);
}
struct ipset_bdd_iterator *
ipset_node_iterate(struct ipset_node_cache *cache, ipset_node_id root)
{
/* First allocate the iterator itself, and all of its contained
* fields. */
struct ipset_bdd_iterator *iterator =
cork_new(struct ipset_bdd_iterator);
iterator->finished = false;
iterator->cache = cache;
cork_array_init(&iterator->stack);
iterator->assignment = ipset_assignment_new();
/* Then add the root node to the iterator, tracing down until we
* find the first terminal node. */
add_node(iterator, root);
return iterator;
}
void
ipset_bdd_iterator_free(struct ipset_bdd_iterator *iterator)
{
cork_array_done(&iterator->stack);
ipset_assignment_free(iterator->assignment);
free(iterator);
}
void
ipset_bdd_iterator_advance(struct ipset_bdd_iterator *iterator)
{
/* If we're already at the end of the iterator, don't do anything. */
if (CORK_UNLIKELY(iterator->finished)) {
return;
}
/* We look at the last node in the stack. If it's currently
* assigned a false value, then we track down its true branch. If
* it's got a true branch, then we pop it off and check the next to
* last node. */
DEBUG("Advancing BDD iterator");
while (cork_array_size(&iterator->stack) > 0) {
ipset_node_id last_node_id =
cork_array_at
(&iterator->stack, cork_array_size(&iterator->stack) - 1);
struct ipset_node *last_node =
ipset_node_cache_get_nonterminal(iterator->cache, last_node_id);
enum ipset_tribool current_value =
ipset_assignment_get(iterator->assignment, last_node->variable);
/* The current value can't be EITHER, because we definitely
* assign a TRUE or FALSE to the variables of the nodes that we
* encounter. */
if (current_value == IPSET_TRUE) {
/* We've checked both outgoing edges for this node, so pop
* it off and look at its parent. */
iterator->stack.size--;
/* Before continuing, reset this node's variable to
* indeterminate in the assignment. */
ipset_assignment_set
(iterator->assignment, last_node->variable, IPSET_EITHER);
} else {
/* We've checked this node's low edge, but not its high
* edge. Set the variable to TRUE in the assignment, and
* add the high edge's node to the node stack. */
ipset_assignment_set
(iterator->assignment, last_node->variable, IPSET_TRUE);
add_node(iterator, last_node->high);
return;
}
}
/* If we fall through then we ran out of nodes to check. That means
* the iterator is done! */
iterator->finished = true;
}
@@ -0,0 +1,138 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <string.h>
#include <libcork/core.h>
#include "ipset/bdd/nodes.h"
#include "ipset/bits.h"
#include "ipset/logging.h"
static void
initialize(struct ipset_expanded_assignment *exp,
const struct ipset_assignment *assignment,
ipset_variable var_count)
{
/* First loop through all of the variables in the assignment vector,
* making sure not to go further than the caller requested. */
ipset_variable last_assignment = cork_array_size(&assignment->values);
if (var_count < last_assignment) {
last_assignment = var_count;
}
ipset_variable var;
for (var = 0; var < last_assignment; var++) {
enum ipset_tribool curr_value =
cork_array_at(&assignment->values, var);
if (curr_value == IPSET_EITHER) {
/* If this variable is EITHER, start it off as FALSE, and
* add it to the eithers list. */
DEBUG("Variable %u is EITHER", var);
IPSET_BIT_SET(exp->values.buf, var, false);
cork_array_append(&exp->eithers, var);
} else {
/* Otherwise set the variable to the same value in the
* expanded assignment as it is in the non-expanded one. */
DEBUG("Variable %u is %s", var, curr_value? "true": "false");
IPSET_BIT_SET(exp->values.buf, var, curr_value);
}
}
/* If the caller requested more variables than there are in the
* assignment vector, add them to the eithers list. */
for (var = last_assignment; var < var_count; var++) {
DEBUG("Variable %u is implicitly EITHER", var);
cork_array_append(&exp->eithers, var);
}
}
struct ipset_expanded_assignment *
ipset_assignment_expand(const struct ipset_assignment *assignment,
ipset_variable var_count)
{
/* First allocate the iterator itself, and all of its contained
* fields. */
struct ipset_expanded_assignment *exp;
unsigned int values_size = (var_count / 8) + ((var_count % 8) != 0);
exp = cork_new(struct ipset_expanded_assignment);
exp->finished = false;
cork_buffer_init(&exp->values);
cork_buffer_ensure_size(&exp->values, values_size);
memset(exp->values.buf, 0, values_size);
cork_array_init(&exp->eithers);
/* Then initialize the values and eithers fields. */
initialize(exp, assignment, var_count);
return exp;
}
void
ipset_expanded_assignment_free(struct ipset_expanded_assignment *exp)
{
if (exp == NULL) {
return;
}
cork_buffer_done(&exp->values);
cork_array_done(&exp->eithers);
free(exp);
}
void
ipset_expanded_assignment_advance(struct ipset_expanded_assignment *exp)
{
/* If we're already at the end of the iterator, don't do anything. */
if (CORK_UNLIKELY(exp->finished)) {
return;
}
DEBUG("Advancing iterator");
/* Look at the last EITHER bit in the assignment. If it's 0, then
* set it to 1 and return. Otherwise we set it to 0 and carry up to
* the previous indeterminate bit. */
size_t i;
for (i = cork_array_size(&exp->eithers); i > 0; i--) {
size_t idx = i - 1;
ipset_variable either_var = cork_array_at(&exp->eithers, idx);
DEBUG("Checking EITHER variable %u", either_var);
if (IPSET_BIT_GET(exp->values.buf, either_var)) {
/* This variable is currently true, so set it back to false
* and carry. */
DEBUG(" Variable %u is true, changing to false and carrying",
either_var);
IPSET_BIT_SET(exp->values.buf, either_var, false);
} else {
/* This variable is currently false, so set it to true and
* return. */
DEBUG(" Variable %u is false, changing to true",
either_var);
IPSET_BIT_SET(exp->values.buf, either_var, true);
return;
}
}
/* If we fall through then we've made it through all of the expanded
* assignments. */
exp->finished = true;
}
@@ -0,0 +1,83 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2013, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <libcork/core.h>
#include <libcork/ds.h>
#include "ipset/bdd/nodes.h"
#include "ipset/logging.h"
size_t
ipset_node_reachable_count(const struct ipset_node_cache *cache,
ipset_node_id node)
{
/* Create a set to track when we've visited a given node. */
struct cork_hash_table *visited = cork_pointer_hash_table_new(0, 0);
/* And a queue of nodes to check. */
cork_array(ipset_node_id) queue;
cork_array_init(&queue);
if (ipset_node_get_type(node) == IPSET_NONTERMINAL_NODE) {
DEBUG("Adding node %u to queue", node);
cork_array_append(&queue, node);
}
/* And somewhere to store the result. */
size_t node_count = 0;
/* Check each node in turn. */
while (!cork_array_is_empty(&queue)) {
ipset_node_id curr = cork_array_at(&queue, --queue.size);
/* We don't have to do anything if this node is already in the
* visited set. */
if (cork_hash_table_get(visited, (void *) (uintptr_t) curr) == NULL) {
DEBUG("Visiting node %u for the first time", curr);
/* Add the node to the visited set. */
cork_hash_table_put
(visited, (void *) (uintptr_t) curr,
(void *) (uintptr_t) true, NULL, NULL, NULL);
/* Increase the node count. */
node_count++;
/* And add the node's nonterminal children to the visit
* queue. */
struct ipset_node *node =
ipset_node_cache_get_nonterminal(cache, curr);
if (ipset_node_get_type(node->low) == IPSET_NONTERMINAL_NODE) {
DEBUG("Adding node %u to queue", node->low);
cork_array_append(&queue, node->low);
}
if (ipset_node_get_type(node->high) == IPSET_NONTERMINAL_NODE) {
DEBUG("Adding node %u to queue", node->high);
cork_array_append(&queue, node->high);
}
}
}
/* Return the result, freeing everything before we go. */
cork_hash_table_free(visited);
cork_array_done(&queue);
return node_count;
}
size_t
ipset_node_memory_size(const struct ipset_node_cache *cache,
ipset_node_id node)
{
return ipset_node_reachable_count(cache, node) * sizeof(struct ipset_node);
}
+350
View File
@@ -0,0 +1,350 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2013, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <libcork/core.h>
#include <libcork/ds.h>
#include <libcork/helpers/errors.h>
#include "ipset/bdd/nodes.h"
#include "ipset/errors.h"
#include "ipset/logging.h"
static const char MAGIC_NUMBER[] = "IP set";
static const size_t MAGIC_NUMBER_LENGTH = sizeof(MAGIC_NUMBER) - 1;
/**
* On disk, we use a different node ID scheme than we do in memory.
* Terminal node IDs are non-negative, and are equal to the terminal
* value. Nonterminal node IDs are negative, starting with -1.
* Nonterminal -1 appears first on disk, then nonterminal -2, and so on.
*/
typedef int serialized_id;
/**
* Sets a libcork error based on the contents of errno.
*/
static void
create_errno_error(FILE *stream)
{
if (ferror(stream)) {
cork_error_set(IPSET_ERROR, IPSET_IO_ERROR, "%s", strerror(errno));
} else {
cork_unknown_error();
}
}
/**
* Read in a big-endian uint8 from a stream. If we can't read the
* integer for some reason, return an error.
*/
static int
read_uint8(FILE *stream, uint8_t *dest)
{
size_t num_read = fread(dest, sizeof(uint8_t), 1, stream);
if (num_read != 1) {
create_errno_error(stream);
return -1;
}
/* for a byte, we don't need to endian-swap */
return 0;
}
/**
* Read in a big-endian uint16 from a stream. If we can't read the
* integer for some reason, return an error.
*/
static uint16_t
read_uint16(FILE *stream, uint16_t *dest)
{
size_t num_read = fread(dest, sizeof(uint16_t), 1, stream);
if (num_read != 1) {
create_errno_error(stream);
return -1;
}
CORK_UINT16_BIG_TO_HOST_IN_PLACE(*dest);
return 0;
}
/**
* Read in a big-endian uint32 from a stream. If we can't read the
* integer for some reason, return an error.
*/
static uint32_t
read_uint32(FILE *stream, uint32_t *dest)
{
size_t num_read = fread(dest, sizeof(uint32_t), 1, stream);
if (num_read != 1) {
create_errno_error(stream);
return -1;
}
CORK_UINT32_BIG_TO_HOST_IN_PLACE(*dest);
return 0;
}
/**
* Read in a big-endian uint64 from a stream. If we can't read the
* integer for some reason, return an error.
*/
static uint64_t
read_uint64(FILE *stream, uint64_t *dest)
{
size_t num_read = fread(dest, sizeof(uint64_t), 1, stream);
if (num_read != 1) {
create_errno_error(stream);
return -1;
}
CORK_UINT64_BIG_TO_HOST_IN_PLACE(*dest);
return 0;
}
/**
* A helper function that verifies that we've read exactly as many bytes
* as we should, returning an error otherwise.
*/
static int
verify_cap(size_t bytes_read, size_t cap)
{
if (bytes_read < cap) {
/* There's extra data at the end of the stream. */
cork_error_set
(IPSET_ERROR, IPSET_PARSE_ERROR,
"Malformed set: extra data at end of stream.");
return -1;
} else if (bytes_read > cap) {
/* We read more data than we were supposed to. */
cork_error_set
(IPSET_ERROR, IPSET_PARSE_ERROR,
"Malformed set: read too much data.");
return -1;
}
return 0;
}
/**
* A helper function for reading a version 1 BDD stream.
*/
static ipset_node_id
load_v1(FILE *stream, struct ipset_node_cache *cache)
{
DEBUG("Stream contains v1 IP set");
ipset_node_id result;
struct cork_hash_table *cache_ids = cork_pointer_hash_table_new(0, 0);
/* We've already read in the magic number and version. Next should
* be the length of the encoded set. */
uint64_t length;
DEBUG("Reading encoded length");
ei_check(read_uint64(stream, &length));
/* The length includes the magic number, version number, and the
* length field itself. Remove those to get the cap on the
* remaining stream. */
size_t bytes_read = 0;
size_t cap = length -
MAGIC_NUMBER_LENGTH -
sizeof(uint16_t) -
sizeof(uint64_t);
DEBUG("Length cap is %zu bytes.", cap);
/* Read in the number of nonterminals. */
uint32_t nonterminal_count;
DEBUG("Reading number of nonterminals");
ei_check(read_uint32(stream, &nonterminal_count));
bytes_read += sizeof(uint32_t);
/* If there are no nonterminals, then there's only a single terminal
* left to read. */
if (nonterminal_count == 0) {
uint32_t value;
DEBUG("Reading single terminal value");
ei_check(read_uint32(stream, &value));
bytes_read += sizeof(uint32_t);
/* We should have reached the end of the encoded set. */
ei_check(verify_cap(bytes_read, cap));
/* Create a terminal node for this value and return it. */
cork_hash_table_free(cache_ids);
return ipset_terminal_node_id(value);
}
/* Otherwise, read in each nonterminal. We need to keep track of a
* mapping between each nonterminal's ID in the stream (which are
* number consecutively from -1), and its ID in the node cache
* (which could be anything). */
size_t i;
for (i = 0; i < nonterminal_count; i++) {
serialized_id serialized_id = -(i+1);
/* Each serialized node consists of a variable index, a low
* pointer, and a high pointer. */
uint8_t variable;
ei_check(read_uint8(stream, &variable));
bytes_read += sizeof(uint8_t);
int32_t low;
ei_check(read_uint32(stream, (uint32_t *) &low));
bytes_read += sizeof(int32_t);
int32_t high;
ei_check(read_uint32(stream, (uint32_t *) &high));
bytes_read += sizeof(int32_t);
DEBUG("Read serialized node %d = (x%d? %" PRId32 ": %" PRId32 ")",
serialized_id, variable, high, low);
/* Turn the low pointer into a node ID. If the pointer is >= 0,
* it's a terminal value. Otherwise, its a nonterminal ID,
* indexing into the serialized nonterminal array.*/
ipset_node_id low_id;
if (low >= 0) {
low_id = ipset_terminal_node_id(low);
} else {
/* The file format guarantees that any node reference points
* to a node earlier in the serialized array. That means we
* can assume that cache_ids has already been filled in for
* this node. */
low_id = (ipset_node_id) (uintptr_t)
cork_hash_table_get(cache_ids, (void *) (intptr_t) low);
DEBUG(" Serialized ID %" PRId32 " is internal ID %u",
low, low_id);
}
/* Do the same for the high pointer. */
ipset_node_id high_id;
if (high >= 0) {
high_id = ipset_terminal_node_id(high);
} else {
/* The file format guarantees that any node reference points
* to a node earlier in the serialized array. That means we
* can assume that cache_ids has already been filled in for
* this node. */
high_id = (ipset_node_id) (uintptr_t)
cork_hash_table_get(cache_ids, (void *) (intptr_t) high);
DEBUG(" Serialized ID %" PRId32 " is internal ID %u",
high, high_id);
}
/* Create a nonterminal node in the node cache. */
result = ipset_node_cache_nonterminal
(cache, variable, low_id, high_id);
DEBUG("Internal node %u = nonterminal(x%d? %u: %u)",
result, (int) variable, high_id, low_id);
/* Remember the internal node ID for this new node, in case any
* later serialized nodes point to it. */
cork_hash_table_put
(cache_ids, (void *) (intptr_t) serialized_id,
(void *) (uintptr_t) result, NULL, NULL, NULL);
}
/* We should have reached the end of the encoded set. */
ei_check(verify_cap(bytes_read, cap));
/* The last node is the nonterminal for the entire set. */
cork_hash_table_free(cache_ids);
return result;
error:
/* If there's an error, clean up the objects that we've created
* before returning. */
cork_hash_table_free(cache_ids);
return 0;
}
ipset_node_id
ipset_node_cache_load(FILE *stream, struct ipset_node_cache *cache)
{
size_t bytes_read;
/* First, read in the magic number from the stream to ensure that
* this is an IP set. */
uint8_t magic[MAGIC_NUMBER_LENGTH];
DEBUG("Reading IP set magic number");
bytes_read = fread(magic, 1, MAGIC_NUMBER_LENGTH, stream);
if (ferror(stream)) {
create_errno_error(stream);
return 0;
}
if (bytes_read != MAGIC_NUMBER_LENGTH) {
/* We reached EOF before reading the entire magic number. */
cork_error_set
(IPSET_ERROR, IPSET_PARSE_ERROR,
"Unexpected end of file");
return 0;
}
if (memcmp(magic, MAGIC_NUMBER, MAGIC_NUMBER_LENGTH) != 0) {
/* The magic number doesn't match, so this isn't a BDD. */
cork_error_set
(IPSET_ERROR, IPSET_PARSE_ERROR,
"Magic number doesn't match; this isn't an IP set.");
return 0;
}
/* Read in the version number and dispatch to the right reading
* function. */
uint16_t version;
DEBUG("Reading IP set version");
xi_check(0, read_uint16(stream, &version));
switch (version) {
case 0x0001:
return load_v1(stream, cache);
default:
/* We don't know how to read this version number. */
cork_error_set
(IPSET_ERROR, IPSET_PARSE_ERROR,
"Unknown version number %" PRIu16, version);
return 0;
}
}
+557
View File
@@ -0,0 +1,557 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2013, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <libcork/core.h>
#include <libcork/helpers/errors.h>
#include "ipset/bdd/nodes.h"
#include "ipset/logging.h"
/*-----------------------------------------------------------------------
* Generic saving logic
*/
/**
* On disk, we use a different node ID scheme than we do in memory.
* Terminal node IDs are non-negative, and are equal to the terminal
* value. Nonterminal node IDs are negative, starting with -1.
* Nonterminal -1 appears first on disk, then nonterminal -2, and so
* on.
*/
typedef int serialized_id;
/* forward declaration */
struct save_data;
/**
* A callback that outputs any necessary header. Should return an int
* status code indicating whether the write was successful.
*/
typedef int
(*write_header_func)(struct save_data *save_data,
struct ipset_node_cache *cache,
ipset_node_id root);
/**
* A callback that outputs any necessary footer. Should return an int
* status code indicating whether the write was successful.
*/
typedef int
(*write_footer_func)(struct save_data *save_data,
struct ipset_node_cache *cache,
ipset_node_id root);
/**
* A callback that actually outputs a terminal node to disk. Should
* return an int status code indicating whether the write was successful.
*/
typedef int
(*write_terminal_func)(struct save_data *save_data,
ipset_value terminal_value);
/**
* A callback that actually outputs a nonterminal node to disk.
* Should return an int status code indicating whether the write was
* successful.
*/
typedef int
(*write_nonterminal_func)(struct save_data *save_data,
serialized_id serialized_node,
ipset_variable variable,
serialized_id serialized_low,
serialized_id serialized_high);
/**
* A helper struct containing all of the persistent data items needed
* during the execution of a save.
*/
struct save_data {
/* The node cache that we're saving nodes from. */
struct ipset_node_cache *cache;
/* The output stream to save the data to. */
struct cork_stream_consumer *stream;
/* The cache of serialized IDs for any nonterminals that we've
* encountered so far. */
struct cork_hash_table *serialized_ids;
/* The serialized ID to use for the next nonterminal that we
* encounter. */
serialized_id next_serialized_id;
/* The callback used to write the file header to the stream. */
write_header_func write_header;
/* The callback used to write the file footer to the stream. */
write_footer_func write_footer;
/* The callback used to write terminals to the stream. */
write_terminal_func write_terminal;
/* The callback used to write nonterminals to the stream. */
write_nonterminal_func write_nonterminal;
/* A pointer to any additional data needed by the callbacks. */
void *user_data;
};
/**
* A helper function for ipset_node_save(). Outputs a nonterminal
* node in a BDD tree, if we haven't done so already. Ensures that
* the children of the nonterminal are output before the nonterminal
* is. Returns the serialized ID of this node.
*/
static int
save_visit_node(struct save_data *save_data,
ipset_node_id node_id, serialized_id *dest)
{
/* Check whether we've already serialized this node. */
struct cork_hash_table_entry *entry;
bool is_new;
entry = cork_hash_table_get_or_create
(save_data->serialized_ids, (void *) (uintptr_t) node_id, &is_new);
if (!is_new) {
*dest = (intptr_t) entry->value;
return 0;
} else {
if (ipset_node_get_type(node_id) == IPSET_TERMINAL_NODE) {
/* For terminals, there isn't really anything to do — we
* just output the terminal node and use its value as the
* serialized ID. */
ipset_value value = ipset_terminal_value(node_id);
DEBUG("Writing terminal(%d)", value);
rii_check(save_data->write_terminal(save_data, value));
entry->value = (void *) (intptr_t) value;
*dest = value;
return 0;
} else {
/* For nonterminals, we drill down into the node's children
* first, then output the nonterminal node. */
struct ipset_node *node =
ipset_node_cache_get_nonterminal(save_data->cache, node_id);
DEBUG("Visiting node %u nonterminal(x%u? %u: %u)",
node_id, node->variable, node->high, node->low);
/* Output the node's nonterminal children before we output
* the node itself. */
serialized_id serialized_low;
serialized_id serialized_high;
rii_check(save_visit_node(save_data, node->low, &serialized_low));
rii_check(save_visit_node(save_data, node->high, &serialized_high));
/* Output the nonterminal */
serialized_id result = save_data->next_serialized_id--;
DEBUG("Writing node %u as serialized node %d = (x%u? %d: %d)",
node_id, result,
node->variable, serialized_low, serialized_high);
entry->value = (void *) (intptr_t) result;
*dest = result;
return save_data->write_nonterminal
(save_data, result, node->variable,
serialized_low, serialized_high);
}
}
}
static int
save_bdd(struct save_data *save_data,
struct ipset_node_cache *cache, ipset_node_id root)
{
/* First, output the file header. */
DEBUG("Writing file header");
rii_check(save_data->write_header(save_data, cache, root));
/* The serialized node IDs are different than the in-memory node
* IDs. This means that, for our nonterminal nodes, we need a
* mapping from internal node ID to serialized node ID. */
DEBUG("Creating file caches");
save_data->serialized_ids = cork_pointer_hash_table_new(0, 0);
save_data->next_serialized_id = -1;
/* Trace down through the BDD tree, outputting each terminal and
* nonterminal node as they're encountered. */
DEBUG("Writing nodes");
serialized_id last_serialized_id;
ei_check(save_visit_node(save_data, root, &last_serialized_id));
/* Finally, output the file footer and cleanup. */
DEBUG("Writing file footer");
ei_check(save_data->write_footer(save_data, cache, root));
DEBUG("Freeing file caches");
cork_hash_table_free(save_data->serialized_ids);
return 0;
error:
/* If there's an error, clean up the objects that we've created
* before returning. */
cork_hash_table_free(save_data->serialized_ids);
return -1;
}
/*-----------------------------------------------------------------------
* Helper functions
*/
/**
* Write a NUL-terminated string to a stream. If we can't write the
* string for some reason, return an error.
*/
static int
write_string(struct cork_stream_consumer *stream, const char *str)
{
size_t len = strlen(str);
return cork_stream_consumer_data(stream, str, len, false);
}
/**
* Write a big-endian uint8 to a stream. If we can't write the
* integer for some reason, return an error.
*/
static int
write_uint8(struct cork_stream_consumer *stream, uint8_t val)
{
/* for a byte, we don't need to endian-swap */
return cork_stream_consumer_data(stream, &val, sizeof(uint8_t), false);
}
/**
* Write a big-endian uint16 to a stream. If we can't write the
* integer for some reason, return an error.
*/
static int
write_uint16(struct cork_stream_consumer *stream, uint16_t val)
{
CORK_UINT16_HOST_TO_BIG_IN_PLACE(val);
return cork_stream_consumer_data(stream, &val, sizeof(uint16_t), false);
}
/**
* Write a big-endian uint32 to a stream. If we can't write the
* integer for some reason, return an error.
*/
static int
write_uint32(struct cork_stream_consumer *stream, uint32_t val)
{
CORK_UINT32_HOST_TO_BIG_IN_PLACE(val);
return cork_stream_consumer_data(stream, &val, sizeof(uint32_t), false);
}
/**
* Write a big-endian uint64 to a stream. If we can't write the
* integer for some reason, return an error.
*/
static int
write_uint64(struct cork_stream_consumer *stream, uint64_t val)
{
CORK_UINT64_HOST_TO_BIG_IN_PLACE(val);
return cork_stream_consumer_data(stream, &val, sizeof(uint64_t), false);
}
/*-----------------------------------------------------------------------
* V1 BDD file
*/
static const char MAGIC_NUMBER[] = "IP set";
static const size_t MAGIC_NUMBER_LENGTH = sizeof(MAGIC_NUMBER) - 1;
static int
write_header_v1(struct save_data *save_data,
struct ipset_node_cache *cache, ipset_node_id root)
{
/* Output the magic number for an IP set, and the file format
* version that we're going to write. */
rii_check(cork_stream_consumer_data(save_data->stream, NULL, 0, true));
rii_check(write_string(save_data->stream, MAGIC_NUMBER));
rii_check(write_uint16(save_data->stream, 0x0001));
/* Determine how many reachable nodes there are, to calculate the
* size of the set. */
size_t nonterminal_count = ipset_node_reachable_count(cache, root);
size_t set_size =
MAGIC_NUMBER_LENGTH + /* magic number */
sizeof(uint16_t) + /* version number */
sizeof(uint64_t) + /* length of set */
sizeof(uint32_t) + /* number of nonterminals */
(nonterminal_count * /* for each nonterminal: */
(sizeof(uint8_t) + /* variable number */
sizeof(uint32_t) + /* low pointer */
sizeof(uint32_t) /* high pointer */
));
/* If the root is a terminal, we need to add 4 bytes to the set
* size, for storing the terminal value. */
if (ipset_node_get_type(root) == IPSET_TERMINAL_NODE) {
set_size += sizeof(uint32_t);
}
rii_check(write_uint64(save_data->stream, set_size));
rii_check(write_uint32(save_data->stream, nonterminal_count));
return 0;
}
static int
write_footer_v1(struct save_data *save_data,
struct ipset_node_cache *cache, ipset_node_id root)
{
/* If the root is a terminal node, then we output the terminal value
* in place of the (nonexistent) list of nonterminal nodes. */
if (ipset_node_get_type(root) == IPSET_TERMINAL_NODE) {
ipset_value value = ipset_terminal_value(root);
return write_uint32(save_data->stream, value);
}
return 0;
}
static int
write_terminal_v1(struct save_data *save_data, ipset_value terminal_value)
{
/* We don't have to write anything out for a terminal in a V1 file,
* since the terminal's value will be encoded into the node ID
* wherever it's used. */
return 0;
}
static int
write_nonterminal_v1(struct save_data *save_data,
serialized_id serialized_node,
ipset_variable variable,
serialized_id serialized_low,
serialized_id serialized_high)
{
rii_check(write_uint8(save_data->stream, variable));
rii_check(write_uint32(save_data->stream, serialized_low));
rii_check(write_uint32(save_data->stream, serialized_high));
return 0;
}
int
ipset_node_cache_save(struct cork_stream_consumer *stream, struct ipset_node_cache *cache,
ipset_node_id node)
{
struct save_data save_data;
save_data.cache = cache;
save_data.stream = stream;
save_data.write_header = write_header_v1;
save_data.write_footer = write_footer_v1;
save_data.write_terminal = write_terminal_v1;
save_data.write_nonterminal = write_nonterminal_v1;
return save_bdd(&save_data, cache, node);
}
/*-----------------------------------------------------------------------
* GraphViz dot file
*/
static const char *GRAPHVIZ_HEADER =
"strict digraph bdd {\n";
static const char *GRAPHVIZ_FOOTER =
"}\n";
struct dot_data {
/* The terminal value to leave out of the dot file. This should be
* the default value of the set or map. */
ipset_value default_value;
/* A scratch buffer */
struct cork_buffer scratch;
};
static int
write_header_dot(struct save_data *save_data,
struct ipset_node_cache *cache, ipset_node_id root)
{
/* Output the opening clause of the GraphViz script. */
rii_check(cork_stream_consumer_data(save_data->stream, NULL, 0, true));
return write_string(save_data->stream, GRAPHVIZ_HEADER);
}
static int
write_footer_dot(struct save_data *save_data,
struct ipset_node_cache *cache, ipset_node_id root)
{
/* Output the closing clause of the GraphViz script. */
return write_string(save_data->stream, GRAPHVIZ_FOOTER);
}
static int
write_terminal_dot(struct save_data *save_data, ipset_value terminal_value)
{
struct dot_data *dot_data = save_data->user_data;
/* If this terminal has the default value, skip it. */
if (terminal_value == dot_data->default_value) {
return 0;
}
/* Output a node for the terminal value. */
cork_buffer_printf
(&dot_data->scratch,
" t%d [shape=box, label=%d];\n",
terminal_value, terminal_value);
return write_string(save_data->stream, dot_data->scratch.buf);
}
static int
write_nonterminal_dot(struct save_data *save_data,
serialized_id serialized_node,
ipset_variable variable,
serialized_id serialized_low,
serialized_id serialized_high)
{
struct dot_data *dot_data = save_data->user_data;
/* Include a node for the nonterminal value. */
cork_buffer_printf
(&dot_data->scratch,
" n%d [shape=circle,label=%u];\n",
(-serialized_node), variable);
/* Include an edge for the low pointer. */
if (serialized_low < 0) {
/* The low pointer is a nonterminal. */
cork_buffer_append_printf
(&dot_data->scratch,
" n%d -> n%d",
(-serialized_node), (-serialized_low));
} else {
/* The low pointer is a terminal. */
ipset_value low_value = (ipset_value) serialized_low;
if (low_value == dot_data->default_value) {
/* The terminal is the default value, so instead of a real
* terminal, connect this pointer to a dummy circle node. */
cork_buffer_append_printf
(&dot_data->scratch,
" low%d [shape=circle,label=\"\"]\n"
" n%d -> low%d",
(-serialized_node), (-serialized_node), (-serialized_node));
} else {
/* The terminal isn't a default, so go ahead and output it. */
cork_buffer_append_printf
(&dot_data->scratch,
" n%d -> t%d",
(-serialized_node), serialized_low);
}
}
cork_buffer_append_printf
(&dot_data->scratch, " [style=dashed,color=red]\n");
/* Include an edge for the high pointer. */
if (serialized_high < 0) {
/* The high pointer is a nonterminal. */
cork_buffer_append_printf
(&dot_data->scratch,
" n%d -> n%d",
(-serialized_node), (-serialized_high));
} else {
/* The high pointer is a terminal. */
ipset_value high_value = (ipset_value) serialized_high;
if (high_value == dot_data->default_value) {
/* The terminal is the default value, so instead of a real
* terminal, connect this pointer to a dummy circle node. */
cork_buffer_append_printf
(&dot_data->scratch,
" high%d "
"[shape=circle,"
"fixedsize=true,"
"height=0.25,"
"width=0.25,"
"label=\"\"]\n"
" n%d -> high%d",
(-serialized_node), (-serialized_node), (-serialized_node));
} else {
/* The terminal isn't a default, so go ahead and output it. */
cork_buffer_append_printf
(&dot_data->scratch,
" n%d -> t%d",
(-serialized_node), serialized_high);
}
}
cork_buffer_append_printf
(&dot_data->scratch, " [style=solid,color=black]\n");
/* Output the clauses to the stream. */
return write_string(save_data->stream, dot_data->scratch.buf);
}
int
ipset_node_cache_save_dot(struct cork_stream_consumer *stream,
struct ipset_node_cache *cache, ipset_node_id node)
{
struct dot_data dot_data = {
0, /* default value */
{NULL, 0, 0}
};
struct save_data save_data;
save_data.cache = cache;
save_data.stream = stream;
save_data.write_header = write_header_dot;
save_data.write_footer = write_footer_dot;
save_data.write_terminal = write_terminal_dot;
save_data.write_nonterminal = write_nonterminal_dot;
save_data.user_data = &dot_data;
return save_bdd(&save_data, cache, node);
}
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------
# Copyright © 2015, RedJack, LLC.
# All rights reserved.
#
# Please see the COPYING file in this distribution for license details.
# ----------------------------------------------------------------------
#-----------------------------------------------------------------------
# Library, with options to build both shared and static versions
function(target_add_static_libraries TARGET_NAME LIBRARIES LOCAL_LIBRARIES)
foreach(lib ${LIBRARIES})
string(REPLACE "-" "_" lib ${lib})
string(TOUPPER ${lib} upperlib)
target_link_libraries(
${TARGET_NAME}
${${upperlib}_STATIC_LDFLAGS}
)
endforeach(lib)
foreach(lib ${LOCAL_LIBRARIES})
target_link_libraries(${TARGET_NAME} ${lib})
endforeach(lib)
endfunction(target_add_static_libraries)
set_property(GLOBAL PROPERTY ALL_LOCAL_LIBRARIES "")
function(add_c_library __TARGET_NAME)
set(options)
set(one_args OUTPUT_NAME PKGCONFIG_NAME VERSION)
set(multi_args LIBRARIES LOCAL_LIBRARIES SOURCES)
cmake_parse_arguments(_ "${options}" "${one_args}" "${multi_args}" ${ARGN})
if (__VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$")
set(__VERSION_CURRENT "${CMAKE_MATCH_1}")
set(__VERSION_REVISION "${CMAKE_MATCH_2}")
set(__VERSION_AGE "${CMAKE_MATCH_3}")
else (__VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$")
message(FATAL_ERROR "Invalid library version number: ${__VERSION}")
endif (__VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$")
math(EXPR __SOVERSION "${__VERSION_CURRENT} - ${__VERSION_AGE}")
get_property(ALL_LOCAL_LIBRARIES GLOBAL PROPERTY ALL_LOCAL_LIBRARIES)
list(APPEND ALL_LOCAL_LIBRARIES ${__TARGET_NAME})
set_property(GLOBAL PROPERTY ALL_LOCAL_LIBRARIES "${ALL_LOCAL_LIBRARIES}")
include_directories(
${PROJECT_SOURCE_DIR}/include
${PROJECT_BINARY_DIR}/include
)
add_library(${__TARGET_NAME} STATIC ${__SOURCES})
set_target_properties(
${__TARGET_NAME} PROPERTIES
OUTPUT_NAME ${__OUTPUT_NAME}
CLEAN_DIRECT_OUTPUT 1
)
target_include_directories(
${__TARGET_NAME} PUBLIC
${CMAKE_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/include
)
target_add_static_libraries(
${__TARGET_NAME}
"${__LIBRARIES}"
"${__LOCAL_LIBRARIES}"
)
endfunction(add_c_library)
+21
View File
@@ -0,0 +1,21 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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/ipset.h"
int
ipset_init_library()
{
return 0;
}
@@ -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 */
@@ -0,0 +1,30 @@
# This file is part of libasyncns.
#
# Copyright 2005-2008 Lennart Poettering
#
# libasyncns is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 2.1 of the
# License, or (at your option) any later version.
#
# libasyncns is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with libasyncns. If not, see
# <http://www.gnu.org/licenses/>.
noinst_LTLIBRARIES = libipset.la
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
bdd/reachable.c bdd/read.c bdd/write.c
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
map/storage.c
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
set/iterator.c set/storage.c
libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src}
libipset_la_LDFLAGS = -static
Whitespace-only changes.
@@ -0,0 +1,50 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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/ipset.h"
void
ipmap_init(struct ip_map *map, int default_value)
{
/* The map starts empty, so every value assignment should yield the
* default. */
map->cache = ipset_node_cache_new();
map->default_bdd = ipset_terminal_node_id(default_value);
map->map_bdd = map->default_bdd;
}
struct ip_map *
ipmap_new(int default_value)
{
struct ip_map *result = cork_new(struct ip_map);
ipmap_init(result, default_value);
return result;
}
void
ipmap_done(struct ip_map *map)
{
ipset_node_decref(map->cache, map->map_bdd);
ipset_node_cache_free(map->cache);
}
void
ipmap_free(struct ip_map *map)
{
ipmap_done(map);
free(map);
}
@@ -0,0 +1,88 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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
IPMAP_NAME(bit_for_var)(ipset_variable var)
{
return (var - 1);
}
/**
* An assignment function that can be used to evaluate an IP map BDD.
*/
static bool
IPMAP_NAME(assignment)(const void *addr, ipset_variable var)
{
if (var == 0) {
return IP_DISCRIMINATOR_VALUE;
} else {
unsigned int bit = IPMAP_NAME(bit_for_var)(var);
return IPSET_BIT_GET(addr, bit);
}
}
int
IPMAP_NAME(get)(struct ip_map *map, CORK_IP *elem)
{
return ipset_node_evaluate
(map->cache, map->map_bdd, IPMAP_NAME(assignment), elem);
}
void
IPMAP_NAME(set_network)(struct ip_map *map, CORK_IP *elem,
unsigned int cidr_prefix, int value)
{
/* 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;
}
ipset_node_id new_bdd =
ipset_node_insert
(map->cache, map->map_bdd,
IPMAP_NAME(assignment), elem, cidr_prefix + 1, value);
ipset_node_decref(map->cache, map->map_bdd);
map->map_bdd = new_bdd;
}
void
IPMAP_NAME(set)(struct ip_map *map, CORK_IP *elem, int value)
{
ipset_node_id new_bdd =
ipset_node_insert
(map->cache, map->map_bdd,
IPMAP_NAME(assignment), elem, IP_BIT_SIZE + 1, value);
ipset_node_decref(map->cache, map->map_bdd);
map->map_bdd = new_bdd;
}
@@ -0,0 +1,69 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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/ipset.h"
bool
ipmap_is_empty(const struct ip_map *map)
{
/* Since BDDs are unique, any map that maps all addresses to the
* default value is “empty”. */
return (map->map_bdd == map->default_bdd);
}
bool
ipmap_is_equal(const struct ip_map *map1, const struct ip_map *map2)
{
return ipset_node_cache_nodes_equal
(map1->cache, map1->map_bdd, map2->cache, map2->map_bdd);
}
size_t
ipmap_memory_size(const struct ip_map *map)
{
return ipset_node_memory_size(map->cache, map->map_bdd);
}
void
ipmap_ip_set(struct ip_map *map, struct cork_ip *addr, int value)
{
if (addr->version == 4) {
ipmap_ipv4_set(map, &addr->ip.v4, value);
} else {
ipmap_ipv6_set(map, &addr->ip.v6, value);
}
}
void
ipmap_ip_set_network(struct ip_map *map, struct cork_ip *addr,
unsigned int cidr_prefix, int value)
{
if (addr->version == 4) {
ipmap_ipv4_set_network(map, &addr->ip.v4, cidr_prefix, value);
} else {
ipmap_ipv6_set_network(map, &addr->ip.v6, cidr_prefix, value);
}
}
int
ipmap_ip_get(struct ip_map *map, struct cork_ip *addr)
{
if (addr->version == 4) {
return ipmap_ipv4_get(map, &addr->ip.v4);
} else {
return ipmap_ipv6_get(map, &addr->ip.v6);
}
}
@@ -0,0 +1,37 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
/*
* The IPv4 and IPv6 map types are basically identical, except for the
* names of the functions, and the size of the values that are being
* stored. Rather than having two mostly duplicate definitions of each
* function, we define “template functions” where anything that depends
* on the size of the IP address is defined using the following macros.
*/
/* The name of the cork_ipvX type. */
#define CORK_IP struct cork_ipv4
/* The number of bits in an IPvX address. */
#define IP_BIT_SIZE 32
/* The value of the discriminator variable for an IPvX address. */
#define IP_DISCRIMINATOR_VALUE true
/* Creates a identifier of the form “ipset_ipv4_<basename>”. */
#define IPSET_NAME(basename) ipset_ipv4_##basename
/* Creates a identifier of the form “ipmap_ipv4_<basename>”. */
#define IPMAP_NAME(basename) ipmap_ipv4_##basename
/* Now include all of the templates. */
#include "inspection-template.c.in"
@@ -0,0 +1,37 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
/*
* The IPv4 and IPv6 map types are basically identical, except for the
* names of the functions, and the size of the values that are being
* stored. Rather than having two mostly duplicate definitions of each
* function, we define “template functions” where anything that depends
* on the size of the IP address is defined using the following macros.
*/
/* The name of the cork_ipvX type. */
#define CORK_IP struct cork_ipv6
/* The number of bits in an IPvX address. */
#define IP_BIT_SIZE 128
/* The value of the discriminator variable for an IPvX address. */
#define IP_DISCRIMINATOR_VALUE false
/* Creates a identifier of the form “ipset_ipv6_<basename>”. */
#define IPSET_NAME(basename) ipset_ipv6_##basename
/* Creates a identifier of the form “ipmap_ipv6_<basename>”. */
#define IPMAP_NAME(basename) ipmap_ipv6_##basename
/* Now include all of the templates. */
#include "inspection-template.c.in"
@@ -0,0 +1,101 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libcork/core.h>
#include "ipset/bdd/nodes.h"
#include "ipset/errors.h"
#include "ipset/ipset.h"
static void
create_errno_error(FILE *stream)
{
if (ferror(stream)) {
cork_error_set(IPSET_ERROR, IPSET_IO_ERROR, "%s", strerror(errno));
} else {
cork_unknown_error();
}
}
struct file_consumer {
/* file_consumer is a subclass of cork_stream_consumer */
struct cork_stream_consumer parent;
/* the file to write the data into */
FILE *fp;
};
static int
file_consumer_data(struct cork_stream_consumer *vself,
const void *buf, size_t size, bool is_first)
{
struct file_consumer *self =
cork_container_of(vself, struct file_consumer, parent);
size_t bytes_written = fwrite(buf, 1, size, self->fp);
/* If there was an error writing to the file, then signal this to
* the producer */
if (bytes_written == size) {
return 0;
} else {
create_errno_error(self->fp);
return -1;
}
}
static int
file_consumer_eof(struct cork_stream_consumer *vself)
{
/* We don't close the file, so there's nothing special to do at
* end-of-stream. */
return 0;
}
int
ipmap_save_to_stream(struct cork_stream_consumer *stream,
const struct ip_map *map)
{
return ipset_node_cache_save(stream, map->cache, map->map_bdd);
}
int
ipmap_save(FILE *fp, const struct ip_map *map)
{
struct file_consumer stream = {
{ file_consumer_data, file_consumer_eof, NULL }, fp
};
return ipmap_save_to_stream(&stream.parent, map);
}
struct ip_map *
ipmap_load(FILE *stream)
{
struct ip_map *map;
ipset_node_id new_bdd;
/* It doesn't matter what default value we use here, because we're
* going to replace it with the default BDD we load in from the
* file. */
map = ipmap_new(0);
new_bdd = ipset_node_cache_load(stream, map->cache);
if (cork_error_occurred()) {
ipmap_free(map);
return NULL;
}
map->map_bdd = new_bdd;
return map;
}
@@ -0,0 +1,30 @@
# This file is part of libasyncns.
#
# Copyright 2005-2008 Lennart Poettering
#
# libasyncns is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 2.1 of the
# License, or (at your option) any later version.
#
# libasyncns is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with libasyncns. If not, see
# <http://www.gnu.org/licenses/>.
noinst_LTLIBRARIES = libipset.la
bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
bdd/reachable.c bdd/read.c bdd/write.c
map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
map/storage.c
set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
set/iterator.c set/storage.c
libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src}
libipset_la_LDFLAGS = -static
Whitespace-only changes.
@@ -0,0 +1,49 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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/ipset.h"
void
ipset_init(struct ip_set *set)
{
/* The set starts empty, so every value assignment should yield
* false. */
set->cache = ipset_node_cache_new();
set->set_bdd = ipset_terminal_node_id(false);
}
struct ip_set *
ipset_new(void)
{
struct ip_set *result = cork_new(struct ip_set);
ipset_init(result);
return result;
}
void
ipset_done(struct ip_set *set)
{
ipset_node_decref(set->cache, set->set_bdd);
ipset_node_cache_free(set->cache);
}
void
ipset_free(struct ip_set *set)
{
ipset_done(set);
free(set);
}
@@ -0,0 +1,130 @@
/* -*- 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;
}
@@ -0,0 +1,91 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-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/ipset.h"
bool
ipset_is_empty(const struct ip_set *set)
{
/* Since BDDs are unique, the only empty set is the “false” BDD. */
return (set->set_bdd == ipset_terminal_node_id(false));
}
bool
ipset_is_equal(const struct ip_set *set1, const struct ip_set *set2)
{
return ipset_node_cache_nodes_equal
(set1->cache, set1->set_bdd, set2->cache, set2->set_bdd);
}
size_t
ipset_memory_size(const struct ip_set *set)
{
return ipset_node_memory_size(set->cache, set->set_bdd);
}
bool
ipset_ip_add(struct ip_set *set, struct cork_ip *addr)
{
if (addr->version == 4) {
return ipset_ipv4_add(set, &addr->ip.v4);
} else {
return ipset_ipv6_add(set, &addr->ip.v6);
}
}
bool
ipset_ip_add_network(struct ip_set *set, struct cork_ip *addr,
unsigned int cidr_prefix)
{
if (addr->version == 4) {
return ipset_ipv4_add_network(set, &addr->ip.v4, cidr_prefix);
} else {
return ipset_ipv6_add_network(set, &addr->ip.v6, cidr_prefix);
}
}
bool
ipset_ip_remove(struct ip_set *set, struct cork_ip *addr)
{
if (addr->version == 4) {
return ipset_ipv4_remove(set, &addr->ip.v4);
} else {
return ipset_ipv6_remove(set, &addr->ip.v6);
}
}
bool
ipset_ip_remove_network(struct ip_set *set, struct cork_ip *addr,
unsigned int cidr_prefix)
{
if (addr->version == 4) {
return ipset_ipv4_remove_network(set, &addr->ip.v4, cidr_prefix);
} else {
return ipset_ipv6_remove_network(set, &addr->ip.v6, cidr_prefix);
}
}
bool
ipset_contains_ip(const struct ip_set *set, struct cork_ip *addr)
{
if (addr->version == 4) {
return ipset_contains_ipv4(set, &addr->ip.v4);
} else {
return ipset_contains_ipv6(set, &addr->ip.v6);
}
}
@@ -0,0 +1,37 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
/*
* The IPv4 and IPv6 set types are basically identical, except for the
* names of the functions, and the size of the values that are being
* stored. Rather than having two mostly duplicate definitions of each
* function, we define “template functions” where anything that depends
* on the size of the IP address is defined using the following macros.
*/
/* The name of the cork_ipvX type. */
#define CORK_IP struct cork_ipv4
/* The number of bits in an IPvX address. */
#define IP_BIT_SIZE 32
/* The value of the discriminator variable for an IPvX address. */
#define IP_DISCRIMINATOR_VALUE true
/* Creates a identifier of the form “ipset_ipv4_<basename>”. */
#define IPSET_NAME(basename) ipset_ipv4_##basename
/* Creates a identifier of the form “ipset_<basename>_ipv4”. */
#define IPSET_PRENAME(basename) ipset_##basename##_ipv4
/* Now include all of the templates. */
#include "inspection-template.c.in"
@@ -0,0 +1,38 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2009-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
/*
* The IPv4 and IPv6 set types are basically identical, except for the
* names of the functions, and the size of the values that are being
* stored. Rather than having two mostly duplicate definitions of
* each function, we define “template functions” where anything that
* depends on the size of the IP address is defined using the
* following macros.
*/
/* The name of the cork_ipvX type. */
#define CORK_IP struct cork_ipv6
/* The number of bits in an IPvX address. */
#define IP_BIT_SIZE 128
/* The value of the discriminator variable for an IPvX address. */
#define IP_DISCRIMINATOR_VALUE false
/* Creates a identifier of the form “ipset_ipv6_<basename>”. */
#define IPSET_NAME(basename) ipset_ipv6_##basename
/* Creates a identifier of the form “ipset_<basename>_ipv6”. */
#define IPSET_PRENAME(basename) ipset_##basename##_ipv6
/* Now include all of the templates. */
#include "inspection-template.c.in"
@@ -0,0 +1,342 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <string.h>
#include <libcork/core.h>
#include "ipset/bdd/nodes.h"
#include "ipset/bits.h"
#include "ipset/ipset.h"
#include "ipset/logging.h"
#define IPV4_BIT_SIZE 32
#define IPV6_BIT_SIZE 128
/* Forward declarations */
static void
process_assignment(struct ipset_iterator *iterator);
static void
expand_ipv6(struct ipset_iterator *iterator);
/**
* Find the highest non-EITHER bit in an assignment, starting from the
* given bit index.
*/
static unsigned int
find_last_non_either_bit(struct ipset_assignment *assignment,
unsigned int starting_bit)
{
unsigned int i;
for (i = starting_bit; i >= 1; i--) {
enum ipset_tribool value = ipset_assignment_get(assignment, i);
if (value != IPSET_EITHER) {
return i;
}
}
return 0;
}
/**
* Create a generic IP address object from the current expanded
* assignment.
*/
static void
create_ip_address(struct ipset_iterator *iterator)
{
struct cork_ip *addr = &iterator->addr;
struct ipset_expanded_assignment *exp = iterator->assignment_iterator;
/* Initialize the address to all 0 bits. */
memset(addr, 0, sizeof(struct cork_ip));
/* Check variable 0 to see if this is an IPv4 or IPv6 address. */
addr->version = IPSET_BIT_GET(exp->values.buf, 0)? 4: 6;
/* Copy bits from the expanded assignment. The number of bits to
* copy is given as the current netmask. We'll have calculated that
* already based on the non-expanded assignment. */
unsigned int i;
for (i = 0; i < iterator->cidr_prefix; i++) {
IPSET_BIT_SET(&addr->ip, i, IPSET_BIT_GET(exp->values.buf, i+1));
}
#if IPSET_DEBUG
char buf[CORK_IP_STRING_LENGTH];
cork_ip_to_raw_string(addr, buf);
DEBUG("Current IP address is %s/%u", buf, iterator->cidr_prefix);
#endif
}
/**
* Advance the BDD iterator, taking into account that some assignments
* need to be expanded twice.
*/
static void
advance_assignment(struct ipset_iterator *iterator)
{
/* Check the current state of the iterator to determine how to
* advance. */
/* In most cases, the assignment we just finished only needed to be
* expanded once. So we move on to the next assignment and process
* it. */
if (CORK_LIKELY(iterator->multiple_expansion_state ==
IPSET_ITERATOR_NORMAL))
{
ipset_bdd_iterator_advance(iterator->bdd_iterator);
process_assignment(iterator);
return;
}
/* If the assignment needs to be expanded twice, we'll do the IPv4
* expansion first. If that's what we've just finished, do the IPv6
* expansion next. */
if (iterator->multiple_expansion_state == IPSET_ITERATOR_MULTIPLE_IPV4) {
DEBUG("Expanding IPv6 second");
iterator->multiple_expansion_state = IPSET_ITERATOR_MULTIPLE_IPV6;
ipset_assignment_set
(iterator->bdd_iterator->assignment, 0, IPSET_FALSE);
expand_ipv6(iterator);
return;
}
/* If we've just finished the IPv6 expansion, then we've finished
* with this assignment. Before moving on to the next one, we have
* to reset variable 0 to EITHER (which it was before we started
* this whole mess). */
if (iterator->multiple_expansion_state == IPSET_ITERATOR_MULTIPLE_IPV6) {
DEBUG("Finished both expansions");
ipset_assignment_set
(iterator->bdd_iterator->assignment, 0, IPSET_EITHER);
ipset_bdd_iterator_advance(iterator->bdd_iterator);
process_assignment(iterator);
return;
}
}
/**
* Process the current expanded assignment in the current BDD
* assignment.
*/
static void
process_expanded_assignment(struct ipset_iterator *iterator)
{
if (iterator->assignment_iterator->finished) {
/* If there isn't anything in the expanded assignment, advance
* to the next BDD assignment. */
DEBUG("Expanded assignment is finished");
ipset_expanded_assignment_free(iterator->assignment_iterator);
iterator->assignment_iterator = NULL;
advance_assignment(iterator);
} else {
/* Otherwise, we've found a fully expanded assignment, so create
* an IP address for it and return. */
create_ip_address(iterator);
}
}
/**
* Expand the current assignment as IPv4 addresses.
*/
static void
expand_ipv4(struct ipset_iterator *iterator)
{
unsigned int last_bit;
if (iterator->summarize) {
last_bit = find_last_non_either_bit
(iterator->bdd_iterator->assignment, IPV4_BIT_SIZE);
DEBUG("Last non-either bit is %u", last_bit);
} else {
last_bit = IPV4_BIT_SIZE;
}
iterator->assignment_iterator =
ipset_assignment_expand
(iterator->bdd_iterator->assignment, last_bit + 1);
iterator->cidr_prefix = last_bit;
process_expanded_assignment(iterator);
}
/**
* Expand the current assignment as IPv4 addresses.
*/
static void
expand_ipv6(struct ipset_iterator *iterator)
{
unsigned int last_bit;
if (iterator->summarize) {
last_bit = find_last_non_either_bit
(iterator->bdd_iterator->assignment, IPV6_BIT_SIZE);
DEBUG("Last non-either bit is %u", last_bit);
} else {
last_bit = IPV6_BIT_SIZE;
}
iterator->assignment_iterator =
ipset_assignment_expand
(iterator->bdd_iterator->assignment, last_bit + 1);
iterator->cidr_prefix = last_bit;
process_expanded_assignment(iterator);
}
/**
* Process the current assignment in the BDD iterator.
*/
static void
process_assignment(struct ipset_iterator *iterator)
{
while (!iterator->bdd_iterator->finished) {
if (iterator->bdd_iterator->value == iterator->desired_value) {
/* If the BDD iterator hasn't finished, and the result of
* the function with this assignment matches what the caller
* wants, then we've found an assignment to generate IP
* addresses from.
*
* Try to expand this assignment, and process the first
* expanded assignment. We want 32 + 1 variables if the
* current address is IPv4; 128 + 1 if it's IPv6. */
DEBUG("Got a matching BDD assignment");
enum ipset_tribool address_type = ipset_assignment_get
(iterator->bdd_iterator->assignment, 0);
if (address_type == IPSET_FALSE) {
/* FALSE means IPv6*/
DEBUG("Assignment is IPv6");
iterator->multiple_expansion_state = IPSET_ITERATOR_NORMAL;
expand_ipv6(iterator);
return;
} else if (address_type == IPSET_TRUE) {
/* TRUE means IPv4*/
DEBUG("Assignment is IPv4");
iterator->multiple_expansion_state = IPSET_ITERATOR_NORMAL;
expand_ipv4(iterator);
return;
} else {
/* EITHER means that this assignment contains both IPv4
* and IPv6 addresses. Expand it as IPv4 first. */
DEBUG("Assignment is both IPv4 and IPv6");
DEBUG("Expanding IPv4 first");
iterator->multiple_expansion_state =
IPSET_ITERATOR_MULTIPLE_IPV4;
ipset_assignment_set
(iterator->bdd_iterator->assignment, 0, IPSET_TRUE);
expand_ipv4(iterator);
return;
}
}
/* The BDD iterator has a value, but it doesn't match the one we
* want. Advance the BDD iterator and try again. */
DEBUG("Value is %d, skipping", iterator->bdd_iterator->value);
ipset_bdd_iterator_advance(iterator->bdd_iterator);
}
/* If we fall through, then the BDD iterator has finished. That
* means there's nothing left for the set iterator. */
DEBUG("Set iterator is finished");
ipset_expanded_assignment_free(iterator->assignment_iterator);
iterator->assignment_iterator = NULL;
ipset_bdd_iterator_free(iterator->bdd_iterator);
iterator->bdd_iterator = NULL;
iterator->finished = true;
}
static struct ipset_iterator *
create_iterator(struct ip_set *set, bool desired_value, bool summarize)
{
/* First allocate the iterator itself. */
struct ipset_iterator *iterator = cork_new(struct ipset_iterator);
iterator->finished = false;
iterator->assignment_iterator = NULL;
iterator->desired_value = desired_value;
iterator->summarize = summarize;
/* Then create the iterator that returns each BDD assignment. */
DEBUG("Iterating set");
iterator->bdd_iterator = ipset_node_iterate(set->cache, set->set_bdd);
/* Then drill down from the current BDD assignment, creating an
* expanded assignment for it. */
process_assignment(iterator);
return iterator;
}
struct ipset_iterator *
ipset_iterate(struct ip_set *set, bool desired_value)
{
return create_iterator(set, desired_value, false);
}
struct ipset_iterator *
ipset_iterate_networks(struct ip_set *set, bool desired_value)
{
return create_iterator(set, desired_value, true);
}
void
ipset_iterator_free(struct ipset_iterator *iterator)
{
if (iterator->bdd_iterator != NULL) {
ipset_bdd_iterator_free(iterator->bdd_iterator);
}
if (iterator->assignment_iterator != NULL) {
ipset_expanded_assignment_free(iterator->assignment_iterator);
}
free(iterator);
}
void
ipset_iterator_advance(struct ipset_iterator *iterator)
{
/* If we're already at the end of the iterator, don't do anything. */
if (CORK_UNLIKELY(iterator->finished)) {
return;
}
/* Otherwise, advance the expanded assignment iterator to the next
* assignment, and then drill down into it. */
DEBUG("Advancing set iterator");
ipset_expanded_assignment_advance(iterator->assignment_iterator);
process_expanded_assignment(iterator);
}
@@ -0,0 +1,107 @@
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2010-2012, RedJack, LLC.
* All rights reserved.
*
* Please see the LICENSE.txt file in this distribution for license
* details.
* ----------------------------------------------------------------------
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libcork/core.h>
#include "ipset/bdd/nodes.h"
#include "ipset/errors.h"
#include "ipset/ipset.h"
static void
create_errno_error(FILE *stream)
{
if (ferror(stream)) {
cork_error_set(IPSET_ERROR, IPSET_IO_ERROR, "%s", strerror(errno));
} else {
cork_unknown_error();
}
}
struct file_consumer {
/* file_consumer is a subclass of cork_stream_consumer */
struct cork_stream_consumer parent;
/* the file to write the data into */
FILE *fp;
};
static int
file_consumer_data(struct cork_stream_consumer *vself,
const void *buf, size_t size, bool is_first)
{
struct file_consumer *self =
cork_container_of(vself, struct file_consumer, parent);
size_t bytes_written = fwrite(buf, 1, size, self->fp);
/* If there was an error writing to the file, then signal this to
* the producer */
if (bytes_written == size) {
return 0;
} else {
create_errno_error(self->fp);
return -1;
}
}
static int
file_consumer_eof(struct cork_stream_consumer *vself)
{
/* We don't close the file, so there's nothing special to do at
* end-of-stream. */
return 0;
}
int
ipset_save_to_stream(struct cork_stream_consumer *stream,
const struct ip_set *set)
{
return ipset_node_cache_save(stream, set->cache, set->set_bdd);
}
int
ipset_save(FILE *fp, const struct ip_set *set)
{
struct file_consumer stream = {
{ file_consumer_data, file_consumer_eof, NULL }, fp
};
return ipset_save_to_stream(&stream.parent, set);
}
int
ipset_save_dot(FILE *fp, const struct ip_set *set)
{
struct file_consumer stream = {
{ file_consumer_data, file_consumer_eof, NULL }, fp
};
return ipset_node_cache_save_dot(&stream.parent, set->cache, set->set_bdd);
}
struct ip_set *
ipset_load(FILE *stream)
{
struct ip_set *set;
ipset_node_id new_bdd;
set = ipset_new();
new_bdd = ipset_node_cache_load(stream, set->cache);
if (cork_error_occurred()) {
ipset_free(set);
return NULL;
}
set->set_bdd = new_bdd;
return set;
}