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
{
292 // The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field.
298 // Print with possible :: in place of run of zeros
300 for i
:= 0; i
< IPv6len
; i
+= 2 {
310 s
+= itox((uint(p
[i
])<<8)|
uint(p
[i
+1]), 1)
315 // ipEmptyString is like ip.String except that it returns
316 // an empty string when ip is unset.
317 func ipEmptyString(ip IP
) string {
324 // MarshalText implements the encoding.TextMarshaler interface.
325 // The encoding is the same as returned by String.
326 func (ip IP
) MarshalText() ([]byte, error
) {
328 return []byte(""), nil
330 if len(ip
) != IPv4len
&& len(ip
) != IPv6len
{
331 return nil, errors
.New("invalid IP address")
333 return []byte(ip
.String()), nil
336 // UnmarshalText implements the encoding.TextUnmarshaler interface.
337 // The IP address is expected in a form accepted by ParseIP.
338 func (ip
*IP
) UnmarshalText(text
[]byte) error
{
346 return &ParseError
{"IP address", s
}
352 // Equal returns true if ip and x are the same IP address.
353 // An IPv4 address and that same address in IPv6 form are
354 // considered to be equal.
355 func (ip IP
) Equal(x IP
) bool {
356 if len(ip
) == len(x
) {
357 return bytesEqual(ip
, x
)
359 if len(ip
) == IPv4len
&& len(x
) == IPv6len
{
360 return bytesEqual(x
[0:12], v4InV6Prefix
) && bytesEqual(ip
, x
[12:])
362 if len(ip
) == IPv6len
&& len(x
) == IPv4len
{
363 return bytesEqual(ip
[0:12], v4InV6Prefix
) && bytesEqual(ip
[12:], x
)
368 func bytesEqual(x
, y
[]byte) bool {
369 if len(x
) != len(y
) {
372 for i
, b
:= range x
{
380 // If mask is a sequence of 1 bits followed by 0 bits,
381 // return the number of 1 bits.
382 func simpleMaskLength(mask IPMask
) int {
384 for i
, v
:= range mask
{
395 // rest must be 0 bits
399 for i
++; i
< len(mask
); i
++ {
409 // Size returns the number of leading ones and total bits in the mask.
410 // If the mask is not in the canonical form--ones followed by zeros--then
411 // Size returns 0, 0.
412 func (m IPMask
) Size() (ones
, bits
int) {
413 ones
, bits
= simpleMaskLength(m
), len(m
)*8
420 // String returns the hexadecimal form of m, with no punctuation.
421 func (m IPMask
) String() string {
423 for _
, b
:= range m
{
424 s
+= itox(uint(b
), 2)
432 func networkNumberAndMask(n
*IPNet
) (ip IP
, m IPMask
) {
433 if ip
= n
.IP
.To4(); ip
== nil {
435 if len(ip
) != IPv6len
{
442 if len(ip
) != IPv4len
{
446 if len(ip
) == IPv4len
{
455 // Contains reports whether the network includes ip.
456 func (n
*IPNet
) Contains(ip IP
) bool {
457 nn
, m
:= networkNumberAndMask(n
)
458 if x
:= ip
.To4(); x
!= nil {
465 for i
:= 0; i
< l
; i
++ {
466 if nn
[i
]&m
[i
] != ip
[i
]&m
[i
] {
473 // Network returns the address's network name, "ip+net".
474 func (n
*IPNet
) Network() string { return "ip+net" }
476 // String returns the CIDR notation of n like "192.168.100.1/24"
477 // or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
478 // If the mask is not in the canonical form, it returns the
479 // string which consists of an IP address, followed by a slash
480 // character and a mask expressed as hexadecimal form with no
481 // punctuation like "192.168.100.1/c000ff00".
482 func (n
*IPNet
) String() string {
483 nn
, m
:= networkNumberAndMask(n
)
484 if nn
== nil || m
== nil {
487 l
:= simpleMaskLength(m
)
489 return nn
.String() + "/" + m
.String()
491 return nn
.String() + "/" + itod(uint(l
))
494 // Parse IPv4 address (d.d.d.d).
495 func parseIPv4(s
string) IP
{
498 for j
:= 0; j
< IPv4len
; j
++ {
513 n
, i
, ok
= dtoi(s
, i
)
522 return IPv4(p
[0], p
[1], p
[2], p
[3])
525 // parseIPv6 parses s as a literal IPv6 address described in RFC 4291
526 // and RFC 5952. It can also parse a literal scoped IPv6 address with
527 // zone identifier which is described in RFC 4007 when zoneAllowed is
529 func parseIPv6(s
string, zoneAllowed
bool) (ip IP
, zone
string) {
530 ip
= make(IP
, IPv6len
)
531 ellipsis
:= -1 // position of ellipsis in p
532 i
:= 0 // index in string s
535 s
, zone
= splitHostZone(s
)
538 // Might have leading ellipsis
539 if len(s
) >= 2 && s
[0] == ':' && s
[1] == ':' {
542 // Might be only ellipsis
548 // Loop, parsing hex numbers followed by colon.
552 n
, i1
, ok
:= xtoi(s
, i
)
553 if !ok || n
> 0xFFFF {
557 // If followed by dot, might be in trailing IPv4.
558 if i1
< len(s
) && s
[i1
] == '.' {
559 if ellipsis
< 0 && j
!= IPv6len
-IPv4len
{
560 // Not the right place.
563 if j
+IPv4len
> IPv6len
{
567 ip4
:= parseIPv4(s
[i
:])
580 // Save this 16-bit chunk.
585 // Stop at end of string.
591 // Otherwise must be followed by colon and more.
592 if s
[i
] != ':' || i
+1 == len(s
) {
597 // Look for ellipsis.
599 if ellipsis
>= 0 { // already have one
603 if i
++; i
== len(s
) { // can be at end
609 // Must have used entire string.
614 // If didn't parse enough, expand ellipsis.
620 for k
:= j
- 1; k
>= ellipsis
; k
-- {
623 for k
:= ellipsis
+ n
- 1; k
>= ellipsis
; k
-- {
626 } else if ellipsis
>= 0 {
627 // Ellipsis must represent at least one 0 group.
633 // A ParseError represents a malformed text string and the type of string that was expected.
634 type ParseError
struct {
639 func (e
*ParseError
) Error() string {
640 return "invalid " + e
.Type
+ ": " + e
.Text
643 // ParseIP parses s as an IP address, returning the result.
644 // The string s can be in dotted decimal ("74.125.19.99")
645 // or IPv6 ("2001:4860:0:2001::68") form.
646 // If s is not a valid textual representation of an IP address,
647 // ParseIP returns nil.
648 func ParseIP(s
string) IP
{
649 if ip
:= parseIPv4(s
); ip
!= nil {
652 ip
, _
:= parseIPv6(s
, false)
656 // ParseCIDR parses s as a CIDR notation IP address and mask,
657 // like "192.168.100.1/24" or "2001:DB8::/48", as defined in
658 // RFC 4632 and RFC 4291.
660 // It returns the IP address and the network implied by the IP
661 // and mask. For example, ParseCIDR("192.168.100.1/16") returns
662 // the IP address 192.168.100.1 and the network 192.168.0.0/16.
663 func ParseCIDR(s
string) (IP
, *IPNet
, error
) {
664 i
:= byteIndex(s
, '/')
666 return nil, nil, &ParseError
{"CIDR address", s
}
668 addr
, mask
:= s
[:i
], s
[i
+1:]
670 ip
:= parseIPv4(addr
)
673 ip
, _
= parseIPv6(addr
, false)
675 n
, i
, ok
:= dtoi(mask
, 0)
676 if ip
== nil ||
!ok || i
!= len(mask
) || n
< 0 || n
> 8*iplen
{
677 return nil, nil, &ParseError
{"CIDR address", s
}
679 m
:= CIDRMask(n
, 8*iplen
)
680 return ip
, &IPNet
{IP
: ip
.Mask(m
), Mask
: m
}, nil