Aggregator.rb
This content was produced by an LLM and could include errors.
This script summarizes a list of IP addresses into the smallest possible CIDR blocks, then converts those blocks into standard Access Control List (ACL) format.
def summarize_ips(ip_list, min_mask: 0)
ips = ip_list.uniq.map { IPAddr.new(_1) }.sort_by(&:to_i)
ips.chunk_while { |a, b| b.to_i == a.to_i + 1 }
.flat_map { |c| range_to_cidrs(c.first, c.last, min_mask: min_mask) }
end
#=> :summarize_ips
def cidrs_to_acl(entries)
entries.map { |e| cidr_to_acl(e) }
end
#=> :cidrs_to_acl
def mask_to_netmask(mask)
[(0xffffffff << (32 - mask)) & 0xffffffff]
.pack('N').unpack('C4').join('.')
end
#=> :mask_to_netmask
def cidr_to_acl(entry)
ip, mask = entry
return "host #{ip}" if mask == 32
"#{ip} #{mask_to_netmask(mask)}"
end
#=> :cidr_to_acl
def largest_block(start_ip, end_ip, min_mask)
mask = 32
best = [start_ip.to_s, 32]
while mask >= min_mask
block = IPAddr.new("#{start_ip}/#{mask}")
break unless block.to_range.first == start_ip
break if block.to_range.last > end_ip
best = [start_ip.to_s, mask]
mask -= 1
end
best
end
#=> :largest_block
def range_to_cidrs(start_ip, end_ip, min_mask:)
res = []
cur = start_ip
while cur <= end_ip
ip_str, mask = largest_block(cur, end_ip, min_mask)
res << [ip_str, mask]
block = IPAddr.new("#{cur}/#{mask}")
cur = IPAddr.new(block.to_range.last.to_i + 1, Socket::AF_INET)
end
res
end
#=> :range_to_cidrs
ips = ['192.168.1.0', '192.168.1.1']
#=> ["192.168.1.0", "192.168.1.1"]
raw = summarize_ips(ips)
#=> [["192.168.1.0", 31]]
cidrs_to_acl(raw)
#=> ["192.168.1.0 255.255.255.254"]
Ruby 4.0.3