Skip to content

Commit

Permalink
Support two representations for embedded IPv4 addresses
Browse files Browse the repository at this point in the history
DTrace's inet_ntoa6() represents mapped and embedded IPv4 addresses
using the regular IPv4 representation, whereas inet_ntop() uses a
strict IPv6 representation (:: or ::ffff: prefix followed by a regular
IPv4 address).

The implementation uses a 2nd argument to inet_ntoa6() that must be
an integer constant that indicates basic IPv4 representation (0), or
strict IPv4-in-IPv6 representation (non-0).

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Sep 23, 2023
1 parent 26e2d63 commit 6e4d2b0
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 11 deletions.
31 changes: 27 additions & 4 deletions bpf/inet_ntoa6.S
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ write_hex16:

/*
* void inet_ntoa6(const dt_dctx_t *dctx, const uint8_t *src, char *dst,
* uint32 tbloff)
* uint32 tbloff, int strict)
*/
.align 4
.global dt_inet_ntoa6
Expand All @@ -121,6 +121,7 @@ dt_inet_ntoa6:
add %r8, OUTPUT_LEN /* %r8 = converted copy */
mov %r6, %r1 /* %r6 = dctx */
stxw [%fp + -4], %r4 /* store tbloff */
stxw [%fp + -8], %r5 /* store strict */

mov %r3, %r2
mov %r2, INPUT_LEN
Expand Down Expand Up @@ -198,12 +199,12 @@ dt_inet_ntoa6:
and %r0, 0xf8
jne %r0, 0, .Lnotipv4
ldxh %r0, [%r8 + 10]
jeq %r0, 0xffff, .Lipv4
jeq %r0, 0xffff, .Lipv4_2
jne %r0, 0, .Lnotipv4
ldxh %r0, [%r8 + 12]
jne %r0, 0, .Lipv4
jne %r0, 0, .Lipv4_1
ldxh %r0, [%r8 + 14]
jgt %r0, 1, .Lipv4
jgt %r0, 1, .Lipv4_1
.Lnotipv4:

/*
Expand Down Expand Up @@ -335,6 +336,28 @@ dt_inet_ntoa6:
mov %r0, 0
exit

.Lipv4_1:
/* Output IPv4 address prefixed by :: (if strict is set). */
ldxw %r0, [%fp + -8] /* restore strict */
jeq %r0, 0, .Lipv4
stb [%r9 + 0], ':'
stb [%r9 + 1], ':'
add %r9, 2
ja .Lipv4

.Lipv4_2:
/* Output IPv4 address prefixed by ::ffff: (if strict is set). */
ldxw %r0, [%fp + -8] /* restore strict */
jeq %r0, 0, .Lipv4
stb [%r9 + 0], ':'
stb [%r9 + 1], ':'
stb [%r9 + 2], 'f'
stb [%r9 + 3], 'f'
stb [%r9 + 4], 'f'
stb [%r9 + 5], 'f'
stb [%r9 + 6], ':'
add %r9, 7

.Lipv4:
/* Output the last two words as an IPv4 address and return. */
mov %r1, %r6
Expand Down
15 changes: 11 additions & 4 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -5941,6 +5941,8 @@ static void
dt_cg_subr_inet_ntoa6(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
dt_node_t *addr = dnp->dn_args;
dt_node_t *strict = addr->dn_list;
ssize_t tbloff;
/*
* This table encodes the start and length of the longest run of 0 bits
Expand Down Expand Up @@ -5986,14 +5988,19 @@ dt_cg_subr_inet_ntoa6(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
0x53, 0x52, 0x70, 0x70, 0x62, 0x70, 0x70, 0x70,
};

if (strict != NULL && strict->dn_kind != DT_NODE_INT)
dnerror(strict, D_PROTO_ARG, "inet_ntoa6( ) argument #2 "
"must be an integer constant\n");

tbloff = dt_rodata_insert(dtp->dt_rodata, tbl, 256);
if (tbloff == -1L)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
if (tbloff > DIF_STROFF_MAX)
longjmp(yypcb->pcb_jmpbuf, EDT_STR2BIG);

dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_inet_ntoa6",
DT_ISIMM, tbloff, DT_IGNOR, 0);
DT_ISIMM, tbloff,
DT_ISIMM, strict && strict->dn_value ? 1 : 0);
}

static void
Expand Down Expand Up @@ -6027,8 +6034,9 @@ dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
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);
xnp = dt_node_op2(DT_TOK_LPAR, xnp, addr); /* (type)addr */
xnp->dn_list = dt_node_int(1);

lnp->dn_args = xnp; /* inet_ntoa6((type)addr) */

/* Create a node for the function call: inet_ntoa(addr) */
Expand All @@ -6043,7 +6051,6 @@ dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
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) */

Expand Down
2 changes: 1 addition & 1 deletion libdtrace/dt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ static const dt_ident_t _dtrace_globals[] = {
{ "inet_ntoa", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_INET_NTOA, DT_ATTR_STABCMN,
DT_VERS_1_5, &dt_idops_func, "string(ipaddr_t *)" },
{ "inet_ntoa6", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_INET_NTOA6, DT_ATTR_STABCMN,
DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *)" },
DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *, [int])" },
{ "inet_ntop", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_INET_NTOP, DT_ATTR_STABCMN,
DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
p[3] = htonl(0x7f000001);
trace(inet_ntoa6(p));

exit(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
n = 0;
p[3] = htonl(0x7f000001);
trace(inet_ntoa6((struct in6_addr *)p, n));

exit(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
p[3] = htonl(0x7f000001);
trace(inet_ntoa6((struct in6_addr *)p, ""));

exit(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

BEGIN
{
inet_ntoa6();

exit(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

BEGIN
{
inet_ntoa6(0, 0, 0);

exit(0);
}
19 changes: 19 additions & 0 deletions test/unittest/funcs/inet_ntoa6/tst.inet_ntoa6.strict-0.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
p[3] = htonl(0x7f000001);
trace(inet_ntoa6((struct in6_addr *)p, 0));

exit(0);
}
1 change: 1 addition & 0 deletions test/unittest/funcs/inet_ntoa6/tst.inet_ntoa6.strict-0.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
127.0.0.1
19 changes: 19 additions & 0 deletions test/unittest/funcs/inet_ntoa6/tst.inet_ntoa6.strict-1.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
p[3] = htonl(0x7f000001);
trace(inet_ntoa6((struct in6_addr *)p, 1));

exit(0);
}
1 change: 1 addition & 0 deletions test/unittest/funcs/inet_ntoa6/tst.inet_ntoa6.strict-1.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::127.0.0.1
19 changes: 19 additions & 0 deletions test/unittest/funcs/inet_ntoa6/tst.inet_ntoa6.strict-not-0.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 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.
*/

#pragma D option quiet

int *p;

BEGIN
{
p = alloca(sizeof(int) * 4);
p[3] = htonl(0x7f000001);
trace(inet_ntoa6((struct in6_addr *)p, 42));

exit(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::127.0.0.1
4 changes: 2 additions & 2 deletions test/unittest/funcs/tst.inet_ntop_runtime_af.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fe80::214:4fff:fe0b:76c8
1080::808:c:417a
::1
::
127.0.0.1
127.0.0.1
::127.0.0.1
::ffff:127.0.0.1
::fffe:7f00:1

0 comments on commit 6e4d2b0

Please sign in to comment.