IPアドレス計算ツール

http://www.bsddiary.net/d/200704.html#26を参考にRubyで使えるように移植してみました。んー、結構便利。
ファイル: ip.rb

#!/usr/bin/env ruby

def addrs(n)
  [
    (n >> 24) & 0xff,
    (n >> 16) & 0xff,
    (n >>  8) & 0xff,
    (n >>  0) & 0xff
  ]
end

def to_dec(n)
  addrs(n).map {|i| i.to_s }.join('.')
end

def to_hex(n)
  addrs(n).map {|i| "%02x" % i }.join(':')
end

def to_bin(n)
  addrs(n).map {|i| "%08b" % i }.join(':')
end

def calc_ip(s)
  ips, mlens = s.split(/\//)
  ip = ips.split(/\./).inject(0) {|r, n| r * 256 + n.to_i }
  if mlens.nil?
    mlen = case
           when (ip >> 24) & 0x80 == 0x00; 8
           when (ip >> 24) & 0xc0 == 0x80; 16
           when (ip >> 24) & 0xf0 == 0xc0; 24
           else; 0
           end
  else
    mlen = mlens.to_i
  end
  nmask = (0 ... mlen).inject(0) {|r, n| (1 << 31) | (r >> 1) }
  bcast = (ip & nmask) | ~nmask
  net   = ip & nmask

  [ip, mlen, nmask, bcast, net]
end

def do_ip(s)
  ip, mlen, nmask, bcast, net = calc_ip(s)
  printf "inet      %-15s %s %s\n", to_dec(ip),    to_hex(ip),    to_bin(ip)
  printf "netmask   %-15s %s %s\n", to_dec(nmask), to_hex(nmask), to_bin(nmask)
  printf "network   %-15s %s %s\n", to_dec(net),   to_hex(net),   to_bin(net)
  printf "broadcast %-15s %s %s\n", to_dec(bcast), to_hex(bcast), to_bin(bcast)
  printf "inet %s/%d netmask %s broadcast %s\n",
    to_dec(ip), mlen, to_dec(nmask), to_dec(bcast)
end

if $0 == __FILE__
  if ARGV.empty?
    $stderr.puts "usage: ip ipv4_addr[/mask]"
    exit 1
  end
  ARGV.each {|s| do_ip(s) }
end

実行例:

> ruby ip.rb 192.168.113.45/28
inet      192.168.113.45  c0:a8:71:2d 11000000:10101000:01110001:00101101
netmask   255.255.255.240 ff:ff:ff:f0 11111111:11111111:11111111:11110000
network   192.168.113.32  c0:a8:71:20 11000000:10101000:01110001:00100000
broadcast 192.168.113.47  c0:a8:71:2f 11000000:10101000:01110001:00101111
inet 192.168.113.45/28 netmask 255.255.255.240 broadcast 192.168.113.47