upnp: extending the cram tests

Added extended cram tests for UPnP port mapping.

References: PCF-1998

Signed-off-by: Volodymyr Martysh <v.martysh@inango-systems.com>
This commit is contained in:
Volodymyr Martysh 2025-10-03 22:00:13 +03:00 committed by Matthias Franck
parent 69835b433d
commit b0ee814f61
7 changed files with 638 additions and 2 deletions

View File

@ -47,7 +47,8 @@ RUN pip3 install \
humanize \
jira \
'marshmallow<3.0.0' \
pyjwt
pyjwt \
async-upnp-client
ENV TMATE_VERSION=2.4.0
ENV TMATE_SHA256SUM=6e503a1a3b0f9117bce6ff7cc30cf61bdc79e9b32d074cf96deb0264e067a60d

View File

@ -46,7 +46,7 @@ Check that miniupnpd is disabled and not running:
{}
{"amxd-error-code":0}
$ R "netstat -tulpn 2>&1 | grep miniupnpd"
$ R "netstat -tulpn | grep miniupnpd"
[1]
Enable miniupnpd:

View File

@ -0,0 +1,150 @@
Index continuity for NAT rules (UPNPIGD_0036)
Install upnp-client (Installing via Dockerfile does not work):
$ pip install async-upnp-client >/dev/null 2>&1
$ export PATH="$PATH:$HOME/.local/bin"
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
upnp-client definitions:
$ export SCHEMA_DEVICE_IGDv2='urn:schemas-upnp-org:device:InternetGatewayDevice:2'
$ export CLIENT_IP="$(ip -4 route get "192.168.1.1" 2>/dev/null | sed -n 's/.* src \([0-9.]*\).*/\1/p')"
$ disc_igd_desc() { upnp-client search --target 192.168.1.1 | jq "select(.ST==\"$SCHEMA_DEVICE_IGDv2\")" | jq -rs ".[0].LOCATION"; }
Allow Reserved WAN IP Addresses:
$ R "ba-cli 'Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1'" | grep -v '^>'
Device.UPnP.X_PRPLWARE-COM_IGDConfig.
Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1
$ sleep 3
Verify UPnP IGD is present in the network:
$ upnp-client search --target 192.168.1.1 | jq -r '.ST' | grep urn | uniq
urn:schemas-upnp-org:device:InternetGatewayDevice:2
urn:schemas-upnp-org:device:WANConnectionDevice:2
urn:schemas-upnp-org:device:WANDevice:2
urn:schemas-upnp-org:service:WANIPConnection:2
urn:schemas-upnp-org:service:DeviceProtection:1
urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
urn:schemas-upnp-org:service:Layer3Forwarding:1
Ged Description URL:
$ export DESC_URL=$(disc_igd_desc)
Check there are no NAT PortMapping rules:
$ R "ba-cli 'Device.NAT.PortMapping.?'" | grep -v '^>'
No data found
Create NAT PortMapping rules:
$ R "ba-cli 'Device.NAT.PortMapping.+{Alias=testrule1,Enable=1,Interface=Device.IP.Interface.2,Origin=UPnP,RemoteHost=1.1.1.1,ExternalPort=12345,InternalPort=12345,InternalClient=192.168.1.123}'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Device.NAT.PortMapping.X.Alias="testrule1"
Device.NAT.PortMapping.X.ExternalPort=12345
Device.NAT.PortMapping.X.Protocol="TCP"
Device.NAT.PortMapping.X.RemoteHost="1.1.1.1"
$ R "ba-cli 'Device.NAT.PortMapping.+{Alias=testrule2,Enable=1,Interface=Device.IP.Interface.2,Origin=UPnP,RemoteHost=1.1.1.1,ExternalPort=23456,InternalPort=23456,InternalClient=192.168.1.123}'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Device.NAT.PortMapping.X.Alias="testrule2"
Device.NAT.PortMapping.X.ExternalPort=23456
Device.NAT.PortMapping.X.Protocol="TCP"
Device.NAT.PortMapping.X.RemoteHost="1.1.1.1"
$ R "ba-cli 'Device.NAT.PortMapping.+{Alias=testrule3,Enable=1,Interface=Device.IP.Interface.2,Origin=UPnP,RemoteHost=1.1.1.1,ExternalPort=34567,InternalPort=34567,InternalClient=192.168.1.123}'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Device.NAT.PortMapping.X.Alias="testrule3"
Device.NAT.PortMapping.X.ExternalPort=34567
Device.NAT.PortMapping.X.Protocol="TCP"
Device.NAT.PortMapping.X.RemoteHost="1.1.1.1"
$ R "ba-cli 'Device.NAT.PortMapping.+{Alias=testrule4,Enable=1,Interface=Device.IP.Interface.2,Origin=Controller,RemoteHost=1.1.1.1,ExternalPort=45678,InternalPort=45678,InternalClient=192.168.1.123}'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Device.NAT.PortMapping.X.Alias="testrule4"
Device.NAT.PortMapping.X.ExternalPort=45678
Device.NAT.PortMapping.X.Protocol="TCP"
Device.NAT.PortMapping.X.RemoteHost="1.1.1.1"
Delete the second NAT PortMapping rules:
$ R "ba-cli 'Device.NAT.PortMapping.testrule2.-'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Rtrieve NAT PortMapping with index 0:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=0 | jq 'del(.timestamp, .service_id, .service_type)'
{
"action": "GetGenericPortMappingEntry",
"in_parameters": {
"NewPortMappingIndex": 0
},
"out_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 12345,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewInternalClient": "192.168.1.123",
"NewEnabled": true,
"NewPortMappingDescription": "",
"NewLeaseDuration": 0
}
}
Rtrieve NAT PortMapping with index 1:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=1 | jq 'del(.timestamp, .service_id, .service_type)'
{
"action": "GetGenericPortMappingEntry",
"in_parameters": {
"NewPortMappingIndex": 1
},
"out_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 34567,
"NewProtocol": "TCP",
"NewInternalPort": 34567,
"NewInternalClient": "192.168.1.123",
"NewEnabled": true,
"NewPortMappingDescription": "",
"NewLeaseDuration": 0
}
}
Retrieve NAT PortMapping with index 2:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=2 2>/dev/null
[1]
Retrieve NAT PortMapping with index 3:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=3 2>/dev/null
[1]
Clean up:
$ R "ba-cli 'Device.NAT.PortMapping.testrule1.-'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
$ R "ba-cli 'Device.NAT.PortMapping.testrule3.-'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
$ R "ba-cli 'Device.NAT.PortMapping.testrule4.-'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.

