On Mon, Nov 15, 2021 at 05:23:43PM +0100, Alexander Bluhm wrote:
> Hi,
>
> To debug IPsec and tdb refcounting it may be useful to have "show
> tdb" and "show all tdbs" in ddb.
>
> ok?
>
Indeed this is useful.
ok mvs@
> bluhm
>
> Index: share/man/man4/ddb.4
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/share/man/man4/ddb.4,v
> retrieving revision 1.99
> diff -u -p -r1.99 ddb.4
> --- share/man/man4/ddb.4 26 Oct 2020 18:53:20 -0000 1.99
> +++ share/man/man4/ddb.4 15 Nov 2021 14:43:46 -0000
> @@ -812,6 +812,19 @@ as a struct
> Nested structures and bit fields are not printed.
> Character arrays are printed as bytes.
> .\" --------------------
> +.It Xo
> +.Ic show tdb
> +.Op Cm /f
> +.Ar addr
> +.Xc
> +Prints the
> +.Li struct tdb
> +at
> +.Ar addr .
> +If the
> +.Cm /f
> +modifier is specified prints out all fields of this IPsec SA.
> +.\" --------------------
> .It Ic show uvmexp
> Displays a selection of uvm counters and statistics.
> .\" --------------------
> @@ -938,6 +951,17 @@ Display information for all outstanding
> For each NFS requests, print a more detailed output.
> See the
> .Ic show nfsreq
> +command for more information.
> +.El
> +.\" --------------------
> +.It Ic show all tdbs Op Cm /f
> +Display information about all IPsec SAs in the system.
> +.Pp
> +.Bl -tag -width foo -compact
> +.It Cm /f
> +For each tdb, print a more detailed output.
> +See the
> +.Ic show tdb
> command for more information.
> .El
> .\" --------------------
> Index: sys/ddb/db_command.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/ddb/db_command.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 db_command.c
> --- sys/ddb/db_command.c 2 Jun 2021 00:39:25 -0000 1.91
> +++ sys/ddb/db_command.c 15 Nov 2021 13:54:41 -0000
> @@ -56,6 +56,7 @@
> #include <ddb/db_interface.h>
> #include <ddb/db_extern.h>
>
> +#include <netinet/ip_ipsp.h>
> #include <uvm/uvm_ddb.h>
>
> /*
> @@ -89,12 +90,14 @@ void db_mount_print_cmd(db_expr_t, int,
> void db_show_all_mounts(db_expr_t, int, db_expr_t, char *);
> void db_show_all_vnodes(db_expr_t, int, db_expr_t, char *);
> void db_show_all_bufs(db_expr_t, int, db_expr_t, char *);
> +void db_show_all_tdbs(db_expr_t, int, db_expr_t, char *);
> void db_object_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_page_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_extent_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_pool_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_proc_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_uvmexp_print_cmd(db_expr_t, int, db_expr_t, char *);
> +void db_tdb_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_vnode_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_nfsreq_print_cmd(db_expr_t, int, db_expr_t, char *);
> void db_nfsnode_print_cmd(db_expr_t, int, db_expr_t, char *);
> @@ -399,6 +402,19 @@ db_show_all_bufs(db_expr_t addr, int hav
> pool_walk(&bufpool, full, db_printf, vfs_buf_print);
> }
>
> +#ifdef IPSEC
> +void
> +db_show_all_tdbs(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
> +{
> + int full = 0;
> +
> + if (modif[0] == 'f')
> + full = 1;
> +
> + pool_walk(&tdb_pool, full, db_printf, tdb_printit);
> +}
> +#endif
> +
> /*ARGSUSED*/
> void
> db_object_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char
> *modif)
> @@ -509,6 +525,19 @@ db_proc_print_cmd(db_expr_t addr, int ha
> proc_printit((struct proc *)addr, modif, db_printf);
> }
>
> +#ifdef IPSEC
> +void
> +db_tdb_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
> +{
> + int full = 0;
> +
> + if (modif[0] == 'f')
> + full = 1;
> +
> + tdb_printit((void *)addr, full, db_printf);
> +}
> +#endif
> +
> /*ARGSUSED*/
> void
> db_uvmexp_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char
> *modif)
> @@ -540,6 +569,9 @@ struct db_command db_show_all_cmds[] = {
> { "nfsreqs", db_show_all_nfsreqs, 0, NULL },
> { "nfsnodes", db_show_all_nfsnodes, 0, NULL },
> #endif
> +#ifdef IPSEC
> + { "tdbs", db_show_all_tdbs, 0, NULL },
> +#endif
> #ifdef WITNESS
> { "locks", db_witness_list_all, 0, NULL },
> #endif
> @@ -571,6 +603,9 @@ struct db_command db_show_cmds[] = {
> { "registers", db_show_regs, 0, NULL },
> { "socket", db_socket_print_cmd, 0, NULL },
> { "struct", db_ctf_show_struct, CS_OWN, NULL },
> +#ifdef IPSEC
> + { "tdb", db_tdb_print_cmd, 0, NULL },
> +#endif
> { "uvmexp", db_uvmexp_print_cmd, 0, NULL },
> { "vnode", db_vnode_print_cmd, 0, NULL },
> { "watches", db_listwatch_cmd, 0, NULL },
> Index: sys/netinet/ip_ipsp.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.c,v
> retrieving revision 1.249
> diff -u -p -r1.249 ip_ipsp.c
> --- sys/netinet/ip_ipsp.c 27 Oct 2021 16:58:44 -0000 1.249
> +++ sys/netinet/ip_ipsp.c 15 Nov 2021 16:16:34 -0000
> @@ -532,6 +532,85 @@ tdb_hashstats(void)
> db_printf("%d%s\t\t%d\n", i, i == NBUCKETS - 1 ?
> "+" : "", buckets[i]);
> }
> +
> +#define DUMP(m, f) pr("%18s: " f "\n", #m, tdb->tdb_##m)
> +void
> +tdb_printit(void *addr, int full, int (*pr)(const char *, ...))
> +{
> + struct tdb *tdb = addr;
> + char buf[INET6_ADDRSTRLEN];
> +
> + if (full) {
> + pr("tdb at %p\n", tdb);
> + DUMP(hnext, "%p");
> + DUMP(dnext, "%p");
> + DUMP(snext, "%p");
> + DUMP(inext, "%p");
> + DUMP(onext, "%p");
> + DUMP(xform, "%p");
> + DUMP(encalgxform, "%p");
> + DUMP(authalgxform, "%p");
> + DUMP(compalgxform, "%p");
> + pr("%18s: %b\n", "flags", tdb->tdb_flags, TDBF_BITS);
> + /* tdb_XXX_tmo */
> + DUMP(seq, "%d");
> + DUMP(exp_allocations, "%d");
> + DUMP(soft_allocations, "%d");
> + DUMP(cur_allocations, "%d");
> + DUMP(exp_bytes, "%lld");
> + DUMP(soft_bytes, "%lld");
> + DUMP(cur_bytes, "%lld");
> + DUMP(exp_timeout, "%lld");
> + DUMP(soft_timeout, "%lld");
> + DUMP(established, "%lld");
> + DUMP(first_use, "%lld");
> + DUMP(soft_first_use, "%lld");
> + DUMP(exp_first_use, "%lld");
> + DUMP(last_used, "%lld");
> + DUMP(last_marked, "%lld");
> + /* tdb_data */
> + DUMP(cryptoid, "%lld");
> + pr("%18s: %08x\n", "tdb_spi", ntohl(tdb->tdb_spi));
> + DUMP(amxkeylen, "%d");
> + DUMP(emxkeylen, "%d");
> + DUMP(ivlen, "%d");
> + DUMP(sproto, "%d");
> + DUMP(wnd, "%d");
> + DUMP(satype, "%d");
> + DUMP(updates, "%d");
> + pr("%18s: %s\n", "dst",
> + ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)));
> + pr("%18s: %s\n", "src",
> + ipsp_address(&tdb->tdb_src, buf, sizeof(buf)));
> + DUMP(amxkey, "%p");
> + DUMP(emxkey, "%p");
> + DUMP(rpl, "%lld");
> + /* tdb_seen */
> + /* tdb_iv */
> + DUMP(ids, "%p");
> + DUMP(ids_swapped, "%d");
> + DUMP(mtu, "%d");
> + DUMP(mtutimeout, "%lld");
> + pr("%18s: %08x\n", "udpencap_port",
> + ntohl(tdb->tdb_udpencap_port));
> + DUMP(tag, "%d");
> + DUMP(tap, "%d");
> + DUMP(rdomain, "%d");
> + DUMP(rdomain_post, "%d");
> + /* tdb_filter */
> + /* tdb_filtermask */
> + /* tdb_policy_head */
> + /* tdb_sync_entry */
> + } else {
> + pr("%p:", tdb);
> + pr(" %08x", ntohl(tdb->tdb_spi));
> + pr(" %s", ipsp_address(&tdb->tdb_src, buf, sizeof(buf)));
> + pr("->%s", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)));
> + pr(":%d", tdb->tdb_sproto);
> + pr(" %08x\n", tdb->tdb_flags);
> + }
> +}
> +#undef DUMP
> #endif /* DDB */
>
> int
> @@ -939,7 +1018,7 @@ tdb_init(struct tdb *tdbp, u_int16_t alg
> return EINVAL;
> }
>
> -#ifdef ENCDEBUG
> +#if defined(DDB) || defined(ENCDEBUG)
> /* Return a printable string for the address. */
> const char *
> ipsp_address(union sockaddr_union *sa, char *buf, socklen_t size)
> @@ -959,7 +1038,7 @@ ipsp_address(union sockaddr_union *sa, c
> return "(unknown address family)";
> }
> }
> -#endif /* ENCDEBUG */
> +#endif /* DDB || ENCDEBUG */
>
> /* Check whether an IP{4,6} address is unspecified. */
> int
> Index: sys/netinet/ip_ipsp.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.h,v
> retrieving revision 1.219
> diff -u -p -r1.219 ip_ipsp.h
> --- sys/netinet/ip_ipsp.h 25 Oct 2021 18:25:01 -0000 1.219
> +++ sys/netinet/ip_ipsp.h 15 Nov 2021 13:33:05 -0000
> @@ -345,6 +345,14 @@ struct tdb { /* tunnel
> descriptor blo
> #define TDBF_PFSYNC_RPL 0x80000 /* Replay counter should be
> bumped */
> #define TDBF_ESN 0x100000 /* 64-bit sequence numbers
> (ESN) */
>
> +#define TDBF_BITS ("\20" \
> + "\1UNIQUE\2TIMER\3BYTES\4ALLOCATIONS" \
> + "\5INVALID\6FIRSTUSE\10SOFT_TIMER" \
> + "\11SOFT_BYTES\12SOFT_ALLOCATIONS\13SOFT_FIRSTUSE\14PFS" \
> + "\15TUNNELING" \
> + "\21USEDTUNNEL\22UDPENCAP\23PFSYNC\24PFSYNC_RPL" \
> + "\25ESN")
> +
> u_int32_t tdb_flags; /* Flags related to this TDB */
>
> struct timeout tdb_timer_tmo;
> @@ -486,6 +494,7 @@ struct xformsw {
> extern int ipsec_in_use;
> extern u_int64_t ipsec_last_added;
> extern int encdebug; /* enable message reporting */
> +extern struct pool tdb_pool;
>
> extern int ipsec_keep_invalid; /* lifetime of embryonic SAs
> (in sec) */
> extern int ipsec_require_pfs; /* use Perfect Forward Secrecy
> */
> @@ -526,9 +535,7 @@ extern TAILQ_HEAD(ipsec_policy_head, ips
> struct cryptop;
>
> /* Misc. */
> -#ifdef ENCDEBUG
> const char *ipsp_address(union sockaddr_union *, char *, socklen_t);
> -#endif /* ENCDEBUG */
>
> /* SPD tables */
> struct radix_node_head *spd_table_add(unsigned int);
> @@ -560,6 +567,7 @@ int tdb_init(struct tdb *, u_int16_t, st
> void tdb_unlink(struct tdb *);
> void tdb_unlink_locked(struct tdb *);
> int tdb_walk(u_int, int (*)(struct tdb *, void *, int), void *);
> +void tdb_printit(void *, int, int (*)(const char *, ...));
>
> /* XF_IP4 */
> int ipe4_attach(void);
>