|
| 1 | +# Parsing packets |
| 2 | + |
| 3 | +In the previous chapter, our XDP application ran until Ctrl-C was hit and |
| 4 | +permitted all the traffic. Each time a packet was received, the BPF program |
| 5 | +created a logged the string "received a packet" for each packet received. In |
| 6 | +this chapter we're |
| 7 | +going to show how to parse packets. |
| 8 | + |
| 9 | +While we could go all out and extract data all the way up to L7, we'll constrain |
| 10 | +our example to L3, and to make things easier, IPv4 only. |
| 11 | + |
| 12 | +!!! example "Source code" |
| 13 | + |
| 14 | + Full code for the example in this chapter is available |
| 15 | + [here](https://github.com/aya-rs/book/tree/main/examples/xdp-log) |
| 16 | + |
| 17 | +## Using network types |
| 18 | + |
| 19 | +We're going to log the source ip address of incoming packets. So we'll need to: |
| 20 | + |
| 21 | +* Read the ethernet header to determine if we're dealing with an IPv4 packet, |
| 22 | + else terminate parsing. |
| 23 | +* Read the source IP Address from the IPv4 header. |
| 24 | + |
| 25 | +We could read the specifications of those protocols and parse manually, but |
| 26 | +instead we're going to use the [network-types](https://crates.io/crates/network-types) |
| 27 | +crate which provides convenient type definitions for many of the common Internet |
| 28 | +protocols. |
| 29 | + |
| 30 | +Let's add it to our eBPF crate by adding a dependency on `network-types` in our |
| 31 | +`xdp-log-ebpf/Cargo.toml`: |
| 32 | + |
| 33 | +=== "xdp-log-ebpf/Cargo.toml" |
| 34 | + |
| 35 | + ```toml linenums="1" |
| 36 | + --8<-- "examples/xdp-log/xdp-log-ebpf/Cargo.toml" |
| 37 | + ``` |
| 38 | + |
| 39 | +## Getting packet data from the context and into the map |
| 40 | + |
| 41 | +`XdpContext` contains two fields that we're going to use: data and data_end, |
| 42 | +which are respectively a pointer to the beginning and to the end of the packet. |
| 43 | + |
| 44 | +In order to access the data in the packet and to ensure that we do so in a way |
| 45 | +that keeps the eBPF verifier happy, we're going to introduce an helper function |
| 46 | +called `ptr_at`. The function ensure that before we access any data, we insert |
| 47 | +the bound checks which are required by the verifier. |
| 48 | + |
| 49 | +Finally to access individual fields from the ethernet and IPv4 headers, we're |
| 50 | +going to use the memoffset crate, let's add a dependency for it in |
| 51 | +`xdp-log-ebpf/Cargo.toml`. |
| 52 | + |
| 53 | +To do this efficiently we'll add a dependency on `memoffset = "0.8"` in our |
| 54 | +`myapp-ebpf/Cargo.toml` |
| 55 | + |
| 56 | +!!! tip "Reading fields using `offset_of!`" |
| 57 | + |
| 58 | + As there is limited stack space, it's more memory efficient to use the |
| 59 | + `offset_of!` macro to read a single field from a struct, rather than reading |
| 60 | + the whole struct and accessing the field by name. |
| 61 | + |
| 62 | +The resulting code looks like this: |
| 63 | + |
| 64 | +```rust linenums="1" title="xdp-log-ebpf/src/main.rs" |
| 65 | +--8<-- "examples/xdp-log/xdp-log-ebpf/src/main.rs" |
| 66 | +``` |
| 67 | + |
| 68 | +1. Create our map. |
| 69 | +2. Here's `ptr_at`, which gives ensures packet access is bounds checked. |
| 70 | +3. Using `ptr_at` to read our ethernet header. |
| 71 | +4. Logging the IP address and port. |
| 72 | + |
| 73 | +Don't forget to rebuild your eBPF program! |
| 74 | + |
| 75 | +## User-space component |
| 76 | + |
| 77 | +Our user-space code doesn't really differ from the previous chapter, but for the |
| 78 | +reference, here's the code: |
| 79 | + |
| 80 | +```rust linenums="1" title="xdp-log/src/main.rs" |
| 81 | +--8<-- "examples/xdp-log/xdp-log/src/main.rs" |
| 82 | +``` |
| 83 | + |
| 84 | +## Running the program |
| 85 | + |
| 86 | +As before, the interface can be overwritten by providing the interface name as a |
| 87 | +parameter, for example, `RUST_LOG=info cargo xtask run -- --iface wlp2s0`. |
| 88 | + |
| 89 | +```console |
| 90 | +$ RUST_LOG=info cargo xtask run |
| 91 | +[2022-12-22T11:32:21Z INFO xdp_log] SRC IP: 172.52.22.104, SRC PORT: 443 |
| 92 | +[2022-12-22T11:32:21Z INFO xdp_log] SRC IP: 172.52.22.104, SRC PORT: 443 |
| 93 | +[2022-12-22T11:32:21Z INFO xdp_log] SRC IP: 172.52.22.104, SRC PORT: 443 |
| 94 | +[2022-12-22T11:32:21Z INFO xdp_log] SRC IP: 172.52.22.104, SRC PORT: 443 |
| 95 | +[2022-12-22T11:32:21Z INFO xdp_log] SRC IP: 234.130.159.162, SRC PORT: 443 |
| 96 | +``` |
0 commit comments