View File

@ -0,0 +1,108 @@
GetGenericPortMappingEntry action (UPNPIGD_0038)
Install upnp-client (Installing via Dockerfile does not work):
$ pip install async-upnp-client >/dev/null 2>&1
$ export PATH="$PATH:$HOME/.local/bin"
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
upnp-client definitions:
$ export SCHEMA_DEVICE_IGDv2='urn:schemas-upnp-org:device:InternetGatewayDevice:2'
$ export CLIENT_IP="$(ip -4 route get "192.168.1.1" 2>/dev/null | sed -n 's/.* src \([0-9.]*\).*/\1/p')"
$ disc_igd_desc() { upnp-client search --target 192.168.1.1 | jq "select(.ST==\"$SCHEMA_DEVICE_IGDv2\")" | jq -rs ".[0].LOCATION"; }
Allow Reserved WAN IP Addresses:
$ R "ba-cli 'Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1'" | grep -v '^>'
Device.UPnP.X_PRPLWARE-COM_IGDConfig.
Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1
$ sleep 3
Verify UPnP IGD is present in the network:
$ upnp-client search --target 192.168.1.1 | jq -r '.ST' | grep urn | uniq
urn:schemas-upnp-org:device:InternetGatewayDevice:2
urn:schemas-upnp-org:device:WANConnectionDevice:2
urn:schemas-upnp-org:device:WANDevice:2
urn:schemas-upnp-org:service:WANIPConnection:2
urn:schemas-upnp-org:service:DeviceProtection:1
urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
urn:schemas-upnp-org:service:Layer3Forwarding:1
Ged Description URL:
$ export DESC_URL=$(disc_igd_desc)
Check there are no NAT PortMapping rules:
$ R "ba-cli 'Device.NAT.PortMapping.?'" | grep -v '^>'
No data found
Create 1 NAT PortMapping rule with non-UPnP origin:
$ R "ba-cli 'Device.NAT.PortMapping.+{Alias=testrule1,Enable=1,Interface=Device.IP.Interface.2,Origin=Controller,RemoteHost=1.1.1.1,ExternalPort=12345,InternalPort=12345,InternalClient=192.168.1.123}'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
Device.NAT.PortMapping.X.Alias="testrule1"
Device.NAT.PortMapping.X.ExternalPort=12345
Device.NAT.PortMapping.X.Protocol="TCP"
Device.NAT.PortMapping.X.RemoteHost="1.1.1.1"
Retrieve NAT PortMapping with index 0:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=0 2>/dev/null
[1]
Add port mapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=2.2.2.2 NewExternalPort=23456 NewProtocol=TCP NewInternalPort=23456 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddPortMapping",
"in_parameters": {
"NewRemoteHost": "2.2.2.2",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 23456,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {}
}
Rtrieve NAT PortMapping with index 0:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetGenericPortMappingEntry NewPortMappingIndex=1 | jq 'del(.timestamp, .service_id, .service_type, .out_parameters.NewInternalClient)'
{
"action": "GetGenericPortMappingEntry",
"in_parameters": {
"NewPortMappingIndex": 1
},
"out_parameters": {
"NewRemoteHost": "2.2.2.2",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 23456,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
}
}
Clean up:
$ R "ba-cli 'Device.NAT.PortMapping.testrule1.-'" | grep -v '^>' | sed -E 's/\.PortMapping\.[0-9]+\./.PortMapping.X./'
Device.NAT.PortMapping.X.
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=2.2.2.2 NewExternalPort=23456 NewProtocol=TCP >/dev/null

