Skip to content
Snippets Groups Projects
Commit ef213a61 authored by Thomas Bellman's avatar Thomas Bellman
Browse files

Add flag 'forcemask' for resolve_ipnets() function.

This new flag to the resolve_ipnets() function causes it to add an
appropriate explicit host mask (/32 or /128 depending on IP family)
if the input did not contain a mask.  I.e, if calling:

    $hosts = [ "www.example.com", "smurf.example.net/28",
               "203.0.113.99", "2001:db8:113::99" ]
    $addrs = resolve_ipnets($hosts, "forcemask")

the return value from resolve_ipnets() will be something like:

    [ "192.0.2.17/32", "2001:db8:1:2::17/128",
      "198.51.100.23/28", "2001:db8:51:100::23/28",
      "203.0.113.99/32", "2001:db8:113::99/128"
    ]

Since there is no mask specified for www.example.com, an explicit
/32 will be added to its IPv4 address, and an explicit /128 to its
IPv6 address.  Likewise for the numeric addresses.  However, as the
smurf.example.net/28 name contained a netmask, that /28 will be kept
(although using the same mask for both IPv4 and IPv6 is unlikely to
be something you want).

This can be useful when the result is to be used in situations where
plain IP addresses are not allowed, only complete CIDR specifications.
An example, and the motivation for implementing this, is Munin, where
"cidr_allow" directives in munin-node configuration files must include
the prefix length.
parent 89c8ffc5
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,9 @@ module Puppet::Parser::Functions
'ipv6' => Socket::AF_INET6,
}
def resolve_ipnets__netspec(addr, ipfamilies, on_error, do_partsort)
def resolve_ipnets__netspec(
addr, ipfamilies, on_error, do_partsort, forcemask)
m = /^((v[0-9]+|ipv[0-9]+):)?(.*?)(\/[^\/]*)?$/.match(addr)
familyspec,hostname,maskspec = m[2], m[3], (m[4] or "")
......@@ -34,6 +36,11 @@ module Puppet::Parser::Functions
end
if m = /^\[(.*)\]$/.match(hostname) # "[" address "]"
if forcemask && maskspec == ""
raise(Puppet::ParseError,
("resolve_ipnets(): Can't force a netmask on bracketed" +
" address, #{addr}"))
end
return [m[1] + maskspec]
end
......@@ -55,6 +62,15 @@ module Puppet::Parser::Functions
"resolve_ipnets(): Internal error: bad return from IPAddr.new")
end
# Can only match one family, so return immediately
if forcemask && maskspec == ""
if ip.ipv4?; maskspec = "/32"
elsif ip.ipv6?; maskspec = "/128"
else
raise(Puppet::Error,
("resolve_ipnets(): " +
"Unsupported IP address, #{hostname}"))
end
end
return [ip.to_s + maskspec]
end
end
......@@ -89,13 +105,22 @@ module Puppet::Parser::Functions
ipaddrs = [ ]
found_families.each do |family|
ips.fetch(family).sort! if do_partsort
ipaddrs += ips[family]
if forcemask && maskspec == ""
family_maskspec = (
if family == Socket::AF_INET; "/32"
elsif family == Socket::AF_INET6; "/128"
end
)
else
family_maskspec = maskspec
end
ipaddrs += ips[family].collect {|ip| ip + family_maskspec }
end
if ipaddrs.length == 0
# Note: this will only show the last error message
raise err.class.new(err.to_s + ', ' + addr)
end
return ipaddrs.collect {|ip| ip + maskspec }
return ipaddrs
end
module_function :resolve_ipnets__netspec
......@@ -115,6 +140,10 @@ module Puppet::Parser::Functions
"ipv6" Force lookup of hostnames as IPv6 addresses.
"forcemask"
Always add a host mask (/32 or /128) to the result if no
mask was specified in the input.
"ignoreerrors"
If an address cannot be resolved, return it unchanged.
......@@ -185,12 +214,15 @@ module Puppet::Parser::Functions
end
netspecs,*flags = args
ipfamilies = []
forcemask = false
on_error = :fail
do_partsort = false # Sort addresses for each input netspec
[flags].flatten.each do |f|
case f
when 'ipv4', 'ipv6'
ipfamilies << f
when 'forcemask'
forcemask = true
when 'ignoreerrors'
on_error = :ignore
when 'failerrors'
......@@ -207,7 +239,7 @@ module Puppet::Parser::Functions
res = []
[netspecs].flatten.each do |netspec|
res += Puppet::Parser::Functions::resolve_ipnets__netspec(
netspec, ipfamilies, on_error, do_partsort)
netspec, ipfamilies, on_error, do_partsort, forcemask)
end
return res.uniq
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment