ipaddress.rb

Heads up: This description was created by AI and might not be 100% accurate.

このRubyスクリプトは、IPアドレスとサブネットマスクを扱うためのユーティリティ関数群です。それぞれの関数は、IPアドレスやサブネットマスクの検証、CIDR表記からマスク表記への変換、マスク表記からCIDR表記への変換などの処理を行います。

1. mask_to_cidr(mask)

2. cidr_to_mask(cidr)

3. ip_address?(ip)

4. subnet_mask?(mask)

5. network_address?(ip, mask)

Ruby code snippet

# frozen_string_literal: true
#=> nil

def mask_to_cidr(mask)
  # count num of 1.
  mask.split('.').sum { it.to_i.to_s(2).count('1') }
end
#=> :mask_to_cidr

p mask_to_cidr('255.255.255.0')
24
#=> 24

def cidr_to_mask(cidr)
  # Repeat '1' cidr times and then pad with '0's to make 32 bits.
  bits = '1' * cidr + '0' * (32 - cidr)
  # split into chunks of 8 characters.
  bits.scan(/.{8}/).map { it.to_i(2) }.join('.')
end
#=> :cidr_to_mask

p cidr_to_mask(24)
"255.255.255.0"
#=> "255.255.255.0"

def ip_address?(ip)
  parts = ip.split('.')
  return false unless parts.size == 4

  parts.all? do |p|
      return false unless p =~ /^\d+$/
  
      num = p.to_i
      return false if num.negative? || num > 255
      return false if p != num.to_s # 先頭ゼロ防止
  
      true
  end
end
#=> :ip_address?

p ip_address?('127.0.0.1')
true
#=> true

def subnet_mask?(mask)
  parts = mask.split('.')
  return false unless parts.size == 4

  binary = ''
  parts.each do |p|
      return false unless p =~ /^\d+$/
  
      num = p.to_i
      return false if num.negative? || num > 255
  
      binary += num.to_s(2).rjust(8, '0')
  end
  # 1の後に0が続く形式のみ許可
  return false if binary.include?('01')
  # 全0 or 全1は除外
  return false if binary == '0' * 32 || binary == '1' * 32

  true
end
#=> :subnet_mask?

p subnet_mask?('255.0.0.0')
true
#=> true

def network_address?(ip, mask)
  return false unless ip_address?(ip)
  return false unless subnet_mask?(mask)

  ip_parts   = ip.split('.').map(&:to_i)
  mask_parts = mask.split('.').map(&:to_i)

  4.times do |i|
      # ホスト部が0かチェック
      return false if (ip_parts[i] & (~mask_parts[i] & 0xFF)) != 0
  end

  true
end
#=> :network_address?
p network_address?('10.0.0.0', cidr_to_mask(16))
true
#=> true

Executed with Ruby 3.4.9.