#!/usr/bin/env python3
"""
Diagnosi completa configurazione telefonia Fritz!Box
Verifica perché non ci sono interni attivi
"""
import requests
from requests.auth import HTTPDigestAuth
import xml.etree.ElementTree as ET
import argparse
def check_credentials(ip, user, password):
"""Verifica che le credenziali funzionino"""
print("\n" + "="*60)
print("TEST 1: VERIFICA CREDENZIALI")
print("="*60)
url = f"http://{ip}:49000/upnp/control/deviceinfo"
soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetInfo xmlns:u="urn:dslforum-org:service:DeviceInfo:1"/>
</s:Body>
</s:Envelope>'''
headers = {
'Content-Type': 'text/xml',
'SOAPAction': 'urn:dslforum-org:service:DeviceInfo:1#GetInfo'
}
try:
auth = HTTPDigestAuth(user, password)
r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
if r.status_code == 200:
print("✓ Credenziali VALIDE")
print("✓ Autenticazione riuscita")
# Estrai info dispositivo
try:
root = ET.fromstring(r.text)
for elem in root.iter():
if 'ModelName' in elem.tag and elem.text:
print(f"✓ Modello: {elem.text}")
elif 'SoftwareVersion' in elem.tag and elem.text:
print(f"✓ Firmware: {elem.text}")
except:
pass
return True
elif r.status_code == 401:
print("✗ CREDENZIALI ERRATE")
print("\nProva con:")
print(f" python3 {__file__} --ip {ip} --user admin --password TUA_PASSWORD")
return False
else:
print(f"⚠ Status code inatteso: {r.status_code}")
return False
except Exception as e:
print(f"✗ Errore: {e}")
return False
def check_voip_service(ip, user, password):
"""Verifica che il servizio VoIP sia disponibile"""
print("\n" + "="*60)
print("TEST 2: VERIFICA SERVIZIO VOIP")
print("="*60)
url = f"http://{ip}:49000/upnp/control/x_voip"
auth = HTTPDigestAuth(user, password)
# Prova a ottenere il numero di dispositivi VoIP
soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetInfo xmlns:u="urn:dslforum-org:service:X_VoIP:1"/>
</s:Body>
</s:Envelope>'''
headers = {
'Content-Type': 'text/xml',
'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#GetInfo'
}
try:
r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
if r.status_code == 200:
print("✓ Servizio VoIP ATTIVO")
# Cerca numero di telefoni
try:
root = ET.fromstring(r.text)
for elem in root.iter():
tag = elem.tag.split('}')[-1] if '}' in elem.tag else elem.tag
if elem.text and elem.text.strip() and 'Phone' in tag:
print(f" {tag}: {elem.text.strip()}")
except:
pass
return True
elif r.status_code == 401:
print("✗ Autenticazione fallita per servizio VoIP")
print(" L'utente potrebbe non avere i permessi sulla telefonia")
return False
else:
print(f"⚠ Servizio VoIP risponde con status {r.status_code}")
print(f" Risposta: {r.text[:200]}")
return False
except Exception as e:
print(f"✗ Errore: {e}")
return False
def check_phone_numbers(ip, user, password):
"""Verifica se ci sono numeri telefonici configurati"""
print("\n" + "="*60)
print("TEST 3: VERIFICA NUMERI TELEFONICI")
print("="*60)
url = f"http://{ip}:49000/upnp/control/x_voip"
auth = HTTPDigestAuth(user, password)
numeri_trovati = []
# Prova a leggere fino a 10 numeri telefonici
for i in range(10):
soap = f'''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_GetNumberOfNumbers xmlns:u="urn:dslforum-org:service:X_VoIP:1"/>
</s:Body>
</s:Envelope>'''
headers = {
'Content-Type': 'text/xml',
'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_GetNumberOfNumbers'
}
try:
r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
if r.status_code == 200:
try:
root = ET.fromstring(r.text)
for elem in root.iter():
if 'NumberOfNumbers' in elem.tag and elem.text:
num_count = elem.text.strip()
print(f"✓ Numeri telefonici configurati: {num_count}")
if int(num_count) > 0:
return True
else:
print("\n⚠ NESSUN NUMERO TELEFONICO CONFIGURATO!")
return False
except:
pass
break
except:
pass
print("⚠ Impossibile verificare i numeri telefonici")
return None
def check_phone_devices(ip, user, password):
"""Verifica dispositivi telefonici configurati"""
print("\n" + "="*60)
print("TEST 4: VERIFICA DISPOSITIVI TELEFONICI")
print("="*60)
url = f"http://{ip}:49000/upnp/control/x_voip"
auth = HTTPDigestAuth(user, password)
dispositivi_trovati = []
# Prova a leggere info sui dispositivi
for i in range(10):
soap = f'''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_GetPhonePort xmlns:u="urn:dslforum-org:service:X_VoIP:1">
<NewIndex>{i}</NewIndex>
</u:X_AVM-DE_GetPhonePort>
</s:Body>
</s:Envelope>'''
headers = {
'Content-Type': 'text/xml',
'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_GetPhonePort'
}
try:
r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
if r.status_code == 200:
try:
root = ET.fromstring(r.text)
phone_name = None
for elem in root.iter():
if 'PhoneName' in elem.tag and elem.text:
phone_name = elem.text.strip()
break
if phone_name and phone_name != "":
dispositivi_trovati.append((i, phone_name))
print(f"✓ Dispositivo {i}: {phone_name}")
except:
pass
except:
pass
if dispositivi_trovati:
return True, dispositivi_trovati
else:
print("\n⚠ NESSUN DISPOSITIVO TELEFONICO TROVATO!")
return False, []
def test_simple_dial(ip, user, password):
"""Testa una chiamata semplicissima senza interno"""
print("\n" + "="*60)
print("TEST 5: CHIAMATA SEMPLICE (senza interno)")
print("="*60)
url = f"http://{ip}:49000/upnp/control/x_voip"
auth = HTTPDigestAuth(user, password)
# Chiamata senza specificare l'interno
soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_DialNumber xmlns:u="urn:dslforum-org:service:X_VoIP:1">
<NewX_AVM-DE_PhoneNumber>0</NewX_AVM-DE_PhoneNumber>
</u:X_AVM-DE_DialNumber>
</s:Body>
</s:Envelope>'''
headers = {
'Content-Type': 'text/xml',
'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_DialNumber'
}
try:
r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=10)
print(f"Status: {r.status_code}")
if r.status_code == 200:
print("✓ Chiamata ACCETTATA!")
print(" Il Fritz!Box può effettuare chiamate")
return True
else:
print(f"✗ Chiamata RIFIUTATA")
print(f"\nRisposta:")
print(r.text[:500])
# Analizza errore
try:
root = ET.fromstring(r.text)
for elem in root.iter():
if 'errorCode' in elem.tag and elem.text:
code = elem.text.strip()
print(f"\nCodice errore: {code}")
if code == "713":
print(" Significato: Nessun telefono configurato o disponibile")
elif code == "714":
print(" Significato: Formato numero non valido")
elif code == "501":
print(" Significato: Funzione non supportata")
except:
pass
return False
except Exception as e:
print(f"✗ Errore: {e}")
return False
def main():
parser = argparse.ArgumentParser(description='Diagnosi telefonia Fritz!Box')
parser.add_argument('-i', '--ip', default='192.168.1.10', help='IP Fritz!Box')
parser.add_argument('-u', '--user', default='user1', help='Username')
parser.add_argument('-p', '--password', default='pass1', help='Password')
args = parser.parse_args()
print("\n" + "="*60)
print("DIAGNOSI COMPLETA TELEFONIA FRITZ!BOX")
print("="*60)
print(f"\nFritz!Box: {args.ip}")
print(f"Utente: {args.user}")
# Esegui tutti i test
cred_ok = check_credentials(args.ip, args.user, args.password)
if not cred_ok:
print("\n" + "="*60)
print("ARRESTO: Credenziali non valide")
print("="*60)
return
voip_ok = check_voip_service(args.ip, args.user, args.password)
numbers_ok = check_phone_numbers(args.ip, args.user, args.password)
devices_ok, devices = check_phone_devices(args.ip, args.user, args.password)
dial_ok = test_simple_dial(args.ip, args.user, args.password)
# Riepilogo finale
print("\n" + "="*60)
print("RIEPILOGO DIAGNOSI")
print("="*60)
print(f"\n✓ Credenziali: {'OK' if cred_ok else 'ERRORE'}")
print(f"{'✓' if voip_ok else '✗'} Servizio VoIP: {'ATTIVO' if voip_ok else 'NON DISPONIBILE'}")
print(f"{'✓' if numbers_ok else '✗'} Numeri telefonici: {'CONFIGURATI' if numbers_ok else 'NON CONFIGURATI'}")
print(f"{'✓' if devices_ok else '✗'} Dispositivi: {'TROVATI' if devices_ok else 'NON TROVATI'}")
print(f"{'✓' if dial_ok else '✗'} Capacità chiamata: {'FUNZIONANTE' if dial_ok else 'NON FUNZIONANTE'}")
print("\n" + "="*60)
print("CONCLUSIONE")
print("="*60)
if not numbers_ok:
print("\n❌ PROBLEMA: NESSUN NUMERO TELEFONICO CONFIGURATO")
print("\nIl Fritz!Box non ha numeri di telefono configurati.")
print("Senza un numero telefonico, non puoi effettuare chiamate.")
print("\n📋 COME CONFIGURARE:")
print("\n1. Accedi al Fritz!Box: http://" + args.ip)
print("2. Vai su: Telefonia → Numeri telefonici")
print("3. Clicca 'Nuovo numero'")
print("4. Segui la procedura guidata per configurare:")
print(" - Numero VoIP/SIP del tuo provider")
print(" - Oppure numero fisso se connesso a linea telefonica")
print("\nSenza numero configurato, le chiamate non funzioneranno!")
elif not devices_ok:
print("\n❌ PROBLEMA: NESSUN DISPOSITIVO TELEFONICO")
print("\nHai un numero configurato ma nessun telefono registrato.")
print("\n📋 COME CONFIGURARE:")
print("\n1. Accedi al Fritz!Box: http://" + args.ip)
print("2. Vai su: Telefonia → Dispositivi telefonici")
print("3. Clicca 'Configura nuovo dispositivo'")
print("4. Scegli il tipo:")
print(" - Telefono IP")
print(" - Telefono analogico (se collegato)")
print(" - Telefono DECT")
print("5. Assegna un interno (es: 1, 2, 620)")
elif not voip_ok:
print("\n❌ PROBLEMA: SERVIZIO VOIP NON DISPONIBILE")
print("\nPossibili cause:")
print("1. L'utente non ha permessi sulla telefonia")
print("2. TR-064 non completamente attivo")
print("\n📋 SOLUZIONI:")
print("\n1. Usa l'utente admin:")
print(f" python3 {__file__} --ip {args.ip} --user admin --password TUA_PASSWORD")
print("\n2. Riavvia il Fritz!Box")
print("\n3. Verifica permessi utente:")
print(" Sistema → Utenti Fritz!Box")
print(" Assicurati che l'utente abbia 'Accesso alle impostazioni'")
elif not dial_ok:
print("\n⚠ PROBLEMA: CHIAMATA RIFIUTATA")
print("\nPossibili cause:")
print("1. Configurazione telefonia incompleta")
print("2. Nessuna linea telefonica attiva")
print("3. Permessi insufficienti")
else:
print("\n✓✓✓ TUTTO CONFIGURATO CORRETTAMENTE ✓✓✓")
print("\nIl Fritz!Box è pronto per le chiamate!")
if devices:
print("\nDispositivi disponibili:")
for idx, name in devices:
print(f" - {name} (indice {idx})")
print("\n📞 PROVA A CHIAMARE:")
print(f"\npython3 chiama_minimo.py")
print("\nModifica:")
print(f" INTERNO = '{devices[0][0]}' # Usa indice primo dispositivo")
print(f" # Oppure prova senza interno (usa predefinito)")
if __name__ == "__main__":
main()