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.
17 // IP address lengths (bytes).
23 // An IP is a single IP address, a slice of bytes.
24 // Functions in this package accept either 4-byte (IPv4)
25 // or 16-byte (IPv6) slices as input.
27 // Note that in this documentation, referring to an
28 // IP address as an IPv4 address or an IPv6 address
29 // is a semantic property of the address, not just the
30 // length of the byte slice: a 16-byte slice can still
31 // be an IPv4 address.
34 // An IP mask is an IP address.
37 // An IPNet represents an IP network.
39 IP IP
// network number
40 Mask IPMask
// network mask
43 // IPv4 returns the IP address (in 16-byte form) of the
44 // IPv4 address a.b.c.d.
45 func IPv4(a
, b
, c
, d
byte) IP
{
46 p
:= make(IP
, IPv6len
)
55 var v4InV6Prefix
= []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
57 // IPv4Mask returns the IP mask (in 4-byte form) of the
59 func IPv4Mask(a
, b
, c
, d
byte) IPMask
{
60 p
:= make(IPMask
, IPv4len
)
68 // CIDRMask returns an IPMask consisting of `ones' 1 bits
69 // followed by 0s up to a total length of `bits' bits.
70 // For a mask of this form, CIDRMask is the inverse of IPMask.Size.
71 func CIDRMask(ones
, bits
int) IPMask
{
72 if bits
!= 8*IPv4len
&& bits
!= 8*IPv6len
{
75 if ones
< 0 || ones
> bits
{
81 for i
:= 0; i
< l
; i
++ {
87 m
[i
] = ^byte(0xff >> n
)
93 // Well-known IPv4 addresses
95 IPv4bcast
= IPv4(255, 255, 255, 255) // broadcast
96 IPv4allsys
= IPv4(224, 0, 0, 1) // all systems
97 IPv4allrouter
= IPv4(224, 0, 0, 2) // all routers
98 IPv4zero
= IPv4(0, 0, 0, 0) // all zeros
101 // Well-known IPv6 addresses
103 IPv6zero
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
104 IPv6unspecified
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
105 IPv6loopback
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
106 IPv6interfacelocalallnodes
= IP
{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
107 IPv6linklocalallnodes
= IP
{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
108 IPv6linklocalallrouters
= IP
{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
111 // IsUnspecified returns true if ip is an unspecified address.
112 func (ip IP
) IsUnspecified() bool {
113 if ip
.Equal(IPv4zero
) || ip
.Equal(IPv6unspecified
) {
119 // IsLoopback returns true if ip is a loopback address.
120 func (ip IP
) IsLoopback() bool {
121 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 127 {
124 return ip
.Equal(IPv6loopback
)
127 // IsMulticast returns true if ip is a multicast address.
128 func (ip IP
) IsMulticast() bool {
129 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0]&0xf0 == 0xe0 {
135 // IsInterfaceLinkLocalMulticast returns true if ip is
136 // an interface-local multicast address.
137 func (ip IP
) IsInterfaceLocalMulticast() bool {
138 return len(ip
) == IPv6len
&& ip
[0] == 0xff && ip
[1]&0x0f == 0x01
141 // IsLinkLocalMulticast returns true if ip is a link-local
142 // multicast address.
143 func (ip IP
) IsLinkLocalMulticast() bool {
144 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 224 && ip4
[1] == 0 && ip4
[2] == 0 {
147 return ip
[0] == 0xff && ip
[1]&0x0f == 0x02
150 // IsLinkLocalUnicast returns true if ip is a link-local
152 func (ip IP
) IsLinkLocalUnicast() bool {
153 if ip4
:= ip
.To4(); ip4
!= nil && ip4
[0] == 169 && ip4
[1] == 254 {
156 return ip
[0] == 0xfe && ip
[1]&0xc0 == 0x80
159 // IsGlobalUnicast returns true if ip is a global unicast
161 func (ip IP
) IsGlobalUnicast() bool {
162 return !ip
.IsUnspecified() &&
165 !ip
.IsLinkLocalUnicast()
169 func isZeros(p IP
) bool {
170 for i
:= 0; i
< len(p
); i
++ {
178 // To4 converts the IPv4 address ip to a 4-byte representation.
179 // If ip is not an IPv4 address, To4 returns nil.
180 func (ip IP
) To4() IP
{
181 if len(ip
) == IPv4len
{
184 if len(ip
) == IPv6len
&&
193 // To16 converts the IP address ip to a 16-byte representation.
194 // If ip is not an IP address (it is the wrong length), To16 returns nil.
195 func (ip IP
) To16() IP
{
196 if len(ip
) == IPv4len
{
197 return IPv4(ip
[0], ip
[1], ip
[2], ip
[3])
199 if len(ip
) == IPv6len
{
205 // Default route masks for IPv4.
207 classAMask
= IPv4Mask(0xff, 0, 0, 0)
208 classBMask
= IPv4Mask(0xff, 0xff, 0, 0)
209 classCMask
= IPv4Mask(0xff, 0xff, 0xff, 0)
212 // DefaultMask returns the default IP mask for the IP address ip.
213 // Only IPv4 addresses have default masks; DefaultMask returns
214 // nil if ip is not a valid IPv4 address.
215 func (ip IP
) DefaultMask() IPMask
{
216 if ip
= ip
.To4(); ip
== nil {
229 func allFF(b
[]byte) bool {
230 for _
, c
:= range b
{
238 // Mask returns the result of masking the IP address ip with mask.
239 func (ip IP
) Mask(mask IPMask
) IP
{
240 if len(mask
) == IPv6len
&& len(ip
) == IPv4len
&& allFF(mask
[:12]) {
243 if len(mask
) == IPv4len
&& len(ip
) == IPv6len
&& bytesEqual(ip
[:12], v4InV6Prefix
) {
251 for i
:= 0; i
< n
; i
++ {
252 out
[i
] = ip
[i
] & mask
[i
]
257 // String returns the string form of the IP address ip.
258 // If the address is an IPv4 address, the string representation
259 // is dotted decimal ("74.125.19.99"). Otherwise the representation
260 // is IPv6 ("2001:4860:0:2001::68").
261 func (ip IP
) String() string {
268 // If IPv4, use dotted notation.
269 if p4
:= p
.To4(); len(p4
) == IPv4len
{
270 return itod(uint(p4
[0])) + "." +
271 itod(uint(p4
[1])) + "." +
272 itod(uint(p4
[2])) + "." +
275 if len(p
) != IPv6len
{
279 // Find longest run of zeros.
282 for i
:= 0; i
< IPv6len
; i
+= 2 {
284 for j
< IPv6len
&& p
[j
] == 0 && p
[j
+1] == 0 {
287 if j
> i
&& j
-i
> e1
-e0
{
293 // The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field.
299 const maxLen
= len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
300 b
:= make([]byte, 0, maxLen
)
302 // Print with possible :: in place of run of zeros
303 for i
:= 0; i
< IPv6len
; i
+= 2 {
305 b
= append(b
, ':', ':')
313 b
= appendHex(b
, (uint32(p
[i
])<<8)|
uint32(p
[i
+1]))
318 // ipEmptyString is like ip.String except that it returns
319 // an empty string when ip is unset.
320 func ipEmptyString(ip IP
) string {
327 // MarshalText implements the encoding.TextMarshaler interface.
328 // The encoding is the same as returned by String.
329 func (ip IP
) MarshalText() ([]byte, error
) {
331 return []byte(""), nil
333 if len(ip
) != IPv4len
&& len(ip
) != IPv6len
{
334 return nil, errors
.New("invalid IP address")
336 return []byte(ip
.String()), nil
339 // UnmarshalText implements the encoding.TextUnmarshaler interface.
340 // The IP address is expected in a form accepted by ParseIP.
341 func (ip
*IP
) UnmarshalText(text
[]byte) error
{
349 return &ParseError
{"IP address", s
}
355 // Equal returns true if ip and x are the same IP address.
356 // An IPv4 address and that same address in IPv6 form are
357 // considered to be equal.
358 func (ip IP
) Equal(x IP
) bool {
359 if len(ip
) == len(x
) {
360 return bytesEqual(ip
, x
)
362 if len(ip
) == IPv4len
&& len(x
) == IPv6len
{
363 return bytesEqual(x
[0:12], v4InV6Prefix
) && bytesEqual(ip
, x
[12:])
365 if len(ip
) == IPv6len
&& len(x
) == IPv4len
{
366 return bytesEqual(ip
[0:12], v4InV6Prefix
) && bytesEqual(ip
[12:], x
)
371 func bytesEqual(x
, y
[]byte) bool {
372 if len(x
) != len(y
) {
375 for i
, b
:= range x
{
383 // If mask is a sequence of 1 bits followed by 0 bits,
384 // return the number of 1 bits.
385 func simpleMaskLength(mask IPMask
) int {
387 for i
, v
:= range mask
{
398 // rest must be 0 bits
402 for i
++; i
< len(mask
); i
++ {
412 // Size returns the number of leading ones and total bits in the mask.
413 // If the mask is not in the canonical form--ones followed by zeros--then
414 // Size returns 0, 0.
415 func (m IPMask
) Size() (ones
, bits
int) {
416 ones
, bits
= simpleMaskLength(m
), len(m
)*8
423 // String returns the hexadecimal form of m, with no punctuation.
424 func (m IPMask
) String() string {
428 buf
:= make([]byte, len(m
)*2)
429 for i
, b
:= range m
{
430 buf
[i
*2], buf
[i
*2+1] = hexDigit
[b
>>4], hexDigit
[b
&0xf]
435 func networkNumberAndMask(n
*IPNet
) (ip IP
, m IPMask
) {
436 if ip
= n
.IP
.To4(); ip
== nil {
438 if len(ip
) != IPv6len
{
445 if len(ip
) != IPv4len
{
449 if len(ip
) == IPv4len
{
458 // Contains reports whether the network includes ip.
459 func (n
*IPNet
) Contains(ip IP
) bool {
460 nn
, m
:= networkNumberAndMask(n
)
461 if x
:= ip
.To4(); x
!= nil {
468 for i
:= 0; i
< l
; i
++ {
469 if nn
[i
]&m
[i
] != ip
[i
]&m
[i
] {
476 // Network returns the address's network name, "ip+net".
477 func (n
*IPNet
) Network() string { return "ip+net" }
479 // String returns the CIDR notation of n like "192.168.100.1/24"
480 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
481 // If the mask is not in the canonical form, it returns the
482 // string which consists of an IP address, followed by a slash
483 // character and a mask expressed as hexadecimal form with no
484 // punctuation like "192.168.100.1/c000ff00".
485 func (n
*IPNet
) String() string {
486 nn
, m
:= networkNumberAndMask(n
)
487 if nn
== nil || m
== nil {
490 l
:= simpleMaskLength(m
)
492 return nn
.String() + "/" + m
.String()
494 return nn
.String() + "/" + itod(uint(l
))
497 // Parse IPv4 address (d.d.d.d).
498 func parseIPv4(s
string) IP
{
501 for j
:= 0; j
< IPv4len
; j
++ {
516 n
, i
, ok
= dtoi(s
, i
)
525 return IPv4(p
[0], p
[1], p
[2], p
[3])
528 // parseIPv6 parses s as a literal IPv6 address described in RFC 4291
529 // and RFC 5952. It can also parse a literal scoped IPv6 address with
530 // zone identifier which is described in RFC 4007 when zoneAllowed is
532 func parseIPv6(s
string, zoneAllowed
bool) (ip IP
, zone
string) {
533 ip
= make(IP
, IPv6len
)
534 ellipsis
:= -1 // position of ellipsis in p
535 i
:= 0 // index in string s
538 s
, zone
= splitHostZone(s
)
541 // Might have leading ellipsis
542 if len(s
) >= 2 && s
[0] == ':' && s
[1] == ':' {
545 // Might be only ellipsis
551 // Loop, parsing hex numbers followed by colon.
555 n
, i1
, ok
:= xtoi(s
, i
)
556 if !ok || n
> 0xFFFF {
560 // If followed by dot, might be in trailing IPv4.
561 if i1
< len(s
) && s
[i1
] == '.' {
562 if ellipsis
< 0 && j
!= IPv6len
-IPv4len
{
563 // Not the right place.
566 if j
+IPv4len
> IPv6len
{
570 ip4
:= parseIPv4(s
[i
:])
583 // Save this 16-bit chunk.
588 // Stop at end of string.
594 // Otherwise must be followed by colon and more.
595 if s
[i
] != ':' || i
+1 == len(s
) {
600 // Look for ellipsis.
602 if ellipsis
>= 0 { // already have one
606 if i
++; i
== len(s
) { // can be at end
612 // Must have used entire string.
617 // If didn't parse enough, expand ellipsis.
623 for k
:= j
- 1; k
>= ellipsis
; k
-- {
626 for k
:= ellipsis
+ n
- 1; k
>= ellipsis
; k
-- {
629 } else if ellipsis
>= 0 {
630 // Ellipsis must represent at least one 0 group.
636 // A ParseError represents a malformed text string and the type of string that was expected.
637 type ParseError
struct {
642 func (e
*ParseError
) Error() string {
643 return "invalid " + e
.Type
+ ": " + e
.Text
646 // ParseIP parses s as an IP address, returning the result.
647 // The string s can be in dotted decimal ("74.125.19.99")
648 // or IPv6 ("2001:4860:0:2001::68") form.
649 // If s is not a valid textual representation of an IP address,
650 // ParseIP returns nil.
651 func ParseIP(s
string) IP
{
652 for i
:= 0; i
< len(s
); i
++ {
657 ip
, _
:= parseIPv6(s
, false)
664 // ParseCIDR parses s as a CIDR notation IP address and mask,
665 // like "192.168.100.1/24" or "2001:DB8::/48", as defined in
666 // RFC 4632 and RFC 4291.
668 // It returns the IP address and the network implied by the IP
669 // and mask. For example, ParseCIDR("192.168.100.1/16") returns
670 // the IP address 192.168.100.1 and the network 192.168.0.0/16.
671 func ParseCIDR(s
string) (IP
, *IPNet
, error
) {
672 i
:= byteIndex(s
, '/')
674 return nil, nil, &ParseError
{"CIDR address", s
}
676 addr
, mask
:= s
[:i
], s
[i
+1:]
678 ip
:= parseIPv4(addr
)
681 ip
, _
= parseIPv6(addr
, false)
683 n
, i
, ok
:= dtoi(mask
, 0)
684 if ip
== nil ||
!ok || i
!= len(mask
) || n
< 0 || n
> 8*iplen
{
685 return nil, nil, &ParseError
{"CIDR address", s
}
687 m
:= CIDRMask(n
, 8*iplen
)
688 return ip
, &IPNet
{IP
: ip
.Mask(m
), Mask
: m
}, nil