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

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

#915 Validate POST /poweroff REST API parameters

This patch ensures that all required parameters are sent in the request.

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