Reputation: 312390
I am writing some bpftrace
code in which I would like to compare an IP address (stored as a 32 bit integer) against the string representation of an address. That is, I want to do something like this:
kprobe:netif_receive_skb {
$skb = (struct sk_buff *)arg0;
$dev = $skb->dev;
$name = $dev->name;
$ipheader = ((struct iphdr *) ($skb->head + $skb->network_header));
// This pseudocode conditional is what I am trying to figure out
if ($ipheader->daddr == "8.8.8.8") {
printf("%s %s %s -> %s\n",
func, $name, ntop($ipheader->saddr), ntop($ipheader->daddr))
}
}
In the above, $ipheader
is a struct iphdr *
, and struct iphdr
looks like this:
struct iphdr {
...
__struct_group(/* no tag */, addrs, /* no attrs */,
__be32 saddr;
__be32 daddr;
);
};
So both saddr
and daddr
are unsigned 32-bit integers.
I thought perhaps I could use the pton()
function, like this:
if ($ipheader->daddr == pton("8.8.8.8")) {
But unfortunately pton()
returns an int8[4]
array instead of a single 32 bit integer, so this fails with:
traceit.bpf:8:5-41: ERROR: Type mismatch for '==': comparing 'unsigned int32' with 'unsigned int8[4]'
if ($ipheader->daddr == pton("8.8.8.8")) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I next tried to see if I could normalize both values into int8[4]
arrays, like this:
$target = pton("8.8.8.8");
$daddr = pton(ntop($ipheader->daddr));
if ($target == $daddr) {
But this fails because ntop()
doesn't actually return a string, so we get:
ERROR: Expected string literal, got inet
traceit.bpf:9:10-38: ERROR: pton() expects an string argument of an IPv4/IPv6 address, got
$daddr = pton(ntop($ipheader->daddr));
I realize I could just specify the target as an integer myself:
if ($ipheader->daddr == 0x08080808) {
But while that's easy to interpret for a contrived address like 8.8.8.8, it's opaque when the hex form of the address is something like 0xacd9004e
.
Is it possible to compare a 32-bit integer representation of an address with the string representation of an address using bpftrace
(and if so, what's the canonical way of doing so)?
Upvotes: 1
Views: 508
Reputation: 1536
This has been fixed in version 0.17 and 0.19:
Both of these should allow comparing IP addresses by casting them to a common type.
Upvotes: 1
Reputation: 1
if the $ipheader->daddr is 192.168.2.44, just convert this four number to hex chars, which are c0 a8 02 2c
. reversal chars are 2c 02 a8 c0
. so you can just write:
if ($ipheader->daddr == 0x2c02a8c0) {
...
}
Upvotes: -1