Skip to content

IPv4-mapped IPv6 address cannot be used as route gateway #1114

@3u13r

Description

@3u13r

Netlink still makes use of Golang's net package, instead of the newer netip package to represent prefixes and addresses. In multiple instances netlink checks if a user-given address is a IPv4 or an IPv6 address via nl.GetIPFamily(). This function calls ip.To4() and if this returns anything other than nil we identify ip to be a IPv4 address. The problem is that the function contract is not that .To4 returns not-nil for IPv4 addresses but it returns non-nil if the address can be represented as IPv4. The second definition includes IPv4-mapped IPv6 addresses, while the first does not.

Example:
I want to create the following route entry:

2300:5800:ab00::2 via ::ffff:100.95.128.2 dev br3 proto bgp onlink 

With ip one can do this by calling:

ip route add 2300:5800:ab00::2 via ::ffff:100.95.128.2 dev br3 proto bgp onlink

One would assume that the following Go code works:

nlh.RouteAdd(
			&netlink.Route{
				LinkIndex: remoteBridge.Attrs().Index,	// some index
				Dst:       route.Dst,					// 2300:5800:ab00::2/128
				Gw:        hostAddress.AsSlice(),		//::ffff:100.95.128.2
				Flags:     int(unix.RTNH_F_ONLINK),		// onlink
				Protocol:  186,							// bgp
			},
		)

But it returns gateway, source, and destination ip are not the same IP family since it translates the Gw to an IPv4 first. Moreover, there's no way to override this interpretation with e.g., another Family field.

Note that this behavior exists in multiple places around the code and not only in nl.GetIPFamily(). For example, in neighHandle() there's an direct call to .To4 to again decide if an address is a IPv4 or IPv6.

related issue: #908

Interestingly, changing Gw with a Via struct also doesn't work:

nlh.RouteAdd(
			&netlink.Route{
				LinkIndex: remoteBridge.Attrs().Index,	// some index
				Dst:       route.Dst,					// 2300:5800:ab00::2/128
				Via: &netlink.Via{
					AddrFamily: netlink.FAMILY_V6,
					Addr:       hostAddress.AsSlice(), //::ffff:100.95.128.2
				},	
				Flags:     int(unix.RTNH_F_ONLINK),		// onlink
				Protocol:  186,							// bgp
			},
		)

As this returns invalid argument. Though I haven't debugged the reason for this one yet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions