source: ogServer-Git/sources/ogAdmServer.cpp @ 99c6c62

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

#915 remove Actualizar(), Purgar(), Reiniciar() and IniciarSesion?()

The new REST API obsoletes the following commands:

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