source: ogServer-Git/sources/ogAdmServer.cpp @ 727a109

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

#915 validate message length based on announced Content-Length field

Otherwise, TCP segmentation leads to handle an incomplete payload, this
problems manifests with errors when parsing the json body.

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