net/portmapper: silently handle PCP NOT_AUTHORIZED responses.
Fixes
@@ -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()
+ 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)
}
@@ -547,6 +559,7 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
pcpPort = 5351
pcpCodeOK = 0
+ pcpCodeNotAuthorized = 2
pcpOpReply = 0x80 // OR'd into request's op code on response
pcpOpAnnounce = 0
