netlinkファンのためのnlmon

Linux kernel には netlink という仕組みがある。`ip` コマンドはこれを使っているし、`libnl` というライブラリもある。netlink は `struct nlmsghdr` という構造体を使っていて、通信の形で操作する。

実はこの通信を Wireshark で見る方法がある。`nlmon` という kernel module を使う。Linux kernel の `drivers/net/nlmon.c` で同梱されていて、Ubuntu であれば `linux-kernel-image-extra` に入っている。

```bash
sudo apt-get install linux-image-extra-`uname -r`
```

`iw` コマンドといった genl (generic netlink) を使った複雑な nl80211 を観察するときにも、大変便利。

使い方
-----

`nlmon` な netdev を作って、Wireshark でモニターすればよい。

```
modprobe nlmon
ip link add nlmon0 type nlmon
ip link set nlmon0 up
tshark -i nlmon0 -V
```

例えばこんな感じになる。

```
root@minimal-xenial:~# tshark -i nlmon0 -V
Running as user "root" and group "root". This could be dangerous.
tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:44: dofile has been disabled due to running Wireshark as superuser. See https://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user.
Capturing on 'nlmon0'
Frame 1: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on interface 0
    Interface id: 0 (nlmon0)
    Encapsulation type: Linux Netlink (159)
    Arrival Time: Mar  2, 2017 01:28:39.493853332 UTC
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1488418119.493853332 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 36 bytes (288 bits)
    Capture Length: 36 bytes (288 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: netlink:netlink-route]
Linux netlink (cooked header)
    Link-layer address type: Netlink (824)
    Family: Route (0x0000)
Linux rtnetlink (route netlink) message
    Header
        Length: 20
        Type: Unknown (0x0012)
        Flags: 259
            .... .... .... ...1 = Request: 1
            .... .... .... ..1. = Multipart message: 1
            .... .... .... .0.. = Ack: 0
            .... .... .... 0... = Echo: 0
            .... ...1 .... .... = Specify tree root: 1
            .... ..0. .... .... = Return all matching: 0
            .... .0.. .... .... = Atomic: 0
        Sequence: 1488418119
        Port ID: 0
    Message type: Get network interface (18)
    Interface family: 0
    Device type: NET/ROM pseudo (0)
[Malformed Packet: rtnetlink]
    [Expert Info (Error/Malformed): Malformed Packet (Exception occurred)]
        [Malformed Packet (Exception occurred)]
        [Severity level: Error]
        [Group: Malformed]

Frame 2: 3560 bytes on wire (28480 bits), 3560 bytes captured (28480 bits) on interface 0
    Interface id: 0 (nlmon0)
    Encapsulation type: Linux Netlink (159)
    Arrival Time: Mar  2, 2017 01:28:39.493940573 UTC
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1488418119.493940573 seconds
    [Time delta from previous captured frame: 0.000087241 seconds]
    [Time delta from previous displayed frame: 0.000087241 seconds]
    [Time since reference or first frame: 0.000087241 seconds]
    Frame Number: 2
    Frame Length: 3560 bytes (28480 bits)
    Capture Length: 3560 bytes (28480 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: netlink:netlink-route:netlink-route:netlink-route]
Linux netlink (cooked header)
    Link-layer address type: Netlink (824)
    Family: Route (0x0000)
Linux rtnetlink (route netlink) message
    Header
        Length: 1180
        Type: Unknown (0x0010)
        Flags: 512
            .... .... .... ...0 = Request: 0
            .... .... .... ..0. = Multipart message: 0
            .... .... .... .0.. = Ack: 0
            .... .... .... 0... = Echo: 0
            .... ...0 .... .... = Replace: 0
            .... ..1. .... .... = Excl: 1
            .... .0.. .... .... = Create: 0
            .... 0... .... .... = Append: 0
        Sequence: 1488418119
        Port ID: 4085872433
    Message type: Create network interface (16)
    Interface family: 0
    Device type: Unknown (772)
    Interface index: 1
    Device flags: UP, LOOPBACK, RUNNING, LOWER_UP (0x00010049)
        .... .... .... .... .... .... .... ...1 = Interface: Up
        .... .... .... .... .... .... .... ..0. = Broadcast: Invalid
    Device change flags: 0
    Attribute: Device name: lo
        Len: 7
        Attribute type: Device name (3)
        Device name: lo
    Attribute: TxQueue length
        Len: 8
        Attribute type: TxQueue length (13)
    Attribute: Operstate
        Len: 5
        Attribute type: Operstate (16)
    Attribute: Link mode
        Len: 5
        Attribute type: Link mode (17)
    Attribute: MTU: 65536
        Len: 8
        Attribute type: MTU (4)
        MTU of device: 65536
    Attribute: Group
        Len: 8
        Attribute type: Group (27)
    Attribute: Promiscuity
        Len: 8
        Attribute type: Promiscuity (30)
    Attribute: Number of Tx queues
        Len: 8
        Attribute type: Number of Tx queues (31)
    Attribute: Number of Rx queues
        Len: 8
        Attribute type: Number of Rx queues (32)
    Attribute: Carrier
        Len: 5
        Attribute type: Carrier (33)
    Attribute: Queueing discipline
        Len: 12
        Attribute type: Queueing discipline (6)
    Attribute
        Len: 8
        Attribute type: Unknown (35)
    Attribute
        Len: 5
        Attribute type: Unknown (39)
    Attribute: Map
        Len: 36
        Attribute type: Map (14)
    Attribute: Address
        Len: 10
        Attribute type: Address (1)
    Attribute: Broadcast
        Len: 10
        Attribute type: Broadcast (2)
    Attribute: Interface Statistics
        Len: 96
        Attribute type: Interface Statistics (7)
    Attribute: Stats
        Len: 188
        Attribute type: Stats (23)
    Attribute: AF spec
        Len: 696
        Attribute type: AF spec (26)
```

request が壊れてるらしいんだが、誰が出してるんだろう…？