Skip to content

net/ip: ParsePrefix with IPv6 zone should return an error #51899

Closed
@mdlayher

Description

@mdlayher

EDIT 2022-03-29: Go is documented to comply with https://www.rfc-editor.org/rfc/rfc4291.html#section-2.3 which makes no mention of IPv6 prefix + zone syntax.

Leaving the rest of this message alone for historical context.


What version of Go are you using (go version)?

Go 1.18, tip

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

linux/amd64, but n/a.

What did you do?

Attempted to parse a link-local IPv6 address prefix with zone: fe80::%2/64
https://go.dev/play/p/EeZwl0aah3q

What did you expect to see?

  • net.ParseCIDR: no error, valid *net.IPNet with zone
  • netip.ParsePrefix: no error, valid *netip.Prefix with zone

What did you see instead?

  • net.ParseCIDR: error: invalid CIDR address: fe80::%2/64
  • netip.ParsePrefix: no error, fe80::/64 returned with zone stripped

This was brought to my attention by a blog and associated thread on reddit:

https://old.reddit.com/r/golang/comments/tkf9rm/a_tiny_flaw_in_gos_netip_design/
https://adam-p.ca/blog/2022/03/go-netip-flaw/

While working on inet.af/netaddr which ultimately became net/netip, I don't believe we were able to find any evidence of an IPv6 prefix with associated zone. However, that evidence turned up today while I was doing further research:

RFC 4007: IPv6 Scoped Address Architecture, March 2005
https://datatracker.ietf.org/doc/html/rfc4007#section-11.7

[11.7] Combinations of Delimiter Characters

   There are other kinds of delimiter characters defined for IPv6
   addresses.  In this subsection, we describe how they should be
   combined with the format for non-global addresses.

   The IPv6 addressing architecture [[1](https://datatracker.ietf.org/doc/html/rfc4007#ref-1)] also defines the syntax of IPv6
   prefixes.  If the address portion of a prefix is non-global and its
   scope zone should be disambiguated, the address portion SHOULD be in
   the format.  For example, a link-local prefix fe80::/64 on the second
   link can be represented as follows:

            fe80::%2/64

Note that the prefix fe80::%2/64 should be considered valid, and thus both the current behaviors of net.ParseCIDR and netip.ParsePrefix are incorrect. I believe this was an oversight on my part during the development of inet.af/netaddr, as I was the primary user of IPv6 link-local addresses with zones. However, I have not run into a need to use IPv6 prefixes with zones as of yet.

Either way, I believe both functions should be updated to handle this case as appropriate.

In addition, RFC6874, Section 1 (https://datatracker.ietf.org/doc/html/rfc6874#section-1) says:

It should be noted that
   zone identifiers have purely local meaning within the node in which
   they are defined, often being the same as IPv6 interface names.  They
   are completely meaningless for any other node.  Today, they are
   meaningful only when attached to addresses with less than global
   scope, but it is possible that other uses might be defined in the
   future.

I don't believe the status quo has changed in the 9 years since that RFC, and would suggest that we do one of the following:

  1. parse prefix zones for any type of IPv6 address prefix (link-local is the only current "less than global scope" user, but zones could also be used for other address types later)
  2. parse prefix zones for only link-local IPv6 address prefixes; that is, if ip.IsLinkLocalUnicast() == true or IP is contained in fe80::/10

EDIT: as a data point, since net/netip already accepts the following, even given the RFC text above, I am in favor of option 1.

fmt.Println(netip.MustParseAddr("2001:db8::1%eth0"))
// 2001:db8::1%eth0

I do think this should be fixed for link-local addresses at a minimum though. If we agree this should be done, I'm happy to fix this in both net and net/netip.

/cc @bradfitz @danderson @josharian @ianlancetaylor @neild

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions