source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.cpp @ 9e0f6c9

918-git-images-111dconfigfileconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacion
Last change on this file since 9e0f6c9 was f06fcf6f, checked in by OpenGnSys Support Team <soporte-og@…>, 6 years ago

#915 returns 401 when incorrect authentication happens

ogAdmServer REST API now meets the starndar RFC 7235 when incorrect auth
happens.

og_client_not_authorized() now sends "401 Unauthorized" and
"WWW-Authenticate" instead of 404.

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