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

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

#915 add POST refresh command to REST API in ogAdmServer

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

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

Request

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

Reply:

200 OK

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