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

New function cidrnet_to_addr_mask().

This new function tries to convert a network specification in CIDR
notation (<address> "/" <prefix_length>) into an old-style address
plus mask pair.  It supports this for both IPv4 and IPv6.  It is
intended to be used when generating config files for programs that
does not support CIDR notation, and needs a network mask instead,
e.g. the ntp.org NTP daemon, or ISC dhcpd.
parent 78aff125
No related branches found
No related tags found
No related merge requests found
# Copyright (C) 2020 Thomas Bellman.
# Licensed under the GNU LGPL v3+; see the README file for more information.
module Puppet::Parser::Functions
newfunction(:cidrnet_to_addr_mask, :type => :rvalue, :doc => '
Parse a network specification on the form "ipaddr/netmask" into a
pair "ipaddr" and "netmask". The netmask can be either a prefix
length in bits, or a full netmask in (dotted quad for IPv4, hex
mask with colons for IPv6). In the former case it is converted to
a full netmask. If no netmask is specified, nil is returned for
the mask, unless the optional second argument is true, in which
case a mask specifying a host is returned for the mask.
This is useful when generating configuration files for programs
needing network masks instead of prefix lengths, e.g. ISC dhcpd
or the ntp.org NTP daemon.
The address part of the network specification does not need to be
a valid IP address. This can be used e.g. to specify a hostname
instead of a numeric address, which can be useful somtimes. In
that case, the function cannot determine if the netmask / prefix
length is for IPv4 or IPv6, and the mask will be returned without
any changes. You should really not specify a mask in that case,
and the fillmask flag is not used.
If an invalid mask / prefix length is specified, it will currently
be returned unchanged, without any error being raised. This might
change in the future.
') \
do |args|
if args.length < 1 or args.length > 2
raise(ArgumentError, #Puppet::ParseError,
"cidrnet_to_addr_mask(): Bad number of arguments, #{args.length}")
end
netspec = args[0]
fillmask = args[1] or false
ipv6_re = /^[0-9a-f:]+$/i
ipv4_re = /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/
addr,mask = netspec.split('/', 2)
if ipv6_re =~ addr and mask == nil
# IPv6 without mask
mask = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" if fillmask
elsif ipv4_re =~ addr and mask == nil
# IPv4 without mask
mask = "255.255.255.255" if fillmask
elsif ipv6_re =~ addr and /^[0-9]+$/ =~ mask
# IPv6 with prefix length
bits = mask.to_i
m = 0xffffffffffffffffffffffffffffffff >> (128-bits) << (128-bits)
mask = sprintf("%032x", m).gsub(/....(?!$)/, '\&:')
mask.sub!(/(:0000)+$/, '::')
elsif ipv4_re =~ addr and /^[0-9]+$/ =~ mask
# IPv4 with prefix length
bits = mask.to_i
m = 0xffffffff >> (32-bits) << (32-bits)
mask = sprintf("%d.%d.%d.%d",
m>>24 & 0xff, m>>16 & 0xff, m>>8 & 0xff, m & 0xff)
else
# Assume proper mask according to address family
end
return addr,mask
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment