Just testing this blog, why not writing a post as an exercise. 🙂
In big projects I have hundreds of sub networks. There’s a lot of small transport networks with small subnet masks, that partition a summarizing net, and there are gateways. All these data is part of documentation and drawings. When I have a second project of the same kind, I can re-use documentation and drawings, just based on another IP address range. Will I calculate all again, typing the new IP addresses into each place at the drawings and docs? No, I like to automate it. TeX can do it.
You all know, what an IP address is:
I chose Lua for calculating things, and LuaLaTeX compiles my documents. I will post a simplified example here.
On the Internet, I found a nice snippet ipv4.lua by Nick Barret, so I did not have to program all myself. How to use it? Here are basic steps for a possible implementation:
- Add
\usepackage{luacode}
to your preamble - Get some Lua code (google for <keyword> and Lua) or program yourself
- Use the code as argument of a
\luaexec
command - Modify the Lua code a bit:
-
- remove Lua comments or change them (incompatible syntax)
- quote % by a backslash:
\%
- quote backslashes, such as here:
tex.sprint( "\\def\\ipDevice{#1}" )
- Instead of
print
, usetex.sprint
for handing over things to TeX
A compilable demo:
\usepackage{luacode}
\newcommand{\ip}[2]{%
\luaexec{
local ip1= string.gsub("#1", "\%.(\%d+).(\%d+).(\%d+)","")
local ip2= string.gsub("#1", "(\%d+)\%.","",1)
local ip2= string.gsub(ip2, "\%.(\%d+).(\%d+)","")
local ip3= string.gsub("#1", "(\%d+)\%.(\%d+)\%.","",1)
local ip3= string.gsub(ip3, "\%.(\%d+)","")
local ip4= string.gsub("#1", "(\%d+)\%.(\%d+)\%.(\%d+)\%.","",1)
local mask = #2
local ip = { tonumber( ip1 ), tonumber( ip2 ), tonumber( ip3 ), tonumber( ip4 ) }
local masks = {
[1] = { 127, 255, 255, 255 },
[2] = { 63, 255, 255, 255 },
[3] = { 31, 255, 255, 255 },
[4] = { 15, 255, 255, 255 },
[5] = { 7, 255, 255, 255 },
[6] = { 3, 255, 255, 255 },
[7] = { 1, 255, 255, 255 },
[8] = { 0, 255, 255, 255 },
[9] = { 0, 127, 255, 255 },
[10] = { 0, 63, 255, 255 },
[11] = { 0, 31, 255, 255 },
[12] = { 0, 15, 255, 255 },
[13] = { 0, 7, 255, 255 },
[14] = { 0, 3, 255, 255 },
[15] = { 0, 1, 255, 255 },
[16] = { 0, 0, 255, 255 },
[17] = { 0, 0, 127, 255 },
[18] = { 0, 0, 63, 255 },
[19] = { 0, 0, 31, 255 },
[20] = { 0, 0, 15, 255 },
[21] = { 0, 0, 7, 255 },
[22] = { 0, 0, 3, 255 },
[23] = { 0, 0, 1, 255 },
[24] = { 0, 0, 0, 255 },
[25] = { 0, 0, 0, 127 },
[26] = { 0, 0, 0, 63 },
[27] = { 0, 0, 0, 31 },
[28] = { 0, 0, 0, 15 },
[29] = { 0, 0, 0, 7 },
[30] = { 0, 0, 0, 3 },
[31] = { 0, 0, 0, 1 }
}
local wildcard = masks[tonumber( mask )]
local ipcount = math.pow( 2, ( 32 - mask ) )
local bottomip = {}
for k, v in pairs( ip ) do
if wildcard[k] == 0 then
bottomip[k] = v
elseif wildcard[k] == 255 then
bottomip[k] = 0
else
local mod = v \% ( wildcard[k] + 1 )
bottomip[k] = v - mod
end
end
local topip = {}
for k, v in pairs( bottomip ) do
topip[k] = v + wildcard[k]
end
tex.sprint( "\def\ipMask{" .. 255-wildcard[1] .. "." .. 255-wildcard[2]
.. "." .. 255-wildcard[3] .. "." .. 255-wildcard[4].. "}" )
local isnetworkip = ( ip[1] == bottomip[1] and ip[2] == bottomip[2]
and ip[3] == bottomip[3] and ip[4] == bottomip[4] )
local isbroadcastip = ( ip[1] == topip[1] and ip[2] == topip[2]
and ip[3] == topip[3] and ip[4] == topip[4] )
tex.sprint( "\def\ipDevice{#1}" )
tex.sprint( "\def\ipNetwork{" .. bottomip[1] .. "." .. bottomip[2]
.. "." .. bottomip[3] .. "." .. bottomip[4] .. "/" .. mask .. "}" )
tex.sprint( "\def\ipGateway{" .. bottomip[1] .. "." .. bottomip[2]
.. "." .. bottomip[3] .. "." .. bottomip[4]+1 .. "}" )
tex.sprint( "\def\ipBroadcast{" .. topip[1] .. "." .. topip[2]
.. "." .. topip[3] .. "." .. topip[4] .. "}" )
tex.sprint( "\def\ipHostRange{" .. bottomip[1] .. "." .. bottomip[2]
.. "." .. bottomip[3] .. "." .. bottomip[4] + 2 .. " - " .. topip[1]
.. "." .. topip[2] .. "." .. topip[3] .. "." .. topip[4] - 1 .. "}")
}}
\begin{document}
\ip{10.240.3.38}{29}
Network data for device \ipDevice:
\bigskip
\begin{tabular}{rl}
Subnet: & \ipNetwork \
Subnet mask: & \ipMask \
Gateway: & \ipGateway \
Broadcast: & \ipBroadcast \
Host range: & \ipHostRange \
\end{tabular}
\end{document}
In this demo, I specified a device IP and its net mask, an got these values in return:
Network data for device 10.240.3.38:
Subnet: 10.240.3.32/29
Subnet mask: 255.255.255.248
Gateway: 10.240.3.33
Broadcast: 10.240.3.39
Host range: 10.240.3.34 – 10.240.3.38
In the real world, I use loops to fill tables with such data or use it in labels on edges in TikZ drawings, such as here: