source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.c @ 83167ac

configure-oglivelgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacion
Last change on this file since 83167ac was 847eb13, checked in by Irina Gómez <irinagomez@…>, 3 years ago

#1066 #990 When ogAdmServer sends WOL packets it includes the netmask of the client to be able to boot the computer on another subnet.

  • Property mode set to 100644
File size: 147.6 KB
RevLine 
[f679cf0]1// *******************************************************************************************************
[3ec149c]2// Servicio: ogAdmServer
3// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
4// Fecha Creación: Marzo-2010
5// Fecha Última modificación: Marzo-2010
6// Nombre del fichero: ogAdmServer.cpp
7// Descripción :Este fichero implementa el servicio de administración general del sistema
[f679cf0]8// *******************************************************************************************************
[3ec149c]9#include "ogAdmServer.h"
10#include "ogAdmLib.c"
[43070d2]11#include "dbi.h"
[9baecf8]12#include <ev.h>
[13e48b4]13#include <syslog.h>
[332487d]14#include <sys/ioctl.h>
15#include <ifaddrs.h>
[165cea3]16#include <sys/types.h>
17#include <sys/stat.h>
18#include <fcntl.h>
[1a08c06]19#include <jansson.h>
[7cd0b13]20
21static char usuario[LONPRM]; // Usuario de acceso a la base de datos
22static char pasguor[LONPRM]; // Password del usuario
23static char datasource[LONPRM]; // Dirección IP del gestor de base de datos
24static char catalog[LONPRM]; // Nombre de la base de datos
[332487d]25static char interface[LONPRM]; // Interface name
[2ccec278]26static char auth_token[LONPRM]; // API token
[7cd0b13]27
[43070d2]28static struct og_dbi_config dbi_config = {
29        .user           = usuario,
30        .passwd         = pasguor,
31        .host           = datasource,
32        .database       = catalog,
33};
34
[3ec149c]35//________________________________________________________________________________________________________
36//      Función: tomaConfiguracion
37//
38//      Descripción:
39//              Lee el fichero de configuración del servicio
40//      Parámetros:
41//              filecfg : Ruta completa al fichero de configuración
42//      Devuelve:
[5759db40]43//              true: Si el proceso es correcto
44//              false: En caso de ocurrir algún error
[3ec149c]45//________________________________________________________________________________________________________
[d647d81]46static bool tomaConfiguracion(const char *filecfg)
47{
[353da2d]48        char buf[1024], *line;
49        char *key, *value;
50        FILE *fcfg;
[3ec149c]51
52        if (filecfg == NULL || strlen(filecfg) == 0) {
[8c04716]53                syslog(LOG_ERR, "No configuration file has been specified\n");
[5759db40]54                return false;
[3ec149c]55        }
56
57        fcfg = fopen(filecfg, "rt");
58        if (fcfg == NULL) {
[8c04716]59                syslog(LOG_ERR, "Cannot open configuration file `%s'\n",
60                       filecfg);
[5759db40]61                return false;
[3ec149c]62        }
63
[8aa0c08]64        servidoradm[0] = '\0'; //inicializar variables globales
[3ec149c]65
[353da2d]66        line = fgets(buf, sizeof(buf), fcfg);
67        while (line != NULL) {
68                const char *delim = "=";
69
70                line[strlen(line) - 1] = '\0';
71
72                key = strtok(line, delim);
73                value = strtok(NULL, delim);
74
75                if (!strcmp(StrToUpper(key), "SERVIDORADM"))
76                        snprintf(servidoradm, sizeof(servidoradm), "%s", value);
77                else if (!strcmp(StrToUpper(key), "PUERTO"))
78                        snprintf(puerto, sizeof(puerto), "%s", value);
79                else if (!strcmp(StrToUpper(key), "USUARIO"))
80                        snprintf(usuario, sizeof(usuario), "%s", value);
81                else if (!strcmp(StrToUpper(key), "PASSWORD"))
82                        snprintf(pasguor, sizeof(pasguor), "%s", value);
83                else if (!strcmp(StrToUpper(key), "DATASOURCE"))
84                        snprintf(datasource, sizeof(datasource), "%s", value);
85                else if (!strcmp(StrToUpper(key), "CATALOG"))
86                        snprintf(catalog, sizeof(catalog), "%s", value);
[332487d]87                else if (!strcmp(StrToUpper(key), "INTERFACE"))
88                        snprintf(interface, sizeof(interface), "%s", value);
[2ccec278]89                else if (!strcmp(StrToUpper(key), "APITOKEN"))
90                        snprintf(auth_token, sizeof(auth_token), "%s", value);
[353da2d]91
92                line = fgets(buf, sizeof(buf), fcfg);
[3ec149c]93        }
[353da2d]94
[bf17dde]95        fclose(fcfg);
96
[f613fb2]97        if (!servidoradm[0]) {
[8c04716]98                syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n");
[5759db40]99                return false;
[3ec149c]100        }
[f613fb2]101        if (!puerto[0]) {
[8c04716]102                syslog(LOG_ERR, "Missing PUERTO in configuration file\n");
[5759db40]103                return false;
[3ec149c]104        }
[f613fb2]105        if (!usuario[0]) {
[8c04716]106                syslog(LOG_ERR, "Missing USUARIO in configuration file\n");
[5759db40]107                return false;
[3ec149c]108        }
[f613fb2]109        if (!pasguor[0]) {
[8c04716]110                syslog(LOG_ERR, "Missing PASSWORD in configuration file\n");
[5759db40]111                return false;
[3ec149c]112        }
[f613fb2]113        if (!datasource[0]) {
[8c04716]114                syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n");
[5759db40]115                return false;
[3ec149c]116        }
[f613fb2]117        if (!catalog[0]) {
[8c04716]118                syslog(LOG_ERR, "Missing CATALOG in configuration file\n");
[5759db40]119                return false;
[3ec149c]120        }
[332487d]121        if (!interface[0])
122                syslog(LOG_ERR, "Missing INTERFACE in configuration file\n");
[0a73ecf7]123
[5759db40]124        return true;
[3ec149c]125}
[0a73ecf7]126
[9baecf8]127enum og_client_state {
128        OG_CLIENT_RECEIVING_HEADER      = 0,
129        OG_CLIENT_RECEIVING_PAYLOAD,
130        OG_CLIENT_PROCESSING_REQUEST,
131};
132
[1d9d93c]133#define OG_MSG_REQUEST_MAXLEN   16384
[d8a2d5f]134
[9baecf8]135/* Shut down connection if there is no complete message after 10 seconds. */
136#define OG_CLIENT_TIMEOUT       10
137
138struct og_client {
139        struct ev_io            io;
140        struct ev_timer         timer;
[13e48b4]141        struct sockaddr_in      addr;
[9baecf8]142        enum og_client_state    state;
[d8a2d5f]143        char                    buf[OG_MSG_REQUEST_MAXLEN];
[9baecf8]144        unsigned int            buf_len;
145        unsigned int            msg_len;
[2e0c063]146        int                     keepalive_idx;
[1a08c06]147        bool                    rest;
[8793b71]148        int                     content_length;
[2ccec278]149        char                    auth_token[64];
[9baecf8]150};
151
152static inline int og_client_socket(const struct og_client *cli)
153{
154        return cli->io.fd;
155}
156
[3ec149c]157// ________________________________________________________________________________________________________
158// Función: clienteDisponible
159//
160//      Descripción:
161//              Comprueba la disponibilidad del cliente para recibir comandos interactivos
162//      Parametros:
163//              - ip : La ip del cliente a buscar
164//              - idx: (Salida)  Indice que ocupa el cliente, de estar ya registrado
165//      Devuelve:
[5759db40]166//              true: Si el cliente está disponible
167//              false: En caso contrario
[3ec149c]168// ________________________________________________________________________________________________________
[d647d81]169bool clienteDisponible(char *ip, int* idx)
170{
[3ec149c]171        int estado;
172
173        if (clienteExistente(ip, idx)) {
174                estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado
175                if (estado == 0)
[5759db40]176                        return false;
[3ec149c]177
178                estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado
179                if (estado == 0)
[5759db40]180                        return false;
[3ec149c]181
182                estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión
183                if (estado == 0)
[5759db40]184                        return false;
[3ec149c]185
[5759db40]186                return true; // En caso contrario el cliente está disponible
[3ec149c]187        }
[5759db40]188        return false; // Cliente no está registrado en el sistema
[3ec149c]189}
190// ________________________________________________________________________________________________________
191// Función: clienteExistente
192//
193//      Descripción:
194//              Comprueba si el cliente está registrado en la tabla de socket del sistema
195//      Parametros:
196//              - ip : La ip del cliente a buscar
197//              - idx:(Salida)  Indice que ocupa el cliente, de estar ya registrado
198//      Devuelve:
[5759db40]199//              true: Si el cliente está registrado
200//              false: En caso contrario
[3ec149c]201// ________________________________________________________________________________________________________
[d647d81]202bool clienteExistente(char *ip, int* idx)
203{
[3ec149c]204        int i;
205        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
206                if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena
207                        *idx = i;
[5759db40]208                        return true;
[3ec149c]209                }
210        }
[5759db40]211        return false;
[3ec149c]212}
213// ________________________________________________________________________________________________________
214// Función: hayHueco
215//
216//      Descripción:
[5759db40]217//              Esta función devuelve true o false dependiendo de que haya hueco en la tabla de sockets para un nuevo cliente.
[3ec149c]218//      Parametros:
219//              - idx:   Primer indice libre que se podrn utilizar
220//      Devuelve:
[5759db40]221//              true: Si el proceso es correcto
222//              false: En caso de ocurrir algún error
[3ec149c]223// ________________________________________________________________________________________________________
[d647d81]224static bool hayHueco(int *idx)
225{
[3ec149c]226        int i;
227
228        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
229                if (strncmp(tbsockets[i].ip, "\0", 1) == 0) { // Hay un hueco
230                        *idx = i;
[5759db40]231                        return true;
[3ec149c]232                }
233        }
[5759db40]234        return false;
[3ec149c]235}
236// ________________________________________________________________________________________________________
[f679cf0]237// Función: InclusionClienteWin
238//
239//      Descripción:
240//              Esta función incorpora el socket de un nuevo cliente Windows o Linux a la tabla de clientes
241//      Parámetros:
242//              - socket_c: Socket del cliente que envió el mensaje
243//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
244//      Devuelve:
[5759db40]245//              true: Si el proceso es correcto
246//              false: En caso de ocurrir algún error
[f679cf0]247// ________________________________________________________________________________________________________
[9baecf8]248static bool InclusionClienteWinLnx(TRAMA *ptrTrama, struct og_client *cli)
[d647d81]249{
[9baecf8]250        int socket_c = og_client_socket(cli);
[f679cf0]251        int res,idordenador,lon;
252        char nombreordenador[LONFIL];
[9baecf8]253
254        res = procesoInclusionClienteWinLnx(socket_c, ptrTrama, &idordenador,
255                                            nombreordenador);
256
[f679cf0]257        // Prepara la trama de respuesta
258
259        initParametros(ptrTrama,0);
260        ptrTrama->tipo=MSG_RESPUESTA;
261        lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionClienteWinLnx\r");
262        lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador);
263        lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador);       
264        lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", res);   
[8c04716]265
[ba03878]266        if (!mandaTrama(&socket_c, ptrTrama)) {
[8c04716]267                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
268                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
269                       strerror(errno));
[5759db40]270                return false;
[f679cf0]271        }
[5759db40]272        return true;
[f679cf0]273}
274// ________________________________________________________________________________________________________
275// Función: procesoInclusionClienteWinLnx
276//
277//      Descripción:
278//              Implementa el proceso de inclusión en el sistema del Cliente Windows o Linux
279//      Parámetros de entrada:
280//              - socket_c: Socket del cliente que envió el mensaje
281//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
282//      Parámetros de salida:
283//              - ido: Identificador del ordenador
284//              - nombreordenador: Nombre del ordenador
285//      Devuelve:
286//              Código del error producido en caso de ocurrir algún error, 0 si el proceso es correcto
287// ________________________________________________________________________________________________________
[d647d81]288bool procesoInclusionClienteWinLnx(int socket_c, TRAMA *ptrTrama, int *idordenador, char *nombreordenador)
[f679cf0]289 {
[43070d2]290        struct og_dbi *dbi;
291        const char *msglog;
292        dbi_result result;
[f679cf0]293        char *iph;
[35cc972]294
[f679cf0]295        // Toma parámetros
296        iph = copiaParametro("iph",ptrTrama); // Toma ip
297
[43070d2]298        dbi = og_dbi_open(&dbi_config);
299        if (!dbi) {
300                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
301                       __func__, __LINE__);
302                goto err_dbi_open;
[f679cf0]303        }
304
[43070d2]305        result = dbi_conn_queryf(dbi->conn,
[f679cf0]306                        "SELECT idordenador,nombreordenador FROM ordenadores "
307                                " WHERE ordenadores.ip = '%s'", iph);
[43070d2]308        if (!result) {
309                dbi_conn_error(dbi->conn, &msglog);
[8c04716]310                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
311                       __func__, __LINE__, msglog);
[43070d2]312                goto err_query_fail;
[f679cf0]313        }
314
[43070d2]315        if (!dbi_result_next_row(result)) {
[8c04716]316                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
317                       __func__, __LINE__);
[43070d2]318                dbi_result_free(result);
319                goto err_query_fail;
[f679cf0]320        }
321
[8c04716]322        syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph);
323
[43070d2]324        *idordenador = dbi_result_get_uint(result, "idordenador");
325        nombreordenador = (char *)dbi_result_get_string(result, "nombreordenador");
326
327        dbi_result_free(result);
328        og_dbi_close(dbi);
[71f5b7d]329
[f679cf0]330        if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets
[0a73ecf7]331                liberaMemoria(iph);
[8c04716]332                syslog(LOG_ERR, "client table is full\n");
[71f5b7d]333                return false;
[f679cf0]334        }
[0a73ecf7]335        liberaMemoria(iph);
[71f5b7d]336        return true;
[43070d2]337
338err_query_fail:
339        og_dbi_close(dbi);
340err_dbi_open:
341        liberaMemoria(iph);
342        return false;
[f679cf0]343}
344// ________________________________________________________________________________________________________
[3ec149c]345// Función: InclusionCliente
346//
347//      Descripción:
348//              Esta función incorpora el socket de un nuevo cliente a la tabla de clientes y le devuelve alguna de sus propiedades:
349//              nombre, identificador, tamaño de la caché , etc ...
350//      Parámetros:
351//              - socket_c: Socket del cliente que envió el mensaje
352//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
353//      Devuelve:
[5759db40]354//              true: Si el proceso es correcto
355//              false: En caso de ocurrir algún error
[3ec149c]356// ________________________________________________________________________________________________________
[9baecf8]357static bool InclusionCliente(TRAMA *ptrTrama, struct og_client *cli)
[d647d81]358{
[9baecf8]359        int socket_c = og_client_socket(cli);
360
[8c04716]361        if (!procesoInclusionCliente(cli, ptrTrama)) {
[3ec149c]362                initParametros(ptrTrama,0);
363                strcpy(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\rres=0\r");
[ba03878]364                if (!mandaTrama(&socket_c, ptrTrama)) {
[8c04716]365                        syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
366                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
367                               strerror(errno));
[5759db40]368                        return false;
[3ec149c]369                }
370        }
[5759db40]371        return true;
[d647d81]372}
[3ec149c]373// ________________________________________________________________________________________________________
374// Función: procesoInclusionCliente
375//
376//      Descripción:
377//              Implementa el proceso de inclusión en el sistema del Cliente
378//      Parámetros:
379//              - socket_c: Socket del cliente que envió el mensaje
380//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
381//      Devuelve:
[5759db40]382//              true: Si el proceso es correcto
383//              false: En caso de ocurrir algún error
[3ec149c]384// ________________________________________________________________________________________________________
[8c04716]385bool procesoInclusionCliente(struct og_client *cli, TRAMA *ptrTrama)
[d647d81]386{
[8c04716]387        int socket_c = og_client_socket(cli);
[da48c98]388        const char *msglog, *str;
389        struct og_dbi *dbi;
390        dbi_result result;
[3ec149c]391
392        char *iph, *cfg;
393        char nombreordenador[LONFIL];
[da48c98]394        int lon, resul, idordenador, cache, idproautoexec, idaula, idcentro;
[3ec149c]395
396        // Toma parámetros
397        iph = copiaParametro("iph",ptrTrama); // Toma ip
398        cfg = copiaParametro("cfg",ptrTrama); // Toma configuracion
399
[da48c98]400        dbi = og_dbi_open(&dbi_config);
401        if (!dbi) {
402                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
403                       __func__, __LINE__);
404                goto err_dbi_open;
405        }
406
[3ec149c]407        // Recupera los datos del cliente
[da48c98]408        result = dbi_conn_queryf(dbi->conn,
[3ec149c]409                        "SELECT ordenadores.*,aulas.idaula,centros.idcentro FROM ordenadores "
410                                " INNER JOIN aulas ON aulas.idaula=ordenadores.idaula"
411                                " INNER JOIN centros ON centros.idcentro=aulas.idcentro"
412                                " WHERE ordenadores.ip = '%s'", iph);
413
[da48c98]414        if (!result) {
415                dbi_conn_error(dbi->conn, &msglog);
[8c04716]416                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
417                       __func__, __LINE__, msglog);
[da48c98]418                goto err_query_fail;
[3ec149c]419        }
420
[da48c98]421        if (!dbi_result_next_row(result)) {
[8c04716]422                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
423                       __func__, __LINE__);
[da48c98]424                dbi_result_free(result);
425                goto err_query_fail;
[3ec149c]426        }
427
[8c04716]428        syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph);
429
[da48c98]430        idordenador = dbi_result_get_uint(result, "idordenador");
431        str = (char *)dbi_result_get_string(result, "nombreordenador");
432        sprintf(nombreordenador, "%s", str);
433        cache = dbi_result_get_uint(result, "cache");
434        idproautoexec = dbi_result_get_uint(result, "idproautoexec");
435        idaula = dbi_result_get_uint(result, "idaula");
436        idcentro = dbi_result_get_uint(result, "idcentro");
437        dbi_result_free(result);
[3ec149c]438
[e052fdc]439        resul = actualizaConfiguracion(dbi, cfg, idordenador); // Actualiza la configuración del ordenador
[0a73ecf7]440        liberaMemoria(cfg);
[da48c98]441        og_dbi_close(dbi);
[3ec149c]442
443        if (!resul) {
[0a73ecf7]444                liberaMemoria(iph);
[8c04716]445                syslog(LOG_ERR, "Cannot add client to database\n");
[5759db40]446                return false;
[3ec149c]447        }
448
449        if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets
[0a73ecf7]450                liberaMemoria(iph);
[8c04716]451                syslog(LOG_ERR, "client table is full\n");
[5759db40]452                return false;
[3ec149c]453        }
454
455        /*------------------------------------------------------------------------------------------------------------------------------
456         Prepara la trama de respuesta
457         -------------------------------------------------------------------------------------------------------------------------------*/
458        initParametros(ptrTrama,0);
459        ptrTrama->tipo=MSG_RESPUESTA;
460        lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\r");
461        lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador);
462        lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador);
463        lon += sprintf(ptrTrama->parametros + lon, "che=%d\r", cache);
464        lon += sprintf(ptrTrama->parametros + lon, "exe=%d\r", idproautoexec);
465        lon += sprintf(ptrTrama->parametros + lon, "ida=%d\r", idaula);
466        lon += sprintf(ptrTrama->parametros + lon, "idc=%d\r", idcentro);
467        lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", 1); // Confirmación proceso correcto
468
[ba03878]469        if (!mandaTrama(&socket_c, ptrTrama)) {
[8c04716]470                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
471                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
472                       strerror(errno));
[5759db40]473                return false;
[3ec149c]474        }
[0a73ecf7]475        liberaMemoria(iph);
[5759db40]476        return true;
[da48c98]477
478err_query_fail:
479        og_dbi_close(dbi);
480err_dbi_open:
481        liberaMemoria(iph);
482        liberaMemoria(cfg);
483        return false;
[3ec149c]484}
485// ________________________________________________________________________________________________________
486// Función: actualizaConfiguracion
487//
488//      Descripción:
489//              Esta función actualiza la base de datos con la configuracion de particiones de un cliente
490//      Parámetros:
491//              - db: Objeto base de datos (ya operativo)
492//              - tbl: Objeto tabla
493//              - cfg: cadena con una Configuración
494//              - ido: Identificador del ordenador cliente
495//      Devuelve:
[5759db40]496//              true: Si el proceso es correcto
497//              false: En caso de ocurrir algún error
[3ec149c]498//      Especificaciones:
499//              Los parametros de la configuración son:
500//                      par= Número de partición
501//                      cpt= Codigo o tipo de partición
502//                      sfi= Sistema de ficheros que está implementado en la partición
503//                      soi= Nombre del sistema de ficheros instalado en la partición
504//                      tam= Tamaño de la partición
505// ________________________________________________________________________________________________________
[e052fdc]506bool actualizaConfiguracion(struct og_dbi *dbi, char *cfg, int ido)
[3ec149c]507{
[7224a0a]508        int lon, p, c,i, dato, swu, idsoi, idsfi,k;
[0f1e5ad]509        char *ptrPar[MAXPAR], *ptrCfg[7], *ptrDual[2], tbPar[LONSTD];
[db4d467]510        char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración.
[e052fdc]511        dbi_result result, result_update;
512        const char *msglog;
[3ec149c]513
[0d6ed7ac]514        lon = 0;
[3ec149c]515        p = splitCadena(ptrPar, cfg, '\n');
516        for (i = 0; i < p; i++) {
517                c = splitCadena(ptrCfg, ptrPar[i], '\t');
[db4d467]518
519                // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD.
520                if (i == 0 && c == 1) {
521                        splitCadena(ptrDual, ptrCfg[0], '=');
522                        ser = ptrDual[1];
523                        if (strlen(ser) > 0) {
524                                // Solo actualizar si número de serie no existía.
[e052fdc]525                                result = dbi_conn_queryf(dbi->conn,
526                                                "UPDATE ordenadores SET numserie='%s'"
[ac933ca]527                                                " WHERE idordenador=%d AND numserie IS NULL",
[db4d467]528                                                ser, ido);
[e052fdc]529                                if (!result) {
530                                        dbi_conn_error(dbi->conn, &msglog);
[9bdd4aa]531                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
532                                               __func__, __LINE__, msglog);
[5759db40]533                                        return false;
[db4d467]534                                }
[9bdd4aa]535                                dbi_result_free(result);
[db4d467]536                        }
537                        continue;
538                }
539
540                // Distribución de particionado.
[b0c9683]541                disk = par = cpt = sfi = soi = tam = uso = NULL;
[db4d467]542
[3ec149c]543                splitCadena(ptrDual, ptrCfg[0], '=');
[ba98026]544                disk = ptrDual[1]; // Número de disco
[3ec149c]545
546                splitCadena(ptrDual, ptrCfg[1], '=');
[ba98026]547                par = ptrDual[1]; // Número de partición
548
[5f9eca0]549                k=splitCadena(ptrDual, ptrCfg[2], '=');
550                if(k==2){
551                        cpt = ptrDual[1]; // Código de partición
552                }else{
[db4d467]553                        cpt = (char*)"0";
[5f9eca0]554                }
[3ec149c]555
[ba98026]556                k=splitCadena(ptrDual, ptrCfg[3], '=');
[3ec149c]557                if(k==2){
558                        sfi = ptrDual[1]; // Sistema de ficheros
[0a73ecf7]559                        /* Comprueba existencia del s0xistema de ficheros instalado */
[e052fdc]560                        idsfi = checkDato(dbi, sfi, "sistemasficheros", "descripcion","idsistemafichero");
[3ec149c]561                }
562                else
563                        idsfi=0;
564
[ba98026]565                k=splitCadena(ptrDual, ptrCfg[4], '=');
[3ec149c]566                if(k==2){ // Sistema operativo detecdtado
567                        soi = ptrDual[1]; // Nombre del S.O. instalado
568                        /* Comprueba existencia del sistema operativo instalado */
[e052fdc]569                        idsoi = checkDato(dbi, soi, "nombresos", "nombreso", "idnombreso");
[3ec149c]570                }
571                else
572                        idsoi=0;
573
[ba98026]574                splitCadena(ptrDual, ptrCfg[5], '=');
[3ec149c]575                tam = ptrDual[1]; // Tamaño de la partición
576
[b0c9683]577                splitCadena(ptrDual, ptrCfg[6], '=');
578                uso = ptrDual[1]; // Porcentaje de uso del S.F.
579
[0d6ed7ac]580                lon += sprintf(tbPar + lon, "(%s, %s),", disk, par);
[3ec149c]581
[e052fdc]582                result = dbi_conn_queryf(dbi->conn,
583                                "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso"
[b0c9683]584                                "  FROM ordenadores_particiones"
585                                " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[ba98026]586                                ido, disk, par);
[e052fdc]587                if (!result) {
588                        dbi_conn_error(dbi->conn, &msglog);
[8c04716]589                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
590                               __func__, __LINE__, msglog);
[5759db40]591                        return false;
[3ec149c]592                }
[e052fdc]593                if (!dbi_result_next_row(result)) {
594                        result_update = dbi_conn_queryf(dbi->conn,
595                                        "INSERT INTO ordenadores_particiones(idordenador,numdisk,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)"
[b0c9683]596                                        " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)",
597                                        ido, disk, par, cpt, tam, uso, idsfi, idsoi);
[e052fdc]598                        if (!result_update) {
599                                dbi_conn_error(dbi->conn, &msglog);
[9bdd4aa]600                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
601                                       __func__, __LINE__, msglog);
[5759db40]602                                return false;
[3ec149c]603                        }
[e052fdc]604                        dbi_result_free(result_update);
605
[3ec149c]606                } else { // Existe el registro
[5759db40]607                        swu = true; // Se supone que algún dato ha cambiado
[e052fdc]608
[ffdeba9]609                        dato = dbi_result_get_ulonglong(result, "tamano");
[e052fdc]610                        if (atoi(tam) == dato) {// Parámetro tamaño igual al almacenado
611                                dato = dbi_result_get_uint(result, "idsistemafichero");
612                                if (idsfi == dato) {// Parámetro sistema de fichero igual al almacenado
613                                        dato = dbi_result_get_uint(result, "idnombreso");
614                                        if (idsoi == dato) {// Parámetro sistema de fichero distinto al almacenado
[83f20d1]615                                                swu = false; // Todos los parámetros de la partición son iguales, no se actualiza
[3ec149c]616                                        }
617                                }
618                        }
619                        if (swu) { // Hay que actualizar los parámetros de la partición
[e052fdc]620                                result_update = dbi_conn_queryf(dbi->conn,
621                                        "UPDATE ordenadores_particiones SET "
[3ec149c]622                                        " codpar=0x%s,"
623                                        " tamano=%s,"
[b0c9683]624                                        " uso=%s,"
[3ec149c]625                                        " idsistemafichero=%d,"
626                                        " idnombreso=%d,"
[c916af9]627                                        " idimagen=0,"
628                                        " idperfilsoft=0,"
629                                        " fechadespliegue=NULL"
[ba98026]630                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[b0c9683]631                                        cpt, tam, uso, idsfi, idsoi, ido, disk, par);
[bbd1290]632                        } else {  // Actualizar porcentaje de uso.
[e052fdc]633                                result_update = dbi_conn_queryf(dbi->conn,
634                                        "UPDATE ordenadores_particiones SET "
[5118932]635                                        " codpar=0x%s,"
[bbd1290]636                                        " uso=%s"
637                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[5118932]638                                        cpt, uso, ido, disk, par);
[bbd1290]639                        }
[e052fdc]640                        if (!result_update) {
641                                dbi_conn_error(dbi->conn, &msglog);
[8c04716]642                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
643                                       __func__, __LINE__, msglog);
[5759db40]644                                return false;
[3ec149c]645                        }
[e052fdc]646
647                        dbi_result_free(result_update);
[3ec149c]648                }
[9bdd4aa]649                dbi_result_free(result);
[3ec149c]650        }
[0d6ed7ac]651        lon += sprintf(tbPar + lon, "(0,0)");
[3ec149c]652        // Eliminar particiones almacenadas que ya no existen
[e052fdc]653        result_update = dbi_conn_queryf(dbi->conn,
654                "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)",
[0d6ed7ac]655                        ido, tbPar);
[e052fdc]656        if (!result_update) {
657                dbi_conn_error(dbi->conn, &msglog);
[8c04716]658                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
659                       __func__, __LINE__, msglog);
[5759db40]660                return false;
[3ec149c]661        }
[e052fdc]662        dbi_result_free(result_update);
663
[5759db40]664        return true;
[3ec149c]665}
666// ________________________________________________________________________________________________________
667// Función: checkDato
668//
669//      Descripción:
670//               Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en
671//              cualquier caso el identificador del registro existenet o del insertado
672//      Parámetros:
673//              - db: Objeto base de datos (ya operativo)
674//              - tbl: Objeto tabla
675//              - dato: Dato
676//              - tabla: Nombre de la tabla
677//              - nomdato: Nombre del dato en la tabla
678//              - nomidentificador: Nombre del identificador en la tabla
679//      Devuelve:
680//              El identificador del registro existente o el del insertado
681//
682//      Especificaciones:
683//              En caso de producirse algún error se devuelve el valor 0
684// ________________________________________________________________________________________________________
685
[e052fdc]686int checkDato(struct og_dbi *dbi, char *dato, const char *tabla,
[d647d81]687                     const char *nomdato, const char *nomidentificador)
688{
[e052fdc]689        const char *msglog;
[3ec149c]690        int identificador;
[e052fdc]691        dbi_result result;
[3ec149c]692
693        if (strlen(dato) == 0)
694                return (0); // EL dato no tiene valor
[e052fdc]695        result = dbi_conn_queryf(dbi->conn,
696                        "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador,
[3ec149c]697                        tabla, nomdato, dato);
698
699        // Ejecuta consulta
[e052fdc]700        if (!result) {
701                dbi_conn_error(dbi->conn, &msglog);
[8c04716]702                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
703                       __func__, __LINE__, msglog);
[3ec149c]704                return (0);
705        }
[e052fdc]706        if (!dbi_result_next_row(result)) { //  Software NO existente
707                dbi_result_free(result);
708
709                result = dbi_conn_queryf(dbi->conn,
710                                "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato);
711                if (!result) {
712                        dbi_conn_error(dbi->conn, &msglog);
713                        og_info((char *)msglog);
[3ec149c]714                        return (0);
715                }
716                // Recupera el identificador del software
[e052fdc]717                identificador = dbi_conn_sequence_last(dbi->conn, NULL);
[3ec149c]718        } else {
[e052fdc]719                identificador = dbi_result_get_uint(result, nomidentificador);
[3ec149c]720        }
[e052fdc]721        dbi_result_free(result);
722
[3ec149c]723        return (identificador);
724}
725// ________________________________________________________________________________________________________
726// Función: registraCliente
727//
728//      Descripción:
729//               Incluye al cliente en la tabla de sokets
730//      Parámetros:
731//              - iph: Dirección ip del cliente
732//      Devuelve:
[5759db40]733//              true: Si el proceso es correcto
734//              false: En caso de ocurrir algún error
[3ec149c]735// ________________________________________________________________________________________________________
[d647d81]736bool registraCliente(char *iph)
737{
[3ec149c]738        int idx;
739
740        if (!clienteExistente(iph, &idx)) { // Si no existe la IP ...
741                if (!hayHueco(&idx)) { // Busca hueco para el nuevo cliente
[5759db40]742                        return false; // No hay huecos
[3ec149c]743                }
744        }
745        strcpy(tbsockets[idx].ip, iph); // Copia IP
746        strcpy(tbsockets[idx].estado, CLIENTE_INICIANDO); // Actualiza el estado del cliente
[5759db40]747        return true;
[3ec149c]748}
749// ________________________________________________________________________________________________________
750// Función: AutoexecCliente
751//
752//      Descripción:
753//              Envía archivo de autoexec al cliente
754//      Parámetros:
755//              - socket_c: Socket del cliente que envió el mensaje
756//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
757//      Devuelve:
[5759db40]758//              true: Si el proceso es correcto
759//              false: En caso de ocurrir algún error
[3ec149c]760// ________________________________________________________________________________________________________
[9baecf8]761static bool AutoexecCliente(TRAMA *ptrTrama, struct og_client *cli)
[d647d81]762{
[9baecf8]763        int socket_c = og_client_socket(cli);
[3ec149c]764        int lon;
[46d07a2]765        char *iph, *exe;
[3ec149c]766        FILE *fileexe;
767        char fileautoexec[LONPRM];
768        char parametros[LONGITUD_PARAMETROS];
[46d07a2]769        struct og_dbi *dbi;
[3ec149c]770
771        iph = copiaParametro("iph",ptrTrama); // Toma dirección IP del cliente
772        exe = copiaParametro("exe",ptrTrama); // Toma identificador del procedimiento inicial
773
774        sprintf(fileautoexec, "/tmp/Sautoexec-%s", iph);
[0a73ecf7]775        liberaMemoria(iph);
[3ec149c]776        fileexe = fopen(fileautoexec, "wb"); // Abre fichero de script
777        if (fileexe == NULL) {
[8c04716]778                syslog(LOG_ERR, "cannot create temporary file\n");
[5759db40]779                return false;
[3ec149c]780        }
781
[46d07a2]782        dbi = og_dbi_open(&dbi_config);
783        if (!dbi) {
784                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
785                       __func__, __LINE__);
[5759db40]786                return false;
[3ec149c]787        }
788        initParametros(ptrTrama,0);
[46d07a2]789        if (recorreProcedimientos(dbi, parametros, fileexe, exe)) {
[3ec149c]790                lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r");
791                lon += sprintf(ptrTrama->parametros + lon, "nfl=%s\r", fileautoexec);
792                lon += sprintf(ptrTrama->parametros + lon, "res=1\r");
793        } else {
794                lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r");
795                lon += sprintf(ptrTrama->parametros + lon, "res=0\r");
796        }
797
[46d07a2]798        og_dbi_close(dbi);
[3ec149c]799        fclose(fileexe);
800
[ba03878]801        if (!mandaTrama(&socket_c, ptrTrama)) {
[0a73ecf7]802                liberaMemoria(exe);
[8c04716]803                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
804                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
805                       strerror(errno));
[5759db40]806                return false;
[3ec149c]807        }
[0a73ecf7]808        liberaMemoria(exe);
[5759db40]809        return true;
[3ec149c]810}
811// ________________________________________________________________________________________________________
812// Función: recorreProcedimientos
813//
814//      Descripción:
815//              Crea un archivo con el código de un procedimiento separando cada comando  por un salto de linea
816//      Parámetros:
817//              Database db,char* parametros,FILE* fileexe,char* idp
818//      Devuelve:
[5759db40]819//              true: Si el proceso es correcto
820//              false: En caso de ocurrir algún error
[3ec149c]821// ________________________________________________________________________________________________________
[46d07a2]822bool recorreProcedimientos(struct og_dbi *dbi, char *parametros, FILE *fileexe, char *idp)
[d647d81]823{
[46d07a2]824        char idprocedimiento[LONPRM];
[3ec149c]825        int procedimientoid, lsize;
[46d07a2]826        const char *msglog, *param;
827        dbi_result result;
[3ec149c]828
[46d07a2]829        result = dbi_conn_queryf(dbi->conn,
[3ec149c]830                        "SELECT procedimientoid,parametros FROM procedimientos_acciones"
831                                " WHERE idprocedimiento=%s ORDER BY orden", idp);
[46d07a2]832        if (!result) {
833                dbi_conn_error(dbi->conn, &msglog);
[8c04716]834                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
835                       __func__, __LINE__, msglog);
[5759db40]836                return false;
[3ec149c]837        }
[46d07a2]838        while (dbi_result_next_row(result)) {
839                procedimientoid = dbi_result_get_uint(result, "procedimientoid");
[3ec149c]840                if (procedimientoid > 0) { // Procedimiento recursivo
841                        sprintf(idprocedimiento, "%d", procedimientoid);
[46d07a2]842                        if (!recorreProcedimientos(dbi, parametros, fileexe, idprocedimiento)) {
[5759db40]843                                return false;
[3ec149c]844                        }
845                } else {
[46d07a2]846                        param = dbi_result_get_string(result, "parametros");
847                        sprintf(parametros, "%s@", param);
[3ec149c]848                        lsize = strlen(parametros);
849                        fwrite(parametros, 1, lsize, fileexe); // Escribe el código a ejecutar
850                }
851        }
[46d07a2]852        dbi_result_free(result);
853
[5759db40]854        return true;
[3ec149c]855}
856// ________________________________________________________________________________________________________
857// Función: ComandosPendientes
858//
859//      Descripción:
860//              Esta función busca en la base de datos,comandos pendientes de ejecutar por un  ordenador  concreto
861//      Parámetros:
862//              - socket_c: Socket del cliente que envió el mensaje
863//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
864//      Devuelve:
[5759db40]865//              true: Si el proceso es correcto
866//              false: En caso de ocurrir algún error
[3ec149c]867// ________________________________________________________________________________________________________
[9baecf8]868static bool ComandosPendientes(TRAMA *ptrTrama, struct og_client *cli)
[0a73ecf7]869{
[9baecf8]870        int socket_c = og_client_socket(cli);
[0a73ecf7]871        char *ido,*iph,pids[LONPRM];
[3ec149c]872        int ids, idx;
873
[0a73ecf7]874        iph = copiaParametro("iph",ptrTrama); // Toma dirección IP
[3ec149c]875        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
876
877        if (!clienteExistente(iph, &idx)) { // Busca índice del cliente
[0a73ecf7]878                liberaMemoria(iph);
879                liberaMemoria(ido);
[8c04716]880                syslog(LOG_ERR, "client does not exist\n");
[5759db40]881                return false;
[3ec149c]882        }
883        if (buscaComandos(ido, ptrTrama, &ids)) { // Existen comandos pendientes
884                ptrTrama->tipo = MSG_COMANDO;
885                sprintf(pids, "\rids=%d\r", ids);
886                strcat(ptrTrama->parametros, pids);
887                strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO);
888        } else {
889                initParametros(ptrTrama,0);
890                strcpy(ptrTrama->parametros, "nfn=NoComandosPtes\r");
891        }
[ba03878]892        if (!mandaTrama(&socket_c, ptrTrama)) {
[0a73ecf7]893                liberaMemoria(iph);
[8c04716]894                liberaMemoria(ido);
895                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
896                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
897                       strerror(errno));
[5759db40]898                return false;
[3ec149c]899        }
[0a73ecf7]900        liberaMemoria(iph);
901        liberaMemoria(ido);     
[5759db40]902        return true;
[3ec149c]903}
904// ________________________________________________________________________________________________________
905// Función: buscaComandos
906//
907//      Descripción:
908//              Busca en la base de datos,comandos pendientes de ejecutar por el cliente
909//      Parámetros:
910//              - ido: Identificador del ordenador
911//              - cmd: Parámetros del comando (Salida)
[0a73ecf7]912//              - ids: Identificador de la sesion(Salida)
[3ec149c]913//      Devuelve:
[5759db40]914//              true: Si el proceso es correcto
915//              false: En caso de ocurrir algún error
[3ec149c]916// ________________________________________________________________________________________________________
[c0a46e2]917bool buscaComandos(char *ido, TRAMA *ptrTrama, int *ids)
[3ec149c]918{
[d1f9fdd]919        const char *param, *msglog;
920        struct og_dbi *dbi;
921        dbi_result result;
922        unsigned int lonprm;
[3ec149c]923
[d1f9fdd]924        dbi = og_dbi_open(&dbi_config);
925        if (!dbi) {
926                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
927                       __func__, __LINE__);
928                goto err_dbi_open;
[3ec149c]929        }
[d1f9fdd]930        result = dbi_conn_queryf(dbi->conn,
931                        "SELECT sesion, parametros"\
932                        " FROM acciones WHERE idordenador=%s AND estado='%d'"\
933                        " ORDER BY idaccion", ido, ACCION_INICIADA);
934        if (!result) {
935                dbi_conn_error(dbi->conn, &msglog);
[8c04716]936                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
937                       __func__, __LINE__, msglog);
[d1f9fdd]938                goto err_query_fail;
[3ec149c]939        }
[d1f9fdd]940        if (!dbi_result_next_row(result)) {
941                dbi_result_free(result);
942                og_dbi_close(dbi);
[5759db40]943                return false; // No hay comandos pendientes
[3ec149c]944        }
[d1f9fdd]945
946        *ids = dbi_result_get_uint(result, "sesion");
947        param = dbi_result_get_string(result, "parametros");
948        lonprm = strlen(param);
949
950        if(!initParametros(ptrTrama,lonprm + LONGITUD_PARAMETROS)){
951                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
952                goto err_init_params;
953        }
954        sprintf(ptrTrama->parametros, "%s", param);
955
956        dbi_result_free(result);
957        og_dbi_close(dbi);
958
[5759db40]959        return true; // Hay comandos pendientes, se toma el primero de la cola
[d1f9fdd]960
961err_init_params:
962        dbi_result_free(result);
963err_query_fail:
964        og_dbi_close(dbi);
965err_dbi_open:
966        return false;
[3ec149c]967}
968// ________________________________________________________________________________________________________
969// Función: DisponibilidadComandos
970//
971//      Descripción:
972//              Esta función habilita a un cliente para recibir comandos desde la consola
973//      Parámetros:
974//              - socket_c: Socket del cliente que envió el mensaje
975//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
976//      Devuelve:
[5759db40]977//              true: Si el proceso es correcto
978//              false: En caso de ocurrir algún error
[3ec149c]979// ________________________________________________________________________________________________________
[0a73ecf7]980//
[9baecf8]981static bool DisponibilidadComandos(TRAMA *ptrTrama, struct og_client *cli)
[0a73ecf7]982{
983        char *iph, *tpc;
[2e0c063]984        int idx;
[3ec149c]985
[0a73ecf7]986        iph = copiaParametro("iph",ptrTrama); // Toma ip
[3ec149c]987        if (!clienteExistente(iph, &idx)) { // Busca índice del cliente
[0a73ecf7]988                liberaMemoria(iph);
[8c04716]989                syslog(LOG_ERR, "client does not exist\n");
[5759db40]990                return false;
[3ec149c]991        }
[0a73ecf7]992        tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.)
[3ec149c]993        strcpy(tbsockets[idx].estado, tpc);
[2e0c063]994        cli->keepalive_idx = idx;
[0a73ecf7]995        liberaMemoria(iph);
996        liberaMemoria(tpc);             
[5759db40]997        return true;
[3ec149c]998}
999// ________________________________________________________________________________________________________
1000// Función: respuestaEstandar
1001//
1002//      Descripción:
1003//              Esta función actualiza la base de datos con el resultado de la ejecución de un comando con seguimiento
1004//      Parámetros:
1005//              - res: resultado de la ejecución del comando
1006//              - der: Descripción del error si hubiese habido
1007//              - iph: Dirección IP
[0a73ecf7]1008//              - ids: identificador de la sesión
[3ec149c]1009//              - ido: Identificador del ordenador que notifica
1010//              - db: Objeto base de datos (operativo)
1011//              - tbl: Objeto tabla
1012//      Devuelve:
[5759db40]1013//              true: Si el proceso es correcto
1014//              false: En caso de ocurrir algún error
[3ec149c]1015// ________________________________________________________________________________________________________
[8a2ae26]1016static bool respuestaEstandar(TRAMA *ptrTrama, char *iph, char *ido,
1017                              struct og_dbi *dbi)
[d647d81]1018{
[3ec149c]1019        char *res, *ids, *der;
1020        char fechafin[LONPRM];
[8a2ae26]1021        const char *msglog;
1022        dbi_result result;
[3ec149c]1023        struct tm* st;
[0a73ecf7]1024        int idaccion;
[3ec149c]1025
[78a97c5]1026        ids = copiaParametro("ids",ptrTrama);
1027        res = copiaParametro("res",ptrTrama);
[3ec149c]1028
[78a97c5]1029        if (ids == NULL) {
1030                if (atoi(res) == ACCION_FALLIDA) {
1031                        liberaMemoria(res);
1032                        return false;
1033                }
1034                liberaMemoria(res);
[5759db40]1035                return true;
[78a97c5]1036        }
[5759db40]1037
[78a97c5]1038        if (atoi(ids) == 0) {
[0a73ecf7]1039                liberaMemoria(ids);
[78a97c5]1040                if (atoi(res) == ACCION_FALLIDA) {
1041                        liberaMemoria(res);
1042                        return false;
1043                }
1044                liberaMemoria(res);
[5759db40]1045                return true;
[0a73ecf7]1046        }
[3ec149c]1047
[8a2ae26]1048        result = dbi_conn_queryf(dbi->conn,
[0a73ecf7]1049                        "SELECT * FROM acciones WHERE idordenador=%s"
1050                        " AND sesion=%s ORDER BY idaccion", ido,ids);
1051
1052        liberaMemoria(ids);
1053
[8a2ae26]1054        if (!result) {
1055                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1056                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1057                       __func__, __LINE__, msglog);
[5759db40]1058                return false;
[3ec149c]1059        }
[8a2ae26]1060        if (!dbi_result_next_row(result)) {
[8c04716]1061                syslog(LOG_ERR, "no actions available\n");
[8a2ae26]1062                dbi_result_free(result);
[5759db40]1063                return true;
[3ec149c]1064        }
[8a2ae26]1065
1066        idaccion = dbi_result_get_uint(result, "idaccion");
1067        dbi_result_free(result);
1068
[3ec149c]1069        st = tomaHora();
1070        sprintf(fechafin, "%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1,
1071                        st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
1072
[0a73ecf7]1073        der = copiaParametro("der",ptrTrama); // Toma descripción del error (si hubiera habido)
[8a2ae26]1074
1075        result = dbi_conn_queryf(dbi->conn,
[f55923d]1076                        "UPDATE acciones"\
1077                        "   SET resultado='%s',estado='%d',fechahorafin='%s',descrinotificacion='%s'"\
[0a73ecf7]1078                        " WHERE idordenador=%s AND idaccion=%d",
1079                        res, ACCION_FINALIZADA, fechafin, der, ido, idaccion);
[8a2ae26]1080        if (!result) {
1081                dbi_conn_error(dbi->conn, &msglog);
[0a73ecf7]1082                liberaMemoria(res);
1083                liberaMemoria(der);
[8a2ae26]1084                og_info((char *)msglog);
[5759db40]1085                return false;
[3ec149c]1086        }
[8a2ae26]1087        dbi_result_free(result);
1088
[0a73ecf7]1089        liberaMemoria(der);
[3ec149c]1090
[b2b8797]1091        if (atoi(res) == ACCION_FALLIDA) {
1092                liberaMemoria(res);
1093                return false;
1094        }
1095
[f55923d]1096        liberaMemoria(res);
[5759db40]1097        return true;
[3ec149c]1098}
[c8e415b]1099
1100static bool og_send_cmd(char *ips_array[], int ips_array_len,
1101                        const char *state, TRAMA *ptrTrama)
1102{
1103        int i, idx;
1104
1105        for (i = 0; i < ips_array_len; i++) {
1106                if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos
1107                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
1108
1109                        strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente
[0deba63]1110                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[c8e415b]1111                                syslog(LOG_ERR, "failed to send response to %s:%s\n",
1112                                       ips_array[i], strerror(errno));
1113                        }
1114                }
1115        }
1116        return true;
1117}
1118
[3ec149c]1119// ________________________________________________________________________________________________________
1120// Función: enviaComando
1121//
1122//      Descripción:
1123//              Envía un comando a los clientes
1124//      Parámetros:
1125//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1126//              - estado: Estado en el se deja al cliente mientras se ejecuta el comando
1127//      Devuelve:
[5759db40]1128//              true: Si el proceso es correcto
1129//              false: En caso de ocurrir algún error
[3ec149c]1130// ________________________________________________________________________________________________________
[c0a46e2]1131bool enviaComando(TRAMA* ptrTrama, const char *estado)
[d647d81]1132{
[3ec149c]1133        char *iph, *Ipes, *ptrIpes[MAXIMOS_CLIENTES];
[c8e415b]1134        int lon;
[3ec149c]1135
1136        iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP
1137        lon = strlen(iph); // Calcula longitud de la cadena de direccion/es IPE/S
1138        Ipes = (char*) reservaMemoria(lon + 1);
1139        if (Ipes == NULL) {
[8c04716]1140                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[5759db40]1141                return false;
[3ec149c]1142        }
[0a73ecf7]1143       
[3ec149c]1144        strcpy(Ipes, iph); // Copia cadena de IPES
[0a73ecf7]1145        liberaMemoria(iph);
1146
[3ec149c]1147        lon = splitCadena(ptrIpes, Ipes, ';');
1148        FINCADaINTRO(ptrTrama);
[2e0c063]1149
[c8e415b]1150        if (!og_send_cmd(ptrIpes, lon, estado, ptrTrama))
1151                return false;
1152
[fc480f2]1153        liberaMemoria(Ipes);
[5759db40]1154        return true;
[3ec149c]1155}
1156//______________________________________________________________________________________________________
1157// Función: respuestaConsola
1158//
1159//      Descripción:
1160//              Envia una respuesta a la consola sobre el resultado de la ejecución de un comando
1161//      Parámetros:
1162//              - socket_c: (Salida) Socket utilizado para el envío
1163//              - res: Resultado del envío del comando
1164//      Devuelve:
[5759db40]1165//              true: Si el proceso es correcto
1166//              false: En caso de ocurrir algún error
[3ec149c]1167// ________________________________________________________________________________________________________
[d647d81]1168bool respuestaConsola(int socket_c, TRAMA *ptrTrama, int res)
1169{
[3ec149c]1170        initParametros(ptrTrama,0);
1171        sprintf(ptrTrama->parametros, "res=%d\r", res);
[ba03878]1172        if (!mandaTrama(&socket_c, ptrTrama)) {
[8c04716]1173                syslog(LOG_ERR, "%s:%d failed to send response: %s\n",
1174                       __func__, __LINE__, strerror(errno));
[5759db40]1175                return false;
[3ec149c]1176        }
[5759db40]1177        return true;
[3ec149c]1178}
1179// ________________________________________________________________________________________________________
1180// Función: Levanta
1181//
1182//      Descripción:
1183//              Enciende ordenadores a través de la red cuyas macs se pasan como parámetro
1184//      Parámetros:
[4329e85]1185//              - iph: Cadena de direcciones ip separadas por ";"
[3ec149c]1186//              - mac: Cadena de direcciones mac separadas por ";"
[4329e85]1187//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
[3ec149c]1188//      Devuelve:
[5759db40]1189//              true: Si el proceso es correcto
1190//              false: En caso de ocurrir algún error
[3ec149c]1191// ________________________________________________________________________________________________________
[847eb13]1192bool Levanta(char *ptrIP[], char *ptrMacs[], char *ptrNetmasks[], int lon, char *mar)
[4329e85]1193{
[a52f983]1194        unsigned int on = 1;
[8aa0c08]1195        struct sockaddr_in local;
[62c0560]1196        int i, res;
[aaa2c57]1197        int s;
[3ec149c]1198
1199        /* Creación de socket para envío de magig packet */
1200        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
[70f6f10]1201        if (s < 0) {
[8c04716]1202                syslog(LOG_ERR, "cannot create socket for magic packet\n");
[5759db40]1203                return false;
[3ec149c]1204        }
[a52f983]1205        res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on,
1206                         sizeof(on));
[70f6f10]1207        if (res < 0) {
[8c04716]1208                syslog(LOG_ERR, "cannot set broadcast socket\n");
[5759db40]1209                return false;
[3ec149c]1210        }
[847eb13]1211
[a52f983]1212        memset(&local, 0, sizeof(local));
[3ec149c]1213        local.sin_family = AF_INET;
[a52f983]1214        local.sin_port = htons(PUERTO_WAKEUP);
1215        local.sin_addr.s_addr = htonl(INADDR_ANY);
1216
[3ec149c]1217        for (i = 0; i < lon; i++) {
[847eb13]1218                if (!WakeUp(s, ptrIP[i], ptrMacs[i], ptrNetmasks[i], mar)) {
[8c04716]1219                        syslog(LOG_ERR, "problem sending magic packet\n");
[3ec149c]1220                        close(s);
[5759db40]1221                        return false;
[3ec149c]1222                }
1223        }
1224        close(s);
[5759db40]1225        return true;
[3ec149c]1226}
[332487d]1227
1228#define OG_WOL_SEQUENCE         6
1229#define OG_WOL_MACADDR_LEN      6
1230#define OG_WOL_REPEAT           16
1231
1232struct wol_msg {
1233        char secuencia_FF[OG_WOL_SEQUENCE];
1234        char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN];
1235};
1236
1237static bool wake_up_broadcast(int sd, struct sockaddr_in *client,
[847eb13]1238                              const struct wol_msg *msg, const struct in_addr *addr)
[332487d]1239{
1240        struct sockaddr_in *broadcast_addr;
1241        struct ifaddrs *ifaddr, *ifa;
[847eb13]1242        int ret1, ret2;
[332487d]1243
1244        if (getifaddrs(&ifaddr) < 0) {
1245                syslog(LOG_ERR, "cannot get list of addresses\n");
1246                return false;
1247        }
1248
[847eb13]1249
[332487d]1250        client->sin_addr.s_addr = htonl(INADDR_BROADCAST);
1251
1252        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1253                if (ifa->ifa_addr == NULL ||
1254                    ifa->ifa_addr->sa_family != AF_INET ||
1255                    strcmp(ifa->ifa_name, interface) != 0)
1256                        continue;
1257
1258                broadcast_addr =
1259                        (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr;
1260                client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr;
1261                break;
1262        }
[d2a9dd8]1263        freeifaddrs(ifaddr);
[332487d]1264
[847eb13]1265        ret1 = sendto(sd, msg, sizeof(*msg), 0,
[8aa0c08]1266                     (struct sockaddr *)client, sizeof(*client));
[847eb13]1267        client->sin_addr.s_addr = addr->s_addr;
1268        ret2 = sendto(sd, msg, sizeof(*msg), 0,
1269                     (struct sockaddr *)client, sizeof(*client));
1270        if ((ret1 < 0) & (ret2 < 0)) {
[332487d]1271                syslog(LOG_ERR, "failed to send broadcast wol\n");
1272                return false;
1273        }
1274
1275        return true;
1276}
1277
1278static bool wake_up_unicast(int sd, struct sockaddr_in *client,
1279                            const struct wol_msg *msg,
1280                            const struct in_addr *addr)
1281{
1282        int ret;
1283
1284        client->sin_addr.s_addr = addr->s_addr;
1285
1286        ret = sendto(sd, msg, sizeof(*msg), 0,
[8aa0c08]1287                     (struct sockaddr *)client, sizeof(*client));
[332487d]1288        if (ret < 0) {
1289                syslog(LOG_ERR, "failed to send unicast wol\n");
1290                return false;
1291        }
1292
1293        return true;
1294}
1295
[847eb13]1296
1297
[332487d]1298enum wol_delivery_type {
1299        OG_WOL_BROADCAST = 1,
1300        OG_WOL_UNICAST = 2
1301};
1302
[3ec149c]1303//_____________________________________________________________________________________________________________
1304// Función: WakeUp
1305//
1306//       Descripción:
1307//              Enciende el ordenador cuya MAC se pasa como parámetro
1308//      Parámetros:
1309//              - s : Socket para enviar trama magic packet
[4329e85]1310//              - iph : Cadena con la dirección ip
[3ec149c]1311//              - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX
[4329e85]1312//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
[3ec149c]1313//      Devuelve:
[5759db40]1314//              true: Si el proceso es correcto
1315//              false: En caso de ocurrir algún error
[3ec149c]1316//_____________________________________________________________________________________________________________
[4329e85]1317//
[847eb13]1318bool WakeUp(int s, char* iph, char *mac, char *netmask, char *mar)
[4329e85]1319{
[43763e4]1320        unsigned int macaddr[OG_WOL_MACADDR_LEN];
[332487d]1321        char HDaddress_bin[OG_WOL_MACADDR_LEN];
1322        struct sockaddr_in WakeUpCliente;
1323        struct wol_msg Trama_WakeUp;
[847eb13]1324        struct in_addr addr, netmask_addr, broadcast_addr ={};
[332487d]1325        bool ret;
1326        int i;
[3ec149c]1327
[847eb13]1328        if (!inet_aton(iph, &addr)) {
1329                syslog(LOG_ERR, "bad IP address\n");
1330                return false;
1331        }
1332
1333        if (!inet_aton(netmask, &netmask_addr)) {
1334                syslog(LOG_ERR, "bad netmask address: %s\n", netmask);
1335                return false;
1336        }
1337        broadcast_addr.s_addr = addr.s_addr | ~netmask_addr.s_addr;
1338
[3ec149c]1339        for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF)
1340                Trama_WakeUp.secuencia_FF[i] = 0xFF;
1341
[a52f983]1342        sscanf(mac, "%02x%02x%02x%02x%02x%02x",
[43763e4]1343               &macaddr[0], &macaddr[1], &macaddr[2],
1344               &macaddr[3], &macaddr[4], &macaddr[5]);
1345
1346        for (i = 0; i < 6; i++)
1347                HDaddress_bin[i] = (uint8_t)macaddr[i];
[3ec149c]1348
1349        for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC
1350                memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6);
1351
1352        /* Creación de socket del cliente que recibe la trama magic packet */
1353        WakeUpCliente.sin_family = AF_INET;
1354        WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP);
1355
[332487d]1356        switch (atoi(mar)) {
1357        case OG_WOL_BROADCAST:
[847eb13]1358                ret = wake_up_broadcast(s, &WakeUpCliente, &Trama_WakeUp, &broadcast_addr );
[332487d]1359                break;
1360        case OG_WOL_UNICAST:
[aaa2c57]1361                ret = wake_up_unicast(s, &WakeUpCliente, &Trama_WakeUp, &addr);
[332487d]1362                break;
1363        default:
1364                syslog(LOG_ERR, "unknown wol type\n");
1365                ret = false;
1366                break;
1367        }
1368        return ret;
[3ec149c]1369}
1370// ________________________________________________________________________________________________________
1371// Función: RESPUESTA_Arrancar
1372//
1373//      Descripción:
[f55923d]1374//              Respuesta del cliente al comando Arrancar
[3ec149c]1375//      Parámetros:
1376//              - socket_c: Socket del cliente que envió el mensaje
1377//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1378//      Devuelve:
[5759db40]1379//              true: Si el proceso es correcto
1380//              false: En caso de ocurrir algún error
[3ec149c]1381// ________________________________________________________________________________________________________
[9baecf8]1382static bool RESPUESTA_Arrancar(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1383{
[8a2ae26]1384        struct og_dbi *dbi;
[3ec149c]1385        char *iph, *ido;
1386        char *tpc;
[8a2ae26]1387        int i;
[3ec149c]1388
[8a2ae26]1389        dbi = og_dbi_open(&dbi_config);
1390        if (!dbi) {
1391                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1392                       __func__, __LINE__);
[5759db40]1393                return false;
[3ec149c]1394        }
1395
1396        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1397        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1398
[8a2ae26]1399        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
[0a73ecf7]1400                liberaMemoria(iph);
1401                liberaMemoria(ido);
[8c04716]1402                syslog(LOG_ERR, "failed to register notification\n");
[8a2ae26]1403                og_dbi_close(dbi);
[8c04716]1404                return false;
[3ec149c]1405        }
1406
1407        tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.)
1408        if (clienteExistente(iph, &i)) // Actualiza estado
1409                strcpy(tbsockets[i].estado, tpc);
[8a2ae26]1410
[0a73ecf7]1411        liberaMemoria(iph);
1412        liberaMemoria(ido);
1413        liberaMemoria(tpc);
[8a2ae26]1414        og_dbi_close(dbi);
1415
[5759db40]1416        return true;
[3ec149c]1417}
1418// ________________________________________________________________________________________________________
1419// Función: RESPUESTA_Apagar
1420//
1421//      Descripción:
1422//              Respuesta del cliente al comando Apagar
1423//      Parámetros:
1424//              - socket_c: Socket del cliente que envió el mensaje
1425//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1426//      Devuelve:
[5759db40]1427//              true: Si el proceso es correcto
1428//              false: En caso de ocurrir algún error
[3ec149c]1429// ________________________________________________________________________________________________________
[9baecf8]1430static bool RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1431{
[8a2ae26]1432        struct og_dbi *dbi;
[3ec149c]1433        char *iph, *ido;
[8a2ae26]1434        int i;
[3ec149c]1435
[8a2ae26]1436        dbi = og_dbi_open(&dbi_config);
1437        if (!dbi) {
1438                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1439                       __func__, __LINE__);
[5759db40]1440                return false;
[3ec149c]1441        }
1442
1443        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1444        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1445
[8a2ae26]1446        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
[0a73ecf7]1447                liberaMemoria(iph);
1448                liberaMemoria(ido);
[8c04716]1449                syslog(LOG_ERR, "failed to register notification\n");
[8a2ae26]1450                og_dbi_close(dbi);
[5759db40]1451                return false; // Error al registrar notificacion
[3ec149c]1452        }
1453
1454        if (clienteExistente(iph, &i)) // Actualiza estado
1455                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[8a2ae26]1456
[0a73ecf7]1457        liberaMemoria(iph);
1458        liberaMemoria(ido);
[8a2ae26]1459        og_dbi_close(dbi);
1460
[5759db40]1461        return true;
[3ec149c]1462}
1463// ________________________________________________________________________________________________________
1464// Función: RESPUESTA_CrearImagen
1465//
1466//      Descripción:
1467//              Respuesta del cliente al comando CrearImagen
1468//      Parámetros:
1469//              - socket_c: Socket del cliente que envió el mensaje
1470//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1471//      Devuelve:
[5759db40]1472//              true: Si el proceso es correcto
1473//              false: En caso de ocurrir algún error
[3ec149c]1474// ________________________________________________________________________________________________________
[9baecf8]1475static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli)
[0a73ecf7]1476{
[c916af9]1477        char *iph, *dsk, *par, *cpt, *ipr, *ido;
[8a2ae26]1478        struct og_dbi *dbi;
[3ec149c]1479        char *idi;
[c0a46e2]1480        bool res;
[3ec149c]1481
[8a2ae26]1482        dbi = og_dbi_open(&dbi_config);
1483        if (!dbi) {
1484                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1485                       __func__, __LINE__);
1486                return false;
1487        }
1488
[3ec149c]1489        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1490        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1491
[8a2ae26]1492        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
[0a73ecf7]1493                liberaMemoria(iph);
1494                liberaMemoria(ido);
[8c04716]1495                syslog(LOG_ERR, "failed to register notification\n");
[8a2ae26]1496                og_dbi_close(dbi);
[5759db40]1497                return false; // Error al registrar notificacion
[3ec149c]1498        }
1499
1500        // Acciones posteriores
1501        idi = copiaParametro("idi",ptrTrama);
[c916af9]1502        dsk = copiaParametro("dsk",ptrTrama);
[3ec149c]1503        par = copiaParametro("par",ptrTrama);
1504        cpt = copiaParametro("cpt",ptrTrama);
1505        ipr = copiaParametro("ipr",ptrTrama);
1506
[7a8fae6]1507        res=actualizaCreacionImagen(dbi, idi, dsk, par, cpt, ipr, ido);
[0a73ecf7]1508
1509        liberaMemoria(idi);
1510        liberaMemoria(par);
1511        liberaMemoria(cpt);
1512        liberaMemoria(ipr);
[8a2ae26]1513        og_dbi_close(dbi);
[8c04716]1514
[8a2ae26]1515        if (!res)
[8c04716]1516                syslog(LOG_ERR, "Problem processing update\n");
[3ec149c]1517
[8a2ae26]1518        return res;
[3ec149c]1519}
1520// ________________________________________________________________________________________________________
1521// Función: actualizaCreacionImagen
1522//
1523//      Descripción:
1524//              Esta función actualiza la base de datos con el resultado de la creación de una imagen
1525//      Parámetros:
1526//              - db: Objeto base de datos (ya operativo)
1527//              - tbl: Objeto tabla
1528//              - idi: Identificador de la imagen
[c916af9]1529//              - dsk: Disco de donde se creó
[3ec149c]1530//              - par: Partición de donde se creó
1531//              - cpt: Código de partición
1532//              - ipr: Ip del repositorio
1533//              - ido: Identificador del ordenador modelo
1534//      Devuelve:
[5759db40]1535//              true: Si el proceso es correcto
1536//              false: En caso de ocurrir algún error
[3ec149c]1537// ________________________________________________________________________________________________________
[7a8fae6]1538bool actualizaCreacionImagen(struct og_dbi *dbi, char *idi, char *dsk,
[d647d81]1539                             char *par, char *cpt, char *ipr, char *ido)
1540{
[7a8fae6]1541        const char *msglog;
1542        dbi_result result;
[f029b3b]1543        int idr,ifs;
[3ec149c]1544
[5a0e8ec]1545        /* Toma identificador del repositorio correspondiente al ordenador modelo */
[7a8fae6]1546        result = dbi_conn_queryf(dbi->conn,
[c916af9]1547                        "SELECT repositorios.idrepositorio"
[5a0e8ec]1548                        "  FROM repositorios"
1549                        "  LEFT JOIN ordenadores USING (idrepositorio)"
1550                        " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido);
[3ec149c]1551
[7a8fae6]1552        if (!result) {
1553                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1554                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1555                       __func__, __LINE__, msglog);
[5759db40]1556                return false;
[3ec149c]1557        }
[7a8fae6]1558        if (!dbi_result_next_row(result)) {
1559                syslog(LOG_ERR,
1560                       "repository does not exist in database (%s:%d)\n",
1561                       __func__, __LINE__);
1562                dbi_result_free(result);
[5759db40]1563                return false;
[3ec149c]1564        }
[7a8fae6]1565        idr = dbi_result_get_uint(result, "idrepositorio");
1566        dbi_result_free(result);
[3ec149c]1567
1568        /* Toma identificador del perfilsoftware */
[7a8fae6]1569        result = dbi_conn_queryf(dbi->conn,
[c916af9]1570                        "SELECT idperfilsoft"
1571                        "  FROM ordenadores_particiones"
1572                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par);
[3ec149c]1573
[7a8fae6]1574        if (!result) {
1575                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1576                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1577                       __func__, __LINE__, msglog);
[5759db40]1578                return false;
[3ec149c]1579        }
[7a8fae6]1580        if (!dbi_result_next_row(result)) {
1581                syslog(LOG_ERR,
1582                       "software profile does not exist in database (%s:%d)\n",
1583                       __func__, __LINE__);
1584                dbi_result_free(result);
[5759db40]1585                return false;
[3ec149c]1586        }
[7a8fae6]1587        ifs = dbi_result_get_uint(result, "idperfilsoft");
1588        dbi_result_free(result);
[3ec149c]1589
1590        /* Actualizar los datos de la imagen */
[7a8fae6]1591        result = dbi_conn_queryf(dbi->conn,
[ab4ab39]1592                "UPDATE imagenes"
1593                "   SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
1594                "       idperfilsoft=%d, idrepositorio=%d,"
1595                "       fechacreacion=NOW(), revision=revision+1"
1596                " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi);
[3ec149c]1597
[7a8fae6]1598        if (!result) {
1599                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1600                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1601                       __func__, __LINE__, msglog);
[5759db40]1602                return false;
[3ec149c]1603        }
[7a8fae6]1604        dbi_result_free(result);
1605
[ab4ab39]1606        /* Actualizar los datos en el cliente */
[7a8fae6]1607        result = dbi_conn_queryf(dbi->conn,
[ab4ab39]1608                "UPDATE ordenadores_particiones"
[f029b3b]1609                "   SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
1610                "       fechadespliegue=NOW()"
[ab4ab39]1611                " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
[f029b3b]1612                idi, idi, ido, dsk, par);
[7a8fae6]1613        if (!result) {
1614                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1615                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1616                       __func__, __LINE__, msglog);
[5759db40]1617                return false;
[ab4ab39]1618        }
[7a8fae6]1619        dbi_result_free(result);
1620
[5759db40]1621        return true;
[3ec149c]1622}
1623// ________________________________________________________________________________________________________
[0a73ecf7]1624// Función: RESPUESTA_CrearImagenBasica
1625//
1626//      Descripción:
1627//              Respuesta del cliente al comando CrearImagenBasica
1628//      Parámetros:
1629//              - socket_c: Socket del cliente que envió el mensaje
1630//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1631//      Devuelve:
[5759db40]1632//              true: Si el proceso es correcto
1633//              false: En caso de ocurrir algún error
[0a73ecf7]1634// ________________________________________________________________________________________________________
[9baecf8]1635static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1636{
[9baecf8]1637        // La misma respuesta que la creación de imagen monolítica
1638        return RESPUESTA_CrearImagen(ptrTrama, cli);
[0a73ecf7]1639}
1640// ________________________________________________________________________________________________________
1641// Función: RESPUESTA_CrearSoftIncremental
1642//
1643//      Descripción:
1644//              Respuesta del cliente al comando crearImagenDiferencial
1645//      Parámetros:
1646//              - socket_c: Socket del cliente que envió el mensaje
1647//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1648//      Devuelve:
[5759db40]1649//              true: Si el proceso es correcto
1650//              false: En caso de ocurrir algún error
[0a73ecf7]1651// ________________________________________________________________________________________________________
[9baecf8]1652static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[0a73ecf7]1653{
1654        char *iph,*par,*ido,*idf;
1655        int ifs;
[f6322a5]1656        const char *msglog;
[8a2ae26]1657        struct og_dbi *dbi;
[f6322a5]1658        dbi_result result;
[0a73ecf7]1659
[8a2ae26]1660        dbi = og_dbi_open(&dbi_config);
1661        if (!dbi) {
1662                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1663                       __func__, __LINE__);
1664                return false;
1665        }
1666
[0a73ecf7]1667        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1668        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1669
[8a2ae26]1670        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
1671                og_dbi_close(dbi);
[0a73ecf7]1672                liberaMemoria(iph);
[8c04716]1673                liberaMemoria(ido);
1674                syslog(LOG_ERR, "failed to register notification\n");
1675                return false;
[0a73ecf7]1676        }
1677
1678        par = copiaParametro("par",ptrTrama);
1679
1680        /* Toma identificador del perfilsoftware creado por el inventario de software */
[f6322a5]1681        result = dbi_conn_queryf(dbi->conn,
1682                                 "SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s",
1683                                 ido, par);
[0a73ecf7]1684        liberaMemoria(iph);
1685        liberaMemoria(ido);     
1686        liberaMemoria(par);     
[8c04716]1687
[f6322a5]1688        if (!result) {
1689                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1690                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1691                       __func__, __LINE__, msglog);
[f6322a5]1692                og_dbi_close(dbi);
[5759db40]1693                return false;
[0a73ecf7]1694        }
[f6322a5]1695        if (!dbi_result_next_row(result)) {
1696                syslog(LOG_ERR,
1697                       "software profile does not exist in database (%s:%d)\n",
1698                       __func__, __LINE__);
1699                dbi_result_free(result);
1700                og_dbi_close(dbi);
[5759db40]1701                return false;
[0a73ecf7]1702        }
[f6322a5]1703        ifs = dbi_result_get_uint(result, "idperfilsoft");
1704        dbi_result_free(result);
[0a73ecf7]1705
1706        /* Actualizar los datos de la imagen */
[f6322a5]1707        idf = copiaParametro("idf", ptrTrama);
1708        result = dbi_conn_queryf(dbi->conn,
1709                                 "UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s",
1710                                 ifs, idf);
[0a73ecf7]1711        liberaMemoria(idf);     
[8c04716]1712
[f6322a5]1713        if (!result) {
1714                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1715                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1716                       __func__, __LINE__, msglog);
[f6322a5]1717                og_dbi_close(dbi);
[5759db40]1718                return false;
[0a73ecf7]1719        }
[f6322a5]1720        dbi_result_free(result);
1721
[8a2ae26]1722        og_dbi_close(dbi);
[f6322a5]1723
[5759db40]1724        return true;
[0a73ecf7]1725}
1726// ________________________________________________________________________________________________________
[3ec149c]1727// Función: RESPUESTA_RestaurarImagen
1728//
1729//      Descripción:
1730//              Respuesta del cliente al comando RestaurarImagen
1731//      Parámetros:
1732//              - socket_c: Socket del cliente que envió el mensaje
1733//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1734//      Devuelve:
[5759db40]1735//              true: Si el proceso es correcto
1736//              false: En caso de ocurrir algún error
[3ec149c]1737// ________________________________________________________________________________________________________
[0a73ecf7]1738//
[9baecf8]1739static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli)
[0a73ecf7]1740{
[c0a46e2]1741        bool res;
[82e5b6c]1742        char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg;
[8a2ae26]1743        struct og_dbi *dbi;
[3ec149c]1744
[8a2ae26]1745        dbi = og_dbi_open(&dbi_config);
1746        if (!dbi) {
1747                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1748                       __func__, __LINE__);
1749                return false;
1750        }
1751
[3ec149c]1752        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1753        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1754
[8a2ae26]1755        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
1756                og_dbi_close(dbi);
[0a73ecf7]1757                liberaMemoria(iph);
[8c04716]1758                liberaMemoria(ido);
1759                syslog(LOG_ERR, "failed to register notification\n");
1760                return false;
[3ec149c]1761        }
1762
1763        // Acciones posteriores
1764        idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen
[c916af9]1765        dsk = copiaParametro("dsk",ptrTrama); // Número de disco
[3ec149c]1766        par = copiaParametro("par",ptrTrama); // Número de partición
1767        ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido
[82e5b6c]1768        cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos
1769        if(cfg){
[e052fdc]1770                actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador
[82e5b6c]1771                liberaMemoria(cfg);     
1772        }
[e052fdc]1773        res=actualizaRestauracionImagen(dbi, idi, dsk, par, ido, ifs);
[0a73ecf7]1774       
1775        liberaMemoria(iph);
[82e5b6c]1776        liberaMemoria(ido);
[0a73ecf7]1777        liberaMemoria(idi);
1778        liberaMemoria(par);
1779        liberaMemoria(ifs);
[8a2ae26]1780        og_dbi_close(dbi);
[0a73ecf7]1781
[8a2ae26]1782        if(!res)
[8c04716]1783                syslog(LOG_ERR, "Problem after restoring image\n");
[3ec149c]1784
[8a2ae26]1785        return res;
[3ec149c]1786}
1787// ________________________________________________________________________________________________________
[0a73ecf7]1788//
1789// Función: RESPUESTA_RestaurarImagenBasica
1790//
1791//      Descripción:
1792//              Respuesta del cliente al comando RestaurarImagen
1793//      Parámetros:
1794//              - socket_c: Socket del cliente que envió el mensaje
1795//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1796//      Devuelve:
[5759db40]1797//              true: Si el proceso es correcto
1798//              false: En caso de ocurrir algún error
[0a73ecf7]1799// ________________________________________________________________________________________________________
1800//
[9baecf8]1801static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1802{
[9baecf8]1803        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[0a73ecf7]1804}
1805// ________________________________________________________________________________________________________
1806// Función: RESPUESTA_RestaurarSoftIncremental
1807//
1808//      Descripción:
1809//              Respuesta del cliente al comando RestaurarSoftIncremental
1810//      Parámetros:
1811//              - socket_c: Socket del cliente que envió el mensaje
1812//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1813//      Devuelve:
[5759db40]1814//              true: Si el proceso es correcto
1815//              false: En caso de ocurrir algún error
[0a73ecf7]1816// ________________________________________________________________________________________________________
[9baecf8]1817static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1818{
[9baecf8]1819        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[0a73ecf7]1820}
1821// ________________________________________________________________________________________________________
[3ec149c]1822// Función: actualizaRestauracionImagen
1823//
1824//      Descripción:
[0a73ecf7]1825//              Esta función actualiza la base de datos con el resultado de la restauración de una imagen
[3ec149c]1826//      Parámetros:
1827//              - db: Objeto base de datos (ya operativo)
1828//              - tbl: Objeto tabla
1829//              - idi: Identificador de la imagen
[c916af9]1830//              - dsk: Disco de donde se restauró
[3ec149c]1831//              - par: Partición de donde se restauró
1832//              - ido: Identificador del cliente donde se restauró
1833//              - ifs: Identificador del perfil software contenido      en la imagen
1834//      Devuelve:
[5759db40]1835//              true: Si el proceso es correcto
1836//              false: En caso de ocurrir algún error
[3ec149c]1837// ________________________________________________________________________________________________________
[e052fdc]1838bool actualizaRestauracionImagen(struct og_dbi *dbi, char *idi,
[d647d81]1839                                 char *dsk, char *par, char *ido, char *ifs)
1840{
[e052fdc]1841        const char *msglog;
1842        dbi_result result;
[3ec149c]1843
1844        /* Actualizar los datos de la imagen */
[e052fdc]1845        result = dbi_conn_queryf(dbi->conn,
[c916af9]1846                        "UPDATE ordenadores_particiones"
[84fa8d6]1847                        "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
[c870c84]1848                        "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
1849                        "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
[dbbe689]1850                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par);
[3ec149c]1851
[e052fdc]1852        if (!result) {
1853                dbi_conn_error(dbi->conn, &msglog);
[8c04716]1854                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1855                       __func__, __LINE__, msglog);
[5759db40]1856                return false;
[3ec149c]1857        }
[e052fdc]1858        dbi_result_free(result);
1859
[5759db40]1860        return true;
[3ec149c]1861}
1862// ________________________________________________________________________________________________________
1863// Función: RESPUESTA_EjecutarScript
1864//
1865//      Descripción:
1866//              Respuesta del cliente al comando EjecutarScript
1867//      Parámetros:
1868//              - socket_c: Socket del cliente que envió el mensaje
1869//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1870//      Devuelve:
[5759db40]1871//              true: Si el proceso es correcto
1872//              false: En caso de ocurrir algún error
[3ec149c]1873// ________________________________________________________________________________________________________
[9baecf8]1874static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
[7224a0a]1875{
1876        char *iph, *ido,*cfg;
[8a2ae26]1877        struct og_dbi *dbi;
[36b7cf4]1878        bool res = true;
[3ec149c]1879
[8a2ae26]1880        dbi = og_dbi_open(&dbi_config);
1881        if (!dbi) {
1882                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1883                       __func__, __LINE__);
1884                return false;
1885        }
1886
[3ec149c]1887        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1888        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1889
[8a2ae26]1890        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
1891                og_dbi_close(dbi);
[0a73ecf7]1892                liberaMemoria(iph);
[8c04716]1893                liberaMemoria(ido);
1894                syslog(LOG_ERR, "failed to register notification\n");
1895                return false;
[3ec149c]1896        }
[0a73ecf7]1897       
[7224a0a]1898        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
[46f7d6f]1899        if(cfg){
[e052fdc]1900                res = actualizaConfiguracion(dbi, cfg, atoi(ido)); // Actualiza la configuración del ordenador
[46f7d6f]1901                liberaMemoria(cfg);     
1902        }
[7224a0a]1903
[0a73ecf7]1904        liberaMemoria(iph);
[7224a0a]1905        liberaMemoria(ido);
[8a2ae26]1906        og_dbi_close(dbi);
[46f7d6f]1907
[8a2ae26]1908        if (!res)
[36b7cf4]1909                syslog(LOG_ERR, "Problem updating client configuration\n");
1910
[8a2ae26]1911        return res;
[3ec149c]1912}
1913// ________________________________________________________________________________________________________
1914// Función: RESPUESTA_InventarioHardware
1915//
1916//      Descripción:
1917//              Respuesta del cliente al comando InventarioHardware
1918//      Parámetros:
1919//              - socket_c: Socket del cliente que envió el mensaje
1920//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1921//      Devuelve:
[5759db40]1922//              true: Si el proceso es correcto
1923//              false: En caso de ocurrir algún error
[3ec149c]1924// ________________________________________________________________________________________________________
[9baecf8]1925static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]1926{
[c0a46e2]1927        bool res;
[3ec149c]1928        char *iph, *ido, *idc, *npc, *hrd, *buffer;
[8a2ae26]1929        struct og_dbi *dbi;
[3ec149c]1930
[8a2ae26]1931        dbi = og_dbi_open(&dbi_config);
1932        if (!dbi) {
1933                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1934                       __func__, __LINE__);
1935                return false;
1936        }
1937
[3ec149c]1938        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente
1939        ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente
1940
[8a2ae26]1941        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
1942                og_dbi_close(dbi);
[0a73ecf7]1943                liberaMemoria(iph);
[8c04716]1944                liberaMemoria(ido);
1945                syslog(LOG_ERR, "failed to register notification\n");
1946                return false;
[3ec149c]1947        }
1948        // Lee archivo de inventario enviado anteriormente
1949        hrd = copiaParametro("hrd",ptrTrama);
1950        buffer = rTrim(leeArchivo(hrd));
[0a73ecf7]1951       
1952        npc = copiaParametro("npc",ptrTrama);
1953        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro
1954       
1955        if (buffer)
[54bd82d]1956                res=actualizaHardware(dbi, buffer, ido, npc, idc);
[fe20a3c]1957        else
1958                res = false;
1959
[0a73ecf7]1960        liberaMemoria(iph);
1961        liberaMemoria(ido);                     
1962        liberaMemoria(npc);                     
1963        liberaMemoria(idc);             
1964        liberaMemoria(buffer);         
[8a2ae26]1965        og_dbi_close(dbi);
1966
1967        if (!res)
[8c04716]1968                syslog(LOG_ERR, "Problem updating client configuration\n");
[8a2ae26]1969
1970        return res;
[3ec149c]1971}
1972// ________________________________________________________________________________________________________
1973// Función: actualizaHardware
1974//
1975//              Descripción:
1976//                      Actualiza la base de datos con la configuracion hardware del cliente
1977//              Parámetros:
1978//                      - db: Objeto base de datos (ya operativo)
1979//                      - tbl: Objeto tabla
1980//                      - hrd: cadena con el inventario hardware
1981//                      - ido: Identificador del ordenador
1982//                      - npc: Nombre del ordenador
1983//                      - idc: Identificador del centro o Unidad organizativa
1984// ________________________________________________________________________________________________________
[0a73ecf7]1985//
[54bd82d]1986bool actualizaHardware(struct og_dbi *dbi, char *hrd, char *ido, char *npc,
[d647d81]1987                       char *idc)
[0a73ecf7]1988{
[54bd82d]1989        const char *msglog;
[3ec149c]1990        int idtipohardware, idperfilhard;
1991        int lon, i, j, aux;
[fc480f2]1992        bool retval;
[0a73ecf7]1993        char *whard;
[3ec149c]1994        int tbidhardware[MAXHARDWARE];
[54bd82d]1995        char *tbHardware[MAXHARDWARE],*dualHardware[2], strInt[LONINT], *idhardwares;
1996        dbi_result result;
[3ec149c]1997
1998        /* Toma Centro (Unidad Organizativa) */
[54bd82d]1999        result = dbi_conn_queryf(dbi->conn,
2000                                 "SELECT idperfilhard FROM ordenadores WHERE idordenador=%s",
2001                                 ido);
2002        if (!result) {
2003                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2004                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2005                       __func__, __LINE__, msglog);
[5759db40]2006                return false;
[3ec149c]2007        }
[54bd82d]2008        if (!dbi_result_next_row(result)) {
2009                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
2010                       __func__, __LINE__);
2011                dbi_result_free(result);
[5759db40]2012                return false;
[3ec149c]2013        }
[54bd82d]2014        idperfilhard = dbi_result_get_uint(result, "idperfilhard");
2015        dbi_result_free(result);
2016
[0a73ecf7]2017        whard=escaparCadena(hrd); // Codificar comillas simples
2018        if(!whard)
[5759db40]2019                return false;
[3ec149c]2020        /* Recorre componentes hardware*/
[0a73ecf7]2021        lon = splitCadena(tbHardware, whard, '\n');
[3ec149c]2022        if (lon > MAXHARDWARE)
2023                lon = MAXHARDWARE; // Limita el número de componentes hardware
2024        /*
2025         for (i=0;i<lon;i++){
2026         sprintf(msglog,"Linea de inventario: %s",tbHardware[i]);
[5759db40]2027         RegistraLog(msglog,false);
[3ec149c]2028         }
2029         */
2030        for (i = 0; i < lon; i++) {
2031                splitCadena(dualHardware, rTrim(tbHardware[i]), '=');
2032                //sprintf(msglog,"nemonico: %s",dualHardware[0]);
[5759db40]2033                //RegistraLog(msglog,false);
[3ec149c]2034                //sprintf(msglog,"valor: %s",dualHardware[1]);
[5759db40]2035                //RegistraLog(msglog,false);
[54bd82d]2036                result = dbi_conn_queryf(dbi->conn,
2037                                         "SELECT idtipohardware,descripcion FROM tipohardwares WHERE nemonico='%s'",
2038                                         dualHardware[0]);
2039                if (!result) {
2040                        dbi_conn_error(dbi->conn, &msglog);
[8c04716]2041                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2042                               __func__, __LINE__, msglog);
[5759db40]2043                        return false;
[3ec149c]2044                }
[54bd82d]2045                if (!dbi_result_next_row(result)) { //  Tipo de Hardware NO existente
2046                        dbi_result_free(result);
[5759db40]2047                        return false;
[3ec149c]2048                } else { //  Tipo de Hardware Existe
[54bd82d]2049                        idtipohardware = dbi_result_get_uint(result, "idtipohardware");
2050                        dbi_result_free(result);
[3ec149c]2051
[54bd82d]2052                        result = dbi_conn_queryf(dbi->conn,
2053                                                 "SELECT idhardware FROM hardwares WHERE idtipohardware=%d AND descripcion='%s'",
2054                                                 idtipohardware, dualHardware[1]);
[3ec149c]2055
[54bd82d]2056                        if (!result) {
2057                                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2058                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2059                                       __func__, __LINE__, msglog);
[5759db40]2060                                return false;
[3ec149c]2061                        }
2062
[54bd82d]2063                        if (!dbi_result_next_row(result)) { //  Hardware NO existente
2064                                dbi_result_free(result);
2065                                result = dbi_conn_queryf(dbi->conn,
2066                                                        "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) "
[3ec149c]2067                                                        " VALUES(%d,'%s',%s,0)", idtipohardware,
2068                                                dualHardware[1], idc);
[54bd82d]2069                                if (!result) {
2070                                        dbi_conn_error(dbi->conn, &msglog);
[8c04716]2071                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2072                                               __func__, __LINE__, msglog);
[5759db40]2073                                        return false;
[3ec149c]2074                                }
[54bd82d]2075
2076                                // Recupera el identificador del hardware
2077                                tbidhardware[i] = dbi_conn_sequence_last(dbi->conn, NULL);
[3ec149c]2078                        } else {
[54bd82d]2079                                tbidhardware[i] = dbi_result_get_uint(result, "idhardware");
[3ec149c]2080                        }
[54bd82d]2081                        dbi_result_free(result);
[3ec149c]2082                }
2083        }
2084        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2085
2086        for (i = 0; i < lon - 1; i++) {
2087                for (j = i + 1; j < lon; j++) {
2088                        if (tbidhardware[i] > tbidhardware[j]) {
2089                                aux = tbidhardware[i];
2090                                tbidhardware[i] = tbidhardware[j];
2091                                tbidhardware[j] = aux;
2092                        }
2093                }
2094        }
2095        /* Crea cadena de identificadores de componentes hardware separados por coma */
2096        sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2097        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2098        idhardwares = reservaMemoria(sizeof(aux) * lon + lon);
2099        if (idhardwares == NULL) {
[8c04716]2100                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[5759db40]2101                return false;
[3ec149c]2102        }
2103        aux = sprintf(idhardwares, "%d", tbidhardware[0]);
2104        for (i = 1; i < lon; i++)
2105                aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]);
2106
[54bd82d]2107        if (!cuestionPerfilHardware(dbi, idc, ido, idperfilhard, idhardwares,
[3ec149c]2108                        npc, tbidhardware, lon)) {
[8c04716]2109                syslog(LOG_ERR, "Problem updating client hardware\n");
[5759db40]2110                retval=false;
[3ec149c]2111        }
[fc480f2]2112        else {
[5759db40]2113                retval=true;
[fc480f2]2114        }
[0a73ecf7]2115        liberaMemoria(whard);
[fc480f2]2116        liberaMemoria(idhardwares);
2117        return (retval);
[3ec149c]2118}
2119// ________________________________________________________________________________________________________
2120// Función: cuestionPerfilHardware
2121//
2122//              Descripción:
2123//                      Comprueba existencia de perfil hardware y actualización de éste para el ordenador
2124//              Parámetros:
2125//                      - db: Objeto base de datos (ya operativo)
2126//                      - tbl: Objeto tabla
2127//                      - idc: Identificador de la Unidad organizativa donde se encuentra el cliente
2128//                      - ido: Identificador del ordenador
2129//                      - tbidhardware: Identificador del tipo de hardware
2130//                      - con: Número de componentes detectados para configurar un el perfil hardware
2131//                      - npc: Nombre del cliente
2132// ________________________________________________________________________________________________________
[54bd82d]2133bool cuestionPerfilHardware(struct og_dbi *dbi, char *idc, char *ido,
[d647d81]2134                int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware,
[3ec149c]2135                int lon)
2136{
[54bd82d]2137        const char *msglog;
2138        dbi_result result;
[3ec149c]2139        int i;
2140        int nwidperfilhard;
2141
2142        // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados
[54bd82d]2143        result = dbi_conn_queryf(dbi->conn,
2144                "SELECT idperfilhard FROM"
[3ec149c]2145                " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard,"
2146                "       group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )"
2147                "       ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares"
2148                " FROM  perfileshard_hardwares"
2149                " GROUP BY perfileshard_hardwares.idperfilhard) AS temp"
2150                " WHERE idhardwares LIKE '%s'", idhardwares);
[8c04716]2151
[54bd82d]2152        if (!result) {
2153                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2154                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2155                       __func__, __LINE__, msglog);
[5759db40]2156                return false;
[3ec149c]2157        }
[54bd82d]2158        if (!dbi_result_next_row(result)) {
2159                // No existe un perfil hardware con esos componentes de componentes hardware, lo crea
2160                dbi_result_free(result);
2161                result = dbi_conn_queryf(dbi->conn,
2162                                "INSERT perfileshard  (descripcion,idcentro,grupoid)"
[df052e1]2163                                " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc);
[54bd82d]2164                if (!result) {
2165                        dbi_conn_error(dbi->conn, &msglog);
2166                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2167                               __func__, __LINE__, msglog);
[5759db40]2168                        return false;
[3ec149c]2169                }
[54bd82d]2170                dbi_result_free(result);
2171
[3ec149c]2172                // Recupera el identificador del nuevo perfil hardware
[54bd82d]2173                nwidperfilhard = dbi_conn_sequence_last(dbi->conn, NULL);
2174
[3ec149c]2175                // Crea la relación entre perfiles y componenetes hardware
2176                for (i = 0; i < lon; i++) {
[54bd82d]2177                        result = dbi_conn_queryf(dbi->conn,
2178                                        "INSERT perfileshard_hardwares  (idperfilhard,idhardware)"
[3ec149c]2179                                                " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]);
[54bd82d]2180                        if (!result) {
2181                                dbi_conn_error(dbi->conn, &msglog);
2182                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2183                                       __func__, __LINE__, msglog);
[5759db40]2184                                return false;
[3ec149c]2185                        }
[54bd82d]2186                        dbi_result_free(result);
[3ec149c]2187                }
2188        } else { // Existe un perfil con todos esos componentes
[54bd82d]2189                nwidperfilhard = dbi_result_get_uint(result, "idperfilhard");
2190                dbi_result_free(result);
[3ec149c]2191        }
2192        if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles
2193                // Actualiza el identificador del perfil hardware del ordenador
[54bd82d]2194                result = dbi_conn_queryf(dbi->conn,
2195                        "UPDATE ordenadores SET idperfilhard=%d"
[3ec149c]2196                        " WHERE idordenador=%s", nwidperfilhard, ido);
[54bd82d]2197                if (!result) {
2198                        dbi_conn_error(dbi->conn, &msglog);
2199                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2200                               __func__, __LINE__, msglog);
[5759db40]2201                        return false;
[3ec149c]2202                }
[54bd82d]2203                dbi_result_free(result);
[3ec149c]2204        }
2205        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
[54bd82d]2206        result = dbi_conn_queryf(dbi->conn,
2207                "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN "
[3ec149c]2208                " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN"
2209                " (SELECT DISTINCT idperfilhard from ordenadores))");
[54bd82d]2210        if (!result) {
2211                dbi_conn_error(dbi->conn, &msglog);
2212                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2213                       __func__, __LINE__, msglog);
[5759db40]2214                return false;
[3ec149c]2215        }
[54bd82d]2216        dbi_result_free(result);
[3ec149c]2217
2218        /* Eliminar Perfiles hardware que quedan húerfanos */
[54bd82d]2219        result = dbi_conn_queryf(dbi->conn,
2220                        "DELETE FROM perfileshard WHERE idperfilhard NOT IN"
[fc480f2]2221                        " (SELECT DISTINCT idperfilhard FROM ordenadores)");
[54bd82d]2222        if (!result) {
2223                dbi_conn_error(dbi->conn, &msglog);
2224                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2225                       __func__, __LINE__, msglog);
[5759db40]2226                return false;
[3ec149c]2227        }
[54bd82d]2228        dbi_result_free(result);
2229
[3ec149c]2230        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
[54bd82d]2231        result = dbi_conn_queryf(dbi->conn,
2232                        "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN"
[fc480f2]2233                        " (SELECT idperfilhard FROM perfileshard)");
[54bd82d]2234        if (!result) {
2235                dbi_conn_error(dbi->conn, &msglog);
2236                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2237                       __func__, __LINE__, msglog);
[5759db40]2238                return false;
[3ec149c]2239        }
[54bd82d]2240        dbi_result_free(result);
2241
[5759db40]2242        return true;
[3ec149c]2243}
2244// ________________________________________________________________________________________________________
2245// Función: RESPUESTA_InventarioSoftware
2246//
2247//      Descripción:
2248//              Respuesta del cliente al comando InventarioSoftware
2249//      Parámetros:
2250//              - socket_c: Socket del cliente que envió el mensaje
2251//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2252//      Devuelve:
[5759db40]2253//              true: Si el proceso es correcto
2254//              false: En caso de ocurrir algún error
[3ec149c]2255// ________________________________________________________________________________________________________
[9baecf8]2256static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli)
[d647d81]2257{
[c0a46e2]2258        bool res;
[3ec149c]2259        char *iph, *ido, *npc, *idc, *par, *sft, *buffer;
[8a2ae26]2260        struct og_dbi *dbi;
[3ec149c]2261
[8a2ae26]2262        dbi = og_dbi_open(&dbi_config);
2263        if (!dbi) {
2264                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2265                       __func__, __LINE__);
2266                return false;
2267        }
2268
[3ec149c]2269        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2270        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2271
[8a2ae26]2272        if (!respuestaEstandar(ptrTrama, iph, ido, dbi)) {
2273                og_dbi_close(dbi);
[0a73ecf7]2274                liberaMemoria(iph);
[8c04716]2275                liberaMemoria(ido);
2276                syslog(LOG_ERR, "failed to register notification\n");
2277                return false;
[3ec149c]2278        }
[8c04716]2279
[0a73ecf7]2280        npc = copiaParametro("npc",ptrTrama);
2281        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro 
[3ec149c]2282        par = copiaParametro("par",ptrTrama);
2283        sft = copiaParametro("sft",ptrTrama);
2284
2285        buffer = rTrim(leeArchivo(sft));
[0a73ecf7]2286        if (buffer)
[e052fdc]2287                res=actualizaSoftware(dbi, buffer, par, ido, npc, idc);
[fe20a3c]2288        else
2289                res = false;
[0a73ecf7]2290
2291        liberaMemoria(iph);
2292        liberaMemoria(ido);     
2293        liberaMemoria(npc);     
2294        liberaMemoria(idc);     
2295        liberaMemoria(par);     
2296        liberaMemoria(sft);     
[8a2ae26]2297        og_dbi_close(dbi);
[0a73ecf7]2298
[8a2ae26]2299        if (!res)
[8c04716]2300                syslog(LOG_ERR, "cannot update software\n");
2301
[8a2ae26]2302        return res;
[3ec149c]2303}
2304// ________________________________________________________________________________________________________
2305// Función: actualizaSoftware
2306//
2307//      Descripción:
2308//              Actualiza la base de datos con la configuración software del cliente
2309//      Parámetros:
2310//              - db: Objeto base de datos (ya operativo)
2311//              - tbl: Objeto tabla
2312//              - sft: cadena con el inventario software
2313//              - par: Número de la partición
2314//              - ido: Identificador del ordenador del cliente en la tabla
2315//              - npc: Nombre del ordenador
2316//              - idc: Identificador del centro o Unidad organizativa
2317//      Devuelve:
[5759db40]2318//              true: Si el proceso es correcto
2319//              false: En caso de ocurrir algún error
[38e2328]2320//
2321//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
[3ec149c]2322// ________________________________________________________________________________________________________
[e052fdc]2323bool actualizaSoftware(struct og_dbi *dbi, char *sft, char *par,char *ido,
[d647d81]2324                       char *npc, char *idc)
[0a73ecf7]2325{
[38e2328]2326        int i, j, lon, aux, idperfilsoft, idnombreso;
[fc480f2]2327        bool retval;
[0a73ecf7]2328        char *wsft;
[3ec149c]2329        int tbidsoftware[MAXSOFTWARE];
[e052fdc]2330        char *tbSoftware[MAXSOFTWARE], strInt[LONINT], *idsoftwares;
2331        const char *msglog;
2332        dbi_result result;
[3ec149c]2333
2334        /* Toma Centro (Unidad Organizativa) y perfil software */
[e052fdc]2335        result = dbi_conn_queryf(dbi->conn,
2336                "SELECT idperfilsoft,numpar"
[3ec149c]2337                " FROM ordenadores_particiones"
2338                " WHERE idordenador=%s", ido);
[e052fdc]2339        if (!result) {
2340                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2341                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2342                       __func__, __LINE__, msglog);
[5759db40]2343                return false;
[3ec149c]2344        }
2345        idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software
[e052fdc]2346        while (dbi_result_next_row(result)) {
2347                aux = dbi_result_get_uint(result, "numpar");
[3ec149c]2348                if (aux == atoi(par)) { // Se encuentra la partición
[e052fdc]2349                        idperfilsoft = dbi_result_get_uint(result, "idperfilsoft");
[3ec149c]2350                        break;
2351                }
2352        }
[e052fdc]2353        dbi_result_free(result);
[0a73ecf7]2354        wsft=escaparCadena(sft); // Codificar comillas simples
2355        if(!wsft)
[5759db40]2356                return false;
[3ec149c]2357
2358        /* Recorre componentes software*/
[0a73ecf7]2359        lon = splitCadena(tbSoftware, wsft, '\n');
2360
[3ec149c]2361        if (lon == 0)
[5759db40]2362                return true; // No hay lineas que procesar
[3ec149c]2363        if (lon > MAXSOFTWARE)
2364                lon = MAXSOFTWARE; // Limita el número de componentes software
2365
[fe20a3c]2366        idnombreso = 0;
[3ec149c]2367        for (i = 0; i < lon; i++) {
[38e2328]2368                // Primera línea es el sistema operativo: se obtiene identificador
2369                if (i == 0) {
[e052fdc]2370                        idnombreso = checkDato(dbi, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso");
[38e2328]2371                        continue;
2372                }
2373
[e052fdc]2374                result = dbi_conn_queryf(dbi->conn,
[3ec149c]2375                                "SELECT idsoftware FROM softwares WHERE descripcion ='%s'",
2376                                rTrim(tbSoftware[i]));
[e052fdc]2377                if (!result) {
2378                        dbi_conn_error(dbi->conn, &msglog);
[8c04716]2379                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2380                               __func__, __LINE__, msglog);
[5759db40]2381                        return false;
[3ec149c]2382                }
2383
[e052fdc]2384                if (!dbi_result_next_row(result)) {
2385                        dbi_result_free(result);
2386                        result = dbi_conn_queryf(dbi->conn,
2387                                                "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)"
[3ec149c]2388                                                " VALUES(2,'%s',%s,0)", tbSoftware[i], idc);
[e052fdc]2389                        if (!result) { // Error al insertar
2390                                dbi_conn_error(dbi->conn, &msglog);
[9cf5bf7]2391                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2392                                       __func__, __LINE__, msglog);
[5759db40]2393                                return false;
[3ec149c]2394                        }
[e052fdc]2395
[3ec149c]2396                        // Recupera el identificador del software
[e052fdc]2397                        tbidsoftware[i] = dbi_conn_sequence_last(dbi->conn, NULL);
[3ec149c]2398                } else {
[e052fdc]2399                        tbidsoftware[i] = dbi_result_get_uint(result, "idsoftware");
[3ec149c]2400                }
[9cf5bf7]2401                dbi_result_free(result);
[3ec149c]2402        }
2403
2404        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2405
2406        for (i = 0; i < lon - 1; i++) {
2407                for (j = i + 1; j < lon; j++) {
2408                        if (tbidsoftware[i] > tbidsoftware[j]) {
2409                                aux = tbidsoftware[i];
2410                                tbidsoftware[i] = tbidsoftware[j];
2411                                tbidsoftware[j] = aux;
2412                        }
2413                }
2414        }
2415        /* Crea cadena de identificadores de componentes software separados por coma */
2416        sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2417        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2418        idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon);
2419        if (idsoftwares == NULL) {
[8c04716]2420                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[5759db40]2421                return false;
[3ec149c]2422        }
2423        aux = sprintf(idsoftwares, "%d", tbidsoftware[0]);
2424        for (i = 1; i < lon; i++)
2425                aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]);
2426
2427        // Comprueba existencia de perfil software y actualización de éste para el ordenador
[e052fdc]2428        if (!cuestionPerfilSoftware(dbi, idc, ido, idperfilsoft, idnombreso, idsoftwares,
[3ec149c]2429                        npc, par, tbidsoftware, lon)) {
[8c04716]2430                syslog(LOG_ERR, "cannot update software\n");
[e052fdc]2431                og_info((char *)msglog);
[5759db40]2432                retval=false;
[3ec149c]2433        }
[fc480f2]2434        else {
[5759db40]2435                retval=true;
[fc480f2]2436        }
[0a73ecf7]2437        liberaMemoria(wsft);
[fc480f2]2438        liberaMemoria(idsoftwares);
2439        return (retval);
[3ec149c]2440}
2441// ________________________________________________________________________________________________________
2442// Función: CuestionPerfilSoftware
2443//
2444//      Parámetros:
2445//              - db: Objeto base de datos (ya operativo)
2446//              - tbl: Objeto tabla
2447//              - idcentro: Identificador del centro en la tabla
2448//              - ido: Identificador del ordenador del cliente en la tabla
[38e2328]2449//              - idnombreso: Identificador del sistema operativo
[3ec149c]2450//              - idsoftwares: Cadena con los identificadores de componentes software separados por comas
2451//              - npc: Nombre del ordenador del cliente
2452//              - particion: Número de la partición
2453//              - tbidsoftware: Array con los identificadores de componentes software
2454//              - lon: Número de componentes
2455//      Devuelve:
[5759db40]2456//              true: Si el proceso es correcto
2457//              false: En caso de ocurrir algún error
[38e2328]2458//
2459//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
2460//_________________________________________________________________________________________________________
[e052fdc]2461bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido,
[d647d81]2462                            int idperfilsoftware, int idnombreso,
2463                            char *idsoftwares, char *npc, char *par,
2464                            int *tbidsoftware, int lon)
2465{
[3ec149c]2466        int i, nwidperfilsoft;
[e052fdc]2467        const char *msglog;
2468        dbi_result result;
[3ec149c]2469
2470        // Busca perfil soft del ordenador que contenga todos los componentes software encontrados
[e052fdc]2471        result = dbi_conn_queryf(dbi->conn,
2472                "SELECT idperfilsoft FROM"
[3ec149c]2473                " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft,"
2474                "       group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )"
2475                "       ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares"
2476                " FROM  perfilessoft_softwares"
2477                " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp"
2478                " WHERE idsoftwares LIKE '%s'", idsoftwares);
[8c04716]2479
[e052fdc]2480        if (!result) {
2481                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2482                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2483                       __func__, __LINE__, msglog);
[5759db40]2484                return false;
[3ec149c]2485        }
[e052fdc]2486        if (!dbi_result_next_row(result)) { // No existe un perfil software con esos componentes de componentes software, lo crea
2487                dbi_result_free(result);
2488                result = dbi_conn_queryf(dbi->conn,
2489                                "INSERT perfilessoft  (descripcion, idcentro, grupoid, idnombreso)"
[38e2328]2490                                " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso);
[e052fdc]2491                if (!result) {
2492                        dbi_conn_error(dbi->conn, &msglog);
2493                        og_info((char *)msglog);
[5759db40]2494                        return false;
[3ec149c]2495                }
[e052fdc]2496
2497                dbi_result_free(result);
[3ec149c]2498                // Recupera el identificador del nuevo perfil software
[e052fdc]2499                nwidperfilsoft = dbi_conn_sequence_last(dbi->conn, NULL);
2500
[3ec149c]2501                // Crea la relación entre perfiles y componenetes software
2502                for (i = 0; i < lon; i++) {
[e052fdc]2503                        result = dbi_conn_queryf(dbi->conn,
2504                                                "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)"
[3ec149c]2505                                                " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]);
[e052fdc]2506                        if (!result) {
2507                                dbi_conn_error(dbi->conn, &msglog);
2508                                og_info((char *)msglog);
[5759db40]2509                                return false;
[3ec149c]2510                        }
[e052fdc]2511                        dbi_result_free(result);
[3ec149c]2512                }
2513        } else { // Existe un perfil con todos esos componentes
[e052fdc]2514                nwidperfilsoft = dbi_result_get_uint(result, "idperfilsoft");
2515                dbi_result_free(result);
[3ec149c]2516        }
2517
2518        if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
2519                // Actualiza el identificador del perfil software del ordenador
[e052fdc]2520                result = dbi_conn_queryf(dbi->conn,
2521                                "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
[fc480f2]2522                                " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
[e052fdc]2523                if (!result) { // Error al insertar
2524                        dbi_conn_error(dbi->conn, &msglog);
2525                        og_info((char *)msglog);
[5759db40]2526                        return false;
[3ec149c]2527                }
[e052fdc]2528                dbi_result_free(result);
[3ec149c]2529        }
2530
2531        /* DEPURACIÓN DE PERFILES SOFTWARE */
2532
2533         /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
[e052fdc]2534        result = dbi_conn_queryf(dbi->conn,
2535                "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\
[3ec149c]2536                " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\
2537                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\
2538                " (SELECT DISTINCT idperfilsoft from imagenes))");
[e052fdc]2539        if (!result) {
2540                dbi_conn_error(dbi->conn, &msglog);
2541                og_info((char *)msglog);
[5759db40]2542                return false;
[3ec149c]2543        }
[e052fdc]2544        dbi_result_free(result),
[3ec149c]2545        /* Eliminar Perfiles software que quedan húerfanos */
[e052fdc]2546        result = dbi_conn_queryf(dbi->conn,
2547                "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN"
[3ec149c]2548                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\
2549                " AND  idperfilsoft NOT IN"\
2550                " (SELECT DISTINCT idperfilsoft from imagenes)");
[e052fdc]2551        if (!result) {
2552                dbi_conn_error(dbi->conn, &msglog);
2553                og_info((char *)msglog);
[5759db40]2554                return false;
[3ec149c]2555        }
[e052fdc]2556        dbi_result_free(result),
2557
[3ec149c]2558        /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
[e052fdc]2559        result = dbi_conn_queryf(dbi->conn,
2560                        "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN"
[fc480f2]2561                        " (SELECT idperfilsoft from perfilessoft)");
[e052fdc]2562        if (!result) {
2563                dbi_conn_error(dbi->conn, &msglog);
2564                og_info((char *)msglog);
[5759db40]2565                return false;
[3ec149c]2566        }
[e052fdc]2567        dbi_result_free(result);
2568
[5759db40]2569        return true;
[3ec149c]2570}
2571// ________________________________________________________________________________________________________
2572// Función: enviaArchivo
2573//
2574//      Descripción:
2575//              Envia un archivo por la red, por bloques
2576//      Parámetros:
2577//              - socket_c: Socket del cliente que envió el mensaje
2578//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2579//      Devuelve:
[5759db40]2580//              true: Si el proceso es correcto
2581//              false: En caso de ocurrir algún error
[3ec149c]2582// ________________________________________________________________________________________________________
[9baecf8]2583static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli)
[d647d81]2584{
[9baecf8]2585        int socket_c = og_client_socket(cli);
[3ec149c]2586        char *nfl;
2587
2588        // Toma parámetros
2589        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
[ba03878]2590        if (!sendArchivo(&socket_c, nfl)) {
[0a73ecf7]2591                liberaMemoria(nfl);
[8c04716]2592                syslog(LOG_ERR, "Problem sending file\n");
[5759db40]2593                return false;
[3ec149c]2594        }
[0a73ecf7]2595        liberaMemoria(nfl);
[5759db40]2596        return true;
[3ec149c]2597}
2598// ________________________________________________________________________________________________________
2599// Función: enviaArchivo
2600//
2601//      Descripción:
2602//              Envia un archivo por la red, por bloques
2603//      Parámetros:
2604//              - socket_c: Socket del cliente que envió el mensaje
2605//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2606//      Devuelve:
[5759db40]2607//              true: Si el proceso es correcto
2608//              false: En caso de ocurrir algún error
[3ec149c]2609// ________________________________________________________________________________________________________
[9baecf8]2610static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli)
[d647d81]2611{
[9baecf8]2612        int socket_c = og_client_socket(cli);
[3ec149c]2613        char *nfl;
2614
2615        // Toma parámetros
2616        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
2617        ptrTrama->tipo = MSG_NOTIFICACION;
[ba03878]2618        enviaFlag(&socket_c, ptrTrama);
2619        if (!recArchivo(&socket_c, nfl)) {
[0a73ecf7]2620                liberaMemoria(nfl);
[8c04716]2621                syslog(LOG_ERR, "Problem receiving file\n");
[5759db40]2622                return false;
[3ec149c]2623        }
[0a73ecf7]2624        liberaMemoria(nfl);
[5759db40]2625        return true;
[3ec149c]2626}
2627// ________________________________________________________________________________________________________
2628// Función: envioProgramacion
2629//
2630//      Descripción:
2631//              Envia un comando de actualización a todos los ordenadores que han sido programados con
2632//              alguna acción para que entren en el bucle de comandos pendientes y las ejecuten
2633//      Parámetros:
2634//              - socket_c: Socket del cliente que envió el mensaje
2635//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2636//      Devuelve:
[5759db40]2637//              true: Si el proceso es correcto
2638//              false: En caso de ocurrir algún error
[3ec149c]2639// ________________________________________________________________________________________________________
[9baecf8]2640static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli)
[3ec149c]2641{
[847eb13]2642        char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES],*ptrNetmasks[MAXIMOS_CLIENTES];
2643        char *idp, *iph, *mac, *netmask;
[62c0560]2644        int idx,idcomando,lon;
[7db4aa4]2645        const char *msglog;
2646        struct og_dbi *dbi;
2647        dbi_result result;
[3ec149c]2648
[7db4aa4]2649        dbi = og_dbi_open(&dbi_config);
2650        if (!dbi) {
2651                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2652                       __func__, __LINE__);
[5759db40]2653                return false;
[3ec149c]2654        }
2655
[0a73ecf7]2656        idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones
[3ec149c]2657
[7db4aa4]2658        result = dbi_conn_queryf(dbi->conn,
[847eb13]2659                        "SELECT ordenadores.ip,ordenadores.mac,aulas.netmask, acciones.idcomando FROM acciones "\
[3ec149c]2660                        " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\
[847eb13]2661                        " INNER JOIN aulas ON ordenadores.idaula=aulas.idaula "\
[3ec149c]2662                        " WHERE acciones.idprogramacion=%s",idp);
[7db4aa4]2663
[0a73ecf7]2664        liberaMemoria(idp);
[8c04716]2665
[7db4aa4]2666        if (!result) {
2667                dbi_conn_error(dbi->conn, &msglog);
[8c04716]2668                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2669                       __func__, __LINE__, msglog);
[7db4aa4]2670                og_dbi_close(dbi);
[5759db40]2671                return false;
[3ec149c]2672        }
2673
2674        /* Prepara la trama de actualizacion */
2675
2676        initParametros(ptrTrama,0);
2677        ptrTrama->tipo=MSG_COMANDO;
2678        sprintf(ptrTrama->parametros, "nfn=Actualizar\r");
2679
[7db4aa4]2680        while (dbi_result_next_row(result)) {
2681                iph = (char *)dbi_result_get_string(result, "ip");
2682                idcomando = dbi_result_get_uint(result, "idcomando");
[c916af9]2683
[7db4aa4]2684                if (idcomando == 1){ // Arrancar
2685                        mac = (char *)dbi_result_get_string(result, "mac");
[847eb13]2686                        netmask = (char *)dbi_result_get_string(result, "netmask");
[62c0560]2687                        lon = splitCadena(ptrIP, iph, ';');
2688                        lon = splitCadena(ptrMacs, mac, ';');
[847eb13]2689                        lon = splitCadena(ptrNetmasks, netmask, ';');
[62c0560]2690
[e70c867]2691                        // Se manda por broadcast y por unicast
[847eb13]2692                        if (!Levanta(ptrIP, ptrMacs, ptrNetmasks, lon, (char*)"1")) {
[7db4aa4]2693                                dbi_result_free(result);
2694                                og_dbi_close(dbi);
[5759db40]2695                                return false;
[7db4aa4]2696                        }
[e70c867]2697
[847eb13]2698                        if (!Levanta(ptrIP, ptrMacs, ptrNetmasks, lon, (char*)"2")) {
[7db4aa4]2699                                dbi_result_free(result);
2700                                og_dbi_close(dbi);
[5759db40]2701                                return false;
[7db4aa4]2702                        }
[e70c867]2703
[3ec149c]2704                }
2705                if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos
[2e0c063]2706                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
2707
[3ec149c]2708                        strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente
[0deba63]2709                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[8c04716]2710                                syslog(LOG_ERR, "failed to send response: %s\n",
2711                                       strerror(errno));
[3ec149c]2712                        }
[eeeb98a]2713                        //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad
[3ec149c]2714                }
2715        }
[7db4aa4]2716        dbi_result_free(result);
2717        og_dbi_close(dbi);
2718
[5759db40]2719        return true; // No existen registros
[3ec149c]2720}
[f997cc1]2721
2722// This object stores function handler for messages
2723static struct {
2724        const char *nf; // Nombre de la función
[9baecf8]2725        bool (*fcn)(TRAMA *, struct og_client *cli);
[0e095f1]2726} tbfuncionesServer[] = {
[f997cc1]2727        { "InclusionCliente",                   InclusionCliente,       },
2728        { "InclusionClienteWinLnx",             InclusionClienteWinLnx, },
2729        { "AutoexecCliente",                    AutoexecCliente,        },
2730        { "ComandosPendientes",                 ComandosPendientes,     },
2731        { "DisponibilidadComandos",             DisponibilidadComandos, },
2732        { "RESPUESTA_Arrancar",                 RESPUESTA_Arrancar,     },
2733        { "RESPUESTA_Apagar",                   RESPUESTA_Apagar,       },
[7df4693]2734        { "RESPUESTA_Reiniciar",                RESPUESTA_Apagar,       },
2735        { "RESPUESTA_IniciarSesion",            RESPUESTA_Apagar, },
[f997cc1]2736        { "RESPUESTA_CrearImagen",              RESPUESTA_CrearImagen,  },
2737        { "RESPUESTA_CrearImagenBasica",        RESPUESTA_CrearImagenBasica, },
2738        { "RESPUESTA_CrearSoftIncremental",     RESPUESTA_CrearSoftIncremental, },
2739        { "RESPUESTA_RestaurarImagen",          RESPUESTA_RestaurarImagen },
2740        { "RESPUESTA_RestaurarImagenBasica",    RESPUESTA_RestaurarImagenBasica, },
2741        { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, },
[36b7cf4]2742        { "RESPUESTA_Configurar",               RESPUESTA_EjecutarScript, },
[f997cc1]2743        { "RESPUESTA_EjecutarScript",           RESPUESTA_EjecutarScript, },
2744        { "RESPUESTA_InventarioHardware",       RESPUESTA_InventarioHardware, },
2745        { "RESPUESTA_InventarioSoftware",       RESPUESTA_InventarioSoftware, },
2746        { "enviaArchivo",                       enviaArchivo,           },
2747        { "recibeArchivo",                      recibeArchivo,          },
2748        { "envioProgramacion",                  envioProgramacion,      },
[0e095f1]2749        { NULL,                                 NULL,                   },
[f997cc1]2750};
2751
2752// ________________________________________________________________________________________________________
2753// Función: gestionaTrama
2754//
2755//              Descripción:
2756//                      Procesa las tramas recibidas .
2757//              Parametros:
2758//                      - s : Socket usado para comunicaciones
2759//      Devuelve:
[5759db40]2760//              true: Si el proceso es correcto
2761//              false: En caso de ocurrir algún error
[f997cc1]2762// ________________________________________________________________________________________________________
[8c04716]2763static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli)
[f997cc1]2764{
2765        int i, res;
2766        char *nfn;
2767
2768        if (ptrTrama){
2769                INTROaFINCAD(ptrTrama);
2770                nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función
2771
[9baecf8]2772                for (i = 0; tbfuncionesServer[i].fcn; i++) {
2773                        if (!strncmp(tbfuncionesServer[i].nf, nfn,
2774                                     strlen(tbfuncionesServer[i].nf))) {
2775                                res = tbfuncionesServer[i].fcn(ptrTrama, cli);
[8c04716]2776                                if (!res) {
2777                                        syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n",
2778                                               tbfuncionesServer[i].nf,
2779                                               inet_ntoa(cli->addr.sin_addr),
2780                                               ntohs(cli->addr.sin_port));
2781                                } else {
2782                                        syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n",
2783                                               tbfuncionesServer[i].nf,
2784                                               inet_ntoa(cli->addr.sin_addr),
2785                                               ntohs(cli->addr.sin_port));
2786                                }
[9baecf8]2787                                break;
[f997cc1]2788                        }
2789                }
[13e48b4]2790                if (!tbfuncionesServer[i].fcn)
[2e0c063]2791                        syslog(LOG_ERR, "unknown request %s from client %s:%hu\n",
2792                               nfn, inet_ntoa(cli->addr.sin_addr),
2793                               ntohs(cli->addr.sin_port));
[13e48b4]2794
[f997cc1]2795                liberaMemoria(nfn);
[9baecf8]2796        }
2797}
2798
[2e0c063]2799static void og_client_release(struct ev_loop *loop, struct og_client *cli)
2800{
2801        if (cli->keepalive_idx >= 0) {
[0e16db2]2802                syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n",
[2e0c063]2803                       inet_ntoa(cli->addr.sin_addr),
2804                       ntohs(cli->addr.sin_port), cli->keepalive_idx);
2805                tbsockets[cli->keepalive_idx].cli = NULL;
2806        }
2807
2808        ev_io_stop(loop, &cli->io);
2809        close(cli->io.fd);
2810        free(cli);
2811}
2812
2813static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli)
2814{
2815        struct og_client *old_cli;
2816
2817        old_cli = tbsockets[cli->keepalive_idx].cli;
2818        if (old_cli && old_cli != cli) {
[0e16db2]2819                syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n",
[2e0c063]2820                       inet_ntoa(old_cli->addr.sin_addr),
2821                       ntohs(old_cli->addr.sin_port));
2822
2823                og_client_release(loop, old_cli);
2824        }
2825        tbsockets[cli->keepalive_idx].cli = cli;
2826}
2827
2828static void og_client_reset_state(struct og_client *cli)
2829{
2830        cli->state = OG_CLIENT_RECEIVING_HEADER;
2831        cli->buf_len = 0;
2832}
2833
[39c3261]2834static int og_client_state_recv_hdr(struct og_client *cli)
[9baecf8]2835{
2836        char hdrlen[LONHEXPRM];
[39c3261]2837
2838        /* Still too short to validate protocol fingerprint and message
2839         * length.
2840         */
2841        if (cli->buf_len < 15 + LONHEXPRM)
2842                return 0;
2843
2844        if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) {
2845                syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n",
2846                       inet_ntoa(cli->addr.sin_addr),
2847                       ntohs(cli->addr.sin_port));
2848                return -1;
2849        }
2850
2851        memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM);
2852        cli->msg_len = strtol(hdrlen, NULL, 16);
2853
2854        /* Header announces more that we can fit into buffer. */
2855        if (cli->msg_len >= sizeof(cli->buf)) {
2856                syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n",
2857                       cli->msg_len, inet_ntoa(cli->addr.sin_addr),
2858                       ntohs(cli->addr.sin_port));
2859                return -1;
2860        }
2861
2862        return 1;
2863}
2864
[3973759]2865static TRAMA *og_msg_alloc(char *data, unsigned int len)
[39c3261]2866{
[9baecf8]2867        TRAMA *ptrTrama;
[07c51e2]2868
2869        ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA));
2870        if (!ptrTrama) {
2871                syslog(LOG_ERR, "OOM\n");
[3973759]2872                return NULL;
[07c51e2]2873        }
2874
2875        initParametros(ptrTrama, len);
[3973759]2876        memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA);
[07c51e2]2877        memcpy(ptrTrama->parametros, data, len);
2878        ptrTrama->lonprm = len;
2879
[3973759]2880        return ptrTrama;
2881}
[07c51e2]2882
[3973759]2883static void og_msg_free(TRAMA *ptrTrama)
2884{
[07c51e2]2885        liberaMemoria(ptrTrama->parametros);
2886        liberaMemoria(ptrTrama);
[3973759]2887}
2888
2889static int og_client_state_process_payload(struct og_client *cli)
2890{
2891        TRAMA *ptrTrama;
2892        char *data;
2893        int len;
2894
2895        len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM);
2896        data = &cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM];
2897
2898        ptrTrama = og_msg_alloc(data, len);
2899        if (!ptrTrama)
2900                return -1;
2901
2902        gestionaTrama(ptrTrama, cli);
2903
2904        og_msg_free(ptrTrama);
[07c51e2]2905
2906        return 1;
2907}
2908
[c935fc9]2909#define OG_CLIENTS_MAX  4096
[2385710e]2910#define OG_PARTITION_MAX 4
2911
2912struct og_partition {
2913        const char      *number;
2914        const char      *code;
2915        const char      *size;
2916        const char      *filesystem;
2917        const char      *format;
2918};
[c935fc9]2919
[7258dac]2920struct og_sync_params {
2921        const char      *sync;
2922        const char      *diff;
2923        const char      *remove;
2924        const char      *compress;
2925        const char      *cleanup;
2926        const char      *cache;
2927        const char      *cleanup_cache;
2928        const char      *remove_dst;
[f72c984]2929        const char      *diff_id;
2930        const char      *diff_name;
[d521845]2931        const char      *path;
2932        const char      *method;
[7258dac]2933};
2934
[1a08c06]2935struct og_msg_params {
[c935fc9]2936        const char      *ips_array[OG_CLIENTS_MAX];
2937        const char      *mac_array[OG_CLIENTS_MAX];
[847eb13]2938        const char      *netmask_array[OG_CLIENTS_MAX];
[1a08c06]2939        unsigned int    ips_array_len;
[73c4bdff]2940        const char      *wol_type;
[775f6f0]2941        char            run_cmd[4096];
[22ab637]2942        const char      *disk;
2943        const char      *partition;
[7f2dd15]2944        const char      *repository;
2945        const char      *name;
2946        const char      *id;
2947        const char      *code;
[fc15dd1]2948        const char      *type;
2949        const char      *profile;
[2385710e]2950        const char      *cache;
2951        const char      *cache_size;
[454ab57]2952        bool            echo;
[2385710e]2953        struct og_partition     partition_setup[OG_PARTITION_MAX];
[7258dac]2954        struct og_sync_params sync_setup;
[70a698a]2955        uint64_t        flags;
[1a08c06]2956};
2957
[70a698a]2958#define OG_REST_PARAM_ADDR                      (1UL << 0)
[becce94]2959#define OG_REST_PARAM_MAC                       (1UL << 1)
2960#define OG_REST_PARAM_WOL_TYPE                  (1UL << 2)
[3debec6]2961#define OG_REST_PARAM_RUN_CMD                   (1UL << 3)
[66ce511]2962#define OG_REST_PARAM_DISK                      (1UL << 4)
2963#define OG_REST_PARAM_PARTITION                 (1UL << 5)
[072f5c5]2964#define OG_REST_PARAM_REPO                      (1UL << 6)
2965#define OG_REST_PARAM_NAME                      (1UL << 7)
2966#define OG_REST_PARAM_ID                        (1UL << 8)
2967#define OG_REST_PARAM_CODE                      (1UL << 9)
[bc0ad31]2968#define OG_REST_PARAM_TYPE                      (1UL << 10)
2969#define OG_REST_PARAM_PROFILE                   (1UL << 11)
[12e25a9]2970#define OG_REST_PARAM_CACHE                     (1UL << 12)
2971#define OG_REST_PARAM_CACHE_SIZE                (1UL << 13)
2972#define OG_REST_PARAM_PART_0                    (1UL << 14)
2973#define OG_REST_PARAM_PART_1                    (1UL << 15)
2974#define OG_REST_PARAM_PART_2                    (1UL << 16)
2975#define OG_REST_PARAM_PART_3                    (1UL << 17)
[6c1b3a9]2976#define OG_REST_PARAM_SYNC_SYNC                 (1UL << 18)
2977#define OG_REST_PARAM_SYNC_DIFF                 (1UL << 19)
2978#define OG_REST_PARAM_SYNC_REMOVE               (1UL << 20)
2979#define OG_REST_PARAM_SYNC_COMPRESS             (1UL << 21)
2980#define OG_REST_PARAM_SYNC_CLEANUP              (1UL << 22)
2981#define OG_REST_PARAM_SYNC_CACHE                (1UL << 23)
2982#define OG_REST_PARAM_SYNC_CLEANUP_CACHE        (1UL << 24)
2983#define OG_REST_PARAM_SYNC_REMOVE_DST           (1UL << 25)
2984#define OG_REST_PARAM_SYNC_DIFF_ID              (1UL << 26)
2985#define OG_REST_PARAM_SYNC_DIFF_NAME            (1UL << 27)
2986#define OG_REST_PARAM_SYNC_PATH                 (1UL << 28)
2987#define OG_REST_PARAM_SYNC_METHOD               (1UL << 29)
[454ab57]2988#define OG_REST_PARAM_ECHO                      (1UL << 30)
[70a698a]2989
2990static bool og_msg_params_validate(const struct og_msg_params *params,
2991                                   const uint64_t flags)
2992{
2993        return (params->flags & flags) == flags;
2994}
2995
[1a08c06]2996static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
2997{
2998        unsigned int i;
2999        json_t *k;
3000
3001        if (json_typeof(element) != JSON_ARRAY)
3002                return -1;
3003
3004        for (i = 0; i < json_array_size(element); i++) {
3005                k = json_array_get(element, i);
3006                if (json_typeof(k) != JSON_STRING)
3007                        return -1;
3008
3009                params->ips_array[params->ips_array_len++] =
3010                        json_string_value(k);
[70a698a]3011
[18d2376]3012                params->flags |= OG_REST_PARAM_ADDR;
3013        }
[70a698a]3014
[1a08c06]3015        return 0;
3016}
3017
[70b1e58]3018static int og_json_parse_string(json_t *element, const char **str)
3019{
3020        if (json_typeof(element) != JSON_STRING)
3021                return -1;
3022
3023        *str = json_string_value(element);
3024        return 0;
3025}
3026
[454ab57]3027static int og_json_parse_bool(json_t *element, bool *value)
3028{
3029        if (json_typeof(element) == JSON_TRUE)
3030                *value = true;
3031        else if (json_typeof(element) == JSON_FALSE)
3032                *value = false;
3033        else
3034                return -1;
3035
3036        return 0;
3037}
3038
[6c1b3a9]3039static int og_json_parse_sync_params(json_t *element,
3040                                     struct og_msg_params *params)
[7258dac]3041{
3042        const char *key;
3043        json_t *value;
3044        int err = 0;
3045
3046        json_object_foreach(element, key, value) {
[6c1b3a9]3047                if (!strcmp(key, "sync")) {
3048                        err = og_json_parse_string(value, &params->sync_setup.sync);
3049                        params->flags |= OG_REST_PARAM_SYNC_SYNC;
3050                } else if (!strcmp(key, "diff")) {
3051                        err = og_json_parse_string(value, &params->sync_setup.diff);
3052                        params->flags |= OG_REST_PARAM_SYNC_DIFF;
3053                } else if (!strcmp(key, "remove")) {
3054                        err = og_json_parse_string(value, &params->sync_setup.remove);
3055                        params->flags |= OG_REST_PARAM_SYNC_REMOVE;
3056                } else if (!strcmp(key, "compress")) {
3057                        err = og_json_parse_string(value, &params->sync_setup.compress);
3058                        params->flags |= OG_REST_PARAM_SYNC_COMPRESS;
3059                } else if (!strcmp(key, "cleanup")) {
3060                        err = og_json_parse_string(value, &params->sync_setup.cleanup);
3061                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP;
3062                } else if (!strcmp(key, "cache")) {
3063                        err = og_json_parse_string(value, &params->sync_setup.cache);
3064                        params->flags |= OG_REST_PARAM_SYNC_CACHE;
3065                } else if (!strcmp(key, "cleanup_cache")) {
3066                        err = og_json_parse_string(value, &params->sync_setup.cleanup_cache);
3067                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP_CACHE;
3068                } else if (!strcmp(key, "remove_dst")) {
3069                        err = og_json_parse_string(value, &params->sync_setup.remove_dst);
3070                        params->flags |= OG_REST_PARAM_SYNC_REMOVE_DST;
3071                } else if (!strcmp(key, "diff_id")) {
3072                        err = og_json_parse_string(value, &params->sync_setup.diff_id);
3073                        params->flags |= OG_REST_PARAM_SYNC_DIFF_ID;
3074                } else if (!strcmp(key, "diff_name")) {
3075                        err = og_json_parse_string(value, &params->sync_setup.diff_name);
3076                        params->flags |= OG_REST_PARAM_SYNC_DIFF_NAME;
3077                } else if (!strcmp(key, "path")) {
3078                        err = og_json_parse_string(value, &params->sync_setup.path);
3079                        params->flags |= OG_REST_PARAM_SYNC_PATH;
3080                } else if (!strcmp(key, "method")) {
3081                        err = og_json_parse_string(value, &params->sync_setup.method);
3082                        params->flags |= OG_REST_PARAM_SYNC_METHOD;
3083                }
[7258dac]3084
3085                if (err != 0)
3086                        return err;
3087        }
3088        return err;
3089}
3090
[12e25a9]3091#define OG_PARAM_PART_NUMBER                    (1UL << 0)
3092#define OG_PARAM_PART_CODE                      (1UL << 1)
3093#define OG_PARAM_PART_FILESYSTEM                (1UL << 2)
3094#define OG_PARAM_PART_SIZE                      (1UL << 3)
3095#define OG_PARAM_PART_FORMAT                    (1UL << 4)
3096
3097static int og_json_parse_partition(json_t *element,
3098                                   struct og_msg_params *params,
3099                                   unsigned int i)
[70aef0d]3100{
[12e25a9]3101        struct og_partition *part = &params->partition_setup[i];
3102        uint64_t flags = 0UL;
[70aef0d]3103        const char *key;
3104        json_t *value;
3105        int err = 0;
3106
3107        json_object_foreach(element, key, value) {
[12e25a9]3108                if (!strcmp(key, "partition")) {
[70aef0d]3109                        err = og_json_parse_string(value, &part->number);
[12e25a9]3110                        flags |= OG_PARAM_PART_NUMBER;
3111                } else if (!strcmp(key, "code")) {
[70aef0d]3112                        err = og_json_parse_string(value, &part->code);
[12e25a9]3113                        flags |= OG_PARAM_PART_CODE;
3114                } else if (!strcmp(key, "filesystem")) {
[70aef0d]3115                        err = og_json_parse_string(value, &part->filesystem);
[12e25a9]3116                        flags |= OG_PARAM_PART_FILESYSTEM;
3117                } else if (!strcmp(key, "size")) {
[70aef0d]3118                        err = og_json_parse_string(value, &part->size);
[12e25a9]3119                        flags |= OG_PARAM_PART_SIZE;
3120                } else if (!strcmp(key, "format")) {
[70aef0d]3121                        err = og_json_parse_string(value, &part->format);
[12e25a9]3122                        flags |= OG_PARAM_PART_FORMAT;
3123                }
[70aef0d]3124
3125                if (err < 0)
3126                        return err;
3127        }
[12e25a9]3128
3129        if (flags != (OG_PARAM_PART_NUMBER |
3130                      OG_PARAM_PART_CODE |
3131                      OG_PARAM_PART_FILESYSTEM |
3132                      OG_PARAM_PART_SIZE |
3133                      OG_PARAM_PART_FORMAT))
3134                return -1;
3135
3136        params->flags |= (OG_REST_PARAM_PART_0 << i);
3137
[70aef0d]3138        return err;
[2385710e]3139}
3140
[12e25a9]3141static int og_json_parse_partition_setup(json_t *element,
3142                                         struct og_msg_params *params)
[2385710e]3143{
3144        unsigned int i;
3145        json_t *k;
3146
3147        if (json_typeof(element) != JSON_ARRAY)
3148                return -1;
3149
3150        for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
3151                k = json_array_get(element, i);
3152
3153                if (json_typeof(k) != JSON_OBJECT)
3154                        return -1;
3155
[12e25a9]3156                if (og_json_parse_partition(k, params, i) != 0)
[70aef0d]3157                        return -1;
[2385710e]3158        }
3159        return 0;
3160}
3161
[8411d3b]3162static int og_cmd_legacy_send(struct og_msg_params *params, const char *cmd,
3163                              const char *state)
[1a08c06]3164{
3165        char buf[4096] = {};
3166        int len, err = 0;
3167        TRAMA *msg;
3168
[8411d3b]3169        len = snprintf(buf, sizeof(buf), "nfn=%s\r", cmd);
[1a08c06]3170
3171        msg = og_msg_alloc(buf, len);
3172        if (!msg)
3173                return -1;
3174
3175        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
[8411d3b]3176                         state, msg))
[1a08c06]3177                err = -1;
3178
3179        og_msg_free(msg);
3180
3181        return err;
3182}
3183
3184static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
3185{
3186        const char *key;
3187        json_t *value;
3188        int err = 0;
3189
3190        if (json_typeof(element) != JSON_OBJECT)
3191                return -1;
3192
3193        json_object_foreach(element, key, value) {
3194                if (!strcmp(key, "clients"))
3195                        err = og_json_parse_clients(value, params);
3196
3197                if (err < 0)
3198                        break;
3199        }
3200
[70a698a]3201        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3202                return -1;
3203
[8411d3b]3204        return og_cmd_legacy_send(params, "Sondeo", CLIENTE_APAGADO);
[1a08c06]3205}
3206
[ea03692]3207struct og_buffer {
3208        char    *data;
3209        int     len;
3210};
3211
3212static int og_json_dump_clients(const char *buffer, size_t size, void *data)
3213{
3214        struct og_buffer *og_buffer = (struct og_buffer *)data;
3215
3216        memcpy(og_buffer->data + og_buffer->len, buffer, size);
3217        og_buffer->len += size;
3218
3219        return 0;
3220}
3221
3222static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
3223                              char *buffer_reply)
3224{
3225        json_t *root, *array, *addr, *state, *object;
3226        struct og_buffer og_buffer = {
3227                .data   = buffer_reply,
3228        };
3229        int i;
3230
3231        array = json_array();
3232        if (!array)
3233                return -1;
3234
3235        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
3236                if (tbsockets[i].ip[0] == '\0')
3237                        continue;
3238
3239                object = json_object();
3240                if (!object) {
3241                        json_decref(array);
3242                        return -1;
3243                }
3244                addr = json_string(tbsockets[i].ip);
3245                if (!addr) {
3246                        json_decref(object);
3247                        json_decref(array);
3248                        return -1;
3249                }
3250                json_object_set_new(object, "addr", addr);
3251
3252                state = json_string(tbsockets[i].estado);
3253                if (!state) {
3254                        json_decref(object);
3255                        json_decref(array);
3256                        return -1;
3257                }
3258                json_object_set_new(object, "state", state);
3259
3260                json_array_append_new(array, object);
3261        }
3262        root = json_pack("{s:o}", "clients", array);
3263        if (!root) {
3264                json_decref(array);
3265                return -1;
3266        }
3267
[a36ed20]3268        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[ea03692]3269        json_decref(root);
3270
3271        return 0;
3272}
3273
[73c4bdff]3274static int og_json_parse_target(json_t *element, struct og_msg_params *params)
3275{
3276        const char *key;
3277        json_t *value;
3278
3279        if (json_typeof(element) != JSON_OBJECT) {
3280                return -1;
3281        }
3282
3283        json_object_foreach(element, key, value) {
3284                if (!strcmp(key, "addr")) {
3285                        if (json_typeof(value) != JSON_STRING)
3286                                return -1;
3287
3288                        params->ips_array[params->ips_array_len] =
3289                                json_string_value(value);
[becce94]3290
3291                        params->flags |= OG_REST_PARAM_ADDR;
[73c4bdff]3292                } else if (!strcmp(key, "mac")) {
3293                        if (json_typeof(value) != JSON_STRING)
3294                                return -1;
3295
3296                        params->mac_array[params->ips_array_len] =
3297                                json_string_value(value);
[becce94]3298
3299                        params->flags |= OG_REST_PARAM_MAC;
[73c4bdff]3300                }
3301        }
3302
3303        return 0;
3304}
3305
3306static int og_json_parse_targets(json_t *element, struct og_msg_params *params)
3307{
3308        unsigned int i;
3309        json_t *k;
3310        int err;
3311
3312        if (json_typeof(element) != JSON_ARRAY)
3313                return -1;
3314
3315        for (i = 0; i < json_array_size(element); i++) {
3316                k = json_array_get(element, i);
3317
3318                if (json_typeof(k) != JSON_OBJECT)
3319                        return -1;
3320
3321                err = og_json_parse_target(k, params);
3322                if (err < 0)
3323                        return err;
3324
3325                params->ips_array_len++;
3326        }
3327        return 0;
3328}
3329
3330static int og_json_parse_type(json_t *element, struct og_msg_params *params)
3331{
3332        const char *type;
3333
3334        if (json_typeof(element) != JSON_STRING)
3335                return -1;
3336
3337        params->wol_type = json_string_value(element);
3338
3339        type = json_string_value(element);
3340        if (!strcmp(type, "unicast"))
3341                params->wol_type = "2";
3342        else if (!strcmp(type, "broadcast"))
3343                params->wol_type = "1";
3344
[becce94]3345        params->flags |= OG_REST_PARAM_WOL_TYPE;
3346
[73c4bdff]3347        return 0;
3348}
3349
3350static int og_cmd_wol(json_t *element, struct og_msg_params *params)
3351{
[847eb13]3352        char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
3353        int ips_str_len = 0;
3354        const char *msglog;
3355        struct og_dbi *dbi;
3356        int i = 0;
3357        dbi_result result;
[73c4bdff]3358        const char *key;
3359        json_t *value;
3360        int err = 0;
3361
3362        if (json_typeof(element) != JSON_OBJECT)
3363                return -1;
3364
3365        json_object_foreach(element, key, value) {
3366                if (!strcmp(key, "clients")) {
3367                        err = og_json_parse_targets(value, params);
3368                } else if (!strcmp(key, "type")) {
3369                        err = og_json_parse_type(value, params);
3370                }
3371
3372                if (err < 0)
3373                        break;
3374        }
3375
[becce94]3376        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3377                                            OG_REST_PARAM_MAC |
3378                                            OG_REST_PARAM_WOL_TYPE))
3379                return -1;
3380
[847eb13]3381        for (i = 0; i < params->ips_array_len; ++i) {
3382                ips_str_len += snprintf(ips_str + ips_str_len,
3383                                        sizeof(ips_str) - ips_str_len,
3384                                        "'%s',", params->ips_array[i]);
3385        }
3386        ips_str[ips_str_len - 1] = '\0';
3387
3388        dbi = og_dbi_open(&dbi_config);
3389        if (!dbi) {
3390                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3391                       __func__, __LINE__);
3392                return -1;
3393        }
3394
3395        result = dbi_conn_queryf(dbi->conn,
3396                                 "SELECT ordenadores.ip, ordenadores.mac, "
3397                                        "aulas.netmask "
3398                                 "FROM   ordenadores "
3399                                 "INNER JOIN aulas "
3400                                         "ON ordenadores.idaula = aulas.idaula "
3401                                 "WHERE  ordenadores.ip IN (%s)",
3402                                 ips_str);
3403        if (!result) {
3404                dbi_conn_error(dbi->conn, &msglog);
3405                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3406                       __func__, __LINE__, msglog);
3407                og_dbi_close(dbi);
3408                return -1;
3409        }
3410
3411        for (i = 0; dbi_result_next_row(result); i++) {
3412                params->ips_array[i] = dbi_result_get_string_copy(result, "ip");
3413                params->mac_array[i] = dbi_result_get_string_copy(result, "mac");
3414                params->netmask_array[i] = dbi_result_get_string_copy(result, "netmask");
3415        }
3416
3417        dbi_result_free(result);
3418        og_dbi_close(dbi);
3419
[73c4bdff]3420        if (!Levanta((char **)params->ips_array, (char **)params->mac_array,
[847eb13]3421                     (char **)params->netmask_array, i,
3422                     (char *)params->wol_type))
[73c4bdff]3423                return -1;
3424
3425        return 0;
3426}
3427
[775f6f0]3428static int og_json_parse_run(json_t *element, struct og_msg_params *params)
3429{
3430        if (json_typeof(element) != JSON_STRING)
3431                return -1;
3432
3433        snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
3434                 json_string_value(element));
3435
[3debec6]3436        params->flags |= OG_REST_PARAM_RUN_CMD;
3437
[775f6f0]3438        return 0;
3439}
3440
3441static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
3442{
3443        char buf[4096] = {}, iph[4096] = {};
3444        int err = 0, len;
3445        const char *key;
3446        unsigned int i;
3447        json_t *value;
3448        TRAMA *msg;
3449
3450        if (json_typeof(element) != JSON_OBJECT)
3451                return -1;
3452
3453        json_object_foreach(element, key, value) {
3454                if (!strcmp(key, "clients"))
3455                        err = og_json_parse_clients(value, params);
[454ab57]3456                else if (!strcmp(key, "run"))
[775f6f0]3457                        err = og_json_parse_run(value, params);
[454ab57]3458                else if (!strcmp(key, "echo")) {
3459                        err = og_json_parse_bool(value, &params->echo);
3460                        params->flags |= OG_REST_PARAM_ECHO;
3461                }
[775f6f0]3462
3463                if (err < 0)
3464                        break;
3465        }
3466
[3debec6]3467        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
[454ab57]3468                                            OG_REST_PARAM_RUN_CMD |
3469                                            OG_REST_PARAM_ECHO))
[3debec6]3470                return -1;
3471
[775f6f0]3472        for (i = 0; i < params->ips_array_len; i++) {
3473                len = snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3474                               params->ips_array[i]);
3475        }
[454ab57]3476
3477        if (params->echo) {
3478                len = snprintf(buf, sizeof(buf),
3479                               "nfn=ConsolaRemota\riph=%s\rscp=%s\r",
3480                               iph, params->run_cmd);
3481        } else {
3482                len = snprintf(buf, sizeof(buf),
3483                               "nfn=EjecutarScript\riph=%s\rscp=%s\r",
3484                               iph, params->run_cmd);
3485        }
[775f6f0]3486
3487        msg = og_msg_alloc(buf, len);
3488        if (!msg)
3489                return -1;
3490
3491        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3492                         CLIENTE_OCUPADO, msg))
3493                err = -1;
3494
3495        og_msg_free(msg);
3496
3497        if (err < 0)
3498                return err;
3499
3500        for (i = 0; i < params->ips_array_len; i++) {
3501                char filename[4096];
3502                FILE *f;
3503
3504                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3505                f = fopen(filename, "wt");
3506                fclose(f);
3507        }
3508
3509        return 0;
3510}
3511
[165cea3]3512static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
3513                          char *buffer_reply)
3514{
3515        struct og_buffer og_buffer = {
3516                .data   = buffer_reply,
3517        };
3518        json_t *root, *value, *array;
3519        const char *key;
3520        unsigned int i;
3521        int err = 0;
3522
3523        if (json_typeof(element) != JSON_OBJECT)
3524                return -1;
3525
3526        json_object_foreach(element, key, value) {
3527                if (!strcmp(key, "clients"))
3528                        err = og_json_parse_clients(value, params);
3529
3530                if (err < 0)
3531                        return err;
3532        }
3533
[22469c6]3534        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3535                return -1;
3536
[165cea3]3537        array = json_array();
3538        if (!array)
3539                return -1;
3540
3541        for (i = 0; i < params->ips_array_len; i++) {
3542                json_t *object, *output, *addr;
3543                char data[4096] = {};
3544                char filename[4096];
3545                int fd, numbytes;
3546
3547                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3548
3549                fd = open(filename, O_RDONLY);
3550                if (!fd)
3551                        return -1;
3552
3553                numbytes = read(fd, data, sizeof(data));
3554                if (numbytes < 0) {
3555                        close(fd);
3556                        return -1;
3557                }
3558                data[sizeof(data) - 1] = '\0';
3559                close(fd);
3560
3561                object = json_object();
3562                if (!object) {
3563                        json_decref(array);
3564                        return -1;
3565                }
3566                addr = json_string(params->ips_array[i]);
3567                if (!addr) {
3568                        json_decref(object);
3569                        json_decref(array);
3570                        return -1;
3571                }
3572                json_object_set_new(object, "addr", addr);
3573
3574                output = json_string(data);
3575                if (!output) {
3576                        json_decref(object);
3577                        json_decref(array);
3578                        return -1;
3579                }
3580                json_object_set_new(object, "output", output);
3581
3582                json_array_append_new(array, object);
3583        }
3584
3585        root = json_pack("{s:o}", "clients", array);
3586        if (!root)
3587                return -1;
3588
[a36ed20]3589        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[165cea3]3590        json_decref(root);
3591
3592        return 0;
3593}
3594
[22ab637]3595static int og_cmd_session(json_t *element, struct og_msg_params *params)
3596{
3597        char buf[4096], iph[4096];
3598        int err = 0, len;
3599        const char *key;
3600        unsigned int i;
3601        json_t *value;
3602        TRAMA *msg;
3603
3604        if (json_typeof(element) != JSON_OBJECT)
3605                return -1;
3606
3607        json_object_foreach(element, key, value) {
[66ce511]3608                if (!strcmp(key, "clients")) {
[22ab637]3609                        err = og_json_parse_clients(value, params);
[66ce511]3610                } else if (!strcmp(key, "disk")) {
[70b1e58]3611                        err = og_json_parse_string(value, &params->disk);
[66ce511]3612                        params->flags |= OG_REST_PARAM_DISK;
3613                } else if (!strcmp(key, "partition")) {
[70b1e58]3614                        err = og_json_parse_string(value, &params->partition);
[66ce511]3615                        params->flags |= OG_REST_PARAM_PARTITION;
3616                }
[22ab637]3617
3618                if (err < 0)
3619                        return err;
3620        }
3621
[66ce511]3622        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3623                                            OG_REST_PARAM_DISK |
3624                                            OG_REST_PARAM_PARTITION))
3625                return -1;
3626
[22ab637]3627        for (i = 0; i < params->ips_array_len; i++) {
3628                snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3629                         params->ips_array[i]);
3630        }
3631        len = snprintf(buf, sizeof(buf),
3632                       "nfn=IniciarSesion\riph=%s\rdsk=%s\rpar=%s\r",
3633                       iph, params->disk, params->partition);
3634
3635        msg = og_msg_alloc(buf, len);
3636        if (!msg)
3637                return -1;
3638
3639        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3640                         CLIENTE_APAGADO, msg))
3641                err = -1;
3642
3643        og_msg_free(msg);
3644
3645        return 0;
3646}
3647
[b231a5a]3648static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
3649{
3650        const char *key;
3651        json_t *value;
3652        int err = 0;
3653
3654        if (json_typeof(element) != JSON_OBJECT)
3655                return -1;
3656
3657        json_object_foreach(element, key, value) {
3658                if (!strcmp(key, "clients"))
3659                        err = og_json_parse_clients(value, params);
3660
3661                if (err < 0)
3662                        break;
3663        }
3664
[2aad3d9]3665        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3666                return -1;
3667
[b231a5a]3668        return og_cmd_legacy_send(params, "Apagar", CLIENTE_OCUPADO);
3669}
3670
[b317d24]3671static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
3672{
3673        const char *key;
3674        json_t *value;
3675        int err = 0;
3676
3677        if (json_typeof(element) != JSON_OBJECT)
3678                return -1;
3679
3680        json_object_foreach(element, key, value) {
3681                if (!strcmp(key, "clients"))
3682                        err = og_json_parse_clients(value, params);
3683
3684                if (err < 0)
3685                        break;
3686        }
3687
[3402460]3688        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3689                return -1;
3690
[b317d24]3691        return og_cmd_legacy_send(params, "Actualizar", CLIENTE_APAGADO);
3692}
3693
[68270b3]3694static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
3695{
3696        const char *key;
3697        json_t *value;
3698        int err = 0;
3699
3700        if (json_typeof(element) != JSON_OBJECT)
3701                return -1;
3702
3703        json_object_foreach(element, key, value) {
3704                if (!strcmp(key, "clients"))
3705                        err = og_json_parse_clients(value, params);
3706
3707                if (err < 0)
3708                        break;
3709        }
3710
[d86ddce]3711        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3712                return -1;
3713
[68270b3]3714        return og_cmd_legacy_send(params, "Reiniciar", CLIENTE_OCUPADO);
3715}
3716
[5513435]3717static int og_cmd_stop(json_t *element, struct og_msg_params *params)
3718{
3719        const char *key;
3720        json_t *value;
3721        int err = 0;
3722
3723        if (json_typeof(element) != JSON_OBJECT)
3724                return -1;
3725
3726        json_object_foreach(element, key, value) {
3727                if (!strcmp(key, "clients"))
3728                        err = og_json_parse_clients(value, params);
3729
3730                if (err < 0)
3731                        break;
3732        }
3733
[04a8c17]3734        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3735                return -1;
3736
[5513435]3737        return og_cmd_legacy_send(params, "Purgar", CLIENTE_APAGADO);
3738}
3739
[1316c877]3740static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
3741{
3742        const char *key;
3743        json_t *value;
3744        int err = 0;
3745
3746        if (json_typeof(element) != JSON_OBJECT)
3747                return -1;
3748
3749        json_object_foreach(element, key, value) {
3750                if (!strcmp(key, "clients"))
3751                        err = og_json_parse_clients(value, params);
3752
3753                if (err < 0)
3754                        break;
3755        }
3756
[a0df5af7]3757        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3758                return -1;
3759
[1316c877]3760        return og_cmd_legacy_send(params, "InventarioHardware",
3761                                  CLIENTE_OCUPADO);
3762}
3763
[a0f41fc]3764static int og_cmd_software(json_t *element, struct og_msg_params *params)
3765{
[de36dbe]3766        char buf[4096] = {};
3767        int err = 0, len;
[a0f41fc]3768        const char *key;
3769        json_t *value;
[de36dbe]3770        TRAMA *msg;
[a0f41fc]3771
3772        if (json_typeof(element) != JSON_OBJECT)
3773                return -1;
3774
3775        json_object_foreach(element, key, value) {
3776                if (!strcmp(key, "clients"))
3777                        err = og_json_parse_clients(value, params);
[c80150e]3778                else if (!strcmp(key, "disk")) {
[de36dbe]3779                        err = og_json_parse_string(value, &params->disk);
[c80150e]3780                        params->flags |= OG_REST_PARAM_DISK;
3781                }
3782                else if (!strcmp(key, "partition")) {
[de36dbe]3783                        err = og_json_parse_string(value, &params->partition);
[c80150e]3784                        params->flags |= OG_REST_PARAM_PARTITION;
3785                }
[a0f41fc]3786
3787                if (err < 0)
3788                        break;
3789        }
3790
[c80150e]3791        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3792                                            OG_REST_PARAM_DISK |
3793                                            OG_REST_PARAM_PARTITION))
3794                return -1;
3795
[de36dbe]3796        len = snprintf(buf, sizeof(buf),
3797                       "nfn=InventarioSoftware\rdsk=%s\rpar=%s\r",
3798                       params->disk, params->partition);
3799
3800        msg = og_msg_alloc(buf, len);
3801        if (!msg)
3802                return -1;
3803
3804        og_send_cmd((char **)params->ips_array, params->ips_array_len,
3805                    CLIENTE_OCUPADO, msg);
3806
3807        og_msg_free(msg);
3808
3809        return 0;
[a0f41fc]3810}
3811
[7f2dd15]3812static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
3813{
3814        char buf[4096] = {};
3815        int err = 0, len;
3816        const char *key;
3817        json_t *value;
3818        TRAMA *msg;
3819
3820        if (json_typeof(element) != JSON_OBJECT)
3821                return -1;
3822
3823        json_object_foreach(element, key, value) {
[072f5c5]3824                if (!strcmp(key, "disk")) {
[70b1e58]3825                        err = og_json_parse_string(value, &params->disk);
[072f5c5]3826                        params->flags |= OG_REST_PARAM_DISK;
3827                } else if (!strcmp(key, "partition")) {
[70b1e58]3828                        err = og_json_parse_string(value, &params->partition);
[072f5c5]3829                        params->flags |= OG_REST_PARAM_PARTITION;
3830                } else if (!strcmp(key, "name")) {
[70b1e58]3831                        err = og_json_parse_string(value, &params->name);
[072f5c5]3832                        params->flags |= OG_REST_PARAM_NAME;
3833                } else if (!strcmp(key, "repository")) {
[70b1e58]3834                        err = og_json_parse_string(value, &params->repository);
[072f5c5]3835                        params->flags |= OG_REST_PARAM_REPO;
3836                } else if (!strcmp(key, "clients")) {
[7f2dd15]3837                        err = og_json_parse_clients(value, params);
[072f5c5]3838                } else if (!strcmp(key, "id")) {
[70b1e58]3839                        err = og_json_parse_string(value, &params->id);
[072f5c5]3840                        params->flags |= OG_REST_PARAM_ID;
3841                } else if (!strcmp(key, "code")) {
[70b1e58]3842                        err = og_json_parse_string(value, &params->code);
[072f5c5]3843                        params->flags |= OG_REST_PARAM_CODE;
3844                }
[7f2dd15]3845
3846                if (err < 0)
3847                        break;
3848        }
3849
[072f5c5]3850        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3851                                            OG_REST_PARAM_DISK |
3852                                            OG_REST_PARAM_PARTITION |
3853                                            OG_REST_PARAM_CODE |
3854                                            OG_REST_PARAM_ID |
3855                                            OG_REST_PARAM_NAME |
3856                                            OG_REST_PARAM_REPO))
3857                return -1;
3858
[7f2dd15]3859        len = snprintf(buf, sizeof(buf),
3860                        "nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
3861                        params->disk, params->partition, params->code,
3862                        params->id, params->name, params->repository);
3863
3864        msg = og_msg_alloc(buf, len);
3865        if (!msg)
3866                return -1;
3867
3868        og_send_cmd((char **)params->ips_array, params->ips_array_len,
3869                    CLIENTE_OCUPADO, msg);
3870
3871        og_msg_free(msg);
3872
3873        return 0;
3874}
3875
[fc15dd1]3876static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
3877{
3878        char buf[4096] = {};
3879        int err = 0, len;
3880        const char *key;
3881        json_t *value;
3882        TRAMA *msg;
3883
3884        if (json_typeof(element) != JSON_OBJECT)
3885                return -1;
3886
3887        json_object_foreach(element, key, value) {
[bc0ad31]3888                if (!strcmp(key, "disk")) {
[fc15dd1]3889                        err = og_json_parse_string(value, &params->disk);
[bc0ad31]3890                        params->flags |= OG_REST_PARAM_DISK;
3891                } else if (!strcmp(key, "partition")) {
[fc15dd1]3892                        err = og_json_parse_string(value, &params->partition);
[bc0ad31]3893                        params->flags |= OG_REST_PARAM_PARTITION;
3894                } else if (!strcmp(key, "name")) {
[fc15dd1]3895                        err = og_json_parse_string(value, &params->name);
[bc0ad31]3896                        params->flags |= OG_REST_PARAM_NAME;
3897                } else if (!strcmp(key, "repository")) {
[fc15dd1]3898                        err = og_json_parse_string(value, &params->repository);
[bc0ad31]3899                        params->flags |= OG_REST_PARAM_REPO;
3900                } else if (!strcmp(key, "clients")) {
[fc15dd1]3901                        err = og_json_parse_clients(value, params);
[bc0ad31]3902                } else if (!strcmp(key, "type")) {
[fc15dd1]3903                        err = og_json_parse_string(value, &params->type);
[bc0ad31]3904                        params->flags |= OG_REST_PARAM_TYPE;
3905                } else if (!strcmp(key, "profile")) {
[fc15dd1]3906                        err = og_json_parse_string(value, &params->profile);
[bc0ad31]3907                        params->flags |= OG_REST_PARAM_PROFILE;
3908                } else if (!strcmp(key, "id")) {
[fc15dd1]3909                        err = og_json_parse_string(value, &params->id);
[bc0ad31]3910                        params->flags |= OG_REST_PARAM_ID;
3911                }
[fc15dd1]3912
3913                if (err < 0)
3914                        break;
3915        }
3916
[bc0ad31]3917        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3918                                            OG_REST_PARAM_DISK |
3919                                            OG_REST_PARAM_PARTITION |
3920                                            OG_REST_PARAM_NAME |
3921                                            OG_REST_PARAM_REPO |
3922                                            OG_REST_PARAM_TYPE |
3923                                            OG_REST_PARAM_PROFILE |
3924                                            OG_REST_PARAM_ID))
3925                return -1;
3926
[fc15dd1]3927        len = snprintf(buf, sizeof(buf),
3928                       "nfn=RestaurarImagen\ridi=%s\rdsk=%s\rpar=%s\rifs=%s\r"
3929                       "nci=%s\ripr=%s\rptc=%s\r",
3930                       params->id, params->disk, params->partition,
3931                       params->profile, params->name,
3932                       params->repository, params->type);
3933
3934        msg = og_msg_alloc(buf, len);
3935        if (!msg)
3936                return -1;
3937
3938        og_send_cmd((char **)params->ips_array, params->ips_array_len,
3939                    CLIENTE_OCUPADO, msg);
3940
3941        og_msg_free(msg);
3942
3943        return 0;
3944}
3945
[9381fdf]3946static int og_cmd_setup(json_t *element, struct og_msg_params *params)
[2385710e]3947{
3948        char buf[4096] = {};
3949        int err = 0, len;
3950        const char *key;
3951        json_t *value;
3952        TRAMA *msg;
3953
3954        if (json_typeof(element) != JSON_OBJECT)
3955                return -1;
3956
3957        json_object_foreach(element, key, value) {
[12e25a9]3958                if (!strcmp(key, "clients")) {
[2385710e]3959                        err = og_json_parse_clients(value, params);
[12e25a9]3960                } else if (!strcmp(key, "disk")) {
[2385710e]3961                        err = og_json_parse_string(value, &params->disk);
[12e25a9]3962                        params->flags |= OG_REST_PARAM_DISK;
3963                } else if (!strcmp(key, "cache")) {
[2385710e]3964                        err = og_json_parse_string(value, &params->cache);
[12e25a9]3965                        params->flags |= OG_REST_PARAM_CACHE;
3966                } else if (!strcmp(key, "cache_size")) {
[2385710e]3967                        err = og_json_parse_string(value, &params->cache_size);
[12e25a9]3968                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
3969                } else if (!strcmp(key, "partition_setup")) {
3970                        err = og_json_parse_partition_setup(value, params);
3971                }
[2385710e]3972
3973                if (err < 0)
3974                        break;
3975        }
3976
[12e25a9]3977        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3978                                            OG_REST_PARAM_DISK |
3979                                            OG_REST_PARAM_CACHE |
3980                                            OG_REST_PARAM_CACHE_SIZE |
3981                                            OG_REST_PARAM_PART_0 |
3982                                            OG_REST_PARAM_PART_1 |
3983                                            OG_REST_PARAM_PART_2 |
3984                                            OG_REST_PARAM_PART_3))
3985                return -1;
3986
[2385710e]3987        len = snprintf(buf, sizeof(buf),
3988                        "nfn=Configurar\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!",
3989                        params->disk, params->disk, params->cache, params->cache_size);
3990
3991        for (unsigned int i = 0; i < OG_PARTITION_MAX; ++i) {
[12e25a9]3992                const struct og_partition *part = &params->partition_setup[i];
[2385710e]3993
3994                len += snprintf(buf + strlen(buf), sizeof(buf),
3995                        "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%",
3996                        part->number, part->code, part->filesystem, part->size, part->format);
3997        }
3998
3999        msg = og_msg_alloc(buf, len + 1);
4000        if (!msg)
4001                return -1;
4002
4003        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4004                        CLIENTE_OCUPADO, msg);
4005
4006        og_msg_free(msg);
4007
4008        return 0;
4009}
4010
[3ca392f]4011static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
4012{
4013        const char *key;
4014        json_t *value;
[207a74b]4015        int err = 0;
[3ca392f]4016
4017        json_object_foreach(element, key, value) {
4018                if (!strcmp(key, "clients"))
4019                        err = og_json_parse_clients(value, params);
4020
4021                if (err < 0)
4022                        break;
4023        }
4024
[3aac64e]4025        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
4026                return -1;
4027
[207a74b]4028        og_cmd_legacy_send(params, "EjecutaComandosPendientes", CLIENTE_OCUPADO);
[3ca392f]4029
4030        return 0;
4031}
4032
[7258dac]4033static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params)
4034{
4035        char buf[4096] = {};
4036        int err = 0, len;
4037        const char *key;
4038        json_t *value;
4039        TRAMA *msg;
4040
4041        if (json_typeof(element) != JSON_OBJECT)
4042                return -1;
4043
4044        json_object_foreach(element, key, value) {
[6c1b3a9]4045                if (!strcmp(key, "clients")) {
[7258dac]4046                        err = og_json_parse_clients(value, params);
[6c1b3a9]4047                } else if (!strcmp(key, "disk")) {
[7258dac]4048                        err = og_json_parse_string(value, &params->disk);
[6c1b3a9]4049                        params->flags |= OG_REST_PARAM_DISK;
4050                } else if (!strcmp(key, "partition")) {
[7258dac]4051                        err = og_json_parse_string(value, &params->partition);
[6c1b3a9]4052                        params->flags |= OG_REST_PARAM_PARTITION;
4053                } else if (!strcmp(key, "code")) {
[7258dac]4054                        err = og_json_parse_string(value, &params->code);
[6c1b3a9]4055                        params->flags |= OG_REST_PARAM_CODE;
4056                } else if (!strcmp(key, "id")) {
[7258dac]4057                        err = og_json_parse_string(value, &params->id);
[6c1b3a9]4058                        params->flags |= OG_REST_PARAM_ID;
4059                } else if (!strcmp(key, "name")) {
[7258dac]4060                        err = og_json_parse_string(value, &params->name);
[6c1b3a9]4061                        params->flags |= OG_REST_PARAM_NAME;
4062                } else if (!strcmp(key, "repository")) {
[7258dac]4063                        err = og_json_parse_string(value, &params->repository);
[6c1b3a9]4064                        params->flags |= OG_REST_PARAM_REPO;
4065                } else if (!strcmp(key, "sync_params")) {
4066                        err = og_json_parse_sync_params(value, params);
4067                }
[7258dac]4068
4069                if (err < 0)
4070                        break;
4071        }
4072
[6c1b3a9]4073        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4074                                            OG_REST_PARAM_DISK |
4075                                            OG_REST_PARAM_PARTITION |
4076                                            OG_REST_PARAM_CODE |
4077                                            OG_REST_PARAM_ID |
4078                                            OG_REST_PARAM_NAME |
4079                                            OG_REST_PARAM_REPO |
4080                                            OG_REST_PARAM_SYNC_SYNC |
4081                                            OG_REST_PARAM_SYNC_DIFF |
4082                                            OG_REST_PARAM_SYNC_REMOVE |
4083                                            OG_REST_PARAM_SYNC_COMPRESS |
4084                                            OG_REST_PARAM_SYNC_CLEANUP |
4085                                            OG_REST_PARAM_SYNC_CACHE |
4086                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4087                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4088                return -1;
4089
[7258dac]4090        len = snprintf(buf, sizeof(buf),
4091                       "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r"
4092                       "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r"
4093                       "cpc=%s\rbpc=%s\rnba=%s\r",
4094                       params->disk, params->partition, params->code, params->id,
4095                       params->name, params->repository, params->sync_setup.sync,
4096                       params->sync_setup.diff, params->sync_setup.remove,
4097                       params->sync_setup.compress, params->sync_setup.cleanup,
4098                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4099                       params->sync_setup.remove_dst);
4100
4101        msg = og_msg_alloc(buf, len);
4102        if (!msg)
4103                return -1;
4104
4105        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4106                    CLIENTE_OCUPADO, msg);
4107
4108        og_msg_free(msg);
4109
4110        return 0;
4111}
4112
[f72c984]4113static int og_cmd_create_incremental_image(json_t *element, struct og_msg_params *params)
4114{
4115        char buf[4096] = {};
4116        int err = 0, len;
4117        const char *key;
4118        json_t *value;
4119        TRAMA *msg;
4120
4121        if (json_typeof(element) != JSON_OBJECT)
4122                return -1;
4123
4124        json_object_foreach(element, key, value) {
4125                if (!strcmp(key, "clients"))
4126                        err = og_json_parse_clients(value, params);
[3e6623d]4127                else if (!strcmp(key, "disk")) {
[f72c984]4128                        err = og_json_parse_string(value, &params->disk);
[3e6623d]4129                        params->flags |= OG_REST_PARAM_DISK;
4130                } else if (!strcmp(key, "partition")) {
[f72c984]4131                        err = og_json_parse_string(value, &params->partition);
[3e6623d]4132                        params->flags |= OG_REST_PARAM_PARTITION;
4133                } else if (!strcmp(key, "id")) {
[f72c984]4134                        err = og_json_parse_string(value, &params->id);
[3e6623d]4135                        params->flags |= OG_REST_PARAM_ID;
4136                } else if (!strcmp(key, "name")) {
[f72c984]4137                        err = og_json_parse_string(value, &params->name);
[3e6623d]4138                        params->flags |= OG_REST_PARAM_NAME;
4139                } else if (!strcmp(key, "repository")) {
[f72c984]4140                        err = og_json_parse_string(value, &params->repository);
[3e6623d]4141                        params->flags |= OG_REST_PARAM_REPO;
4142                } else if (!strcmp(key, "sync_params")) {
4143                        err = og_json_parse_sync_params(value, params);
4144                }
[f72c984]4145
4146                if (err < 0)
4147                        break;
4148        }
4149
[3e6623d]4150        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4151                                            OG_REST_PARAM_DISK |
4152                                            OG_REST_PARAM_PARTITION |
4153                                            OG_REST_PARAM_ID |
4154                                            OG_REST_PARAM_NAME |
4155                                            OG_REST_PARAM_REPO |
4156                                            OG_REST_PARAM_SYNC_SYNC |
4157                                            OG_REST_PARAM_SYNC_PATH |
4158                                            OG_REST_PARAM_SYNC_DIFF |
4159                                            OG_REST_PARAM_SYNC_DIFF_ID |
4160                                            OG_REST_PARAM_SYNC_DIFF_NAME |
4161                                            OG_REST_PARAM_SYNC_REMOVE |
4162                                            OG_REST_PARAM_SYNC_COMPRESS |
4163                                            OG_REST_PARAM_SYNC_CLEANUP |
4164                                            OG_REST_PARAM_SYNC_CACHE |
4165                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4166                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4167                return -1;
4168
[f72c984]4169        len = snprintf(buf, sizeof(buf),
4170                       "nfn=CrearSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4171                       "rti=%s\ripr=%s\ridf=%s\rncf=%s\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\r"
4172                       "bpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
4173                       params->disk, params->partition, params->id, params->name,
4174                       params->sync_setup.path, params->repository, params->sync_setup.diff_id,
4175                       params->sync_setup.diff_name, params->sync_setup.sync,
4176                       params->sync_setup.diff, params->sync_setup.remove_dst,
4177                       params->sync_setup.compress, params->sync_setup.cleanup,
4178                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4179                       params->sync_setup.remove_dst);
4180
4181        msg = og_msg_alloc(buf, len);
4182        if (!msg)
4183                return -1;
4184
4185        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4186                    CLIENTE_OCUPADO, msg);
4187
4188        og_msg_free(msg);
4189
4190        return 0;
4191}
4192
[d521845]4193static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params)
4194{
4195        char buf[4096] = {};
4196        int err = 0, len;
4197        const char *key;
4198        json_t *value;
4199        TRAMA *msg;
4200
4201        if (json_typeof(element) != JSON_OBJECT)
4202                return -1;
4203
4204        json_object_foreach(element, key, value) {
[bd07a93]4205                if (!strcmp(key, "clients")) {
[d521845]4206                        err = og_json_parse_clients(value, params);
[bd07a93]4207                } else if (!strcmp(key, "disk")) {
[d521845]4208                        err = og_json_parse_string(value, &params->disk);
[bd07a93]4209                        params->flags |= OG_REST_PARAM_DISK;
4210                } else if (!strcmp(key, "partition")) {
[d521845]4211                        err = og_json_parse_string(value, &params->partition);
[bd07a93]4212                        params->flags |= OG_REST_PARAM_PARTITION;
4213                } else if (!strcmp(key, "id")) {
[d521845]4214                        err = og_json_parse_string(value, &params->id);
[bd07a93]4215                        params->flags |= OG_REST_PARAM_ID;
4216                } else if (!strcmp(key, "name")) {
[d521845]4217                        err = og_json_parse_string(value, &params->name);
[bd07a93]4218                        params->flags |= OG_REST_PARAM_NAME;
4219                } else if (!strcmp(key, "repository")) {
[d521845]4220                        err = og_json_parse_string(value, &params->repository);
[bd07a93]4221                        params->flags |= OG_REST_PARAM_REPO;
4222                } else if (!strcmp(key, "profile")) {
[d521845]4223                        err = og_json_parse_string(value, &params->profile);
[bd07a93]4224                        params->flags |= OG_REST_PARAM_PROFILE;
4225                } else if (!strcmp(key, "type")) {
[d521845]4226                        err = og_json_parse_string(value, &params->type);
[bd07a93]4227                        params->flags |= OG_REST_PARAM_TYPE;
4228                } else if (!strcmp(key, "sync_params")) {
4229                        err = og_json_parse_sync_params(value, params);
4230                }
[d521845]4231
4232                if (err < 0)
4233                        break;
4234        }
4235
[bd07a93]4236        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4237                                            OG_REST_PARAM_DISK |
4238                                            OG_REST_PARAM_PARTITION |
4239                                            OG_REST_PARAM_ID |
4240                                            OG_REST_PARAM_NAME |
4241                                            OG_REST_PARAM_REPO |
4242                                            OG_REST_PARAM_PROFILE |
4243                                            OG_REST_PARAM_TYPE |
4244                                            OG_REST_PARAM_SYNC_PATH |
4245                                            OG_REST_PARAM_SYNC_METHOD |
4246                                            OG_REST_PARAM_SYNC_SYNC |
4247                                            OG_REST_PARAM_SYNC_DIFF |
4248                                            OG_REST_PARAM_SYNC_REMOVE |
4249                                            OG_REST_PARAM_SYNC_COMPRESS |
4250                                            OG_REST_PARAM_SYNC_CLEANUP |
4251                                            OG_REST_PARAM_SYNC_CACHE |
4252                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4253                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4254                return -1;
4255
[d521845]4256        len = snprintf(buf, sizeof(buf),
4257                       "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4258                           "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r"
4259                           "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
4260                       params->disk, params->partition, params->id, params->name,
4261                           params->repository, params->profile, params->sync_setup.path,
4262                           params->sync_setup.method, params->sync_setup.sync, params->type,
4263                           params->sync_setup.diff, params->sync_setup.remove,
4264                       params->sync_setup.compress, params->sync_setup.cleanup,
4265                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4266                       params->sync_setup.remove_dst);
4267
4268        msg = og_msg_alloc(buf, len);
4269        if (!msg)
4270                return -1;
4271
4272        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4273                    CLIENTE_OCUPADO, msg);
4274
4275        og_msg_free(msg);
4276
4277        return 0;
4278}
4279
[1707bc6]4280static int og_cmd_restore_incremental_image(json_t *element, struct og_msg_params *params)
4281{
4282        char buf[4096] = {};
4283        int err = 0, len;
4284        const char *key;
4285        json_t *value;
4286        TRAMA *msg;
4287
4288        if (json_typeof(element) != JSON_OBJECT)
4289                return -1;
4290
4291        json_object_foreach(element, key, value) {
[64aef4d]4292                if (!strcmp(key, "clients")) {
[1707bc6]4293                        err = og_json_parse_clients(value, params);
[64aef4d]4294                } else if (!strcmp(key, "disk")) {
[1707bc6]4295                        err = og_json_parse_string(value, &params->disk);
[64aef4d]4296                        params->flags |= OG_REST_PARAM_DISK;
4297                } else if (!strcmp(key, "partition")) {
[1707bc6]4298                        err = og_json_parse_string(value, &params->partition);
[64aef4d]4299                        params->flags |= OG_REST_PARAM_PARTITION;
4300                } else if (!strcmp(key, "id")) {
[1707bc6]4301                        err = og_json_parse_string(value, &params->id);
[64aef4d]4302                        params->flags |= OG_REST_PARAM_ID;
4303                } else if (!strcmp(key, "name")) {
[1707bc6]4304                        err = og_json_parse_string(value, &params->name);
[64aef4d]4305                        params->flags |= OG_REST_PARAM_NAME;
4306                } else if (!strcmp(key, "repository")) {
[1707bc6]4307                        err = og_json_parse_string(value, &params->repository);
[64aef4d]4308                        params->flags |= OG_REST_PARAM_REPO;
4309                } else if (!strcmp(key, "profile")) {
[1707bc6]4310                        err = og_json_parse_string(value, &params->profile);
[64aef4d]4311                        params->flags |= OG_REST_PARAM_PROFILE;
4312                } else if (!strcmp(key, "type")) {
[1707bc6]4313                        err = og_json_parse_string(value, &params->type);
[64aef4d]4314                        params->flags |= OG_REST_PARAM_TYPE;
4315                } else if (!strcmp(key, "sync_params")) {
4316                        err = og_json_parse_sync_params(value, params);
4317                }
[1707bc6]4318
4319                if (err < 0)
4320                        break;
4321        }
4322
[64aef4d]4323        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4324                                            OG_REST_PARAM_DISK |
4325                                            OG_REST_PARAM_PARTITION |
4326                                            OG_REST_PARAM_ID |
4327                                            OG_REST_PARAM_NAME |
4328                                            OG_REST_PARAM_REPO |
4329                                            OG_REST_PARAM_PROFILE |
4330                                            OG_REST_PARAM_TYPE |
4331                                            OG_REST_PARAM_SYNC_DIFF_ID |
4332                                            OG_REST_PARAM_SYNC_DIFF_NAME |
4333                                            OG_REST_PARAM_SYNC_PATH |
4334                                            OG_REST_PARAM_SYNC_METHOD |
4335                                            OG_REST_PARAM_SYNC_SYNC |
4336                                            OG_REST_PARAM_SYNC_DIFF |
4337                                            OG_REST_PARAM_SYNC_REMOVE |
4338                                            OG_REST_PARAM_SYNC_COMPRESS |
4339                                            OG_REST_PARAM_SYNC_CLEANUP |
4340                                            OG_REST_PARAM_SYNC_CACHE |
4341                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4342                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4343                return -1;
4344
[1707bc6]4345        len = snprintf(buf, sizeof(buf),
4346                       "nfn=RestaurarSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4347                           "ipr=%s\rifs=%s\ridf=%s\rncf=%s\rrti=%s\rmet=%s\rmsy=%s\r"
4348                           "tpt=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\r"
4349                           "nba=%s\r",
4350                       params->disk, params->partition, params->id, params->name,
4351                           params->repository, params->profile, params->sync_setup.diff_id,
4352                           params->sync_setup.diff_name, params->sync_setup.path,
4353                           params->sync_setup.method, params->sync_setup.sync, params->type,
4354                           params->sync_setup.diff, params->sync_setup.remove,
4355                       params->sync_setup.compress, params->sync_setup.cleanup,
4356                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4357                       params->sync_setup.remove_dst);
4358
4359        msg = og_msg_alloc(buf, len);
4360        if (!msg)
4361                return -1;
4362
4363        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4364                    CLIENTE_OCUPADO, msg);
4365
4366        og_msg_free(msg);
4367
4368        return 0;
4369}
4370
[e804134]4371static int og_client_method_not_found(struct og_client *cli)
4372{
4373        /* To meet RFC 7231, this function MUST generate an Allow header field
4374         * containing the correct methods. For example: "Allow: POST\r\n"
4375         */
4376        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
4377                     "Content-Length: 0\r\n\r\n";
4378
4379        send(og_client_socket(cli), buf, strlen(buf), 0);
4380
4381        return -1;
4382}
4383
[391f9be]4384static int og_client_bad_request(struct og_client *cli)
4385{
4386        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
4387
4388        send(og_client_socket(cli), buf, strlen(buf), 0);
4389
4390        return -1;
4391}
4392
[1a08c06]4393static int og_client_not_found(struct og_client *cli)
4394{
4395        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
4396
4397        send(og_client_socket(cli), buf, strlen(buf), 0);
4398
4399        return -1;
4400}
4401
[2ccec278]4402static int og_client_not_authorized(struct og_client *cli)
4403{
[f06fcf6f]4404        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
4405                     "WWW-Authenticate: Basic\r\n"
4406                     "Content-Length: 0\r\n\r\n";
[2ccec278]4407
4408        send(og_client_socket(cli), buf, strlen(buf), 0);
4409
4410        return -1;
4411}
4412
[d6852fb]4413static int og_server_internal_error(struct og_client *cli)
4414{
4415        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
4416                     "Content-Length: 0\r\n\r\n";
4417
4418        send(og_client_socket(cli), buf, strlen(buf), 0);
4419
4420        return -1;
4421}
4422
[4d7fd58]4423static int og_client_payload_too_large(struct og_client *cli)
4424{
4425        char buf[] = "HTTP/1.1 413 Payload Too Large\r\n"
4426                     "Content-Length: 0\r\n\r\n";
4427
4428        send(og_client_socket(cli), buf, strlen(buf), 0);
4429
4430        return -1;
4431}
4432
[611f470]4433#define OG_MSG_RESPONSE_MAXLEN  65536
4434
[ea03692]4435static int og_client_ok(struct og_client *cli, char *buf_reply)
[1a08c06]4436{
[611f470]4437        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
[5bbcedc]4438        int err = 0, len;
[ea03692]4439
[5bbcedc]4440        len = snprintf(buf, sizeof(buf),
4441                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
4442                       strlen(buf_reply), buf_reply);
[d6852fb]4443        if (len >= (int)sizeof(buf))
4444                err = og_server_internal_error(cli);
[1a08c06]4445
4446        send(og_client_socket(cli), buf, strlen(buf), 0);
4447
[5bbcedc]4448        return err;
[1a08c06]4449}
4450
4451enum og_rest_method {
4452        OG_METHOD_GET   = 0,
4453        OG_METHOD_POST,
4454};
4455
4456static int og_client_state_process_payload_rest(struct og_client *cli)
4457{
[611f470]4458        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
[1a08c06]4459        struct og_msg_params params = {};
4460        enum og_rest_method method;
[b3467f7]4461        const char *cmd, *body;
[1a08c06]4462        json_error_t json_err;
4463        json_t *root = NULL;
4464        int err = 0;
4465
[2cced2b3]4466        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
4467               inet_ntoa(cli->addr.sin_addr),
4468               ntohs(cli->addr.sin_port), cli->buf);
4469
[1a08c06]4470        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
4471                method = OG_METHOD_GET;
4472                cmd = cli->buf + strlen("GET") + 2;
4473        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
4474                method = OG_METHOD_POST;
4475                cmd = cli->buf + strlen("POST") + 2;
4476        } else
[e804134]4477                return og_client_method_not_found(cli);
[1a08c06]4478
4479        body = strstr(cli->buf, "\r\n\r\n") + 4;
4480
[2ccec278]4481        if (strcmp(cli->auth_token, auth_token)) {
4482                syslog(LOG_ERR, "wrong Authentication key\n");
4483                return og_client_not_authorized(cli);
4484        }
4485
[b3467f7]4486        if (cli->content_length) {
[1a08c06]4487                root = json_loads(body, 0, &json_err);
4488                if (!root) {
4489                        syslog(LOG_ERR, "malformed json line %d: %s\n",
4490                               json_err.line, json_err.text);
4491                        return og_client_not_found(cli);
4492                }
4493        }
4494
4495        if (!strncmp(cmd, "clients", strlen("clients"))) {
[ea03692]4496                if (method != OG_METHOD_POST &&
4497                    method != OG_METHOD_GET)
[e804134]4498                        return og_client_method_not_found(cli);
[ea03692]4499
4500                if (method == OG_METHOD_POST && !root) {
[1a08c06]4501                        syslog(LOG_ERR, "command clients with no payload\n");
[391f9be]4502                        return og_client_bad_request(cli);
[1a08c06]4503                }
[ea03692]4504                switch (method) {
4505                case OG_METHOD_POST:
4506                        err = og_cmd_post_clients(root, &params);
4507                        break;
4508                case OG_METHOD_GET:
4509                        err = og_cmd_get_clients(root, &params, buf_reply);
4510                        break;
4511                }
[73c4bdff]4512        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
4513                if (method != OG_METHOD_POST)
[e804134]4514                        return og_client_method_not_found(cli);
[73c4bdff]4515
4516                if (!root) {
4517                        syslog(LOG_ERR, "command wol with no payload\n");
[391f9be]4518                        return og_client_bad_request(cli);
[73c4bdff]4519                }
4520                err = og_cmd_wol(root, &params);
[775f6f0]4521        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
4522                if (method != OG_METHOD_POST)
[e804134]4523                        return og_client_method_not_found(cli);
[775f6f0]4524
4525                if (!root) {
4526                        syslog(LOG_ERR, "command run with no payload\n");
[391f9be]4527                        return og_client_bad_request(cli);
[775f6f0]4528                }
4529                err = og_cmd_run_post(root, &params);
[165cea3]4530        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
4531                if (method != OG_METHOD_POST)
[e804134]4532                        return og_client_method_not_found(cli);
[165cea3]4533
4534                if (!root) {
4535                        syslog(LOG_ERR, "command output with no payload\n");
[391f9be]4536                        return og_client_bad_request(cli);
[165cea3]4537                }
4538
4539                err = og_cmd_run_get(root, &params, buf_reply);
[22ab637]4540        } else if (!strncmp(cmd, "session", strlen("session"))) {
4541                if (method != OG_METHOD_POST)
[e804134]4542                        return og_client_method_not_found(cli);
[22ab637]4543
4544                if (!root) {
4545                        syslog(LOG_ERR, "command session with no payload\n");
[391f9be]4546                        return og_client_bad_request(cli);
[22ab637]4547                }
4548                err = og_cmd_session(root, &params);
[b231a5a]4549        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
4550                if (method != OG_METHOD_POST)
[e804134]4551                        return og_client_method_not_found(cli);
[b231a5a]4552
4553                if (!root) {
4554                        syslog(LOG_ERR, "command poweroff with no payload\n");
[391f9be]4555                        return og_client_bad_request(cli);
[b231a5a]4556                }
4557                err = og_cmd_poweroff(root, &params);
[68270b3]4558        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
4559                if (method != OG_METHOD_POST)
[e804134]4560                        return og_client_method_not_found(cli);
[68270b3]4561
4562                if (!root) {
4563                        syslog(LOG_ERR, "command reboot with no payload\n");
[391f9be]4564                        return og_client_bad_request(cli);
[68270b3]4565                }
4566                err = og_cmd_reboot(root, &params);
[5513435]4567        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
4568                if (method != OG_METHOD_POST)
[e804134]4569                        return og_client_method_not_found(cli);
[5513435]4570
4571                if (!root) {
4572                        syslog(LOG_ERR, "command stop with no payload\n");
[391f9be]4573                        return og_client_bad_request(cli);
[5513435]4574                }
4575                err = og_cmd_stop(root, &params);
[b317d24]4576        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
4577                if (method != OG_METHOD_POST)
[e804134]4578                        return og_client_method_not_found(cli);
[b317d24]4579
4580                if (!root) {
4581                        syslog(LOG_ERR, "command refresh with no payload\n");
[391f9be]4582                        return og_client_bad_request(cli);
[b317d24]4583                }
4584                err = og_cmd_refresh(root, &params);
[1316c877]4585        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4586                if (method != OG_METHOD_POST)
[e804134]4587                        return og_client_method_not_found(cli);
[1316c877]4588
4589                if (!root) {
4590                        syslog(LOG_ERR, "command hardware with no payload\n");
[391f9be]4591                        return og_client_bad_request(cli);
[1316c877]4592                }
4593                err = og_cmd_hardware(root, &params);
[a0f41fc]4594        } else if (!strncmp(cmd, "software", strlen("software"))) {
4595                if (method != OG_METHOD_POST)
[e804134]4596                        return og_client_method_not_found(cli);
[a0f41fc]4597
4598                if (!root) {
4599                        syslog(LOG_ERR, "command software with no payload\n");
[391f9be]4600                        return og_client_bad_request(cli);
[a0f41fc]4601                }
4602                err = og_cmd_software(root, &params);
[7258dac]4603        } else if (!strncmp(cmd, "image/create/basic",
4604                            strlen("image/create/basic"))) {
4605                if (method != OG_METHOD_POST)
4606                        return og_client_method_not_found(cli);
4607
4608                if (!root) {
4609                        syslog(LOG_ERR, "command create with no payload\n");
4610                        return og_client_bad_request(cli);
4611                }
4612                err = og_cmd_create_basic_image(root, &params);
[f72c984]4613        } else if (!strncmp(cmd, "image/create/incremental",
4614                            strlen("image/create/incremental"))) {
4615                if (method != OG_METHOD_POST)
4616                        return og_client_method_not_found(cli);
4617
4618                if (!root) {
4619                        syslog(LOG_ERR, "command create with no payload\n");
4620                        return og_client_bad_request(cli);
4621                }
4622                err = og_cmd_create_incremental_image(root, &params);
[7f2dd15]4623        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4624                if (method != OG_METHOD_POST)
4625                        return og_client_method_not_found(cli);
4626
4627                if (!root) {
4628                        syslog(LOG_ERR, "command create with no payload\n");
4629                        return og_client_bad_request(cli);
4630                }
4631                err = og_cmd_create_image(root, &params);
[d521845]4632        } else if (!strncmp(cmd, "image/restore/basic",
4633                                strlen("image/restore/basic"))) {
4634                if (method != OG_METHOD_POST)
4635                        return og_client_method_not_found(cli);
4636
4637                if (!root) {
4638                        syslog(LOG_ERR, "command create with no payload\n");
4639                        return og_client_bad_request(cli);
4640                }
4641                err = og_cmd_restore_basic_image(root, &params);
[1707bc6]4642        } else if (!strncmp(cmd, "image/restore/incremental",
4643                                strlen("image/restore/incremental"))) {
4644                if (method != OG_METHOD_POST)
4645                        return og_client_method_not_found(cli);
4646
4647                if (!root) {
4648                        syslog(LOG_ERR, "command create with no payload\n");
4649                        return og_client_bad_request(cli);
4650                }
4651                err = og_cmd_restore_incremental_image(root, &params);
[fc15dd1]4652        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4653                if (method != OG_METHOD_POST)
4654                        return og_client_method_not_found(cli);
4655
4656                if (!root) {
4657                        syslog(LOG_ERR, "command create with no payload\n");
4658                        return og_client_bad_request(cli);
4659                }
4660                err = og_cmd_restore_image(root, &params);
[9381fdf]4661        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
[2385710e]4662                if (method != OG_METHOD_POST)
4663                        return og_client_method_not_found(cli);
4664
4665                if (!root) {
4666                        syslog(LOG_ERR, "command create with no payload\n");
4667                        return og_client_bad_request(cli);
4668                }
[9381fdf]4669                err = og_cmd_setup(root, &params);
[3ca392f]4670        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4671                if (method != OG_METHOD_POST)
4672                        return og_client_method_not_found(cli);
4673
4674                if (!root) {
4675                        syslog(LOG_ERR, "command create with no payload\n");
4676                        return og_client_bad_request(cli);
4677                }
4678
4679                err = og_cmd_run_schedule(root, &params);
[1a08c06]4680        } else {
[ca239ad]4681                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
[1a08c06]4682                err = og_client_not_found(cli);
4683        }
4684
[ea03692]4685        if (root)
4686                json_decref(root);
[1a08c06]4687
[0c1ff40]4688        if (err < 0)
[2f3d7f53]4689                return og_client_bad_request(cli);
[0c1ff40]4690
4691        err = og_client_ok(cli, buf_reply);
4692        if (err < 0) {
4693                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4694                       inet_ntoa(cli->addr.sin_addr),
4695                       ntohs(cli->addr.sin_port));
4696        }
[1a08c06]4697
4698        return err;
4699}
4700
4701static int og_client_state_recv_hdr_rest(struct og_client *cli)
4702{
[b3467f7]4703        char *ptr;
[1a08c06]4704
[b3467f7]4705        ptr = strstr(cli->buf, "\r\n\r\n");
4706        if (!ptr)
[1a08c06]4707                return 0;
4708
[b3467f7]4709        cli->msg_len = ptr - cli->buf + 4;
4710
4711        ptr = strstr(cli->buf, "Content-Length: ");
4712        if (ptr) {
4713                sscanf(ptr, "Content-Length: %i[^\r\n]", &cli->content_length);
[8793b71]4714                if (cli->content_length < 0)
4715                        return -1;
[b3467f7]4716                cli->msg_len += cli->content_length;
4717        }
4718
[2ccec278]4719        ptr = strstr(cli->buf, "Authorization: ");
4720        if (ptr)
[ba5651bc]4721                sscanf(ptr, "Authorization: %63[^\r\n]", cli->auth_token);
[2ccec278]4722
[1a08c06]4723        return 1;
4724}
4725
[07c51e2]4726static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
4727{
4728        struct og_client *cli;
4729        int ret;
[9baecf8]4730
4731        cli = container_of(io, struct og_client, io);
4732
[2e0c063]4733        if (events & EV_ERROR) {
4734                syslog(LOG_ERR, "unexpected error event from client %s:%hu\n",
4735                               inet_ntoa(cli->addr.sin_addr),
4736                               ntohs(cli->addr.sin_port));
4737                goto close;
4738        }
4739
[9baecf8]4740        ret = recv(io->fd, cli->buf + cli->buf_len,
4741                   sizeof(cli->buf) - cli->buf_len, 0);
[2e0c063]4742        if (ret <= 0) {
4743                if (ret < 0) {
4744                        syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n",
4745                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
4746                               strerror(errno));
4747                } else {
[0e16db2]4748                        syslog(LOG_DEBUG, "closed connection by %s:%hu\n",
[2e0c063]4749                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
4750                }
[9baecf8]4751                goto close;
[2e0c063]4752        }
4753
4754        if (cli->keepalive_idx >= 0)
4755                return;
[9baecf8]4756
4757        ev_timer_again(loop, &cli->timer);
4758
4759        cli->buf_len += ret;
[d8a2d5f]4760        if (cli->buf_len >= sizeof(cli->buf)) {
4761                syslog(LOG_ERR, "client request from %s:%hu is too long\n",
4762                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[4d7fd58]4763                og_client_payload_too_large(cli);
[d8a2d5f]4764                goto close;
4765        }
[9baecf8]4766
4767        switch (cli->state) {
4768        case OG_CLIENT_RECEIVING_HEADER:
[1a08c06]4769                if (cli->rest)
4770                        ret = og_client_state_recv_hdr_rest(cli);
4771                else
4772                        ret = og_client_state_recv_hdr(cli);
4773
[39c3261]4774                if (ret < 0)
[9baecf8]4775                        goto close;
[39c3261]4776                if (!ret)
4777                        return;
[9baecf8]4778
4779                cli->state = OG_CLIENT_RECEIVING_PAYLOAD;
4780                /* Fall through. */
4781        case OG_CLIENT_RECEIVING_PAYLOAD:
4782                /* Still not enough data to process request. */
4783                if (cli->buf_len < cli->msg_len)
4784                        return;
4785
4786                cli->state = OG_CLIENT_PROCESSING_REQUEST;
4787                /* fall through. */
4788        case OG_CLIENT_PROCESSING_REQUEST:
[0c1ff40]4789                if (cli->rest) {
[1a08c06]4790                        ret = og_client_state_process_payload_rest(cli);
[0c1ff40]4791                        if (ret < 0) {
4792                                syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n",
4793                                       inet_ntoa(cli->addr.sin_addr),
4794                                       ntohs(cli->addr.sin_port));
4795                        }
4796                } else {
[1a08c06]4797                        ret = og_client_state_process_payload(cli);
[0c1ff40]4798                }
[07c51e2]4799                if (ret < 0)
[9baecf8]4800                        goto close;
4801
[2e0c063]4802                if (cli->keepalive_idx < 0) {
[0e16db2]4803                        syslog(LOG_DEBUG, "server closing connection to %s:%hu\n",
[2e0c063]4804                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[9baecf8]4805                        goto close;
[2e0c063]4806                } else {
[0e16db2]4807                        syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n",
[2e0c063]4808                               inet_ntoa(cli->addr.sin_addr),
4809                               ntohs(cli->addr.sin_port));
4810                        og_client_keepalive(loop, cli);
4811                        og_client_reset_state(cli);
4812                }
[9baecf8]4813                break;
[13e48b4]4814        default:
4815                syslog(LOG_ERR, "unknown state, critical internal error\n");
4816                goto close;
[f997cc1]4817        }
[9baecf8]4818        return;
4819close:
4820        ev_timer_stop(loop, &cli->timer);
[2e0c063]4821        og_client_release(loop, cli);
[f997cc1]4822}
4823
[9baecf8]4824static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events)
4825{
4826        struct og_client *cli;
4827
4828        cli = container_of(timer, struct og_client, timer);
[2e0c063]4829        if (cli->keepalive_idx >= 0) {
[9baecf8]4830                ev_timer_again(loop, &cli->timer);
4831                return;
4832        }
[2e0c063]4833        syslog(LOG_ERR, "timeout request for client %s:%hu\n",
4834               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[13e48b4]4835
[2e0c063]4836        og_client_release(loop, cli);
[9baecf8]4837}
4838
[1a08c06]4839static int socket_s, socket_rest;
4840
[9baecf8]4841static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io,
4842                                int events)
4843{
4844        struct sockaddr_in client_addr;
4845        socklen_t addrlen = sizeof(client_addr);
4846        struct og_client *cli;
4847        int client_sd;
4848
4849        if (events & EV_ERROR)
4850                return;
4851
4852        client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen);
4853        if (client_sd < 0) {
[8c04716]4854                syslog(LOG_ERR, "cannot accept client connection\n");
[9baecf8]4855                return;
4856        }
4857
4858        cli = (struct og_client *)calloc(1, sizeof(struct og_client));
4859        if (!cli) {
4860                close(client_sd);
4861                return;
4862        }
[13e48b4]4863        memcpy(&cli->addr, &client_addr, sizeof(client_addr));
[2e0c063]4864        cli->keepalive_idx = -1;
[13e48b4]4865
[1a08c06]4866        if (io->fd == socket_rest)
4867                cli->rest = true;
4868
[0e16db2]4869        syslog(LOG_DEBUG, "connection from client %s:%hu\n",
[2e0c063]4870               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[9baecf8]4871
4872        ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ);
4873        ev_io_start(loop, &cli->io);
4874        ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.);
4875        ev_timer_start(loop, &cli->timer);
4876}
4877
[588052e]4878static int og_socket_server_init(const char *port)
4879{
4880        struct sockaddr_in local;
4881        int sd, on = 1;
4882
4883        sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
4884        if (sd < 0) {
4885                syslog(LOG_ERR, "cannot create main socket\n");
4886                return -1;
4887        }
4888        setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
4889
4890        local.sin_addr.s_addr = htonl(INADDR_ANY);
4891        local.sin_family = AF_INET;
4892        local.sin_port = htons(atoi(port));
4893
4894        if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) {
[438afb2]4895                close(sd);
[588052e]4896                syslog(LOG_ERR, "cannot bind socket\n");
4897                return -1;
4898        }
4899
4900        listen(sd, 250);
4901
4902        return sd;
4903}
4904
[9baecf8]4905int main(int argc, char *argv[])
4906{
[1a08c06]4907        struct ev_io ev_io_server, ev_io_server_rest;
[9baecf8]4908        struct ev_loop *loop = ev_default_loop(0);
4909        int i;
[3ec149c]4910
[4797e93]4911        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
4912                exit(EXIT_FAILURE);
4913
[b11b753]4914        openlog("ogAdmServer", LOG_PID, LOG_DAEMON);
[13e48b4]4915
[3ec149c]4916        /*--------------------------------------------------------------------------------------------------------
4917         Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
4918         ---------------------------------------------------------------------------------------------------------*/
4919        if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución
4920                exit(EXIT_FAILURE);
4921
4922        if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
4923                exit(EXIT_FAILURE);
4924        }
4925
4926        /*--------------------------------------------------------------------------------------------------------
4927         // Inicializa array de información de los clientes
4928         ---------------------------------------------------------------------------------------------------------*/
4929        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
4930                tbsockets[i].ip[0] = '\0';
[2e0c063]4931                tbsockets[i].cli = NULL;
[3ec149c]4932        }
4933        /*--------------------------------------------------------------------------------------------------------
4934         Creación y configuración del socket del servicio
4935         ---------------------------------------------------------------------------------------------------------*/
[588052e]4936        socket_s = og_socket_server_init(puerto);
4937        if (socket_s < 0)
[3ec149c]4938                exit(EXIT_FAILURE);
[9baecf8]4939
4940        ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ);
4941        ev_io_start(loop, &ev_io_server);
4942
[1a08c06]4943        socket_rest = og_socket_server_init("8888");
4944        if (socket_rest < 0)
4945                exit(EXIT_FAILURE);
4946
4947        ev_io_init(&ev_io_server_rest, og_server_accept_cb, socket_rest, EV_READ);
4948        ev_io_start(loop, &ev_io_server_rest);
4949
[3ec149c]4950        infoLog(1); // Inicio de sesión
[9baecf8]4951
[256fbf2]4952        /* old log file has been deprecated. */
4953        og_log(97, false);
4954
[13e48b4]4955        syslog(LOG_INFO, "Waiting for connections\n");
4956
[9baecf8]4957        while (1)
4958                ev_loop(loop, 0);
4959
[3ec149c]4960        exit(EXIT_SUCCESS);
4961}
Note: See TracBrowser for help on using the repository browser.