View File

@ -0,0 +1,137 @@
Allowed values for NewRemoteHost parameter of AddPortMapping and AddAnyPortMapping action (UPNPIGD_0039)
Install upnp-client (Installing via Dockerfile does not work):
$ pip install async-upnp-client >/dev/null 2>&1
$ export PATH="$PATH:$HOME/.local/bin"
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
upnp-client definitions:
$ export SCHEMA_DEVICE_IGDv2='urn:schemas-upnp-org:device:InternetGatewayDevice:2'
$ export CLIENT_IP="$(ip -4 route get "192.168.1.1" 2>/dev/null | sed -n 's/.* src \([0-9.]*\).*/\1/p')"
$ disc_igd_desc() { upnp-client search --target 192.168.1.1 | jq "select(.ST==\"$SCHEMA_DEVICE_IGDv2\")" | jq -rs ".[0].LOCATION"; }
Allow Reserved WAN IP Addresses:
$ R "ba-cli 'Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1'" | grep -v '^>'
Device.UPnP.X_PRPLWARE-COM_IGDConfig.
Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1
$ sleep 3
Verify UPnP IGD is present in the network:
$ upnp-client search --target 192.168.1.1 | jq -r '.ST' | grep urn | uniq
urn:schemas-upnp-org:device:InternetGatewayDevice:2
urn:schemas-upnp-org:device:WANConnectionDevice:2
urn:schemas-upnp-org:device:WANDevice:2
urn:schemas-upnp-org:service:WANIPConnection:2
urn:schemas-upnp-org:service:DeviceProtection:1
urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
urn:schemas-upnp-org:service:Layer3Forwarding:1
Ged Description URL:
$ export DESC_URL=$(disc_igd_desc)
Add port mapping with wildcard RemoteHost with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost="" NewExternalPort=12345 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddPortMapping",
"in_parameters": {
"NewRemoteHost": "",
"NewExternalPort": 12345,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {}
}
Add port mapping with RemoteHost as IP address with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP NewInternalPort=23456 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 23456,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {}
}
Add port mapping with RemoteHost as hostname with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=example NewExternalPort=34567 NewProtocol=TCP NewInternalPort=34567 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
600
Clean up:
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost="" NewExternalPort=12345 NewProtocol=TCP >/dev/null
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP >/dev/null
Add port mapping with wildcard RemoteHost with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost="" NewExternalPort=12345 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddAnyPortMapping",
"in_parameters": {
"NewRemoteHost": "",
"NewExternalPort": 12345,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {
"NewReservedPort": 12345
}
}
Add port mapping with RemoteHost as IP address with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP NewInternalPort=23456 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddAnyPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 23456,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {
"NewReservedPort": 23456
}
}
Add port mapping with RemoteHost as hostname with AddAnyPortMapping:
$ upnp-client call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=example.com NewExternalPort=34567 NewProtocol=TCP NewInternalPort=34567 NewInternalClient=$CLEINT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
715
Clean up
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost="" NewExternalPort=12345 NewProtocol=TCP >/dev/null
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP >/dev/null

