1#!/usr/bin/env bcc-lua 2--[[ 3Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> 4 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16]] 17-- Simple parsing example of UDP/DNS that counts frequency of QTYPEs. 18-- It shows how to parse packet variable-length packet structures. 19local ffi = require("ffi") 20local bpf = require("bpf") 21local S = require("syscall") 22 23-- Shared part of the program 24local map = assert(bpf.map('array', 256)) 25-- Kernel-space part of the program 26local prog = bpf.socket('lo', function (skb) 27 local ip = pkt.ip -- Accept only UDP messages 28 if ip.proto ~= c.ip.proto_udp then return false end 29 local udp = ip.udp -- Only messages >12 octets (DNS header) 30 if udp.length < 12 then return false end 31 -- Unroll QNAME (up to 2 labels) 32 udp = udp.data + 12 33 local label = udp[0] 34 if label > 0 then 35 udp = udp + label + 1 36 label = udp[0] 37 if label > 0 then 38 udp = udp + label + 1 39 end 40 end 41 -- Track QTYPE (low types) 42 if udp[0] == 0 then 43 local qtype = udp[2] -- Low octet from QTYPE 44 xadd(map[qtype], 1) 45 end 46end) 47-- User-space part of the program 48for _ = 1, 10 do 49 for k,v in map.pairs,map,0 do 50 v = tonumber(v) 51 if v > 0 then 52 print(string.format('TYPE%d: %d', k, v)) 53 end 54 end 55 S.sleep(1) 56end