From 8d4ac771383f254b7a68cd89aee37e2ac19de18e Mon Sep 17 00:00:00 2001 From: lolandhold <77760965+lolandhold@users.noreply.github.com> Date: Sat, 13 Mar 2021 22:57:05 -0500 Subject: [PATCH] upnp: More accurate getOurIP. This makes getOurIP return a local IP that is on the same subnet as the serviceIP used for uPnP. Verified getOurIP doesn't return a local IPv6 IP when the serviceIP is IPv4. Didn't test with IPv6 serviceIP. Co-authored-by: lol_and_hold --- upnp.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/upnp.go b/upnp.go index a1291e48..b5cbf806 100644 --- a/upnp.go +++ b/upnp.go @@ -40,6 +40,7 @@ import ( "fmt" "net" "net/http" + "net/url" "strconv" "strings" "time" @@ -113,8 +114,9 @@ func discover(ctx context.Context) (*upnpNAT, error) { if err != nil { return nil, err } + var serviceIP string = getServiceIP(serviceURL) var ourIP string - ourIP, err = getOurIP() + ourIP, err = getOurIP(serviceIP) if err != nil { return nil, err } @@ -197,12 +199,18 @@ func getChildService(d *device, serviceType string) *service { return nil } -// getOurIP returns a best guess at what the local IP is. -func getOurIP() (ip string, err error) { +func getServiceIP(serviceURL string) (routerIP string) { + url, _ := url.Parse(serviceURL) + return url.Hostname() +} + +// getOurIP returns the local IP that is on the same subnet as the serviceIP. +func getOurIP(serviceIP string) (ip string, err error) { + _, serviceNet, _ := net.ParseCIDR(serviceIP + "/24") addrs, err := net.InterfaceAddrs() for _, addr := range addrs { ip, _, _ := net.ParseCIDR(addr.String()) - if !ip.IsLoopback() { + if serviceNet.Contains(ip) { return ip.String(), nil } }