@ -805,11 +805,10 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
continue
continue
}
}
ip = ip . Unmap ( )
ip = ip . Unmap ( )
port := uint16 ( addr . ( * net . UDPAddr ) . Port )
switch port {
handleUPnPResponse := func ( ) {
case c . upnpPort ( ) :
metricUPnPResponse . Add ( 1 )
metricUPnPResponse . Add ( 1 )
if mem . Contains ( mem . B ( buf [ : n ] ) , mem . S ( ":InternetGatewayDevice:" ) ) {
if ip != gw {
if ip != gw {
// https://github.com/tailscale/tailscale/issues/5502
// https://github.com/tailscale/tailscale/issues/5502
c . logf ( "UPnP discovery response from %v, but gateway IP is %v" , ip , gw )
c . logf ( "UPnP discovery response from %v, but gateway IP is %v" , ip , gw )
@ -818,7 +817,7 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
if err != nil {
if err != nil {
metricUPnPParseErr . Add ( 1 )
metricUPnPParseErr . Add ( 1 )
c . logf ( "unrecognized UPnP discovery response; ignoring: %v" , err )
c . logf ( "unrecognized UPnP discovery response; ignoring: %v" , err )
continue
return
}
}
metricUPnPOK . Add ( 1 )
metricUPnPOK . Add ( 1 )
c . logf ( "[v1] UPnP reply %+v, %q" , meta , buf [ : n ] )
c . logf ( "[v1] UPnP reply %+v, %q" , meta , buf [ : n ] )
@ -832,6 +831,22 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
}
}
c . mu . Unlock ( )
c . mu . Unlock ( )
}
}
port := uint16 ( addr . ( * net . UDPAddr ) . Port )
switch port {
case c . upnpPort ( ) :
if mem . Contains ( mem . B ( buf [ : n ] ) , mem . S ( ":InternetGatewayDevice:" ) ) {
handleUPnPResponse ( )
}
default :
// https://github.com/tailscale/tailscale/issues/7377
if mem . Contains ( mem . B ( buf [ : n ] ) , mem . S ( ":InternetGatewayDevice:" ) ) {
c . logf ( "UPnP discovery response from non-UPnP port %d" , port )
metricUPnPResponseAlternatePort . Add ( 1 )
handleUPnPResponse ( )
}
case c . pxpPort ( ) : // same value for PMP and PCP
case c . pxpPort ( ) : // same value for PMP and PCP
metricPXPResponse . Add ( 1 )
metricPXPResponse . Add ( 1 )
if pres , ok := parsePCPResponse ( buf [ : n ] ) ; ok {
if pres , ok := parsePCPResponse ( buf [ : n ] ) ; ok {
@ -983,6 +998,10 @@ var (
// metricUPnPResponse counts the number of times we received a UPnP response.
// metricUPnPResponse counts the number of times we received a UPnP response.
metricUPnPResponse = clientmetric . NewCounter ( "portmap_upnp_response" )
metricUPnPResponse = clientmetric . NewCounter ( "portmap_upnp_response" )
// metricUPnPResponseAlternatePort counts the number of times we
// received a UPnP response from a port other than the UPnP port.
metricUPnPResponseAlternatePort = clientmetric . NewCounter ( "portmap_upnp_response_alternate_port" )
// metricUPnPParseErr counts the number of times we failed to parse a UPnP response.
// metricUPnPParseErr counts the number of times we failed to parse a UPnP response.
metricUPnPParseErr = clientmetric . NewCounter ( "portmap_upnp_parse_err" )
metricUPnPParseErr = clientmetric . NewCounter ( "portmap_upnp_parse_err" )