source: ogServer-Git/sources/ogAdmServer.cpp @ 9cc156c

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

#941 use dbi layer from actualizaCreacionImagen()

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