[DTrace-devel] [PATCH v2] Add support for inet_ntop() subroutine

Eugene Loh eugene.loh at oracle.com
Thu Sep 14 19:56:38 UTC 2023


Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                             |  69 +++++++++++-
 test/unittest/funcs/tst.inet_ntop.d           |   1 -
 .../unittest/funcs/tst.inet_ntop_runtime_af.d | 104 ++++++++++++++++++
 .../unittest/funcs/tst.inet_ntop_runtime_af.r |  12 ++
 4 files changed, 184 insertions(+), 2 deletions(-)
 create mode 100644 test/unittest/funcs/tst.inet_ntop_runtime_af.d
 create mode 100644 test/unittest/funcs/tst.inet_ntop_runtime_af.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 372694d8..0c518953 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -5986,6 +5986,73 @@ dt_cg_subr_inet_ntoa6(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 				  DT_ISIMM, tbloff);
 }
 
+static void
+dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_node_t	*af = dnp->dn_args;
+	dt_node_t	*addr = af->dn_list;
+	dt_node_t	*tnp, *cnp, *lnp, *rnp, *anp, *xnp;;
+	dt_idsig_t	*isp;
+	dt_decl_t	*ddp;
+
+	/*
+	 * Implement this subroutine as a ternary expression:
+	 *
+	 *	af == AF_INET6 ? inet_ntoa6((typ1)addr) : inet_ntoa((typ2)addr)
+	 *
+	 * where typ1 is the datatype of the argument of inet_ntoa6()
+	 *	 typ2 is the datatype of the argument of inet_ntoa()
+	 */
+	cnp = dt_node_op2(DT_TOK_EQU, af, dt_node_int(AF_INET6));
+
+	/* Create a node for the function call: inet_ntoa6(addr) */
+	lnp = dt_node_func(dt_node_ident(strdup("inet_ntoa6")), addr);
+
+	/* Get the datatype of the argument of inet_ntoa6(). */
+	assert(lnp->dn_ident && lnp->dn_ident->di_data);
+	isp = lnp->dn_ident->di_data;
+	assert(isp->dis_args);
+	anp = &isp->dis_args[0];
+	ddp = dt_decl_alloc(ctf_type_kind(anp->dn_ctfp, anp->dn_type), NULL);
+	ddp->dd_ctfp = anp->dn_ctfp;
+	ddp->dd_type = anp->dn_type;
+	xnp = dt_node_type(ddp);		/* frees ddp */
+	/* Create a node to represent: (type)addr */
+	xnp = dt_node_op2(DT_TOK_LPAR, xnp, addr);
+
+	lnp->dn_args = xnp;			/* inet_ntoa6((type)addr) */
+
+	/* Create a node for the function call: inet_ntoa(addr) */
+	rnp = dt_node_func(dt_node_ident(strdup("inet_ntoa")), addr);
+
+	/* Get the datatype of the argument of inet_ntoa(). */
+	assert(rnp->dn_ident && rnp->dn_ident->di_data);
+	isp = rnp->dn_ident->di_data;
+	assert(isp->dis_args);
+	anp = &isp->dis_args[0];
+	ddp = dt_decl_alloc(ctf_type_kind(anp->dn_ctfp, anp->dn_type), NULL);
+	ddp->dd_ctfp = anp->dn_ctfp;
+	ddp->dd_type = anp->dn_type;
+	xnp = dt_node_type(ddp);		/* frees ddp */
+
+	xnp = dt_node_op2(DT_TOK_LPAR, xnp, addr); /* (type)addr */
+	rnp->dn_args = xnp;			/* inet_ntoa((type)addr) */
+
+	tnp = dt_node_op3(cnp, lnp, rnp);	/* cnp ? lnp : rnp */
+
+	/* Finalize the node tree and generate code. */
+	dt_node_cook(tnp, 0);
+	dt_cg_node(tnp, dlp, drp);
+
+	/*
+	 * Copy the result into dnp (register value and tstring).  We need to
+	 * clear the tstring from tnp once we move it to dnp.
+	 */
+	dnp->dn_reg = tnp->dn_reg;
+	dnp->dn_tstring = tnp->dn_tstring;
+	tnp->dn_tstring = NULL;
+}
+
 typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);
 
 static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
@@ -6030,7 +6097,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
 	[DIF_SUBR_NTOHS]		= &dt_cg_subr_htons,
 	[DIF_SUBR_NTOHL]		= &dt_cg_subr_htonl,
 	[DIF_SUBR_NTOHLL]		= &dt_cg_subr_htonll,
-	[DIF_SUBR_INET_NTOP]		= NULL,
+	[DIF_SUBR_INET_NTOP]		= &dt_cg_subr_inet_ntop,
 	[DIF_SUBR_INET_NTOA]		= &dt_cg_subr_inet_ntoa,
 	[DIF_SUBR_INET_NTOA6]		= &dt_cg_subr_inet_ntoa6,
 	[DIF_SUBR_D_PATH]		= NULL,
