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

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

#559 fixes memory leak in tomaConfiguracion()

Calls fclose() after fopen() to release memory.

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