diff options
author | Andreas Brodmann <andreas.brodmann@gmail.com> | 2007-11-16 22:09:29 +0000 |
---|---|---|
committer | Andreas Brodmann <andreas.brodmann@gmail.com> | 2007-11-16 22:09:29 +0000 |
commit | 365f56f2b68b036352d12daa13695b662a9d0017 (patch) | |
tree | 8fe9bc1a6b845fafa6c29a52127c7aa9940dc520 | |
parent | 4d2aa0242d937da6b3431dbdb743a02669628023 (diff) | |
download | acf-dhcp-365f56f2b68b036352d12daa13695b662a9d0017.tar.bz2 acf-dhcp-365f56f2b68b036352d12daa13695b662a9d0017.tar.xz |
/acf/dhcp: added static/dynamic host behaviour on a per subnet basis
git-svn-id: svn://svn.alpinelinux.org/acf/dhcp/trunk@326 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r-- | dhcp-controller.lua | 6 | ||||
-rw-r--r-- | dhcp-createnet-html.lsp | 11 | ||||
-rw-r--r-- | dhcp-editnet-html.lsp | 28 | ||||
-rw-r--r-- | dhcp-model.lua | 304 |
4 files changed, 268 insertions, 81 deletions
diff --git a/dhcp-controller.lua b/dhcp-controller.lua index 00f213d..fc0e6f8 100644 --- a/dhcp-controller.lua +++ b/dhcp-controller.lua @@ -127,7 +127,7 @@ editnet = function ( self ) tmp = self.clientdata net = self.model.create_new_net( tmp.name, tmp.defleasetime, tmp.maxleasetime, tmp.gateway, tmp.domainname, tmp.dnssrv1, tmp.dnssrv2, tmp.subnet, tmp.netmask, tmp.leaserangestart, - tmp.leaserangeend, tmp.wpad, tmp.spechosts ) + tmp.leaserangeend, tmp.wpad, tmp.statichosts, tmp.unknownclients, tmp.dynamichosts ) errcode, net = self.model.subnet_write( net ) return ( cfe({ option = option, value = net, errcode = errcode }) ) end @@ -150,13 +150,13 @@ createnet = function ( self ) } if self.clientdata.cmd == "new" then - net = self.model.create_new_net( "<new>", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ) + net = self.model.create_new_net( "<new>", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ) return ( cfe({ option = option, value = net, errcode = { msg = "", fields = nil }}) ) elseif self.clientdata.cmd == "create" then tmp = self.clientdata net = self.model.create_new_net( tmp.name, tmp.defleasetime, tmp.maxleasetime, tmp.gateway, tmp.domainname, tmp.dnssrv1, tmp.dnssrv2, tmp.subnet, - tmp.netmask, tmp.leaserangestart, tmp.leaserangeend, tmp.wpad, "" ) + tmp.netmask, tmp.leaserangestart, tmp.leaserangeend, tmp.wpad, "", tmp.unknownclients, "" ) errcode, net = self.model.subnet_create( net ) if #errcode.msg == 0 then self.conf.type = "redir" diff --git a/dhcp-createnet-html.lsp b/dhcp-createnet-html.lsp index 2fe5a45..dc5d88f 100644 --- a/dhcp-createnet-html.lsp +++ b/dhcp-createnet-html.lsp @@ -27,5 +27,16 @@ <tr><td><nobr>WPAD:</nobr></td><td><input type="text" name="wpad" value="<? io.write(net.wpad.value) ?>"></td></tr> <tr><td><nobr>Lease Range Start:</nobr></td><td><input type="text" name="leaserangestart" value="<? io.write(net.leaserangestart.value) ?>"></td></tr> <tr><td><nobr>Lease Range End:</nobr></td><td><input type="text" name="leaserangeend" value="<? io.write(net.leaserangeend.value) ?>"></td></tr> + <tr><td><nobr>Unknown Clients</nobr></td><td><select name="unknownclients" size="1"> +<? + if net.unknownclients.value == "permit" then + io.write(" <option selected>permit</option>\n"); + io.write(" <option>deny</option>\n"); + else + io.write(" <option>permit</option>\n"); + io.write(" <option selected>deny</option>\n"); + end +?> + </select></td></tr> <tr><td></td><td><input type=submit name=cmd value="create" style="width:100px"></form><form action="<? io.write(option.script .. option.prefix .. option.controller .. "/home") ?> method="POST"> <input type=submit name="cmd" value="back" style="width:100px"></form></td></tr></table> diff --git a/dhcp-editnet-html.lsp b/dhcp-editnet-html.lsp index ea281a0..9bab76b 100644 --- a/dhcp-editnet-html.lsp +++ b/dhcp-editnet-html.lsp @@ -13,9 +13,10 @@ end ?> -<form action="<? io.write(option.script .. option.prefix .. +<form name="mainform" action="<? io.write(option.script .. option.prefix .. option.controller .. "/" .. option.action .. option.extra) ?>" method="POST"> <input type="hidden" name="name" value="<? io.write(net.name.value) ?>"> +<input type="hidden" name="dynhost1" value=""> <table> <tr><td><nobr>Subnet:</nobr></td><td><input type="text" name="subnet" value="<? io.write(net.subnet.value) ?>"></td></tr> <tr><td><nobr>Netmask:</nobr></td><td><input type="text" name="netmask" value="<? io.write(net.netmask.value) ?>"></td></tr> @@ -28,11 +29,22 @@ <tr><td><nobr>WPAD:</nobr></td><td><input type="text" name="wpad" value="<? io.write(net.wpad.value) ?>"></td></tr> <tr><td><nobr>Lease Range Start:</nobr></td><td><input type="text" name="leaserangestart" value="<? io.write(net.leaserangestart.value) ?>"></td></tr> <tr><td><nobr>Lease Range End:</nobr></td><td><input type="text" name="leaserangeend" value="<? io.write(net.leaserangeend.value) ?>"></td></tr> + <tr><td><nobr>Unknown Clients</nobr></td><td><select name="unknownclients" size="1"> +<? + if net.unknownclients.value == "permit" then + io.write(" <option selected>permit</option>\n"); + io.write(" <option>deny</option>\n"); + else + io.write(" <option>permit</option>\n"); + io.write(" <option selected>deny</option>\n"); + end +?> + </select></td></tr> <form action="<? io.write(option.script .. option.prefix .. option.controller .. "/home") ?>" method="POST"> </td></tr></table> <br><br> -<h2>Subnet: Special Hosts</h2> +<h2>Subnet: Static Hosts</h2> Enter one host per line in the format: <i>hostname;ip;mac;comment</i><br> <table> <tr><td>Hostname</td><td>[a-z], [0-9], -</td></tr> @@ -40,7 +52,17 @@ Enter one host per line in the format: <i>hostname;ip;mac;comment</i><br> <tr><td>MAC</td><td>XX:XX:XX:XX:XX:XX</td></tr> </table> <table> -<tr><td><textarea name="spechosts" style="width:600px;"><? io.write( net.spechosts.value ) ?></textarea></td></tr> +<tr><td><textarea name="statichosts" style="width:600px;"><? io.write( net.statichosts.value ) ?></textarea></td></tr> +</table><br> +<h2>Subnet: Dynamic Hosts</h2> +Enter one host per line in the format: <i>hostname;mac;comment</i><br> +<table> +<tr><td>Hostname</td><td>[a-z], [0-9], -</td></tr> +<tr><td>MAC</td><td>XX:XX:XX:XX:XX:XX</td></tr> +</table> +<table> +<tr><td><div id="dynamic"><textarea name="dynamichosts" style="width:600px;"><? io.write( net.dynamichosts.value ) ?></textarea></div></td></tr> +</table><br> <tr><td><input type=submit name="cmd" value="update" style="width:100px"></form> <form action="<? io.write(option.script .. option.prefix .. option.controller .. "/delnet") ?>" method="POST"> <input type=submit name="cmd" value="delete" style="width:100px"> diff --git a/dhcp-model.lua b/dhcp-model.lua index b16124c..9cbc069 100644 --- a/dhcp-model.lua +++ b/dhcp-model.lua @@ -151,12 +151,23 @@ config_generate = function() if #net.domainname.value > 0 then tmpfile:write( " option domain-name \"" .. net.domainname.value .. "\";\n" ) end - if #net.leaserangestart.value > 0 then - tmpfile:write( " range " .. net.leaserangestart.value .. " " .. net.leaserangeend.value .. ";\n" ) - end if #net.wpad.value > 0 then tmpfile:write( " option local-wpad-server \"" .. net.wpad.value .. "\\n\";\n" ) end + spec2_msg = generate_pool( tmpfile, tmpfilename, net ) + if #spec2_msg > 0 then + tmpfile:close() + os.remove( tmpfilename ) + msg = "Configuration Generation Failed!\n\n" .. spec2_msg + return msg + end + spec2_msg = generate_hosts( tmpfile, tmpfilename, net ) + if #spec2_msg > 0 then + tmpfile:close() + os.remove( tmpfilename ) + msg = "Configuration Generation Failed!\n\n" .. spec2_msg + return msg + end tmpfile:write( "}\n\n" ) end @@ -168,62 +179,127 @@ config_generate = function() return msg end - --- generate special hosts - subnets = get_subnets() - for k,v in ipairs( subnets ) do - spechostsfile = io.open( cfgdir .. v .. ".spechosts", "r" ) - if spechostsfile ~= nil then - spechosts = spechostsfile:read( "*a" ) - if spechosts == nil then - spechostsfile:close() - tmpfile:close() - os.remove( tmpfilename ) - msg = "Configuration Generation Failed!\n\n" .. - "Reason: failed to read special hosts file for '" .. v .. "'" - return msg - end - msg = validate_spechosts( spechosts ) - if #msg > 0 then - spechostsfile:close() - tmpfile:close() - os.remove( tmpfilename ) - msg = "Configuration Generation Failed!\n\n" .. - "Reason: " .. msg - return msg - end - - --- loop through all hosts - tmpfile:write("group {\n") - done = false - hosttoken = tokenizer.new( spechosts, "\n" ) - while not done do - hosttoken, nexthost = tokenizer.next( hosttoken ) - if nexthost ~= nil then - if string.sub( nexthost, 1, 1) ~= "#" then - spectoken = tokenizer.new( nexthost, ";" ) - spectoken, hostname = tokenizer.next( spectoken ) - spectoken, ip = tokenizer.next( spectoken ) - spectoken, mac = tokenizer.next( spectoken ) - spectoken, comment = tokenizer.next( spectoken ) - tmpfile:write(" host " .. hostname .. " {\n") - tmpfile:write(" hardware ethernet " .. mac .. ";\n") - tmpfile:write(" fixed-address " .. ip .. ";\n") - tmpfile:write(" }\n") - end - else - done = true + tmpfile:close() + os.rename( tmpfilename, "/etc/dhcp/dhcpd.conf" ) + + return "Configuration Generation Successful!\n" +end + +generate_pool = function( tmpfile, tmpfilename, net ) + if not validator.is_ipv4( net.leaserangestart.value ) or + not validator.is_ipv4( net.leaserangeend.value ) then + if net.unknownclients.value == "permit" then + msg = "Reason: permitted unknown clients but failed to define lease range!\n" + return msg + end + + return "" + end + + --- pool header + tmpfile:write( " pool {\n" ) + if net.unknownclients.value == "permit" then + tmpfile:write( " permit known clients;\n" ) + tmpfile:write( " permit unknown clients;\n" ) + else + tmpfile:write( " permit known clients;\n" ) + tmpfile:write( " deny unknown clients;\n" ) + end + tmpfile:write( " range " .. net.leaserangestart.value .. " " .. net.leaserangeend.value .. ";\n" ) + tmpfile:write( " }\n" ) + + return "" +end + +generate_hosts = function( tmpfile, tmpfilename, net ) + --- generate static hosts + statichostsfile = io.open( cfgdir .. net.name.value .. ".static", "r" ) + if statichostsfile ~= nil then + statichosts = statichostsfile:read( "*a" ) + if statichosts == nil then + statichostsfile:close() + msg = "Configuration Generation Failed!\n\n" .. + "Reason: failed to read static hosts file for '" .. net.name.value .. "'" + return msg + end + msg = validate_statichosts( statichosts ) + if #msg > 0 then + statichostsfile:close() + msg = "Configuration Generation Failed!\n\n" .. + "Reason: " .. msg + return msg + end + + --- loop through all hosts + done = false + hosttoken = tokenizer.new( statichosts, "\n" ) + while not done do + hosttoken, nexthost = tokenizer.next( hosttoken ) + if nexthost ~= nil then + if string.sub( nexthost, 1, 1) ~= "#" then + spectoken = tokenizer.new( nexthost, ";" ) + spectoken, hostname = tokenizer.next( spectoken ) + spectoken, ip = tokenizer.next( spectoken ) + spectoken, mac = tokenizer.next( spectoken ) + spectoken, comment = tokenizer.next( spectoken ) + tmpfile:write(" host " .. hostname .. " {\n") + tmpfile:write(" hardware ethernet " .. mac .. ";\n") + tmpfile:write(" fixed-address " .. ip .. ";\n") + tmpfile:write(" }\n") end + else + done = true end - spechostsfile:close() - tmpfile:write("}\n\n") end + statichostsfile:close() end --- + + if net.unknownclients.value == "permit" then + return "" + end + --- generate dynamic hosts + dynamichostsfile = io.open( cfgdir .. net.name.value .. ".dynamic", "r" ) + if dynamichostsfile ~= nil then + dynamichosts = dynamichostsfile:read( "*a" ) + if dynamichosts == nil then + dynamichostsfile:close() + msg = "Configuration Generation Failed!\n\n" .. + "Reason: failed to read dynamic hosts file for '" .. net.name.value .. "'" + return msg + end + msg = validate_dynamichosts( dynamichosts ) + if #msg > 0 then + dynamichostsfile:close() + msg = "Configuration Generation Failed!\n\n" .. + "Reason: " .. msg + return msg + end - tmpfile:close() - os.rename( tmpfilename, "/etc/dhcp/dhcpd.conf" ) + --- loop through all hosts + done = false + hosttoken = tokenizer.new( dynamichosts, "\n" ) + while not done do + hosttoken, nexthost = tokenizer.next( hosttoken ) + if nexthost ~= nil then + if string.sub( nexthost, 1, 1) ~= "#" then + spectoken = tokenizer.new( nexthost, ";" ) + spectoken, hostname = tokenizer.next( spectoken ) + spectoken, mac = tokenizer.next( spectoken ) + spectoken, comment = tokenizer.next( spectoken ) + tmpfile:write(" host " .. hostname .. " {\n") + tmpfile:write(" hardware ethernet " .. mac .. ";\n") + tmpfile:write(" }\n") + end + else + done = true + end + end + dynamichostsfile:close() + end + --- - return "Configuration Generation Successful!\n" + return "" end subnet_delete = function( name ) @@ -232,14 +308,15 @@ subnet_delete = function( name ) local filename = cfgdir .. name os.remove( filename .. ".subnet" ) - os.remove( filename .. ".spechosts" ) + os.remove( filename .. ".static" ) + os.remove( filename .. ".dynamic" ) return msg end subnet_read = function( name ) local filename = cfgdir .. name .. ".subnet" - local net = create_new_net( name, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ) + local net = create_new_net( name, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ) for line in io.lines(filename) do if (string.sub(line, 1, 15) == "def-lease-time:") then @@ -264,17 +341,23 @@ subnet_read = function( name ) net.leaserangeend.value = string.sub(line, 18) elseif (string.sub(line, 1, 5) == "wpad:") then net.wpad.value = string.sub(line, 7) + elseif (string.sub(line, 1, 16) == "unknown-clients:") then + net.unknownclients.value = string.sub(line, 18) end end + if net.unknownclients.value ~= "permit" then + net.unknownclients.value = "deny" + end - net.spechosts.value = subnet_get_spechosts( name ) + net.statichosts.value = subnet_get_spechosts( name, "static" ) + net.dynamichosts.value = subnet_get_spechosts( name, "dynamic" ) return net end -subnet_get_spechosts = function( name ) +subnet_get_spechosts = function( name, suffix ) local retval = "" - local filename = cfgdir .. name .. ".spechosts" + local filename = cfgdir .. name .. "." .. suffix if file_exists( filename ) then local file = io.open( filename, "r" ) if file ~= nil then @@ -289,15 +372,30 @@ subnet_get_spechosts = function( name ) return retval end -subnet_update_spechosts = function( name, spechosts ) +subnet_update_statichosts = function( name, statichosts ) + local msg = ""; + local filename = cfgdir .. name .. ".static" + + file, errmsg = io.open( filename, "wb+" ) + if file == nil then + msg = "Error: Failed to open " .. filename .. "(" .. errmsg .. ")!" + else + file:write( statichosts ) + file:close() + end + + return msg +end + +subnet_update_dynamichosts = function( name, dynamichosts ) local msg = ""; - local filename = cfgdir .. name .. ".spechosts" + local filename = cfgdir .. name .. ".dynamic" file, errmsg = io.open( filename, "wb+" ) if file == nil then msg = "Error: Failed to open " .. filename .. "(" .. errmsg .. ")!" else - file:write( spechosts ) + file:write( dynamichosts ) file:close() end @@ -340,27 +438,41 @@ subnet_write = function( net ) file:write( "lease-range-start: " .. net.leaserangestart.value .. "\n" ) file:write( "lease-range-end: " .. net.leaserangeend.value .. "\n" ) file:write( "wpad: " .. net.wpad.value .. "\n" ) + file:write( "unknown-clients: " .. net.unknownclients.value .. "\n" ) file:close() - spec_msg = validate_spechosts( net.spechosts.value ) + + spec_msg = validate_statichosts( net.statichosts.value ) + if #spec_msg == 0 then + spec_msg = subnet_update_statichosts( net.name.value, net.statichosts.value ) + if #spec_msg > 0 then + msg = spec_msg + table.insert( fields, "statichosts" ) + end + else + msg = spec_msg + table.insert( fields, "statichosts" ) + end + + spec_msg = validate_dynamichosts( net.dynamichosts.value ) if #spec_msg == 0 then - spec_msg = subnet_update_spechosts( net.name.value, net.spechosts.value ) + spec_msg = subnet_update_dynamichosts( net.name.value, net.dynamichosts.value ) if #spec_msg > 0 then msg = spec_msg - table.insert( fields, "spechosts" ) + table.insert( fields, "dynamichosts" ) end else msg = spec_msg - table.insert( fields, "spechosts" ) + table.insert( fields, "dynamichosts" ) end + return cfe({ msg = msg, fields = {}}), net end -validate_spechosts = function( spechosts ) - +validate_statichosts = function( statichosts ) local line = 1 local msg = "" local done = false - hosttoken = tokenizer.new( spechosts, "\n") + hosttoken = tokenizer.new( statichosts, "\n") while not done do hosttoken, nexthost = tokenizer.next( hosttoken ) if nexthost ~= nil then @@ -371,24 +483,61 @@ validate_spechosts = function( spechosts ) fieldtoken, mac = tokenizer.next( fieldtoken ) fieldtoken, comment = tokenizer.next( fieldtoken ) if hostname == nil then - msg = msg .. "hostname missing on line " .. line .. "!\n" + msg = msg .. "Static Hosts: hostname missing on line " .. line .. "!\n" else if not is_valid_hostname( hostname ) then - msg = msg .. "Invalid hostname on line " .. line .. "!\n" + msg = msg .. "Static Hosts: Invalid hostname on line " .. line .. "!\n" end end if ip == nil then - msg = msg .. "ip missing on line " .. line .. "!\n" + msg = msg .. "Static Hosts: ip missing on line " .. line .. "!\n" else if not validator.is_ipv4( ip ) then - msg = msg .. "Invalid ip on line " .. line .. "!\n" + msg = msg .. "Static Hosts: Invalid ip on line " .. line .. "!\n" + end + end + if mac == nil then + msg = msg .. "Static Hosts: mac missing on line " .. line .. "!\n" + else + if not validator.is_mac( mac ) then + msg = msg .. "Static Hosts: Invalid mac on line " .. line .. "!\n" + end + end + end + line = line + 1 + else + done = true + end + end + + return msg +end + +validate_dynamichosts = function( dynamichosts ) + local line = 1 + local msg = "" + local done = false + hosttoken = tokenizer.new( dynamichosts, "\n") + while not done do + hosttoken, nexthost = tokenizer.next( hosttoken ) + if nexthost ~= nil then + if string.sub(nexthost, 1, 1) ~= "#" then + fieldtoken = tokenizer.new( nexthost, ";") + fieldtoken, hostname = tokenizer.next( fieldtoken ) + fieldtoken, mac = tokenizer.next( fieldtoken ) + fieldtoken, comment = tokenizer.next( fieldtoken ) + if hostname == nil then + msg = msg .. "Static Hosts: hostname missing on line " .. line .. "!\n" + else + if not is_valid_hostname( hostname ) then + msg = msg .. "Static Hosts: Invalid hostname on line " .. line .. "!\n" end end if mac == nil then - msg = msg .. "mac missing on line " .. line .. "!\n" + msg = msg .. "Static Hosts: mac missing on line " .. line .. "!\n" else if not validator.is_mac( mac ) then - msg = msg .. "Invalid mac on line " .. line .. "!\n" + msg = msg .. "Static Hosts: Invalid mac on line " .. line .. "!\n" end end end @@ -596,7 +745,7 @@ get_subnets = function () return retval end -create_new_net = function( name, defleasetime, maxleasetime, gateway, domainname, dnssrv1, dnssrv2, subnet, netmask, leaserangestart, leaserangeend, wpad, spechosts ) +create_new_net = function( name, defleasetime, maxleasetime, gateway, domainname, dnssrv1, dnssrv2, subnet, netmask, leaserangestart, leaserangeend, wpad, statichosts, unknownclients, dynamichosts ) net = { name = { label="Name", value=nonil(name), type="message" }, defleasetime = { label="Default Lease Time", value=nonil(defleasetime), type="text" }, maxleasetime = { label="Maximum Lease Time", value=nonil(maxleasetime), type="text" }, @@ -609,8 +758,13 @@ create_new_net = function( name, defleasetime, maxleasetime, gateway, domainname leaserangestart = { label="Lease Range Start", value=nonil(leaserangestart), type="text" }, leaserangeend = { label="Lease Range End", value=nonil(leaserangeend), type="text" }, wpad = { label="Web Proxy Auto Discovery", value=nonil(wpad), type="text" }, - spechosts = { label="Special Hosts Config", value=nonil(spechosts), type="text" } + statichosts = { label="Static Hosts", value=nonil(statichosts), type="text" }, + dynamichosts = { label="Dynamic Hosts", value=nonil(dynamichosts), type="text" }, + unknownclients = { label="Unknown Clients", value=nonil(unknownclients), type="text" } } + if net.unknownclients.value ~= "permit" then + net.unknownclients.value = "deny" + end return net end |