From 2baf362ac200f63f1c380154bfaa386b0b5f7d23 Mon Sep 17 00:00:00 2001 From: Javier Sánchez Parra Date: Wed, 6 Feb 2019 13:23:51 +0100 Subject: #896: Send multicast WoL through a specific interface * New parameter in ogAdmServer config file for setting an interface. * ogAdmServer multicast WoL now search the interface of the config file in the system, if the interface is found in the system the destination IP of the packet change to a broadcast address of a specific range of addresses. --- ogAdmServer.cfg | 1 + sources/ogAdmServer.cpp | 118 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 102 insertions(+), 17 deletions(-) diff --git a/ogAdmServer.cfg b/ogAdmServer.cfg index 9273952..07d7d97 100644 --- a/ogAdmServer.cfg +++ b/ogAdmServer.cfg @@ -4,3 +4,4 @@ USUARIO=DBUSER PASSWORD=DBPASSWORD datasource=localhost CATALOG=DATABASE +INTERFACE=eth0 diff --git a/sources/ogAdmServer.cpp b/sources/ogAdmServer.cpp index 7461fc0..b6c2f5f 100644 --- a/sources/ogAdmServer.cpp +++ b/sources/ogAdmServer.cpp @@ -10,11 +10,14 @@ #include "ogAdmLib.c" #include #include +#include +#include static char usuario[LONPRM]; // Usuario de acceso a la base de datos static char pasguor[LONPRM]; // Password del usuario static char datasource[LONPRM]; // Dirección IP del gestor de base de datos static char catalog[LONPRM]; // Nombre de la base de datos +static char interface[LONPRM]; // Interface name //________________________________________________________________________________________________________ // Función: tomaConfiguracion @@ -68,6 +71,9 @@ static bool tomaConfiguracion(const char *filecfg) snprintf(datasource, sizeof(datasource), "%s", value); else if (!strcmp(StrToUpper(key), "CATALOG")) snprintf(catalog, sizeof(catalog), "%s", value); + else if (!strcmp(StrToUpper(key), "INTERFACE")) + snprintf(interface, sizeof(interface), "%s", value); + line = fgets(buf, sizeof(buf), fcfg); } @@ -96,6 +102,8 @@ static bool tomaConfiguracion(const char *filecfg) syslog(LOG_ERR, "Missing CATALOG in configuration file\n"); return false; } + if (!interface[0]) + syslog(LOG_ERR, "Missing INTERFACE in configuration file\n"); return true; } @@ -1457,6 +1465,76 @@ bool Levanta(char *iph, char *mac, char *mar) close(s); return true; } + +#define OG_WOL_SEQUENCE 6 +#define OG_WOL_MACADDR_LEN 6 +#define OG_WOL_REPEAT 16 + +struct wol_msg { + char secuencia_FF[OG_WOL_SEQUENCE]; + char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN]; +}; + +static bool wake_up_broadcast(int sd, struct sockaddr_in *client, + const struct wol_msg *msg) +{ + struct sockaddr_in *broadcast_addr; + struct ifaddrs *ifaddr, *ifa; + int ret; + + if (getifaddrs(&ifaddr) < 0) { + syslog(LOG_ERR, "cannot get list of addresses\n"); + return false; + } + + client->sin_addr.s_addr = htonl(INADDR_BROADCAST); + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL || + ifa->ifa_addr->sa_family != AF_INET || + strcmp(ifa->ifa_name, interface) != 0) + continue; + + broadcast_addr = + (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr; + client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr; + break; + } + free(ifaddr); + + ret = sendto(sd, msg, sizeof(*msg), 0, + (sockaddr *)client, sizeof(*client)); + if (ret < 0) { + syslog(LOG_ERR, "failed to send broadcast wol\n"); + return false; + } + + return true; +} + +static bool wake_up_unicast(int sd, struct sockaddr_in *client, + const struct wol_msg *msg, + const struct in_addr *addr) +{ + int ret; + + client->sin_addr.s_addr = addr->s_addr; + + ret = sendto(sd, msg, sizeof(*msg), 0, + (sockaddr *)client, sizeof(*client)); + if (ret < 0) { + syslog(LOG_ERR, "failed to send unicast wol\n"); + return false; + } + + return true; +} + +enum wol_delivery_type { + OG_WOL_BROADCAST = 1, + OG_WOL_UNICAST = 2 +}; + //_____________________________________________________________________________________________________________ // Función: WakeUp // @@ -1474,13 +1552,12 @@ bool Levanta(char *iph, char *mac, char *mar) // bool WakeUp(SOCKET *s, char* iph, char *mac, char *mar) { - int i, res; - char HDaddress_bin[6]; - struct { - BYTE secuencia_FF[6]; - char macbin[16][6]; - } Trama_WakeUp; - sockaddr_in WakeUpCliente; + char HDaddress_bin[OG_WOL_MACADDR_LEN]; + struct sockaddr_in WakeUpCliente; + struct wol_msg Trama_WakeUp; + struct in_addr addr; + bool ret; + int i; for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF) Trama_WakeUp.secuencia_FF[i] = 0xFF; @@ -1499,18 +1576,25 @@ bool WakeUp(SOCKET *s, char* iph, char *mac, char *mar) /* Creación de socket del cliente que recibe la trama magic packet */ WakeUpCliente.sin_family = AF_INET; WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP); - if(atoi(mar)==2) - WakeUpCliente.sin_addr.s_addr = inet_addr(iph); // Para hacerlo con IP - else - WakeUpCliente.sin_addr.s_addr = htonl(INADDR_BROADCAST); // Para hacerlo con broadcast - res = sendto(*s, (char *) &Trama_WakeUp, sizeof(Trama_WakeUp), 0, - (sockaddr *) &WakeUpCliente, sizeof(WakeUpCliente)); - if (res < 0) { - syslog(LOG_ERR, "failed to send wake up\n"); - return false; + switch (atoi(mar)) { + case OG_WOL_BROADCAST: + ret = wake_up_broadcast(*s, &WakeUpCliente, &Trama_WakeUp); + break; + case OG_WOL_UNICAST: + if (inet_aton(iph, &addr) < 0) { + syslog(LOG_ERR, "bad IP address for unicast wol\n"); + ret = false; + break; + } + ret = wake_up_unicast(*s, &WakeUpCliente, &Trama_WakeUp, &addr); + break; + default: + syslog(LOG_ERR, "unknown wol type\n"); + ret = false; + break; } - return true; + return ret; } // ________________________________________________________________________________________________________ // Función: RESPUESTA_Arrancar -- cgit v1.2.3-18-g5258