|
1 | 1 | package manet
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "bytes" |
| 4 | + "net" |
5 | 5 |
|
6 | 6 | ma "github.com/multiformats/go-multiaddr"
|
7 | 7 | )
|
|
24 | 24 | IP6Unspecified = ma.StringCast("/ip6/::")
|
25 | 25 | )
|
26 | 26 |
|
27 |
| -// Loopback multiaddr prefixes. Any multiaddr beginning with one of the |
28 |
| -// following byte sequences is considered a loopback multiaddr. |
29 |
| -var loopbackPrefixes = [][]byte{ |
30 |
| - {ma.P_IP4, 127}, // 127.* |
31 |
| - {ma.P_IP6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 127}, // ::ffff:127.* |
32 |
| - IP6Loopback.Bytes(), // ::1 |
33 |
| -} |
34 |
| - |
35 | 27 | // IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
|
36 | 28 | // This means: /{IP4, IP6}[/{TCP, UDP}]
|
37 | 29 | func IsThinWaist(m ma.Multiaddr) bool {
|
@@ -62,22 +54,41 @@ func IsThinWaist(m ma.Multiaddr) bool {
|
62 | 54 | // IsIPLoopback returns whether a Multiaddr is a "Loopback" IP address
|
63 | 55 | // This means either /ip4/127.*.*.*, /ip6/::1, or /ip6/::ffff:127.*.*.*.*
|
64 | 56 | func IsIPLoopback(m ma.Multiaddr) bool {
|
65 |
| - b := m.Bytes() |
66 |
| - for _, prefix := range loopbackPrefixes { |
67 |
| - if bytes.HasPrefix(b, prefix) { |
68 |
| - return true |
69 |
| - } |
| 57 | + c, rest := ma.SplitFirst(m) |
| 58 | + if rest != nil { |
| 59 | + // Not *just* an IPv4 addr |
| 60 | + return false |
| 61 | + } |
| 62 | + switch c.Protocol().Code { |
| 63 | + case ma.P_IP4, ma.P_IP6: |
| 64 | + return net.IP(c.RawValue()).IsLoopback() |
70 | 65 | }
|
71 | 66 | return false
|
72 | 67 | }
|
73 | 68 |
|
74 |
| -// IsIP6LinkLocal returns if a multiaddress is an IPv6 local link. These |
75 |
| -// addresses are non routable. The prefix is technically |
76 |
| -// fe80::/10, but we test fe80::/16 for simplicity (no need to mask). |
77 |
| -// So far, no hardware interfaces exist long enough to use those 2 bits. |
78 |
| -// Send a PR if there is. |
| 69 | +// IsIP6LinkLocal returns if a an IPv6 link-local multiaddress (with zero or |
| 70 | +// more leading zones). These addresses are non routable. |
79 | 71 | func IsIP6LinkLocal(m ma.Multiaddr) bool {
|
80 |
| - return bytes.HasPrefix(m.Bytes(), []byte{ma.P_IP6, 0xfe, 0x80}) |
| 72 | + matched := false |
| 73 | + ma.ForEach(m, func(c ma.Component) bool { |
| 74 | + // Too much. |
| 75 | + if matched { |
| 76 | + matched = false |
| 77 | + return false |
| 78 | + } |
| 79 | + |
| 80 | + switch c.Protocol().Code { |
| 81 | + case ma.P_IP6ZONE: |
| 82 | + return true |
| 83 | + case ma.P_IP6: |
| 84 | + ip := net.IP(c.RawValue()) |
| 85 | + matched = ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() |
| 86 | + return true |
| 87 | + default: |
| 88 | + return false |
| 89 | + } |
| 90 | + }) |
| 91 | + return matched |
81 | 92 | }
|
82 | 93 |
|
83 | 94 | // IsIPUnspecified returns whether a Multiaddr is am Unspecified IP address
|
|
0 commit comments