Alessio Caiazza is sharing code with you

Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.

Don't show this again

nolith / dns_gen

BIND record generator (AAAA and PTR) for IPv6

Clone this repository (size: 6.6 KB): HTTPS / SSH
hg clone https://bitbucket.org/nolith/dns_gen
hg clone ssh://hg@bitbucket.org/nolith/dns_gen

dns_gen / dns_gen.rb

Branch
default
#!/usr/bin/env ruby

## dns_gen.rb - BIND record generator (AAAA and PTR) for IPv6
## Copyright (C) 2009  Alessio Caiazza <nolith AT abisso DOT org>
## 
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.


IPV6_LEN = 39

#
# Classe per la gestione degli indirizzi IPv6
#      implementa i Range 
#
class V6Addr                
  include Comparable
  attr :addr
  attr :comp_addr
  
  def initialize(addr)
    @comp_addr = addr
    @addr = expand
  end
  
  #
  # genera l'indirizzo successivo (implementazione Range)
  #
  def succ
    splitted = @addr.split(':')
    next_addr = ''
    1.upto(8) do |i|
      fourNibble = (splitted[-i].to_i(16)+1).to_s(16)
      if fourNibble.length <= 4
        0.upto(8-i-1) { |j| next_addr << splitted[j]+':' }
        next_addr << fourNibble
        (i-1).times { next_addr << ':0000' }
        return V6Addr.new(next_addr)
      end
    end
    V6Addr.new('::0')
  end
  
  #
  # confronta due indirizzi (implementazione Range)
  #
  def <=>(other)
    @addr <=> other.addr
  end
  def to_s
    sprintf "%s #{inspect}", @addr
  end
  
  #
  # genera una stringa compatibile con un hostname
  #
  def addr_to_host(domain_pre)
    splitted = @addr.split(':')
    host = domain_pre.dup
    4.upto(7) { |i| host << '-'+splitted[i].to_i(16).to_s(16)}
    host
  end
  def expand
    V6Addr.expand_ipv6(@comp_addr)
  end
  
  # 
  #  Espande un indirizzo ipv6 dalla forma contratta alla forma estesa
  #
  def self.expand_ipv6(ip)
    low, high = ip.split("::")
    expanded = low.split(":").map{ |i| "0"*(4-i.length)+i}.join(":")
    unless high.nil?
      high = ":"+high.split(":").map{ |i| "0"*(4-i.length)+i}.join(":")
      padding = (IPV6_LEN - (expanded+high).length) / 5
      expanded = expanded + ":0000"*padding + high
    end

    return expanded 
  end
end

#
#   Genera i record AAAA per il range di indirizzi IPv6
#   fornito.
#   domain_pref viene messo come prefisso al nome di dominio
#   generato a partire dall'interface ID dell'indirizzo 
#   se self_domain è true appende al record il nome di
#   dominio completo.
#   
def gen_forward(range, domain, domain_pref, self_domain)
  puts ";  HOSTS "
  range.each do |addr|
    puts "#{addr.addr_to_host(domain_pref)}#{self_domain ? '' : '.'+domain+'.'}\t4800 IN AAAA #{addr.addr}"
  end
end

#
#   Genera i record PTR per il range di indirizzi IPv6
#   fornito.
#   I parametri domain e domain_pref hanno lo stesso significato
#   descritto nel metodo 
#   gen_forward(range, domain, domain_pref, self_domain)
#
def gen_reverse(range, domain, domain_pref)
  ip6_arpa = range.first.addr.delete(':')[0..15].reverse.split(/s*/).join('.')+'.ip6.arpa.'
  puts ";  REVERSE "
  puts "$ORIGIN #{ip6_arpa}"
  range.each do |addr|
    reverse = addr.addr.delete(':')[16..-1].reverse.split(/s*/).join('.')
    puts "#{reverse} IN PTR #{addr.addr_to_host(domain_pref)}.#{domain}."
  end
end

def main()
  if ARGV.length < 4
    puts "Wrong parameters!\nUsage:"
    puts "#{$0} 2001:db8:bear::cafe 2001:db8:bear::dead mydomain.com dhcp [--complete]"
    puts "Use --complete for appending mydomain.com. on AAAA records."
    exit 1
  end
  first_host = V6Addr.new(ARGV[0])
  last_host = V6Addr.new(ARGV[1])
  domain=ARGV[2]
  domain_pref = ARGV[3]
  self_domain = true
  if !ARGV[4].nil? && ARGV[4].eql?('--complete')
    self_domain = false
  end
  gen_forward(first_host..last_host, domain, domain_pref, self_domain)
  gen_reverse(first_host..last_host, domain, domain_pref)
end

if __FILE__ == $0
  main()
end