[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Fri Mar 2 15:38:40 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/22418adf039f
changeset: 371:22418adf039f
user: ray at terran.dlink.ua
date: Fri Mar 02 17:01:18 2012 +0200
description:
Update to FreeBSD-HEAD @232391
diffstat:
head/tools/build/options/WITHOUT_SOURCELESS | 2 +
head/tools/build/options/WITHOUT_SOURCELESS_HOST | 2 +
head/tools/build/options/WITHOUT_SOURCELESS_UCODE | 2 +
head/tools/build/options/WITH_CLANG_EXTRAS | 2 +
head/tools/build/options/WITH_CLANG_IS_CC | 8 +
head/tools/regression/bin/sh/builtins/hash4.0 | 6 +
head/tools/regression/lib/libc/gen/test-fmtmsg.c | 251 ++
head/tools/regression/sockets/so_setfib/Makefile | 14 +
head/tools/regression/sockets/so_setfib/so_setfib.c | 189 ++
head/tools/regression/sockets/so_setfib/so_setfib.t | 59 +
head/tools/regression/usb/usb_enum.t | 30 +
head/tools/test/hwpmc/pmctest.py | 94 +
head/tools/test/netfibs/Makefile | 7 +
head/tools/test/netfibs/README | 64 +
head/tools/test/netfibs/forwarding.sh | 1652 +++++++++++++++++++
head/tools/test/netfibs/initiator.sh | 1521 +++++++++++++++++
head/tools/test/netfibs/reflect.c | 365 ++++
head/tools/test/netfibs/reflector.sh | 1098 ++++++++++++
head/tools/test/ptrace/Makefile | 7 +
head/tools/test/ptrace/scescx.c | 406 ++++
head/tools/tools/fixwhite/Makefile | 7 +
head/tools/tools/fixwhite/fixwhite.1 | 48 +
head/tools/tools/fixwhite/fixwhite.c | 180 ++
23 files changed, 6014 insertions(+), 0 deletions(-)
diffs (6106 lines):
diff -r 77b2b05d6591 -r 22418adf039f head/tools/build/options/WITHOUT_SOURCELESS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/build/options/WITHOUT_SOURCELESS Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,2 @@
+.\" $FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS 230972 2012-02-04 00:54:43Z rmh $
+Set to not build kernel modules that include sourceless code (either microcode or native code for host CPU).
diff -r 77b2b05d6591 -r 22418adf039f head/tools/build/options/WITHOUT_SOURCELESS_HOST
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/build/options/WITHOUT_SOURCELESS_HOST Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,2 @@
+.\" $FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS_HOST 230972 2012-02-04 00:54:43Z rmh $
+Set to not build kernel modules that include sourceless native code for host CPU.
diff -r 77b2b05d6591 -r 22418adf039f head/tools/build/options/WITHOUT_SOURCELESS_UCODE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/build/options/WITHOUT_SOURCELESS_UCODE Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,2 @@
+.\" $FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS_UCODE 230972 2012-02-04 00:54:43Z rmh $
+Set to not build kernel modules that include sourceless microcode.
diff -r 77b2b05d6591 -r 22418adf039f head/tools/build/options/WITH_CLANG_EXTRAS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/build/options/WITH_CLANG_EXTRAS Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,2 @@
+.\" $FreeBSD: head/tools/build/options/WITH_CLANG_EXTRAS 231057 2012-02-05 23:56:22Z dim $
+Set to build additional clang and llvm tools, such as bugpoint.
diff -r 77b2b05d6591 -r 22418adf039f head/tools/build/options/WITH_CLANG_IS_CC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/build/options/WITH_CLANG_IS_CC Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,8 @@
+.\" $FreeBSD: head/tools/build/options/WITH_CLANG_IS_CC 232322 2012-02-29 22:58:51Z dim $
+Set to install the Clang C/C++ compiler as
+.Pa /usr/bin/cc
+,
+.Pa /usr/bin/c++
+and
+.Pa /usr/bin/cpp
+.
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/bin/sh/builtins/hash4.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/bin/sh/builtins/hash4.0 Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,6 @@
+# $FreeBSD: head/tools/regression/bin/sh/builtins/hash4.0 231535 2012-02-11 21:06:45Z jilles $
+
+exec 3>&1
+m=`hash nosuchtool 2>&1 >&3`
+r=$?
+[ "$r" != 0 ] && [ -n "$m" ]
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/lib/libc/gen/test-fmtmsg.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/lib/libc/gen/test-fmtmsg.c Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 2012 Jilles Tjoelker
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/tools/regression/lib/libc/gen/test-fmtmsg.c 231984 2012-02-21 23:46:41Z jilles $");
+
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fmtmsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static char *run_test(long classification, const char *label, int severity,
+ const char *text, const char *action, const char *tag);
+
+struct testcase {
+ long classification;
+ const char *label;
+ int severity;
+ const char *text;
+ const char *action;
+ const char *tag;
+ const char *msgverb;
+ const char *result;
+} testcases[] = {
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "text:severity:action:tag",
+ "illegal option -- z: ERROR\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "text",
+ "illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "severity:text",
+ "ERROR: illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "ignore me",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "tag:severity:text:nothing:action",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, MM_NULLLBL, MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ "ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", MM_NULLACT, MM_NULLTAG,
+ NULL,
+ "BSD:ls: ERROR: illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_NULLMC, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ ""
+ },
+ {
+ MM_APPL | MM_PRINT, "ABCDEFGHIJ:abcdefghijklmn", MM_INFO,
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "refer to manual", "ABCDEFGHIJ:abcdefghijklmn:001",
+ NULL,
+ "ABCDEFGHIJ:abcdefghijklmn: INFO: "
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
+ "TO FIX: refer to manual ABCDEFGHIJ:abcdefghijklmn:001\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_HALT,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: HALT: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_WARNING,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: WARNING: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_NOSEV,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ }
+};
+
+static char *
+run_test(long classification, const char *label, int severity,
+ const char *text, const char *action, const char *tag)
+{
+ int pip[2];
+ pid_t pid, wpid;
+ char *result, *p;
+ size_t resultsize;
+ ssize_t n;
+ int status;
+
+ if (pipe(pip) == -1)
+ err(2, "pipe");
+ pid = fork();
+ if (pid == -1)
+ err(2, "fork");
+ if (pid == 0) {
+ close(pip[0]);
+ if (pip[1] != STDERR_FILENO &&
+ dup2(pip[1], STDERR_FILENO) == -1)
+ _exit(2);
+ if (fmtmsg(classification, label, severity, text, action, tag)
+ != MM_OK)
+ _exit(1);
+ else
+ _exit(0);
+ }
+ close(pip[1]);
+ resultsize = 1024;
+ result = malloc(resultsize);
+ p = result;
+ while ((n = read(pip[0], p, result + resultsize - p - 1)) != 0) {
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ err(2, "read");
+ }
+ p += n;
+ if (result + resultsize == p - 1) {
+ resultsize *= 2;
+ result = realloc(result, resultsize);
+ if (result == NULL)
+ err(2, "realloc");
+ }
+ }
+ if (memchr(result, '\0', p - result) != NULL) {
+ free(result);
+ return (NULL);
+ }
+ *p = '\0';
+ close(pip[0]);
+ while ((wpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+ if (wpid == -1)
+ err(2, "waitpid");
+ if (status != 0) {
+ free(result);
+ return (NULL);
+ }
+ return (result);
+}
+
+int
+main(void)
+{
+ size_t i, n;
+ int errors;
+ char *result;
+ struct testcase *t;
+
+ n = sizeof(testcases) / sizeof(testcases[0]);
+ errors = 0;
+ printf("1..%zu\n", n);
+ for (i = 0; i < n; i++) {
+ t = &testcases[i];
+ if (t->msgverb != NULL)
+ setenv("MSGVERB", t->msgverb, 1);
+ else
+ unsetenv("MSGVERB");
+ result = run_test(t->classification, t->label, t->severity,
+ t->text, t->action, t->tag);
+ if (result != NULL && strcmp(result, t->result) == 0)
+ printf("ok %zu - correct\n",
+ i + 1);
+ else {
+ printf("not ok %zu - %s\n",
+ i + 1, result != NULL ? "incorrect" : "failed");
+ errors = 1;
+ }
+ free(result);
+ }
+
+ return (errors);
+}
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/sockets/so_setfib/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/sockets/so_setfib/Makefile Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,14 @@
+# $FreeBSD: head/tools/regression/sockets/so_setfib/Makefile 231855 2012-02-17 03:25:26Z bz $
+
+PROG= so_setfib
+NO_MAN=
+WARNS?= 6
+
+.ifdef INET6
+CFLAGS+= -DINET6
+.endif
+.ifdef INET
+CFLAGS+= -DINET
+.endif
+
+.include <bsd.prog.mk>
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/sockets/so_setfib/so_setfib.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/sockets/so_setfib/so_setfib.c Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 2012 Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Bjoern Zeeb under contract to
+ * Cisco Systems, Inc..
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: head/tools/regression/sockets/so_setfib/so_setfib.c 231855 2012-02-17 03:25:26Z bz $
+ */
+
+/*
+ * Regression test on SO_SETFIB setsockopt(2).
+ *
+ * Check that the expected domain(9) families all handle the socket option
+ * correctly and do proper bounds checks.
+ *
+ * Test plan:
+ * 1. Get system wide number of FIBs from sysctl and convert to index (-= 1).
+ * 2. For each protocol family (INET, INET6, ROUTE and LOCAL) open socketes of
+ * type (STREAM, DGRAM and RAW) as supported.
+ * 3. Do a sequence of -2, -1, 0, .. n, n+1, n+2 SO_SETFIB sockopt calls,
+ * expecting the first two and last two to fail (valid 0 ... n).
+ * 4. Try 3 random numbers. Calculate result based on valid range.
+ * 5. Repeat for next domain family and type from (2) on.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static struct t_dom {
+ int domain;
+ const char *name;
+} t_dom[] = {
+#ifdef INET6
+ { .domain = PF_INET6, .name = "PF_INET6" },
+#endif
+#ifdef INET
+ { .domain = PF_INET, .name = "PF_INET" },
+#endif
+ { .domain = PF_ROUTE, .name = "PF_ROUTE" },
+ { .domain = PF_LOCAL, .name = "PF_LOCAL" },
+};
+
+static struct t_type {
+ int type;
+ const char *name;
+} t_type[] = {
+ { .type = SOCK_STREAM, .name = "SOCK_STREAM" },
+ { .type = SOCK_DGRAM, .name = "SOCK_DGRAM" },
+ { .type = SOCK_RAW, .name = "SOCK_RAW" },
+};
+
+/*
+ * Number of FIBs as read from net.fibs sysctl - 1. Initialize to clear out of
+ * bounds value to not accidentally run on a limited range.
+ */
+static int rt_numfibs = -42;
+
+/* Number of test case. */
+static int testno = 1;
+
+
+/*
+ * Try the setsockopt with given FIB number i on socket s.
+ * Handle result given on error and valid range and errno.
+ */
+static void
+so_setfib(int s, int i, u_int dom, u_int type)
+{
+ int error;
+
+ error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &i, sizeof(i));
+ /* For out of bounds we expect an error. */
+ if (error == -1 && (i < 0 || i > rt_numfibs))
+ printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name,
+ t_type[type].name, i);
+ else if (error != -1 && (i < 0 || i > rt_numfibs))
+ printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, "
+ "SO_SETFIB, %d, ..) unexpectedly succeeded\n", testno,
+ t_dom[dom].name, t_type[type].name, i, s, i);
+ else if (error == 0)
+ printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name,
+ t_type[type].name, i);
+ else if (errno != EINVAL)
+ printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, "
+ "SO_SETFIB, %d, ..) unexpected error: %s\n", testno,
+ t_dom[dom].name, t_type[type].name, i, s, i,
+ strerror(errno));
+ else
+ printf("not ok %d %s_%s_%d\n", testno, t_dom[dom].name,
+ t_type[type].name, i);
+
+ /* Test run done, next please. */
+ testno++;
+}
+
+/*
+ * Main test. Open socket given domain family and type. For each FIB, out of
+ * bounds FIB numbers and 3 random FIB numbers set the socket option.
+ */
+static void
+t(u_int dom, u_int type)
+{
+ int i, s;
+
+ /* PF_ROUTE only supports RAW socket types, while PF_LOCAL does not. */
+ if (t_dom[dom].domain == PF_ROUTE && t_type[type].type != SOCK_RAW)
+ return;
+ if (t_dom[dom].domain == PF_LOCAL && t_type[type].type == SOCK_RAW)
+ return;
+
+ /* Open socket for given combination. */
+ s = socket(t_dom[dom].domain, t_type[type].type, 0);
+ if (s == -1) {
+ printf("not ok %d %s_%s # socket(): %s\n", testno,
+ t_dom[dom].name, t_type[type].name, strerror(errno));
+ return;
+ }
+
+ /* Test FIBs -2, -1, 0, .. n, n + 1, n + 2. */
+ for (i = -2; i <= (rt_numfibs + 2); i++)
+ so_setfib(s, i, dom, type);
+
+ /* Test 3 random FIB numbers. */
+ for (i = 0; i < 3; i++)
+ so_setfib(s, (int)random(), dom, type);
+
+ /* Close socket. */
+ close(s);
+}
+
+/*
+ * Returns 0 if no program error, 1 on sysctlbyname error.
+ * Test results are communicated by printf("[not ]ok <n> ..").
+ */
+int
+main(int argc __unused, char *argv[] __unused)
+{
+ u_int i, j;
+ size_t s;
+
+ /* Initalize randomness. */
+ srandomdev();
+
+ /* Get number of FIBs supported by kernel. */
+ s = sizeof(rt_numfibs);
+ if (sysctlbyname("net.fibs", &rt_numfibs, &s, NULL, 0) == -1)
+ err(1, "sysctlbyname(net.fibs, ..)");
+ /* Adjust from number to index. */
+ rt_numfibs -= 1;
+
+ /* Run tests. */
+ for (i = 0; i < sizeof(t_dom) / sizeof(struct t_dom); i++)
+ for (j = 0; j < sizeof(t_type) / sizeof(struct t_type); j++)
+ t(i, j);
+
+ return (0);
+}
+
+/* end */
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/sockets/so_setfib/so_setfib.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/sockets/so_setfib/so_setfib.t Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,59 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Cisco Systems, Inc.
+# All rights reserved.
+#
+# This software was developed by Bjoern Zeeb under contract to
+# Cisco Systems, Inc..
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: head/tools/regression/sockets/so_setfib/so_setfib.t 231855 2012-02-17 03:25:26Z bz $
+#
+
+cd `dirname $0`
+
+EXECUTABLE=`basename $0 .t`
+
+FIBS=`sysctl -n net.fibs`
+INET=`sysctl -n kern.features.inet`
+INET6=`sysctl -n kern.features.inet6`
+
+case "${INET}" in
+1) OPTS="${OPTS} -DINET" ;;
+*) INET=0 ;;
+esac
+case "${INET6}" in
+1) OPTS="${OPTS} -DINET6" ;;
+*) INET6=0 ;;
+esac
+
+make ${EXECUTABLE} ${OPTS} 2>&1 > /dev/null
+
+# two out of bounds on each side + 3 random
+FIBS=$((2 + FIBS + 2 + 3))
+# ROUTE and LOCAL are 1 domain together given 2 or 1 types only
+TESTS=$(((1 + ${INET} + ${INET6}) * 3 * ${FIBS}))
+
+echo "1..${TESTS}"
+
+exec ./${EXECUTABLE}
diff -r 77b2b05d6591 -r 22418adf039f head/tools/regression/usb/usb_enum.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/regression/usb/usb_enum.t Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,30 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/usb/usb_enum.t 232364 2012-03-01 20:45:17Z hselasky $
+
+#
+# About:
+# This script implements a simple USB enumeration test
+#
+# Usage:
+# ./usb_enum.t ugenX.Y
+#
+
+echo "1..100"
+
+if [ "$1" = "" ]; then
+# First Root HUB
+DEV="ugen0.1"
+else
+# Custom device
+DEV="$1"
+fi
+
+for N in $(jot 100 1)
+do
+if [ -c /dev/$DEV ] && [ -r /dev/$DEV ] && usbconfig -d $DEV reset ; then
+echo "ok $N"
+else
+echo "not ok $N"
+fi
+done
+
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/hwpmc/pmctest.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/hwpmc/pmctest.py Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# Copyright (c) 2012, Neville-Neil Consulting
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Neville-Neil Consulting nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER 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.
+#
+# Author: George V. Neville-Neil
+#
+# $FreeBSD: head/tools/test/hwpmc/pmctest.py 231699 2012-02-14 18:57:10Z gnn $
+
+# Description: A program to run a simple program against every available
+# pmc counter present in a system.
+#
+# To use:
+#
+# pmctest.py -p ls > /dev/null
+#
+# This should result in ls being run with every available counter
+# and the system should neither lock up nor panic.
+#
+# The default is to wait after each counter is tested. Since the
+# prompt would go to stdout you won't see it, just press return
+# to continue or Ctrl-D to stop.
+
+import sys
+import subprocess
+from subprocess import PIPE
+
+# A list of strings that are not really counters, just
+# name tags that are output by pmccontrol -L
+notcounter = ["IAF", "IAP", "TSC", "UNC", "UCF", "UCP"]
+
+def main():
+
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option("-p", "--program", dest="program",
+ help="program to execute")
+ parser.add_option("-w", "--wait", action="store_true", dest="wait",
+ default=True, help="wait after each execution")
+
+ (options, args) = parser.parse_args()
+
+ p = subprocess.Popen(["pmccontrol", "-L"], stdout=PIPE)
+ counters = p.communicate()[0]
+
+ if len(counters) <= 0:
+ print "no counters found"
+ sys.exit()
+
+ for counter in counters.split():
+ if counter in notcounter:
+ continue
+ p = subprocess.Popen(["pmcstat", "-p", counter, options.program],
+ stdout=PIPE)
+ result = p.communicate()[0]
+ print result
+ if (options.wait == True):
+ try:
+ value = raw_input("next?")
+ except EOFError:
+ sys.exit()
+
+# The canonical way to make a python module into a script.
+# Remove if unnecessary.
+
+if __name__ == "__main__":
+ main()
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/Makefile Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,7 @@
+# $FreeBSD: head/tools/test/netfibs/Makefile 231858 2012-02-17 04:26:24Z bz $
+
+PROG= reflect
+NO_MAN=
+WARNS?= 6
+
+.include <bsd.prog.mk>
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/README Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,64 @@
+# $FreeBSD: head/tools/test/netfibs/README 232114 2012-02-24 14:13:06Z bz $
+
+This directory holds scripts and a support program for multiple test cases
+exercising multi-IP FIBs. At this time only IPv6 test cases are provided.
+
+Makefile
+reflect.c
+
+ Makefile just builds reflect, a program to echo data on a TCP or UDP
+ socket in very simplistic ways. It has a couple of options to provide
+ an address or port, a FIB to bind to or a FIB to add to a reflected
+ message as well as some "magic" keyword handling to let the intiators
+ control it.
+
+initiator.sh and reflector.sh
+
+ intiator.sh runs two local test cases, one which shows a documented
+ limitation.
+
+ All further tests are either exercising the sending or receiving of
+ ICMP6, TCP or UDP packets with multiple FIBs. initiator.sh and
+ reflector.sh must run on two different nodes both having a network
+ interface in the same broadcast domain (be it cross-over or on a
+ bridge/switch). The tests will use the IPv6 benchmarking working
+ group (BMWG) prefix. The prefix is hard coded into some tests.
+ Control messages will synchronize reflector with initiator. The
+ reflector needs the reflect binary. Apart from that the scripts
+ depend on ping6, netcat, awk, tr and ipfw. The interface to use can
+ be set from the environment. The commands can be run like:
+
+ env IFACE=ifname sh intiator.sh
+ env IFACE=ifname sh reflector.sh
+
+ Both scripts also support a DEBUG environment variable for additional
+ output. A special value of 42 will enable sh(1) xtrace printing.
+
+ The output format is modeled after Test::Harness Perl as used in
+ tools/regression/ but not always compliant following the test case name.
+
+ NOTE: at the time of writing reflector.sh can trigger kernel races
+ unrelated to multi-FIB test leading to a panic(9). "delay" calls
+ are used to mitigate the problem some but are not always good enough.
+ It is suggested to run one test case at a time manually disabling
+ the others in both scripts.
+
+forwarding.sh
+
+ forwarding.sh tests FIBs in the forwarding path, making sure that
+ packets tagged on input are leaving on the correct FIB.
+ The script must be run on three nodes with both edge nodes (left
+ and right) being connected to the middle node on separate interfaces.
+
+ The script operates on the same principles and requirements as the
+ two afore described ones. Environment options equally apply, with
+ the middle node also taking an IFACEFAR variable to name the interface
+ to the right. See the ASCII art at the beginning of the script for
+ details. The script needs to be told which node it is running with
+ the first argument:
+
+ env IFACE=ifname sh forwarding.sh left
+ env IFACE=leftifname IFACEFAR=rightifname sh forwarding.sh middle
+ env IFACE=ifname sh forwarding.sh right
+
+# end
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/forwarding.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/forwarding.sh Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,1652 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Cisco Systems, Inc.
+# All rights reserved.
+#
+# This software was developed by Bjoern Zeeb under contract to
+# Cisco Systems, Inc..
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: head/tools/test/netfibs/forwarding.sh 232114 2012-02-24 14:13:06Z bz $
+#
+
+# Test setup:
+#
+# left ------------------------- middle ------------------------- right
+# IFACE IFACE IFACEFAR IFACE
+# LEFTADDR MIDDLELEFTADDR MIDDLERIGHTADDR RIGHTADDR
+# forwarding=1
+# initiator FIB tests reflector
+
+# We will use the RFC5180 (and Errata) benchmarking working group prefix
+# 2001:0002::/48 for testing.
+PREFIX="2001:2:"
+
+# Set IFACE to the real interface you want to run the test on.
+# IFACEFAR is only relevant on the middle (forwarding) node and will be the
+# 'right' side (far end) one.
+: ${IFACE:=lo0}
+: ${IFACEFAR:=lo0}
+
+# Number of seconds to wait for peer node to synchronize for test.
+: ${WAITS:=120}
+
+# Control port we use to exchange messages between nodes to sync. tests, etc.
+: ${CTRLPORT:=6666}
+
+# Get the number of FIBs from the kernel.
+RT_NUMFIBS=`sysctl -n net.fibs`
+
+# This is the initiator and connected middle node.
+LEFTADDR="2001:2:fe00::1"
+MIDDLELEFTADDR="2001:2:fe00::2"
+# This is the far end middle node and receiver side.
+MIDDLERIGHTADDR="2001:2:ff00::1"
+RIGHTADDR="2001:2:ff00::2"
+
+# By default all commands must succeed. Individual tests may disable this
+# temporary.
+set -e
+
+# Debug magic.
+case "${DEBUG}" in
+42) set -x ;;
+esac
+
+
+################################################################################
+#
+# Input validation.
+#
+
+node=$1
+case ${node} in
+left) ;;
+middle) ;;
+right) ;;
+*) echo "ERROR: invalid node name '${node}'. Must be left, middle or" \
+ " right" >&1
+ exit 1
+ ;;
+esac
+
+################################################################################
+#
+# Helper functions.
+#
+check_rc()
+{
+ local _rc _exp _testno _testname _msg _r
+ _rc=$1
+ _exp=$2
+ _testno=$3
+ _testname="$4"
+ _msg="$5"
+
+ _r="not ok"
+ if test ${_rc} -eq ${_exp}; then
+ _r="ok"
+ fi
+ echo "${_r} ${_testno} ${_testname} # ${_msg} ${_rc} ${_exp}"
+}
+
+print_debug()
+{
+ local _msg
+ _msg="$*"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) echo "DEBUG: ${_msg}" >&2 ;;
+ esac
+}
+
+die()
+{
+ local _msg
+ _msg="$*"
+
+ echo "ERROR: ${_msg}" >&2
+ exit 1
+}
+
+
+################################################################################
+#
+# Functions to configure networking and do a basic reachability check.
+#
+
+setup_networking()
+{
+
+ print_debug "Setting up networking"
+ case ${node} in
+ left) ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 ${LEFTADDR}/64 alias up
+ ifconfig ${IFACE} fib 0
+ sysctl net.inet6.ip6.forwarding=0 > /dev/null
+ route delete -net -inet6 default > /dev/null 2>&1 || true
+ route delete -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \
+ > /dev/null 2>&1 || true
+ route add -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \
+ > /dev/null
+ route delete -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \
+ > /dev/null 2>&1 || true
+ route add -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \
+ > /dev/null 2>&1 || true
+ ;;
+ middle) ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 alias up
+ ifconfig ${IFACE} fib 0
+ ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 alias up
+ ifconfig ${IFACEFAR} fib 0
+ sysctl net.inet6.ip6.forwarding=1 > /dev/null
+ ;;
+ right) ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 alias up
+ ifconfig ${IFACE} fib 0
+ sysctl net.inet6.ip6.forwarding=0 > /dev/null
+ route delete -net -inet6 default > /dev/null 2>&1 || true
+ route delete -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \
+ > /dev/null 2>&1 || true
+ route add -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \
+ > /dev/null
+ route delete -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \
+ > /dev/null 2>&1 || true
+ route add -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \
+ > /dev/null
+ ;;
+ esac
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+}
+
+cleanup_networking()
+{
+
+ case ${node} in
+ left) ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias
+ ;;
+ middle) ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias
+ ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias
+ sysctl net.inet6.ip6.forwarding=0 > /dev/null
+ ;;
+ right) ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias
+ ;;
+ esac
+ print_debug "Cleaned up networking"
+}
+
+_reachability_check()
+{
+ local _addr _rc
+ _addr="$1"
+
+ ping6 -n -c1 ${_addr} > /dev/null 2>&1
+ _rc=$?
+ case ${_rc} in
+ 0) ;;
+ *) print_debug "cannot ping6 ${_addr}, rc=${_rc}"
+ return 1
+ ;;
+ esac
+ return 0
+}
+
+reachability_check()
+{
+ local _i rc
+
+ # Try to reach all control addresses on other nodes.
+ # We need to loop for a while as we cannot expect all to be up
+ # the very same moment.
+ i=1
+ rc=42
+ while test ${rc} -ne 0 -a ${i} -le ${WAITS}; do
+ print_debug "${i}/${WAITS} trying to ping6 control addresses."
+ rc=0
+ set +e
+ case ${node} in
+ left) _reachability_check ${MIDDLELEFTADDR}
+ rc=$((rc + $?))
+ _reachability_check ${MIDDLERIGHTADDR}
+ rc=$((rc + $?))
+ _reachability_check ${RIGHTADDR}
+ rc=$((rc + $?))
+ ;;
+ middle) _reachability_check ${LEFTADDR}
+ rc=$((rc + $?))
+ _reachability_check ${RIGHTADDR}
+ rc=$((rc + $?))
+ ;;
+ right) _reachability_check ${MIDDLERIGHTADDR}
+ rc=$((rc + $?))
+ _reachability_check ${MIDDLELEFTADDR}
+ rc=$((rc + $?))
+ _reachability_check ${LEFTADDR}
+ rc=$((rc + $?))
+ ;;
+ esac
+ set -e
+ sleep 1
+ i=$((i + 1))
+ done
+}
+
+################################################################################
+#
+# "Greeting" handling to sync notes to the agreed upon next test case.
+#
+send_control_msg()
+{
+ local _case _addr i rc _msg _keyword _fibs
+ _case="$1"
+ _addr="$2"
+
+ set +e
+ i=0
+ rc=-1
+ while test ${i} -lt ${WAITS} -a ${rc} -ne 0; do
+ print_debug "Sending control msg #${i} to peer ${_addr}"
+ _msg=`echo "${_case} ${RT_NUMFIBS}" | \
+ nc -6 -w 1 ${_addr} ${CTRLPORT}`
+ rc=$?
+ i=$((i + 1))
+ # Might sleep longer in total but better than to DoS
+ # and not get anywhere.
+ sleep 1
+ done
+ set -e
+
+ read _keyword _fibs <<EOI
+${_msg}
+EOI
+ print_debug "_keyword=${_keyword}"
+ print_debug "_fibs=${_fibs}"
+ case ${_keyword} in
+ ${_case});;
+ *) die "Got invalid keyword from ${_addr} in control message:" \
+ "${_msg}"
+ ;;
+ esac
+ if test ${_fibs} -ne ${RT_NUMFIBS}; then
+ die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
+ "control message from ${_addr}: ${_msg}"
+ fi
+
+ print_debug "Successfully exchanged control message with ${_addr}."
+}
+
+send_control_msgs()
+{
+ local _case _addr
+ _case="$1"
+
+ # Always start with the far end. Otherwise we will cut that off when
+ # cleanly taering down things again.
+ for _addr in ${RIGHTADDR} ${MIDDLELEFTADDR}; do
+ send_control_msg "${_case}" ${_addr}
+ done
+
+ # Allow us to flush ipfw counters etc before new packets will arrive.
+ sleep 1
+}
+
+# We are setup. Wait for the initiator to tell us that it is ready.
+wait_remote_ready()
+{
+ local _case _msg _keyword _fibs
+ _case="$1"
+
+ # Wait for the remote to connect and start things.
+ # We tell it the magic keyword, and our number of FIBs.
+ _msg=`echo "${_case} ${RT_NUMFIBS}" | nc -6 -l ${CTRLPORT}`
+
+ read _keyword _fibs <<EOI
+${_msg}
+EOI
+ print_debug "_keyword=${_keyword}"
+ print_debug "_fibs=${_fibs}"
+ case ${_keyword} in
+ ${_case});;
+ *) die "Got invalid keyword in control message: ${_msg}"
+ ;;
+ esac
+ if test ${_fibs} -ne ${RT_NUMFIBS}; then
+ die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
+ "control message: ${_msg}"
+ fi
+
+ print_debug "Successfully received control message."
+}
+
+################################################################################
+#
+# Test case helper functions.
+#
+# Please note that neither on the intiator nor the reflector are FIBs despite
+# a variable name might indicate. If such a variable is used it mirrors FIB
+# numbers from the middle node to match for test cases.
+#
+test_icmp6()
+{
+ local _maxfibs _addr _n _testno i _rc _ec
+ _maxfibs=$1
+ _addr="$2"
+ _n="$3"
+
+ printf "1..%d\n" ${_maxfibs}
+ _testno=1
+ set +e
+ i=0
+ while test ${i} -lt ${_maxfibs}; do
+ _txt="${_n}_${i}"
+ print_debug "Testing ${_txt}"
+
+ # Generate HEX for ping6 payload.
+ _fibtxt=`echo "${_txt}" | hd -v | cut -b11-60 | tr -d ' \r\n'`
+
+ eval _rc="\${rc_${i}}"
+ ping6 -n -c1 -p ${_fibtxt} ${_addr} > /dev/null 2>&1
+ _ec=$?
+ # We need to normalize the exit code of ping6.
+ case ${_ec} in
+ 0) ;;
+ *) _ec=1 ;;
+ esac
+ check_rc ${_ec} ${_rc} ${_testno} "${_txt}" "FIB ${i} ${_addr}"
+ testno=$((testno + 1))
+ i=$((i + 1))
+ done
+ set -e
+}
+
+test_ulp_reflect_one()
+{
+ local _txt _opts port fib
+ _txt="$1"
+ _opts="$2"
+ port=$3
+ fib=$4
+
+ print_debug "./reflect -p $((port + 1 + fib)) -t ${_txt}" "${_opts}"
+ ./reflect -p $((port + 1 + fib)) -t ${_txt} ${_opts}
+ print_debug "reflect '${_txt}' terminated without error."
+}
+
+test_ulp_reflect_multiple()
+{
+ local _maxfibs _txt _opts i _jobs _p
+ _maxfibs=$1
+ _txt="$2"
+ _opts="$3"
+
+ i=0
+ _jobs=""
+ while test ${i} -lt ${_maxfibs}; do
+ print_debug "./reflect -p $((CTRLPORT + 1000 + i))" \
+ "-t ${_txt} ${_opts} -N -f ${i} &"
+ ./reflect -p $((CTRLPORT + 1000 + i)) \
+ -t ${_txt} ${_opts} -N -f ${i} &
+ _p=$!
+ _jobs="${_jobs}${_p} "
+ i=$((i + 1))
+ done
+
+ # Start OOB control connection for START/DONE.
+ testrx_run_one "${_txt}" "${_opts}"
+ print_debug "KILL ${_jobs}"
+ for i in ${_jobs}; do
+ kill ${i} || true
+ done
+ #killall reflect || true
+ print_debug "reflects for '${_txt}' terminated without error."
+}
+
+nc_send_recv()
+{
+ local _loops _msg _expreply _addr _port _opts i
+ _loops=$1
+ _msg="$2"
+ _expreply="$3"
+ _addr=$4
+ _port=$5
+ _opts="$6"
+
+ i=0
+ while test ${i} -lt ${_loops}; do
+ i=$((i + 1))
+ print_debug "e ${_msg} | nc -6 -w1 ${_opts} ${_addr} ${_port}"
+ _reply=`echo "${_msg}" | nc -6 -w1 ${_opts} ${_addr} ${_port}`
+ if test "${_reply}" != "${_expreply}"; then
+ if test ${i} -lt ${_loops}; then
+ sleep 1
+ else
+ # Must let caller decide how to handle the error.
+ # die "Got invalid reply from peer." \
+ # "Expected '${_expreply}', got '${_reply}'"
+ return 1
+ fi
+ else
+ break
+ fi
+ done
+ return 0
+}
+
+test_ulp()
+{
+ local maxfibs _msg _addr port fib i _txt testno _rc _reply
+ maxfibs=$1
+ _msg="$2"
+ _addr=$3
+ port=$4
+ fib=$5
+
+ printf "1..%d\n" $((${maxfibs} * 2))
+ testno=1
+ i=0
+ while test ${i} -lt ${maxfibs}; do
+
+ if test ${i} -eq $((${maxfibs} - 1)); then
+ # Last one; signal DONE.
+ _txt="DONE ${_msg}_${i}"
+ else
+ _txt="DONE ${_msg}_${i}"
+ fi
+
+ eval _rc="\${rc_${i}}"
+
+ # Test TCP.
+ nc_send_recv ${maxfibs} "${_txt}" "${_txt}" ${_addr} \
+ $((${port} + 1 + fib)) ""
+ check_rc $? ${_rc} ${testno} "${_msg}_${i}_tcp" \
+ "[${_addr}]:$((${port} + 1 + fib)) ${_reply}"
+ testno=$((testno + 1))
+ sleep 1
+
+ # Test UDP.
+ nc_send_recv ${maxfibs} "${_txt}" "${_txt}" ${_addr} \
+ $((${port} + 1 + fib)) "-u"
+ check_rc $? ${_rc} ${testno} "${_msg}_${i}_udp" \
+ "[${_addr}]:$((${port} + 1 + fib)) ${_reply}"
+ sleep 1
+
+ i=$((i + 1))
+ testno=$((testno + 1))
+ done
+}
+
+setup_ipfw_count()
+{
+ local i port maxfib _p _fib _ofib
+ port=$1
+ maxfib=$2
+ _fib=$3
+ _ofib=$4
+
+ i=0
+ while test ${i} -lt ${maxfib}; do
+
+ case ${_ofib} in
+ -1) _p=$((port + 1 + i)) ;;
+ *) _p=$((port + 1 + maxfib - 1 - i)) ;;
+ esac
+
+ # Only count ICMP6 echo replies.
+ ipfw add $((10000 + i)) count ipv6-icmp from any to any \
+ icmp6types 129 fib ${i} via ${IFACE} out > /dev/null
+ ipfw add $((10000 + i)) count tcp from any to any \
+ src-port ${_p} fib ${i} via ${IFACE} out > /dev/null
+ ipfw add $((10000 + i)) count udp from any to any \
+ src-port ${_p} fib ${i} via ${IFACE} out > /dev/null
+
+ # Only count ICMP6 echo requests.
+ ipfw add $((20000 + i)) count ipv6-icmp from any to any \
+ icmp6types 128 fib ${i} via ${IFACEFAR} out > /dev/null
+ ipfw add $((20000 + i)) count tcp from any to any \
+ dst-port $((${port} + 1 + i)) fib ${i} \
+ via ${IFACEFAR} out > /dev/null
+ ipfw add $((20000 + i)) count udp from any to any \
+ dst-port $((${port} + 1 + i)) fib ${i} \
+ via ${IFACEFAR} out > /dev/null
+
+ i=$((i + 1))
+ done
+}
+
+report_ipfw_count()
+{
+ local _fib _o i _rstr _c _req _p _opts base
+ _o="$2"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) ipfw show ;;
+ esac
+
+ _rstr="RESULTS "
+ for base in 10000 20000; do
+ for _o in i t u; do
+ case ${base} in
+ 10000) _rstr="${_rstr}\nLEFT " ;;
+ 20000) _rstr="${_rstr}\nRIGHT " ;;
+ esac
+ case ${_o} in
+ i) _rstr="${_rstr}ICMP6 " ;;
+ t) _rstr="${_rstr}TCP " ;;
+ u) _rstr="${_rstr}UDP " ;;
+ esac
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ case "${_o}" in
+ i) _c=`ipfw show $((${base} + i)) | \
+ awk '/ ipv6-icmp / { print $2 }'` ;;
+ t) _c=`ipfw show $((${base} + i)) | \
+ awk '/ tcp / { print $2 }'` ;;
+ u) _c=`ipfw show $((${base} + i)) | \
+ awk '/ udp / { print $2 }'` ;;
+ esac
+ _rstr="${_rstr}${i} ${_c},"
+
+ i=$((i + 1))
+ done
+ done
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ipfw delete $((${base} + i)) > /dev/null 2>&1 || true
+ i=$((i + 1))
+ done
+ done
+
+ # We do not care about the request.
+ _req=`printf "${_rstr}" | nc -6 -l $((${CTRLPORT} - 1))`
+ print_debug "$? -- ${_req} -- ${_rstr}"
+}
+
+fetch_ipfw_count()
+{
+ local _n _reply _line _edge _type _fib _count _rc _ec _status
+ _n="$1"
+
+ # Leave node some time to build result set.
+ sleep 3
+
+ print_debug "Asking for ipfw count results..."
+ set +e
+ nc_send_recv 1 "RESULT REQUEST" "" ${MIDDLELEFTADDR} \
+ $((${CTRLPORT} - 1)) ""
+ set -e
+ case "${_reply}" in
+ RESULTS\ *) ;;
+ *) die "Got invalid reply from peer." \
+ "Expected 'RESULTS ...', got '${_reply}'" ;;
+ esac
+
+ # Trim "RESULTS "
+ _reply=${_reply#* }
+
+ # FIBs * {left, right} * {icmp6, tcp, udp}
+ printf "1..%d\n" $((RT_NUMFIBS * 2 * 3))
+ testno=1
+ while read _line; do
+ print_debug "_line == ${_line}"
+ _edge=${_line%% *}
+ _line=${_line#* }
+ _type=${_line%% *}
+ _line=${_line#* }
+
+ while read _fib _count; do
+ eval _em="\${rc_${_n}_${_edge}_${_type}_${_fib}}"
+ : ${_em:=-42}
+ if test ${_count} -gt 0; then
+ _rc=1
+ else
+ _rc=0
+ fi
+ if test ${_rc} -eq ${_em}; then
+ _status="ok"
+ else
+ _status="not ok"
+ fi
+ printf "%s %d %s # count=%s _rc=%d _em=%d\n" \
+ "${_status}" ${testno} "${_n}_${_edge}_${_type}_${_fib}" \
+ ${_count} ${_rc} ${_em}
+ testno=$((testno + 1))
+ done <<EOi
+`printf "${_line}" | tr ',' '\n'`
+EOi
+
+ done <<EOo
+`printf "${_reply}" | grep -v "^$"`
+EOo
+
+ print_debug "ipfw count results processed"
+}
+
+################################################################################
+#
+# Test cases.
+#
+# In general we set the FIB on in, but count on out.
+#
+
+_fwd_default_fib_symmetric_results()
+{
+ local _n i _edge _type _rc
+ _n="$1"
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ for _edge in "LEFT" "RIGHT"; do
+ for _type in "ICMP6" "TCP" "UDP"; do
+
+ case ${i} in
+ 0) eval rc_${_n}_${_edge}_${_type}_${i}=1
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=1"
+ ;;
+ *) eval rc_${_n}_${_edge}_${_type}_${i}=0
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=0"
+ ;;
+ esac
+
+ done
+ done
+ i=$((i + 1))
+ done
+}
+
+_fwd_default_fib_symmetric_left()
+{
+ local _n
+ _n="$1"
+
+ send_control_msgs "START_${_n}"
+
+ # Setup expected return code
+ rc_0=0
+
+ # Initiate probes for ICMP6, TCP and UDP.
+ test_icmp6 1 ${RIGHTADDR} "${_n}_icmp6"
+ test_ulp 1 "${_n}" ${RIGHTADDR} ${CTRLPORT} 0
+
+ send_control_msgs "STOP_${_n}"
+ _fwd_default_fib_symmetric_results "${_n}"
+ fetch_ipfw_count "${_n}"
+}
+
+_fwd_default_fib_symmetric_middle()
+{
+ local _n
+ _n="$1"
+
+ setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
+ wait_remote_ready "START_${_n}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}"
+ report_ipfw_count
+}
+
+_fwd_default_fib_symmetric_right()
+{
+ local _n
+ _n="$1"
+
+ wait_remote_ready "START_${_n}"
+
+ # No need to do anything for ICMPv6.
+ # Start reflect for TCP and UDP.
+ test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" 0 ${CTRLPORT}
+ test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" 0 ${CTRLPORT}
+
+ wait_remote_ready "STOP_${_n}"
+}
+
+fwd_default_fib_symmetric()
+{
+ local _n
+
+ _n="fwd_default_fib_symmetric"
+
+ print_debug "${_n}"
+ case ${node} in
+ left) _fwd_default_fib_symmetric_left ${_n} ;;
+ middle) _fwd_default_fib_symmetric_middle ${_n} ;;
+ right) _fwd_default_fib_symmetric_right ${_n} ;;
+ esac
+}
+
+_fwd_default_fib_symmetric_middle_ifconfig()
+{
+ local _n
+ _n="$1"
+
+ ifconfig ${IFACE} fib 0
+ ifconfig ${IFACEFAR} fib 0
+ setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
+ wait_remote_ready "START_${_n}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}"
+ report_ipfw_count
+}
+
+fwd_default_fib_symmetric_ifconfig()
+{
+ local _n
+
+ _n="fwd_default_fib_symmetric_ifconfig"
+
+ print_debug "${_n}"
+ case ${node} in
+ left) _fwd_default_fib_symmetric_left ${_n} ;;
+ middle) _fwd_default_fib_symmetric_middle_ifconfig ${_n} ;;
+ right) _fwd_default_fib_symmetric_right ${_n} ;;
+ esac
+}
+
+_fwd_default_fib_symmetric_middle_ipfw()
+{
+ local _n
+ _n="$1"
+
+ ipfw add 100 setfib 0 ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACE} in > /dev/null
+ ipfw add 100 setfib 0 ip6 from any to any \
+ proto tcp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null
+ ipfw add 100 setfib 0 ip6 from any to any \
+ proto udp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null
+
+ ipfw add 100 setfib 0 ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib 0 tcp from any to any \
+ dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib 0 udp from any to any \
+ dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null
+
+ setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
+ wait_remote_ready "START_${_n}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}"
+ report_ipfw_count
+
+ ipfw delete 100 > /dev/null
+}
+
+fwd_default_fib_symmetric_ipfw()
+{
+ local _n
+
+ _n="fwd_default_fib_symmetric_ipfw"
+
+ print_debug "${_n}"
+ case ${node} in
+ left) _fwd_default_fib_symmetric_left ${_n} ;;
+ middle) _fwd_default_fib_symmetric_middle_ipfw ${_n} ;;
+ right) _fwd_default_fib_symmetric_right ${_n} ;;
+ esac
+}
+
+################################################################################
+
+_fwd_fib_symmetric_results()
+{
+ local _n _fib i _edge _type _rc
+ _n="$1"
+ _fib=$2
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ for _edge in "LEFT" "RIGHT"; do
+ for _type in "ICMP6" "TCP" "UDP"; do
+
+ case ${i} in
+ ${_fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=1"
+ ;;
+ *) eval rc_${_n}_${_edge}_${_type}_${i}=0
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=0"
+ ;;
+ esac
+
+ done
+ done
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_left()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ # Setup expected return code
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ eval rc_${i}=0
+ i=$((i + 1))
+ done
+
+ # Initiate probes for ICMP6, TCP and UDP.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+
+ sleep 1
+
+ send_control_msgs "START_${_n}_${i}"
+
+ test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6"
+ test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i}
+
+ send_control_msgs "STOP_${_n}_${i}"
+ _fwd_fib_symmetric_results "${_n}_${i}" ${i}
+ fetch_ipfw_count "${_n}_${i}"
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_right()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ wait_remote_ready "START_${_n}_${i}"
+
+ # No need to do anything for ICMPv6.
+ # Start reflect for TCP and UDP.
+ test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" ${i} ${CTRLPORT}
+ test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" ${i} ${CTRLPORT}
+
+ wait_remote_ready "STOP_${_n}_${i}"
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_middle_ifconfig()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} fib ${i}
+ ifconfig ${IFACEFAR} fib ${i}
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_middle_ipfw()
+{
+ local _n _maxfib i _port
+ _n="$1"
+ _maxfib=$2
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ _port=$((CTRLPORT + 1 + i))
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 129 via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+
+ ipfw delete 100 > /dev/null
+ i=$((i + 1))
+ done
+}
+
+fwd_fib_symmetric_ifconfig()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_ifconfig"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_middle_ifconfig ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+fwd_fib_symmetric_ipfw()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_ipfw"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_middle_ipfw ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+################################################################################
+
+_fwd_fib_asymmetric_results()
+{
+ local _n fib maxfib i _edge _type _rc
+ _n="$1"
+ fib=$2
+ maxfib=$3
+
+ i=0
+ while test ${i} -lt ${maxfib}; do
+ _edge="RIGHT"
+ for _type in "ICMP6" "TCP" "UDP"; do
+
+ case ${i} in
+ ${fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=1"
+ ;;
+ *) eval rc_${_n}_${_edge}_${_type}_${i}=0
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=0"
+ ;;
+ esac
+
+ done
+ i=$((i + 1))
+ done
+ fib=$((maxfib - 1 - fib))
+ i=0
+ while test ${i} -lt ${maxfib}; do
+ _edge="LEFT"
+ for _type in "ICMP6" "TCP" "UDP"; do
+
+ case ${i} in
+ ${fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=1"
+ ;;
+ *) eval rc_${_n}_${_edge}_${_type}_${i}=0
+ #print_debug \
+ # "rc_${_n}_${_edge}_${_type}_${i}=0"
+ ;;
+ esac
+
+ done
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_asymmetric_left()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ # Setup expected return code
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ eval rc_${i}=0
+ i=$((i + 1))
+ done
+
+ # Initiate probes for ICMP6, TCP and UDP.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+
+ sleep 1
+
+ send_control_msgs "START_${_n}_${i}"
+
+ test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6"
+ test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i}
+
+ send_control_msgs "STOP_${_n}_${i}"
+ _fwd_fib_asymmetric_results "${_n}_${i}" ${i} ${_maxfib}
+ fetch_ipfw_count "${_n}_${i}"
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_asymmetric_middle_ifconfig()
+{
+ local _n maxfib i
+ _n="$1"
+ maxfib=$2
+
+ i=0
+ while test ${i} -lt ${maxfib}; do
+ ifconfig ${IFACE} fib ${i}
+ ifconfig ${IFACEFAR} fib $((${maxfib} - 1 - ${i}))
+ setup_ipfw_count ${CTRLPORT} ${maxfib} ${i} \
+ $((${maxfib} - 1 - ${i}))
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_asymmetric_middle_ipfw()
+{
+ local _n maxfib i j _port
+ _n="$1"
+ maxfib=$2
+
+ i=0
+ while test ${i} -lt ${maxfib}; do
+
+ _port=$((CTRLPORT + 1 + i))
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+
+ j=$((${maxfib} - 1 - ${i}))
+ ipfw add 100 setfib ${j} ipv6-icmp from any to any \
+ icmp6types 129 via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${j} tcp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${j} udp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+
+ setup_ipfw_count ${CTRLPORT} ${maxfib} ${i} ${j}
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+
+ ipfw delete 100 > /dev/null
+ i=$((i + 1))
+ done
+}
+
+fwd_fib_asymmetric_ifconfig()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_asymmetric_ifconfig"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_asymmetric_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_asymmetric_middle_ifconfig ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+fwd_fib_asymmetric_ipfw()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_asymmetric_ipfw"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_asymmetric_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_asymmetric_middle_ipfw ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+################################################################################
+
+_fwd_fib_symmetric_destructive_left()
+{
+ local _n _maxfib i _addr
+ _n="$1"
+ _maxfib=$2
+
+ # Setup expected return code
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ eval rc_${i}=0
+ i=$((i + 1))
+ done
+
+ # Add default route.
+ route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null
+
+ # Initiate probes for ICMP6, TCP and UDP.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+
+ sleep 1
+
+ send_control_msgs "START_${_n}_${i}"
+
+ _addr="2001:2:${i}::2"
+ test_icmp6 1 ${_addr} "${_n}_${i}_icmp6"
+ test_ulp 1 "${_n}_${i}" ${_addr} ${CTRLPORT} ${i}
+
+ send_control_msgs "STOP_${_n}_${i}"
+ _fwd_fib_symmetric_results "${_n}_${i}" ${i}
+ fetch_ipfw_count "${_n}_${i}"
+ i=$((i + 1))
+ done
+
+ # Cleanup networking.
+ route delete -net -inet6 default > /dev/null
+}
+
+_fwd_fib_symmetric_destructive_right()
+{
+ local _n _maxfib i _addr
+ _n="$1"
+ _maxfib=$2
+
+ # Setup networking (ideally we'd use the link-local).
+ route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias
+ i=$((i + 1))
+ done
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ wait_remote_ready "START_${_n}_${i}"
+
+ # No need to do anything for ICMPv6.
+ # Start reflect for TCP and UDP.
+ _addr="2001:2:${i}::2"
+ test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \
+ ${i} ${CTRLPORT}
+ test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \
+ ${i} ${CTRLPORT}
+
+ wait_remote_ready "STOP_${_n}_${i}"
+ i=$((i + 1))
+ done
+
+ # Cleanup networking again.
+ route delete -net -inet6 default > /dev/null 2>&1
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias
+ i=$((i + 1))
+ done
+
+}
+
+
+_fwd_fib_symmetric_destructive_middle_setup_networking()
+{
+ local _maxfib i j
+ _maxfib=$1
+
+ # Setup networking.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias
+ j=0
+ while test ${j} -lt ${_maxfib}; do
+ # Only work on all other FIBs.
+ if test ${j} -ne ${i}; then
+ setfib -F ${j} route delete -net -inet6 \
+ 2001:2:${i}::/64 > /dev/null
+ fi
+ j=$((j + 1))
+ done
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_destructive_middle_cleanup_networking()
+{
+ local _maxfib i
+ _maxfib=$1
+
+ # Cleanup networking again.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_destructive_middle_ifconfig()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ _fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib}
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} fib ${i}
+ ifconfig ${IFACEFAR} fib ${i}
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+ i=$((i + 1))
+ done
+
+ _fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib}
+}
+
+_fwd_fib_symmetric_destructive_middle_ipfw()
+{
+ local _n _maxfib i _port
+ _n="$1"
+ _maxfib=$2
+
+ _fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib}
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ _port=$((CTRLPORT + 1 + i))
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 129 via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+
+ ipfw delete 100 > /dev/null
+ i=$((i + 1))
+ done
+
+ _fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib}
+}
+
+fwd_fib_symmetric_destructive_ifconfig()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_destructive_ifconfig"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_destructive_middle_ifconfig \
+ ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+fwd_fib_symmetric_destructive_ipfw()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_destructive_ipfw"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_destructive_middle_ipfw \
+ ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;;
+ esac
+}
+
+################################################################################
+
+_fwd_fib_symmetric_destructive_defroute_left()
+{
+ local _n _maxfib i _addr
+ _n="$1"
+ _maxfib=$2
+
+ # Setup expected return code
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ eval rc_${i}=0
+ i=$((i + 1))
+ done
+
+ # Add default route.
+ route delete -net -inet6 default > /dev/null 2>&1 || true
+ route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null
+
+ # Initiate probes for ICMP6, TCP and UDP.
+ _addr="2001:2:1234::2"
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+
+ sleep 1
+
+ send_control_msgs "START_${_n}_${i}"
+
+ test_icmp6 1 "${_addr}" "${_n}_${i}_icmp6"
+ test_ulp 1 "${_n}_${i}" "${_addr}" ${CTRLPORT} ${i}
+
+ send_control_msgs "STOP_${_n}_${i}"
+ _fwd_fib_symmetric_results "${_n}_${i}" ${i}
+ fetch_ipfw_count "${_n}_${i}"
+ i=$((i + 1))
+ done
+
+ # Cleanup networking.
+ route delete -net -inet6 default > /dev/null 2>&1
+}
+
+_fwd_fib_symmetric_destructive_defroute_right()
+{
+ local _n _maxfib i _addr
+ _n="$1"
+ _maxfib=$2
+
+ # Setup networking (ideally we'd use the link-local).
+ route delete -net -inet6 default > /dev/null 2>&1 || true
+ route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias
+ i=$((i + 1))
+ done
+ _addr="2001:2:1234::2"
+ ifconfig lo0 inet6 ${_addr}/128 alias
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ wait_remote_ready "START_${_n}_${i}"
+
+ # No need to do anything for ICMPv6.
+ # Start reflect for TCP and UDP.
+ test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \
+ ${i} ${CTRLPORT}
+ test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \
+ ${i} ${CTRLPORT}
+
+ wait_remote_ready "STOP_${_n}_${i}"
+ i=$((i + 1))
+ done
+
+ # Cleanup networking again.
+ route delete -net -inet6 default > /dev/null 2>&1
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias
+ i=$((i + 1))
+ done
+ ifconfig lo0 inet6 ${_addr}/128 -alias
+
+}
+
+_fwd_fib_symmetric_destructive_defroute_middle_setup_networking()
+{
+ local _maxfib i j
+ _maxfib=$1
+
+ # Setup networking.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias
+ j=0
+ while test ${j} -lt ${_maxfib}; do
+ # Only work on all other FIBs.
+ if test ${j} -ne ${i}; then
+ setfib -F ${j} route delete -net -inet6 \
+ 2001:2:${i}::/64 > /dev/null
+ fi
+ j=$((j + 1))
+ done
+ setfib -F ${i} route delete -net -inet6 \
+ 2001:2:1234::2 2001:2:${i}::2 > /dev/null 2>&1 || true
+ setfib -F ${i} route add -net -inet6 \
+ 2001:2:1234::2 2001:2:${i}::2 > /dev/null
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking()
+{
+ local _maxfib i
+ _maxfib=$1
+
+ # Cleanup networking again.
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias
+ setfib -F ${i} route delete -net -inet6 \
+ 2001:2:1234::2 2001:2:${i}::2 > /dev/null
+ i=$((i + 1))
+ done
+}
+
+_fwd_fib_symmetric_destructive_defroute_middle_ifconfig()
+{
+ local _n _maxfib i
+ _n="$1"
+ _maxfib=$2
+
+ _fwd_fib_symmetric_destructive_defroute_middle_setup_networking \
+ ${_maxfib}
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ ifconfig ${IFACE} fib ${i}
+ ifconfig ${IFACEFAR} fib ${i}
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+ i=$((i + 1))
+ done
+
+ _fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \
+ ${_maxfib}
+}
+
+_fwd_fib_symmetric_destructive_defroute_middle_ipfw()
+{
+ local _n _maxfib i _port
+ _n="$1"
+ _maxfib=$2
+
+ _fwd_fib_symmetric_destructive_defroute_middle_setup_networking \
+ ${_maxfib}
+
+ i=0
+ while test ${i} -lt ${_maxfib}; do
+ _port=$((CTRLPORT + 1 + i))
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 128 via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ dst-port ${_port} via ${IFACE} in > /dev/null
+
+ ipfw add 100 setfib ${i} ipv6-icmp from any to any \
+ icmp6types 129 via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} tcp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+ ipfw add 100 setfib ${i} udp from any to any \
+ src-port ${_port} via ${IFACEFAR} in > /dev/null
+
+ setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
+ wait_remote_ready "START_${_n}_${i}"
+ ipfw -q zero > /dev/null
+ # Nothing to do for the middle node testing the default.
+ sleep 1
+ wait_remote_ready "STOP_${_n}_${i}"
+ report_ipfw_count
+
+ ipfw delete 100 > /dev/null
+ i=$((i + 1))
+ done
+
+ _fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \
+ ${_maxfib}
+}
+
+fwd_fib_symmetric_destructive_defroute_ifconfig()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_destructive_defroute_ifconfig"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_destructive_defroute_left \
+ ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_destructive_defroute_middle_ifconfig \
+ ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_destructive_defroute_right \
+ ${_n} ${_maxfib} ;;
+ esac
+}
+
+fwd_fib_symmetric_destructive_defroute_ipfw()
+{
+ local _maxfib _n
+ _maxfib=$1
+
+ _n="fwd_fib_symmetric_destructive_defroute_ipfw"
+
+ print_debug "${_n} ${_maxfib}"
+ case ${node} in
+ left) _fwd_fib_symmetric_destructive_defroute_left \
+ ${_n} ${_maxfib} ;;
+ middle) _fwd_fib_symmetric_destructive_defroute_middle_ipfw \
+ ${_n} ${_maxfib} ;;
+ right) _fwd_fib_symmetric_destructive_defroute_right \
+ ${_n} ${_maxfib} ;;
+ esac
+}
+
+################################################################################
+#
+# MAIN
+#
+
+# Same for all hosts.
+if test `sysctl -n security.jail.jailed` -eq 0; then
+ kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw
+fi
+ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system"
+ipfw add 65000 permit ip from any to any > /dev/null 2>&1
+
+# Per host setup.
+setup_networking
+reachability_check
+
+#
+# Tests
+#
+
+fwd_default_fib_symmetric
+fwd_default_fib_symmetric_ifconfig
+fwd_default_fib_symmetric_ipfw
+
+fwd_fib_symmetric_ifconfig ${RT_NUMFIBS}
+fwd_fib_symmetric_ipfw ${RT_NUMFIBS}
+
+fwd_fib_asymmetric_ifconfig ${RT_NUMFIBS}
+fwd_fib_asymmetric_ipfw ${RT_NUMFIBS}
+
+fwd_fib_symmetric_destructive_ifconfig ${RT_NUMFIBS}
+fwd_fib_symmetric_destructive_ipfw ${RT_NUMFIBS}
+
+fwd_fib_symmetric_destructive_defroute_ifconfig ${RT_NUMFIBS}
+fwd_fib_symmetric_destructive_defroute_ipfw ${RT_NUMFIBS}
+
+# Per host cleanup.
+cleanup_networking
+
+# end
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/initiator.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/initiator.sh Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,1521 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Cisco Systems, Inc.
+# All rights reserved.
+#
+# This software was developed by Bjoern Zeeb under contract to
+# Cisco Systems, Inc..
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: head/tools/test/netfibs/initiator.sh 232114 2012-02-24 14:13:06Z bz $
+#
+
+# We will use the RFC5180 (and Errata) benchmarking working group prefix
+# 2001:0002::/48 for testing.
+PREFIX="2001:2:"
+
+# Set IFACE to the real interface you want to run the test on.
+: ${IFACE:=lo0}
+
+# Number of seconds to wait for peer node to synchronize for test.
+: ${WAITS:=120}
+
+# Control port we use to exchange messages between nodes to sync. tests, etc.
+: ${CTRLPORT:=6666}
+
+# Get the number of FIBs from the kernel.
+RT_NUMFIBS=`sysctl -n net.fibs`
+
+OURADDR="2001:2:ff00::1"
+PEERADDR="2001:2:ff00::2"
+PEERLINKLOCAL=""
+
+# By default all commands must succeed. Individual tests may disable this
+# temporary.
+set -e
+
+# Debug magic.
+case "${DEBUG}" in
+42) set -x ;;
+esac
+
+
+
+#
+# Helper functions.
+#
+check_rc()
+{
+ local _rc _exp _testno _testname _msg _r
+ _rc=$1
+ _exp=$2
+ _testno=$3
+ _testname="$4"
+ _msg="$5"
+
+ _r="not ok"
+ if test ${_rc} -eq ${_exp}; then
+ _r="ok"
+ fi
+ echo "${_r} ${_testno} ${_testname} # ${_msg} ${_rc} ${_exp}"
+}
+
+print_debug()
+{
+ local _msg
+ _msg="$*"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) echo "DEBUG: ${_msg}" >&2 ;;
+ esac
+}
+
+die()
+{
+ local _msg
+ _msg="$*"
+
+ echo "ERROR: ${_msg}" >&2
+ exit 1
+}
+
+#
+# Test functions.
+#
+
+# Make sure the local link-local and global addresses are reachable
+# from all FIBs.
+check_local_addr()
+{
+ local _l i testno
+
+ print_debug "Setting up interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ _l=`ifconfig ${IFACE} | awk '/inet6 fe80:/ { print $2 }'`
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+
+ printf "1..%d\n" `expr 2 \* ${RT_NUMFIBS}`
+ testno=1
+ i=0
+ set +e
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ print_debug "Testing FIB ${i}"
+
+ setfib -F${i} ping6 -n -c1 ${_l} > /dev/null 2>&1
+ check_rc $? 0 ${testno} "check_local_addr_${i}_l" \
+ "FIB ${i} ${_l}"
+ testno=$((testno + 1))
+
+ setfib -F${i} ping6 -n -c1 ${OURADDR} > /dev/null 2>&1
+ check_rc $? 0 ${testno} "check_local_addr_${i}_a" \
+ "FIB ${i} ${OURADDR}"
+ testno=$((testno + 1))
+
+ i=$((i + 1))
+ done
+ set -e
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias
+}
+
+
+# Cloned tun(4) devices behave differently on FIB 0 vs. FIB 1..n after creation
+# (they also do in IPv4).
+check_local_tun()
+{
+ local _l i testno IFACE _msg
+
+ IFACE=tun42
+ print_debug "Setting up interface ${IFACE}"
+ ifconfig ${IFACE} create
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ _l=`ifconfig ${IFACE} | awk '/inet6 fe80:/ { print $2 }'`
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+
+ printf "1..%d\n" `expr 2 \* ${RT_NUMFIBS}`
+ testno=1
+ _msg=""
+ i=0
+ set +e
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ print_debug "Testing FIB ${i}"
+ if test ${i} -gt 0; then
+ # Flag the well known behaviour as such.
+ _msg="TODO "
+ fi
+
+ setfib -F${i} ping6 -n -c1 ${_l} > /dev/null 2>&1
+ check_rc $? 0 ${testno} "check_local_addr_${i}_l" \
+ "${_msg}FIB ${i} ${_l}"
+ testno=$((testno + 1))
+
+ setfib -F${i} ping6 -n -c1 ${OURADDR} > /dev/null 2>&1
+ check_rc $? 0 ${testno} "check_local_addr_${i}_a" \
+ "${_msg}FIB ${i} ${OURADDR}"
+ testno=$((testno + 1))
+
+ i=$((i + 1))
+ done
+ set -e
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias
+ ifconfig ${IFACE} destroy
+}
+
+check_remote_up()
+{
+ local _l i testno
+
+ print_debug "Setting up interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ _l=`ifconfig ${IFACE} | awk '/inet6 fe80:/ { print $2 }'`
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+
+
+
+}
+
+send_greeting()
+{
+ local _l _greeting _keyword _fib _fibs _linklocal
+
+ print_debug "Setting up interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ _l=`ifconfig ${IFACE} | awk '/inet6 fe80:/ { print $2 }'`
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+
+ # Cleanup firewall and install rules to always allow NS/NA to succeed.
+ # The latter is needed to allow indvidiual less specific later rules
+ # from test cases to just disallow any IPv6 traffic on a matching FIB.
+ ipfw -f flush > /dev/null 2>&1
+ ipfw add 65000 permit ip from any to any > /dev/null 2>&1
+ ipfw add 5 permit ipv6-icmp from any to any icmp6types 135,136 fib 0 \
+ via ${IFACE} out > /dev/null 2>&1
+
+ set +e
+ i=0
+ rc=-1
+ while test ${i} -lt ${WAITS} -a ${rc} -ne 0; do
+ print_debug "Sending greeting #${i} to peer"
+ _greeting=`echo "SETUP ${RT_NUMFIBS} ${_l}" | \
+ nc -6 -w 1 ${PEERADDR} ${CTRLPORT}`
+ rc=$?
+ i=$((i + 1))
+ # Might sleep longer in total but better than to DoS
+ # and not get anywhere.
+ sleep 1
+ done
+ set -e
+
+ read _keyword _fibs _linklocal <<EOI
+${_greeting}
+EOI
+ print_debug "_keyword=${_keyword}"
+ print_debug "_fibs=${_fibs}"
+ print_debug "_linklocal=${_linklocal}"
+ case ${_keyword} in
+ SETUP) ;;
+ *) die "Got invalid keyword in greeting: ${_greeting}"
+ ;;
+ esac
+ if test ${_fibs} -ne ${RT_NUMFIBS}; then
+ die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
+ "greeting: ${_greeting}"
+ fi
+ PEERLINKLOCAL=${_linklocal}
+
+ # Swap the zoneid to the local interface scope.
+ PEERLINKLOCAL=${PEERLINKLOCAL%%\%*}"%${IFACE}"
+
+ print_debug "Successfully exchanged greeting. Peer at ${PEERLINKLOCAL}"
+}
+
+cleanup()
+{
+
+ # Cleanup ipfw.
+ ipfw delete 5 > /dev/null 2>&1
+
+ print_debug "Removing address from interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias
+}
+
+testtx_icmp6()
+{
+ local _n _transfer i testno _txt _fibtxt _rc _ec _p
+ _n="$1"
+ _transfer=$2
+
+ printf "1..%d\n" `expr 2 \* ${RT_NUMFIBS}`
+ testno=1
+ set +e
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ _txt="${_n}${i}"
+ print_debug "Testing ${_txt}"
+ _fibtxt=`echo "${_txt}" | hd -v | cut -b11-60 | tr -d ' \r\n'`
+
+ eval _rc="\${rc_${i}_l}"
+ setfib -F${i} ping6 -n -c1 -p ${_fibtxt} \
+ ${PEERLINKLOCAL} > /dev/null 2>&1
+ _ec=$?
+ # We need to normalize the exit code of ping6.
+ case ${_ec} in
+ 0) ;;
+ *) _ec=1 ;;
+ esac
+ check_rc ${_ec} ${_rc} ${testno} "${_txt}_l" \
+ "FIB ${i} ${PEERLINKLOCAL}"
+ testno=$((testno + 1))
+
+ # If doing multiple transfer networks, replace PEERADDR.
+ _p="${PEERADDR}"
+ case ${_transfer} in
+ 1) PEERADDR=2001:2:${i}::2 ;;
+ esac
+
+ eval _rc="\${rc_${i}_a}"
+ setfib -F${i} ping6 -n -c1 -p ${_fibtxt} ${PEERADDR} \
+ > /dev/null 2>&1
+ _ec=$?
+ # We need to normalize the exit code of ping6.
+ case ${_ec} in
+ 0) ;;
+ *) _ec=1 ;;
+ esac
+ check_rc ${_ec} ${_rc} ${testno} "${_txt}_a" \
+ "FIB ${i} ${PEERADDR}"
+ testno=$((testno + 1))
+
+ # Restore PEERADDR.
+ PEERADDR="${_p}"
+
+ i=$((i + 1))
+ done
+ set -e
+}
+
+nc_send_recv()
+{
+ local _fib _loops _msg _expreply _addr _port _opts i
+ _fib=$1
+ _loops=$2
+ _msg="$3"
+ _expreply="$4"
+ _addr=$5
+ _port=$6
+ _opts="$7"
+
+ i=0
+ while test ${i} -lt ${_loops}; do
+ i=$((i + 1))
+ case "${USE_SOSETFIB}" in
+ 1)
+ _reply=`echo "${_msg}" | \
+ nc -V ${_fib} ${_opts} ${_addr} ${_port}`
+ ;;
+ *)
+ _reply=`echo "${_msg}" | \
+ setfib -F${_fib} nc ${_opts} ${_addr} ${_port}`
+ ;;
+ esac
+ if test "${_reply}" != "${_expreply}"; then
+ if test ${i} -lt ${_loops}; then
+ sleep 1
+ else
+ # Must let caller decide how to handle the error.
+ # die "Got invalid reply from peer." \
+ # "Expected '${_expreply}', got '${_reply}'"
+ return 1
+ fi
+ else
+ break
+ fi
+ done
+ return 0
+}
+
+testtx_tcp_udp()
+{
+ local _n _o _f testno i _fibtxt
+ _n="$1"
+ _o="$2"
+ _f="$3"
+
+ printf "1..%d\n" `expr 2 \* ${RT_NUMFIBS}`
+ testno=1
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ print_debug "Testing ${_f} ${i}"
+
+ eval _rc="\${rc_${i}_l}"
+ _fibtxt="${_n}_${i}_l ${_f} ${i} ${PEERLINKLOCAL}"
+ nc_send_recv ${i} 1 "${_fibtxt}" "${_fibtxt}" ${PEERLINKLOCAL} \
+ ${CTRLPORT} "-6 ${_o} -w1"
+ check_rc $? ${_rc} ${testno} "${_fibtxt}"
+ testno=$((testno + 1))
+
+ eval _rc="\${rc_${i}_a}"
+ _fibtxt="${_n}_${i}_a ${_f} ${i} ${PEERADDR}"
+ nc_send_recv ${i} 1 "${_fibtxt}" "${_fibtxt}" ${PEERADDR} \
+ ${CTRLPORT} "-6 ${_o} -w1"
+ check_rc $? ${_rc} ${testno} "${_fibtxt}"
+ testno=$((testno + 1))
+
+ i=$((i + 1))
+ done
+}
+
+# setfib TCP|UDP/IPv6 test on link-local and global address of peer from all FIBs.
+testtx_ulp6_connected()
+{
+ local _fibtxt _reply _n _o _rc _fib _f _opts
+ _n=$1
+ _o="$2"
+ _fib=$3
+
+ case "${USE_SOSETFIB}" in
+ 1) _f="SO_SETFIB" ;;
+ *) _f="SETFIB" ;;
+ esac
+
+ if test "${_o}" == "-i" -a "${_f}" == "SO_SETFIB"; then
+ print_debug "Skipping icmp6 tests for SO_SETFIB."
+ return 0
+ fi
+
+ # Clear the neighbor table to get deterministic runs.
+ ndp -cn > /dev/null 2>&1
+
+ case "${_o}" in
+ -i) _opts="" ;; # Use TCP for START/DONE.
+ *) _opts="${_o}" ;;
+ esac
+
+ set +e
+ # Let peer know that we are about to start.
+ _msg="START ${_n}"
+ nc_send_recv ${_fib} ${WAITS} "${_msg}" "${_msg}" ${PEERADDR} \
+ ${CTRLPORT} "-6 ${_opts} -w1"
+ case $? in
+ 0) ;;
+ *) die "Got invalid reply from peer." \
+ "Expected '${_msg}', got '${_reply}'" ;;
+ esac
+
+ case "${_o}" in
+ -i) testtx_icmp6 "${_n}" ;;
+ *) testtx_tcp_udp "${_n}" "${_o}" "${_f}" ;;
+ esac
+
+ # Let peer know that we are done with this test to move to next.
+ # This must immediately succeed.
+ _msg="DONE ${_n}"
+ nc_send_recv ${_fib} ${WAITS} "${_msg}" "${_msg}" ${PEERADDR} \
+ ${CTRLPORT} "-6 ${_opts} -w1"
+ case $? in
+ 0) ;;
+ *) die "Got invalid reply from peer." \
+ "Expected '${_msg}', got '${_reply}'" ;;
+ esac
+ set -e
+
+ print_debug "Successfully received status update '${_reply}'."
+}
+
+################################################################################
+#
+# ping6|TCP/UDP connect link-local and global address of peer from all FIBs.
+# Default reachability test.
+#
+testtx_icmp6_connected()
+{
+ local i
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ eval rc_${i}_a=0
+ i=$((i + 1))
+ done
+
+ testtx_ulp6_connected "testtx_icmp6_connected" "-i" 0
+}
+
+testtx_tcp6_connected()
+{
+ local i
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ eval rc_${i}_a=0
+ i=$((i + 1))
+ done
+
+ testtx_ulp6_connected testtx_tcp6_connected "" 0
+}
+
+testtx_udp6_connected()
+{
+ local i
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ eval rc_${i}_a=0
+ i=$((i + 1))
+ done
+
+ testtx_ulp6_connected testtx_udp6_connected "-u" 0
+}
+
+################################################################################
+#
+# Use ipfw to return unreach messages for all but one FIB. Rotate over all.
+# Making sure error messages are properly returned.
+#
+testtx_ulp6_connected_blackhole()
+{
+ local fib i _n _o
+ _n="$1"
+ _o="$2"
+
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+
+ print_debug "${_n} ${fib}"
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ipfw delete $((100 + i)) > /dev/null 2>&1 || true
+ case ${i} in
+ ${fib})
+ eval rc_${i}_l=0
+ eval rc_${i}_a=0
+ ;;
+ *) eval rc_${i}_l=1
+ eval rc_${i}_a=1
+ ipfw add $((100 + i)) unreach6 admin-prohib \
+ ip6 from any to any fib ${i} via ${IFACE} \
+ out > /dev/null 2>&1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+
+ testtx_ulp6_connected "${_n}${fib}" "${_o}" ${fib}
+ case ${DEBUG} in
+ ''|0) ;;
+ *) ipfw show ;;
+ esac
+ fib=$((fib + 1))
+ done
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ipfw delete $((100 + fib)) > /dev/null 2>&1 || true
+ fib=$((fib + 1))
+ done
+}
+
+testtx_icmp6_connected_blackhole()
+{
+
+ testtx_ulp6_connected_blackhole \
+ "testtx_icmp6_connected_blackhole" "-i"
+}
+
+testtx_tcp6_connected_blackhole()
+{
+
+ testtx_ulp6_connected_blackhole \
+ "testtx_tcp6_connected_blackhole" ""
+}
+
+testtx_udp6_connected_blackhole()
+{
+
+ testtx_ulp6_connected_blackhole \
+ "testtx_udp6_connected_blackhole" "-u"
+}
+
+################################################################################
+#
+# Setup a different transfer net on each FIB. Delete all but one connected
+# route in all FIBs (e.g. FIB 0 uses prefix 0, FIB 1 uses prefix 1 , ...).
+#
+# Need to tag NS/NA incoming to the right FIB given the default FIB does not
+# know about the prefix and thus cannot do proper source address lookups for
+# replying otherwise. Use ipfw.
+#
+testtx_ulp6_connected_transfernets()
+{
+ local fib i _n _o _p
+ _n="$1"
+ _o="$2"
+
+ # Setup transfer networks and firewall.
+ ipfw delete 10 > /dev/null 2>&1 || true
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 alias
+ ipfw add 10 setfib ${fib} ipv6-icmp from 2001:2:${fib}::/64 \
+ to any ip6 icmp6types 135,136 via ${IFACE} in \
+ > /dev/null 2>&1
+ # Remove connected routes from all but matching FIB.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case ${i} in
+ ${fib});;
+ *) setfib -F${i} route delete -inet6 \
+ -net 2001:2:${fib}:: > /dev/null 2>&1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+ fib=$((fib + 1))
+ done
+
+ # Save PEERADDR
+ _p=${PEERADDR}
+
+ # Run tests.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ PEERADDR=2001:2:${fib}::2
+
+ print_debug "${_n} ${fib}"
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ case ${i} in
+ ${fib})
+ eval rc_${i}_a=0
+ ;;
+ *) eval rc_${i}_a=1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+
+ testtx_ulp6_connected "${_n}${fib}" "${_o}" ${fib}
+ fib=$((fib + 1))
+ done
+
+ # Restore PEERADDR
+ PEERADDR=${_p}
+
+ # Cleanup transfer networks and firewall.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias
+ fib=$((fib + 1))
+ done
+ ipfw delete 10 > /dev/null 2>&1
+}
+
+testtx_icmp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_icmp6_connected_transfernets" "-i"
+}
+
+testtx_tcp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_tcp6_connected_transfernets" ""
+}
+
+testtx_udp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_udp6_connected_transfernets" "-u"
+}
+
+################################################################################
+#
+# Setup a different transfernet on each FIB. Delete all but one connected
+# route in all FIBs (e.g. FIB 0 uses prefix 0, FIB 1 uses prefix 1 , ...).
+#
+# Need to tag NS/NA incoming to the right FIB given the default FIB does not
+# know about the prefix and thus cannot do proper source address lookups for
+# replying otherwise. Use ifconfig IFACE fib.
+#
+testtx_ulp6_connected_ifconfig_transfernets()
+{
+ local fib i _n _o _p
+ _n="$1"
+ _o="$2"
+
+ # Setup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 alias
+ # Remove connected routes from all but matching FIB.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case ${i} in
+ ${fib});;
+ *) setfib -F${i} route delete -inet6 \
+ -net 2001:2:${fib}:: > /dev/null 2>&1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+ fib=$((fib + 1))
+ done
+
+ # Save PEERADDR
+ _p=${PEERADDR}
+
+ # Run tests.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ PEERADDR=2001:2:${fib}::2
+
+ print_debug "${_n} ${fib}"
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ case ${i} in
+ ${fib})
+ eval rc_${i}_a=0
+ ;;
+ *) eval rc_${i}_a=1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+
+ ifconfig ${IFACE} fib ${fib}
+
+ testtx_ulp6_connected "${_n}${fib}" "${_o}" ${fib}
+ fib=$((fib + 1))
+ done
+
+ # Restore PEERADDR
+ PEERADDR=${_p}
+
+ # Cleanup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias
+ fib=$((fib + 1))
+ done
+ ifconfig ${IFACE} fib 0
+}
+
+testtx_icmp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_ifconfig_transfernets \
+ "testtx_icmp6_connected_ifconfig_transfernets" "-i"
+}
+
+
+testtx_tcp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_ifconfig_transfernets \
+ "testtx_tcp6_connected_ifconfig_transfernets" ""
+}
+
+testtx_udp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_ifconfig_transfernets \
+ "testtx_udp6_connected_ifconfig_transfernets" "-u"
+}
+
+################################################################################
+#
+# Make destination reachable through the same default route in each FIB only.
+# Run standard reachability test.
+#
+testtx_ulp6_gateway()
+{
+ local fib i _n _o _p
+ _n="$1"
+ _o="$2"
+
+ # Setup default gateway and expected error codes.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1 || true
+ setfib -F${fib} route add -inet6 -net default ${PEERADDR} \
+ > /dev/null 2>&1
+ case "${_o}" in
+ -i) eval rc_${fib}_l=0 ;; # ICMPv6 will succeed
+ *) eval rc_${fib}_l=1 ;;
+ esac
+ eval rc_${fib}_a=0
+ fib=$((fib + 1))
+ done
+
+ # Save PEERADDR
+ _p=${PEERADDR}
+ PEERADDR="2001:2:ff01::2"
+
+ # Run tests.
+ print_debug "${_n}"
+ testtx_ulp6_connected "${_n}" "${_o}" 0
+
+ # Restore PEERADDR
+ PEERADDR=${_p}
+
+ # Cleanup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1
+ fib=$((fib + 1))
+ done
+}
+
+testtx_icmp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_icmp6_gateway" "-i"
+}
+
+testtx_tcp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_tcp6_gateway" ""
+}
+
+testtx_udp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_udp6_gateway" "-u"
+}
+
+################################################################################
+#
+# Make destination reachable through a different default route in each FIB.
+# Generate a dedicated transfer network for that in each FIB. Delete all but
+# one connected route in all FIBs (e.g. FIB 0 uses prefix 0, ...).
+#
+# Have a default route present in each FIB all time.
+#
+# Need to tag NS/NA incoming to the right FIB given the default FIB does not
+# know about the prefix and thus cannot do proper source address lookups for
+# replying otherwise. Use ipfw.
+#
+#
+testtx_ulp6_transfernets_gateways()
+{
+ local fib i _n _o _p
+ _n="$1"
+ _o="$2"
+
+ # Setup transfer networks, default routes, and firewall.
+ fib=0
+ ipfw delete 10 > /dev/null 2>&1 || true
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 alias \
+ > /dev/null 2>&1
+ ipfw add 10 setfib ${fib} ipv6-icmp \
+ from 2001:2:${fib}::/64 to any ip6 icmp6types 135,136 \
+ via ${IFACE} in > /dev/null 2>&1
+ # Remove connected routes from all but matching FIB.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case ${i} in
+ ${fib});;
+ *) setfib -F${i} route delete -inet6 \
+ -net 2001:2:${fib}:: > /dev/null 2>&1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+ # Add default route.
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1 || true
+ setfib -F${fib} route add -inet6 -net default \
+ 2001:2:${fib}::2 > /dev/null 2>&1
+ fib=$((fib + 1))
+ done
+
+ # Save PEERADDR
+ _p=${PEERADDR}
+ PEERADDR="2001:2:ff01::2"
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case "${_o}" in
+ -i) eval rc_${i}_l=0 ;; # ICMPv6 will succeed
+ *) eval rc_${i}_l=1 ;;
+ esac
+ eval rc_${i}_a=0
+ i=$((i + 1))
+ done
+
+ # Run tests.
+ print_debug "${_n}"
+ testtx_ulp6_connected "${_n}" "${_o}" 0
+
+ # Restore PEERADDR
+ PEERADDR=${_p}
+
+ # Cleanup default routes, transfer networks, and firewall.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1
+ fib=$((fib + 1))
+ done
+ ipfw delete 10 > /dev/null 2>&1
+}
+
+testtx_icmp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_icmp6_transfernets_gateways" "-i"
+}
+
+testtx_tcp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_tcp6_transfernets_gateways" ""
+}
+
+testtx_udp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_udp6_transfernets_gateways" "-u"
+}
+
+################################################################################
+#
+# Make destination reachable through a different default route in each FIB.
+# Generate a dedicated transfer network for that in each FIB. Delete all but
+# one connected route in all FIBs (e.g. FIB 0 uses prefix 0, ...).
+#
+# Only have a default route present in 1 FIB at a time.
+#
+# Need to tag NS/NA incoming to the right FIB given the default FIB does not
+# know about the prefix and thus cannot do proper source address lookups for
+# replying otherwise. Use ipfw.
+#
+testtx_ulp6_transfernets_gateway()
+{
+ local fib i _n _o _p
+ _n="$1"
+ _o="$2"
+
+ # Setup transfer networks, default routes, and firewall.
+ fib=0
+ ipfw delete 10 > /dev/null 2>&1 || true
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 alias \
+ > /dev/null 2>&1
+ ipfw add 10 setfib ${fib} ipv6-icmp \
+ from 2001:2:${fib}::/64 to any ip6 icmp6types 135,136 \
+ via ${IFACE} in > /dev/null 2>&1
+ # Remove connected routes from all but matching FIB.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case ${i} in
+ ${fib});;
+ *) setfib -F${i} route delete -inet6 \
+ -net 2001:2:${fib}:: > /dev/null 2>&1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+ fib=$((fib + 1))
+ done
+
+ # Save PEERADDR
+ _p=${PEERADDR}
+ PEERADDR="2001:2:ff01::2"
+
+ # Run tests.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+
+ print_debug "${_n} ${fib}"
+
+ # Setup expected return values.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case "${_o}" in
+ -i) eval rc_${i}_l=0 ;; # ICMPv6 will succeed
+ *) eval rc_${i}_l=1 ;;
+ esac
+ case ${i} in
+ ${fib})
+ eval rc_${i}_a=0
+ ;;
+ *) eval rc_${i}_a=1
+ ;;
+ esac
+ i=$((i + 1))
+ done
+
+ # Add default route.
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1 || true
+ setfib -F${fib} route add -inet6 -net default \
+ 2001:2:${fib}::2 > /dev/null 2>&1
+
+ testtx_ulp6_connected "${_n}${fib}" "${_o}" ${fib}
+
+ # Delete default route again.
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1
+ fib=$((fib + 1))
+ done
+
+ # Restore PEERADDR
+ PEERADDR=${_p}
+
+ # Cleanup default routes, transfer networks, and firewall.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} route delete -inet6 -net default \
+ > /dev/null 2>&1
+ ifconfig ${IFACE} inet6 2001:2:${fib}::1/64 -alias \
+ > /dev/null 2>&1
+ fib=$((fib + 1))
+ done
+ ipfw delete 10 > /dev/null 2>&1
+}
+
+testtx_icmp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_icmp6_transfernets_gateway" "-i"
+}
+
+
+testtx_tcp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_tcp6_transfernets_gateway" ""
+}
+
+testtx_udp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_udp6_transfernets_gateway" "-u"
+}
+
+
+################################################################################
+#
+# RX tests (Remotely originated connections). The FIB tests happens on peer.
+#
+# # For IPFW, IFCONFIG
+# # For each FIB
+# # Send OOB well known to work START, wait for reflect
+# # Send probe, wait for reply with FIB# or RST/ICMP6 unreach
+# # (in case of ICMP6 use magic like ipfw count and OOB reply)
+# # Send OOB well known to work DONE, wait for reflect
+# # Compare real with expected results.
+#
+testrx_results()
+{
+ local _r _n _fib i count _instances _transfer _o
+ _fib="$1"
+ _n="$2"
+ _r="$3"
+ _instances=$4
+ _transfer=$5
+ _o="$6"
+
+ print_debug "testrx_results ${_fib} ${_n} ${_r} ${_instances}"
+
+ # Trim "RESULT "
+ _r=${_r#* }
+
+ echo "1..${RT_NUMFIBS}"
+ while read i count; do
+ if test ${_instances} -gt 1; then
+ if test ${count} -gt 0; then
+ echo "ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count} (tested)"
+ else
+ echo "not ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count} (tested)"
+ fi
+ else
+ case ${i} in
+ ${_fib})
+ if test ${count} -gt 0; then
+ echo "ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count} (tested)"
+ else
+ echo "not ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count} (tested)"
+ fi
+ ;;
+ *) if test ${count} -eq 0; then
+ echo "ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count}"
+ else
+ echo "not ok ${i} ${_n}result_${i} #" \
+ "FIB ${i} ${count}"
+ fi
+ ;;
+ esac
+ fi
+ i=$((i + 1))
+ done <<EOI
+`echo "${_r}" | tr ',' '\n'`
+EOI
+
+}
+
+testrx_tcp_udp()
+{
+ local _n _o _f testno i _fibtxt _instances _res _port _transfer _p
+ _n="$1"
+ _o="$2"
+ _f="$3"
+ _instances=$4
+ _transfer=$5
+
+ # Unused so far.
+ : ${_instances:=1}
+
+ printf "1..%d\n" `expr 2 \* ${RT_NUMFIBS}`
+ testno=1
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ print_debug "Testing ${_f} ${i}"
+
+ # We are expecting the FIB number (only) to be returned.
+ eval _rc="\${rc_${i}_l}"
+ _fibtxt="${_n}_${i}_l ${_f} ${i} ${PEERLINKLOCAL}"
+ if test ${_instances} -gt 1; then
+ _res="FIB ${i}"
+ _port=$((CTRLPORT + 1000 + i))
+ else
+ _res="${_fibtxt}"
+ _port=${CTRLPORT}
+ fi
+ nc_send_recv ${i} 1 "${_fibtxt}" "${_res}" ${PEERLINKLOCAL} \
+ ${_port} "-6 ${_o} -w1"
+ check_rc $? ${_rc} ${testno} "${_fibtxt}" "${_reply}"
+ testno=$((testno + 1))
+
+ # If doing multiple transfer networks, replace PEERADDR.
+ _p="${PEERADDR}"
+ case ${_transfer} in
+ 1) PEERADDR=2001:2:${i}::2 ;;
+ esac
+
+ eval _rc="\${rc_${i}_a}"
+ _fibtxt="${_n}_${i}_a ${_f} ${i} ${PEERADDR}"
+ if test ${_instances} -gt 1; then
+ _res="FIB ${i}"
+ _port=$((CTRLPORT + 1000 + i))
+ else
+ _res="${_fibtxt}"
+ _port=${CTRLPORT}
+ fi
+ nc_send_recv ${i} 1 "${_fibtxt}" "${_res}" ${PEERADDR} \
+ ${_port} "-6 ${_o} -w1"
+ check_rc $? ${_rc} ${testno} "${_fibtxt}" "${_reply}"
+ testno=$((testno + 1))
+
+ # Restore PEERADDR.
+ PEERADDR="${_p}"
+
+ i=$((i + 1))
+ done
+}
+
+
+testrx_setup_transfer_networks()
+{
+ local i
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::1/64 -alias \
+ > /dev/null 2>&1 || true
+ ifconfig ${IFACE} inet6 2001:2:${i}::1/64 alias
+ i=$((i + 1))
+ done
+}
+
+testrx_cleanup_transfer_networks()
+{
+ local i
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::1/64 -alias \
+ > /dev/null 2>&1
+ i=$((i + 1))
+ done
+}
+
+
+testrx_run_test()
+{
+ local _n _t _fib _o _txt _msg i _reply _instances _destructive _transfer
+ _n="$1"
+ _t="$2"
+ _fib=$3
+ _o="$4"
+ _instances=$5
+ _detsructive=$6
+ _transfer=$7
+
+ # Netcat options (for UDP basically).
+ case "${_o}" in
+ -i) _opts="" ;; # Use TCP for START/DONE.
+ *) _opts="${_o}" ;;
+ esac
+
+ # Combined test case base name.
+ case ${USE_SOSETFIB} in
+ 0) _f="setfib" ;;
+ 1) _f="so_setfib" ;;
+ *) die "Unexpected value for SO_SETFIB: ${SO_SETFIB}" ;;
+ esac
+ _txt="${_n}_${_f}_${_t}_${_fib}_${_instances}_${_detsructive}_${_transfer}"
+
+ print_debug "Starting test '${_txt}' (for ${_instances} instances)."
+
+ case ${_transfer} in
+ 1) testrx_setup_transfer_networks ;;
+ esac
+
+ # Let the other side a chance to get ready as well.
+ sleep 1
+
+ set +e
+ # Let peer know that we are about to start.
+ _msg="START ${_txt}"
+ nc_send_recv ${_fib} ${WAITS} "${_msg}" "${_msg}" ${PEERADDR} \
+ ${CTRLPORT} "-6 ${_opts} -w1"
+ case $? in
+ 0) ;;
+ *) die "Got invalid reply from peer." \
+ "Expected '${_msg}', got '${_reply}'" ;;
+ esac
+
+ # Let the other side a chance to get ready as well.
+ sleep 1
+
+ # Send probe.
+ case "${_o}" in
+ -i) testtx_icmp6 "${_txt}_" ${_transfer} ;;
+ *) testrx_tcp_udp "${_txt}" "${_o}" "${_fib}" ${_instances} \
+ ${_transfer} ;;
+ esac
+
+ # Let peer know that we are done with this test to move to next.
+ # This must immediately succeed.
+ _msg="DONE ${_txt}"
+ nc_send_recv ${_fib} ${WAITS} "${_msg}" "${_msg}" ${PEERADDR} \
+ ${CTRLPORT} "-6 ${_opts} -w1"
+ case $? in
+ 0) ;;
+ *) die "Got invalid reply from peer." \
+ "Expected '${_msg}', got '${_reply}'" ;;
+ esac
+
+ # Collect and validate the results. Always use TCP.
+ sleep 1
+ set +e
+ nc_send_recv ${_fib} 1 "RESULT REQUEST" "" ${PEERADDR} \
+ ${CTRLPORT} "-6 -w1"
+ case "${_reply}" in
+ RESULT\ *) testrx_results ${_fib} "${_txt}_" "${_reply}" ${_instances} \
+ ${_transfer} "${_o}"
+ ;;
+ *) die "Got invalid reply from peer." \
+ "Expected 'RESULT ...', got '${_reply}'" ;;
+ esac
+ set -e
+
+ case ${_transfer} in
+ 1) testrx_cleanup_transfer_networks ;;
+ esac
+
+ print_debug "Successfully received status update '${_reply}'."
+}
+
+testrx_main_setup_rc()
+{
+ local _n _t _fib _o _instances _destructive _transfer i
+ _n="$1"
+ _t="$2"
+ _fib=$3
+ _o="$4"
+ _instances=$5
+ _destructive=$6
+ _transfer=$7
+
+ # Setup expected return values.
+ if test ${_destructive} -eq 0; then
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ eval rc_${i}_a=0
+ i=$((i + 1))
+ done
+ else
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ eval rc_${i}_l=0
+ case ${i} in
+ ${_fib}) eval rc_${i}_a=0 ;;
+ *) # ICMP6 cannot be distinguished and will
+ # always work in single transfer network.
+ case "${_o}" in
+ -i) case ${_transfer} in
+ 0) eval rc_${i}_a=0 ;;
+ 1) eval rc_${i}_a=1 ;;
+ esac
+ ;;
+ *) if test ${_instances} -eq 1 -a \
+ ${_transfer} -eq 0; then
+ eval rc_${i}_a=0
+ else
+ eval rc_${i}_a=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ i=$((i + 1))
+ done
+ fi
+
+ print_debug "${_n}_${t}_${_fib} ${_instances} ${_destructive}" \
+ "${_transfer}"
+ testrx_run_test "${_n}" "${t}" ${_fib} "${_o}" ${_instances} \
+ ${_destructive} ${_transfer}
+}
+
+testrx_main()
+{
+ local _n _o s t fib _instances _destructive _transfer
+ _n="$1"
+ _o="$2"
+ _instances=$3
+
+ : ${_instances:=1}
+
+ print_debug "${_n}"
+ for _transfer in 1 0; do
+ for _destructive in 0 1; do
+ for t in ipfw ifconfig; do
+
+ print_debug "${_n}_${t}"
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+
+ testrx_main_setup_rc "${_n}" "${t}" \
+ ${fib} "${_o}" ${_instances} \
+ ${_destructive} ${_transfer}
+
+ fib=$((fib + 1))
+ done
+ done
+ done
+ done
+}
+
+################################################################################
+#
+#
+#
+
+testrx_icmp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main \
+ "testrx_icmp6_same_addr_one_fib_a_time" "-i"
+}
+
+testrx_tcp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main \
+ "testrx_tcp6_same_addr_one_fib_a_time" ""
+}
+
+
+testrx_udp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main \
+ "testrx_udp6_same_addr_one_fib_a_time" "-u"
+}
+
+
+################################################################################
+
+testrx_tcp6_same_addr_all_fibs_a_time()
+{
+
+ testrx_main \
+ "testrx_tcp6_same_addr_all_fibs_a_time" "" ${RT_NUMFIBS}
+}
+
+testrx_udp6_same_addr_all_fibs_a_time()
+{
+
+ testrx_main \
+ "testrx_udp6_same_addr_all_fibs_a_time" "-u" ${RT_NUMFIBS}
+}
+
+
+################################################################################
+#
+# Prereqs.
+#
+if test `sysctl -n security.jail.jailed` -eq 0; then
+ kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw
+
+ # Reduce the time we wait in case of no reply to 2s.
+ sysctl net.inet.tcp.keepinit=2000 > /dev/null 2>&1
+fi
+ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system"
+ipfw add 65000 permit ip from any to any > /dev/null 2>&1
+
+################################################################################
+#
+# Run tests.
+#
+
+# 64 cases at 16 FIBs.
+check_local_addr
+check_local_tun
+
+send_greeting
+
+# Initiator testing.
+for uso in 0 1; do
+
+ USE_SOSETFIB=${uso}
+
+ # Only run ICMP6 tests for the first loop.
+ # 160 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_connected && sleep 1
+ testtx_tcp6_connected && sleep 1
+ testtx_udp6_connected && sleep 1
+
+ # 2560 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_connected_blackhole && sleep 1
+ testtx_tcp6_connected_blackhole && sleep 1
+ testtx_udp6_connected_blackhole && sleep 1
+
+ # 2560 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_connected_transfernets && sleep 1
+ testtx_tcp6_connected_transfernets && sleep 1
+ testtx_udp6_connected_transfernets && sleep 1
+
+ # 2560 cases at 16 FIBs.
+ test ${uso} -ne 0 || \
+ testtx_icmp6_connected_ifconfig_transfernets && sleep 1
+ testtx_tcp6_connected_ifconfig_transfernets && sleep 1
+ testtx_udp6_connected_ifconfig_transfernets && sleep 1
+
+ # 160 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_gateway && sleep 1
+ testtx_tcp6_gateway && sleep 1
+ testtx_udp6_gateway && sleep 1
+
+ # 160 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_transfernets_gateways && sleep 1
+ testtx_tcp6_transfernets_gateways && sleep 1
+ testtx_udp6_transfernets_gateways && sleep 1
+
+ # 2560 cases at 16 FIBs.
+ test ${uso} -ne 0 || testtx_icmp6_transfernets_gateway && sleep 1
+ testtx_tcp6_transfernets_gateway && sleep 1
+ testtx_udp6_transfernets_gateway && sleep 1
+done
+
+# Receiver testing.
+for uso in 0 1; do
+
+ USE_SOSETFIB=${uso}
+
+ # Only expect ICMP6 tests for the first loop.
+ # 6144 cases at 16 FIBs.
+ test ${uso} -ne 0 || testrx_icmp6_same_addr_one_fib_a_time && sleep 1
+ # 12288 cases at 16 FIBs.
+ testrx_tcp6_same_addr_one_fib_a_time && sleep 1
+ # 12288 cases at 16 FIBs.
+ testrx_udp6_same_addr_one_fib_a_time && sleep 1
+
+ # 12288 cases at 16 FIBs.
+ testrx_tcp6_same_addr_all_fibs_a_time && sleep 1
+ # 12288 cases at 16 FIBs.
+ testrx_udp6_same_addr_all_fibs_a_time && sleep 1
+
+done
+
+cleanup
+
+# end
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/reflect.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/reflect.c Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2012 Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Bjoern Zeeb under contract to
+ * Cisco Systems, Inc..
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: head/tools/test/netfibs/reflect.c 231858 2012-02-17 04:26:24Z bz $
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static char *testcase;
+static int accepts;
+static int debug;
+static u_int fib = -1;
+static u_int reflectfib = -1;
+static uint16_t port = 6666;
+static char *addr;
+static int nostart;
+
+static int
+reflect_conn(int s, char *buf, size_t buflen, ssize_t l, struct sockaddr *sa,
+ socklen_t salen)
+{
+ ssize_t m;
+
+ if (l == -1)
+ err(EX_OSERR, "read()");
+ if (l == 0)
+ errx(EX_NOINPUT, "EOF");
+ if ((size_t)l > (buflen - 1))
+ errx(EX_DATAERR, "Input too long");
+ /* Nuke the \n from echo | netcat. */
+ buf[l-1] = '\0';
+
+ /*
+ * Match three cases: (1) START, (2) DONE, (3) anything else.
+ * For anything but START and DONE we just reflect everything.
+ */
+ /*
+ * We expected a "START testcase" on first connect. Otherwise it means
+ * that we are out of sync. Exit to not produce weird results.
+ */
+ if (accepts == 0 && nostart == 0) {
+ if (strncmp(buf, "START ", 6) != 0)
+ errx(EX_PROTOCOL, "Not received START on first "
+ "connect: %s", buf);
+ if (l < 8)
+ errx(EX_PROTOCOL, "START without test case name: %s",
+ buf);
+ if (strcmp(buf+6, testcase) != 0)
+ errx(EX_PROTOCOL, "START test case does not match "
+ "'%s': '%s'", testcase, buf+6);
+ }
+ /* If debug is on, log. */
+ if (debug > 0)
+ fprintf(stderr, "<< %s: %s\n", testcase, buf);
+
+ if (reflectfib != (u_int)-1)
+ l = snprintf(buf, sizeof(buf), "FIB %u\n", reflectfib);
+
+ /* If debug is on, log. */
+ if (debug > 0) {
+ buf[l-1] = '\0';
+ fprintf(stderr, ">> %s: %s\n", testcase, buf);
+ }
+
+ /* Reflect data with \n again. */
+ buf[l-1] = '\n';
+
+ if (sa != NULL) {
+ m = sendto(s, buf, l, 0, sa, salen);
+ } else
+ m = write(s, buf, l);
+ /* XXX This is simplified handling. */
+ if (m == -1 && sa != NULL && errno == EHOSTUNREACH)
+ warn("ignored expected: sendto(%s, %zd)", buf, l);
+ else if (m == -1 && (sa == NULL || errno != EHOSTUNREACH))
+ err(EX_OSERR, "write(%s, %zd)", buf, l);
+ else if (m != l)
+ err(EX_OSERR, "short write(%s, %zd) %zd", buf, l, m);
+
+
+ accepts++;
+
+ /* See if we got an end signal. */
+ if (strncmp(buf, "DONE", 4) == 0)
+ return (-2);
+ return (0);
+}
+
+static int
+reflect_tcp6_conn(int as)
+{
+ char buf[1500];
+ ssize_t l;
+ int error, s;
+
+ s = accept(as, NULL, NULL);
+ if (s == -1)
+ err(EX_OSERR, "accept()");
+
+ l = read(s, buf, sizeof(buf));
+ error = reflect_conn(s, buf, sizeof(buf), l, NULL, 0);
+ close(s);
+
+ return (error);
+}
+
+static int
+reflect_udp6_conn(int s)
+{
+ char buf[1500];
+ struct sockaddr_in6 from;
+ socklen_t fromlen;
+ ssize_t l;
+ int error;
+
+ fromlen = sizeof(from);
+ l = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from,
+ &fromlen);
+#if 0
+ if (l != -1) {
+ rc = connect(s, (struct sockaddr *)&from, fromlen);
+ if (rc == -1) {
+ if (inet_ntop(PF_INET6, &from, buf, sizeof(buf)) == NULL)
+ buf[0] = '\0';
+ err(EX_OSERR, "connect(%d, %s, %u)", s, buf, fromlen);
+ }
+ }
+#endif
+ error = reflect_conn(s, buf, sizeof(buf), l, (struct sockaddr *)&from,
+ fromlen);
+#if 0
+ if (l != -1) {
+ /* Undo the connect binding again. */
+ fromlen = sizeof(from);
+ bzero(&from, fromlen);
+ from.sin6_len = fromlen;
+ from.sin6_family = AF_INET6;
+ from.sin6_port = htons(port); /* This only gives us a ::1:port ::1:port binding */
+ rc = connect(s, (struct sockaddr *)&from, fromlen);
+ if (rc == -1) {
+ if (inet_ntop(PF_INET6, &from.sin6_addr, buf,
+ sizeof(buf)) == NULL)
+ buf[0] = '\0';
+ err(EX_OSERR, "un-connect(%d, %s, %u)", s, buf, fromlen);
+ }
+ }
+#endif
+
+ return (error);
+}
+
+static int
+reflect_6(int domain, int type)
+{
+ struct sockaddr_in6 sin6;
+ fd_set rset;
+ int i, rc, s;
+
+ /* Get us a listen socket. */
+ s = socket(domain, type, 0);
+ if (s == -1)
+ err(EX_OSERR, "socket()");
+
+ /*
+ * In case a FIB was given on cmd line, set it. Let the kernel do the
+ * the bounds check.
+ */
+ if (fib != (u_int)-1) {
+ rc = setsockopt(s, SOL_SOCKET, SO_SETFIB, &fib, sizeof(fib));
+ if (rc == -1)
+ err(EX_OSERR, "setsockopt(SO_SETFIB)");
+ }
+
+ /* Allow re-use. Otherwise restarting for the next test might error. */
+ i = 1;
+ rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+ if (rc == -1)
+ err(EX_OSERR, "setsockopt(SO_REUSEADDR)");
+ i = 1;
+ rc = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &i, sizeof(i));
+ if (rc == -1)
+ err(EX_OSERR, "setsockopt(SO_REUSEPORT)");
+
+ /* Bind address and port or just port. */
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(port);
+ sin6.sin6_flowinfo = 0;
+ bzero(&sin6.sin6_addr, sizeof(sin6.sin6_addr));
+ if (addr != NULL) {
+ rc = inet_pton(PF_INET6, addr, &sin6.sin6_addr);
+ if (rc == 0)
+ errx(EX_USAGE, "inet_pton()");
+ else if (rc == -1)
+ err(EX_OSERR, "inet_pton()");
+ else if (rc != 1)
+ errx(EX_SOFTWARE, "inet_pton()");
+ }
+ sin6.sin6_scope_id = 0;
+ rc = bind(s, (struct sockaddr *)&sin6, sizeof(sin6));
+ if (rc == -1)
+ err(EX_OSERR, "bind(%d)", s);
+
+ if (type == SOCK_STREAM) {
+ rc = listen(s, port);
+ if (rc == -1)
+ err(EX_OSERR, "listen(%d, %u)", s, port);
+ }
+
+ /*
+ * We shall never do more than one connection in parallel so can keep
+ * it simple.
+ */
+ do {
+ FD_ZERO(&rset);
+ FD_SET(s, &rset);
+ rc = select(s + 1, &rset, NULL, NULL, NULL);
+ if (rc == -1 && errno != EINTR)
+ err(EX_OSERR, "select()");
+
+ if (rc == 0 || errno == EINTR)
+ continue;
+
+ if (rc != 1)
+ errx(EX_OSERR, "select() miscounted 1 to %d", rc);
+ if (!FD_ISSET(s, &rset))
+ errx(EX_OSERR, "select() did not return our socket");
+
+ if (type == SOCK_STREAM)
+ rc = reflect_tcp6_conn(s);
+ else if (type == SOCK_DGRAM)
+ rc = reflect_udp6_conn(s);
+ else
+ errx(EX_SOFTWARE, "Unsupported socket type %d", type);
+ } while (rc == 0);
+ /* Turn end flagging into no error. */
+ if (rc == -2)
+ rc = 0;
+
+ /* Close listen socket. */
+ close(s);
+
+ return (rc);
+}
+
+static int
+reflect_tcp6(void)
+{
+
+ return (reflect_6(PF_INET6, SOCK_STREAM));
+}
+
+static int
+reflect_udp6(void)
+{
+
+ return (reflect_6(PF_INET6, SOCK_DGRAM));
+}
+
+int
+main(int argc, char *argv[])
+{
+ long long l;
+ char *dummy, *afname;
+ int ch, rc;
+
+ afname = NULL;
+ while ((ch = getopt(argc, argv, "A:dF:f:Np:t:T:")) != -1) {
+ switch (ch) {
+ case 'A':
+ addr = optarg;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'F':
+ l = strtoll(optarg, &dummy, 10);
+ if (*dummy != '\0' || l < 0)
+ errx(EX_USAGE, "Invalid FIB number");
+ fib = (u_int)l;
+ break;
+ case 'f':
+ l = strtoll(optarg, &dummy, 10);
+ if (*dummy != '\0' || l < 0)
+ errx(EX_USAGE, "Invalid FIB number");
+ reflectfib = (u_int)l;
+ break;
+ case 'N':
+ nostart=1;
+ break;
+ case 'p':
+ l = strtoll(optarg, &dummy, 10);
+ if (*dummy != '\0' || l < 0)
+ errx(EX_USAGE, "Invalid port number");
+ port = (uint16_t)l;
+ break;
+ case 't':
+ testcase = optarg;
+ break;
+ case 'T':
+ afname = optarg;
+ break;
+ case '?':
+ default:
+ errx(EX_USAGE, "Unknown command line option at '%c'",
+ optopt);
+ /* NOTREACHED */
+ }
+ }
+
+ if (testcase == NULL)
+ errx(EX_USAGE, "Mandatory option -t <testcase> not given");
+ if (afname == NULL)
+ errx(EX_USAGE, "Mandatory option -T <afname> not given");
+
+ if (strcmp(afname, "TCP6") == 0)
+ rc = reflect_tcp6();
+ else if (strcmp(afname, "UDP6") == 0)
+ rc = reflect_udp6();
+ else
+ errx(EX_USAGE, "Mandatory option -T %s not a valid option",
+ afname);
+
+ return (rc);
+}
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/netfibs/reflector.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/netfibs/reflector.sh Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,1098 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Cisco Systems, Inc.
+# All rights reserved.
+#
+# This software was developed by Bjoern Zeeb under contract to
+# Cisco Systems, Inc..
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: head/tools/test/netfibs/reflector.sh 232114 2012-02-24 14:13:06Z bz $
+#
+
+# We will use the RFC5180 (and Errata) benchmarking working group prefix
+# 2001:0002::/48 for testing.
+PREFIX="2001:2:"
+
+# Set IFACE to the real interface you want to run the test on.
+: ${IFACE:=lo0}
+
+# Control port we use to exchange messages between nodes to sync. tests, etc.
+: ${CTRLPORT:=6666}
+
+# Get the number of FIBs from the kernel.
+RT_NUMFIBS=`sysctl -n net.fibs`
+
+PEERADDR="2001:2:ff00::1"
+OURADDR="2001:2:ff00::2"
+
+OURLINKLOCAL=""
+PEERLINKLOCAL=""
+
+# By default all commands must succeed. Individual tests may disable this
+# temporary.
+set -e
+
+# Debug magic.
+case "${DEBUG}" in
+42) set -x ;;
+esac
+
+
+
+#
+# Helper functions.
+#
+
+# Function to avoid prelist races adding and deleting prefixes too quickly.
+delay()
+{
+
+ # sleep 1 is too long.
+ touch /tmp/foo || true
+ stat /tmp/foo > /dev/null 2>&1 || true
+}
+
+check_rc()
+{
+ local _rc _exp _testno _testname _msg _r
+ _rc=$1
+ _exp=$2
+ _testno=$3
+ _testname="$4"
+ _msg="$5"
+
+ _r="not ok"
+ if test ${_rc} -eq ${_exp}; then
+ _r="ok"
+ fi
+ echo "${_r} ${_testno} ${_testname} # ${_msg} ${_rc}"
+}
+
+print_debug()
+{
+ local _msg
+ _msg="$*"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) echo "DEBUG: ${_msg}" >&2 ;;
+ esac
+}
+
+die()
+{
+ local _msg
+ _msg="$*"
+
+ echo "ERROR: ${_msg}" >&2
+ exit 1
+}
+
+#
+# Test functions.
+#
+
+# Setup our side and wait for the peer to tell us that it is ready.
+wait_remote_ready()
+{
+ local _greeting _keyword _fibs _linklocal i
+
+ print_debug "Setting up interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias > /dev/null 2>&1 || true
+ delay
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \
+ > /dev/null 2>&1 || true
+ delay
+ i=$((i + 1))
+ done
+ OURLINKLOCAL=`ifconfig ${IFACE} | awk '/inet6 fe80:/ { print $2 }'`
+
+ # Let things settle.
+ print_debug "Waiting 4 seconds for things to settle"
+ sleep 4
+
+ # Wait for the remote to connect and start things.
+ # We tell it the magic keyword, our number of FIBs and our link-local.
+ # It already knows our global address.
+ _greeting=`echo "SETUP ${RT_NUMFIBS} ${OURLINKLOCAL}" | \
+ nc -6 -l ${CTRLPORT}`
+
+ read _keyword _fibs _linklocal <<EOI
+${_greeting}
+EOI
+ print_debug "_keyword=${_keyword}"
+ print_debug "_fibs=${_fibs}"
+ print_debug "_linklocal=${_linklocal}"
+ case ${_keyword} in
+ SETUP) ;;
+ *) die "Got invalid keyword in greeting: ${_greeting}"
+ ;;
+ esac
+ if test ${_fibs} -ne ${RT_NUMFIBS}; then
+ die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
+ "greeting: ${_greeting}"
+ fi
+ PEERLINKLOCAL=${_linklocal}
+
+ print_debug "Successfully received greeting. Peer at ${PEERLINKLOCAL}"
+}
+
+cleanup()
+{
+
+ print_debug "Removing address from interface ${IFACE}"
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias
+ delay
+}
+
+################################################################################
+#
+testtx_icmp6_connected()
+{
+ local _opts
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+ print_debug "./reflect -p ${CTRLPORT} -T TCP6 " \
+ "-t testtx_icmp6_connected ${_opts}"
+ ./reflect -p ${CTRLPORT} -T TCP6 -t testtx_icmp6_connected ${_opts}
+ print_debug "reflect terminated without error."
+}
+
+testtx_tcp6_connected()
+{
+ local _opts
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+ print_debug "./reflect -p ${CTRLPORT} -T TCP6 " \
+ "-t testtx_tcp6_connected ${_opts}"
+ ./reflect -p ${CTRLPORT} -T TCP6 -t testtx_tcp6_connected ${_opts}
+ print_debug "reflect terminated without error."
+}
+
+testtx_udp6_connected()
+{
+ local _opts
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+ print_debug "./reflect -p ${CTRLPORT} -T UDP6 " \
+ "-t testtx_udp6_connected ${_opts}"
+ ./reflect -p ${CTRLPORT} -T UDP6 -t testtx_udp6_connected ${_opts}
+ print_debug "reflect terminated without error."
+}
+
+################################################################################
+#
+testtx_icmp6_connected_blackhole()
+{
+ local _opts fib
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ print_debug "./reflect -p ${CTRLPORT} -T TCP6 " \
+ "-t testtx_icmp6_connected_blackhole${fib} ${_opts}"
+ ./reflect -p ${CTRLPORT} -T TCP6 \
+ -t testtx_icmp6_connected_blackhole${fib} ${_opts}
+ print_debug "reflect terminated without error."
+ fib=$((fib + 1))
+ done
+}
+
+testtx_tcp6_connected_blackhole()
+{
+ local _opts fib
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ print_debug "./reflect -p ${CTRLPORT} -T TCP6 " \
+ "-t testtx_tcp6_connected_blackhole${fib} ${_opts}"
+ ./reflect -p ${CTRLPORT} -T TCP6 \
+ -t testtx_tcp6_connected_blackhole${fib} ${_opts}
+ print_debug "reflect terminated without error."
+ fib=$((fib + 1))
+ done
+}
+
+testtx_udp6_connected_blackhole()
+{
+ local _opts fib
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ print_debug "./reflect -p ${CTRLPORT} -T UDP6 " \
+ "-t testtx_udp6_connected_blackhole${fib} ${_opts}"
+ ./reflect -p ${CTRLPORT} -T UDP6 \
+ -t testtx_udp6_connected_blackhole${fib} ${_opts}
+ print_debug "reflect terminated without error."
+ fib=$((fib + 1))
+ done
+}
+
+################################################################################
+#
+testtx_ulp6_connected_transfernets()
+{
+ local _opts fib _n _o
+ _n="$1"
+ _o="$2"
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ # Setup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 alias
+ fib=$((fib + 1))
+ done
+
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ print_debug "./reflect -p ${CTRLPORT} -T ${_o} -t ${_n}${fib} ${_opts}"
+ ./reflect -p ${CTRLPORT} -T ${_o} -t ${_n}${fib} ${_opts}
+ print_debug "reflect terminated without error."
+ fib=$((fib + 1))
+ done
+
+ # Cleanup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 -alias
+ delay
+ fib=$((fib + 1))
+ done
+}
+
+testtx_icmp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_icmp6_connected_transfernets" "TCP6"
+}
+
+testtx_tcp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_tcp6_connected_transfernets" "TCP6"
+}
+
+testtx_udp6_connected_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_udp6_connected_transfernets" "UDP6"
+}
+
+testtx_icmp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_icmp6_connected_ifconfig_transfernets" "TCP6"
+}
+
+testtx_tcp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_tcp6_connected_ifconfig_transfernets" "TCP6"
+}
+
+testtx_udp6_connected_ifconfig_transfernets()
+{
+
+ testtx_ulp6_connected_transfernets \
+ "testtx_udp6_connected_ifconfig_transfernets" "UDP6"
+}
+
+################################################################################
+#
+testtx_ulp6_gateway()
+{
+ local _opts _n _o
+ _n="$1"
+ _o="$2"
+
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias > /dev/null 2>&1 || true
+ delay
+ ifconfig lo0 inet6 2001:2:ff01::2 alias
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ print_debug "./reflect -p ${CTRLPORT} -T ${_o} " \
+ "-t ${_n} ${_opts} -A 2001:2:ff01::2"
+ ./reflect -p ${CTRLPORT} -T ${_o} \
+ -t ${_n} ${_opts} -A 2001:2:ff01::2
+ print_debug "reflect terminated without error."
+
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias
+ delay
+}
+
+testtx_icmp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_icmp6_gateway" "TCP6"
+}
+
+testtx_tcp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_tcp6_gateway" "TCP6"
+}
+
+testtx_udp6_gateway()
+{
+
+ testtx_ulp6_gateway "testtx_udp6_gateway" "UDP6"
+}
+
+################################################################################
+#
+testtx_ulp6_transfernets_gateways()
+{
+ local _opts fib _n _o
+ _n="$1"
+ _o="$2"
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ # Setup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 alias
+ fib=$((fib + 1))
+ done
+
+ # Setup out listener IP.
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias > /dev/null 2>&1 || true
+ delay
+ ifconfig lo0 inet6 2001:2:ff01::2 alias
+
+ # Reflect requests.
+ print_debug "./reflect -p ${CTRLPORT} -T ${_o} " \
+ "-t ${_n} ${_opts} -A 2001:2:ff01::2"
+ ./reflect -p ${CTRLPORT} -T ${_o} \
+ -t ${_n} ${_opts} -A 2001:2:ff01::2
+ print_debug "reflect terminated without error."
+
+ # Cleanup transfer networks and listener IP.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 -alias
+ delay
+ fib=$((fib + 1))
+ done
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias
+}
+
+testtx_icmp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_icmp6_transfernets_gateways" "TCP6"
+}
+
+testtx_tcp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_tcp6_transfernets_gateways" "TCP6"
+}
+
+testtx_udp6_transfernets_gateways()
+{
+
+ testtx_ulp6_transfernets_gateways \
+ "testtx_udp6_transfernets_gateways" "UDP6"
+}
+
+
+################################################################################
+#
+testtx_ulp6_transfernets_gateway()
+{
+ local _opts fib _n _o
+ _n="$1"
+ _o="$2"
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ # Setup transfer networks.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 alias
+ fib=$((fib + 1))
+ done
+
+ # Setup out listener IP.
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias > /dev/null 2>&1 || true
+ delay
+ ifconfig lo0 inet6 2001:2:ff01::2 alias
+
+ # Reflect requests.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ print_debug "./reflect -p ${CTRLPORT} -T ${_o} " \
+ "-t ${_n}${fib} ${_opts} -A 2001:2:ff01::2"
+ ./reflect -p ${CTRLPORT} -T ${_o} \
+ -t ${_n}${fib} ${_opts} -A 2001:2:ff01::2
+ print_debug "reflect terminated without error."
+ fib=$((fib + 1))
+ done
+
+ # Cleanup transfer networks and listener IP.
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+ setfib -F${fib} \
+ ifconfig ${IFACE} inet6 2001:2:${fib}::2/64 -alias
+ delay
+ fib=$((fib + 1))
+ done
+ ifconfig lo0 inet6 2001:2:ff01::2 -alias
+}
+
+testtx_icmp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_icmp6_transfernets_gateway" "TCP6"
+}
+
+testtx_tcp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_tcp6_transfernets_gateway" "TCP6"
+}
+
+testtx_udp6_transfernets_gateway()
+{
+
+ testtx_ulp6_transfernets_gateway \
+ "testtx_udp6_transfernets_gateway" "UDP6"
+}
+
+################################################################################
+#
+# We are receiver, but the FIBs are with us this time.
+#
+#
+
+# # For IPFW, IFCONFIG
+# # For each FIB
+# # Send OOB well known to work START, wait for reflect
+# # Send probe, wait for reply with FIB# or RST/ICMP6 unreach
+# # (in case of ICMP6 use magic like ipfw count and OOB reply)
+# # Send OOB well known to work DONE, wait for reflect
+# # Compare real with expected results.
+#
+
+textrx_ipfw_setup()
+{
+ local _fib _transfer i _p _o
+ _fib=$1
+ _transfer=$2
+
+ # ICMP6 would need content inspection to distinguish FIB, we can
+ # only differentiate by address.
+ # For the default single-address cases always set to current FIB.
+ ipfw add 100 setfib ${_fib} ipv6-icmp \
+ from ${PEERADDR} to ${OURADDR} \
+ via ${IFACE} in > /dev/null 2>&1
+ ipfw add 100 setfib ${_fib} ipv6-icmp \
+ from ${PEERLINKLOCAL%\%*} to ${OURLINKLOCAL%\%*} \
+ via ${IFACE} in > /dev/null 2>&1
+
+ # Always also do a setfib for the control port so that OOB
+ # signaling workes even if we remove connected subnets.
+ ipfw add 200 setfib ${_fib} ip6 from ${PEERADDR} to ${OURADDR} \
+ dst-port ${CTRLPORT} via ${IFACE} in > /dev/null 2>&1
+
+ # Save addresses
+ _p="${PEERADDR}"
+ _o="${OURADDR}"
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ # If doing multiple transfer networks, replace PEERADDR.
+ case ${_transfer} in
+ 1) PEERADDR=2001:2:${i}::1
+ OURADDR=2001:2:${i}::2
+ ;;
+ esac
+
+ if test ${_instances} -gt 1 -o ${_transfer} -eq 1; then
+ ipfw add 400 setfib ${_fib} ipv6-icmp \
+ from ${PEERADDR} to ${OURADDR} \
+ icmp6types 128 \
+ via ${IFACE} in > /dev/null 2>&1
+ fi
+
+ case ${i} in
+ ${_fib})
+ ipfw add 400 setfib ${_fib} ip6 \
+ from ${PEERADDR} to ${OURADDR} \
+ dst-port $((CTRLPORT + 1000 + i)) \
+ via ${IFACE} in > /dev/null 2>&1
+ ipfw add 400 setfib ${_fib} ip6 \
+ from ${PEERLINKLOCAL%\%*} to ${OURLINKLOCAL%\%*} \
+ dst-port $((CTRLPORT + 1000 + i)) \
+ via ${IFACE} in > /dev/null 2>&1
+ if test ${_instances} -le 1 -o ${_transfer} -ne 1; then
+ ipfw add 400 setfib ${_fib} ipv6-icmp \
+ from ${PEERADDR} to ${OURADDR} \
+ icmp6types 128 \
+ via ${IFACE} in > /dev/null 2>&1
+ fi
+ ;;
+ esac
+
+ i=$((i + 1))
+ done
+
+ # Restore addresses.
+ PEERADDR="${_p}"
+ OURADDR="${_o}"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) ipfw show ;;
+ esac
+}
+
+textrx_ifconfig_setup()
+{
+ local _fib
+ _fib=$1
+
+ ifconfig ${IFACE} fib ${_fib} > /dev/null 2>&1
+}
+
+textrx_ipfw_cleanup()
+{
+ local i
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) ipfw show ;;
+ esac
+
+ ipfw delete 100 > /dev/null 2>&1 || true
+ ipfw delete 200 > /dev/null 2>&1 || true
+ ipfw delete 400 > /dev/null 2>&1 || true
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ ipfw delete $((1000 + i)) > /dev/null 2>&1 || true
+ i=$((i + 1))
+ done
+}
+
+textrx_ifconfig_cleanup()
+{
+
+ ifconfig ${IFACE} fib 0 > /dev/null 2>&1
+}
+
+textrx_count_setup()
+{
+ local i
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ # Count ICMP6 echo replies.
+ ipfw add $((500 + i)) count ipv6-icmp from any to any \
+ icmp6types 129 fib ${i} via ${IFACE} out > /dev/null 2>&1
+ ipfw add $((500 + i)) count tcp from any to any \
+ fib ${i} via ${IFACE} out > /dev/null 2>&1
+ ipfw add $((500 + i)) count udp from any to any \
+ fib ${i} via ${IFACE} out > /dev/null 2>&1
+ i=$((i + 1))
+ done
+}
+
+textrx_count_results()
+{
+ local _fib _o i _rstr _c _req _p _opts
+ _fib=$1
+ _o="$2"
+
+ case ${DEBUG} in
+ ''|0) ;;
+ *) ipfw show ;;
+ esac
+
+ _rstr=""
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ case "${_o}" in
+ "-i") _c=`ipfw show $((500 + i)) | awk '/ ipv6-icmp / { print $2 }'` ;;
+ "-u") _c=`ipfw show $((500 + i)) | awk '/ udp / { print $2 }'` ;;
+ *) _c=`ipfw show $((500 + i)) | awk '/ tcp / { print $2 }'` ;;
+ esac
+ _rstr="${_rstr}${i} ${_c},"
+
+ ipfw delete $((500 + i)) > /dev/null 2>&1 || true
+ i=$((i + 1))
+ done
+
+ # We do not care about the request.
+ _req=`echo "RESULT ${_rstr}" | nc -V ${_fib} -6 -l ${CTRLPORT}`
+ print_debug "$? -- ${_req} -- RESULT ${_rstr}"
+}
+
+testrx_remove_connected()
+{
+ local _fib _transfer i j _prefix
+ _fib=$1
+ _transfer=$2
+
+ if test ${_transfer} -eq 1; then
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ j=0
+ while test ${j} -lt ${RT_NUMFIBS}; do
+ _prefix="2001:2:${j}::"
+
+ case ${j} in
+ ${_fib});;
+ *) print_debug "setfib -F${i} route delete" \
+ "-inet6 -net ${_prefix}"
+ setfib -F${i} route delete -inet6 -net \
+ ${_prefix} > /dev/null 2>&1
+ ;;
+ esac
+ j=$((j + 1))
+ done
+ i=$((i + 1))
+ done
+
+ else
+ _prefix=${OURADDR%2} # Luckily we know the details.
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+
+ case ${i} in
+ ${_fib});;
+ *) print_debug "setfib -F${i} route delete" \
+ "-inet6 -net ${_prefix}"
+ setfib -F${i} route delete -inet6 -net \
+ ${_prefix} > /dev/null 2>&1
+ ;;
+ esac
+
+ i=$((i + 1))
+ done
+ fi
+}
+
+testrx_cleanup_connected()
+{
+ local _fib _transfer i _prefix
+ _fib=$1
+ _transfer=$2
+
+ if test ${_transfer} -eq 1; then
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ setfib -F${i} \
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \
+ > /dev/null 2>&1
+ delay
+ i=$((i + 1))
+ done
+
+ else
+ # Use the hammer removing the address and adding it again to get
+ # the connected subnet back to all FIBs. Hard to do otherwise.
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 -alias || true
+ delay
+ ifconfig ${IFACE} inet6 ${OURADDR}/64 alias up
+ fi
+}
+
+testrx_setup_transfer_networks()
+{
+ local i
+
+ i=0
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \
+ > /dev/null 2>&1 || true
+ delay
+ ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias
+ i=$((i + 1))
+ done
+}
+
+testrx_run_one()
+{
+ local _fib _txt _opts
+ _fib=$1
+ _txt="$2"
+ _opts="$3"
+
+ case ${USE_SOSETFIB} in
+ 0) print_debug "setfib -F${_fib} ./reflect -p ${CTRLPORT}" \
+ "-t ${_txt} ${_opts}"
+ setfib -F${_fib} ./reflect -p ${CTRLPORT} -t ${_txt} ${_opts}
+ ;;
+ 1) print_debug "./reflect -F${_fib} -p ${CTRLPORT} -t ${_txt}" \
+ "${_opts}"
+ ./reflect -F${_fib} -p ${CTRLPORT} -t ${_txt} ${_opts}
+ ;;
+ *) die "Invalid value for USE_SOSETFIB: ${USE_SOSETFIB}" ;;
+ esac
+ print_debug "reflect '${_txt}' terminated without error."
+}
+
+testrx_run_multiple()
+{
+ local _fib _txt _opts i _jobs _p _w
+ _fib=$1
+ _txt="$2"
+ _opts="$3"
+
+ i=0
+ _jobs=""
+ while test ${i} -lt ${RT_NUMFIBS}; do
+ case ${USE_SOSETFIB} in
+ 0) print_debug "setfib -F${i} ./reflect" \
+ "-p $((CTRLPORT + 1000 + i))" \
+ "-t ${_txt} ${_opts} -N -f ${i} &"
+ setfib -F${i} ./reflect -p $((CTRLPORT + 1000 + i)) \
+ -t ${_txt} ${_opts} -N -f ${i} &
+ ;;
+ 1) print_debug "./reflect -F ${i}" \
+ "-p $((CTRLPORT + 1000 + i))" \
+ "-t ${_txt} ${_opts} -N -f ${i} &"
+ ./reflect -F ${i} -p $((CTRLPORT + 1000 + i)) \
+ -t ${_txt} ${_opts} -N -f ${i} &
+ ;;
+ *) die "Invalid value for USE_SOSETFIB: ${USE_SOSETFIB}" ;;
+ esac
+ _p=$!
+ _jobs="${_jobs}${_p} "
+ case ${i} in
+ ${_fib}) _w=${_p} ;;
+ esac
+ i=$((i + 1))
+ done
+
+ # Start OOB control connection for START/DONE.
+ testrx_run_one ${_fib} "${_txt}" "${_opts}"
+ print_debug "KILL ${_jobs}"
+ for i in ${_jobs}; do
+ kill ${i} || true
+ done
+ #killall reflect || true
+ print_debug "reflects for '${_txt}' terminated without error."
+}
+
+testrx_run_test()
+{
+ local _n _t _fib _o _txt i _f _instance _destructive _transfer
+ _n="$1"
+ _t="$2"
+ _fib=$3
+ _o="$4"
+ _instances=$5
+ _destructive=$6
+ _transfer=$7
+
+ : ${_destructive:=0}
+
+ _opts=""
+ case ${DEBUG} in
+ ''|0) ;;
+ 42) _opts="-d -d" ;;
+ *) _opts="-d" ;;
+ esac
+
+ # Convert netcat options to reflect aguments.
+ case "${_o}" in
+ -i) _opts="${_opts} -T TCP6" ;; # Use TCP for START/DONE.
+ -u) _opts="${_opts} -T UDP6" ;;
+ *) _opts="${_opts} -T TCP6" ;;
+ esac
+
+ # Combined test case base name.
+ case ${USE_SOSETFIB} in
+ 0) _f="setfib" ;;
+ 1) _f="so_setfib" ;;
+ *) die "Unexpected value for SO_SETFIB: ${SO_SETFIB}" ;;
+ esac
+
+ _txt="${_n}_${_f}_${_t}_${_fib}_${_instances}_${_destructive}_${_transfer}"
+
+ case ${_transfer} in
+ 1) testrx_setup_transfer_networks ;;
+ esac
+
+ case "${_t}" in
+ ipfw) textrx_ipfw_setup ${_fib} ${_transfer} ${_instances} ;;
+ ifconfig) textrx_ifconfig_setup ${_fib} ;;
+ *) die "Invalid type in ${_txt}" ;;
+ esac
+
+ # Setup unresponsive FIBs.
+ case ${_destructive} in
+ 1) testrx_remove_connected ${_fib} ${_transfer} ;;
+ esac
+
+ # Setup to get result counts.
+ textrx_count_setup
+
+ # Run just one / one per FIB (with incremental ports).
+ #case ${_instances} in
+ #1) testrx_run_one ${_fib} "${_txt}" "${_opts}" ;;
+ #*) testrx_run_multiple ${_fib} "${_txt}" "${_opts}" ;;
+ #esac
+ testrx_run_multiple ${_fib} "${_txt}" "${_opts}" ${_transfer}
+
+ # Export result counts.
+ textrx_count_results ${_fib} "${_o}"
+
+ # Cleanup unresponsive FIBs or multiple prefixes.
+ if test ${_destructive} -eq 1 -o ${_transfer} -eq 1; then
+ testrx_cleanup_connected ${_fib} ${_transfer}
+ fi
+
+ case "${_t}" in
+ ipfw) textrx_ipfw_cleanup ;;
+ ifconfig) textrx_ifconfig_cleanup ;;
+ *) die "Invalid type in ${_txt}" ;;
+ esac
+}
+
+testrx_main()
+{
+ local _n _o s t fib _instances _destructive
+ _n="$1"
+ _o="$2"
+ _instances=$3
+
+ : ${_instances:=1}
+
+ print_debug "${_n}"
+ for _transfer in 1 0; do
+ for _destructive in 0 1; do
+ for t in ipfw ifconfig; do
+
+ print_debug "${_n}_${t}"
+ fib=0
+ while test ${fib} -lt ${RT_NUMFIBS}; do
+
+ print_debug "${_n}_${t}_${fib}" \
+ "${_instances} ${_destructive}" \
+ "${_transfer}"
+ testrx_run_test "${_n}" "${t}" ${fib} \
+ "${_o}" ${_instances} \
+ ${_destructive} ${_transfer}
+
+ fib=$((fib + 1))
+ done
+ done
+ done
+ done
+}
+
+################################################################################
+#
+# Probe all FIBs with one "active" one a time.
+#
+testrx_icmp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main "testrx_icmp6_same_addr_one_fib_a_time" "-i"
+}
+
+testrx_tcp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main "testrx_tcp6_same_addr_one_fib_a_time" ""
+}
+
+testrx_udp6_same_addr_one_fib_a_time()
+{
+
+ testrx_main "testrx_udp6_same_addr_one_fib_a_time" "-u"
+}
+
+################################################################################
+#
+# Probe all FIBs with all "active" all time.
+#
+testrx_tcp6_same_addr_all_fibs_a_time()
+{
+
+ testrx_main "testrx_tcp6_same_addr_all_fibs_a_time" "" ${RT_NUMFIBS}
+}
+
+testrx_udp6_same_addr_all_fibs_a_time()
+{
+
+ testrx_main "testrx_udp6_same_addr_all_fibs_a_time" "-u" ${RT_NUMFIBS}
+}
+
+
+################################################################################
+#
+# Prereqs.
+#
+if test `sysctl -n security.jail.jailed` -eq 0; then
+ kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw
+fi
+ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system"
+ipfw add 65000 permit ip from any to any > /dev/null 2>&1
+killall reflect || true
+
+################################################################################
+#
+# Run tests.
+#
+wait_remote_ready
+
+# We are receiver reflecting the input back.
+for uso in 0 1; do
+
+ # Only run ICMP6 tests for the first loop.
+ test ${uso} -ne 0 || testtx_icmp6_connected
+ testtx_tcp6_connected
+ testtx_udp6_connected
+
+ test ${uso} -ne 0 || testtx_icmp6_connected_blackhole
+ testtx_tcp6_connected_blackhole
+ testtx_udp6_connected_blackhole
+
+ test ${uso} -ne 0 || testtx_icmp6_connected_transfernets
+ testtx_tcp6_connected_transfernets
+ testtx_udp6_connected_transfernets
+
+ test ${uso} -ne 0 || testtx_icmp6_connected_ifconfig_transfernets
+ testtx_tcp6_connected_ifconfig_transfernets
+ testtx_udp6_connected_ifconfig_transfernets
+
+ test ${uso} -ne 0 || testtx_icmp6_gateway
+ testtx_tcp6_gateway
+ testtx_udp6_gateway
+
+ test ${uso} -ne 0 || testtx_icmp6_transfernets_gateways
+ testtx_tcp6_transfernets_gateways
+ testtx_udp6_transfernets_gateways
+
+ test ${uso} -ne 0 || testtx_icmp6_transfernets_gateway
+ testtx_tcp6_transfernets_gateway
+ testtx_udp6_transfernets_gateway
+done
+
+ipfw -f flush > /dev/null 2>&1
+ipfw add 65000 permit ip from any to any > /dev/null 2>&1
+
+# We are receiver, but the FIBs are with us this time.
+for uso in 0 1; do
+
+ USE_SOSETFIB=${uso}
+
+ # Only expect ICMP6 tests for the first loop.
+ test ${uso} -ne 0 || testrx_icmp6_same_addr_one_fib_a_time
+ testrx_tcp6_same_addr_one_fib_a_time
+ testrx_udp6_same_addr_one_fib_a_time
+
+ testrx_tcp6_same_addr_all_fibs_a_time
+ testrx_udp6_same_addr_all_fibs_a_time
+
+done
+
+cleanup
+
+# end
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/ptrace/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/ptrace/Makefile Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,7 @@
+# $FreeBSD: head/tools/test/ptrace/Makefile 231443 2012-02-10 21:33:12Z kib $
+
+PROG= scescx
+NO_MAN=
+WARNS?= 6
+
+.include <bsd.prog.mk>
diff -r 77b2b05d6591 -r 22418adf039f head/tools/test/ptrace/scescx.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/test/ptrace/scescx.c Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,406 @@
+/*-
+ * Copyright (c) 2011, 2012 Konstantin Belousov <kib at FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/tools/test/ptrace/scescx.c 231443 2012-02-10 21:33:12Z kib $");
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define TRACE ">>>> "
+
+static const char *
+decode_wait_status(int status)
+{
+ static char c[128];
+ char b[32];
+ int first;
+
+ c[0] = '\0';
+ first = 1;
+ if (WIFCONTINUED(status)) {
+ first = 0;
+ strlcat(c, "CONT", sizeof(c));
+ }
+ if (WIFEXITED(status)) {
+ if (first)
+ first = 0;
+ else
+ strlcat(c, ",", sizeof(c));
+ snprintf(b, sizeof(b), "EXIT(%d)", WEXITSTATUS(status));
+ strlcat(c, b, sizeof(c));
+ }
+ if (WIFSIGNALED(status)) {
+ if (first)
+ first = 0;
+ else
+ strlcat(c, ",", sizeof(c));
+ snprintf(b, sizeof(b), "SIG(%s)", strsignal(WTERMSIG(status)));
+ strlcat(c, b, sizeof(c));
+ if (WCOREDUMP(status))
+ strlcat(c, ",CORE", sizeof(c));
+ }
+ if (WIFSTOPPED(status)) {
+ if (first)
+ first = 0;
+ else
+ strlcat(c, ",", sizeof(c));
+ snprintf(b, sizeof(b), "SIG(%s)", strsignal(WSTOPSIG(status)));
+ strlcat(c, b, sizeof(c));
+ }
+ return (c);
+}
+
+static const char *
+decode_pl_flags(struct ptrace_lwpinfo *lwpinfo)
+{
+ static char c[128];
+ static struct decode_tag {
+ int flag;
+ const char *desc;
+ } decode[] = {
+ { PL_FLAG_SA, "SA" },
+ { PL_FLAG_BOUND, "BOUND" },
+ { PL_FLAG_SCE, "SCE" },
+ { PL_FLAG_SCX, "SCX" },
+ { PL_FLAG_EXEC, "EXEC" },
+ { PL_FLAG_SI, "SI" },
+ { PL_FLAG_FORKED, "FORKED" },
+ };
+ char de[32];
+ unsigned first, flags, i;
+
+ c[0] = '\0';
+ first = 1;
+ flags = lwpinfo->pl_flags;
+ for (i = 0; i < sizeof(decode) / sizeof(decode[0]); i++) {
+ if ((flags & decode[i].flag) != 0) {
+ if (first)
+ first = 0;
+ else
+ strlcat(c, ",", sizeof(c));
+ strlcat(c, decode[i].desc, sizeof(c));
+ flags &= ~decode[i].flag;
+ }
+ }
+ for (i = 0; i < sizeof(flags) * NBBY; i++) {
+ if ((flags & (1 << i)) != 0) {
+ if (first)
+ first = 0;
+ else
+ strlcat(c, ",", sizeof(c));
+ snprintf(de, sizeof(de), "<%d>", i);
+ strlcat(c, de, sizeof(c));
+ }
+ }
+ return (c);
+}
+
+static const char *
+decode_pl_event(struct ptrace_lwpinfo *lwpinfo)
+{
+
+ switch (lwpinfo->pl_event) {
+ case PL_EVENT_NONE:
+ return ("NONE");
+
+ case PL_EVENT_SIGNAL:
+ return ("SIG");
+
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+static void
+get_pathname(pid_t pid)
+{
+ char pathname[PATH_MAX];
+ int error, name[4];
+ size_t len;
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_PATHNAME;
+ name[3] = pid;
+
+ len = sizeof(pathname);
+ error = sysctl(name, 4, pathname, &len, NULL, 0);
+ if (error < 0) {
+ if (errno != ESRCH) {
+ fprintf(stderr, "sysctl kern.proc.pathname.%d: %s\n",
+ pid, strerror(errno));
+ return;
+ }
+ fprintf(stderr, "pid %d exited\n", pid);
+ return;
+ }
+ if (len == 0 || strlen(pathname) == 0) {
+ fprintf(stderr, "No cached pathname for process %d\n", pid);
+ return;
+ }
+ printf(TRACE "pid %d path %s\n", pid, pathname);
+}
+
+static void
+wait_info(int pid, int status, struct ptrace_lwpinfo *lwpinfo)
+{
+
+ printf(TRACE "pid %d wait %s", pid,
+ decode_wait_status(status));
+ if (lwpinfo != NULL) {
+ printf(" event %s flags %s",
+ decode_pl_event(lwpinfo), decode_pl_flags(lwpinfo));
+ }
+ printf("\n");
+}
+
+static int
+trace_sc(int pid)
+{
+ struct ptrace_lwpinfo lwpinfo;
+ int status;
+
+ if (ptrace(PT_TO_SCE, pid, (caddr_t)1, 0) < 0) {
+ perror("PT_TO_SCE");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid");
+ return (-1);
+ }
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ wait_info(pid, status, NULL);
+ return (-1);
+ }
+ assert(WIFSTOPPED(status));
+ assert(WSTOPSIG(status) == SIGTRAP);
+
+ if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
+ perror("PT_LWPINFO");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+ wait_info(pid, status, &lwpinfo);
+ assert(lwpinfo.pl_flags & PL_FLAG_SCE);
+
+ if (ptrace(PT_TO_SCX, pid, (caddr_t)1, 0) < 0) {
+ perror("PT_TO_SCX");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid");
+ return (-1);
+ }
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ wait_info(pid, status, NULL);
+ return (-1);
+ }
+ assert(WIFSTOPPED(status));
+ assert(WSTOPSIG(status) == SIGTRAP);
+
+ if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
+ perror("PT_LWPINFO");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+ wait_info(pid, status, &lwpinfo);
+ assert(lwpinfo.pl_flags & PL_FLAG_SCX);
+
+ if (lwpinfo.pl_flags & PL_FLAG_EXEC)
+ get_pathname(pid);
+
+ if (lwpinfo.pl_flags & PL_FLAG_FORKED) {
+ printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid);
+ return (lwpinfo.pl_child_pid);
+ }
+ return (0);
+}
+
+static int
+trace_cont(int pid)
+{
+ struct ptrace_lwpinfo lwpinfo;
+ int status;
+
+ if (ptrace(PT_CONTINUE, pid, (caddr_t)1, 0) < 0) {
+ perror("PT_CONTINUE");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid");
+ return (-1);
+ }
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ wait_info(pid, status, NULL);
+ return (-1);
+ }
+ assert(WIFSTOPPED(status));
+ assert(WSTOPSIG(status) == SIGTRAP);
+
+ if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
+ perror("PT_LWPINFO");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+ wait_info(pid, status, &lwpinfo);
+
+ if ((lwpinfo.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
+ (PL_FLAG_EXEC | PL_FLAG_SCX))
+ get_pathname(pid);
+
+ if ((lwpinfo.pl_flags & (PL_FLAG_FORKED | PL_FLAG_SCX)) ==
+ (PL_FLAG_FORKED | PL_FLAG_SCX)) {
+ printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid);
+ return (lwpinfo.pl_child_pid);
+ }
+
+ return (0);
+}
+
+static int trace_syscalls = 1;
+
+static int
+trace(pid_t pid)
+{
+
+ return (trace_syscalls ? trace_sc(pid) : trace_cont(pid));
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ struct ptrace_lwpinfo lwpinfo;
+ int c, status, use_vfork;
+ pid_t pid, pid1;
+
+ trace_syscalls = 1;
+ use_vfork = 0;
+ while ((c = getopt(argc, argv, "csv")) != -1) {
+ switch (c) {
+ case 'c':
+ trace_syscalls = 0;
+ break;
+ case 's':
+ trace_syscalls = 1;
+ break;
+ case 'v':
+ use_vfork = 1;
+ break;
+ default:
+ case '?':
+ fprintf(stderr, "Usage: %s [-c] [-s] [-v]\n", argv[0]);
+ return (2);
+ }
+ }
+
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ return 1;
+ }
+ else if (pid == 0) {
+ if (ptrace(PT_TRACE_ME, 0, NULL, 0) < 0) {
+ perror("PT_TRACE_ME");
+ _exit(1);
+ }
+ kill(getpid(), SIGSTOP);
+ getpid();
+ if ((pid1 = use_vfork ? vfork() : fork()) < 0) {
+ perror("fork1");
+ return (1);
+ } else if (pid1 == 0) {
+ printf("Hi from child %d\n", getpid());
+ execl("/bin/ls", "ls", "/", (char *)NULL);
+ }
+ }
+ else { /* parent */
+ if (waitpid(pid, &status, 0) == -1) {
+ perror("waitpid");
+ return (-1);
+ }
+ assert(WIFSTOPPED(status));
+ assert(WSTOPSIG(status) == SIGSTOP);
+
+ if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo,
+ sizeof(lwpinfo)) < 0) {
+ perror("PT_LWPINFO");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (-1);
+ }
+ wait_info(pid, status, &lwpinfo);
+
+ if (ptrace(PT_FOLLOW_FORK, pid, 0, 1) < 0) {
+ perror("PT_FOLLOW_FORK");
+ ptrace(PT_KILL, pid, NULL, 0);
+ return (2);
+ }
+
+ while ((pid1 = trace(pid)) >= 0) {
+ if (pid1 != 0) {
+ printf(TRACE "attached to pid %d\n", pid1);
+#if 0
+ kill(pid1, SIGCONT);
+#endif
+ if (waitpid(pid1, &status, 0) == -1) {
+ perror("waitpid");
+ return (-1);
+ }
+ printf(TRACE "nested loop, pid %d status %s\n",
+ pid1, decode_wait_status(status));
+ assert(WIFSTOPPED(status));
+ assert(WSTOPSIG(status) == SIGSTOP);
+ if (ptrace(PT_LWPINFO, pid1, (caddr_t)&lwpinfo,
+ sizeof(lwpinfo)) < 0) {
+ perror("PT_LWPINFO");
+ ptrace(PT_KILL, pid1, NULL, 0);
+ return (-1);
+ }
+ wait_info(pid1, status, &lwpinfo);
+
+ while (trace(pid1) >= 0)
+ ;
+ }
+ }
+
+ ptrace(PT_CONTINUE, pid, (caddr_t)1, 0);
+ }
+ return (0);
+}
diff -r 77b2b05d6591 -r 22418adf039f head/tools/tools/fixwhite/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/tools/fixwhite/Makefile Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,7 @@
+# $FreeBSD: head/tools/tools/fixwhite/Makefile 231071 2012-02-06 10:23:11Z ed $
+
+PROG= fixwhite
+BINDIR= /usr/bin
+WARNS= 6
+
+.include <bsd.prog.mk>
diff -r 77b2b05d6591 -r 22418adf039f head/tools/tools/fixwhite/fixwhite.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/tools/fixwhite/fixwhite.1 Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,48 @@
+.\" Copyright (c) 2012 Ed Schouten <ed at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD: head/tools/tools/fixwhite/fixwhite.1 231098 2012-02-06 18:52:40Z ed $
+.\"
+.Dd February 6, 2012
+.Dt FIXWHITE 1
+.Os
+.Sh NAME
+.Nm fixwhite
+.Nd remove unneeded whitespace from text files
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility removes unneeded whitespace from text passed to standard input
+and prints the result to standard output.
+.Pp
+It removes leading and trailing empty lines from the input, as well as
+trailing whitespace characters from ever line of text.
+Multiple successive empty lines are merged together.
+If the whitespace at the beginning of a sentence is exactly a multiple
+of eight spaces, the whitespace is replaced by tabs.
+Also, spaces preceeding tabs will be merged into the tab character.
+.Sh AUTHORS
+.An Ed Schouten Aq ed at FreeBSD.org
diff -r 77b2b05d6591 -r 22418adf039f head/tools/tools/fixwhite/fixwhite.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/tools/tools/fixwhite/fixwhite.c Fri Mar 02 17:01:18 2012 +0200
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2012 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/tools/tools/fixwhite/fixwhite.c 231098 2012-02-06 18:52:40Z ed $");
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static char *queue = NULL;
+static size_t queuelen = 0, queuesize = 0;
+static off_t column = 0;
+
+static void
+savebyte(char c)
+{
+
+ if (queuelen >= queuesize) {
+ queuesize += 128;
+ queue = realloc(queue, queuesize);
+ if (queue == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ }
+ queue[queuelen++] = c;
+
+ switch (c) {
+ case '\n':
+ column = 0;
+ break;
+ case ' ':
+ column++;
+ break;
+ case '\t':
+ column = (column / 8 + 1) * 8;
+ break;
+ }
+}
+
+static bool
+peekbyte(size_t back, char c)
+{
+
+ return (queuelen >= back && queue[queuelen - back] == c);
+}
+
+static void
+savewhite(char c, bool leading)
+{
+ off_t ncolumn;
+
+ switch (c) {
+ case '\n':
+ if (leading) {
+ /* Remove empty lines before input. */
+ queuelen = 0;
+ column = 0;
+ } else {
+ /* Remove trailing whitespace. */
+ while (peekbyte(1, ' ') || peekbyte(1, '\t'))
+ queuelen--;
+ /* Remove redundant empty lines. */
+ if (peekbyte(2, '\n') && peekbyte(1, '\n'))
+ return;
+ savebyte('\n');
+ }
+ break;
+ case ' ':
+ savebyte(' ');
+ break;
+ case '\t':
+ /* Convert preceeding spaces to tabs. */
+ ncolumn = (column / 8 + 1) * 8;
+ while (peekbyte(1, ' ')) {
+ queuelen--;
+ column--;
+ }
+ while (column < ncolumn)
+ savebyte('\t');
+ break;
+ }
+}
+
+static void
+printwhite(void)
+{
+ off_t i;
+
+ /* Merge spaces at the start of a sentence to tabs if possible. */
+ if ((column % 8) == 0) {
+ for (i = 0; i < column; i++)
+ if (!peekbyte(i + 1, ' '))
+ break;
+ if (i == column) {
+ queuelen -= column;
+ for (i = 0; i < column; i += 8)
+ queue[queuelen++] = '\t';
+ }
+ }
+
+ if (fwrite(queue, 1, queuelen, stdout) != queuelen) {
+ perror("write");
+ exit(1);
+ }
+ queuelen = 0;
+}
+
+static char
+readchar(void)
+{
+ int c;
+
+ c = getchar();
+ if (c == EOF && ferror(stdin)) {
+ perror("read");
+ exit(1);
+ }
+ return (c);
+}
+
+static void
+writechar(char c)
+{
+
+ if (putchar(c) == EOF) {
+ perror("write");
+ exit(1);
+ }
+ /* XXX: Multi-byte characters. */
+ column++;
+}
+
+int
+main(void)
+{
+ int c;
+ bool leading = true;
+
+ while ((c = readchar()) != EOF) {
+ if (isspace(c))
+ /* Save whitespace. */
+ savewhite(c, leading);
+ else {
+ /* Reprint whitespace and print regular character. */
+ printwhite();
+ writechar(c);
+ leading = false;
+ }
+ }
+ /* Terminate non-empty files with a newline. */
+ if (!leading)
+ writechar('\n');
+ return (0);
+}
More information about the Zrouter-src-freebsd
mailing list