kbr / fritzconnection

Python-Tool to communicate with the AVM Fritz!Box by the TR-064 protocol and the AHA-HTTP-Interface
MIT License
304 stars 59 forks source link

Fail calling WANPPPConnection1/GetInfo #65

Closed chevdor closed 3 years ago

chevdor commented 3 years ago

I created a minimum example showing the issue:

#!/usr/bin/env python 

from fritzconnection import FritzConnection
import sys
import os

FRITZBOX_IP = os.environ.get('TGFB_IP', '192.168.178.1')
FRITZBOX_USER = os.environ.get('TGFB_USER', 'telegraf')
FRITZBOX_PASSWORD = os.environ.get('TGFB_PASSWD')
FRITZBOX_ID = os.environ.get('TGFB_ID', 'FrizBox')

def readfritz(module, action):
    try:
        answer= fc.call_action(module, action)
    except BaseException:
        print(f"Could not query {module} with action {action}")
        raise
    return answer

try:
    print(f"Connecting to {FRITZBOX_IP} as user {FRITZBOX_USER}")
    fc = FritzConnection(address=FRITZBOX_IP, user=FRITZBOX_USER, password=FRITZBOX_PASSWORD, timeout=5.0)
except BaseException:
    print("Cannot connect to fritzbox.")
    sys.exit(1)

deviceInfo = readfritz('DeviceInfo1', 'GetInfo')
print(f"connected to {deviceInfo['NewModelName']}")

connectionInfo = readfritz('WANPPPConnection1', 'GetInfo') 
print(connectionInfo)

When ran with, it fails with:

$ TGFB_IP=192.168.0.1 TGFB_USER=someuser TGFB_PASSWD=secret python3 ./test.py
Connecting to 192.168.0.1 as user someuser
connected to FRITZ!Box 6490 Cable (lgi)
Could not query WANPPPConnection1 with action GetInfo
Traceback (most recent call last):
  File "./test.py", line 31, in <module>
    connectionInfo = readfritz('WANPPPConnection1', 'GetInfo') 
  File "./test.py", line 14, in readfritz
    answer= fc.call_action(module, action)
  File "/usr/local/lib/python3.8/site-packages/fritzconnection/core/fritzconnection.py", line 218, in call_action
    return self.soaper.execute(service, action_name, arguments)
  File "/usr/local/lib/python3.8/site-packages/fritzconnection/core/soaper.py", line 233, in execute
    return handle_response(response)
  File "/usr/local/lib/python3.8/site-packages/fritzconnection/core/soaper.py", line 218, in handle_response
    raise_fritzconnection_error(response)
  File "/usr/local/lib/python3.8/site-packages/fritzconnection/core/soaper.py", line 147, in raise_fritzconnection_error
    raise exception(message)
fritzconnection.core.exceptions.FritzActionError: UPnPError: 
errorCode: 401
errorDescription: Invalid Action

This was obviously ran with a valid user and password.

chevdor commented 3 years ago

I tested btw using 1.3.4 all the way down to 1.1.1 and the same issue occurs.

kbr commented 3 years ago

May be that's because you are using a cable model. Try to check at the command line for the available actions and whether GetInfo gets listed there. Below is the corresponding output from my DSL-Router which may have a different action-set.

Btw.: you can store the user name and password in the environment variables FRITZ_USER and FRITZ_PASSWORD and FritzConnection will take these values.

$ fritzconnection -i 192.168.178.1 -S WANPPPConnection1

fritzconnection v1.3.4
FRITZ!Box 7590 at http://192.168.178.1
FRITZ!OS: 7.20

Servicename:        WANPPPConnection1
Actionnames:
                    GetInfo
                    GetConnectionTypeInfo
                    SetConnectionType
                    GetStatusInfo
                    GetUserName
                    SetUserName
                    SetPassword
                    GetNATRSIPStatus
                    SetConnectionTrigger
                    ForceTermination
                    RequestConnection
                    GetGenericPortMappingEntry
                    GetSpecificPortMappingEntry
                    AddPortMapping
                    DeletePortMapping
                    GetExternalIPAddress
                    X_GetDNSServers
                    GetLinkLayerMaxBitRates
                    GetPortMappingNumberOfEntries
                    SetRouteProtocolRx
                    SetIdleDisconnectTime
                    X_AVM-DE_GetAutoDisconnectTimeSpan
                    X_AVM-DE_SetAutoDisconnectTimeSpan
