Search code examples
bcc-bpf

Colon functions and $ variables in c++?


I'm still a bit new to c++ and I'm having trouble understanding what this piece of code is doing:

    #include <net/sock.h>

BEGIN
{
    printf("%-8s %-6s %-16s %-2s %-16s %-5s\n", "TIME", "PID", "COMM",
        "IP", "RADDR", "RPORT");
}

kprobe:ip4_datagram_connect,
kprobe:ip6_datagram_connect
{
    $sk = (struct sock *)arg0;
    $sa = (struct sockaddr *)arg1;
    if (($sa->sa_family == AF_INET || $sa->sa_family == AF_INET6) &&
        $sk->sk_protocol == IPPROTO_UDP) {
        time("%H:%M:%S ");
        if ($sa->sa_family == AF_INET) {
            $s = (struct sockaddr_in *)arg1;
            $port = ($s->sin_port >> 8) |
                (($s->sin_port << 8) & 0xff00);
            printf("%-6d %-16s 4  %-16s %-5d\n", pid, comm,
                ntop(AF_INET, $s->sin_addr.s_addr), $port);
        } else {
            $s6 = (struct sockaddr_in6 *)arg1;
            $port = ($s6->sin6_port >> 8) |
                (($s6->sin6_port << 8) & 0xff00);
            printf("%-6d %-16s 6  %-16s %-5d\n", pid, comm,
                ntop(AF_INET6, $s6->sin6_addr.in6_u.u6_addr8),
                $port);
        }
    }
}

I think the "BEGIN" portion of this is defining a macro, but I'm not fully sure. What I'm really confused about is the

kprobe:ip4_datagram_connect,
kprobe:ip6_datagram_connect
{

What is this doing? It seems like a function declaration, but what does the single colon mean in this context? Is this some sort initialization list but for functions? Is this setting both ip4 and ip6 to that function?

Also, do the dollar sign variable names have any sort of significance? or are they just a valid way of declaring variables?

This is the code for udpconnect.bt from bcc tools. I'm try to convert it to python.


Solution

  • As mentioned in the comments, this is a script for bpftrace. You probably want to look at the reference guide for this tool.

    The BEGIN block is run at the start of your program (just like with awk scripts, if you are familiar with it). In this case it is used to print the header row for an array to the console output.

    Then the block:

    kprobe:ip4_datagram_connect,
    kprobe:ip6_datagram_connect
    {
    

    ... defines instructions that will be translated to an eBPF program (with an intermediary step as LLVM intermediate representation), and attached to one or several hooks in the Linux kernel. In the current case, the kprobe:... define the hooks: The program will run as a kprobe function for the functions ip4_datagram_connect and its IPv6 counterpart in the kernel. In other words, it will run each time the kernel enters those functions.

    On a quick look, I think the program is supposed to print, each time a UDP flow starts, the time, PID and name of the process opening the socket, the IP address, remote address and remote port. The first if checks that the packet is (IPv4 or IPv6) and UDP, the if/else below splits the two cases IPv4/IPv6.