View File

@ -0,0 +1,117 @@
Allowed values for NewInternalPort parameter of AddPortMapping and AddAnyPortMapping actions (UPNPIGD_0041)
Install upnp-client (Installing via Dockerfile does not work):
$ pip install async-upnp-client >/dev/null 2>&1
$ export PATH="$PATH:$HOME/.local/bin"
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
upnp-client definitions:
$ export SCHEMA_DEVICE_IGDv2='urn:schemas-upnp-org:device:InternetGatewayDevice:2'
$ export CLIENT_IP="$(ip -4 route get "192.168.1.1" 2>/dev/null | sed -n 's/.* src \([0-9.]*\).*/\1/p')"
$ disc_igd_desc() { upnp-client search --target 192.168.1.1 | jq "select(.ST==\"$SCHEMA_DEVICE_IGDv2\")" | jq -rs ".[0].LOCATION"; }
Allow Reserved WAN IP Addresses:
$ R "ba-cli 'Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1'" | grep -v '^>'
Device.UPnP.X_PRPLWARE-COM_IGDConfig.
Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1
$ sleep 3
Verify UPnP IGD is present in the network:
$ upnp-client search --target 192.168.1.1 | jq -r '.ST' | grep urn | uniq
urn:schemas-upnp-org:device:InternetGatewayDevice:2
urn:schemas-upnp-org:device:WANConnectionDevice:2
urn:schemas-upnp-org:device:WANDevice:2
urn:schemas-upnp-org:service:WANIPConnection:2
urn:schemas-upnp-org:service:DeviceProtection:1
urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
urn:schemas-upnp-org:service:Layer3Forwarding:1
Ged Description URL:
$ export DESC_URL=$(disc_igd_desc)
Add port mapping with InternalPort=0 with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=0 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
732
Add port mapping with InternalPort=1 with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=1 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
606
Add port mapping with InternalPort=1023 with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=1023 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
606
Add port mapping with InternalPort=12345 with AddPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {}
}
Clean up:
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP >/dev/null
Add port mapping with InternalPort=0 with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=0 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
732
Add port mapping with InternalPort=1 with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=1 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
606
Add port mapping with InternalPort=1023 with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=1023 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
606
Add port mapping with InternalPort=12345 with AddAnyPortMapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddAnyPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 23456,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {
"NewReservedPort": 23456
}
}
Clean up:
$ upnp-client call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=1.1.1.1 NewExternalPort=23456 NewProtocol=TCP >/dev/null

