diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Makefile.am | 8 | ||||
-rw-r--r-- | include/Makefile.in | 427 | ||||
-rw-r--r-- | include/alarm.h | 33 | ||||
-rw-r--r-- | include/bitops.h | 36 | ||||
-rw-r--r-- | include/cache.h | 128 | ||||
-rw-r--r-- | include/channel.h | 124 | ||||
-rw-r--r-- | include/cidr.h | 9 | ||||
-rw-r--r-- | include/conntrack.h | 206 | ||||
-rw-r--r-- | include/conntrackd.h | 265 | ||||
-rw-r--r-- | include/date.h | 10 | ||||
-rw-r--r-- | include/debug.h | 21 | ||||
-rw-r--r-- | include/event.h | 14 | ||||
-rw-r--r-- | include/external.h | 24 | ||||
-rw-r--r-- | include/fds.h | 22 | ||||
-rw-r--r-- | include/filter.h | 55 | ||||
-rw-r--r-- | include/hash.h | 44 | ||||
-rw-r--r-- | include/internal.h | 39 | ||||
-rw-r--r-- | include/jhash.h | 146 | ||||
-rw-r--r-- | include/linux_list.h | 727 | ||||
-rw-r--r-- | include/linux_rbtree.h | 160 | ||||
-rw-r--r-- | include/local.h | 37 | ||||
-rw-r--r-- | include/log.h | 13 | ||||
-rw-r--r-- | include/mcast.h | 60 | ||||
-rw-r--r-- | include/netlink.h | 33 | ||||
-rw-r--r-- | include/network.h | 239 | ||||
-rw-r--r-- | include/origin.h | 16 | ||||
-rw-r--r-- | include/process.h | 25 | ||||
-rw-r--r-- | include/queue.h | 62 | ||||
-rw-r--r-- | include/sync.h | 28 | ||||
-rw-r--r-- | include/tcp.h | 76 | ||||
-rw-r--r-- | include/traffic_stats.h | 10 | ||||
-rw-r--r-- | include/udp.h | 64 | ||||
-rw-r--r-- | include/vector.h | 13 |
33 files changed, 3174 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..cbbca6b --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,8 @@ + +noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \ + sync.h conntrackd.h local.h udp.h tcp.h \ + debug.h log.h hash.h mcast.h conntrack.h \ + network.h filter.h queue.h vector.h cidr.h \ + traffic_stats.h netlink.h fds.h event.h bitops.h channel.h \ + process.h origin.h internal.h external.h date.h + diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..5a38ca1 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,427 @@ +# Makefile.in generated by automake 1.11 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ +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@ +target_triplet = @target@ +subdir = include +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(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)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +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@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBNETFILTER_CONNTRACK_CFLAGS = @LIBNETFILTER_CONNTRACK_CFLAGS@ +LIBNETFILTER_CONNTRACK_LIBS = @LIBNETFILTER_CONNTRACK_LIBS@ +LIBNFNETLINK_CFLAGS = @LIBNFNETLINK_CFLAGS@ +LIBNFNETLINK_LIBS = @LIBNFNETLINK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +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@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XLEX = @XLEX@ +XYACC = @XYACC@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +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@ +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@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \ + sync.h conntrackd.h local.h udp.h tcp.h \ + debug.h log.h hash.h mcast.h conntrack.h \ + network.h filter.h queue.h vector.h cidr.h \ + traffic_stats.h netlink.h fds.h event.h bitops.h channel.h \ + process.h origin.h internal.h external.h date.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(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) --gnu include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/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: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +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 $(HEADERS) +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: + $(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) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am 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 -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean 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-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +# 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/include/alarm.h b/include/alarm.h new file mode 100644 index 0000000..38aaa01 --- /dev/null +++ b/include/alarm.h @@ -0,0 +1,33 @@ +#ifndef _ALARM_H_ +#define _ALARM_H_ + +#include "linux_rbtree.h" +#include "linux_list.h" + +#include <sys/time.h> + +struct alarm_block { + struct rb_node node; + struct list_head list; + struct timeval tv; + void *data; + void (*function)(struct alarm_block *a, void *data); +}; + +void init_alarm(struct alarm_block *t, + void *data, + void (*fcn)(struct alarm_block *a, void *data)); + +void add_alarm(struct alarm_block *alarm, unsigned long sc, unsigned long usc); + +void del_alarm(struct alarm_block *alarm); + +int alarm_pending(struct alarm_block *alarm); + +struct timeval * +get_next_alarm_run(struct timeval *next_alarm); + +struct timeval * +do_alarm_run(struct timeval *next_alarm); + +#endif diff --git a/include/bitops.h b/include/bitops.h new file mode 100644 index 0000000..51f4289 --- /dev/null +++ b/include/bitops.h @@ -0,0 +1,36 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include <stdlib.h> + +static inline void set_bit_u32(int nr, u_int32_t *addr) +{ + addr[nr >> 5] |= (1UL << (nr & 31)); +} + +static inline void unset_bit_u32(int nr, u_int32_t *addr) +{ + addr[nr >> 5] &= ~(1UL << (nr & 31)); +} + +static inline int test_bit_u32(int nr, const u_int32_t *addr) +{ + return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; +} + +static inline void set_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] |= (1UL << (nr & 15)); +} + +static inline void unset_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] &= ~(1UL << (nr & 15)); +} + +static inline int test_bit_u16(int nr, const u_int16_t *addr) +{ + return ((1UL << (nr & 15)) & (addr[nr >> 4])) != 0; +} + +#endif diff --git a/include/cache.h b/include/cache.h new file mode 100644 index 0000000..28917f2 --- /dev/null +++ b/include/cache.h @@ -0,0 +1,128 @@ +#ifndef _CACHE_H_ +#define _CACHE_H_ + +#include <stdint.h> +#include <stddef.h> +#include "hash.h" +#include "date.h" + +/* cache features */ +enum { + NO_FEATURES = 0, + + TIMER_FEATURE = 0, + TIMER = (1 << TIMER_FEATURE), + + __CACHE_MAX_FEATURE +}; +#define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE + +enum { + C_OBJ_NONE = 0, /* not in the cache */ + C_OBJ_NEW, /* just added to the cache */ + C_OBJ_ALIVE, /* in the cache, alive */ + C_OBJ_DEAD /* still in the cache, but dead */ +}; + +struct cache; +struct cache_object { + struct hashtable_node hashnode; + struct nf_conntrack *ct; + struct cache *cache; + int status; + int refcnt; + long lifetime; + long lastupdate; + char data[0]; +}; + +struct cache_feature { + size_t size; + void (*add)(struct cache_object *obj, void *data); + void (*update)(struct cache_object *obj, void *data); + void (*destroy)(struct cache_object *obj, void *data); + int (*dump)(struct cache_object *obj, void *data, char *buf, int type); +}; + +extern struct cache_feature timer_feature; + +#define CACHE_MAX_NAMELEN 32 + +struct cache { + char name[CACHE_MAX_NAMELEN]; + struct hashtable *h; + + unsigned int num_features; + struct cache_feature **features; + unsigned int feature_type[CACHE_MAX_FEATURE]; + unsigned int *feature_offset; + struct cache_extra *extra; + unsigned int extra_offset; + size_t object_size; + + /* statistics */ + struct { + uint32_t active; + + uint32_t add_ok; + uint32_t del_ok; + uint32_t upd_ok; + + uint32_t add_fail; + uint32_t del_fail; + uint32_t upd_fail; + + uint32_t add_fail_enomem; + uint32_t add_fail_enospc; + uint32_t del_fail_enoent; + uint32_t upd_fail_enoent; + + uint32_t commit_ok; + uint32_t commit_fail; + + uint32_t flush; + + uint32_t objects; + } stats; +}; + +struct cache_extra { + unsigned int size; + + void (*add)(struct cache_object *obj, void *data); + void (*update)(struct cache_object *obj, void *data); + void (*destroy)(struct cache_object *obj, void *data); +}; + +struct nf_conntrack; + +struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra); +void cache_destroy(struct cache *e); + +struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct); +void cache_object_free(struct cache_object *obj); +void cache_object_get(struct cache_object *obj); +int cache_object_put(struct cache_object *obj); +void cache_object_set_status(struct cache_object *obj, int status); + +int cache_add(struct cache *c, struct cache_object *obj, int id); +void cache_update(struct cache *c, struct cache_object *obj, int id, struct nf_conntrack *ct); +struct cache_object *cache_update_force(struct cache *c, struct nf_conntrack *ct); +void cache_del(struct cache *c, struct cache_object *obj); +struct cache_object *cache_find(struct cache *c, struct nf_conntrack *ct, int *pos); +void cache_stats(const struct cache *c, int fd); +void cache_stats_extended(const struct cache *c, int fd); +struct cache_object *cache_data_get_object(struct cache *c, void *data); +void *cache_get_extra(struct cache *, void *); +void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)); +void cache_iterate_limit(struct cache *c, void *data, uint32_t from, uint32_t steps, int (*iterate)(void *data1, void *data2)); + +/* iterators */ +struct nfct_handle; + +void cache_dump(struct cache *c, int fd, int type); +void cache_commit(struct cache *c, struct nfct_handle *h, int clientfd); +void cache_flush(struct cache *c); +void cache_bulk(struct cache *c); + +#endif diff --git a/include/channel.h b/include/channel.h new file mode 100644 index 0000000..9b5fad8 --- /dev/null +++ b/include/channel.h @@ -0,0 +1,124 @@ +#ifndef _CHANNEL_H_ +#define _CHANNEL_H_ + +#include "mcast.h" +#include "udp.h" +#include "tcp.h" + +struct channel; +struct nethdr; + +enum { + CHANNEL_NONE, + CHANNEL_MCAST, + CHANNEL_UDP, + CHANNEL_TCP, + CHANNEL_MAX, +}; + +struct mcast_channel { + struct mcast_sock *client; + struct mcast_sock *server; +}; + +struct udp_channel { + struct udp_sock *client; + struct udp_sock *server; +}; + +struct tcp_channel { + struct tcp_sock *client; + struct tcp_sock *server; +}; + +#define CHANNEL_F_DEFAULT (1 << 0) +#define CHANNEL_F_BUFFERED (1 << 1) +#define CHANNEL_F_STREAM (1 << 2) +#define CHANNEL_F_ERRORS (1 << 3) +#define CHANNEL_F_MAX (1 << 4) + +union channel_type_conf { + struct mcast_conf mcast; + struct udp_conf udp; + struct tcp_conf tcp; +}; + +struct channel_conf { + int channel_type; + char channel_ifname[IFNAMSIZ]; + unsigned int channel_flags; + union channel_type_conf u; +}; + +struct nlif_handle; + +struct channel_ops { + int headersiz; + void * (*open)(void *conf); + void (*close)(void *channel); + int (*send)(void *channel, const void *data, int len); + int (*recv)(void *channel, char *buf, int len); + int (*accept)(struct channel *c); + int (*get_fd)(void *channel); + int (*isset)(struct channel *c, fd_set *readfds); + int (*accept_isset)(struct channel *c, fd_set *readfds); + void (*stats)(struct channel *c, int fd); + void (*stats_extended)(struct channel *c, int active, + struct nlif_handle *h, int fd); +}; + +struct channel_buffer; + +struct channel { + int channel_type; + int channel_ifindex; + int channel_ifmtu; + unsigned int channel_flags; + struct channel_buffer *buffer; + struct channel_ops *ops; + void *data; +}; + +int channel_init(void); +void channel_end(void); +struct channel *channel_open(struct channel_conf *conf); +void channel_close(struct channel *c); + +int channel_send(struct channel *c, const struct nethdr *net); +int channel_send_flush(struct channel *c); +int channel_recv(struct channel *c, char *buf, int size); +int channel_accept(struct channel *c); + +int channel_get_fd(struct channel *c); +int channel_accept_isset(struct channel *c, fd_set *readfds); +int channel_isset(struct channel *c, fd_set *readfds); + +void channel_stats(struct channel *c, int fd); +void channel_stats_extended(struct channel *c, int active, + struct nlif_handle *h, int fd); + +#define MULTICHANNEL_MAX 4 + +struct multichannel { + int channel_num; + struct channel *channel[MULTICHANNEL_MAX]; + struct channel *current; +}; + +struct multichannel *multichannel_open(struct channel_conf *conf, int len); +void multichannel_close(struct multichannel *m); + +int multichannel_send(struct multichannel *c, const struct nethdr *net); +int multichannel_send_flush(struct multichannel *c); +int multichannel_recv(struct multichannel *c, char *buf, int size); + +void multichannel_stats(struct multichannel *m, int fd); +void multichannel_stats_extended(struct multichannel *m, + struct nlif_handle *h, int fd); + +int multichannel_get_ifindex(struct multichannel *m, int i); +int multichannel_get_current_ifindex(struct multichannel *m); +void multichannel_set_current_channel(struct multichannel *m, int i); +void multichannel_change_current_channel(struct multichannel *m, int i); + +#endif /* _CHANNEL_H_ */ diff --git a/include/cidr.h b/include/cidr.h new file mode 100644 index 0000000..413c321 --- /dev/null +++ b/include/cidr.h @@ -0,0 +1,9 @@ +#ifndef _CIDR_H_ + +uint32_t ipv4_cidr2mask_host(uint8_t cidr); +uint32_t ipv4_cidr2mask_net(uint8_t cidr); +void ipv6_cidr2mask_host(uint8_t cidr, uint32_t *res); +void ipv6_cidr2mask_net(uint8_t cidr, uint32_t *res); +void ipv6_addr2addr_host(uint32_t *addr, uint32_t *res); + +#endif diff --git a/include/conntrack.h b/include/conntrack.h new file mode 100644 index 0000000..61e7581 --- /dev/null +++ b/include/conntrack.h @@ -0,0 +1,206 @@ +#ifndef _CONNTRACK_H +#define _CONNTRACK_H + +#include "linux_list.h" +#include <stdint.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + +#define PROGNAME "conntrack" + +#include <netinet/in.h> + +enum action { + CT_NONE = 0, + + CT_LIST_BIT = 0, + CT_LIST = (1 << CT_LIST_BIT), + + CT_CREATE_BIT = 1, + CT_CREATE = (1 << CT_CREATE_BIT), + + CT_UPDATE_BIT = 2, + CT_UPDATE = (1 << CT_UPDATE_BIT), + + CT_DELETE_BIT = 3, + CT_DELETE = (1 << CT_DELETE_BIT), + + CT_GET_BIT = 4, + CT_GET = (1 << CT_GET_BIT), + + CT_FLUSH_BIT = 5, + CT_FLUSH = (1 << CT_FLUSH_BIT), + + CT_EVENT_BIT = 6, + CT_EVENT = (1 << CT_EVENT_BIT), + + CT_VERSION_BIT = 7, + CT_VERSION = (1 << CT_VERSION_BIT), + + CT_HELP_BIT = 8, + CT_HELP = (1 << CT_HELP_BIT), + + EXP_LIST_BIT = 9, + EXP_LIST = (1 << EXP_LIST_BIT), + + EXP_CREATE_BIT = 10, + EXP_CREATE = (1 << EXP_CREATE_BIT), + + EXP_DELETE_BIT = 11, + EXP_DELETE = (1 << EXP_DELETE_BIT), + + EXP_GET_BIT = 12, + EXP_GET = (1 << EXP_GET_BIT), + + EXP_FLUSH_BIT = 13, + EXP_FLUSH = (1 << EXP_FLUSH_BIT), + + EXP_EVENT_BIT = 14, + EXP_EVENT = (1 << EXP_EVENT_BIT), + + CT_COUNT_BIT = 15, + CT_COUNT = (1 << CT_COUNT_BIT), + + EXP_COUNT_BIT = 16, + EXP_COUNT = (1 << EXP_COUNT_BIT), + + X_STATS_BIT = 17, + X_STATS = (1 << X_STATS_BIT), +}; +#define NUMBER_OF_CMD 18 + +enum options { + CT_OPT_ORIG_SRC_BIT = 0, + CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT), + + CT_OPT_ORIG_DST_BIT = 1, + CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT), + + CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST), + + CT_OPT_REPL_SRC_BIT = 2, + CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT), + + CT_OPT_REPL_DST_BIT = 3, + CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT), + + CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST), + + CT_OPT_PROTO_BIT = 4, + CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), + + CT_OPT_TUPLE_ORIG = (CT_OPT_ORIG | CT_OPT_PROTO), + CT_OPT_TUPLE_REPL = (CT_OPT_REPL | CT_OPT_PROTO), + + CT_OPT_TIMEOUT_BIT = 5, + CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), + + CT_OPT_STATUS_BIT = 6, + CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), + + CT_OPT_ZERO_BIT = 7, + CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), + + CT_OPT_EVENT_MASK_BIT = 8, + CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), + + CT_OPT_EXP_SRC_BIT = 9, + CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT), + + CT_OPT_EXP_DST_BIT = 10, + CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT), + + CT_OPT_MASK_SRC_BIT = 11, + CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), + + CT_OPT_MASK_DST_BIT = 12, + CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), + + CT_OPT_NATRANGE_BIT = 13, + CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT), + + CT_OPT_MARK_BIT = 14, + CT_OPT_MARK = (1 << CT_OPT_MARK_BIT), + + CT_OPT_ID_BIT = 15, + CT_OPT_ID = (1 << CT_OPT_ID_BIT), + + CT_OPT_FAMILY_BIT = 16, + CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT), + + CT_OPT_SRC_NAT_BIT = 17, + CT_OPT_SRC_NAT = (1 << CT_OPT_SRC_NAT_BIT), + + CT_OPT_DST_NAT_BIT = 18, + CT_OPT_DST_NAT = (1 << CT_OPT_DST_NAT_BIT), + + CT_OPT_OUTPUT_BIT = 19, + CT_OPT_OUTPUT = (1 << CT_OPT_OUTPUT_BIT), + + CT_OPT_SECMARK_BIT = 20, + CT_OPT_SECMARK = (1 << CT_OPT_SECMARK_BIT), + + CT_OPT_BUFFERSIZE_BIT = 21, + CT_OPT_BUFFERSIZE = (1 << CT_OPT_BUFFERSIZE_BIT), + + CT_OPT_MAX = CT_OPT_BUFFERSIZE_BIT +}; +#define NUMBER_OF_OPT CT_OPT_MAX+1 + +enum { + _O_XML = (1 << 0), + _O_EXT = (1 << 1), + _O_TMS = (1 << 2), + _O_ID = (1 << 3), +}; + +struct ctproto_handler { + struct list_head head; + + const char *name; + uint16_t protonum; + const char *version; + + enum ctattr_protoinfo protoinfo_attr; + + int (*parse_opts)(char c, + struct nf_conntrack *ct, + struct nf_conntrack *exptuple, + struct nf_conntrack *mask, + unsigned int *flags); + + void (*final_check)(unsigned int flags, + unsigned int command, + struct nf_conntrack *ct); + + void (*help)(void); + + struct option *opts; + + unsigned int option_offset; +}; + +enum exittype { + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, + VERSION_PROBLEM +}; + +int generic_opt_check(int options, int nops, + char *optset, const char *optflg[], + unsigned int *coupled_flags, int coupled_flags_size, + int *partial); +void exit_error(enum exittype status, const char *msg, ...); + +extern void register_proto(struct ctproto_handler *h); + +extern void register_tcp(void); +extern void register_udp(void); +extern void register_udplite(void); +extern void register_sctp(void); +extern void register_dccp(void); +extern void register_icmp(void); +extern void register_icmpv6(void); +extern void register_gre(void); +extern void register_unknown(void); + +#endif diff --git a/include/conntrackd.h b/include/conntrackd.h new file mode 100644 index 0000000..c7f33f0 --- /dev/null +++ b/include/conntrackd.h @@ -0,0 +1,265 @@ +#ifndef _CONNTRACKD_H_ +#define _CONNTRACKD_H_ + +#include "mcast.h" +#include "local.h" +#include "alarm.h" +#include "filter.h" +#include "channel.h" +#include "internal.h" + +#include <stdint.h> +#include <stdio.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> +#include <syslog.h> + +/* UNIX facilities */ +#define FLUSH_MASTER 0 /* flush kernel conntrack table */ +#define RESYNC_MASTER 1 /* resync with kernel conntrack table */ +#define DUMP_INTERNAL 16 /* dump internal cache */ +#define DUMP_EXTERNAL 17 /* dump external cache */ +#define COMMIT 18 /* commit external cache */ +#define FLUSH_CACHE 19 /* flush cache */ +#define KILL 20 /* kill conntrackd */ +#define STATS 21 /* dump statistics */ +#define SEND_BULK 22 /* send a bulk */ +#define REQUEST_DUMP 23 /* request dump */ +#define DUMP_INT_XML 24 /* dump internal cache in XML */ +#define DUMP_EXT_XML 25 /* dump external cache in XML */ +#define RESET_TIMERS 26 /* reset kernel timers */ +#define DEBUG_INFO 27 /* unused */ +#define STATS_NETWORK 28 /* extended network stats */ +#define STATS_CACHE 29 /* extended cache stats */ +#define STATS_RUNTIME 30 /* extended runtime stats */ +#define STATS_LINK 31 /* dedicated link stats */ +#define STATS_RSQUEUE 32 /* resend queue stats */ +#define FLUSH_INT_CACHE 33 /* flush internal cache */ +#define FLUSH_EXT_CACHE 34 /* flush external cache */ +#define STATS_PROCESS 35 /* child process stats */ +#define STATS_QUEUE 36 /* queue stats */ + +#define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" +#define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" +#define DEFAULT_LOGFILE "/var/log/conntrackd.log" +#define DEFAULT_STATS_LOGFILE "/var/log/conntrackd-stats.log" +#define DEFAULT_SYSLOG_FACILITY LOG_DAEMON + +/* daemon/request modes */ +#define NOT_SET 0 +#define DAEMON 1 +#define REQUEST 2 + +/* conntrackd modes */ +#define CTD_SYNC_MODE (1UL << 0) +#define CTD_STATS_MODE (1UL << 1) +#define CTD_SYNC_FTFW (1UL << 2) +#define CTD_SYNC_ALARM (1UL << 3) +#define CTD_SYNC_NOTRACK (1UL << 4) +#define CTD_POLL (1UL << 5) + +/* FILENAME_MAX is 4096 on my system, perhaps too much? */ +#ifndef FILENAME_MAXLEN +#define FILENAME_MAXLEN 256 +#endif + +union inet_address { + uint32_t ipv4; + uint32_t ipv6[4]; + uint32_t all[4]; +}; + +#define CONFIG(x) conf.x + +struct ct_conf { + char logfile[FILENAME_MAXLEN]; + int syslog_facility; + char lockfile[FILENAME_MAXLEN]; + int hashsize; /* hashtable size */ + int channel_num; + int channel_default; + int channel_type_global; + struct channel_conf channel[MULTICHANNEL_MAX]; + struct local_conf local; /* unix socket facilities */ + int nice; + int limit; + int refresh; + int cache_timeout; /* cache entries timeout */ + int commit_timeout; /* committed entries timeout */ + unsigned int purge_timeout; /* purge kernel entries timeout */ + unsigned int netlink_buffer_size; + unsigned int netlink_buffer_size_max_grown; + int nl_overrun_resync; + unsigned int flags; + int family; /* protocol family */ + unsigned int resend_queue_size; /* FTFW protocol */ + unsigned int window_size; + int poll_kernel_secs; + int filter_from_kernelspace; + int event_iterations_limit; + struct { + int error_queue_length; + } channelc; + struct { + int internal_cache_disable; + int external_cache_disable; + } sync; + struct { + int events_reliable; + } netlink; + struct { + int commit_steps; + } general; + struct { + int type; + int prio; + } sched; + struct { + char logfile[FILENAME_MAXLEN]; + int syslog_facility; + size_t buffer_size; + } stats; +}; + +#define STATE(x) st.x + +struct ct_general_state { + sigset_t block; + FILE *log; + FILE *stats_log; + struct local_server local; + struct ct_mode *mode; + struct ct_filter *us_filter; + + struct nfct_handle *event; /* event handler */ + struct nfct_filter *filter; /* event filter */ + int event_iterations_limit; + + struct nfct_handle *dump; /* dump handler */ + struct nfct_handle *resync; /* resync handler */ + struct nfct_handle *get; /* get handler */ + int get_retval; /* hackish */ + struct nfct_handle *flush; /* flusher */ + + struct alarm_block resync_alarm; + struct alarm_block polling_alarm; + + struct fds *fds; + + /* statistics */ + struct { + uint64_t bytes_orig; + uint64_t bytes_repl; + uint64_t packets_orig; + uint64_t packets_repl; + + time_t daemon_start_time; + + uint64_t nl_events_received; + uint64_t nl_events_filtered; + uint32_t nl_events_unknown_type; + uint32_t nl_catch_event_failed; + uint32_t nl_overrun; + uint32_t nl_dump_unknown_type; + uint32_t nl_kernel_table_flush; + uint32_t nl_kernel_table_resync; + + uint32_t child_process_failed; + uint32_t child_process_error_segfault; + uint32_t child_process_error_term; + + uint32_t select_failed; + uint32_t wait_failed; + + uint32_t local_read_failed; + uint32_t local_unknown_request; + + } stats; +}; + +#define STATE_SYNC(x) state.sync->x + +struct ct_sync_state { + struct external_handler *external; + + struct multichannel *channel; + struct nlif_handle *interface; + struct queue *tx_queue; + +#define COMMIT_STATE_INACTIVE 0 +#define COMMIT_STATE_MASTER 1 +#define COMMIT_STATE_RELATED 2 + + struct { + int state; + int clientfd; + struct nfct_handle *h; + struct evfd *evfd; + int current; + struct { + int ok; + int fail; + struct timeval start; + } stats; + } commit; + + struct alarm_block reset_cache_alarm; + + struct sync_mode *sync; /* sync mode */ + + /* statistics */ + struct { + uint64_t msg_rcv_malformed; + uint32_t msg_rcv_bad_version; + uint32_t msg_rcv_bad_payload; + uint32_t msg_rcv_bad_header; + uint32_t msg_rcv_bad_type; + uint32_t msg_rcv_truncated; + uint32_t msg_rcv_bad_size; + uint32_t msg_snd_malformed; + uint64_t msg_rcv_lost; + uint64_t msg_rcv_before; + } error; + + uint32_t last_seq_sent; /* last sequence number sent */ + uint32_t last_seq_recv; /* last sequence number recv */ +}; + +#define STATE_STATS(x) state.stats->x + +struct ct_stats_state { + struct cache *cache; /* internal events cache (netlink) */ +}; + +union ct_state { + struct ct_sync_state *sync; + struct ct_stats_state *stats; +}; + +extern struct ct_conf conf; +extern union ct_state state; +extern struct ct_general_state st; + +struct ct_mode { + struct internal_handler *internal; + int (*init)(void); + void (*run)(fd_set *readfds); + int (*local)(int fd, int type, void *data); + void (*kill)(void); +}; + +/* conntrackd modes */ +extern struct ct_mode sync_mode; +extern struct ct_mode stats_mode; + +#define MAX(x, y) x > y ? x : y + +/* These live in run.c */ +void killer(int foo); +int init(void); +void run(void); + +/* from read_config_yy.c */ +int +init_config(char *filename); + +#endif diff --git a/include/date.h b/include/date.h new file mode 100644 index 0000000..296b996 --- /dev/null +++ b/include/date.h @@ -0,0 +1,10 @@ +#ifndef _DATE_H_ +#define _DATE_H_ + +#include <sys/time.h> + +int do_gettimeofday(void); +void gettimeofday_cached(struct timeval *tv); +int time_cached(void); + +#endif diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..f205983 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,21 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + +#undef DEBUG_CT + +#ifdef DEBUG_CT +#define debug_ct(ct, msg) \ +({ \ + char buf[1024]; \ + nfct_snprintf(buf, 1024, ct, NFCT_T_ALL, 0, 0); \ + printf("[%s]: %s\n", msg, buf); \ +}) +#define debug printf +#else +#define debug_ct(ct, msg) do {} while (0) +#define debug(...) do {} while (0) +#endif + +#endif diff --git a/include/event.h b/include/event.h new file mode 100644 index 0000000..b6bff5a --- /dev/null +++ b/include/event.h @@ -0,0 +1,14 @@ +#ifndef _EVENT_H_ +#define _EVENT_H_ + +struct evfd *create_evfd(void); + +void destroy_evfd(struct evfd *e); + +int get_read_evfd(struct evfd *evfd); + +int write_evfd(struct evfd *evfd); + +int read_evfd(struct evfd *evfd); + +#endif diff --git a/include/external.h b/include/external.h new file mode 100644 index 0000000..938941a --- /dev/null +++ b/include/external.h @@ -0,0 +1,24 @@ +#ifndef _EXTERNAL_H_ +#define _EXTERNAL_H_ + +struct nf_conntrack; + +struct external_handler { + int (*init)(void); + void (*close)(void); + + void (*new)(struct nf_conntrack *ct); + void (*update)(struct nf_conntrack *ct); + void (*destroy)(struct nf_conntrack *ct); + + void (*dump)(int fd, int type); + void (*flush)(void); + void (*commit)(struct nfct_handle *h, int fd); + void (*stats)(int fd); + void (*stats_ext)(int fd); +}; + +extern struct external_handler external_cache; +extern struct external_handler external_inject; + +#endif diff --git a/include/fds.h b/include/fds.h new file mode 100644 index 0000000..f3728d7 --- /dev/null +++ b/include/fds.h @@ -0,0 +1,22 @@ +#ifndef _FDS_H_ +#define _FDS_H_ + +#include "linux_list.h" + +struct fds { + int maxfd; + fd_set readfds; + struct list_head list; +}; + +struct fds_item { + struct list_head head; + int fd; +}; + +struct fds *create_fds(void); +void destroy_fds(struct fds *); +int register_fd(int fd, struct fds *fds); +int unregister_fd(int fd, struct fds *fds); + +#endif diff --git a/include/filter.h b/include/filter.h new file mode 100644 index 0000000..72c2aa4 --- /dev/null +++ b/include/filter.h @@ -0,0 +1,55 @@ +#ifndef _FILTER_H_ +#define _FILTER_H_ + +#include <stdint.h> +#include <string.h> +#include <netinet/in.h> +#include <hash.h> + +enum ct_filter_type { + CT_FILTER_L4PROTO, + CT_FILTER_STATE, + CT_FILTER_ADDRESS, /* also for netmask */ + CT_FILTER_MAX +}; + +enum ct_filter_logic { + CT_FILTER_NEGATIVE = 0, + CT_FILTER_POSITIVE = 1, +}; + +struct ct_filter_ipv4_hnode { + struct hashtable_node node; + uint32_t ip; +}; + +struct ct_filter_ipv6_hnode { + struct hashtable_node node; + uint32_t ipv6[4]; +}; + +struct ct_filter_netmask_ipv4 { + uint32_t ip; + uint32_t mask; +}; + +struct ct_filter_netmask_ipv6 { + uint32_t ip[4]; + uint32_t mask[4]; +}; + +struct nf_conntrack; +struct ct_filter; + +struct ct_filter *ct_filter_create(void); +void ct_filter_destroy(struct ct_filter *filter); +int ct_filter_add_ip(struct ct_filter *filter, void *data, uint8_t family); +int ct_filter_add_netmask(struct ct_filter *filter, void *data, uint8_t family); +void ct_filter_add_proto(struct ct_filter *filter, int protonum); +void ct_filter_add_state(struct ct_filter *f, int protonum, int state); +void ct_filter_set_logic(struct ct_filter *f, + enum ct_filter_type type, + enum ct_filter_logic logic); +int ct_filter_conntrack(struct nf_conntrack *ct, int userspace); + +#endif diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 0000000..eaa9e96 --- /dev/null +++ b/include/hash.h @@ -0,0 +1,44 @@ +#ifndef _NF_SET_HASH_H_ +#define _NF_SET_HASH_H_ + +#include <unistd.h> +#include "linux_list.h" + +#include <stdint.h> + +struct hashtable; +struct hashtable_node; + +struct hashtable { + uint32_t hashsize; + uint32_t limit; + uint32_t count; + uint32_t initval; + + uint32_t (*hash)(const void *data, const struct hashtable *table); + int (*compare)(const void *data1, const void *data2); + + struct list_head members[0]; +}; + +struct hashtable_node { + struct list_head head; +}; + +struct hashtable * +hashtable_create(int hashsize, int limit, + uint32_t (*hash)(const void *data, + const struct hashtable *table), + int (*compare)(const void *data1, const void *data2)); +void hashtable_destroy(struct hashtable *h); +int hashtable_hash(const struct hashtable *table, const void *data); +struct hashtable_node *hashtable_find(const struct hashtable *table, const void *data, int id); +int hashtable_add(struct hashtable *table, struct hashtable_node *n, int id); +void hashtable_del(struct hashtable *table, struct hashtable_node *node); +int hashtable_flush(struct hashtable *table); +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data, void *n)); +int hashtable_iterate_limit(struct hashtable *table, void *data, uint32_t from, uint32_t steps, int (*iterate)(void *data1, void *n)); +unsigned int hashtable_counter(const struct hashtable *table); + +#endif diff --git a/include/internal.h b/include/internal.h new file mode 100644 index 0000000..1f11340 --- /dev/null +++ b/include/internal.h @@ -0,0 +1,39 @@ +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + +struct nf_conntrack; + +enum { + INTERNAL_F_POPULATE = (1 << 0), + INTERNAL_F_RESYNC = (1 << 1), + INTERNAL_F_MAX = (1 << 2) +}; + +struct internal_handler { + void *data; + unsigned int flags; + + int (*init)(void); + void (*close)(void); + + void (*new)(struct nf_conntrack *ct, int origin_type); + void (*update)(struct nf_conntrack *ct, int origin_type); + int (*destroy)(struct nf_conntrack *ct, int origin_type); + + void (*dump)(int fd, int type); + void (*populate)(struct nf_conntrack *ct); + void (*purge)(void); + int (*resync)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data); + void (*flush)(void); + + void (*stats)(int fd); + void (*stats_ext)(int fd); +}; + +extern struct internal_handler internal_cache; +extern struct internal_handler internal_bypass; + +#endif diff --git a/include/jhash.h b/include/jhash.h new file mode 100644 index 0000000..d164e38 --- /dev/null +++ b/include/jhash.h @@ -0,0 +1,146 @@ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +#define u32 unsigned int +#define u8 char + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(const u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/include/linux_list.h b/include/linux_list.h new file mode 100644 index 0000000..de182a4 --- /dev/null +++ b/include/linux_list.h @@ -0,0 +1,727 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include <stddef.h> + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define prefetch(x) 1 + +/* empty define to make this work in userspace -HW */ +#ifndef smp_wmb +#define smp_wmb() +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; + smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_kernel() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +#define hlist_del_rcu_init hlist_del_init + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(), but only if smp_read_barrier_depends() + * is used to prevent memory-consistency problems on Alpha CPUs. + * Regardless of the type of CPU, the list-traversal primitive + * must be guarded by rcu_read_lock(). + * + * OK, so why don't we have an hlist_for_each_entry_rcu()??? + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; + smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) + +#endif diff --git a/include/linux_rbtree.h b/include/linux_rbtree.h new file mode 100644 index 0000000..ee98891 --- /dev/null +++ b/include/linux_rbtree.h @@ -0,0 +1,160 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + + 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 + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop drammatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + Some example of insert and search follows here. The search is a plain + normal search over an ordered tree. The insert instead must be implemented + int two steps: as first thing the code must insert the element in + order as a red leaf in the tree, then the support library function + rb_insert_color() must be called. Such function will do the + not trivial work to rebalance the rbtree if necessary. + +----------------------------------------------------------------------- +static inline struct page * rb_search_page_cache(struct inode * inode, + unsigned long offset) +{ + struct rb_node * n = inode->i_rb_page_cache.rb_node; + struct page * page; + + while (n) + { + page = rb_entry(n, struct page, rb_page_cache); + + if (offset < page->offset) + n = n->rb_left; + else if (offset > page->offset) + n = n->rb_right; + else + return page; + } + return NULL; +} + +static inline struct page * __rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct rb_node ** p = &inode->i_rb_page_cache.rb_node; + struct rb_node * parent = NULL; + struct page * page; + + while (*p) + { + parent = *p; + page = rb_entry(parent, struct page, rb_page_cache); + + if (offset < page->offset) + p = &(*p)->rb_left; + else if (offset > page->offset) + p = &(*p)->rb_right; + else + return page; + } + + rb_link_node(node, parent, p); + + return NULL; +} + +static inline struct page * rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct page * ret; + if ((ret = __rb_insert_page_cache(inode, offset, node))) + goto out; + rb_insert_color(node, &inode->i_rb_page_cache); + out: + return ret; +} +----------------------------------------------------------------------- +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +#include <stdlib.h> + +struct rb_node +{ + unsigned long rb_parent_color; +#define RB_RED 0 +#define RB_BLACK 1 + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + struct rb_node *rb_node; +}; + + +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define rb_color(r) ((r)->rb_parent_color & 1) +#define rb_is_red(r) (!rb_color(r)) +#define rb_is_black(r) rb_color(r) +#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) + +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; +} +static inline void rb_set_color(struct rb_node *rb, int color) +{ + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; +} + +#define RB_ROOT { NULL, } +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) +#define RB_EMPTY_NODE(node) (rb_parent(node) == node) +#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) + +extern void rb_insert_color(struct rb_node *, struct rb_root *); +extern void rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *rb_next(struct rb_node *); +extern struct rb_node *rb_prev(struct rb_node *); +extern struct rb_node *rb_first(struct rb_root *); +extern struct rb_node *rb_last(struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent_color = (unsigned long )parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#endif /* _LINUX_RBTREE_H */ diff --git a/include/local.h b/include/local.h new file mode 100644 index 0000000..f9121b1 --- /dev/null +++ b/include/local.h @@ -0,0 +1,37 @@ +#ifndef _LOCAL_SOCKET_H_ +#define _LOCAL_SOCKET_H_ + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +struct local_conf { + int backlog; + int reuseaddr; + char path[UNIX_PATH_MAX]; +}; + +struct local_server { + int fd; + char path[UNIX_PATH_MAX]; +}; + +/* callback return values */ +#define LOCAL_RET_ERROR -1 +#define LOCAL_RET_OK 0 +#define LOCAL_RET_STOLEN 1 + +/* local server */ +int local_server_create(struct local_server *server, struct local_conf *conf); +void local_server_destroy(struct local_server *server); +int do_local_server_step(struct local_server *server, void *data, + int (*process)(int fd, void *data)); + +/* local client */ +int local_client_create(struct local_conf *conf); +void local_client_destroy(int fd); +int do_local_client_step(int fd, void (*process)(char *buf)); +int do_local_request(int, struct local_conf *,void (*step)(char *buf)); +void local_step(char *buf); + +#endif diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..f5c5b4f --- /dev/null +++ b/include/log.h @@ -0,0 +1,13 @@ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include <stdio.h> + +struct nf_conntrack; + +int init_log(void); +void dlog(int priority, const char *format, ...); +void dlog_ct(FILE *fd, struct nf_conntrack *ct, unsigned int type); +void close_log(void); + +#endif diff --git a/include/mcast.h b/include/mcast.h new file mode 100644 index 0000000..402a033 --- /dev/null +++ b/include/mcast.h @@ -0,0 +1,60 @@ +#ifndef _MCAST_H_ +#define _MCAST_H_ + +#include <stdint.h> +#include <netinet/in.h> +#include <net/if.h> + +struct mcast_conf { + int ipproto; + int reuseaddr; + int checksum; + unsigned short port; + union { + struct in_addr inet_addr; + struct in6_addr inet_addr6; + } in; + union { + struct in_addr interface_addr; + unsigned int interface_index6; + } ifa; + int sndbuf; + int rcvbuf; +}; + +struct mcast_stats { + uint64_t bytes; + uint64_t messages; + uint64_t error; +}; + +struct mcast_sock { + int fd; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + socklen_t sockaddr_len; + struct mcast_stats stats; +}; + +struct mcast_sock *mcast_server_create(struct mcast_conf *conf); +void mcast_server_destroy(struct mcast_sock *m); + +struct mcast_sock *mcast_client_create(struct mcast_conf *conf); +void mcast_client_destroy(struct mcast_sock *m); + +ssize_t mcast_send(struct mcast_sock *m, const void *data, int size); +ssize_t mcast_recv(struct mcast_sock *m, void *data, int size); + +int mcast_get_fd(struct mcast_sock *m); +int mcast_isset(struct mcast_sock *m, fd_set *readfds); + +int mcast_snprintf_stats(char *buf, size_t buflen, char *ifname, + struct mcast_stats *s, struct mcast_stats *r); + +int mcast_snprintf_stats2(char *buf, size_t buflen, const char *ifname, + const char *status, int active, + struct mcast_stats *s, struct mcast_stats *r); + +#endif diff --git a/include/netlink.h b/include/netlink.h new file mode 100644 index 0000000..0df0cbb --- /dev/null +++ b/include/netlink.h @@ -0,0 +1,33 @@ +#ifndef _NETLINK_H_ +#define _NETLINK_H_ + +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + +struct nf_conntrack; +struct nfct_handle; + +struct nfct_handle *nl_init_event_handler(void); +struct nlif_handle *nl_init_interface_handler(void); + +int nl_send_resync(struct nfct_handle *h); +void nl_resize_socket_buffer(struct nfct_handle *h); +int nl_dump_conntrack_table(struct nfct_handle *h); +int nl_flush_conntrack_table(struct nfct_handle *h); +int nl_get_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct); +int nl_create_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct, int timeout); +int nl_update_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct, int timeout); +int nl_destroy_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct); + +static inline int ct_is_related(const struct nf_conntrack *ct) +{ + return (nfct_attr_is_set(ct, ATTR_MASTER_L3PROTO) && + nfct_attr_is_set(ct, ATTR_MASTER_L4PROTO) && + ((nfct_attr_is_set(ct, ATTR_MASTER_IPV4_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_IPV4_DST)) || + (nfct_attr_is_set(ct, ATTR_MASTER_IPV6_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_IPV6_DST))) && + nfct_attr_is_set(ct, ATTR_MASTER_PORT_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_PORT_DST)); +} + +#endif diff --git a/include/network.h b/include/network.h new file mode 100644 index 0000000..70812b1 --- /dev/null +++ b/include/network.h @@ -0,0 +1,239 @@ +#ifndef _NETWORK_H_ +#define _NETWORK_H_ + +#include <stdint.h> +#include <sys/types.h> + +#define CONNTRACKD_PROTOCOL_VERSION 0 + +struct nf_conntrack; + +struct nethdr { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t type:4, + version:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t version:4, + type:4; +#else +#error "Unknown system endianess!" +#endif + uint8_t flags; + uint16_t len; + uint32_t seq; +}; +#define NETHDR_SIZ nethdr_align(sizeof(struct nethdr)) + +enum nethdr_type { + NET_T_STATE_NEW = 0, + NET_T_STATE_UPD, + NET_T_STATE_DEL, + NET_T_STATE_MAX = NET_T_STATE_DEL, + NET_T_CTL = 10, +}; + +int nethdr_align(int len); +int nethdr_size(int len); +void nethdr_set(struct nethdr *net, int type); +void nethdr_set_ack(struct nethdr *net); +void nethdr_set_ctl(struct nethdr *net); +int object_status_to_network_type(int status); + +#define NETHDR_DATA(x) \ + (struct netattr *)(((char *)x) + NETHDR_SIZ) +#define NETHDR_TAIL(x) \ + (struct netattr *)(((char *)x) + x->len) + +struct nethdr_ack { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t type:4, + version:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t version:4, + type:4; +#else +#error "Unknown system endianess!" +#endif + uint8_t flags; + uint16_t len; + uint32_t seq; + uint32_t from; + uint32_t to; +}; +#define NETHDR_ACK_SIZ nethdr_align(sizeof(struct nethdr_ack)) + +enum { + NET_F_UNUSED = (1 << 0), + NET_F_RESYNC = (1 << 1), + NET_F_NACK = (1 << 2), + NET_F_ACK = (1 << 3), + NET_F_ALIVE = (1 << 4), + NET_F_HELLO = (1 << 5), + NET_F_HELLO_BACK= (1 << 6), +}; + +enum { + MSG_DATA, + MSG_CTL, + MSG_DROP, + MSG_BAD, +}; + +#define BUILD_NETMSG(ct, query) \ +({ \ + static char __net[4096]; \ + struct nethdr *__hdr = (struct nethdr *) __net; \ + memset(__hdr, 0, NETHDR_SIZ); \ + nethdr_set(__hdr, query); \ + build_payload(ct, __hdr); \ + HDR_HOST2NETWORK(__hdr); \ + __hdr; \ +}) + +struct mcast_sock_multi; + +enum { + SEQ_UNKNOWN, + SEQ_UNSET, + SEQ_IN_SYNC, + SEQ_AFTER, + SEQ_BEFORE, +}; + +int nethdr_track_seq(uint32_t seq, uint32_t *exp_seq); +void nethdr_track_update_seq(uint32_t seq); +int nethdr_track_is_seq_set(void); + +struct mcast_conf; + +#define IS_DATA(x) (x->type <= NET_T_STATE_MAX && \ + (x->flags & ~(NET_F_HELLO | NET_F_HELLO_BACK)) == 0) +#define IS_ACK(x) (x->type == NET_T_CTL && x->flags & NET_F_ACK) +#define IS_NACK(x) (x->type == NET_T_CTL && x->flags & NET_F_NACK) +#define IS_RESYNC(x) (x->type == NET_T_CTL && x->flags & NET_F_RESYNC) +#define IS_ALIVE(x) (x->type == NET_T_CTL && x->flags & NET_F_ALIVE) +#define IS_HELLO(x) (x->flags & NET_F_HELLO) +#define IS_HELLO_BACK(x)(x->flags & NET_F_HELLO_BACK) + +#define HDR_NETWORK2HOST(x) \ +({ \ + x->len = ntohs(x->len); \ + x->seq = ntohl(x->seq); \ + if (IS_ACK(x) || IS_NACK(x) || IS_RESYNC(x)) { \ + struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ + __ack->from = ntohl(__ack->from); \ + __ack->to = ntohl(__ack->to); \ + } \ +}) + +#define HDR_HOST2NETWORK(x) \ +({ \ + if (IS_ACK(x) || IS_NACK(x) || IS_RESYNC(x)) { \ + struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ + __ack->from = htonl(__ack->from); \ + __ack->to = htonl(__ack->to); \ + } \ + x->len = htons(x->len); \ + x->seq = htonl(x->seq); \ +}) + +/* extracted from net/tcp.h */ + +/* + * The next routines deal with comparing 32 bit unsigned ints + * and worry about wraparound (automatic with unsigned arithmetic). + */ + +static inline int before(uint32_t seq1, uint32_t seq2) +{ + return (int32_t)(seq1-seq2) < 0; +} +#define after(seq2, seq1) before(seq1, seq2) + +/* is s2<=s1<=s3 ? */ +static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3) +{ + return seq3 - seq2 >= seq1 - seq2; +} + +#define PLD_NETWORK2HOST(x) \ +({ \ + x->len = ntohs(x->len); \ + x->query = ntohs(x->query); \ +}) + +#define PLD_HOST2NETWORK(x) \ +({ \ + x->len = htons(x->len); \ + x->query = htons(x->query); \ +}) + +struct netattr { + uint16_t nta_len; + uint16_t nta_attr; +}; + +#define ATTR_NETWORK2HOST(x) \ +({ \ + x->nta_len = ntohs(x->nta_len); \ + x->nta_attr = ntohs(x->nta_attr); \ +}) + +#define NTA_SIZE(len) NTA_ALIGN(sizeof(struct netattr)) + len + +#define NTA_DATA(x) \ + (void *)(((char *)x) + NTA_ALIGN(sizeof(struct netattr))) + +#define NTA_NEXT(x, len) \ +( \ + len -= NTA_ALIGN(x->nta_len), \ + (struct netattr *)(((char *)x) + NTA_ALIGN(x->nta_len)) \ +) + +#define NTA_ALIGNTO 4 +#define NTA_ALIGN(len) (((len) + NTA_ALIGNTO - 1) & ~(NTA_ALIGNTO - 1)) +#define NTA_LENGTH(len) (NTA_ALIGN(sizeof(struct netattr)) + (len)) + +enum nta_attr { + NTA_IPV4 = 0, /* struct nfct_attr_grp_ipv4 */ + NTA_IPV6, /* struct nfct_attr_grp_ipv6 */ + NTA_L4PROTO, /* uint8_t */ + NTA_PORT, /* struct nfct_attr_grp_port */ + NTA_TCP_STATE = 4, /* uint8_t */ + NTA_STATUS, /* uint32_t */ + NTA_TIMEOUT, /* uint32_t */ + NTA_MARK, /* uint32_t */ + NTA_MASTER_IPV4 = 8, /* struct nfct_attr_grp_ipv4 */ + NTA_MASTER_IPV6, /* struct nfct_attr_grp_ipv6 */ + NTA_MASTER_L4PROTO, /* uint8_t */ + NTA_MASTER_PORT, /* struct nfct_attr_grp_port */ + NTA_SNAT_IPV4 = 12, /* uint32_t */ + NTA_DNAT_IPV4, /* uint32_t */ + NTA_SPAT_PORT, /* uint16_t */ + NTA_DPAT_PORT, /* uint16_t */ + NTA_NAT_SEQ_ADJ = 16, /* struct nta_attr_natseqadj */ + NTA_SCTP_STATE, /* uint8_t */ + NTA_SCTP_VTAG_ORIG, /* uint32_t */ + NTA_SCTP_VTAG_REPL, /* uint32_t */ + NTA_DCCP_STATE = 20, /* uint8_t */ + NTA_DCCP_ROLE, /* uint8_t */ + NTA_ICMP_TYPE, /* uint8_t */ + NTA_ICMP_CODE, /* uint8_t */ + NTA_ICMP_ID, /* uint16_t */ + NTA_MAX +}; + +struct nta_attr_natseqadj { + uint32_t orig_seq_correction_pos; + uint32_t orig_seq_offset_before; + uint32_t orig_seq_offset_after; + uint32_t repl_seq_correction_pos; + uint32_t repl_seq_offset_before; + uint32_t repl_seq_offset_after; +}; + +void build_payload(const struct nf_conntrack *ct, struct nethdr *n); + +int parse_payload(struct nf_conntrack *ct, struct nethdr *n, size_t remain); + +#endif diff --git a/include/origin.h b/include/origin.h new file mode 100644 index 0000000..1b974e9 --- /dev/null +++ b/include/origin.h @@ -0,0 +1,16 @@ +#ifndef _ORIGIN_H_ +#define _ORIGIN_H_ + +enum { + CTD_ORIGIN_NOT_ME = 0, /* this event comes from the kernel or + any process, but not conntrackd */ + CTD_ORIGIN_COMMIT, /* event comes from committer */ + CTD_ORIGIN_FLUSH, /* event comes from flush */ + CTD_ORIGIN_INJECT, /* event comes from direct inject */ +}; + +int origin_register(struct nfct_handle *h, int origin_type); +int origin_find(const struct nlmsghdr *nlh); +int origin_unregister(struct nfct_handle *h); + +#endif diff --git a/include/process.h b/include/process.h new file mode 100644 index 0000000..41c7c10 --- /dev/null +++ b/include/process.h @@ -0,0 +1,25 @@ +#ifndef _PROCESS_H_ +#define _PROCESS_H_ + +enum process_type { + CTD_PROC_ANY, /* any type */ + CTD_PROC_FLUSH, /* flush process */ + CTD_PROC_COMMIT, /* commit process */ + CTD_PROC_MAX +}; + +#define CTD_PROC_F_EXCL (1 << 0) /* only one process at a time */ + +struct child_process { + struct list_head head; + int pid; + int type; + void (*cb)(void *data); + void *data; +}; + +int fork_process_new(int type, int flags, void (*cb)(void *data), void *data); +int fork_process_delete(int pid); +void fork_process_dump(int fd); + +#endif diff --git a/include/queue.h b/include/queue.h new file mode 100644 index 0000000..188e106 --- /dev/null +++ b/include/queue.h @@ -0,0 +1,62 @@ +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +#include <stdint.h> +#include "linux_list.h" + +struct queue_node { + struct list_head head; + uint32_t type; + struct queue *owner; + size_t size; +}; + +enum { + Q_ELEM_OBJ = 0, + Q_ELEM_CTL = 1, + Q_ELEM_ERR = 2, +}; + +void queue_node_init(struct queue_node *n, int type); +void *queue_node_data(struct queue_node *n); + +struct queue_object { + struct queue_node qnode; + char data[0]; +}; + +struct queue_object *queue_object_new(int type, size_t size); +void queue_object_free(struct queue_object *obj); + +struct evfd; + +#define QUEUE_NAMELEN 16 + +struct queue { + struct list_head list; + unsigned int max_elems; + unsigned int num_elems; + uint32_t enospc_err; + uint32_t flags; + struct list_head head; + struct evfd *evfd; + char name[QUEUE_NAMELEN]; +}; + +#define QUEUE_F_EVFD (1U << 0) + +struct queue *queue_create(const char *name, + int max_objects, unsigned int flags); +void queue_destroy(struct queue *b); +void queue_stats_show(int fd); +unsigned int queue_len(const struct queue *b); +int queue_add(struct queue *b, struct queue_node *n); +int queue_del(struct queue_node *n); +struct queue_node *queue_del_head(struct queue *b); +int queue_in(struct queue *b, struct queue_node *n); +void queue_iterate(struct queue *b, + const void *data, + int (*iterate)(struct queue_node *n, const void *data2)); +int queue_get_eventfd(struct queue *b); + +#endif diff --git a/include/sync.h b/include/sync.h new file mode 100644 index 0000000..51f8f5b --- /dev/null +++ b/include/sync.h @@ -0,0 +1,28 @@ +#ifndef _SYNC_HOOKS_H_ +#define _SYNC_HOOKS_H_ + +#include <sys/select.h> + +struct nethdr; +struct cache_object; +struct fds; + +struct sync_mode { + int internal_cache_flags; + int external_cache_flags; + struct cache_extra *internal_cache_extra; + struct cache_extra *external_cache_extra; + + int (*init)(void); + void (*kill)(void); + int (*local)(int fd, int type, void *data); + int (*recv)(const struct nethdr *net); + void (*enqueue)(struct cache_object *obj, int type); + void (*xmit)(void); +}; + +extern struct sync_mode sync_alarm; +extern struct sync_mode sync_ftfw; +extern struct sync_mode sync_notrack; + +#endif diff --git a/include/tcp.h b/include/tcp.h new file mode 100644 index 0000000..2f0fd0a --- /dev/null +++ b/include/tcp.h @@ -0,0 +1,76 @@ +#ifndef _TCP_H_ +#define _TCP_H_ + +#include <stdint.h> +#include <netinet/in.h> + +struct tcp_conf { + int ipproto; + int reuseaddr; + int checksum; + unsigned short port; + union { + struct { + struct in_addr inet_addr; + } ipv4; + struct { + struct in6_addr inet_addr6; + int scope_id; + } ipv6; + } server; + union { + struct in_addr inet_addr; + struct in6_addr inet_addr6; + } client; + int sndbuf; + int rcvbuf; +}; + +struct tcp_stats { + uint64_t bytes; + uint64_t messages; + uint64_t error; +}; + +enum tcp_sock_state { + TCP_SERVER_ACCEPTING, + TCP_SERVER_CONNECTED, + TCP_CLIENT_DISCONNECTED, + TCP_CLIENT_CONNECTED +}; + +struct tcp_sock { + int state; /* enum tcp_sock_state */ + int fd; + int client_fd; /* only for the server side */ + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + socklen_t sockaddr_len; + struct tcp_stats stats; + struct tcp_conf *conf; +}; + +struct tcp_sock *tcp_server_create(struct tcp_conf *conf); +void tcp_server_destroy(struct tcp_sock *m); + +struct tcp_sock *tcp_client_create(struct tcp_conf *conf); +void tcp_client_destroy(struct tcp_sock *m); + +ssize_t tcp_send(struct tcp_sock *m, const void *data, int size); +ssize_t tcp_recv(struct tcp_sock *m, void *data, int size); +int tcp_accept(struct tcp_sock *m); + +int tcp_get_fd(struct tcp_sock *m); +int tcp_isset(struct tcp_sock *m, fd_set *readfds); +int tcp_accept_isset(struct tcp_sock *m, fd_set *readfds); + +int tcp_snprintf_stats(char *buf, size_t buflen, char *ifname, + struct tcp_sock *s, struct tcp_sock *r); + +int tcp_snprintf_stats2(char *buf, size_t buflen, const char *ifname, + const char *status, int active, + struct tcp_stats *s, struct tcp_stats *r); + +#endif diff --git a/include/traffic_stats.h b/include/traffic_stats.h new file mode 100644 index 0000000..71fd268 --- /dev/null +++ b/include/traffic_stats.h @@ -0,0 +1,10 @@ +#ifndef _TRAFFIC_STATS_H_ +#define _TRAFFIC_STATS_H_ + +struct nf_conntrack; + +void update_traffic_stats(struct nf_conntrack *ct); + +void dump_traffic_stats(int fd); + +#endif diff --git a/include/udp.h b/include/udp.h new file mode 100644 index 0000000..9f9c17a --- /dev/null +++ b/include/udp.h @@ -0,0 +1,64 @@ +#ifndef _UDP_H_ +#define _UDP_H_ + +#include <stdint.h> +#include <netinet/in.h> + +struct udp_conf { + int ipproto; + int reuseaddr; + int checksum; + unsigned short port; + union { + struct { + struct in_addr inet_addr; + } ipv4; + struct { + struct in6_addr inet_addr6; + int scope_id; + } ipv6; + } server; + union { + struct in_addr inet_addr; + struct in6_addr inet_addr6; + } client; + int sndbuf; + int rcvbuf; +}; + +struct udp_stats { + uint64_t bytes; + uint64_t messages; + uint64_t error; +}; + +struct udp_sock { + int fd; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + socklen_t sockaddr_len; + struct udp_stats stats; +}; + +struct udp_sock *udp_server_create(struct udp_conf *conf); +void udp_server_destroy(struct udp_sock *m); + +struct udp_sock *udp_client_create(struct udp_conf *conf); +void udp_client_destroy(struct udp_sock *m); + +ssize_t udp_send(struct udp_sock *m, const void *data, int size); +ssize_t udp_recv(struct udp_sock *m, void *data, int size); + +int udp_get_fd(struct udp_sock *m); +int udp_isset(struct udp_sock *m, fd_set *readfds); + +int udp_snprintf_stats(char *buf, size_t buflen, char *ifname, + struct udp_stats *s, struct udp_stats *r); + +int udp_snprintf_stats2(char *buf, size_t buflen, const char *ifname, + const char *status, int active, + struct udp_stats *s, struct udp_stats *r); + +#endif diff --git a/include/vector.h b/include/vector.h new file mode 100644 index 0000000..5b05cba --- /dev/null +++ b/include/vector.h @@ -0,0 +1,13 @@ +#ifndef _VECTOR_H_ +#define _VECTOR_H_ + +#include <stdlib.h> + +struct vector; + +struct vector *vector_create(size_t size); +void vector_destroy(struct vector *v); +int vector_add(struct vector *v, void *data); +int vector_iterate(struct vector *v, const void *data, int (*fcn)(const void *a, const void *b)); + +#endif |