日記

日本語の勉強のためのブログ

eBPFでiphdr構造体のsaddr/daddrをIPアドレスの表記に直して出力する方法

1. bpf_printkのフォーマット指定子%pI4を使う

2つ目の方法とは違い、ビッグエンディアンに直す必要はない。
フォーマット指定子がpから始まっていることからわかるように、引数にはアドレスを渡す必要があるので注意。
参考:https://qiita.com/todok-r/items/d754fb29930431c9efa0

struct iphdr *iph = (略);
bpf_printk("source addr: %pI4", &iph->saddr);

出力↓

source addr: 192.168.0.1

2. bpf_ntohlでビッグエンディアンに直し、自力でIPアドレスの形式に整形する

bpf_ntohsという関数もあるが、こちらは16bitの値を返す。IPアドレスは32bitなので、bpf_ntohlを使う必要がある。
※なお、64bitの値を返すbpf_be64_to_cpuという関数も定義されているが、詳細は不明。

整形についてはinet_ntoa関数が使えると聞いたが、うまく実行できなかったため自力で関数ip_int2strを作った。

struct iphdr *iph = (略);
char str_saddr[16] = "XXX.XXX.XXX.XXX";
ip_int2str(bpf_ntohl(iph->saddr), str_saddr);
bpf_printk("source addr: %s", str_saddr);
void ip_int2str(unsigned int ip, char *ip_str) {
  // IPv4アドレスは最長15文字のはずなんでNULL終端含めても16文字で足りる
  BPF_SNPRINTF(ip_str, 16, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
               (ip >> 8) & 0xFF, ip & 0xFF);
}

出力(方法1と同じ)↓

source addr: 192.168.0.1