mirror of
				https://github.com/vishvananda/netlink.git
				synced 2025-10-31 03:06:20 +08:00 
			
		
		
		
	fix prefixlen/local IP, incl. PtP addresses
From libnl addr.c comment: IPv6 sends the local address as IFA_ADDRESS with no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS with IFA_ADDRESS being the peer address if they differ But obviously, IPv6 sends IFA_LOCAL in case of PtP. From iproute2 manual: If a peer address is specified, the local address cannot have a prefix length. The network prefix is associated with the peer rather than with the local address.
This commit is contained in:
		 semicomplete
					semicomplete
				
			
				
					committed by
					
						 Vish (Ishaya) Abrams
						Vish (Ishaya) Abrams
					
				
			
			
				
	
			
			
			 Vish (Ishaya) Abrams
						Vish (Ishaya) Abrams
					
				
			
						parent
						
							7c0b5944a3
						
					
				
				
					commit
					b1cc70dea2
				
			| @@ -65,7 +65,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error | ||||
| 	msg := nl.NewIfAddrmsg(family) | ||||
| 	msg.Index = uint32(base.Index) | ||||
| 	msg.Scope = uint8(addr.Scope) | ||||
| 	prefixlen, masklen := addr.Mask.Size() | ||||
| 	mask := addr.Mask | ||||
| 	if addr.Peer != nil { | ||||
| 		mask = addr.Peer.Mask | ||||
| 	} | ||||
| 	prefixlen, masklen := mask.Size() | ||||
| 	msg.Prefixlen = uint8(prefixlen) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| @@ -107,7 +111,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error | ||||
| 		if addr.Broadcast == nil { | ||||
| 			calcBroadcast := make(net.IP, masklen/8) | ||||
| 			for i := range localAddrData { | ||||
| 				calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i] | ||||
| 				calcBroadcast[i] = localAddrData[i] | ^mask[i] | ||||
| 			} | ||||
| 			addr.Broadcast = calcBroadcast | ||||
| 		} | ||||
| @@ -206,13 +210,17 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { | ||||
| 				IP:   attr.Value, | ||||
| 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), | ||||
| 			} | ||||
| 			addr.Peer = dst | ||||
| 		case unix.IFA_LOCAL: | ||||
| 			// iproute2 manual: | ||||
| 			// If a peer address is specified, the local address | ||||
| 			// cannot have a prefix length. The network prefix is | ||||
| 			// associated with the peer rather than with the local | ||||
| 			// address. | ||||
| 			n := 8 * len(attr.Value) | ||||
| 			local = &net.IPNet{ | ||||
| 				IP:   attr.Value, | ||||
| 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), | ||||
| 				Mask: net.CIDRMask(n, n), | ||||
| 			} | ||||
| 			addr.IPNet = local | ||||
| 		case unix.IFA_BROADCAST: | ||||
| 			addr.Broadcast = attr.Value | ||||
| 		case unix.IFA_LABEL: | ||||
| @@ -226,12 +234,24 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS | ||||
| 	// libnl addr.c comment: | ||||
| 	// IPv6 sends the local address as IFA_ADDRESS with no | ||||
| 	// IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS | ||||
| 	// with IFA_ADDRESS being the peer address if they differ | ||||
| 	// | ||||
| 	// But obviously, as there are IPv6 PtP addresses, too, | ||||
| 	// IFA_LOCAL should also be handled for IPv6. | ||||
| 	if local != nil { | ||||
| 		if family == FAMILY_V4 && local.IP.Equal(dst.IP) { | ||||
| 			addr.IPNet = dst | ||||
| 		} else { | ||||
| 			addr.IPNet = local | ||||
| 			addr.Peer = dst | ||||
| 		} | ||||
| 	} else { | ||||
| 		addr.IPNet = dst | ||||
| 	} | ||||
|  | ||||
| 	addr.Scope = int(msg.Scope) | ||||
|  | ||||
| 	return | ||||
|   | ||||
| @@ -24,7 +24,7 @@ func DoTestAddr(t *testing.T, FunctionUndertest func(Link, *Addr) error) { | ||||
| 		t.Skipf("Fails in travis with: addr_test.go:68: Address flags not set properly, got=0, expected=128") | ||||
| 	} | ||||
| 	// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels? | ||||
| 	var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(24, 32)} | ||||
| 	var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(32, 32)} | ||||
| 	var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)} | ||||
| 	var addrTests = []struct { | ||||
| 		addr     *Addr | ||||
|   | ||||
		Reference in New Issue
	
	Block a user