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

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

#915 add support for HTTP Authorization

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

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