From ad2d308436190aeb70cc04a313c228fe9e8f778a Mon Sep 17 00:00:00 2001 From: OpenGnSys Support Team Date: Tue, 26 Nov 2019 18:59:32 +0100 Subject: #967 rename .cpp to .c This actually is C code, use the gcc compiler instead. --- Makefile | 6 +- sources/dbi.c | 37 + sources/dbi.cpp | 37 - sources/ogAdmServer.c | 4907 +++++++++++++++++++++++++++++++++++++++++++++++ sources/ogAdmServer.cpp | 4907 ----------------------------------------------- 5 files changed, 4945 insertions(+), 4949 deletions(-) create mode 100644 sources/dbi.c delete mode 100644 sources/dbi.cpp create mode 100644 sources/ogAdmServer.c delete mode 100644 sources/ogAdmServer.cpp diff --git a/Makefile b/Makefile index eafecb3..0c3360e 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,6 @@ INSTALL_DIR := /opt/opengnsys # Opciones de compilacion CFLAGS := $(shell mysql_config --cflags) CFLAGS += -g -Wall -I../../Includes -CPPFLAGS := $(CFLAGS) # Opciones de linkado LDFLAGS := -Wl,--no-as-needed $(shell mysql_config --libs) -lev -ljansson -ldbi @@ -21,7 +20,7 @@ OBJS := sources/ogAdmServer.o sources/dbi.o all: $(PROYECTO) $(PROYECTO): $(OBJS) - g++ $(LDFLAGS) $(OBJS) -o $(PROYECTO) + gcc $(LDFLAGS) $(CFLAGS) $(OBJS) -o $(PROYECTO) install: $(PROYECTO) cp $(PROYECTO) $(INSTALL_DIR)/sbin @@ -33,9 +32,6 @@ clean: uninstall: clean rm -f /usr/local/sbin/$(PROYECTO) /usr/local/etc/$(PROYECTO).cfg -sources/%.o: sources/%.cpp - g++ $(CPPFLAGS) -c -o"$@" "$<" - sources/%.o: sources/%.c gcc $(CFLAGS) -c -o"$@" "$<" diff --git a/sources/dbi.c b/sources/dbi.c new file mode 100644 index 0000000..cc5c5b5 --- /dev/null +++ b/sources/dbi.c @@ -0,0 +1,37 @@ +#include "dbi.h" + +struct og_dbi *og_dbi_open(struct og_dbi_config *config) +{ + struct og_dbi *dbi; + + dbi = (struct og_dbi *)malloc(sizeof(struct og_dbi)); + if (!dbi) + return NULL; + + dbi_initialize_r(NULL, &dbi->inst); + dbi->conn = dbi_conn_new_r("mysql", dbi->inst); + if (!dbi->conn) { + free(dbi); + return NULL; + } + + dbi_conn_set_option(dbi->conn, "host", config->host); + dbi_conn_set_option(dbi->conn, "username", config->user); + dbi_conn_set_option(dbi->conn, "password", config->passwd); + dbi_conn_set_option(dbi->conn, "dbname", config->database); + dbi_conn_set_option(dbi->conn, "encoding", "UTF-8"); + + if (dbi_conn_connect(dbi->conn) < 0) { + free(dbi); + return NULL; + } + + return dbi; +} + +void og_dbi_close(struct og_dbi *dbi) +{ + dbi_conn_close(dbi->conn); + dbi_shutdown_r(dbi->inst); + free(dbi); +} diff --git a/sources/dbi.cpp b/sources/dbi.cpp deleted file mode 100644 index cc5c5b5..0000000 --- a/sources/dbi.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "dbi.h" - -struct og_dbi *og_dbi_open(struct og_dbi_config *config) -{ - struct og_dbi *dbi; - - dbi = (struct og_dbi *)malloc(sizeof(struct og_dbi)); - if (!dbi) - return NULL; - - dbi_initialize_r(NULL, &dbi->inst); - dbi->conn = dbi_conn_new_r("mysql", dbi->inst); - if (!dbi->conn) { - free(dbi); - return NULL; - } - - dbi_conn_set_option(dbi->conn, "host", config->host); - dbi_conn_set_option(dbi->conn, "username", config->user); - dbi_conn_set_option(dbi->conn, "password", config->passwd); - dbi_conn_set_option(dbi->conn, "dbname", config->database); - dbi_conn_set_option(dbi->conn, "encoding", "UTF-8"); - - if (dbi_conn_connect(dbi->conn) < 0) { - free(dbi); - return NULL; - } - - return dbi; -} - -void og_dbi_close(struct og_dbi *dbi) -{ - dbi_conn_close(dbi->conn); - dbi_shutdown_r(dbi->inst); - free(dbi); -} diff --git a/sources/ogAdmServer.c b/sources/ogAdmServer.c new file mode 100644 index 0000000..562a39d --- /dev/null +++ b/sources/ogAdmServer.c @@ -0,0 +1,4907 @@ +// ******************************************************************************************************* +// Servicio: ogAdmServer +// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla +// Fecha Creación: Marzo-2010 +// Fecha Última modificación: Marzo-2010 +// Nombre del fichero: ogAdmServer.cpp +// Descripción :Este fichero implementa el servicio de administración general del sistema +// ******************************************************************************************************* +#include "ogAdmServer.h" +#include "ogAdmLib.c" +#include "dbi.h" +#include +#include +#include +#include +#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 +static char auth_token[LONPRM]; // API token + +static struct og_dbi_config dbi_config = { + .user = usuario, + .passwd = pasguor, + .host = datasource, + .database = catalog, +}; + +//________________________________________________________________________________________________________ +// Función: tomaConfiguracion +// +// Descripción: +// Lee el fichero de configuración del servicio +// Parámetros: +// filecfg : Ruta completa al fichero de configuración +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +//________________________________________________________________________________________________________ +static bool tomaConfiguracion(const char *filecfg) +{ + char buf[1024], *line; + char *key, *value; + FILE *fcfg; + + if (filecfg == NULL || strlen(filecfg) == 0) { + syslog(LOG_ERR, "No configuration file has been specified\n"); + return false; + } + + fcfg = fopen(filecfg, "rt"); + if (fcfg == NULL) { + syslog(LOG_ERR, "Cannot open configuration file `%s'\n", + filecfg); + return false; + } + + servidoradm[0] = '\0'; //inicializar variables globales + + line = fgets(buf, sizeof(buf), fcfg); + while (line != NULL) { + const char *delim = "="; + + line[strlen(line) - 1] = '\0'; + + key = strtok(line, delim); + value = strtok(NULL, delim); + + if (!strcmp(StrToUpper(key), "SERVIDORADM")) + snprintf(servidoradm, sizeof(servidoradm), "%s", value); + else if (!strcmp(StrToUpper(key), "PUERTO")) + snprintf(puerto, sizeof(puerto), "%s", value); + else if (!strcmp(StrToUpper(key), "USUARIO")) + snprintf(usuario, sizeof(usuario), "%s", value); + else if (!strcmp(StrToUpper(key), "PASSWORD")) + snprintf(pasguor, sizeof(pasguor), "%s", value); + else if (!strcmp(StrToUpper(key), "DATASOURCE")) + 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); + else if (!strcmp(StrToUpper(key), "APITOKEN")) + snprintf(auth_token, sizeof(auth_token), "%s", value); + + line = fgets(buf, sizeof(buf), fcfg); + } + + fclose(fcfg); + + if (!servidoradm[0]) { + syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n"); + return false; + } + if (!puerto[0]) { + syslog(LOG_ERR, "Missing PUERTO in configuration file\n"); + return false; + } + if (!usuario[0]) { + syslog(LOG_ERR, "Missing USUARIO in configuration file\n"); + return false; + } + if (!pasguor[0]) { + syslog(LOG_ERR, "Missing PASSWORD in configuration file\n"); + return false; + } + if (!datasource[0]) { + syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n"); + return false; + } + if (!catalog[0]) { + 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; +} + +enum og_client_state { + OG_CLIENT_RECEIVING_HEADER = 0, + OG_CLIENT_RECEIVING_PAYLOAD, + OG_CLIENT_PROCESSING_REQUEST, +}; + +#define OG_MSG_REQUEST_MAXLEN 4096 + +/* Shut down connection if there is no complete message after 10 seconds. */ +#define OG_CLIENT_TIMEOUT 10 + +struct og_client { + struct ev_io io; + struct ev_timer timer; + struct sockaddr_in addr; + enum og_client_state state; + char buf[OG_MSG_REQUEST_MAXLEN]; + unsigned int buf_len; + unsigned int msg_len; + int keepalive_idx; + bool rest; + int content_length; + char auth_token[64]; +}; + +static inline int og_client_socket(const struct og_client *cli) +{ + return cli->io.fd; +} + +// ________________________________________________________________________________________________________ +// Función: clienteDisponible +// +// Descripción: +// Comprueba la disponibilidad del cliente para recibir comandos interactivos +// Parametros: +// - ip : La ip del cliente a buscar +// - idx: (Salida) Indice que ocupa el cliente, de estar ya registrado +// Devuelve: +// true: Si el cliente está disponible +// false: En caso contrario +// ________________________________________________________________________________________________________ +bool clienteDisponible(char *ip, int* idx) +{ + int estado; + + if (clienteExistente(ip, idx)) { + estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado + if (estado == 0) + return false; + + estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado + if (estado == 0) + return false; + + estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión + if (estado == 0) + return false; + + return true; // En caso contrario el cliente está disponible + } + return false; // Cliente no está registrado en el sistema +} +// ________________________________________________________________________________________________________ +// Función: clienteExistente +// +// Descripción: +// Comprueba si el cliente está registrado en la tabla de socket del sistema +// Parametros: +// - ip : La ip del cliente a buscar +// - idx:(Salida) Indice que ocupa el cliente, de estar ya registrado +// Devuelve: +// true: Si el cliente está registrado +// false: En caso contrario +// ________________________________________________________________________________________________________ +bool clienteExistente(char *ip, int* idx) +{ + int i; + for (i = 0; i < MAXIMOS_CLIENTES; i++) { + if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena + *idx = i; + return true; + } + } + return false; +} +// ________________________________________________________________________________________________________ +// Función: hayHueco +// +// Descripción: +// Esta función devuelve true o false dependiendo de que haya hueco en la tabla de sockets para un nuevo cliente. +// Parametros: +// - idx: Primer indice libre que se podrn utilizar +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool hayHueco(int *idx) +{ + int i; + + for (i = 0; i < MAXIMOS_CLIENTES; i++) { + if (strncmp(tbsockets[i].ip, "\0", 1) == 0) { // Hay un hueco + *idx = i; + return true; + } + } + return false; +} +// ________________________________________________________________________________________________________ +// Función: InclusionClienteWin +// +// Descripción: +// Esta función incorpora el socket de un nuevo cliente Windows o Linux a la tabla de clientes +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool InclusionClienteWinLnx(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + int res,idordenador,lon; + char nombreordenador[LONFIL]; + + res = procesoInclusionClienteWinLnx(socket_c, ptrTrama, &idordenador, + nombreordenador); + + // Prepara la trama de respuesta + + initParametros(ptrTrama,0); + ptrTrama->tipo=MSG_RESPUESTA; + lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionClienteWinLnx\r"); + lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador); + lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador); + lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", res); + + if (!mandaTrama(&socket_c, ptrTrama)) { + syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + return false; + } + return true; +} +// ________________________________________________________________________________________________________ +// Función: procesoInclusionClienteWinLnx +// +// Descripción: +// Implementa el proceso de inclusión en el sistema del Cliente Windows o Linux +// Parámetros de entrada: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Parámetros de salida: +// - ido: Identificador del ordenador +// - nombreordenador: Nombre del ordenador +// Devuelve: +// Código del error producido en caso de ocurrir algún error, 0 si el proceso es correcto +// ________________________________________________________________________________________________________ +bool procesoInclusionClienteWinLnx(int socket_c, TRAMA *ptrTrama, int *idordenador, char *nombreordenador) + { + struct og_dbi *dbi; + const char *msglog; + dbi_result result; + char *iph; + + // Toma parámetros + iph = copiaParametro("iph",ptrTrama); // Toma ip + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + goto err_dbi_open; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT idordenador,nombreordenador FROM ordenadores " + " WHERE ordenadores.ip = '%s'", iph); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + goto err_query_fail; + } + + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + goto err_query_fail; + } + + syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph); + + *idordenador = dbi_result_get_uint(result, "idordenador"); + nombreordenador = (char *)dbi_result_get_string(result, "nombreordenador"); + + dbi_result_free(result); + og_dbi_close(dbi); + + if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets + liberaMemoria(iph); + syslog(LOG_ERR, "client table is full\n"); + return false; + } + liberaMemoria(iph); + return true; + +err_query_fail: + og_dbi_close(dbi); +err_dbi_open: + liberaMemoria(iph); + return false; +} +// ________________________________________________________________________________________________________ +// Función: InclusionCliente +// +// Descripción: +// Esta función incorpora el socket de un nuevo cliente a la tabla de clientes y le devuelve alguna de sus propiedades: +// nombre, identificador, tamaño de la caché , etc ... +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool InclusionCliente(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + + if (!procesoInclusionCliente(cli, ptrTrama)) { + initParametros(ptrTrama,0); + strcpy(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\rres=0\r"); + if (!mandaTrama(&socket_c, ptrTrama)) { + syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + return false; + } + } + return true; +} +// ________________________________________________________________________________________________________ +// Función: procesoInclusionCliente +// +// Descripción: +// Implementa el proceso de inclusión en el sistema del Cliente +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool procesoInclusionCliente(struct og_client *cli, TRAMA *ptrTrama) +{ + int socket_c = og_client_socket(cli); + const char *msglog, *str; + struct og_dbi *dbi; + dbi_result result; + + char *iph, *cfg; + char nombreordenador[LONFIL]; + int lon, resul, idordenador, cache, idproautoexec, idaula, idcentro; + + // Toma parámetros + iph = copiaParametro("iph",ptrTrama); // Toma ip + cfg = copiaParametro("cfg",ptrTrama); // Toma configuracion + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + goto err_dbi_open; + } + + // Recupera los datos del cliente + result = dbi_conn_queryf(dbi->conn, + "SELECT ordenadores.*,aulas.idaula,centros.idcentro FROM ordenadores " + " INNER JOIN aulas ON aulas.idaula=ordenadores.idaula" + " INNER JOIN centros ON centros.idcentro=aulas.idcentro" + " WHERE ordenadores.ip = '%s'", iph); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + goto err_query_fail; + } + + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + goto err_query_fail; + } + + syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph); + + idordenador = dbi_result_get_uint(result, "idordenador"); + str = (char *)dbi_result_get_string(result, "nombreordenador"); + sprintf(nombreordenador, "%s", str); + cache = dbi_result_get_uint(result, "cache"); + idproautoexec = dbi_result_get_uint(result, "idproautoexec"); + idaula = dbi_result_get_uint(result, "idaula"); + idcentro = dbi_result_get_uint(result, "idcentro"); + dbi_result_free(result); + + resul = actualizaConfiguracion(dbi, cfg, idordenador); // Actualiza la configuración del ordenador + liberaMemoria(cfg); + og_dbi_close(dbi); + + if (!resul) { + liberaMemoria(iph); + syslog(LOG_ERR, "Cannot add client to database\n"); + return false; + } + + if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets + liberaMemoria(iph); + syslog(LOG_ERR, "client table is full\n"); + return false; + } + + /*------------------------------------------------------------------------------------------------------------------------------ + Prepara la trama de respuesta + -------------------------------------------------------------------------------------------------------------------------------*/ + initParametros(ptrTrama,0); + ptrTrama->tipo=MSG_RESPUESTA; + lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\r"); + lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador); + lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador); + lon += sprintf(ptrTrama->parametros + lon, "che=%d\r", cache); + lon += sprintf(ptrTrama->parametros + lon, "exe=%d\r", idproautoexec); + lon += sprintf(ptrTrama->parametros + lon, "ida=%d\r", idaula); + lon += sprintf(ptrTrama->parametros + lon, "idc=%d\r", idcentro); + lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", 1); // Confirmación proceso correcto + + if (!mandaTrama(&socket_c, ptrTrama)) { + syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + return false; + } + liberaMemoria(iph); + return true; + +err_query_fail: + og_dbi_close(dbi); +err_dbi_open: + liberaMemoria(iph); + liberaMemoria(cfg); + return false; +} +// ________________________________________________________________________________________________________ +// Función: actualizaConfiguracion +// +// Descripción: +// Esta función actualiza la base de datos con la configuracion de particiones de un cliente +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - cfg: cadena con una Configuración +// - ido: Identificador del ordenador cliente +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// Especificaciones: +// Los parametros de la configuración son: +// par= Número de partición +// cpt= Codigo o tipo de partición +// sfi= Sistema de ficheros que está implementado en la partición +// soi= Nombre del sistema de ficheros instalado en la partición +// tam= Tamaño de la partición +// ________________________________________________________________________________________________________ +bool actualizaConfiguracion(struct og_dbi *dbi, char *cfg, int ido) +{ + int lon, p, c,i, dato, swu, idsoi, idsfi,k; + char *ptrPar[MAXPAR], *ptrCfg[7], *ptrDual[2], tbPar[LONSTD]; + char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración. + dbi_result result, result_update; + const char *msglog; + + lon = 0; + p = splitCadena(ptrPar, cfg, '\n'); + for (i = 0; i < p; i++) { + c = splitCadena(ptrCfg, ptrPar[i], '\t'); + + // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD. + if (i == 0 && c == 1) { + splitCadena(ptrDual, ptrCfg[0], '='); + ser = ptrDual[1]; + if (strlen(ser) > 0) { + // Solo actualizar si número de serie no existía. + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET numserie='%s'" + " WHERE idordenador=%d AND numserie IS NULL", + ser, ido); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + } + continue; + } + + // Distribución de particionado. + disk = par = cpt = sfi = soi = tam = uso = NULL; + + splitCadena(ptrDual, ptrCfg[0], '='); + disk = ptrDual[1]; // Número de disco + + splitCadena(ptrDual, ptrCfg[1], '='); + par = ptrDual[1]; // Número de partición + + k=splitCadena(ptrDual, ptrCfg[2], '='); + if(k==2){ + cpt = ptrDual[1]; // Código de partición + }else{ + cpt = (char*)"0"; + } + + k=splitCadena(ptrDual, ptrCfg[3], '='); + if(k==2){ + sfi = ptrDual[1]; // Sistema de ficheros + /* Comprueba existencia del s0xistema de ficheros instalado */ + idsfi = checkDato(dbi, sfi, "sistemasficheros", "descripcion","idsistemafichero"); + } + else + idsfi=0; + + k=splitCadena(ptrDual, ptrCfg[4], '='); + if(k==2){ // Sistema operativo detecdtado + soi = ptrDual[1]; // Nombre del S.O. instalado + /* Comprueba existencia del sistema operativo instalado */ + idsoi = checkDato(dbi, soi, "nombresos", "nombreso", "idnombreso"); + } + else + idsoi=0; + + splitCadena(ptrDual, ptrCfg[5], '='); + tam = ptrDual[1]; // Tamaño de la partición + + splitCadena(ptrDual, ptrCfg[6], '='); + uso = ptrDual[1]; // Porcentaje de uso del S.F. + + lon += sprintf(tbPar + lon, "(%s, %s),", disk, par); + + result = dbi_conn_queryf(dbi->conn, + "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso" + " FROM ordenadores_particiones" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + ido, disk, par); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + result_update = dbi_conn_queryf(dbi->conn, + "INSERT INTO ordenadores_particiones(idordenador,numdisk,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)" + " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)", + ido, disk, par, cpt, tam, uso, idsfi, idsoi); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result_update); + + } else { // Existe el registro + swu = true; // Se supone que algún dato ha cambiado + + dato = dbi_result_get_uint(result, "tamano"); + if (atoi(tam) == dato) {// Parámetro tamaño igual al almacenado + dato = dbi_result_get_uint(result, "idsistemafichero"); + if (idsfi == dato) {// Parámetro sistema de fichero igual al almacenado + dato = dbi_result_get_uint(result, "idnombreso"); + if (idsoi == dato) {// Parámetro sistema de fichero distinto al almacenado + swu = false; // Todos los parámetros de la partición son iguales, no se actualiza + } + } + } + if (swu) { // Hay que actualizar los parámetros de la partición + result_update = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET " + " codpar=0x%s," + " tamano=%s," + " uso=%s," + " idsistemafichero=%d," + " idnombreso=%d," + " idimagen=0," + " idperfilsoft=0," + " fechadespliegue=NULL" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + cpt, tam, uso, idsfi, idsoi, ido, disk, par); + } else { // Actualizar porcentaje de uso. + result_update = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET " + " codpar=0x%s," + " uso=%s" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + cpt, uso, ido, disk, par); + } + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + dbi_result_free(result_update); + } + } + lon += sprintf(tbPar + lon, "(0,0)"); + // Eliminar particiones almacenadas que ya no existen + result_update = dbi_conn_queryf(dbi->conn, + "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)", + ido, tbPar); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: checkDato +// +// Descripción: +// Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en +// cualquier caso el identificador del registro existenet o del insertado +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - dato: Dato +// - tabla: Nombre de la tabla +// - nomdato: Nombre del dato en la tabla +// - nomidentificador: Nombre del identificador en la tabla +// Devuelve: +// El identificador del registro existente o el del insertado +// +// Especificaciones: +// En caso de producirse algún error se devuelve el valor 0 +// ________________________________________________________________________________________________________ + +int checkDato(struct og_dbi *dbi, char *dato, const char *tabla, + const char *nomdato, const char *nomidentificador) +{ + const char *msglog; + int identificador; + dbi_result result; + + if (strlen(dato) == 0) + return (0); // EL dato no tiene valor + result = dbi_conn_queryf(dbi->conn, + "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador, + tabla, nomdato, dato); + + // Ejecuta consulta + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return (0); + } + if (!dbi_result_next_row(result)) { // Software NO existente + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return (0); + } + dbi_result_free(result); + + // Recupera el identificador del software + identificador = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + identificador = dbi_result_get_uint(result, nomidentificador); + } + dbi_result_free(result); + + return (identificador); +} +// ________________________________________________________________________________________________________ +// Función: registraCliente +// +// Descripción: +// Incluye al cliente en la tabla de sokets +// Parámetros: +// - iph: Dirección ip del cliente +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool registraCliente(char *iph) +{ + int idx; + + if (!clienteExistente(iph, &idx)) { // Si no existe la IP ... + if (!hayHueco(&idx)) { // Busca hueco para el nuevo cliente + return false; // No hay huecos + } + } + strcpy(tbsockets[idx].ip, iph); // Copia IP + strcpy(tbsockets[idx].estado, CLIENTE_INICIANDO); // Actualiza el estado del cliente + return true; +} +// ________________________________________________________________________________________________________ +// Función: AutoexecCliente +// +// Descripción: +// Envía archivo de autoexec al cliente +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool AutoexecCliente(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + int lon; + char *iph, *exe; + FILE *fileexe; + char fileautoexec[LONPRM]; + char parametros[LONGITUD_PARAMETROS]; + struct og_dbi *dbi; + + iph = copiaParametro("iph",ptrTrama); // Toma dirección IP del cliente + exe = copiaParametro("exe",ptrTrama); // Toma identificador del procedimiento inicial + + sprintf(fileautoexec, "/tmp/Sautoexec-%s", iph); + liberaMemoria(iph); + fileexe = fopen(fileautoexec, "wb"); // Abre fichero de script + if (fileexe == NULL) { + syslog(LOG_ERR, "cannot create temporary file\n"); + return false; + } + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + initParametros(ptrTrama,0); + if (recorreProcedimientos(dbi, parametros, fileexe, exe)) { + lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r"); + lon += sprintf(ptrTrama->parametros + lon, "nfl=%s\r", fileautoexec); + lon += sprintf(ptrTrama->parametros + lon, "res=1\r"); + } else { + lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r"); + lon += sprintf(ptrTrama->parametros + lon, "res=0\r"); + } + + og_dbi_close(dbi); + fclose(fileexe); + + if (!mandaTrama(&socket_c, ptrTrama)) { + liberaMemoria(exe); + syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + return false; + } + liberaMemoria(exe); + return true; +} +// ________________________________________________________________________________________________________ +// Función: recorreProcedimientos +// +// Descripción: +// Crea un archivo con el código de un procedimiento separando cada comando por un salto de linea +// Parámetros: +// Database db,char* parametros,FILE* fileexe,char* idp +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool recorreProcedimientos(struct og_dbi *dbi, char *parametros, FILE *fileexe, char *idp) +{ + char idprocedimiento[LONPRM]; + int procedimientoid, lsize; + const char *msglog, *param; + dbi_result result; + + result = dbi_conn_queryf(dbi->conn, + "SELECT procedimientoid,parametros FROM procedimientos_acciones" + " WHERE idprocedimiento=%s ORDER BY orden", idp); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + while (dbi_result_next_row(result)) { + procedimientoid = dbi_result_get_uint(result, "procedimientoid"); + if (procedimientoid > 0) { // Procedimiento recursivo + sprintf(idprocedimiento, "%d", procedimientoid); + if (!recorreProcedimientos(dbi, parametros, fileexe, idprocedimiento)) { + return false; + } + } else { + param = dbi_result_get_string(result, "parametros"); + sprintf(parametros, "%s@", param); + lsize = strlen(parametros); + fwrite(parametros, 1, lsize, fileexe); // Escribe el código a ejecutar + } + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: ComandosPendientes +// +// Descripción: +// Esta función busca en la base de datos,comandos pendientes de ejecutar por un ordenador concreto +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool ComandosPendientes(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + char *ido,*iph,pids[LONPRM]; + int ids, idx; + + iph = copiaParametro("iph",ptrTrama); // Toma dirección IP + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!clienteExistente(iph, &idx)) { // Busca índice del cliente + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "client does not exist\n"); + return false; + } + if (buscaComandos(ido, ptrTrama, &ids)) { // Existen comandos pendientes + ptrTrama->tipo = MSG_COMANDO; + sprintf(pids, "\rids=%d\r", ids); + strcat(ptrTrama->parametros, pids); + strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); + } else { + initParametros(ptrTrama,0); + strcpy(ptrTrama->parametros, "nfn=NoComandosPtes\r"); + } + if (!mandaTrama(&socket_c, ptrTrama)) { + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + return false; + } + liberaMemoria(iph); + liberaMemoria(ido); + return true; +} +// ________________________________________________________________________________________________________ +// Función: buscaComandos +// +// Descripción: +// Busca en la base de datos,comandos pendientes de ejecutar por el cliente +// Parámetros: +// - ido: Identificador del ordenador +// - cmd: Parámetros del comando (Salida) +// - ids: Identificador de la sesion(Salida) +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool buscaComandos(char *ido, TRAMA *ptrTrama, int *ids) +{ + const char *param, *msglog; + struct og_dbi *dbi; + dbi_result result; + unsigned int lonprm; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + goto err_dbi_open; + } + result = dbi_conn_queryf(dbi->conn, + "SELECT sesion, parametros"\ + " FROM acciones WHERE idordenador=%s AND estado='%d'"\ + " ORDER BY idaccion", ido, ACCION_INICIADA); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + goto err_query_fail; + } + if (!dbi_result_next_row(result)) { + dbi_result_free(result); + og_dbi_close(dbi); + return false; // No hay comandos pendientes + } + + *ids = dbi_result_get_uint(result, "sesion"); + param = dbi_result_get_string(result, "parametros"); + lonprm = strlen(param); + + if(!initParametros(ptrTrama,lonprm + LONGITUD_PARAMETROS)){ + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + goto err_init_params; + } + sprintf(ptrTrama->parametros, "%s", param); + + dbi_result_free(result); + og_dbi_close(dbi); + + return true; // Hay comandos pendientes, se toma el primero de la cola + +err_init_params: + dbi_result_free(result); +err_query_fail: + og_dbi_close(dbi); +err_dbi_open: + return false; +} +// ________________________________________________________________________________________________________ +// Función: DisponibilidadComandos +// +// Descripción: +// Esta función habilita a un cliente para recibir comandos desde la consola +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +// +static bool DisponibilidadComandos(TRAMA *ptrTrama, struct og_client *cli) +{ + char *iph, *tpc; + int idx; + + iph = copiaParametro("iph",ptrTrama); // Toma ip + if (!clienteExistente(iph, &idx)) { // Busca índice del cliente + liberaMemoria(iph); + syslog(LOG_ERR, "client does not exist\n"); + return false; + } + tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.) + strcpy(tbsockets[idx].estado, tpc); + cli->keepalive_idx = idx; + liberaMemoria(iph); + liberaMemoria(tpc); + return true; +} +// ________________________________________________________________________________________________________ +// Función: respuestaEstandar +// +// Descripción: +// Esta función actualiza la base de datos con el resultado de la ejecución de un comando con seguimiento +// Parámetros: +// - res: resultado de la ejecución del comando +// - der: Descripción del error si hubiese habido +// - iph: Dirección IP +// - ids: identificador de la sesión +// - ido: Identificador del ordenador que notifica +// - db: Objeto base de datos (operativo) +// - tbl: Objeto tabla +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool respuestaEstandar(TRAMA *ptrTrama, char *iph, char *ido, + struct og_dbi *dbi) +{ + char *res, *ids, *der; + char fechafin[LONPRM]; + const char *msglog; + dbi_result result; + struct tm* st; + int idaccion; + + ids = copiaParametro("ids",ptrTrama); + res = copiaParametro("res",ptrTrama); + + if (ids == NULL) { + if (atoi(res) == ACCION_FALLIDA) { + liberaMemoria(res); + return false; + } + liberaMemoria(res); + return true; + } + + if (atoi(ids) == 0) { + liberaMemoria(ids); + if (atoi(res) == ACCION_FALLIDA) { + liberaMemoria(res); + return false; + } + liberaMemoria(res); + return true; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT * FROM acciones WHERE idordenador=%s" + " AND sesion=%s ORDER BY idaccion", ido,ids); + + liberaMemoria(ids); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "no actions available\n"); + dbi_result_free(result); + return true; + } + + idaccion = dbi_result_get_uint(result, "idaccion"); + dbi_result_free(result); + + st = tomaHora(); + sprintf(fechafin, "%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1, + st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec); + + der = copiaParametro("der",ptrTrama); // Toma descripción del error (si hubiera habido) + + result = dbi_conn_queryf(dbi->conn, + "UPDATE acciones"\ + " SET resultado='%s',estado='%d',fechahorafin='%s',descrinotificacion='%s'"\ + " WHERE idordenador=%s AND idaccion=%d", + res, ACCION_FINALIZADA, fechafin, der, ido, idaccion); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + liberaMemoria(res); + liberaMemoria(der); + og_info((char *)msglog); + return false; + } + dbi_result_free(result); + + liberaMemoria(der); + + if (atoi(res) == ACCION_FALLIDA) { + liberaMemoria(res); + return false; + } + + liberaMemoria(res); + return true; +} + +static bool og_send_cmd(char *ips_array[], int ips_array_len, + const char *state, TRAMA *ptrTrama) +{ + int i, idx; + + for (i = 0; i < ips_array_len; i++) { + if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos + int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1; + + strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente + if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) { + syslog(LOG_ERR, "failed to send response to %s:%s\n", + ips_array[i], strerror(errno)); + } + } + } + return true; +} + +// ________________________________________________________________________________________________________ +// Función: enviaComando +// +// Descripción: +// Envía un comando a los clientes +// Parámetros: +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// - estado: Estado en el se deja al cliente mientras se ejecuta el comando +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool enviaComando(TRAMA* ptrTrama, const char *estado) +{ + char *iph, *Ipes, *ptrIpes[MAXIMOS_CLIENTES]; + int lon; + + iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP + lon = strlen(iph); // Calcula longitud de la cadena de direccion/es IPE/S + Ipes = (char*) reservaMemoria(lon + 1); + if (Ipes == NULL) { + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + return false; + } + + strcpy(Ipes, iph); // Copia cadena de IPES + liberaMemoria(iph); + + lon = splitCadena(ptrIpes, Ipes, ';'); + FINCADaINTRO(ptrTrama); + + if (!og_send_cmd(ptrIpes, lon, estado, ptrTrama)) + return false; + + liberaMemoria(Ipes); + return true; +} +//______________________________________________________________________________________________________ +// Función: respuestaConsola +// +// Descripción: +// Envia una respuesta a la consola sobre el resultado de la ejecución de un comando +// Parámetros: +// - socket_c: (Salida) Socket utilizado para el envío +// - res: Resultado del envío del comando +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool respuestaConsola(int socket_c, TRAMA *ptrTrama, int res) +{ + initParametros(ptrTrama,0); + sprintf(ptrTrama->parametros, "res=%d\r", res); + if (!mandaTrama(&socket_c, ptrTrama)) { + syslog(LOG_ERR, "%s:%d failed to send response: %s\n", + __func__, __LINE__, strerror(errno)); + return false; + } + return true; +} +// ________________________________________________________________________________________________________ +// Función: Levanta +// +// Descripción: +// Enciende ordenadores a través de la red cuyas macs se pasan como parámetro +// Parámetros: +// - iph: Cadena de direcciones ip separadas por ";" +// - mac: Cadena de direcciones mac separadas por ";" +// - mar: Método de arranque (1=Broadcast, 2=Unicast) +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ + +bool Levanta(char *ptrIP[], char *ptrMacs[], int lon, char *mar) +{ + unsigned int on = 1; + struct sockaddr_in local; + int i, res; + int s; + + /* Creación de socket para envío de magig packet */ + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) { + syslog(LOG_ERR, "cannot create socket for magic packet\n"); + return false; + } + res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on, + sizeof(on)); + if (res < 0) { + syslog(LOG_ERR, "cannot set broadcast socket\n"); + return false; + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(PUERTO_WAKEUP); + local.sin_addr.s_addr = htonl(INADDR_ANY); + + for (i = 0; i < lon; i++) { + if (!WakeUp(s, ptrIP[i], ptrMacs[i], mar)) { + syslog(LOG_ERR, "problem sending magic packet\n"); + close(s); + return false; + } + } + 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; + } + freeifaddrs(ifaddr); + + ret = sendto(sd, msg, sizeof(*msg), 0, + (struct 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, + (struct 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 +// +// Descripción: +// Enciende el ordenador cuya MAC se pasa como parámetro +// Parámetros: +// - s : Socket para enviar trama magic packet +// - iph : Cadena con la dirección ip +// - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX +// - mar: Método de arranque (1=Broadcast, 2=Unicast) +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +//_____________________________________________________________________________________________________________ +// +bool WakeUp(int s, char* iph, char *mac, char *mar) +{ + unsigned int macaddr[OG_WOL_MACADDR_LEN]; + 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; + + sscanf(mac, "%02x%02x%02x%02x%02x%02x", + &macaddr[0], &macaddr[1], &macaddr[2], + &macaddr[3], &macaddr[4], &macaddr[5]); + + for (i = 0; i < 6; i++) + HDaddress_bin[i] = (uint8_t)macaddr[i]; + + for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC + memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6); + + /* Creación de socket del cliente que recibe la trama magic packet */ + WakeUpCliente.sin_family = AF_INET; + WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP); + + 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 ret; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_Arrancar +// +// Descripción: +// Respuesta del cliente al comando Arrancar +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_Arrancar(TRAMA* ptrTrama, struct og_client *cli) +{ + struct og_dbi *dbi; + char *iph, *ido; + char *tpc; + int i; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + og_dbi_close(dbi); + return false; + } + + tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.) + if (clienteExistente(iph, &i)) // Actualiza estado + strcpy(tbsockets[i].estado, tpc); + + liberaMemoria(iph); + liberaMemoria(ido); + liberaMemoria(tpc); + og_dbi_close(dbi); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_Apagar +// +// Descripción: +// Respuesta del cliente al comando Apagar +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli) +{ + struct og_dbi *dbi; + char *iph, *ido; + int i; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + og_dbi_close(dbi); + return false; // Error al registrar notificacion + } + + if (clienteExistente(iph, &i)) // Actualiza estado + strcpy(tbsockets[i].estado, CLIENTE_APAGADO); + + liberaMemoria(iph); + liberaMemoria(ido); + og_dbi_close(dbi); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_CrearImagen +// +// Descripción: +// Respuesta del cliente al comando CrearImagen +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli) +{ + char *iph, *dsk, *par, *cpt, *ipr, *ido; + struct og_dbi *dbi; + char *idi; + bool res; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + og_dbi_close(dbi); + return false; // Error al registrar notificacion + } + + // Acciones posteriores + idi = copiaParametro("idi",ptrTrama); + dsk = copiaParametro("dsk",ptrTrama); + par = copiaParametro("par",ptrTrama); + cpt = copiaParametro("cpt",ptrTrama); + ipr = copiaParametro("ipr",ptrTrama); + + res=actualizaCreacionImagen(dbi, idi, dsk, par, cpt, ipr, ido); + + liberaMemoria(idi); + liberaMemoria(par); + liberaMemoria(cpt); + liberaMemoria(ipr); + og_dbi_close(dbi); + + if (!res) + syslog(LOG_ERR, "Problem processing update\n"); + + return res; +} +// ________________________________________________________________________________________________________ +// Función: actualizaCreacionImagen +// +// Descripción: +// Esta función actualiza la base de datos con el resultado de la creación de una imagen +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idi: Identificador de la imagen +// - dsk: Disco de donde se creó +// - par: Partición de donde se creó +// - cpt: Código de partición +// - ipr: Ip del repositorio +// - ido: Identificador del ordenador modelo +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool actualizaCreacionImagen(struct og_dbi *dbi, char *idi, char *dsk, + char *par, char *cpt, char *ipr, char *ido) +{ + const char *msglog; + dbi_result result; + int idr,ifs; + + /* Toma identificador del repositorio correspondiente al ordenador modelo */ + result = dbi_conn_queryf(dbi->conn, + "SELECT repositorios.idrepositorio" + " FROM repositorios" + " LEFT JOIN ordenadores USING (idrepositorio)" + " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, + "repository does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + idr = dbi_result_get_uint(result, "idrepositorio"); + dbi_result_free(result); + + /* Toma identificador del perfilsoftware */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft" + " FROM ordenadores_particiones" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, + "software profile does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + ifs = dbi_result_get_uint(result, "idperfilsoft"); + dbi_result_free(result); + + /* Actualizar los datos de la imagen */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE imagenes" + " SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s," + " idperfilsoft=%d, idrepositorio=%d," + " fechacreacion=NOW(), revision=revision+1" + " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + /* Actualizar los datos en el cliente */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones" + " SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," + " fechadespliegue=NOW()" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", + idi, idi, ido, dsk, par); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: CrearImagenBasica +// +// Descripción: +// Crea una imagen basica usando sincronización +// Parámetros: +// - socket_c: Socket de la consola al envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli) +{ + if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) { + respuestaConsola(og_client_socket(cli), ptrTrama, false); + return false; + } + respuestaConsola(og_client_socket(cli), ptrTrama, true); + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_CrearImagenBasica +// +// Descripción: +// Respuesta del cliente al comando CrearImagenBasica +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli) +{ + // La misma respuesta que la creación de imagen monolítica + return RESPUESTA_CrearImagen(ptrTrama, cli); +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_CrearSoftIncremental +// +// Descripción: +// Respuesta del cliente al comando crearImagenDiferencial +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli) +{ + char *iph,*par,*ido,*idf; + int ifs; + const char *msglog; + struct og_dbi *dbi; + dbi_result result; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + og_dbi_close(dbi); + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + return false; + } + + par = copiaParametro("par",ptrTrama); + + /* Toma identificador del perfilsoftware creado por el inventario de software */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s", + ido, par); + liberaMemoria(iph); + liberaMemoria(ido); + liberaMemoria(par); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return false; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, + "software profile does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + og_dbi_close(dbi); + return false; + } + ifs = dbi_result_get_uint(result, "idperfilsoft"); + dbi_result_free(result); + + /* Actualizar los datos de la imagen */ + idf = copiaParametro("idf", ptrTrama); + result = dbi_conn_queryf(dbi->conn, + "UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s", + ifs, idf); + liberaMemoria(idf); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return false; + } + dbi_result_free(result); + + og_dbi_close(dbi); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_RestaurarImagen +// +// Descripción: +// Respuesta del cliente al comando RestaurarImagen +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +// +static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli) +{ + bool res; + char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg; + struct og_dbi *dbi; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + og_dbi_close(dbi); + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + return false; + } + + // Acciones posteriores + idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen + dsk = copiaParametro("dsk",ptrTrama); // Número de disco + par = copiaParametro("par",ptrTrama); // Número de partición + ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido + cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos + if(cfg){ + actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador + liberaMemoria(cfg); + } + res=actualizaRestauracionImagen(dbi, idi, dsk, par, ido, ifs); + + liberaMemoria(iph); + liberaMemoria(ido); + liberaMemoria(idi); + liberaMemoria(par); + liberaMemoria(ifs); + og_dbi_close(dbi); + + if(!res) + syslog(LOG_ERR, "Problem after restoring image\n"); + + return res; +} +// ________________________________________________________________________________________________________ +// +// Función: RESPUESTA_RestaurarImagenBasica +// +// Descripción: +// Respuesta del cliente al comando RestaurarImagen +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +// +static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli) +{ + return RESPUESTA_RestaurarImagen(ptrTrama, cli); +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_RestaurarSoftIncremental +// +// Descripción: +// Respuesta del cliente al comando RestaurarSoftIncremental +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli) +{ + return RESPUESTA_RestaurarImagen(ptrTrama, cli); +} +// ________________________________________________________________________________________________________ +// Función: actualizaRestauracionImagen +// +// Descripción: +// Esta función actualiza la base de datos con el resultado de la restauración de una imagen +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idi: Identificador de la imagen +// - dsk: Disco de donde se restauró +// - par: Partición de donde se restauró +// - ido: Identificador del cliente donde se restauró +// - ifs: Identificador del perfil software contenido en la imagen +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool actualizaRestauracionImagen(struct og_dbi *dbi, char *idi, + char *dsk, char *par, char *ido, char *ifs) +{ + const char *msglog; + dbi_result result; + + /* Actualizar los datos de la imagen */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones" + " SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW()," + " revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," + " idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_EjecutarScript +// +// Descripción: +// Respuesta del cliente al comando EjecutarScript +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli) +{ + char *iph, *ido,*cfg; + struct og_dbi *dbi; + bool res = true; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + og_dbi_close(dbi); + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + return false; + } + + cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones + if(cfg){ + res = actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador + liberaMemoria(cfg); + } + + liberaMemoria(iph); + liberaMemoria(ido); + og_dbi_close(dbi); + + if (!res) + syslog(LOG_ERR, "Problem updating client configuration\n"); + + return res; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_InventarioHardware +// +// Descripción: +// Respuesta del cliente al comando InventarioHardware +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli) +{ + bool res; + char *iph, *ido, *idc, *npc, *hrd, *buffer; + struct og_dbi *dbi; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente + ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + og_dbi_close(dbi); + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + return false; + } + // Lee archivo de inventario enviado anteriormente + hrd = copiaParametro("hrd",ptrTrama); + buffer = rTrim(leeArchivo(hrd)); + + npc = copiaParametro("npc",ptrTrama); + idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro + + if (buffer) + res=actualizaHardware(dbi, buffer, ido, npc, idc); + + liberaMemoria(iph); + liberaMemoria(ido); + liberaMemoria(npc); + liberaMemoria(idc); + liberaMemoria(buffer); + og_dbi_close(dbi); + + if (!res) + syslog(LOG_ERR, "Problem updating client configuration\n"); + + return res; +} +// ________________________________________________________________________________________________________ +// Función: actualizaHardware +// +// Descripción: +// Actualiza la base de datos con la configuracion hardware del cliente +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - hrd: cadena con el inventario hardware +// - ido: Identificador del ordenador +// - npc: Nombre del ordenador +// - idc: Identificador del centro o Unidad organizativa +// ________________________________________________________________________________________________________ +// +bool actualizaHardware(struct og_dbi *dbi, char *hrd, char *ido, char *npc, + char *idc) +{ + const char *msglog; + int idtipohardware, idperfilhard; + int lon, i, j, aux; + bool retval; + char *whard; + int tbidhardware[MAXHARDWARE]; + char *tbHardware[MAXHARDWARE],*dualHardware[2], strInt[LONINT], *idhardwares; + dbi_result result; + + /* Toma Centro (Unidad Organizativa) */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilhard FROM ordenadores WHERE idordenador=%s", + ido); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + idperfilhard = dbi_result_get_uint(result, "idperfilhard"); + dbi_result_free(result); + + whard=escaparCadena(hrd); // Codificar comillas simples + if(!whard) + return false; + /* Recorre componentes hardware*/ + lon = splitCadena(tbHardware, whard, '\n'); + if (lon > MAXHARDWARE) + lon = MAXHARDWARE; // Limita el número de componentes hardware + /* + for (i=0;iconn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { // Tipo de Hardware NO existente + dbi_result_free(result); + return false; + } else { // Tipo de Hardware Existe + idtipohardware = dbi_result_get_uint(result, "idtipohardware"); + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "SELECT idhardware FROM hardwares WHERE idtipohardware=%d AND descripcion='%s'", + idtipohardware, dualHardware[1]); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + if (!dbi_result_next_row(result)) { // Hardware NO existente + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) " + " VALUES(%d,'%s',%s,0)", idtipohardware, + dualHardware[1], idc); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + // Recupera el identificador del hardware + tbidhardware[i] = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + tbidhardware[i] = dbi_result_get_uint(result, "idhardware"); + } + dbi_result_free(result); + } + } + // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones + + for (i = 0; i < lon - 1; i++) { + for (j = i + 1; j < lon; j++) { + if (tbidhardware[i] > tbidhardware[j]) { + aux = tbidhardware[i]; + tbidhardware[i] = tbidhardware[j]; + tbidhardware[j] = aux; + } + } + } + /* Crea cadena de identificadores de componentes hardware separados por coma */ + sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud + aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles + idhardwares = reservaMemoria(sizeof(aux) * lon + lon); + if (idhardwares == NULL) { + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + return false; + } + aux = sprintf(idhardwares, "%d", tbidhardware[0]); + for (i = 1; i < lon; i++) + aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]); + + if (!cuestionPerfilHardware(dbi, idc, ido, idperfilhard, idhardwares, + npc, tbidhardware, lon)) { + syslog(LOG_ERR, "Problem updating client hardware\n"); + retval=false; + } + else { + retval=true; + } + liberaMemoria(whard); + liberaMemoria(idhardwares); + return (retval); +} +// ________________________________________________________________________________________________________ +// Función: cuestionPerfilHardware +// +// Descripción: +// Comprueba existencia de perfil hardware y actualización de éste para el ordenador +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idc: Identificador de la Unidad organizativa donde se encuentra el cliente +// - ido: Identificador del ordenador +// - tbidhardware: Identificador del tipo de hardware +// - con: Número de componentes detectados para configurar un el perfil hardware +// - npc: Nombre del cliente +// ________________________________________________________________________________________________________ +bool cuestionPerfilHardware(struct og_dbi *dbi, char *idc, char *ido, + int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware, + int lon) +{ + const char *msglog; + dbi_result result; + int i; + int nwidperfilhard; + + // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilhard FROM" + " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard," + " group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )" + " ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares" + " FROM perfileshard_hardwares" + " GROUP BY perfileshard_hardwares.idperfilhard) AS temp" + " WHERE idhardwares LIKE '%s'", idhardwares); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { + // No existe un perfil hardware con esos componentes de componentes hardware, lo crea + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT perfileshard (descripcion,idcentro,grupoid)" + " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + // Recupera el identificador del nuevo perfil hardware + nwidperfilhard = dbi_conn_sequence_last(dbi->conn, NULL); + + // Crea la relación entre perfiles y componenetes hardware + for (i = 0; i < lon; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT perfileshard_hardwares (idperfilhard,idhardware)" + " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + } + } else { // Existe un perfil con todos esos componentes + nwidperfilhard = dbi_result_get_uint(result, "idperfilhard"); + dbi_result_free(result); + } + if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles + // Actualiza el identificador del perfil hardware del ordenador + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET idperfilhard=%d" + " WHERE idordenador=%s", nwidperfilhard, ido); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + } + /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN " + " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN" + " (SELECT DISTINCT idperfilhard from ordenadores))"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + /* Eliminar Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard WHERE idperfilhard NOT IN" + " (SELECT DISTINCT idperfilhard FROM ordenadores)"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN" + " (SELECT idperfilhard FROM perfileshard)"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: RESPUESTA_InventarioSoftware +// +// Descripción: +// Respuesta del cliente al comando InventarioSoftware +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli) +{ + bool res; + char *iph, *ido, *npc, *idc, *par, *sft, *buffer; + struct og_dbi *dbi; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + iph = copiaParametro("iph",ptrTrama); // Toma dirección ip + ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador + + if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { + og_dbi_close(dbi); + liberaMemoria(iph); + liberaMemoria(ido); + syslog(LOG_ERR, "failed to register notification\n"); + return false; + } + + npc = copiaParametro("npc",ptrTrama); + idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro + par = copiaParametro("par",ptrTrama); + sft = copiaParametro("sft",ptrTrama); + + buffer = rTrim(leeArchivo(sft)); + if (buffer) + res=actualizaSoftware(dbi, buffer, par, ido, npc, idc); + + liberaMemoria(iph); + liberaMemoria(ido); + liberaMemoria(npc); + liberaMemoria(idc); + liberaMemoria(par); + liberaMemoria(sft); + og_dbi_close(dbi); + + if (!res) + syslog(LOG_ERR, "cannot update software\n"); + + return res; +} +// ________________________________________________________________________________________________________ +// Función: actualizaSoftware +// +// Descripción: +// Actualiza la base de datos con la configuración software del cliente +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - sft: cadena con el inventario software +// - par: Número de la partición +// - ido: Identificador del ordenador del cliente en la tabla +// - npc: Nombre del ordenador +// - idc: Identificador del centro o Unidad organizativa +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// +// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla +// ________________________________________________________________________________________________________ +bool actualizaSoftware(struct og_dbi *dbi, char *sft, char *par,char *ido, + char *npc, char *idc) +{ + int i, j, lon, aux, idperfilsoft, idnombreso; + bool retval; + char *wsft; + int tbidsoftware[MAXSOFTWARE]; + char *tbSoftware[MAXSOFTWARE], strInt[LONINT], *idsoftwares; + const char *msglog; + dbi_result result; + + /* Toma Centro (Unidad Organizativa) y perfil software */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft,numpar" + " FROM ordenadores_particiones" + " WHERE idordenador=%s", ido); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software + while (dbi_result_next_row(result)) { + aux = dbi_result_get_uint(result, "numpar"); + if (aux == atoi(par)) { // Se encuentra la partición + idperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); + break; + } + } + dbi_result_free(result); + wsft=escaparCadena(sft); // Codificar comillas simples + if(!wsft) + return false; + + /* Recorre componentes software*/ + lon = splitCadena(tbSoftware, wsft, '\n'); + + if (lon == 0) + return true; // No hay lineas que procesar + if (lon > MAXSOFTWARE) + lon = MAXSOFTWARE; // Limita el número de componentes software + + for (i = 0; i < lon; i++) { + // Primera línea es el sistema operativo: se obtiene identificador + if (i == 0) { + idnombreso = checkDato(dbi, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso"); + continue; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT idsoftware FROM softwares WHERE descripcion ='%s'", + rTrim(tbSoftware[i])); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + if (!dbi_result_next_row(result)) { + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)" + " VALUES(2,'%s',%s,0)", tbSoftware[i], idc); + if (!result) { // Error al insertar + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result); + + // Recupera el identificador del software + tbidsoftware[i] = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + tbidsoftware[i] = dbi_result_get_uint(result, "idsoftware"); + } + } + + // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones + + for (i = 0; i < lon - 1; i++) { + for (j = i + 1; j < lon; j++) { + if (tbidsoftware[i] > tbidsoftware[j]) { + aux = tbidsoftware[i]; + tbidsoftware[i] = tbidsoftware[j]; + tbidsoftware[j] = aux; + } + } + } + /* Crea cadena de identificadores de componentes software separados por coma */ + sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud + aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles + idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon); + if (idsoftwares == NULL) { + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + return false; + } + aux = sprintf(idsoftwares, "%d", tbidsoftware[0]); + for (i = 1; i < lon; i++) + aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]); + + // Comprueba existencia de perfil software y actualización de éste para el ordenador + if (!cuestionPerfilSoftware(dbi, idc, ido, idperfilsoft, idnombreso, idsoftwares, + npc, par, tbidsoftware, lon)) { + syslog(LOG_ERR, "cannot update software\n"); + og_info((char *)msglog); + retval=false; + } + else { + retval=true; + } + liberaMemoria(wsft); + liberaMemoria(idsoftwares); + return (retval); +} +// ________________________________________________________________________________________________________ +// Función: CuestionPerfilSoftware +// +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idcentro: Identificador del centro en la tabla +// - ido: Identificador del ordenador del cliente en la tabla +// - idnombreso: Identificador del sistema operativo +// - idsoftwares: Cadena con los identificadores de componentes software separados por comas +// - npc: Nombre del ordenador del cliente +// - particion: Número de la partición +// - tbidsoftware: Array con los identificadores de componentes software +// - lon: Número de componentes +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// +// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla +//_________________________________________________________________________________________________________ +bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido, + int idperfilsoftware, int idnombreso, + char *idsoftwares, char *npc, char *par, + int *tbidsoftware, int lon) +{ + int i, nwidperfilsoft; + const char *msglog; + dbi_result result; + + // Busca perfil soft del ordenador que contenga todos los componentes software encontrados + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft FROM" + " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft," + " group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )" + " ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares" + " FROM perfilessoft_softwares" + " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp" + " WHERE idsoftwares LIKE '%s'", idsoftwares); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + if (!dbi_result_next_row(result)) { // No existe un perfil software con esos componentes de componentes software, lo crea + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT perfilessoft (descripcion, idcentro, grupoid, idnombreso)" + " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + + dbi_result_free(result); + // Recupera el identificador del nuevo perfil software + nwidperfilsoft = dbi_conn_sequence_last(dbi->conn, NULL); + + // Crea la relación entre perfiles y componenetes software + for (i = 0; i < lon; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)" + " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result); + } + } else { // Existe un perfil con todos esos componentes + nwidperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); + dbi_result_free(result); + } + + if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles + // Actualiza el identificador del perfil software del ordenador + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0" + " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par); + if (!result) { // Error al insertar + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result); + } + + /* DEPURACIÓN DE PERFILES SOFTWARE */ + + /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\ + " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from imagenes))"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result), + /* Eliminar Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN" + " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\ + " AND idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from imagenes)"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result), + + /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN" + " (SELECT idperfilsoft from perfilessoft)"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + og_info((char *)msglog); + return false; + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: enviaArchivo +// +// Descripción: +// Envia un archivo por la red, por bloques +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + char *nfl; + + // Toma parámetros + nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo + if (!sendArchivo(&socket_c, nfl)) { + liberaMemoria(nfl); + syslog(LOG_ERR, "Problem sending file\n"); + return false; + } + liberaMemoria(nfl); + return true; +} +// ________________________________________________________________________________________________________ +// Función: enviaArchivo +// +// Descripción: +// Envia un archivo por la red, por bloques +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli) +{ + int socket_c = og_client_socket(cli); + char *nfl; + + // Toma parámetros + nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo + ptrTrama->tipo = MSG_NOTIFICACION; + enviaFlag(&socket_c, ptrTrama); + if (!recArchivo(&socket_c, nfl)) { + liberaMemoria(nfl); + syslog(LOG_ERR, "Problem receiving file\n"); + return false; + } + liberaMemoria(nfl); + return true; +} +// ________________________________________________________________________________________________________ +// Función: envioProgramacion +// +// Descripción: +// Envia un comando de actualización a todos los ordenadores que han sido programados con +// alguna acción para que entren en el bucle de comandos pendientes y las ejecuten +// Parámetros: +// - socket_c: Socket del cliente que envió el mensaje +// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli) +{ + char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES]; + char *idp, *iph, *mac; + int idx,idcomando,lon; + const char *msglog; + struct og_dbi *dbi; + dbi_result result; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return false; + } + + idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones + + result = dbi_conn_queryf(dbi->conn, + "SELECT ordenadores.ip,ordenadores.mac,acciones.idcomando FROM acciones "\ + " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\ + " WHERE acciones.idprogramacion=%s",idp); + + liberaMemoria(idp); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return false; + } + + /* Prepara la trama de actualizacion */ + + initParametros(ptrTrama,0); + ptrTrama->tipo=MSG_COMANDO; + sprintf(ptrTrama->parametros, "nfn=Actualizar\r"); + + while (dbi_result_next_row(result)) { + iph = (char *)dbi_result_get_string(result, "ip"); + idcomando = dbi_result_get_uint(result, "idcomando"); + + if (idcomando == 1){ // Arrancar + mac = (char *)dbi_result_get_string(result, "mac"); + lon = splitCadena(ptrIP, iph, ';'); + lon = splitCadena(ptrMacs, mac, ';'); + + // Se manda por broadcast y por unicast + if (!Levanta(ptrIP, ptrMacs, lon, (char*)"1")) { + dbi_result_free(result); + og_dbi_close(dbi); + return false; + } + + if (!Levanta(ptrIP, ptrMacs, lon, (char*)"2")) { + dbi_result_free(result); + og_dbi_close(dbi); + return false; + } + + } + if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos + int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1; + + strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente + if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) { + syslog(LOG_ERR, "failed to send response: %s\n", + strerror(errno)); + } + //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad + } + } + dbi_result_free(result); + og_dbi_close(dbi); + + return true; // No existen registros +} + +// This object stores function handler for messages +static struct { + const char *nf; // Nombre de la función + bool (*fcn)(TRAMA *, struct og_client *cli); +} tbfuncionesServer[] = { + { "InclusionCliente", InclusionCliente, }, + { "InclusionClienteWinLnx", InclusionClienteWinLnx, }, + { "AutoexecCliente", AutoexecCliente, }, + { "ComandosPendientes", ComandosPendientes, }, + { "DisponibilidadComandos", DisponibilidadComandos, }, + { "RESPUESTA_Arrancar", RESPUESTA_Arrancar, }, + { "RESPUESTA_Apagar", RESPUESTA_Apagar, }, + { "RESPUESTA_Reiniciar", RESPUESTA_Apagar, }, + { "RESPUESTA_IniciarSesion", RESPUESTA_Apagar, }, + { "RESPUESTA_CrearImagen", RESPUESTA_CrearImagen, }, + { "CrearImagenBasica", CrearImagenBasica, }, + { "RESPUESTA_CrearImagenBasica", RESPUESTA_CrearImagenBasica, }, + { "CrearSoftIncremental", CrearImagenBasica, }, + { "RESPUESTA_CrearSoftIncremental", RESPUESTA_CrearSoftIncremental, }, + { "RESPUESTA_RestaurarImagen", RESPUESTA_RestaurarImagen }, + { "RestaurarImagenBasica", CrearImagenBasica, }, + { "RESPUESTA_RestaurarImagenBasica", RESPUESTA_RestaurarImagenBasica, }, + { "RestaurarSoftIncremental", CrearImagenBasica, }, + { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, }, + { "Configurar", CrearImagenBasica, }, + { "RESPUESTA_Configurar", RESPUESTA_EjecutarScript, }, + { "EjecutarScript", CrearImagenBasica, }, + { "RESPUESTA_EjecutarScript", RESPUESTA_EjecutarScript, }, + { "RESPUESTA_InventarioHardware", RESPUESTA_InventarioHardware, }, + { "RESPUESTA_InventarioSoftware", RESPUESTA_InventarioSoftware, }, + { "enviaArchivo", enviaArchivo, }, + { "recibeArchivo", recibeArchivo, }, + { "envioProgramacion", envioProgramacion, }, + { NULL, NULL, }, +}; + +// ________________________________________________________________________________________________________ +// Función: gestionaTrama +// +// Descripción: +// Procesa las tramas recibidas . +// Parametros: +// - s : Socket usado para comunicaciones +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli) +{ + int i, res; + char *nfn; + + if (ptrTrama){ + INTROaFINCAD(ptrTrama); + nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función + + for (i = 0; tbfuncionesServer[i].fcn; i++) { + if (!strncmp(tbfuncionesServer[i].nf, nfn, + strlen(tbfuncionesServer[i].nf))) { + res = tbfuncionesServer[i].fcn(ptrTrama, cli); + if (!res) { + syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n", + tbfuncionesServer[i].nf, + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + } else { + syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n", + tbfuncionesServer[i].nf, + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + } + break; + } + } + if (!tbfuncionesServer[i].fcn) + syslog(LOG_ERR, "unknown request %s from client %s:%hu\n", + nfn, inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + + liberaMemoria(nfn); + } +} + +static void og_client_release(struct ev_loop *loop, struct og_client *cli) +{ + if (cli->keepalive_idx >= 0) { + syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port), cli->keepalive_idx); + tbsockets[cli->keepalive_idx].cli = NULL; + } + + ev_io_stop(loop, &cli->io); + close(cli->io.fd); + free(cli); +} + +static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli) +{ + struct og_client *old_cli; + + old_cli = tbsockets[cli->keepalive_idx].cli; + if (old_cli && old_cli != cli) { + syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n", + inet_ntoa(old_cli->addr.sin_addr), + ntohs(old_cli->addr.sin_port)); + + og_client_release(loop, old_cli); + } + tbsockets[cli->keepalive_idx].cli = cli; +} + +static void og_client_reset_state(struct og_client *cli) +{ + cli->state = OG_CLIENT_RECEIVING_HEADER; + cli->buf_len = 0; +} + +static int og_client_state_recv_hdr(struct og_client *cli) +{ + char hdrlen[LONHEXPRM]; + + /* Still too short to validate protocol fingerprint and message + * length. + */ + if (cli->buf_len < 15 + LONHEXPRM) + return 0; + + if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) { + syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + return -1; + } + + memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM); + cli->msg_len = strtol(hdrlen, NULL, 16); + + /* Header announces more that we can fit into buffer. */ + if (cli->msg_len >= sizeof(cli->buf)) { + syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n", + cli->msg_len, inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + return -1; + } + + return 1; +} + +static TRAMA *og_msg_alloc(char *data, unsigned int len) +{ + TRAMA *ptrTrama; + + ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA)); + if (!ptrTrama) { + syslog(LOG_ERR, "OOM\n"); + return NULL; + } + + initParametros(ptrTrama, len); + memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA); + memcpy(ptrTrama->parametros, data, len); + ptrTrama->lonprm = len; + + return ptrTrama; +} + +static void og_msg_free(TRAMA *ptrTrama) +{ + liberaMemoria(ptrTrama->parametros); + liberaMemoria(ptrTrama); +} + +static int og_client_state_process_payload(struct og_client *cli) +{ + TRAMA *ptrTrama; + char *data; + int len; + + len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM); + data = &cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM]; + + ptrTrama = og_msg_alloc(data, len); + if (!ptrTrama) + return -1; + + gestionaTrama(ptrTrama, cli); + + og_msg_free(ptrTrama); + + return 1; +} + +#define OG_CLIENTS_MAX 4096 +#define OG_PARTITION_MAX 4 + +struct og_partition { + const char *number; + const char *code; + const char *size; + const char *filesystem; + const char *format; +}; + +struct og_sync_params { + const char *sync; + const char *diff; + const char *remove; + const char *compress; + const char *cleanup; + const char *cache; + const char *cleanup_cache; + const char *remove_dst; + const char *diff_id; + const char *diff_name; + const char *path; + const char *method; +}; + +struct og_msg_params { + const char *ips_array[OG_CLIENTS_MAX]; + const char *mac_array[OG_CLIENTS_MAX]; + unsigned int ips_array_len; + const char *wol_type; + char run_cmd[4096]; + const char *disk; + const char *partition; + const char *repository; + const char *name; + const char *id; + const char *code; + const char *type; + const char *profile; + const char *cache; + const char *cache_size; + bool echo; + struct og_partition partition_setup[OG_PARTITION_MAX]; + struct og_sync_params sync_setup; + uint64_t flags; +}; + +#define OG_REST_PARAM_ADDR (1UL << 0) +#define OG_REST_PARAM_MAC (1UL << 1) +#define OG_REST_PARAM_WOL_TYPE (1UL << 2) +#define OG_REST_PARAM_RUN_CMD (1UL << 3) +#define OG_REST_PARAM_DISK (1UL << 4) +#define OG_REST_PARAM_PARTITION (1UL << 5) +#define OG_REST_PARAM_REPO (1UL << 6) +#define OG_REST_PARAM_NAME (1UL << 7) +#define OG_REST_PARAM_ID (1UL << 8) +#define OG_REST_PARAM_CODE (1UL << 9) +#define OG_REST_PARAM_TYPE (1UL << 10) +#define OG_REST_PARAM_PROFILE (1UL << 11) +#define OG_REST_PARAM_CACHE (1UL << 12) +#define OG_REST_PARAM_CACHE_SIZE (1UL << 13) +#define OG_REST_PARAM_PART_0 (1UL << 14) +#define OG_REST_PARAM_PART_1 (1UL << 15) +#define OG_REST_PARAM_PART_2 (1UL << 16) +#define OG_REST_PARAM_PART_3 (1UL << 17) +#define OG_REST_PARAM_SYNC_SYNC (1UL << 18) +#define OG_REST_PARAM_SYNC_DIFF (1UL << 19) +#define OG_REST_PARAM_SYNC_REMOVE (1UL << 20) +#define OG_REST_PARAM_SYNC_COMPRESS (1UL << 21) +#define OG_REST_PARAM_SYNC_CLEANUP (1UL << 22) +#define OG_REST_PARAM_SYNC_CACHE (1UL << 23) +#define OG_REST_PARAM_SYNC_CLEANUP_CACHE (1UL << 24) +#define OG_REST_PARAM_SYNC_REMOVE_DST (1UL << 25) +#define OG_REST_PARAM_SYNC_DIFF_ID (1UL << 26) +#define OG_REST_PARAM_SYNC_DIFF_NAME (1UL << 27) +#define OG_REST_PARAM_SYNC_PATH (1UL << 28) +#define OG_REST_PARAM_SYNC_METHOD (1UL << 29) +#define OG_REST_PARAM_ECHO (1UL << 30) + +static bool og_msg_params_validate(const struct og_msg_params *params, + const uint64_t flags) +{ + return (params->flags & flags) == flags; +} + +static int og_json_parse_clients(json_t *element, struct og_msg_params *params) +{ + unsigned int i; + json_t *k; + + if (json_typeof(element) != JSON_ARRAY) + return -1; + + for (i = 0; i < json_array_size(element); i++) { + k = json_array_get(element, i); + if (json_typeof(k) != JSON_STRING) + return -1; + + params->ips_array[params->ips_array_len++] = + json_string_value(k); + + params->flags |= OG_REST_PARAM_ADDR; + } + + return 0; +} + +static int og_json_parse_string(json_t *element, const char **str) +{ + if (json_typeof(element) != JSON_STRING) + return -1; + + *str = json_string_value(element); + return 0; +} + +static int og_json_parse_bool(json_t *element, bool *value) +{ + if (json_typeof(element) == JSON_TRUE) + *value = true; + else if (json_typeof(element) == JSON_FALSE) + *value = false; + else + return -1; + + return 0; +} + +static int og_json_parse_sync_params(json_t *element, + struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "sync")) { + err = og_json_parse_string(value, ¶ms->sync_setup.sync); + params->flags |= OG_REST_PARAM_SYNC_SYNC; + } else if (!strcmp(key, "diff")) { + err = og_json_parse_string(value, ¶ms->sync_setup.diff); + params->flags |= OG_REST_PARAM_SYNC_DIFF; + } else if (!strcmp(key, "remove")) { + err = og_json_parse_string(value, ¶ms->sync_setup.remove); + params->flags |= OG_REST_PARAM_SYNC_REMOVE; + } else if (!strcmp(key, "compress")) { + err = og_json_parse_string(value, ¶ms->sync_setup.compress); + params->flags |= OG_REST_PARAM_SYNC_COMPRESS; + } else if (!strcmp(key, "cleanup")) { + err = og_json_parse_string(value, ¶ms->sync_setup.cleanup); + params->flags |= OG_REST_PARAM_SYNC_CLEANUP; + } else if (!strcmp(key, "cache")) { + err = og_json_parse_string(value, ¶ms->sync_setup.cache); + params->flags |= OG_REST_PARAM_SYNC_CACHE; + } else if (!strcmp(key, "cleanup_cache")) { + err = og_json_parse_string(value, ¶ms->sync_setup.cleanup_cache); + params->flags |= OG_REST_PARAM_SYNC_CLEANUP_CACHE; + } else if (!strcmp(key, "remove_dst")) { + err = og_json_parse_string(value, ¶ms->sync_setup.remove_dst); + params->flags |= OG_REST_PARAM_SYNC_REMOVE_DST; + } else if (!strcmp(key, "diff_id")) { + err = og_json_parse_string(value, ¶ms->sync_setup.diff_id); + params->flags |= OG_REST_PARAM_SYNC_DIFF_ID; + } else if (!strcmp(key, "diff_name")) { + err = og_json_parse_string(value, ¶ms->sync_setup.diff_name); + params->flags |= OG_REST_PARAM_SYNC_DIFF_NAME; + } else if (!strcmp(key, "path")) { + err = og_json_parse_string(value, ¶ms->sync_setup.path); + params->flags |= OG_REST_PARAM_SYNC_PATH; + } else if (!strcmp(key, "method")) { + err = og_json_parse_string(value, ¶ms->sync_setup.method); + params->flags |= OG_REST_PARAM_SYNC_METHOD; + } + + if (err != 0) + return err; + } + return err; +} + +#define OG_PARAM_PART_NUMBER (1UL << 0) +#define OG_PARAM_PART_CODE (1UL << 1) +#define OG_PARAM_PART_FILESYSTEM (1UL << 2) +#define OG_PARAM_PART_SIZE (1UL << 3) +#define OG_PARAM_PART_FORMAT (1UL << 4) + +static int og_json_parse_partition(json_t *element, + struct og_msg_params *params, + unsigned int i) +{ + struct og_partition *part = ¶ms->partition_setup[i]; + uint64_t flags = 0UL; + const char *key; + json_t *value; + int err = 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, &part->number); + flags |= OG_PARAM_PART_NUMBER; + } else if (!strcmp(key, "code")) { + err = og_json_parse_string(value, &part->code); + flags |= OG_PARAM_PART_CODE; + } else if (!strcmp(key, "filesystem")) { + err = og_json_parse_string(value, &part->filesystem); + flags |= OG_PARAM_PART_FILESYSTEM; + } else if (!strcmp(key, "size")) { + err = og_json_parse_string(value, &part->size); + flags |= OG_PARAM_PART_SIZE; + } else if (!strcmp(key, "format")) { + err = og_json_parse_string(value, &part->format); + flags |= OG_PARAM_PART_FORMAT; + } + + if (err < 0) + return err; + } + + if (flags != (OG_PARAM_PART_NUMBER | + OG_PARAM_PART_CODE | + OG_PARAM_PART_FILESYSTEM | + OG_PARAM_PART_SIZE | + OG_PARAM_PART_FORMAT)) + return -1; + + params->flags |= (OG_REST_PARAM_PART_0 << i); + + return err; +} + +static int og_json_parse_partition_setup(json_t *element, + struct og_msg_params *params) +{ + unsigned int i; + json_t *k; + + if (json_typeof(element) != JSON_ARRAY) + return -1; + + for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) { + k = json_array_get(element, i); + + if (json_typeof(k) != JSON_OBJECT) + return -1; + + if (og_json_parse_partition(k, params, i) != 0) + return -1; + } + return 0; +} + +static int og_cmd_legacy_send(struct og_msg_params *params, const char *cmd, + const char *state) +{ + char buf[4096] = {}; + int len, err = 0; + TRAMA *msg; + + len = snprintf(buf, sizeof(buf), "nfn=%s\r", cmd); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, + state, msg)) + err = -1; + + og_msg_free(msg); + + return err; +} + +static int og_cmd_post_clients(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "Sondeo", CLIENTE_APAGADO); +} + +struct og_buffer { + char *data; + int len; +}; + +static int og_json_dump_clients(const char *buffer, size_t size, void *data) +{ + struct og_buffer *og_buffer = (struct og_buffer *)data; + + memcpy(og_buffer->data + og_buffer->len, buffer, size); + og_buffer->len += size; + + return 0; +} + +static int og_cmd_get_clients(json_t *element, struct og_msg_params *params, + char *buffer_reply) +{ + json_t *root, *array, *addr, *state, *object; + struct og_buffer og_buffer = { + .data = buffer_reply, + }; + int i; + + array = json_array(); + if (!array) + return -1; + + for (i = 0; i < MAXIMOS_CLIENTES; i++) { + if (tbsockets[i].ip[0] == '\0') + continue; + + object = json_object(); + if (!object) { + json_decref(array); + return -1; + } + addr = json_string(tbsockets[i].ip); + if (!addr) { + json_decref(object); + json_decref(array); + return -1; + } + json_object_set_new(object, "addr", addr); + + state = json_string(tbsockets[i].estado); + if (!state) { + json_decref(object); + json_decref(array); + return -1; + } + json_object_set_new(object, "state", state); + + json_array_append_new(array, object); + } + root = json_pack("{s:o}", "clients", array); + if (!root) { + json_decref(array); + return -1; + } + + json_dump_callback(root, og_json_dump_clients, &og_buffer, 0); + json_decref(root); + + return 0; +} + +static int og_json_parse_target(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + + if (json_typeof(element) != JSON_OBJECT) { + return -1; + } + + json_object_foreach(element, key, value) { + if (!strcmp(key, "addr")) { + if (json_typeof(value) != JSON_STRING) + return -1; + + params->ips_array[params->ips_array_len] = + json_string_value(value); + + params->flags |= OG_REST_PARAM_ADDR; + } else if (!strcmp(key, "mac")) { + if (json_typeof(value) != JSON_STRING) + return -1; + + params->mac_array[params->ips_array_len] = + json_string_value(value); + + params->flags |= OG_REST_PARAM_MAC; + } + } + + return 0; +} + +static int og_json_parse_targets(json_t *element, struct og_msg_params *params) +{ + unsigned int i; + json_t *k; + int err; + + if (json_typeof(element) != JSON_ARRAY) + return -1; + + for (i = 0; i < json_array_size(element); i++) { + k = json_array_get(element, i); + + if (json_typeof(k) != JSON_OBJECT) + return -1; + + err = og_json_parse_target(k, params); + if (err < 0) + return err; + + params->ips_array_len++; + } + return 0; +} + +static int og_json_parse_type(json_t *element, struct og_msg_params *params) +{ + const char *type; + + if (json_typeof(element) != JSON_STRING) + return -1; + + params->wol_type = json_string_value(element); + + type = json_string_value(element); + if (!strcmp(type, "unicast")) + params->wol_type = "2"; + else if (!strcmp(type, "broadcast")) + params->wol_type = "1"; + + params->flags |= OG_REST_PARAM_WOL_TYPE; + + return 0; +} + +static int og_cmd_wol(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_targets(value, params); + } else if (!strcmp(key, "type")) { + err = og_json_parse_type(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_MAC | + OG_REST_PARAM_WOL_TYPE)) + return -1; + + if (!Levanta((char **)params->ips_array, (char **)params->mac_array, + params->ips_array_len, (char *)params->wol_type)) + return -1; + + return 0; +} + +static int og_json_parse_run(json_t *element, struct og_msg_params *params) +{ + if (json_typeof(element) != JSON_STRING) + return -1; + + snprintf(params->run_cmd, sizeof(params->run_cmd), "%s", + json_string_value(element)); + + params->flags |= OG_REST_PARAM_RUN_CMD; + + return 0; +} + +static int og_cmd_run_post(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}, iph[4096] = {}; + int err = 0, len; + const char *key; + unsigned int i; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + else if (!strcmp(key, "run")) + err = og_json_parse_run(value, params); + else if (!strcmp(key, "echo")) { + err = og_json_parse_bool(value, ¶ms->echo); + params->flags |= OG_REST_PARAM_ECHO; + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_RUN_CMD | + OG_REST_PARAM_ECHO)) + return -1; + + for (i = 0; i < params->ips_array_len; i++) { + len = snprintf(iph + strlen(iph), sizeof(iph), "%s;", + params->ips_array[i]); + } + + if (params->echo) { + len = snprintf(buf, sizeof(buf), + "nfn=ConsolaRemota\riph=%s\rscp=%s\r", + iph, params->run_cmd); + } else { + len = snprintf(buf, sizeof(buf), + "nfn=EjecutarScript\riph=%s\rscp=%s\r", + iph, params->run_cmd); + } + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg)) + err = -1; + + og_msg_free(msg); + + if (err < 0) + return err; + + for (i = 0; i < params->ips_array_len; i++) { + char filename[4096]; + FILE *f; + + sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]); + f = fopen(filename, "wt"); + fclose(f); + } + + return 0; +} + +static int og_cmd_run_get(json_t *element, struct og_msg_params *params, + char *buffer_reply) +{ + struct og_buffer og_buffer = { + .data = buffer_reply, + }; + json_t *root, *value, *array; + const char *key; + unsigned int i; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + return err; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + array = json_array(); + if (!array) + return -1; + + for (i = 0; i < params->ips_array_len; i++) { + json_t *object, *output, *addr; + char data[4096] = {}; + char filename[4096]; + int fd, numbytes; + + sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]); + + fd = open(filename, O_RDONLY); + if (!fd) + return -1; + + numbytes = read(fd, data, sizeof(data)); + if (numbytes < 0) { + close(fd); + return -1; + } + data[sizeof(data) - 1] = '\0'; + close(fd); + + object = json_object(); + if (!object) { + json_decref(array); + return -1; + } + addr = json_string(params->ips_array[i]); + if (!addr) { + json_decref(object); + json_decref(array); + return -1; + } + json_object_set_new(object, "addr", addr); + + output = json_string(data); + if (!output) { + json_decref(object); + json_decref(array); + return -1; + } + json_object_set_new(object, "output", output); + + json_array_append_new(array, object); + } + + root = json_pack("{s:o}", "clients", array); + if (!root) + return -1; + + json_dump_callback(root, og_json_dump_clients, &og_buffer, 0); + json_decref(root); + + return 0; +} + +static int og_cmd_session(json_t *element, struct og_msg_params *params) +{ + char buf[4096], iph[4096]; + int err = 0, len; + const char *key; + unsigned int i; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } + + if (err < 0) + return err; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION)) + return -1; + + for (i = 0; i < params->ips_array_len; i++) { + snprintf(iph + strlen(iph), sizeof(iph), "%s;", + params->ips_array[i]); + } + len = snprintf(buf, sizeof(buf), + "nfn=IniciarSesion\riph=%s\rdsk=%s\rpar=%s\r", + iph, params->disk, params->partition); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_APAGADO, msg)) + err = -1; + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_poweroff(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "Apagar", CLIENTE_OCUPADO); +} + +static int og_cmd_refresh(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "Actualizar", CLIENTE_APAGADO); +} + +static int og_cmd_reboot(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "Reiniciar", CLIENTE_OCUPADO); +} + +static int og_cmd_stop(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "Purgar", CLIENTE_APAGADO); +} + +static int og_cmd_hardware(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + return og_cmd_legacy_send(params, "InventarioHardware", + CLIENTE_OCUPADO); +} + +static int og_cmd_software(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } + else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=InventarioSoftware\rdsk=%s\rpar=%s\r", + params->disk, params->partition); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_create_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "code")) { + err = og_json_parse_string(value, ¶ms->code); + params->flags |= OG_REST_PARAM_CODE; + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_CODE | + OG_REST_PARAM_ID | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r", + params->disk, params->partition, params->code, + params->id, params->name, params->repository); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_restore_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "type")) { + err = og_json_parse_string(value, ¶ms->type); + params->flags |= OG_REST_PARAM_TYPE; + } else if (!strcmp(key, "profile")) { + err = og_json_parse_string(value, ¶ms->profile); + params->flags |= OG_REST_PARAM_PROFILE; + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO | + OG_REST_PARAM_TYPE | + OG_REST_PARAM_PROFILE | + OG_REST_PARAM_ID)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=RestaurarImagen\ridi=%s\rdsk=%s\rpar=%s\rifs=%s\r" + "nci=%s\ripr=%s\rptc=%s\r", + params->id, params->disk, params->partition, + params->profile, params->name, + params->repository, params->type); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_setup(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "cache")) { + err = og_json_parse_string(value, ¶ms->cache); + params->flags |= OG_REST_PARAM_CACHE; + } else if (!strcmp(key, "cache_size")) { + err = og_json_parse_string(value, ¶ms->cache_size); + params->flags |= OG_REST_PARAM_CACHE_SIZE; + } else if (!strcmp(key, "partition_setup")) { + err = og_json_parse_partition_setup(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_CACHE | + OG_REST_PARAM_CACHE_SIZE | + OG_REST_PARAM_PART_0 | + OG_REST_PARAM_PART_1 | + OG_REST_PARAM_PART_2 | + OG_REST_PARAM_PART_3)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=Configurar\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!", + params->disk, params->disk, params->cache, params->cache_size); + + for (unsigned int i = 0; i < OG_PARTITION_MAX; ++i) { + const struct og_partition *part = ¶ms->partition_setup[i]; + + len += snprintf(buf + strlen(buf), sizeof(buf), + "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%", + part->number, part->code, part->filesystem, part->size, part->format); + } + + msg = og_msg_alloc(buf, len + 1); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params) +{ + const char *key; + json_t *value; + int err = 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) + return -1; + + og_cmd_legacy_send(params, "EjecutaComandosPendientes", CLIENTE_OCUPADO); + + return 0; +} + +static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "code")) { + err = og_json_parse_string(value, ¶ms->code); + params->flags |= OG_REST_PARAM_CODE; + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "sync_params")) { + err = og_json_parse_sync_params(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_CODE | + OG_REST_PARAM_ID | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO | + OG_REST_PARAM_SYNC_SYNC | + OG_REST_PARAM_SYNC_DIFF | + OG_REST_PARAM_SYNC_REMOVE | + OG_REST_PARAM_SYNC_COMPRESS | + OG_REST_PARAM_SYNC_CLEANUP | + OG_REST_PARAM_SYNC_CACHE | + OG_REST_PARAM_SYNC_CLEANUP_CACHE | + OG_REST_PARAM_SYNC_REMOVE_DST)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r" + "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r" + "cpc=%s\rbpc=%s\rnba=%s\r", + params->disk, params->partition, params->code, params->id, + params->name, params->repository, params->sync_setup.sync, + params->sync_setup.diff, params->sync_setup.remove, + params->sync_setup.compress, params->sync_setup.cleanup, + params->sync_setup.cache, params->sync_setup.cleanup_cache, + params->sync_setup.remove_dst); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_create_incremental_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) + err = og_json_parse_clients(value, params); + else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "sync_params")) { + err = og_json_parse_sync_params(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_ID | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO | + OG_REST_PARAM_SYNC_SYNC | + OG_REST_PARAM_SYNC_PATH | + OG_REST_PARAM_SYNC_DIFF | + OG_REST_PARAM_SYNC_DIFF_ID | + OG_REST_PARAM_SYNC_DIFF_NAME | + OG_REST_PARAM_SYNC_REMOVE | + OG_REST_PARAM_SYNC_COMPRESS | + OG_REST_PARAM_SYNC_CLEANUP | + OG_REST_PARAM_SYNC_CACHE | + OG_REST_PARAM_SYNC_CLEANUP_CACHE | + OG_REST_PARAM_SYNC_REMOVE_DST)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=CrearSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" + "rti=%s\ripr=%s\ridf=%s\rncf=%s\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\r" + "bpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r", + params->disk, params->partition, params->id, params->name, + params->sync_setup.path, params->repository, params->sync_setup.diff_id, + params->sync_setup.diff_name, params->sync_setup.sync, + params->sync_setup.diff, params->sync_setup.remove_dst, + params->sync_setup.compress, params->sync_setup.cleanup, + params->sync_setup.cache, params->sync_setup.cleanup_cache, + params->sync_setup.remove_dst); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "profile")) { + err = og_json_parse_string(value, ¶ms->profile); + params->flags |= OG_REST_PARAM_PROFILE; + } else if (!strcmp(key, "type")) { + err = og_json_parse_string(value, ¶ms->type); + params->flags |= OG_REST_PARAM_TYPE; + } else if (!strcmp(key, "sync_params")) { + err = og_json_parse_sync_params(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_ID | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO | + OG_REST_PARAM_PROFILE | + OG_REST_PARAM_TYPE | + OG_REST_PARAM_SYNC_PATH | + OG_REST_PARAM_SYNC_METHOD | + OG_REST_PARAM_SYNC_SYNC | + OG_REST_PARAM_SYNC_DIFF | + OG_REST_PARAM_SYNC_REMOVE | + OG_REST_PARAM_SYNC_COMPRESS | + OG_REST_PARAM_SYNC_CLEANUP | + OG_REST_PARAM_SYNC_CACHE | + OG_REST_PARAM_SYNC_CLEANUP_CACHE | + OG_REST_PARAM_SYNC_REMOVE_DST)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" + "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r" + "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r", + params->disk, params->partition, params->id, params->name, + params->repository, params->profile, params->sync_setup.path, + params->sync_setup.method, params->sync_setup.sync, params->type, + params->sync_setup.diff, params->sync_setup.remove, + params->sync_setup.compress, params->sync_setup.cleanup, + params->sync_setup.cache, params->sync_setup.cleanup_cache, + params->sync_setup.remove_dst); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_cmd_restore_incremental_image(json_t *element, struct og_msg_params *params) +{ + char buf[4096] = {}; + int err = 0, len; + const char *key; + json_t *value; + TRAMA *msg; + + if (json_typeof(element) != JSON_OBJECT) + return -1; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "disk")) { + err = og_json_parse_string(value, ¶ms->disk); + params->flags |= OG_REST_PARAM_DISK; + } else if (!strcmp(key, "partition")) { + err = og_json_parse_string(value, ¶ms->partition); + params->flags |= OG_REST_PARAM_PARTITION; + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string(value, ¶ms->name); + params->flags |= OG_REST_PARAM_NAME; + } else if (!strcmp(key, "repository")) { + err = og_json_parse_string(value, ¶ms->repository); + params->flags |= OG_REST_PARAM_REPO; + } else if (!strcmp(key, "profile")) { + err = og_json_parse_string(value, ¶ms->profile); + params->flags |= OG_REST_PARAM_PROFILE; + } else if (!strcmp(key, "type")) { + err = og_json_parse_string(value, ¶ms->type); + params->flags |= OG_REST_PARAM_TYPE; + } else if (!strcmp(key, "sync_params")) { + err = og_json_parse_sync_params(value, params); + } + + if (err < 0) + break; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_DISK | + OG_REST_PARAM_PARTITION | + OG_REST_PARAM_ID | + OG_REST_PARAM_NAME | + OG_REST_PARAM_REPO | + OG_REST_PARAM_PROFILE | + OG_REST_PARAM_TYPE | + OG_REST_PARAM_SYNC_DIFF_ID | + OG_REST_PARAM_SYNC_DIFF_NAME | + OG_REST_PARAM_SYNC_PATH | + OG_REST_PARAM_SYNC_METHOD | + OG_REST_PARAM_SYNC_SYNC | + OG_REST_PARAM_SYNC_DIFF | + OG_REST_PARAM_SYNC_REMOVE | + OG_REST_PARAM_SYNC_COMPRESS | + OG_REST_PARAM_SYNC_CLEANUP | + OG_REST_PARAM_SYNC_CACHE | + OG_REST_PARAM_SYNC_CLEANUP_CACHE | + OG_REST_PARAM_SYNC_REMOVE_DST)) + return -1; + + len = snprintf(buf, sizeof(buf), + "nfn=RestaurarSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" + "ipr=%s\rifs=%s\ridf=%s\rncf=%s\rrti=%s\rmet=%s\rmsy=%s\r" + "tpt=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\r" + "nba=%s\r", + params->disk, params->partition, params->id, params->name, + params->repository, params->profile, params->sync_setup.diff_id, + params->sync_setup.diff_name, params->sync_setup.path, + params->sync_setup.method, params->sync_setup.sync, params->type, + params->sync_setup.diff, params->sync_setup.remove, + params->sync_setup.compress, params->sync_setup.cleanup, + params->sync_setup.cache, params->sync_setup.cleanup_cache, + params->sync_setup.remove_dst); + + msg = og_msg_alloc(buf, len); + if (!msg) + return -1; + + og_send_cmd((char **)params->ips_array, params->ips_array_len, + CLIENTE_OCUPADO, msg); + + og_msg_free(msg); + + return 0; +} + +static int og_client_method_not_found(struct og_client *cli) +{ + /* To meet RFC 7231, this function MUST generate an Allow header field + * containing the correct methods. For example: "Allow: POST\r\n" + */ + char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n" + "Content-Length: 0\r\n\r\n"; + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return -1; +} + +static int og_client_bad_request(struct og_client *cli) +{ + char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n"; + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return -1; +} + +static int og_client_not_found(struct og_client *cli) +{ + char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return -1; +} + +static int og_client_not_authorized(struct og_client *cli) +{ + char buf[] = "HTTP/1.1 401 Unauthorized\r\n" + "WWW-Authenticate: Basic\r\n" + "Content-Length: 0\r\n\r\n"; + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return -1; +} + +static int og_server_internal_error(struct og_client *cli) +{ + char buf[] = "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Length: 0\r\n\r\n"; + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return -1; +} + +#define OG_MSG_RESPONSE_MAXLEN 65536 + +static int og_client_ok(struct og_client *cli, char *buf_reply) +{ + char buf[OG_MSG_RESPONSE_MAXLEN] = {}; + int err = 0, len; + + len = snprintf(buf, sizeof(buf), + "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s", + strlen(buf_reply), buf_reply); + if (len >= (int)sizeof(buf)) + err = og_server_internal_error(cli); + + send(og_client_socket(cli), buf, strlen(buf), 0); + + return err; +} + +enum og_rest_method { + OG_METHOD_GET = 0, + OG_METHOD_POST, +}; + +static int og_client_state_process_payload_rest(struct og_client *cli) +{ + char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {}; + struct og_msg_params params = {}; + enum og_rest_method method; + const char *cmd, *body; + json_error_t json_err; + json_t *root = NULL; + int err = 0; + + syslog(LOG_DEBUG, "%s:%hu %.32s ...\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port), cli->buf); + + if (!strncmp(cli->buf, "GET", strlen("GET"))) { + method = OG_METHOD_GET; + cmd = cli->buf + strlen("GET") + 2; + } else if (!strncmp(cli->buf, "POST", strlen("POST"))) { + method = OG_METHOD_POST; + cmd = cli->buf + strlen("POST") + 2; + } else + return og_client_method_not_found(cli); + + body = strstr(cli->buf, "\r\n\r\n") + 4; + + if (strcmp(cli->auth_token, auth_token)) { + syslog(LOG_ERR, "wrong Authentication key\n"); + return og_client_not_authorized(cli); + } + + if (cli->content_length) { + root = json_loads(body, 0, &json_err); + if (!root) { + syslog(LOG_ERR, "malformed json line %d: %s\n", + json_err.line, json_err.text); + return og_client_not_found(cli); + } + } + + if (!strncmp(cmd, "clients", strlen("clients"))) { + if (method != OG_METHOD_POST && + method != OG_METHOD_GET) + return og_client_method_not_found(cli); + + if (method == OG_METHOD_POST && !root) { + syslog(LOG_ERR, "command clients with no payload\n"); + return og_client_bad_request(cli); + } + switch (method) { + case OG_METHOD_POST: + err = og_cmd_post_clients(root, ¶ms); + break; + case OG_METHOD_GET: + err = og_cmd_get_clients(root, ¶ms, buf_reply); + break; + } + } else if (!strncmp(cmd, "wol", strlen("wol"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command wol with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_wol(root, ¶ms); + } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command run with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_run_post(root, ¶ms); + } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command output with no payload\n"); + return og_client_bad_request(cli); + } + + err = og_cmd_run_get(root, ¶ms, buf_reply); + } else if (!strncmp(cmd, "session", strlen("session"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command session with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_session(root, ¶ms); + } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command poweroff with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_poweroff(root, ¶ms); + } else if (!strncmp(cmd, "reboot", strlen("reboot"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command reboot with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_reboot(root, ¶ms); + } else if (!strncmp(cmd, "stop", strlen("stop"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command stop with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_stop(root, ¶ms); + } else if (!strncmp(cmd, "refresh", strlen("refresh"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command refresh with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_refresh(root, ¶ms); + } else if (!strncmp(cmd, "hardware", strlen("hardware"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command hardware with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_hardware(root, ¶ms); + } else if (!strncmp(cmd, "software", strlen("software"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command software with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_software(root, ¶ms); + } else if (!strncmp(cmd, "image/create/basic", + strlen("image/create/basic"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_create_basic_image(root, ¶ms); + } else if (!strncmp(cmd, "image/create/incremental", + strlen("image/create/incremental"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_create_incremental_image(root, ¶ms); + } else if (!strncmp(cmd, "image/create", strlen("image/create"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_create_image(root, ¶ms); + } else if (!strncmp(cmd, "image/restore/basic", + strlen("image/restore/basic"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_restore_basic_image(root, ¶ms); + } else if (!strncmp(cmd, "image/restore/incremental", + strlen("image/restore/incremental"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_restore_incremental_image(root, ¶ms); + } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_restore_image(root, ¶ms); + } else if (!strncmp(cmd, "setup", strlen("setup"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + err = og_cmd_setup(root, ¶ms); + } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) { + if (method != OG_METHOD_POST) + return og_client_method_not_found(cli); + + if (!root) { + syslog(LOG_ERR, "command create with no payload\n"); + return og_client_bad_request(cli); + } + + err = og_cmd_run_schedule(root, ¶ms); + } else { + syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd); + err = og_client_not_found(cli); + } + + if (root) + json_decref(root); + + if (err < 0) + return og_client_bad_request(cli); + + err = og_client_ok(cli, buf_reply); + if (err < 0) { + syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + } + + return err; +} + +static int og_client_state_recv_hdr_rest(struct og_client *cli) +{ + char *ptr; + + ptr = strstr(cli->buf, "\r\n\r\n"); + if (!ptr) + return 0; + + cli->msg_len = ptr - cli->buf + 4; + + ptr = strstr(cli->buf, "Content-Length: "); + if (ptr) { + sscanf(ptr, "Content-Length: %i[^\r\n]", &cli->content_length); + if (cli->content_length < 0) + return -1; + cli->msg_len += cli->content_length; + } + + ptr = strstr(cli->buf, "Authorization: "); + if (ptr) + sscanf(ptr, "Authorization: %63[^\r\n]", cli->auth_token); + + return 1; +} + +static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events) +{ + struct og_client *cli; + int ret; + + cli = container_of(io, struct og_client, io); + + if (events & EV_ERROR) { + syslog(LOG_ERR, "unexpected error event from client %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + goto close; + } + + ret = recv(io->fd, cli->buf + cli->buf_len, + sizeof(cli->buf) - cli->buf_len, 0); + if (ret <= 0) { + if (ret < 0) { + syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), + strerror(errno)); + } else { + syslog(LOG_DEBUG, "closed connection by %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + } + goto close; + } + + if (cli->keepalive_idx >= 0) + return; + + ev_timer_again(loop, &cli->timer); + + cli->buf_len += ret; + if (cli->buf_len >= sizeof(cli->buf)) { + syslog(LOG_ERR, "client request from %s:%hu is too long\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + goto close; + } + + switch (cli->state) { + case OG_CLIENT_RECEIVING_HEADER: + if (cli->rest) + ret = og_client_state_recv_hdr_rest(cli); + else + ret = og_client_state_recv_hdr(cli); + + if (ret < 0) + goto close; + if (!ret) + return; + + cli->state = OG_CLIENT_RECEIVING_PAYLOAD; + /* Fall through. */ + case OG_CLIENT_RECEIVING_PAYLOAD: + /* Still not enough data to process request. */ + if (cli->buf_len < cli->msg_len) + return; + + cli->state = OG_CLIENT_PROCESSING_REQUEST; + /* fall through. */ + case OG_CLIENT_PROCESSING_REQUEST: + if (cli->rest) { + ret = og_client_state_process_payload_rest(cli); + if (ret < 0) { + syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + } + } else { + ret = og_client_state_process_payload(cli); + } + if (ret < 0) + goto close; + + if (cli->keepalive_idx < 0) { + syslog(LOG_DEBUG, "server closing connection to %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + goto close; + } else { + syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n", + inet_ntoa(cli->addr.sin_addr), + ntohs(cli->addr.sin_port)); + og_client_keepalive(loop, cli); + og_client_reset_state(cli); + } + break; + default: + syslog(LOG_ERR, "unknown state, critical internal error\n"); + goto close; + } + return; +close: + ev_timer_stop(loop, &cli->timer); + og_client_release(loop, cli); +} + +static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events) +{ + struct og_client *cli; + + cli = container_of(timer, struct og_client, timer); + if (cli->keepalive_idx >= 0) { + ev_timer_again(loop, &cli->timer); + return; + } + syslog(LOG_ERR, "timeout request for client %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + + og_client_release(loop, cli); +} + +static int socket_s, socket_rest; + +static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io, + int events) +{ + struct sockaddr_in client_addr; + socklen_t addrlen = sizeof(client_addr); + struct og_client *cli; + int client_sd; + + if (events & EV_ERROR) + return; + + client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen); + if (client_sd < 0) { + syslog(LOG_ERR, "cannot accept client connection\n"); + return; + } + + cli = (struct og_client *)calloc(1, sizeof(struct og_client)); + if (!cli) { + close(client_sd); + return; + } + memcpy(&cli->addr, &client_addr, sizeof(client_addr)); + cli->keepalive_idx = -1; + + if (io->fd == socket_rest) + cli->rest = true; + + syslog(LOG_DEBUG, "connection from client %s:%hu\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + + ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ); + ev_io_start(loop, &cli->io); + ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.); + ev_timer_start(loop, &cli->timer); +} + +static int og_socket_server_init(const char *port) +{ + struct sockaddr_in local; + int sd, on = 1; + + sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sd < 0) { + syslog(LOG_ERR, "cannot create main socket\n"); + return -1; + } + setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)); + + local.sin_addr.s_addr = htonl(INADDR_ANY); + local.sin_family = AF_INET; + local.sin_port = htons(atoi(port)); + + if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) { + close(sd); + syslog(LOG_ERR, "cannot bind socket\n"); + return -1; + } + + listen(sd, 250); + + return sd; +} + +int main(int argc, char *argv[]) +{ + struct ev_io ev_io_server, ev_io_server_rest; + struct ev_loop *loop = ev_default_loop(0); + int i; + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + exit(EXIT_FAILURE); + + openlog("ogAdmServer", LOG_PID, LOG_DAEMON); + + /*-------------------------------------------------------------------------------------------------------- + Validación de parámetros de ejecución y lectura del fichero de configuración del servicio + ---------------------------------------------------------------------------------------------------------*/ + if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución + exit(EXIT_FAILURE); + + if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion + exit(EXIT_FAILURE); + } + + /*-------------------------------------------------------------------------------------------------------- + // Inicializa array de información de los clientes + ---------------------------------------------------------------------------------------------------------*/ + for (i = 0; i < MAXIMOS_CLIENTES; i++) { + tbsockets[i].ip[0] = '\0'; + tbsockets[i].cli = NULL; + } + /*-------------------------------------------------------------------------------------------------------- + Creación y configuración del socket del servicio + ---------------------------------------------------------------------------------------------------------*/ + socket_s = og_socket_server_init(puerto); + if (socket_s < 0) + exit(EXIT_FAILURE); + + ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ); + ev_io_start(loop, &ev_io_server); + + socket_rest = og_socket_server_init("8888"); + if (socket_rest < 0) + exit(EXIT_FAILURE); + + ev_io_init(&ev_io_server_rest, og_server_accept_cb, socket_rest, EV_READ); + ev_io_start(loop, &ev_io_server_rest); + + infoLog(1); // Inicio de sesión + + /* old log file has been deprecated. */ + og_log(97, false); + + syslog(LOG_INFO, "Waiting for connections\n"); + + while (1) + ev_loop(loop, 0); + + exit(EXIT_SUCCESS); +} diff --git a/sources/ogAdmServer.cpp b/sources/ogAdmServer.cpp deleted file mode 100644 index 562a39d..0000000 --- a/sources/ogAdmServer.cpp +++ /dev/null @@ -1,4907 +0,0 @@ -// ******************************************************************************************************* -// Servicio: ogAdmServer -// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla -// Fecha Creación: Marzo-2010 -// Fecha Última modificación: Marzo-2010 -// Nombre del fichero: ogAdmServer.cpp -// Descripción :Este fichero implementa el servicio de administración general del sistema -// ******************************************************************************************************* -#include "ogAdmServer.h" -#include "ogAdmLib.c" -#include "dbi.h" -#include -#include -#include -#include -#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 -static char auth_token[LONPRM]; // API token - -static struct og_dbi_config dbi_config = { - .user = usuario, - .passwd = pasguor, - .host = datasource, - .database = catalog, -}; - -//________________________________________________________________________________________________________ -// Función: tomaConfiguracion -// -// Descripción: -// Lee el fichero de configuración del servicio -// Parámetros: -// filecfg : Ruta completa al fichero de configuración -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -//________________________________________________________________________________________________________ -static bool tomaConfiguracion(const char *filecfg) -{ - char buf[1024], *line; - char *key, *value; - FILE *fcfg; - - if (filecfg == NULL || strlen(filecfg) == 0) { - syslog(LOG_ERR, "No configuration file has been specified\n"); - return false; - } - - fcfg = fopen(filecfg, "rt"); - if (fcfg == NULL) { - syslog(LOG_ERR, "Cannot open configuration file `%s'\n", - filecfg); - return false; - } - - servidoradm[0] = '\0'; //inicializar variables globales - - line = fgets(buf, sizeof(buf), fcfg); - while (line != NULL) { - const char *delim = "="; - - line[strlen(line) - 1] = '\0'; - - key = strtok(line, delim); - value = strtok(NULL, delim); - - if (!strcmp(StrToUpper(key), "SERVIDORADM")) - snprintf(servidoradm, sizeof(servidoradm), "%s", value); - else if (!strcmp(StrToUpper(key), "PUERTO")) - snprintf(puerto, sizeof(puerto), "%s", value); - else if (!strcmp(StrToUpper(key), "USUARIO")) - snprintf(usuario, sizeof(usuario), "%s", value); - else if (!strcmp(StrToUpper(key), "PASSWORD")) - snprintf(pasguor, sizeof(pasguor), "%s", value); - else if (!strcmp(StrToUpper(key), "DATASOURCE")) - 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); - else if (!strcmp(StrToUpper(key), "APITOKEN")) - snprintf(auth_token, sizeof(auth_token), "%s", value); - - line = fgets(buf, sizeof(buf), fcfg); - } - - fclose(fcfg); - - if (!servidoradm[0]) { - syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n"); - return false; - } - if (!puerto[0]) { - syslog(LOG_ERR, "Missing PUERTO in configuration file\n"); - return false; - } - if (!usuario[0]) { - syslog(LOG_ERR, "Missing USUARIO in configuration file\n"); - return false; - } - if (!pasguor[0]) { - syslog(LOG_ERR, "Missing PASSWORD in configuration file\n"); - return false; - } - if (!datasource[0]) { - syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n"); - return false; - } - if (!catalog[0]) { - 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; -} - -enum og_client_state { - OG_CLIENT_RECEIVING_HEADER = 0, - OG_CLIENT_RECEIVING_PAYLOAD, - OG_CLIENT_PROCESSING_REQUEST, -}; - -#define OG_MSG_REQUEST_MAXLEN 4096 - -/* Shut down connection if there is no complete message after 10 seconds. */ -#define OG_CLIENT_TIMEOUT 10 - -struct og_client { - struct ev_io io; - struct ev_timer timer; - struct sockaddr_in addr; - enum og_client_state state; - char buf[OG_MSG_REQUEST_MAXLEN]; - unsigned int buf_len; - unsigned int msg_len; - int keepalive_idx; - bool rest; - int content_length; - char auth_token[64]; -}; - -static inline int og_client_socket(const struct og_client *cli) -{ - return cli->io.fd; -} - -// ________________________________________________________________________________________________________ -// Función: clienteDisponible -// -// Descripción: -// Comprueba la disponibilidad del cliente para recibir comandos interactivos -// Parametros: -// - ip : La ip del cliente a buscar -// - idx: (Salida) Indice que ocupa el cliente, de estar ya registrado -// Devuelve: -// true: Si el cliente está disponible -// false: En caso contrario -// ________________________________________________________________________________________________________ -bool clienteDisponible(char *ip, int* idx) -{ - int estado; - - if (clienteExistente(ip, idx)) { - estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado - if (estado == 0) - return false; - - estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado - if (estado == 0) - return false; - - estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión - if (estado == 0) - return false; - - return true; // En caso contrario el cliente está disponible - } - return false; // Cliente no está registrado en el sistema -} -// ________________________________________________________________________________________________________ -// Función: clienteExistente -// -// Descripción: -// Comprueba si el cliente está registrado en la tabla de socket del sistema -// Parametros: -// - ip : La ip del cliente a buscar -// - idx:(Salida) Indice que ocupa el cliente, de estar ya registrado -// Devuelve: -// true: Si el cliente está registrado -// false: En caso contrario -// ________________________________________________________________________________________________________ -bool clienteExistente(char *ip, int* idx) -{ - int i; - for (i = 0; i < MAXIMOS_CLIENTES; i++) { - if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena - *idx = i; - return true; - } - } - return false; -} -// ________________________________________________________________________________________________________ -// Función: hayHueco -// -// Descripción: -// Esta función devuelve true o false dependiendo de que haya hueco en la tabla de sockets para un nuevo cliente. -// Parametros: -// - idx: Primer indice libre que se podrn utilizar -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool hayHueco(int *idx) -{ - int i; - - for (i = 0; i < MAXIMOS_CLIENTES; i++) { - if (strncmp(tbsockets[i].ip, "\0", 1) == 0) { // Hay un hueco - *idx = i; - return true; - } - } - return false; -} -// ________________________________________________________________________________________________________ -// Función: InclusionClienteWin -// -// Descripción: -// Esta función incorpora el socket de un nuevo cliente Windows o Linux a la tabla de clientes -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool InclusionClienteWinLnx(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - int res,idordenador,lon; - char nombreordenador[LONFIL]; - - res = procesoInclusionClienteWinLnx(socket_c, ptrTrama, &idordenador, - nombreordenador); - - // Prepara la trama de respuesta - - initParametros(ptrTrama,0); - ptrTrama->tipo=MSG_RESPUESTA; - lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionClienteWinLnx\r"); - lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador); - lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador); - lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", res); - - if (!mandaTrama(&socket_c, ptrTrama)) { - syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - return false; - } - return true; -} -// ________________________________________________________________________________________________________ -// Función: procesoInclusionClienteWinLnx -// -// Descripción: -// Implementa el proceso de inclusión en el sistema del Cliente Windows o Linux -// Parámetros de entrada: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Parámetros de salida: -// - ido: Identificador del ordenador -// - nombreordenador: Nombre del ordenador -// Devuelve: -// Código del error producido en caso de ocurrir algún error, 0 si el proceso es correcto -// ________________________________________________________________________________________________________ -bool procesoInclusionClienteWinLnx(int socket_c, TRAMA *ptrTrama, int *idordenador, char *nombreordenador) - { - struct og_dbi *dbi; - const char *msglog; - dbi_result result; - char *iph; - - // Toma parámetros - iph = copiaParametro("iph",ptrTrama); // Toma ip - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - goto err_dbi_open; - } - - result = dbi_conn_queryf(dbi->conn, - "SELECT idordenador,nombreordenador FROM ordenadores " - " WHERE ordenadores.ip = '%s'", iph); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - goto err_query_fail; - } - - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - goto err_query_fail; - } - - syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph); - - *idordenador = dbi_result_get_uint(result, "idordenador"); - nombreordenador = (char *)dbi_result_get_string(result, "nombreordenador"); - - dbi_result_free(result); - og_dbi_close(dbi); - - if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets - liberaMemoria(iph); - syslog(LOG_ERR, "client table is full\n"); - return false; - } - liberaMemoria(iph); - return true; - -err_query_fail: - og_dbi_close(dbi); -err_dbi_open: - liberaMemoria(iph); - return false; -} -// ________________________________________________________________________________________________________ -// Función: InclusionCliente -// -// Descripción: -// Esta función incorpora el socket de un nuevo cliente a la tabla de clientes y le devuelve alguna de sus propiedades: -// nombre, identificador, tamaño de la caché , etc ... -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool InclusionCliente(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - - if (!procesoInclusionCliente(cli, ptrTrama)) { - initParametros(ptrTrama,0); - strcpy(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\rres=0\r"); - if (!mandaTrama(&socket_c, ptrTrama)) { - syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - return false; - } - } - return true; -} -// ________________________________________________________________________________________________________ -// Función: procesoInclusionCliente -// -// Descripción: -// Implementa el proceso de inclusión en el sistema del Cliente -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool procesoInclusionCliente(struct og_client *cli, TRAMA *ptrTrama) -{ - int socket_c = og_client_socket(cli); - const char *msglog, *str; - struct og_dbi *dbi; - dbi_result result; - - char *iph, *cfg; - char nombreordenador[LONFIL]; - int lon, resul, idordenador, cache, idproautoexec, idaula, idcentro; - - // Toma parámetros - iph = copiaParametro("iph",ptrTrama); // Toma ip - cfg = copiaParametro("cfg",ptrTrama); // Toma configuracion - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - goto err_dbi_open; - } - - // Recupera los datos del cliente - result = dbi_conn_queryf(dbi->conn, - "SELECT ordenadores.*,aulas.idaula,centros.idcentro FROM ordenadores " - " INNER JOIN aulas ON aulas.idaula=ordenadores.idaula" - " INNER JOIN centros ON centros.idcentro=aulas.idcentro" - " WHERE ordenadores.ip = '%s'", iph); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - goto err_query_fail; - } - - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - goto err_query_fail; - } - - syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph); - - idordenador = dbi_result_get_uint(result, "idordenador"); - str = (char *)dbi_result_get_string(result, "nombreordenador"); - sprintf(nombreordenador, "%s", str); - cache = dbi_result_get_uint(result, "cache"); - idproautoexec = dbi_result_get_uint(result, "idproautoexec"); - idaula = dbi_result_get_uint(result, "idaula"); - idcentro = dbi_result_get_uint(result, "idcentro"); - dbi_result_free(result); - - resul = actualizaConfiguracion(dbi, cfg, idordenador); // Actualiza la configuración del ordenador - liberaMemoria(cfg); - og_dbi_close(dbi); - - if (!resul) { - liberaMemoria(iph); - syslog(LOG_ERR, "Cannot add client to database\n"); - return false; - } - - if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets - liberaMemoria(iph); - syslog(LOG_ERR, "client table is full\n"); - return false; - } - - /*------------------------------------------------------------------------------------------------------------------------------ - Prepara la trama de respuesta - -------------------------------------------------------------------------------------------------------------------------------*/ - initParametros(ptrTrama,0); - ptrTrama->tipo=MSG_RESPUESTA; - lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\r"); - lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador); - lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador); - lon += sprintf(ptrTrama->parametros + lon, "che=%d\r", cache); - lon += sprintf(ptrTrama->parametros + lon, "exe=%d\r", idproautoexec); - lon += sprintf(ptrTrama->parametros + lon, "ida=%d\r", idaula); - lon += sprintf(ptrTrama->parametros + lon, "idc=%d\r", idcentro); - lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", 1); // Confirmación proceso correcto - - if (!mandaTrama(&socket_c, ptrTrama)) { - syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - return false; - } - liberaMemoria(iph); - return true; - -err_query_fail: - og_dbi_close(dbi); -err_dbi_open: - liberaMemoria(iph); - liberaMemoria(cfg); - return false; -} -// ________________________________________________________________________________________________________ -// Función: actualizaConfiguracion -// -// Descripción: -// Esta función actualiza la base de datos con la configuracion de particiones de un cliente -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - cfg: cadena con una Configuración -// - ido: Identificador del ordenador cliente -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// Especificaciones: -// Los parametros de la configuración son: -// par= Número de partición -// cpt= Codigo o tipo de partición -// sfi= Sistema de ficheros que está implementado en la partición -// soi= Nombre del sistema de ficheros instalado en la partición -// tam= Tamaño de la partición -// ________________________________________________________________________________________________________ -bool actualizaConfiguracion(struct og_dbi *dbi, char *cfg, int ido) -{ - int lon, p, c,i, dato, swu, idsoi, idsfi,k; - char *ptrPar[MAXPAR], *ptrCfg[7], *ptrDual[2], tbPar[LONSTD]; - char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración. - dbi_result result, result_update; - const char *msglog; - - lon = 0; - p = splitCadena(ptrPar, cfg, '\n'); - for (i = 0; i < p; i++) { - c = splitCadena(ptrCfg, ptrPar[i], '\t'); - - // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD. - if (i == 0 && c == 1) { - splitCadena(ptrDual, ptrCfg[0], '='); - ser = ptrDual[1]; - if (strlen(ser) > 0) { - // Solo actualizar si número de serie no existía. - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET numserie='%s'" - " WHERE idordenador=%d AND numserie IS NULL", - ser, ido); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - } - continue; - } - - // Distribución de particionado. - disk = par = cpt = sfi = soi = tam = uso = NULL; - - splitCadena(ptrDual, ptrCfg[0], '='); - disk = ptrDual[1]; // Número de disco - - splitCadena(ptrDual, ptrCfg[1], '='); - par = ptrDual[1]; // Número de partición - - k=splitCadena(ptrDual, ptrCfg[2], '='); - if(k==2){ - cpt = ptrDual[1]; // Código de partición - }else{ - cpt = (char*)"0"; - } - - k=splitCadena(ptrDual, ptrCfg[3], '='); - if(k==2){ - sfi = ptrDual[1]; // Sistema de ficheros - /* Comprueba existencia del s0xistema de ficheros instalado */ - idsfi = checkDato(dbi, sfi, "sistemasficheros", "descripcion","idsistemafichero"); - } - else - idsfi=0; - - k=splitCadena(ptrDual, ptrCfg[4], '='); - if(k==2){ // Sistema operativo detecdtado - soi = ptrDual[1]; // Nombre del S.O. instalado - /* Comprueba existencia del sistema operativo instalado */ - idsoi = checkDato(dbi, soi, "nombresos", "nombreso", "idnombreso"); - } - else - idsoi=0; - - splitCadena(ptrDual, ptrCfg[5], '='); - tam = ptrDual[1]; // Tamaño de la partición - - splitCadena(ptrDual, ptrCfg[6], '='); - uso = ptrDual[1]; // Porcentaje de uso del S.F. - - lon += sprintf(tbPar + lon, "(%s, %s),", disk, par); - - result = dbi_conn_queryf(dbi->conn, - "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso" - " FROM ordenadores_particiones" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - ido, disk, par); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - result_update = dbi_conn_queryf(dbi->conn, - "INSERT INTO ordenadores_particiones(idordenador,numdisk,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)" - " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)", - ido, disk, par, cpt, tam, uso, idsfi, idsoi); - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result_update); - - } else { // Existe el registro - swu = true; // Se supone que algún dato ha cambiado - - dato = dbi_result_get_uint(result, "tamano"); - if (atoi(tam) == dato) {// Parámetro tamaño igual al almacenado - dato = dbi_result_get_uint(result, "idsistemafichero"); - if (idsfi == dato) {// Parámetro sistema de fichero igual al almacenado - dato = dbi_result_get_uint(result, "idnombreso"); - if (idsoi == dato) {// Parámetro sistema de fichero distinto al almacenado - swu = false; // Todos los parámetros de la partición son iguales, no se actualiza - } - } - } - if (swu) { // Hay que actualizar los parámetros de la partición - result_update = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones SET " - " codpar=0x%s," - " tamano=%s," - " uso=%s," - " idsistemafichero=%d," - " idnombreso=%d," - " idimagen=0," - " idperfilsoft=0," - " fechadespliegue=NULL" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - cpt, tam, uso, idsfi, idsoi, ido, disk, par); - } else { // Actualizar porcentaje de uso. - result_update = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones SET " - " codpar=0x%s," - " uso=%s" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - cpt, uso, ido, disk, par); - } - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - - dbi_result_free(result_update); - } - } - lon += sprintf(tbPar + lon, "(0,0)"); - // Eliminar particiones almacenadas que ya no existen - result_update = dbi_conn_queryf(dbi->conn, - "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)", - ido, tbPar); - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result_update); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: checkDato -// -// Descripción: -// Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en -// cualquier caso el identificador del registro existenet o del insertado -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - dato: Dato -// - tabla: Nombre de la tabla -// - nomdato: Nombre del dato en la tabla -// - nomidentificador: Nombre del identificador en la tabla -// Devuelve: -// El identificador del registro existente o el del insertado -// -// Especificaciones: -// En caso de producirse algún error se devuelve el valor 0 -// ________________________________________________________________________________________________________ - -int checkDato(struct og_dbi *dbi, char *dato, const char *tabla, - const char *nomdato, const char *nomidentificador) -{ - const char *msglog; - int identificador; - dbi_result result; - - if (strlen(dato) == 0) - return (0); // EL dato no tiene valor - result = dbi_conn_queryf(dbi->conn, - "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador, - tabla, nomdato, dato); - - // Ejecuta consulta - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return (0); - } - if (!dbi_result_next_row(result)) { // Software NO existente - dbi_result_free(result); - - result = dbi_conn_queryf(dbi->conn, - "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return (0); - } - dbi_result_free(result); - - // Recupera el identificador del software - identificador = dbi_conn_sequence_last(dbi->conn, NULL); - } else { - identificador = dbi_result_get_uint(result, nomidentificador); - } - dbi_result_free(result); - - return (identificador); -} -// ________________________________________________________________________________________________________ -// Función: registraCliente -// -// Descripción: -// Incluye al cliente en la tabla de sokets -// Parámetros: -// - iph: Dirección ip del cliente -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool registraCliente(char *iph) -{ - int idx; - - if (!clienteExistente(iph, &idx)) { // Si no existe la IP ... - if (!hayHueco(&idx)) { // Busca hueco para el nuevo cliente - return false; // No hay huecos - } - } - strcpy(tbsockets[idx].ip, iph); // Copia IP - strcpy(tbsockets[idx].estado, CLIENTE_INICIANDO); // Actualiza el estado del cliente - return true; -} -// ________________________________________________________________________________________________________ -// Función: AutoexecCliente -// -// Descripción: -// Envía archivo de autoexec al cliente -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool AutoexecCliente(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - int lon; - char *iph, *exe; - FILE *fileexe; - char fileautoexec[LONPRM]; - char parametros[LONGITUD_PARAMETROS]; - struct og_dbi *dbi; - - iph = copiaParametro("iph",ptrTrama); // Toma dirección IP del cliente - exe = copiaParametro("exe",ptrTrama); // Toma identificador del procedimiento inicial - - sprintf(fileautoexec, "/tmp/Sautoexec-%s", iph); - liberaMemoria(iph); - fileexe = fopen(fileautoexec, "wb"); // Abre fichero de script - if (fileexe == NULL) { - syslog(LOG_ERR, "cannot create temporary file\n"); - return false; - } - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - initParametros(ptrTrama,0); - if (recorreProcedimientos(dbi, parametros, fileexe, exe)) { - lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r"); - lon += sprintf(ptrTrama->parametros + lon, "nfl=%s\r", fileautoexec); - lon += sprintf(ptrTrama->parametros + lon, "res=1\r"); - } else { - lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r"); - lon += sprintf(ptrTrama->parametros + lon, "res=0\r"); - } - - og_dbi_close(dbi); - fclose(fileexe); - - if (!mandaTrama(&socket_c, ptrTrama)) { - liberaMemoria(exe); - syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - return false; - } - liberaMemoria(exe); - return true; -} -// ________________________________________________________________________________________________________ -// Función: recorreProcedimientos -// -// Descripción: -// Crea un archivo con el código de un procedimiento separando cada comando por un salto de linea -// Parámetros: -// Database db,char* parametros,FILE* fileexe,char* idp -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool recorreProcedimientos(struct og_dbi *dbi, char *parametros, FILE *fileexe, char *idp) -{ - char idprocedimiento[LONPRM]; - int procedimientoid, lsize; - const char *msglog, *param; - dbi_result result; - - result = dbi_conn_queryf(dbi->conn, - "SELECT procedimientoid,parametros FROM procedimientos_acciones" - " WHERE idprocedimiento=%s ORDER BY orden", idp); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - while (dbi_result_next_row(result)) { - procedimientoid = dbi_result_get_uint(result, "procedimientoid"); - if (procedimientoid > 0) { // Procedimiento recursivo - sprintf(idprocedimiento, "%d", procedimientoid); - if (!recorreProcedimientos(dbi, parametros, fileexe, idprocedimiento)) { - return false; - } - } else { - param = dbi_result_get_string(result, "parametros"); - sprintf(parametros, "%s@", param); - lsize = strlen(parametros); - fwrite(parametros, 1, lsize, fileexe); // Escribe el código a ejecutar - } - } - dbi_result_free(result); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: ComandosPendientes -// -// Descripción: -// Esta función busca en la base de datos,comandos pendientes de ejecutar por un ordenador concreto -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool ComandosPendientes(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - char *ido,*iph,pids[LONPRM]; - int ids, idx; - - iph = copiaParametro("iph",ptrTrama); // Toma dirección IP - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!clienteExistente(iph, &idx)) { // Busca índice del cliente - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "client does not exist\n"); - return false; - } - if (buscaComandos(ido, ptrTrama, &ids)) { // Existen comandos pendientes - ptrTrama->tipo = MSG_COMANDO; - sprintf(pids, "\rids=%d\r", ids); - strcat(ptrTrama->parametros, pids); - strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); - } else { - initParametros(ptrTrama,0); - strcpy(ptrTrama->parametros, "nfn=NoComandosPtes\r"); - } - if (!mandaTrama(&socket_c, ptrTrama)) { - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - return false; - } - liberaMemoria(iph); - liberaMemoria(ido); - return true; -} -// ________________________________________________________________________________________________________ -// Función: buscaComandos -// -// Descripción: -// Busca en la base de datos,comandos pendientes de ejecutar por el cliente -// Parámetros: -// - ido: Identificador del ordenador -// - cmd: Parámetros del comando (Salida) -// - ids: Identificador de la sesion(Salida) -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool buscaComandos(char *ido, TRAMA *ptrTrama, int *ids) -{ - const char *param, *msglog; - struct og_dbi *dbi; - dbi_result result; - unsigned int lonprm; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - goto err_dbi_open; - } - result = dbi_conn_queryf(dbi->conn, - "SELECT sesion, parametros"\ - " FROM acciones WHERE idordenador=%s AND estado='%d'"\ - " ORDER BY idaccion", ido, ACCION_INICIADA); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - goto err_query_fail; - } - if (!dbi_result_next_row(result)) { - dbi_result_free(result); - og_dbi_close(dbi); - return false; // No hay comandos pendientes - } - - *ids = dbi_result_get_uint(result, "sesion"); - param = dbi_result_get_string(result, "parametros"); - lonprm = strlen(param); - - if(!initParametros(ptrTrama,lonprm + LONGITUD_PARAMETROS)){ - syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); - goto err_init_params; - } - sprintf(ptrTrama->parametros, "%s", param); - - dbi_result_free(result); - og_dbi_close(dbi); - - return true; // Hay comandos pendientes, se toma el primero de la cola - -err_init_params: - dbi_result_free(result); -err_query_fail: - og_dbi_close(dbi); -err_dbi_open: - return false; -} -// ________________________________________________________________________________________________________ -// Función: DisponibilidadComandos -// -// Descripción: -// Esta función habilita a un cliente para recibir comandos desde la consola -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -// -static bool DisponibilidadComandos(TRAMA *ptrTrama, struct og_client *cli) -{ - char *iph, *tpc; - int idx; - - iph = copiaParametro("iph",ptrTrama); // Toma ip - if (!clienteExistente(iph, &idx)) { // Busca índice del cliente - liberaMemoria(iph); - syslog(LOG_ERR, "client does not exist\n"); - return false; - } - tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.) - strcpy(tbsockets[idx].estado, tpc); - cli->keepalive_idx = idx; - liberaMemoria(iph); - liberaMemoria(tpc); - return true; -} -// ________________________________________________________________________________________________________ -// Función: respuestaEstandar -// -// Descripción: -// Esta función actualiza la base de datos con el resultado de la ejecución de un comando con seguimiento -// Parámetros: -// - res: resultado de la ejecución del comando -// - der: Descripción del error si hubiese habido -// - iph: Dirección IP -// - ids: identificador de la sesión -// - ido: Identificador del ordenador que notifica -// - db: Objeto base de datos (operativo) -// - tbl: Objeto tabla -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool respuestaEstandar(TRAMA *ptrTrama, char *iph, char *ido, - struct og_dbi *dbi) -{ - char *res, *ids, *der; - char fechafin[LONPRM]; - const char *msglog; - dbi_result result; - struct tm* st; - int idaccion; - - ids = copiaParametro("ids",ptrTrama); - res = copiaParametro("res",ptrTrama); - - if (ids == NULL) { - if (atoi(res) == ACCION_FALLIDA) { - liberaMemoria(res); - return false; - } - liberaMemoria(res); - return true; - } - - if (atoi(ids) == 0) { - liberaMemoria(ids); - if (atoi(res) == ACCION_FALLIDA) { - liberaMemoria(res); - return false; - } - liberaMemoria(res); - return true; - } - - result = dbi_conn_queryf(dbi->conn, - "SELECT * FROM acciones WHERE idordenador=%s" - " AND sesion=%s ORDER BY idaccion", ido,ids); - - liberaMemoria(ids); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, "no actions available\n"); - dbi_result_free(result); - return true; - } - - idaccion = dbi_result_get_uint(result, "idaccion"); - dbi_result_free(result); - - st = tomaHora(); - sprintf(fechafin, "%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1, - st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec); - - der = copiaParametro("der",ptrTrama); // Toma descripción del error (si hubiera habido) - - result = dbi_conn_queryf(dbi->conn, - "UPDATE acciones"\ - " SET resultado='%s',estado='%d',fechahorafin='%s',descrinotificacion='%s'"\ - " WHERE idordenador=%s AND idaccion=%d", - res, ACCION_FINALIZADA, fechafin, der, ido, idaccion); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - liberaMemoria(res); - liberaMemoria(der); - og_info((char *)msglog); - return false; - } - dbi_result_free(result); - - liberaMemoria(der); - - if (atoi(res) == ACCION_FALLIDA) { - liberaMemoria(res); - return false; - } - - liberaMemoria(res); - return true; -} - -static bool og_send_cmd(char *ips_array[], int ips_array_len, - const char *state, TRAMA *ptrTrama) -{ - int i, idx; - - for (i = 0; i < ips_array_len; i++) { - if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos - int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1; - - strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente - if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) { - syslog(LOG_ERR, "failed to send response to %s:%s\n", - ips_array[i], strerror(errno)); - } - } - } - return true; -} - -// ________________________________________________________________________________________________________ -// Función: enviaComando -// -// Descripción: -// Envía un comando a los clientes -// Parámetros: -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// - estado: Estado en el se deja al cliente mientras se ejecuta el comando -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool enviaComando(TRAMA* ptrTrama, const char *estado) -{ - char *iph, *Ipes, *ptrIpes[MAXIMOS_CLIENTES]; - int lon; - - iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP - lon = strlen(iph); // Calcula longitud de la cadena de direccion/es IPE/S - Ipes = (char*) reservaMemoria(lon + 1); - if (Ipes == NULL) { - syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); - return false; - } - - strcpy(Ipes, iph); // Copia cadena de IPES - liberaMemoria(iph); - - lon = splitCadena(ptrIpes, Ipes, ';'); - FINCADaINTRO(ptrTrama); - - if (!og_send_cmd(ptrIpes, lon, estado, ptrTrama)) - return false; - - liberaMemoria(Ipes); - return true; -} -//______________________________________________________________________________________________________ -// Función: respuestaConsola -// -// Descripción: -// Envia una respuesta a la consola sobre el resultado de la ejecución de un comando -// Parámetros: -// - socket_c: (Salida) Socket utilizado para el envío -// - res: Resultado del envío del comando -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool respuestaConsola(int socket_c, TRAMA *ptrTrama, int res) -{ - initParametros(ptrTrama,0); - sprintf(ptrTrama->parametros, "res=%d\r", res); - if (!mandaTrama(&socket_c, ptrTrama)) { - syslog(LOG_ERR, "%s:%d failed to send response: %s\n", - __func__, __LINE__, strerror(errno)); - return false; - } - return true; -} -// ________________________________________________________________________________________________________ -// Función: Levanta -// -// Descripción: -// Enciende ordenadores a través de la red cuyas macs se pasan como parámetro -// Parámetros: -// - iph: Cadena de direcciones ip separadas por ";" -// - mac: Cadena de direcciones mac separadas por ";" -// - mar: Método de arranque (1=Broadcast, 2=Unicast) -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ - -bool Levanta(char *ptrIP[], char *ptrMacs[], int lon, char *mar) -{ - unsigned int on = 1; - struct sockaddr_in local; - int i, res; - int s; - - /* Creación de socket para envío de magig packet */ - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s < 0) { - syslog(LOG_ERR, "cannot create socket for magic packet\n"); - return false; - } - res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on, - sizeof(on)); - if (res < 0) { - syslog(LOG_ERR, "cannot set broadcast socket\n"); - return false; - } - memset(&local, 0, sizeof(local)); - local.sin_family = AF_INET; - local.sin_port = htons(PUERTO_WAKEUP); - local.sin_addr.s_addr = htonl(INADDR_ANY); - - for (i = 0; i < lon; i++) { - if (!WakeUp(s, ptrIP[i], ptrMacs[i], mar)) { - syslog(LOG_ERR, "problem sending magic packet\n"); - close(s); - return false; - } - } - 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; - } - freeifaddrs(ifaddr); - - ret = sendto(sd, msg, sizeof(*msg), 0, - (struct 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, - (struct 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 -// -// Descripción: -// Enciende el ordenador cuya MAC se pasa como parámetro -// Parámetros: -// - s : Socket para enviar trama magic packet -// - iph : Cadena con la dirección ip -// - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX -// - mar: Método de arranque (1=Broadcast, 2=Unicast) -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -//_____________________________________________________________________________________________________________ -// -bool WakeUp(int s, char* iph, char *mac, char *mar) -{ - unsigned int macaddr[OG_WOL_MACADDR_LEN]; - 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; - - sscanf(mac, "%02x%02x%02x%02x%02x%02x", - &macaddr[0], &macaddr[1], &macaddr[2], - &macaddr[3], &macaddr[4], &macaddr[5]); - - for (i = 0; i < 6; i++) - HDaddress_bin[i] = (uint8_t)macaddr[i]; - - for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC - memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6); - - /* Creación de socket del cliente que recibe la trama magic packet */ - WakeUpCliente.sin_family = AF_INET; - WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP); - - 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 ret; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_Arrancar -// -// Descripción: -// Respuesta del cliente al comando Arrancar -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_Arrancar(TRAMA* ptrTrama, struct og_client *cli) -{ - struct og_dbi *dbi; - char *iph, *ido; - char *tpc; - int i; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - og_dbi_close(dbi); - return false; - } - - tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.) - if (clienteExistente(iph, &i)) // Actualiza estado - strcpy(tbsockets[i].estado, tpc); - - liberaMemoria(iph); - liberaMemoria(ido); - liberaMemoria(tpc); - og_dbi_close(dbi); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_Apagar -// -// Descripción: -// Respuesta del cliente al comando Apagar -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli) -{ - struct og_dbi *dbi; - char *iph, *ido; - int i; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - og_dbi_close(dbi); - return false; // Error al registrar notificacion - } - - if (clienteExistente(iph, &i)) // Actualiza estado - strcpy(tbsockets[i].estado, CLIENTE_APAGADO); - - liberaMemoria(iph); - liberaMemoria(ido); - og_dbi_close(dbi); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_CrearImagen -// -// Descripción: -// Respuesta del cliente al comando CrearImagen -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli) -{ - char *iph, *dsk, *par, *cpt, *ipr, *ido; - struct og_dbi *dbi; - char *idi; - bool res; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - og_dbi_close(dbi); - return false; // Error al registrar notificacion - } - - // Acciones posteriores - idi = copiaParametro("idi",ptrTrama); - dsk = copiaParametro("dsk",ptrTrama); - par = copiaParametro("par",ptrTrama); - cpt = copiaParametro("cpt",ptrTrama); - ipr = copiaParametro("ipr",ptrTrama); - - res=actualizaCreacionImagen(dbi, idi, dsk, par, cpt, ipr, ido); - - liberaMemoria(idi); - liberaMemoria(par); - liberaMemoria(cpt); - liberaMemoria(ipr); - og_dbi_close(dbi); - - if (!res) - syslog(LOG_ERR, "Problem processing update\n"); - - return res; -} -// ________________________________________________________________________________________________________ -// Función: actualizaCreacionImagen -// -// Descripción: -// Esta función actualiza la base de datos con el resultado de la creación de una imagen -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - idi: Identificador de la imagen -// - dsk: Disco de donde se creó -// - par: Partición de donde se creó -// - cpt: Código de partición -// - ipr: Ip del repositorio -// - ido: Identificador del ordenador modelo -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool actualizaCreacionImagen(struct og_dbi *dbi, char *idi, char *dsk, - char *par, char *cpt, char *ipr, char *ido) -{ - const char *msglog; - dbi_result result; - int idr,ifs; - - /* Toma identificador del repositorio correspondiente al ordenador modelo */ - result = dbi_conn_queryf(dbi->conn, - "SELECT repositorios.idrepositorio" - " FROM repositorios" - " LEFT JOIN ordenadores USING (idrepositorio)" - " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, - "repository does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - return false; - } - idr = dbi_result_get_uint(result, "idrepositorio"); - dbi_result_free(result); - - /* Toma identificador del perfilsoftware */ - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilsoft" - " FROM ordenadores_particiones" - " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, - "software profile does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - return false; - } - ifs = dbi_result_get_uint(result, "idperfilsoft"); - dbi_result_free(result); - - /* Actualizar los datos de la imagen */ - result = dbi_conn_queryf(dbi->conn, - "UPDATE imagenes" - " SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s," - " idperfilsoft=%d, idrepositorio=%d," - " fechacreacion=NOW(), revision=revision+1" - " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - /* Actualizar los datos en el cliente */ - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones" - " SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," - " fechadespliegue=NOW()" - " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", - idi, idi, ido, dsk, par); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: CrearImagenBasica -// -// Descripción: -// Crea una imagen basica usando sincronización -// Parámetros: -// - socket_c: Socket de la consola al envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli) -{ - if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) { - respuestaConsola(og_client_socket(cli), ptrTrama, false); - return false; - } - respuestaConsola(og_client_socket(cli), ptrTrama, true); - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_CrearImagenBasica -// -// Descripción: -// Respuesta del cliente al comando CrearImagenBasica -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli) -{ - // La misma respuesta que la creación de imagen monolítica - return RESPUESTA_CrearImagen(ptrTrama, cli); -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_CrearSoftIncremental -// -// Descripción: -// Respuesta del cliente al comando crearImagenDiferencial -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli) -{ - char *iph,*par,*ido,*idf; - int ifs; - const char *msglog; - struct og_dbi *dbi; - dbi_result result; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - og_dbi_close(dbi); - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - return false; - } - - par = copiaParametro("par",ptrTrama); - - /* Toma identificador del perfilsoftware creado por el inventario de software */ - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s", - ido, par); - liberaMemoria(iph); - liberaMemoria(ido); - liberaMemoria(par); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - og_dbi_close(dbi); - return false; - } - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, - "software profile does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - og_dbi_close(dbi); - return false; - } - ifs = dbi_result_get_uint(result, "idperfilsoft"); - dbi_result_free(result); - - /* Actualizar los datos de la imagen */ - idf = copiaParametro("idf", ptrTrama); - result = dbi_conn_queryf(dbi->conn, - "UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s", - ifs, idf); - liberaMemoria(idf); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - og_dbi_close(dbi); - return false; - } - dbi_result_free(result); - - og_dbi_close(dbi); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_RestaurarImagen -// -// Descripción: -// Respuesta del cliente al comando RestaurarImagen -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -// -static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli) -{ - bool res; - char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg; - struct og_dbi *dbi; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - og_dbi_close(dbi); - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - return false; - } - - // Acciones posteriores - idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen - dsk = copiaParametro("dsk",ptrTrama); // Número de disco - par = copiaParametro("par",ptrTrama); // Número de partición - ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido - cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos - if(cfg){ - actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador - liberaMemoria(cfg); - } - res=actualizaRestauracionImagen(dbi, idi, dsk, par, ido, ifs); - - liberaMemoria(iph); - liberaMemoria(ido); - liberaMemoria(idi); - liberaMemoria(par); - liberaMemoria(ifs); - og_dbi_close(dbi); - - if(!res) - syslog(LOG_ERR, "Problem after restoring image\n"); - - return res; -} -// ________________________________________________________________________________________________________ -// -// Función: RESPUESTA_RestaurarImagenBasica -// -// Descripción: -// Respuesta del cliente al comando RestaurarImagen -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -// -static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli) -{ - return RESPUESTA_RestaurarImagen(ptrTrama, cli); -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_RestaurarSoftIncremental -// -// Descripción: -// Respuesta del cliente al comando RestaurarSoftIncremental -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli) -{ - return RESPUESTA_RestaurarImagen(ptrTrama, cli); -} -// ________________________________________________________________________________________________________ -// Función: actualizaRestauracionImagen -// -// Descripción: -// Esta función actualiza la base de datos con el resultado de la restauración de una imagen -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - idi: Identificador de la imagen -// - dsk: Disco de donde se restauró -// - par: Partición de donde se restauró -// - ido: Identificador del cliente donde se restauró -// - ifs: Identificador del perfil software contenido en la imagen -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -bool actualizaRestauracionImagen(struct og_dbi *dbi, char *idi, - char *dsk, char *par, char *ido, char *ifs) -{ - const char *msglog; - dbi_result result; - - /* Actualizar los datos de la imagen */ - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones" - " SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW()," - " revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," - " idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)" - " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_EjecutarScript -// -// Descripción: -// Respuesta del cliente al comando EjecutarScript -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli) -{ - char *iph, *ido,*cfg; - struct og_dbi *dbi; - bool res = true; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - og_dbi_close(dbi); - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - return false; - } - - cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones - if(cfg){ - res = actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador - liberaMemoria(cfg); - } - - liberaMemoria(iph); - liberaMemoria(ido); - og_dbi_close(dbi); - - if (!res) - syslog(LOG_ERR, "Problem updating client configuration\n"); - - return res; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_InventarioHardware -// -// Descripción: -// Respuesta del cliente al comando InventarioHardware -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli) -{ - bool res; - char *iph, *ido, *idc, *npc, *hrd, *buffer; - struct og_dbi *dbi; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente - ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - og_dbi_close(dbi); - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - return false; - } - // Lee archivo de inventario enviado anteriormente - hrd = copiaParametro("hrd",ptrTrama); - buffer = rTrim(leeArchivo(hrd)); - - npc = copiaParametro("npc",ptrTrama); - idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro - - if (buffer) - res=actualizaHardware(dbi, buffer, ido, npc, idc); - - liberaMemoria(iph); - liberaMemoria(ido); - liberaMemoria(npc); - liberaMemoria(idc); - liberaMemoria(buffer); - og_dbi_close(dbi); - - if (!res) - syslog(LOG_ERR, "Problem updating client configuration\n"); - - return res; -} -// ________________________________________________________________________________________________________ -// Función: actualizaHardware -// -// Descripción: -// Actualiza la base de datos con la configuracion hardware del cliente -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - hrd: cadena con el inventario hardware -// - ido: Identificador del ordenador -// - npc: Nombre del ordenador -// - idc: Identificador del centro o Unidad organizativa -// ________________________________________________________________________________________________________ -// -bool actualizaHardware(struct og_dbi *dbi, char *hrd, char *ido, char *npc, - char *idc) -{ - const char *msglog; - int idtipohardware, idperfilhard; - int lon, i, j, aux; - bool retval; - char *whard; - int tbidhardware[MAXHARDWARE]; - char *tbHardware[MAXHARDWARE],*dualHardware[2], strInt[LONINT], *idhardwares; - dbi_result result; - - /* Toma Centro (Unidad Organizativa) */ - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilhard FROM ordenadores WHERE idordenador=%s", - ido); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", - __func__, __LINE__); - dbi_result_free(result); - return false; - } - idperfilhard = dbi_result_get_uint(result, "idperfilhard"); - dbi_result_free(result); - - whard=escaparCadena(hrd); // Codificar comillas simples - if(!whard) - return false; - /* Recorre componentes hardware*/ - lon = splitCadena(tbHardware, whard, '\n'); - if (lon > MAXHARDWARE) - lon = MAXHARDWARE; // Limita el número de componentes hardware - /* - for (i=0;iconn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { // Tipo de Hardware NO existente - dbi_result_free(result); - return false; - } else { // Tipo de Hardware Existe - idtipohardware = dbi_result_get_uint(result, "idtipohardware"); - dbi_result_free(result); - - result = dbi_conn_queryf(dbi->conn, - "SELECT idhardware FROM hardwares WHERE idtipohardware=%d AND descripcion='%s'", - idtipohardware, dualHardware[1]); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - - if (!dbi_result_next_row(result)) { // Hardware NO existente - dbi_result_free(result); - result = dbi_conn_queryf(dbi->conn, - "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) " - " VALUES(%d,'%s',%s,0)", idtipohardware, - dualHardware[1], idc); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - - // Recupera el identificador del hardware - tbidhardware[i] = dbi_conn_sequence_last(dbi->conn, NULL); - } else { - tbidhardware[i] = dbi_result_get_uint(result, "idhardware"); - } - dbi_result_free(result); - } - } - // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones - - for (i = 0; i < lon - 1; i++) { - for (j = i + 1; j < lon; j++) { - if (tbidhardware[i] > tbidhardware[j]) { - aux = tbidhardware[i]; - tbidhardware[i] = tbidhardware[j]; - tbidhardware[j] = aux; - } - } - } - /* Crea cadena de identificadores de componentes hardware separados por coma */ - sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud - aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles - idhardwares = reservaMemoria(sizeof(aux) * lon + lon); - if (idhardwares == NULL) { - syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); - return false; - } - aux = sprintf(idhardwares, "%d", tbidhardware[0]); - for (i = 1; i < lon; i++) - aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]); - - if (!cuestionPerfilHardware(dbi, idc, ido, idperfilhard, idhardwares, - npc, tbidhardware, lon)) { - syslog(LOG_ERR, "Problem updating client hardware\n"); - retval=false; - } - else { - retval=true; - } - liberaMemoria(whard); - liberaMemoria(idhardwares); - return (retval); -} -// ________________________________________________________________________________________________________ -// Función: cuestionPerfilHardware -// -// Descripción: -// Comprueba existencia de perfil hardware y actualización de éste para el ordenador -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - idc: Identificador de la Unidad organizativa donde se encuentra el cliente -// - ido: Identificador del ordenador -// - tbidhardware: Identificador del tipo de hardware -// - con: Número de componentes detectados para configurar un el perfil hardware -// - npc: Nombre del cliente -// ________________________________________________________________________________________________________ -bool cuestionPerfilHardware(struct og_dbi *dbi, char *idc, char *ido, - int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware, - int lon) -{ - const char *msglog; - dbi_result result; - int i; - int nwidperfilhard; - - // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilhard FROM" - " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard," - " group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )" - " ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares" - " FROM perfileshard_hardwares" - " GROUP BY perfileshard_hardwares.idperfilhard) AS temp" - " WHERE idhardwares LIKE '%s'", idhardwares); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - // No existe un perfil hardware con esos componentes de componentes hardware, lo crea - dbi_result_free(result); - result = dbi_conn_queryf(dbi->conn, - "INSERT perfileshard (descripcion,idcentro,grupoid)" - " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - // Recupera el identificador del nuevo perfil hardware - nwidperfilhard = dbi_conn_sequence_last(dbi->conn, NULL); - - // Crea la relación entre perfiles y componenetes hardware - for (i = 0; i < lon; i++) { - result = dbi_conn_queryf(dbi->conn, - "INSERT perfileshard_hardwares (idperfilhard,idhardware)" - " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - } - } else { // Existe un perfil con todos esos componentes - nwidperfilhard = dbi_result_get_uint(result, "idperfilhard"); - dbi_result_free(result); - } - if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles - // Actualiza el identificador del perfil hardware del ordenador - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET idperfilhard=%d" - " WHERE idordenador=%s", nwidperfilhard, ido); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - } - /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN " - " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN" - " (SELECT DISTINCT idperfilhard from ordenadores))"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - /* Eliminar Perfiles hardware que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfileshard WHERE idperfilhard NOT IN" - " (SELECT DISTINCT idperfilhard FROM ordenadores)"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN" - " (SELECT idperfilhard FROM perfileshard)"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: RESPUESTA_InventarioSoftware -// -// Descripción: -// Respuesta del cliente al comando InventarioSoftware -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli) -{ - bool res; - char *iph, *ido, *npc, *idc, *par, *sft, *buffer; - struct og_dbi *dbi; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - iph = copiaParametro("iph",ptrTrama); // Toma dirección ip - ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador - - if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) { - og_dbi_close(dbi); - liberaMemoria(iph); - liberaMemoria(ido); - syslog(LOG_ERR, "failed to register notification\n"); - return false; - } - - npc = copiaParametro("npc",ptrTrama); - idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro - par = copiaParametro("par",ptrTrama); - sft = copiaParametro("sft",ptrTrama); - - buffer = rTrim(leeArchivo(sft)); - if (buffer) - res=actualizaSoftware(dbi, buffer, par, ido, npc, idc); - - liberaMemoria(iph); - liberaMemoria(ido); - liberaMemoria(npc); - liberaMemoria(idc); - liberaMemoria(par); - liberaMemoria(sft); - og_dbi_close(dbi); - - if (!res) - syslog(LOG_ERR, "cannot update software\n"); - - return res; -} -// ________________________________________________________________________________________________________ -// Función: actualizaSoftware -// -// Descripción: -// Actualiza la base de datos con la configuración software del cliente -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - sft: cadena con el inventario software -// - par: Número de la partición -// - ido: Identificador del ordenador del cliente en la tabla -// - npc: Nombre del ordenador -// - idc: Identificador del centro o Unidad organizativa -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// -// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla -// ________________________________________________________________________________________________________ -bool actualizaSoftware(struct og_dbi *dbi, char *sft, char *par,char *ido, - char *npc, char *idc) -{ - int i, j, lon, aux, idperfilsoft, idnombreso; - bool retval; - char *wsft; - int tbidsoftware[MAXSOFTWARE]; - char *tbSoftware[MAXSOFTWARE], strInt[LONINT], *idsoftwares; - const char *msglog; - dbi_result result; - - /* Toma Centro (Unidad Organizativa) y perfil software */ - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilsoft,numpar" - " FROM ordenadores_particiones" - " WHERE idordenador=%s", ido); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software - while (dbi_result_next_row(result)) { - aux = dbi_result_get_uint(result, "numpar"); - if (aux == atoi(par)) { // Se encuentra la partición - idperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); - break; - } - } - dbi_result_free(result); - wsft=escaparCadena(sft); // Codificar comillas simples - if(!wsft) - return false; - - /* Recorre componentes software*/ - lon = splitCadena(tbSoftware, wsft, '\n'); - - if (lon == 0) - return true; // No hay lineas que procesar - if (lon > MAXSOFTWARE) - lon = MAXSOFTWARE; // Limita el número de componentes software - - for (i = 0; i < lon; i++) { - // Primera línea es el sistema operativo: se obtiene identificador - if (i == 0) { - idnombreso = checkDato(dbi, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso"); - continue; - } - - result = dbi_conn_queryf(dbi->conn, - "SELECT idsoftware FROM softwares WHERE descripcion ='%s'", - rTrim(tbSoftware[i])); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - - if (!dbi_result_next_row(result)) { - dbi_result_free(result); - result = dbi_conn_queryf(dbi->conn, - "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)" - " VALUES(2,'%s',%s,0)", tbSoftware[i], idc); - if (!result) { // Error al insertar - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result); - - // Recupera el identificador del software - tbidsoftware[i] = dbi_conn_sequence_last(dbi->conn, NULL); - } else { - tbidsoftware[i] = dbi_result_get_uint(result, "idsoftware"); - } - } - - // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones - - for (i = 0; i < lon - 1; i++) { - for (j = i + 1; j < lon; j++) { - if (tbidsoftware[i] > tbidsoftware[j]) { - aux = tbidsoftware[i]; - tbidsoftware[i] = tbidsoftware[j]; - tbidsoftware[j] = aux; - } - } - } - /* Crea cadena de identificadores de componentes software separados por coma */ - sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud - aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles - idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon); - if (idsoftwares == NULL) { - syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); - return false; - } - aux = sprintf(idsoftwares, "%d", tbidsoftware[0]); - for (i = 1; i < lon; i++) - aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]); - - // Comprueba existencia de perfil software y actualización de éste para el ordenador - if (!cuestionPerfilSoftware(dbi, idc, ido, idperfilsoft, idnombreso, idsoftwares, - npc, par, tbidsoftware, lon)) { - syslog(LOG_ERR, "cannot update software\n"); - og_info((char *)msglog); - retval=false; - } - else { - retval=true; - } - liberaMemoria(wsft); - liberaMemoria(idsoftwares); - return (retval); -} -// ________________________________________________________________________________________________________ -// Función: CuestionPerfilSoftware -// -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - idcentro: Identificador del centro en la tabla -// - ido: Identificador del ordenador del cliente en la tabla -// - idnombreso: Identificador del sistema operativo -// - idsoftwares: Cadena con los identificadores de componentes software separados por comas -// - npc: Nombre del ordenador del cliente -// - particion: Número de la partición -// - tbidsoftware: Array con los identificadores de componentes software -// - lon: Número de componentes -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// -// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla -//_________________________________________________________________________________________________________ -bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido, - int idperfilsoftware, int idnombreso, - char *idsoftwares, char *npc, char *par, - int *tbidsoftware, int lon) -{ - int i, nwidperfilsoft; - const char *msglog; - dbi_result result; - - // Busca perfil soft del ordenador que contenga todos los componentes software encontrados - result = dbi_conn_queryf(dbi->conn, - "SELECT idperfilsoft FROM" - " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft," - " group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )" - " ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares" - " FROM perfilessoft_softwares" - " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp" - " WHERE idsoftwares LIKE '%s'", idsoftwares); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { // No existe un perfil software con esos componentes de componentes software, lo crea - dbi_result_free(result); - result = dbi_conn_queryf(dbi->conn, - "INSERT perfilessoft (descripcion, idcentro, grupoid, idnombreso)" - " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - - dbi_result_free(result); - // Recupera el identificador del nuevo perfil software - nwidperfilsoft = dbi_conn_sequence_last(dbi->conn, NULL); - - // Crea la relación entre perfiles y componenetes software - for (i = 0; i < lon; i++) { - result = dbi_conn_queryf(dbi->conn, - "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)" - " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result); - } - } else { // Existe un perfil con todos esos componentes - nwidperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); - dbi_result_free(result); - } - - if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles - // Actualiza el identificador del perfil software del ordenador - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0" - " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par); - if (!result) { // Error al insertar - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result); - } - - /* DEPURACIÓN DE PERFILES SOFTWARE */ - - /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\ - " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\ - " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\ - " (SELECT DISTINCT idperfilsoft from imagenes))"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result), - /* Eliminar Perfiles software que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN" - " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\ - " AND idperfilsoft NOT IN"\ - " (SELECT DISTINCT idperfilsoft from imagenes)"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result), - - /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ - result = dbi_conn_queryf(dbi->conn, - "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN" - " (SELECT idperfilsoft from perfilessoft)"); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - og_info((char *)msglog); - return false; - } - dbi_result_free(result); - - return true; -} -// ________________________________________________________________________________________________________ -// Función: enviaArchivo -// -// Descripción: -// Envia un archivo por la red, por bloques -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - char *nfl; - - // Toma parámetros - nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo - if (!sendArchivo(&socket_c, nfl)) { - liberaMemoria(nfl); - syslog(LOG_ERR, "Problem sending file\n"); - return false; - } - liberaMemoria(nfl); - return true; -} -// ________________________________________________________________________________________________________ -// Función: enviaArchivo -// -// Descripción: -// Envia un archivo por la red, por bloques -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli) -{ - int socket_c = og_client_socket(cli); - char *nfl; - - // Toma parámetros - nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo - ptrTrama->tipo = MSG_NOTIFICACION; - enviaFlag(&socket_c, ptrTrama); - if (!recArchivo(&socket_c, nfl)) { - liberaMemoria(nfl); - syslog(LOG_ERR, "Problem receiving file\n"); - return false; - } - liberaMemoria(nfl); - return true; -} -// ________________________________________________________________________________________________________ -// Función: envioProgramacion -// -// Descripción: -// Envia un comando de actualización a todos los ordenadores que han sido programados con -// alguna acción para que entren en el bucle de comandos pendientes y las ejecuten -// Parámetros: -// - socket_c: Socket del cliente que envió el mensaje -// - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli) -{ - char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES]; - char *idp, *iph, *mac; - int idx,idcomando,lon; - const char *msglog; - struct og_dbi *dbi; - dbi_result result; - - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); - return false; - } - - idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones - - result = dbi_conn_queryf(dbi->conn, - "SELECT ordenadores.ip,ordenadores.mac,acciones.idcomando FROM acciones "\ - " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\ - " WHERE acciones.idprogramacion=%s",idp); - - liberaMemoria(idp); - - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - og_dbi_close(dbi); - return false; - } - - /* Prepara la trama de actualizacion */ - - initParametros(ptrTrama,0); - ptrTrama->tipo=MSG_COMANDO; - sprintf(ptrTrama->parametros, "nfn=Actualizar\r"); - - while (dbi_result_next_row(result)) { - iph = (char *)dbi_result_get_string(result, "ip"); - idcomando = dbi_result_get_uint(result, "idcomando"); - - if (idcomando == 1){ // Arrancar - mac = (char *)dbi_result_get_string(result, "mac"); - lon = splitCadena(ptrIP, iph, ';'); - lon = splitCadena(ptrMacs, mac, ';'); - - // Se manda por broadcast y por unicast - if (!Levanta(ptrIP, ptrMacs, lon, (char*)"1")) { - dbi_result_free(result); - og_dbi_close(dbi); - return false; - } - - if (!Levanta(ptrIP, ptrMacs, lon, (char*)"2")) { - dbi_result_free(result); - og_dbi_close(dbi); - return false; - } - - } - if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos - int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1; - - strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente - if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) { - syslog(LOG_ERR, "failed to send response: %s\n", - strerror(errno)); - } - //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad - } - } - dbi_result_free(result); - og_dbi_close(dbi); - - return true; // No existen registros -} - -// This object stores function handler for messages -static struct { - const char *nf; // Nombre de la función - bool (*fcn)(TRAMA *, struct og_client *cli); -} tbfuncionesServer[] = { - { "InclusionCliente", InclusionCliente, }, - { "InclusionClienteWinLnx", InclusionClienteWinLnx, }, - { "AutoexecCliente", AutoexecCliente, }, - { "ComandosPendientes", ComandosPendientes, }, - { "DisponibilidadComandos", DisponibilidadComandos, }, - { "RESPUESTA_Arrancar", RESPUESTA_Arrancar, }, - { "RESPUESTA_Apagar", RESPUESTA_Apagar, }, - { "RESPUESTA_Reiniciar", RESPUESTA_Apagar, }, - { "RESPUESTA_IniciarSesion", RESPUESTA_Apagar, }, - { "RESPUESTA_CrearImagen", RESPUESTA_CrearImagen, }, - { "CrearImagenBasica", CrearImagenBasica, }, - { "RESPUESTA_CrearImagenBasica", RESPUESTA_CrearImagenBasica, }, - { "CrearSoftIncremental", CrearImagenBasica, }, - { "RESPUESTA_CrearSoftIncremental", RESPUESTA_CrearSoftIncremental, }, - { "RESPUESTA_RestaurarImagen", RESPUESTA_RestaurarImagen }, - { "RestaurarImagenBasica", CrearImagenBasica, }, - { "RESPUESTA_RestaurarImagenBasica", RESPUESTA_RestaurarImagenBasica, }, - { "RestaurarSoftIncremental", CrearImagenBasica, }, - { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, }, - { "Configurar", CrearImagenBasica, }, - { "RESPUESTA_Configurar", RESPUESTA_EjecutarScript, }, - { "EjecutarScript", CrearImagenBasica, }, - { "RESPUESTA_EjecutarScript", RESPUESTA_EjecutarScript, }, - { "RESPUESTA_InventarioHardware", RESPUESTA_InventarioHardware, }, - { "RESPUESTA_InventarioSoftware", RESPUESTA_InventarioSoftware, }, - { "enviaArchivo", enviaArchivo, }, - { "recibeArchivo", recibeArchivo, }, - { "envioProgramacion", envioProgramacion, }, - { NULL, NULL, }, -}; - -// ________________________________________________________________________________________________________ -// Función: gestionaTrama -// -// Descripción: -// Procesa las tramas recibidas . -// Parametros: -// - s : Socket usado para comunicaciones -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// ________________________________________________________________________________________________________ -static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli) -{ - int i, res; - char *nfn; - - if (ptrTrama){ - INTROaFINCAD(ptrTrama); - nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función - - for (i = 0; tbfuncionesServer[i].fcn; i++) { - if (!strncmp(tbfuncionesServer[i].nf, nfn, - strlen(tbfuncionesServer[i].nf))) { - res = tbfuncionesServer[i].fcn(ptrTrama, cli); - if (!res) { - syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n", - tbfuncionesServer[i].nf, - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - } else { - syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n", - tbfuncionesServer[i].nf, - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - } - break; - } - } - if (!tbfuncionesServer[i].fcn) - syslog(LOG_ERR, "unknown request %s from client %s:%hu\n", - nfn, inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - - liberaMemoria(nfn); - } -} - -static void og_client_release(struct ev_loop *loop, struct og_client *cli) -{ - if (cli->keepalive_idx >= 0) { - syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port), cli->keepalive_idx); - tbsockets[cli->keepalive_idx].cli = NULL; - } - - ev_io_stop(loop, &cli->io); - close(cli->io.fd); - free(cli); -} - -static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli) -{ - struct og_client *old_cli; - - old_cli = tbsockets[cli->keepalive_idx].cli; - if (old_cli && old_cli != cli) { - syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n", - inet_ntoa(old_cli->addr.sin_addr), - ntohs(old_cli->addr.sin_port)); - - og_client_release(loop, old_cli); - } - tbsockets[cli->keepalive_idx].cli = cli; -} - -static void og_client_reset_state(struct og_client *cli) -{ - cli->state = OG_CLIENT_RECEIVING_HEADER; - cli->buf_len = 0; -} - -static int og_client_state_recv_hdr(struct og_client *cli) -{ - char hdrlen[LONHEXPRM]; - - /* Still too short to validate protocol fingerprint and message - * length. - */ - if (cli->buf_len < 15 + LONHEXPRM) - return 0; - - if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) { - syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - return -1; - } - - memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM); - cli->msg_len = strtol(hdrlen, NULL, 16); - - /* Header announces more that we can fit into buffer. */ - if (cli->msg_len >= sizeof(cli->buf)) { - syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n", - cli->msg_len, inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - return -1; - } - - return 1; -} - -static TRAMA *og_msg_alloc(char *data, unsigned int len) -{ - TRAMA *ptrTrama; - - ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA)); - if (!ptrTrama) { - syslog(LOG_ERR, "OOM\n"); - return NULL; - } - - initParametros(ptrTrama, len); - memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA); - memcpy(ptrTrama->parametros, data, len); - ptrTrama->lonprm = len; - - return ptrTrama; -} - -static void og_msg_free(TRAMA *ptrTrama) -{ - liberaMemoria(ptrTrama->parametros); - liberaMemoria(ptrTrama); -} - -static int og_client_state_process_payload(struct og_client *cli) -{ - TRAMA *ptrTrama; - char *data; - int len; - - len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM); - data = &cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM]; - - ptrTrama = og_msg_alloc(data, len); - if (!ptrTrama) - return -1; - - gestionaTrama(ptrTrama, cli); - - og_msg_free(ptrTrama); - - return 1; -} - -#define OG_CLIENTS_MAX 4096 -#define OG_PARTITION_MAX 4 - -struct og_partition { - const char *number; - const char *code; - const char *size; - const char *filesystem; - const char *format; -}; - -struct og_sync_params { - const char *sync; - const char *diff; - const char *remove; - const char *compress; - const char *cleanup; - const char *cache; - const char *cleanup_cache; - const char *remove_dst; - const char *diff_id; - const char *diff_name; - const char *path; - const char *method; -}; - -struct og_msg_params { - const char *ips_array[OG_CLIENTS_MAX]; - const char *mac_array[OG_CLIENTS_MAX]; - unsigned int ips_array_len; - const char *wol_type; - char run_cmd[4096]; - const char *disk; - const char *partition; - const char *repository; - const char *name; - const char *id; - const char *code; - const char *type; - const char *profile; - const char *cache; - const char *cache_size; - bool echo; - struct og_partition partition_setup[OG_PARTITION_MAX]; - struct og_sync_params sync_setup; - uint64_t flags; -}; - -#define OG_REST_PARAM_ADDR (1UL << 0) -#define OG_REST_PARAM_MAC (1UL << 1) -#define OG_REST_PARAM_WOL_TYPE (1UL << 2) -#define OG_REST_PARAM_RUN_CMD (1UL << 3) -#define OG_REST_PARAM_DISK (1UL << 4) -#define OG_REST_PARAM_PARTITION (1UL << 5) -#define OG_REST_PARAM_REPO (1UL << 6) -#define OG_REST_PARAM_NAME (1UL << 7) -#define OG_REST_PARAM_ID (1UL << 8) -#define OG_REST_PARAM_CODE (1UL << 9) -#define OG_REST_PARAM_TYPE (1UL << 10) -#define OG_REST_PARAM_PROFILE (1UL << 11) -#define OG_REST_PARAM_CACHE (1UL << 12) -#define OG_REST_PARAM_CACHE_SIZE (1UL << 13) -#define OG_REST_PARAM_PART_0 (1UL << 14) -#define OG_REST_PARAM_PART_1 (1UL << 15) -#define OG_REST_PARAM_PART_2 (1UL << 16) -#define OG_REST_PARAM_PART_3 (1UL << 17) -#define OG_REST_PARAM_SYNC_SYNC (1UL << 18) -#define OG_REST_PARAM_SYNC_DIFF (1UL << 19) -#define OG_REST_PARAM_SYNC_REMOVE (1UL << 20) -#define OG_REST_PARAM_SYNC_COMPRESS (1UL << 21) -#define OG_REST_PARAM_SYNC_CLEANUP (1UL << 22) -#define OG_REST_PARAM_SYNC_CACHE (1UL << 23) -#define OG_REST_PARAM_SYNC_CLEANUP_CACHE (1UL << 24) -#define OG_REST_PARAM_SYNC_REMOVE_DST (1UL << 25) -#define OG_REST_PARAM_SYNC_DIFF_ID (1UL << 26) -#define OG_REST_PARAM_SYNC_DIFF_NAME (1UL << 27) -#define OG_REST_PARAM_SYNC_PATH (1UL << 28) -#define OG_REST_PARAM_SYNC_METHOD (1UL << 29) -#define OG_REST_PARAM_ECHO (1UL << 30) - -static bool og_msg_params_validate(const struct og_msg_params *params, - const uint64_t flags) -{ - return (params->flags & flags) == flags; -} - -static int og_json_parse_clients(json_t *element, struct og_msg_params *params) -{ - unsigned int i; - json_t *k; - - if (json_typeof(element) != JSON_ARRAY) - return -1; - - for (i = 0; i < json_array_size(element); i++) { - k = json_array_get(element, i); - if (json_typeof(k) != JSON_STRING) - return -1; - - params->ips_array[params->ips_array_len++] = - json_string_value(k); - - params->flags |= OG_REST_PARAM_ADDR; - } - - return 0; -} - -static int og_json_parse_string(json_t *element, const char **str) -{ - if (json_typeof(element) != JSON_STRING) - return -1; - - *str = json_string_value(element); - return 0; -} - -static int og_json_parse_bool(json_t *element, bool *value) -{ - if (json_typeof(element) == JSON_TRUE) - *value = true; - else if (json_typeof(element) == JSON_FALSE) - *value = false; - else - return -1; - - return 0; -} - -static int og_json_parse_sync_params(json_t *element, - struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "sync")) { - err = og_json_parse_string(value, ¶ms->sync_setup.sync); - params->flags |= OG_REST_PARAM_SYNC_SYNC; - } else if (!strcmp(key, "diff")) { - err = og_json_parse_string(value, ¶ms->sync_setup.diff); - params->flags |= OG_REST_PARAM_SYNC_DIFF; - } else if (!strcmp(key, "remove")) { - err = og_json_parse_string(value, ¶ms->sync_setup.remove); - params->flags |= OG_REST_PARAM_SYNC_REMOVE; - } else if (!strcmp(key, "compress")) { - err = og_json_parse_string(value, ¶ms->sync_setup.compress); - params->flags |= OG_REST_PARAM_SYNC_COMPRESS; - } else if (!strcmp(key, "cleanup")) { - err = og_json_parse_string(value, ¶ms->sync_setup.cleanup); - params->flags |= OG_REST_PARAM_SYNC_CLEANUP; - } else if (!strcmp(key, "cache")) { - err = og_json_parse_string(value, ¶ms->sync_setup.cache); - params->flags |= OG_REST_PARAM_SYNC_CACHE; - } else if (!strcmp(key, "cleanup_cache")) { - err = og_json_parse_string(value, ¶ms->sync_setup.cleanup_cache); - params->flags |= OG_REST_PARAM_SYNC_CLEANUP_CACHE; - } else if (!strcmp(key, "remove_dst")) { - err = og_json_parse_string(value, ¶ms->sync_setup.remove_dst); - params->flags |= OG_REST_PARAM_SYNC_REMOVE_DST; - } else if (!strcmp(key, "diff_id")) { - err = og_json_parse_string(value, ¶ms->sync_setup.diff_id); - params->flags |= OG_REST_PARAM_SYNC_DIFF_ID; - } else if (!strcmp(key, "diff_name")) { - err = og_json_parse_string(value, ¶ms->sync_setup.diff_name); - params->flags |= OG_REST_PARAM_SYNC_DIFF_NAME; - } else if (!strcmp(key, "path")) { - err = og_json_parse_string(value, ¶ms->sync_setup.path); - params->flags |= OG_REST_PARAM_SYNC_PATH; - } else if (!strcmp(key, "method")) { - err = og_json_parse_string(value, ¶ms->sync_setup.method); - params->flags |= OG_REST_PARAM_SYNC_METHOD; - } - - if (err != 0) - return err; - } - return err; -} - -#define OG_PARAM_PART_NUMBER (1UL << 0) -#define OG_PARAM_PART_CODE (1UL << 1) -#define OG_PARAM_PART_FILESYSTEM (1UL << 2) -#define OG_PARAM_PART_SIZE (1UL << 3) -#define OG_PARAM_PART_FORMAT (1UL << 4) - -static int og_json_parse_partition(json_t *element, - struct og_msg_params *params, - unsigned int i) -{ - struct og_partition *part = ¶ms->partition_setup[i]; - uint64_t flags = 0UL; - const char *key; - json_t *value; - int err = 0; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, &part->number); - flags |= OG_PARAM_PART_NUMBER; - } else if (!strcmp(key, "code")) { - err = og_json_parse_string(value, &part->code); - flags |= OG_PARAM_PART_CODE; - } else if (!strcmp(key, "filesystem")) { - err = og_json_parse_string(value, &part->filesystem); - flags |= OG_PARAM_PART_FILESYSTEM; - } else if (!strcmp(key, "size")) { - err = og_json_parse_string(value, &part->size); - flags |= OG_PARAM_PART_SIZE; - } else if (!strcmp(key, "format")) { - err = og_json_parse_string(value, &part->format); - flags |= OG_PARAM_PART_FORMAT; - } - - if (err < 0) - return err; - } - - if (flags != (OG_PARAM_PART_NUMBER | - OG_PARAM_PART_CODE | - OG_PARAM_PART_FILESYSTEM | - OG_PARAM_PART_SIZE | - OG_PARAM_PART_FORMAT)) - return -1; - - params->flags |= (OG_REST_PARAM_PART_0 << i); - - return err; -} - -static int og_json_parse_partition_setup(json_t *element, - struct og_msg_params *params) -{ - unsigned int i; - json_t *k; - - if (json_typeof(element) != JSON_ARRAY) - return -1; - - for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) { - k = json_array_get(element, i); - - if (json_typeof(k) != JSON_OBJECT) - return -1; - - if (og_json_parse_partition(k, params, i) != 0) - return -1; - } - return 0; -} - -static int og_cmd_legacy_send(struct og_msg_params *params, const char *cmd, - const char *state) -{ - char buf[4096] = {}; - int len, err = 0; - TRAMA *msg; - - len = snprintf(buf, sizeof(buf), "nfn=%s\r", cmd); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, - state, msg)) - err = -1; - - og_msg_free(msg); - - return err; -} - -static int og_cmd_post_clients(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "Sondeo", CLIENTE_APAGADO); -} - -struct og_buffer { - char *data; - int len; -}; - -static int og_json_dump_clients(const char *buffer, size_t size, void *data) -{ - struct og_buffer *og_buffer = (struct og_buffer *)data; - - memcpy(og_buffer->data + og_buffer->len, buffer, size); - og_buffer->len += size; - - return 0; -} - -static int og_cmd_get_clients(json_t *element, struct og_msg_params *params, - char *buffer_reply) -{ - json_t *root, *array, *addr, *state, *object; - struct og_buffer og_buffer = { - .data = buffer_reply, - }; - int i; - - array = json_array(); - if (!array) - return -1; - - for (i = 0; i < MAXIMOS_CLIENTES; i++) { - if (tbsockets[i].ip[0] == '\0') - continue; - - object = json_object(); - if (!object) { - json_decref(array); - return -1; - } - addr = json_string(tbsockets[i].ip); - if (!addr) { - json_decref(object); - json_decref(array); - return -1; - } - json_object_set_new(object, "addr", addr); - - state = json_string(tbsockets[i].estado); - if (!state) { - json_decref(object); - json_decref(array); - return -1; - } - json_object_set_new(object, "state", state); - - json_array_append_new(array, object); - } - root = json_pack("{s:o}", "clients", array); - if (!root) { - json_decref(array); - return -1; - } - - json_dump_callback(root, og_json_dump_clients, &og_buffer, 0); - json_decref(root); - - return 0; -} - -static int og_json_parse_target(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - - if (json_typeof(element) != JSON_OBJECT) { - return -1; - } - - json_object_foreach(element, key, value) { - if (!strcmp(key, "addr")) { - if (json_typeof(value) != JSON_STRING) - return -1; - - params->ips_array[params->ips_array_len] = - json_string_value(value); - - params->flags |= OG_REST_PARAM_ADDR; - } else if (!strcmp(key, "mac")) { - if (json_typeof(value) != JSON_STRING) - return -1; - - params->mac_array[params->ips_array_len] = - json_string_value(value); - - params->flags |= OG_REST_PARAM_MAC; - } - } - - return 0; -} - -static int og_json_parse_targets(json_t *element, struct og_msg_params *params) -{ - unsigned int i; - json_t *k; - int err; - - if (json_typeof(element) != JSON_ARRAY) - return -1; - - for (i = 0; i < json_array_size(element); i++) { - k = json_array_get(element, i); - - if (json_typeof(k) != JSON_OBJECT) - return -1; - - err = og_json_parse_target(k, params); - if (err < 0) - return err; - - params->ips_array_len++; - } - return 0; -} - -static int og_json_parse_type(json_t *element, struct og_msg_params *params) -{ - const char *type; - - if (json_typeof(element) != JSON_STRING) - return -1; - - params->wol_type = json_string_value(element); - - type = json_string_value(element); - if (!strcmp(type, "unicast")) - params->wol_type = "2"; - else if (!strcmp(type, "broadcast")) - params->wol_type = "1"; - - params->flags |= OG_REST_PARAM_WOL_TYPE; - - return 0; -} - -static int og_cmd_wol(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_targets(value, params); - } else if (!strcmp(key, "type")) { - err = og_json_parse_type(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_MAC | - OG_REST_PARAM_WOL_TYPE)) - return -1; - - if (!Levanta((char **)params->ips_array, (char **)params->mac_array, - params->ips_array_len, (char *)params->wol_type)) - return -1; - - return 0; -} - -static int og_json_parse_run(json_t *element, struct og_msg_params *params) -{ - if (json_typeof(element) != JSON_STRING) - return -1; - - snprintf(params->run_cmd, sizeof(params->run_cmd), "%s", - json_string_value(element)); - - params->flags |= OG_REST_PARAM_RUN_CMD; - - return 0; -} - -static int og_cmd_run_post(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}, iph[4096] = {}; - int err = 0, len; - const char *key; - unsigned int i; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - else if (!strcmp(key, "run")) - err = og_json_parse_run(value, params); - else if (!strcmp(key, "echo")) { - err = og_json_parse_bool(value, ¶ms->echo); - params->flags |= OG_REST_PARAM_ECHO; - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_RUN_CMD | - OG_REST_PARAM_ECHO)) - return -1; - - for (i = 0; i < params->ips_array_len; i++) { - len = snprintf(iph + strlen(iph), sizeof(iph), "%s;", - params->ips_array[i]); - } - - if (params->echo) { - len = snprintf(buf, sizeof(buf), - "nfn=ConsolaRemota\riph=%s\rscp=%s\r", - iph, params->run_cmd); - } else { - len = snprintf(buf, sizeof(buf), - "nfn=EjecutarScript\riph=%s\rscp=%s\r", - iph, params->run_cmd); - } - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg)) - err = -1; - - og_msg_free(msg); - - if (err < 0) - return err; - - for (i = 0; i < params->ips_array_len; i++) { - char filename[4096]; - FILE *f; - - sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]); - f = fopen(filename, "wt"); - fclose(f); - } - - return 0; -} - -static int og_cmd_run_get(json_t *element, struct og_msg_params *params, - char *buffer_reply) -{ - struct og_buffer og_buffer = { - .data = buffer_reply, - }; - json_t *root, *value, *array; - const char *key; - unsigned int i; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - return err; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - array = json_array(); - if (!array) - return -1; - - for (i = 0; i < params->ips_array_len; i++) { - json_t *object, *output, *addr; - char data[4096] = {}; - char filename[4096]; - int fd, numbytes; - - sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]); - - fd = open(filename, O_RDONLY); - if (!fd) - return -1; - - numbytes = read(fd, data, sizeof(data)); - if (numbytes < 0) { - close(fd); - return -1; - } - data[sizeof(data) - 1] = '\0'; - close(fd); - - object = json_object(); - if (!object) { - json_decref(array); - return -1; - } - addr = json_string(params->ips_array[i]); - if (!addr) { - json_decref(object); - json_decref(array); - return -1; - } - json_object_set_new(object, "addr", addr); - - output = json_string(data); - if (!output) { - json_decref(object); - json_decref(array); - return -1; - } - json_object_set_new(object, "output", output); - - json_array_append_new(array, object); - } - - root = json_pack("{s:o}", "clients", array); - if (!root) - return -1; - - json_dump_callback(root, og_json_dump_clients, &og_buffer, 0); - json_decref(root); - - return 0; -} - -static int og_cmd_session(json_t *element, struct og_msg_params *params) -{ - char buf[4096], iph[4096]; - int err = 0, len; - const char *key; - unsigned int i; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } - - if (err < 0) - return err; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION)) - return -1; - - for (i = 0; i < params->ips_array_len; i++) { - snprintf(iph + strlen(iph), sizeof(iph), "%s;", - params->ips_array[i]); - } - len = snprintf(buf, sizeof(buf), - "nfn=IniciarSesion\riph=%s\rdsk=%s\rpar=%s\r", - iph, params->disk, params->partition); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - if (!og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_APAGADO, msg)) - err = -1; - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_poweroff(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "Apagar", CLIENTE_OCUPADO); -} - -static int og_cmd_refresh(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "Actualizar", CLIENTE_APAGADO); -} - -static int og_cmd_reboot(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "Reiniciar", CLIENTE_OCUPADO); -} - -static int og_cmd_stop(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "Purgar", CLIENTE_APAGADO); -} - -static int og_cmd_hardware(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - return og_cmd_legacy_send(params, "InventarioHardware", - CLIENTE_OCUPADO); -} - -static int og_cmd_software(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } - else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=InventarioSoftware\rdsk=%s\rpar=%s\r", - params->disk, params->partition); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_create_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } else if (!strcmp(key, "code")) { - err = og_json_parse_string(value, ¶ms->code); - params->flags |= OG_REST_PARAM_CODE; - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_CODE | - OG_REST_PARAM_ID | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r", - params->disk, params->partition, params->code, - params->id, params->name, params->repository); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_restore_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "type")) { - err = og_json_parse_string(value, ¶ms->type); - params->flags |= OG_REST_PARAM_TYPE; - } else if (!strcmp(key, "profile")) { - err = og_json_parse_string(value, ¶ms->profile); - params->flags |= OG_REST_PARAM_PROFILE; - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO | - OG_REST_PARAM_TYPE | - OG_REST_PARAM_PROFILE | - OG_REST_PARAM_ID)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=RestaurarImagen\ridi=%s\rdsk=%s\rpar=%s\rifs=%s\r" - "nci=%s\ripr=%s\rptc=%s\r", - params->id, params->disk, params->partition, - params->profile, params->name, - params->repository, params->type); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_setup(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "cache")) { - err = og_json_parse_string(value, ¶ms->cache); - params->flags |= OG_REST_PARAM_CACHE; - } else if (!strcmp(key, "cache_size")) { - err = og_json_parse_string(value, ¶ms->cache_size); - params->flags |= OG_REST_PARAM_CACHE_SIZE; - } else if (!strcmp(key, "partition_setup")) { - err = og_json_parse_partition_setup(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_CACHE | - OG_REST_PARAM_CACHE_SIZE | - OG_REST_PARAM_PART_0 | - OG_REST_PARAM_PART_1 | - OG_REST_PARAM_PART_2 | - OG_REST_PARAM_PART_3)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=Configurar\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!", - params->disk, params->disk, params->cache, params->cache_size); - - for (unsigned int i = 0; i < OG_PARTITION_MAX; ++i) { - const struct og_partition *part = ¶ms->partition_setup[i]; - - len += snprintf(buf + strlen(buf), sizeof(buf), - "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%", - part->number, part->code, part->filesystem, part->size, part->format); - } - - msg = og_msg_alloc(buf, len + 1); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params) -{ - const char *key; - json_t *value; - int err = 0; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) - return -1; - - og_cmd_legacy_send(params, "EjecutaComandosPendientes", CLIENTE_OCUPADO); - - return 0; -} - -static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "code")) { - err = og_json_parse_string(value, ¶ms->code); - params->flags |= OG_REST_PARAM_CODE; - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "sync_params")) { - err = og_json_parse_sync_params(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_CODE | - OG_REST_PARAM_ID | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO | - OG_REST_PARAM_SYNC_SYNC | - OG_REST_PARAM_SYNC_DIFF | - OG_REST_PARAM_SYNC_REMOVE | - OG_REST_PARAM_SYNC_COMPRESS | - OG_REST_PARAM_SYNC_CLEANUP | - OG_REST_PARAM_SYNC_CACHE | - OG_REST_PARAM_SYNC_CLEANUP_CACHE | - OG_REST_PARAM_SYNC_REMOVE_DST)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r" - "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r" - "cpc=%s\rbpc=%s\rnba=%s\r", - params->disk, params->partition, params->code, params->id, - params->name, params->repository, params->sync_setup.sync, - params->sync_setup.diff, params->sync_setup.remove, - params->sync_setup.compress, params->sync_setup.cleanup, - params->sync_setup.cache, params->sync_setup.cleanup_cache, - params->sync_setup.remove_dst); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_create_incremental_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) - err = og_json_parse_clients(value, params); - else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "sync_params")) { - err = og_json_parse_sync_params(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_ID | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO | - OG_REST_PARAM_SYNC_SYNC | - OG_REST_PARAM_SYNC_PATH | - OG_REST_PARAM_SYNC_DIFF | - OG_REST_PARAM_SYNC_DIFF_ID | - OG_REST_PARAM_SYNC_DIFF_NAME | - OG_REST_PARAM_SYNC_REMOVE | - OG_REST_PARAM_SYNC_COMPRESS | - OG_REST_PARAM_SYNC_CLEANUP | - OG_REST_PARAM_SYNC_CACHE | - OG_REST_PARAM_SYNC_CLEANUP_CACHE | - OG_REST_PARAM_SYNC_REMOVE_DST)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=CrearSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" - "rti=%s\ripr=%s\ridf=%s\rncf=%s\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\r" - "bpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r", - params->disk, params->partition, params->id, params->name, - params->sync_setup.path, params->repository, params->sync_setup.diff_id, - params->sync_setup.diff_name, params->sync_setup.sync, - params->sync_setup.diff, params->sync_setup.remove_dst, - params->sync_setup.compress, params->sync_setup.cleanup, - params->sync_setup.cache, params->sync_setup.cleanup_cache, - params->sync_setup.remove_dst); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "profile")) { - err = og_json_parse_string(value, ¶ms->profile); - params->flags |= OG_REST_PARAM_PROFILE; - } else if (!strcmp(key, "type")) { - err = og_json_parse_string(value, ¶ms->type); - params->flags |= OG_REST_PARAM_TYPE; - } else if (!strcmp(key, "sync_params")) { - err = og_json_parse_sync_params(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_ID | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO | - OG_REST_PARAM_PROFILE | - OG_REST_PARAM_TYPE | - OG_REST_PARAM_SYNC_PATH | - OG_REST_PARAM_SYNC_METHOD | - OG_REST_PARAM_SYNC_SYNC | - OG_REST_PARAM_SYNC_DIFF | - OG_REST_PARAM_SYNC_REMOVE | - OG_REST_PARAM_SYNC_COMPRESS | - OG_REST_PARAM_SYNC_CLEANUP | - OG_REST_PARAM_SYNC_CACHE | - OG_REST_PARAM_SYNC_CLEANUP_CACHE | - OG_REST_PARAM_SYNC_REMOVE_DST)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" - "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r" - "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r", - params->disk, params->partition, params->id, params->name, - params->repository, params->profile, params->sync_setup.path, - params->sync_setup.method, params->sync_setup.sync, params->type, - params->sync_setup.diff, params->sync_setup.remove, - params->sync_setup.compress, params->sync_setup.cleanup, - params->sync_setup.cache, params->sync_setup.cleanup_cache, - params->sync_setup.remove_dst); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_cmd_restore_incremental_image(json_t *element, struct og_msg_params *params) -{ - char buf[4096] = {}; - int err = 0, len; - const char *key; - json_t *value; - TRAMA *msg; - - if (json_typeof(element) != JSON_OBJECT) - return -1; - - json_object_foreach(element, key, value) { - if (!strcmp(key, "clients")) { - err = og_json_parse_clients(value, params); - } else if (!strcmp(key, "disk")) { - err = og_json_parse_string(value, ¶ms->disk); - params->flags |= OG_REST_PARAM_DISK; - } else if (!strcmp(key, "partition")) { - err = og_json_parse_string(value, ¶ms->partition); - params->flags |= OG_REST_PARAM_PARTITION; - } else if (!strcmp(key, "id")) { - err = og_json_parse_string(value, ¶ms->id); - params->flags |= OG_REST_PARAM_ID; - } else if (!strcmp(key, "name")) { - err = og_json_parse_string(value, ¶ms->name); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "repository")) { - err = og_json_parse_string(value, ¶ms->repository); - params->flags |= OG_REST_PARAM_REPO; - } else if (!strcmp(key, "profile")) { - err = og_json_parse_string(value, ¶ms->profile); - params->flags |= OG_REST_PARAM_PROFILE; - } else if (!strcmp(key, "type")) { - err = og_json_parse_string(value, ¶ms->type); - params->flags |= OG_REST_PARAM_TYPE; - } else if (!strcmp(key, "sync_params")) { - err = og_json_parse_sync_params(value, params); - } - - if (err < 0) - break; - } - - if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | - OG_REST_PARAM_DISK | - OG_REST_PARAM_PARTITION | - OG_REST_PARAM_ID | - OG_REST_PARAM_NAME | - OG_REST_PARAM_REPO | - OG_REST_PARAM_PROFILE | - OG_REST_PARAM_TYPE | - OG_REST_PARAM_SYNC_DIFF_ID | - OG_REST_PARAM_SYNC_DIFF_NAME | - OG_REST_PARAM_SYNC_PATH | - OG_REST_PARAM_SYNC_METHOD | - OG_REST_PARAM_SYNC_SYNC | - OG_REST_PARAM_SYNC_DIFF | - OG_REST_PARAM_SYNC_REMOVE | - OG_REST_PARAM_SYNC_COMPRESS | - OG_REST_PARAM_SYNC_CLEANUP | - OG_REST_PARAM_SYNC_CACHE | - OG_REST_PARAM_SYNC_CLEANUP_CACHE | - OG_REST_PARAM_SYNC_REMOVE_DST)) - return -1; - - len = snprintf(buf, sizeof(buf), - "nfn=RestaurarSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r" - "ipr=%s\rifs=%s\ridf=%s\rncf=%s\rrti=%s\rmet=%s\rmsy=%s\r" - "tpt=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\r" - "nba=%s\r", - params->disk, params->partition, params->id, params->name, - params->repository, params->profile, params->sync_setup.diff_id, - params->sync_setup.diff_name, params->sync_setup.path, - params->sync_setup.method, params->sync_setup.sync, params->type, - params->sync_setup.diff, params->sync_setup.remove, - params->sync_setup.compress, params->sync_setup.cleanup, - params->sync_setup.cache, params->sync_setup.cleanup_cache, - params->sync_setup.remove_dst); - - msg = og_msg_alloc(buf, len); - if (!msg) - return -1; - - og_send_cmd((char **)params->ips_array, params->ips_array_len, - CLIENTE_OCUPADO, msg); - - og_msg_free(msg); - - return 0; -} - -static int og_client_method_not_found(struct og_client *cli) -{ - /* To meet RFC 7231, this function MUST generate an Allow header field - * containing the correct methods. For example: "Allow: POST\r\n" - */ - char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n" - "Content-Length: 0\r\n\r\n"; - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return -1; -} - -static int og_client_bad_request(struct og_client *cli) -{ - char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n"; - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return -1; -} - -static int og_client_not_found(struct og_client *cli) -{ - char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return -1; -} - -static int og_client_not_authorized(struct og_client *cli) -{ - char buf[] = "HTTP/1.1 401 Unauthorized\r\n" - "WWW-Authenticate: Basic\r\n" - "Content-Length: 0\r\n\r\n"; - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return -1; -} - -static int og_server_internal_error(struct og_client *cli) -{ - char buf[] = "HTTP/1.1 500 Internal Server Error\r\n" - "Content-Length: 0\r\n\r\n"; - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return -1; -} - -#define OG_MSG_RESPONSE_MAXLEN 65536 - -static int og_client_ok(struct og_client *cli, char *buf_reply) -{ - char buf[OG_MSG_RESPONSE_MAXLEN] = {}; - int err = 0, len; - - len = snprintf(buf, sizeof(buf), - "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s", - strlen(buf_reply), buf_reply); - if (len >= (int)sizeof(buf)) - err = og_server_internal_error(cli); - - send(og_client_socket(cli), buf, strlen(buf), 0); - - return err; -} - -enum og_rest_method { - OG_METHOD_GET = 0, - OG_METHOD_POST, -}; - -static int og_client_state_process_payload_rest(struct og_client *cli) -{ - char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {}; - struct og_msg_params params = {}; - enum og_rest_method method; - const char *cmd, *body; - json_error_t json_err; - json_t *root = NULL; - int err = 0; - - syslog(LOG_DEBUG, "%s:%hu %.32s ...\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port), cli->buf); - - if (!strncmp(cli->buf, "GET", strlen("GET"))) { - method = OG_METHOD_GET; - cmd = cli->buf + strlen("GET") + 2; - } else if (!strncmp(cli->buf, "POST", strlen("POST"))) { - method = OG_METHOD_POST; - cmd = cli->buf + strlen("POST") + 2; - } else - return og_client_method_not_found(cli); - - body = strstr(cli->buf, "\r\n\r\n") + 4; - - if (strcmp(cli->auth_token, auth_token)) { - syslog(LOG_ERR, "wrong Authentication key\n"); - return og_client_not_authorized(cli); - } - - if (cli->content_length) { - root = json_loads(body, 0, &json_err); - if (!root) { - syslog(LOG_ERR, "malformed json line %d: %s\n", - json_err.line, json_err.text); - return og_client_not_found(cli); - } - } - - if (!strncmp(cmd, "clients", strlen("clients"))) { - if (method != OG_METHOD_POST && - method != OG_METHOD_GET) - return og_client_method_not_found(cli); - - if (method == OG_METHOD_POST && !root) { - syslog(LOG_ERR, "command clients with no payload\n"); - return og_client_bad_request(cli); - } - switch (method) { - case OG_METHOD_POST: - err = og_cmd_post_clients(root, ¶ms); - break; - case OG_METHOD_GET: - err = og_cmd_get_clients(root, ¶ms, buf_reply); - break; - } - } else if (!strncmp(cmd, "wol", strlen("wol"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command wol with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_wol(root, ¶ms); - } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command run with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_run_post(root, ¶ms); - } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command output with no payload\n"); - return og_client_bad_request(cli); - } - - err = og_cmd_run_get(root, ¶ms, buf_reply); - } else if (!strncmp(cmd, "session", strlen("session"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command session with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_session(root, ¶ms); - } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command poweroff with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_poweroff(root, ¶ms); - } else if (!strncmp(cmd, "reboot", strlen("reboot"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command reboot with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_reboot(root, ¶ms); - } else if (!strncmp(cmd, "stop", strlen("stop"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command stop with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_stop(root, ¶ms); - } else if (!strncmp(cmd, "refresh", strlen("refresh"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command refresh with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_refresh(root, ¶ms); - } else if (!strncmp(cmd, "hardware", strlen("hardware"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command hardware with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_hardware(root, ¶ms); - } else if (!strncmp(cmd, "software", strlen("software"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command software with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_software(root, ¶ms); - } else if (!strncmp(cmd, "image/create/basic", - strlen("image/create/basic"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_create_basic_image(root, ¶ms); - } else if (!strncmp(cmd, "image/create/incremental", - strlen("image/create/incremental"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_create_incremental_image(root, ¶ms); - } else if (!strncmp(cmd, "image/create", strlen("image/create"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_create_image(root, ¶ms); - } else if (!strncmp(cmd, "image/restore/basic", - strlen("image/restore/basic"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_restore_basic_image(root, ¶ms); - } else if (!strncmp(cmd, "image/restore/incremental", - strlen("image/restore/incremental"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_restore_incremental_image(root, ¶ms); - } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_restore_image(root, ¶ms); - } else if (!strncmp(cmd, "setup", strlen("setup"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - err = og_cmd_setup(root, ¶ms); - } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) { - if (method != OG_METHOD_POST) - return og_client_method_not_found(cli); - - if (!root) { - syslog(LOG_ERR, "command create with no payload\n"); - return og_client_bad_request(cli); - } - - err = og_cmd_run_schedule(root, ¶ms); - } else { - syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd); - err = og_client_not_found(cli); - } - - if (root) - json_decref(root); - - if (err < 0) - return og_client_bad_request(cli); - - err = og_client_ok(cli, buf_reply); - if (err < 0) { - syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - } - - return err; -} - -static int og_client_state_recv_hdr_rest(struct og_client *cli) -{ - char *ptr; - - ptr = strstr(cli->buf, "\r\n\r\n"); - if (!ptr) - return 0; - - cli->msg_len = ptr - cli->buf + 4; - - ptr = strstr(cli->buf, "Content-Length: "); - if (ptr) { - sscanf(ptr, "Content-Length: %i[^\r\n]", &cli->content_length); - if (cli->content_length < 0) - return -1; - cli->msg_len += cli->content_length; - } - - ptr = strstr(cli->buf, "Authorization: "); - if (ptr) - sscanf(ptr, "Authorization: %63[^\r\n]", cli->auth_token); - - return 1; -} - -static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events) -{ - struct og_client *cli; - int ret; - - cli = container_of(io, struct og_client, io); - - if (events & EV_ERROR) { - syslog(LOG_ERR, "unexpected error event from client %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - goto close; - } - - ret = recv(io->fd, cli->buf + cli->buf_len, - sizeof(cli->buf) - cli->buf_len, 0); - if (ret <= 0) { - if (ret < 0) { - syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port), - strerror(errno)); - } else { - syslog(LOG_DEBUG, "closed connection by %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); - } - goto close; - } - - if (cli->keepalive_idx >= 0) - return; - - ev_timer_again(loop, &cli->timer); - - cli->buf_len += ret; - if (cli->buf_len >= sizeof(cli->buf)) { - syslog(LOG_ERR, "client request from %s:%hu is too long\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); - goto close; - } - - switch (cli->state) { - case OG_CLIENT_RECEIVING_HEADER: - if (cli->rest) - ret = og_client_state_recv_hdr_rest(cli); - else - ret = og_client_state_recv_hdr(cli); - - if (ret < 0) - goto close; - if (!ret) - return; - - cli->state = OG_CLIENT_RECEIVING_PAYLOAD; - /* Fall through. */ - case OG_CLIENT_RECEIVING_PAYLOAD: - /* Still not enough data to process request. */ - if (cli->buf_len < cli->msg_len) - return; - - cli->state = OG_CLIENT_PROCESSING_REQUEST; - /* fall through. */ - case OG_CLIENT_PROCESSING_REQUEST: - if (cli->rest) { - ret = og_client_state_process_payload_rest(cli); - if (ret < 0) { - syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - } - } else { - ret = og_client_state_process_payload(cli); - } - if (ret < 0) - goto close; - - if (cli->keepalive_idx < 0) { - syslog(LOG_DEBUG, "server closing connection to %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); - goto close; - } else { - syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); - og_client_keepalive(loop, cli); - og_client_reset_state(cli); - } - break; - default: - syslog(LOG_ERR, "unknown state, critical internal error\n"); - goto close; - } - return; -close: - ev_timer_stop(loop, &cli->timer); - og_client_release(loop, cli); -} - -static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events) -{ - struct og_client *cli; - - cli = container_of(timer, struct og_client, timer); - if (cli->keepalive_idx >= 0) { - ev_timer_again(loop, &cli->timer); - return; - } - syslog(LOG_ERR, "timeout request for client %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); - - og_client_release(loop, cli); -} - -static int socket_s, socket_rest; - -static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io, - int events) -{ - struct sockaddr_in client_addr; - socklen_t addrlen = sizeof(client_addr); - struct og_client *cli; - int client_sd; - - if (events & EV_ERROR) - return; - - client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen); - if (client_sd < 0) { - syslog(LOG_ERR, "cannot accept client connection\n"); - return; - } - - cli = (struct og_client *)calloc(1, sizeof(struct og_client)); - if (!cli) { - close(client_sd); - return; - } - memcpy(&cli->addr, &client_addr, sizeof(client_addr)); - cli->keepalive_idx = -1; - - if (io->fd == socket_rest) - cli->rest = true; - - syslog(LOG_DEBUG, "connection from client %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); - - ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ); - ev_io_start(loop, &cli->io); - ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.); - ev_timer_start(loop, &cli->timer); -} - -static int og_socket_server_init(const char *port) -{ - struct sockaddr_in local; - int sd, on = 1; - - sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sd < 0) { - syslog(LOG_ERR, "cannot create main socket\n"); - return -1; - } - setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)); - - local.sin_addr.s_addr = htonl(INADDR_ANY); - local.sin_family = AF_INET; - local.sin_port = htons(atoi(port)); - - if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) { - close(sd); - syslog(LOG_ERR, "cannot bind socket\n"); - return -1; - } - - listen(sd, 250); - - return sd; -} - -int main(int argc, char *argv[]) -{ - struct ev_io ev_io_server, ev_io_server_rest; - struct ev_loop *loop = ev_default_loop(0); - int i; - - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - exit(EXIT_FAILURE); - - openlog("ogAdmServer", LOG_PID, LOG_DAEMON); - - /*-------------------------------------------------------------------------------------------------------- - Validación de parámetros de ejecución y lectura del fichero de configuración del servicio - ---------------------------------------------------------------------------------------------------------*/ - if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución - exit(EXIT_FAILURE); - - if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion - exit(EXIT_FAILURE); - } - - /*-------------------------------------------------------------------------------------------------------- - // Inicializa array de información de los clientes - ---------------------------------------------------------------------------------------------------------*/ - for (i = 0; i < MAXIMOS_CLIENTES; i++) { - tbsockets[i].ip[0] = '\0'; - tbsockets[i].cli = NULL; - } - /*-------------------------------------------------------------------------------------------------------- - Creación y configuración del socket del servicio - ---------------------------------------------------------------------------------------------------------*/ - socket_s = og_socket_server_init(puerto); - if (socket_s < 0) - exit(EXIT_FAILURE); - - ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ); - ev_io_start(loop, &ev_io_server); - - socket_rest = og_socket_server_init("8888"); - if (socket_rest < 0) - exit(EXIT_FAILURE); - - ev_io_init(&ev_io_server_rest, og_server_accept_cb, socket_rest, EV_READ); - ev_io_start(loop, &ev_io_server_rest); - - infoLog(1); // Inicio de sesión - - /* old log file has been deprecated. */ - og_log(97, false); - - syslog(LOG_INFO, "Waiting for connections\n"); - - while (1) - ev_loop(loop, 0); - - exit(EXIT_SUCCESS); -} -- cgit v1.2.3-18-g5258