diff --git a/test/unittest/funcs/tst.inet_ntop.d b/test/unittest/funcs/tst.inet_ntop.d
index 234effb2..e2f00356 100644
--- a/test/unittest/funcs/tst.inet_ntop.d
+++ b/test/unittest/funcs/tst.inet_ntop.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/funcs/tst.inet_ntop_runtime_af.d b/test/unittest/funcs/tst.inet_ntop_runtime_af.d
new file mode 100644
index 00000000..7843a4ea
--- /dev/null
+++ b/test/unittest/funcs/tst.inet_ntop_runtime_af.d
@@ -0,0 +1,104 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * Check that inet_ntop(af, addr) works even if af is not known until runtime.
+ */
+
+#pragma D option quiet
+
+ipaddr_t *ip4a;
+ipaddr_t *ip4b;
+ipaddr_t *ip4c;
+ipaddr_t *ip4d;
+struct in6_addr *ip6a;
+struct in6_addr *ip6b;
+struct in6_addr *ip6c;
+struct in6_addr *ip6d;
+struct in6_addr *ip6e;
+struct in6_addr *ip6f;
+struct in6_addr *ip6g;
+
+BEGIN
+{
+	this->buf4a = alloca(sizeof(ipaddr_t));
+	this->buf4b = alloca(sizeof(ipaddr_t));
+	this->buf4c = alloca(sizeof(ipaddr_t));
+	this->buf4d = alloca(sizeof(ipaddr_t));
+	this->buf6a = alloca(sizeof(struct in6_addr));
+	this->buf6b = alloca(sizeof(struct in6_addr));
+	this->buf6c = alloca(sizeof(struct in6_addr));
+	this->buf6d = alloca(sizeof(struct in6_addr));
+	this->buf6e = alloca(sizeof(struct in6_addr));
+	this->buf6f = alloca(sizeof(struct in6_addr));
+	this->buf6g = alloca(sizeof(struct in6_addr));
+	ip4a = this->buf4a;
+	ip4b = this->buf4b;
+	ip4c = this->buf4c;
+	ip4d = this->buf4d;
+	ip6a = this->buf6a;
+	ip6b = this->buf6b;
+	ip6c = this->buf6c;
+	ip6d = this->buf6d;
+	ip6e = this->buf6e;
+	ip6f = this->buf6f;
+	ip6g = this->buf6g;
+
+	*ip4a = htonl(0xc0a80117);
+	*ip4b = htonl(0x7f000001);
+	*ip4c = htonl(0xffffffff);
+	*ip4d = htonl(0x00000000);
+
+	ip6a->in6_u.u6_addr8[0] = 0xfe;
+	ip6a->in6_u.u6_addr8[1] = 0x80;
+	ip6a->in6_u.u6_addr8[8] = 0x02;
+	ip6a->in6_u.u6_addr8[9] = 0x14;
+	ip6a->in6_u.u6_addr8[10] = 0x4f;
+	ip6a->in6_u.u6_addr8[11] = 0xff;
+	ip6a->in6_u.u6_addr8[12] = 0xfe;
+	ip6a->in6_u.u6_addr8[13] = 0x0b;
+	ip6a->in6_u.u6_addr8[14] = 0x76;
+	ip6a->in6_u.u6_addr8[15] = 0xc8;
+	ip6b->in6_u.u6_addr8[0] = 0x10;
+	ip6b->in6_u.u6_addr8[1] = 0x80;
+	ip6b->in6_u.u6_addr8[10] = 0x08;
+	ip6b->in6_u.u6_addr8[11] = 0x08;
+	ip6b->in6_u.u6_addr8[13] = 0x20;
+	ip6b->in6_u.u6_addr8[13] = 0x0c;
+	ip6b->in6_u.u6_addr8[14] = 0x41;
+	ip6b->in6_u.u6_addr8[15] = 0x7a;
+	ip6c->in6_u.u6_addr8[15] = 0x01;
+	ip6e->in6_u.u6_addr8[12] = 0x7f;
+	ip6e->in6_u.u6_addr8[15] = 0x01;
+	ip6f->in6_u.u6_addr8[10] = 0xff;
+	ip6f->in6_u.u6_addr8[11] = 0xff;
+	ip6f->in6_u.u6_addr8[12] = 0x7f;
+	ip6f->in6_u.u6_addr8[15] = 0x01;
+	ip6g->in6_u.u6_addr8[10] = 0xff;
+	ip6g->in6_u.u6_addr8[11] = 0xfe;
+	ip6g->in6_u.u6_addr8[12] = 0x7f;
+	ip6g->in6_u.u6_addr8[15] = 0x01;
+
+	v = 4;
+	af = (v == 4 ? AF_INET : (v == 6 ? AF_INET6 : -1));
+	printf("%s\n", inet_ntop(af, ip4a));
+	printf("%s\n", inet_ntop(af, ip4b));
+	printf("%s\n", inet_ntop(af, ip4c));
+	printf("%s\n", inet_ntop(af, ip4d));
+
+	v = 6;
+	af = (v == 4 ? AF_INET : (v == 6 ? AF_INET6 : -1));
+	printf("%s\n", inet_ntop(af, ip6a));
+	printf("%s\n", inet_ntop(af, ip6b));
+	printf("%s\n", inet_ntop(af, ip6c));
+	printf("%s\n", inet_ntop(af, ip6d));
+	printf("%s\n", inet_ntop(af, ip6e));
+	printf("%s\n", inet_ntop(af, ip6f));
+	printf("%s\n", inet_ntop(af, ip6g));
+
+	exit(0);
+}
diff --git a/test/unittest/funcs/tst.inet_ntop_runtime_af.r b/test/unittest/funcs/tst.inet_ntop_runtime_af.r
new file mode 100644
index 00000000..913eff77
--- /dev/null
+++ b/test/unittest/funcs/tst.inet_ntop_runtime_af.r
@@ -0,0 +1,12 @@
+192.168.1.23
+127.0.0.1
+255.255.255.255
+0.0.0.0
+fe80::214:4fff:fe0b:76c8
+1080::808:c:417a
+::1
+::
+127.0.0.1
+127.0.0.1
+::fffe:7f00:1
+
-- 
2.40.1




More information about the DTrace-devel mailing list