source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.c @ f3499a3

918-git-images-111dconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacion opengnsys-1.1.1b
Last change on this file since f3499a3 was 4d7fd58, checked in by OpenGnSys Support Team <soporte-og@…>, 5 years ago

#915: Reply 413 status code when no payload is too large

If the payload is too long, then the API returns a 413 status code
(following RFC 7231) instead of the resetting the communication without
replying. This way it should be more clear when this problem is
happening.

The other commit I did related to the issue of the payload size
(1d9d93c) said that ogAdmServer do not log anything when it receives a
payload of a bigger size than supported, this is false. ogAdmServer
prints the next message to the syslog when this happens:

ogAdmServer[6824]: client request from 127.0.0.1:43552 is too long

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