From nobody Fri Apr 18 12:34:20 2025 X-Original-To: dev-commits-src-main@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 4ZfDj86LhDz5skjQ; Fri, 18 Apr 2025 12:34:20 +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 "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZfDj83l6Hz3PYT; Fri, 18 Apr 2025 12:34:20 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744979660; 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=zQmqC2ny65e6rAvHnw8X2oAeTZO17OFcjxmAgiAs1vc=; b=jrItLOr2iXgWRDdg4zlrwtURIuxjo0/ep49IhfYQyHij76D3Qj9hj/xdaET04Q9rv/fFXx /Lqt7Xdr31DN3yhghmRY+g6JrpYtCRtP0T7ss3jw16kuZrVdpf64A65lonyTDaqCbQnv8W 6r06pYWcPdvP+Lm4/qVtGS0LDKJz1n6sHP1hVRVTMDYJy63hh1Ivdushps6N2sN2knyrqZ 0TeSJ/+LJnxNPFekuVFhOVHl4gTfR6S9Fqi9kcqwcbhIuK0Y3Pkra4IGqFjGc5pje7WKdF clSglvq+wRZ3EAKEQ9/XOd47dl77UMNePmb4xOlBfmG+qHw03+Sq42m/d6BC5A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1744979660; a=rsa-sha256; cv=none; b=IcAq0gHwBC/lGIz379cZYubRmc9oHfVsbsaU3TjlMCrxHNRsn4M3BXXpDerhnbOTdFVM68 mOmW9BWgtbb2mrlIqU2cRzQ1/gBjrCgvEx4sE83sCH/lYOYR35UQv0Xart30C6YGKpelwM pmkU8F3q/j6YbKpeFIgRmKnyMTNm3Ro6ZQ6+GvOMI3SBQbuTJKt8ug+hNCcriPd9ZNbl64 5i9qY+J7g2LXVyq/WWv0b0qzF/abNIDrUwoDMGkY648fhVZWFn4A/Tg71fQ7jgnMhxYU15 NbmSA4QGmBKOHGejoRA3cU9sN8MdEJU5z810uAZ6T1b9osxyPSxhjbfIgMccQg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744979660; 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=zQmqC2ny65e6rAvHnw8X2oAeTZO17OFcjxmAgiAs1vc=; b=X4Wmob3XxAv8GLydcSxLQxs0Z7+SNXaLxvSAcAygdHvSVvc7Iii4H7nePutdU/rnmDHg5z wkAGtMotpD5NJbd+SNyFUxDqgpUZvRi6qna6WTLlmt1iBhTcBu+ux/F7zDe8G3zlK7IYhS vVtrWIH77moAQRM+U1gMX6Rs+jAzo5Xs5wlMKpw4No6YAnYuBjVRp/QvRASTpj7kcGXgr0 MBN6XhXfOOSUyJvlw1FJhsFWDjbijgDGkM57dwdOq6OV84+Si6oda7tBJ+MFuYfRc4/IqP eMWAaH8PmHsS+yMs3sVopoPCgf9Hlj04cW7X0Zormg5UqUKJVsnJJfsxN3BOGA== 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 4ZfDj83J3Pzb68; Fri, 18 Apr 2025 12:34:20 +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 53ICYKUT064658; Fri, 18 Apr 2025 12:34:20 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53ICYKOZ064655; Fri, 18 Apr 2025 12:34:20 GMT (envelope-from git) Date: Fri, 18 Apr 2025 12:34:20 GMT Message-Id: <202504181234.53ICYKOZ064655@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Andrey V. Elsukov" Subject: git: 3c76623ad553 - main - ipfw: add 'internal monitor' subcommand to capture rtsock messages. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ae X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3c76623ad55369c3998b2b00d7322f8aeedc98fd Auto-Submitted: auto-generated The branch main has been updated by ae: URL: https://cgit.FreeBSD.org/src/commit/?id=3c76623ad55369c3998b2b00d7322f8aeedc98fd commit 3c76623ad55369c3998b2b00d7322f8aeedc98fd Author: Andrey V. Elsukov AuthorDate: 2025-04-18 12:22:56 +0000 Commit: Andrey V. Elsukov CommitDate: 2025-04-18 12:22:56 +0000 ipfw: add 'internal monitor' subcommand to capture rtsock messages. This command is similar to route(8) monitor subcommand. It can be used for debugging rules in run-time. Also add __pritflike() to bprintf function and fix some related bugs. Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sbin/ipfw/ipfw.8 | 11 +++++ sbin/ipfw/ipfw2.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++- sbin/ipfw/ipfw2.h | 3 +- 3 files changed, 148 insertions(+), 3 deletions(-) diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 719f92e96e68..ddfdc35ce651 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -171,6 +171,8 @@ in-kernel NAT.\& .Nm .Cm internal iflist .Nm +.Cm internal monitor Op Ar filter-comment +.Nm .Cm internal talist .Nm .Cm internal vlist @@ -4332,6 +4334,15 @@ sub-options: Lists all interface which are currently tracked by .Nm with their in-kernel status. +.It Cm monitor Op Ar filter-comment +Capture messages from +.Xr route 4 +socket, that were logged using rules with +.Cm log Cm logdst Ar rtsock +opcode. Optional +.Ar filter-comment +can be specified to show only those messages, that were logged +by rules with specific rule comment. .It Cm talist List all table lookup algorithms currently available. .El diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index be796808380f..8eeff72463b5 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -47,6 +47,8 @@ #include #include /* only IFNAMSIZ */ +#include +#include #include #include /* only n_short, n_long */ #include @@ -2009,7 +2011,7 @@ print_logdst(struct buf_pr *bp, uint16_t arg1) { char const *comma = ""; - bprintf(bp, " logdst ", arg1); + bprintf(bp, " logdst "); if (arg1 & IPFW_LOG_SYSLOG) { bprintf(bp, "%ssyslog", comma); comma = ","; @@ -2179,7 +2181,7 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo, if (cmd->len == F_INSN_SIZE(ipfw_insn)) bprintf(bp, " %u", cmd->arg1); else - bprintf(bp, " %ubytes", + bprintf(bp, " %lubytes", cmd->len * sizeof(uint32_t)); break; case O_SETDSCP: @@ -5956,6 +5958,7 @@ static struct _s_x intcmds[] = { { "iflist", TOK_IFLIST }, { "olist", TOK_OLIST }, { "vlist", TOK_VLIST }, + { "monitor", TOK_MONITOR }, { NULL, 0 } }; @@ -6030,6 +6033,132 @@ ipfw_list_objects(int ac __unused, char *av[] __unused) free(olh); } +static void +bprint_sa(struct buf_pr *bp, const struct sockaddr *sa) +{ + struct sockaddr_storage ss; + char buf[INET6_ADDRSTRLEN]; + + memset(&ss, 0, sizeof(ss)); + if (sa->sa_len == 0) + ss.ss_family = sa->sa_family; + else + memcpy(&ss, sa, sa->sa_len); + + /* set ss_len in case it was shortened */ + switch (sa->sa_family) { + case AF_INET: + ss.ss_len = sizeof(struct sockaddr_in); + break; + default: + ss.ss_len = sizeof(struct sockaddr_in6); + } + if (getnameinfo((const struct sockaddr *)&ss, ss.ss_len, + buf, sizeof(buf), NULL, 0, NI_NUMERICHOST) != 0) { + bprintf(bp, "bad-addr"); + return; + } + bprintf(bp, "%s", buf); +} + +static void +ipfw_rtsock_monitor(const char *filter) +{ + char msg[2048], buf[32]; + struct timespec tp; + struct tm tm; + struct buf_pr bp; + struct rt_msghdr *hdr; + struct sockaddr *sa; + struct sockaddr_dl *sdl; + ipfwlog_rtsock_hdr_v2 *loghdr; + ssize_t msglen; + int rtsock; + + rtsock = socket(PF_ROUTE, SOCK_RAW, AF_IPFWLOG); + if (rtsock < 0) + err(EX_UNAVAILABLE, "socket(AF_IPFWLOG)"); + bp_alloc(&bp, 4096); + for (;;) { + msglen = read(rtsock, msg, sizeof(msg)); + if (msglen < 0) { + warn("read()"); + continue; + } + if (sizeof(*hdr) - msglen < 0) + continue; + + hdr = (struct rt_msghdr *)msg; + if (hdr->rtm_version != RTM_VERSION || + hdr->rtm_type != RTM_IPFWLOG || + (hdr->rtm_addrs & (1 << RTAX_DST)) == 0 || + (hdr->rtm_addrs & (1 << RTAX_GATEWAY)) == 0 || + (hdr->rtm_addrs & (1 << RTAX_NETMASK)) == 0) + continue; + + msglen -= sizeof(*hdr); + sdl = (struct sockaddr_dl *)(hdr + 1); + if (msglen - sizeof(*sdl) < 0 || msglen - SA_SIZE(sdl) < 0 || + sdl->sdl_family != AF_IPFWLOG || + sdl->sdl_type != 2 /* version */ || + sdl->sdl_alen != sizeof(*loghdr)) + continue; + + msglen -= SA_SIZE(sdl); + loghdr = (ipfwlog_rtsock_hdr_v2 *)sdl->sdl_data; + /* filter by rule comment. MAX_COMMENT_LEN = 80 */ + if (filter != NULL && + strncmp(filter, loghdr->comment, 80) != 0) + continue; + + sa = (struct sockaddr *)((char *)sdl + SA_SIZE(sdl)); + if (msglen - SA_SIZE(sa) < 0) + continue; + + msglen -= SA_SIZE(sa); + bp_flush(&bp); + + clock_gettime(CLOCK_REALTIME, &tp); + localtime_r(&tp.tv_sec, &tm); + strftime(buf, sizeof(buf), "%T", &tm); + bprintf(&bp, "%s.%03ld AF %s", buf, tp.tv_nsec / 1000000, + sa->sa_family == AF_INET ? "IPv4" : "IPv6"); + + bprintf(&bp, " %s >", + ether_ntoa((const struct ether_addr *)loghdr->ether_shost)); + bprintf(&bp, " %s, ", + ether_ntoa((const struct ether_addr *)loghdr->ether_dhost)); + bprint_sa(&bp, sa); + + sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); + if (msglen - SA_SIZE(sa) < 0) + continue; + + msglen -= SA_SIZE(sa); + bprintf(&bp, " > "); + bprint_sa(&bp, sa); + bprintf(&bp, ", set %u, rulenum %u, targ 0x%08x, " + "%scmd[op %d, len %d, arg1 0x%04x], mark 0x%08x", + sdl->sdl_index, loghdr->rulenum, loghdr->tablearg, + (loghdr->cmd.len & F_NOT) ? "!": "", + loghdr->cmd.opcode, F_LEN(&loghdr->cmd), + loghdr->cmd.arg1, loghdr->mark); + + sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); + if ((hdr->rtm_addrs & (1 << RTAX_GENMASK)) != 0 && + msglen - SA_SIZE(sa) >= 0) { + msglen -= SA_SIZE(sa); + bprintf(&bp, ", nh "); + bprint_sa(&bp, sa); + } + if (sdl->sdl_nlen > 0) + bprintf(&bp, " // %s", loghdr->comment); + printf("%s\n", bp.buf); + } + bp_free(&bp); + close(rtsock); +} + void ipfw_internal_handler(int ac, char *av[]) { @@ -6054,6 +6183,10 @@ ipfw_internal_handler(int ac, char *av[]) case TOK_VLIST: ipfw_list_values(ac, av); break; + case TOK_MONITOR: + av++; + ipfw_rtsock_monitor(*av); + break; } } diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 788e9fe365f3..f19ea59c1bb4 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -275,6 +275,7 @@ enum tokens { TOK_UNLOCK, TOK_VLIST, TOK_OLIST, + TOK_MONITOR, TOK_MISSING, TOK_ORFLUSH, @@ -347,7 +348,7 @@ struct buf_pr { int pr_u64(struct buf_pr *bp, void *pd, int width); int bp_alloc(struct buf_pr *b, size_t size); void bp_free(struct buf_pr *b); -int bprintf(struct buf_pr *b, const char *format, ...); +int bprintf(struct buf_pr *b, const char *format, ...) __printflike(2, 3); /* memory allocation support */