diff -Nru vpcs-0.5b2/debian/changelog vpcs-0.6.1/debian/changelog --- vpcs-0.5b2/debian/changelog 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/changelog 2016-10-14 08:55:30.000000000 +0000 @@ -1,28 +1,27 @@ -vpcs (0.5b2-1) unstable; urgency=medium +vpcs (1:0.6.1-1~yakkety1) yakkety; urgency=low - * Imported Upstream version 0.5b2 - * Remove patches applied upstream. - + BuildOnGNUkFreeBSD - + HypervisorPathPatch - + ManpageFix - + echild_fix - * Update CreateTopLevelMakefile patch - * Update copyright years - * Add patch to correct lintian info alert. - + Hyphen used as minus sign in manpage + * Imported Upstream version 0.6.1 + * Release for yakkety + * Release for yakkety + * Release for yakkety + * Release for yakkety + * Release for yakkety - -- Daniel Lintott Mon, 07 Jul 2014 16:59:00 +0100 + -- Julien Duponchelle Mon, 09 Nov 2015 11:47:00 +0000 -vpcs (0.5b0-2) unstable; urgency=low +vpcs (0.5b0-1~ppa1) raring; urgency=low - * [63d71f16] Bump standards version to 3.9.5 - No changes - * [1ab1f0cb] Update debian/rules - * [37017180] Add patch to fix FTBFS on hurd-i386 + * Imported Upstream version 0.5b0 + * Add debian/watch + * Remove comments/un-needed override from debian/rules + * Update copyright + * Change build-depends to debhelper (>= 9) + * Update patches - -- Daniel Lintott Tue, 18 Mar 2014 16:38:45 +0000 + -- Daniel Lintott Fri, 27 Sep 2013 14:06:54 +0100 -vpcs (0.5b0-1) unstable; urgency=low +vpcs (0.4b2-1~ppa1) raring; urgency=low - * Initial release. (Closes: #720196) + * Initial release to Launchpad PPA - -- Daniel Lintott Wed, 06 Nov 2013 11:42:03 +0000 + -- Daniel Lintott Mon, 19 Aug 2013 19:40:34 +0100 diff -Nru vpcs-0.5b2/debian/control vpcs-0.6.1/debian/control --- vpcs-0.5b2/debian/control 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/control 2016-10-14 08:55:06.000000000 +0000 @@ -1,20 +1,17 @@ Source: vpcs Section: net Priority: optional -Maintainer: Daniel Lintott +Maintainer: GNS3 team Build-Depends: debhelper (>= 9) -Standards-Version: 3.9.5 +Standards-Version: 3.9.4 Homepage: http://sourceforge.net/projects/vpcs/ -Vcs-Browser: https://github.com/dlintott/vpcs -Vcs-Git: https://github.com/dlintott/vpcs.git Package: vpcs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Description: virtual PC simulator for Dynamips +Description: Virtual PC Simulator VPCS can simulate up to 9 PCs. You can ping/traceroute to them or ping/traceroute to other hosts/routers from the VPCS. . - VPCS is not intended to be a fully functional PC, but is - a tool to be used together with Dynamips. + VPCS is not intended to be a fully functional PC. diff -Nru vpcs-0.5b2/debian/copyright vpcs-0.6.1/debian/copyright --- vpcs-0.5b2/debian/copyright 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/copyright 2016-10-14 08:55:06.000000000 +0000 @@ -3,7 +3,7 @@ Source: http://sourceforge.net/projects/vpcs/ Files: * -Copyright: 2007-2014 Paul Meng +Copyright: 2007-2013 Paul Meng License: BSD-2-Clause Files: src/getopt.* @@ -16,7 +16,7 @@ License: ISC Files: debian/* -Copyright: 2013-2014 Daniel Lintott +Copyright: 2013 Daniel Lintott License: BSD-2-Clause License: BSD-2-Clause diff -Nru vpcs-0.5b2/debian/install vpcs-0.6.1/debian/install --- vpcs-0.5b2/debian/install 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/debian/install 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1 @@ +src/vpcs /usr/bin diff -Nru vpcs-0.5b2/debian/patches/CreateTopLevelMakefile vpcs-0.6.1/debian/patches/CreateTopLevelMakefile --- vpcs-0.5b2/debian/patches/CreateTopLevelMakefile 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/patches/CreateTopLevelMakefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -Description: Create a top level makefile - The original source package does not include a top-level makefile, so we - create one. - -Author: Daniel Lintott - -Index: vpcs/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ vpcs/Makefile 2013-09-27 12:05:16.658688079 +0100 -@@ -0,0 +1,32 @@ -+# Makefile for VPCS 0.5b2 -+ -+# Operating System Type -+# Linux = linux -+# Windows = cygwin -+# MacOSX = osx -+# FreeBSD = fbsd -+export VPCS_OS?=linux -+ -+# Executable binary extension -+export PREFIX?=/usr -+export BIN_EXT?= -+ -+ -+.PHONY: all install clean -+all: vpcs -+ -+vpcs: -+ @echo Building VPCS for $(VPCS_OS) on $(ARCH) -+ $(MAKE) -C src -f Makefile.$(VPCS_OS) -+ mv src/vpcs vpcs$(BIN_EXT) -+ -+install: vpcs$(BIN_EXT) -+ @echo "Installing VPCS to $(DESTDIR)" -+ install -d $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/share/man/man1 -+ install vpcs$(BIN_EXT) $(DESTDIR)$(PREFIX)/bin/ -+ install -m644 man/vpcs.1 $(DESTDIR)$(PREFIX)/share/man/man1/ -+ -+clean: -+ $(MAKE) -C src -f Makefile.$(VPCS_OS) clean -+ $(RM) -f vpcs$(BIN_EXT) -+ diff -Nru vpcs-0.5b2/debian/patches/hurd_path_max vpcs-0.6.1/debian/patches/hurd_path_max --- vpcs-0.5b2/debian/patches/hurd_path_max 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/patches/hurd_path_max 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -Description: Fix FTBFS on hurd-i386 - hurd does not define PATH_MAX. Fix taken from pathmax.h - http://lists.gnu.org/archive/html/bug-gnulib/2011-08/msg00025.html -Author: Daniel Lintott -Index: vpcs/src/command.h -=================================================================== ---- vpcs.orig/src/command.h 2013-12-04 14:27:08.127058344 +0000 -+++ vpcs/src/command.h 2013-12-10 15:59:52.957747281 +0000 -@@ -45,6 +45,10 @@ - - const char *ip4Info(const int id); - -+#ifndef PATH_MAX -+# define PATH_MAX 8192 -+#endif -+ - #endif - - /* end of file */ -Index: vpcs/src/hv.h -=================================================================== ---- vpcs.orig/src/hv.h 2013-09-26 14:50:13.290976827 +0100 -+++ vpcs/src/hv.h 2013-12-10 16:01:53.176235930 +0000 -@@ -31,6 +31,10 @@ - #include - #include - -+#ifndef PATH_MAX -+# define PATH_MAX 8192 -+#endif -+ - #define delay_ms(x) usleep((x) * 1000) - - #define ERR(out, ...) do { \ diff -Nru vpcs-0.5b2/debian/patches/hyphen-used-as-minus.patch vpcs-0.6.1/debian/patches/hyphen-used-as-minus.patch --- vpcs-0.5b2/debian/patches/hyphen-used-as-minus.patch 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/patches/hyphen-used-as-minus.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Description: Hyphen used as minus in manpage -Author: Daniel Lintott -Applied-Upstream: https://sourceforge.net/p/vpcs/code/92/ -Last-Update: 2014-07-07 ---- a/man/vpcs.1 -+++ b/man/vpcs.1 -@@ -54,7 +54,7 @@ - .SS "TAP Mode Options" - .TP - \fB-d\fR \fIdevice\fR --Device name, works only when -i is set to 1 -+Device name, works only when \fB-i\fR is set to 1 - .SS "Hypervisor Mode Option" - .TP - \fB-H\fR \fIport\fR diff -Nru vpcs-0.5b2/debian/patches/LinuxMakefilePatch vpcs-0.6.1/debian/patches/LinuxMakefilePatch --- vpcs-0.5b2/debian/patches/LinuxMakefilePatch 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/patches/LinuxMakefilePatch 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -Description: Patch Makefile.linux - Modify upstream linux Makefile to allow hardening/autobuilding -Author: Daniel Lintott - ---- vpcs-0.5b0.orig/src/Makefile.linux -+++ vpcs-0.5b0/src/Makefile.linux -@@ -1,12 +1,11 @@ - RM=rm -f --CC=gcc $(CCOPT) -+CC=gcc - OSTYPE=Linux --CPUTYPE=i386 - OPT=-O2 - HVOPT=-DHV - --CFLAGS=-D$(OSTYPE) -D$(CPUTYPE) $(OPT) $(HVOPT) -Wall -I. -DTAP --LDFLAGS=-lpthread -lutil -s -static -+CFLAGS?=-D$(OSTYPE) -D$(CPUTYPE) $(OPT) $(HVOPT) -Wall -I. -DTAP -+LDFLAGS?=-lpthread -lutil -s -static - OBJS=vpcs.o \ - daemon.o \ - readline.o \ -@@ -31,10 +30,10 @@ OBJS=vpcs.o \ - all: vpcs - - vpcs: $(OBJS) -- $(CC) $(OBJS) -o vpcs $(LDFLAGS) -+ $(CC) $(CPPFLAGS) $(CFLAGS) $(OBJS) -o vpcs $(LDFLAGS) - - .c.o: keys.h vpcs.h packets.h dhcp.h -- $(CC) $(INCLUDE_PATH) $(CFLAGS) -c $< -+ $(CC) $(INCLUDE_PATH) $(CPPFLAGS) $(CFLAGS) -c $< - - clean: - $(RM) *.o vpcs diff -Nru vpcs-0.5b2/debian/patches/series vpcs-0.6.1/debian/patches/series --- vpcs-0.5b2/debian/patches/series 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -hyphen-used-as-minus.patch -LinuxMakefilePatch -CreateTopLevelMakefile -hurd_path_max diff -Nru vpcs-0.5b2/debian/rules vpcs-0.6.1/debian/rules --- vpcs-0.5b2/debian/rules 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/rules 2016-10-14 08:55:06.000000000 +0000 @@ -1,30 +1,14 @@ #!/usr/bin/make -f # Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -# To enable all, uncomment following line -export DEB_BUILD_MAINT_OPTIONS = hardening=+all - -ifeq ($(DEB_HOST_ARCH_OS),hurd) -export DEB_CFLAGS_MAINT_APPEND = -DLinux -Wall -I. -I/usr/share/libdde_linux26/build/include/linux-headers -DHV -Wno-strict-aliasing -else -ifeq ($(DEB_HOST_ARCH_OS),kfreebsd) -export DEB_CFLAGS_MAINT_APPEND = -DGNUkFreeBSD -DFreeBSD -Wall -I. -DHV -Wno-strict-aliasing -else -export DEB_CFLAGS_MAINT_APPEND = -DLinux -Wall -I. -DTAP -DHV -Wno-strict-aliasing -endif -endif - -export DEB_LDFLAGS_MAINT_APPEND = -lpthread -lutil -s +export DH_VERBOSE=1 %: - dh $@ + dh $@ override_dh_auto_build: - dh_auto_build - sed -n -e '1,/History/!p' readme.txt > CHANGELOG + $(MAKE) -C src -f Makefile.linux override_dh_auto_clean: $(MAKE) -C src -f Makefile.linux clean - rm -f vpcs + rm -f src/vpcs diff -Nru vpcs-0.5b2/debian/source/format vpcs-0.6.1/debian/source/format --- vpcs-0.5b2/debian/source/format 2014-07-07 15:59:13.000000000 +0000 +++ vpcs-0.6.1/debian/source/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -3.0 (quilt) diff -Nru vpcs-0.5b2/.git/config vpcs-0.6.1/.git/config --- vpcs-0.5b2/.git/config 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/config 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1,11 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "origin"] + url = https://github.com/GNS3/vpcs.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master diff -Nru vpcs-0.5b2/.git/description vpcs-0.6.1/.git/description --- vpcs-0.5b2/.git/description 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/description 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff -Nru vpcs-0.5b2/.git/FETCH_HEAD vpcs-0.6.1/.git/FETCH_HEAD --- vpcs-0.5b2/.git/FETCH_HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/FETCH_HEAD 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1,5 @@ +eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 branch 'master' of https://github.com/GNS3/vpcs +6842de5454f354c85dace2b63ba065ff0a1b0255 not-for-merge branch 'old_master' of https://github.com/GNS3/vpcs +1663ce6604d47b87ae9fc28f63c59a9bbfa83819 not-for-merge tag 'v0.5b1' of https://github.com/GNS3/vpcs +4cb66e6443892d4c942e2406a551a0bef6ebf7b4 not-for-merge tag 'v0.6.1' of https://github.com/GNS3/vpcs +0e97595f73b98bf3978241f3927b3eb5bfb92fb8 not-for-merge tag 'v0.8beta1' of https://github.com/GNS3/vpcs diff -Nru vpcs-0.5b2/.git/HEAD vpcs-0.6.1/.git/HEAD --- vpcs-0.5b2/.git/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/HEAD 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1 @@ +4cb66e6443892d4c942e2406a551a0bef6ebf7b4 diff -Nru vpcs-0.5b2/.git/hooks/applypatch-msg.sample vpcs-0.6.1/.git/hooks/applypatch-msg.sample --- vpcs-0.5b2/.git/hooks/applypatch-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/applypatch-msg.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +test -x "$GIT_DIR/hooks/commit-msg" && + exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} +: diff -Nru vpcs-0.5b2/.git/hooks/commit-msg.sample vpcs-0.6.1/.git/hooks/commit-msg.sample --- vpcs-0.5b2/.git/hooks/commit-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/commit-msg.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff -Nru vpcs-0.5b2/.git/hooks/post-update.sample vpcs-0.6.1/.git/hooks/post-update.sample --- vpcs-0.5b2/.git/hooks/post-update.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/post-update.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff -Nru vpcs-0.5b2/.git/hooks/pre-applypatch.sample vpcs-0.6.1/.git/hooks/pre-applypatch.sample --- vpcs-0.5b2/.git/hooks/pre-applypatch.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/pre-applypatch.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} +: diff -Nru vpcs-0.5b2/.git/hooks/pre-commit.sample vpcs-0.6.1/.git/hooks/pre-commit.sample --- vpcs-0.5b2/.git/hooks/pre-commit.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/pre-commit.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff -Nru vpcs-0.5b2/.git/hooks/prepare-commit-msg.sample vpcs-0.6.1/.git/hooks/prepare-commit-msg.sample --- vpcs-0.5b2/.git/hooks/prepare-commit-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/prepare-commit-msg.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,36 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first comments out the +# "Conflicts:" part of a merge commit. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +case "$2,$3" in + merge,) + /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; + +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$1" ;; + + *) ;; +esac + +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff -Nru vpcs-0.5b2/.git/hooks/pre-push.sample vpcs-0.6.1/.git/hooks/pre-push.sample --- vpcs-0.5b2/.git/hooks/pre-push.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/pre-push.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,54 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +z40=0000000000000000000000000000000000000000 + +IFS=' ' +while read local_ref local_sha remote_ref remote_sha +do + if [ "$local_sha" = $z40 ] + then + # Handle delete + : + else + if [ "$remote_sha" = $z40 ] + then + # New branch, examine all commits + range="$local_sha" + else + # Update to existing branch, examine new commits + range="$remote_sha..$local_sha" + fi + + # Check for WIP commit + commit=`git rev-list -n 1 --grep '^WIP' "$range"` + if [ -n "$commit" ] + then + echo "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff -Nru vpcs-0.5b2/.git/hooks/pre-rebase.sample vpcs-0.6.1/.git/hooks/pre-rebase.sample --- vpcs-0.5b2/.git/hooks/pre-rebase.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/pre-rebase.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up-to-date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff -Nru vpcs-0.5b2/.git/hooks/update.sample vpcs-0.6.1/.git/hooks/update.sample --- vpcs-0.5b2/.git/hooks/update.sample 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/hooks/update.sample 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to blocks unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 Binary files /tmp/tmpDjL9xC/hHTEZ0JJKn/vpcs-0.5b2/.git/index and /tmp/tmpDjL9xC/fl22NlwC4a/vpcs-0.6.1/.git/index differ diff -Nru vpcs-0.5b2/.git/info/exclude vpcs-0.6.1/.git/info/exclude --- vpcs-0.5b2/.git/info/exclude 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/info/exclude 2016-10-14 08:55:00.000000000 +0000 @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff -Nru vpcs-0.5b2/.git/logs/HEAD vpcs-0.6.1/.git/logs/HEAD --- vpcs-0.5b2/.git/logs/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/logs/HEAD 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 vagrant 1476435304 +0000 clone: from https://github.com/GNS3/vpcs.git +eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 4cb66e6443892d4c942e2406a551a0bef6ebf7b4 vagrant 1476435306 +0000 checkout: moving from master to v0.6.1 diff -Nru vpcs-0.5b2/.git/logs/refs/heads/master vpcs-0.6.1/.git/logs/refs/heads/master --- vpcs-0.5b2/.git/logs/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/logs/refs/heads/master 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 vagrant 1476435304 +0000 clone: from https://github.com/GNS3/vpcs.git diff -Nru vpcs-0.5b2/.git/logs/refs/remotes/origin/HEAD vpcs-0.6.1/.git/logs/refs/remotes/origin/HEAD --- vpcs-0.5b2/.git/logs/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/logs/refs/remotes/origin/HEAD 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 vagrant 1476435304 +0000 clone: from https://github.com/GNS3/vpcs.git Binary files /tmp/tmpDjL9xC/hHTEZ0JJKn/vpcs-0.5b2/.git/objects/pack/pack-621b4596d06a0fd9a3e3f6b0bd0d04da3f5f9e5b.idx and /tmp/tmpDjL9xC/fl22NlwC4a/vpcs-0.6.1/.git/objects/pack/pack-621b4596d06a0fd9a3e3f6b0bd0d04da3f5f9e5b.idx differ Binary files /tmp/tmpDjL9xC/hHTEZ0JJKn/vpcs-0.5b2/.git/objects/pack/pack-621b4596d06a0fd9a3e3f6b0bd0d04da3f5f9e5b.pack and /tmp/tmpDjL9xC/fl22NlwC4a/vpcs-0.6.1/.git/objects/pack/pack-621b4596d06a0fd9a3e3f6b0bd0d04da3f5f9e5b.pack differ diff -Nru vpcs-0.5b2/.git/ORIG_HEAD vpcs-0.6.1/.git/ORIG_HEAD --- vpcs-0.5b2/.git/ORIG_HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/ORIG_HEAD 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1 @@ +4cb66e6443892d4c942e2406a551a0bef6ebf7b4 diff -Nru vpcs-0.5b2/.git/packed-refs vpcs-0.6.1/.git/packed-refs --- vpcs-0.5b2/.git/packed-refs 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/packed-refs 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1,6 @@ +# pack-refs with: peeled fully-peeled +eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 refs/remotes/origin/master +6842de5454f354c85dace2b63ba065ff0a1b0255 refs/remotes/origin/old_master +1663ce6604d47b87ae9fc28f63c59a9bbfa83819 refs/tags/v0.5b1 +4cb66e6443892d4c942e2406a551a0bef6ebf7b4 refs/tags/v0.6.1 +0e97595f73b98bf3978241f3927b3eb5bfb92fb8 refs/tags/v0.8beta1 diff -Nru vpcs-0.5b2/.git/refs/heads/master vpcs-0.6.1/.git/refs/heads/master --- vpcs-0.5b2/.git/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/refs/heads/master 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1 @@ +eb106e996a01fb4cc8ecc9f43b90d52d193b5a24 diff -Nru vpcs-0.5b2/.git/refs/remotes/origin/HEAD vpcs-0.6.1/.git/refs/remotes/origin/HEAD --- vpcs-0.5b2/.git/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/.git/refs/remotes/origin/HEAD 2016-10-14 08:55:04.000000000 +0000 @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff -Nru vpcs-0.5b2/man/vpcs.1 vpcs-0.6.1/man/vpcs.1 --- vpcs-0.5b2/man/vpcs.1 2014-06-30 02:53:02.000000000 +0000 +++ vpcs-0.6.1/man/vpcs.1 2016-10-14 08:55:06.000000000 +0000 @@ -1,6 +1,6 @@ -.TH VPCS "1" "2014-06-28" "0.5" "Virtual PC Simulator" -.\" Last revision: 2014-06-28 16:25:50 +.TH VPCS "1" "2014-07-07" "0.5" "Virtual PC Simulator" +.\" Last revision: 2014-07-07 16:25:50 .hy 0 .if n .ad l @@ -54,7 +54,7 @@ .SS "TAP Mode Options" .TP \fB-d\fR \fIdevice\fR -Device name, works only when -i is set to 1 +Device name, works only when \fB-i\fR is set to 1 .SS "Hypervisor Mode Option" .TP \fB-H\fR \fIport\fR diff -Nru vpcs-0.5b2/README.md vpcs-0.6.1/README.md --- vpcs-0.5b2/README.md 1970-01-01 00:00:00.000000000 +0000 +++ vpcs-0.6.1/README.md 2016-10-14 08:55:06.000000000 +0000 @@ -0,0 +1,7 @@ +VPCS +====== + +This is not the official VPCS repository and it will not be updated anymore. +The latest VPCS release can be downloaded from http://sourceforge.net/projects/vpcs/files/ + + diff -Nru vpcs-0.5b2/src/command6.c vpcs-0.6.1/src/command6.c --- vpcs-0.5b2/src/command6.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/command6.c 2016-10-14 08:55:06.000000000 +0000 @@ -621,8 +621,8 @@ } buf[j - 1] = ' '; - if (vpc[i].ip6.mtu) - j += sprintf(buf + j, " %4.4d", vpc[i].ip6.mtu); + if (vpc[i].mtu) + j += sprintf(buf + j, " %4.4d", vpc[i].mtu); else j += sprintf(buf + j, " "); //buf[j] = ' '; @@ -666,8 +666,8 @@ in.s_addr = vpc[id].rhost; printf("RHOST:PORT : %s:%d\n", inet_ntoa(in), vpc[id].rport); printf("MTU: : "); - if (vpc[id].ip6.mtu) - printf("%d", vpc[id].ip6.mtu); + if (vpc[id].mtu) + printf("%d", vpc[id].mtu); printf("\n"); return 1; } diff -Nru vpcs-0.5b2/src/command.c vpcs-0.6.1/src/command.c --- vpcs-0.5b2/src/command.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/command.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,8 @@ #include "remote.h" #include "readline.h" #include "help.h" +#include "dump.h" +#include "relay.h" extern int pcid; extern int devtype; @@ -56,7 +58,8 @@ extern int ctrl_z; extern u_int time_tick; extern u_long ip_masks[33]; -extern int canEcho; +extern struct echoctl echoctl; +//int canEcho; extern void clear_hist(void); extern const char *ver; extern struct rls *rls; @@ -65,6 +68,9 @@ extern const char *default_startupfile; extern int num_pths; +static const char *color_name[8] = { + "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"}; + static int set_dump(int argc, char **argv); static int show_dump(int argc, char **argv); static int show_ip(int argc, char **argv); @@ -73,6 +79,8 @@ static int run_dhcp_new(int renew, int dump); static int run_dhcp_release(int dump); + +static int str2color(const char *cstr); /* * 1 2 3 4 5 6 @@ -220,14 +228,14 @@ return help_ping(argc, argv); } - pc->mscb.frag = 0; - pc->mscb.mtu = pc->ip4.mtu; + pc->mscb.frag = IPF_FRAG; + pc->mscb.mtu = pc->mtu; pc->mscb.waittime = 1000; pc->mscb.ipid = time(0) & 0xffff; pc->mscb.seq = time(0); pc->mscb.proto = IPPROTO_ICMP; pc->mscb.ttl = TTL; - pc->mscb.dsize = 64; + pc->mscb.dsize = PAYLOAD56; pc->mscb.sport = (random() % (65000 - 1024)) + 1024; pc->mscb.dport = 7; pc->mscb.sip = pc->ip4.ip; @@ -245,7 +253,7 @@ switch (c) { case 'D': - pc->mscb.frag = 1; + pc->mscb.frag = ~IPF_FRAG; break; case 'u': if (i < argc) @@ -365,7 +373,7 @@ pc->mscb.winsize = 0xb68; /* 1460 * 4 */ if (strchr(argv[1], ':') != NULL) { - pc->mscb.mtu = pc->ip6.mtu; + pc->mscb.mtu = pc->mtu; return run_ping6(argc, argv); } pc->mscb.dip = inet_addr(argv[1]); @@ -423,7 +431,7 @@ struct timeval ts0, ts; u_int usec; int k; - int dsize = pc->mscb.dsize; + int dsize; int traveltime = 1; if (i > 1) @@ -434,6 +442,9 @@ del_pkt(m); /* connect the remote */ gettimeofday(&(ts), (void*)0); + + dsize = pc->mscb.dsize; + pc->mscb.dsize = PAYLOAD56; k = tcp_open(4); /* restore data size */ @@ -492,7 +503,10 @@ if (k != 2) delay_ms(traveltime); gettimeofday(&(ts), (void*)0); + dsize = pc->mscb.dsize; + pc->mscb.dsize = PAYLOAD56; k = tcp_close(4); + pc->mscb.dsize = dsize; if (k == 0) { printf("Close %d@%s timeout\n", pc->mscb.dport, argv[1]); continue; @@ -530,7 +544,7 @@ while (!timeout(tv, pc->mscb.waittime) && !respok && !ctrl_c) { delay_ms(1); respok = 0; - + while ((p = deq(&pc->iq)) != NULL && !respok && !ctrl_c) { pc->mscb.icmptype = pc->mscb.icmpcode = 0; @@ -540,7 +554,7 @@ p->ts.tv_usec - tv.tv_usec; del_pkt(p); - + if (respok == 0) continue; @@ -549,8 +563,9 @@ if ((pc->mscb.proto == IPPROTO_ICMP && pc->mscb.icmptype == ICMP_ECHOREPLY) || (pc->mscb.proto == IPPROTO_UDP && respok == IPPROTO_UDP) || (pc->mscb.proto == IPPROTO_TCP && respok == IPPROTO_TCP)) { - printf("%s %s=%d ttl=%d time=%.3f ms\n", inet_ntoa(in), - proto_seq, i++, pc->mscb.rttl, usec / 1000.0); + printf("%d bytes from %s %s=%d ttl=%d time=%.3f ms\n", + pc->mscb.rdsize, inet_ntoa(in), proto_seq, i++, + pc->mscb.rttl, usec / 1000.0); break; } @@ -559,14 +574,14 @@ if (pc->mscb.icmptype == ICMP_REDIRECT && pc->mscb.icmpcode == ICMP_REDIRECT_NET) { - din.s_addr = pc->ip4.gw; - printf("Redirect Network, gateway %s", inet_ntoa(din)); - din.s_addr = pc->mscb.rdip; - printf(" -> %s\n", inet_ntoa(din)); - - gwip = pc->mscb.rdip; - delay_ms(100); - goto redirect; + din.s_addr = pc->ip4.gw; + printf("Redirect Network, gateway %s", inet_ntoa(din)); + din.s_addr = pc->mscb.rdip; + printf(" -> %s\n", inet_ntoa(din)); + + gwip = pc->mscb.rdip; + delay_ms(100); + goto redirect; } din.s_addr = pc->mscb.rdip; printf("*%s %s=%d ttl=%d time=%.3f ms", @@ -651,6 +666,8 @@ struct in_addr in; u_char mac[6]; + pc->ip4.dynip = 1; + srand(time(0)); pc->ip4.dhcp.xid = rand(); @@ -749,8 +766,13 @@ in.s_addr = pc->ip4.gw; printf(" GW %s\n", inet_ntoa(in)); } - pc->ip4.dynip = 1; - pc->ip4.mtu = MTU; + + pc->mtu = MTU; + if (pc->ip4.dhcp.renew == 0) + pc->ip4.dhcp.renew = pc->ip4.dhcp.lease / 2; + if (pc->ip4.dhcp.rebind == 0) + pc->ip4.dhcp.rebind = pc->ip4.dhcp.lease * 7 / 8; + pc->ip4.dhcp.timetick = time_tick; return 1; } @@ -844,20 +866,7 @@ if (!strncmp("auto", argv[1], strlen(argv[1]))) return ipauto6(); - if (!strncmp("mtu", argv[1], strlen(argv[1]))) { - if (argc == 2 || argc > 3 || - (argc == 3 && !digitstring(argv[2]))) { - argc = 3; - argv[2] = "?"; - return help_ip(argc, argv); - } - i = atoi(argv[2]); - if (i < 576) { - printf("Invalid MTU, should bigger than 576\n"); - } else - pc->ip4.mtu = i; - return 1; - } + if (!strncmp("domain", argv[1], strlen(argv[1]))) { if (argc != 3) { @@ -1005,7 +1014,7 @@ pc->ip4.ip = rip; pc->ip4.gw = gip; pc->ip4.cidr = icidr; - pc->ip4.mtu = MTU; + pc->mtu = MTU; /* set tap ip address */ if (DEV_TAP == devtype) { @@ -1049,7 +1058,7 @@ pc->mscb.seq = time(0); pc->mscb.proto = IPPROTO_UDP; pc->mscb.dsize = 64; - pc->mscb.mtu = pc->ip4.mtu; + pc->mscb.mtu = pc->mtu; pc->mscb.sport = rand() & 0xfff1; pc->mscb.dport = pc->mscb.sport + 1; pc->mscb.sip = pc->ip4.ip; @@ -1062,7 +1071,7 @@ } if (strchr(argv[1], ':')) { - pc->mscb.mtu = pc->ip6.mtu; + pc->mscb.mtu = pc->mtu; return run_tracert6(argc, argv); } @@ -1317,6 +1326,21 @@ return set_dump(argc, argv); } + if (!strncmp("mtu", argv[1], strlen(argv[1]))) { + if (argc == 2 || argc > 3 || + (argc == 3 && !digitstring(argv[2]))) { + argc = 3; + argv[2] = "?"; + return help_set(argc, argv); + } + value = atoi(argv[2]); + if (value < 576) { + printf("Invalid MTU, should bigger than 576\n"); + } else + pc->mtu = value; + return 1; + } + if (!strncmp("lport", argv[1], strlen(argv[1]))) { if (argc != 3) { printf("Incomplete command.\n"); @@ -1363,22 +1387,48 @@ return 1; } if (strlen(argv[2]) > MAX_NAMES_LEN) - printf("Hostname is too long. (should be less than %d)\n", MAX_NAMES_LEN); + printf("Hostname is too long. (Maximum %d characters)\n", MAX_NAMES_LEN); else strcpy(vpc[pcid].xname, argv[2]); } else if (!strncmp("echo", argv[1], strlen(argv[1]))) { if (!strcmp(argv[argc - 1], "?")) return help_set(argc, argv); - if (argc != 3) { + if (argc < 3) { printf("Incomplete command.\n"); return 1; } if (!strcasecmp(argv[2], "on")) { - canEcho = 1; + echoctl.enable = 1; } else if (!strcasecmp(argv[2], "off")) { - canEcho = 0; + echoctl.enable = 0; + } + if (argc > 3 && !strcasecmp(argv[2], "color")) { + if (argc == 4) { + if (!strcasecmp(argv[3], "clear")) { + echoctl.fgcolor = 0; + echoctl.bgcolor = 0; + } else + echoctl.fgcolor = str2color(argv[3]); + } + if (argc == 5) { + echoctl.fgcolor = str2color(argv[3]); + echoctl.bgcolor = str2color(argv[4]) + 10; + } + } else if (argc > 4 && !strcasecmp(argv[3], "color")) { + if (argc == 5) { + if (!strcasecmp(argv[3], "clear")) { + echoctl.fgcolor = 0; + echoctl.bgcolor = 0; + } else + echoctl.fgcolor = str2color(argv[4]); + } + if (argc == 6) { + echoctl.fgcolor = str2color(argv[4]); + echoctl.bgcolor = str2color(argv[5]) + 10; + } } + } else printf("Invalid command.\n"); return 1; @@ -1452,8 +1502,18 @@ { int i; + if (echoctl.fgcolor != 0) { + if (echoctl.bgcolor != 0) + printf("\033[%d;%dm", echoctl.fgcolor, echoctl.bgcolor); + else + printf("\033[%dm", echoctl.fgcolor); + } for (i = 1; i < argc; i++) printf("%s ", argv[i]); + + if (echoctl.fgcolor != 0) + printf("\033[0m"); + // printf("\n"); return 1; @@ -1486,6 +1546,7 @@ int ok = 1; int i = 2; pcs *pc = &vpc[pcid]; + int dmpflag = 0; if (argc == 2) @@ -1500,9 +1561,22 @@ dmpflag |= DMP_DETAIL; else if (!strncmp(argv[i], "all", strlen(argv[i]))) dmpflag |= DMP_ALL; - else if (!strncmp(argv[i], "off", strlen(argv[i]))) + else if (!strncmp(argv[i], "file", strlen(argv[i]))) { + if (pc->dmpfile == NULL) { + char tfname[1024]; + sprintf(tfname, "vpcs%d", pc->id + 1); + pc->dmpfile = open_dmpfile(tfname); + } + dmpflag |= DMP_FILE; + } else if (!strncmp(argv[i], "off", strlen(argv[i]))) { dmpflag = 0; - else { + /* give pthread reader/writer a little time */ + usleep(1000); + if (pc->dmpfile) { + close_dmpfile(pc->dmpfile); + pc->dmpfile = NULL; + } + } else { printf("Invalid options\n"); ok = 0; break; @@ -1524,6 +1598,8 @@ printf(" detail"); if (pc->dmpflag & DMP_ALL) printf(" all"); + if (pc->dmpflag & DMP_FILE) + printf(" file"); if (pc->dmpflag == 0) printf(" (none)"); printf("\n"); @@ -1626,6 +1702,8 @@ printf(" detail"); if (vpc[i].dmpflag & DMP_ALL) printf(" all"); + if (vpc[i].dmpflag & DMP_FILE) + printf(" file"); if (vpc[i].dmpflag == 0) printf(" (none)"); printf("\n"); @@ -1651,6 +1729,8 @@ printf(" detail"); if (pc->dmpflag & DMP_ALL) printf(" all"); + if (pc->dmpflag & DMP_FILE) + printf(" file"); if (pc->dmpflag == 0) printf(" (none)"); printf("\n"); @@ -1742,6 +1822,13 @@ if (vpc[id].ip4.dhcp.svr) { in.s_addr = vpc[id].ip4.dhcp.svr; printf("DHCP SERVER : %s\n", inet_ntoa(in)); + k = time_tick - vpc[id].ip4.dhcp.timetick; + k = vpc[id].ip4.dhcp.lease - k; + printf("DHCP LEASE : %u, %u/%u/%u\n", + k > 0 ? k : 0, + vpc[id].ip4.dhcp.lease, + vpc[id].ip4.dhcp.renew, + vpc[id].ip4.dhcp.rebind); } if (vpc[id].ip4.domain[0]) { printf("DOMAIN NAME : %s\n", vpc[id].ip4.domain); @@ -1754,7 +1841,7 @@ printf("LPORT : %d\n", vpc[id].lport); in.s_addr = vpc[id].rhost; printf("RHOST:PORT : %s:%d\n", inet_ntoa(in), vpc[id].rport); - printf("MTU: : %d\n", vpc[id].ip4.mtu); + printf("MTU: : %d\n", vpc[id].mtu); return 1; } @@ -1768,12 +1855,18 @@ { printf("\n"); - if (canEcho) - printf("Echo On\n"); - else - printf("Echo Off\n"); + esc_prn("Echo {H%s}\n", (echoctl.enable) ? "On" : "Off"); + printf("Foreground color: %s\n", + (echoctl.fgcolor >= 30 && echoctl.fgcolor <= 37) ? + color_name[echoctl.fgcolor - 30] : + "default"); + + printf("Background color: %s\n", + (echoctl.bgcolor >= 40 && echoctl.bgcolor <= 47) ? + color_name[echoctl.bgcolor - 40] : + "default"); - return 1; + return 1; } int run_ver(int argc, char **argv) @@ -1889,47 +1982,70 @@ strcat(fname, ".vpc"); fp = fopen(fname, "w"); - if (fp != NULL) { - local_ip = inet_addr("127.0.0.1"); - for (i = 0; i < num_pths; i++) { - if (num_pths > 1) - fprintf(fp, "%d\n", i + 1); - - sprintf(buf, "VPCS[%d]", i + 1); - if (strncmp(vpc[i].xname, buf, 3)) - fprintf(fp, "set pcname %s\n", vpc[i].xname); - - if (num_pths > 1) { - if (vpc[i].lport != (20000 + i)) - fprintf(fp, "set lport %d\n", vpc[i].lport); - - if (vpc[i].rport != (30000 + i)) - fprintf(fp, "set rport %d\n", vpc[i].rport); - if (vpc[i].rhost != local_ip) { - in.s_addr = vpc[i].rhost; - fprintf(fp, "set rhost %s\n", inet_ntoa(in)); + if (fp == NULL) { + printf("failed: %s\n", strerror(errno)); + return 1; + } + + printf("Saving startup configuration to %s\n", fname); + local_ip = inet_addr("127.0.0.1"); + for (i = 0; i < num_pths; i++) { + if (num_pths > 1) + fprintf(fp, "%d\n", i + 1); + sprintf(buf, "VPCS[%d]", i + 1); + if (strncmp(vpc[i].xname, buf, 3)) + fprintf(fp, "set pcname %s\n", vpc[i].xname); + + if (num_pths > 1) { + if (vpc[i].lport != (20000 + i)) + fprintf(fp, "set lport %d\n", vpc[i].lport); + if (vpc[i].rport != (30000 + i)) + fprintf(fp, "set rport %d\n", vpc[i].rport); + if (vpc[i].rhost != local_ip) { + in.s_addr = vpc[i].rhost; + fprintf(fp, "set rhost %s\n", inet_ntoa(in)); + } + } + + if (vpc[i].ip4.dynip == 1) + fputs("dhcp\n", fp); + else { + p = (char *)ip4Info(i); + if (p != NULL) + fprintf(fp, "%s\n", p); + p = (char *)ip6Info(i); + if (p != NULL) + fprintf(fp, "%s\n", p); + if (vpc[i].ip4.domain[0]) + fprintf(fp, "ip domain %s\n", vpc[i].ip4.domain); + if (vpc[i].ip4.dns[0]) { + in.s_addr = vpc[i].ip4.dns[0]; + fprintf(fp, "ip dns %s", inet_ntoa(in)); + if (vpc[i].ip4.dns[1]) { + in.s_addr = vpc[i].ip4.dns[1]; + fprintf(fp, " %s", inet_ntoa(in)); } + fprintf(fp, "\n"); } - if (vpc[i].ip4.dynip == 1) - fputs("dhcp\n", fp); - else { - p = (char *)ip4Info(i); - if (p != NULL) - fprintf(fp, "%s\n", p); - p = (char *)ip6Info(i); - if (p != NULL) - fprintf(fp, "%s\n", p); - } - if (vpc[i].ip6auto == 1) - fputs("ip auto\n", fp); - printf("."); } - if (num_pths > 1) - fprintf(fp, "1\n"); - fclose(fp); - printf(" done\n"); - } else - printf("failed: %s\n", strerror(errno)); + + if (vpc[i].ip6auto == 1) + fputs("ip auto\n", fp); + + if (vpc[i].mtu != 1500) + fprintf(fp, "set mtu %d\n", vpc[i].mtu); + + printf("."); + } + + save_relay(fp); + + if (num_pths > 1) + fprintf(fp, "1\n"); + + fclose(fp); + printf(" done\n"); + return 1; } @@ -1955,4 +2071,16 @@ return buf; } +int str2color(const char *cstr) +{ + int i; + + for (i = 0; i < 8; i++) + if (!strncasecmp(cstr, color_name[i], strlen(color_name[i]))) + break; + if (i == 8) + return 0; + else + return 30 + i; +} /* end of file */ diff -Nru vpcs-0.5b2/src/command.h vpcs-0.6.1/src/command.h --- vpcs-0.5b2/src/command.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/command.h 2016-10-14 08:55:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru vpcs-0.5b2/src/dhcp.c vpcs-0.6.1/src/dhcp.c --- vpcs-0.5b2/src/dhcp.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/dhcp.c 2016-10-14 08:55:04.000000000 +0000 @@ -393,8 +393,6 @@ } return 1; - - return 0; } int isDhcp4_packer(pcs *pc, struct packet *m) @@ -423,6 +421,8 @@ p = dh->options; magic = ((long*)(p))[0]; if (magic == htonl(0x63825363)) { + pc->ip4.dhcp.renew = 0; + pc->ip4.dhcp.rebind = 0; p += 4; while (*p != DHO_END && p - dh->options < DHCP_OPTION_LEN) { if (*p == DHO_SUBNET_MASK && *(p + 1) == 4) { @@ -436,10 +436,18 @@ p += 6; continue; } else if (*p == DHO_DHCP_LEASE_TIME && *(p + 1) == 4) { - pc->ip4.lease += ((int*)(p + 2))[0]; + pc->ip4.lease = ntohl(((int*)(p + 2))[0]); pc->ip4.dhcp.lease = pc->ip4.lease; p += 6; continue; + } else if (*p == DHO_DHCP_RENEWAL_TIME && *(p + 1) == 4) { + pc->ip4.dhcp.renew = ntohl(((int*)(p + 2))[0]); + p += 6; + continue; + } else if (*p == DHO_DHCP_REBIND_TIME && *(p + 1) == 4) { + pc->ip4.dhcp.rebind = ntohl(((int*)(p + 2))[0]); + p += 6; + continue; } else if (*p == DHO_DNS) { if (*(p + 1) == 4) { pc->ip4.dhcp.dns[0] = ((int*)(p + 2))[0]; @@ -458,6 +466,11 @@ memcpy(pc->ip4.dhcp.domain, p + 2, *(p + 1)); strcpy(pc->ip4.domain, pc->ip4.dhcp.domain); p += *(p + 1) + 2; + continue; + } else if (*p == DHO_DHCP_SERVER_IDENTIFIER && *(p + 1) == 4) { + pc->ip4.dhcp.svr = ((int*)(p + 2))[0]; + p += 6; + continue; } else { p++; /* skip op code */ p += *(p) + 1; /* add op offset(length) */ @@ -643,4 +656,118 @@ return 0; } + +int dhcp_renew(pcs *pc) +{ + struct packet *m; + struct packet *p; + int i; + int ok; + + pc->ip4.dhcp.xid = rand(); + /* request */ + i = 0; + ok = 0; + while (i++ < 3 && !ok) { + m = dhcp4_request(pc); + if (m == NULL) { + sleep(1); + continue; + } + + enq(&pc->oq, m); + sleep(1); + + while ((p = deq(&pc->bgiq)) != NULL && !ok) { + ok = isDhcp4_packer(pc, p); + free(p); + } + + i++; + } + if (ok) { + if (pc->ip4.dhcp.renew == 0) + pc->ip4.dhcp.renew = pc->ip4.dhcp.lease / 2; + if (pc->ip4.dhcp.rebind == 0) + pc->ip4.dhcp.rebind = pc->ip4.dhcp.lease * 7 / 8; + return 1; + } + return 0; +} + +int dhcp_rebind(pcs *pc) +{ + int ts[3] = {1, 3, 9}; + struct packet *m; + struct packet *p; + int i; + int ok; + + pc->ip4.dhcp.xid = rand(); + /* request */ + i = 0; + ok = 0; + while (i < 3 && !ok) { + m = dhcp4_discover(pc, 0); + if (m == NULL) { + sleep(1); + continue; + } + enq(&pc->oq, m); + sleep(ts[i]); + + while ((p = deq(&pc->bgiq)) != NULL && !ok) { + ok = isDhcp4_Offer(pc, p); + free(p); + } + } + if (!ok) + return 0; + + /* request */ + i = 0; + ok = 0; + while (i < 3 && !ok) { + m = dhcp4_request(pc); + if (m == NULL) { + sleep(1); + continue; + } + + enq(&pc->oq, m); + sleep(1); + + while ((p = deq(&pc->bgiq)) != NULL && !ok) { + ok = isDhcp4_packer(pc, p); + free(p); + } + } + if (ok) { + if (pc->ip4.dhcp.renew == 0) + pc->ip4.dhcp.renew = pc->ip4.dhcp.lease / 2; + if (pc->ip4.dhcp.rebind == 0) + pc->ip4.dhcp.rebind = pc->ip4.dhcp.lease * 7 / 8; + return 1; + } + return 0; +} + +int dhcp_enq(pcs *pc, const struct packet *m) +{ + ethdr *eh; + iphdr *ip; + udpiphdr *ui; + dhcp4_hdr *dh; + + eh = (ethdr *)(m->data); + ip = (iphdr *)(eh + 1); + ui = (udpiphdr *)ip; + dh = (dhcp4_hdr*)(ui + 1); + + if (pc->bgjobflag && dh->xid == pc->ip4.dhcp.xid) { + enq(&pc->bgiq, (struct packet *)m); + return 1; + } + return 0; +} /* end of file */ diff -Nru vpcs-0.5b2/src/dhcp.h vpcs-0.6.1/src/dhcp.h --- vpcs-0.5b2/src/dhcp.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/dhcp.h 2016-10-14 08:55:04.000000000 +0000 @@ -89,5 +89,10 @@ int dmp_dhcp(pcs *pc, const struct packet *m); +int dhcp_renew(pcs *pc); +int dhcp_rebind(pcs *pc); +int dhcp_enq(pcs *pc, const struct packet *m); + + #endif /* end of file */ diff -Nru vpcs-0.5b2/src/dns.c vpcs-0.6.1/src/dns.c --- vpcs-0.5b2/src/dns.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/dns.c 2016-10-14 08:55:06.000000000 +0000 @@ -99,7 +99,7 @@ cb.data = data; cb.dsize = dlen; cb.proto = IPPROTO_UDP; - cb.mtu = pc->ip4.mtu; + cb.mtu = pc->mtu; cb.ipid = time(0) & 0xffff; cb.ttl = TTL; cb.sip = pc->ip4.ip; diff -Nru vpcs-0.5b2/src/dump.c vpcs-0.6.1/src/dump.c --- vpcs-0.5b2/src/dump.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/dump.c 2016-10-14 08:55:06.000000000 +0000 @@ -166,16 +166,19 @@ printf("IPv%d, id: %x, length: %d, ttl: %d, sum: %4.4x", iph->ver, ntohs(iph->id), ntohs(iph->len), iph->ttl, ntohs(iph->cksum)); - if (ntohs(iph->frag) == IPDF) + if ((ntohs(iph->frag) & IP_DF) == IP_DF) printf(", DF"); - if (ntohs(iph->frag) == IPMF) - printf(", MF"); + if (ntohs(iph->frag) & (IP_MF | IP_OFFMASK)) + printf(", MF/%d", (ntohs(iph->frag) << 3) & 0xffff); in.s_addr = iph->sip; printf("\nAddress: %s -> ", inet_ntoa(in)); in.s_addr = iph->dip; printf("%s\n", inet_ntoa(in)); + if ((ntohs(iph->frag) << 3) & 0xffff) + return; + if (iph->proto == IPPROTO_ICMP) { printf("Proto: icmp, "); printf("type: %d, ", icmp->type); @@ -532,3 +535,85 @@ return buf; } +FILE * +open_dmpfile(const char *fname) +{ + char tfname[1024]; + FILE *fp; + pcap_hdr_t phdr; + time_t t0; + struct tm *tm; + + t0 = time(0); + tm = localtime(&t0); + + snprintf(tfname, sizeof(tfname), "%s_%4d%02d%02d%02d%02d%02d.pcap", + fname, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + fp = fopen(tfname, "ab"); + if (!fp) + return NULL; + + phdr.magic_number = 0xa1b2c3d4; + phdr.version_major = 2; + phdr.version_minor = 4; + phdr.thiszone = 0; + phdr.sigfigs = 0; + phdr.snaplen = 0xffff; + phdr.network = 1; + + fwrite(&phdr, sizeof(phdr), 1, fp); + fflush(fp); + return fp; +} + +void +close_dmpfile(FILE *fp) +{ + fclose(fp); +} + +int +dmp_packet2file(const struct packet *m, FILE *fp) +{ + pcaprec_hdr_t phdr; + struct timeval ts; + + gettimeofday(&(ts), (void*)0); + + phdr.ts_sec = ts.tv_sec; + phdr.ts_usec = ts.tv_usec; + phdr.incl_len = m->len; + phdr.orig_len = m->len; + + fwrite(&phdr, sizeof(phdr), 1, fp); + fwrite(m->data, m->len, 1, fp); + fflush(fp); + + return 0; +} + +int +dmp_buffer2file(const char *m, int len, FILE *fp) +{ + pcaprec_hdr_t phdr; + struct timeval ts; + + gettimeofday(&(ts), (void*)0); + + phdr.ts_sec = ts.tv_sec; + phdr.ts_usec = ts.tv_usec; + phdr.incl_len = len; + phdr.orig_len = len; + + if (!fp) + return 0; + + fwrite(&phdr, sizeof(phdr), 1, fp); + fwrite(m, len, 1, fp); + fflush(fp); + + return 0; + +} diff -Nru vpcs-0.5b2/src/dump.h vpcs-0.6.1/src/dump.h --- vpcs-0.5b2/src/dump.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/dump.h 2016-10-14 08:55:04.000000000 +0000 @@ -27,8 +27,33 @@ #ifndef _DUMP_H_ #define _DUMP_H_ +#include + + #include "queue.h" +typedef struct pcap_hdr_s { + u_int magic_number; /* magic number */ + u_short version_major; /* major version number */ + u_short version_minor; /* minor version number */ + u_int thiszone; /* GMT to local correction */ + u_int sigfigs; /* accuracy of timestamps */ + u_int snaplen; /* max length of captured packets, in octets */ + u_int network; /* data link type */ +} pcap_hdr_t; + +typedef struct pcaprec_hdr_s { + u_int ts_sec; /* timestamp seconds */ + u_int ts_usec; /* timestamp microseconds */ + u_int incl_len; /* number of octets of packet saved in file */ + u_int orig_len; /* actual length of packet */ +} pcaprec_hdr_t; + int dmp_packet(const struct packet *m, const int flag); +FILE *open_dmpfile(const char *fname); +void close_dmpfile(FILE *fp); +int dmp_packet2file(const struct packet *m, FILE *fp); +int dmp_buffer2file(const char *m, int len, FILE *fp); + #endif diff -Nru vpcs-0.5b2/src/getopt.c vpcs-0.6.1/src/getopt.c --- vpcs-0.5b2/src/getopt.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/getopt.c 2016-10-14 08:55:04.000000000 +0000 @@ -40,7 +40,7 @@ #include #include "getopt.h" -//static const char* ID = "$Id: getopt.c 38 2012-07-17 15:23:35Z mirnshi $"; +//static const char* ID = "$Id$"; char* optarg = NULL; int optind = 0; diff -Nru vpcs-0.5b2/src/help.c vpcs-0.6.1/src/help.c --- vpcs-0.5b2/src/help.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/help.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,12 +27,15 @@ #include #include #include "help.h" +#include "utils.h" + +extern int num_pths; int help_clear(int argc, char **argv) { - printf( "\n\033[1mclear [ip|ipv6|arp|neighbor|hist]\033[0m\n" - " Clear ip/ipv6 address, arp/neighbor table, command history\n"); - + esc_prn("\n{Hclear} {Hip}|{Hipv6}|{Harp}|{Hneighbor}|{Hhist}\n" + " Clear ip/ipv6 address, arp/neighbor table, command history.\n"); + return 1; } @@ -49,90 +52,108 @@ int help_relay(int argc, char **argv) { - printf( "\n\033[1mrelay [arguments]\033[0m\n" - " arguments:\n" - " port set relay hub port\n" - " show show the relay rules\n" - " add [ip1:]port1 [ip2:]port2 relay the packets between port1 and port2\n" - " del [ip1:]port1 [ip2:]port2 delete the relay rule\n" - " del delete the relay rule\n"); + char *s[2] = { + "[{Uip1}:]{Uport1} [{Uip2}:]{Uport2}", + "{Uip1} and {Uip2}"}; + + esc_prn("\n{Hrelay} {UARG}\n" + " The relay command allows the VPCS to become a virtual patch panel where\n" + " connections can be dynamically changed using the {Hrelay} command.\n" + " There are three steps required to use VPCS as a virtual patch panel.\n" + " 1. A relay {Hhub port} must be defined using the {Hrelay port} {Uport} command.\n" + " 2. Remote NIO_UDP connections (cloud connections in GNS3) use this {Hhub}\n" + " {Hport} as the remote port, ensuring each NIO_UDP connection has a unique \n" + " {Hlocal} port (The local {Hport} numbers will be used to 'patch' the\n" + " connection). VPC instances can be directed to use this hub port as\n" + " their remote port using the command {Hset rport} {Uport}.\n" + " 3. The 'patching' is completed using the command:\n" + " {Hrelay add} [{Uip1}:]{Uport1} [{Uip2}:]{Uport2}, where {Uport1} and {Uport2} are the\n" + " {Hlocal} port numbers used in step 2.\n" + " ARG:\n" + " {Hadd} %s Relay the packets between %s\n" + " {Hdel} %s Delete the relay rule\n" + " {Hdel} {Uid} Delete the relay rule\n" + " {Hdump} [{Hon}|{Hoff}] Dump relay packets to file\n" + " {Hport} {Uport} Set relay hub port\n" + " {Hshow} Show the relay rules\n" + " Note: %s are 127.0.0.1 by default\n", + s[0], s[1], s[0], s[1]); return 1; } - int help_ip(int argc, char **argv) { - if (!strncmp(argv[0], "dhcp", strlen(argv[0])) || (argc == 3 && !strncmp(argv[1], "dhcp", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2]))))) { - printf( "\n\033[1mip dhcp [-options]\033[0m\n" + esc_prn("\n{Hip dhcp} [{UOPTION}]\n" " Attempt to obtain IPv4 address, mask, gateway and DNS via DHCP\n" - " options:\n" - " -d Show DHCP packet decode\n" - " -r Renew DHCP lease\n" - " -x Release DHCP lease\n"); - return 1; - } + " OPTION:\n" + " {H-d} Show DHCP packet decode\n" + " {H-r} Renew DHCP lease\n" + " {H-x} Release DHCP lease\n"); - if (argc == 3 && !strncmp(argv[1], "mtu", strlen(argv[1])) && - (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mip mtu \033[0m\n" - " Set IPv4 MTU to , at least 576.\n"); - return 1; + return 1; } if (argc == 3 && !strncmp(argv[1], "dns", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mip dns \033[0m\n" - " Set DNS server , delete if is '0'\n"); - return 1; + esc_prn("\n{Hip dns} {Uip}\n" + " Set DNS server {Uip}, delete if {Uip} is '0'.\n"); + + return 1; } if (argc == 3 && !strncmp(argv[1], "domain", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mip domain \033[0m\n" + esc_prn("\n\{Hip domain} {Uname}\n" " Sets local domain name. \n" - " If there's no '.' in the host name: the name is assumed within the local domain, \n" - " it is a short name relative to the local domain. The resolver will append the local\n" - " domain name to the hostname to resolve it\n"); - return 1; + " If there's no '.' in the host name: the name is assumed within the local\n" + " domain, it is a short name relative to the local domain. The resolver\n" + " will append the local domain name to the hostname to resolve it.\n"); + + return 1; } - printf( "\n\033[1mip [arguments]\033[0m\n" + esc_prn("\n{Hip} {UARG} ... [{UOPTION}]\n" " Configure the current VPC's IP settings\n" - " arguments:\n" - "
[/] []\n" - "
[] [/]\n" + " ARG ...:\n" + " {Uaddress} [{Umask}] [{Ugateway}]\n" + " {Uaddress} [{Ugateway}] [{Umask}]\n" " Set the VPC's ip, default gateway ip and network mask\n" - " Default IPv4 mask is /24, IPv6 is /64. In the ether mode, \n" - " the ip of the tapx is the maximum host ID of the subnet. \n" - " \033[1mip 10.1.1.70 /26 10.1.1.65\033[0m set the VPC's ip to 10.1.1.70, \n" - " the gateway to 10.1.1.65, the netmask to 255.255.255.192, \n" - " the tapx ip to 10.1.1.126 in the ether mode.\n" - " may be written as /26, 26 or 255.255.255.192\n" - " auto Attempt to obtain IPv6 address, mask and gateway using SLAAC\n" - " dhcp -[d|r|x] Attempt to obtain IPv4 address, mask, gateway, DNS via DHCP\n" - " -d Show DHCP packet decode\n" - " -r Renew DHCP lease\n" - " -x Release DHCP lease\n" - " dns Set DNS server , delete if is '0'\n" - " domain set local domain name\n" - " mtu Set IPv4 MTU to , at least 576. \n"); + " Default IPv4 mask is /24, IPv6 is /64. Example:\n" + " {Hip 10.1.1.70/26 10.1.1.65} set the VPC's ip to 10.1.1.70,\n" + " the gateway to 10.1.1.65, the netmask to 255.255.255.192.\n" + " In tap mode, the ip of the tapx is the maximum host ID\n" + " of the subnet. In the example above the tapx ip would be \n" + " 10.1.1.126\n" + " {Umask} may be written as /26, 26 or 255.255.255.192\n" + " {Hauto} Attempt to obtain IPv6 address, mask and gateway using SLAAC\n" + " {Hdhcp} [{UOPTION}] Attempt to obtain IPv4 address, mask, gateway, DNS via DHCP\n" + " {H-d} Show DHCP packet decode\n" + " {H-r} Renew DHCP lease\n" + " {H-x} Release DHCP lease\n" + " {Hdns} {Uip} Set DNS server {Uip}, delete if {Uip} is '0'\n" + " {Hdomain} {UNAME} Set local domain name to {UNAME}\n"); return 1; } int help_load(int argc, char **argv) { - printf( "\n\033[1mload [filename]\033[0m\n" - " Load the configuration/script from the file [filename] (startup.vpc is the default filename).\n" - " When the file is loaded, commands will be displayed before being executed \n" - " if the state of the echo flag is on. See \033[1mset echo\033[0m\n" - " \033[1msleep\033[0m command will ignore \033[1mset echo on\033[0m, ONLY if \033[1msleep\033[0m misses the \n" - " parameter. \n\n" - " Note: Press Ctrl+C to interrupt the running script\n"); - + esc_prn("\n{Hload} [{UFILENAME}[.vpc]]\n" + " Load the configuration/script from the file {UFILENAME}. If {UFILENAME} ends with\n" + " '.vpc', then the '.vpc' can be omitted. If {UFILENAME} is omitted then \n" + " {Ustartup.vpc} will be loaded if it exists. When the file is loaded, each\n" + " line of the file is executed as a VPCS command. If the state of the echo flag\n" + " is on, the command will be echoed to the console before execution, except: \n" + " * If the command is prefixed with a '@' symbol (eg {H@set echo color red});\n" + " * If the command is an echo command;\n" + " * If the command is a sleep command \n" + " Note: The command {Hsleep 0} will be echoed if the echo flag is on\n" + " See {Hset echo} and {Hshow echo}\n\n" + " Note: Press Ctrl+C to interrupt the running script.\n"); + return 1; } @@ -144,59 +165,64 @@ int help_ping(int argc, char **argv) { - printf( "\n\033[1mping [-options]\033[0m\n" - " Ping the network . can be an ip address or name\n" - " options:\n" - " -1 ICMP mode, default\n" - " -2 UDP mode\n" - " -3 TCP mode\n" - " -P Same as above, setting ip protocol\n" - " 1 - icmp, 17 - udp, 6 - tcp\n" - " -c packet count, default 5\n" - " -l data size\n" - " -T set TTL, default 64\n" - " -s source port\n" - " -p destination port\n" - " -f tcp head flag, |C|E|U|A|P|R|S|F|\n" - " bits |7 6 5 4 3 2 1 0|\n" - " -t send packet until interrupt by Ctrl+C\n" - " -i wait milliseconds between sending each packet\n" - " -w wait milliseconds to receive the response\n\n" - " Note: 1. Using names requires DNS to be set.\n" - " 2. Use Ctrl+C to stop the command.\n"); + esc_prn("\n{Hping} {UHOST} [{UOPTION} ...]\n" + " Ping the network {UHOST}. {UHOST} can be an ip address or name\n" + " Options:\n" + " {H-1} ICMP mode, default\n" + " {H-2} UDP mode\n" + " {H-3} TCP mode\n" + " {H-c} {Ucount} Packet count, default 5\n" + " {H-D} Set the Don't Fragment bit\n" + " {H-f} {UFLAG} Tcp header FLAG |{HC}|{HE}|{HU}|{HA}|{HP}|{HR}|{HS}|{HF}|\n" + " bits |7 6 5 4 3 2 1 0|\n" + " {H-i} {Ums} Wait {Ums} milliseconds between sending each packet\n" + " {H-l} {Usize} Data size\n" + " {H-P} {Uprotocol} Use IP {Uprotocol} in ping packets\n" + " {H1} - ICMP (default), {H17} - UDP, {H6} - TCP\n" + " {H-p} {Uport} Destination port\n" + " {H-s} {Uport} Source port\n" + " {H-T} {Uttl} Set {Uttl}, default 64\n" + " {H-t} Send packets until interrupted by Ctrl+C\n" + " {H-w} {Ums} Wait {Ums} milliseconds to receive the response\n\n" + " Notes: 1. Using names requires DNS to be set.\n" + " 2. Use Ctrl+C to stop the command.\n"); return 1; } int help_trace(int argc, char **argv) { - printf( "\n\033[1mtrace [-options]\033[0m\n" - " Print the path packets take to network . can be an ip address or name.\n" - " options:\n" - " -P Use IP in trace packets\n" - " 1 - icmp, 17 - udp (default), 6 - tcp \n" - " -m maximum TTL, default 8\n" - " Same as -m option, compatible with the old version\n\n" - " Note: 1. Using names requires DNS to be set.\n" - " 2. Use Ctrl+C to stop the command.\n"); + esc_prn("\n{Htrace} {UHOST} [{UOPTION} ...]\n" + " Print the path packets take to the network {UHOST}. {UHOST} can be an ip address or\n" + " name.\n" + " Options:\n" + " {H-P} {Uprotocol} Use IP {Uprotocol} in trace packets\n" + " {H1} - icmp, {H17} - udp (default), {H6} - tcp\n" + " {H-m} {Uttl} Maximum {Uttl}, default 8\n\n" + " Notes: 1. Using names requires DNS to be set.\n" + " 2. Use Ctrl+C to stop the command.\n"); + return 1; } int help_rlogin(int argc, char **argv) { - printf( "\n\033[1mrlogin [] \033[0m\n" - " Telnet to at (def 127.0.0.1) relative to HOST PC. \n" + esc_prn("\n{Hrlogin} [{Uip}] {Uport}\n" + " Telnet to {Uport} at {Uip} (default 127.0.0.1) relative to host PC. \n" " To attach to the console of a virtual router running on port 2000 of this\n" - " host PC, use \033[1mrlogin 2000\033[0m\n" + " host PC, use {Hrlogin 2000}\n" " To telnet to the port 2004 of a remote host 10.1.1.1, use\n" - " \033[1mrlogin 10.1.1.1 2004\033[0m\n"); + " {Hrlogin 10.1.1.1 2004}\n"); + return 1; } int help_save(int argc, char **argv) { - printf( "\n\033[1msave [filename]\033[0m\n" - " Save the configuration to the file [filename] (startup.vpc is the default filename).\n"); + esc_prn("\n{Hsave} [{UFILENAME}[.vpc]]\n" + " Save the configuration to the file {UFILENAME.vpc}. If there is no '.' in\n" + " {UFILENAME} then a '.vpc' extension is added. If {UFILENAME} is omitted then the\n" + " configuration will be saved to {Ustartup.vpc}\n"); return 1; } @@ -205,104 +231,169 @@ { if (argc == 3 && !strncmp(argv[1], "dump", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mset dump [detail|mac|raw|all|off]\033[0m\n" - " Set the packet dump flag for this VPC\n" - " detail print protocol\n" - " mac print ether address\n" - " raw print the first 40 bytes\n" - " all all the packets including incoming\n" - " must use [detail|mac|raw] as well as 'all'\n" - " off clear all the flags\n"); - + esc_prn("\n{Hset dump} {Hall}|{Hdetail}|{Hfile}|{Hoff}|{Hmac}|{Hraw}\n" + " Set the packet dump flags for this VPC\n" + " {Hall} All the packets including incoming\n" + " must use {Udetail}|{Umac}|{Uraw} as well as 'all'\n" + " {Hdetail} Print protocol\n" + " {Hfile} Dump packets to file 'vpcs[id]_yyyymmddHHMMSS.pcap'\n" + " {Hmac} Print harware MAC address\n" + " {Hoff} Clear all the flags\n" + " {Hraw} Print the first 40 bytes\n"); + return 1; } if (argc == 3 && !strncmp(argv[1], "echo", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mset echo [on|off]\033[0m\n" - " Sets the state of the echo flag used when loading script files.\n" - " See \033[1mload [filename]\033[0m.\n"); - return 1; - } - - printf( "\n\033[1mset [lport|rport|rhost|pcname|echo|dump|]\033[0m\n" - " Set hostname, connection port, dump options and echo on or off\n" - " lport local port\n" - " rport remote peer port\n" - " rhost remote peer host IPv4 address\n" - " pcname set the hostname of the current VPC\n" - " echo [on|off] set echoing on or off during script execution\n" - " dump [options] set the packet dump flag for this VPC. \n" - " Options:\n" - " detail print protocol\n" - " mac print ether address\n" - " raw print the first 40 bytes\n" - " all all the packets including incoming.\n" - " must use [detail|mac|raw] as well as 'all'\n" - " off clear all the flag\n"); - + esc_prn("\n{Hset echo} {Hon}|{Hoff}|[{Hcolor} [{Hclear}|{UFGCOLOR} [{UBGCOLOR}]]]\n" + " Sets the state of the echo flag used when executing script files,\n" + " or sets the color of text to {UFGCOLOR} with optional {UBGCOLOR}\n" + " Color list: black, red, green, yellow, blue, magenta, cyan, white\n" + " See {Hload ?}.\n"); + + return 1; + } + + if (argc == 3 && !strncmp(argv[1], "mtu", strlen(argv[1])) && + (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { + esc_prn("\n{Hset mtu} {Uvalue}\n" + " Set the maximum transmission unit of the interface, at least 576.\n"); + + return 1; + } + + esc_prn("\n{Hset} {UARG} ...\n" + " Set hostname, connection port, ipfrag state, dump options and echo options\n" + " ARG:\n" + " {Hdump} {UFLAG} [[{UFLAG}]...] Set the packet dump flags for this VPC. \n" + " FLAG:\n" + " {Hall} All the packets including incoming.\n" + " must use [detail|mac|raw] as well as 'all'\n" + " {Hdetail} Print protocol\n" + " {Hfile} Dump packets to file 'vpcs[id]_yyyymmddHHMMSS.pcap'\n" + " {Hoff} Clear all the flags\n" + " {Hmac} Print hardware MAC address\n" + " {Hraw} Print the first 40 bytes\n" + " {Hecho} {Hon}|{Hoff}|{Ucolor} ... Set echoing options. See {Hset echo ?}\n" + " {Hlport} {Uport} Local port\n" + " {Hmtu} {Uvalue} Set the maximum transmission unit of the interface\n" + " {Hpcname} {UNAME} Set the hostname of the current VPC to {UNAME}\n" + " {Hrport} {Uport} Remote peer port\n" + " {Hrhost} {Uip} Remote peer host IPv4 address\n"); + return 1; } int help_shell(int argc, char **argv) { - printf( "\n\033[1m! [command [args]]\033[0m\n" - " Invoke an OS command with the 'args' as its arguments\n"); - + esc_prn("\n{H!} {UCOMMAND} [{UARG} ...]\n" + " Invoke an OS command {UCOMMAND} with optional [{UARG} ...] as arguments\n"); + return 1; } int help_show(int argc, char **argv) { + char *harp[2] = { + "\n{Hshow arp} [{Udigit}|{Hall}]\n" + " Show arp table for VPC {Udigit} (default this VPC) or all VPCs\n", + "\n{Hshow arp}\n" + " Show arp table\n"}; + char *hdump[2] = { + "\n{Hshow dump} [{Udigit}|{Hall}]\n" + " Show dump flags for VPC {Udigit} (default this VPC) or all VPCs\n", + "\n{Hshow dump}\n" + " Show dump flags\n"}; + char *hip[2] = { + "\n{Hshow ip} [{Udigit}|{Hall}]\n" + " Show IPv4 details for VPC {Udigit} (default this VPC) or all VPCs, including\n" + " VPC Name, IP address, mask, gateway, DNS, MAC, lport, rhost:rport and MTU.\n", + "\n{Hshow ip} [{Hall}]\n" + " Show IPv4 details for including:\n" + " VPC Name, IP address, mask, gateway, DNS, MAC, lport, rhost:rport and MTU.\n" + " (reduced view in tablular format if 'all' option used)\n"}; + char *hip6[2] = { + "\n{Hshow ipv6} [{Udigit}|{Hall}]\n" + " Show IPv6 details for VPC {Udigit} (default this VPC) or all VPCs, including\n" + " VPC Name, IPv6 addresses/mask, router link-layer, MAC, lport, rhost:rport and\n" + " MTU\n", + "\n{Hshow ipv6} [{Hall}]\n" + " Show IPv6 details, including:\n" + " VPC Name, IPv6 addresses/mask, router link-layer, MAC, lport, rhost:rport and\n" + " MTU (reduced view in tablular format if 'all' option used)\n"}; + char *hh[3] = { + "\n{Hshow} [{UARG}]\n" + " Show information for ARG\n" + " ARG:\n", + " {Harp} [{Udigit}|{Hall}] Show arp table for VPC {Udigit} or all VPCs\n" + " {Hdump} [{Udigit}|{Hall}] Show dump flags for VPC {Udigit} or all VPCs\n" + " {Hecho} Show the status of the echo flag. See {Hset echo ?}\n" + " {Hhistory} List the command history\n" + " {Hip} [{Udigit}|{Hall}] Show IPv4 details for VPC {Udigit} or all VPCs\n" + " shows VPC Name, IP address, mask, gateway, DNS, MAC, \n" + " lport, rhost:rport and MTU\n" + " {Hipv6} [{Udigit}|{Hall}] Show IPv6 details for VPC {Udigit} or all VPCs\n" + " shows VPC Name, IPv6 addresses/mask, gateway, MAC,\n" + " lport, rhost:rport and MTU\n" + " {Hversion} Show the version information\n\n" + " Notes: \n" + " 1. If no parameter is given, the key information of all VPCs will be displayed\n" + " 2. If no parameter is given for {Harp}/{Hdump}/{Hip}/{Hipv6} information for the\n" + " current VPC will be displayed.\n", + " {Harp} Show arp table\n" + " {Hdump} Show dump flags \n" + " {Hecho} Show the status of the echo flag. See {Hset echo ?}\n" + " {Hhistory} List the command history\n" + " {Hip} [{Hall}] Show IPv4 details\n" + " Shows VPC Name, IP address, mask, gateway, DNS, MAC, \n" + " lport, rhost:rport and MTU\n" + " {Hipv6} [{Hall}] Show IPv6 details\n" + " Shows VPC Name, IPv6 addresses/mask, gateway, MAC,\n" + " lport, rhost:rport and MTU\n" + " {Hversion} Show the version information\n\n" + " Notes: \n" + " 1. If no parameter is given, the key information of the current VPC will be\n" + " displayed\n" + " 2. If 'all' parameter is given for {Hip}/{Hipv6} a reduced view in tablular\n" + " format will be displayed.\n"}; + if (argc == 3 && !strncmp(argv[1], "arp", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mshow arp [|all]\033[0m\n" - " Show arp table for VPC (default this VPC) or all VPCs\n"); + esc_prn("%s", num_pths > 1 ? harp[0] : harp[1]); + return 1; } if (argc == 3 && !strncmp(argv[1], "dump", strlen(argv[1])) && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mshow dump [|all]\033[0m\n" - " Show dump flags for VPC (default this VPC) or all VPCs\n"); + esc_prn("%s", num_pths > 1 ? hdump[0] : hdump[1]); + return 1; } if (argc == 3 && !strcmp(argv[1], "ip") && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mshow ip [|all]\033[0m\n" - " Show IPv4 details for VPC (default this VPC) or all VPCs, including\n" - " VPC Name, IP address, mask, gateway, DNS, MAC, lport, rhost:rport and MTU.\n"); + esc_prn("%s", num_pths > 1 ? hip[0] : hip[1]); + return 1; } if (argc == 3 && !strcmp(argv[1], "ipv6") && (!strcmp(argv[2], "?") || !strncmp(argv[2], "help", strlen(argv[2])))) { - printf( "\n\033[1mshow ipv6 [|all]\033[0m\n" - " Show IPv6 details for VPC (default this VPC) or all VPCs, including\n" - " VPC Name, IP address, mask, gateway, DNS, MAC, lport, rhost:rport and MTU\n"); + esc_prn("%s", num_pths > 1 ? hip6[0] : hip6[1]); + return 1; } if (argc > 1 && (!strcmp(argv[argc - 1], "?") || !strncmp(argv[argc - 1], "help", strlen(argv[argc - 1])))) { - printf( "\n\033[1mshow [arp [|all]|dump|echo|history|ip [|all]|ipv6 [|all]]\033[0m\n" - " arp [|all] Show arp table for VPC or all VPCs\n" - " dump [|all] Show dump flags for VPC or all VPCs\n" - " echo Show the status of the echo flag. see \033[1mset echo\033[0m\n" - " history List the command history\n" - " ip [|all] Show IPv4 details for VPC or all VPCs\n" - " Shows VPC Name, IP address, mask, gateway, DNS, MAC, \n" - " lport, rhost:rport and MTU\n" - " ipv6 [|all] Show IPv6 details for VPC or all VPCs\n" - " Shows VPC Name, IPv6 addresses/mask, gateway, MAC,\n" - " lport, rhost:rport and MTU\n" - " version Show the version information\n\n" - " Notes: if and are missing, \033[1marp\033[0m/\033[1mdump\033[0m/\033[1mip\033[0m/\033[1mipv6\033[0m will display\n" - " the current VPC.\n"); + esc_prn("%s", hh[0]); + esc_prn("%s", num_pths > 1 ? hh[1] : hh[2]); + return 1; } - return 0; + return 0; } int help_version(int argc, char **argv) @@ -312,54 +403,64 @@ int help_sleep(int argc, char **argv) { - printf( "\n\033[1msleep [] [text]\033[0m\n" - " Print and pause execution of script for .\n" - " If =0 or missing, pause until a key is pressed. \n" - " See \033[1mload [filename]\033[0m\n"); + esc_prn("\n{Hsleep} [{Useconds}] [{Utext}]\n" + " Print {Utext} and pause execution of script for {Utime} seconds.\n" + " If {Useconds} is zero or missing, pause until a key is pressed. \n" + " Default text when no parameters given: 'Press any key to continue'\n" + " See {Hload} [{Ufilename}]\n"); + return 1; } int help_help(int argc, char **argv) { - printf( "\n\033[1m%s\033[0m, Print help. Use command \033[1m?\033[0m for more help\n", argv[0]); + esc_prn("\n{H%s}, Print help. Use {UCOMMAND} {H?} or " + "{HCOMMAND} {UARG} {H?} for more help\n", argv[0]); return 1; } int help_shut(int argc, char **argv) { - printf( "\n\033[1m%s\033[0m, shutdown the process (only in daemon mode)\n", argv[0]); + esc_prn("\n{H%s}, shutdown the process (only in daemon mode)\n", argv[0]); return 1; } int run_help(int argc, char **argv) { - printf ("\n" - "? Print help\n" - "! [command [args]] Invoke an OS command with the 'args' as its arguments\n" - " Switch to the VPC. range 1 to 9\n" - "arp Shortcut for: \033[1mshow arp\033[0m. Show arp table\n" - "clear [arguments] Clear IPv4/IPv6, arp/neighbor cache, command history\n" - "dhcp [-options] Shortcut for: \033[1mip dhcp\033[0m. Get IPv4 address via DHCP\n" - "disconnect Exit the telnet session (daemon mode)\r\n" - "echo Display in output\n" - "help Print help\n" - "history Shortcut for: \033[1mshow history\033[0m. List the command history\n" - "ip [arguments] Configure VPC's IP settings\n" - "load [filename] Load the configuration/script from the file [filename] (startup.vpc is the default filename).\n" - "ping [-options] Ping the network with ICMP (default) or TCP/UDP\n" - "quit Quit program\n" - "relay [arguments] Relay packets between two UDP ports\n" - "rlogin [] Telnet to host relative to HOST PC\n" - "save [filename] Save the configuration to the file [filename] (startup.vpc is the default filename).\n" - "set [arguments] Set VPC name, peer ports, dump options, echo on or off\n" - "show [arguments] Print the information of VPCs (default). Try \033[1mshow ?\033[0m\n" - "sleep [text] Print and pause the running script for \n" - "trace [-options] Print the path packets take to network \n" - "version Shortcut for: \033[1mshow version\033[0m\n\n" - "To get command syntax help, please enter '?' as an argument of the command.\n"); - return 1; + esc_prn("\n" + "{H?} Print help\n" + "{H!} {UCOMMAND} [{UARG} ...] Invoke an OS {UCOMMAND} with optional {UARG(s)}\n"); + + if (num_pths > 1) { + esc_prn("{Udigit} Switch to the VPC{Udigit}. " + "{Udigit} range 1 to %d\n", num_pths); + } + + esc_prn("{Harp} %s Shortcut for: {Hshow arp}. " + "Show arp table\n", (num_pths > 1) ? "[{Udigit}|{Hall}]" : " "); + esc_prn("{Hclear} {UARG} Clear IPv4/IPv6, arp/neighbor cache, command history\n" + "{Hdhcp} [{UOPTION}] Shortcut for: {Hip dhcp}. Get IPv4 address via DHCP\n" + "{Hdisconnect} Exit the telnet session (daemon mode)\r\n" + "{Hecho} {UTEXT} Display {UTEXT} in output. See also {Hset echo ?}\n" + "{Hhelp} Print help\n" + "{Hhistory} Shortcut for: {Hshow history}. List the command history\n" + "{Hip} {UARG} ... [{UOPTION}] Configure the current VPC's IP settings. See {Hip ?}\n" + "{Hload} [{UFILENAME}] Load the configuration/script from the file {UFILENAME}\n" + "{Hping} {UHOST} [{UOPTION} ...] Ping {UHOST} with ICMP (default) or TCP/UDP. See {Hping ?}\n" + "{Hquit} Quit program\n" + "{Hrelay} {UARG} ... Configure packet relay between UDP ports. See {Hrelay ?}\n" + "{Hrlogin} [{Uip}] {Uport} Telnet to {Uport} on host at {Uip} (relative to host PC)\n" + "{Hsave} [{UFILENAME}] Save the configuration to the file {UFILENAME}\n" + "{Hset} {UARG} ... Set VPC name and other options. Try {Hset ?}\n" + "{Hshow} [{UARG} ...] Print the information of VPCs (default). See {Hshow ?}\n" + "{Hsleep} [{Useconds}] [TEXT] Print TEXT and pause running script for {Useconds}\n" + "{Htrace} {UHOST} [{UOPTION} ...] Print the path packets take to network {UHOST}\n" + "{Hversion} Shortcut for: {Hshow version}\n\n" + "To get command syntax help, please enter '{H?}' as an argument of the command.\n"); + + return 1; } /* end of file */ diff -Nru vpcs-0.5b2/src/help.h vpcs-0.6.1/src/help.h --- vpcs-0.5b2/src/help.h 2014-06-30 02:53:02.000000000 +0000 +++ vpcs-0.6.1/src/help.h 2016-10-14 08:55:04.000000000 +0000 @@ -48,6 +48,8 @@ int help_sleep(int argc, char **argv); int help_version(int argc, char **argv); +#define EHL(x) "\033[1m"x"\033[0m" +#define EUL(x) "\033[4m"x"\033[0m" #endif /* end of file */ diff -Nru vpcs-0.5b2/src/ip.c vpcs-0.6.1/src/ip.c --- vpcs-0.5b2/src/ip.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/ip.c 2016-10-14 08:55:06.000000000 +0000 @@ -247,7 +247,6 @@ "ICMPv6 neighbor solicitation", "ICMPv6 neighbor advertisement", "ICMPv6 redirect"}; - const char *empty = ""; diff -Nru vpcs-0.5b2/src/ip.h vpcs-0.6.1/src/ip.h --- vpcs-0.5b2/src/ip.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/ip.h 2016-10-14 08:55:06.000000000 +0000 @@ -68,6 +68,9 @@ u_short len; /* ip packet length */ u_short id; /* identification */ u_short frag; /* fragment offset field */ +#define IP_DF 0x4000 +#define IP_MF 0x2000 +#define IP_OFFMASK 0x1fff u_char ttl; /* time to live */ #define TTL 64 u_char proto; /* protocol */ @@ -77,9 +80,6 @@ }; typedef struct iphdr iphdr; -#define IPDF 0x4000 -#define IPMF 0x2000 - #ifndef IPPROTO_ICMP #define IPPROTO_ICMP 1 #endif @@ -99,6 +99,9 @@ #ifndef ICMP_UNREACH_PORT #define ICMP_UNREACH_PORT 3 #endif +#ifndef ICMP_UNREACH_NEEDFRAG +#define ICMP_UNREACH_NEEDFRAG 4 +#endif #ifndef ICMP_REDIRECT #define ICMP_REDIRECT 5 @@ -407,6 +410,7 @@ #define DMP_RAW 2 #define DMP_DETAIL 4 #define DMP_ALL 0x80 +#define DMP_FILE 0x1000 struct packet; /* defined in queue.h */ diff -Nru vpcs-0.5b2/src/Makefile.fbsd vpcs-0.6.1/src/Makefile.fbsd --- vpcs-0.5b2/src/Makefile.fbsd 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/Makefile.fbsd 2016-10-14 08:55:06.000000000 +0000 @@ -28,6 +28,7 @@ relay.o \ hv.o +debug: all all: vpcs vpcs: $(OBJS) diff -Nru vpcs-0.5b2/src/packets6.c vpcs-0.6.1/src/packets6.c --- vpcs-0.5b2/src/packets6.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/packets6.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -144,6 +144,7 @@ icmp->cksum = cksum_fixup(icmp->cksum, ICMP6_ECHO_REQUEST, ICMP6_ECHO_REPLY, 0); swap_ehead(m->data); + fix_dmac6(pc, m); enq(&pc->oq, m); return PKT_ENQ; @@ -227,7 +228,7 @@ pc->ip6.type = IP6TYPE_EUI64; if (mtu != 0) - pc->ip6.mtu = mtu; + pc->mtu = mtu; mtu = 0; } if (sameNet6((char *)pc->ip6.ip.addr8, p + 16, pc->ip6.cidr)) { @@ -266,8 +267,10 @@ p = icmp6Reply(m); else p = udp6Reply(m); - if (p != NULL) + if (p != NULL) { + fix_dmac6(pc, p); enq(&pc->oq, p); + } } /* anyway tell caller to drop this packet */ @@ -891,4 +894,16 @@ return i; } +void fix_dmac6(pcs *pc, struct packet *m) +{ + u_char *p; + ethdr *eh; + + eh = (ethdr *)(m->data); + + p = nbDiscovery(pc, &pc->mscb.dip6); + if (p) + memcpy(eh->dst, p, 6); +} + /* end of file */ diff -Nru vpcs-0.5b2/src/packets6.h vpcs-0.6.1/src/packets6.h --- vpcs-0.5b2/src/packets6.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/packets6.h 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,8 @@ u_char *nbDiscovery(pcs *pc, ip6 *dst); struct packet* nbr_sol(pcs *pc); +void fix_dmac6(pcs *pc, struct packet *m); + #endif /* end of file */ diff -Nru vpcs-0.5b2/src/packets.c vpcs-0.6.1/src/packets.c --- vpcs-0.5b2/src/packets.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/packets.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,15 +36,25 @@ #include "vpcs.h" #include "utils.h" +#define IPFRG_MAXHASH (1 << 10) +#define IPFRG_HASHMASK (IPFRG_MAXHASH - 1) +#define IPFRG_HASH(x,y) \ + (((((x) & 0xF) | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPFRG_HASHMASK) + static struct packet *arp(pcs *pc, u_int dip); - static struct packet *udpReply(struct packet *m0); -static struct packet *icmpReply(struct packet *m0, char icmptype); +static struct packet *icmpReply(struct packet *m0, char icmptype, char icmpcode); static void save_eaddr(pcs *pc, u_int addr, u_char *mac); extern int upv6(pcs *pc, struct packet *m); extern int tcp(pcs *pc, struct packet *m); +static void free_ipfrag(struct ipfrag_head *head, struct ipfrag *fp); +static void free_packet(struct packet *m); +static struct ipfrag *new_ipfrag(struct packet *m, iphdr *ip); +static struct packet *defrag_pkt(struct packet **); + extern u_int time_tick; +static struct ipfrag_head ipfrag_hash[IPFRG_MAXHASH]; /* * ipv4 stack @@ -53,8 +63,10 @@ * PKT_ENQ, in out queue * PKT_DROP, drop the packet */ -int upv4(pcs *pc, struct packet *m) +int upv4(pcs *pc, struct packet **m0) { + struct packet *m = *m0; + struct packet *p = NULL; ethdr *eh = (ethdr *)(m->data); u_int *si, *di; @@ -62,29 +74,58 @@ return upv6(pc, m); /* not ipv4 or arp */ - if ((eh->type != htons(ETHERTYPE_IP)) && (eh->type != htons(ETHERTYPE_ARP))) + if ((eh->type != htons(ETHERTYPE_IP)) && + (eh->type != htons(ETHERTYPE_ARP))) return PKT_DROP; if (etherIsMulticast(eh->src)) return PKT_DROP; if (memcmp(eh->dst, pc->ip4.mac, ETH_ALEN) == 0 && - ((u_short*)m->data)[6] == htons(ETHERTYPE_IP)) { + ((u_short*)m->data)[6] == htons(ETHERTYPE_IP)) { iphdr *ip = (iphdr *)(eh + 1); - + + if (ntohs(ip->len) > pc->mtu) { + p = icmpReply(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG); + if (p) { + fix_dmac(pc, p); + if (pc->ip4.flags & IPF_FRAG) { + p = ipfrag(p, pc->mtu); + } + enq(&pc->oq, p); + } + return PKT_ENQ; + } + + if (ntohs(ip->frag) & (IP_MF | IP_OFFMASK)) { + m = ipreass(m); + if (m == NULL) + return PKT_ENQ; + else + *m0 = m; + ip = (iphdr *)(m->data + sizeof(ethdr)); + } + /* ping me, reply */ if (ip->proto == IPPROTO_ICMP) { icmphdr *icmp = (icmphdr *)(ip + 1); - - if (icmp->type == ICMP_ECHO) { - struct packet *p = icmpReply(m, ICMP_ECHOREPLY); - if (p != NULL) - enq(&pc->oq, p); - return PKT_ENQ; - } + if (ip->dip != pc->ip4.ip) + return PKT_DROP; + /* other type will be sent to application */ - + if (icmp->type != ICMP_ECHO) + return PKT_UP; + + p = icmpReply(m, ICMP_ECHOREPLY, 0); + if (p != NULL) { + fix_dmac(pc, p); + if (pc->ip4.flags & IPF_FRAG) { + p = ipfrag(p, pc->mtu); + } + enq(&pc->oq, p); + } + return PKT_ENQ; } else if (ip->proto == IPPROTO_UDP) { udpiphdr *ui; char *data = NULL; @@ -97,6 +138,9 @@ if (ui->ui_sport == htons(67) && ui->ui_dport == htons(68)) return PKT_UP; + if (ip->dip != pc->ip4.ip) + return PKT_DROP; + /* dns response */ if (ui->ui_sport == htons(53)) return PKT_UP; @@ -109,15 +153,23 @@ else { struct packet *p; if (ip->ttl == 1) - p = icmpReply(m, ICMP_UNREACH); + p = icmpReply(m, ICMP_UNREACH, ICMP_UNREACH_PORT); else p = udpReply(m); - if (p != NULL) + + if (p != NULL) { + fix_dmac(pc, p); + if (pc->ip4.flags & IPF_FRAG) { + p = ipfrag(p, pc->mtu); + } enq(&pc->oq, p); + } } /* anyway tell caller to drop this packet */ return PKT_DROP; } else if (ip->proto == IPPROTO_TCP) { + if (ip->dip != pc->ip4.ip) + return PKT_DROP; return tcp(pc, m); } @@ -161,6 +213,7 @@ { ethdr *eh; iphdr *ip; + int n; eh = (ethdr *)(m->data); ip = (iphdr *)(eh + 1); @@ -194,15 +247,18 @@ if (ip->sip != sesscb->dip) return 0; + sesscb->rdsize = ntohs(ip->len); + if (ip->proto == IPPROTO_ICMP && sesscb->proto == IPPROTO_ICMP) { icmphdr *icmp = (icmphdr *)(ip + 1); sesscb->icmptype = icmp->type; sesscb->icmpcode = icmp->code; sesscb->rttl = ip->ttl; sesscb->rdip = ip->sip; - if (ntohs(icmp->seq) == sesscb->sn) { + + if (ntohs(icmp->seq) == sesscb->sn) return IPPROTO_ICMP; - } + return 0; } @@ -225,17 +281,17 @@ sesscb->rack = ntohl(ti->ti_ack); sesscb->rflags = ti->ti_flags; sesscb->rttl = ip->ttl; - sesscb->rdsize = ntohs(ip->len) - sizeof(iphdr) - (ti->ti_off << 2); sesscb->data = NULL; - + + n = sesscb->rdsize - (ip->ihl << 2) - (ti->ti_off << 2); /* try to get MSS from options */ if (sesscb->flags == TH_SYN && sesscb->rflags == (TH_SYN | TH_ACK) && - sesscb->rdsize > 0) { + n > 0) { int i = 0; while (data[i] == 0x1 && i < sesscb->rdsize) i++; - for (;i < sesscb->rdsize;) { + for (;i < n;) { if (data[i] == TCPOPT_MAXSEG && data[i + 1] == TCPOLEN_MAXSEG) { sesscb->rmss = (data[i + 2] << 8) + data[i + 3]; @@ -296,12 +352,10 @@ { ethdr *eh; iphdr *ip; - int i; struct packet *m; int dlen = 0; /* the size of payload */ int hdr_len = 0; - int frag = 0; char b[9]; dlen = sesscb->dsize; @@ -330,10 +384,7 @@ hdr_len = sizeof(iphdr) + sizeof(tcphdr); break; } - - if (dlen > sesscb->mtu - hdr_len) - dlen = sesscb->mtu - hdr_len; - + m = new_pkt(sizeof(ethdr) + hdr_len + dlen); if (m == NULL) @@ -346,10 +397,8 @@ ip->ihl = sizeof *ip >> 2; ip->len = htons(hdr_len + dlen); ip->id = htons(sesscb->ipid++); - if (!frag) - ip->frag = htons(0x4000); - else - ip->frag = htons(0x2000); + if (!sesscb->frag) + ip->frag = htons(IP_DF); ip->ttl = sesscb->ttl; ip->proto = sesscb->proto; ip->sip = sesscb->sip; @@ -473,11 +522,16 @@ ti->ti_sum = cksum((u_short*)ti, hdr_len + dlen); bcopy(b, ((struct ipovly *)ip)->ih_x1, 9); } - ip->cksum = 0; - ip->cksum = cksum((u_short *)ip, sizeof(iphdr)); encap_ehead(m->data, sesscb->smac, sesscb->dmac, ETHERTYPE_IP); + /* maybe fragmentation failed, let's do cksum first */ + ip->cksum = 0; + ip->cksum = cksum((u_short *)ip, sizeof(iphdr)); + + if ((sesscb->frag & IPF_FRAG) == IPF_FRAG) + ipfrag(m, sesscb->mtu); + return m; } @@ -510,7 +564,6 @@ memcpy(ah->dea, broadcast, ETH_ALEN); memcpy(ah->sea, pc->ip4.mac, ETH_ALEN); - encap_ehead(m->data, pc->ip4.mac, broadcast, ETHERTYPE_ARP); return m; @@ -548,7 +601,7 @@ return m; } -struct packet *icmpReply(struct packet *m0, char icmptype) +struct packet *icmpReply(struct packet *m0, char icmptype, char icmpcode) { struct packet *m = NULL; ethdr *eh = NULL; @@ -570,17 +623,17 @@ icmp->type = ICMP_ECHOREPLY; icmp->cksum = cksum_fixup(icmp->cksum, ICMP_ECHO, ICMP_ECHOREPLY, 0); - + ip->dip ^= ip->sip; ip->sip ^= ip->dip; ip->dip ^= ip->sip; ip->ttl = TTL; - + ip->cksum = cksum_fixup(cksum_fixup(cksum_fixup(ip->cksum, old_ttl, ip->ttl, 0), ICMP_ECHO, ICMP_ECHOREPLY, 0), old_sum, icmp->cksum, 0); - + swap_ehead(m->data); return m; @@ -589,15 +642,15 @@ if (icmptype == ICMP_UNREACH) { int len, len0; - eh = (ethdr *)(m0->data); + eh = (ethdr *)(m0->data); ip = (iphdr *)(eh + 1); - len0 = ntohs(ip->len); - if (len0 > 44) - len0 = 44; - - len = sizeof(ethdr) + sizeof(iphdr) + sizeof(icmphdr) + len0; - + len0 = ntohs(ip->len); + if (len0 > 44) + len0 = 44; + + len = sizeof(ethdr) + sizeof(iphdr) + sizeof(icmphdr) + len0; + m = new_pkt(len); if (m == NULL) return NULL; @@ -624,8 +677,8 @@ icmp->seq = htons(1); icmp->cksum = 0; - icmp->type = ICMP_UNREACH; - icmp->code = ICMP_UNREACH_PORT; + icmp->type = icmptype; + icmp->code = icmpcode; icmp->id = time(0) & 0xffff; icmp->cksum = cksum((unsigned short *) (icmp), sizeof(icmphdr) + len0); @@ -666,6 +719,319 @@ } } +void +fix_dmac(pcs *pc, struct packet *m) +{ + ethdr *eh = NULL; + iphdr *ip = NULL; + u_char mac[6]; + + eh = (ethdr *)(m->data); + ip = (iphdr *)(eh + 1); + + if (sameNet(ip->dip, pc->ip4.ip, pc->ip4.cidr)) + return; + + if (arpResolve(pc, pc->ip4.gw, mac)) + memcpy(eh->dst, mac, sizeof(mac)); +} + +struct packet * +ipfrag(struct packet *m0, int mtu) +{ + struct packet *m = NULL, *mh = NULL; + iphdr *ip = NULL, *ip0 = NULL; + int hlen, len, off, elen, flen, last; + int nfrags; + + elen = sizeof(ethdr) + sizeof(iphdr); + + ip0 = (iphdr *)(m0->data + sizeof(ethdr)); + if (ntohs(ip0->len) <= mtu) + return m0; + + hlen = ip0->ihl << 2; + len = (mtu - hlen) & ~7; /* payload in fragment */ + ip0->len = ntohs(ip0->len); + + /* too small, let it alone */ + if (len < 8) + return m0; + + flen = len; + off = hlen + len; + + mh = m0; + last = 0; + for (nfrags = 1; off < ip0->len; off += len, nfrags++) { + if (off + len >= ip0->len) { + last = 1; + m = new_pkt(elen + ip0->len - off); + } else + m = new_pkt(elen + len); + + if (m == NULL) + goto ipfrag_err; + + /* ether and ip head */ + memcpy(m->data, m0->data, elen); + memcpy(m->data + elen, m0->data + sizeof(ethdr) + off, len); + ip = (iphdr *)(m->data + sizeof(ethdr)); + ip->frag = ((off -hlen) >> 3); + + if (!last) { + ip->frag |= IP_MF; + ip->len = htons(len + sizeof(iphdr)); + } else + ip->len = htons(sizeof(iphdr) + ip0->len - off); + ip->frag = htons(ip->frag); + ip->cksum = 0; + ip->cksum = cksum((u_short *)ip, sizeof(iphdr)); + m->next = NULL; + mh->next = m; + mh = m; + } + m0->len = elen + flen; + ip0->len = htons(len + sizeof(iphdr)); + ip0->frag = htons(IP_MF); + ip0->cksum = 0; + ip0->cksum = cksum((u_short *)ip0, sizeof(iphdr)); + + return m0; + +ipfrag_err: + for (m = mh->next; m; m = mh) { + mh = m->next; + del_pkt(m); + } + + return m0; +} + +/* + * return NULL, the packet is a piece, expired, or invalid. + * return packet, all of pieces have been arrived and reassembled. + */ +struct packet * +ipreass(struct packet *m) +{ + ethdr *eh = (ethdr *)(m->data); + iphdr *ip = (iphdr *)(eh + 1); + iphdr *ip0; + struct ipfrag *fp = NULL; + struct ipfrag_head *qh; + struct packet *m0 = NULL, *m2 = NULL; + u_short hash, off, off0; + int next; + + + hash = IPFRG_HASH(ip->sip, ip->id); + qh = &ipfrag_hash[hash]; + + pthread_mutex_lock(&(qh->locker)); + + ip->frag = ntohs(ip->frag); + for (fp = qh->head; fp; fp = fp->next) { + if (time_tick - fp->expired > 30) { + free_packet(fp->m); + free_ipfrag(qh, fp); + continue; + } + + if (ip->id != fp->id || + ip->sip != fp->sip || + ip->dip != fp->dip || + ip->proto != fp->proto) + continue; + + /* a fragment is existed */ + if ((ip->frag & IP_MF) == IP_MF) + fp->flags |= FF_HEAD; + else if ((ip->frag & (~IP_OFFMASK)) == 0) + fp->flags |= FF_TAIL; + + off = ip->frag << 3; + if (off == 0 && (ip->frag & IP_MF)) { + if (!ip->len || (ip->len & 0x7) != 0) { + del_pkt(m); + free_packet(fp->m); + free_ipfrag(qh, fp); + goto ret_null; + } + m->next = fp->m; + fp->m = m; + } else { + /* Find a segment, insertion sort on singly linked list + */ + m2 = NULL; + for (m0 = fp->m; m0; m2 = m0, m0 = m0->next) { + ip0 = (iphdr *)(m0->data + sizeof(ethdr)); + off0 = ip0->frag << 3; + if (off0 > off) + break; + } + if (m2) { + m->next = m2->next; + m2->next = m; + } else { + m->next = fp->m; + fp->m = m; + } + } + fp->nfrags++; + /* too many fragments */ + if (fp->nfrags > 16) { + free_packet(fp->m); + free_ipfrag(qh, fp); + goto ret_null; + } + /* the head and tail are arrived, scan the chain + * Note: overlap is invalid here. + */ + if (fp->flags == (FF_TAIL | FF_HEAD)) { + for (next = 0, m0 = fp->m; m0; m0 = m0->next) { + ip0 = (iphdr *)(m0->data + sizeof(ethdr)); + off0 = ip0->frag << 3; + if (next < off0) + goto ret_null; + /* the last fragment */ + if ((ip0->len & 0x7) != 0) { + m = fp->m; + free_ipfrag(qh, fp); + /* copy to single packet buffer + * free the old buffer + */ + m = defrag_pkt(&m); + goto ret; + } + next += ip0->len; + } + } + goto ret_null; + } + /* new fragment */ + fp = new_ipfrag(m, ip); + if (qh->head == NULL) { + qh->head = fp; + qh->tail = fp; + } else { + fp->prev = qh->tail; + qh->tail->next = fp; + qh->tail = fp; + } + +ret_null: + pthread_mutex_unlock(&(qh->locker)); + return NULL; + +ret: + pthread_mutex_unlock(&(qh->locker)); + return m; +} + +static struct packet *defrag_pkt(struct packet **m0) +{ + struct packet *m, *mh, *m2; + iphdr *ip; + int len; + int elen; + int off; + + mh = *m0; + len = 0; + while (mh) { + ip = (iphdr *)(mh->data + sizeof(ethdr)); + + len += ntohs(ip->len) - sizeof(iphdr); + mh = mh->next; + } + m = new_pkt(len + sizeof(iphdr) + sizeof(ethdr)); + if (m == NULL) + return mh; + + mh = *m0; + memcpy(m->data, mh->data, mh->len); + ip = (iphdr *)(m->data + sizeof(ethdr)); + ip->len = ntohs(len + sizeof(iphdr)); + off = mh->len; + elen = sizeof(ethdr) + sizeof(iphdr); + m2 = mh; + mh = mh->next; + del_pkt(m2); + while (mh) { + len = mh->len - elen; + memcpy(m->data + off, mh->data + elen, len); + off += len; + m2 = mh; + mh = mh->next; + del_pkt(m2); + } + ip->frag = 0; + ip->cksum = 0; + ip->cksum = cksum((u_short *)ip, sizeof(iphdr)); + + return m; +} + +static void +free_packet(struct packet *m) +{ + struct packet *m0; + + while (m) { + m0 = m->next; + del_pkt(m); + m = m0; + } +} + +static void +free_ipfrag(struct ipfrag_head *qh, struct ipfrag *fp) +{ + if (fp == qh->head) + qh->head = fp->next; + else + fp->prev->next = fp->next; + free(fp); +} + +static struct ipfrag * +new_ipfrag(struct packet *m, iphdr *ip) +{ + struct ipfrag *fp; + + fp = (struct ipfrag *)malloc(sizeof(struct ipfrag)); + if (!fp) + return NULL; + + memset(fp, 0, sizeof(struct ipfrag)); + + fp->expired = time_tick; + fp->nfrags = 1; + fp->proto = ip->proto; + fp->id = ip->id; + fp->sip = ip->sip; + fp->dip = ip->dip; + fp->m = m; + m->next = NULL; + if ((ip->frag & IP_MF) == IP_MF) + fp->flags = FF_HEAD; + else if ((ip->frag & (~IP_OFFMASK)) == 0) + fp->flags = FF_TAIL; + + return fp; +} + +void init_ipfrag(void) +{ + int i; + + memset(ipfrag_hash, 0, sizeof(struct ipfrag_head) * IPFRG_MAXHASH); + for (i = 0; i < IPFRG_MAXHASH; i++) + pthread_mutex_init(&(ipfrag_hash[i].locker), NULL); + +} + #if 0 static void xxpreh(char *e, int c) { diff -Nru vpcs-0.5b2/src/packets.h vpcs-0.6.1/src/packets.h --- vpcs-0.5b2/src/packets.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/packets.h 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,11 +30,39 @@ #include "vpcs.h" #include "ip.h" +struct ipfrag { + struct ipfrag *prev; + struct ipfrag *next; + u_int expired; + u_int flags:4, /* first and last fragments */ + nfrags:4; /* count of fragments */ +#define FF_HEAD 1 +#define FF_TAIL 2 + u_char proto; /* protocol of this fragment */ + u_short id; /* sequence id for reassembly */ + u_int sip; + u_int dip; + struct packet *m; /* to ip headers of fragments */ +}; + +struct ipfrag_head { + struct ipfrag *head; + struct ipfrag *tail; + pthread_mutex_t locker; +}; + +#define PAYLOAD56 56 + +void init_ipfrag(void); +struct packet *ipreass(struct packet *m); +struct packet *ipfrag(struct packet *m0, int mtu); + struct packet *packet(sesscb *sesscb); -int upv4(pcs *pc, struct packet *pkt); +int upv4(pcs *pc, struct packet **pkt); int response(struct packet *pkt, sesscb *sesscb); int arpResolve(pcs *pc, u_int ip, u_char *dmac); int host2ip(pcs *pc, const char *name, u_int *ip); +void fix_dmac(pcs *pc, struct packet *m); #endif diff -Nru vpcs-0.5b2/src/queue.c vpcs-0.6.1/src/queue.c --- vpcs-0.5b2/src/queue.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/queue.c 2016-10-14 08:55:06.000000000 +0000 @@ -89,7 +89,6 @@ lock_q(pq); - m->next = NULL; gettimeofday(&(m->ts), (void*)0); if (pq->q == NULL) @@ -97,11 +96,12 @@ else { q = pq->q; while (q->next != NULL) q = q->next; - q->next = m; + q->next = m; + } + while (m) { + pq->size ++; + m = m->next; } - - pq->size ++; - pthread_cond_signal(&(pq->cond)); ulock_q(pq); diff -Nru vpcs-0.5b2/src/readline.c vpcs-0.6.1/src/readline.c --- vpcs-0.5b2/src/readline.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/readline.c 2016-10-14 08:55:06.000000000 +0000 @@ -236,9 +236,9 @@ flags = 1; ihist = rls->hist_total; if (rls->pos != 0) - strcpy(rls->history[rls->maxhistnum], rls->kbuffer); + strcpy(rls->history[rls->maxhistnum - 1], rls->kbuffer); else - rls->history[rls->maxhistnum][0] = '\0'; + rls->history[rls->maxhistnum - 1][0] = '\0'; } if (ihist == 0) continue; @@ -472,7 +472,7 @@ int len, i; /* no pattern */ - len = strlen(rls->history[rls->maxhistnum]); + len = strlen(rls->history[rls->maxhistnum - 1]); if (len == 0) { if (start >= 0) { start++; @@ -486,14 +486,14 @@ if (start >= 0) { start++; for (i = start; i < rls->hist_total; i++) - if (!strncmp(rls->history[rls->maxhistnum], rls->history[i], len)) + if (!strncmp(rls->history[rls->maxhistnum - 1], rls->history[i], len)) return i; return -1; } else { start = 0 - start; start --; for (i = start; i >= 0; i--) - if (!strncmp(rls->history[rls->maxhistnum], rls->history[i], len)) + if (!strncmp(rls->history[rls->maxhistnum - 1], rls->history[i], len)) return i; return -1; } diff -Nru vpcs-0.5b2/src/relay.c vpcs-0.6.1/src/relay.c --- vpcs-0.5b2/src/relay.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/relay.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ #include "vpcs.h" #include "dev.h" #include "relay.h" +#include "dump.h" struct node { u_int32_t ip; @@ -49,6 +50,8 @@ static struct peerlist *peerlist = NULL; static int relay_fd = 0; static int relay_port = 0; +static FILE *relay_dumpfile = NULL; +static int relaydump = 0; int run_relay(int argc, char **argv) { @@ -59,6 +62,25 @@ char *p; int i, j; + if (argc == 3 && !strcmp(argv[1], "dump")) { + if (!strcasecmp(argv[2], "on")) + relaydump = 1; + else if (!strcasecmp(argv[2], "off")) + relaydump = 0; + if (relaydump) + printf("dump on\n"); + else + printf("dump off\n"); + return 0; + } + + if (argc == 2 && !strcmp(argv[1], "dump")) { + if (relaydump) + printf("dump on\n"); + else + printf("dump off\n"); + return 0; + } if (argc == 3 && !strcmp(argv[1], "port")) { port = atoi(argv[2]); if (port > 1024 && port < 65534) @@ -147,19 +169,19 @@ (peerhost->nodea.port == peer.nodea.port)) || ((peerhost->nodeb.ip == peer.nodea.ip) && (peerhost->nodeb.port == peer.nodea.port))) { - in.s_addr = peer.nodea.ip; - port = peer.nodea.port; - j = 1; - break; + in.s_addr = peer.nodea.ip; + port = peer.nodea.port; + j = 1; + break; } if (((peerhost->nodea.ip == peer.nodeb.ip) && (peerhost->nodea.port == peer.nodeb.port)) || ((peerhost->nodeb.ip == peer.nodeb.ip) && (peerhost->nodeb.port == peer.nodeb.port))) { - in.s_addr = peer.nodeb.ip; - port = peer.nodeb.port; - j = 1; - break; + in.s_addr = peer.nodeb.ip; + port = peer.nodeb.port; + j = 1; + break; } peerhost = peerhost->next; } @@ -247,9 +269,9 @@ (peerhost->nodea.port == peer.nodea.port) && (peerhost->nodeb.ip == peer.nodeb.ip) && (peerhost->nodea.port == peer.nodea.port)) { - if (tpeer == peerlist) - peerlist = peerhost->next; - else + if (tpeer == peerlist) + peerlist = peerhost->next; + else tpeer->next = peerhost->next; free(peerhost); break; @@ -263,6 +285,26 @@ return 0; } +void save_relay(FILE *fp) +{ + struct peerlist *peerhost = NULL; + struct in_addr in; + + peerhost = peerlist; + if (!peerhost || peerhost->nodea.port == 0) + return; + + fprintf(fp, "relay port %d\n", relay_port); + + while (peerhost) { + in.s_addr = peerhost->nodea.ip; + fprintf(fp, "relay add %s:%d ", inet_ntoa(in), ntohs(peerhost->nodea.port)); + in.s_addr = peerhost->nodeb.ip; + fprintf(fp, "%s:%d\n", inet_ntoa(in), ntohs(peerhost->nodeb.port)); + peerhost = peerhost->next; + } +} + void *pth_relay(void *dummy) { char buf[1500]; @@ -286,7 +328,17 @@ size = sizeof(struct sockaddr_in); n = recvfrom(relay_fd, buf, len, 0, (struct sockaddr *)&peeraddr, &size); - + + if (relaydump && relay_dumpfile == NULL) + relay_dumpfile = open_dmpfile("relay"); + + if (relaydump) + dmp_buffer2file(buf, n, relay_dumpfile); + else if (relay_dumpfile) { + close_dmpfile(relay_dumpfile); + relay_dumpfile = NULL; + } + bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; peerhost = peerlist; diff -Nru vpcs-0.5b2/src/relay.h vpcs-0.6.1/src/relay.h --- vpcs-0.5b2/src/relay.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/relay.h 2016-10-14 08:55:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ int run_relay(int argc, char **argv); void *pth_relay(void *dummy); +void save_relay(FILE *fp); #endif /* end of file */ diff -Nru vpcs-0.5b2/src/tcp.c vpcs-0.6.1/src/tcp.c --- vpcs-0.5b2/src/tcp.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/tcp.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -517,9 +517,10 @@ rcb.flags = TH_RST | TH_FIN | TH_ACK; p = tcpReply(m, &rcb); - if (p != NULL) + if (p != NULL) { + fix_dmac(pc, p); enq(&pc->oq, p); - else + } else printf("reply error\n"); /* drop the request packet */ @@ -574,15 +575,21 @@ } else { cb->timeout = time_tick; p = tcpReply(m, cb); - if (p != NULL) + if (p != NULL) { + fix_dmac(pc, p); + if (pc->ip4.flags & IPF_FRAG) + p = ipfrag(p, pc->mtu); enq(&pc->oq, p); + } /* send FIN after ACK if got FIN */ if ((cb->rflags & TH_FIN) == TH_FIN && cb->flags == (TH_ACK | TH_FIN)) { p = tcpReply(m, cb); - if (p != NULL) + if (p != NULL) { + fix_dmac(pc, p); enq(&pc->oq, p); + } } } } @@ -692,9 +699,10 @@ rcb.seq = time(0); p = tcp6Reply(m, &rcb); - if (p != NULL) + if (p != NULL) { + fix_dmac6(pc, p); enq(&pc->oq, p); - else + } else printf("reply error\n"); /* drop the request packet */ @@ -748,14 +756,18 @@ } else { cb->timeout = time_tick; p = tcp6Reply(m, cb); - if (p != NULL) + if (p != NULL) { + fix_dmac6(pc, p); enq(&pc->oq, p); + } /* send FIN after ACK if got FIN */ if ((cb->rflags & TH_FIN) == TH_FIN && cb->flags == (TH_ACK | TH_FIN)) { p = tcp6Reply(m, cb); - if (p != NULL) + if (p != NULL) { + fix_dmac6(pc, p); enq(&pc->oq, p); + } } } } diff -Nru vpcs-0.5b2/src/utils.c vpcs-0.6.1/src/utils.c --- vpcs-0.5b2/src/utils.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/utils.c 2016-10-14 08:55:06.000000000 +0000 @@ -33,6 +33,8 @@ #define MAX_LEN (128) +static int search_pairs(const char *s, char **lf, char **rt); + char *getkv(char *str) { static char buf[MAX_LEN]; @@ -65,7 +67,7 @@ p = buf; es = p + strlen(buf); - while (p && p < es) { + while (p && p < es && n < max) { if (*p == '"') { q = strchr(p + 1, '"'); if (!q) @@ -161,6 +163,88 @@ return r; } + +/* Highlight {Hword} + * Underline {Uword} + * Color {Nword}, N from 1 to 9 +*/ + +void esc_prn(const char *fmt, ...) +{ + char *buf; + char *tmp; + char *p; + char *lf, *rt; + va_list ap; + + buf = malloc(4096); + if (!buf) + return; + tmp = malloc(4096); + if (!tmp) { + free(buf); + return; + } + + va_start(ap, fmt); + vsprintf(tmp, fmt, ap); + va_end(ap); + + p = tmp; + buf[0] = '\0'; + while (1) { + if (search_pairs(p, &lf, &rt) == 0) + break; + strncat(buf, p, lf - p); + lf++; + switch (*lf) { + case 'H': + strcat(buf, "\033[1m"); + break; + case 'U': + strcat(buf, "\033[4m"); + default: + break; + } + lf++; + strncat(buf, lf, rt - lf); + strcat(buf, "\033[0m"); + p = rt + 1; + } + + if (p) + strcat(buf, p); + + printf("%s", buf); + free(tmp); + free(buf); +} + +static int search_pairs(const char *s, char **lf, char **rt) +{ + char *p, *q, *r; + + p = strchr(s, '{'); + if (!p) + return 0; + if (*(p + 1)) { + q = strchr(p + 1, '}'); + r = strchr(p + 1, '{'); + if (!q) + return 0; + + /* nesting is not allowed */ + if (r && r < q) + return 0; + + *lf = p; + *rt = q; + + return 1; + } + + return 0; +} #if 0 void preh(u_char *e) { diff -Nru vpcs-0.5b2/src/utils.h vpcs-0.6.1/src/utils.h --- vpcs-0.5b2/src/utils.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/utils.h 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ #define _UTILS_H_ #include +#include char *getkv(char *str); int mkargv(char *str, char **argv, int max); @@ -37,6 +38,7 @@ int digitstring(const char *s); char *ttrim(char *s); +void esc_prn(const char *fmt, ...); int arg2int(const char* arg, int min, int max, int defalt); diff -Nru vpcs-0.5b2/src/vpcs.c vpcs-0.6.1/src/vpcs.c --- vpcs-0.5b2/src/vpcs.c 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/vpcs.c 2016-10-14 08:55:06.000000000 +0000 @@ -1,26 +1,26 @@ /* - * Copyright (c) 2007-2013, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions + * 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 + * 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 + * 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. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. **/ @@ -50,10 +50,11 @@ #include "help.h" #include "dump.h" #include "relay.h" +#include "dhcp.h" -const char *ver = "0.5b2"; +const char *ver = "0.6.1"; /* track the binary */ -static const char *ident = "$Id: vpcs.c 89 2014-06-28 16:56:30Z dlintott $"; +static const char *ident = "$Id$"; int pcid = 0; /* current vpc id */ int devtype = 0; @@ -62,7 +63,8 @@ int rport_flag = 0; u_int rhost = 0; /* remote host */ -int canEcho = 0; /* echoing on if 1, off if 0 */ +struct echoctl echoctl; +//int canEcho = 0; /* echoing on if 1, off if 0 */ int runLoad = 0; /* work with canEcho */ int runStartup = 0; /* execute startup if 1 */ @@ -87,6 +89,7 @@ static void *pth_reader(void *devid); static void *pth_writer(void *devid); static void *pth_timer_tick(void *); +static void *pth_bgjob(void *); void parse_cmd(char *cmdstr); static void sig_int(int sig); static void sig_clean(int sig); @@ -106,7 +109,7 @@ char *grpname; int (*f)(int argc, char **argv); int (*help)(int argc, char **argv); - + }; typedef struct stub cmdStub; @@ -119,7 +122,7 @@ {"echo", NULL, run_echo, NULL}, {"help", NULL, run_help, help_help}, {"history", NULL, run_hist, NULL}, - {"relay", NULL, run_relay, help_relay}, + //{"relay", NULL, run_relay, help_relay}, {"ip", NULL, run_ipconfig, help_ip}, {"load", NULL, run_load, help_load}, {"neighbor", NULL, run_nb6, NULL}, @@ -145,13 +148,14 @@ int i; char prompt[MAX_LEN]; int c; - pthread_t timer_pid, relay_pid; + pthread_t timer_pid, relay_pid, bgjob_pid; int daemon_bg = 1; char *cmd; + memset(&echoctl, 0, sizeof(struct echoctl)); rhost = inet_addr("127.0.0.1"); - - devtype = DEV_UDP; + + devtype = DEV_UDP; while ((c = getopt(argc, argv, "?c:ehm:p:r:s:t:uvFi:d:")) != -1) { switch (c) { case 'c': @@ -169,7 +173,7 @@ break; case 'r': startupfile = strdup(optarg); - break; + break; case 's': lport = arg2int(optarg, 1024, 65000, 20000); break; @@ -220,12 +224,12 @@ if (!isatty(0)) { printf("Please run in the tty\n"); exit(-1); - } + } signal(SIGINT, &sig_int); signal(SIGUSR1, &sig_clean); signal(SIGCHLD, SIG_IGN); - + welcome(); srand(time(0)); @@ -237,21 +241,22 @@ exit(-1); } strcpy(vpc[i].xname, "VPCS"); - while (vpc[i].ip4.mac[4] == 0) + while (vpc[i].ip4.mac[4] == 0) delay_ms(10); delay_ms(100); } pthread_create(&timer_pid, NULL, pth_timer_tick, (void *)0); delay_ms(100); - pthread_create(&relay_pid, NULL, pth_relay, (void *)0); + //pthread_create(&relay_pid, NULL, pth_relay, (void *)0); + pthread_create(&bgjob_pid, NULL, pth_bgjob, (void *)0); pcid = 0; delay_ms(50); autoconf6(); - + delay_ms(50); startup(); - + rls = readline_init(50, MAX_LEN); if (rls == NULL) { printf("initialize readline error\n"); @@ -281,51 +286,70 @@ char *argv[20]; int argc = 0; int rc = 0; - + char *pcmd; + int at = 0; + + if (cmdstr[0] == '#' || cmdstr[0] == ';') + return; + argc = mkargv(cmdstr, (char **)argv, 20); - + if (argc == 0) return; - if (argc == 1 && strlen(argv[0]) == 1 && num_pths > 1 && - (argv[0][0] - '0') > 0 && (argv[0][0] - '0') <= num_pths) { - if (canEcho && runLoad) - printf("%s[%d] %s\n", vpc[pcid].xname, pcid + 1, cmdstr); - pcid = argv[0][0] - '0' - 1; + if (argc == 1 && strlen(argv[0]) == 1 && num_pths >= 1 && + (argv[0][0] >= '0' && argv[0][0] <= '9')) { + if ((argv[0][0] - '0') <= num_pths) { + if (echoctl.enable && runLoad) + printf("%s[%d] %s\n", vpc[pcid].xname, + pcid + 1, cmdstr); + pcid = argv[0][0] - '0' - 1; + + } else + printf("\nOnly %d VPCs actived\n", num_pths); return; - } - + } + rc = 0; printf("\n"); - + if (!strcmp(argv[0], "srcid")) { printf("Source code ID: %s\n", ident); return; } - + if (!strncmp(argv[0], "echo", strlen(argv[0]))) { char *p = NULL; - + p = strchr(cmdstr, ' '); - + + if (echoctl.fgcolor != 0) { + if (echoctl.bgcolor != 0) + printf("\033[%d;%dm", echoctl.fgcolor, + echoctl.bgcolor); + else + printf("\033[%dm", echoctl.fgcolor); + } if (p != NULL) - printf("%s", p + 1); + printf("%s", p + 1); else { p = strchr(cmdstr, '\t'); if (p != NULL) printf("%s", p + 1); } + if (echoctl.fgcolor != 0) + printf("\033[0m"); fflush(stdout); return; } - + if (*cmdstr == '!') { char *p = NULL; if (strlen(cmdstr) > 1) { p = cmdstr + 1; while (*p== ' ' || *p == '\t') p++; - + if (*p && strcmp(p, "?")) { invoke_cmd(p); return; @@ -334,8 +358,13 @@ help_shell(0, NULL); return; } + pcmd = argv[0]; + if (*pcmd == '@') { + at = 1; + pcmd ++; + } for (ep = cmd_entry; ep->name != NULL; ep++) { - if(!strncmp(argv[0], ep->name, strlen(argv[0]))) { + if(!strncmp(pcmd, ep->name, strlen(pcmd))) { if (cmd != NULL) printf("%s\n", cmd->name); cmd = ep; @@ -347,36 +376,36 @@ printf("%s\n", cmd->name); return; } - + if(cmd && cmd->name != NULL) { if (cmd->grpname != NULL) { - argc = insert_argv(argc, argv, cmd->grpname); + argc = insert_argv(argc, argv, cmd->grpname); for (ep = cmd_entry; ep->name != NULL; ep++) { - if(!strcmp(argv[0], ep->name)) { + if(!strcmp(pcmd, ep->name)) { cmd = ep; break; } } } - - if (canEcho && runLoad) { - if (!strcmp(cmd->name, "sleep") && + + if (echoctl.enable && runLoad) { + if (!strcmp(cmd->name, "sleep") && (argc != 2 || (argc == 2 && !digitstring(argv[1])))) { ; - } else + } else if (at == 0) printf("%s[%d] %s\n", vpc[pcid].xname, pcid + 1, cmdstr); } - if (argc > 1 && cmd->help != NULL && + if (argc > 1 && cmd->help != NULL && ((!strcmp(argv[argc - 1], "?") || !strcmp(argv[argc - 1], "help")))) { argv[0] = cmd->name; cmd->help(argc, argv); return; } - + /* the session control block */ memset(&vpc[pcid].mscb, 0, sizeof(vpc[pcid].mscb)); vpc[pcid].mscb.sock = 1; - + rc = cmd->f(argc, argv); memset(&vpc[pcid].mscb, 0, sizeof(vpc[pcid].mscb)); @@ -404,21 +433,23 @@ id = *(int *)devid; pc = &vpc[id]; pc->id = id; - + pc->rhost = rhost; pc->lport = lport + id; pc->rport = rport + id; - + pc->ip4.mac[0] = 0x00; pc->ip4.mac[1] = 0x50; pc->ip4.mac[2] = 0x79; pc->ip4.mac[3] = 0x66; pc->ip4.mac[4] = 0x68; pc->ip4.mac[5] = (id + macaddr) & 0xff; + pc->ip4.flags |= IPF_FRAG; + pc->mtu = 1500; if (pc->fd == 0) pc->fd = open_dev(id); - + if (pc->fd <= 0) { if (devtype == DEV_TAP) if (num_pths > 1) @@ -429,13 +460,16 @@ printf("Open port %d error [%s]\n", vpc[id].lport, strerror(errno)); return NULL; } - + pthread_mutex_init(&(pc->locker), NULL); init_queue(&pc->iq); pc->iq.type = 0 + id * 100; init_queue(&pc->oq); pc->oq.type = 1 + id * 100; - + init_queue(&pc->bgiq); + pc->bgiq.type = 2 + id * 100; + + if (pthread_create(&(pc->wpid), NULL, pth_writer, devid) != 0) { printf("PC%d error\n", id + 1); exit(-1); @@ -453,11 +487,18 @@ m->len = rc; gettimeofday(&(m->ts), (void*)0); - if (pc->dmpflag & DMP_ALL || !memcmp(m->data, pc->ip4.mac, ETH_ALEN)) + if (!memcmp(m->data, pc->ip4.mac, ETH_ALEN) || + pc->dmpflag & DMP_ALL) { + if (pc->dmpflag & DMP_FILE) + dmp_packet2file(m, pc->dmpfile); dmp_packet(m, pc->dmpflag); - rc = upv4(pc, m); - + } + + rc = upv4(pc, &m); + if (rc == PKT_UP) { + if (dhcp_enq(pc, m)) + continue; if (pc->mscb.sock != 0) { enq(&pc->iq, m); } else @@ -465,7 +506,7 @@ } else if (rc == PKT_DROP) del_pkt(m); } - } + } return NULL; } @@ -474,17 +515,20 @@ { int id; pcs *pc = NULL; - + id = *(int *)devid; pc = &vpc[id]; - + locallink6(pc); - + while (1) { struct packet *pkt = NULL; - + pkt = waitdeq(&pc->oq); - + + if (pc->dmpflag & DMP_FILE) + dmp_packet2file(pkt, pc->dmpfile); + dmp_packet(pkt, pc->dmpflag); if (VWrite(pc, pkt->data, pkt->len) != pkt->len) printf("Send packet error\n"); @@ -508,12 +552,45 @@ return NULL; } +void *pth_bgjob(void *dummy) +{ + int i; + int t, s; + + i = 0; + do { + if (vpc[i].ip4.dhcp.svr && vpc[i].ip4.dhcp.timetick) { + t = time_tick - vpc[i].ip4.dhcp.timetick; + s = t - vpc[i].ip4.dhcp.renew; + if (t > vpc[i].ip4.dhcp.renew && s < 4) { + vpc[i].bgjobflag = 1; + if (dhcp_renew(&vpc[i])) + vpc[i].ip4.dhcp.timetick = time_tick; + vpc[i].bgjobflag = 0; + continue; + } + s = t - vpc[i].ip4.dhcp.rebind; + if (t > vpc[i].ip4.dhcp.rebind && s < 4) { + vpc[i].bgjobflag = 1; + if (dhcp_rebind(&vpc[i])) + vpc[i].ip4.dhcp.timetick = time_tick; + vpc[i].bgjobflag = 0; + continue; + } + } + usleep(10000); + i = (i + 1) % num_pths; + } while (1); + + return NULL; +} + void startup(void) { FILE *fp; int argc; char *argv[3]; - + if (startupfile == NULL) { fp = fopen(default_startupfile, "r"); if (fp != NULL) { @@ -532,13 +609,13 @@ if (fp != NULL) { fclose(fp); runStartup = 1; - + argv[0] = "load"; argv[1] = (char *)startupfile; argv[2] = NULL; argc = 2; run_load(argc, argv); - + runStartup = 0; } else printf("Can't open %s\n", startupfile); @@ -547,27 +624,27 @@ } -void +void sig_clean(int sig) { int i; - + for (i = 0; i < num_pths; i++) close(vpc[i].fd); - if (rls != NULL && histfile != NULL) - savehistory(histfile, rls); + if (rls != NULL && histfile != NULL) + savehistory(histfile, rls); } int run_quit(int argc, char **argv) { pid_t pid; - + if (daemon_port) { pid = getppid(); kill(pid, SIGUSR1); } - + sig_clean(0); printf("\n"); @@ -577,40 +654,40 @@ int run_disconnect(int argc, char **argv) { pid_t pid; - + if (daemon_port) { pid = getppid(); kill(pid, SIGQUIT); } else printf("NOT daemon mode\n"); - + return 0; } void clear_hist(void) { - rls->hist_total = 0; + rls->hist_total = 0; } void welcome(void) { run_ver(0, NULL); - + printf("\nPress '?' to get help.\n"); - return; + return; } -static int +static int invoke_cmd(const char *cmd) { int rc = 0; - + #ifdef cygwin char str[1024]; snprintf(str, sizeof(str), "%s /c %s", getenv("COMSPEC"), cmd); rc = WinExec(str, SW_SHOW); -#else +#else rc = system(cmd); -#endif +#endif return rc; } diff -Nru vpcs-0.5b2/src/vpcs.h vpcs-0.6.1/src/vpcs.h --- vpcs-0.5b2/src/vpcs.h 2014-06-30 02:53:01.000000000 +0000 +++ vpcs-0.6.1/src/vpcs.h 2016-10-14 08:55:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2013, Paul Meng (mirnshi@gmail.com) + * Copyright (c) 2007-2014, Paul Meng (mirnshi@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,10 @@ typedef struct { u_int svr; u_char smac[6]; + u_int timetick; u_int lease; + u_int renew; + u_int rebind; u_int ip; u_int netmask; u_int gw; @@ -69,7 +72,6 @@ #define IP6TYPE_EUI64 1 #define IP6TYPE_LOCALLINK 2 u_char gmac[6]; /* destination host mac */ - int mtu; } hipv6; typedef struct { @@ -77,13 +79,14 @@ u_int ip; /* local host ip */ int cidr; /* local host ip netmask */ u_char mac[6]; /* local host mac */ - u_long gw; /* default gateway ip */ + u_int gw; /* default gateway ip */ u_char gmac[6]; /* destination host mac */ dhcp dhcp; u_int lease; /* dhcp lease time */ u_int dns[2]; /* dns server */ char domain[64]; /* search domain name */ - int mtu; + int flags; +#define IPF_FRAG 0x1 } hipv4; #define MAX_NAMES_LEN (6) @@ -94,13 +97,15 @@ pthread_t rpid; /* reader pthread id */ pthread_t wpid; /* writer pthread id */ int dmpflag; /* dump flag */ - //int sock; /* a command is running (socket is opened) */ + FILE *dmpfile; /* dump file pointer */ + int bgjobflag; /* backgroun job flag */ int fd; /* device handle */ int rfd; /* client handle if in the udp mode */ int lport; /* local udp port */ int rport; /* remote udp port */ u_int rhost; /* remote host */ - struct pq iq; /* queue */ + struct pq bgiq; /* background input queue */ + struct pq iq; /* queue */ struct pq oq; /* queue */ pthread_mutex_t locker; /* mutex */ sesscb mscb; /* opened by app */ @@ -112,8 +117,15 @@ int ip6auto; hipv6 ip6; hipv6 link6; + int mtu; } pcs; +struct echoctl { + int enable; + int fgcolor; + int bgcolor; +}; + pcs vpc[MAX_NUM_PTHS]; #define delay_ms(s) usleep(s * 1000) diff -Nru vpcs-0.5b2/src.drivers/freebsd/if_utun.c vpcs-0.6.1/src.drivers/freebsd/if_utun.c --- vpcs-0.5b2/src.drivers/freebsd/if_utun.c 2014-06-30 02:52:59.000000000 +0000 +++ vpcs-0.6.1/src.drivers/freebsd/if_utun.c 2016-10-14 08:55:04.000000000 +0000 @@ -26,7 +26,7 @@ * */ -/* $Id: if_utun.c 77 2013-08-26 06:23:11Z mirnshi $ +/* $Id$ * * utun, pseudo interface driver * encapsulates the traffic into UDP packets.