From nobody Thu Feb 6 16:27:35 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YpjF36yzVz5mhdZ; Thu, 06 Feb 2025 16:27:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YpjF33Wfrz4My4; Thu, 06 Feb 2025 16:27:35 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1738859255; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nSNmAVku8hIvjXFJ1E/Sorc0516OsQ+EQdikWGlN4io=; b=lxpcSLPo4Gl8fx41QIXJrHrPDzqU8v5Wl5DqzHRFGjJZykRH5iQ+iinCFCMpvex7u3wpj0 QTq1pshS0N/E4Bv+HAzXbA/4dVOnZd0N0ZpZoMzv3UP5Wsjo5GkTfYXUxbuJDSeesf9zcp IOfL2gfm/fUJMJQWY2xztj+tYrUP38D4/BB8Fsk/D+UGM9BlDRojCGwD5Bk68Az2Tjjqg3 n19GGpu5d+QU9ibpERg3n7gLiMYk6P7inOuHGWhIHYIHBBeNH4mDzYdUuABmleCz+tP4SO FGzkhGLps74dCy9mfBI+6Pxe5bEQbOS+1H7eSwfrLZt2ItjIHkkq0Y2uxm5gdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1738859255; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nSNmAVku8hIvjXFJ1E/Sorc0516OsQ+EQdikWGlN4io=; b=MCODFoyOUmCYXYw4QdESKt2ljY8nXrmhEIR8EArF9NpsdcgjmrYVM+kzQdZi5FrQuCtGqv vYMNkSxCywH4Pd2aKerXcuxDP/M4b2sZQwxL3LNVzB5yv+OycyrSRN9BrIPlpLO2hXeTYW dRahAz4YD1cjIgLbFxaGKbQ2mK8wLAKzaX8PM+fRkup51QsnP1ujEPTzVtxUBoUxatQWX/ /G83Bm6HUheAjPbTHQEj9U+Fo4njD1NDLUJ7UU4Fi0l5XsFSivQptaHGfp2sbzf2UOwKiD wA+dYNpozkeMj+fr0c3nlkJWE7ng/oyTsDTDL3lXMNSHqK9wGLl9gdHOx5mrkQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1738859255; a=rsa-sha256; cv=none; b=ISe3ypQoS/Z+qxpMKIqQlZeUfeeS3Bz0S6CSD+/PKZ1WlNafi4SvLznFb3qMsir1F6Qt/h dsUgosnCAC7ZEh5b18o/QXDruF/wZ4tnPlO2YrOO1X2IAuQk265UXeRtg9x70c9HcSzFqP KfxeJvevNpZs6MTxuiQMev5tiwsj7MKlaHDF+9oyPgOvRTgEtSlntCxlPIZeRpabQUBLA/ dyI/jTy2IaMOUBOE46by2voOeb9pt6JxtiLt5Z/B1BwRb8CgL4/8XKVGIUZyU9SF/QxAVr RCy2GuM1K+qlZKCTXt03Twks1R5CKkD9rEa7fjE+zjRFxp+jM9XYpSCsS+RUow== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YpjF32zLqzmTn; Thu, 06 Feb 2025 16:27:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 516GRZwU095448; Thu, 6 Feb 2025 16:27:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 516GRZ58095445; Thu, 6 Feb 2025 16:27:35 GMT (envelope-from git) Date: Thu, 6 Feb 2025 16:27:35 GMT Message-Id: <202502061627.516GRZ58095445@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 3fa552149885 - main - tools: Add a small program to demonstrate FIB handling in bind(2) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3fa552149885766b009d95d20bdf651786fac7b7 Auto-Submitted: auto-generated The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=3fa552149885766b009d95d20bdf651786fac7b7 commit 3fa552149885766b009d95d20bdf651786fac7b7 Author: Mark Johnston AuthorDate: 2025-02-04 16:45:21 +0000 Commit: Mark Johnston CommitDate: 2025-02-06 16:25:31 +0000 tools: Add a small program to demonstrate FIB handling in bind(2) MFC after: 2 weeks Sponsored by: Klara, Inc. Sponsored by: Stormshield --- tools/tools/fib_multibind/Makefile | 4 + tools/tools/fib_multibind/sink.c | 237 +++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) diff --git a/tools/tools/fib_multibind/Makefile b/tools/tools/fib_multibind/Makefile new file mode 100644 index 000000000000..1d447e788a4f --- /dev/null +++ b/tools/tools/fib_multibind/Makefile @@ -0,0 +1,4 @@ +PROG= sink +MAN= + +.include diff --git a/tools/tools/fib_multibind/sink.c b/tools/tools/fib_multibind/sink.c new file mode 100644 index 000000000000..fe93a66fe266 --- /dev/null +++ b/tools/tools/fib_multibind/sink.c @@ -0,0 +1,237 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Klara, Inc. + */ + +/* + * A program to demonstrate the effects of the net.inet.tcp.bind_all_fibs and + * net.inet.udp.bind_all_fibs sysctls when they are set to 0. + * + * The program accepts TCP connections (default) or UDP datagrams (-u flag) and + * prints the FIB on which they were received, then discards them. If -a is + * specific, the program accepts data from all FIBs, otherwise it only accepts + * data from the FIB specified by the -f option. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +struct sink_softc { + struct sockaddr_storage ss; + enum { SINK_TCP, SINK_UDP } type; + int nfibs; + int kq; + int *fds; +}; + +static void _Noreturn +usage(void) +{ + fprintf(stderr, + "usage: sink [-au] [-f ] [] \n"); + exit(1); +} + +static void +check_multibind(struct sink_softc *sc) +{ + const char *sysctl; + size_t len; + int error, val; + + sysctl = sc->type == SINK_TCP ? "net.inet.tcp.bind_all_fibs" : + "net.inet.udp.bind_all_fibs"; + len = sizeof(val); + error = sysctlbyname(sysctl, &val, &len, NULL, 0); + if (error != 0) + err(1, "sysctlbyname(%s)", sysctl); + if (val != 0) + errx(1, "multibind is disabled, set %s=0 to enable", sysctl); +} + +static void +addrinfo(struct sink_softc *sc, const char *addr, int port) +{ + struct addrinfo hints, *res, *res1; + char portstr[8]; + int error; + + memset(&sc->ss, 0, sizeof(sc->ss)); + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = sc->type == SINK_TCP ? SOCK_STREAM : SOCK_DGRAM; + snprintf(portstr, sizeof(portstr), "%d", port); + error = getaddrinfo(addr, portstr, &hints, &res); + if (error != 0) + errx(1, "%s", gai_strerror(error)); + for (res1 = res; res != NULL; res = res->ai_next) { + if ((res->ai_protocol == IPPROTO_TCP && sc->type == SINK_TCP) || + (res->ai_protocol == IPPROTO_UDP && sc->type == SINK_UDP)) { + memcpy(&sc->ss, res->ai_addr, res->ai_addrlen); + break; + } + } + if (res == NULL) { + errx(1, "no %s address found for '%s'", + sc->type == SINK_TCP ? "TCP" : "UDP", addr); + } + freeaddrinfo(res1); +} + +int +main(int argc, char **argv) +{ + struct sink_softc sc; + const char *laddr; + int ch, error, fib, lport; + bool all; + + all = false; + sc.type = SINK_TCP; + fib = -1; + while ((ch = getopt(argc, argv, "af:u")) != -1) { + switch (ch) { + case 'a': + all = true; + break; + case 'f': + fib = atoi(optarg); + break; + case 'u': + sc.type = SINK_UDP; + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + if (all && fib != -1) + errx(1, "-a and -f are mutually exclusive"); + if (fib == -1) { + size_t len; + + error = sysctlbyname("net.my_fibnum", &fib, &len, NULL, 0); + if (error != 0) + err(1, "sysctlbyname(net.my_fibnum)"); + } + + if (argc == 2) { + laddr = argv[0]; + lport = atoi(argv[1]); + } else if (argc == 1) { + laddr = NULL; + lport = atoi(argv[0]); + } else { + usage(); + } + addrinfo(&sc, laddr, lport); + + check_multibind(&sc); + + sc.kq = kqueue(); + if (sc.kq == -1) + err(1, "kqueue"); + + if (all) { + size_t len; + + len = sizeof(sc.nfibs); + error = sysctlbyname("net.fibs", &sc.nfibs, &len, NULL, 0); + if (error != 0) + err(1, "sysctlbyname(net.fibs)"); + } else { + sc.nfibs = 1; + } + + sc.fds = calloc(all ? sc.nfibs : 1, sizeof(int)); + if (sc.fds == NULL) + err(1, "calloc"); + for (int i = 0; i < sc.nfibs; i++) { + struct kevent kev; + int s; + + if (sc.type == SINK_TCP) + s = socket(sc.ss.ss_family, SOCK_STREAM, 0); + else + s = socket(sc.ss.ss_family, SOCK_DGRAM, 0); + if (s == -1) + err(1, "socket"); + error = setsockopt(s, SOL_SOCKET, SO_SETFIB, + all ? &i : &fib, sizeof(int)); + if (error != 0) + err(1, "setsockopt(SO_SETFIB)"); + + error = bind(s, (struct sockaddr *)&sc.ss, sc.ss.ss_len); + if (error != 0) + err(1, "bind"); + + if (sc.type == SINK_TCP) { + error = listen(s, 5); + if (error != 0) + err(1, "listen"); + } + + EV_SET(&kev, s, EVFILT_READ, EV_ADD, 0, 0, NULL); + error = kevent(sc.kq, &kev, 1, NULL, 0, NULL); + if (error != 0) + err(1, "kevent"); + + sc.fds[i] = s; + } + + for (;;) { + struct kevent kev; + socklen_t optlen; + int n; + + n = kevent(sc.kq, NULL, 0, &kev, 1, NULL); + if (n == -1) + err(1, "kevent"); + if (n == 0) + continue; + + optlen = sizeof(fib); + error = getsockopt((int)kev.ident, SOL_SOCKET, SO_FIB, + &fib, &optlen); + if (error == -1) + err(1, "getsockopt(SO_FIB)"); + + if (sc.type == SINK_TCP) { + int cs; + + printf("accepting connection from FIB %d\n", fib); + + cs = accept((int)kev.ident, NULL, NULL); + if (cs == -1) + err(1, "accept"); + close(cs); + } else { + char buf[1024]; + ssize_t nb; + + printf("receiving datagram from FIB %d\n", fib); + + nb = recvfrom((int)kev.ident, buf, sizeof(buf), 0, + NULL, NULL); + if (nb == -1) + err(1, "recvfrom"); + } + } + + return (0); +}