LoginSignup
18

More than 5 years have passed since last update.

GoのnetパッケージにおけるIPアドレスの内部表現

Posted at

GoのnetパッケージにおけるIPアドレスの内部表現

GoにおけるIPアドレスの内部表現については↑のファイルの冒頭に定義と解説がある。以下抜粋。

go/src/net/ip.go
// IP address manipulations                                                                                                                                   
//                                                                                                                                                            
// IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.                                                                                                   
// An IPv4 address can be converted to an IPv6 address by                                                                                                     
// adding a canonical prefix (10 zeros, 2 0xFFs).                                                                                                             
// This library accepts either size of byte slice but always                                                                                                  
// returns 16-byte addresses.                                                                                                                                 

package net

// IP address lengths (bytes).                                                                                                                                
const (
        IPv4len = 4
        IPv6len = 16
)

// An IP is a single IP address, a slice of bytes.                                                                                                            
// Functions in this package accept either 4-byte (IPv4)                                                                                                      
// or 16-byte (IPv6) slices as input.                                                                                                                         
//                                                                                                                                                            
// Note that in this documentation, referring to an                                                                                                           
// IP address as an IPv4 address or an IPv6 address                                                                                                           
// is a semantic property of the address, not just the                                                                                                        
// length of the byte slice: a 16-byte slice can still                                                                                                        
// be an IPv4 address.                                                                                                                                        
type IP []byte

// An IP mask is an IP address.                                                                                                                               
type IPMask []byte

// An IPNet represents an IP network.                                                                                                                         
type IPNet struct {
        IP   IP     // network number                                                                                                                         
        Mask IPMask // network mask                                                                                                                           
}

GoではIPv4、IPv6アドレス共にIPという型で表現される。IPv4アドレスは4バイト、IPv6アドレスは16バイトだが、内部的にはIPv4アドレスであっても16バイトのバイト列で扱われる。

ip := net.ParseIP("8.8.8.8")
fmt.Println(len(ip)) // 16

net.ParseIP()はIPアドレスの文字列をIP型に変換する関数で、引数はIPv4、IPv6どちらのアドレスでも良い。GoのIPアドレス関連ユーティリティはこんな感じでIPv4とIPv6どちらのアドレスも一緒くたに扱うことができる。

なお、4バイトで表現されたIPv4アドレスが欲しい場合はTo4()関数を使う。

ip := net.ParseIP("8.8.8.8")
ipv4 := ip.To4()
fmt.Printf("%d.%d.%d.%d\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]) // 8.8.8.8
fmt.Println(len(ipv4)) // 4

また、16バイト表現によるIPv4アドレスはこんな感じで末尾の4バイトに実際の値が格納される。

go/src/net/ip.go
// IPv4 returns the IP address (in 16-byte form) of the                                                                                                       
// IPv4 address a.b.c.d.                                                                                                                                      
func IPv4(a, b, c, d byte) IP {
        p := make(IP, IPv6len)
        copy(p, v4InV6Prefix)
        p[12] = a
        p[13] = b
        p[14] = c
        p[15] = d
        return p
}

var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}

CIDRとサブネットマスク

10.0.0.0/24のようなCIDR表記のアドレス表現はIPNet、サブネットマスクはIPMaskで表現される。

go/src/net/ip.go
// An IP mask is an IP address.                                                                                                                               
type IPMask []byte

// An IPNet represents an IP network.                                                                                                                         
type IPNet struct {
        IP   IP     // network number                                                                                                                         
        Mask IPMask // network mask                                                                                                                           
}

CIDR表記の文字列をIPNet型に変換するにはnet.ParseCIDR()を使う。

ip, ipnet, err := net.ParseCIDR("10.0.0.0/24")
if err != nil {
        // error handling
}
fmt.Println(ipnet.IP) // 10.0.0.0
fmt.Println(ipnet.Mask) // ffffff00

これは例えば特定のIPアドレスが同じネットワークに所属しているかを調べるのに利用出来る。

_, ipnet, err := net.ParseCIDR("10.0.0.0/24")
if err != nil {
        // error handling
}
ip1 := net.ParseIP("10.0.0.1")
ip2 := net.ParseIP("10.1.0.1")
fmt.Println(ipnet.Contains(ip1)) // true
fmt.Println(ipnet.Contains(ip2)) // false

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
18