View File

@ -0,0 +1,123 @@
Static NAT rules persistency (UPNPIGD_0050)
Skip because this test uses a reboot command:
$ exit 80
Install upnp-client (Installing via Dockerfile does not work):
$ pip install async-upnp-client >/dev/null 2>&1
$ export PATH="$PATH:$HOME/.local/bin"
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
upnp-client definitions:
$ export SCHEMA_DEVICE_IGDv2='urn:schemas-upnp-org:device:InternetGatewayDevice:2'
$ export CLIENT_IP="$(ip -4 route get "192.168.1.1" 2>/dev/null | sed -n 's/.* src \([0-9.]*\).*/\1/p')"
$ disc_igd_desc() { upnp-client search --target 192.168.1.1 | jq "select(.ST==\"$SCHEMA_DEVICE_IGDv2\")" | jq -rs ".[0].LOCATION"; }
Allow Reserved WAN IP Addresses:
$ R "ba-cli 'Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1'" | grep -v '^>'
Device.UPnP.X_PRPLWARE-COM_IGDConfig.
Device.UPnP.X_PRPLWARE-COM_IGDConfig.AllowReservedAddr=1
$ sleep 3
Verify UPnP IGD is present in the network:
$ upnp-client search --target 192.168.1.1 | jq -r '.ST' | grep urn | uniq
urn:schemas-upnp-org:device:InternetGatewayDevice:2
urn:schemas-upnp-org:device:WANConnectionDevice:2
urn:schemas-upnp-org:device:WANDevice:2
urn:schemas-upnp-org:service:WANIPConnection:2
urn:schemas-upnp-org:service:DeviceProtection:1
urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
urn:schemas-upnp-org:service:Layer3Forwarding:1
Ged Description URL:
$ export DESC_URL=$(disc_igd_desc)
Add port mapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 12345,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {}
}
Get the port mapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetSpecificPortMappingEntry NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP | jq 'del(.timestamp, .service_id, .service_type, .out_parameters.NewInternalClient)'
{
"action": "GetSpecificPortMappingEntry",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 12345,
"NewProtocol": "TCP"
},
"out_parameters": {
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
}
}
Reboot DUT:
$ R "reboot"
$ sleep 120
Get Description URL:
$ export DESC_URL=$(disc_igd_desc)
Get the port mapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/GetSpecificPortMappingEntry NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP 2>&1 | sed -n 's/.*upnp error: \([0-9]\+\) (.*/\1/p'
714
Add port mapping:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/AddAnyPortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP NewInternalPort=12345 NewInternalClient=$CLIENT_IP NewEnabled=1 NewPortMappingDescription="UPnP-Test" NewLeaseDuration=0 | jq 'del(.timestamp, .service_id, .service_type, .in_parameters.NewInternalClient)'
{
"action": "AddAnyPortMapping",
"in_parameters": {
"NewRemoteHost": "1.1.1.1",
"NewExternalPort": 12345,
"NewProtocol": "TCP",
"NewInternalPort": 12345,
"NewEnabled": true,
"NewPortMappingDescription": "UPnP-Test",
"NewLeaseDuration": 0
},
"out_parameters": {
"NewReservedPort": 12345
}
}
Get the port mapping:
$ lease=$(upnp-client --pprint call-action $DESC_URL WANIPConn1/GetSpecificPortMappingEntry NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP | jq -r '.out_parameters.NewLeaseDuration')
$ [ "$lease" -gt 600000 ] && echo OK || echo FAIL
OK
Clean up:
$ upnp-client --pprint call-action $DESC_URL WANIPConn1/DeletePortMapping NewRemoteHost=1.1.1.1 NewExternalPort=12345 NewProtocol=TCP >/dev/null