16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

IPアドレス

IPアドレスは、IPネットワーク上の情報機器を識別するために指定するネットワーク層における識別用の番号である。データリンク層のMACアドレスを物理アドレスということに対応して、論理アドレスとも呼ばれる。IPのバージョン(IPv4とIPv6)に応じて、IPv4のIPアドレス(IPv4アドレス)とIPv6のIPアドレス(IPv6アドレス)がある。

IPネットワーク上の情報機器に割り当てられるインターネット上の住所のようなもの。

アドレスプリフィックス

IPアドレスは前から何ビット目かまでの部分と残りの部分の2つに分割されます。

ネットマスク

ネットマスクにより、前から何ビット目までがネットワークのアドレスを表すかを示します。

ネットマスクが255.0.0.0 (二進数で11111111 00000000 00000000 00000000)の場合、プレフィックス長は8ビット。

ネットマスクが255.255.0.0 (二進数で11111111 11111111 00000000 00000000)の場合、プレフィックス長は16ビット。

ネットマスクが255.255.255.0 (二進数で11111111 11111111 11111111 00000000)の場合、プレフィックス長は24ビット。

CIDR記法

IPアドレスは、プレフィックス長と一緒に「a.b.c.d/プレフィックス長」と表記されることがあります。(例、192.168.1.3/24)

ですので、ネットマスクをプレフィックス長に変換したい場合もあるでしょう。

Elixirでネットマスクをプレフィックス長に変換

ElixirのIoTフレームワークであるNervesでネットマスクをプレフィックス長に変換する面白いコードがあるのでご紹介いたします。

「ネットマスクをプレフィックス長に変換する」というのは、単に前から二進数の1の数を数えるだけです。

早速IExを開きます。

iex

以下のモジュールをiexに貼り付けます。

defmodule MyIp do
  def leading_ones(ip_binary, sum \\ 0)
  def leading_ones(<<0b11111111, rest::binary>>, sum), do: leading_ones(rest, sum + 8)
  def leading_ones(<<0b11111110, _rest::binary>>, sum), do: sum + 7
  def leading_ones(<<0b11111100, _rest::binary>>, sum), do: sum + 6
  def leading_ones(<<0b11111000, _rest::binary>>, sum), do: sum + 5
  def leading_ones(<<0b11110000, _rest::binary>>, sum), do: sum + 4
  def leading_ones(<<0b11100000, _rest::binary>>, sum), do: sum + 3
  def leading_ones(<<0b11000000, _rest::binary>>, sum), do: sum + 2
  def leading_ones(<<0b10000000, _rest::binary>>, sum), do: sum + 1
  def leading_ones(_, sum), do: sum
end

遊びます。

<<255, 255, 255, 255>> |> MyIp.leading_ones()
<<255, 255, 255, 254>> |> MyIp.leading_ones()
<<255, 255, 255, 252>> |> MyIp.leading_ones()
<<255, 255, 255, 248>> |> MyIp.leading_ones()
<<255, 255, 255, 240>> |> MyIp.leading_ones()
<<255, 255, 255, 224>> |> MyIp.leading_ones()
<<255, 255, 255, 192>> |> MyIp.leading_ones()
<<255, 255, 255, 128>> |> MyIp.leading_ones()
<<255, 255, 255, 0>> |> MyIp.leading_ones()
<<255, 255, 254, 0>> |> MyIp.leading_ones()
<<255, 255, 252, 0>> |> MyIp.leading_ones()
<<255, 255, 248, 0>> |> MyIp.leading_ones()
<<255, 255, 240, 0>> |> MyIp.leading_ones()
<<255, 255, 224, 0>> |> MyIp.leading_ones()
<<255, 255, 192, 0>> |> MyIp.leading_ones()
<<255, 255, 128, 0>> |> MyIp.leading_ones()
<<255, 255, 0, 0>> |> MyIp.leading_ones()
<<255, 254, 0, 0>> |> MyIp.leading_ones()
<<255, 252, 0, 0>> |> MyIp.leading_ones()
<<255, 248, 0, 0>> |> MyIp.leading_ones()
<<255, 240, 0, 0>> |> MyIp.leading_ones()
<<255, 224, 0, 0>> |> MyIp.leading_ones()
<<255, 192, 0, 0>> |> MyIp.leading_ones()
<<255, 128, 0, 0>> |> MyIp.leading_ones()
<<255, 0, 0, 0>> |> MyIp.leading_ones()
<<254, 0, 0, 0>> |> MyIp.leading_ones()
<<252, 0, 0, 0>> |> MyIp.leading_ones()
<<248, 0, 0, 0>> |> MyIp.leading_ones()
<<240, 0, 0, 0>> |> MyIp.leading_ones()
<<224, 0, 0, 0>> |> MyIp.leading_ones()
<<192, 0, 0, 0>> |> MyIp.leading_ones()
<<128, 0, 0, 0>> |> MyIp.leading_ones()

:tada:

いろんなやり方があると思いますが、ここではバイナリデータパターンマッチが利用されています。

関数使用者のインプットを信用すれば単にリスト全体の1数えるだけでも十分かもしれませんが、プレフィックス(接頭辞)という意味を明示するために律儀に前から数えた方が良いのでしょう。

for <<bit::1 <- <<255, 128, 0, 0>> >>, reduce: 0 do
  count ->
    case bit do
      1 -> count + 1
      0 -> count
    end
end

Elixirのバイナリデータパターンマッチについては以下の記事の解説がおすすめです。

ご参考までに

16
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?