chevdor commented 3 years ago

Hello @kbr, thanks for the tip about the ENV, that makes it easier. What you mention is the first idea I had. I could however confirm that it is NOT the issue as you can see in the output below:

$ fritzconnection -i 192.168.0.1 -S WANPPPConnection1

fritzconnection v1.3.4
FRITZ!Box 6490 Cable (lgi) at http://192.168.0.1
FRITZ!OS: 7.12

Servicename:        WANPPPConnection1               <======== ALL GOOD
Actionnames:
                    GetInfo                         <======== Cable can do that too :)
                    GetConnectionTypeInfo
                    SetConnectionType
                    GetStatusInfo
                    GetUserName
                    SetUserName
                    SetPassword
                    GetNATRSIPStatus
                    SetConnectionTrigger
                    ForceTermination
                    RequestConnection
                    GetGenericPortMappingEntry
                    GetSpecificPortMappingEntry
                    AddPortMapping
                    DeletePortMapping
                    GetExternalIPAddress
                    X_GetDNSServers
                    GetLinkLayerMaxBitRates
                    GetPortMappingNumberOfEntries
                    SetRouteProtocolRx
                    SetIdleDisconnectTime
                    X_AVM-DE_GetAutoDisconnectTimeSpan
                    X_AVM-DE_SetAutoDisconnectTimeSpan
$ fritzconnection -i 192.168.0.1 -A  WANPPPConnection1 GetInfo

fritzconnection v1.3.4
FRITZ!Box 6490 Cable (lgi) at http://192.168.0.1
FRITZ!OS: 7.12

Service:            WANPPPConnection1
Action:             GetInfo
Parameters:

    Name                                  direction     data type

    NewEnable                                out ->     boolean
    NewConnectionStatus                      out ->     string
    NewPossibleConnectionTypes               out ->     string
    NewConnectionType                        out ->     string
    NewName                                  out ->     string
    NewUptime                                out ->     ui4
    NewUpstreamMaxBitRate                    out ->     ui4
    NewDownstreamMaxBitRate                  out ->     ui4
    NewLastConnectionError                   out ->     string
    NewIdleDisconnectTime                    out ->     ui4
    NewRSIPAvailable                         out ->     boolean
    NewUserName                              out ->     string
    NewNATEnabled                            out ->     boolean
    NewExternalIPAddress                     out ->     string
    NewDNSServers                            out ->     string
    NewMACAddress                            out ->     string
    NewConnectionTrigger                     out ->     string
    NewLastAuthErrorInfo                     out ->     string
    NewMaxCharsUsername                      out ->     ui2
    NewMinCharsUsername                      out ->     ui2
    NewAllowedCharsUsername                  out ->     string
    NewMaxCharsPassword                      out ->     ui2
    NewMinCharsPassword                      out ->     ui2
    NewAllowedCharsPassword                  out ->     string
    NewTransportType                         out ->     string
    NewRouteProtocolRx                       out ->     string
    NewPPPoEServiceName                      out ->     string
    NewRemoteIPAddress                       out ->     string
    NewPPPoEACName                           out ->     string
    NewDNSEnabled                            out ->     boolean
    NewDNSOverrideAllowed                    out ->     boolean
kbr commented 3 years ago

@chevdor: I can reproduce this with a 4020, which is able to run the WANPPPConnection1 service behind a DSL-modem, but – as a separate access point – is not configured this way. The box reports that the service exists but every action fails, as the service seems to be not in use.

According to the AVM documentation https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/wanpppconnSCPD.pdf it may be that the WANPPPConnection1 service is also not in use for your type of cable connection as it is typically used by AVM for products with a DSL interface.

In this case AVM recommends to check the type of connection by inspection the Layer3Forwarding. For my 4020 this returns (corresponding to the configuration):

>>> r = fc.call_action('Layer3Forwarding', 'GetDefaultConnectionService')
>>> r
{'NewDefaultConnectionService': '1.WANIPConnection.1'}
>>> 
chevdor commented 3 years ago

Awesome @kbr. I think you pinned it. I am closing this issue as I think we can move on when calling the correct method as you suggested.