net/portmapper: send discovery packet for IGD specifically.

There appear to be devices out there which send only their
first descriptor in response to a discovery packet for
`ssdp:all`, for example the Sagemcom FAST3890V3 only sends
urn:schemas-wifialliance-org:device:WFADevice:1

Send both ssdp:all and a discovery frame for
InternetGatewayDevice specifically.

Updates https://github.com/tailscale/tailscale/issues/3557

Signed-off-by: Denton Gentry <dgentry@tailscale.com>
This commit is contained in:
Denton Gentry 2022-06-11 12:02:01 -07:00 committed by Denton Gentry
parent 09eaba91ad
commit d7f452c0a1

View File

@ -749,9 +749,16 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
// See https://github.com/tailscale/tailscale/issues/3197 for // See https://github.com/tailscale/tailscale/issues/3197 for
// an example of a device that strictly implements UPnP, and // an example of a device that strictly implements UPnP, and
// only responds to multicast queries. // only responds to multicast queries.
//
// Then we send a discovery packet looking for
// urn:schemas-upnp-org:device:InternetGatewayDevice:1 specifically, not
// just ssdp:all, because there appear to be devices which only send
// their first descriptor (like urn:schemas-wifialliance-org:device:WFADevice:1)
// in response to ssdp:all. https://github.com/tailscale/tailscale/issues/3557
metricUPnPSent.Add(1) metricUPnPSent.Add(1)
uc.WriteTo(uPnPPacket, upnpAddr) uc.WriteTo(uPnPPacket, upnpAddr)
uc.WriteTo(uPnPPacket, upnpMulticastAddr) uc.WriteTo(uPnPPacket, upnpMulticastAddr)
uc.WriteTo(uPnPIGDPacket, upnpMulticastAddr)
} }
buf := make([]byte, 1500) buf := make([]byte, 1500)
@ -877,6 +884,15 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
"MAN: \"ssdp:discover\"\r\n" + "MAN: \"ssdp:discover\"\r\n" +
"MX: 2\r\n\r\n") "MX: 2\r\n\r\n")
// Send a discovery frame for InternetGatewayDevice, since some devices respond
// to ssdp:all with only their first descriptor (which is often not IGD).
// https://github.com/tailscale/tailscale/issues/3557
var uPnPIGDPacket = []byte("M-SEARCH * HTTP/1.1\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" +
"MAN: \"ssdp:discover\"\r\n" +
"MX: 2\r\n\r\n")
// PCP/PMP metrics // PCP/PMP metrics
var ( var (
// metricPXPResponse counts the number of times we received a PMP/PCP response. // metricPXPResponse counts the number of times we received a PMP/PCP response.