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

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

#915 add support for HTTP Authorization

Add APITOKEN= field to ogAdmServer.cfg to specify the REST API key.

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