MCPcopy
hub / github.com/tailscale/tailscale / PeerForIP

Method PeerForIP

wgengine/userspace.go:1540–1603  ·  view source on GitHub ↗

PeerForIP returns the Node in the wireguard config that's responsible for handling the given IP address. If none is found in the wireguard config but one is found in the netmap, it's described in an error. peerForIP acquires both e.mu and e.wgLock, but neither at the same time.

(ip netip.Addr)

Source from the content-addressed store, hash-verified

1538// peerForIP acquires both e.mu and e.wgLock, but neither at the same
1539// time.
1540func (e *userspaceEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) {
1541 e.mu.Lock()
1542 nm := e.netMap
1543 e.mu.Unlock()
1544
1545 if !ip.IsValid() {
1546 // Treat invalid IPs as just a mutex probe to detect deadlocks.
1547 // TODO(bradfitz): extend the Engine interface to have an explicit method for
1548 // this purpose, instead of overloading PeerForIP with this special case.
1549 // But I'd rather do that at the beginning of a dev cycle.
1550 e.wgLock.Lock()
1551 defer e.wgLock.Unlock()
1552 return ret, false
1553 }
1554
1555 if nm == nil {
1556 return ret, false
1557 }
1558
1559 // Check for exact matches before looking for subnet matches.
1560 // TODO(bradfitz): add maps for these. on NetworkMap?
1561 for _, p := range nm.Peers {
1562 for i := range p.Addresses().Len() {
1563 a := p.Addresses().At(i)
1564 if a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
1565 return PeerForIP{Node: p, Route: a}, true
1566 }
1567 }
1568 }
1569 addrs := nm.GetAddresses()
1570 for i := range addrs.Len() {
1571 if a := addrs.At(i); a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
1572 return PeerForIP{Node: nm.SelfNode, IsSelf: true, Route: a}, true
1573 }
1574 }
1575
1576 e.wgLock.Lock()
1577 defer e.wgLock.Unlock()
1578
1579 // TODO(bradfitz): this is O(n peers). Add ART to netaddr?
1580 var best netip.Prefix
1581 var bestKey key.NodePublic
1582 for _, p := range e.lastCfgFull.Peers {
1583 for _, cidr := range p.AllowedIPs {
1584 if !cidr.Contains(ip) {
1585 continue
1586 }
1587 if !best.IsValid() || cidr.Bits() > best.Bits() {
1588 best = cidr
1589 bestKey = p.PublicKey
1590 }
1591 }
1592 }
1593 // And another pass. Probably better than allocating a map per peerForIP
1594 // call. But TODO(bradfitz): add a lookup map to netmap.NetworkMap.
1595 if !bestKey.IsZero() {
1596 for _, p := range nm.Peers {
1597 if p.Key() == bestKey {

Callers 4

isOSNetworkProbeMethod · 0.95
onOpenTimeoutMethod · 0.95
NewUserspaceEngineFunction · 0.95
PingMethod · 0.95

Calls 12

IsZeroMethod · 0.95
IsTailscaleIPFunction · 0.92
AddressesMethod · 0.80
GetAddressesMethod · 0.80
LockMethod · 0.65
UnlockMethod · 0.65
LenMethod · 0.65
KeyMethod · 0.65
IsValidMethod · 0.45
AtMethod · 0.45
AddrMethod · 0.45
ContainsMethod · 0.45

Tested by

no test coverage detected