From 1f9df061aa80e6c058ddefb86528a37272dac5ca Mon Sep 17 00:00:00 2001 From: mwnx Date: Mon, 28 May 2018 00:57:53 +0200 Subject: [PATCH 1/2] Add "zone" multiaddr (IPv6 zone) See [rfc4007]. Can be prefixed to "ip6" like so: /zone/eth0/ip6/fe80::1 This corresponds to the rfc4007 address `fe80::1%eth0` [rfc4007] https://tools.ietf.org/html/rfc4007 --- multiaddr_test.go | 36 ++++++++++++++++++++++++++++++++++++ protocols.go | 40 +++++++++++++++++++++++++--------------- transcoders.go | 15 +++++++++++++++ 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/multiaddr_test.go b/multiaddr_test.go index 59e50c4..2cb0cb7 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -23,6 +23,9 @@ func TestConstructFails(t *testing.T) { "/ip4/::1", "/ip4/fdpsofodsajfdoisa", "/ip6", + "/ip6zone", + "/ip6zone/", + "/ip6zone//ip6/fe80::1", "/udp", "/tcp", "/sctp", @@ -65,6 +68,10 @@ func TestConstructSucceeds(t *testing.T) { "/ip6/::1", "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21", "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/udp/1234/quic", + "/ip6zone/x/ip6/fe80::1", + "/ip6zone/x%y/ip6/fe80::1", + "/ip6zone/x%y/ip6/::", + "/ip6zone/x/ip6/fe80::1/udp/1234/quic", "/onion/timaq4ygg2iegci7:1234", "/onion/timaq4ygg2iegci7:80/http", "/udp/0", @@ -492,3 +499,32 @@ func TestInvalidP2PAddr(t *testing.T) { _ = ma.String() } } + +func TestZone(t *testing.T) { + ip6String := "/ip6zone/eth0/ip6/::1" + ip6Bytes := []byte{ + 0x2a, 4, + 'e', 't', 'h', '0', + 0x29, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + } + + ma, err := NewMultiaddr(ip6String) + if err != nil { + t.Error(err) + } + if !bytes.Equal(ma.Bytes(), ip6Bytes) { + t.Errorf("expected %x, got %x", ip6Bytes, ma.Bytes()) + } + + ma2, err2 := NewMultiaddrBytes(ip6Bytes) + if err2 != nil { + t.Error(err) + } + if ma2.String() != ip6String { + t.Errorf("expected %s, got %s", ip6String, ma2.String()) + } +} diff --git a/protocols.go b/protocols.go index bc123a7..d466598 100644 --- a/protocols.go +++ b/protocols.go @@ -6,21 +6,22 @@ package multiaddr // TODO: Use a single source of truth for all multicodecs instead of // distributing them like this... const ( - P_IP4 = 0x0004 - P_TCP = 0x0006 - P_UDP = 0x0111 - P_DCCP = 0x0021 - P_IP6 = 0x0029 - P_QUIC = 0x01CC - P_SCTP = 0x0084 - P_UDT = 0x012D - P_UTP = 0x012E - P_UNIX = 0x0190 - P_P2P = 0x01A5 - P_IPFS = 0x01A5 // alias for backwards compatability - P_HTTP = 0x01E0 - P_HTTPS = 0x01BB - P_ONION = 0x01BC + P_IP4 = 0x0004 + P_TCP = 0x0006 + P_UDP = 0x0111 + P_DCCP = 0x0021 + P_IP6 = 0x0029 + P_IP6ZONE = 0x002A + P_QUIC = 0x01CC + P_SCTP = 0x0084 + P_UDT = 0x012D + P_UTP = 0x012E + P_UNIX = 0x0190 + P_P2P = 0x01A5 + P_IPFS = 0x01A5 // alias for backwards compatability + P_HTTP = 0x01E0 + P_HTTPS = 0x01BB + P_ONION = 0x01BC ) var ( @@ -64,6 +65,14 @@ var ( Transcoder: TranscoderIP6, } // these require varint + protoIP6ZONE = Protocol{ + Name: "ip6zone", + Code: P_IP6ZONE, + VCode: CodeToVarint(P_IP6ZONE), + Size: LengthPrefixedVarSize, + Path: false, + Transcoder: TranscoderIP6Zone, + } protoSCTP = Protocol{ Name: "sctp", Code: P_SCTP, @@ -127,6 +136,7 @@ func init() { protoUDP, protoDCCP, protoIP6, + protoIP6ZONE, protoSCTP, protoONION, protoUTP, diff --git a/transcoders.go b/transcoders.go index 7e31afa..fe64f50 100644 --- a/transcoders.go +++ b/transcoders.go @@ -47,6 +47,7 @@ func (t twrp) ValidateBytes(b []byte) error { var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ipBtS, nil) var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ipBtS, nil) +var TranscoderIP6Zone = NewTranscoderFromFunctions(ip6zoneStB, ip6zoneBtS, nil) func ip4StB(s string) ([]byte, error) { i := net.ParseIP(s).To4() @@ -56,6 +57,20 @@ func ip4StB(s string) ([]byte, error) { return i, nil } +func ip6zoneStB(s string) ([]byte, error) { + if len(s) == 0 { + return nil, fmt.Errorf("empty ip6zone") + } + return []byte(s), nil +} + +func ip6zoneBtS(b []byte) (string, error) { + if len(b) == 0 { + return "", fmt.Errorf("invalid length (should be > 0)") + } + return string(b), nil +} + func ip6StB(s string) ([]byte, error) { i := net.ParseIP(s).To16() if i == nil { From 6f084e635db20f9fea84654af9cba6f48d8cebf5 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 14 Sep 2018 18:51:03 -0700 Subject: [PATCH 2/2] validate ipv6 zone --- transcoders.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/transcoders.go b/transcoders.go index fe64f50..3aef4a2 100644 --- a/transcoders.go +++ b/transcoders.go @@ -1,6 +1,7 @@ package multiaddr import ( + "bytes" "encoding/base32" "encoding/binary" "fmt" @@ -47,7 +48,7 @@ func (t twrp) ValidateBytes(b []byte) error { var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ipBtS, nil) var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ipBtS, nil) -var TranscoderIP6Zone = NewTranscoderFromFunctions(ip6zoneStB, ip6zoneBtS, nil) +var TranscoderIP6Zone = NewTranscoderFromFunctions(ip6zoneStB, ip6zoneBtS, ip6zoneVal) func ip4StB(s string) ([]byte, error) { i := net.ParseIP(s).To4() @@ -71,6 +72,14 @@ func ip6zoneBtS(b []byte) (string, error) { return string(b), nil } +func ip6zoneVal(b []byte) error { + // Not supported as this would break multiaddrs. + if bytes.IndexByte(b, '/') >= 0 { + return fmt.Errorf("IPv6 zone ID contains '/': %s", string(b)) + } + return nil +} + func ip6StB(s string) ([]byte, error) { i := net.ParseIP(s).To16() if i == nil {