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

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

#941 Consolidate CrearSoftIncremental?, RestaurarImagenBasica?, RestaurarSoftIncremental?, Configurar and EjecutarScript?

These functions are identical, remove duplicated code.

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