From e773028f9636ecc388d68dee13fbe3057513f905 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Tue, 19 Apr 2005 19:58:15 +0000 Subject: =?UTF-8?q?add=20userspace=20library=20(Jens=20G=C3=B6tze)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- userspace/libebtc/src/Makefile.am | 55 + userspace/libebtc/src/Makefile.in | 502 +++++++++ userspace/libebtc/src/ebtc.c | 2157 +++++++++++++++++++++++++++++++++++++ 3 files changed, 2714 insertions(+) create mode 100644 userspace/libebtc/src/Makefile.am create mode 100644 userspace/libebtc/src/Makefile.in create mode 100644 userspace/libebtc/src/ebtc.c (limited to 'userspace/libebtc/src') diff --git a/userspace/libebtc/src/Makefile.am b/userspace/libebtc/src/Makefile.am new file mode 100644 index 0000000..972a012 --- /dev/null +++ b/userspace/libebtc/src/Makefile.am @@ -0,0 +1,55 @@ +# +# ==[ Makefile ]================================================================ +# +# Project +# +# Library for ethernet bridge tables. +# +# +# Description +# +# Process this file with automake to create Makefile.in +# +# +# Copyright +# +# Copyright 2005 by Jens Götze +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, +# USA. +# +# +# ============================================================================== +# + + +LT_CUR = 1 +LT_REV = 0 +LT_AGE = 1 + +MAINTAINERCLEANFILES = Makefile.in + +AM_CFLAGS = @CFLAGS@ -I../include +AM_LDFLAGS = @LDFLAGS@ + +EXTRA_DIST = + +lib_LTLIBRARIES = libebtc.la + +libebtc_la_SOURCES = ebtc.c +libebtc_la_LDFLAGS = -version-info ${LT_CUR}:${LT_REV}:${LT_AGE} + + diff --git a/userspace/libebtc/src/Makefile.in b/userspace/libebtc/src/Makefile.in new file mode 100644 index 0000000..3327e83 --- /dev/null +++ b/userspace/libebtc/src/Makefile.in @@ -0,0 +1,502 @@ +# Makefile.in generated by automake 1.9.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 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@ + +# +# ==[ Makefile ]================================================================ +# +# Project +# +# Library for ethernet bridge tables. +# +# +# Description +# +# Process this file with automake to create Makefile.in +# +# +# Copyright +# +# Copyright 2005 by Jens Götze +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, +# USA. +# +# +# ============================================================================== +# + +SOURCES = $(libebtc_la_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libebtc_la_LIBADD = +am_libebtc_la_OBJECTS = ebtc.lo +libebtc_la_OBJECTS = $(am_libebtc_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libebtc_la_SOURCES) +DIST_SOURCES = $(libebtc_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +EBTC_LT_AGE = @EBTC_LT_AGE@ +EBTC_LT_CURRENT = @EBTC_LT_CURRENT@ +EBTC_LT_REVISION = @EBTC_LT_REVISION@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +LT_CUR = 1 +LT_REV = 0 +LT_AGE = 1 +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS = @CFLAGS@ -I../include +AM_LDFLAGS = @LDFLAGS@ +EXTRA_DIST = +lib_LTLIBRARIES = libebtc.la +libebtc_la_SOURCES = ebtc.c +libebtc_la_LDFLAGS = -version-info ${LT_CUR}:${LT_REV}:${LT_AGE} +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 \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: 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 +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libebtc.la: $(libebtc_la_OBJECTS) $(libebtc_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libebtc_la_LDFLAGS) $(libebtc_la_OBJECTS) $(libebtc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ebtc.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(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: uninstall-info-am uninstall-libLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags 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-exec \ + install-exec-am install-info install-info-am \ + install-libLTLIBRARIES install-man 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 uninstall uninstall-am uninstall-info-am \ + uninstall-libLTLIBRARIES + +# 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: diff --git a/userspace/libebtc/src/ebtc.c b/userspace/libebtc/src/ebtc.c new file mode 100644 index 0000000..d7b68ba --- /dev/null +++ b/userspace/libebtc/src/ebtc.c @@ -0,0 +1,2157 @@ +/* + * ==[ FILENAME: ebtc.c ]======================================================= + * + * Project + * + * Library for ethernet bridge tables. + * + * + * Description + * + * See project + * + * + * Copyright + * + * Copyright 2005 by Jens Götze + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, + * USA. + * + * + * ============================================================================= + */ + + +#include +#include +#include +#include +#include +#include + + +/* Macros */ + +#define SUCCESS 0 +#define ERR_CHAINNOTFOUND 1 +#define ERR_CHAINEXIST 2 +#define ERR_POLICYNOTFOUND 3 +#define ERR_ALLOCATEMEM 4 +#define ERR_RULENUM 5 +#define ERR_BUILTINCHAIN 6 +#define ERR_RAWSOCKET 7 +#define ERR_GETINFO 8 +#define ERR_GETENTRIES 9 +#define ERR_SETENTRIES 10 +#define ERR_SETCOUNTERS 11 +#define ERR_BADENTRY 12 +#define ERR_STDCHAINNOTALLOW 13 +#define ERR_ENTRYTARGETINVALID 14 + + +/* Types */ + +typedef struct rule_list_st rule_list_t; + +typedef struct chain_list_st chain_list_t; + +typedef struct chain2id_st chain2id_t; + + +/* Structures */ + +struct rule_list_st { + + rule_list_t *next; + + /* Payload */ + + struct ebt_entry *entry; + + struct { + + int changed; + + int offset; + + struct ebt_counter counter; + + } counter; + +}; + +struct chain_list_st { + + chain_list_t *next; + + int id; /* used for chain jump */ + + int offset; + + /* Payload */ + + int hookid; + + struct ebt_entries entries; + + struct { + + int count; + + unsigned int size; + + rule_list_t *first; + + rule_list_t *cur; + + rule_list_t *last; + + } rules; + +}; + +struct chain2id_st { + + const char name[EBT_CHAIN_MAXNAMELEN]; + + int id; + +}; + +struct ebtc_handle_st { + + /* Communication backend to kernel */ + + int fd; + + struct ebt_replace replace; + + /* Errorhandling */ + + unsigned int error_no; + + /* Cache */ + + struct { + + unsigned int num_counters; + + } cache; + + /* Payload */ + + int changed; + + struct { + + int count; + + int last_id; + + chain_list_t *first; + + chain_list_t *cur; + + chain_list_t *last; + + } chains; + +}; + + +/* Global variables */ + +static chain2id_t targets[] = { + { "ACCEPT", EBT_ACCEPT }, + { "DROP", EBT_DROP }, + { "CONTINUE", EBT_CONTINUE }, + { "RETURN", EBT_RETURN }, + { "", 0 } +}; + +static chain2id_t builtinchains[] = { + { "PREROUTING", NF_BR_PRE_ROUTING, }, + { "INPUT", NF_BR_LOCAL_IN }, + { "FORWARD", NF_BR_FORWARD }, + { "OUTPUT", NF_BR_LOCAL_OUT }, + { "POSTROUTING", NF_BR_POST_ROUTING, }, + { "BROUTING", NF_BR_BROUTING, }, + { "", 0 } +}; + +static struct { + + unsigned int id; + + char *msg; + +} error_msg[] = { + { SUCCESS, "success" }, + { ERR_CHAINNOTFOUND, "chain not found" }, + { ERR_CHAINEXIST, "chain already exist" }, + { ERR_POLICYNOTFOUND, "policy not exist" }, + { ERR_ALLOCATEMEM, "can't allocate memory" }, + { ERR_RULENUM, "rule number is out of range" }, + { ERR_BUILTINCHAIN, "delete denied this chain is a builtin chain" }, + { ERR_RAWSOCKET, "can't open raw socket" }, + { ERR_GETINFO, "can't get informations" }, + { ERR_GETENTRIES, "can't get entries" }, + { ERR_SETENTRIES, "can't set entries" }, + { ERR_SETCOUNTERS, "can't set counters" }, + { ERR_BADENTRY, "entry is not valid" }, + { ERR_STDCHAINNOTALLOW, "standard chain is not allowed" }, + { ERR_ENTRYTARGETINVALID, "target of entry is invalid" } +}; + +static struct { + + /* Errorhandling */ + + unsigned int error_no; + +} self_private; + + +static chain_list_t *find_chain (const char *chainname, + const ebtc_handle_t handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain = handle->chains.first; + + + +/* ---- CODE ---- */ + + for (; chain; chain = chain->next) { + + if (!strcmp(chain->entries.name, chainname)) + return chain; + + } + + return NULL; + +} + + +static int check_entry (const ebt_entry_t *entry) +{ + +/* ---- VAR ---- */ + + ebt_standard_target_t *std_target; + + ebt_entry_target_t *target; + + + +/* ---- CODE ---- */ + + if (!(entry->bitmask & EBT_ENTRY_OR_ENTRIES)) + return -1; + + /* Check offsets */ + + if (!entry->watchers_offset) + return -1; + + if (!entry->target_offset) + return -1; + + if (!entry->next_offset) + return -1; + + if (entry->watchers_offset > entry->target_offset) + return -1; + + if (entry->target_offset > entry->next_offset) + return -1; + + return 0; + +} + + +int ebtc_is_chain (const char *chainname, const ebtc_handle_t handle) +{ + +/* ---- CODE ---- */ + + return find_chain(chainname, handle) ? 0 : -1; + +} + + +const char *ebtc_first_chain (ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + (*handle)->chains.cur = chain = (*handle)->chains.first; + + return chain->entries.name; + +} + + +const char *ebtc_next_chain (ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + chain = (*handle)->chains.cur; + + if (!chain) + return NULL; + + (*handle)->chains.cur = chain = chain->next; + + return chain ? chain->entries.name : NULL; + +} + + +const struct ebt_entry *ebtc_first_rule (const char *chainname, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return NULL; + + } + + rule = chain->rules.cur = chain->rules.first; + + return rule ? rule->entry : NULL; + +} + + +const struct ebt_entry *ebtc_next_rule (const char *chainname, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return NULL; + + } + + if (!chain->rules.cur) + return NULL; + + rule = chain->rules.cur = chain->rules.cur->next; + + (*handle)->error_no = SUCCESS; + + return rule ? rule->entry : NULL; + +} + + +const char *ebtc_get_target (const struct ebt_entry *entry, + const ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + char *ptr; + + ebt_entry_target_t *target; + + ebt_standard_target_t *std_target; + + chain2id_t *chain2id; + + + +/* ---- CODE ---- */ + + ptr = (char *)entry; + ptr += entry->target_offset; + + target = (struct ebt_entry_target *)ptr; + + if (strcmp(target->u.name, "standard")) + return target->u.name; + + /* Convert id to ascii */ + + std_target = (ebt_standard_target_t *)target; + + for (chain2id = targets; *chain2id->name; chain2id++) { + + if (std_target->verdict == chain2id->id) + return chain2id->name; + + } + + return NULL; + +} + + +int ebtc_is_builtin (const char *chainname, const ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + chain = find_chain(chainname, *handle); + + if (!chain) + return -1; + + return chain->hookid == NF_BR_NUMHOOKS ? -1 : 0; + +} + + +int ebtc_set_policy (const char *chainname, const char *policy, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + int i; + + int id = 0; + + chain_list_t *chain = (*handle)->chains.first; + + + +/* ---- CODE ---- */ + + /* Transform policy to id */ + + for (i = 0; ; i++) { + + if (!*targets[i].name) { + + (*handle)->error_no = ERR_POLICYNOTFOUND; + + return -1; + + } + + if (!strcmp(policy, targets[i].name)) { + + id = targets[i].id; + break; + + } + + } + + /* Search chain and set policy */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + if (chain->entries.policy != id) { + + chain->entries.policy = id; + (*handle)->changed = EBTC_TRUE; + + } + + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +const char *ebtc_get_policy (const char *chainname, const ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + int i; + + chain_list_t *chain; + + chain2id_t *chain2id; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return NULL; + + } + + /* Convert id to ascii */ + + for (chain2id = targets; *chain2id->name; chain2id++) { + + if (chain->entries.policy == chain2id->id) { + + (*handle)->error_no = SUCCESS; + + return chain2id->name; + + } + + } + + return NULL; + +} + + +int ebtc_insert_entry (const char *chainname, const struct ebt_entry *entry, + unsigned int rulenum, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule_last = NULL; + + rule_list_t *rule_cur; + + rule_list_t *rule; + + unsigned int size; + + + +/* ---- CODE ---- */ + + if (check_entry(entry)) { + + (*handle)->error_no = ERR_BADENTRY; + + return -1; + + } + + /* Search for chain in chain list */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Copy entry and append to chain */ + + size = sizeof(rule_list_t) + entry->next_offset; + rule = (rule_list_t *)malloc(size); + + if (!rule) { + + (*handle)->error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + memset(rule, 0, size); + + rule->entry = (ebt_entry_t *)(rule + 1); + memcpy(rule->entry, entry, entry->next_offset); + + rule_cur = chain->rules.first; + + if (rule_cur) { + + for (; rulenum > 0 && rule_cur; rulenum--) { + + rule_last = rule_cur; + rule_cur = rule_cur->next; + + } + + if (rulenum || !rule_cur) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + if (rule_last) + rule_last->next = rule; + else + chain->rules.first = rule; + + rule->next = rule_cur; + + } else { + + if (rulenum != 0) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + chain->rules.first = chain->rules.last = rule; + + } + + chain->rules.count++; + chain->rules.size += entry->next_offset; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_replace_entry (const char *chainname, const struct ebt_entry *entry, + unsigned int rulenum, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule_last = NULL; + + rule_list_t *rule_old; + + rule_list_t *rule_new; + + unsigned int size; + + + +/* ---- CODE ---- */ + + if (check_entry(entry)) { + + (*handle)->error_no = ERR_BADENTRY; + + return -1; + + } + + /* Search for chain in chain list */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Copy entry and replace in chain */ + + size = sizeof(rule_list_t) + entry->next_offset; + rule_new = (rule_list_t *)malloc(size); + + if (!rule_new) { + + (*handle)->error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + memset(rule_new, 0, size); + + rule_new->entry = (ebt_entry_t *)(rule_new + 1); + memcpy(rule_new->entry, entry, entry->next_offset); + + rule_old = chain->rules.first; + + if (!rule_old) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + for (; rulenum > 0 && rule_old; rulenum--) { + + rule_last = rule_old; + rule_old = rule_old->next; + + } + + if (rulenum || !rule_old) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + if (rule_last) + rule_last->next = rule_new; + else + chain->rules.first = rule_new; + + rule_new->next = rule_old->next; + + if (!rule_new->next) + chain->rules.last = rule_new; + + chain->rules.size -= rule_old->entry->next_offset; + chain->rules.size += entry->next_offset; + + (*handle)->changed = EBTC_TRUE; + + /* Clean up */ + + free(rule_old); + + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_append_entry (const char *chainname, const struct ebt_entry *entry, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain = (*handle)->chains.first; + + rule_list_t *rule; + + unsigned int size; + + + +/* ---- CODE ---- */ + + if (check_entry(entry)) { + + (*handle)->error_no = ERR_BADENTRY; + + return -1; + + } + + /* Search for chain in chain list */ + + while (chain) { + + if (!strcmp(chain->entries.name, chainname)) + break; + + chain = chain->next; + + } + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Copy entry and insert into chain */ + + size = sizeof(rule_list_t) + entry->next_offset; + rule = (rule_list_t *)malloc(size); + + if (!rule) { + + (*handle)->error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + memset(rule, 0, size); + + rule->entry = (ebt_entry_t *)(rule + 1); + memcpy(rule->entry, entry, entry->next_offset); + + if (chain->rules.last) { + + chain->rules.last->next = rule; + chain->rules.last = rule; + + } else + chain->rules.first = chain->rules.last = rule; + + chain->rules.count++; + chain->rules.size += entry->next_offset; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_delete_entry (const char *chainname, unsigned int rulenum, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule_last = NULL; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Find and delete rule */ + + rule = chain->rules.first; + + if (!rule) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + for (; rulenum > 0 && rule; rulenum--) { + + rule_last = rule; + rule = rule->next; + + } + + if (rulenum || !rule) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + if (rule_last) + rule_last->next = rule->next; + else + chain->rules.first = rule->next; + + if (!rule->next) + chain->rules.last = rule_last; + + chain->rules.count--; + chain->rules.size -= rule->entry->next_offset; + + (*handle)->changed = EBTC_TRUE; + + /* Clean up */ + + free(rule); + + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_flush_entries (const char *chainname, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + rule_list_t *rule_next; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Free all rules */ + + rule = chain->rules.first; + + while (rule) { + + rule_next = rule->next; + + free(rule); + + rule = rule_next; + + } + + memset(&chain->rules, 0, sizeof(chain->rules)); + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_zero_entries (const char *chainname, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Iterate set zero in rule list */ + + rule = chain->rules.first; + + while (rule) { + + memset(&rule->counter.counter, 0, sizeof(ebt_counter_t)); + rule->counter.changed = EBTC_TRUE; + + rule = rule->next; + + } + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_rename_chain (const char *chainname_old, const char *chainname_new, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname_old, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + if (chain->hookid != NF_BR_NUMHOOKS) { + + (*handle)->error_no = ERR_BUILTINCHAIN; + + return -1; + + } + + /* Set new chainname */ + + snprintf(chain->entries.name, EBT_CHAIN_MAXNAMELEN, "%s", chainname_new); + + (*handle)->changed = EBTC_TRUE; + + return 0; + +} + + +int ebtc_create_chain (const char *chainname, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + /* Exist chain */ + + chain = find_chain(chainname, *handle); + + if (chain) { + + (*handle)->error_no = ERR_CHAINEXIST; + + return -1; + + } + + /* Allocate new chain */ + + chain = (chain_list_t *)malloc(sizeof(chain_list_t)); + + if (!chain) { + + (*handle)->error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + memset(chain, 0, sizeof(chain_list_t)); + + chain->hookid = NF_BR_NUMHOOKS; + chain->id = (*handle)->chains.last_id++; + + snprintf(chain->entries.name, EBT_CHAIN_MAXNAMELEN, "%s", chainname); + chain->entries.policy = EBT_ACCEPT; + + if ((*handle)->chains.last) { + + (*handle)->chains.last->next = chain; + (*handle)->chains.last = chain; + + } else + (*handle)->chains.last = (*handle)->chains.first = chain; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_delete_chain (const char *chainname, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain = (*handle)->chains.first; + + chain_list_t *chain_last = NULL; + + rule_list_t *rule; + + rule_list_t *rule_next; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + for (; chain; chain_last = chain, chain = chain->next) { + + if (!strcmp(chain->entries.name, chainname)) + break; + + } + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + if (chain->hookid != NF_BR_NUMHOOKS) { + + (*handle)->error_no = ERR_BUILTINCHAIN; + + return -1; + + } + + /* Free all rules */ + + rule = chain->rules.first; + + while (rule) { + + rule_next = rule->next; + + free(rule); + + rule = rule_next; + + } + + /* Remove chain from list */ + + if (chain_last) + chain_last->next = chain->next; + else + (*handle)->chains.first = chain->next; + + if (!chain->next) + (*handle)->chains.last = chain_last; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + /* Clean up */ + + free(chain); + + return 0; + +} + + +const struct ebt_counter *ebtc_read_counter (const char *chainname, + unsigned int rulenum, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return NULL; + + } + + /* Find rule */ + + rule = chain->rules.first; + + for (; rulenum > 0 && rule; rulenum--) + rule = rule->next; + + if (rulenum || !rule) { + + (*handle)->error_no = ERR_RULENUM; + + return NULL; + + } + + (*handle)->error_no = SUCCESS; + + return &rule->counter.counter; + +} + + +int ebtc_zero_counter (const char *chainname, unsigned int rulenum, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Find rule */ + + rule = chain->rules.first; + + for (; rulenum > 0 && rule; rulenum--) + rule = rule->next; + + if (rulenum || !rule) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + memset(&rule->counter.counter, 0, sizeof(ebt_counter_t)); + rule->counter.changed = EBTC_TRUE; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_set_counter (const char *chainname, unsigned int rulenum, + const struct ebt_counter *counter, ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + chain_list_t *chain; + + rule_list_t *rule; + + + +/* ---- CODE ---- */ + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + /* Find rule */ + + rule = chain->rules.first; + + for (; rulenum > 0 && rule; rulenum--) + rule = rule->next; + + if (rulenum || !rule) { + + (*handle)->error_no = ERR_RULENUM; + + return -1; + + } + + memcpy(&rule->counter.counter, counter, sizeof(ebt_counter_t)); + rule->counter.changed = EBTC_TRUE; + + (*handle)->changed = EBTC_TRUE; + (*handle)->error_no = SUCCESS; + + return 0; + +} + + +int ebtc_target_jumptochain (ebt_standard_target_t *target, char *chainname, + ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + int i; + + chain_list_t *chain; + + + +/* ---- CODE ---- */ + + /* Prepare basics of target */ + + target->target.target_size = EBTC_SIZEOF(ebt_standard_target_t); + target->target.target_size -= EBTC_SIZEOF(ebt_entry_target_t); + + snprintf(target->target.u.name, EBT_FUNCTION_MAXNAMELEN, "standard"); + + /* Check for standard targets */ + + for (i = 0; *targets[i].name; i++) { + + if (!strcmp(chainname, targets[i].name)) { + + target->verdict = targets[i].id; + + return 0; + + } + + } + + /* Check for standard targets */ + + for (i = 0; *targets[i].name; i++) { + + if (!strcmp(chainname, targets[i].name)) { + + target->verdict = targets[i].id; + + return 0; + + } + + } + + /* Find chain */ + + chain = find_chain(chainname, *handle); + + if (!chain) { + + (*handle)->error_no = ERR_CHAINNOTFOUND; + + return -1; + + } + + if (chain->hookid != NF_BR_NUMHOOKS) { + + (*handle)->error_no = ERR_STDCHAINNOTALLOW; + + return -1; + + } + + target->verdict = chain->id; + + return 0; + +} + + +ebtc_handle_t ebtc_init (const char *tablename, int options) +{ + +/* ---- VAR ---- */ + + int i; + + int optlen; + + int optname; + + int counter; + + unsigned int size; + + unsigned int entry_count; + + unsigned int rule_size; + + ebt_replace_t *replace; + + ebt_entries_t *entries; + + ebt_entry_t *entry; + + chain_list_t *chain; + + rule_list_t *rule; + + ebtc_handle_t handle; + + + +/* ---- CODE ---- */ + + /* Allocate memory for handle and initialize this object */ + + handle = (ebtc_handle_t)malloc(sizeof(struct ebtc_handle_st)); + + if (!handle) { + + self_private.error_no = ERR_ALLOCATEMEM; + + return NULL; + + } + + memset(handle, 0, sizeof(struct ebtc_handle_st)); + + handle->changed = options & EBTC_INIT_WITHFLUSH ? EBTC_TRUE : EBTC_FALSE; + replace = &handle->replace; + + /* Open raw socket */ + + handle->fd = socket(AF_INET, SOCK_RAW, PF_INET); + + if (handle->fd == -1) { + + free(handle); + + self_private.error_no = ERR_RAWSOCKET; + + return NULL; + + } + + /* Get infomations */ + + memset(replace, 0, sizeof(ebt_replace_t)); + snprintf(replace->name, EBT_TABLE_MAXNAMELEN, "%s", tablename); + + optlen = sizeof(ebt_replace_t); + optname = options & EBTC_INIT_WITHFLUSH ? EBT_SO_GET_INIT_INFO : + EBT_SO_GET_INFO; + + if (getsockopt(handle->fd, IPPROTO_IP, optname, replace, &optlen)) { + + free(handle); + + self_private.error_no = ERR_GETINFO; + + return NULL; + + } + + /* Get entries */ + + if (replace->nentries) { + + size = replace->nentries * sizeof(ebt_counter_t); + replace->counters = (ebt_counter_t *)malloc(size); + + if (!replace->counters) { + + close(handle->fd); + free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return NULL; + + } + + } else { + + size = 0; + replace->counters = NULL; + + } + + handle->cache.num_counters = replace->num_counters = replace->nentries; + replace->entries = malloc(replace->entries_size); + + if (!replace->entries) { + + if (replace->counters) + free(replace->counters); + + close(handle->fd); + free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return NULL; + + } + + optlen += replace->entries_size; + optlen += replace->num_counters * sizeof(ebt_counter_t); + optname = options & EBTC_INIT_WITHFLUSH ? EBT_SO_GET_INIT_ENTRIES : + EBT_SO_GET_ENTRIES; + + if (getsockopt(handle->fd, IPPROTO_IP, optname, replace, &optlen)) { + + close(handle->fd); + + if (replace->counters) + free(replace->counters); + + free(replace->entries); + free(handle); + + self_private.error_no = ERR_GETENTRIES; + + return NULL; + + } + + /* Split one block from kernel into lists */ + + size = replace->entries_size; + entries = (ebt_entries_t *)replace->entries; + + for (; size > 0; size -= sizeof(ebt_entries_t)) { + + /* Allocate and fill a container for chain */ + + chain = (chain_list_t *)malloc(sizeof(chain_list_t)); + + if (!chain) { + + ebtc_free(&handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return NULL; + + } + + memset(chain, 0, sizeof(chain_list_t)); + memcpy(&chain->entries, entries, sizeof(ebt_entries_t)); + + chain->hookid = NF_BR_NUMHOOKS; + chain->id = handle->chains.last_id++; + + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + + if (!strcmp(entries->name, builtinchains[i].name)) { + + chain->hookid = builtinchains[i].id; + break; + + } + + } + + if (handle->chains.last) { + + handle->chains.last->next = chain; + handle->chains.last = chain; + + } else + handle->chains.last = handle->chains.first = chain; + + handle->chains.count++; + + /* Put entries into rule list of current chain */ + + entry_count = entries->nentries; + counter = entries->counter_offset; + + entries++; + + if (entry_count) { + + entry = (ebt_entry_t *)entries; + counter = chain->entries.counter_offset; + + for (; entry_count > 0; entry_count--) { + + /* Allocate memory for rule */ + + rule_size = sizeof(rule_list_t) + entry->next_offset; + rule = (rule_list_t *)malloc(rule_size); + + if (!rule) { + + ebtc_free(&handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return NULL; + + } + + /* Initialize rule */ + + memset(rule, 0, sizeof(rule_list_t)); + + rule->counter.changed = EBTC_FALSE; + rule->counter.offset = counter; + + rule->entry = (ebt_entry_t *)(rule + 1); + memcpy(rule->entry, entry, entry->next_offset); + + chain->rules.size += entry->next_offset; + + memcpy(&rule->counter.counter, &replace->counters[counter++], + sizeof(ebt_counter_t)); + + if (chain->rules.last) { + + chain->rules.last->next = rule; + chain->rules.last = rule; + + } else + chain->rules.last = chain->rules.first = rule; + + chain->rules.count++; + + /* Jump to next entry */ + + size -= entry->next_offset; + entry = (ebt_entry_t *)((char *)entry + + entry->next_offset); + + } + + entries = (ebt_entries_t *)entry; + + } + + } + + /* Clean up */ + + if (replace->counters) { + + free(replace->counters); + replace->counters = NULL; + + } + + free(replace->entries); + replace->entries = NULL; + + handle->error_no = SUCCESS; + + return handle; + +} + + +static int precommit_standard_target (chain_list_t *chain, ebt_entry_t *entry) +{ + +/* ---- VAR ---- */ + + ebt_standard_target_t *target; + + + +/* ---- CODE ---- */ + + /* Check for standard target */ + + target = (ebt_standard_target_t *)EBTC_ADDOFFSET(entry, + entry->target_offset); + + if (strncmp(target->target.u.name, "standard", EBT_FUNCTION_MAXNAMELEN)) + return 0; + + for (; chain; chain = chain->next) { + + if (chain->id == target->verdict) { + + target->verdict = chain->offset; + + return 0; + + } + + } + + return 0; + +} + + +int ebtc_commit (ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + socklen_t optlen; + + int result; + + int fd; + + int i; + + unsigned int size; + + unsigned int size_entry; + + unsigned int size_entries = 0; + + unsigned int size_counters = 0; + + unsigned int counter_offset = 0; + + unsigned int count_entries = 0; + + chain_list_t *chain; + + rule_list_t *rule; + + ebt_replace_t *replace; + + ebt_entries_t *entries; + + ebt_entry_t *entry; + + ebt_counter_t *counters; + + ebt_counter_t *counters_back; + + + +/* ---- CODE ---- */ + + /* Check of all conditions */ + + if ((*handle)->changed == EBTC_FALSE) { + + ebtc_free(handle); + + self_private.error_no = SUCCESS; + + return 0; + + } + + /* Collect all size informations for entries */ + + for (chain = (*handle)->chains.first; chain; chain = chain->next) { + + chain->offset = size_entries; + + size_entries += sizeof(ebt_entries_t); + size_entries += chain->rules.size; + + size_counters += sizeof(ebt_counter_t) * chain->rules.count; + count_entries += chain->rules.count; + + } + + /* Allocate */ + + replace = (ebt_replace_t *)malloc(sizeof(ebt_replace_t)); + + if (!replace) { + + ebtc_free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + entries = (ebt_entries_t *)malloc(size_entries); + + if (!entries) { + + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + /* Pack all entries in a big block */ + + memcpy(replace, &(*handle)->replace, sizeof(ebt_replace_t)); + + replace->entries_size = size_entries; + replace->nentries = count_entries; + replace->entries = (char *)entries; + replace->counters = counters; + replace->num_counters = 0; + + for (chain = (*handle)->chains.first; chain; chain = chain->next) { + + /* Copy entries */ + + memcpy(entries, &chain->entries, sizeof(ebt_entries_t)); + + entries->distinguisher = 0; + entries->counter_offset = counter_offset; + entries->nentries = chain->rules.count; + + /* Is chain a hook chain? */ + + if (chain->hookid != NF_BR_NUMHOOKS) + replace->hook_entry[chain->hookid] = entries; + + /* Copy list of entries */ + + entries++; + entry = (ebt_entry_t *)entries; + + for (rule = chain->rules.first; rule; rule = rule->next) { + + size_entry = rule->entry->next_offset; + + result = precommit_standard_target((*handle)->chains.first, + rule->entry); + + if (result) { + + free(entries); + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_ENTRYTARGETINVALID; + + return -1; + + } + + memcpy(entry, rule->entry, size_entry); + entry = (ebt_entry_t *)((char *)entry + size_entry); + + } + + /* Setup for next entries */ + + counter_offset += chain->rules.count; + entries = (ebt_entries_t *)entry; + + } + + entries = (ebt_entries_t *)replace->entries; + + /* Create container for counter refresh */ + + if (size_counters > 0 && (*handle)->cache.num_counters > 0) { + + size = (*handle)->cache.num_counters * sizeof(ebt_counter_t); + replace->num_counters = (*handle)->cache.num_counters; + counters_back = replace->counters = (ebt_counter_t *)malloc(size); + + if (!counters_back) { + + free(entries); + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + } else { + + counters_back = replace->counters = NULL; + replace->num_counters = 0; + + } + + /* Submit entries to kernel */ + + fd = (*handle)->fd; + + optlen = sizeof(ebt_replace_t); + optlen += size_entries; + + if (setsockopt(fd, IPPROTO_IP, EBT_SO_SET_ENTRIES, replace, optlen)) { + + if (counters_back) + free(counters_back); + + free(entries); + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_SETENTRIES; + + return -1; + + } + + if (size_counters > 0) { + + /* Allocate memory for counters */ + + replace->counters = counters = (ebt_counter_t *)malloc(size_counters); + + if (!counters) { + + if (counters_back) + free(counters_back); + + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_ALLOCATEMEM; + + return -1; + + } + + /* Fill counters */ + + for (chain = (*handle)->chains.first; chain; chain = chain->next) { + + for (rule = chain->rules.first; rule; rule = rule->next) { + + if (rule->counter.changed == EBTC_FALSE) { + + memcpy(counters, &counters_back[rule->counter.offset], + sizeof(ebt_counter_t)); + + } else { + + memcpy(counters, &rule->counter.counter, + sizeof(ebt_counter_t)); + + } + + counters++; + + } + + } + + counters = replace->counters; + + if (counters_back) + free(counters_back); + + /* Submit counters to kernel */ + + replace->num_counters = count_entries; + replace->entries = NULL; + + optlen = sizeof(ebt_replace_t); + optlen += sizeof(ebt_counter_t) * count_entries; + + if (setsockopt(fd, IPPROTO_IP, EBT_SO_SET_COUNTERS, replace, optlen)) { + + free(counters); + free(entries); + free(replace); + ebtc_free(handle); + + self_private.error_no = ERR_SETCOUNTERS; + + return -1; + + } + + free(counters); + + } + + /* Clean up */ + + free(entries); + free(replace); + ebtc_free(handle); + + self_private.error_no = SUCCESS; + + return 0; + +} + + +void ebtc_free (ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + ebt_replace_t *replace = &(*handle)->replace; + + chain_list_t *chain = (*handle)->chains.first; + + chain_list_t *chain_next; + + rule_list_t *rule; + + rule_list_t *rule_next; + + + +/* ---- CODE ---- */ + + /* Free chain list with all rules */ + + for (; chain; chain = chain_next) { + + for (rule = chain->rules.first; rule; rule = rule_next) { + + rule_next = rule->next; + free(rule); + + } + + chain_next = chain->next; + free(chain); + + } + + /* Close gateway into the kernel */ + + close((*handle)->fd); + + /* Clean up*/ + + if (replace->counters) + free(replace->counters); + + if (replace->entries) + free(replace->entries); + + free(*handle); + + (*handle)->error_no = SUCCESS; + + return; + +} + + +const char *ebtc_strerror (const ebtc_handle_t *handle) +{ + +/* ---- VAR ---- */ + + int i; + + + +/* ---- CODE ---- */ + + if (handle) + i = (*handle)->error_no; + else + i = self_private.error_no; + + if (i > sizeof(error_msg) / sizeof(error_msg[0])) + return NULL; + + return error_msg[i].msg; + +} + + -- cgit v1.2.3