source: ogServer-Git/sources/ogAdmServer.cpp @ 17f55b4

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

#915 add POST refresh command to REST API in ogAdmServer

Forces client to fetch and run any pending command from the server,
reload its local configuration file and re-start its selection menu.

curl -X POST http://127.0.0.1:8888/refresh -d @refresh.json

Request

POST /refresh
{"clients": [ "192.168.2.1" ] }

Reply:

200 OK

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