summaryrefslogtreecommitdiffstats
path: root/libdnet-stripped/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libdnet-stripped/src/Makefile.am11
-rw-r--r--libdnet-stripped/src/Makefile.in470
-rw-r--r--libdnet-stripped/src/addr-util.c304
-rw-r--r--libdnet-stripped/src/addr.c494
-rw-r--r--libdnet-stripped/src/arp-bsd.c323
-rw-r--r--libdnet-stripped/src/arp-ioctl.c489
-rw-r--r--libdnet-stripped/src/arp-none.c58
-rw-r--r--libdnet-stripped/src/arp-win32.c163
-rw-r--r--libdnet-stripped/src/blob.c458
-rw-r--r--libdnet-stripped/src/crc32ct.h83
-rw-r--r--libdnet-stripped/src/err.c110
-rw-r--r--libdnet-stripped/src/eth-bsd.c172
-rw-r--r--libdnet-stripped/src/eth-dlpi.c304
-rw-r--r--libdnet-stripped/src/eth-linux.c118
-rw-r--r--libdnet-stripped/src/eth-ndd.c117
-rw-r--r--libdnet-stripped/src/eth-none.c51
-rw-r--r--libdnet-stripped/src/eth-pfilt.c87
-rw-r--r--libdnet-stripped/src/eth-snoop.c109
-rw-r--r--libdnet-stripped/src/eth-win32.c163
-rw-r--r--libdnet-stripped/src/fw-none.c49
-rw-r--r--libdnet-stripped/src/intf-win32.c621
-rw-r--r--libdnet-stripped/src/intf.c1091
-rw-r--r--libdnet-stripped/src/ip-cooked.c250
-rw-r--r--libdnet-stripped/src/ip-util.c217
-rw-r--r--libdnet-stripped/src/ip-win32.c79
-rw-r--r--libdnet-stripped/src/ip.c104
-rw-r--r--libdnet-stripped/src/ip6.c76
-rw-r--r--libdnet-stripped/src/memcmp.c60
-rw-r--r--libdnet-stripped/src/rand.c208
-rw-r--r--libdnet-stripped/src/route-bsd.c703
-rw-r--r--libdnet-stripped/src/route-hpux.c184
-rw-r--r--libdnet-stripped/src/route-linux.c310
-rw-r--r--libdnet-stripped/src/route-none.c58
-rw-r--r--libdnet-stripped/src/route-win32.c279
-rw-r--r--libdnet-stripped/src/strlcpy.c69
-rw-r--r--libdnet-stripped/src/strsep.c85
-rw-r--r--libdnet-stripped/src/tun-bsd.c146
-rw-r--r--libdnet-stripped/src/tun-linux.c115
-rw-r--r--libdnet-stripped/src/tun-none.c58
-rw-r--r--libdnet-stripped/src/tun-solaris.c127
40 files changed, 8973 insertions, 0 deletions
diff --git a/libdnet-stripped/src/Makefile.am b/libdnet-stripped/src/Makefile.am
new file mode 100644
index 0000000..2f14d98
--- /dev/null
+++ b/libdnet-stripped/src/Makefile.am
@@ -0,0 +1,11 @@
+## $Id: Makefile.am 625 2006-01-19 06:11:01Z dugsong $
+
+include $(top_srcdir)/Makefile.am.common
+
+lib_LTLIBRARIES = libdnet.la
+
+libdnet_la_SOURCES = addr-util.c addr.c blob.c ip-util.c ip6.c rand.c
+
+libdnet_la_LIBADD = @LTLIBOBJS@
+
+libdnet_la_LDFLAGS = -version-info 1:1:0
diff --git a/libdnet-stripped/src/Makefile.in b/libdnet-stripped/src/Makefile.in
new file mode 100644
index 0000000..16880e3
--- /dev/null
+++ b/libdnet-stripped/src/Makefile.in
@@ -0,0 +1,470 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 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@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@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@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/Makefile.am.common arp-bsd.c arp-ioctl.c \
+ arp-none.c arp-win32.c err.c eth-bsd.c eth-dlpi.c eth-linux.c \
+ eth-ndd.c eth-none.c eth-pfilt.c eth-snoop.c eth-win32.c \
+ fw-none.c intf-win32.c intf.c ip-cooked.c ip-win32.c ip.c \
+ memcmp.c route-bsd.c route-hpux.c route-linux.c route-none.c \
+ route-win32.c strlcpy.c strsep.c tun-bsd.c \
+ tun-linux.c tun-none.c tun-solaris.c
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \
+ $(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)
+libdnet_la_DEPENDENCIES = @LTLIBOBJS@
+am_libdnet_la_OBJECTS = addr-util.lo addr.lo blob.lo ip-util.lo ip6.lo \
+ rand.lo
+libdnet_la_OBJECTS = $(am_libdnet_la_OBJECTS)
+libdnet_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libdnet_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libdnet_la_SOURCES)
+DIST_SOURCES = $(libdnet_la_SOURCES)
+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@
+CHECKINC = @CHECKINC@
+CHECKLIB = @CHECKLIB@
+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@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+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_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TCLINC = @TCLINC@
+TCLLIB = @TCLLIB@
+VERSION = @VERSION@
+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_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+AM_CPPFLAGS = -I$(top_srcdir)/include
+lib_LTLIBRARIES = libdnet.la
+libdnet_la_SOURCES = addr-util.c addr.c blob.c ip-util.c ip6.c rand.c
+libdnet_la_LIBADD = @LTLIBOBJS@
+libdnet_la_LDFLAGS = -version-info 1:1:0
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(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) --foreign src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign 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) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --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
+libdnet.la: $(libdnet_la_OBJECTS) $(libdnet_la_DEPENDENCIES)
+ $(libdnet_la_LINK) -rpath $(libdir) $(libdnet_la_OBJECTS) $(libdnet_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -c -o $@ $<
+
+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; nonemtpy = 1; } \
+ END { if (nonempty) { 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; nonempty = 1; } \
+ END { if (nonempty) { 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=; \
+ 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)$$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)'; \
+ 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 $(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."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: 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-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.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-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-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/libdnet-stripped/src/addr-util.c b/libdnet-stripped/src/addr-util.c
new file mode 100644
index 0000000..09c0807
--- /dev/null
+++ b/libdnet-stripped/src/addr-util.c
@@ -0,0 +1,304 @@
+/*
+ * addr-util.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: addr-util.c 539 2005-01-23 07:36:54Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+static const char *octet2dec[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
+ "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34",
+ "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45",
+ "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56",
+ "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67",
+ "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78",
+ "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
+ "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100",
+ "101", "102", "103", "104", "105", "106", "107", "108", "109",
+ "110", "111", "112", "113", "114", "115", "116", "117", "118",
+ "119", "120", "121", "122", "123", "124", "125", "126", "127",
+ "128", "129", "130", "131", "132", "133", "134", "135", "136",
+ "137", "138", "139", "140", "141", "142", "143", "144", "145",
+ "146", "147", "148", "149", "150", "151", "152", "153", "154",
+ "155", "156", "157", "158", "159", "160", "161", "162", "163",
+ "164", "165", "166", "167", "168", "169", "170", "171", "172",
+ "173", "174", "175", "176", "177", "178", "179", "180", "181",
+ "182", "183", "184", "185", "186", "187", "188", "189", "190",
+ "191", "192", "193", "194", "195", "196", "197", "198", "199",
+ "200", "201", "202", "203", "204", "205", "206", "207", "208",
+ "209", "210", "211", "212", "213", "214", "215", "216", "217",
+ "218", "219", "220", "221", "222", "223", "224", "225", "226",
+ "227", "228", "229", "230", "231", "232", "233", "234", "235",
+ "236", "237", "238", "239", "240", "241", "242", "243", "244",
+ "245", "246", "247", "248", "249", "250", "251", "252", "253",
+ "254", "255"
+};
+
+static const char *octet2hex[] = {
+ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a",
+ "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20",
+ "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b",
+ "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36",
+ "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41",
+ "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c",
+ "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57",
+ "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62",
+ "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d",
+ "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78",
+ "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83",
+ "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e",
+ "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
+ "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4",
+ "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba",
+ "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5",
+ "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0",
+ "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db",
+ "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6",
+ "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1",
+ "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc",
+ "fd", "fe", "ff"
+};
+
+char *
+eth_ntop(const eth_addr_t *eth, char *dst, size_t len)
+{
+ const char *x;
+ char *p = dst;
+ int i;
+
+ if (len < 18)
+ return (NULL);
+
+ for (i = 0; i < ETH_ADDR_LEN; i++) {
+ for (x = octet2hex[eth->data[i]]; (*p = *x) != '\0'; x++, p++)
+ ;
+ *p++ = ':';
+ }
+ p[-1] = '\0';
+
+ return (dst);
+}
+
+char *
+eth_ntoa(const eth_addr_t *eth)
+{
+ struct addr a;
+
+ addr_pack(&a, ADDR_TYPE_ETH, ETH_ADDR_BITS, eth->data, ETH_ADDR_LEN);
+ return (addr_ntoa(&a));
+}
+
+int
+eth_pton(const char *p, eth_addr_t *eth)
+{
+ char *ep;
+ long l;
+ int i;
+
+ for (i = 0; i < ETH_ADDR_LEN; i++) {
+ l = strtol(p, &ep, 16);
+ if (ep == p || l < 0 || l > 0xff ||
+ (i < ETH_ADDR_LEN - 1 && *ep != ':'))
+ break;
+ eth->data[i] = (u_char)l;
+ p = ep + 1;
+ }
+ return ((i == ETH_ADDR_LEN && *ep == '\0') ? 0 : -1);
+}
+
+char *
+ip_ntop(const ip_addr_t *ip, char *dst, size_t len)
+{
+ const char *d;
+ char *p = dst;
+ u_char *data = (u_char *)ip;
+ int i;
+
+ if (len < 16)
+ return (NULL);
+
+ for (i = 0; i < IP_ADDR_LEN; i++) {
+ for (d = octet2dec[data[i]]; (*p = *d) != '\0'; d++, p++)
+ ;
+ *p++ = '.';
+ }
+ p[-1] = '\0';
+
+ return (dst);
+}
+
+char *
+ip_ntoa(const ip_addr_t *ip)
+{
+ struct addr a;
+
+ addr_pack(&a, ADDR_TYPE_IP, IP_ADDR_BITS, ip, IP_ADDR_LEN);
+ return (addr_ntoa(&a));
+}
+
+int
+ip_pton(const char *p, ip_addr_t *ip)
+{
+ u_char *data = (u_char *)ip;
+ char *ep;
+ long l;
+ int i;
+
+ for (i = 0; i < IP_ADDR_LEN; i++) {
+ l = strtol(p, &ep, 10);
+ if (ep == p || l < 0 || l > 0xff ||
+ (i < IP_ADDR_LEN - 1 && *ep != '.'))
+ break;
+ data[i] = (u_char)l;
+ p = ep + 1;
+ }
+ return ((i == IP_ADDR_LEN && *ep == '\0') ? 0 : -1);
+}
+
+char *
+ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t len)
+{
+ uint16_t data[IP6_ADDR_LEN / 2];
+ struct { int base, len; } best, cur;
+ char *p = dst;
+ int i;
+
+ cur.len = best.len = 0;
+
+ if (len < 46)
+ return (NULL);
+
+ /* Copy into 16-bit array. */
+ for (i = 0; i < IP6_ADDR_LEN / 2; i++) {
+ data[i] = ip6->data[2 * i] << 8;
+ data[i] |= ip6->data[2 * i + 1];
+ }
+
+ best.base = cur.base = -1;
+ /*
+ * Algorithm borrowed from Vixie's inet_pton6()
+ */
+ for (i = 0; i < IP6_ADDR_LEN; i += 2) {
+ if (data[i / 2] == 0) {
+ if (cur.base == -1) {
+ cur.base = i;
+ cur.len = 0;
+ } else
+ cur.len += 2;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1 && (best.base == -1 || cur.len > best.len))
+ best = cur;
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+ if (best.base == 0)
+ *p++ = ':';
+
+ for (i = 0; i < IP6_ADDR_LEN; i += 2) {
+ if (i == best.base) {
+ *p++ = ':';
+ i += best.len;
+ } else if (i == 12 && best.base == 0 &&
+ (best.len == 10 || (best.len == 8 &&
+ data[5] == 0xffff))) {
+ if (ip_ntop((ip_addr_t *)&data[6], p,
+ len - (p - dst)) == NULL)
+ return (NULL);
+ return (dst);
+ } else p += sprintf(p, "%x:", data[i / 2]);
+ }
+ if (best.base + 2 + best.len == IP6_ADDR_LEN) {
+ *p = '\0';
+ } else
+ p[-1] = '\0';
+
+ return (dst);
+}
+
+char *
+ip6_ntoa(const ip6_addr_t *ip6)
+{
+ struct addr a;
+
+ addr_pack(&a, ADDR_TYPE_IP6, IP6_ADDR_BITS, ip6->data, IP6_ADDR_LEN);
+ return (addr_ntoa(&a));
+}
+
+int
+ip6_pton(const char *p, ip6_addr_t *ip6)
+{
+ uint16_t data[8], *u = (uint16_t *)ip6->data;
+ int i, j, n, z = -1;
+ char *ep;
+ long l;
+
+ if (*p == ':')
+ p++;
+
+ for (n = 0; n < 8; n++) {
+ l = strtol(p, &ep, 16);
+
+ if (ep == p) {
+ if (ep[0] == ':' && z == -1) {
+ z = n;
+ p++;
+ } else if (ep[0] == '\0') {
+ break;
+ } else {
+ return (-1);
+ }
+ } else if (ep[0] == '.' && n <= 6) {
+ if (ip_pton(p, (ip_addr_t *)(data + n)) < 0)
+ return (-1);
+ n += 2;
+ ep = ""; /* XXX */
+ break;
+ } else if (l >= 0 && l <= 0xffff) {
+ data[n] = htons((uint16_t)l);
+
+ if (ep[0] == '\0') {
+ n++;
+ break;
+ } else if (ep[0] != ':' || ep[1] == '\0')
+ return (-1);
+
+ p = ep + 1;
+ } else
+ return (-1);
+ }
+ if (n == 0 || *ep != '\0' || (z == -1 && n != 8))
+ return (-1);
+
+ for (i = 0; i < z; i++) {
+ u[i] = data[i];
+ }
+ while (i < 8 - (n - z - 1)) {
+ u[i++] = 0;
+ }
+ for (j = z + 1; i < 8; i++, j++) {
+ u[i] = data[j];
+ }
+ return (0);
+}
diff --git a/libdnet-stripped/src/addr.c b/libdnet-stripped/src/addr.c
new file mode 100644
index 0000000..7008966
--- /dev/null
+++ b/libdnet-stripped/src/addr.c
@@ -0,0 +1,494 @@
+/*
+ * addr.c
+ *
+ * Network address operations.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: addr.c 610 2005-06-26 18:23:26Z dugsong $
+ */
+
+#ifdef WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_NET_IF_H
+# include <sys/socket.h>
+# include <net/if.h>
+#endif
+#ifdef HAVE_NET_IF_DL_H
+# include <net/if_dl.h>
+#endif
+#ifdef HAVE_NET_RAW_H
+# include <net/raw.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
+union sockunion {
+#ifdef HAVE_NET_IF_DL_H
+ struct sockaddr_dl sdl;
+#endif
+ struct sockaddr_in sin;
+#ifdef HAVE_SOCKADDR_IN6
+ struct sockaddr_in6 sin6;
+#endif
+ struct sockaddr sa;
+#ifdef AF_RAW
+ struct sockaddr_raw sr;
+#endif
+};
+
+int
+addr_cmp(const struct addr *a, const struct addr *b)
+{
+ int i, j, k;
+
+ /* XXX */
+ if ((i = a->addr_type - b->addr_type) != 0)
+ return (i);
+
+ /* XXX - 10.0.0.1 is "smaller" than 10.0.0.0/8? */
+ if ((i = a->addr_bits - b->addr_bits) != 0)
+ return (i);
+
+ j = b->addr_bits / 8;
+
+ for (i = 0; i < j; i++) {
+ if ((k = a->addr_data8[i] - b->addr_data8[i]) != 0)
+ return (k);
+ }
+ if ((k = b->addr_bits % 8) == 0)
+ return (0);
+
+ k = (~(unsigned int)0) << (8 - k);
+ i = b->addr_data8[j] & k;
+ j = a->addr_data8[j] & k;
+
+ return (j - i);
+}
+
+int
+addr_net(const struct addr *a, struct addr *b)
+{
+ uint32_t mask;
+ int i, j;
+
+ if (a->addr_type == ADDR_TYPE_IP) {
+ addr_btom(a->addr_bits, &mask, IP_ADDR_LEN);
+ b->addr_type = ADDR_TYPE_IP;
+ b->addr_bits = IP_ADDR_BITS;
+ b->addr_ip = a->addr_ip & mask;
+ } else if (a->addr_type == ADDR_TYPE_ETH) {
+ memcpy(b, a, sizeof(*b));
+ if (a->addr_data8[0] & 0x1)
+ memset(b->addr_data8 + 3, 0, 3);
+ b->addr_bits = ETH_ADDR_BITS;
+ } else if (a->addr_type == ADDR_TYPE_IP6) {
+ if (a->addr_bits > IP6_ADDR_BITS)
+ return (-1);
+ b->addr_type = ADDR_TYPE_IP6;
+ b->addr_bits = IP6_ADDR_BITS;
+ memset(&b->addr_ip6, 0, IP6_ADDR_LEN);
+
+ switch ((i = a->addr_bits / 32)) {
+ case 4: b->addr_data32[3] = a->addr_data32[3];
+ case 3: b->addr_data32[2] = a->addr_data32[2];
+ case 2: b->addr_data32[1] = a->addr_data32[1];
+ case 1: b->addr_data32[0] = a->addr_data32[0];
+ }
+ if ((j = a->addr_bits % 32) > 0) {
+ addr_btom(j, &mask, sizeof(mask));
+ b->addr_data32[i] = a->addr_data32[i] & mask;
+ }
+ } else
+ return (-1);
+
+ return (0);
+}
+
+int
+addr_bcast(const struct addr *a, struct addr *b)
+{
+ struct addr mask;
+
+ if (a->addr_type == ADDR_TYPE_IP) {
+ addr_btom(a->addr_bits, &mask.addr_ip, IP_ADDR_LEN);
+ b->addr_type = ADDR_TYPE_IP;
+ b->addr_bits = IP_ADDR_BITS;
+ b->addr_ip = (a->addr_ip & mask.addr_ip) |
+ (~0L & ~mask.addr_ip);
+ } else if (a->addr_type == ADDR_TYPE_ETH) {
+ b->addr_type = ADDR_TYPE_ETH;
+ b->addr_bits = ETH_ADDR_BITS;
+ memcpy(&b->addr_eth, ETH_ADDR_BROADCAST, ETH_ADDR_LEN);
+ } else {
+ /* XXX - no broadcast addresses in IPv6 */
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+char *
+addr_ntop(const struct addr *src, char *dst, size_t size)
+{
+ if (src->addr_type == ADDR_TYPE_IP && size >= 20) {
+ if (ip_ntop(&src->addr_ip, dst, size) != NULL) {
+ if (src->addr_bits != IP_ADDR_BITS)
+ sprintf(dst + strlen(dst), "/%d",
+ src->addr_bits);
+ return (dst);
+ }
+ } else if (src->addr_type == ADDR_TYPE_IP6 && size >= 42) {
+ if (ip6_ntop(&src->addr_ip6, dst, size) != NULL) {
+ if (src->addr_bits != IP6_ADDR_BITS)
+ sprintf(dst + strlen(dst), "/%d",
+ src->addr_bits);
+ return (dst);
+ }
+ } else if (src->addr_type == ADDR_TYPE_ETH && size >= 18) {
+ if (src->addr_bits == ETH_ADDR_BITS)
+ return (eth_ntop(&src->addr_eth, dst, size));
+ }
+ errno = EINVAL;
+ return (NULL);
+}
+
+int
+addr_pton(const char *src, struct addr *dst)
+{
+ struct hostent *hp;
+ char *ep, tmp[300];
+ long bits = -1;
+ int i;
+
+ for (i = 0; i < (int)sizeof(tmp) - 1; i++) {
+ if (src[i] == '/') {
+ tmp[i] = '\0';
+ if (strchr(&src[i + 1], '.')) {
+ uint32_t m;
+ uint16_t b;
+ /* XXX - mask is specified like /255.0.0.0 */
+ if (ip_pton(&src[i + 1], &m) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ addr_mtob(&m, sizeof(m), &b);
+ bits = b;
+ } else {
+ bits = strtol(&src[i + 1], &ep, 10);
+ if (ep == src || *ep != '\0' || bits < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ break;
+ } else if ((tmp[i] = src[i]) == '\0')
+ break;
+ }
+ if (ip_pton(tmp, &dst->addr_ip) == 0) {
+ dst->addr_type = ADDR_TYPE_IP;
+ dst->addr_bits = IP_ADDR_BITS;
+ } else if (eth_pton(tmp, &dst->addr_eth) == 0) {
+ dst->addr_type = ADDR_TYPE_ETH;
+ dst->addr_bits = ETH_ADDR_BITS;
+ } else if (ip6_pton(tmp, &dst->addr_ip6) == 0) {
+ dst->addr_type = ADDR_TYPE_IP6;
+ dst->addr_bits = IP6_ADDR_BITS;
+ } else if ((hp = gethostbyname(tmp)) != NULL) {
+ memcpy(&dst->addr_ip, hp->h_addr, IP_ADDR_LEN);
+ dst->addr_type = ADDR_TYPE_IP;
+ dst->addr_bits = IP_ADDR_BITS;
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (bits >= 0) {
+ if (bits > dst->addr_bits) {
+ errno = EINVAL;
+ return (-1);
+ }
+ dst->addr_bits = (uint16_t)bits;
+ }
+ return (0);
+}
+
+char *
+addr_ntoa(const struct addr *a)
+{
+ static char *p, buf[BUFSIZ];
+ char *q = NULL;
+
+ if (p == NULL || p > buf + sizeof(buf) - 64 /* XXX */)
+ p = buf;
+
+ if (addr_ntop(a, p, (buf + sizeof(buf)) - p) != NULL) {
+ q = p;
+ p += strlen(p) + 1;
+ }
+ return (q);
+}
+
+int
+addr_ntos(const struct addr *a, struct sockaddr *sa)
+{
+ union sockunion *so = (union sockunion *)sa;
+
+ switch (a->addr_type) {
+ case ADDR_TYPE_ETH:
+#ifdef HAVE_NET_IF_DL_H
+ memset(&so->sdl, 0, sizeof(so->sdl));
+# ifdef HAVE_SOCKADDR_SA_LEN
+ so->sdl.sdl_len = sizeof(so->sdl);
+# endif
+# ifdef AF_LINK
+ so->sdl.sdl_family = AF_LINK;
+# else
+ so->sdl.sdl_family = AF_UNSPEC;
+# endif
+ so->sdl.sdl_alen = ETH_ADDR_LEN;
+ memcpy(LLADDR(&so->sdl), &a->addr_eth, ETH_ADDR_LEN);
+#else
+ memset(sa, 0, sizeof(*sa));
+# ifdef AF_LINK
+ sa->sa_family = AF_LINK;
+# else
+ sa->sa_family = AF_UNSPEC;
+# endif
+ memcpy(sa->sa_data, &a->addr_eth, ETH_ADDR_LEN);
+#endif
+ break;
+#ifdef HAVE_SOCKADDR_IN6
+ case ADDR_TYPE_IP6:
+ memset(&so->sin6, 0, sizeof(so->sin6));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ so->sin6.sin6_len = sizeof(so->sin6);
+#endif
+ so->sin6.sin6_family = AF_INET6;
+ memcpy(&so->sin6.sin6_addr, &a->addr_ip6, IP6_ADDR_LEN);
+ break;
+#endif
+ case ADDR_TYPE_IP:
+ memset(&so->sin, 0, sizeof(so->sin));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ so->sin.sin_len = sizeof(so->sin);
+#endif
+ so->sin.sin_family = AF_INET;
+ so->sin.sin_addr.s_addr = a->addr_ip;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+addr_ston(const struct sockaddr *sa, struct addr *a)
+{
+ union sockunion *so = (union sockunion *)sa;
+
+ memset(a, 0, sizeof(*a));
+
+ switch (sa->sa_family) {
+#ifdef HAVE_NET_IF_DL_H
+# ifdef AF_LINK
+ case AF_LINK:
+ if (so->sdl.sdl_alen != ETH_ADDR_LEN) {
+ errno = EINVAL;
+ return (-1);
+ }
+ a->addr_type = ADDR_TYPE_ETH;
+ a->addr_bits = ETH_ADDR_BITS;
+ memcpy(&a->addr_eth, LLADDR(&so->sdl), ETH_ADDR_LEN);
+ break;
+# endif
+#endif
+ case AF_UNSPEC:
+ case ARP_HRD_ETH: /* XXX- Linux arp(7) */
+ case ARP_HRD_APPLETALK: /* AppleTalk DDP */
+ case ARP_HRD_INFINIBAND: /* InfiniBand */
+ case ARP_HDR_IEEE80211: /* IEEE 802.11 */
+ case ARP_HRD_IEEE80211_PRISM: /* IEEE 802.11 + prism header */
+ case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */
+ a->addr_type = ADDR_TYPE_ETH;
+ a->addr_bits = ETH_ADDR_BITS;
+ memcpy(&a->addr_eth, sa->sa_data, ETH_ADDR_LEN);
+ break;
+
+#ifdef AF_RAW
+ case AF_RAW: /* XXX - IRIX raw(7f) */
+ a->addr_type = ADDR_TYPE_ETH;
+ a->addr_bits = ETH_ADDR_BITS;
+ memcpy(&a->addr_eth, so->sr.sr_addr, ETH_ADDR_LEN);
+ break;
+#endif
+#ifdef HAVE_SOCKADDR_IN6
+ case AF_INET6:
+ a->addr_type = ADDR_TYPE_IP6;
+ a->addr_bits = IP6_ADDR_BITS;
+ memcpy(&a->addr_ip6, &so->sin6.sin6_addr, IP6_ADDR_LEN);
+ break;
+#endif
+ case AF_INET:
+ a->addr_type = ADDR_TYPE_IP;
+ a->addr_bits = IP_ADDR_BITS;
+ a->addr_ip = so->sin.sin_addr.s_addr;
+ break;
+ case ARP_HRD_VOID:
+ memset(&a->addr_eth, 0, ETH_ADDR_LEN);
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+addr_btos(uint16_t bits, struct sockaddr *sa)
+{
+ union sockunion *so = (union sockunion *)sa;
+
+#ifdef HAVE_SOCKADDR_IN6
+ if (bits > IP_ADDR_BITS && bits <= IP6_ADDR_BITS) {
+ memset(&so->sin6, 0, sizeof(so->sin6));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ so->sin6.sin6_len = IP6_ADDR_LEN + (bits / 8) + (bits % 8);
+#endif
+ so->sin6.sin6_family = AF_INET6;
+ return (addr_btom(bits, &so->sin6.sin6_addr, IP6_ADDR_LEN));
+ } else
+#endif
+ if (bits <= IP_ADDR_BITS) {
+ memset(&so->sin, 0, sizeof(so->sin));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ so->sin.sin_len = IP_ADDR_LEN + (bits / 8) + (bits % 8);
+#endif
+ so->sin.sin_family = AF_INET;
+ return (addr_btom(bits, &so->sin.sin_addr, IP_ADDR_LEN));
+ }
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+addr_stob(const struct sockaddr *sa, uint16_t *bits)
+{
+ union sockunion *so = (union sockunion *)sa;
+ int i, j, len;
+ uint16_t n;
+ u_char *p;
+
+#ifdef HAVE_SOCKADDR_IN6
+ if (sa->sa_family == AF_INET6) {
+ p = (u_char *)&so->sin6.sin6_addr;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ len = sa->sa_len - ((void *) p - (void *) sa);
+ /* Handles the special case of sa->sa_len == 0. */
+ if (len < 0)
+ len = 0;
+ else if (len > IP6_ADDR_LEN)
+ len = IP6_ADDR_LEN;
+#else
+ len = IP6_ADDR_LEN;
+#endif
+ } else
+#endif
+ {
+ p = (u_char *)&so->sin.sin_addr.s_addr;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ len = sa->sa_len - ((void *) p - (void *) sa);
+ /* Handles the special case of sa->sa_len == 0. */
+ if (len < 0)
+ len = 0;
+ else if (len > IP_ADDR_LEN)
+ len = IP_ADDR_LEN;
+#else
+ len = IP_ADDR_LEN;
+#endif
+ }
+ for (n = i = 0; i < len; i++, n += 8) {
+ if (p[i] != 0xff)
+ break;
+ }
+ if (i != len && p[i]) {
+ for (j = 7; j > 0; j--, n++) {
+ if ((p[i] & (1 << j)) == 0)
+ break;
+ }
+ }
+ *bits = n;
+
+ return (0);
+}
+
+int
+addr_btom(uint16_t bits, void *mask, size_t size)
+{
+ int net, host;
+ u_char *p;
+
+ if (size == IP_ADDR_LEN) {
+ if (bits > IP_ADDR_BITS) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *(uint32_t *)mask = bits ?
+ htonl(~(uint32_t)0 << (IP_ADDR_BITS - bits)) : 0;
+ } else {
+ if (size * 8 < bits) {
+ errno = EINVAL;
+ return (-1);
+ }
+ p = (u_char *)mask;
+
+ if ((net = bits / 8) > 0)
+ memset(p, 0xff, net);
+
+ if ((host = bits % 8) > 0) {
+ p[net] = 0xff << (8 - host);
+ memset(&p[net + 1], 0, size - net - 1);
+ } else
+ memset(&p[net], 0, size - net);
+ }
+ return (0);
+}
+
+int
+addr_mtob(const void *mask, size_t size, uint16_t *bits)
+{
+ uint16_t n;
+ u_char *p;
+ int i, j;
+
+ p = (u_char *)mask;
+
+ for (n = i = 0; i < (int)size; i++, n += 8) {
+ if (p[i] != 0xff)
+ break;
+ }
+ if (i != (int)size && p[i]) {
+ for (j = 7; j > 0; j--, n++) {
+ if ((p[i] & (1 << j)) == 0)
+ break;
+ }
+ }
+ *bits = n;
+
+ return (0);
+}
diff --git a/libdnet-stripped/src/arp-bsd.c b/libdnet-stripped/src/arp-bsd.c
new file mode 100644
index 0000000..e2beb25
--- /dev/null
+++ b/libdnet-stripped/src/arp-bsd.c
@@ -0,0 +1,323 @@
+/*
+ * arp-bsd.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: arp-bsd.c 539 2005-01-23 07:36:54Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_STREAMS_ROUTE
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct arp_handle {
+ int fd;
+ int seq;
+};
+
+struct arpmsg {
+ struct rt_msghdr rtm;
+ u_char addrs[256];
+};
+
+arp_t *
+arp_open(void)
+{
+ arp_t *arp;
+
+ if ((arp = calloc(1, sizeof(*arp))) != NULL) {
+#ifdef HAVE_STREAMS_ROUTE
+ if ((arp->fd = open("/dev/route", O_RDWR, 0)) < 0)
+#else
+ if ((arp->fd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
+#endif
+ return (arp_close(arp));
+ }
+ return (arp);
+}
+
+static int
+arp_msg(arp_t *arp, struct arpmsg *msg)
+{
+ struct arpmsg smsg;
+ int len, i = 0;
+ pid_t pid;
+
+ msg->rtm.rtm_version = RTM_VERSION;
+ msg->rtm.rtm_seq = ++arp->seq;
+ memcpy(&smsg, msg, sizeof(smsg));
+
+#ifdef HAVE_STREAMS_ROUTE
+ return (ioctl(arp->fd, RTSTR_SEND, &msg->rtm));
+#else
+ if (write(arp->fd, &smsg, smsg.rtm.rtm_msglen) < 0) {
+ if (errno != ESRCH || msg->rtm.rtm_type != RTM_DELETE)
+ return (-1);
+ }
+ pid = getpid();
+
+ /* XXX - should we only read RTM_GET responses here? */
+ while ((len = read(arp->fd, msg, sizeof(*msg))) > 0) {
+ if (len < (int)sizeof(msg->rtm))
+ return (-1);
+
+ if (msg->rtm.rtm_pid == pid) {
+ if (msg->rtm.rtm_seq == arp->seq)
+ break;
+ continue;
+ } else if ((i++ % 2) == 0)
+ continue;
+
+ /* Repeat request. */
+ if (write(arp->fd, &smsg, smsg.rtm.rtm_msglen) < 0) {
+ if (errno != ESRCH || msg->rtm.rtm_type != RTM_DELETE)
+ return (-1);
+ }
+ }
+ if (len < 0)
+ return (-1);
+
+ return (0);
+#endif
+}
+
+int
+arp_add(arp_t *arp, const struct arp_entry *entry)
+{
+ struct arpmsg msg;
+ struct sockaddr_in *sin;
+ struct sockaddr *sa;
+ int index, type;
+
+ if (entry->arp_pa.addr_type != ADDR_TYPE_IP ||
+ entry->arp_ha.addr_type != ADDR_TYPE_ETH) {
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)msg.addrs;
+ sa = (struct sockaddr *)(sin + 1);
+
+ if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
+ return (-1);
+
+ memset(&msg.rtm, 0, sizeof(msg.rtm));
+ msg.rtm.rtm_type = RTM_GET;
+ msg.rtm.rtm_addrs = RTA_DST;
+ msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);
+
+ if (arp_msg(arp, &msg) < 0)
+ return (-1);
+
+ if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
+ sizeof(*sin) + sizeof(*sa)) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+ if (sin->sin_addr.s_addr == entry->arp_pa.addr_ip) {
+ if ((msg.rtm.rtm_flags & RTF_LLINFO) == 0 ||
+ (msg.rtm.rtm_flags & RTF_GATEWAY) != 0) {
+ errno = EADDRINUSE;
+ return (-1);
+ }
+ }
+ if (sa->sa_family != AF_LINK) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ } else {
+ index = ((struct sockaddr_dl *)sa)->sdl_index;
+ type = ((struct sockaddr_dl *)sa)->sdl_type;
+ }
+ if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0 ||
+ addr_ntos(&entry->arp_ha, sa) < 0)
+ return (-1);
+
+ ((struct sockaddr_dl *)sa)->sdl_index = index;
+ ((struct sockaddr_dl *)sa)->sdl_type = type;
+
+ memset(&msg.rtm, 0, sizeof(msg.rtm));
+ msg.rtm.rtm_type = RTM_ADD;
+ msg.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
+ msg.rtm.rtm_inits = RTV_EXPIRE;
+ msg.rtm.rtm_flags = RTF_HOST | RTF_STATIC;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ msg.rtm.rtm_msglen = sizeof(msg.rtm) + sin->sin_len + sa->sa_len;
+#else
+ msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin) + sizeof(*sa);
+#endif
+ return (arp_msg(arp, &msg));
+}
+
+int
+arp_delete(arp_t *arp, const struct arp_entry *entry)
+{
+ struct arpmsg msg;
+ struct sockaddr_in *sin;
+ struct sockaddr *sa;
+
+ if (entry->arp_pa.addr_type != ADDR_TYPE_IP) {
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)msg.addrs;
+ sa = (struct sockaddr *)(sin + 1);
+
+ if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
+ return (-1);
+
+ memset(&msg.rtm, 0, sizeof(msg.rtm));
+ msg.rtm.rtm_type = RTM_GET;
+ msg.rtm.rtm_addrs = RTA_DST;
+ msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);
+
+ if (arp_msg(arp, &msg) < 0)
+ return (-1);
+
+ if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
+ sizeof(*sin) + sizeof(*sa)) {
+ errno = ESRCH;
+ return (-1);
+ }
+ if (sin->sin_addr.s_addr == entry->arp_pa.addr_ip) {
+ if ((msg.rtm.rtm_flags & RTF_LLINFO) == 0 ||
+ (msg.rtm.rtm_flags & RTF_GATEWAY) != 0) {
+ errno = EADDRINUSE;
+ return (-1);
+ }
+ }
+ if (sa->sa_family != AF_LINK) {
+ errno = ESRCH;
+ return (-1);
+ }
+ msg.rtm.rtm_type = RTM_DELETE;
+
+ return (arp_msg(arp, &msg));
+}
+
+int
+arp_get(arp_t *arp, struct arp_entry *entry)
+{
+ struct arpmsg msg;
+ struct sockaddr_in *sin;
+ struct sockaddr *sa;
+
+ if (entry->arp_pa.addr_type != ADDR_TYPE_IP) {
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)msg.addrs;
+ sa = (struct sockaddr *)(sin + 1);
+
+ if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
+ return (-1);
+
+ memset(&msg.rtm, 0, sizeof(msg.rtm));
+ msg.rtm.rtm_type = RTM_GET;
+ msg.rtm.rtm_addrs = RTA_DST;
+ msg.rtm.rtm_flags = RTF_LLINFO;
+ msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);
+
+ if (arp_msg(arp, &msg) < 0)
+ return (-1);
+
+ if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
+ sizeof(*sin) + sizeof(*sa) ||
+ sin->sin_addr.s_addr != entry->arp_pa.addr_ip ||
+ sa->sa_family != AF_LINK) {
+ errno = ESRCH;
+ return (-1);
+ }
+ if (addr_ston(sa, &entry->arp_ha) < 0)
+ return (-1);
+
+ return (0);
+}
+
+#ifdef HAVE_SYS_SYSCTL_H
+int
+arp_loop(arp_t *arp, arp_handler callback, void *arg)
+{
+ struct arp_entry entry;
+ struct rt_msghdr *rtm;
+ struct sockaddr_in *sin;
+ struct sockaddr *sa;
+ char *buf, *lim, *next;
+ size_t len;
+ int ret, mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET,
+ NET_RT_FLAGS, RTF_LLINFO };
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+ return (-1);
+
+ if (len == 0)
+ return (0);
+
+ if ((buf = malloc(len)) == NULL)
+ return (-1);
+
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return (-1);
+ }
+ lim = buf + len;
+ ret = 0;
+
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ sin = (struct sockaddr_in *)(rtm + 1);
+ sa = (struct sockaddr *)(sin + 1);
+
+ if (addr_ston((struct sockaddr *)sin, &entry.arp_pa) < 0 ||
+ addr_ston(sa, &entry.arp_ha) < 0)
+ continue;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ free(buf);
+
+ return (ret);
+}
+#else
+int
+arp_loop(arp_t *arp, arp_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+#endif
+
+arp_t *
+arp_close(arp_t *arp)
+{
+ if (arp != NULL) {
+ if (arp->fd >= 0)
+ close(arp->fd);
+ free(arp);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/arp-ioctl.c b/libdnet-stripped/src/arp-ioctl.c
new file mode 100644
index 0000000..31b9f8c
--- /dev/null
+++ b/libdnet-stripped/src/arp-ioctl.c
@@ -0,0 +1,489 @@
+/*
+ * arp-ioctl.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: arp-ioctl.c 554 2005-02-09 22:31:00Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_STREAMS_MIB2
+# include <sys/sockio.h>
+# include <sys/stream.h>
+# include <sys/tihdr.h>
+# include <sys/tiuser.h>
+# include <inet/common.h>
+# include <inet/mib2.h>
+# include <inet/ip.h>
+# undef IP_ADDR_LEN
+#elif defined(HAVE_SYS_MIB_H)
+# include <sys/mib.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#ifdef HAVE_STREAMS_MIB2
+# include <netinet/in.h>
+# include <stropts.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#ifdef HAVE_LINUX_PROCFS
+#define PROC_ARP_FILE "/proc/net/arp"
+#endif
+
+struct arp_handle {
+ int fd;
+#ifdef HAVE_ARPREQ_ARP_DEV
+ intf_t *intf;
+#endif
+};
+
+arp_t *
+arp_open(void)
+{
+ arp_t *a;
+
+ if ((a = calloc(1, sizeof(*a))) != NULL) {
+#ifdef HAVE_STREAMS_MIB2
+ if ((a->fd = open(IP_DEV_NAME, O_RDWR)) < 0)
+#elif defined(HAVE_STREAMS_ROUTE)
+ if ((a->fd = open("/dev/route", O_WRONLY, 0)) < 0)
+#else
+ if ((a->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+#endif
+ return (arp_close(a));
+#ifdef HAVE_ARPREQ_ARP_DEV
+ if ((a->intf = intf_open()) == NULL)
+ return (arp_close(a));
+#endif
+ }
+ return (a);
+}
+
+#ifdef HAVE_ARPREQ_ARP_DEV
+static int
+_arp_set_dev(const struct intf_entry *entry, void *arg)
+{
+ struct arpreq *ar = (struct arpreq *)arg;
+ struct addr dst;
+ uint32_t mask;
+
+ if (entry->intf_type == INTF_TYPE_ETH &&
+ entry->intf_addr.addr_type == ADDR_TYPE_IP) {
+ addr_btom(entry->intf_addr.addr_bits, &mask, IP_ADDR_LEN);
+ addr_ston((struct sockaddr *)&ar->arp_pa, &dst);
+
+ if ((entry->intf_addr.addr_ip & mask) ==
+ (dst.addr_ip & mask)) {
+ strlcpy(ar->arp_dev, entry->intf_name,
+ sizeof(ar->arp_dev));
+ return (1);
+ }
+ }
+ return (0);
+}
+#endif
+
+int
+arp_add(arp_t *a, const struct arp_entry *entry)
+{
+ struct arpreq ar;
+
+ memset(&ar, 0, sizeof(ar));
+
+ if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
+ return (-1);
+
+ /* XXX - see arp(7) for details... */
+#ifdef __linux__
+ if (addr_ntos(&entry->arp_ha, &ar.arp_ha) < 0)
+ return (-1);
+ ar.arp_ha.sa_family = ARP_HRD_ETH;
+#else
+ /* XXX - Solaris, HP-UX, IRIX, other Mentat stacks? */
+ ar.arp_ha.sa_family = AF_UNSPEC;
+ memcpy(ar.arp_ha.sa_data, &entry->arp_ha.addr_eth, ETH_ADDR_LEN);
+#endif
+
+#ifdef HAVE_ARPREQ_ARP_DEV
+ if (intf_loop(a->intf, _arp_set_dev, &ar) != 1) {
+ errno = ESRCH;
+ return (-1);
+ }
+#endif
+ ar.arp_flags = ATF_PERM | ATF_COM;
+#ifdef hpux
+ /* XXX - screwy extended arpreq struct */
+ {
+ struct sockaddr_in *sin;
+
+ ar.arp_hw_addr_len = ETH_ADDR_LEN;
+ sin = (struct sockaddr_in *)&ar.arp_pa_mask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = IP_ADDR_BROADCAST;
+ }
+#endif
+ if (ioctl(a->fd, SIOCSARP, &ar) < 0)
+ return (-1);
+
+#ifdef HAVE_STREAMS_MIB2
+ /* XXX - force entry into ipNetToMediaTable. */
+ {
+ struct sockaddr_in sin;
+ int fd;
+
+ addr_ntos(&entry->arp_pa, (struct sockaddr *)&sin);
+ sin.sin_port = htons(666);
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (-1);
+
+ if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ close(fd);
+ return (-1);
+ }
+ write(fd, NULL, 0);
+ close(fd);
+ }
+#endif
+ return (0);
+}
+
+int
+arp_delete(arp_t *a, const struct arp_entry *entry)
+{
+ struct arpreq ar;
+
+ memset(&ar, 0, sizeof(ar));
+
+ if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
+ return (-1);
+
+ if (ioctl(a->fd, SIOCDARP, &ar) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+arp_get(arp_t *a, struct arp_entry *entry)
+{
+ struct arpreq ar;
+
+ memset(&ar, 0, sizeof(ar));
+
+ if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
+ return (-1);
+
+#ifdef HAVE_ARPREQ_ARP_DEV
+ if (intf_loop(a->intf, _arp_set_dev, &ar) != 1) {
+ errno = ESRCH;
+ return (-1);
+ }
+#endif
+ if (ioctl(a->fd, SIOCGARP, &ar) < 0)
+ return (-1);
+
+ if ((ar.arp_flags & ATF_COM) == 0) {
+ errno = ESRCH;
+ return (-1);
+ }
+ return (addr_ston(&ar.arp_ha, &entry->arp_ha));
+}
+
+#ifdef HAVE_LINUX_PROCFS
+int
+arp_loop(arp_t *a, arp_handler callback, void *arg)
+{
+ FILE *fp;
+ struct arp_entry entry;
+ char buf[BUFSIZ], ipbuf[100], macbuf[100], maskbuf[100], devbuf[100];
+ int i, type, flags, ret;
+
+ if ((fp = fopen(PROC_ARP_FILE, "r")) == NULL)
+ return (-1);
+
+ ret = 0;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ i = sscanf(buf, "%s 0x%x 0x%x %99s %99s %99s\n",
+ ipbuf, &type, &flags, macbuf, maskbuf, devbuf);
+
+ if (i < 4 || (flags & ATF_COM) == 0)
+ continue;
+
+ if (addr_aton(ipbuf, &entry.arp_pa) == 0 &&
+ addr_aton(macbuf, &entry.arp_ha) == 0) {
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ }
+ if (ferror(fp)) {
+ fclose(fp);
+ return (-1);
+ }
+ fclose(fp);
+
+ return (ret);
+}
+#elif defined (HAVE_STREAMS_MIB2)
+int
+arp_loop(arp_t *r, arp_handler callback, void *arg)
+{
+ struct arp_entry entry;
+ struct strbuf msg;
+ struct T_optmgmt_req *tor;
+ struct T_optmgmt_ack *toa;
+ struct T_error_ack *tea;
+ struct opthdr *opt;
+ mib2_ipNetToMediaEntry_t *arp, *arpend;
+ u_char buf[8192];
+ int flags, rc, atable, ret;
+
+ tor = (struct T_optmgmt_req *)buf;
+ toa = (struct T_optmgmt_ack *)buf;
+ tea = (struct T_error_ack *)buf;
+
+ tor->PRIM_type = T_OPTMGMT_REQ;
+ tor->OPT_offset = sizeof(*tor);
+ tor->OPT_length = sizeof(*opt);
+ tor->MGMT_flags = T_CURRENT;
+
+ opt = (struct opthdr *)(tor + 1);
+ opt->level = MIB2_IP;
+ opt->name = opt->len = 0;
+
+ msg.maxlen = sizeof(buf);
+ msg.len = sizeof(*tor) + sizeof(*opt);
+ msg.buf = buf;
+
+ if (putmsg(r->fd, &msg, NULL, 0) < 0)
+ return (-1);
+
+ opt = (struct opthdr *)(toa + 1);
+ msg.maxlen = sizeof(buf);
+
+ for (;;) {
+ flags = 0;
+ if ((rc = getmsg(r->fd, &msg, NULL, &flags)) < 0)
+ return (-1);
+
+ /* See if we're finished. */
+ if (rc == 0 &&
+ msg.len >= sizeof(*toa) &&
+ toa->PRIM_type == T_OPTMGMT_ACK &&
+ toa->MGMT_flags == T_SUCCESS && opt->len == 0)
+ break;
+
+ if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
+ return (-1);
+
+ if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
+ toa->PRIM_type != T_OPTMGMT_ACK ||
+ toa->MGMT_flags != T_SUCCESS)
+ return (-1);
+
+ atable = (opt->level == MIB2_IP && opt->name == MIB2_IP_22);
+
+ msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*arp));
+ msg.len = 0;
+ flags = 0;
+
+ do {
+ rc = getmsg(r->fd, NULL, &msg, &flags);
+
+ if (rc != 0 && rc != MOREDATA)
+ return (-1);
+
+ if (!atable)
+ continue;
+
+ arp = (mib2_ipNetToMediaEntry_t *)msg.buf;
+ arpend = (mib2_ipNetToMediaEntry_t *)
+ (msg.buf + msg.len);
+
+ entry.arp_pa.addr_type = ADDR_TYPE_IP;
+ entry.arp_pa.addr_bits = IP_ADDR_BITS;
+
+ entry.arp_ha.addr_type = ADDR_TYPE_ETH;
+ entry.arp_ha.addr_bits = ETH_ADDR_BITS;
+
+ for ( ; arp < arpend; arp++) {
+ entry.arp_pa.addr_ip =
+ arp->ipNetToMediaNetAddress;
+
+ memcpy(&entry.arp_ha.addr_eth,
+ arp->ipNetToMediaPhysAddress.o_bytes,
+ ETH_ADDR_LEN);
+
+ if ((ret = callback(&entry, arg)) != 0)
+ return (ret);
+ }
+ } while (rc == MOREDATA);
+ }
+ return (0);
+}
+#elif defined(HAVE_SYS_MIB_H)
+#define MAX_ARPENTRIES 512 /* XXX */
+
+int
+arp_loop(arp_t *r, arp_handler callback, void *arg)
+{
+ struct nmparms nm;
+ struct arp_entry entry;
+ mib_ipNetToMediaEnt arpentries[MAX_ARPENTRIES];
+ int fd, i, n, ret;
+
+ if ((fd = open_mib("/dev/ip", O_RDWR, 0 /* XXX */, 0)) < 0)
+ return (-1);
+
+ nm.objid = ID_ipNetToMediaTable;
+ nm.buffer = arpentries;
+ n = sizeof(arpentries);
+ nm.len = &n;
+
+ if (get_mib_info(fd, &nm) < 0) {
+ close_mib(fd);
+ return (-1);
+ }
+ close_mib(fd);
+
+ entry.arp_pa.addr_type = ADDR_TYPE_IP;
+ entry.arp_pa.addr_bits = IP_ADDR_BITS;
+
+ entry.arp_ha.addr_type = ADDR_TYPE_ETH;
+ entry.arp_ha.addr_bits = ETH_ADDR_BITS;
+
+ n /= sizeof(*arpentries);
+ ret = 0;
+
+ for (i = 0; i < n; i++) {
+ if (arpentries[i].Type == INTM_INVALID ||
+ arpentries[i].PhysAddr.o_length != ETH_ADDR_LEN)
+ continue;
+
+ entry.arp_pa.addr_ip = arpentries[i].NetAddr;
+ memcpy(&entry.arp_ha.addr_eth, arpentries[i].PhysAddr.o_bytes,
+ ETH_ADDR_LEN);
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ return (ret);
+}
+#elif defined(HAVE_NET_RADIX_H) && !defined(_AIX)
+/* XXX - Tru64, others? */
+#include <netinet/if_ether.h>
+#include <nlist.h>
+
+static int
+_kread(int fd, void *addr, void *buf, int len)
+{
+ if (lseek(fd, (off_t)addr, SEEK_SET) == (off_t)-1L)
+ return (-1);
+ return (read(fd, buf, len) == len ? 0 : -1);
+}
+
+static int
+_radix_walk(int fd, struct radix_node *rn, arp_handler callback, void *arg)
+{
+ struct radix_node rnode;
+ struct rtentry rt;
+ struct sockaddr_in sin;
+ struct arptab at;
+ struct arp_entry entry;
+ int ret = 0;
+ again:
+ _kread(fd, rn, &rnode, sizeof(rnode));
+ if (rnode.rn_b < 0) {
+ if (!(rnode.rn_flags & RNF_ROOT)) {
+ _kread(fd, rn, &rt, sizeof(rt));
+ _kread(fd, rt_key(&rt), &sin, sizeof(sin));
+ addr_ston((struct sockaddr *)&sin, &entry.arp_pa);
+ _kread(fd, rt.rt_llinfo, &at, sizeof(at));
+ if (at.at_flags & ATF_COM) {
+ addr_pack(&entry.arp_ha, ADDR_TYPE_ETH,
+ ETH_ADDR_BITS, at.at_hwaddr, ETH_ADDR_LEN);
+ if ((ret = callback(&entry, arg)) != 0)
+ return (ret);
+ }
+ }
+ if ((rn = rnode.rn_dupedkey))
+ goto again;
+ } else {
+ rn = rnode.rn_r;
+ if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0)
+ return (ret);
+ if ((ret = _radix_walk(fd, rn, callback, arg)) != 0)
+ return (ret);
+ }
+ return (ret);
+}
+
+int
+arp_loop(arp_t *r, arp_handler callback, void *arg)
+{
+ struct ifnet *ifp, ifnet;
+ struct ifnet_arp_cache_head ifarp;
+ struct radix_node_head *head;
+
+ struct nlist nl[2];
+ int fd, ret = 0;
+
+ memset(nl, 0, sizeof(nl));
+ nl[0].n_name = "ifnet";
+
+ if (knlist(nl) < 0 || nl[0].n_type == 0 ||
+ (fd = open("/dev/kmem", O_RDONLY, 0)) < 0)
+ return (-1);
+
+ for (ifp = (struct ifnet *)nl[0].n_value;
+ ifp != NULL; ifp = ifnet.if_next) {
+ _kread(fd, ifp, &ifnet, sizeof(ifnet));
+ if (ifnet.if_arp_cache_head != NULL) {
+ _kread(fd, ifnet.if_arp_cache_head,
+ &ifarp, sizeof(ifarp));
+ /* XXX - only ever one rnh, only ever AF_INET. */
+ if ((ret = _radix_walk(fd, ifarp.arp_cache_head.rnh_treetop,
+ callback, arg)) != 0)
+ break;
+ }
+ }
+ close(fd);
+ return (ret);
+}
+#else
+int
+arp_loop(arp_t *a, arp_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+#endif
+
+arp_t *
+arp_close(arp_t *a)
+{
+ if (a != NULL) {
+ if (a->fd >= 0)
+ close(a->fd);
+#ifdef HAVE_ARPREQ_ARP_DEV
+ if (a->intf != NULL)
+ intf_close(a->intf);
+#endif
+ free(a);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/arp-none.c b/libdnet-stripped/src/arp-none.c
new file mode 100644
index 0000000..293f2dd
--- /dev/null
+++ b/libdnet-stripped/src/arp-none.c
@@ -0,0 +1,58 @@
+/*
+ * arp-none.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: arp-none.c 252 2002-02-02 04:15:57Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+arp_t *
+arp_open(void)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+int
+arp_add(arp_t *a, const struct arp_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+arp_delete(arp_t *a, const struct arp_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+arp_get(arp_t *a, struct arp_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+arp_loop(arp_t *a, arp_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+arp_t *
+arp_close(arp_t *a)
+{
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/arp-win32.c b/libdnet-stripped/src/arp-win32.c
new file mode 100644
index 0000000..31bc565
--- /dev/null
+++ b/libdnet-stripped/src/arp-win32.c
@@ -0,0 +1,163 @@
+/*
+ * arp-win32.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: arp-win32.c 539 2005-01-23 07:36:54Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <ws2tcpip.h>
+#include <iphlpapi.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+struct arp_handle {
+ MIB_IPNET_TABLE2 *iptable;
+};
+
+arp_t *
+arp_open(void)
+{
+ return (calloc(1, sizeof(arp_t)));
+}
+
+int
+arp_add(arp_t *arp, const struct arp_entry *entry)
+{
+ MIB_IPFORWARDROW ipfrow;
+ MIB_IPNETROW iprow;
+
+ if (GetBestRoute(entry->arp_pa.addr_ip,
+ IP_ADDR_ANY, &ipfrow) != NO_ERROR)
+ return (-1);
+
+ iprow.dwIndex = ipfrow.dwForwardIfIndex;
+ iprow.dwPhysAddrLen = ETH_ADDR_LEN;
+ memcpy(iprow.bPhysAddr, &entry->arp_ha.addr_eth, ETH_ADDR_LEN);
+ iprow.dwAddr = entry->arp_pa.addr_ip;
+ iprow.dwType = 4; /* XXX - static */
+
+ if (CreateIpNetEntry(&iprow) != NO_ERROR)
+ return (-1);
+
+ return (0);
+}
+
+int
+arp_delete(arp_t *arp, const struct arp_entry *entry)
+{
+ MIB_IPFORWARDROW ipfrow;
+ MIB_IPNETROW iprow;
+
+ if (GetBestRoute(entry->arp_pa.addr_ip,
+ IP_ADDR_ANY, &ipfrow) != NO_ERROR)
+ return (-1);
+
+ memset(&iprow, 0, sizeof(iprow));
+ iprow.dwIndex = ipfrow.dwForwardIfIndex;
+ iprow.dwAddr = entry->arp_pa.addr_ip;
+
+ if (DeleteIpNetEntry(&iprow) != NO_ERROR) {
+ errno = ENXIO;
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+_arp_get_entry(const struct arp_entry *entry, void *arg)
+{
+ struct arp_entry *e = (struct arp_entry *)arg;
+
+ if (addr_cmp(&entry->arp_pa, &e->arp_pa) == 0) {
+ memcpy(&e->arp_ha, &entry->arp_ha, sizeof(e->arp_ha));
+ return (1);
+ }
+ return (0);
+}
+
+int
+arp_get(arp_t *arp, struct arp_entry *entry)
+{
+ if (arp_loop(arp, _arp_get_entry, entry) != 1) {
+ errno = ENXIO;
+ SetLastError(ERROR_NO_DATA);
+ return (-1);
+ }
+ return (0);
+}
+
+int
+arp_loop(arp_t *arp, arp_handler callback, void *arg)
+{
+ struct arp_entry entry;
+ int ret;
+
+ if (arp->iptable)
+ FreeMibTable(arp->iptable);
+ ret = GetIpNetTable2(AF_UNSPEC, &arp->iptable);
+ switch (ret) {
+ case NO_ERROR:
+ break;
+ case ERROR_NOT_FOUND:
+ return 0;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ entry.arp_ha.addr_type = ADDR_TYPE_ETH;
+ entry.arp_ha.addr_bits = ETH_ADDR_BITS;
+
+ for (ULONG i = 0; i < arp->iptable->NumEntries; i++) {
+ MIB_IPNET_ROW2 *row = &arp->iptable->Table[i];
+ if (row->PhysicalAddressLength != ETH_ADDR_LEN ||
+ row->IsUnreachable ||
+ row->State < NlnsReachable)
+ continue;
+ switch (row->Address.si_family) {
+ case AF_INET:
+ entry.arp_pa.addr_type = ADDR_TYPE_IP;
+ entry.arp_pa.addr_bits = IP_ADDR_BITS;
+ entry.arp_pa.addr_ip = row->Address.Ipv4.sin_addr.S_un.S_addr;
+ break;
+ case AF_INET6:
+ entry.arp_pa.addr_type = ADDR_TYPE_IP6;
+ entry.arp_pa.addr_bits = IP6_ADDR_BITS;
+ memcpy(&entry.arp_pa.addr_ip6,
+ row->Address.Ipv6.sin6_addr.u.Byte, IP6_ADDR_LEN);
+ break;
+ default:
+ continue;
+ break;
+ }
+ memcpy(&entry.arp_ha.addr_eth,
+ row->PhysicalAddress, ETH_ADDR_LEN);
+
+ if ((ret = (*callback)(&entry, arg)) != 0)
+ return (ret);
+ }
+ return (0);
+}
+
+arp_t *
+arp_close(arp_t *arp)
+{
+ if (arp != NULL) {
+ if (arp->iptable != NULL)
+ FreeMibTable(arp->iptable);
+ free(arp);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/blob.c b/libdnet-stripped/src/blob.c
new file mode 100644
index 0000000..57ff0c3
--- /dev/null
+++ b/libdnet-stripped/src/blob.c
@@ -0,0 +1,458 @@
+/*
+ * blob.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: blob.c 615 2006-01-08 16:06:49Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+static void *(*bl_malloc)(size_t) = malloc;
+static void *(*bl_realloc)(void *, size_t) = realloc;
+static void (*bl_free)(void *) = free;
+static int bl_size = BUFSIZ;
+
+static int fmt_D(int, int, blob_t *, va_list *);
+static int fmt_H(int, int, blob_t *, va_list *);
+static int fmt_b(int, int, blob_t *, va_list *);
+static int fmt_c(int, int, blob_t *, va_list *);
+static int fmt_d(int, int, blob_t *, va_list *);
+static int fmt_h(int, int, blob_t *, va_list *);
+static int fmt_s(int, int, blob_t *, va_list *);
+
+static void print_hexl(blob_t *);
+
+static blob_fmt_cb blob_ascii_fmt[] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, fmt_D, NULL, NULL, NULL,
+ fmt_H, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, fmt_b, fmt_c, fmt_d, NULL, NULL, NULL,
+ fmt_h, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, fmt_s, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+struct blob_printer {
+ char *name;
+ void (*print)(blob_t *);
+} blob_printers[] = {
+ { "hexl", print_hexl },
+ { NULL, NULL },
+};
+
+blob_t *
+blob_new(void)
+{
+ blob_t *b;
+
+ if ((b = bl_malloc(sizeof(*b))) != NULL) {
+ b->off = b->end = 0;
+ b->size = bl_size;
+ if ((b->base = bl_malloc(b->size)) == NULL) {
+ bl_free(b);
+ b = NULL;
+ }
+ }
+ return (b);
+}
+
+static int
+blob_reserve(blob_t *b, int len)
+{
+ void *p;
+ int nsize;
+
+ if (b->size < b->end + len) {
+ if (b->size == 0)
+ return (-1);
+
+ if ((nsize = b->end + len) > bl_size)
+ nsize = ((nsize / bl_size) + 1) * bl_size;
+
+ if ((p = bl_realloc(b->base, nsize)) == NULL)
+ return (-1);
+
+ b->base = p;
+ b->size = nsize;
+ }
+ b->end += len;
+
+ return (0);
+}
+
+int
+blob_read(blob_t *b, void *buf, int len)
+{
+ if (b->end - b->off < len)
+ len = b->end - b->off;
+
+ memcpy(buf, b->base + b->off, len);
+ b->off += len;
+
+ return (len);
+}
+
+int
+blob_write(blob_t *b, const void *buf, int len)
+{
+ if (b->off + len <= b->end ||
+ blob_reserve(b, b->off + len - b->end) == 0) {
+ memcpy(b->base + b->off, (u_char *)buf, len);
+ b->off += len;
+ return (len);
+ }
+ return (-1);
+}
+
+int
+blob_insert(blob_t *b, const void *buf, int len)
+{
+ if (blob_reserve(b, len) == 0 && b->size) {
+ if (b->end - b->off > 0)
+ memmove( b->base + b->off + len, b->base + b->off, b->end - b->off);
+ memcpy(b->base + b->off, buf, len);
+ b->off += len;
+ return (len);
+ }
+ return (-1);
+}
+
+int
+blob_delete(blob_t *b, void *buf, int len)
+{
+ if (b->off + len <= b->end && b->size) {
+ if (buf != NULL)
+ memcpy(buf, b->base + b->off, len);
+ memmove(b->base + b->off, b->base + b->off + len, b->end - (b->off + len));
+ b->end -= len;
+ return (len);
+ }
+ return (-1);
+}
+
+static int
+blob_fmt(blob_t *b, int pack, const char *fmt, va_list *ap)
+{
+ blob_fmt_cb fmt_cb;
+ char *p;
+ int len;
+
+ for (p = (char *)fmt; *p != '\0'; p++) {
+ if (*p == '%') {
+ p++;
+ if (isdigit((int) (unsigned char) *p)) {
+ len = strtol(p, &p, 10);
+ } else if (*p == '*') {
+ len = va_arg(*ap, int);
+ p++;
+ } else
+ len = 0;
+
+ if ((fmt_cb = blob_ascii_fmt[(int)*p]) == NULL)
+ return (-1);
+
+ if ((*fmt_cb)(pack, len, b, ap) < 0)
+ return (-1);
+ } else {
+ if (pack) {
+ if (b->off + 1 < b->end ||
+ blob_reserve(b, b->off + 1 - b->end) == 0)
+ b->base[b->off++] = *p;
+ else
+ return (-1);
+ } else {
+ if (b->base[b->off++] != *p)
+ return (-1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+blob_pack(blob_t *b, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ return (blob_fmt(b, 1, fmt, &ap));
+}
+
+int
+blob_unpack(blob_t *b, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ return (blob_fmt(b, 0, fmt, &ap));
+}
+
+int
+blob_seek(blob_t *b, int off, int whence)
+{
+ if (whence == SEEK_CUR)
+ off += b->off;
+ else if (whence == SEEK_END)
+ off += b->end;
+
+ if (off < 0 || off > b->end)
+ return (-1);
+
+ return ((b->off = off));
+}
+
+int
+blob_index(blob_t *b, const void *buf, int len)
+{
+ int i;
+
+ for (i = b->off; i <= b->end - len; i++) {
+ if (memcmp(b->base + i, buf, len) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+int
+blob_rindex(blob_t *b, const void *buf, int len)
+{
+ int i;
+
+ for (i = b->end - len; i >= 0; i--) {
+ if (memcmp(b->base + i, buf, len) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+int
+blob_print(blob_t *b, char *style, int len)
+{
+ struct blob_printer *bp;
+
+ for (bp = blob_printers; bp->name != NULL; bp++) {
+ if (strcmp(bp->name, style) == 0)
+ bp->print(b);
+ }
+ return (0);
+}
+
+int
+blob_sprint(blob_t *b, char *style, int len, char *dst, int size)
+{
+ return (0);
+}
+
+blob_t *
+blob_free(blob_t *b)
+{
+ if (b->size)
+ bl_free(b->base);
+ bl_free(b);
+ return (NULL);
+}
+
+int
+blob_register_alloc(size_t size, void *(bmalloc)(size_t),
+ void (*bfree)(void *), void *(*brealloc)(void *, size_t))
+{
+ bl_size = size;
+ if (bmalloc != NULL)
+ bl_malloc = bmalloc;
+ if (bfree != NULL)
+ bl_free = bfree;
+ if (brealloc != NULL)
+ bl_realloc = brealloc;
+ return (0);
+}
+
+int
+blob_register_pack(char c, blob_fmt_cb fmt_cb)
+{
+ if (blob_ascii_fmt[(int)c] == NULL) {
+ blob_ascii_fmt[(int)c] = fmt_cb;
+ return (0);
+ }
+ return (-1);
+}
+
+static int
+fmt_D(int pack, int len, blob_t *b, va_list *ap)
+{
+ if (len) return (-1);
+
+ if (pack) {
+ uint32_t n = va_arg(*ap, uint32_t);
+ n = htonl(n);
+ if (blob_write(b, &n, sizeof(n)) < 0)
+ return (-1);
+ } else {
+ uint32_t *n = va_arg(*ap, uint32_t *);
+ if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
+ return (-1);
+ *n = ntohl(*n);
+ }
+ return (0);
+}
+
+static int
+fmt_H(int pack, int len, blob_t *b, va_list *ap)
+{
+ if (len) return (-1);
+
+ if (pack) {
+ uint16_t n = va_arg(*ap, int);
+ n = htons(n);
+ if (blob_write(b, &n, sizeof(n)) < 0)
+ return (-1);
+ } else {
+ uint16_t *n = va_arg(*ap, uint16_t *);
+ if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
+ return (-1);
+ *n = ntohs(*n);
+ }
+ return (0);
+}
+
+static int
+fmt_b(int pack, int len, blob_t *b, va_list *ap)
+{
+ void *p = va_arg(*ap, void *);
+
+ if (len <= 0) return (-1);
+
+ if (pack)
+ return (blob_write(b, p, len));
+ else
+ return (blob_read(b, p, len));
+}
+
+static int
+fmt_c(int pack, int len, blob_t *b, va_list *ap)
+{
+ if (len) return (-1);
+
+ if (pack) {
+ uint8_t n = va_arg(*ap, int);
+ return (blob_write(b, &n, sizeof(n)));
+ } else {
+ uint8_t *n = va_arg(*ap, uint8_t *);
+ return (blob_read(b, n, sizeof(*n)));
+ }
+}
+
+static int
+fmt_d(int pack, int len, blob_t *b, va_list *ap)
+{
+ if (len) return (-1);
+
+ if (pack) {
+ uint32_t n = va_arg(*ap, uint32_t);
+ return (blob_write(b, &n, sizeof(n)));
+ } else {
+ uint32_t *n = va_arg(*ap, uint32_t *);
+ return (blob_read(b, n, sizeof(*n)));
+ }
+}
+
+static int
+fmt_h(int pack, int len, blob_t *b, va_list *ap)
+{
+ if (len) return (-1);
+
+ if (pack) {
+ uint16_t n = va_arg(*ap, int);
+ return (blob_write(b, &n, sizeof(n)));
+ } else {
+ uint16_t *n = va_arg(*ap, uint16_t *);
+ return (blob_read(b, n, sizeof(*n)));
+ }
+}
+
+static int
+fmt_s(int pack, int len, blob_t *b, va_list *ap)
+{
+ char *p = va_arg(*ap, char *);
+ char c = '\0';
+ int i, end;
+
+ if (pack) {
+ if (len > 0) {
+ if ((c = p[len - 1]) != '\0')
+ p[len - 1] = '\0';
+ } else
+ len = strlen(p) + 1;
+
+ if (blob_write(b, p, len) > 0) {
+ if (c != '\0')
+ p[len - 1] = c;
+ return (len);
+ }
+ } else {
+ if (len <= 0) return (-1);
+
+ if ((end = b->end - b->off) < len)
+ end = len;
+
+ for (i = 0; i < end; i++) {
+ if ((p[i] = b->base[b->off + i]) == '\0') {
+ b->off += i + 1;
+ return (i);
+ }
+ }
+ }
+ return (-1);
+}
+
+static void
+print_hexl(blob_t *b)
+{
+ u_int i, j, jm, len;
+ u_char *p;
+ int c;
+
+ p = b->base + b->off;
+ len = b->end - b->off;
+
+ printf("\n");
+
+ for (i = 0; i < len; i += 0x10) {
+ printf(" %04x: ", (u_int)(i + b->off));
+ jm = len - i;
+ jm = jm > 16 ? 16 : jm;
+
+ for (j = 0; j < jm; j++) {
+ printf((j % 2) ? "%02x " : "%02x", (u_int)p[i + j]);
+ }
+ for (; j < 16; j++) {
+ printf((j % 2) ? " " : " ");
+ }
+ printf(" ");
+
+ for (j = 0; j < jm; j++) {
+ c = p[i + j];
+ printf("%c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+ }
+}
diff --git a/libdnet-stripped/src/crc32ct.h b/libdnet-stripped/src/crc32ct.h
new file mode 100644
index 0000000..8c3ac92
--- /dev/null
+++ b/libdnet-stripped/src/crc32ct.h
@@ -0,0 +1,83 @@
+/*
+ * crc32ct.h
+ *
+ * Public domain.
+ *
+ * $Id$
+ */
+
+#ifndef CRC32CT_H
+#define CRC32CT_H
+
+#define CRC32C_POLY 0x1EDC6F41
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+
+static unsigned long crc_c[256] = {
+0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
+};
+
+#endif /* CRC32CT_H */
+
diff --git a/libdnet-stripped/src/err.c b/libdnet-stripped/src/err.c
new file mode 100644
index 0000000..cd201c3
--- /dev/null
+++ b/libdnet-stripped/src/err.c
@@ -0,0 +1,110 @@
+/*
+ * err.c
+ *
+ * Adapted from OpenBSD libc *err* *warn* code.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+void
+err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (fmt != NULL) {
+ (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stderr, ": ");
+ }
+ va_end(ap);
+#ifdef _WIN32
+ (void)fprintf(stderr, "error %lu\n", GetLastError());
+#else
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+#endif
+ exit(eval);
+}
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (fmt != NULL) {
+ (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stderr, ": ");
+ }
+ va_end(ap);
+#ifdef _WIN32
+ (void)fprintf(stderr, "error %lu\n", GetLastError());
+#else
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+#endif
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (fmt != NULL)
+ (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stderr, "\n");
+ va_end(ap);
+ exit(eval);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (fmt != NULL)
+ (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stderr, "\n");
+ va_end(ap);
+}
+
diff --git a/libdnet-stripped/src/eth-bsd.c b/libdnet-stripped/src/eth-bsd.c
new file mode 100644
index 0000000..1f4bde6
--- /dev/null
+++ b/libdnet-stripped/src/eth-bsd.c
@@ -0,0 +1,172 @@
+/*
+ * eth-bsd.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-bsd.c 630 2006-02-02 04:17:39Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_ROUTE_RT_MSGHDR)
+#include <sys/sysctl.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#endif
+#include <net/bpf.h>
+#include <net/if.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct eth_handle {
+ int fd;
+ char device[16];
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ struct ifreq ifr;
+ char file[32];
+ eth_t *e;
+ int i;
+
+ if ((e = calloc(1, sizeof(*e))) != NULL) {
+ for (i = 0; i < 128; i++) {
+ snprintf(file, sizeof(file), "/dev/bpf%d", i);
+ /* This would be O_WRONLY, but Mac OS X 10.6 has a bug
+ where that prevents other users of the interface
+ from seeing incoming traffic, even in other
+ processes. */
+ e->fd = open(file, O_RDWR);
+ if (e->fd != -1 || errno != EBUSY)
+ break;
+ }
+ if (e->fd < 0)
+ return (eth_close(e));
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+ if (ioctl(e->fd, BIOCSETIF, (char *)&ifr) < 0)
+ return (eth_close(e));
+#ifdef BIOCSHDRCMPLT
+ i = 1;
+ if (ioctl(e->fd, BIOCSHDRCMPLT, &i) < 0)
+ return (eth_close(e));
+#endif
+ strlcpy(e->device, device, sizeof(e->device));
+ }
+ return (e);
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ return (write(e->fd, buf, len));
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ free(e);
+ }
+ return (NULL);
+}
+
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_ROUTE_RT_MSGHDR)
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ struct if_msghdr *ifm;
+ struct sockaddr_dl *sdl;
+ struct addr ha;
+ u_char *p, *buf;
+ size_t len;
+ int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+ return (-1);
+
+ if ((buf = malloc(len)) == NULL)
+ return (-1);
+
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return (-1);
+ }
+ for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *)p;
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+
+ if (ifm->ifm_type != RTM_IFINFO ||
+ (ifm->ifm_addrs & RTA_IFP) == 0)
+ continue;
+
+ if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
+ memcmp(sdl->sdl_data, e->device, sdl->sdl_nlen) != 0)
+ continue;
+
+ if (addr_ston((struct sockaddr *)sdl, &ha) == 0)
+ break;
+ }
+ free(buf);
+
+ if (p >= buf + len) {
+ errno = ESRCH;
+ return (-1);
+ }
+ memcpy(ea, &ha.addr_eth, sizeof(*ea));
+
+ return (0);
+}
+#else
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+#endif
+
+#if defined(SIOCSIFLLADDR)
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ struct ifreq ifr;
+ struct addr ha;
+
+ ha.addr_type = ADDR_TYPE_ETH;
+ ha.addr_bits = ETH_ADDR_BITS;
+ memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, e->device, sizeof(ifr.ifr_name));
+ addr_ntos(&ha, &ifr.ifr_addr);
+
+ return (ioctl(e->fd, SIOCSIFLLADDR, &ifr));
+}
+#else
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+#endif
diff --git a/libdnet-stripped/src/eth-dlpi.c b/libdnet-stripped/src/eth-dlpi.c
new file mode 100644
index 0000000..dc7b8c9
--- /dev/null
+++ b/libdnet-stripped/src/eth-dlpi.c
@@ -0,0 +1,304 @@
+/*
+ * eth-dlpi.c
+ *
+ * Based on Neal Nuckolls' 1992 "How to Use DLPI" paper.
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-dlpi.c 560 2005-02-10 16:48:36Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#ifdef HAVE_SYS_DLPI_H
+#include <sys/dlpi.h>
+#elif defined(HAVE_SYS_DLPIHDR_H)
+#include <sys/dlpihdr.h>
+#endif
+#ifdef HAVE_SYS_DLPI_EXT_H
+#include <sys/dlpi_ext.h>
+#endif
+#include <sys/stream.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif
+
+struct eth_handle {
+ int fd;
+ int sap_len;
+};
+
+static int
+dlpi_msg(int fd, union DL_primitives *dlp, int rlen, int flags,
+ int ack, int alen, int size)
+{
+ struct strbuf ctl;
+
+ ctl.maxlen = 0;
+ ctl.len = rlen;
+ ctl.buf = (caddr_t)dlp;
+
+ if (putmsg(fd, &ctl, NULL, flags) < 0)
+ return (-1);
+
+ ctl.maxlen = size;
+ ctl.len = 0;
+
+ flags = 0;
+
+ if (getmsg(fd, &ctl, NULL, &flags) < 0)
+ return (-1);
+
+ if (dlp->dl_primitive != ack || ctl.len < alen)
+ return (-1);
+
+ return (0);
+}
+
+#if defined(DLIOCRAW) || defined(HAVE_SYS_DLPIHDR_H)
+static int
+strioctl(int fd, int cmd, int len, char *dp)
+{
+ struct strioctl str;
+
+ str.ic_cmd = cmd;
+ str.ic_timout = INFTIM;
+ str.ic_len = len;
+ str.ic_dp = dp;
+
+ if (ioctl(fd, I_STR, &str) < 0)
+ return (-1);
+
+ return (str.ic_len);
+}
+#endif
+
+#ifdef HAVE_SYS_DLPIHDR_H
+/* XXX - OSF1 is nuts */
+#define ND_GET ('N' << 8 + 0)
+
+static int
+eth_match_ppa(eth_t *e, const char *device)
+{
+ char *p, dev[16], buf[256];
+ int len, ppa;
+
+ strlcpy(buf, "dl_ifnames", sizeof(buf));
+
+ if ((len = strioctl(e->fd, ND_GET, sizeof(buf), buf)) < 0)
+ return (-1);
+
+ for (p = buf; p < buf + len; p += strlen(p) + 1) {
+ ppa = -1;
+ if (sscanf(p, "%s (PPA %d)\n", dev, &ppa) != 2)
+ break;
+ if (strcmp(dev, device) == 0)
+ break;
+ }
+ return (ppa);
+}
+#else
+static char *
+dev_find_ppa(char *dev)
+{
+ char *p;
+
+ p = dev + strlen(dev);
+ while (p > dev && strchr("0123456789", *(p - 1)) != NULL)
+ p--;
+ if (*p == '\0')
+ return NULL;
+
+ return p;
+}
+#endif
+
+eth_t *
+eth_open(const char *device)
+{
+ union DL_primitives *dlp;
+ uint32_t buf[8192];
+ char *p, dev[16];
+ eth_t *e;
+ int ppa;
+
+ if ((e = calloc(1, sizeof(*e))) == NULL)
+ return (NULL);
+
+#ifdef HAVE_SYS_DLPIHDR_H
+ if ((e->fd = open("/dev/streams/dlb", O_RDWR)) < 0)
+ return (eth_close(e));
+
+ if ((ppa = eth_match_ppa(e, device)) < 0) {
+ errno = ESRCH;
+ return (eth_close(e));
+ }
+#else
+ e->fd = -1;
+ snprintf(dev, sizeof(dev), "/dev/%s", device);
+ if ((p = dev_find_ppa(dev)) == NULL) {
+ errno = EINVAL;
+ return (eth_close(e));
+ }
+ ppa = atoi(p);
+ *p = '\0';
+
+ if ((e->fd = open(dev, O_RDWR)) < 0) {
+ snprintf(dev, sizeof(dev), "/dev/%s", device);
+ if ((e->fd = open(dev, O_RDWR)) < 0) {
+ snprintf(dev, sizeof(dev), "/dev/net/%s", device);
+ if ((e->fd = open(dev, O_RDWR)) < 0)
+ return (eth_close(e));
+ }
+ }
+#endif
+ dlp = (union DL_primitives *)buf;
+ dlp->info_req.dl_primitive = DL_INFO_REQ;
+
+ if (dlpi_msg(e->fd, dlp, DL_INFO_REQ_SIZE, RS_HIPRI,
+ DL_INFO_ACK, DL_INFO_ACK_SIZE, sizeof(buf)) < 0)
+ return (eth_close(e));
+
+ e->sap_len = dlp->info_ack.dl_sap_length;
+
+ if (dlp->info_ack.dl_provider_style == DL_STYLE2) {
+ dlp->attach_req.dl_primitive = DL_ATTACH_REQ;
+ dlp->attach_req.dl_ppa = ppa;
+
+ if (dlpi_msg(e->fd, dlp, DL_ATTACH_REQ_SIZE, 0,
+ DL_OK_ACK, DL_OK_ACK_SIZE, sizeof(buf)) < 0)
+ return (eth_close(e));
+ }
+ memset(&dlp->bind_req, 0, DL_BIND_REQ_SIZE);
+ dlp->bind_req.dl_primitive = DL_BIND_REQ;
+#ifdef DL_HP_RAWDLS
+ dlp->bind_req.dl_sap = 24; /* from HP-UX DLPI programmers guide */
+ dlp->bind_req.dl_service_mode = DL_HP_RAWDLS;
+#else
+ dlp->bind_req.dl_sap = DL_ETHER;
+ dlp->bind_req.dl_service_mode = DL_CLDLS;
+#endif
+ if (dlpi_msg(e->fd, dlp, DL_BIND_REQ_SIZE, 0,
+ DL_BIND_ACK, DL_BIND_ACK_SIZE, sizeof(buf)) < 0)
+ return (eth_close(e));
+#ifdef DLIOCRAW
+ if (strioctl(e->fd, DLIOCRAW, 0, NULL) < 0)
+ return (eth_close(e));
+#endif
+ return (e);
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+#if defined(DLIOCRAW)
+ return (write(e->fd, buf, len));
+#else
+ union DL_primitives *dlp;
+ struct strbuf ctl, data;
+ struct eth_hdr *eth;
+ uint32_t ctlbuf[8192];
+ u_char sap[4] = { 0, 0, 0, 0 };
+ int dlen;
+
+ dlp = (union DL_primitives *)ctlbuf;
+#ifdef DL_HP_RAWDATA_REQ
+ dlp->dl_primitive = DL_HP_RAWDATA_REQ;
+ dlen = DL_HP_RAWDATA_REQ_SIZE;
+#else
+ dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
+ dlp->unitdata_req.dl_dest_addr_length = ETH_ADDR_LEN;
+ dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE;
+ dlp->unitdata_req.dl_priority.dl_min =
+ dlp->unitdata_req.dl_priority.dl_max = 0;
+ dlen = DL_UNITDATA_REQ_SIZE;
+#endif
+ eth = (struct eth_hdr *)buf;
+ *(uint16_t *)sap = ntohs(eth->eth_type);
+
+ /* XXX - DLSAP setup logic from ISC DHCP */
+ ctl.maxlen = 0;
+ ctl.len = dlen + ETH_ADDR_LEN + abs(e->sap_len);
+ ctl.buf = (char *)ctlbuf;
+
+ if (e->sap_len >= 0) {
+ memcpy(ctlbuf + dlen, sap, e->sap_len);
+ memcpy(ctlbuf + dlen + e->sap_len,
+ eth->eth_dst.data, ETH_ADDR_LEN);
+ } else {
+ memcpy(ctlbuf + dlen, eth->eth_dst.data, ETH_ADDR_LEN);
+ memcpy(ctlbuf + dlen + ETH_ADDR_LEN, sap, abs(e->sap_len));
+ }
+ data.maxlen = 0;
+ data.len = len;
+ data.buf = (char *)buf;
+
+ if (putmsg(e->fd, &ctl, &data, 0) < 0)
+ return (-1);
+
+ return (len);
+#endif
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ free(e);
+ }
+ return (NULL);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ union DL_primitives *dlp;
+ u_char buf[2048];
+
+ dlp = (union DL_primitives *)buf;
+ dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
+ dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
+
+ if (dlpi_msg(e->fd, dlp, DL_PHYS_ADDR_REQ_SIZE, 0,
+ DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, sizeof(buf)) < 0)
+ return (-1);
+
+ memcpy(ea, buf + dlp->physaddr_ack.dl_addr_offset, sizeof(*ea));
+
+ return (0);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ union DL_primitives *dlp;
+ u_char buf[2048];
+
+ dlp = (union DL_primitives *)buf;
+ dlp->set_physaddr_req.dl_primitive = DL_SET_PHYS_ADDR_REQ;
+ dlp->set_physaddr_req.dl_addr_length = ETH_ADDR_LEN;
+ dlp->set_physaddr_req.dl_addr_offset = DL_SET_PHYS_ADDR_REQ_SIZE;
+
+ memcpy(buf + DL_SET_PHYS_ADDR_REQ_SIZE, ea, sizeof(*ea));
+
+ return (dlpi_msg(e->fd, dlp, DL_SET_PHYS_ADDR_REQ_SIZE + ETH_ADDR_LEN,
+ 0, DL_OK_ACK, DL_OK_ACK_SIZE, sizeof(buf)));
+}
diff --git a/libdnet-stripped/src/eth-linux.c b/libdnet-stripped/src/eth-linux.c
new file mode 100644
index 0000000..9b10840
--- /dev/null
+++ b/libdnet-stripped/src/eth-linux.c
@@ -0,0 +1,118 @@
+/*
+ * eth-linux.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-linux.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <features.h>
+#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#endif /* __GLIBC__ */
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct eth_handle {
+ int fd;
+ struct ifreq ifr;
+ struct sockaddr_ll sll;
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ eth_t *e;
+ int n;
+
+ if ((e = calloc(1, sizeof(*e))) != NULL) {
+ if ((e->fd = socket(PF_PACKET, SOCK_RAW,
+ htons(ETH_P_ALL))) < 0)
+ return (eth_close(e));
+#ifdef SO_BROADCAST
+ n = 1;
+ if (setsockopt(e->fd, SOL_SOCKET, SO_BROADCAST, &n,
+ sizeof(n)) < 0)
+ return (eth_close(e));
+#endif
+ strlcpy(e->ifr.ifr_name, device, sizeof(e->ifr.ifr_name));
+
+ if (ioctl(e->fd, SIOCGIFINDEX, &e->ifr) < 0)
+ return (eth_close(e));
+
+ e->sll.sll_family = AF_PACKET;
+ e->sll.sll_ifindex = e->ifr.ifr_ifindex;
+ }
+ return (e);
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ struct eth_hdr *eth = (struct eth_hdr *)buf;
+
+ e->sll.sll_protocol = eth->eth_type;
+
+ return (sendto(e->fd, buf, len, 0, (struct sockaddr *)&e->sll,
+ sizeof(e->sll)));
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ free(e);
+ }
+ return (NULL);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ struct addr ha;
+
+ if (ioctl(e->fd, SIOCGIFHWADDR, &e->ifr) < 0)
+ return (-1);
+
+ if (addr_ston(&e->ifr.ifr_hwaddr, &ha) < 0)
+ return (-1);
+
+ memcpy(ea, &ha.addr_eth, sizeof(*ea));
+ return (0);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ struct addr ha;
+
+ ha.addr_type = ADDR_TYPE_ETH;
+ ha.addr_bits = ETH_ADDR_BITS;
+ memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);
+
+ addr_ntos(&ha, &e->ifr.ifr_hwaddr);
+
+ return (ioctl(e->fd, SIOCSIFHWADDR, &e->ifr));
+}
diff --git a/libdnet-stripped/src/eth-ndd.c b/libdnet-stripped/src/eth-ndd.c
new file mode 100644
index 0000000..7ac196c
--- /dev/null
+++ b/libdnet-stripped/src/eth-ndd.c
@@ -0,0 +1,117 @@
+/*
+ * eth-ndd.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-ndd.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ndd_var.h>
+#include <sys/kinfo.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct eth_handle {
+ char device[16];
+ int fd;
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ struct sockaddr_ndd_8022 sa;
+ eth_t *e;
+
+ if ((e = calloc(1, sizeof(*e))) == NULL)
+ return (NULL);
+
+ if ((e->fd = socket(AF_NDD, SOCK_DGRAM, NDD_PROT_ETHER)) < 0)
+ return (eth_close(e));
+
+ sa.sndd_8022_family = AF_NDD;
+ sa.sndd_8022_len = sizeof(sa);
+ sa.sndd_8022_filtertype = NS_ETHERTYPE;
+ sa.sndd_8022_ethertype = 0;
+ sa.sndd_8022_filterlen = sizeof(struct ns_8022);
+ strlcpy(sa.sndd_8022_nddname, device, sizeof(sa.sndd_8022_nddname));
+
+ if (bind(e->fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ return (eth_close(e));
+
+ if (connect(e->fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ return (eth_close(e));
+
+ /* XXX - SO_BROADCAST needed? */
+
+ return (e);
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ return (write(e->fd, buf, len));
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ free(e);
+ }
+ return (NULL);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ struct kinfo_ndd *nddp;
+ int size;
+ void *end;
+
+ if ((size = getkerninfo(KINFO_NDD, 0, 0, 0)) == 0) {
+ errno = ENOENT;
+ return (-1);
+ } else if (size < 0)
+ return (-1);
+
+ if ((nddp = malloc(size)) == NULL)
+ return (-1);
+
+ if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
+ free(nddp);
+ return (-1);
+ }
+ for (end = (void *)nddp + size; (void *)nddp < end; nddp++) {
+ if (strcmp(nddp->ndd_alias, e->device) == 0 ||
+ strcmp(nddp->ndd_name, e->device) == 0) {
+ memcpy(ea, nddp->ndd_addr, sizeof(*ea));
+ }
+ }
+ free(nddp);
+
+ if ((void *)nddp >= end) {
+ errno = ESRCH;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ errno = ENOSYS;
+ return (-1);
+}
diff --git a/libdnet-stripped/src/eth-none.c b/libdnet-stripped/src/eth-none.c
new file mode 100644
index 0000000..1ad0fef
--- /dev/null
+++ b/libdnet-stripped/src/eth-none.c
@@ -0,0 +1,51 @@
+/*
+ * eth-none.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-none.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+eth_t *
+eth_open(const char *device)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ return (NULL);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ errno = ENOSYS;
+ return (-1);
+}
diff --git a/libdnet-stripped/src/eth-pfilt.c b/libdnet-stripped/src/eth-pfilt.c
new file mode 100644
index 0000000..aec0e12
--- /dev/null
+++ b/libdnet-stripped/src/eth-pfilt.c
@@ -0,0 +1,87 @@
+/*
+ * eth-pfilt.c
+ *
+ * XXX - requires 'cd dev && ./MAKEDEV pfilt' if not already configured...
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-pfilt.c 563 2005-02-10 17:06:36Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/pfilt.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct eth_handle {
+ int fd;
+ int sock;
+ char device[16];
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ struct eth_handle *e;
+ int fd;
+
+ if ((e = calloc(1, sizeof(*e))) != NULL) {
+ strlcpy(e->device, device, sizeof(e->device));
+ if ((e->fd = pfopen(e->device, O_WRONLY)) < 0 ||
+ (e->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ e = eth_close(e);
+ }
+ return (e);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ struct ifdevea ifd;
+
+ strlcpy(ifd.ifr_name, e->device, sizeof(ifd.ifr_name));
+ if (ioctl(e->sock, SIOCRPHYSADDR, &ifd) < 0)
+ return (-1);
+ memcpy(ea, ifd.current_pa, ETH_ADDR_LEN);
+ return (0);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ struct ifdevea ifd;
+
+ strlcpy(ifd.ifr_name, e->device, sizeof(ifd.ifr_name));
+ memcpy(ifd.current_pa, ea, ETH_ADDR_LEN);
+ return (ioctl(e->sock, SIOCSPHYSADDR, &ifd));
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ return (write(e->fd, buf, len));
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ if (e->sock >= 0)
+ close(e->sock);
+ free(e);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/eth-snoop.c b/libdnet-stripped/src/eth-snoop.c
new file mode 100644
index 0000000..a0147b8
--- /dev/null
+++ b/libdnet-stripped/src/eth-snoop.c
@@ -0,0 +1,109 @@
+/*
+ * eth-snoop.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-snoop.c 548 2005-01-30 06:01:57Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/raw.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+struct eth_handle {
+ int fd;
+ struct ifreq ifr;
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ struct sockaddr_raw sr;
+ eth_t *e;
+ int n;
+
+ if ((e = calloc(1, sizeof(*e))) == NULL)
+ return (NULL);
+
+ if ((e->fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP)) < 0)
+ return (eth_close(e));
+
+ memset(&sr, 0, sizeof(sr));
+ sr.sr_family = AF_RAW;
+ strlcpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
+
+ if (bind(e->fd, (struct sockaddr *)&sr, sizeof(sr)) < 0)
+ return (eth_close(e));
+
+ n = 60000;
+ if (setsockopt(e->fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) < 0)
+ return (eth_close(e));
+
+ strlcpy(e->ifr.ifr_name, device, sizeof(e->ifr.ifr_name));
+
+ return (e);
+}
+
+int
+eth_get(eth_t *e, eth_addr_t *ea)
+{
+ struct addr ha;
+
+ if (ioctl(e->fd, SIOCGIFADDR, &e->ifr) < 0)
+ return (-1);
+
+ if (addr_ston(&e->ifr.ifr_addr, &ha) < 0)
+ return (-1);
+
+ if (ha.addr_type != ADDR_TYPE_ETH) {
+ errno = EINVAL;
+ return (-1);
+ }
+ memcpy(ea, &ha.addr_eth, sizeof(*ea));
+
+ return (0);
+}
+
+int
+eth_set(eth_t *e, const eth_addr_t *ea)
+{
+ struct addr ha;
+
+ ha.addr_type = ADDR_TYPE_ETH;
+ ha.addr_bits = ETH_ADDR_BITS;
+ memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);
+
+ if (addr_ntos(&ha, &e->ifr.ifr_addr) < 0)
+ return (-1);
+
+ return (ioctl(e->fd, SIOCSIFADDR, &e->ifr));
+}
+
+ssize_t
+eth_send(eth_t *e, const void *buf, size_t len)
+{
+ return (write(e->fd, buf, len));
+}
+
+eth_t *
+eth_close(eth_t *e)
+{
+ if (e != NULL) {
+ if (e->fd >= 0)
+ close(e->fd);
+ free(e);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c
new file mode 100644
index 0000000..fc6aed1
--- /dev/null
+++ b/libdnet-stripped/src/eth-win32.c
@@ -0,0 +1,163 @@
+/*
+ * eth-win32.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth-win32.c 613 2005-09-26 02:46:57Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+/* XXX - VC++ 6.0 bogosity */
+#define sockaddr_storage sockaddr
+#undef sockaddr_storage
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+#include <winsock2.h>
+#include "pcap.h"
+#include <Packet32.h>
+#include <Ntddndis.h>
+
+/* From Npcap's Loopback.h */
+/*
+ * * Structure of a DLT_NULL header.
+ * */
+typedef struct _DLT_NULL_HEADER
+{
+ UINT null_type;
+} DLT_NULL_HEADER, *PDLT_NULL_HEADER;
+
+/*
+ * * The length of the combined header.
+ * */
+#define DLT_NULL_HDR_LEN sizeof(DLT_NULL_HEADER)
+
+/*
+ * * Types in a DLT_NULL (Loopback) header.
+ * */
+#define DLTNULLTYPE_IP 0x00000002 /* IP protocol */
+#define DLTNULLTYPE_IPV6 0x00000018 /* IPv6 */
+/* END Loopback.h */
+
+struct eth_handle {
+ LPADAPTER lpa;
+ LPPACKET pkt;
+ NetType type;
+};
+
+eth_t *
+eth_open(const char *device)
+{
+ eth_t *eth;
+ char pcapdev[128];
+
+ if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0)
+ return (NULL);
+
+ if ((eth = calloc(1, sizeof(*eth))) == NULL)
+ return (NULL);
+ eth->lpa = PacketOpenAdapter(pcapdev);
+ if (eth->lpa == NULL) {
+ eth_close(eth);
+ return (NULL);
+ }
+ PacketSetBuff(eth->lpa, 512000);
+ eth->pkt = PacketAllocatePacket();
+ if (eth->pkt == NULL) {
+ eth_close(eth);
+ return NULL;
+ }
+ if (!PacketGetNetType(eth->lpa, &eth->type)) {
+ eth_close(eth);
+ return NULL;
+ }
+
+ return (eth);
+}
+
+ssize_t
+eth_send(eth_t *eth, const void *buf, size_t len)
+{
+ /* 14-byte Ethernet header, but DLT_NULL is a 4-byte header. Skip over the difference */
+ DLT_NULL_HEADER *hdr = (DLT_NULL_HEADER *)((uint8_t *)buf + ETH_HDR_LEN - DLT_NULL_HDR_LEN);
+ if (eth->type.LinkType == NdisMediumNull) {
+ switch (ntohs(((struct eth_hdr *)buf)->eth_type)) {
+ case ETH_TYPE_IP:
+ hdr->null_type = DLTNULLTYPE_IP;
+ break;
+ case ETH_TYPE_IPV6:
+ hdr->null_type = DLTNULLTYPE_IPV6;
+ break;
+ default:
+ hdr->null_type = 0;
+ break;
+ }
+ PacketInitPacket(eth->pkt, (void *)((uint8_t *)buf + ETH_HDR_LEN - DLT_NULL_HDR_LEN), (UINT) (len - ETH_HDR_LEN + DLT_NULL_HDR_LEN));
+ PacketSendPacket(eth->lpa, eth->pkt, TRUE);
+ }
+ else {
+ PacketInitPacket(eth->pkt, (void *)buf, (UINT) len);
+ PacketSendPacket(eth->lpa, eth->pkt, TRUE);
+ }
+ return (ssize_t)(len);
+}
+
+eth_t *
+eth_close(eth_t *eth)
+{
+ if (eth != NULL) {
+ if (eth->pkt != NULL)
+ PacketFreePacket(eth->pkt);
+ if (eth->lpa != NULL)
+ PacketCloseAdapter(eth->lpa);
+ free(eth);
+ }
+ return (NULL);
+}
+
+int
+eth_get(eth_t *eth, eth_addr_t *ea)
+{
+ PACKET_OID_DATA *data;
+ u_char buf[512];
+
+ data = (PACKET_OID_DATA *)buf;
+ data->Oid = OID_802_3_CURRENT_ADDRESS;
+ data->Length = ETH_ADDR_LEN;
+
+ if (PacketRequest(eth->lpa, FALSE, data) == TRUE) {
+ memcpy(ea, data->Data, ETH_ADDR_LEN);
+ return (0);
+ }
+ return (-1);
+}
+
+int
+eth_set(eth_t *eth, const eth_addr_t *ea)
+{
+ PACKET_OID_DATA *data;
+ u_char buf[512];
+
+ data = (PACKET_OID_DATA *)buf;
+ data->Oid = OID_802_3_CURRENT_ADDRESS;
+ memcpy(data->Data, ea, ETH_ADDR_LEN);
+ data->Length = ETH_ADDR_LEN;
+
+ if (PacketRequest(eth->lpa, TRUE, data) == TRUE)
+ return (0);
+
+ return (-1);
+}
+
+int
+eth_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen)
+{
+ return intf_get_pcap_devname(intf_name, pcapdev, pcapdevlen);
+}
diff --git a/libdnet-stripped/src/fw-none.c b/libdnet-stripped/src/fw-none.c
new file mode 100644
index 0000000..f2c84bf
--- /dev/null
+++ b/libdnet-stripped/src/fw-none.c
@@ -0,0 +1,49 @@
+/*
+ * fw-none.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: fw-none.c 208 2002-01-20 21:23:28Z dugsong $
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+fw_t *
+fw_open(void)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+int
+fw_add(fw_t *f, const struct fw_rule *rule)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+fw_delete(fw_t *f, const struct fw_rule *rule)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+fw_loop(fw_t *f, fw_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+fw_t *
+fw_close(fw_t *f)
+{
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c
new file mode 100644
index 0000000..245289f
--- /dev/null
+++ b/libdnet-stripped/src/intf-win32.c
@@ -0,0 +1,621 @@
+/*
+ * intf-win32.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: intf-win32.c 632 2006-08-10 04:36:52Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <iphlpapi.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+#include "pcap.h"
+#include <Packet32.h>
+#include <Ntddndis.h>
+
+int g_has_npcap_loopback = 0;
+#define _DEVICE_PREFIX "\\Device\\"
+
+struct ifcombo {
+ struct {
+ DWORD ipv4;
+ DWORD ipv6;
+ } *idx;
+ int cnt;
+ int max;
+};
+
+/* XXX - ipifcons.h incomplete, use IANA ifTypes MIB */
+#define MIB_IF_TYPE_TUNNEL 131
+#define MIB_IF_TYPE_MAX MAX_IF_TYPE
+
+struct intf_handle {
+ struct ifcombo ifcombo[MIB_IF_TYPE_MAX];
+ IP_ADAPTER_ADDRESSES *iftable;
+};
+
+static char *
+_ifcombo_name(int type)
+{
+ char *name = NULL;
+
+ switch (type) {
+ case IF_TYPE_ETHERNET_CSMACD:
+ case IF_TYPE_IEEE80211:
+ name = "eth";
+ break;
+ case IF_TYPE_ISO88025_TOKENRING:
+ name = "tr";
+ break;
+ case IF_TYPE_PPP:
+ name = "ppp";
+ break;
+ case IF_TYPE_SOFTWARE_LOOPBACK:
+ name = "lo";
+ break;
+ case IF_TYPE_TUNNEL:
+ name = "tun";
+ break;
+ default:
+ name = "unk";
+ break;
+ }
+ return (name);
+}
+
+static int
+_ifcombo_type(const char *device)
+{
+ int type = INTF_TYPE_OTHER;
+
+ if (strncmp(device, "eth", 3) == 0) {
+ type = INTF_TYPE_ETH;
+ } else if (strncmp(device, "tr", 2) == 0) {
+ type = INTF_TYPE_TOKENRING;
+ } else if (strncmp(device, "ppp", 3) == 0) {
+ type = INTF_TYPE_PPP;
+ } else if (strncmp(device, "lo", 2) == 0) {
+ type = INTF_TYPE_LOOPBACK;
+ } else if (strncmp(device, "tun", 3) == 0) {
+ type = INTF_TYPE_TUN;
+ }
+ return (type);
+}
+
+static void
+_ifcombo_add(struct ifcombo *ifc, DWORD ipv4_idx, DWORD ipv6_idx)
+{
+ void* pmem = NULL;
+ if (ifc->cnt == ifc->max) {
+ if (ifc->idx) {
+ ifc->max *= 2;
+ pmem = realloc(ifc->idx,
+ sizeof(ifc->idx[0]) * ifc->max);
+ } else {
+ ifc->max = 8;
+ pmem = malloc(sizeof(ifc->idx[0]) * ifc->max);
+ }
+ if (!pmem) {
+ /* malloc or realloc failed. Restore state.
+ * TODO: notify caller. */
+ ifc->max = ifc->cnt;
+ return;
+ }
+ ifc->idx = pmem;
+ }
+ ifc->idx[ifc->cnt].ipv4 = ipv4_idx;
+ ifc->idx[ifc->cnt].ipv6 = ipv6_idx;
+ ifc->cnt++;
+}
+
+/* Map an MIB interface type into an internal interface type. The
+ internal types are never exposed to users of this library; they exist
+ only for the sake of ordering interface types within an intf_handle,
+ which has an array of ifcombo structures ordered by type. Entries in
+ an intf_handle must not be stored or accessed by a raw MIB type
+ number because they will not be able to be found by a device name
+ such as "net0" if the device name does not map exactly to the type. */
+static int
+_if_type_canonicalize(int type)
+{
+ return _ifcombo_type(_ifcombo_name(type));
+}
+
+static void
+_adapter_address_to_entry(intf_t *intf, IP_ADAPTER_ADDRESSES *a,
+ struct intf_entry *entry)
+{
+ struct addr *ap, *lap;
+ int i;
+ int type;
+ IP_ADAPTER_UNICAST_ADDRESS *addr;
+
+ /* The total length of the entry may be passed inside entry.
+ Remember it and clear the entry. */
+ u_int intf_len = entry->intf_len;
+ memset(entry, 0, sizeof(*entry));
+ entry->intf_len = intf_len;
+
+ type = _if_type_canonicalize(a->IfType);
+ for (i = 0; i < intf->ifcombo[type].cnt; i++) {
+ if (intf->ifcombo[type].idx[i].ipv4 == a->IfIndex &&
+ intf->ifcombo[type].idx[i].ipv6 == a->Ipv6IfIndex) {
+ break;
+ }
+ }
+ /* XXX - type matches MIB-II ifType. */
+ snprintf(entry->intf_name, sizeof(entry->intf_name), "%s%lu",
+ _ifcombo_name(a->IfType), i);
+ entry->intf_type = (uint16_t)type;
+
+ /* Get interface flags. */
+ entry->intf_flags = 0;
+ if (a->OperStatus == IfOperStatusUp)
+ entry->intf_flags |= INTF_FLAG_UP;
+ if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
+ entry->intf_flags |= INTF_FLAG_LOOPBACK;
+ else
+ entry->intf_flags |= INTF_FLAG_MULTICAST;
+
+ /* Get interface MTU. */
+ entry->intf_mtu = a->Mtu;
+
+ /* Get hardware address. */
+ if (a->PhysicalAddressLength == ETH_ADDR_LEN) {
+ entry->intf_link_addr.addr_type = ADDR_TYPE_ETH;
+ entry->intf_link_addr.addr_bits = ETH_ADDR_BITS;
+ memcpy(&entry->intf_link_addr.addr_eth, a->PhysicalAddress,
+ ETH_ADDR_LEN);
+ }
+ /* Get addresses. */
+ ap = entry->intf_alias_addrs;
+ lap = ap + ((entry->intf_len - sizeof(*entry)) /
+ sizeof(entry->intf_alias_addrs[0]));
+ for (addr = a->FirstUnicastAddress; addr != NULL; addr = addr->Next) {
+ IP_ADAPTER_PREFIX *prefix;
+ unsigned short bits;
+
+ /* Find the netmask length. This is stored in a parallel list.
+ We just take the first one with a matching address family,
+ but that may not be right. Windows Vista and later has an
+ OnLinkPrefixLength member that is stored right with the
+ unicast address. */
+ bits = 0;
+ if (addr->Length >= 48) {
+ /* "The size of the IP_ADAPTER_UNICAST_ADDRESS structure changed on
+ * Windows Vista and later. The Length member should be used to determine
+ * which version of the IP_ADAPTER_UNICAST_ADDRESS structure is being
+ * used."
+ * Empirically, 48 is the value on Windows 8.1, so should include the
+ * OnLinkPrefixLength member.*/
+ bits = addr->OnLinkPrefixLength;
+ }
+ else {
+ for (prefix = a->FirstPrefix; prefix != NULL; prefix = prefix->Next) {
+ if (prefix->Address.lpSockaddr->sa_family == addr->Address.lpSockaddr->sa_family) {
+ bits = (unsigned short) prefix->PrefixLength;
+ break;
+ }
+ }
+ }
+
+ if (entry->intf_addr.addr_type == ADDR_TYPE_NONE) {
+ /* Set primary address if unset. */
+ addr_ston(addr->Address.lpSockaddr, &entry->intf_addr);
+ entry->intf_addr.addr_bits = bits;
+ } else if (ap < lap) {
+ /* Set aliases. */
+ addr_ston(addr->Address.lpSockaddr, ap);
+ ap->addr_bits = bits;
+ ap++;
+ entry->intf_alias_num++;
+ }
+ }
+ entry->intf_len = (u_int) ((u_char *)ap - (u_char *)entry);
+}
+
+#define NPCAP_SERVICE_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Services\\npcap"
+
+/* The name of the Npcap loopback adapter is stored in the npcap service's
+ * Registry key in the LoopbackAdapter value. For legacy loopback support, this
+ * is a name like "NPF_{GUID}", but for newer Npcap the name is "NPF_Loopback"
+ */
+int intf_get_loopback_name(char *buffer, int buf_size)
+{
+ HKEY hKey;
+ DWORD type;
+ int size = buf_size;
+ int res = 0;
+
+ memset(buffer, 0, buf_size);
+
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, NPCAP_SERVICE_REGISTRY_KEY "\\Parameters", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueExA(hKey, "LoopbackAdapter", 0, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS && type == REG_SZ)
+ {
+ res = 1;
+ }
+ else
+ {
+ res = 0;
+ }
+
+ RegCloseKey(hKey);
+ }
+ else
+ {
+ res = 0;
+ }
+
+ return res;
+}
+
+static IP_ADAPTER_ADDRESSES*
+_update_tables_for_npcap_loopback(IP_ADAPTER_ADDRESSES *p)
+{
+ IP_ADAPTER_ADDRESSES *a_prev = NULL;
+ IP_ADAPTER_ADDRESSES *a;
+ IP_ADAPTER_ADDRESSES *a_original_loopback_prev = NULL;
+ IP_ADAPTER_ADDRESSES *a_original_loopback = NULL;
+ IP_ADAPTER_ADDRESSES *a_npcap_loopback = NULL;
+ static char npcap_loopback_name[1024] = {0};
+
+ /* Don't bother hitting the registry every time. Not ideal for long-running
+ * processes, but works for Nmap. */
+ if (npcap_loopback_name[0] == '\0')
+ g_has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024);
+ else if (g_has_npcap_loopback == 0)
+ return p;
+
+ if (!p)
+ return p;
+
+ /* Loop through the addresses looking for the dummy loopback interface from Windows. */
+ for (a = p; a != NULL; a = a->Next) {
+ if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
+ /* Dummy loopback. Keep track of it. */
+ a_original_loopback = a;
+ a_original_loopback_prev = a_prev;
+ }
+ else if (strcmp(a->AdapterName, npcap_loopback_name + strlen(_DEVICE_PREFIX) - 1) == 0) {
+ /* Legacy loopback adapter. The modern one doesn't show up in GetAdaptersAddresses. */
+ a_npcap_loopback = a;
+ }
+ a_prev = a;
+ }
+
+ /* If there's no loopback on this system, something's wrong. Windows is
+ * supposed to create this. */
+ if (!a_original_loopback)
+ return p;
+ g_has_npcap_loopback = 1;
+ /* If we didn't find the legacy adapter, use the modern adapter name. */
+ if (!a_npcap_loopback) {
+ /* Overwrite the name we got from the Registry, in case it's a broken legacy
+ * install, in which case we'll never find the legacy adapter anyway. */
+ strlcpy(npcap_loopback_name, _DEVICE_PREFIX "NPF_Loopback", 1024);
+ /* Overwrite the AdapterName from the system's own loopback adapter with
+ * the NPF_Loopback name. This is what we use to open the adapter with
+ * Packet.dll later. */
+ a_original_loopback->AdapterName = npcap_loopback_name + sizeof(_DEVICE_PREFIX) - 1;
+ return p;
+ }
+ else {
+ /* Legacy loopback adapter was found. Copy some key info from the system's
+ * loopback adapter. */
+ a_npcap_loopback->IfType = a_original_loopback->IfType;
+ a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress;
+ a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix;
+ memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN);
+ /* Unlink the original loopback adapter from the list. We'll use Npcap's instead. */
+ if (a_original_loopback_prev) {
+ a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next;
+ return p;
+ }
+ else if (a_original_loopback == p) {
+ return a_original_loopback->Next;
+ }
+ else {
+ return p;
+ }
+ }
+}
+
+static int
+_refresh_tables(intf_t *intf)
+{
+ IP_ADAPTER_ADDRESSES *p;
+ DWORD ret;
+ ULONG len;
+
+ p = NULL;
+ /* GetAdaptersAddresses is supposed to return ERROR_BUFFER_OVERFLOW and
+ * set len to the required size when len is too small. So normally we
+ * would call the function once with a small len, and then again with
+ * the longer len. But, on Windows 2003, apparently you only get
+ * ERROR_BUFFER_OVERFLOW the *first* time you call the function with a
+ * too-small len--the next time you get ERROR_INVALID_PARAMETER. So this
+ * function would fail the second and later times it is called.
+ *
+ * So, make the first call using a large len. On Windows 2003, this will
+ * work the first time as long as there are not too many adapters. (It
+ * will still fail with ERROR_INVALID_PARAMETER if there are too many
+ * adapters, but this will happen infrequently because of the large
+ * buffer.) Other systems that always return ERROR_BUFFER_OVERFLOW when
+ * appropriate will enlarge the buffer if the initial len is too short. */
+ len = 16384;
+ do {
+ free(p);
+ p = malloc(len);
+ if (p == NULL)
+ return (-1);
+ ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL, p, &len);
+ } while (ret == ERROR_BUFFER_OVERFLOW);
+
+ if (ret != NO_ERROR) {
+ free(p);
+ return (-1);
+ }
+ p = _update_tables_for_npcap_loopback(p);
+ intf->iftable = p;
+
+ /*
+ * Map "unfriendly" win32 interface indices to ours.
+ * XXX - like IP_ADAPTER_INFO ComboIndex
+ */
+ for (p = intf->iftable; p != NULL; p = p->Next) {
+ int type;
+ type = _if_type_canonicalize(p->IfType);
+ if (type < MIB_IF_TYPE_MAX)
+ _ifcombo_add(&intf->ifcombo[type], p->IfIndex, p->Ipv6IfIndex);
+ else
+ return (-1);
+ }
+ return (0);
+}
+
+static IP_ADAPTER_ADDRESSES *
+_find_adapter_address(intf_t *intf, const char *device)
+{
+ IP_ADAPTER_ADDRESSES *a;
+ char *p = (char *)device;
+ int n, type = _ifcombo_type(device);
+
+ while (isalpha((int) (unsigned char) *p)) p++;
+ n = atoi(p);
+
+ for (a = intf->iftable; a != NULL; a = a->Next) {
+ if ( intf->ifcombo[type].idx != NULL &&
+ intf->ifcombo[type].idx[n].ipv4 == a->IfIndex &&
+ intf->ifcombo[type].idx[n].ipv6 == a->Ipv6IfIndex) {
+ return a;
+ }
+ }
+
+ return NULL;
+}
+
+static IP_ADAPTER_ADDRESSES *
+_find_adapter_address_by_index(intf_t *intf, int af, unsigned int index)
+{
+ IP_ADAPTER_ADDRESSES *a;
+
+ for (a = intf->iftable; a != NULL; a = a->Next) {
+ if (af == AF_INET && index == a->IfIndex)
+ return a;
+ if (af == AF_INET6 && index == a->Ipv6IfIndex)
+ return a;
+ }
+
+ return NULL;
+}
+
+intf_t *
+intf_open(void)
+{
+ return (calloc(1, sizeof(intf_t)));
+}
+
+int
+intf_get(intf_t *intf, struct intf_entry *entry)
+{
+ IP_ADAPTER_ADDRESSES *a;
+
+ if (_refresh_tables(intf) < 0)
+ return (-1);
+
+ a = _find_adapter_address(intf, entry->intf_name);
+ if (a == NULL)
+ return (-1);
+
+ _adapter_address_to_entry(intf, a, entry);
+
+ return (0);
+}
+
+/* Look up an interface from an index, such as a sockaddr_in6.sin6_scope_id. */
+int
+intf_get_index(intf_t *intf, struct intf_entry *entry, int af, unsigned int index)
+{
+ IP_ADAPTER_ADDRESSES *a;
+
+ if (_refresh_tables(intf) < 0)
+ return (-1);
+
+ a = _find_adapter_address_by_index(intf, af, index);
+ if (a == NULL)
+ return (-1);
+
+ _adapter_address_to_entry(intf, a, entry);
+
+ return (0);
+}
+
+int
+intf_get_src(intf_t *intf, struct intf_entry *entry, struct addr *src)
+{
+ IP_ADAPTER_ADDRESSES *a;
+ IP_ADAPTER_UNICAST_ADDRESS *addr;
+
+ if (src->addr_type != ADDR_TYPE_IP) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_refresh_tables(intf) < 0)
+ return (-1);
+
+ for (a = intf->iftable; a != NULL; a = a->Next) {
+ for (addr = a->FirstUnicastAddress; addr != NULL; addr = addr->Next) {
+ struct addr dnet_addr;
+
+ addr_ston(addr->Address.lpSockaddr, &dnet_addr);
+ if (addr_cmp(&dnet_addr, src) == 0) {
+ _adapter_address_to_entry(intf, a, entry);
+ return (0);
+ }
+ }
+ }
+ errno = ENXIO;
+ return (-1);
+}
+
+int
+intf_get_dst(intf_t *intf, struct intf_entry *entry, struct addr *dst)
+{
+ errno = ENOSYS;
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return (-1);
+}
+
+int
+intf_set(intf_t *intf, const struct intf_entry *entry)
+{
+ /*
+ * XXX - could set interface up/down via SetIfEntry(),
+ * but what about the rest of the configuration? :-(
+ * {Add,Delete}IPAddress for 2000/XP only
+ */
+ errno = ENOSYS;
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return (-1);
+}
+
+int
+intf_loop(intf_t *intf, intf_handler callback, void *arg)
+{
+ IP_ADAPTER_ADDRESSES *a;
+ struct intf_entry *entry;
+ u_char ebuf[1024];
+ int ret = 0;
+
+ if (_refresh_tables(intf) < 0)
+ return (-1);
+
+ entry = (struct intf_entry *)ebuf;
+
+ for (a = intf->iftable; a != NULL; a = a->Next) {
+ entry->intf_len = sizeof(ebuf);
+ _adapter_address_to_entry(intf, a, entry);
+ if ((ret = (*callback)(entry, arg)) != 0)
+ break;
+ }
+ return (ret);
+}
+
+intf_t *
+intf_close(intf_t *intf)
+{
+ int i;
+
+ if (intf != NULL) {
+ for (i = 0; i < MIB_IF_TYPE_MAX; i++) {
+ if (intf->ifcombo[i].idx)
+ free(intf->ifcombo[i].idx);
+ }
+ if (intf->iftable)
+ free(intf->iftable);
+ free(intf);
+ }
+ return (NULL);
+}
+
+/* Converts a libdnet interface name to its pcap equivalent. The pcap name is
+ stored in pcapdev up to a length of pcapdevlen, including the terminating
+ '\0'. Returns -1 on error. */
+int
+intf_get_pcap_devname_cached(const char *intf_name, char *pcapdev, int pcapdevlen, int refresh)
+{
+ IP_ADAPTER_ADDRESSES *a;
+ static pcap_if_t *pcapdevs = NULL;
+ pcap_if_t *pdev;
+ intf_t *intf;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ if ((intf = intf_open()) == NULL)
+ return (-1);
+ if (_refresh_tables(intf) < 0) {
+ intf_close(intf);
+ return (-1);
+ }
+ a = _find_adapter_address(intf, intf_name);
+
+ if (a == NULL) {
+ intf_close(intf);
+ return (-1);
+ }
+
+ if (refresh) {
+ pcap_freealldevs(pcapdevs);
+ pcapdevs = NULL;
+ }
+
+ if (pcapdevs == NULL) {
+ if (pcap_findalldevs(&pcapdevs, errbuf) == -1) {
+ intf_close(intf);
+ return (-1);
+ }
+ }
+
+ /* Loop through all the pcap devices until we find a match. */
+ for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) {
+ char *name;
+
+ if (pdev->name == NULL || strlen(pdev->name) < sizeof(_DEVICE_PREFIX))
+ continue;
+ /* "\\Device\\NPF_{GUID}"
+ * "\\Device\\NPF_Loopback"
+ * Find the '{'after device prefix.
+ */
+ name = strchr(pdev->name + sizeof(_DEVICE_PREFIX) - 1, '{');
+ if (name == NULL) {
+ /* If no GUID, just match the whole device name */
+ name = pdev->name + sizeof(_DEVICE_PREFIX) - 1;
+ }
+ if (strcmp(name, a->AdapterName) == 0)
+ break;
+ }
+ if (pdev != NULL)
+ strlcpy(pcapdev, pdev->name, pcapdevlen);
+ intf_close(intf);
+ if (pdev == NULL)
+ return -1;
+ else
+ return 0;
+}
+int
+intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen)
+{
+ return intf_get_pcap_devname_cached(intf_name, pcapdev, pcapdevlen, 0);
+}
diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c
new file mode 100644
index 0000000..d4faaeb
--- /dev/null
+++ b/libdnet-stripped/src/intf.c
@@ -0,0 +1,1091 @@
+/*
+ * intf.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: intf.c 616 2006-01-09 07:09:49Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+/* XXX - AIX */
+#ifdef HAVE_GETKERNINFO
+#include <sys/ndd_var.h>
+#include <sys/kinfo.h>
+#endif
+#ifndef IP_MULTICAST
+# define IP_MULTICAST
+#endif
+#include <net/if.h>
+#ifdef HAVE_NET_IF_VAR_H
+# include <net/if_var.h>
+#endif
+#undef IP_MULTICAST
+/* XXX - IPv6 ioctls */
+#ifdef HAVE_NETINET_IN_VAR_H
+# include <netinet/in.h>
+# include <netinet/in_var.h>
+#endif
+#ifdef HAVE_NETINET_IN6_VAR_H
+# include <sys/protosw.h>
+# include <netinet/in6_var.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+/* XXX - Tru64 */
+#if defined(SIOCRIPMTU) && defined(SIOCSIPMTU)
+# define SIOCGIFMTU SIOCRIPMTU
+# define SIOCSIFMTU SIOCSIPMTU
+#endif
+
+/* XXX - HP-UX */
+#if defined(SIOCADDIFADDR) && defined(SIOCDELIFADDR)
+# define SIOCAIFADDR SIOCADDIFADDR
+# define SIOCDIFADDR SIOCDELIFADDR
+#endif
+
+/* XXX - HP-UX, Solaris */
+#if !defined(ifr_mtu) && defined(ifr_metric)
+# define ifr_mtu ifr_metric
+#endif
+
+#ifdef HAVE_SOCKADDR_SA_LEN
+# define max(a, b) ((a) > (b) ? (a) : (b))
+# define NEXTIFR(i) ((struct ifreq *) \
+ max((u_char *)i + sizeof(struct ifreq), \
+ (u_char *)&i->ifr_addr + i->ifr_addr.sa_len))
+#else
+# define NEXTIFR(i) (i + 1)
+#endif
+
+#define NEXTLIFR(i) (i + 1)
+
+/* XXX - superset of ifreq, for portable SIOC{A,D}IFADDR */
+struct dnet_ifaliasreq {
+ char ifra_name[IFNAMSIZ];
+ union {
+ struct sockaddr ifrau_addr;
+ int ifrau_align;
+ } ifra_ifrau;
+#ifndef ifra_addr
+#define ifra_addr ifra_ifrau.ifrau_addr
+#endif
+ struct sockaddr ifra_brdaddr;
+ struct sockaddr ifra_mask;
+ int ifra_cookie; /* XXX - IRIX!@#$ */
+};
+
+struct intf_handle {
+ int fd;
+ int fd6;
+ struct ifconf ifc;
+#ifdef SIOCGLIFCONF
+ struct lifconf lifc;
+#endif
+ u_char ifcbuf[4192];
+};
+
+static int
+intf_flags_to_iff(u_short flags, int iff)
+{
+ if (flags & INTF_FLAG_UP)
+ iff |= IFF_UP;
+ else
+ iff &= ~IFF_UP;
+ if (flags & INTF_FLAG_NOARP)
+ iff |= IFF_NOARP;
+ else
+ iff &= ~IFF_NOARP;
+
+ return (iff);
+}
+
+static u_int
+intf_iff_to_flags(uint64_t iff)
+{
+ u_int n = 0;
+
+ if (iff & IFF_UP)
+ n |= INTF_FLAG_UP;
+ if (iff & IFF_LOOPBACK)
+ n |= INTF_FLAG_LOOPBACK;
+ if (iff & IFF_POINTOPOINT)
+ n |= INTF_FLAG_POINTOPOINT;
+ if (iff & IFF_NOARP)
+ n |= INTF_FLAG_NOARP;
+ if (iff & IFF_BROADCAST)
+ n |= INTF_FLAG_BROADCAST;
+ if (iff & IFF_MULTICAST)
+ n |= INTF_FLAG_MULTICAST;
+#ifdef IFF_IPMP
+ /* Unset the BROADCAST and MULTICAST flags from Solaris IPMP interfaces,
+ * otherwise _intf_set_type will think they are INTF_TYPE_ETH. */
+ if (iff & IFF_IPMP)
+ n &= ~(INTF_FLAG_BROADCAST | INTF_FLAG_MULTICAST);
+#endif
+
+ return (n);
+}
+
+intf_t *
+intf_open(void)
+{
+ intf_t *intf;
+ int one = 1;
+
+ if ((intf = calloc(1, sizeof(*intf))) != NULL) {
+ intf->fd = intf->fd6 = -1;
+
+ if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (intf_close(intf));
+
+ setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST,
+ (const char *) &one, sizeof(one));
+
+#if defined(SIOCGLIFCONF) || defined(SIOCGIFNETMASK_IN6) || defined(SIOCGIFNETMASK6)
+ if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+# ifdef EPROTONOSUPPORT
+ if (errno != EPROTONOSUPPORT)
+# endif
+ return (intf_close(intf));
+ }
+#endif
+ }
+ return (intf);
+}
+
+static int
+_intf_delete_addrs(intf_t *intf, struct intf_entry *entry)
+{
+#if defined(SIOCDIFADDR)
+ struct dnet_ifaliasreq ifra;
+
+ memset(&ifra, 0, sizeof(ifra));
+ strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
+ if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
+ addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
+ ioctl(intf->fd, SIOCDIFADDR, &ifra);
+ }
+ if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
+ addr_ntos(&entry->intf_dst_addr, &ifra.ifra_addr);
+ ioctl(intf->fd, SIOCDIFADDR, &ifra);
+ }
+#elif defined(SIOCLIFREMOVEIF)
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
+ /* XXX - overloading Solaris lifreq with ifreq */
+ ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
+#endif
+ return (0);
+}
+
+static int
+_intf_delete_aliases(intf_t *intf, struct intf_entry *entry)
+{
+ int i;
+#if defined(SIOCDIFADDR) && !defined(__linux__) /* XXX - see Linux below */
+ struct dnet_ifaliasreq ifra;
+
+ memset(&ifra, 0, sizeof(ifra));
+ strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
+
+ for (i = 0; i < (int)entry->intf_alias_num; i++) {
+ addr_ntos(&entry->intf_alias_addrs[i], &ifra.ifra_addr);
+ ioctl(intf->fd, SIOCDIFADDR, &ifra);
+ }
+#else
+ struct ifreq ifr;
+
+ for (i = 0; i < entry->intf_alias_num; i++) {
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
+ entry->intf_name, i + 1);
+# ifdef SIOCLIFREMOVEIF
+ /* XXX - overloading Solaris lifreq with ifreq */
+ ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
+# else
+ /* XXX - only need to set interface down on Linux */
+ ifr.ifr_flags = 0;
+ ioctl(intf->fd, SIOCSIFFLAGS, &ifr);
+# endif
+ }
+#endif
+ return (0);
+}
+
+static int
+_intf_add_aliases(intf_t *intf, const struct intf_entry *entry)
+{
+ int i;
+#ifdef SIOCAIFADDR
+ struct dnet_ifaliasreq ifra;
+ struct addr bcast;
+
+ memset(&ifra, 0, sizeof(ifra));
+ strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
+
+ for (i = 0; i < (int)entry->intf_alias_num; i++) {
+ if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
+ continue;
+
+ if (addr_ntos(&entry->intf_alias_addrs[i],
+ &ifra.ifra_addr) < 0)
+ return (-1);
+ addr_bcast(&entry->intf_alias_addrs[i], &bcast);
+ addr_ntos(&bcast, &ifra.ifra_brdaddr);
+ addr_btos(entry->intf_alias_addrs[i].addr_bits,
+ &ifra.ifra_mask);
+
+ if (ioctl(intf->fd, SIOCAIFADDR, &ifra) < 0)
+ return (-1);
+ }
+#else
+ struct ifreq ifr;
+ int n = 1;
+
+ for (i = 0; i < entry->intf_alias_num; i++) {
+ if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
+ continue;
+
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
+ entry->intf_name, n++);
+# ifdef SIOCLIFADDIF
+ if (ioctl(intf->fd, SIOCLIFADDIF, &ifr) < 0)
+ return (-1);
+# endif
+ if (addr_ntos(&entry->intf_alias_addrs[i], &ifr.ifr_addr) < 0)
+ return (-1);
+ if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0)
+ return (-1);
+ }
+ strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
+#endif
+ return (0);
+}
+
+int
+intf_set(intf_t *intf, const struct intf_entry *entry)
+{
+ struct ifreq ifr;
+ struct intf_entry *orig;
+ struct addr bcast;
+ u_char buf[BUFSIZ];
+
+ orig = (struct intf_entry *)buf;
+ orig->intf_len = sizeof(buf);
+ strcpy(orig->intf_name, entry->intf_name);
+
+ if (intf_get(intf, orig) < 0)
+ return (-1);
+
+ /* Delete any existing aliases. */
+ if (_intf_delete_aliases(intf, orig) < 0)
+ return (-1);
+
+ /* Delete any existing addrs. */
+ if (_intf_delete_addrs(intf, orig) < 0)
+ return (-1);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
+
+ /* Set interface MTU. */
+ if (entry->intf_mtu != 0) {
+ ifr.ifr_mtu = entry->intf_mtu;
+#ifdef SIOCSIFMTU
+ if (ioctl(intf->fd, SIOCSIFMTU, &ifr) < 0)
+#endif
+ return (-1);
+ }
+ /* Set interface address. */
+ if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
+#if defined(BSD) && !defined(__OPENBSD__)
+ /* XXX - why must this happen before SIOCSIFADDR? */
+ if (addr_btos(entry->intf_addr.addr_bits,
+ &ifr.ifr_addr) == 0) {
+ if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
+ return (-1);
+ }
+#endif
+ if (addr_ntos(&entry->intf_addr, &ifr.ifr_addr) < 0)
+ return (-1);
+ if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0 && errno != EEXIST)
+ return (-1);
+
+ if (addr_btos(entry->intf_addr.addr_bits, &ifr.ifr_addr) == 0
+#ifdef __linux__
+ && entry->intf_addr.addr_ip != 0
+#endif
+ ) {
+ if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
+ return (-1);
+ }
+ if (addr_bcast(&entry->intf_addr, &bcast) == 0) {
+ if (addr_ntos(&bcast, &ifr.ifr_broadaddr) == 0) {
+ /* XXX - ignore error from non-broadcast ifs */
+ ioctl(intf->fd, SIOCSIFBRDADDR, &ifr);
+ }
+ }
+ }
+ /* Set link-level address. */
+ if (entry->intf_link_addr.addr_type == ADDR_TYPE_ETH &&
+ addr_cmp(&entry->intf_link_addr, &orig->intf_link_addr) != 0) {
+#if defined(SIOCSIFHWADDR)
+ if (addr_ntos(&entry->intf_link_addr, &ifr.ifr_hwaddr) < 0)
+ return (-1);
+ if (ioctl(intf->fd, SIOCSIFHWADDR, &ifr) < 0)
+ return (-1);
+#elif defined (SIOCSIFLLADDR)
+ memcpy(ifr.ifr_addr.sa_data, &entry->intf_link_addr.addr_eth,
+ ETH_ADDR_LEN);
+ ifr.ifr_addr.sa_len = ETH_ADDR_LEN;
+ if (ioctl(intf->fd, SIOCSIFLLADDR, &ifr) < 0)
+ return (-1);
+#else
+ eth_t *eth;
+
+ if ((eth = eth_open(entry->intf_name)) == NULL)
+ return (-1);
+ if (eth_set(eth, &entry->intf_link_addr.addr_eth) < 0) {
+ eth_close(eth);
+ return (-1);
+ }
+ eth_close(eth);
+#endif
+ }
+ /* Set point-to-point destination. */
+ if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
+ if (addr_ntos(&entry->intf_dst_addr, &ifr.ifr_dstaddr) < 0)
+ return (-1);
+ if (ioctl(intf->fd, SIOCSIFDSTADDR, &ifr) < 0 &&
+ errno != EEXIST)
+ return (-1);
+ }
+ /* Add aliases. */
+ if (_intf_add_aliases(intf, entry) < 0)
+ return (-1);
+
+ /* Set interface flags. */
+ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
+ return (-1);
+
+ ifr.ifr_flags = intf_flags_to_iff(entry->intf_flags, ifr.ifr_flags);
+
+ if (ioctl(intf->fd, SIOCSIFFLAGS, &ifr) < 0)
+ return (-1);
+
+ return (0);
+}
+
+/* XXX - this is total crap. how to do this without walking ifnet? */
+static void
+_intf_set_type(struct intf_entry *entry)
+{
+ if ((entry->intf_flags & INTF_FLAG_LOOPBACK) != 0)
+ entry->intf_type = INTF_TYPE_LOOPBACK;
+ else if ((entry->intf_flags & INTF_FLAG_BROADCAST) != 0)
+ entry->intf_type = INTF_TYPE_ETH;
+ else if ((entry->intf_flags & INTF_FLAG_POINTOPOINT) != 0)
+ entry->intf_type = INTF_TYPE_TUN;
+ else
+ entry->intf_type = INTF_TYPE_OTHER;
+}
+
+#ifdef SIOCGLIFCONF
+int
+_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
+{
+ struct lifreq lifr;
+ int fd;
+
+ /* Get interface index. */
+ entry->intf_index = if_nametoindex(entry->intf_name);
+ if (entry->intf_index == 0)
+ return (-1);
+
+ strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name));
+
+ /* Get interface flags. Here he also check whether we need to use fd or
+ * fd6 in the rest of the function. Using the wrong address family in
+ * the ioctls gives ENXIO on Solaris. */
+ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) >= 0)
+ fd = intf->fd;
+ else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifr) >= 0)
+ fd = intf->fd6;
+ else
+ return (-1);
+
+ entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags);
+ _intf_set_type(entry);
+
+ /* Get interface MTU. */
+#ifdef SIOCGLIFMTU
+ if (ioctl(fd, SIOCGLIFMTU, &lifr) < 0)
+#endif
+ return (-1);
+ entry->intf_mtu = lifr.lifr_mtu;
+
+ entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
+ entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
+
+ /* Get primary interface address. */
+ if (ioctl(fd, SIOCGLIFADDR, &lifr) == 0) {
+ addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr);
+ if (ioctl(fd, SIOCGLIFNETMASK, &lifr) < 0)
+ return (-1);
+ addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits);
+ }
+ /* Get other addresses. */
+ if (entry->intf_type == INTF_TYPE_TUN) {
+ if (ioctl(fd, SIOCGLIFDSTADDR, &lifr) == 0) {
+ if (addr_ston((struct sockaddr *)&lifr.lifr_addr,
+ &entry->intf_dst_addr) < 0)
+ return (-1);
+ }
+ } else if (entry->intf_type == INTF_TYPE_ETH) {
+ eth_t *eth;
+
+ if ((eth = eth_open(entry->intf_name)) != NULL) {
+ if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
+ entry->intf_link_addr.addr_type =
+ ADDR_TYPE_ETH;
+ entry->intf_link_addr.addr_bits =
+ ETH_ADDR_BITS;
+ }
+ eth_close(eth);
+ }
+ }
+ return (0);
+}
+#else
+static int
+_intf_get_noalias(intf_t *intf, struct intf_entry *entry)
+{
+ struct ifreq ifr;
+#ifdef HAVE_GETKERNINFO
+ int size;
+ struct kinfo_ndd *nddp;
+ void *end;
+#endif
+
+ /* Get interface index. */
+ entry->intf_index = if_nametoindex(entry->intf_name);
+ if (entry->intf_index == 0)
+ return (-1);
+
+ strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
+
+ /* Get interface flags. */
+ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
+ return (-1);
+
+ entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags);
+ _intf_set_type(entry);
+
+ /* Get interface MTU. */
+#ifdef SIOCGIFMTU
+ if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0)
+#endif
+ return (-1);
+ entry->intf_mtu = ifr.ifr_mtu;
+
+ entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
+ entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
+
+ /* Get primary interface address. */
+ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) {
+ addr_ston(&ifr.ifr_addr, &entry->intf_addr);
+ if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0)
+ return (-1);
+ addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits);
+ }
+ /* Get other addresses. */
+ if (entry->intf_type == INTF_TYPE_TUN) {
+ if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) {
+ if (addr_ston(&ifr.ifr_addr,
+ &entry->intf_dst_addr) < 0)
+ return (-1);
+ }
+ } else if (entry->intf_type == INTF_TYPE_ETH) {
+#if defined(HAVE_GETKERNINFO)
+ /* AIX also defines SIOCGIFHWADDR, but it fails silently?
+ * This is the method IBM recommends here:
+ * http://www-01.ibm.com/support/knowledgecenter/ssw_aix_53/com.ibm.aix.progcomm/doc/progcomc/skt_sndother_ex.htm%23ssqinc2joyc?lang=en
+ */
+ /* How many bytes will be returned? */
+ size = getkerninfo(KINFO_NDD, 0, 0, 0);
+ if (size <= 0) {
+ return -1;
+ }
+ nddp = (struct kinfo_ndd *)malloc(size);
+
+ if (!nddp) {
+ return -1;
+ }
+ /* Get all Network Device Driver (NDD) info */
+ if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
+ free(nddp);
+ return -1;
+ }
+ /* Loop over the returned values until we find a match */
+ end = (void *)nddp + size;
+ while ((void *)nddp < end) {
+ if (!strcmp(nddp->ndd_alias, entry->intf_name) ||
+ !strcmp(nddp->ndd_name, entry->intf_name)) {
+ addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
+ nddp->ndd_addr, ETH_ADDR_LEN);
+ break;
+ } else
+ nddp++;
+ }
+ free(nddp);
+#elif defined(SIOCGIFHWADDR)
+ if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0)
+ return (-1);
+ if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) {
+ /* Likely we got an unsupported address type. Just use NONE for now. */
+ entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
+ entry->intf_link_addr.addr_bits = 0;
+ }
+#elif defined(SIOCRPHYSADDR)
+ /* Tru64 */
+ struct ifdevea *ifd = (struct ifdevea *)&ifr; /* XXX */
+
+ if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0)
+ return (-1);
+ addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
+ ifd->current_pa, ETH_ADDR_LEN);
+#else
+ eth_t *eth;
+
+ if ((eth = eth_open(entry->intf_name)) != NULL) {
+ if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
+ entry->intf_link_addr.addr_type =
+ ADDR_TYPE_ETH;
+ entry->intf_link_addr.addr_bits =
+ ETH_ADDR_BITS;
+ }
+ eth_close(eth);
+ }
+#endif
+ }
+ return (0);
+}
+#endif
+
+#ifdef SIOCLIFADDR
+/* XXX - aliases on IRIX don't show up in SIOCGIFCONF */
+static int
+_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
+{
+ struct dnet_ifaliasreq ifra;
+ struct addr *ap, *lap;
+
+ strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
+ addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
+ addr_btos(entry->intf_addr.addr_bits, &ifra.ifra_mask);
+ memset(&ifra.ifra_brdaddr, 0, sizeof(ifra.ifra_brdaddr));
+ ifra.ifra_cookie = 1;
+
+ ap = entry->intf_alias_addrs;
+ lap = (struct addr *)((u_char *)entry + entry->intf_len);
+
+ while (ioctl(intf->fd, SIOCLIFADDR, &ifra) == 0 &&
+ ifra.ifra_cookie > 0 && (ap + 1) < lap) {
+ if (addr_ston(&ifra.ifra_addr, ap) < 0)
+ break;
+ ap++, entry->intf_alias_num++;
+ }
+ entry->intf_len = (u_char *)ap - (u_char *)entry;
+
+ return (0);
+}
+#elif defined(SIOCGLIFCONF)
+static int
+_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
+{
+ struct lifreq *lifr, *llifr;
+ struct lifreq tmplifr;
+ struct addr *ap, *lap;
+ char *p;
+
+ if (intf->lifc.lifc_len < (int)sizeof(*lifr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ entry->intf_alias_num = 0;
+ ap = entry->intf_alias_addrs;
+ llifr = (struct lifreq *)intf->lifc.lifc_buf +
+ (intf->lifc.lifc_len / sizeof(*llifr));
+ lap = (struct addr *)((u_char *)entry + entry->intf_len);
+
+ /* Get addresses for this interface. */
+ for (lifr = intf->lifc.lifc_req; lifr < llifr && (ap + 1) < lap;
+ lifr = NEXTLIFR(lifr)) {
+ /* XXX - Linux, Solaris ifaliases */
+ if ((p = strchr(lifr->lifr_name, ':')) != NULL)
+ *p = '\0';
+
+ if (strcmp(lifr->lifr_name, entry->intf_name) != 0) {
+ if (p) *p = ':';
+ continue;
+ }
+
+ /* Fix the name back up */
+ if (p) *p = ':';
+
+ if (addr_ston((struct sockaddr *)&lifr->lifr_addr, ap) < 0)
+ continue;
+
+ /* XXX */
+ if (ap->addr_type == ADDR_TYPE_ETH) {
+ memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
+ continue;
+ } else if (ap->addr_type == ADDR_TYPE_IP) {
+ if (ap->addr_ip == entry->intf_addr.addr_ip ||
+ ap->addr_ip == entry->intf_dst_addr.addr_ip)
+ continue;
+ strlcpy(tmplifr.lifr_name, lifr->lifr_name, sizeof(tmplifr.lifr_name));
+ if (ioctl(intf->fd, SIOCGIFNETMASK, &tmplifr) == 0)
+ addr_stob((struct sockaddr *)&tmplifr.lifr_addr, &ap->addr_bits);
+ } else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
+ if (memcmp(&ap->addr_ip6, &entry->intf_addr.addr_ip6, IP6_ADDR_LEN) == 0 ||
+ memcmp(&ap->addr_ip6, &entry->intf_dst_addr.addr_ip6, IP6_ADDR_LEN) == 0)
+ continue;
+ strlcpy(tmplifr.lifr_name, lifr->lifr_name, sizeof(tmplifr.lifr_name));
+ if (ioctl(intf->fd6, SIOCGLIFNETMASK, &tmplifr) == 0) {
+ addr_stob((struct sockaddr *)&tmplifr.lifr_addr,
+ &ap->addr_bits);
+ }
+ else perror("SIOCGLIFNETMASK");
+ }
+ ap++, entry->intf_alias_num++;
+ }
+ entry->intf_len = (u_char *)ap - (u_char *)entry;
+
+ return (0);
+}
+#else
+static int
+_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
+{
+ struct ifreq *ifr, *lifr;
+ struct ifreq tmpifr;
+ struct addr *ap, *lap;
+ char *p;
+
+ if (intf->ifc.ifc_len < (int)sizeof(*ifr) && intf->ifc.ifc_len != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ entry->intf_alias_num = 0;
+ ap = entry->intf_alias_addrs;
+ lifr = (struct ifreq *)intf->ifc.ifc_buf +
+ (intf->ifc.ifc_len / sizeof(*lifr));
+ lap = (struct addr *)((u_char *)entry + entry->intf_len);
+
+ /* Get addresses for this interface. */
+ for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap;
+ ifr = NEXTIFR(ifr)) {
+ /* XXX - Linux, Solaris ifaliases */
+ if ((p = strchr(ifr->ifr_name, ':')) != NULL)
+ *p = '\0';
+
+ if (strcmp(ifr->ifr_name, entry->intf_name) != 0) {
+ if (p) *p = ':';
+ continue;
+ }
+
+ /* Fix the name back up */
+ if (p) *p = ':';
+
+ if (addr_ston(&ifr->ifr_addr, ap) < 0)
+ continue;
+
+ /* XXX */
+ if (ap->addr_type == ADDR_TYPE_ETH) {
+ memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
+ continue;
+ } else if (ap->addr_type == ADDR_TYPE_IP) {
+ if (ap->addr_ip == entry->intf_addr.addr_ip ||
+ ap->addr_ip == entry->intf_dst_addr.addr_ip)
+ continue;
+ strlcpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name));
+ if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0)
+ addr_stob(&tmpifr.ifr_addr, &ap->addr_bits);
+ }
+#ifdef SIOCGIFNETMASK_IN6
+ else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
+ struct in6_ifreq ifr6;
+
+ /* XXX - sizeof(ifr) < sizeof(ifr6) */
+ memcpy(&ifr6, ifr, sizeof(ifr6));
+
+ if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) {
+ addr_stob((struct sockaddr *)&ifr6.ifr_addr,
+ &ap->addr_bits);
+ }
+ else perror("SIOCGIFNETMASK_IN6");
+ }
+#else
+#ifdef SIOCGIFNETMASK6
+ else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
+ struct in6_ifreq ifr6;
+
+ /* XXX - sizeof(ifr) < sizeof(ifr6) */
+ memcpy(&ifr6, ifr, sizeof(ifr6));
+
+ if (ioctl(intf->fd6, SIOCGIFNETMASK6, &ifr6) == 0) {
+ /* For some reason this is 0 after the ioctl. */
+ ifr6.ifr_Addr.sin6_family = AF_INET6;
+ addr_stob((struct sockaddr *)&ifr6.ifr_Addr,
+ &ap->addr_bits);
+ }
+ else perror("SIOCGIFNETMASK6");
+ }
+#endif
+#endif
+ ap++, entry->intf_alias_num++;
+ }
+#ifdef HAVE_LINUX_PROCFS
+#define PROC_INET6_FILE "/proc/net/if_inet6"
+ {
+ FILE *f;
+ char buf[256], s[8][5], name[INTF_NAME_LEN];
+ u_int idx, bits, scope, flags;
+
+ if ((f = fopen(PROC_INET6_FILE, "r")) != NULL) {
+ while (ap < lap &&
+ fgets(buf, sizeof(buf), f) != NULL) {
+ /* scan up to INTF_NAME_LEN-1 bytes to reserve space for null terminator */
+ sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %x %02x %02x %02x %15s\n",
+ s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
+ &idx, &bits, &scope, &flags, name);
+ if (strcmp(name, entry->intf_name) == 0) {
+ snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
+ s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], bits);
+ addr_aton(buf, ap);
+ ap++, entry->intf_alias_num++;
+ }
+ }
+ fclose(f);
+ }
+ }
+#endif
+ entry->intf_len = (u_char *)ap - (u_char *)entry;
+
+ return (0);
+}
+#endif /* SIOCLIFADDR */
+
+int
+intf_get(intf_t *intf, struct intf_entry *entry)
+{
+ if (_intf_get_noalias(intf, entry) < 0)
+ return (-1);
+#ifndef SIOCLIFADDR
+ intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
+ intf->ifc.ifc_len = sizeof(intf->ifcbuf);
+
+ if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0)
+ return (-1);
+#endif
+ return (_intf_get_aliases(intf, entry));
+}
+
+/* Look up an interface from an index, such as a sockaddr_in6.sin6_scope_id. */
+int
+intf_get_index(intf_t *intf, struct intf_entry *entry, int af, unsigned int index)
+{
+ char namebuf[IFNAMSIZ];
+ char *devname;
+
+ /* af is ignored; only used in intf-win32.c. */
+ devname = if_indextoname(index, namebuf);
+ if (devname == NULL)
+ return (-1);
+ strlcpy(entry->intf_name, devname, sizeof(entry->intf_name));
+ return intf_get(intf, entry);
+}
+
+static int
+_match_intf_src(const struct intf_entry *entry, void *arg)
+{
+ struct intf_entry *save = (struct intf_entry *)arg;
+ int matched = 0, cnt;
+
+ if (entry->intf_addr.addr_type == ADDR_TYPE_IP &&
+ entry->intf_addr.addr_ip == save->intf_addr.addr_ip)
+ matched = 1;
+
+ for (cnt = 0; !matched && cnt < (int) entry->intf_alias_num; cnt++) {
+ if (entry->intf_alias_addrs[cnt].addr_type != ADDR_TYPE_IP)
+ continue;
+ if (entry->intf_alias_addrs[cnt].addr_ip == save->intf_addr.addr_ip)
+ matched = 1;
+ }
+
+ if (matched) {
+ /* XXX - truncated result if entry is too small. */
+ if (save->intf_len < entry->intf_len)
+ memcpy(save, entry, save->intf_len);
+ else
+ memcpy(save, entry, entry->intf_len);
+ return (1);
+ }
+ return (0);
+}
+
+int
+intf_get_src(intf_t *intf, struct intf_entry *entry, struct addr *src)
+{
+ memcpy(&entry->intf_addr, src, sizeof(*src));
+
+ if (intf_loop(intf, _match_intf_src, entry) != 1) {
+ errno = ENXIO;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+intf_get_dst(intf_t *intf, struct intf_entry *entry, struct addr *dst)
+{
+ struct sockaddr_in sin;
+ socklen_t n;
+
+ if (dst->addr_type != ADDR_TYPE_IP) {
+ errno = EINVAL;
+ return (-1);
+ }
+ addr_ntos(dst, (struct sockaddr *)&sin);
+ sin.sin_port = htons(666);
+
+ if (connect(intf->fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ return (-1);
+
+ n = sizeof(sin);
+ if (getsockname(intf->fd, (struct sockaddr *)&sin, &n) < 0)
+ return (-1);
+
+ addr_ston((struct sockaddr *)&sin, &entry->intf_addr);
+
+ if (intf_loop(intf, _match_intf_src, entry) != 1)
+ return (-1);
+
+ return (0);
+}
+
+#ifdef HAVE_LINUX_PROCFS
+#define PROC_DEV_FILE "/proc/net/dev"
+
+int
+intf_loop(intf_t *intf, intf_handler callback, void *arg)
+{
+ FILE *fp;
+ struct intf_entry *entry;
+ char *p, buf[BUFSIZ], ebuf[BUFSIZ];
+ int ret;
+
+ entry = (struct intf_entry *)ebuf;
+
+ if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL)
+ return (-1);
+
+ intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
+ intf->ifc.ifc_len = sizeof(intf->ifcbuf);
+
+ if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0) {
+ fclose(fp);
+ return (-1);
+ }
+
+ ret = 0;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if ((p = strchr(buf, ':')) == NULL)
+ continue;
+ *p = '\0';
+ for (p = buf; *p == ' '; p++)
+ ;
+
+ memset(ebuf, 0, sizeof(ebuf));
+ strlcpy(entry->intf_name, p, sizeof(entry->intf_name));
+ entry->intf_len = sizeof(ebuf);
+
+ if (_intf_get_noalias(intf, entry) < 0) {
+ ret = -1;
+ break;
+ }
+ if (_intf_get_aliases(intf, entry) < 0) {
+ ret = -1;
+ break;
+ }
+ if ((ret = (*callback)(entry, arg)) != 0)
+ break;
+ }
+ if (ferror(fp))
+ ret = -1;
+
+ fclose(fp);
+
+ return (ret);
+}
+#elif defined(SIOCGLIFCONF)
+int
+intf_loop(intf_t *intf, intf_handler callback, void *arg)
+{
+ struct intf_entry *entry;
+ struct lifreq *lifr, *llifr, *plifr;
+ char *p, ebuf[BUFSIZ];
+ int ret;
+ struct lifreq lifrflags;
+ memset(&lifrflags, 0, sizeof(struct lifreq));
+
+ entry = (struct intf_entry *)ebuf;
+
+ /* http://www.unix.com/man-page/opensolaris/7p/if_tcp */
+ intf->lifc.lifc_family = AF_UNSPEC;
+ intf->lifc.lifc_flags = 0;
+#ifdef LIFC_UNDER_IPMP
+ intf->lifc.lifc_flags |= LIFC_UNDER_IPMP;
+#endif
+ intf->lifc.lifc_buf = (caddr_t)intf->ifcbuf;
+ intf->lifc.lifc_len = sizeof(intf->ifcbuf);
+
+ if (ioctl(intf->fd, SIOCGLIFCONF, &intf->lifc) < 0)
+ return (-1);
+
+ llifr = (struct lifreq *)&intf->lifc.lifc_buf[intf->lifc.lifc_len];
+
+ for (lifr = intf->lifc.lifc_req; lifr < llifr; lifr = NEXTLIFR(lifr)) {
+ /* XXX - Linux, Solaris ifaliases */
+ if ((p = strchr(lifr->lifr_name, ':')) != NULL)
+ *p = '\0';
+
+ for (plifr = intf->lifc.lifc_req; plifr < lifr; plifr = NEXTLIFR(lifr)) {
+ if (strcmp(lifr->lifr_name, plifr->lifr_name) == 0)
+ break;
+ }
+ if (lifr > intf->lifc.lifc_req && plifr < lifr)
+ continue;
+
+ memset(ebuf, 0, sizeof(ebuf));
+ strlcpy(entry->intf_name, lifr->lifr_name,
+ sizeof(entry->intf_name));
+ entry->intf_len = sizeof(ebuf);
+
+ /* Repair the alias name back up */
+ if (p) *p = ':';
+
+ /* Ignore IPMP interfaces. These are virtual interfaces made up
+ * of physical interfaces. IPMP interfaces do not support things
+ * like packet sniffing; it is necessary to use one of the
+ * underlying physical interfaces instead. This works as long as
+ * the physical interface's test address is on the same subnet
+ * as the IPMP interface's address. */
+ strlcpy(lifrflags.lifr_name, lifr->lifr_name, sizeof(lifrflags.lifr_name));
+ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifrflags) >= 0)
+ ;
+ else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifrflags) >= 0)
+ ;
+ else
+ return (-1);
+#ifdef IFF_IPMP
+ if (lifrflags.lifr_flags & IFF_IPMP) {
+ continue;
+ }
+#endif
+
+ if (_intf_get_noalias(intf, entry) < 0)
+ return (-1);
+ if (_intf_get_aliases(intf, entry) < 0)
+ return (-1);
+
+ if ((ret = (*callback)(entry, arg)) != 0)
+ return (ret);
+ }
+ return (0);
+}
+#else
+int
+intf_loop(intf_t *intf, intf_handler callback, void *arg)
+{
+ struct intf_entry *entry;
+ struct ifreq *ifr, *lifr, *pifr;
+ char *p, ebuf[BUFSIZ];
+ int ret;
+
+ entry = (struct intf_entry *)ebuf;
+
+ intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
+ intf->ifc.ifc_len = sizeof(intf->ifcbuf);
+
+ if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0)
+ return (-1);
+
+ pifr = NULL;
+ lifr = (struct ifreq *)&intf->ifc.ifc_buf[intf->ifc.ifc_len];
+
+ for (ifr = intf->ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr)) {
+ /* XXX - Linux, Solaris ifaliases */
+ if ((p = strchr(ifr->ifr_name, ':')) != NULL)
+ *p = '\0';
+
+ if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0) {
+ if (p) *p = ':';
+ continue;
+ }
+
+ memset(ebuf, 0, sizeof(ebuf));
+ strlcpy(entry->intf_name, ifr->ifr_name,
+ sizeof(entry->intf_name));
+ entry->intf_len = sizeof(ebuf);
+
+ /* Repair the alias name back up */
+ if (p) *p = ':';
+
+ if (_intf_get_noalias(intf, entry) < 0)
+ return (-1);
+ if (_intf_get_aliases(intf, entry) < 0)
+ return (-1);
+
+ if ((ret = (*callback)(entry, arg)) != 0)
+ return (ret);
+
+ pifr = ifr;
+ }
+ return (0);
+}
+#endif /* !HAVE_LINUX_PROCFS */
+
+intf_t *
+intf_close(intf_t *intf)
+{
+ if (intf != NULL) {
+ if (intf->fd >= 0)
+ close(intf->fd);
+ if (intf->fd6 >= 0)
+ close(intf->fd6);
+ free(intf);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/ip-cooked.c b/libdnet-stripped/src/ip-cooked.c
new file mode 100644
index 0000000..98f6e3e
--- /dev/null
+++ b/libdnet-stripped/src/ip-cooked.c
@@ -0,0 +1,250 @@
+/*
+ * ip-cooked.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip-cooked.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+#include "queue.h"
+
+struct ip_intf {
+ eth_t *eth;
+ char name[INTF_NAME_LEN];
+ struct addr ha;
+ struct addr pa;
+ int mtu;
+ LIST_ENTRY(ip_intf) next;
+};
+
+struct ip_handle {
+ arp_t *arp;
+ intf_t *intf;
+ route_t *route;
+ int fd;
+ struct sockaddr_in sin;
+
+ LIST_HEAD(, ip_intf) ip_intf_list;
+};
+
+static int
+_add_ip_intf(const struct intf_entry *entry, void *arg)
+{
+ ip_t *ip = (ip_t *)arg;
+ struct ip_intf *ipi;
+
+ if (entry->intf_type == INTF_TYPE_ETH &&
+ (entry->intf_flags & INTF_FLAG_UP) != 0 &&
+ entry->intf_mtu >= ETH_LEN_MIN &&
+ entry->intf_addr.addr_type == ADDR_TYPE_IP &&
+ entry->intf_link_addr.addr_type == ADDR_TYPE_ETH) {
+
+ if ((ipi = calloc(1, sizeof(*ipi))) == NULL)
+ return (-1);
+
+ strlcpy(ipi->name, entry->intf_name, sizeof(ipi->name));
+ memcpy(&ipi->ha, &entry->intf_link_addr, sizeof(ipi->ha));
+ memcpy(&ipi->pa, &entry->intf_addr, sizeof(ipi->pa));
+ ipi->mtu = entry->intf_mtu;
+
+ LIST_INSERT_HEAD(&ip->ip_intf_list, ipi, next);
+ }
+ return (0);
+}
+
+ip_t *
+ip_open(void)
+{
+ ip_t *ip;
+
+ if ((ip = calloc(1, sizeof(*ip))) != NULL) {
+ ip->fd = -1;
+
+ if ((ip->arp = arp_open()) == NULL ||
+ (ip->intf = intf_open()) == NULL ||
+ (ip->route = route_open()) == NULL)
+ return (ip_close(ip));
+
+ if ((ip->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (ip_close(ip));
+
+ memset(&ip->sin, 0, sizeof(ip->sin));
+ ip->sin.sin_family = AF_INET;
+ ip->sin.sin_port = htons(666);
+
+ LIST_INIT(&ip->ip_intf_list);
+
+ if (intf_loop(ip->intf, _add_ip_intf, ip) != 0)
+ return (ip_close(ip));
+ }
+ return (ip);
+}
+
+static struct ip_intf *
+_lookup_ip_intf(ip_t *ip, ip_addr_t dst)
+{
+ struct ip_intf *ipi;
+ int n;
+
+ ip->sin.sin_addr.s_addr = dst;
+ n = sizeof(ip->sin);
+
+ if (connect(ip->fd, (struct sockaddr *)&ip->sin, n) < 0)
+ return (NULL);
+
+ if (getsockname(ip->fd, (struct sockaddr *)&ip->sin, &n) < 0)
+ return (NULL);
+
+ LIST_FOREACH(ipi, &ip->ip_intf_list, next) {
+ if (ipi->pa.addr_ip == ip->sin.sin_addr.s_addr) {
+ if (ipi->eth == NULL) {
+ if ((ipi->eth = eth_open(ipi->name)) == NULL)
+ return (NULL);
+ }
+ if (ipi != LIST_FIRST(&ip->ip_intf_list)) {
+ LIST_REMOVE(ipi, next);
+ LIST_INSERT_HEAD(&ip->ip_intf_list, ipi, next);
+ }
+ return (ipi);
+ }
+ }
+ return (NULL);
+}
+
+static void
+_request_arp(struct ip_intf *ipi, struct addr *dst)
+{
+ u_char frame[ETH_HDR_LEN + ARP_HDR_LEN + ARP_ETHIP_LEN];
+
+ eth_pack_hdr(frame, ETH_ADDR_BROADCAST, ipi->ha.addr_eth,
+ ETH_TYPE_ARP);
+ arp_pack_hdr_ethip(frame + ETH_HDR_LEN, ARP_OP_REQUEST,
+ ipi->ha.addr_eth, ipi->pa.addr_ip, ETH_ADDR_BROADCAST,
+ dst->addr_ip);
+
+ eth_send(ipi->eth, frame, sizeof(frame));
+}
+
+ssize_t
+ip_send(ip_t *ip, const void *buf, size_t len)
+{
+ struct ip_hdr *iph;
+ struct ip_intf *ipi;
+ struct arp_entry arpent;
+ struct route_entry rtent;
+ u_char frame[ETH_LEN_MAX];
+ int i, usec;
+
+ iph = (struct ip_hdr *)buf;
+
+ if ((ipi = _lookup_ip_intf(ip, iph->ip_dst)) == NULL) {
+ errno = EHOSTUNREACH;
+ return (-1);
+ }
+ arpent.arp_pa.addr_type = ADDR_TYPE_IP;
+ arpent.arp_pa.addr_bits = IP_ADDR_BITS;
+ arpent.arp_pa.addr_ip = iph->ip_dst;
+ memcpy(&rtent.route_dst, &arpent.arp_pa, sizeof(rtent.route_dst));
+
+ for (i = 0, usec = 10; i < 3; i++, usec *= 100) {
+ if (arp_get(ip->arp, &arpent) == 0)
+ break;
+
+ if (route_get(ip->route, &rtent) == 0 &&
+ rtent.route_gw.addr_ip != ipi->pa.addr_ip) {
+ memcpy(&arpent.arp_pa, &rtent.route_gw,
+ sizeof(arpent.arp_pa));
+ if (arp_get(ip->arp, &arpent) == 0)
+ break;
+ }
+ _request_arp(ipi, &arpent.arp_pa);
+
+ usleep(usec);
+ }
+ if (i == 3)
+ memset(&arpent.arp_ha.addr_eth, 0xff, ETH_ADDR_LEN);
+
+ eth_pack_hdr(frame, arpent.arp_ha.addr_eth,
+ ipi->ha.addr_eth, ETH_TYPE_IP);
+
+ if (len > ipi->mtu) {
+ u_char *p, *start, *end, *ip_data;
+ int ip_hl, fraglen;
+
+ ip_hl = iph->ip_hl << 2;
+ fraglen = ipi->mtu - ip_hl;
+
+ iph = (struct ip_hdr *)(frame + ETH_HDR_LEN);
+ memcpy(iph, buf, ip_hl);
+ ip_data = (u_char *)iph + ip_hl;
+
+ start = (u_char *)buf + ip_hl;
+ end = (u_char *)buf + len;
+
+ for (p = start; p < end; ) {
+ memcpy(ip_data, p, fraglen);
+
+ iph->ip_len = htons(ip_hl + fraglen);
+ iph->ip_off = htons(((p + fraglen < end) ? IP_MF : 0) |
+ ((p - start) >> 3));
+
+ ip_checksum(iph, ip_hl + fraglen);
+
+ i = ETH_HDR_LEN + ip_hl + fraglen;
+ if (eth_send(ipi->eth, frame, i) != i)
+ return (-1);
+ p += fraglen;
+ if (end - p < fraglen)
+ fraglen = end - p;
+ }
+ return (len);
+ }
+ memcpy(frame + ETH_HDR_LEN, buf, len);
+ i = ETH_HDR_LEN + len;
+ if (eth_send(ipi->eth, frame, i) != i)
+ return (-1);
+
+ return (len);
+}
+
+ip_t *
+ip_close(ip_t *ip)
+{
+ struct ip_intf *ipi, *nxt;
+
+ if (ip != NULL) {
+ for (ipi = LIST_FIRST(&ip->ip_intf_list);
+ ipi != LIST_END(&ip->ip_intf_list); ipi = nxt) {
+ nxt = LIST_NEXT(ipi, next);
+ if (ipi->eth != NULL)
+ eth_close(ipi->eth);
+ free(ipi);
+ }
+ if (ip->fd >= 0)
+ close(ip->fd);
+ if (ip->route != NULL)
+ route_close(ip->route);
+ if (ip->intf != NULL)
+ intf_close(ip->intf);
+ if (ip->arp != NULL)
+ arp_close(ip->arp);
+ free(ip);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/ip-util.c b/libdnet-stripped/src/ip-util.c
new file mode 100644
index 0000000..280f0ee
--- /dev/null
+++ b/libdnet-stripped/src/ip-util.c
@@ -0,0 +1,217 @@
+/*
+ * ip-util.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip-util.c 595 2005-02-17 02:55:56Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+#include "crc32ct.h"
+
+/* CRC-32C (Castagnoli). Public domain. */
+static unsigned long
+_crc32c(unsigned char *buf, int len)
+{
+ int i;
+ unsigned long crc32 = ~0L;
+ unsigned long result;
+ unsigned char byte0, byte1, byte2, byte3;
+
+ for (i = 0; i < len; i++) {
+ CRC32C(crc32, buf[i]);
+ }
+
+ result = ~crc32;
+
+ byte0 = result & 0xff;
+ byte1 = (result >> 8) & 0xff;
+ byte2 = (result >> 16) & 0xff;
+ byte3 = (result >> 24) & 0xff;
+ crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
+ return crc32;
+}
+
+ssize_t
+ip_add_option(void *buf, size_t len, int proto,
+ const void *optbuf, size_t optlen)
+{
+ struct ip_hdr *ip;
+ struct tcp_hdr *tcp = NULL;
+ u_char *p;
+ int hl, datalen, padlen;
+
+ if (proto != IP_PROTO_IP && proto != IP_PROTO_TCP) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ip = (struct ip_hdr *)buf;
+ hl = ip->ip_hl << 2;
+ p = (u_char *)buf + hl;
+
+ if (proto == IP_PROTO_TCP) {
+ tcp = (struct tcp_hdr *)p;
+ hl = tcp->th_off << 2;
+ p = (u_char *)tcp + hl;
+ }
+ datalen = (int) (ntohs(ip->ip_len) - (p - (u_char *)buf));
+
+ /* Compute padding to next word boundary. */
+ if ((padlen = 4 - (optlen % 4)) == 4)
+ padlen = 0;
+
+ /* XXX - IP_HDR_LEN_MAX == TCP_HDR_LEN_MAX */
+ if (hl + optlen + padlen > IP_HDR_LEN_MAX ||
+ ntohs(ip->ip_len) + optlen + padlen > len) {
+ errno = EINVAL;
+ return (-1);
+ }
+ /* XXX - IP_OPT_TYPEONLY() == TCP_OPT_TYPEONLY */
+ if (IP_OPT_TYPEONLY(((struct ip_opt *)optbuf)->opt_type))
+ optlen = 1;
+
+ /* Shift any existing data. */
+ if (datalen) {
+ memmove(p + optlen + padlen, p, datalen);
+ }
+ /* XXX - IP_OPT_NOP == TCP_OPT_NOP */
+ if (padlen) {
+ memset(p, IP_OPT_NOP, padlen);
+ p += padlen;
+ }
+ memmove(p, optbuf, optlen);
+ p += optlen;
+ optlen += padlen;
+
+ if (proto == IP_PROTO_IP)
+ ip->ip_hl = (int) ((p - (u_char *)ip) >> 2);
+ else if (proto == IP_PROTO_TCP)
+ tcp->th_off = (int) ((p - (u_char *)tcp) >> 2);
+
+ ip->ip_len = htons((u_short) (ntohs(ip->ip_len) + optlen));
+
+ return (ssize_t)(optlen);
+}
+
+void
+ip_checksum(void *buf, size_t len)
+{
+ struct ip_hdr *ip;
+ int hl, off, sum;
+
+ if (len < IP_HDR_LEN)
+ return;
+
+ ip = (struct ip_hdr *)buf;
+ hl = ip->ip_hl << 2;
+ ip->ip_sum = 0;
+ sum = ip_cksum_add(ip, hl, 0);
+ ip->ip_sum = ip_cksum_carry(sum);
+
+ off = htons(ip->ip_off);
+
+ if ((off & IP_OFFMASK) != 0 || (off & IP_MF) != 0)
+ return;
+
+ len -= hl;
+
+ if (ip->ip_p == IP_PROTO_TCP) {
+ struct tcp_hdr *tcp = (struct tcp_hdr *)((u_char *)ip + hl);
+
+ if (len >= TCP_HDR_LEN) {
+ tcp->th_sum = 0;
+ sum = ip_cksum_add(tcp, len, 0) +
+ htons((u_short)(ip->ip_p + len));
+ sum = ip_cksum_add(&ip->ip_src, 8, sum);
+ tcp->th_sum = ip_cksum_carry(sum);
+ }
+ } else if (ip->ip_p == IP_PROTO_UDP) {
+ struct udp_hdr *udp = (struct udp_hdr *)((u_char *)ip + hl);
+
+ if (len >= UDP_HDR_LEN) {
+ udp->uh_sum = 0;
+ sum = ip_cksum_add(udp, len, 0) +
+ htons((u_short)(ip->ip_p + len));
+ sum = ip_cksum_add(&ip->ip_src, 8, sum);
+ udp->uh_sum = ip_cksum_carry(sum);
+ if (!udp->uh_sum)
+ udp->uh_sum = 0xffff; /* RFC 768 */
+ }
+ } else if (ip->ip_p == IP_PROTO_SCTP) {
+ struct sctp_hdr *sctp = (struct sctp_hdr *)((u_char *)ip + hl);
+
+ if (len >= SCTP_HDR_LEN) {
+ sctp->sh_sum = 0;
+ sctp->sh_sum = htonl(_crc32c((u_char *)sctp, len));
+ }
+ } else if (ip->ip_p == IP_PROTO_ICMP || ip->ip_p == IP_PROTO_IGMP) {
+ struct icmp_hdr *icmp = (struct icmp_hdr *)((u_char *)ip + hl);
+
+ if (len >= ICMP_HDR_LEN) {
+ icmp->icmp_cksum = 0;
+ sum = ip_cksum_add(icmp, len, 0);
+ icmp->icmp_cksum = ip_cksum_carry(sum);
+ }
+ }
+}
+
+int
+ip_cksum_add(const void *buf, size_t len, int cksum)
+{
+ uint16_t *sp = (uint16_t *)buf;
+ int n, sn;
+
+ sn = (int) len / 2;
+ n = (sn + 15) / 16;
+
+ /* XXX - unroll loop using Duff's device. */
+ switch (sn % 16) {
+ case 0: do {
+ cksum += *sp++;
+ case 15:
+ cksum += *sp++;
+ case 14:
+ cksum += *sp++;
+ case 13:
+ cksum += *sp++;
+ case 12:
+ cksum += *sp++;
+ case 11:
+ cksum += *sp++;
+ case 10:
+ cksum += *sp++;
+ case 9:
+ cksum += *sp++;
+ case 8:
+ cksum += *sp++;
+ case 7:
+ cksum += *sp++;
+ case 6:
+ cksum += *sp++;
+ case 5:
+ cksum += *sp++;
+ case 4:
+ cksum += *sp++;
+ case 3:
+ cksum += *sp++;
+ case 2:
+ cksum += *sp++;
+ case 1:
+ cksum += *sp++;
+ } while (--n > 0);
+ }
+ if (len & 1)
+ cksum += htons(*(u_char *)sp << 8);
+
+ return (cksum);
+}
diff --git a/libdnet-stripped/src/ip-win32.c b/libdnet-stripped/src/ip-win32.c
new file mode 100644
index 0000000..8f2ae84
--- /dev/null
+++ b/libdnet-stripped/src/ip-win32.c
@@ -0,0 +1,79 @@
+/*
+ * ip-win32.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip-win32.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <ws2tcpip.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+struct ip_handle {
+ WSADATA wsdata;
+ SOCKET fd;
+ struct sockaddr_in sin;
+};
+
+ip_t *
+ip_open(void)
+{
+ BOOL on;
+ ip_t *ip;
+
+ if ((ip = calloc(1, sizeof(*ip))) != NULL) {
+ if (WSAStartup(MAKEWORD(2, 2), &ip->wsdata) != 0) {
+ free(ip);
+ return (NULL);
+ }
+ if ((ip->fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) ==
+ INVALID_SOCKET)
+ return (ip_close(ip));
+
+ on = TRUE;
+ if (setsockopt(ip->fd, IPPROTO_IP, IP_HDRINCL,
+ (const char *)&on, sizeof(on)) == SOCKET_ERROR) {
+ SetLastError(ERROR_NETWORK_ACCESS_DENIED);
+ return (ip_close(ip));
+ }
+ ip->sin.sin_family = AF_INET;
+ ip->sin.sin_port = htons(666);
+ }
+ return (ip);
+}
+
+ssize_t
+ip_send(ip_t *ip, const void *buf, size_t len)
+{
+ struct ip_hdr *hdr = (struct ip_hdr *)buf;
+
+ ip->sin.sin_addr.s_addr = hdr->ip_src;
+
+ if ((len = sendto(ip->fd, (const char *)buf, (int)len, 0,
+ (struct sockaddr *)&ip->sin, sizeof(ip->sin))) != SOCKET_ERROR)
+ return (ssize_t)(len);
+
+ return (-1);
+}
+
+ip_t *
+ip_close(ip_t *ip)
+{
+ if (ip != NULL) {
+ WSACleanup();
+ if (ip->fd != INVALID_SOCKET)
+ closesocket(ip->fd);
+ free(ip);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/ip.c b/libdnet-stripped/src/ip.c
new file mode 100644
index 0000000..6b513ce
--- /dev/null
+++ b/libdnet-stripped/src/ip.c
@@ -0,0 +1,104 @@
+/*
+ * ip.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#include "config.h"
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct ip_handle {
+ int fd;
+};
+
+ip_t *
+ip_open(void)
+{
+ ip_t *i;
+ int n;
+ socklen_t len;
+
+ if ((i = calloc(1, sizeof(*i))) == NULL)
+ return (NULL);
+
+ if ((i->fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
+ return (ip_close(i));
+#ifdef IP_HDRINCL
+ n = 1;
+ if (setsockopt(i->fd, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n)) < 0)
+ return (ip_close(i));
+#endif
+#ifdef SO_SNDBUF
+ len = sizeof(n);
+ if (getsockopt(i->fd, SOL_SOCKET, SO_SNDBUF, &n, &len) < 0)
+ return (ip_close(i));
+
+ for (n += 128; n < 1048576; n += 128) {
+ if (setsockopt(i->fd, SOL_SOCKET, SO_SNDBUF, &n, len) < 0) {
+ if (errno == ENOBUFS)
+ break;
+ return (ip_close(i));
+ }
+ }
+#endif
+#ifdef SO_BROADCAST
+ n = 1;
+ if (setsockopt(i->fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) < 0)
+ return (ip_close(i));
+#endif
+ return (i);
+}
+
+ssize_t
+ip_send(ip_t *i, const void *buf, size_t len)
+{
+ struct ip_hdr *ip;
+ struct sockaddr_in sin;
+
+ ip = (struct ip_hdr *)buf;
+
+ memset(&sin, 0, sizeof(sin));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sin.sin_len = sizeof(sin);
+#endif
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = ip->ip_dst;
+
+#ifdef HAVE_RAWIP_HOST_OFFLEN
+ ip->ip_len = ntohs(ip->ip_len);
+ ip->ip_off = ntohs(ip->ip_off);
+
+ len = sendto(i->fd, buf, len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
+
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+
+ return (len);
+#else
+ return (sendto(i->fd, buf, len, 0,
+ (struct sockaddr *)&sin, sizeof(sin)));
+#endif
+}
+
+ip_t *
+ip_close(ip_t *i)
+{
+ if (i != NULL) {
+ if (i->fd >= 0)
+ close(i->fd);
+ free(i);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/ip6.c b/libdnet-stripped/src/ip6.c
new file mode 100644
index 0000000..b5f474b
--- /dev/null
+++ b/libdnet-stripped/src/ip6.c
@@ -0,0 +1,76 @@
+/*
+ * ip6.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip6.c 539 2005-01-23 07:36:54Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include "dnet.h"
+
+#define IP6_IS_EXT(n) \
+ ((n) == IP_PROTO_HOPOPTS || (n) == IP_PROTO_DSTOPTS || \
+ (n) == IP_PROTO_ROUTING || (n) == IP_PROTO_FRAGMENT)
+
+void
+ip6_checksum(void *buf, size_t len)
+{
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
+ struct ip6_ext_hdr *ext;
+ u_char *p, nxt;
+ int i, sum;
+
+ nxt = ip6->ip6_nxt;
+
+ for (i = IP6_HDR_LEN; IP6_IS_EXT(nxt); i += (ext->ext_len + 1) << 3) {
+ if (i >= (int)len) return;
+ ext = (struct ip6_ext_hdr *)((u_char *)buf + i);
+ nxt = ext->ext_nxt;
+ }
+ p = (u_char *)buf + i;
+ len -= i;
+
+ if (nxt == IP_PROTO_TCP) {
+ struct tcp_hdr *tcp = (struct tcp_hdr *)p;
+
+ if (len >= TCP_HDR_LEN) {
+ tcp->th_sum = 0;
+ sum = ip_cksum_add(tcp, len, 0) + htons(nxt + (u_short)len);
+ sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
+ tcp->th_sum = ip_cksum_carry(sum);
+ }
+ } else if (nxt == IP_PROTO_UDP) {
+ struct udp_hdr *udp = (struct udp_hdr *)p;
+
+ if (len >= UDP_HDR_LEN) {
+ udp->uh_sum = 0;
+ sum = ip_cksum_add(udp, len, 0) + htons(nxt + (u_short)len);
+ sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
+ if ((udp->uh_sum = ip_cksum_carry(sum)) == 0)
+ udp->uh_sum = 0xffff;
+ }
+ } else if (nxt == IP_PROTO_ICMPV6) {
+ struct icmp_hdr *icmp = (struct icmp_hdr *)p;
+
+ if (len >= ICMP_HDR_LEN) {
+ icmp->icmp_cksum = 0;
+ sum = ip_cksum_add(icmp, len, 0) + htons(nxt + (u_short)len);
+ sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
+ icmp->icmp_cksum = ip_cksum_carry(sum);
+ }
+ } else if (nxt == IP_PROTO_ICMP || nxt == IP_PROTO_IGMP) {
+ struct icmp_hdr *icmp = (struct icmp_hdr *)p;
+
+ if (len >= ICMP_HDR_LEN) {
+ icmp->icmp_cksum = 0;
+ sum = ip_cksum_add(icmp, len, 0);
+ icmp->icmp_cksum = ip_cksum_carry(sum);
+ }
+ }
+}
diff --git a/libdnet-stripped/src/memcmp.c b/libdnet-stripped/src/memcmp.c
new file mode 100644
index 0000000..5ce33e2
--- /dev/null
+++ b/libdnet-stripped/src/memcmp.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: memcmp.c,v 1.2 1996/08/19 08:34:05 tholo Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+/*
+ * Compare memory regions.
+ */
+int
+memcmp(s1, s2, n)
+ const void *s1, *s2;
+ size_t n;
+{
+ if (n != 0) {
+ register const unsigned char *p1 = s1, *p2 = s2;
+
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/libdnet-stripped/src/rand.c b/libdnet-stripped/src/rand.c
new file mode 100644
index 0000000..9095ad8
--- /dev/null
+++ b/libdnet-stripped/src/rand.c
@@ -0,0 +1,208 @@
+/*
+ * rand.c
+ *
+ * Pseudorandom number generation, based on OpenBSD arc4random().
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ * Copyright (c) 1996 David Mazieres <dm@lcs.mit.edu>
+ *
+ * $Id: rand.c 587 2005-02-15 06:37:07Z dugsong $
+ */
+
+#include "config.h"
+
+#ifdef _WIN32
+/* XXX */
+# undef _WIN32_WINNT
+# define _WIN32_WINNT _WIN32_WINNT_WIN7
+# include <bcrypt.h>
+# pragma comment(lib, "bcrypt.lib")
+# define inline __inline
+#else
+# include <sys/types.h>
+# include <sys/time.h>
+# include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+struct rand_handle {
+ uint8_t i;
+ uint8_t j;
+ uint8_t s[256];
+ u_char *tmp;
+ int tmplen;
+};
+
+static inline void
+rand_init(rand_t *rand)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ rand->s[i] = i;
+ rand->i = rand->j = 0;
+}
+
+static inline void
+rand_addrandom(rand_t *rand, u_char *buf, int len)
+{
+ int i;
+ uint8_t si;
+
+ rand->i--;
+ for (i = 0; i < 256; i++) {
+ rand->i = (rand->i + 1);
+ si = rand->s[rand->i];
+ rand->j = (rand->j + si + buf[i % len]);
+ rand->s[rand->i] = rand->s[rand->j];
+ rand->s[rand->j] = si;
+ }
+ rand->j = rand->i;
+}
+
+rand_t *
+rand_open(void)
+{
+ rand_t *r;
+ u_char seed[256];
+#ifdef _WIN32
+ if (STATUS_SUCCESS != BCryptGenRandom(NULL, seed, sizeof(seed), BCRYPT_USE_SYSTEM_PREFERRED_RNG))
+ return NULL;
+#else
+ struct timeval *tv = (struct timeval *)seed;
+ int fd;
+
+ if ((fd = open("/dev/arandom", O_RDONLY)) != -1 ||
+ (fd = open("/dev/urandom", O_RDONLY)) != -1) {
+ read(fd, seed + sizeof(*tv), sizeof(seed) - sizeof(*tv));
+ close(fd);
+ }
+ gettimeofday(tv, NULL);
+#endif
+ if ((r = malloc(sizeof(*r))) != NULL) {
+ rand_init(r);
+ rand_addrandom(r, seed, 128);
+ rand_addrandom(r, seed + 128, 128);
+ r->tmp = NULL;
+ r->tmplen = 0;
+ }
+ return (r);
+}
+
+static uint8_t
+rand_getbyte(rand_t *r)
+{
+ uint8_t si, sj;
+
+ r->i = (r->i + 1);
+ si = r->s[r->i];
+ r->j = (r->j + si);
+ sj = r->s[r->j];
+ r->s[r->i] = sj;
+ r->s[r->j] = si;
+ return (r->s[(si + sj) & 0xff]);
+}
+
+int
+rand_get(rand_t *r, void *buf, size_t len)
+{
+ u_char *p;
+ u_int i;
+
+ for (p = buf, i = 0; i < len; i++) {
+ p[i] = rand_getbyte(r);
+ }
+ return (0);
+}
+
+int
+rand_set(rand_t *r, const void *buf, size_t len)
+{
+ rand_init(r);
+ rand_addrandom(r, (u_char *)buf, len);
+ rand_addrandom(r, (u_char *)buf, len);
+ return (0);
+}
+
+int
+rand_add(rand_t *r, const void *buf, size_t len)
+{
+ rand_addrandom(r, (u_char *)buf, len);
+ return (0);
+}
+
+uint8_t
+rand_uint8(rand_t *r)
+{
+ return (rand_getbyte(r));
+}
+
+uint16_t
+rand_uint16(rand_t *r)
+{
+ uint16_t val;
+
+ val = rand_getbyte(r) << 8;
+ val |= rand_getbyte(r);
+ return (val);
+}
+
+uint32_t
+rand_uint32(rand_t *r)
+{
+ uint32_t val;
+
+ val = rand_getbyte(r) << 24;
+ val |= rand_getbyte(r) << 16;
+ val |= rand_getbyte(r) << 8;
+ val |= rand_getbyte(r);
+ return (val);
+}
+
+int
+rand_shuffle(rand_t *r, void *base, size_t nmemb, size_t size)
+{
+ u_char *save, *src, *dst, *start = (u_char *)base;
+ u_int i, j;
+
+ if (nmemb < 2)
+ return (0);
+
+ if ((u_int)r->tmplen < size) {
+ if (r->tmp == NULL) {
+ if ((save = malloc(size)) == NULL)
+ return (-1);
+ } else if ((save = realloc(r->tmp, size)) == NULL)
+ return (-1);
+
+ r->tmp = save;
+ r->tmplen = size;
+ } else
+ save = r->tmp;
+
+ for (i = 0; i < nmemb; i++) {
+ if ((j = rand_uint32(r) % (nmemb - 1)) != i) {
+ src = start + (size * i);
+ dst = start + (size * j);
+ memcpy(save, dst, size);
+ memcpy(dst, src, size);
+ memcpy(src, save, size);
+ }
+ }
+ return (0);
+}
+
+rand_t *
+rand_close(rand_t *r)
+{
+ if (r != NULL) {
+ if (r->tmp != NULL)
+ free(r->tmp);
+ free(r);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/route-bsd.c b/libdnet-stripped/src/route-bsd.c
new file mode 100644
index 0000000..2ca799c
--- /dev/null
+++ b/libdnet-stripped/src/route-bsd.c
@@ -0,0 +1,703 @@
+/*
+ * route-bsd.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ * Copyright (c) 1999 Masaki Hirabaru <masaki@merit.edu>
+ *
+ * $Id: route-bsd.c 555 2005-02-10 05:18:38Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_STREAMS_MIB2
+#include <sys/stream.h>
+#include <sys/tihdr.h>
+#include <sys/tiuser.h>
+#include <inet/common.h>
+#include <inet/mib2.h>
+#include <inet/ip.h>
+#undef IP_ADDR_LEN
+#include <stropts.h>
+#elif defined(HAVE_STREAMS_ROUTE)
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#endif
+#ifdef HAVE_GETKERNINFO
+#include <sys/kinfo.h>
+#endif
+
+#define route_t oroute_t /* XXX - unixware */
+#include <net/route.h>
+#undef route_t
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#if defined(RT_ROUNDUP) && defined(__NetBSD__)
+/* NetBSD defines this macro rounding to 64-bit boundaries.
+ http://fxr.watson.org/fxr/ident?v=NETBSD;i=RT_ROUNDUP */
+#define ROUNDUP(a) RT_ROUNDUP(a)
+#else
+/* Unix Network Programming, 3rd edition says that sockaddr structures in
+ rt_msghdr should be padded so their addresses start on a multiple of
+ sizeof(u_long). But on 64-bit Mac OS X 10.6 at least, this is false. Apple's
+ netstat code uses 4-byte padding, not 8-byte. This is relevant for IPv6
+ addresses, for which sa_len == 28.
+ http://www.opensource.apple.com/source/network_cmds/network_cmds-329.2.2/netstat.tproj/route.c */
+#ifdef __APPLE__
+#define RT_MSGHDR_ALIGNMENT sizeof(uint32_t)
+#else
+#define RT_MSGHDR_ALIGNMENT sizeof(unsigned long)
+#endif
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (RT_MSGHDR_ALIGNMENT - 1))) : RT_MSGHDR_ALIGNMENT)
+#endif
+
+#ifdef HAVE_SOCKADDR_SA_LEN
+#define NEXTSA(s) \
+ ((struct sockaddr *)((u_char *)(s) + ROUNDUP((s)->sa_len)))
+#else
+#define NEXTSA(s) \
+ ((struct sockaddr *)((u_char *)(s) + ROUNDUP(sizeof(*(s)))))
+#endif
+
+struct route_handle {
+ int fd;
+ int seq;
+#ifdef HAVE_STREAMS_MIB2
+ int ip_fd;
+#endif
+};
+
+#ifdef DEBUG
+static void
+route_msg_print(struct rt_msghdr *rtm)
+{
+ printf("v: %d type: 0x%x flags: 0x%x addrs: 0x%x pid: %d seq: %d\n",
+ rtm->rtm_version, rtm->rtm_type, rtm->rtm_flags,
+ rtm->rtm_addrs, rtm->rtm_pid, rtm->rtm_seq);
+}
+#endif
+
+static int
+route_msg(route_t *r, int type, char intf_name[INTF_NAME_LEN], struct addr *dst, struct addr *gw)
+{
+ struct addr net;
+ struct rt_msghdr *rtm;
+ struct sockaddr *sa;
+ u_char buf[BUFSIZ];
+ pid_t pid;
+ int len;
+
+ memset(buf, 0, sizeof(buf));
+
+ rtm = (struct rt_msghdr *)buf;
+ rtm->rtm_version = RTM_VERSION;
+ if ((rtm->rtm_type = type) != RTM_DELETE)
+ rtm->rtm_flags = RTF_UP;
+ rtm->rtm_addrs = RTA_DST;
+ rtm->rtm_seq = ++r->seq;
+
+ /* Destination */
+ sa = (struct sockaddr *)(rtm + 1);
+ if (addr_net(dst, &net) < 0 || addr_ntos(&net, sa) < 0)
+ return (-1);
+ sa = NEXTSA(sa);
+
+ /* Gateway */
+ if (gw != NULL && type != RTM_GET) {
+ rtm->rtm_flags |= RTF_GATEWAY;
+ rtm->rtm_addrs |= RTA_GATEWAY;
+ if (addr_ntos(gw, sa) < 0)
+ return (-1);
+ sa = NEXTSA(sa);
+ }
+ /* Netmask */
+ if (dst->addr_ip == IP_ADDR_ANY || dst->addr_bits < IP_ADDR_BITS) {
+ rtm->rtm_addrs |= RTA_NETMASK;
+ if (addr_btos(dst->addr_bits, sa) < 0)
+ return (-1);
+ sa = NEXTSA(sa);
+ } else
+ rtm->rtm_flags |= RTF_HOST;
+
+ rtm->rtm_msglen = (u_char *)sa - buf;
+#ifdef DEBUG
+ route_msg_print(rtm);
+#endif
+#ifdef HAVE_STREAMS_ROUTE
+ if (ioctl(r->fd, RTSTR_SEND, rtm) < 0)
+ return (-1);
+#else
+ if (write(r->fd, buf, rtm->rtm_msglen) < 0)
+ return (-1);
+
+ pid = getpid();
+
+ while (type == RTM_GET && (len = read(r->fd, buf, sizeof(buf))) > 0) {
+ if (len < (int)sizeof(*rtm)) {
+ return (-1);
+ }
+ if (rtm->rtm_type == type && rtm->rtm_pid == pid &&
+ rtm->rtm_seq == r->seq) {
+ if (rtm->rtm_errno) {
+ errno = rtm->rtm_errno;
+ return (-1);
+ }
+ break;
+ }
+ }
+#endif
+ if (type == RTM_GET && (rtm->rtm_addrs & (RTA_DST|RTA_GATEWAY)) ==
+ (RTA_DST|RTA_GATEWAY)) {
+ sa = (struct sockaddr *)(rtm + 1);
+ sa = NEXTSA(sa);
+
+ if (addr_ston(sa, gw) < 0 || gw->addr_type != ADDR_TYPE_IP) {
+ errno = ESRCH;
+ return (-1);
+ }
+
+ if (intf_name != NULL) {
+ char namebuf[IF_NAMESIZE];
+
+ if (if_indextoname(rtm->rtm_index, namebuf) == NULL) {
+ errno = ESRCH;
+ return (-1);
+ }
+ strlcpy(intf_name, namebuf, INTF_NAME_LEN);
+ }
+ }
+ return (0);
+}
+
+route_t *
+route_open(void)
+{
+ route_t *r;
+
+ if ((r = calloc(1, sizeof(*r))) != NULL) {
+ r->fd = -1;
+#ifdef HAVE_STREAMS_MIB2
+ if ((r->ip_fd = open(IP_DEV_NAME, O_RDWR)) < 0)
+ return (route_close(r));
+#endif
+#ifdef HAVE_STREAMS_ROUTE
+ if ((r->fd = open("/dev/route", O_RDWR, 0)) < 0)
+#else
+ if ((r->fd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0)
+#endif
+ return (route_close(r));
+ }
+ return (r);
+}
+
+int
+route_add(route_t *r, const struct route_entry *entry)
+{
+ struct route_entry rtent;
+
+ memcpy(&rtent, entry, sizeof(rtent));
+
+ if (route_msg(r, RTM_ADD, NULL, &rtent.route_dst, &rtent.route_gw) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+route_delete(route_t *r, const struct route_entry *entry)
+{
+ struct route_entry rtent;
+
+ memcpy(&rtent, entry, sizeof(rtent));
+
+ if (route_get(r, &rtent) < 0)
+ return (-1);
+
+ if (route_msg(r, RTM_DELETE, NULL, &rtent.route_dst, &rtent.route_gw) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+route_get(route_t *r, struct route_entry *entry)
+{
+ if (route_msg(r, RTM_GET, entry->intf_name, &entry->route_dst, &entry->route_gw) < 0)
+ return (-1);
+ entry->intf_name[0] = '\0';
+ entry->metric = 0;
+
+ return (0);
+}
+
+#if defined(HAVE_SYS_SYSCTL_H) || defined(HAVE_STREAMS_ROUTE) || defined(HAVE_GETKERNINFO)
+/* This wrapper around addr_ston, on failure, checks for a gateway address
+ * family of AF_LINK, and if it finds one, stores an all-zero address of the
+ * same type as dst. The all-zero address is a convention for same-subnet
+ * routing table entries. */
+static int
+addr_ston_gateway(const struct addr *dst,
+ const struct sockaddr *sa, struct addr *a)
+{
+ int rc;
+
+ rc = addr_ston(sa, a);
+ if (rc == 0)
+ return rc;
+
+#ifdef HAVE_NET_IF_DL_H
+# ifdef AF_LINK
+ if (sa->sa_family == AF_LINK) {
+ memset(a, 0, sizeof(*a));
+ a->addr_type = dst->addr_type;
+ return (0);
+ }
+# endif
+#endif
+
+ return (-1);
+}
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ struct rt_msghdr *rtm;
+ struct route_entry entry;
+ struct sockaddr *sa;
+ char *buf, *lim, *next;
+ int ret;
+#ifdef HAVE_SYS_SYSCTL_H
+ int mib[6] = { CTL_NET, PF_ROUTE, 0, 0 /* XXX */, NET_RT_DUMP, 0 };
+ size_t len;
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+ return (-1);
+
+ if (len == 0)
+ return (0);
+
+ if ((buf = malloc(len)) == NULL)
+ return (-1);
+
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return (-1);
+ }
+ lim = buf + len;
+ next = buf;
+#elif defined(HAVE_GETKERNINFO)
+ int len = getkerninfo(KINFO_RT_DUMP,0,0,0);
+
+ if (len == 0)
+ return (0);
+
+ if ((buf = malloc(len)) == NULL)
+ return (-1);
+
+ if (getkerninfo(KINFO_RT_DUMP,buf,&len,0) < 0) {
+ free(buf);
+ return (-1);
+ }
+ lim = buf + len;
+ next = buf;
+#else /* HAVE_STREAMS_ROUTE */
+ struct rt_giarg giarg, *gp;
+
+ memset(&giarg, 0, sizeof(giarg));
+ giarg.gi_op = KINFO_RT_DUMP;
+
+ if (ioctl(r->fd, RTSTR_GETROUTE, &giarg) < 0)
+ return (-1);
+
+ if ((buf = malloc(giarg.gi_size)) == NULL)
+ return (-1);
+
+ gp = (struct rt_giarg *)buf;
+ gp->gi_size = giarg.gi_size;
+ gp->gi_op = KINFO_RT_DUMP;
+ gp->gi_where = buf;
+ gp->gi_arg = RTF_UP | RTF_GATEWAY;
+
+ if (ioctl(r->fd, RTSTR_GETROUTE, buf) < 0) {
+ free(buf);
+ return (-1);
+ }
+ lim = buf + gp->gi_size;
+ next = buf + sizeof(giarg);
+#endif
+ /* This loop assumes that RTA_DST, RTA_GATEWAY, and RTA_NETMASK have the
+ * values, 1, 2, and 4 respectively. Cf. Unix Network Programming,
+ * p. 494, function get_rtaddrs. */
+ for (ret = 0; next < lim; next += rtm->rtm_msglen) {
+ char namebuf[IF_NAMESIZE];
+ sa_family_t sfam;
+ rtm = (struct rt_msghdr *)next;
+ sa = (struct sockaddr *)(rtm + 1);
+ /* peek at address family */
+ sfam = sa->sa_family;
+
+ if (if_indextoname(rtm->rtm_index, namebuf) == NULL)
+ continue;
+ strlcpy(entry.intf_name, namebuf, sizeof(entry.intf_name));
+
+ if ((rtm->rtm_addrs & RTA_DST) == 0)
+ /* Need a destination. */
+ continue;
+ if (addr_ston(sa, &entry.route_dst) < 0)
+ continue;
+
+ if ((rtm->rtm_addrs & RTA_GATEWAY) == 0)
+ /* Need a gateway. */
+ continue;
+ sa = NEXTSA(sa);
+ if (addr_ston_gateway(&entry.route_dst, sa, &entry.route_gw) < 0)
+ continue;
+
+ if (entry.route_dst.addr_type != entry.route_gw.addr_type ||
+ (entry.route_dst.addr_type != ADDR_TYPE_IP &&
+ entry.route_dst.addr_type != ADDR_TYPE_IP6))
+ continue;
+
+ if (rtm->rtm_addrs & RTA_NETMASK) {
+ sa = NEXTSA(sa);
+ /* FreeBSD for IPv6 uses a different AF for netmasks. Force the same one. */
+ sa->sa_family = sfam;
+ if (addr_stob(sa, &entry.route_dst.addr_bits) < 0)
+ continue;
+ }
+
+ entry.metric = 0;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ free(buf);
+
+ return (ret);
+}
+#elif defined(HAVE_STREAMS_MIB2)
+
+#ifdef IRE_DEFAULT /* This means Solaris 5.6 */
+/* I'm not sure if they are compatible, though -- masaki */
+#define IRE_ROUTE IRE_CACHE
+#define IRE_ROUTE_REDIRECT IRE_HOST_REDIRECT
+#endif /* IRE_DEFAULT */
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ struct route_entry entry;
+ struct strbuf msg;
+ struct T_optmgmt_req *tor;
+ struct T_optmgmt_ack *toa;
+ struct T_error_ack *tea;
+ struct opthdr *opt;
+ u_char buf[8192];
+ int flags, rc, rtable, ret;
+
+ tor = (struct T_optmgmt_req *)buf;
+ toa = (struct T_optmgmt_ack *)buf;
+ tea = (struct T_error_ack *)buf;
+
+ tor->PRIM_type = T_OPTMGMT_REQ;
+ tor->OPT_offset = sizeof(*tor);
+ tor->OPT_length = sizeof(*opt);
+ tor->MGMT_flags = T_CURRENT;
+
+ opt = (struct opthdr *)(tor + 1);
+ opt->level = MIB2_IP;
+ opt->name = opt->len = 0;
+
+ msg.maxlen = sizeof(buf);
+ msg.len = sizeof(*tor) + sizeof(*opt);
+ msg.buf = buf;
+
+ if (putmsg(r->ip_fd, &msg, NULL, 0) < 0)
+ return (-1);
+
+ opt = (struct opthdr *)(toa + 1);
+ msg.maxlen = sizeof(buf);
+
+ for (;;) {
+ mib2_ipRouteEntry_t *rt, *rtend;
+
+ flags = 0;
+ if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
+ return (-1);
+
+ /* See if we're finished. */
+ if (rc == 0 &&
+ msg.len >= sizeof(*toa) &&
+ toa->PRIM_type == T_OPTMGMT_ACK &&
+ toa->MGMT_flags == T_SUCCESS && opt->len == 0)
+ break;
+
+ if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
+ return (-1);
+
+ if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
+ toa->PRIM_type != T_OPTMGMT_ACK ||
+ toa->MGMT_flags != T_SUCCESS)
+ return (-1);
+
+ rtable = (opt->level == MIB2_IP && opt->name == MIB2_IP_21);
+
+ msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt));
+ msg.len = 0;
+ flags = 0;
+
+ do {
+ struct sockaddr_in sin;
+
+ rc = getmsg(r->ip_fd, NULL, &msg, &flags);
+
+ if (rc != 0 && rc != MOREDATA)
+ return (-1);
+
+ if (!rtable)
+ continue;
+
+ rt = (mib2_ipRouteEntry_t *)msg.buf;
+ rtend = (mib2_ipRouteEntry_t *)(msg.buf + msg.len);
+
+ sin.sin_family = AF_INET;
+
+ for ( ; rt < rtend; rt++) {
+ if ((rt->ipRouteInfo.re_ire_type &
+ (IRE_BROADCAST|IRE_ROUTE_REDIRECT|
+ IRE_LOCAL|IRE_ROUTE)) != 0 ||
+ rt->ipRouteNextHop == IP_ADDR_ANY)
+ continue;
+
+ entry.intf_name[0] = '\0';
+
+ sin.sin_addr.s_addr = rt->ipRouteNextHop;
+ addr_ston((struct sockaddr *)&sin,
+ &entry.route_gw);
+
+ sin.sin_addr.s_addr = rt->ipRouteDest;
+ addr_ston((struct sockaddr *)&sin,
+ &entry.route_dst);
+
+ sin.sin_addr.s_addr = rt->ipRouteMask;
+ addr_stob((struct sockaddr *)&sin,
+ &entry.route_dst.addr_bits);
+
+ entry.metric = 0;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ return (ret);
+ }
+ } while (rc == MOREDATA);
+ }
+
+ tor = (struct T_optmgmt_req *)buf;
+ toa = (struct T_optmgmt_ack *)buf;
+ tea = (struct T_error_ack *)buf;
+
+ tor->PRIM_type = T_OPTMGMT_REQ;
+ tor->OPT_offset = sizeof(*tor);
+ tor->OPT_length = sizeof(*opt);
+ tor->MGMT_flags = T_CURRENT;
+
+ opt = (struct opthdr *)(tor + 1);
+ opt->level = MIB2_IP6;
+ opt->name = opt->len = 0;
+
+ msg.maxlen = sizeof(buf);
+ msg.len = sizeof(*tor) + sizeof(*opt);
+ msg.buf = buf;
+
+ if (putmsg(r->ip_fd, &msg, NULL, 0) < 0)
+ return (-1);
+
+ opt = (struct opthdr *)(toa + 1);
+ msg.maxlen = sizeof(buf);
+
+ for (;;) {
+ mib2_ipv6RouteEntry_t *rt, *rtend;
+
+ flags = 0;
+ if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
+ return (-1);
+
+ /* See if we're finished. */
+ if (rc == 0 &&
+ msg.len >= sizeof(*toa) &&
+ toa->PRIM_type == T_OPTMGMT_ACK &&
+ toa->MGMT_flags == T_SUCCESS && opt->len == 0)
+ break;
+
+ if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
+ return (-1);
+
+ if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
+ toa->PRIM_type != T_OPTMGMT_ACK ||
+ toa->MGMT_flags != T_SUCCESS)
+ return (-1);
+
+ rtable = (opt->level == MIB2_IP6 && opt->name == MIB2_IP6_ROUTE);
+
+ msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt));
+ msg.len = 0;
+ flags = 0;
+
+ do {
+ struct sockaddr_in6 sin6;
+
+ rc = getmsg(r->ip_fd, NULL, &msg, &flags);
+
+ if (rc != 0 && rc != MOREDATA)
+ return (-1);
+
+ if (!rtable)
+ continue;
+
+ rt = (mib2_ipv6RouteEntry_t *)msg.buf;
+ rtend = (mib2_ipv6RouteEntry_t *)(msg.buf + msg.len);
+
+ sin6.sin6_family = AF_INET6;
+
+ for ( ; rt < rtend; rt++) {
+ if ((rt->ipv6RouteInfo.re_ire_type &
+ (IRE_BROADCAST|IRE_ROUTE_REDIRECT|
+ IRE_LOCAL|IRE_ROUTE)) != 0 ||
+ memcmp(&rt->ipv6RouteNextHop, IP6_ADDR_UNSPEC, IP6_ADDR_LEN) == 0)
+ continue;
+
+ entry.intf_name[0] = '\0';
+
+ sin6.sin6_addr = rt->ipv6RouteNextHop;
+ addr_ston((struct sockaddr *)&sin6,
+ &entry.route_gw);
+
+ sin6.sin6_addr = rt->ipv6RouteDest;
+ addr_ston((struct sockaddr *)&sin6,
+ &entry.route_dst);
+
+ entry.route_dst.addr_bits = rt->ipv6RoutePfxLength;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ return (ret);
+ }
+ } while (rc == MOREDATA);
+ }
+ return (0);
+}
+#elif defined(HAVE_NET_RADIX_H)
+/* XXX - Tru64, others? */
+#include <nlist.h>
+
+static int
+_kread(int fd, void *addr, void *buf, int len)
+{
+ if (lseek(fd, (off_t)addr, SEEK_SET) == (off_t)-1L)
+ return (-1);
+ return (read(fd, buf, len) == len ? 0 : -1);
+}
+
+static int
+_radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg)
+{
+ struct radix_node rnode;
+ struct rtentry rt;
+ struct sockaddr_in sin;
+ struct route_entry entry;
+ int ret = 0;
+ again:
+ _kread(fd, rn, &rnode, sizeof(rnode));
+ if (rnode.rn_b < 0) {
+ if (!(rnode.rn_flags & RNF_ROOT)) {
+ entry.intf_name[0] = '\0';
+ _kread(fd, rn, &rt, sizeof(rt));
+ _kread(fd, rt_key(&rt), &sin, sizeof(sin));
+ addr_ston((struct sockaddr *)&sin, &entry.route_dst);
+ if (!(rt.rt_flags & RTF_HOST)) {
+ _kread(fd, rt_mask(&rt), &sin, sizeof(sin));
+ addr_stob((struct sockaddr *)&sin,
+ &entry.route_dst.addr_bits);
+ }
+ _kread(fd, rt.rt_gateway, &sin, sizeof(sin));
+ addr_ston((struct sockaddr *)&sin, &entry.route_gw);
+ entry.metric = 0;
+ if ((ret = callback(&entry, arg)) != 0)
+ return (ret);
+ }
+ if ((rn = rnode.rn_dupedkey))
+ goto again;
+ } else {
+ rn = rnode.rn_r;
+ if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0)
+ return (ret);
+ if ((ret = _radix_walk(fd, rn, callback, arg)) != 0)
+ return (ret);
+ }
+ return (ret);
+}
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ struct radix_node_head *rnh, head;
+ struct nlist nl[2];
+ int fd, ret = 0;
+
+ memset(nl, 0, sizeof(nl));
+ nl[0].n_name = "radix_node_head";
+
+ if (knlist(nl) < 0 || nl[0].n_type == 0 ||
+ (fd = open("/dev/kmem", O_RDONLY, 0)) < 0)
+ return (-1);
+
+ for (_kread(fd, (void *)nl[0].n_value, &rnh, sizeof(rnh));
+ rnh != NULL; rnh = head.rnh_next) {
+ _kread(fd, rnh, &head, sizeof(head));
+ /* XXX - only IPv4 for now... */
+ if (head.rnh_af == AF_INET) {
+ if ((ret = _radix_walk(fd, head.rnh_treetop,
+ callback, arg)) != 0)
+ break;
+ }
+ }
+ close(fd);
+ return (ret);
+}
+#else
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+#endif
+
+route_t *
+route_close(route_t *r)
+{
+ if (r != NULL) {
+#ifdef HAVE_STREAMS_MIB2
+ if (r->ip_fd >= 0)
+ close(r->ip_fd);
+#endif
+ if (r->fd >= 0)
+ close(r->fd);
+ free(r);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/route-hpux.c b/libdnet-stripped/src/route-hpux.c
new file mode 100644
index 0000000..07e7f8c
--- /dev/null
+++ b/libdnet-stripped/src/route-hpux.c
@@ -0,0 +1,184 @@
+/*
+ * route-hpux.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: route-hpux.c 483 2004-01-14 04:52:11Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mib.h>
+#include <sys/socket.h>
+
+#include <net/route.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#define ADDR_ISHOST(a) (((a)->addr_type == ADDR_TYPE_IP && \
+ (a)->addr_bits == IP_ADDR_BITS) || \
+ ((a)->addr_type == ADDR_TYPE_IP6 && \
+ (a)->addr_bits == IP6_ADDR_BITS))
+
+struct route_handle {
+ int fd;
+};
+
+route_t *
+route_open(void)
+{
+ route_t *r;
+
+ if ((r = calloc(1, sizeof(*r))) != NULL) {
+ if ((r->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (route_close(r));
+ }
+ return (r);
+}
+
+int
+route_add(route_t *r, const struct route_entry *entry)
+{
+ struct rtentry rt;
+ struct addr dst;
+
+ memset(&rt, 0, sizeof(rt));
+ rt.rt_flags = RTF_UP | RTF_GATEWAY;
+
+ if (ADDR_ISHOST(&entry->route_dst)) {
+ rt.rt_flags |= RTF_HOST;
+ memcpy(&dst, &entry->route_dst, sizeof(dst));
+ } else
+ addr_net(&entry->route_dst, &dst);
+
+ if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
+ addr_ntos(&entry->route_gw, &rt.rt_gateway) < 0 ||
+ addr_btom(entry->route_dst.addr_bits, &rt.rt_subnetmask,
+ IP_ADDR_LEN) < 0)
+ return (-1);
+
+ return (ioctl(r->fd, SIOCADDRT, &rt));
+}
+
+int
+route_delete(route_t *r, const struct route_entry *entry)
+{
+ struct rtentry rt;
+ struct addr dst;
+
+ memset(&rt, 0, sizeof(rt));
+ rt.rt_flags = RTF_UP;
+
+ if (ADDR_ISHOST(&entry->route_dst)) {
+ rt.rt_flags |= RTF_HOST;
+ memcpy(&dst, &entry->route_dst, sizeof(dst));
+ } else
+ addr_net(&entry->route_dst, &dst);
+
+ if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
+ addr_btom(entry->route_dst.addr_bits, &rt.rt_subnetmask,
+ IP_ADDR_LEN) < 0)
+ return (-1);
+
+ return (ioctl(r->fd, SIOCDELRT, &rt));
+}
+
+int
+route_get(route_t *r, struct route_entry *entry)
+{
+ struct rtreq rtr;
+
+ memset(&rtr, 0, sizeof(rtr));
+
+ /* XXX - gross hack for default route */
+ if (entry->route_dst.addr_ip == IP_ADDR_ANY) {
+ rtr.rtr_destaddr = htonl(0x60060606);
+ rtr.rtr_subnetmask = 0xffffffff;
+ } else {
+ memcpy(&rtr.rtr_destaddr, &entry->route_dst.addr_ip,
+ IP_ADDR_LEN);
+ if (entry->route_dst.addr_bits < IP_ADDR_BITS)
+ addr_btom(entry->route_dst.addr_bits,
+ &rtr.rtr_subnetmask, IP_ADDR_LEN);
+ }
+ if (ioctl(r->fd, SIOCGRTENTRY, &rtr) < 0)
+ return (-1);
+
+ if (rtr.rtr_gwayaddr == 0) {
+ errno = ESRCH;
+ return (-1);
+ }
+ entry->intf_name[0] = '\0';
+ entry->route_gw.addr_type = ADDR_TYPE_IP;
+ entry->route_gw.addr_bits = IP_ADDR_BITS;
+ memcpy(&entry->route_gw.addr_ip, &rtr.rtr_gwayaddr, IP_ADDR_LEN);
+ entry->metric = 0;
+
+ return (0);
+}
+
+#define MAX_RTENTRIES 256 /* XXX */
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ struct nmparms nm;
+ struct route_entry entry;
+ mib_ipRouteEnt rtentries[MAX_RTENTRIES];
+ int fd, i, n, ret;
+
+ if ((fd = open_mib("/dev/ip", O_RDWR, 0 /* XXX */, 0)) < 0)
+ return (-1);
+
+ nm.objid = ID_ipRouteTable;
+ nm.buffer = rtentries;
+ n = sizeof(rtentries);
+ nm.len = &n;
+
+ if (get_mib_info(fd, &nm) < 0) {
+ close_mib(fd);
+ return (-1);
+ }
+ close_mib(fd);
+
+ n /= sizeof(*rtentries);
+ ret = 0;
+
+ for (i = 0; i < n; i++) {
+ if (rtentries[i].Type != NMDIRECT &&
+ rtentries[i].Type != NMREMOTE)
+ continue;
+
+ entry.intf_name[0] = '\0';
+ entry.route_dst.addr_type = entry.route_gw.addr_type = ADDR_TYPE_IP;
+ entry.route_dst.addr_bits = entry.route_gw.addr_bits = IP_ADDR_BITS;
+ entry.route_dst.addr_ip = rtentries[i].Dest;
+ addr_mtob(&rtentries[i].Mask, IP_ADDR_LEN,
+ &entry.route_dst.addr_bits);
+ entry.route_gw.addr_ip = rtentries[i].NextHop;
+ entry.metric = 0;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ return (ret);
+}
+
+route_t *
+route_close(route_t *r)
+{
+ if (r != NULL) {
+ if (r->fd >= 0)
+ close(r->fd);
+ free(r);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/route-linux.c b/libdnet-stripped/src/route-linux.c
new file mode 100644
index 0000000..b14c527
--- /dev/null
+++ b/libdnet-stripped/src/route-linux.c
@@ -0,0 +1,310 @@
+/*
+ * route-linux.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: route-linux.c 619 2006-01-15 07:33:29Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <asm/types.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <net/route.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#define ADDR_ISHOST(a) (((a)->addr_type == ADDR_TYPE_IP && \
+ (a)->addr_bits == IP_ADDR_BITS) || \
+ ((a)->addr_type == ADDR_TYPE_IP6 && \
+ (a)->addr_bits == IP6_ADDR_BITS))
+
+#define PROC_ROUTE_FILE "/proc/net/route"
+#define PROC_IPV6_ROUTE_FILE "/proc/net/ipv6_route"
+
+struct route_handle {
+ int fd;
+ int nlfd;
+};
+
+route_t *
+route_open(void)
+{
+ struct sockaddr_nl snl;
+ route_t *r;
+
+ if ((r = calloc(1, sizeof(*r))) != NULL) {
+ r->fd = r->nlfd = -1;
+
+ if ((r->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (route_close(r));
+
+ if ((r->nlfd = socket(AF_NETLINK, SOCK_RAW,
+ NETLINK_ROUTE)) < 0)
+ return (route_close(r));
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+
+ if (bind(r->nlfd, (struct sockaddr *)&snl, sizeof(snl)) < 0)
+ return (route_close(r));
+ }
+ return (r);
+}
+
+int
+route_add(route_t *r, const struct route_entry *entry)
+{
+ struct rtentry rt;
+ struct addr dst;
+
+ memset(&rt, 0, sizeof(rt));
+ rt.rt_flags = RTF_UP | RTF_GATEWAY;
+
+ if (ADDR_ISHOST(&entry->route_dst)) {
+ rt.rt_flags |= RTF_HOST;
+ memcpy(&dst, &entry->route_dst, sizeof(dst));
+ } else
+ addr_net(&entry->route_dst, &dst);
+
+ if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
+ addr_ntos(&entry->route_gw, &rt.rt_gateway) < 0 ||
+ addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
+ return (-1);
+
+ return (ioctl(r->fd, SIOCADDRT, &rt));
+}
+
+int
+route_delete(route_t *r, const struct route_entry *entry)
+{
+ struct rtentry rt;
+ struct addr dst;
+
+ memset(&rt, 0, sizeof(rt));
+ rt.rt_flags = RTF_UP;
+
+ if (ADDR_ISHOST(&entry->route_dst)) {
+ rt.rt_flags |= RTF_HOST;
+ memcpy(&dst, &entry->route_dst, sizeof(dst));
+ } else
+ addr_net(&entry->route_dst, &dst);
+
+ if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
+ addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
+ return (-1);
+
+ return (ioctl(r->fd, SIOCDELRT, &rt));
+}
+
+int
+route_get(route_t *r, struct route_entry *entry)
+{
+ static int seq;
+ struct nlmsghdr *nmsg;
+ struct rtmsg *rmsg;
+ struct rtattr *rta;
+ struct sockaddr_nl snl;
+ struct iovec iov;
+ struct msghdr msg;
+ u_char buf[512];
+ int i, af, alen;
+
+ switch (entry->route_dst.addr_type) {
+ case ADDR_TYPE_IP:
+ af = AF_INET;
+ alen = IP_ADDR_LEN;
+ break;
+ case ADDR_TYPE_IP6:
+ af = AF_INET6;
+ alen = IP6_ADDR_LEN;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ memset(buf, 0, sizeof(buf));
+
+ nmsg = (struct nlmsghdr *)buf;
+ nmsg->nlmsg_len = NLMSG_LENGTH(sizeof(*nmsg)) + RTA_LENGTH(alen);
+ nmsg->nlmsg_flags = NLM_F_REQUEST;
+ nmsg->nlmsg_type = RTM_GETROUTE;
+ nmsg->nlmsg_seq = ++seq;
+
+ rmsg = (struct rtmsg *)(nmsg + 1);
+ rmsg->rtm_family = af;
+ rmsg->rtm_dst_len = entry->route_dst.addr_bits;
+
+ rta = RTM_RTA(rmsg);
+ rta->rta_type = RTA_DST;
+ rta->rta_len = RTA_LENGTH(alen);
+
+ /* XXX - gross hack for default route */
+ if (af == AF_INET && entry->route_dst.addr_ip == IP_ADDR_ANY) {
+ i = htonl(0x60060606);
+ memcpy(RTA_DATA(rta), &i, alen);
+ } else
+ memcpy(RTA_DATA(rta), entry->route_dst.addr_data8, alen);
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+
+ iov.iov_base = nmsg;
+ iov.iov_len = nmsg->nlmsg_len;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = &snl;
+ msg.msg_namelen = sizeof(snl);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (sendmsg(r->nlfd, &msg, 0) < 0)
+ return (-1);
+
+ iov.iov_base = buf;
+ iov.iov_len = sizeof(buf);
+
+ if ((i = recvmsg(r->nlfd, &msg, 0)) <= 0)
+ return (-1);
+
+ if (nmsg->nlmsg_len < (int)sizeof(*nmsg) || nmsg->nlmsg_len > i ||
+ nmsg->nlmsg_seq != seq) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (nmsg->nlmsg_type == NLMSG_ERROR)
+ return (-1);
+
+ i -= NLMSG_LENGTH(sizeof(*nmsg));
+
+ entry->route_gw.addr_type = ADDR_TYPE_NONE;
+ entry->intf_name[0] = '\0';
+ for (rta = RTM_RTA(rmsg); RTA_OK(rta, i); rta = RTA_NEXT(rta, i)) {
+ if (rta->rta_type == RTA_GATEWAY) {
+ entry->route_gw.addr_type = entry->route_dst.addr_type;
+ memcpy(entry->route_gw.addr_data8, RTA_DATA(rta), alen);
+ entry->route_gw.addr_bits = alen * 8;
+ } else if (rta->rta_type == RTA_OIF) {
+ char ifbuf[IFNAMSIZ];
+ char *p;
+ int intf_index;
+
+ intf_index = *(int *) RTA_DATA(rta);
+ p = if_indextoname(intf_index, ifbuf);
+ if (p == NULL)
+ return (-1);
+ strlcpy(entry->intf_name, ifbuf, sizeof(entry->intf_name));
+ }
+ }
+ if (entry->route_gw.addr_type == ADDR_TYPE_NONE) {
+ errno = ESRCH;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ FILE *fp;
+ struct route_entry entry;
+ char buf[BUFSIZ];
+ char ifbuf[16];
+ int ret = 0;
+
+ if ((fp = fopen(PROC_ROUTE_FILE, "r")) != NULL) {
+ int i, iflags, refcnt, use, metric, mss, win, irtt;
+ uint32_t mask;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ i = sscanf(buf, "%15s %X %X %X %d %d %d %X %d %d %d\n",
+ ifbuf, &entry.route_dst.addr_ip,
+ &entry.route_gw.addr_ip, &iflags, &refcnt, &use,
+ &metric, &mask, &mss, &win, &irtt);
+
+ if (i < 11 || !(iflags & RTF_UP))
+ continue;
+
+ strlcpy(entry.intf_name, ifbuf, sizeof(entry.intf_name));
+
+ entry.route_dst.addr_type = entry.route_gw.addr_type =
+ ADDR_TYPE_IP;
+
+ if (addr_mtob(&mask, IP_ADDR_LEN,
+ &entry.route_dst.addr_bits) < 0)
+ continue;
+
+ entry.route_gw.addr_bits = IP_ADDR_BITS;
+ entry.metric = metric;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ fclose(fp);
+ }
+ if (ret == 0 && (fp = fopen(PROC_IPV6_ROUTE_FILE, "r")) != NULL) {
+ char s[33], d[8][5], n[8][5];
+ int i, iflags, metric;
+ u_int slen, dlen;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ i = sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x "
+ "%32s %02x %04s%04s%04s%04s%04s%04s%04s%04s "
+ "%x %*x %*x %x %15s",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+ &dlen, s, &slen,
+ n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7],
+ &metric, &iflags, ifbuf);
+
+ if (i < 21 || !(iflags & RTF_UP))
+ continue;
+
+ strlcpy(entry.intf_name, ifbuf, sizeof(entry.intf_name));
+
+ snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+ dlen);
+ addr_aton(buf, &entry.route_dst);
+ snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
+ n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7],
+ IP6_ADDR_BITS);
+ addr_aton(buf, &entry.route_gw);
+ entry.metric = metric;
+
+ if ((ret = callback(&entry, arg)) != 0)
+ break;
+ }
+ fclose(fp);
+ }
+ return (ret);
+}
+
+route_t *
+route_close(route_t *r)
+{
+ if (r != NULL) {
+ if (r->fd >= 0)
+ close(r->fd);
+ if (r->nlfd >= 0)
+ close(r->nlfd);
+ free(r);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/route-none.c b/libdnet-stripped/src/route-none.c
new file mode 100644
index 0000000..bbe2216
--- /dev/null
+++ b/libdnet-stripped/src/route-none.c
@@ -0,0 +1,58 @@
+/*
+ * route-none.c
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: route-none.c 260 2002-02-04 04:03:45Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+route_t *
+route_open(void)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+int
+route_add(route_t *r, const struct route_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+route_delete(route_t *r, const struct route_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+route_get(route_t *r, struct route_entry *entry)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+route_t *
+route_close(route_t *r)
+{
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/route-win32.c b/libdnet-stripped/src/route-win32.c
new file mode 100644
index 0000000..8a9d2bc
--- /dev/null
+++ b/libdnet-stripped/src/route-win32.c
@@ -0,0 +1,279 @@
+/*
+ * route-win32.c
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: route-win32.c 589 2005-02-15 07:11:32Z dugsong $
+ */
+
+#ifdef _WIN32
+#include "dnet_winconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include <ws2tcpip.h>
+#include <iphlpapi.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dnet.h"
+
+typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2 *);
+
+struct route_handle {
+ HINSTANCE iphlpapi;
+ MIB_IPFORWARDTABLE *ipftable;
+ MIB_IPFORWARD_TABLE2 *ipftable2;
+};
+
+route_t *
+route_open(void)
+{
+ route_t *r;
+
+ r = calloc(1, sizeof(route_t));
+ if (r == NULL)
+ return NULL;
+ r->iphlpapi = GetModuleHandle("iphlpapi.dll");
+
+ return r;
+}
+
+int
+route_add(route_t *route, const struct route_entry *entry)
+{
+ MIB_IPFORWARDROW ipfrow;
+ struct addr net;
+
+ memset(&ipfrow, 0, sizeof(ipfrow));
+
+ if (GetBestInterface(entry->route_gw.addr_ip,
+ &ipfrow.dwForwardIfIndex) != NO_ERROR)
+ return (-1);
+
+ if (addr_net(&entry->route_dst, &net) < 0 ||
+ net.addr_type != ADDR_TYPE_IP)
+ return (-1);
+
+ ipfrow.dwForwardDest = net.addr_ip;
+ addr_btom(entry->route_dst.addr_bits,
+ &ipfrow.dwForwardMask, IP_ADDR_LEN);
+ ipfrow.dwForwardNextHop = entry->route_gw.addr_ip;
+ ipfrow.dwForwardType = 4; /* XXX - next hop != final dest */
+ ipfrow.dwForwardProto = 3; /* XXX - MIB_PROTO_NETMGMT */
+
+ if (CreateIpForwardEntry(&ipfrow) != NO_ERROR)
+ return (-1);
+
+ return (0);
+}
+
+int
+route_delete(route_t *route, const struct route_entry *entry)
+{
+ MIB_IPFORWARDROW ipfrow;
+ DWORD mask;
+
+ if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
+ GetBestRoute(entry->route_dst.addr_ip,
+ IP_ADDR_ANY, &ipfrow) != NO_ERROR)
+ return (-1);
+
+ addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
+
+ if (ipfrow.dwForwardDest != entry->route_dst.addr_ip ||
+ ipfrow.dwForwardMask != mask) {
+ errno = ENXIO;
+ SetLastError(ERROR_NO_DATA);
+ return (-1);
+ }
+ if (DeleteIpForwardEntry(&ipfrow) != NO_ERROR)
+ return (-1);
+
+ return (0);
+}
+
+int
+route_get(route_t *route, struct route_entry *entry)
+{
+ MIB_IPFORWARDROW ipfrow;
+ DWORD mask;
+ intf_t *intf;
+ struct intf_entry intf_entry;
+
+ if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
+ GetBestRoute(entry->route_dst.addr_ip,
+ IP_ADDR_ANY, &ipfrow) != NO_ERROR)
+ return (-1);
+
+ if (ipfrow.dwForwardProto == 2 && /* XXX - MIB_IPPROTO_LOCAL */
+ (ipfrow.dwForwardNextHop|IP_CLASSA_NET) !=
+ (IP_ADDR_LOOPBACK|IP_CLASSA_NET) &&
+ !IP_LOCAL_GROUP(ipfrow.dwForwardNextHop)) {
+ errno = ENXIO;
+ SetLastError(ERROR_NO_DATA);
+ return (-1);
+ }
+ addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
+
+ entry->route_gw.addr_type = ADDR_TYPE_IP;
+ entry->route_gw.addr_bits = IP_ADDR_BITS;
+ entry->route_gw.addr_ip = ipfrow.dwForwardNextHop;
+ entry->metric = ipfrow.dwForwardMetric1;
+
+ entry->intf_name[0] = '\0';
+ intf = intf_open();
+ if (intf_get_index(intf, &intf_entry,
+ AF_INET, ipfrow.dwForwardIfIndex) == 0) {
+ strlcpy(entry->intf_name, intf_entry.intf_name, sizeof(entry->intf_name));
+ }
+ intf_close(intf);
+
+ return (0);
+}
+
+static int
+route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg)
+{
+ struct route_entry entry;
+ intf_t *intf;
+ ULONG len;
+ int i, ret;
+
+ for (len = sizeof(r->ipftable[0]); ; ) {
+ if (r->ipftable)
+ free(r->ipftable);
+ r->ipftable = malloc(len);
+ if (r->ipftable == NULL)
+ return (-1);
+ ret = GetIpForwardTable(r->ipftable, &len, FALSE);
+ if (ret == NO_ERROR)
+ break;
+ else if (ret != ERROR_INSUFFICIENT_BUFFER)
+ return (-1);
+ }
+
+ intf = intf_open();
+
+ ret = 0;
+ for (i = 0; i < (int)r->ipftable->dwNumEntries; i++) {
+ struct intf_entry intf_entry;
+
+ entry.route_dst.addr_type = ADDR_TYPE_IP;
+ entry.route_dst.addr_bits = IP_ADDR_BITS;
+
+ entry.route_gw.addr_type = ADDR_TYPE_IP;
+ entry.route_gw.addr_bits = IP_ADDR_BITS;
+
+ entry.route_dst.addr_ip = r->ipftable->table[i].dwForwardDest;
+ addr_mtob(&r->ipftable->table[i].dwForwardMask, IP_ADDR_LEN,
+ &entry.route_dst.addr_bits);
+ entry.route_gw.addr_ip =
+ r->ipftable->table[i].dwForwardNextHop;
+ entry.metric = r->ipftable->table[i].dwForwardMetric1;
+
+ /* Look up the interface name. */
+ entry.intf_name[0] = '\0';
+ intf_entry.intf_len = sizeof(intf_entry);
+ if (intf_get_index(intf, &intf_entry,
+ AF_INET, r->ipftable->table[i].dwForwardIfIndex) == 0) {
+ strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name));
+ }
+
+ if ((ret = (*callback)(&entry, arg)) != 0)
+ break;
+ }
+
+ intf_close(intf);
+
+ return ret;
+}
+
+static int
+route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2,
+ route_t *r, route_handler callback, void *arg)
+{
+ struct route_entry entry;
+ intf_t *intf;
+ ULONG i;
+ int ret;
+
+ ret = GetIpForwardTable2(AF_UNSPEC, &r->ipftable2);
+ if (ret != NO_ERROR)
+ return (-1);
+
+ intf = intf_open();
+
+ ret = 0;
+ for (i = 0; i < r->ipftable2->NumEntries; i++) {
+ struct intf_entry intf_entry;
+ MIB_IPFORWARD_ROW2 *row;
+ MIB_IPINTERFACE_ROW ifrow;
+ ULONG metric;
+
+ row = &r->ipftable2->Table[i];
+ addr_ston((struct sockaddr *) &row->DestinationPrefix.Prefix, &entry.route_dst);
+ entry.route_dst.addr_bits = row->DestinationPrefix.PrefixLength;
+ addr_ston((struct sockaddr *) &row->NextHop, &entry.route_gw);
+
+ /* Look up the interface name. */
+ entry.intf_name[0] = '\0';
+ intf_entry.intf_len = sizeof(intf_entry);
+ if (intf_get_index(intf, &intf_entry,
+ row->DestinationPrefix.Prefix.si_family,
+ row->InterfaceIndex) == 0) {
+ strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name));
+ }
+
+ ifrow.Family = row->DestinationPrefix.Prefix.si_family;
+ ifrow.InterfaceLuid = row->InterfaceLuid;
+ ifrow.InterfaceIndex = row->InterfaceIndex;
+ if (GetIpInterfaceEntry(&ifrow) != NO_ERROR) {
+ return (-1);
+ }
+ metric = ifrow.Metric + row->Metric;
+ if (metric < INT_MAX)
+ entry.metric = metric;
+ else
+ entry.metric = INT_MAX;
+
+ if ((ret = (*callback)(&entry, arg)) != 0)
+ break;
+ }
+
+ intf_close(intf);
+
+ return ret;
+}
+
+int
+route_loop(route_t *r, route_handler callback, void *arg)
+{
+ GETIPFORWARDTABLE2 GetIpForwardTable2;
+
+ /* GetIpForwardTable2 is only available on Vista and later, dynamic load. */
+ GetIpForwardTable2 = NULL;
+ if (r->iphlpapi != NULL)
+ GetIpForwardTable2 = (GETIPFORWARDTABLE2) GetProcAddress(r->iphlpapi, "GetIpForwardTable2");
+
+ if (GetIpForwardTable2 == NULL)
+ return route_loop_getipforwardtable(r, callback, arg);
+ else
+ return route_loop_getipforwardtable2(GetIpForwardTable2, r, callback, arg);
+}
+
+route_t *
+route_close(route_t *r)
+{
+ if (r != NULL) {
+ if (r->ipftable != NULL)
+ free(r->ipftable);
+ if (r->ipftable2 != NULL)
+ FreeMibTable(r->ipftable2);
+ free(r);
+ }
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/strlcpy.c b/libdnet-stripped/src/strlcpy.c
new file mode 100644
index 0000000..5f58696
--- /dev/null
+++ b/libdnet-stripped/src/strlcpy.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(dst, src, siz)
+ char *dst;
+ const char *src;
+ size_t siz;
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/libdnet-stripped/src/strsep.c b/libdnet-stripped/src/strsep.c
new file mode 100644
index 0000000..b69b715
--- /dev/null
+++ b/libdnet-stripped/src/strsep.c
@@ -0,0 +1,85 @@
+/* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#else
+static char *rcsid = "$OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(stringp, delim)
+ register char **stringp;
+ register const char *delim;
+{
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/libdnet-stripped/src/tun-bsd.c b/libdnet-stripped/src/tun-bsd.c
new file mode 100644
index 0000000..293abc8
--- /dev/null
+++ b/libdnet-stripped/src/tun-bsd.c
@@ -0,0 +1,146 @@
+/*
+ * tun-bsd.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: tun-bsd.c 573 2005-02-10 23:50:04Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct tun {
+ int fd;
+ intf_t *intf;
+ struct intf_entry save;
+};
+
+#define MAX_DEVS 16 /* XXX - max number of tunnel devices */
+
+tun_t *
+tun_open(struct addr *src, struct addr *dst, int mtu)
+{
+ struct intf_entry ifent;
+ tun_t *tun;
+ char dev[128];
+ int i;
+
+ if (src->addr_type != ADDR_TYPE_IP || dst->addr_type != ADDR_TYPE_IP ||
+ src->addr_bits != IP_ADDR_BITS || dst->addr_bits != IP_ADDR_BITS) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if ((tun = calloc(1, sizeof(*tun))) == NULL)
+ return (NULL);
+
+ if ((tun->intf = intf_open()) == NULL)
+ return (tun_close(tun));
+
+ memset(&ifent, 0, sizeof(ifent));
+ ifent.intf_len = sizeof(ifent);
+
+ for (i = 0; i < MAX_DEVS; i++) {
+ snprintf(dev, sizeof(dev), "/dev/tun%d", i);
+ strlcpy(ifent.intf_name, dev + 5, sizeof(ifent.intf_name));
+ tun->save = ifent;
+
+ if ((tun->fd = open(dev, O_RDWR, 0)) != -1 &&
+ intf_get(tun->intf, &tun->save) == 0) {
+ route_t *r;
+ struct route_entry entry;
+
+ ifent.intf_flags = INTF_FLAG_UP|INTF_FLAG_POINTOPOINT;
+ ifent.intf_addr = *src;
+ ifent.intf_dst_addr = *dst;
+ ifent.intf_mtu = mtu;
+
+ if (intf_set(tun->intf, &ifent) < 0)
+ tun = tun_close(tun);
+
+ /* XXX - try to ensure our route got set */
+ if ((r = route_open()) != NULL) {
+ entry.route_dst = *dst;
+ entry.route_gw = *src;
+ route_add(r, &entry);
+ route_close(r);
+ }
+ break;
+ }
+ }
+ if (i == MAX_DEVS)
+ tun = tun_close(tun);
+ return (tun);
+}
+
+const char *
+tun_name(tun_t *tun)
+{
+ return (tun->save.intf_name);
+}
+
+int
+tun_fileno(tun_t *tun)
+{
+ return (tun->fd);
+}
+
+ssize_t
+tun_send(tun_t *tun, const void *buf, size_t size)
+{
+#ifdef __OpenBSD__
+ struct iovec iov[2];
+ uint32_t af = htonl(AF_INET);
+
+ iov[0].iov_base = &af;
+ iov[0].iov_len = sizeof(af);
+ iov[1].iov_base = (void *)buf;
+ iov[1].iov_len = size;
+
+ return (writev(tun->fd, iov, 2));
+#else
+ return (write(tun->fd, buf, size));
+#endif
+}
+
+ssize_t
+tun_recv(tun_t *tun, void *buf, size_t size)
+{
+#ifdef __OpenBSD__
+ struct iovec iov[2];
+ uint32_t af;
+
+ iov[0].iov_base = &af;
+ iov[0].iov_len = sizeof(af);
+ iov[1].iov_base = (void *)buf;
+ iov[1].iov_len = size;
+
+ return (readv(tun->fd, iov, 2) - sizeof(af));
+#else
+ return (read(tun->fd, buf, size));
+#endif
+}
+
+tun_t *
+tun_close(tun_t *tun)
+{
+ if (tun->fd > 0)
+ close(tun->fd);
+ if (tun->intf != NULL) {
+ /* Restore interface configuration on close. */
+ intf_set(tun->intf, &tun->save);
+ intf_close(tun->intf);
+ }
+ free(tun);
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/tun-linux.c b/libdnet-stripped/src/tun-linux.c
new file mode 100644
index 0000000..38fe0b4
--- /dev/null
+++ b/libdnet-stripped/src/tun-linux.c
@@ -0,0 +1,115 @@
+/*
+ * tun-linux.c
+ *
+ * Universal TUN/TAP driver, in Linux 2.4+
+ * /usr/src/linux/Documentation/networking/tuntap.txt
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: tun-linux.c 612 2005-09-12 02:18:06Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+struct tun {
+ int fd;
+ intf_t *intf;
+ struct ifreq ifr;
+};
+
+tun_t *
+tun_open(struct addr *src, struct addr *dst, int mtu)
+{
+ tun_t *tun;
+ struct intf_entry ifent;
+
+ if ((tun = calloc(1, sizeof(*tun))) == NULL)
+ return (NULL);
+
+ if ((tun->fd = open("/dev/net/tun", O_RDWR, 0)) < 0 ||
+ (tun->intf = intf_open()) == NULL)
+ return (tun_close(tun));
+
+ tun->ifr.ifr_flags = IFF_TUN;
+
+ if (ioctl(tun->fd, TUNSETIFF, (void *) &tun->ifr) < 0)
+ return (tun_close(tun));
+
+ memset(&ifent, 0, sizeof(ifent));
+ strlcpy(ifent.intf_name, tun->ifr.ifr_name, sizeof(ifent.intf_name));
+ ifent.intf_flags = INTF_FLAG_UP|INTF_FLAG_POINTOPOINT;
+ ifent.intf_addr = *src;
+ ifent.intf_dst_addr = *dst;
+ ifent.intf_mtu = mtu;
+
+ if (intf_set(tun->intf, &ifent) < 0)
+ return (tun_close(tun));
+
+ return (tun);
+}
+
+const char *
+tun_name(tun_t *tun)
+{
+ return (tun->ifr.ifr_name);
+}
+
+int
+tun_fileno(tun_t *tun)
+{
+ return (tun->fd);
+}
+
+ssize_t
+tun_send(tun_t *tun, const void *buf, size_t size)
+{
+ struct iovec iov[2];
+ uint32_t type = ETH_TYPE_IP;
+
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = (void *)buf;
+ iov[1].iov_len = size;
+
+ return (writev(tun->fd, iov, 2));
+}
+
+ssize_t
+tun_recv(tun_t *tun, void *buf, size_t size)
+{
+ struct iovec iov[2];
+ uint32_t type;
+
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = (void *)buf;
+ iov[1].iov_len = size;
+
+ return (readv(tun->fd, iov, 2) - sizeof(type));
+}
+
+tun_t *
+tun_close(tun_t *tun)
+{
+ if (tun->fd > 0)
+ close(tun->fd);
+ if (tun->intf != NULL)
+ intf_close(tun->intf);
+ free(tun);
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/tun-none.c b/libdnet-stripped/src/tun-none.c
new file mode 100644
index 0000000..940d8ae
--- /dev/null
+++ b/libdnet-stripped/src/tun-none.c
@@ -0,0 +1,58 @@
+/*
+ * tun-none.c
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: tun-none.c 548 2005-01-30 06:01:57Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dnet.h"
+
+tun_t *
+tun_open(struct addr *src, struct addr *dst, int mtu)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+const char *
+tun_name(tun_t *tun)
+{
+ errno = ENOSYS;
+ return (NULL);
+}
+
+int
+tun_fileno(tun_t *tun)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+ssize_t
+tun_send(tun_t *tun, const void *buf, size_t size)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+ssize_t
+tun_recv(tun_t *tun, void *buf, size_t size)
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+tun_t *
+tun_close(tun_t *tun)
+{
+ return (NULL);
+}
diff --git a/libdnet-stripped/src/tun-solaris.c b/libdnet-stripped/src/tun-solaris.c
new file mode 100644
index 0000000..07186ce
--- /dev/null
+++ b/libdnet-stripped/src/tun-solaris.c
@@ -0,0 +1,127 @@
+/*
+ * tun-solaris.c
+ *
+ * Universal TUN/TAP driver
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: tun-solaris.c 547 2005-01-25 21:30:40Z dugsong $
+ */
+
+#include "config.h"
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_tun.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "dnet.h"
+
+#define DEV_TUN "/dev/tun"
+#define DEV_IP "/dev/ip"
+
+struct tun {
+ int fd;
+ int ip_fd;
+ int if_fd;
+ char name[16];
+};
+
+tun_t *
+tun_open(struct addr *src, struct addr *dst, int mtu)
+{
+ tun_t *tun;
+ char cmd[512];
+ int ppa;
+
+ if ((tun = calloc(1, sizeof(*tun))) == NULL)
+ return (NULL);
+
+ tun->fd = tun->ip_fd = tun->if_fd = -1;
+
+ if ((tun->fd = open(DEV_TUN, O_RDWR, 0)) < 0)
+ return (tun_close(tun));
+
+ if ((tun->ip_fd = open(DEV_IP, O_RDWR, 0)) < 0)
+ return (tun_close(tun));
+
+ if ((ppa = ioctl(tun->fd, TUNNEWPPA, ppa)) < 0)
+ return (tun_close(tun));
+
+ if ((tun->if_fd = open(DEV_TUN, O_RDWR, 0)) < 0)
+ return (tun_close(tun));
+
+ if (ioctl(tun->if_fd, I_PUSH, "ip") < 0)
+ return (tun_close(tun));
+
+ if (ioctl(tun->if_fd, IF_UNITSEL, (char *)&ppa) < 0)
+ return (tun_close(tun));
+
+ if (ioctl(tun->ip_fd, I_LINK, tun->if_fd) < 0)
+ return (tun_close(tun));
+
+ snprintf(tun->name, sizeof(tun->name), "tun%d", ppa);
+
+ snprintf(cmd, sizeof(cmd), "ifconfig %s %s/32 %s mtu %d up",
+ tun->name, addr_ntoa(src), addr_ntoa(dst), mtu);
+
+ if (system(cmd) < 0)
+ return (tun_close(tun));
+
+ return (tun);
+}
+
+const char *
+tun_name(tun_t *tun)
+{
+ return (tun->name);
+}
+
+int
+tun_fileno(tun_t *tun)
+{
+ return (tun->fd);
+}
+
+ssize_t
+tun_send(tun_t *tun, const void *buf, size_t size)
+{
+ struct strbuf sbuf;
+
+ sbuf.buf = buf;
+ sbuf.len = size;
+ return (putmsg(tun->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1);
+}
+
+ssize_t
+tun_recv(tun_t *tun, void *buf, size_t size)
+{
+ struct strbuf sbuf;
+ int flags = 0;
+
+ sbuf.buf = buf;
+ sbuf.maxlen = size;
+ return (getmsg(tun->fd, NULL, &sbuf, &flags) >= 0 ? sbuf.len : -1);
+}
+
+tun_t *
+tun_close(tun_t *tun)
+{
+ if (tun->if_fd >= 0)
+ close(tun->if_fd);
+ if (tun->ip_fd >= 0)
+ close(tun->ip_fd);
+ if (tun->fd >= 0)
+ close(tun->fd);
+ free(tun);
+ return (NULL);
+}