net/portmapper: silently handle PCP NOT_AUTHORIZED responses.

Fixes #1525.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson 2021-03-17 15:33:45 -07:00 committed by Dave Anderson
parent 4145bb7148
commit 6fb5d4080c

View File

@ -492,8 +492,9 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
}
buf := make([]byte, 1500)
pcpHeard := false // true when we get any PCP response
for {
if res.PCP && res.PMP && res.UPnP {
if pcpHeard && res.PMP && res.UPnP {
// Nothing more to discover.
return res, nil
}
@ -515,13 +516,24 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
}
case pcpPort: // same as pmpPort
if pres, ok := parsePCPResponse(buf[:n]); ok {
if pres.OpCode == pcpOpReply|pcpOpAnnounce && pres.ResultCode == pcpCodeOK {
c.logf("Got PCP response: epoch: %v", pres.Epoch)
res.PCP = true
if pres.OpCode == pcpOpReply|pcpOpAnnounce {
pcpHeard = true
c.mu.Lock()
c.pcpSawTime = time.Now()
c.mu.Unlock()
continue
switch pres.ResultCode {
case pcpCodeOK:
c.logf("Got PCP response: epoch: %v", pres.Epoch)
res.PCP = true
continue
case pcpCodeNotAuthorized:
// A PCP service is running, but refuses to
// provide port mapping services.
res.PCP = false
continue
default:
// Fall through to unexpected log line.
}
}
c.logf("unexpected PCP probe response: %+v", pres)
}
@ -546,7 +558,8 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
pcpVersion = 2
pcpPort = 5351
pcpCodeOK = 0
pcpCodeOK = 0
pcpCodeNotAuthorized = 2
pcpOpReply = 0x80 // OR'd into request's op code on response
pcpOpAnnounce = 0