[Dnsmasq-discuss] Scripting with lua
Hi All, Feeling inquisitive about the options --dhcp-luascript, script-arp, and script-on-renewal, I've been exploring what possibilities this brings. Knowing absolutely nothing about lua, I have pulled together a simple logging script that works -- but I've run up against a problem in accessing the stored variables. Therefore, this is probably more of a query about lua than it is about dnsmasq. The man page states that the environment inherits a number of variables (example: DNSMASQ_TAGS) which I am trying to retrieve -- but my current approach is returning nil (eg. tags = os.getenv("DNSMASQ_TAGS")) Questions: * How can I retrieve the contents of the DNSMASQ_ variables (if set) * Does the dnsmasq log the return status if there is an error? * and (tentatively / hypothetically), could the actions taken by dnsmasq in granting/renewing a lease be modified following the results of running the lua script? For example, if the lua script modified the DNSMASQ_TAGS variable. Note: This is NOT a feature request -- purely thinking about what might be possible... I've uploaded my current test script to: https://github.com/whitepj/dnsmasq-lua if this makes anything clearer. Many thanks, Phil ___ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
Re: [Dnsmasq-discuss] Scripting with lua
On Tue, May 14, 2024 at 10:09:12PM +0100, White, Phil via Dnsmasq-discuss wrote: > Hi All, > > Feeling inquisitive about the options --dhcp-luascript, script-arp, > and script-on-renewal, I've been exploring what possibilities this > brings. Knowing absolutely nothing about lua, I have pulled together a > simple logging script that works -- but I've run up against a problem > in accessing the stored variables. Therefore, this is probably more of > a query about lua than it is about dnsmasq. > > The man page states that the environment inherits a number of > variables (example: DNSMASQ_TAGS) which I am trying to retrieve -- but > my current approach is returning nil (eg. tags = > os.getenv("DNSMASQ_TAGS")) > > Questions: > * How can I retrieve the contents of the DNSMASQ_ variables (if set) > * Does the dnsmasq log the return status if there is an error? > * and (tentatively / hypothetically), could the actions taken by > dnsmasq in granting/renewing a lease be modified following the results > of running the lua script? For example, if the lua script modified the > DNSMASQ_TAGS variable. > > Note: This is NOT a feature request -- purely thinking about what > might be possible... > > I've uploaded my current test script to: > https://github.com/whitepj/dnsmasq-lua if this makes anything clearer. I've followed that URL and had to click deeper. Now sharing the output of $ curl --silent https://raw.githubusercontent.com/whitepj/dnsmasq-lua/main/dhcp.lua --[[ LUA script for dnsmasq DHCP leases. Modified from original source at: http://lists.thekelleys.org/pipermail/dnsmasq-discuss/2012q1/005425.html This script is principally a boilerplate example, to show what is possible... Tested using dnsmasq v2.90 Run when: - Startup (existing leases are invoked with 'old' event - SIGHUP ? - dhcp lease created, renewed, changed, or destroyed. - tftp file transfer completes (not tested) WHY? Gives us another way to monitor dhcp leases. ENVIRONMENT VARIABLES = - DNSMASQ_DOMAIN - DNSMASQ_SUPPLIED_HOSTNAME - DNSMASQ_USER_CLASS0 ... _CLASSn - DNSMASQ_LEASE_LENGTH / DNSMASQ_LEASE_EXPIRES - DNSMASQ_TIME_REMAINING - DNSMASQ_DATA_MISSING - DNSMASQ_INTERFACE - DNSMASQ_RELAY_ADDRESS - DNSMASQ_TAGS - DNSMASQ_REQUESTED_OPTIONS - DNSMASQ_MUD_URL - IPv4 Only - DNSMASQ_CLIENT_ID - DNSMASQ_CIRCUIT_ID - DNSMASQ_SUBSCRIBER_ID - DNSMASQ_REMOTE_ID - DNSMASQ_VENDOR_CLASS - IPv6 Only - DNSMASQ_VENDOR_CLASS_ID - DNSMASQ_VENDOR_CLASS0 ... _CLASSn - DNSMASQ_SERVER_DUID - DNSMASQ_IAID - DNSMASQ_MAC FUNCTIONS & ARGUMENTS = - init - shutdown - lease - add - old - del - arp - arp-add - arp-del - relay-snoop ??? or is this relay(arg), where arg='snoop'? - tftp ??? not yet tested dnsmasq CONFIGURATION = dhcp-scriptuser = WHATEVER dhcp-luascript = /usr/local/etc/dnsmasq.d/THIS_SCRIPT.lua script-on-renewal script-arp --]] DBI = require "DBI" -- The ONLY external dependency. On gentoo, use emerge dev-lua/luadbi (or use luarocks) -- Variable Declarations counter = 0 file = nil -- writing to a normal file dbh = nil -- our database connection dbinsert = nil -- preprepared call to write to a database local function myenv() -- For testing. How do we retrieve the contents of the environment variables? a = (os.getenv("DNSMASQ_TIME_REMAINING") or "blank")-- Help. Always blank. return a end local function myerrorhandler(err) print("ERROR: " .. err) end function init(a) a = (a or "--\n") -- MOST of this function will need to be deleted or commented out, depending on what functionality is required. local ok, err, code = os.rename("/tmp/ilua.db","/tmp/ilua.db") if not ok then if code == 13 then print("DB File exists, but we can't open it! Please fix (or delete).") os.exit() else print("No DB file found. Creating...") os.execute('sqlite3 --line /tmp/ilua.db "CREATE TABLE table1(\"a\");"') end end print(a .. "Starting dnsmasq lua script...\n==\n") file = assert(io.open("/tmp/test.log", "a+")) -- dbh = assert(DBI.Connect('PostgreSQL', 'db', 'user', 'password' )) -- Alternative dbh = assert(DBI.Connect('SQLite3','/tmp/ilua.db')) dbh:autocommit(true) -- dbinsert = assert(dbh:prepare('INSERT INTO table1(a) values ($1)')) -- PostgreSQL end local function output(mystring) print(mystring) -- In production
Re: [Dnsmasq-discuss] Scripting with lua
On 14/05/2024 23:09, White, Phil via Dnsmasq-discuss wrote: * and (tentatively / hypothetically), could the actions taken by dnsmasq in granting/renewing a lease be modified following the results of running the lua script? For example, if the lua script modified the DNSMASQ_TAGS variable. The lua script (or non-lua script) is run after dnsmasq replies, so the answer is no. ___ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
Re: [Dnsmasq-discuss] Scripting with lua
On Wed, 15 May 2024 at 06:32, Geert Stappers wrote: > I've followed that URL and had to click deeper. > Now sharing the output of > $ curl --silent > https://raw.githubusercontent.com/whitepj/dnsmasq-lua/main/dhcp.lua Thanks Geert. Apologies -- it was my intention to keep the actual noise down to a minimum. You can see from the script that the vast majority of it is nothing more than comment. The line that I am having the problem with is that which retrieves that various variables. I have tried: a = (os.getenv("DNSMASQ_TIME_REMAINING") or "blank") but this returns nothing at all. Since my knowledge of lua is far from extensive, I'm hoping that someone may know what I'm doing wrong.. Many thanks. > --[[ > >LUA script for dnsmasq DHCP leases. Modified from original source at: >http://lists.thekelleys.org/pipermail/dnsmasq-discuss/2012q1/005425.html >This script is principally a boilerplate example, to show what is > possible... >Tested using dnsmasq v2.90 > >Run when: > - Startup (existing leases are invoked with 'old' event > - SIGHUP ? > - dhcp lease created, renewed, changed, or destroyed. > - tftp file transfer completes (not tested) > >ENVIRONMENT VARIABLES >= > - DNSMASQ_DOMAIN > - DNSMASQ_SUPPLIED_HOSTNAME > - DNSMASQ_USER_CLASS0 ... _CLASSn > - DNSMASQ_LEASE_LENGTH / DNSMASQ_LEASE_EXPIRES > - DNSMASQ_TIME_REMAINING > - DNSMASQ_DATA_MISSING > - DNSMASQ_INTERFACE > - DNSMASQ_RELAY_ADDRESS > - DNSMASQ_TAGS > - DNSMASQ_REQUESTED_OPTIONS > - DNSMASQ_MUD_URL >- IPv4 Only > - DNSMASQ_CLIENT_ID > - DNSMASQ_CIRCUIT_ID > - DNSMASQ_SUBSCRIBER_ID > - DNSMASQ_REMOTE_ID > - DNSMASQ_VENDOR_CLASS >- IPv6 Only > - DNSMASQ_VENDOR_CLASS_ID > - DNSMASQ_VENDOR_CLASS0 ... _CLASSn > - DNSMASQ_SERVER_DUID > - DNSMASQ_IAID > - DNSMASQ_MAC >--]] > > DBI = require "DBI" -- The ONLY external dependency. On gentoo, use > emerge dev-lua/luadbi (or use luarocks) > > -- Variable Declarations > counter = 0 > file = nil -- writing to a normal file > dbh = nil -- our database connection > dbinsert = nil -- preprepared call to write to a database > > local function myenv() -- For testing. How do we retrieve the contents of > the environment variables? > a = (os.getenv("DNSMASQ_TIME_REMAINING") or "blank") -- > Help. Always blank. > return a > end > > local function myerrorhandler(err) > print("ERROR: " .. err) > end > > function init(a) > a = (a or "--\n") > -- MOST of this function will need to be deleted or commented out, > depending on what functionality is required. > local ok, err, code = os.rename("/tmp/ilua.db","/tmp/ilua.db") > if not ok then > if code == 13 then > print("DB File exists, but we can't open it! Please > fix (or delete).") > os.exit() > else > print("No DB file found. Creating...") > os.execute('sqlite3 --line /tmp/ilua.db "CREATE TABLE > table1(\"a\");"') > end > end > > print(a .. "Starting dnsmasq lua > script...\n==\n") > > file = assert(io.open("/tmp/test.log", "a+")) > -- dbh = assert(DBI.Connect('PostgreSQL', 'db', 'user', 'password' )) > -- Alternative > dbh = assert(DBI.Connect('SQLite3','/tmp/ilua.db')) > dbh:autocommit(true) > -- dbinsert = assert(dbh:prepare('INSERT INTO table1(a) values ($1)')) > -- PostgreSQL > end > > local function output(mystring) > print(mystring) -- In production, I see little point > in this. Left for testing. > file:write(mystring)-- We write our data to a standard > file... > file:flush() > > DBI.Do(dbh, "INSERT INTO table1(a) VALUES ('" .. mystring .. "');") > -- ... or a SQLite3 file ... > -- dbinsert:execute(mystring) -- ... or a database (if using > postgreSQL) > > -- See: http:jpmens.net/2013/10/21/tracking-dhcp-leases-with-dnsmasq/ > local cmd = 'mosquitto_pub -h 192.168.1.2 -t "' .. "topic" .. '" -m > "' .. "payload" .. '" -r' > print(cmd .. "\n") -- Edit, and change 'print' > to 'os.execute' > > -- What else might we like to do? > -- Possibly look at a hook for collectd. > end > > function shutdown() > file:write("Stopping dnsmasq lua > script..!\n==\n") > file:close() > -- dbinsert:close() -- only needed if we have a prepared > SQL insert function. > dbh:close() > end > > local function tabletostring(table) > local k,v > local line = "" > for k,v in pairs(table) do line = line .