source: ogServer-Git/sources/ogAdmServer.cpp @ 496f5eb

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

#915 validate message length based on announced Content-Length field

Otherwise, TCP segmentation leads to handle an incomplete payload, this
problems manifests with errors when parsing the json body.

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