| #!/usr/bin/env bcc-lua |
| --[[ |
| Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ]] |
| -- Simple parsing example of UDP/DNS that counts frequency of QTYPEs. |
| -- It shows how to parse packet variable-length packet structures. |
| local ffi = require("ffi") |
| local bpf = require("bpf") |
| local S = require("syscall") |
| |
| -- Shared part of the program |
| local map = assert(bpf.map('array', 256)) |
| -- Kernel-space part of the program |
| local prog = bpf.socket('lo', function (skb) |
| local ip = pkt.ip -- Accept only UDP messages |
| if ip.proto ~= c.ip.proto_udp then return false end |
| local udp = ip.udp -- Only messages >12 octets (DNS header) |
| if udp.length < 12 then return false end |
| -- Unroll QNAME (up to 2 labels) |
| udp = udp.data + 12 |
| local label = udp[0] |
| if label > 0 then |
| udp = udp + label + 1 |
| label = udp[0] |
| if label > 0 then |
| udp = udp + label + 1 |
| end |
| end |
| -- Track QTYPE (low types) |
| if udp[0] == 0 then |
| local qtype = udp[2] -- Low octet from QTYPE |
| xadd(map[qtype], 1) |
| end |
| end) |
| -- User-space part of the program |
| for _ = 1, 10 do |
| for k,v in map.pairs,map,0 do |
| v = tonumber(v) |
| if v > 0 then |
| print(string.format('TYPE%d: %d', k, v)) |
| end |
| end |
| S.sleep(1) |
| end |