You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
3.7 KiB
160 lines
3.7 KiB
local net = require("net")
|
|
local fs = require("filesystem")
|
|
local io = require("io")
|
|
local serial = require("serialization")
|
|
|
|
local dhcp = {
|
|
SERV_PORT = 67,
|
|
CLIENT_PORT = 68,
|
|
CONFIG_FILE = "/etc/dhcp/config"
|
|
}
|
|
|
|
-- Local function for creating directory
|
|
function createConfigDir(fileName)
|
|
local configsExist = true
|
|
local dir = fs.path(fileName)
|
|
|
|
if fs.exists(dir) and not fs.isDirectory(dir) then
|
|
fs.remove(dir)
|
|
end
|
|
|
|
if not fs.exists(dir) then
|
|
fs.makeDirectory(dir)
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Gets an existing server config or creates one if it doesn't exist
|
|
function dhcp.getServerConfig(fileName)
|
|
|
|
if fileName == nil then fileName = dhcp.CONFIG_FILE end
|
|
|
|
local configsExist = true
|
|
|
|
if not createConfigDir(fileName) then
|
|
if fs.isDirectory(fileName) then
|
|
fs.remove(fileName)
|
|
end
|
|
|
|
if not fs.exists(fileName) then
|
|
configsExist = false
|
|
end
|
|
else
|
|
configsExist = false
|
|
end
|
|
|
|
if not configsExist then
|
|
print("Creating config since one doesn't exist")
|
|
local f = io.open(fileName, "w")
|
|
config = {dns = "", pxe = ""}
|
|
f:write(serial.serialize(config, 5))
|
|
f:close()
|
|
return config
|
|
else
|
|
f = io.open(fileName, "r")
|
|
local data = ""
|
|
while true do
|
|
local line = f:read()
|
|
if line ~= nil then
|
|
data = data..line
|
|
else
|
|
break
|
|
end
|
|
end
|
|
f:close()
|
|
return serial.unserialize(data)
|
|
end
|
|
end
|
|
|
|
function dhcp.startServer(servPort, clientPort, nonblocking, cacheConfig)
|
|
-- Make sure ports aren't invalid
|
|
if type(servPort) ~= "number" then
|
|
servPort = dhcp.SERV_PORT
|
|
end
|
|
|
|
if type(clientPort) ~= "number" then
|
|
clientPort = dhcp.CLIENT_PORT
|
|
end
|
|
|
|
-- Filter function for getting dhcp server messages
|
|
function dhcp.serverMsg(name, ...)
|
|
local t = {...}
|
|
|
|
if t[3] == servPort and
|
|
t[5] == "dhcp" and
|
|
t[6] == clientPort and
|
|
t[7] == "get" then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
print("Starting up DHCP server")
|
|
|
|
if cacheConfig == nil then
|
|
cacheConfig = true
|
|
else
|
|
cacheConfig = false
|
|
end
|
|
|
|
-- Read from config file each time, or just read once and use that for life of execution
|
|
local config = dhcp.getServerConfig()
|
|
|
|
while true do
|
|
local pkt, err = net.recv{servPort, filter = dhcp.serverMsg, nonblocking = nonblocking}
|
|
|
|
if pkt == nil and err == "interrupted" then
|
|
print("Interrupted")
|
|
return pkt, err
|
|
end
|
|
|
|
print("Received request from "..pkt.raddr)
|
|
if cacheConfig then
|
|
net.send(pkt.raddr, clientPort, "dhcp", serial.serialize(config))
|
|
else
|
|
print("Here")
|
|
net.send(pkt.raddr, clientPort, "dhcp", serial.serialize(dhcp.getServerConfig()))
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
function dhcp.query(servPort, clientPort, nonblocking)
|
|
-- Make sure ports aren't invalid
|
|
if type(servPort) ~= "number" then
|
|
servPort = dhcp.SERV_PORT
|
|
end
|
|
|
|
if type(clientPort) ~= "number" then
|
|
clientPort = dhcp.CLIENT_PORT
|
|
end
|
|
|
|
-- Filter function for getting dhcp client messages
|
|
function dhcp.clientMsg(name, ...)
|
|
local t = {...}
|
|
|
|
if t[3] ~= clientPort or t[5] ~= "dhcp" then
|
|
return false
|
|
elseif type(t[6]) ~= "string" then
|
|
return false
|
|
elseif serial.unserialize(t[6]) == nil then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
net.broadcast(servPort, "dhcp", clientPort, "get")
|
|
pkt, err = net.recv{
|
|
clientPort,
|
|
timeout = 3,
|
|
filter = dhcp.clientMsg,
|
|
nonblocking = not not nonblocking
|
|
}
|
|
return pkt, err
|
|
end
|
|
|
|
-- wget -f http://mc.bashed.rocks:13699/lib/dhcp.lua lib/dhcp.lua
|
|
|
|
return dhcp
|