diff --git a/tests/sys/netgraph/bridge.c b/tests/sys/netgraph/bridge.c index 41d2346b527b..3e3c0f804278 100644 --- a/tests/sys/netgraph/bridge.c +++ b/tests/sys/netgraph/bridge.c @@ -1,654 +1,632 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright 2021 Lutz Donnerhacke * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "util.h" #include -static void get_data0(void *data, size_t len, void *ctx); -static void get_data1(void *data, size_t len, void *ctx); -static void get_data2(void *data, size_t len, void *ctx); -static void get_data3(void *data, size_t len, void *ctx); - static void get_tablesize(char const *source, struct ng_mesg *msg, void *ctx); struct gettable { u_int32_t tok; int cnt; }; struct frame4 { struct ether_header eh; struct ip ip; char data[64]; }; struct frame6 { struct ether_header eh; struct ip6_hdr ip; char data[64]; }; static struct frame4 msg4 = { .ip.ip_v = 4, .ip.ip_hl = 5, .ip.ip_ttl = 1, .ip.ip_p = 254, .ip.ip_src = {htonl(0x0a00dead)}, .ip.ip_dst = {htonl(0x0a00beef)}, .ip.ip_len = 32, .eh.ether_type = ETHERTYPE_IP, .eh.ether_shost = {2, 4, 6}, .eh.ether_dhost = {2, 4, 6}, }; ATF_TC(basic); ATF_TC_HEAD(basic, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(basic, dummy) { - int r[4]; + ng_counter_t r; struct gettable rm; ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_errors(FAIL); ng_mkpeer(".", "a", "bridge", "link0"); ng_name("a", "bridge"); ng_connect(".", "b", "bridge:", "link1"); ng_connect(".", "c", "bridge:", "link2"); /* do not bounce back */ ng_register_data("a", get_data0); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0); /* send to others */ ng_register_data("b", get_data1); ng_register_data("c", get_data2); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 2; ng_send_data("b", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 3; ng_send_data("c", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 1 && r[2] == 0); /* send to learned unicast */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[5] = 3; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1); /* inspect mac table */ ng_register_msg(get_tablesize); rm.tok = ng_send_msg("bridge:", "gettable"); rm.cnt = 0; ng_handle_events(50, &rm); ATF_CHECK(rm.cnt == 3); /* remove a link */ ng_rmhook(".", "b"); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[5] = 0; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1); /* inspect mac table */ ng_register_msg(get_tablesize); rm.tok = ng_send_msg("bridge:", "gettable"); rm.cnt = 0; ng_handle_events(50, &rm); ATF_CHECK(rm.cnt == 2); ng_shutdown("bridge:"); } ATF_TC(persistence); ATF_TC_HEAD(persistence, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(persistence, dummy) { ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_errors(FAIL); ng_mkpeer(".", "a", "bridge", "link0"); ng_name("a", "bridge"); ng_send_msg("bridge:", "setpersistent"); ng_rmhook(".", "a"); ng_shutdown("bridge:"); } ATF_TC(loop); ATF_TC_HEAD(loop, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(loop, dummy) { - int r[4], i; + ng_counter_t r; + int i; ng_init(); ng_errors(PASS); ng_shutdown("bridge1:"); ng_shutdown("bridge2:"); ng_errors(FAIL); ng_mkpeer(".", "a", "bridge", "link0"); ng_name("a", "bridge1"); ng_mkpeer(".", "b", "bridge", "link1"); ng_name("b", "bridge2"); ng_register_data("a", get_data0); ng_register_data("b", get_data1); /*- * Open loop * * /-- bridge1 * . < | * \-- bridge2 */ ng_connect("bridge1:", "link11", "bridge2:", "link11"); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1); /*- * Closed loop, DANGEROUS! * * /-- bridge1 -\ * . < | | * \-- bridge2 -/ */ ng_connect("bridge1:", "link12", "bridge2:", "link12"); - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_errors(PASS); ng_send_data("a", &msg4, sizeof(msg4)); ATF_CHECK_ERRNO(ELOOP, errno != 0); /* loop might be detected */ ng_errors(FAIL); for (i = 0; i < 10; i++) /* don't run forever */ if (!ng_handle_event(50, &r)) break; ATF_CHECK(r[0] == 0 && r[1] == 1); ng_shutdown("bridge1:"); ng_shutdown("bridge2:"); } ATF_TC(many_unicasts); ATF_TC_HEAD(many_unicasts, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(many_unicasts, dummy) { - int r[4], i; + ng_counter_t r; + int i; const int HOOKS = 1000; struct gettable rm; ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_errors(FAIL); ng_mkpeer(".", "a", "bridge", "link0"); ng_name("a", "bridge"); ng_register_data("a", get_data0); /* learn MAC */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[3] = 0xff; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0); /* use learned MAC as destination */ msg4.eh.ether_shost[3] = 0; msg4.eh.ether_dhost[3] = 0xff; /* now send */ - bzero(r, sizeof(r)); + ng_counter_clear(r); for (i = 1; i <= HOOKS; i++) { char hook[20]; snprintf(hook, sizeof(hook), "link%d", i); ng_connect(".", hook, "bridge:", hook); ng_register_data(hook, get_data2); msg4.eh.ether_shost[4] = i >> 8; msg4.eh.ether_shost[5] = i & 0xff; ng_errors(PASS); ng_send_data(hook, &msg4, sizeof(msg4)); ng_errors(FAIL); if (errno != 0) break; ng_handle_events(50, &r); } ATF_CHECK(r[0] == HOOKS && r[2] == 0); /* inspect mac table */ ng_register_msg(get_tablesize); rm.cnt = 0; ng_errors(PASS); rm.tok = ng_send_msg("bridge:", "gettable"); ng_errors(FAIL); if (rm.tok == (u_int32_t)-1) { ATF_CHECK_ERRNO(ENOBUFS, 1); atf_tc_expect_fail("response too large"); } ng_handle_events(50, &rm); ATF_CHECK(rm.cnt == HOOKS + 1); atf_tc_expect_pass(); ng_shutdown("bridge:"); } ATF_TC(many_broadcasts); ATF_TC_HEAD(many_broadcasts, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(many_broadcasts, dummy) { - int r[4], i; + ng_counter_t r; + int i; const int HOOKS = 1000; ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_errors(FAIL); ng_mkpeer(".", "a", "bridge", "link0"); ng_name("a", "bridge"); ng_register_data("a", get_data0); /* learn MAC */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[3] = 0xff; ng_send_data("a", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0); /* use broadcast MAC */ msg4.eh.ether_shost[3] = 0; memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); /* now send */ - bzero(r, sizeof(r)); + ng_counter_clear(r); for (i = 1; i <= HOOKS; i++) { char hook[20]; snprintf(hook, sizeof(hook), "link%d", i); ng_connect(".", hook, "bridge:", hook); ng_register_data(hook, get_data3); msg4.eh.ether_shost[4] = i >> 8; msg4.eh.ether_shost[5] = i & 0xff; ng_errors(PASS); ng_send_data(hook, &msg4, sizeof(msg4)); ng_errors(FAIL); if (errno != 0) break; ng_handle_events(50, &r); } ATF_CHECK(r[0] > 100 && r[3] > 100); if (i < HOOKS) atf_tc_expect_fail("netgraph queue full (%d)", i); ATF_CHECK(r[0] == HOOKS); atf_tc_expect_pass(); ng_shutdown("bridge:"); } ATF_TC(uplink_private); ATF_TC_HEAD(uplink_private, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(uplink_private, dummy) { - int r[4]; + ng_counter_t r; struct gettable rm; ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_mkpeer(".", "u1", "bridge", "uplink1"); if (errno > 0) atf_tc_skip("uplinks are not supported."); ng_errors(FAIL); ng_name("u1", "bridge"); ng_register_data("u1", get_data1); ng_connect(".", "u2", "bridge:", "uplink2"); ng_register_data("u2", get_data2); ng_connect(".", "l0", "bridge:", "link0"); ng_register_data("l0", get_data0); ng_connect(".", "l3", "bridge:", "link3"); ng_register_data("l3", get_data3); /* unknown unicast 0 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0); /* unknown unicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; msg4.eh.ether_dhost[5] = 2; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0); /* known unicast 0 from uplink2 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 2; msg4.eh.ether_dhost[5] = 0; ng_send_data("u2", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); /* known unicast 0 from link3 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 3; msg4.eh.ether_dhost[5] = 0; ng_send_data("l3", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); /* (un)known unicast 2 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[5] = 2; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0); /* (un)known unicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0); /* unknown multicast 2 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[0] = 0xff; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* unknown multicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* broadcast from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* broadcast from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* inspect mac table */ ng_register_msg(get_tablesize); rm.tok = ng_send_msg("bridge:", "gettable"); rm.cnt = 0; ng_handle_events(50, &rm); ATF_CHECK(rm.cnt == 2); ng_shutdown("bridge:"); } ATF_TC(uplink_classic); ATF_TC_HEAD(uplink_classic, conf) { atf_tc_set_md_var(conf, "require.user", "root"); } ATF_TC_BODY(uplink_classic, dummy) { - int r[4]; + ng_counter_t r; struct gettable rm; ng_init(); ng_errors(PASS); ng_shutdown("bridge:"); ng_mkpeer(".", "l0", "bridge", "link0"); if (errno > 0) atf_tc_skip("uplinks are not supported."); ng_errors(FAIL); ng_name("l0", "bridge"); ng_register_data("l0", get_data0); ng_connect(".", "u1", "bridge:", "uplink1"); ng_register_data("u1", get_data1); ng_connect(".", "u2", "bridge:", "uplink2"); ng_register_data("u2", get_data2); ng_connect(".", "l3", "bridge:", "link3"); ng_register_data("l3", get_data3); /* unknown unicast 0 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* unknown unicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; msg4.eh.ether_dhost[5] = 2; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* known unicast 0 from uplink2 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 2; msg4.eh.ether_dhost[5] = 0; ng_send_data("u2", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); /* known unicast 0 from link3 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 3; msg4.eh.ether_dhost[5] = 0; ng_send_data("l3", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); /* (un)known unicast 2 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[5] = 2; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* (un)known unicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* unknown multicast 2 from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; msg4.eh.ether_dhost[0] = 0xff; ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* unknown multicast 2 from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* broadcast from uplink1 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 1; memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); ng_send_data("u1", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); /* broadcast from link0 */ - bzero(r, sizeof(r)); + ng_counter_clear(r); msg4.eh.ether_shost[5] = 0; ng_send_data("l0", &msg4, sizeof(msg4)); ng_handle_events(50, &r); ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); /* inspect mac table */ ng_register_msg(get_tablesize); rm.tok = ng_send_msg("bridge:", "gettable"); rm.cnt = 0; ng_handle_events(50, &rm); ATF_CHECK(rm.cnt == 2); ng_shutdown("bridge:"); } ATF_TP_ADD_TCS(bridge) { ATF_TP_ADD_TC(bridge, basic); ATF_TP_ADD_TC(bridge, loop); ATF_TP_ADD_TC(bridge, persistence); ATF_TP_ADD_TC(bridge, many_unicasts); ATF_TP_ADD_TC(bridge, many_broadcasts); ATF_TP_ADD_TC(bridge, uplink_private); ATF_TP_ADD_TC(bridge, uplink_classic); return atf_no_error(); } -static inline void -_get_data(void *data, size_t len, void *ctx, int i) -{ - int *cnt = ctx; - - (void)data; - fprintf(stderr, "[%d] Got %zu bytes of data.\n", i, len); - cnt[i]++; -} - -#define GD(x) static void \ -get_data##x(void *data, size_t len, void *ctx) {\ - _get_data(data, len, ctx, x); \ -} - -GD(0) -GD(1) -GD(2) -GD(3) - static void get_tablesize(char const *source, struct ng_mesg *msg, void *ctx) { struct gettable *rm = ctx; struct ng_bridge_host_ary *gt = (void *)msg->data; fprintf(stderr, "Response from %s to query %d\n", source, msg->header.token); if (rm->tok == msg->header.token) rm->cnt = gt->numHosts; } diff --git a/tests/sys/netgraph/util.c b/tests/sys/netgraph/util.c index 307bacfa8cc6..b25e63dfa76d 100644 --- a/tests/sys/netgraph/util.c +++ b/tests/sys/netgraph/util.c @@ -1,257 +1,277 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright 2021 Lutz Donnerhacke * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include "util.h" static int cs = -1, ds = -1; static ng_error_t error_handling = FAIL; #define CHECK(r, x) do { \ if (!(x)) { \ if (error_handling == PASS) \ return r; \ atf_tc_fail_requirement(file, line, "%s (%s)", \ #x " not met", strerror(errno));\ } \ } while(0) struct data_handler { char const *hook; ng_data_handler_t handler; SLIST_ENTRY(data_handler) next; }; static SLIST_HEAD(, data_handler) data_head = SLIST_HEAD_INITIALIZER(data_head); static ng_msg_handler_t msg_handler = NULL; static void handle_data(void *ctx); static void handle_msg(void *ctx); void _ng_connect(char const *path1, char const *hook1, char const *path2, char const *hook2, char const *file, size_t line) { struct ngm_connect c; strncpy(c.ourhook, hook1, sizeof(c.ourhook)); strncpy(c.peerhook, hook2, sizeof(c.peerhook)); strncpy(c.path, path2, sizeof(c.path)); CHECK(, -1 != NgSendMsg(cs, path1, NGM_GENERIC_COOKIE, NGM_CONNECT, &c, sizeof(c))); } void _ng_mkpeer(char const *path1, char const *hook1, char const *type, char const *hook2, char const *file, size_t line) { struct ngm_mkpeer p; strncpy(p.ourhook, hook1, sizeof(p.ourhook)); strncpy(p.peerhook, hook2, sizeof(p.peerhook)); strncpy(p.type, type, sizeof(p.type)); CHECK(, -1 != NgSendMsg(cs, path1, NGM_GENERIC_COOKIE, NGM_MKPEER, &p, sizeof(p))); } void _ng_rmhook(char const *path, char const *hook, char const *file, size_t line) { struct ngm_rmhook h; strncpy(h.ourhook, hook, sizeof(h.ourhook)); CHECK(, -1 != NgSendMsg(cs, path, NGM_GENERIC_COOKIE, NGM_RMHOOK, &h, sizeof(h))); } void _ng_name(char const *path, char const *name, char const *file, size_t line) { struct ngm_name n; strncpy(n.name, name, sizeof(n.name)); CHECK(, -1 != NgSendMsg(cs, path, NGM_GENERIC_COOKIE, NGM_NAME, &n, sizeof(n))); } void _ng_shutdown(char const *path, char const *file, size_t line) { CHECK(, -1 != NgSendMsg(cs, path, NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0)); } void ng_register_data(char const *hook, ng_data_handler_t proc) { struct data_handler *p; ATF_REQUIRE(NULL != (p = calloc(1, sizeof(struct data_handler)))); ATF_REQUIRE(NULL != (p->hook = strdup(hook))); ATF_REQUIRE(NULL != (p->handler = proc)); SLIST_INSERT_HEAD(&data_head, p, next); } void _ng_send_data(char const *hook, void const *data, size_t len, char const *file, size_t line) { CHECK(, -1 != NgSendData(ds, hook, data, len)); } void ng_register_msg(ng_msg_handler_t proc) { msg_handler = proc; } static void handle_msg(void *ctx) { struct ng_mesg *m; char path[NG_PATHSIZ]; ATF_REQUIRE(-1 != NgAllocRecvMsg(cs, &m, path)); if (msg_handler != NULL) (*msg_handler) (path, m, ctx); free(m); } static void handle_data(void *ctx) { char hook[NG_HOOKSIZ]; struct data_handler *hnd; u_char *data; int len; ATF_REQUIRE(0 < (len = NgAllocRecvData(ds, &data, hook))); SLIST_FOREACH(hnd, &data_head, next) { if (0 == strcmp(hnd->hook, hook)) break; } if (hnd != NULL) (*(hnd->handler)) (data, len, ctx); free(data); } int ng_handle_event(unsigned int ms, void *context) { fd_set fds; int maxfd = (ds < cs) ? cs : ds; struct timeval timeout = {0, ms * 1000lu}; FD_ZERO(&fds); FD_SET(cs, &fds); FD_SET(ds, &fds); retry: switch (select(maxfd + 1, &fds, NULL, NULL, &timeout)) { case -1: ATF_REQUIRE_ERRNO(EINTR, 1); goto retry; case 0: /* timeout */ return 0; default: /* something to do */ if (FD_ISSET(cs, &fds)) handle_msg(context); if (FD_ISSET(ds, &fds)) handle_data(context); return 1; } } void ng_handle_events(unsigned int ms, void *context) { while (ng_handle_event(ms, context)) ; } int _ng_send_msg(char const *path, char const *msg, char const *file, size_t line) { int res; CHECK(-1, -1 != (res = NgSendAsciiMsg(cs, path, "%s", msg))); return (res); } ng_error_t ng_errors(ng_error_t n) { ng_error_t o = error_handling; error_handling = n; return (o); } void _ng_init(char const *file, size_t line) { if (cs >= 0) /* prevent reinit */ return; CHECK(, 0 == NgMkSockNode(NULL, &cs, &ds)); NgSetDebug(3); } + +#define GD(x) void \ +get_data##x(void *data, size_t len, void *ctx) {\ + int *cnt = ctx; \ + \ + (void)data; \ + (void)len; \ + cnt[x]++; \ +} + +GD(0) +GD(1) +GD(2) +GD(3) +GD(4) +GD(5) +GD(6) +GD(7) +GD(8) +GD(9) diff --git a/tests/sys/netgraph/util.h b/tests/sys/netgraph/util.h index 21ecc68459ea..44c9f3a360a7 100644 --- a/tests/sys/netgraph/util.h +++ b/tests/sys/netgraph/util.h @@ -1,97 +1,114 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright 2021 Lutz Donnerhacke * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include void _ng_connect(char const *path1, char const *hook1, char const *path2, char const *hook2, char const *file, size_t line); #define ng_connect(p1,h1,p2,h2) \ _ng_connect(p1,h1,p2,h2,__FILE__,__LINE__) void _ng_mkpeer(char const *path1, char const *hook1, char const *type, char const *hook2, char const *file, size_t line); #define ng_mkpeer(p1,h1,t,h2) \ _ng_mkpeer(p1,h1,t,h2,__FILE__,__LINE__) void _ng_shutdown(char const *path, char const *file, size_t line); #define ng_shutdown(p) \ _ng_shutdown(p,__FILE__,__LINE__) void _ng_rmhook(char const *path, char const *hook, char const *file, size_t line); #define ng_rmhook(p,h) \ _ng_rmhook(p,h,__FILE__,__LINE__) void _ng_name(char const *path, char const *name, char const *file, size_t line); #define ng_name(p,n) \ _ng_name(p,n,__FILE__,__LINE__) typedef void (*ng_data_handler_t)(void *, size_t, void *ctx); void ng_register_data(char const *hook, ng_data_handler_t proc); void _ng_send_data(char const *hook, void const *, size_t, char const *file, size_t line); #define ng_send_data(h,d,l) \ _ng_send_data(h,d,l,__FILE__,__LINE__) typedef void (*ng_msg_handler_t)(char const *, struct ng_mesg *, void *); void ng_register_msg(ng_msg_handler_t proc); int _ng_send_msg(char const *path, char const *msg, char const *file, size_t line); #define ng_send_msg(p,m) \ _ng_send_msg(p,m,__FILE__,__LINE__) int ng_handle_event(unsigned int ms, void *ctx); void ng_handle_events(unsigned int ms, void *ctx); typedef enum { FAIL, PASS } ng_error_t; ng_error_t ng_errors(ng_error_t); void _ng_init(char const *file, size_t line); #define ng_init() \ _ng_init(__FILE__,__LINE__) + +/* Helper function to count received data */ + +typedef int ng_counter_t[10]; +#define ng_counter_clear(x)\ + bzero((x), sizeof(x)) + +void get_data0(void *data, size_t len, void *ctx); +void get_data1(void *data, size_t len, void *ctx); +void get_data2(void *data, size_t len, void *ctx); +void get_data3(void *data, size_t len, void *ctx); +void get_data4(void *data, size_t len, void *ctx); +void get_data5(void *data, size_t len, void *ctx); +void get_data6(void *data, size_t len, void *ctx); +void get_data7(void *data, size_t len, void *ctx); +void get_data8(void *data, size_t len, void *ctx); +void get_data9(void *data, size_t len, void *ctx);