source: ogServer-Git/sources/ogAdmServer.cpp @ f482bda

Last change on this file since f482bda was f482bda, checked in by OpenGnSys Support Team <soporte-og@…>, 5 years ago

#941 use dbi layer from RESPUESTA_CrearSoftIncremental

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