dcreager / libcork

A simple, easily embeddable cross-platform C library
https://libcork.io/
BSD 3-Clause "New" or "Revised" License
371 stars 107 forks source link

Rendering IPv6 containing an IPv4 address #83

Open JohnMcHugh opened 10 years ago

JohnMcHugh commented 10 years ago

cork_ipv6_to_raw_string() is incomplete in its handling of IPv6 addresses that contain IPv4 addresses as their low order 32 bits. The RFCs that I have found address a total of 5 cases, the first 2 of which are covered by the existing code:

  1. Prefix of ::/96 IPv4-compatible (RFC 1933)
  2. Prefix of ::ffff:0:0/96 IPv4-mapped (RFC 2765)
  3. Prefix of ::ffff:0:0:0/96 IPv4-translated (RFC 2765)
  4. Prefix of 64:ff9b::\96 IPv4-embeded (RFC 6052) 5: Automatic tunneling per RFC 5214. This starts with an arbitrary 64 bit routing prefix followed by :X:00:5efe: and the IPv4 address, where X has the hex representation of

    a. 0 indicating a local, individual IPv4 address b. 100 indicating a local, group IPv4 address c. 200 indicating a global, individual IPv4 address d. 300 indicating a global, group IPv4 address

The code should be extended to cover the additional forms. It may be useful to make the presentation of the IPv4 address in dotted form optional given the advice of RFC 5952 which covers the representation of IPv6 addresses as text.

Addresses such as IPv4-Mapped IPv6 addresses, ISATAP [RFC5214], and IPv4-translatable addresses [ADDR-FORMAT] have IPv4 addresses embedded in the low-order 32 bits of the address. These addresses have a special representation that may mix hexadecimal and dot decimal notations. The decimal notation may be used only for the last 32 bits of the address. For these addresses, mixed notation is RECOMMENDED if the following condition is met: the address can be distinguished as having IPv4 addresses embedded in the lower 32 bits solely from the address field through the use of a well-known prefix. Such prefixes are defined in [RFC4291] and [RFC2765] at the time of this writing. If it is known by some external method that a given prefix is used to embed IPv4, it MAY be represented as mixed notation. Tools that provide options to specify prefixes that are (or are not) to be represented as mixed notation may be useful.

There is a trade-off here where a recommendation to achieve an exact match in a search (no dot decimals whatsoever) and a recommendation to help the readability of an address (dot decimal whenever possible) does not result in the same solution. The above recommendation is aimed at fixing the representation as much as possible while leaving the opportunity for future well-known prefixes to be represented in a human-friendly manner as tools adjust to newly assigned prefixes.

JohnMcHugh commented 10 years ago

I have found a few dark corners of the IP address space where the cork rendering of IPv6 addresses containing IPv4 addresses is wrong and two where the result is dubious.

First the dubious cases.

  1. 0:0:0:0:0:0:0:0 is a special IPv6 address, but is is also an IPv4 compatible IPv6 address under rfc 1993 Libcork renders it as ::, but successfully parses ::0.0.0.0 and it might be possible to render :: this way, as well.
  2. The same applies to 0:0:0:0:0:0:0:1 which is also special and is rendered as ::1 but could be rendered as ::0.0.0.1

There is a class of cases where libcork renders IPv6 addresses conforming to rfc 1993 incorrectly.

  1. Addresses with the prefix ::/96 are IPv4 compatible under rfc 1993 and should be rendered as ::W.X.Y.Z, however, if the W and X octets are zero, the first hextet of the IPv4 address is subsumed into the :: i.e. ::0.0.1.0 renders as ::100.

This can probably be fixed by adding an additional branch for a best.len of 7 along with the existing tests for a best.len of 6 and 5 with the ffff 6th hextet. If the dubious case of ::1 is to be resolved as a non IPv4, this will also require special handling.

As noted in the issue, the code does not handle the IPv4 translated form of RFC 2765 ::ffff:0/96, the IPv4 embedded form of RFC 6052 64:ff9b::/96, or the tunneling forms of RFC 5214.