source: ogServer-Git/sources/ogAdmServer.c @ 6a0fcf9

Last change on this file since 6a0fcf9 was 54d172e, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

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

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

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

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

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