--- /dev/null
+#!/usr/bin/env lua
+local socket = require("socket")
+local udpl = assert(socket.udp())
+
+
+function getpid()
+ local line
+ statfp = io.open("/proc/self/stat", "r")
+ if statfp == nil then
+ return "--unknown--"
+ end
+ line = statfp:read()
+ return line:match("%d+")
+end
+
+
+function args_parse()
+ local opt
+ for _, opt in ipairs(arg) do
+ if opt:find("port=", 1, true) then
+ listenport = tonumber(opt:match("%d+$", 5))
+ elseif opt:find("pidfile=", 1, true) then
+ pidfile = opt:match("[^%c]+", 9)
+ elseif opt:find("outfile=", 1, true) then
+ outfile = opt:match("[^%c]+", 9)
+ else
+ io.stderr:write("FATAL: unsupported option: " .. opt .. "\n")
+ os.exit(1)
+ end
+ end
+end
+
+
+function args_validate()
+ local args_valid=true
+
+ if listenport == nil or listenport < 1 or listenport > 65535 then
+ args_valid=false
+ io.stderr:write("FATAL: please set a valid 'listenport=...' parameter.\n")
+ end
+
+ if outfile == nil then
+ args_valid=false
+ io.stderr:write("FATAL: please set a valid 'outfile=...' parameter (use `-` for stdout).\n")
+ elseif outfile == "-" then
+ outp = io.stdout
+ else
+ outp, err = io.open(outfile, "w+")
+ if err then
+ args_valid=false
+ io.stderr:write("FATAL: failed to open output stream at '", outfile, "'\n")
+ end
+ end
+
+ if pidfile ~= nil then
+ pidf, err = io.open(pidfile, "w")
+ if err == nil then
+ pidf:write(mypid .. "\n")
+ pidf:close()
+ else
+ args_valid=false
+ io.stderr:write("FATAL: failed to record PID info in '", pidfile, "'\n")
+ end
+ end
+
+ return args_valid
+end
+
+
+function isoutctime()
+ return os.date("!%Y-%m-%dT%TZ")
+end
+
+
+-- init --
+
+mypid = getpid()
+args_parse()
+
+if not args_validate() then
+ os.exit(1)
+end
+
+udpl:setsockname("*", listenport)
+udpl:settimeout(0.1)
+outp:setvbuf("line")
+io.stderr:write("netconsole-rx.lua / pid " .. mypid .. " / input UDP port " .. listenport .. " / output '" .. outfile .. "'\n")
+
+-- processing loop --
+
+while(true)
+do
+ data, peer, peerport = udpl:receivefrom()
+ if data and string.len(data) > 0 then
+ data, _ = string.gsub(data, "%c", "")
+ if string.byte(data) == 91 then
+ -- simple netconsole message, no ksmg-like metadata
+ outp:write(string.format("%s %s:%s \t%s\n", isoutctime(), peer, peerport, data))
+ else
+ so = string.find(data, ";")
+ if so ~= nil then
+ mdata = string.sub(data, 1, (so - 1))
+ data = string.sub(data, (so + 1))
+ -- TODO: parse mdata, print it sensibly
+ -- <level>,<sequnum>,<timestamp>,<contflag>;<message text>
+ -- outp:write(string.format("%s:%s \t%s\n", peer, peerport, mdata))
+ outp:write(string.format("%s %s:%s \t%s\n", isoutctime(), peer, peerport, data))
+ else
+ io.stderr:write("WARN: garbage input from peer " .. peer .. ":" .. peerport .. " discarded\n")
+ end
+ end
+ end
+end