net/portmapper: retry UPnP when we get an "Invalid Args"

We previously retried getting a UPnP mapping when the device returned
error code 725, "OnlyPermanentLeasesSupported". However, we've seen
devices in the wild also return 402, "Invalid Args", when given a lease
duration. Fall back to the no-duration mapping method in these cases.

Updates #15223

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I6a25007c9eeac0dac83750dd3ae9bfcc287c8fcf
This commit is contained in:
Andrew Dunham
2025-03-06 21:00:18 -05:00
parent a4b8c24834
commit 5177fd2ccb
2 changed files with 110 additions and 2 deletions

View File

@@ -610,8 +610,9 @@ func (c *Client) tryUPnPPortmapWithDevice(
}
// From the UPnP spec: http://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v2-Service.pdf
// 402: Invalid Args (see: https://github.com/tailscale/tailscale/issues/15223)
// 725: OnlyPermanentLeasesSupported
if ok && code == 725 {
if ok && (code == 402 || code == 725) {
newPort, err = addAnyPortMapping(
ctx,
client,
@@ -620,7 +621,7 @@ func (c *Client) tryUPnPPortmapWithDevice(
internal.Addr().String(),
0, // permanent
)
c.vlogf("addAnyPortMapping: 725 retry %v, err=%q", newPort, err)
c.vlogf("addAnyPortMapping: errcode=%d retried: port=%v err=%v", code, newPort, err)
}
}
if err != nil {