/* Connectivity checker for Loxone Miniserver. Checks outgoing connections necessary for specific services. Based on version 2026-01-04 of https://updatefiles.loxone.com/KnowledgeBase/Online/Common/Documents/Loxone-Required-Ports-Domains.pdf Andrej Konkow, 05/2026, v01 */ #ifdef LOXMOCK #include "loxmock.c" #endif #define MAX_CHECKS 100 /* Maximum number of checks defined below */ enum nettype { NT_NONE, NT_TCP, NT_UDP }; enum direction { DIR_NONE, DIR_IN, DIR_OUT }; struct endpoint { char *category; char *service; char *address; int port; enum nettype netType; }; int adrIdx=0, structSize=sizeof(struct endpoint); struct endpoint *checkList[MAX_CHECKS], *ep; memset(checkList, NULL, MAX_CHECKS * sizeof(struct endpoint *)); // Own home devices //checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Own device"; ep->service = "Wallbox"; ep->address = "mywallboxIP"; ep->port = 502; ep->netType = NT_TCP; //checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Own device"; ep->service = "Inverter"; ep->address = "myinverterIP"; ep->port = 1502; ep->netType = NT_TCP; //checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Own device"; ep->service = "Heat pump"; ep->address = "myheatpumpIP"; ep->port = 502; ep->netType = NT_TCP; // Loxone defined TCP-endpoints checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "https"; ep->address = "localhost"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "http"; ep->address = "localhost"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "Communication"; ep->address = "localhost"; ep->port = 7095; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "Communication"; ep->address = "localhost"; ep->port = 7091; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "FTP data"; ep->address = "localhost"; ep->port = 20; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "FTP control"; ep->address = "localhost"; ep->port = 21; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Localports"; ep->service = "BacNET"; ep->address = "localhost"; ep->port = 47808; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Weather Service"; ep->address = "weather.loxone.com"; ep->port = 6066; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Weather Service"; ep->address = "weather.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Caller Service"; ep->address = "caller.loxone.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Caller Service"; ep->address = "caller.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Cloud-Mailer"; ep->address = "mail.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Push"; ep->address = "push.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Common Services"; ep->address = "services.loxonecloud.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Cloud - Out"; ep->service = "Common Services"; ep->address = "services.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "Connect Service API"; ep->address = "connect.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "MQTT broker communication"; ep->address = "eu.ccbroker.loxonecloud.com"; ep->port = 8443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "SSH Tunneling Connection"; ep->address = "eu.ccd2.loxonecloud.com"; ep->port = 22; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "Cloud Services"; ep->address = "api.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "Cloud Services"; ep->address = "secureapi.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "HTTPS Certificate Request"; ep->address = "ca.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Remote Connect"; ep->service = "Config API"; ep->address = "registry.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Auto-Update"; ep->address = "update.loxone.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Auto-Update"; ep->address = "update.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Shop"; ep->address = "shop.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Geo coordinates"; ep->address = "geo.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Library"; ep->address = "api.library.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Documentation"; ep->address = "loxone.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Loxone Config"; ep->service = "Documentation"; ep->address = "loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Auto-Update"; ep->service = "http"; ep->address = "updatefiles.loxone.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Auto-Update"; ep->service = "https"; ep->address = "updatefiles.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Online Check"; ep->service = "http"; ep->address = "dns.loxonecloud.com"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Online Check"; ep->service = "https"; ep->address = "dns.loxonecloud.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Online Check"; ep->service = "http"; ep->address = "icann.org"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Online Check"; ep->service = "http"; ep->address = "w3c.org"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "TechReport"; ep->service = "https"; ep->address = "techreport.loxone.com"; ep->port = 443; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Remote Connect"; ep->address = "195.201.222.243"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Remote Connect"; ep->address = "168.119.185.175"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Remote Connect"; ep->address = "5.75.128.138"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Remote Connect"; ep->address = "88.99.85.148"; ep->port = 80; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Google STUN fallback"; ep->address = "stun.l.google.com"; ep->port = 19302; ep->netType = NT_TCP; checkList[adrIdx++] = ep = malloc(structSize); ep->category = "App"; ep->service = "Air/Tree"; ep->address = "extended-app-content.s3.eu-central-1.amazonaws.com"; ep->port = 443; ep->netType = NT_TCP; // No addresses for *.dyndns.loxonecloud.com, *.remcov3.loxonecloud.com // Take care of correct sending source ip and pattern reading on loxone input channel. UDP check will send value "1". //checkList[adrIdx++] = ep = malloc(structSize); ep->category = "Own device"; ep->service = "Check UDP"; ep->address = "localhost"; ep->port = 7610; ep->netType = NT_UDP; /* print result in a readable short format */ void printCheckResult(struct endpoint *ep, int sentBytes, char *resultBuf) { char *netType = "Unknown"; char *conResult = "NOK"; if (ep->netType == NT_TCP) netType = "TCP"; else if (ep->netType == NT_UDP) netType = "UDP"; if (sentBytes > 0) conResult = "OK"; sprintf(resultBuf, "%5s %30s:%d %3s\n", netType, ep->address, ep->port, conResult); } /* Check a tcp connection by connecting systems */ int checkTCPConnection(struct endpoint *ep) { char buf[300]; sprintf(buf, "/dev/tcp/%s/%d", ep->address, ep->port); STREAM* pTcpStream = stream_create(buf, 0, 0); if (pTcpStream == NULL) return 0; stream_close(pTcpStream); return 1; } /* Check a udp connection by opening and sending over port No real checking possible as there is no connection or response. Only serverside validation/receival can be done by sending something. */ int checkUDPConnection(struct endpoint *ep) { char buf[300]; sprintf(buf, "/dev/udp/%s/%d", ep->address, ep->port); char udpRequest[1] = { 1 }; STREAM* pUdpStream = stream_create(buf, 0, 0); int noWritten = stream_write(pUdpStream,udpRequest,1); stream_close(pUdpStream); return noWritten; // return number of sent bytes } /* go into the right direction */ int checkConnection(struct endpoint *ep) { if (ep->netType == NT_UDP) return checkUDPConnection(ep); return checkTCPConnection(ep); } void doWork() { char bufResult[4*1024]; memset(bufResult, 0, 4*1024); char hlp[60]; sprintf(hlp, "Please be patient. Now checking %d connections...", adrIdx); setoutputtext(0, hlp); for (int i=0; i