Lua FFI 簡單封裝 libpcap

1. 由來

最近在 LuaJit 的 FFI 封裝已有功能,期間用到libpcap,這裏共享一下我的簡單封裝

2. 代碼

2.1 type.lua

這是一個類型申明的封裝

module(...,package.seeall)

local ffi = require("ffi")

-- PCAP file format: http://wiki.wireshark.org/Development/LibpcapFileFormat/
ffi.cdef[[
struct pcap_file {
    /* file header */
    uint32_t magic_number;   /* magic number */
    uint16_t version_major;  /* major version number */
    uint16_t version_minor;  /* minor version number */
    int32_t  thiszone;       /* GMT to local correction */
    uint32_t sigfigs;        /* accuracy of timestamps */
    uint32_t snaplen;        /* max length of captured packets, in octets */
    uint32_t network;        /* data link type */
};

/* This is the header of a packet on disk.  */
struct pcap_record {
    /* record header */
    uint32_t ts_sec;         /* timestamp seconds */
    uint32_t ts_usec;        /* timestamp microseconds */
    uint32_t incl_len;       /* number of octets of packet saved in file */
    uint32_t orig_len;       /* actual length of packet */
};

/* This is the header of a packet as passed to pcap_offline_filter.  */
struct pcap_pkthdr {
    /* record header */
    long ts_sec;             /* timestamp seconds */
    long ts_usec;            /* timestamp microseconds */
    uint32_t incl_len;       /* number of octets of packet saved in file */
    uint32_t orig_len;       /* actual length of packet */
};
]]

-- BPF program format.  Note: the bit module represents uint32_t values
-- with the high-bit set as negative int32_t values, so we do the same
-- for all of our 32-bit values including the "k" field in BPF
-- instructions.
ffi.cdef[[
struct bpf_insn { uint16_t code; uint8_t jt, jf; int32_t k; };
struct bpf_program { uint32_t bf_len; struct bpf_insn *bf_insns; };
]]
local bpf_program_mt = {
  __len = function (program) return program.bf_len end,
  __index = function (program, idx)
     assert(idx >= 0 and idx < #program)
     return program.bf_insns[idx]
  end
}

bpf_insn = ffi.typeof("struct bpf_insn")
bpf_program = ffi.metatype("struct bpf_program", bpf_program_mt)
pcap_record = ffi.typeof("struct pcap_record")
pcap_pkthdr = ffi.typeof("struct pcap_pkthdr")

function selftest ()
   print("selftest: ffi_types")
   print("OK")
end

2.2 pcap.lua

這個爲主要函數的封裝,暫時我只封裝了我需要的,有些沒有,這裏提供一個例子。

module(..., package.seeall)

local ffi = require("ffi")
local types = require("types")
local pcap


ffi.cdef[[
    typedef struct pcap pcap_t;
    typedef unsigned char u_char;
    pcap_t  *pcap_open_offline(const char *, char *);
    int     pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
    int     pcap_datalink(pcap_t *);
]]

function open_offline(pcap_name)
    if not pcap then pcap = ffi.load("pcap") end
    local err = ffi.new("char[128]", {})
    local p = pcap.pcap_open_offline(pcap_name, err)
    if p == nil then
        print(ffi.string(err))
        return nil
    else
        print(" open file " .. pcap_name .. " sucessfully")
        return p
    end
end

function new_pkthdr()
    return ffi.new 'struct pcap_pkthdr *[1]'
end

function new_packet()
    return ffi.new 'const u_char *[1]'
end

function next_ex(p, pkt_hdr, packet)
    if not pcap then pcap = ffi.load("pcap") end
    return pcap.pcap_next_ex(p, pkt_hdr, packet)
end

function datalink(p)
    return pcap.pcap_datalink(p)
end

3. 總結

封裝不是太完善,但基本功能都還是有,這裏只提供思路,授人以魚,不如授人以漁(說實話就是懶)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章