1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // IP address manipulations
7 // IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
8 // An IPv4 address can be converted to an IPv6 address by
9 // adding a canonical prefix (10 zeros, 2 0xFFs).
10 // This library accepts either size of byte slice but always
11 // returns 16-byte addresses.
15 // IP address lengths (bytes).
21 // An IP is a single IP address, a slice of bytes.
22 // Functions in this package accept either 4-byte (IPv4)
23 // or 16-byte (IPv6) slices as input.
25 // Note that in this documentation, referring to an
26 // IP address as an IPv4 address or an IPv6 address
27 // is a semantic property of the address, not just the
28 // length of the byte slice: a 16-byte slice can still
29 // be an IPv4 address.
32 // An IP mask is an IP address.
35 // An IPNet represents an IP network.
37 IP IP
// network number
38 Mask IPMask
// network mask
41 // IPv4 returns the IP address (in 16-byte form) of the
42 // IPv4 address a.b.c.d.
43 func IPv4(a
, b
, c
, d
byte) IP
{
44 p
:= make(IP
, IPv6len
)
53 var v4InV6Prefix
= []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
55 // IPv4Mask returns the IP mask (in 4-byte form) of the
57 func IPv4Mask(a
, b
, c
, d
byte) IPMask
{
58 p
:= make(IPMask
, IPv4len
)
66 // CIDRMask returns an IPMask consisting of `ones' 1 bits
67 // followed by 0s up to a total length of `bits' bits.
68 // For a mask of this form, CIDRMask is the inverse of IPMask.Size.
69 func CIDRMask(ones
, bits
int) IPMask
{
70 if bits
!= 8*IPv4len
&& bits
!= 8*IPv6len
{
73 if ones
< 0 || ones
> bits
{
79 for i
:= 0; i
< l
; i
++ {
85 m
[i
] = ^byte(0xff >> n
)
91 // Well-known IPv4 addresses
93 IPv4bcast
= IPv4(255, 255, 255, 255) // broadcast
94 IPv4allsys
= IPv4(224, 0, 0, 1) // all systems
95 IPv4allrouter
= IPv4(224, 0, 0, 2) // all routers
96 IPv4zero
= IPv4(0, 0, 0, 0) // all zeros
99 // Well-known IPv6 addresses
101 IPv6zero
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
102 IPv6unspecified
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
103 IPv6loopback
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
104 IPv6interfacelocalallnodes
= IP
{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
105 IPv6linklocalallnodes
= IP
{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
106 IPv6linklocalallrouters
= IP
{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
109 // IsUnspecified returns true if ip is an unspecified address.
110 func (ip IP
) IsUnspecified() bool {
111 if ip
.Equal(IPv4zero
) || ip
.Equal(IPv6unspecified
) {
117 // IsLoopback returns true if ip is a loopback address.
118 func (ip IP
) IsLoopback() bool {
119 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 127 {
122 return ip
.Equal(IPv6loopback
)
125 // IsMulticast returns true if ip is a multicast address.
126 func (ip IP
) IsMulticast() bool {
127 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0]&0xf0 == 0xe0 {
133 // IsInterfaceLinkLocalMulticast returns true if ip is
134 // an interface-local multicast address.
135 func (ip IP
) IsInterfaceLocalMulticast() bool {
136 return len(ip
) == IPv6len
&& ip
[0] == 0xff && ip
[1]&0x0f == 0x01
139 // IsLinkLocalMulticast returns true if ip is a link-local
140 // multicast address.
141 func (ip IP
) IsLinkLocalMulticast() bool {
142 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 224 && ip4
[1] == 0 && ip4
[2] == 0 {
145 return ip
[0] == 0xff && ip
[1]&0x0f == 0x02
148 // IsLinkLocalUnicast returns true if ip is a link-local
150 func (ip IP
) IsLinkLocalUnicast() bool {
151 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 169 && ip4
[1] == 254 {
154 return ip
[0] == 0xfe && ip
[1]&0xc0 == 0x80
157 // IsGlobalUnicast returns true if ip is a global unicast
159 func (ip IP
) IsGlobalUnicast() bool {
160 return !ip
.IsUnspecified() &&
163 !ip
.IsLinkLocalUnicast()
167 func isZeros(p IP
) bool {
168 for i
:= 0; i
< len(p
); i
++ {
176 // To4 converts the IPv4 address ip to a 4-byte representation.
177 // If ip is not an IPv4 address, To4 returns nil.
178 func (ip IP
) To4() IP
{
179 if len(ip
) == IPv4len
{
182 if len(ip
) == IPv6len
&&
191 // To16 converts the IP address ip to a 16-byte representation.
192 // If ip is not an IP address (it is the wrong length), To16 returns nil.
193 func (ip IP
) To16() IP
{
194 if len(ip
) == IPv4len
{
195 return IPv4(ip
[0], ip
[1], ip
[2], ip
[3])
197 if len(ip
) == IPv6len
{
203 // Default route masks for IPv4.
205 classAMask
= IPv4Mask(0xff, 0, 0, 0)
206 classBMask
= IPv4Mask(0xff, 0xff, 0, 0)
207 classCMask
= IPv4Mask(0xff, 0xff, 0xff, 0)
210 // DefaultMask returns the default IP mask for the IP address ip.
211 // Only IPv4 addresses have default masks; DefaultMask returns
212 // nil if ip is not a valid IPv4 address.
213 func (ip IP
) DefaultMask() IPMask
{
214 if ip
= ip
.To4(); ip
== nil {
227 func allFF(b
[]byte) bool {
228 for _
, c
:= range b
{
236 // Mask returns the result of masking the IP address ip with mask.
237 func (ip IP
) Mask(mask IPMask
) IP
{
238 if len(mask
) == IPv6len
&& len(ip
) == IPv4len
&& allFF(mask
[:12]) {
241 if len(mask
) == IPv4len
&& len(ip
) == IPv6len
&& bytesEqual(ip
[:12], v4InV6Prefix
) {
249 for i
:= 0; i
< n
; i
++ {
250 out
[i
] = ip
[i
] & mask
[i
]
255 // String returns the string form of the IP address ip.
256 // If the address is an IPv4 address, the string representation
257 // is dotted decimal ("74.125.19.99"). Otherwise the representation
258 // is IPv6 ("2001:4860:0:2001::68").
259 func (ip IP
) String() string {
266 // If IPv4, use dotted notation.
267 if p4
:= p
.To4(); len(p4
) == IPv4len
{
268 return itod(uint(p4
[0])) + "." +
269 itod(uint(p4
[1])) + "." +
270 itod(uint(p4
[2])) + "." +
273 if len(p
) != IPv6len
{
277 // Find longest run of zeros.
280 for i
:= 0; i
< IPv6len
; i
+= 2 {
282 for j
< IPv6len
&& p
[j
] == 0 && p
[j
+1] == 0 {
285 if j
> i
&& j
-i
> e1
-e0
{
290 // The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field.
296 // Print with possible :: in place of run of zeros
298 for i
:= 0; i
< IPv6len
; i
+= 2 {
308 s
+= itox((uint(p
[i
])<<8)|
uint(p
[i
+1]), 1)
313 // Equal returns true if ip and x are the same IP address.
314 // An IPv4 address and that same address in IPv6 form are
315 // considered to be equal.
316 func (ip IP
) Equal(x IP
) bool {
317 if len(ip
) == len(x
) {
318 return bytesEqual(ip
, x
)
320 if len(ip
) == IPv4len
&& len(x
) == IPv6len
{
321 return bytesEqual(x
[0:12], v4InV6Prefix
) && bytesEqual(ip
, x
[12:])
323 if len(ip
) == IPv6len
&& len(x
) == IPv4len
{
324 return bytesEqual(ip
[0:12], v4InV6Prefix
) && bytesEqual(ip
[12:], x
)
329 func bytesEqual(x
, y
[]byte) bool {
330 if len(x
) != len(y
) {
333 for i
, b
:= range x
{
341 // If mask is a sequence of 1 bits followed by 0 bits,
342 // return the number of 1 bits.
343 func simpleMaskLength(mask IPMask
) int {
345 for i
, v
:= range mask
{
356 // rest must be 0 bits
360 for i
++; i
< len(mask
); i
++ {
370 // Size returns the number of leading ones and total bits in the mask.
371 // If the mask is not in the canonical form--ones followed by zeros--then
372 // Size returns 0, 0.
373 func (m IPMask
) Size() (ones
, bits
int) {
374 ones
, bits
= simpleMaskLength(m
), len(m
)*8
381 // String returns the hexadecimal form of m, with no punctuation.
382 func (m IPMask
) String() string {
384 for _
, b
:= range m
{
385 s
+= itox(uint(b
), 2)
393 func networkNumberAndMask(n
*IPNet
) (ip IP
, m IPMask
) {
394 if ip
= n
.IP
.To4(); ip
== nil {
396 if len(ip
) != IPv6len
{
403 if len(ip
) != IPv4len
{
407 if len(ip
) == IPv4len
{
416 // Contains reports whether the network includes ip.
417 func (n
*IPNet
) Contains(ip IP
) bool {
418 nn
, m
:= networkNumberAndMask(n
)
419 if x
:= ip
.To4(); x
!= nil {
426 for i
:= 0; i
< l
; i
++ {
427 if nn
[i
]&m
[i
] != ip
[i
]&m
[i
] {
434 // Network returns the address's network name, "ip+net".
435 func (n
*IPNet
) Network() string { return "ip+net" }
437 // String returns the CIDR notation of n like "192.168.100.1/24"
438 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
439 // If the mask is not in the canonical form, it returns the
440 // string which consists of an IP address, followed by a slash
441 // character and a mask expressed as hexadecimal form with no
442 // punctuation like "192.168.100.1/c000ff00".
443 func (n
*IPNet
) String() string {
444 nn
, m
:= networkNumberAndMask(n
)
445 if nn
== nil || m
== nil {
448 l
:= simpleMaskLength(m
)
450 return nn
.String() + "/" + m
.String()
452 return nn
.String() + "/" + itod(uint(l
))
455 // Parse IPv4 address (d.d.d.d).
456 func parseIPv4(s
string) IP
{
459 for j
:= 0; j
< IPv4len
; j
++ {
474 n
, i
, ok
= dtoi(s
, i
)
483 return IPv4(p
[0], p
[1], p
[2], p
[3])
486 // parseIPv6 parses s as a literal IPv6 address described in RFC 4291
487 // and RFC 5952. It can also parse a literal scoped IPv6 address with
488 // zone identifier which is described in RFC 4007 when zoneAllowed is
490 func parseIPv6(s
string, zoneAllowed
bool) (ip IP
, zone
string) {
491 ip
= make(IP
, IPv6len
)
492 ellipsis
:= -1 // position of ellipsis in p
493 i
:= 0 // index in string s
496 s
, zone
= splitHostZone(s
)
499 // Might have leading ellipsis
500 if len(s
) >= 2 && s
[0] == ':' && s
[1] == ':' {
503 // Might be only ellipsis
509 // Loop, parsing hex numbers followed by colon.
513 n
, i1
, ok
:= xtoi(s
, i
)
514 if !ok || n
> 0xFFFF {
518 // If followed by dot, might be in trailing IPv4.
519 if i1
< len(s
) && s
[i1
] == '.' {
520 if ellipsis
< 0 && j
!= IPv6len
-IPv4len
{
521 // Not the right place.
524 if j
+IPv4len
> IPv6len
{
528 ip4
:= parseIPv4(s
[i
:])
541 // Save this 16-bit chunk.
546 // Stop at end of string.
552 // Otherwise must be followed by colon and more.
553 if s
[i
] != ':' || i
+1 == len(s
) {
558 // Look for ellipsis.
560 if ellipsis
>= 0 { // already have one
564 if i
++; i
== len(s
) { // can be at end
570 // Must have used entire string.
575 // If didn't parse enough, expand ellipsis.
581 for k
:= j
- 1; k
>= ellipsis
; k
-- {
584 for k
:= ellipsis
+ n
- 1; k
>= ellipsis
; k
-- {
591 // A ParseError represents a malformed text string and the type of string that was expected.
592 type ParseError
struct {
597 func (e
*ParseError
) Error() string {
598 return "invalid " + e
.Type
+ ": " + e
.Text
601 // ParseIP parses s as an IP address, returning the result.
602 // The string s can be in dotted decimal ("74.125.19.99")
603 // or IPv6 ("2001:4860:0:2001::68") form.
604 // If s is not a valid textual representation of an IP address,
605 // ParseIP returns nil.
606 func ParseIP(s
string) IP
{
607 if ip
:= parseIPv4(s
); ip
!= nil {
610 ip
, _
:= parseIPv6(s
, false)
614 // ParseCIDR parses s as a CIDR notation IP address and mask,
615 // like "192.168.100.1/24" or "2001:DB8::/48", as defined in
616 // RFC 4632 and RFC 4291.
618 // It returns the IP address and the network implied by the IP
619 // and mask. For example, ParseCIDR("192.168.100.1/16") returns
620 // the IP address 192.168.100.1 and the network 192.168.0.0/16.
621 func ParseCIDR(s
string) (IP
, *IPNet
, error
) {
622 i
:= byteIndex(s
, '/')
624 return nil, nil, &ParseError
{"CIDR address", s
}
626 addr
, mask
:= s
[:i
], s
[i
+1:]
628 ip
:= parseIPv4(addr
)
631 ip
, _
= parseIPv6(addr
, false)
633 n
, i
, ok
:= dtoi(mask
, 0)
634 if ip
== nil ||
!ok || i
!= len(mask
) || n
< 0 || n
> 8*iplen
{
635 return nil, nil, &ParseError
{"CIDR address", s
}
637 m
:= CIDRMask(n
, 8*iplen
)
638 return ip
, &IPNet
{IP
: ip
.Mask(m
), Mask
: m
}, nil