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 <lolandhold@protonmail.com>
This commit is contained in:
lolandhold 2021-03-13 22:57:05 -05:00 committed by GitHub
parent 7023938846
commit 8d4ac77138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

16
upnp.go
View File

@ -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
}
}