diff --git a/internal/upnp/upnp.go b/internal/upnp/upnp.go
index a6780bce2..5d2d529c1 100644
--- a/internal/upnp/upnp.go
+++ b/internal/upnp/upnp.go
@@ -472,22 +472,12 @@ func soapRequest(url, device, function, message string) ([]byte, error) {
return resp, nil
}
-// Add a port mapping to the specified InternetGatewayDevice.
+// Add a port mapping to all relevant services on the specified InternetGatewayDevice.
+// Port mapping will fail and return an error if action is fails for _any_ of the relevant services.
+// For this reason, it is generally better to configure port mapping for each individual service instead.
func (n *IGD) AddPortMapping(protocol Protocol, externalPort, internalPort int, description string, timeout int) error {
for _, service := range n.services {
- tpl := `
-
- %d
- %s
- %d
- %s
- 1
- %s
- %d
- `
- body := fmt.Sprintf(tpl, service.serviceURN, externalPort, protocol, internalPort, n.localIPAddress, description, timeout)
-
- _, err := soapRequest(service.serviceURL, service.serviceURN, "AddPortMapping", body)
+ err := service.AddPortMapping(n.localIPAddress, protocol, externalPort, internalPort, description, timeout)
if err != nil {
return err
}
@@ -495,17 +485,12 @@ func (n *IGD) AddPortMapping(protocol Protocol, externalPort, internalPort int,
return nil
}
-// Delete a port mapping from the specified InternetGatewayDevice.
-func (n *IGD) DeletePortMapping(protocol Protocol, externalPort int) (err error) {
+// Delete a port mapping from all relevant services on the specified InternetGatewayDevice.
+// Port mapping will fail and return an error if action is fails for _any_ of the relevant services.
+// For this reason, it is generally better to configure port mapping for each individual service instead.
+func (n *IGD) DeletePortMapping(protocol Protocol, externalPort int) error {
for _, service := range n.services {
- tpl := `
-
- %d
- %s
- `
- body := fmt.Sprintf(tpl, service.serviceURN, externalPort, protocol)
-
- _, err := soapRequest(service.serviceURL, service.serviceURN, "DeletePortMapping", body)
+ err := service.DeletePortMapping(protocol, externalPort)
if err != nil {
return err
}
@@ -547,6 +532,46 @@ type getExternalIPAddressResponse struct {
NewExternalIPAddress string `xml:"NewExternalIPAddress"`
}
+// Add a port mapping to the specified IGD service.
+func (s *IGDService) AddPortMapping(localIPAddress string, protocol Protocol, externalPort, internalPort int, description string, timeout int) error {
+ tpl := `
+
+ %d
+ %s
+ %d
+ %s
+ 1
+ %s
+ %d
+ `
+ body := fmt.Sprintf(tpl, s.serviceURN, externalPort, protocol, internalPort, localIPAddress, description, timeout)
+
+ _, err := soapRequest(s.serviceURL, s.serviceURN, "AddPortMapping", body)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Delete a port mapping from the specified IGD service.
+func (s *IGDService) DeletePortMapping(protocol Protocol, externalPort int) error {
+ tpl := `
+
+ %d
+ %s
+ `
+ body := fmt.Sprintf(tpl, s.serviceURN, externalPort, protocol)
+
+ _, err := soapRequest(s.serviceURL, s.serviceURN, "DeletePortMapping", body)
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// Query the IGD service for its external IP address.
// Returns nil if the external IP address is invalid or undefined, along with any relevant errors
func (s *IGDService) GetExternalIPAddress() (net.IP, error) {