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

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

#915 Add POST "image/restore/basic" command to REST API in ogAdmServer

This patch implements the command "image/restore/basic" that provides
partitioning and formatting functionality.

Request:

POST /image/restore/basic
{

"clients":[

"192.168.56.11"

],
"disk":"1",
"partition":"1",
"id":"9",
"name":"test",
"repository":"192.168.56.10",
"profile":"17",
"type":"UNICAST",
"sync_params":{

"path":"",
"method":"1",
"sync":"1",
"diff":"0",
"remove":"1",
"compress":"0",
"cleanup":"0",
"cache":"0",
"cleanup_cache":"0",
"remove_dst":"0"

}

}

Reply:

200 OK

  • Property mode set to 100644
File size: 142.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
1071        ids = copiaParametro("ids",ptrTrama); // Toma identificador de la sesión
1072
1073        if (ids == NULL) // No existe seguimiento de la acción
[9dea2d6]1074                return true;
1075
[eb99080]1076        if (atoi(ids) == 0){ // No existe seguimiento de la acción
1077                liberaMemoria(ids);
[9dea2d6]1078                return true;
[eb99080]1079        }
[b9eb98b]1080
1081        sprintf(sqlstr,
[eb99080]1082                        "SELECT * FROM acciones WHERE idordenador=%s"
1083                        " AND sesion=%s ORDER BY idaccion", ido,ids);
1084
1085        liberaMemoria(ids);
1086
[b56cbeb]1087        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1088                db.GetErrorErrStr(msglog);
[b56cbeb]1089                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1090                       __func__, __LINE__, msglog);
[9dea2d6]1091                return false;
[b9eb98b]1092        }
[b56cbeb]1093        if (tbl.ISEOF()) {
1094                syslog(LOG_ERR, "no actions available\n");
[9dea2d6]1095                return true;
[b9eb98b]1096        }
[eb99080]1097        if (!tbl.Get("idaccion", idaccion)) { // Toma identificador de la accion
1098                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1099                og_info(msglog);
[9dea2d6]1100                return false;
[eb99080]1101        }
[b9eb98b]1102        st = tomaHora();
1103        sprintf(fechafin, "%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1,
1104                        st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
1105
[eb99080]1106        res = copiaParametro("res",ptrTrama); // Toma resultado
1107        der = copiaParametro("der",ptrTrama); // Toma descripción del error (si hubiera habido)
1108       
[28cc16b]1109        sprintf(sqlstr,
1110                        "UPDATE acciones"\
1111                        "   SET resultado='%s',estado='%d',fechahorafin='%s',descrinotificacion='%s'"\
[eb99080]1112                        " WHERE idordenador=%s AND idaccion=%d",
1113                        res, ACCION_FINALIZADA, fechafin, der, ido, idaccion);
1114                       
[b9eb98b]1115        if (!db.Execute(sqlstr, tbl)) { // Error al actualizar
[eb99080]1116                liberaMemoria(res);
1117                liberaMemoria(der);
[b9eb98b]1118                db.GetErrorErrStr(msglog);
[9764185]1119                og_info(msglog);
[9dea2d6]1120                return false;
[b9eb98b]1121        }
[eb99080]1122       
1123        liberaMemoria(der);
1124       
[28cc16b]1125        if (atoi(res) == ACCION_FALLIDA) {
1126                liberaMemoria(res);
[9dea2d6]1127                return false; // Error en la ejecución del comando
[28cc16b]1128        }
[b9eb98b]1129
[28cc16b]1130        liberaMemoria(res);
[9dea2d6]1131        return true;
[b9eb98b]1132}
[e979fd2]1133
1134static bool og_send_cmd(char *ips_array[], int ips_array_len,
1135                        const char *state, TRAMA *ptrTrama)
1136{
1137        int i, idx;
1138
1139        for (i = 0; i < ips_array_len; i++) {
1140                if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos
1141                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
1142
1143                        strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente
[3e8fcf0]1144                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[e979fd2]1145                                syslog(LOG_ERR, "failed to send response to %s:%s\n",
1146                                       ips_array[i], strerror(errno));
1147                        }
1148                }
1149        }
1150        return true;
1151}
1152
[b9eb98b]1153// ________________________________________________________________________________________________________
1154// Función: enviaComando
1155//
1156//      Descripción:
1157//              Envía un comando a los clientes
1158//      Parámetros:
1159//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1160//              - estado: Estado en el se deja al cliente mientras se ejecuta el comando
1161//      Devuelve:
[9dea2d6]1162//              true: Si el proceso es correcto
1163//              false: En caso de ocurrir algún error
[b9eb98b]1164// ________________________________________________________________________________________________________
[f74067f]1165bool enviaComando(TRAMA* ptrTrama, const char *estado)
[59fb4d5]1166{
[b9eb98b]1167        char *iph, *Ipes, *ptrIpes[MAXIMOS_CLIENTES];
[e979fd2]1168        int lon;
[b9eb98b]1169
1170        iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP
1171        lon = strlen(iph); // Calcula longitud de la cadena de direccion/es IPE/S
1172        Ipes = (char*) reservaMemoria(lon + 1);
1173        if (Ipes == NULL) {
[b56cbeb]1174                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]1175                return false;
[b9eb98b]1176        }
[eb99080]1177       
[b9eb98b]1178        strcpy(Ipes, iph); // Copia cadena de IPES
[eb99080]1179        liberaMemoria(iph);
1180
[b9eb98b]1181        lon = splitCadena(ptrIpes, Ipes, ';');
1182        FINCADaINTRO(ptrTrama);
[f09aca6]1183
[e979fd2]1184        if (!og_send_cmd(ptrIpes, lon, estado, ptrTrama))
1185                return false;
1186
[7f46c45]1187        liberaMemoria(Ipes);
[9dea2d6]1188        return true;
[b9eb98b]1189}
1190//______________________________________________________________________________________________________
1191// Función: respuestaConsola
1192//
1193//      Descripción:
1194//              Envia una respuesta a la consola sobre el resultado de la ejecución de un comando
1195//      Parámetros:
1196//              - socket_c: (Salida) Socket utilizado para el envío
1197//              - res: Resultado del envío del comando
1198//      Devuelve:
[9dea2d6]1199//              true: Si el proceso es correcto
1200//              false: En caso de ocurrir algún error
[b9eb98b]1201// ________________________________________________________________________________________________________
[59fb4d5]1202bool respuestaConsola(int socket_c, TRAMA *ptrTrama, int res)
1203{
[b9eb98b]1204        initParametros(ptrTrama,0);
1205        sprintf(ptrTrama->parametros, "res=%d\r", res);
[07d2b73]1206        if (!mandaTrama(&socket_c, ptrTrama)) {
[b56cbeb]1207                syslog(LOG_ERR, "%s:%d failed to send response: %s\n",
1208                       __func__, __LINE__, strerror(errno));
[9dea2d6]1209                return false;
[b9eb98b]1210        }
[9dea2d6]1211        return true;
[b9eb98b]1212}
1213// ________________________________________________________________________________________________________
1214// Función: Levanta
1215//
1216//      Descripción:
1217//              Enciende ordenadores a través de la red cuyas macs se pasan como parámetro
1218//      Parámetros:
[0cee7a6]1219//              - iph: Cadena de direcciones ip separadas por ";"
[b9eb98b]1220//              - mac: Cadena de direcciones mac separadas por ";"
[0cee7a6]1221//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
[b9eb98b]1222//      Devuelve:
[9dea2d6]1223//              true: Si el proceso es correcto
1224//              false: En caso de ocurrir algún error
[b9eb98b]1225// ________________________________________________________________________________________________________
[507c75c]1226
1227bool Levanta(char *ptrIP[], char *ptrMacs[], int lon, char *mar)
[0cee7a6]1228{
[63a3d4d]1229        unsigned int on = 1;
1230        sockaddr_in local;
[507c75c]1231        int i, res;
[b38ed0d]1232        int s;
[b9eb98b]1233
1234        /* Creación de socket para envío de magig packet */
1235        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
[28b435c]1236        if (s < 0) {
[b56cbeb]1237                syslog(LOG_ERR, "cannot create socket for magic packet\n");
[9dea2d6]1238                return false;
[b9eb98b]1239        }
[63a3d4d]1240        res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on,
1241                         sizeof(on));
[28b435c]1242        if (res < 0) {
[b56cbeb]1243                syslog(LOG_ERR, "cannot set broadcast socket\n");
[9dea2d6]1244                return false;
[b9eb98b]1245        }
[63a3d4d]1246        memset(&local, 0, sizeof(local));
[b9eb98b]1247        local.sin_family = AF_INET;
[63a3d4d]1248        local.sin_port = htons(PUERTO_WAKEUP);
1249        local.sin_addr.s_addr = htonl(INADDR_ANY);
1250
[b9eb98b]1251        for (i = 0; i < lon; i++) {
[b38ed0d]1252                if (!WakeUp(s, ptrIP[i], ptrMacs[i], mar)) {
[b56cbeb]1253                        syslog(LOG_ERR, "problem sending magic packet\n");
[b9eb98b]1254                        close(s);
[9dea2d6]1255                        return false;
[b9eb98b]1256                }
1257        }
1258        close(s);
[9dea2d6]1259        return true;
[b9eb98b]1260}
[2baf362]1261
1262#define OG_WOL_SEQUENCE         6
1263#define OG_WOL_MACADDR_LEN      6
1264#define OG_WOL_REPEAT           16
1265
1266struct wol_msg {
1267        char secuencia_FF[OG_WOL_SEQUENCE];
1268        char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN];
1269};
1270
1271static bool wake_up_broadcast(int sd, struct sockaddr_in *client,
1272                              const struct wol_msg *msg)
1273{
1274        struct sockaddr_in *broadcast_addr;
1275        struct ifaddrs *ifaddr, *ifa;
1276        int ret;
1277
1278        if (getifaddrs(&ifaddr) < 0) {
1279                syslog(LOG_ERR, "cannot get list of addresses\n");
1280                return false;
1281        }
1282
1283        client->sin_addr.s_addr = htonl(INADDR_BROADCAST);
1284
1285        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1286                if (ifa->ifa_addr == NULL ||
1287                    ifa->ifa_addr->sa_family != AF_INET ||
1288                    strcmp(ifa->ifa_name, interface) != 0)
1289                        continue;
1290
1291                broadcast_addr =
1292                        (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr;
1293                client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr;
1294                break;
1295        }
[8322fd6]1296        freeifaddrs(ifaddr);
[2baf362]1297
1298        ret = sendto(sd, msg, sizeof(*msg), 0,
1299                     (sockaddr *)client, sizeof(*client));
1300        if (ret < 0) {
1301                syslog(LOG_ERR, "failed to send broadcast wol\n");
1302                return false;
1303        }
1304
1305        return true;
1306}
1307
1308static bool wake_up_unicast(int sd, struct sockaddr_in *client,
1309                            const struct wol_msg *msg,
1310                            const struct in_addr *addr)
1311{
1312        int ret;
1313
1314        client->sin_addr.s_addr = addr->s_addr;
1315
1316        ret = sendto(sd, msg, sizeof(*msg), 0,
1317                     (sockaddr *)client, sizeof(*client));
1318        if (ret < 0) {
1319                syslog(LOG_ERR, "failed to send unicast wol\n");
1320                return false;
1321        }
1322
1323        return true;
1324}
1325
1326enum wol_delivery_type {
1327        OG_WOL_BROADCAST = 1,
1328        OG_WOL_UNICAST = 2
1329};
1330
[b9eb98b]1331//_____________________________________________________________________________________________________________
1332// Función: WakeUp
1333//
1334//       Descripción:
1335//              Enciende el ordenador cuya MAC se pasa como parámetro
1336//      Parámetros:
1337//              - s : Socket para enviar trama magic packet
[0cee7a6]1338//              - iph : Cadena con la dirección ip
[b9eb98b]1339//              - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX
[0cee7a6]1340//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
[b9eb98b]1341//      Devuelve:
[9dea2d6]1342//              true: Si el proceso es correcto
1343//              false: En caso de ocurrir algún error
[b9eb98b]1344//_____________________________________________________________________________________________________________
[0cee7a6]1345//
[b38ed0d]1346bool WakeUp(int s, char* iph, char *mac, char *mar)
[0cee7a6]1347{
[429bd36]1348        unsigned int macaddr[OG_WOL_MACADDR_LEN];
[2baf362]1349        char HDaddress_bin[OG_WOL_MACADDR_LEN];
1350        struct sockaddr_in WakeUpCliente;
1351        struct wol_msg Trama_WakeUp;
1352        struct in_addr addr;
1353        bool ret;
1354        int i;
[b9eb98b]1355
1356        for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF)
1357                Trama_WakeUp.secuencia_FF[i] = 0xFF;
1358
[63a3d4d]1359        sscanf(mac, "%02x%02x%02x%02x%02x%02x",
[429bd36]1360               &macaddr[0], &macaddr[1], &macaddr[2],
1361               &macaddr[3], &macaddr[4], &macaddr[5]);
1362
1363        for (i = 0; i < 6; i++)
1364                HDaddress_bin[i] = (uint8_t)macaddr[i];
[b9eb98b]1365
1366        for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC
1367                memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6);
1368
1369        /* Creación de socket del cliente que recibe la trama magic packet */
1370        WakeUpCliente.sin_family = AF_INET;
1371        WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP);
1372
[2baf362]1373        switch (atoi(mar)) {
1374        case OG_WOL_BROADCAST:
[b38ed0d]1375                ret = wake_up_broadcast(s, &WakeUpCliente, &Trama_WakeUp);
[2baf362]1376                break;
1377        case OG_WOL_UNICAST:
1378                if (inet_aton(iph, &addr) < 0) {
1379                        syslog(LOG_ERR, "bad IP address for unicast wol\n");
1380                        ret = false;
1381                        break;
1382                }
[b38ed0d]1383                ret = wake_up_unicast(s, &WakeUpCliente, &Trama_WakeUp, &addr);
[2baf362]1384                break;
1385        default:
1386                syslog(LOG_ERR, "unknown wol type\n");
1387                ret = false;
1388                break;
1389        }
1390        return ret;
[b9eb98b]1391}
1392// ________________________________________________________________________________________________________
1393// Función: RESPUESTA_Arrancar
1394//
1395//      Descripción:
[28cc16b]1396//              Respuesta del cliente al comando Arrancar
[b9eb98b]1397//      Parámetros:
1398//              - socket_c: Socket del cliente que envió el mensaje
1399//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1400//      Devuelve:
[9dea2d6]1401//              true: Si el proceso es correcto
1402//              false: En caso de ocurrir algún error
[b9eb98b]1403// ________________________________________________________________________________________________________
[212280e]1404static bool RESPUESTA_Arrancar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1405{
[b9eb98b]1406        char msglog[LONSTD];
1407        Database db;
1408        Table tbl;
1409        int i;
1410        char *iph, *ido;
1411        char *tpc;
1412
[b56cbeb]1413        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1414                db.GetErrorErrStr(msglog);
[b56cbeb]1415                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1416                       __func__, __LINE__, msglog);
[9dea2d6]1417                return false;
[b9eb98b]1418        }
1419
1420        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1421        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1422
1423        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1424                liberaMemoria(iph);
1425                liberaMemoria(ido);
[b56cbeb]1426                syslog(LOG_ERR, "failed to register notification\n");
1427                return false;
[b9eb98b]1428        }
1429
1430        tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.)
1431        if (clienteExistente(iph, &i)) // Actualiza estado
1432                strcpy(tbsockets[i].estado, tpc);
[eb99080]1433               
1434        liberaMemoria(iph);
1435        liberaMemoria(ido);
1436        liberaMemoria(tpc);
1437       
[b9eb98b]1438        db.Close(); // Cierra conexión
[9dea2d6]1439        return true;
[b9eb98b]1440}
1441// ________________________________________________________________________________________________________
1442// Función: RESPUESTA_Apagar
1443//
1444//      Descripción:
1445//              Respuesta del cliente al comando Apagar
1446//      Parámetros:
1447//              - socket_c: Socket del cliente que envió el mensaje
1448//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1449//      Devuelve:
[9dea2d6]1450//              true: Si el proceso es correcto
1451//              false: En caso de ocurrir algún error
[b9eb98b]1452// ________________________________________________________________________________________________________
[212280e]1453static bool RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1454{
[b9eb98b]1455        char msglog[LONSTD];
1456        Database db;
1457        Table tbl;
1458        int i;
1459        char *iph, *ido;
1460
[b56cbeb]1461        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1462                db.GetErrorErrStr(msglog);
[b56cbeb]1463                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1464                       __func__, __LINE__, msglog);
[9dea2d6]1465                return false;
[b9eb98b]1466        }
1467
1468        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1469        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1470
1471        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1472                liberaMemoria(iph);
1473                liberaMemoria(ido);
[b56cbeb]1474                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1475                return false; // Error al registrar notificacion
[b9eb98b]1476        }
1477
1478        if (clienteExistente(iph, &i)) // Actualiza estado
1479                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1480       
1481        liberaMemoria(iph);
1482        liberaMemoria(ido);
1483       
[b9eb98b]1484        db.Close(); // Cierra conexión
[9dea2d6]1485        return true;
[b9eb98b]1486}
1487// ________________________________________________________________________________________________________
1488// Función: RESPUESTA_Reiniciar
1489//
1490//      Descripción:
1491//              Respuesta del cliente al comando Reiniciar
1492//      Parámetros:
1493//              - socket_c: Socket del cliente que envió el mensaje
1494//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1495//      Devuelve:
[9dea2d6]1496//              true: Si el proceso es correcto
1497//              false: En caso de ocurrir algún error
[b9eb98b]1498// ________________________________________________________________________________________________________
[212280e]1499static bool RESPUESTA_Reiniciar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1500{
[b9eb98b]1501        char msglog[LONSTD];
1502        Database db;
1503        Table tbl;
1504        int i;
1505        char *iph, *ido;
1506
[b56cbeb]1507        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1508                db.GetErrorErrStr(msglog);
[b56cbeb]1509                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1510                       __func__, __LINE__, msglog);
[9dea2d6]1511                return false;
[b9eb98b]1512        }
1513
1514        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1515        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1516
1517        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1518                liberaMemoria(iph);
1519                liberaMemoria(ido);
[b56cbeb]1520                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1521                return false; // Error al registrar notificacion
[b9eb98b]1522        }
1523
1524        if (clienteExistente(iph, &i)) // Actualiza estado
1525                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1526       
1527        liberaMemoria(iph);
1528        liberaMemoria(ido);
[b9eb98b]1529
1530        db.Close(); // Cierra conexión
[9dea2d6]1531        return true;
[b9eb98b]1532}
1533// ________________________________________________________________________________________________________
1534// Función: RESPUESTA_IniciarSesion
1535//
1536//      Descripción:
1537//              Respuesta del cliente al comando Iniciar Sesión
1538//      Parámetros:
1539//              - socket_c: Socket del cliente que envió el mensaje
1540//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1541//      Devuelve:
[9dea2d6]1542//              true: Si el proceso es correcto
1543//              false: En caso de ocurrir algún error
[b9eb98b]1544// ________________________________________________________________________________________________________
[212280e]1545static bool RESPUESTA_IniciarSesion(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1546{
[b9eb98b]1547        char msglog[LONSTD];
1548        Database db;
1549        Table tbl;
1550        int i;
1551        char *iph, *ido;
1552
[b56cbeb]1553        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1554                db.GetErrorErrStr(msglog);
[b56cbeb]1555                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1556                       __func__, __LINE__, msglog);
[9dea2d6]1557                return false;
[b9eb98b]1558        }
1559
1560        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1561        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1562
1563        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1564                liberaMemoria(iph);
1565                liberaMemoria(ido);
[b56cbeb]1566                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1567                return false; // Error al registrar notificacion
[b9eb98b]1568        }
1569
1570        if (clienteExistente(iph, &i)) // Actualiza estado
1571                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1572               
1573        liberaMemoria(iph);
1574        liberaMemoria(ido);
1575               
[b9eb98b]1576        db.Close(); // Cierra conexión
[9dea2d6]1577        return true;
[b9eb98b]1578}
1579// ________________________________________________________________________________________________________
1580// Función: RESPUESTA_CrearImagen
1581//
1582//      Descripción:
1583//              Respuesta del cliente al comando CrearImagen
1584//      Parámetros:
1585//              - socket_c: Socket del cliente que envió el mensaje
1586//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1587//      Devuelve:
[9dea2d6]1588//              true: Si el proceso es correcto
1589//              false: En caso de ocurrir algún error
[b9eb98b]1590// ________________________________________________________________________________________________________
[212280e]1591static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1592{
[b9eb98b]1593        char msglog[LONSTD];
1594        Database db;
1595        Table tbl;
[599c505]1596        char *iph, *dsk, *par, *cpt, *ipr, *ido;
[b9eb98b]1597        char *idi;
[f74067f]1598        bool res;
[b9eb98b]1599
[b56cbeb]1600        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1601                db.GetErrorErrStr(msglog);
[b56cbeb]1602                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1603                       __func__, __LINE__, msglog);
[9dea2d6]1604                return false;
[b9eb98b]1605        }
1606
1607        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1608        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1609
1610        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1611                liberaMemoria(iph);
1612                liberaMemoria(ido);
[b56cbeb]1613                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1614                return false; // Error al registrar notificacion
[b9eb98b]1615        }
1616
1617        // Acciones posteriores
1618        idi = copiaParametro("idi",ptrTrama);
[599c505]1619        dsk = copiaParametro("dsk",ptrTrama);
[b9eb98b]1620        par = copiaParametro("par",ptrTrama);
1621        cpt = copiaParametro("cpt",ptrTrama);
1622        ipr = copiaParametro("ipr",ptrTrama);
1623
[599c505]1624        res=actualizaCreacionImagen(db, tbl, idi, dsk, par, cpt, ipr, ido);
[eb99080]1625
1626        liberaMemoria(idi);
1627        liberaMemoria(par);
1628        liberaMemoria(cpt);
1629        liberaMemoria(ipr);
[b56cbeb]1630
[eb99080]1631        if(!res){
[b56cbeb]1632                syslog(LOG_ERR, "Problem processing update\n");
1633                db.Close();
[9dea2d6]1634                return false;
[b9eb98b]1635        }
1636
1637        db.Close(); // Cierra conexión
[9dea2d6]1638        return true;
[b9eb98b]1639}
1640// ________________________________________________________________________________________________________
1641// Función: actualizaCreacionImagen
1642//
1643//      Descripción:
1644//              Esta función actualiza la base de datos con el resultado de la creación de una imagen
1645//      Parámetros:
1646//              - db: Objeto base de datos (ya operativo)
1647//              - tbl: Objeto tabla
1648//              - idi: Identificador de la imagen
[599c505]1649//              - dsk: Disco de donde se creó
[b9eb98b]1650//              - par: Partición de donde se creó
1651//              - cpt: Código de partición
1652//              - ipr: Ip del repositorio
1653//              - ido: Identificador del ordenador modelo
1654//      Devuelve:
[9dea2d6]1655//              true: Si el proceso es correcto
1656//              false: En caso de ocurrir algún error
[b9eb98b]1657// ________________________________________________________________________________________________________
[59fb4d5]1658bool actualizaCreacionImagen(Database db, Table tbl, char *idi, char *dsk,
1659                             char *par, char *cpt, char *ipr, char *ido)
1660{
[b9eb98b]1661        char msglog[LONSTD], sqlstr[LONSQL];
[ed05cd5]1662        int idr,ifs;
[b9eb98b]1663
[80d1dfd]1664        /* Toma identificador del repositorio correspondiente al ordenador modelo */
[599c505]1665        snprintf(sqlstr, LONSQL,
1666                        "SELECT repositorios.idrepositorio"
[80d1dfd]1667                        "  FROM repositorios"
1668                        "  LEFT JOIN ordenadores USING (idrepositorio)"
1669                        " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido);
[b9eb98b]1670
[b56cbeb]1671        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1672                db.GetErrorErrStr(msglog);
[b56cbeb]1673                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1674                       __func__, __LINE__, msglog);
[9dea2d6]1675                return false;
[b9eb98b]1676        }
1677        if (!tbl.Get("idrepositorio", idr)) { // Toma dato
1678                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1679                og_info(msglog);
[9dea2d6]1680                return false;
[b9eb98b]1681        }
1682
1683        /* Toma identificador del perfilsoftware */
[599c505]1684        snprintf(sqlstr, LONSQL,
1685                        "SELECT idperfilsoft"
1686                        "  FROM ordenadores_particiones"
1687                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par);
[b9eb98b]1688
[b56cbeb]1689        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1690                db.GetErrorErrStr(msglog);
[b56cbeb]1691                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1692                       __func__, __LINE__, msglog);
[9dea2d6]1693                return false;
[b9eb98b]1694        }
1695        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
1696                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1697                og_info(msglog);
[9dea2d6]1698                return false;
[b9eb98b]1699        }
1700
1701        /* Actualizar los datos de la imagen */
[599c505]1702        snprintf(sqlstr, LONSQL,
[faee12e]1703                "UPDATE imagenes"
1704                "   SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
1705                "       idperfilsoft=%d, idrepositorio=%d,"
1706                "       fechacreacion=NOW(), revision=revision+1"
1707                " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi);
[b9eb98b]1708
[b56cbeb]1709        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1710                db.GetErrorErrStr(msglog);
[b56cbeb]1711                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1712                       __func__, __LINE__, msglog);
[9dea2d6]1713                return false;
[b9eb98b]1714        }
[faee12e]1715        /* Actualizar los datos en el cliente */
1716        snprintf(sqlstr, LONSQL,
1717                "UPDATE ordenadores_particiones"
[ed05cd5]1718                "   SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
1719                "       fechadespliegue=NOW()"
[faee12e]1720                " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
[ed05cd5]1721                idi, idi, ido, dsk, par);
[b56cbeb]1722        if (!db.Execute(sqlstr, tbl)) {
[faee12e]1723                db.GetErrorErrStr(msglog);
[b56cbeb]1724                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1725                       __func__, __LINE__, msglog);
[9dea2d6]1726                return false;
[faee12e]1727        }
[9dea2d6]1728        return true;
[b9eb98b]1729}
1730// ________________________________________________________________________________________________________
[eb99080]1731// Función: CrearImagenBasica
1732//
1733//      Descripción:
1734//              Crea una imagen basica usando sincronización
1735//      Parámetros:
1736//              - socket_c: Socket de la consola al envió el mensaje
1737//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1738//      Devuelve:
[9dea2d6]1739//              true: Si el proceso es correcto
1740//              false: En caso de ocurrir algún error
[eb99080]1741// ________________________________________________________________________________________________________
[212280e]1742static bool CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1743{
[eb99080]1744        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1745                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1746                return false;
[eb99080]1747        }
[212280e]1748        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1749        return true;
[eb99080]1750}
1751// ________________________________________________________________________________________________________
1752// Función: RESPUESTA_CrearImagenBasica
1753//
1754//      Descripción:
1755//              Respuesta del cliente al comando CrearImagenBasica
1756//      Parámetros:
1757//              - socket_c: Socket del cliente que envió el mensaje
1758//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1759//      Devuelve:
[9dea2d6]1760//              true: Si el proceso es correcto
1761//              false: En caso de ocurrir algún error
[eb99080]1762// ________________________________________________________________________________________________________
[212280e]1763static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1764{
[212280e]1765        // La misma respuesta que la creación de imagen monolítica
1766        return RESPUESTA_CrearImagen(ptrTrama, cli);
[eb99080]1767}
1768// ________________________________________________________________________________________________________
1769// Función: CrearSoftIncremental
1770//
1771//      Descripción:
1772//              Crea una imagen incremental entre una partición de un disco y una imagen ya creada guardandola en el
1773//              mismo repositorio y en la misma carpeta donde está la imagen básica
1774//      Parámetros:
1775//              - socket_c: Socket de la consola al envió el mensaje
1776//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1777//      Devuelve:
[9dea2d6]1778//              true: Si el proceso es correcto
1779//              false: En caso de ocurrir algún error
[eb99080]1780// ________________________________________________________________________________________________________
[212280e]1781static bool CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1782{
[eb99080]1783        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1784                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1785                return false;
[eb99080]1786        }
[212280e]1787        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1788        return true;
[eb99080]1789}
1790// ________________________________________________________________________________________________________
1791// Función: RESPUESTA_CrearSoftIncremental
1792//
1793//      Descripción:
1794//              Respuesta del cliente al comando crearImagenDiferencial
1795//      Parámetros:
1796//              - socket_c: Socket del cliente que envió el mensaje
1797//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1798//      Devuelve:
[9dea2d6]1799//              true: Si el proceso es correcto
1800//              false: En caso de ocurrir algún error
[eb99080]1801// ________________________________________________________________________________________________________
[212280e]1802static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1803{
1804        Database db;
1805        Table tbl;
1806        char *iph,*par,*ido,*idf;
1807        int ifs;
1808        char msglog[LONSTD],sqlstr[LONSQL];
1809
[b56cbeb]1810        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[eb99080]1811                db.GetErrorErrStr(msglog);
[b56cbeb]1812                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1813                       __func__, __LINE__, msglog);
[9dea2d6]1814                return false;
[eb99080]1815        }
1816
1817        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1818        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1819
1820        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1821                liberaMemoria(iph);
[b56cbeb]1822                liberaMemoria(ido);
1823                syslog(LOG_ERR, "failed to register notification\n");
1824                return false;
[eb99080]1825        }
1826
1827        par = copiaParametro("par",ptrTrama);
1828
1829        /* Toma identificador del perfilsoftware creado por el inventario de software */
1830        sprintf(sqlstr,"SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s",ido,par);
1831       
1832        liberaMemoria(iph);
1833        liberaMemoria(ido);     
1834        liberaMemoria(par);     
[b56cbeb]1835
1836        if (!db.Execute(sqlstr, tbl)) {
[eb99080]1837                db.GetErrorErrStr(msglog);
[b56cbeb]1838                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1839                       __func__, __LINE__, msglog);
[9dea2d6]1840                return false;
[eb99080]1841        }
1842        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
1843                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1844                og_info(msglog);
[9dea2d6]1845                return false;
[eb99080]1846        }
1847
1848        /* Actualizar los datos de la imagen */
1849        idf = copiaParametro("idf",ptrTrama);
1850        sprintf(sqlstr,"UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s",ifs,idf);
1851        liberaMemoria(idf);     
[b56cbeb]1852
1853        if (!db.Execute(sqlstr, tbl)) {
[eb99080]1854                db.GetErrorErrStr(msglog);
[b56cbeb]1855                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1856                       __func__, __LINE__, msglog);
[9dea2d6]1857                return false;
[eb99080]1858        }
1859        db.Close(); // Cierra conexión
[9dea2d6]1860        return true;
[eb99080]1861}
1862// ________________________________________________________________________________________________________
1863// Función: RestaurarImagenBasica
1864//
1865//      Descripción:
1866//              Restaura una imagen básica en una partición
1867//      Parámetros:
1868//              - socket_c: Socket de la consola al envió el mensaje
1869//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1870//      Devuelve:
[9dea2d6]1871//              true: Si el proceso es correcto
1872//              false: En caso de ocurrir algún error
[eb99080]1873// ________________________________________________________________________________________________________
[212280e]1874static bool RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1875{
[eb99080]1876        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1877                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1878                return false;
[eb99080]1879        }
[212280e]1880        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1881        return true;
[eb99080]1882}
1883// ________________________________________________________________________________________________________
1884// Función: RestaurarSoftIncremental
1885//
1886//      Descripción:
1887//              Restaura una imagen básica junto con software incremental en una partición
1888//      Parámetros:
1889//              - socket_c: Socket de la consola al envió el mensaje
1890//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1891//      Devuelve:
[9dea2d6]1892//              true: Si el proceso es correcto
1893//              false: En caso de ocurrir algún error
[eb99080]1894// ________________________________________________________________________________________________________
[212280e]1895static bool RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1896{
[eb99080]1897        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1898                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1899                return false;
[eb99080]1900        }
[212280e]1901        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1902        return true;
[eb99080]1903}
1904// ________________________________________________________________________________________________________
[b9eb98b]1905// Función: RESPUESTA_RestaurarImagen
1906//
1907//      Descripción:
1908//              Respuesta del cliente al comando RestaurarImagen
1909//      Parámetros:
1910//              - socket_c: Socket del cliente que envió el mensaje
1911//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1912//      Devuelve:
[9dea2d6]1913//              true: Si el proceso es correcto
1914//              false: En caso de ocurrir algún error
[b9eb98b]1915// ________________________________________________________________________________________________________
[eb99080]1916//
[212280e]1917static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1918{
[b9eb98b]1919        char msglog[LONSTD];
1920        Database db;
1921        Table tbl;
[f74067f]1922        bool res;
[6ee505f]1923        char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg;
[b9eb98b]1924
[b56cbeb]1925        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1926                db.GetErrorErrStr(msglog);
[b56cbeb]1927                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1928                       __func__, __LINE__, msglog);
[9dea2d6]1929                return false;
[b9eb98b]1930        }
1931
1932        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1933        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1934
1935        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1936                liberaMemoria(iph);
[b56cbeb]1937                liberaMemoria(ido);
1938                syslog(LOG_ERR, "failed to register notification\n");
1939                return false;
[b9eb98b]1940        }
1941
1942        // Acciones posteriores
1943        idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen
[599c505]1944        dsk = copiaParametro("dsk",ptrTrama); // Número de disco
[b9eb98b]1945        par = copiaParametro("par",ptrTrama); // Número de partición
1946        ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido
[6ee505f]1947        cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos
1948        if(cfg){
1949                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
1950                liberaMemoria(cfg);     
1951        }
[599c505]1952        res=actualizaRestauracionImagen(db, tbl, idi, dsk, par, ido, ifs);
[eb99080]1953       
1954        liberaMemoria(iph);
[6ee505f]1955        liberaMemoria(ido);
[eb99080]1956        liberaMemoria(idi);
1957        liberaMemoria(par);
1958        liberaMemoria(ifs);
1959
1960        if(!res){
[b56cbeb]1961                syslog(LOG_ERR, "Problem after restoring image\n");
1962                db.Close();
[9dea2d6]1963                return false;
[b9eb98b]1964        }
1965
1966        db.Close(); // Cierra conexión
[9dea2d6]1967        return true;
[b9eb98b]1968}
1969// ________________________________________________________________________________________________________
[eb99080]1970//
1971// Función: RESPUESTA_RestaurarImagenBasica
1972//
1973//      Descripción:
1974//              Respuesta del cliente al comando RestaurarImagen
1975//      Parámetros:
1976//              - socket_c: Socket del cliente que envió el mensaje
1977//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1978//      Devuelve:
[9dea2d6]1979//              true: Si el proceso es correcto
1980//              false: En caso de ocurrir algún error
[eb99080]1981// ________________________________________________________________________________________________________
1982//
[212280e]1983static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1984{
[212280e]1985        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[eb99080]1986}
1987// ________________________________________________________________________________________________________
1988// Función: RESPUESTA_RestaurarSoftIncremental
1989//
1990//      Descripción:
1991//              Respuesta del cliente al comando RestaurarSoftIncremental
1992//      Parámetros:
1993//              - socket_c: Socket del cliente que envió el mensaje
1994//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1995//      Devuelve:
[9dea2d6]1996//              true: Si el proceso es correcto
1997//              false: En caso de ocurrir algún error
[eb99080]1998// ________________________________________________________________________________________________________
[212280e]1999static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2000{
[212280e]2001        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[eb99080]2002}
2003// ________________________________________________________________________________________________________
[b9eb98b]2004// Función: actualizaRestauracionImagen
2005//
2006//      Descripción:
[eb99080]2007//              Esta función actualiza la base de datos con el resultado de la restauración de una imagen
[b9eb98b]2008//      Parámetros:
2009//              - db: Objeto base de datos (ya operativo)
2010//              - tbl: Objeto tabla
2011//              - idi: Identificador de la imagen
[599c505]2012//              - dsk: Disco de donde se restauró
[b9eb98b]2013//              - par: Partición de donde se restauró
2014//              - ido: Identificador del cliente donde se restauró
2015//              - ifs: Identificador del perfil software contenido      en la imagen
2016//      Devuelve:
[9dea2d6]2017//              true: Si el proceso es correcto
2018//              false: En caso de ocurrir algún error
[b9eb98b]2019// ________________________________________________________________________________________________________
[59fb4d5]2020bool actualizaRestauracionImagen(Database db, Table tbl, char *idi,
2021                                 char *dsk, char *par, char *ido, char *ifs)
2022{
[b9eb98b]2023        char msglog[LONSTD], sqlstr[LONSQL];
2024
2025        /* Actualizar los datos de la imagen */
[599c505]2026        snprintf(sqlstr, LONSQL,
2027                        "UPDATE ordenadores_particiones"
[60bbc25]2028                        "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
[9e3c02a]2029                        "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
2030                        "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
[c20cf9c]2031                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par);
[b9eb98b]2032
[b56cbeb]2033        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2034                db.GetErrorErrStr(msglog);
[b56cbeb]2035                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2036                       __func__, __LINE__, msglog);
[9dea2d6]2037                return false;
[b9eb98b]2038        }
[9dea2d6]2039        return true;
[b9eb98b]2040}
2041// ________________________________________________________________________________________________________
2042// Función: Configurar
2043//
2044//      Descripción:
2045//              Configura la tabla de particiones
2046//      Parámetros:
2047//              - socket_c: Socket de la consola al envió el mensaje
2048//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2049//      Devuelve:
[9dea2d6]2050//              true: Si el proceso es correcto
2051//              false: En caso de ocurrir algún error
[b9eb98b]2052// ________________________________________________________________________________________________________
[212280e]2053static bool Configurar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2054{
[b9eb98b]2055        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]2056                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]2057                return false;
[b9eb98b]2058        }
[212280e]2059        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]2060        return true;
[b9eb98b]2061}
2062// ________________________________________________________________________________________________________
2063// Función: RESPUESTA_Configurar
2064//
2065//      Descripción:
2066//              Respuesta del cliente al comando Configurar
2067//      Parámetros:
2068//              - socket_c: Socket del cliente que envió el mensaje
2069//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2070//      Devuelve:
[9dea2d6]2071//              true: Si el proceso es correcto
2072//              false: En caso de ocurrir algún error
[b9eb98b]2073// ________________________________________________________________________________________________________
[eb99080]2074//
[212280e]2075static bool RESPUESTA_Configurar(TRAMA* ptrTrama, struct og_client *ci)
[eb99080]2076{
[b9eb98b]2077        char msglog[LONSTD];
2078        Database db;
2079        Table tbl;
[f74067f]2080        bool res;
[b9eb98b]2081        char *iph, *ido,*cfg;
2082
[b56cbeb]2083        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2084                db.GetErrorErrStr(msglog);
[b56cbeb]2085                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2086                       __func__, __LINE__, msglog);
[9dea2d6]2087                return false;
[b9eb98b]2088        }
2089
2090        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2091        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2092
2093        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2094                liberaMemoria(iph);
[b56cbeb]2095                liberaMemoria(ido);
2096                syslog(LOG_ERR, "failed to register notification\n");
2097                return false;
[b9eb98b]2098        }
2099
2100        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
[eb99080]2101        res=actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
2102       
2103        liberaMemoria(iph);
2104        liberaMemoria(ido);     
2105        liberaMemoria(cfg);     
[b56cbeb]2106
2107        if(!res){
2108                syslog(LOG_ERR, "Problem updating client configuration\n");
2109                return false;
[b9eb98b]2110        }
[b56cbeb]2111
[b9eb98b]2112        db.Close(); // Cierra conexión
[9dea2d6]2113        return true;
[b9eb98b]2114}
2115// ________________________________________________________________________________________________________
2116// Función: EjecutarScript
2117//
2118//      Descripción:
2119//              Ejecuta un script de código
2120//      Parámetros:
2121//              - socket_c: Socket de la consola al envió el mensaje
2122//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2123//      Devuelve:
[9dea2d6]2124//              true: Si el proceso es correcto
2125//              false: En caso de ocurrir algún error
[b9eb98b]2126// ________________________________________________________________________________________________________
[212280e]2127static bool EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2128{
[b9eb98b]2129        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]2130                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]2131                return false;
[b9eb98b]2132        }
[212280e]2133        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]2134        return true;
[b9eb98b]2135}
2136// ________________________________________________________________________________________________________
2137// Función: RESPUESTA_EjecutarScript
2138//
2139//      Descripción:
2140//              Respuesta del cliente al comando EjecutarScript
2141//      Parámetros:
2142//              - socket_c: Socket del cliente que envió el mensaje
2143//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2144//      Devuelve:
[9dea2d6]2145//              true: Si el proceso es correcto
2146//              false: En caso de ocurrir algún error
[b9eb98b]2147// ________________________________________________________________________________________________________
[212280e]2148static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
[827bac5]2149{
[b9eb98b]2150        char msglog[LONSTD];
2151        Database db;
2152        Table tbl;
[827bac5]2153        char *iph, *ido,*cfg;
[b9eb98b]2154
[b56cbeb]2155        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2156                db.GetErrorErrStr(msglog);
[b56cbeb]2157                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2158                       __func__, __LINE__, msglog);
[9dea2d6]2159                return false;
[b9eb98b]2160        }
2161
2162        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2163        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2164
2165        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2166                liberaMemoria(iph);
[b56cbeb]2167                liberaMemoria(ido);
2168                syslog(LOG_ERR, "failed to register notification\n");
2169                return false;
[b9eb98b]2170        }
[eb99080]2171       
[827bac5]2172        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
[1c04180]2173        if(cfg){
[24df599]2174                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
[1c04180]2175                liberaMemoria(cfg);     
2176        }
[827bac5]2177
[eb99080]2178        liberaMemoria(iph);
[827bac5]2179        liberaMemoria(ido);
[1c04180]2180
[eb99080]2181       
[b9eb98b]2182        db.Close(); // Cierra conexión
[9dea2d6]2183        return true;
[b9eb98b]2184}
2185// ________________________________________________________________________________________________________
2186// Función: RESPUESTA_InventarioHardware
2187//
2188//      Descripción:
2189//              Respuesta del cliente al comando InventarioHardware
2190//      Parámetros:
2191//              - socket_c: Socket del cliente que envió el mensaje
2192//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2193//      Devuelve:
[9dea2d6]2194//              true: Si el proceso es correcto
2195//              false: En caso de ocurrir algún error
[b9eb98b]2196// ________________________________________________________________________________________________________
[212280e]2197static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2198{
[b9eb98b]2199        char msglog[LONSTD];
2200        Database db;
2201        Table tbl;
[f74067f]2202        bool res;
[b9eb98b]2203        char *iph, *ido, *idc, *npc, *hrd, *buffer;
2204
[b56cbeb]2205        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2206                db.GetErrorErrStr(msglog);
[b56cbeb]2207                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2208                       __func__, __LINE__, msglog);
[9dea2d6]2209                return false;
[b9eb98b]2210        }
[eb99080]2211
[b9eb98b]2212        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente
2213        ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente
2214
2215        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2216                liberaMemoria(iph);
[b56cbeb]2217                liberaMemoria(ido);
2218                syslog(LOG_ERR, "failed to register notification\n");
2219                return false;
[b9eb98b]2220        }
2221        // Lee archivo de inventario enviado anteriormente
2222        hrd = copiaParametro("hrd",ptrTrama);
2223        buffer = rTrim(leeArchivo(hrd));
[eb99080]2224       
2225        npc = copiaParametro("npc",ptrTrama); 
2226        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro
2227       
2228        if (buffer) 
2229                res=actualizaHardware(db, tbl, buffer, ido, npc, idc);
2230       
2231        liberaMemoria(iph);
2232        liberaMemoria(ido);                     
2233        liberaMemoria(npc);                     
2234        liberaMemoria(idc);             
2235        liberaMemoria(buffer);         
2236       
2237        if(!res){
[b56cbeb]2238                syslog(LOG_ERR, "Problem updating client configuration\n");
[9dea2d6]2239                return false;
[b9eb98b]2240        }
[eb99080]2241               
[b9eb98b]2242        db.Close(); // Cierra conexión
[9dea2d6]2243        return true;
[b9eb98b]2244}
2245// ________________________________________________________________________________________________________
2246// Función: actualizaHardware
2247//
2248//              Descripción:
2249//                      Actualiza la base de datos con la configuracion hardware del cliente
2250//              Parámetros:
2251//                      - db: Objeto base de datos (ya operativo)
2252//                      - tbl: Objeto tabla
2253//                      - hrd: cadena con el inventario hardware
2254//                      - ido: Identificador del ordenador
2255//                      - npc: Nombre del ordenador
2256//                      - idc: Identificador del centro o Unidad organizativa
2257// ________________________________________________________________________________________________________
[eb99080]2258//
[59fb4d5]2259bool actualizaHardware(Database db, Table tbl, char *hrd, char *ido, char *npc,
2260                       char *idc)
[eb99080]2261{
[b9eb98b]2262        char msglog[LONSTD], sqlstr[LONSQL];
2263        int idtipohardware, idperfilhard;
2264        int lon, i, j, aux;
[7f46c45]2265        bool retval;
[eb99080]2266        char *whard;
[b9eb98b]2267        int tbidhardware[MAXHARDWARE];
[eb99080]2268        char *tbHardware[MAXHARDWARE],*dualHardware[2], descripcion[250], strInt[LONINT], *idhardwares;
[b9eb98b]2269
2270        /* Toma Centro (Unidad Organizativa) */
2271        sprintf(sqlstr, "SELECT * FROM ordenadores WHERE idordenador=%s", ido);
2272
[b56cbeb]2273        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2274                db.GetErrorErrStr(msglog);
[b56cbeb]2275                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2276                       __func__, __LINE__, msglog);
[9dea2d6]2277                return false;
[b9eb98b]2278        }
2279        if (!tbl.Get("idperfilhard", idperfilhard)) { // Toma dato
2280                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2281                og_info(msglog);
[9dea2d6]2282                return false;
[b9eb98b]2283        }
[eb99080]2284        whard=escaparCadena(hrd); // Codificar comillas simples
2285        if(!whard)
[9dea2d6]2286                return false;
[b9eb98b]2287        /* Recorre componentes hardware*/
[eb99080]2288        lon = splitCadena(tbHardware, whard, '\n');
[b9eb98b]2289        if (lon > MAXHARDWARE)
2290                lon = MAXHARDWARE; // Limita el número de componentes hardware
2291        /*
2292         for (i=0;i<lon;i++){
2293         sprintf(msglog,"Linea de inventario: %s",tbHardware[i]);
[9dea2d6]2294         RegistraLog(msglog,false);
[b9eb98b]2295         }
2296         */
2297        for (i = 0; i < lon; i++) {
2298                splitCadena(dualHardware, rTrim(tbHardware[i]), '=');
2299                //sprintf(msglog,"nemonico: %s",dualHardware[0]);
[9dea2d6]2300                //RegistraLog(msglog,false);
[b9eb98b]2301                //sprintf(msglog,"valor: %s",dualHardware[1]);
[9dea2d6]2302                //RegistraLog(msglog,false);
[b9eb98b]2303                sprintf(sqlstr, "SELECT idtipohardware,descripcion FROM tipohardwares "
2304                        " WHERE nemonico='%s'", dualHardware[0]);
[b56cbeb]2305                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2306                        db.GetErrorErrStr(msglog);
[b56cbeb]2307                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2308                               __func__, __LINE__, msglog);
[9dea2d6]2309                        return false;
[b9eb98b]2310                }
2311                if (tbl.ISEOF()) { //  Tipo de Hardware NO existente
2312                        sprintf(msglog, "%s: %s)", tbErrores[54], dualHardware[0]);
[9764185]2313                        og_info(msglog);
[9dea2d6]2314                        return false;
[b9eb98b]2315                } else { //  Tipo de Hardware Existe
2316                        if (!tbl.Get("idtipohardware", idtipohardware)) { // Toma dato
2317                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2318                                og_info(msglog);
[9dea2d6]2319                                return false;
[b9eb98b]2320                        }
2321                        if (!tbl.Get("descripcion", descripcion)) { // Toma dato
2322                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2323                                og_info(msglog);
[9dea2d6]2324                                return false;
[b9eb98b]2325                        }
2326
2327                        sprintf(sqlstr, "SELECT idhardware FROM hardwares "
2328                                " WHERE idtipohardware=%d AND descripcion='%s'",
2329                                        idtipohardware, dualHardware[1]);
2330
[b56cbeb]2331                        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2332                                db.GetErrorErrStr(msglog);
[b56cbeb]2333                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2334                                       __func__, __LINE__, msglog);
[9dea2d6]2335                                return false;
[b9eb98b]2336                        }
2337
2338                        if (tbl.ISEOF()) { //  Hardware NO existente
[bde1389]2339                                sprintf(sqlstr, "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) "
[b9eb98b]2340                                                        " VALUES(%d,'%s',%s,0)", idtipohardware,
2341                                                dualHardware[1], idc);
2342                                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2343                                        db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2344                                        og_info(msglog);
[9dea2d6]2345                                        return false;
[b9eb98b]2346                                }
2347                                // Recupera el identificador del hardware
2348                                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
[b56cbeb]2349                                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2350                                        db.GetErrorErrStr(msglog);
[b56cbeb]2351                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2352                                               __func__, __LINE__, msglog);
[9dea2d6]2353                                        return false;
[b9eb98b]2354                                }
2355                                if (!tbl.ISEOF()) { // Si existe registro
2356                                        if (!tbl.Get("identificador", tbidhardware[i])) {
2357                                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2358                                                og_info(msglog);
[9dea2d6]2359                                                return false;
[b9eb98b]2360                                        }
2361                                }
2362                        } else {
2363                                if (!tbl.Get("idhardware", tbidhardware[i])) { // Toma dato
2364                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2365                                        og_info(msglog);
[9dea2d6]2366                                        return false;
[b9eb98b]2367                                }
2368                        }
2369                }
2370        }
2371        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2372
2373        for (i = 0; i < lon - 1; i++) {
2374                for (j = i + 1; j < lon; j++) {
2375                        if (tbidhardware[i] > tbidhardware[j]) {
2376                                aux = tbidhardware[i];
2377                                tbidhardware[i] = tbidhardware[j];
2378                                tbidhardware[j] = aux;
2379                        }
2380                }
2381        }
2382        /* Crea cadena de identificadores de componentes hardware separados por coma */
2383        sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2384        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2385        idhardwares = reservaMemoria(sizeof(aux) * lon + lon);
2386        if (idhardwares == NULL) {
[b56cbeb]2387                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2388                return false;
[b9eb98b]2389        }
2390        aux = sprintf(idhardwares, "%d", tbidhardware[0]);
2391        for (i = 1; i < lon; i++)
2392                aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]);
2393
2394        if (!cuestionPerfilHardware(db, tbl, idc, ido, idperfilhard, idhardwares,
2395                        npc, tbidhardware, lon)) {
[b56cbeb]2396                syslog(LOG_ERR, "Problem updating client hardware\n");
[9dea2d6]2397                retval=false;
[b9eb98b]2398        }
[7f46c45]2399        else {
[9dea2d6]2400                retval=true;
[7f46c45]2401        }
[eb99080]2402        liberaMemoria(whard);
[7f46c45]2403        liberaMemoria(idhardwares);
2404        return (retval);
[b9eb98b]2405}
2406// ________________________________________________________________________________________________________
2407// Función: cuestionPerfilHardware
2408//
2409//              Descripción:
2410//                      Comprueba existencia de perfil hardware y actualización de éste para el ordenador
2411//              Parámetros:
2412//                      - db: Objeto base de datos (ya operativo)
2413//                      - tbl: Objeto tabla
2414//                      - idc: Identificador de la Unidad organizativa donde se encuentra el cliente
2415//                      - ido: Identificador del ordenador
2416//                      - tbidhardware: Identificador del tipo de hardware
2417//                      - con: Número de componentes detectados para configurar un el perfil hardware
2418//                      - npc: Nombre del cliente
2419// ________________________________________________________________________________________________________
[59fb4d5]2420bool cuestionPerfilHardware(Database db, Table tbl, char *idc, char *ido,
2421                int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware,
[b9eb98b]2422                int lon)
2423{
2424        char msglog[LONSTD], *sqlstr;
2425        int i;
2426        int nwidperfilhard;
2427
2428        sqlstr = reservaMemoria(strlen(idhardwares)+LONSQL); // Reserva para escribir sentencia SQL
2429        if (sqlstr == NULL) {
[b56cbeb]2430                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2431                return false;
[b9eb98b]2432        }
2433        // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados
2434        sprintf(sqlstr, "SELECT idperfilhard FROM"
2435                " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard,"
2436                "       group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )"
2437                "       ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares"
2438                " FROM  perfileshard_hardwares"
2439                " GROUP BY perfileshard_hardwares.idperfilhard) AS temp"
2440                " WHERE idhardwares LIKE '%s'", idhardwares);
[b56cbeb]2441
2442        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2443                db.GetErrorErrStr(msglog);
[b56cbeb]2444                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2445                       __func__, __LINE__, msglog);
[7f46c45]2446                liberaMemoria(sqlstr);
[9dea2d6]2447                return false;
[b9eb98b]2448        }
2449        if (tbl.ISEOF()) { // No existe un perfil hardware con esos componentes de componentes hardware, lo crea
2450                sprintf(sqlstr, "INSERT perfileshard  (descripcion,idcentro,grupoid)"
[bde1389]2451                                " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc);
[b9eb98b]2452                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2453                        db.GetErrorErrStr(msglog);
[9764185]2454                        og_info(msglog);
[7f46c45]2455                        liberaMemoria(sqlstr);
[9dea2d6]2456                        return false;
[b9eb98b]2457                }
2458                // Recupera el identificador del nuevo perfil hardware
2459                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2460                if (!db.Execute(sqlstr, tbl)) { // Error al leer
2461                        db.GetErrorErrStr(msglog);
[9764185]2462                        og_info(msglog);
[7f46c45]2463                        liberaMemoria(sqlstr);
[9dea2d6]2464                        return false;
[b9eb98b]2465                }
2466                if (!tbl.ISEOF()) { // Si existe registro
2467                        if (!tbl.Get("identificador", nwidperfilhard)) {
2468                                tbl.GetErrorErrStr(msglog);
[9764185]2469                                og_info(msglog);
[7f46c45]2470                                liberaMemoria(sqlstr);
[9dea2d6]2471                                return false;
[b9eb98b]2472                        }
2473                }
2474                // Crea la relación entre perfiles y componenetes hardware
2475                for (i = 0; i < lon; i++) {
[bde1389]2476                        sprintf(sqlstr, "INSERT perfileshard_hardwares  (idperfilhard,idhardware)"
[b9eb98b]2477                                                " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]);
2478                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2479                                db.GetErrorErrStr(msglog);
[9764185]2480                                og_info(msglog);
[7f46c45]2481                                liberaMemoria(sqlstr);
[9dea2d6]2482                                return false;
[b9eb98b]2483                        }
2484                }
2485        } else { // Existe un perfil con todos esos componentes
2486                if (!tbl.Get("idperfilhard", nwidperfilhard)) {
2487                        tbl.GetErrorErrStr(msglog);
[9764185]2488                        og_info(msglog);
[7f46c45]2489                        liberaMemoria(sqlstr);
[9dea2d6]2490                        return false;
[b9eb98b]2491                }
2492        }
2493        if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles
2494                // Actualiza el identificador del perfil hardware del ordenador
2495                sprintf(sqlstr, "UPDATE ordenadores SET idperfilhard=%d"
2496                        " WHERE idordenador=%s", nwidperfilhard, ido);
2497                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2498                        db.GetErrorErrStr(msglog);
[9764185]2499                        og_info(msglog);
[7f46c45]2500                        liberaMemoria(sqlstr);
[9dea2d6]2501                        return false;
[b9eb98b]2502                }
2503        }
2504        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
2505        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN "
2506                " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN"
2507                " (SELECT DISTINCT idperfilhard from ordenadores))");
2508        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2509                db.GetErrorErrStr(msglog);
[9764185]2510                og_info(msglog);
[7f46c45]2511                liberaMemoria(sqlstr);
[9dea2d6]2512                return false;
[b9eb98b]2513        }
2514
2515        /* Eliminar Perfiles hardware que quedan húerfanos */
2516        sprintf(sqlstr, "DELETE FROM perfileshard WHERE idperfilhard NOT IN"
[7f46c45]2517                        " (SELECT DISTINCT idperfilhard FROM ordenadores)");
[b9eb98b]2518        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2519                db.GetErrorErrStr(msglog);
[9764185]2520                og_info(msglog);
[7f46c45]2521                liberaMemoria(sqlstr);
[9dea2d6]2522                return false;
[b9eb98b]2523        }
2524        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
[7f46c45]2525        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN"
2526                        " (SELECT idperfilhard FROM perfileshard)");
[b9eb98b]2527        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2528                db.GetErrorErrStr(msglog);
[9764185]2529                og_info(msglog);
[7f46c45]2530                liberaMemoria(sqlstr);
[9dea2d6]2531                return false;
[b9eb98b]2532        }
[7f46c45]2533        liberaMemoria(sqlstr);
[9dea2d6]2534        return true;
[b9eb98b]2535}
2536// ________________________________________________________________________________________________________
2537// Función: RESPUESTA_InventarioSoftware
2538//
2539//      Descripción:
2540//              Respuesta del cliente al comando InventarioSoftware
2541//      Parámetros:
2542//              - socket_c: Socket del cliente que envió el mensaje
2543//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2544//      Devuelve:
[9dea2d6]2545//              true: Si el proceso es correcto
2546//              false: En caso de ocurrir algún error
[b9eb98b]2547// ________________________________________________________________________________________________________
[212280e]2548static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2549{
[b9eb98b]2550        char msglog[LONSTD];
2551        Database db;
2552        Table tbl;
[f74067f]2553        bool res;
[b9eb98b]2554        char *iph, *ido, *npc, *idc, *par, *sft, *buffer;
2555
[b56cbeb]2556        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2557                db.GetErrorErrStr(msglog);
[b56cbeb]2558                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2559                       __func__, __LINE__, msglog);
[9dea2d6]2560                return false;
[b9eb98b]2561        }
2562
2563        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2564        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2565
2566        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2567                liberaMemoria(iph);
[b56cbeb]2568                liberaMemoria(ido);
2569                syslog(LOG_ERR, "failed to register notification\n");
2570                return false;
[b9eb98b]2571        }
[b56cbeb]2572
[eb99080]2573        npc = copiaParametro("npc",ptrTrama); 
2574        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro 
[b9eb98b]2575        par = copiaParametro("par",ptrTrama);
2576        sft = copiaParametro("sft",ptrTrama);
2577
2578        buffer = rTrim(leeArchivo(sft));
[eb99080]2579        if (buffer)
2580                res=actualizaSoftware(db, tbl, buffer, par, ido, npc, idc);
2581
2582        liberaMemoria(iph);
2583        liberaMemoria(ido);     
2584        liberaMemoria(npc);     
2585        liberaMemoria(idc);     
2586        liberaMemoria(par);     
2587        liberaMemoria(sft);     
2588
2589        if(!res){
[b56cbeb]2590                syslog(LOG_ERR, "cannot update software\n");
[9dea2d6]2591                return false;
[b56cbeb]2592        }
2593
[b9eb98b]2594        db.Close(); // Cierra conexión
[9dea2d6]2595        return true;
[b9eb98b]2596}
2597// ________________________________________________________________________________________________________
2598// Función: actualizaSoftware
2599//
2600//      Descripción:
2601//              Actualiza la base de datos con la configuración software del cliente
2602//      Parámetros:
2603//              - db: Objeto base de datos (ya operativo)
2604//              - tbl: Objeto tabla
2605//              - sft: cadena con el inventario software
2606//              - par: Número de la partición
2607//              - ido: Identificador del ordenador del cliente en la tabla
2608//              - npc: Nombre del ordenador
2609//              - idc: Identificador del centro o Unidad organizativa
2610//      Devuelve:
[9dea2d6]2611//              true: Si el proceso es correcto
2612//              false: En caso de ocurrir algún error
[8712fd9]2613//
2614//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
[b9eb98b]2615// ________________________________________________________________________________________________________
[59fb4d5]2616bool actualizaSoftware(Database db, Table tbl, char *sft, char *par,char *ido,
2617                       char *npc, char *idc)
[eb99080]2618{
[8712fd9]2619        int i, j, lon, aux, idperfilsoft, idnombreso;
[7f46c45]2620        bool retval;
[eb99080]2621        char *wsft;
[b9eb98b]2622        int tbidsoftware[MAXSOFTWARE];
[eb99080]2623        char *tbSoftware[MAXSOFTWARE],msglog[LONSTD], sqlstr[LONSQL], strInt[LONINT], *idsoftwares;
[b9eb98b]2624
2625        /* Toma Centro (Unidad Organizativa) y perfil software */
2626        sprintf(sqlstr, "SELECT idperfilsoft,numpar"
2627                " FROM ordenadores_particiones"
2628                " WHERE idordenador=%s", ido);
2629
[b56cbeb]2630        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2631                db.GetErrorErrStr(msglog);
[b56cbeb]2632                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2633                       __func__, __LINE__, msglog);
[9dea2d6]2634                return false;
[b9eb98b]2635        }
2636        idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software
2637        while (!tbl.ISEOF()) { // Recorre particiones
2638                if (!tbl.Get("numpar", aux)) {
2639                        tbl.GetErrorErrStr(msglog);
[9764185]2640                        og_info(msglog);
[9dea2d6]2641                        return false;
[b9eb98b]2642                }
2643                if (aux == atoi(par)) { // Se encuentra la partición
2644                        if (!tbl.Get("idperfilsoft", idperfilsoft)) {
2645                                tbl.GetErrorErrStr(msglog);
[9764185]2646                                og_info(msglog);
[9dea2d6]2647                                return false;
[b9eb98b]2648                        }
2649                        break;
2650                }
2651                tbl.MoveNext();
2652        }
[eb99080]2653        wsft=escaparCadena(sft); // Codificar comillas simples
2654        if(!wsft)
[9dea2d6]2655                return false;
[b9eb98b]2656
2657        /* Recorre componentes software*/
[eb99080]2658        lon = splitCadena(tbSoftware, wsft, '\n');
2659
[b9eb98b]2660        if (lon == 0)
[9dea2d6]2661                return true; // No hay lineas que procesar
[b9eb98b]2662        if (lon > MAXSOFTWARE)
2663                lon = MAXSOFTWARE; // Limita el número de componentes software
2664
2665        for (i = 0; i < lon; i++) {
[8712fd9]2666                // Primera línea es el sistema operativo: se obtiene identificador
2667                if (i == 0) {
2668                        idnombreso = checkDato(db, tbl, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso");
2669                        continue;
2670                }
2671
[b9eb98b]2672                sprintf(sqlstr,
2673                                "SELECT idsoftware FROM softwares WHERE descripcion ='%s'",
2674                                rTrim(tbSoftware[i]));
2675
[b56cbeb]2676                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2677                        db.GetErrorErrStr(msglog);
[b56cbeb]2678                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2679                               __func__, __LINE__, msglog);
[9dea2d6]2680                        return false;
[b9eb98b]2681                }
2682
2683                if (tbl.ISEOF()) { //  Software NO existente
[bde1389]2684                        sprintf(sqlstr, "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)"
[b9eb98b]2685                                                " VALUES(2,'%s',%s,0)", tbSoftware[i], idc);
2686
2687                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2688                                db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2689                                og_info(msglog);
[9dea2d6]2690                                return false;
[b9eb98b]2691                        }
2692                        // Recupera el identificador del software
2693                        sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2694                        if (!db.Execute(sqlstr, tbl)) { // Error al leer
2695                                db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2696                                og_info(msglog);
[9dea2d6]2697                                return false;
[b9eb98b]2698                        }
2699                        if (!tbl.ISEOF()) { // Si existe registro
2700                                if (!tbl.Get("identificador", tbidsoftware[i])) {
2701                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2702                                        og_info(msglog);
[9dea2d6]2703                                        return false;
[b9eb98b]2704                                }
2705                        }
2706                } else {
2707                        if (!tbl.Get("idsoftware", tbidsoftware[i])) { // Toma dato
2708                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2709                                og_info(msglog);
[9dea2d6]2710                                return false;
[b9eb98b]2711                        }
2712                }
2713        }
2714
2715        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2716
2717        for (i = 0; i < lon - 1; i++) {
2718                for (j = i + 1; j < lon; j++) {
2719                        if (tbidsoftware[i] > tbidsoftware[j]) {
2720                                aux = tbidsoftware[i];
2721                                tbidsoftware[i] = tbidsoftware[j];
2722                                tbidsoftware[j] = aux;
2723                        }
2724                }
2725        }
2726        /* Crea cadena de identificadores de componentes software separados por coma */
2727        sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2728        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2729        idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon);
2730        if (idsoftwares == NULL) {
[b56cbeb]2731                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2732                return false;
[b9eb98b]2733        }
2734        aux = sprintf(idsoftwares, "%d", tbidsoftware[0]);
2735        for (i = 1; i < lon; i++)
2736                aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]);
2737
2738        // Comprueba existencia de perfil software y actualización de éste para el ordenador
[8712fd9]2739        if (!cuestionPerfilSoftware(db, tbl, idc, ido, idperfilsoft, idnombreso, idsoftwares, 
[b9eb98b]2740                        npc, par, tbidsoftware, lon)) {
[b56cbeb]2741                syslog(LOG_ERR, "cannot update software\n");
[9764185]2742                og_info(msglog);
[9dea2d6]2743                retval=false;
[b9eb98b]2744        }
[7f46c45]2745        else {
[9dea2d6]2746                retval=true;
[7f46c45]2747        }
[eb99080]2748        liberaMemoria(wsft);
[7f46c45]2749        liberaMemoria(idsoftwares);
2750        return (retval);
[b9eb98b]2751}
2752// ________________________________________________________________________________________________________
2753// Función: CuestionPerfilSoftware
2754//
2755//      Parámetros:
2756//              - db: Objeto base de datos (ya operativo)
2757//              - tbl: Objeto tabla
2758//              - idcentro: Identificador del centro en la tabla
2759//              - ido: Identificador del ordenador del cliente en la tabla
[8712fd9]2760//              - idnombreso: Identificador del sistema operativo
[b9eb98b]2761//              - idsoftwares: Cadena con los identificadores de componentes software separados por comas
2762//              - npc: Nombre del ordenador del cliente
2763//              - particion: Número de la partición
2764//              - tbidsoftware: Array con los identificadores de componentes software
2765//              - lon: Número de componentes
2766//      Devuelve:
[9dea2d6]2767//              true: Si el proceso es correcto
2768//              false: En caso de ocurrir algún error
[8712fd9]2769//
2770//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
2771//_________________________________________________________________________________________________________
[59fb4d5]2772bool cuestionPerfilSoftware(Database db, Table tbl, char *idc, char *ido,
2773                            int idperfilsoftware, int idnombreso,
2774                            char *idsoftwares, char *npc, char *par,
2775                            int *tbidsoftware, int lon)
2776{
[b9eb98b]2777        char *sqlstr, msglog[LONSTD];
2778        int i, nwidperfilsoft;
2779
2780        sqlstr = reservaMemoria(strlen(idsoftwares)+LONSQL); // Reserva para escribir sentencia SQL
2781        if (sqlstr == NULL) {
[b56cbeb]2782                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2783                return false;
[b9eb98b]2784        }
2785        // Busca perfil soft del ordenador que contenga todos los componentes software encontrados
2786        sprintf(sqlstr, "SELECT idperfilsoft FROM"
2787                " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft,"
2788                "       group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )"
2789                "       ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares"
2790                " FROM  perfilessoft_softwares"
2791                " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp"
2792                " WHERE idsoftwares LIKE '%s'", idsoftwares);
[b56cbeb]2793
2794        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2795                db.GetErrorErrStr(msglog);
[b56cbeb]2796                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2797                       __func__, __LINE__, msglog);
[7f46c45]2798                liberaMemoria(sqlstr);
[9dea2d6]2799                return false;
[b9eb98b]2800        }
2801        if (tbl.ISEOF()) { // No existe un perfil software con esos componentes de componentes software, lo crea
[8712fd9]2802                sprintf(sqlstr, "INSERT perfilessoft  (descripcion, idcentro, grupoid, idnombreso)"
2803                                " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso);
[b9eb98b]2804                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2805                        db.GetErrorErrStr(msglog);
[9764185]2806                        og_info(msglog);
[9dea2d6]2807                        return false;
[b9eb98b]2808                }
2809                // Recupera el identificador del nuevo perfil software
2810                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2811                if (!db.Execute(sqlstr, tbl)) { // Error al leer
2812                        tbl.GetErrorErrStr(msglog);
[9764185]2813                        og_info(msglog);
[7f46c45]2814                        liberaMemoria(sqlstr);
[9dea2d6]2815                        return false;
[b9eb98b]2816                }
2817                if (!tbl.ISEOF()) { // Si existe registro
2818                        if (!tbl.Get("identificador", nwidperfilsoft)) {
2819                                tbl.GetErrorErrStr(msglog);
[9764185]2820                                og_info(msglog);
[7f46c45]2821                                liberaMemoria(sqlstr);
[9dea2d6]2822                                return false;
[b9eb98b]2823                        }
2824                }
2825                // Crea la relación entre perfiles y componenetes software
2826                for (i = 0; i < lon; i++) {
[7f46c45]2827                        sprintf(sqlstr, "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)"
[b9eb98b]2828                                                " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]);
2829                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2830                                db.GetErrorErrStr(msglog);
[9764185]2831                                og_info(msglog);
[7f46c45]2832                                liberaMemoria(sqlstr);
[9dea2d6]2833                                return false;
[b9eb98b]2834                        }
2835                }
2836        } else { // Existe un perfil con todos esos componentes
2837                if (!tbl.Get("idperfilsoft", nwidperfilsoft)) {
2838                        tbl.GetErrorErrStr(msglog);
[9764185]2839                        og_info(msglog);
[7f46c45]2840                        liberaMemoria(sqlstr);
[9dea2d6]2841                        return false;
[b9eb98b]2842                }
2843        }
2844
2845        if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
2846                // Actualiza el identificador del perfil software del ordenador
[7f46c45]2847                sprintf(sqlstr, "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
2848                                " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
[b9eb98b]2849                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2850                        db.GetErrorErrStr(msglog);
[9764185]2851                        og_info(msglog);
[7f46c45]2852                        liberaMemoria(sqlstr);
[9dea2d6]2853                        return false;
[b9eb98b]2854                }
2855        }
2856
2857        /* DEPURACIÓN DE PERFILES SOFTWARE */
2858
2859         /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
2860        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\
2861                " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\
2862                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\
2863                " (SELECT DISTINCT idperfilsoft from imagenes))");
2864        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2865                db.GetErrorErrStr(msglog);
[9764185]2866                og_info(msglog);
[7f46c45]2867                liberaMemoria(sqlstr);
[9dea2d6]2868                return false;
[b9eb98b]2869        }
2870        /* Eliminar Perfiles software que quedan húerfanos */
2871        sprintf(sqlstr, "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN"
2872                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\
2873                " AND  idperfilsoft NOT IN"\
2874                " (SELECT DISTINCT idperfilsoft from imagenes)");
2875        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2876                db.GetErrorErrStr(msglog);
[9764185]2877                og_info(msglog);
[7f46c45]2878                liberaMemoria(sqlstr);
[9dea2d6]2879                return false;
[b9eb98b]2880        }
2881        /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
[7f46c45]2882        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN"
2883                        " (SELECT idperfilsoft from perfilessoft)");
[b9eb98b]2884        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2885                db.GetErrorErrStr(msglog);
[9764185]2886                og_info(msglog);
[7f46c45]2887                liberaMemoria(sqlstr);
[9dea2d6]2888                return false;
[b9eb98b]2889        }
[7f46c45]2890        liberaMemoria(sqlstr);
[9dea2d6]2891        return true;
[b9eb98b]2892}
2893// ________________________________________________________________________________________________________
2894// Función: enviaArchivo
2895//
2896//      Descripción:
2897//              Envia un archivo por la red, por bloques
2898//      Parámetros:
2899//              - socket_c: Socket del cliente que envió el mensaje
2900//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2901//      Devuelve:
[9dea2d6]2902//              true: Si el proceso es correcto
2903//              false: En caso de ocurrir algún error
[b9eb98b]2904// ________________________________________________________________________________________________________
[212280e]2905static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]2906{
[212280e]2907        int socket_c = og_client_socket(cli);
[b9eb98b]2908        char *nfl;
2909
2910        // Toma parámetros
2911        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
[07d2b73]2912        if (!sendArchivo(&socket_c, nfl)) {
[eb99080]2913                liberaMemoria(nfl);
[b56cbeb]2914                syslog(LOG_ERR, "Problem sending file\n");
[9dea2d6]2915                return false;
[b9eb98b]2916        }
[eb99080]2917        liberaMemoria(nfl);
[9dea2d6]2918        return true;
[b9eb98b]2919}
2920// ________________________________________________________________________________________________________
2921// Función: enviaArchivo
2922//
2923//      Descripción:
2924//              Envia un archivo por la red, por bloques
2925//      Parámetros:
2926//              - socket_c: Socket del cliente que envió el mensaje
2927//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2928//      Devuelve:
[9dea2d6]2929//              true: Si el proceso es correcto
2930//              false: En caso de ocurrir algún error
[b9eb98b]2931// ________________________________________________________________________________________________________
[212280e]2932static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]2933{
[212280e]2934        int socket_c = og_client_socket(cli);
[b9eb98b]2935        char *nfl;
2936
2937        // Toma parámetros
2938        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
2939        ptrTrama->tipo = MSG_NOTIFICACION;
[07d2b73]2940        enviaFlag(&socket_c, ptrTrama);
2941        if (!recArchivo(&socket_c, nfl)) {
[eb99080]2942                liberaMemoria(nfl);
[b56cbeb]2943                syslog(LOG_ERR, "Problem receiving file\n");
[9dea2d6]2944                return false;
[b9eb98b]2945        }
[eb99080]2946        liberaMemoria(nfl);
[9dea2d6]2947        return true;
[b9eb98b]2948}
2949// ________________________________________________________________________________________________________
2950// Función: envioProgramacion
2951//
2952//      Descripción:
2953//              Envia un comando de actualización a todos los ordenadores que han sido programados con
2954//              alguna acción para que entren en el bucle de comandos pendientes y las ejecuten
2955//      Parámetros:
2956//              - socket_c: Socket del cliente que envió el mensaje
2957//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2958//      Devuelve:
[9dea2d6]2959//              true: Si el proceso es correcto
2960//              false: En caso de ocurrir algún error
[b9eb98b]2961// ________________________________________________________________________________________________________
[212280e]2962static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli)
[b9eb98b]2963{
[507c75c]2964        char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES];
[b9eb98b]2965        char sqlstr[LONSQL], msglog[LONSTD];
[24df599]2966        char *idp,iph[LONIP],mac[LONMAC];
[b9eb98b]2967        Database db;
2968        Table tbl;
[507c75c]2969        int idx,idcomando,lon;
[b9eb98b]2970
[b56cbeb]2971        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2972                db.GetErrorErrStr(msglog);
[b56cbeb]2973                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2974                       __func__, __LINE__, msglog);
[9dea2d6]2975                return false;
[b9eb98b]2976        }
2977
[eb99080]2978        idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones
[b9eb98b]2979
2980        sprintf(sqlstr, "SELECT ordenadores.ip,ordenadores.mac,acciones.idcomando FROM acciones "\
2981                        " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\
2982                        " WHERE acciones.idprogramacion=%s",idp);
[eb99080]2983       
2984        liberaMemoria(idp);
[b56cbeb]2985
2986        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2987                db.GetErrorErrStr(msglog);
[b56cbeb]2988                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2989                       __func__, __LINE__, msglog);
[9dea2d6]2990                return false;
[b9eb98b]2991        }
[fcc271f]2992        db.Close();
[b9eb98b]2993        if(tbl.ISEOF())
[9dea2d6]2994                return true; // No existen registros
[b9eb98b]2995
2996        /* Prepara la trama de actualizacion */
2997
2998        initParametros(ptrTrama,0);
2999        ptrTrama->tipo=MSG_COMANDO;
3000        sprintf(ptrTrama->parametros, "nfn=Actualizar\r");
3001
3002        while (!tbl.ISEOF()) { // Recorre particiones
3003                if (!tbl.Get("ip", iph)) {
3004                        tbl.GetErrorErrStr(msglog);
[a1d02f4]3005                        syslog(LOG_ERR, "cannot find ip column in table: %s\n",
3006                               msglog);
[9dea2d6]3007                        return false;
[b9eb98b]3008                }
3009                if (!tbl.Get("idcomando", idcomando)) {
3010                        tbl.GetErrorErrStr(msglog);
[a1d02f4]3011                        syslog(LOG_ERR, "cannot find idcomando column in table: %s\n",
3012                               msglog);
[9dea2d6]3013                        return false;
[b9eb98b]3014                }
3015                if(idcomando==1){ // Arrancar
3016                        if (!tbl.Get("mac", mac)) {
3017                                tbl.GetErrorErrStr(msglog);
[a1d02f4]3018                                syslog(LOG_ERR, "cannot find mac column in table: %s\n",
3019                                       msglog);
[9dea2d6]3020                                return false;
[b9eb98b]3021                        }
[599c505]3022
[507c75c]3023                        lon = splitCadena(ptrIP, iph, ';');
3024                        lon = splitCadena(ptrMacs, mac, ';');
3025
[ad4ae52]3026                        // Se manda por broadcast y por unicast
[507c75c]3027                        if (!Levanta(ptrIP, ptrMacs, lon, (char*)"1"))
[9dea2d6]3028                                return false;
[ad4ae52]3029
[507c75c]3030                        if (!Levanta(ptrIP, ptrMacs, lon, (char*)"2"))
[9dea2d6]3031                                return false;
[ad4ae52]3032
[b9eb98b]3033                }
3034                if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos
[f09aca6]3035                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
3036
[b9eb98b]3037                        strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente
[3e8fcf0]3038                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[b56cbeb]3039                                syslog(LOG_ERR, "failed to send response: %s\n",
3040                                       strerror(errno));
[b9eb98b]3041                        }
[b937298]3042                        //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad
[b9eb98b]3043                }
3044                tbl.MoveNext();
3045        }
[9dea2d6]3046        return true; // No existen registros
[b9eb98b]3047}
[8e0216a]3048
3049// This object stores function handler for messages
3050static struct {
3051        const char *nf; // Nombre de la función
[212280e]3052        bool (*fcn)(TRAMA *, struct og_client *cli);
[4665749]3053} tbfuncionesServer[] = {
[8e0216a]3054        { "InclusionCliente",                   InclusionCliente,       },
3055        { "InclusionClienteWinLnx",             InclusionClienteWinLnx, },
3056        { "AutoexecCliente",                    AutoexecCliente,        },
3057        { "ComandosPendientes",                 ComandosPendientes,     },
3058        { "DisponibilidadComandos",             DisponibilidadComandos, },
3059        { "RESPUESTA_Arrancar",                 RESPUESTA_Arrancar,     },
3060        { "RESPUESTA_Apagar",                   RESPUESTA_Apagar,       },
3061        { "RESPUESTA_Reiniciar",                RESPUESTA_Reiniciar,    },
3062        { "RESPUESTA_IniciarSesion",            RESPUESTA_IniciarSesion, },
3063        { "RESPUESTA_CrearImagen",              RESPUESTA_CrearImagen,  },
3064        { "CrearImagenBasica",                  CrearImagenBasica,      },
3065        { "RESPUESTA_CrearImagenBasica",        RESPUESTA_CrearImagenBasica, },
3066        { "CrearSoftIncremental",               CrearSoftIncremental,   },
3067        { "RESPUESTA_CrearSoftIncremental",     RESPUESTA_CrearSoftIncremental, },
3068        { "RESPUESTA_RestaurarImagen",          RESPUESTA_RestaurarImagen },
3069        { "RestaurarImagenBasica",              RestaurarImagenBasica, },
3070        { "RESPUESTA_RestaurarImagenBasica",    RESPUESTA_RestaurarImagenBasica, },
3071        { "RestaurarSoftIncremental",           RestaurarSoftIncremental, },
3072        { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, },
3073        { "Configurar",                         Configurar,             },
3074        { "RESPUESTA_Configurar",               RESPUESTA_Configurar,   },
3075        { "EjecutarScript",                     EjecutarScript,         },
3076        { "RESPUESTA_EjecutarScript",           RESPUESTA_EjecutarScript, },
3077        { "RESPUESTA_InventarioHardware",       RESPUESTA_InventarioHardware, },
3078        { "RESPUESTA_InventarioSoftware",       RESPUESTA_InventarioSoftware, },
3079        { "enviaArchivo",                       enviaArchivo,           },
3080        { "recibeArchivo",                      recibeArchivo,          },
3081        { "envioProgramacion",                  envioProgramacion,      },
[4665749]3082        { NULL,                                 NULL,                   },
[8e0216a]3083};
3084
3085// ________________________________________________________________________________________________________
3086// Función: gestionaTrama
3087//
3088//              Descripción:
3089//                      Procesa las tramas recibidas .
3090//              Parametros:
3091//                      - s : Socket usado para comunicaciones
3092//      Devuelve:
[9dea2d6]3093//              true: Si el proceso es correcto
3094//              false: En caso de ocurrir algún error
[8e0216a]3095// ________________________________________________________________________________________________________
[b56cbeb]3096static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli)
[8e0216a]3097{
3098        int i, res;
3099        char *nfn;
3100
3101        if (ptrTrama){
3102                INTROaFINCAD(ptrTrama);
3103                nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función
3104
[212280e]3105                for (i = 0; tbfuncionesServer[i].fcn; i++) {
3106                        if (!strncmp(tbfuncionesServer[i].nf, nfn,
3107                                     strlen(tbfuncionesServer[i].nf))) {
3108                                res = tbfuncionesServer[i].fcn(ptrTrama, cli);
[b56cbeb]3109                                if (!res) {
3110                                        syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n",
3111                                               tbfuncionesServer[i].nf,
3112                                               inet_ntoa(cli->addr.sin_addr),
3113                                               ntohs(cli->addr.sin_port));
3114                                } else {
3115                                        syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n",
3116                                               tbfuncionesServer[i].nf,
3117                                               inet_ntoa(cli->addr.sin_addr),
3118                                               ntohs(cli->addr.sin_port));
3119                                }
[212280e]3120                                break;
[8e0216a]3121                        }
3122                }
[ef6e3d2]3123                if (!tbfuncionesServer[i].fcn)
[f09aca6]3124                        syslog(LOG_ERR, "unknown request %s from client %s:%hu\n",
3125                               nfn, inet_ntoa(cli->addr.sin_addr),
3126                               ntohs(cli->addr.sin_port));
[ef6e3d2]3127
[8e0216a]3128                liberaMemoria(nfn);
[212280e]3129        }
3130}
3131
[f09aca6]3132static void og_client_release(struct ev_loop *loop, struct og_client *cli)
3133{
3134        if (cli->keepalive_idx >= 0) {
[2ed3a0c]3135                syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n",
[f09aca6]3136                       inet_ntoa(cli->addr.sin_addr),
3137                       ntohs(cli->addr.sin_port), cli->keepalive_idx);
3138                tbsockets[cli->keepalive_idx].cli = NULL;
3139        }
3140
3141        ev_io_stop(loop, &cli->io);
3142        close(cli->io.fd);
3143        free(cli);
3144}
3145
3146static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli)
3147{
3148        struct og_client *old_cli;
3149
3150        old_cli = tbsockets[cli->keepalive_idx].cli;
3151        if (old_cli && old_cli != cli) {
[2ed3a0c]3152                syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n",
[f09aca6]3153                       inet_ntoa(old_cli->addr.sin_addr),
3154                       ntohs(old_cli->addr.sin_port));
3155
3156                og_client_release(loop, old_cli);
3157        }
3158        tbsockets[cli->keepalive_idx].cli = cli;
3159}
3160
3161static void og_client_reset_state(struct og_client *cli)
3162{
3163        cli->state = OG_CLIENT_RECEIVING_HEADER;
3164        cli->buf_len = 0;
3165}
3166
[d491dfd]3167static int og_client_state_recv_hdr(struct og_client *cli)
[212280e]3168{
3169        char hdrlen[LONHEXPRM];
[d491dfd]3170
3171        /* Still too short to validate protocol fingerprint and message
3172         * length.
3173         */
3174        if (cli->buf_len < 15 + LONHEXPRM)
3175                return 0;
3176
3177        if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) {
3178                syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n",
3179                       inet_ntoa(cli->addr.sin_addr),
3180                       ntohs(cli->addr.sin_port));
3181                return -1;
3182        }
3183
3184        memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM);
3185        cli->msg_len = strtol(hdrlen, NULL, 16);
3186
3187        /* Header announces more that we can fit into buffer. */
3188        if (cli->msg_len >= sizeof(cli->buf)) {
3189                syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n",
3190                       cli->msg_len, inet_ntoa(cli->addr.sin_addr),
3191                       ntohs(cli->addr.sin_port));
3192                return -1;
3193        }
3194
3195        return 1;
3196}
3197
[2226378]3198static TRAMA *og_msg_alloc(char *data, unsigned int len)
[d491dfd]3199{
[212280e]3200        TRAMA *ptrTrama;
[107b17a]3201
3202        ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA));
3203        if (!ptrTrama) {
3204                syslog(LOG_ERR, "OOM\n");
[2226378]3205                return NULL;
[107b17a]3206        }
3207
3208        initParametros(ptrTrama, len);
[2226378]3209        memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA);
[107b17a]3210        memcpy(ptrTrama->parametros, data, len);
3211        ptrTrama->lonprm = len;
3212
[2226378]3213        return ptrTrama;
3214}
[107b17a]3215
[2226378]3216static void og_msg_free(TRAMA *ptrTrama)
3217{
[107b17a]3218        liberaMemoria(ptrTrama->parametros);
3219        liberaMemoria(ptrTrama);
[2226378]3220}
3221
3222static int og_client_state_process_payload(struct og_client *cli)
3223{
3224        TRAMA *ptrTrama;
3225        char *data;
3226        int len;
3227
3228        len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM);
3229        data = &cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM];
3230
3231        ptrTrama = og_msg_alloc(data, len);
3232        if (!ptrTrama)
3233                return -1;
3234
3235        gestionaTrama(ptrTrama, cli);
3236
3237        og_msg_free(ptrTrama);
[107b17a]3238
3239        return 1;
3240}
3241
[881f532]3242#define OG_CLIENTS_MAX  4096
[dbcc83d]3243#define OG_PARTITION_MAX 4
3244
3245struct og_partition {
3246        const char      *number;
3247        const char      *code;
3248        const char      *size;
3249        const char      *filesystem;
3250        const char      *format;
3251};
[881f532]3252
[01e77f4]3253struct og_sync_params {
3254        const char      *sync;
3255        const char      *diff;
3256        const char      *remove;
3257        const char      *compress;
3258        const char      *cleanup;
3259        const char      *cache;
3260        const char      *cleanup_cache;
3261        const char      *remove_dst;
[f61fd9a]3262        const char      *path;
3263        const char      *method;
[01e77f4]3264};
3265
[95e6520]3266struct og_msg_params {
[881f532]3267        const char      *ips_array[OG_CLIENTS_MAX];
3268        const char      *mac_array[OG_CLIENTS_MAX];
[95e6520]3269        unsigned int    ips_array_len;
[5797e0b]3270        const char      *wol_type;
[7e4e5b5]3271        char            run_cmd[4096];
[7ab5f0c]3272        const char      *disk;
3273        const char      *partition;
[1a8ada1]3274        const char      *repository;
3275        const char      *name;
3276        const char      *id;
3277        const char      *code;
[1dde02e]3278        const char      *type;
3279        const char      *profile;
[dbcc83d]3280        const char      *cache;
3281        const char      *cache_size;
3282        struct og_partition     partition_setup[OG_PARTITION_MAX];
[01e77f4]3283        struct og_sync_params sync_setup;
[95e6520]3284};
3285
3286static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
3287{
3288        unsigned int i;
3289        json_t *k;
3290
3291        if (json_typeof(element) != JSON_ARRAY)
3292                return -1;
3293
3294        for (i = 0; i < json_array_size(element); i++) {
3295                k = json_array_get(element, i);
3296                if (json_typeof(k) != JSON_STRING)
3297                        return -1;
3298
3299                params->ips_array[params->ips_array_len++] =
3300                        json_string_value(k);
3301        }
3302        return 0;
3303}
3304
[c87a1db]3305static int og_json_parse_string(json_t *element, const char **str)
3306{
3307        if (json_typeof(element) != JSON_STRING)
3308                return -1;
3309
3310        *str = json_string_value(element);
3311        return 0;
3312}
3313
[01e77f4]3314static int og_json_parse_sync_params(json_t *element, og_sync_params *params)
3315{
3316        const char *key;
3317        json_t *value;
3318        int err = 0;
3319
3320        json_object_foreach(element, key, value) {
3321                if (!strcmp(key, "sync"))
3322                        err = og_json_parse_string(value, &params->sync);
3323                else if (!strcmp(key, "diff"))
3324                        err = og_json_parse_string(value, &params->diff);
3325                else if (!strcmp(key, "remove"))
3326                        err = og_json_parse_string(value, &params->remove);
3327                else if (!strcmp(key, "compress"))
3328                        err = og_json_parse_string(value, &params->compress);
3329                else if (!strcmp(key, "cleanup"))
3330                        err = og_json_parse_string(value, &params->cleanup);
3331                else if (!strcmp(key, "cache"))
3332                        err = og_json_parse_string(value, &params->cache);
3333                else if (!strcmp(key, "cleanup_cache"))
3334                        err = og_json_parse_string(value, &params->cleanup_cache);
3335                else if (!strcmp(key, "remove_dst"))
3336                        err = og_json_parse_string(value, &params->remove_dst);
[f61fd9a]3337                else if (!strcmp(key, "path"))
3338                        err = og_json_parse_string(value, &params->path);
3339                else if (!strcmp(key, "method"))
3340                        err = og_json_parse_string(value, &params->method);
[01e77f4]3341
3342                if (err != 0)
3343                        return err;
3344        }
3345        return err;
3346}
3347
[e3af7ee]3348static int og_json_parse_partition(json_t *element, og_partition *part)
3349{
3350        const char *key;
3351        json_t *value;
3352        int err = 0;
3353
3354        json_object_foreach(element, key, value) {
3355                if (!strcmp(key, "partition"))
3356                        err = og_json_parse_string(value, &part->number);
3357                else if (!strcmp(key, "code"))
3358                        err = og_json_parse_string(value, &part->code);
3359                else if (!strcmp(key, "filesystem"))
3360                        err = og_json_parse_string(value, &part->filesystem);
3361                else if (!strcmp(key, "size"))
3362                        err = og_json_parse_string(value, &part->size);
3363                else if (!strcmp(key, "format"))
3364                        err = og_json_parse_string(value, &part->format);
3365
3366                if (err < 0)
3367                        return err;
3368        }
3369        return err;
[dbcc83d]3370}
3371
3372static int og_json_parse_partition_setup(json_t *element, og_partition *part)
3373{
3374        unsigned int i;
3375        json_t *k;
3376
3377        if (json_typeof(element) != JSON_ARRAY)
3378                return -1;
3379
3380        for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
3381                k = json_array_get(element, i);
3382
3383                if (json_typeof(k) != JSON_OBJECT)
3384                        return -1;
3385
[e3af7ee]3386                if (og_json_parse_partition(k, part + i) != 0)
3387                        return -1;
[dbcc83d]3388        }
3389        return 0;
3390}
3391
[40023ff]3392static int og_cmd_legacy_send(struct og_msg_params *params, const char *cmd,
3393                              const char *state)
[95e6520]3394{
3395        char buf[4096] = {};
3396        int len, err = 0;
3397        TRAMA *msg;
3398
[40023ff]3399        len = snprintf(buf, sizeof(buf), "nfn=%s\r", cmd);
[95e6520]3400
3401        msg = og_msg_alloc(buf, len);
3402        if (!msg)
3403                return -1;
3404
3405        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
[40023ff]3406                         state, msg))
[95e6520]3407                err = -1;
3408
3409        og_msg_free(msg);
3410
3411        return err;
3412}
3413
3414static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
3415{
3416        const char *key;
3417        json_t *value;
3418        int err = 0;
3419
3420        if (json_typeof(element) != JSON_OBJECT)
3421                return -1;
3422
3423        json_object_foreach(element, key, value) {
3424                if (!strcmp(key, "clients"))
3425                        err = og_json_parse_clients(value, params);
3426
3427                if (err < 0)
3428                        break;
3429        }
3430
[40023ff]3431        return og_cmd_legacy_send(params, "Sondeo", CLIENTE_APAGADO);
[95e6520]3432}
3433
[7b6fcdb]3434struct og_buffer {
3435        char    *data;
3436        int     len;
3437};
3438
3439static int og_json_dump_clients(const char *buffer, size_t size, void *data)
3440{
3441        struct og_buffer *og_buffer = (struct og_buffer *)data;
3442
3443        memcpy(og_buffer->data + og_buffer->len, buffer, size);
3444        og_buffer->len += size;
3445
3446        return 0;
3447}
3448
3449static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
3450                              char *buffer_reply)
3451{
3452        json_t *root, *array, *addr, *state, *object;
3453        struct og_buffer og_buffer = {
3454                .data   = buffer_reply,
3455        };
3456        int i;
3457
3458        array = json_array();
3459        if (!array)
3460                return -1;
3461
3462        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
3463                if (tbsockets[i].ip[0] == '\0')
3464                        continue;
3465
3466                object = json_object();
3467                if (!object) {
3468                        json_decref(array);
3469                        return -1;
3470                }
3471                addr = json_string(tbsockets[i].ip);
3472                if (!addr) {
3473                        json_decref(object);
3474                        json_decref(array);
3475                        return -1;
3476                }
3477                json_object_set_new(object, "addr", addr);
3478
3479                state = json_string(tbsockets[i].estado);
3480                if (!state) {
3481                        json_decref(object);
3482                        json_decref(array);
3483                        return -1;
3484                }
3485                json_object_set_new(object, "state", state);
3486
3487                json_array_append_new(array, object);
3488        }
3489        root = json_pack("{s:o}", "clients", array);
3490        if (!root) {
3491                json_decref(array);
3492                return -1;
3493        }
3494
[7e6ba45]3495        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[7b6fcdb]3496        json_decref(root);
3497
3498        return 0;
3499}
3500
[5797e0b]3501static int og_json_parse_target(json_t *element, struct og_msg_params *params)
3502{
3503        const char *key;
3504        json_t *value;
3505
3506        if (json_typeof(element) != JSON_OBJECT) {
3507                return -1;
3508        }
3509
3510        json_object_foreach(element, key, value) {
3511                if (!strcmp(key, "addr")) {
3512                        if (json_typeof(value) != JSON_STRING)
3513                                return -1;
3514
3515                        params->ips_array[params->ips_array_len] =
3516                                json_string_value(value);
3517                } else if (!strcmp(key, "mac")) {
3518                        if (json_typeof(value) != JSON_STRING)
3519                                return -1;
3520
3521                        params->mac_array[params->ips_array_len] =
3522                                json_string_value(value);
3523                }
3524        }
3525
3526        return 0;
3527}
3528
3529static int og_json_parse_targets(json_t *element, struct og_msg_params *params)
3530{
3531        unsigned int i;
3532        json_t *k;
3533        int err;
3534
3535        if (json_typeof(element) != JSON_ARRAY)
3536                return -1;
3537
3538        for (i = 0; i < json_array_size(element); i++) {
3539                k = json_array_get(element, i);
3540
3541                if (json_typeof(k) != JSON_OBJECT)
3542                        return -1;
3543
3544                err = og_json_parse_target(k, params);
3545                if (err < 0)
3546                        return err;
3547
3548                params->ips_array_len++;
3549        }
3550        return 0;
3551}
3552
3553static int og_json_parse_type(json_t *element, struct og_msg_params *params)
3554{
3555        const char *type;
3556
3557        if (json_typeof(element) != JSON_STRING)
3558                return -1;
3559
3560        params->wol_type = json_string_value(element);
3561
3562        type = json_string_value(element);
3563        if (!strcmp(type, "unicast"))
3564                params->wol_type = "2";
3565        else if (!strcmp(type, "broadcast"))
3566                params->wol_type = "1";
3567
3568        return 0;
3569}
3570
3571static int og_cmd_wol(json_t *element, struct og_msg_params *params)
3572{
3573        const char *key;
3574        json_t *value;
3575        int err = 0;
3576
3577        if (json_typeof(element) != JSON_OBJECT)
3578                return -1;
3579
3580        json_object_foreach(element, key, value) {
3581                if (!strcmp(key, "clients")) {
3582                        err = og_json_parse_targets(value, params);
3583                } else if (!strcmp(key, "type")) {
3584                        err = og_json_parse_type(value, params);
3585                }
3586
3587                if (err < 0)
3588                        break;
3589        }
3590
3591        if (!Levanta((char **)params->ips_array, (char **)params->mac_array,
3592                     params->ips_array_len, (char *)params->wol_type))
3593                return -1;
3594
3595        return 0;
3596}
3597
[7e4e5b5]3598static int og_json_parse_run(json_t *element, struct og_msg_params *params)
3599{
3600        if (json_typeof(element) != JSON_STRING)
3601                return -1;
3602
3603        snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
3604                 json_string_value(element));
3605
3606        return 0;
3607}
3608
3609static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
3610{
3611        char buf[4096] = {}, iph[4096] = {};
3612        int err = 0, len;
3613        const char *key;
3614        unsigned int i;
3615        json_t *value;
3616        TRAMA *msg;
3617
3618        if (json_typeof(element) != JSON_OBJECT)
3619                return -1;
3620
3621        json_object_foreach(element, key, value) {
3622                if (!strcmp(key, "clients"))
3623                        err = og_json_parse_clients(value, params);
3624                if (!strcmp(key, "run"))
3625                        err = og_json_parse_run(value, params);
3626
3627                if (err < 0)
3628                        break;
3629        }
3630
3631        for (i = 0; i < params->ips_array_len; i++) {
3632                len = snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3633                               params->ips_array[i]);
3634        }
3635        len = snprintf(buf, sizeof(buf), "nfn=ConsolaRemota\riph=%s\rscp=%s\r",
3636                       iph, params->run_cmd);
3637
3638        msg = og_msg_alloc(buf, len);
3639        if (!msg)
3640                return -1;
3641
3642        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3643                         CLIENTE_OCUPADO, msg))
3644                err = -1;
3645
3646        og_msg_free(msg);
3647
3648        if (err < 0)
3649                return err;
3650
3651        for (i = 0; i < params->ips_array_len; i++) {
3652                char filename[4096];
3653                FILE *f;
3654
3655                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3656                f = fopen(filename, "wt");
3657                fclose(f);
3658        }
3659
3660        return 0;
3661}
3662
[c6020f2]3663static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
3664                          char *buffer_reply)
3665{
3666        struct og_buffer og_buffer = {
3667                .data   = buffer_reply,
3668        };
3669        json_t *root, *value, *array;
3670        const char *key;
3671        unsigned int i;
3672        int err = 0;
3673
3674        if (json_typeof(element) != JSON_OBJECT)
3675                return -1;
3676
3677        json_object_foreach(element, key, value) {
3678                if (!strcmp(key, "clients"))
3679                        err = og_json_parse_clients(value, params);
3680
3681                if (err < 0)
3682                        return err;
3683        }
3684
3685        array = json_array();
3686        if (!array)
3687                return -1;
3688
3689        for (i = 0; i < params->ips_array_len; i++) {
3690                json_t *object, *output, *addr;
3691                char data[4096] = {};
3692                char filename[4096];
3693                int fd, numbytes;
3694
3695                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3696
3697                fd = open(filename, O_RDONLY);
3698                if (!fd)
3699                        return -1;
3700
3701                numbytes = read(fd, data, sizeof(data));
3702                if (numbytes < 0) {
3703                        close(fd);
3704                        return -1;
3705                }
3706                data[sizeof(data) - 1] = '\0';
3707                close(fd);
3708
3709                object = json_object();
3710                if (!object) {
3711                        json_decref(array);
3712                        return -1;
3713                }
3714                addr = json_string(params->ips_array[i]);
3715                if (!addr) {
3716                        json_decref(object);
3717                        json_decref(array);
3718                        return -1;
3719                }
3720                json_object_set_new(object, "addr", addr);
3721
3722                output = json_string(data);
3723                if (!output) {
3724                        json_decref(object);
3725                        json_decref(array);
3726                        return -1;
3727                }
3728                json_object_set_new(object, "output", output);
3729
3730                json_array_append_new(array, object);
3731        }
3732
3733        root = json_pack("{s:o}", "clients", array);
3734        if (!root)
3735                return -1;
3736
[7e6ba45]3737        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[c6020f2]3738        json_decref(root);
3739
3740        return 0;
3741}
3742
[7ab5f0c]3743static int og_cmd_session(json_t *element, struct og_msg_params *params)
3744{
3745        char buf[4096], iph[4096];
3746        int err = 0, len;
3747        const char *key;
3748        unsigned int i;
3749        json_t *value;
3750        TRAMA *msg;
3751
3752        if (json_typeof(element) != JSON_OBJECT)
3753                return -1;
3754
3755        json_object_foreach(element, key, value) {
[7bdc8fd]3756                if (!strcmp(key, "clients"))
[7ab5f0c]3757                        err = og_json_parse_clients(value, params);
[7bdc8fd]3758                else if (!strcmp(key, "disk"))
[c87a1db]3759                        err = og_json_parse_string(value, &params->disk);
[7bdc8fd]3760                else if (!strcmp(key, "partition"))
[c87a1db]3761                        err = og_json_parse_string(value, &params->partition);
[7ab5f0c]3762
3763                if (err < 0)
3764                        return err;
3765        }
3766
3767        for (i = 0; i < params->ips_array_len; i++) {
3768                snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3769                         params->ips_array[i]);
3770        }
3771        len = snprintf(buf, sizeof(buf),
3772                       "nfn=IniciarSesion\riph=%s\rdsk=%s\rpar=%s\r",
3773                       iph, params->disk, params->partition);
3774
3775        msg = og_msg_alloc(buf, len);
3776        if (!msg)
3777                return -1;
3778
3779        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3780                         CLIENTE_APAGADO, msg))
3781                err = -1;
3782
3783        og_msg_free(msg);
3784
3785        return 0;
3786}
3787
[23fed47]3788static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
3789{
3790        const char *key;
3791        json_t *value;
3792        int err = 0;
3793
3794        if (json_typeof(element) != JSON_OBJECT)
3795                return -1;
3796
3797        json_object_foreach(element, key, value) {
3798                if (!strcmp(key, "clients"))
3799                        err = og_json_parse_clients(value, params);
3800
3801                if (err < 0)
3802                        break;
3803        }
3804
3805        return og_cmd_legacy_send(params, "Apagar", CLIENTE_OCUPADO);
3806}
3807
[17f55b4]3808static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
3809{
3810        const char *key;
3811        json_t *value;
3812        int err = 0;
3813
3814        if (json_typeof(element) != JSON_OBJECT)
3815                return -1;
3816
3817        json_object_foreach(element, key, value) {
3818                if (!strcmp(key, "clients"))
3819                        err = og_json_parse_clients(value, params);
3820
3821                if (err < 0)
3822                        break;
3823        }
3824
3825        return og_cmd_legacy_send(params, "Actualizar", CLIENTE_APAGADO);
3826}
3827
[5f0191d]3828static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
3829{
3830        const char *key;
3831        json_t *value;
3832        int err = 0;
3833
3834        if (json_typeof(element) != JSON_OBJECT)
3835                return -1;
3836
3837        json_object_foreach(element, key, value) {
3838                if (!strcmp(key, "clients"))
3839                        err = og_json_parse_clients(value, params);
3840
3841                if (err < 0)
3842                        break;
3843        }
3844
3845        return og_cmd_legacy_send(params, "Reiniciar", CLIENTE_OCUPADO);
3846}
3847
[1e6c889]3848static int og_cmd_stop(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
3865        return og_cmd_legacy_send(params, "Purgar", CLIENTE_APAGADO);
3866}
3867
[6b30dbc]3868static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
3869{
3870        const char *key;
3871        json_t *value;
3872        int err = 0;
3873
3874        if (json_typeof(element) != JSON_OBJECT)
3875                return -1;
3876
3877        json_object_foreach(element, key, value) {
3878                if (!strcmp(key, "clients"))
3879                        err = og_json_parse_clients(value, params);
3880
3881                if (err < 0)
3882                        break;
3883        }
3884
3885        return og_cmd_legacy_send(params, "InventarioHardware",
3886                                  CLIENTE_OCUPADO);
3887}
3888
[b4a9fdd]3889static int og_cmd_software(json_t *element, struct og_msg_params *params)
3890{
3891        const char *key;
3892        json_t *value;
3893        int err = 0;
3894
3895        if (json_typeof(element) != JSON_OBJECT)
3896                return -1;
3897
3898        json_object_foreach(element, key, value) {
3899                if (!strcmp(key, "clients"))
3900                        err = og_json_parse_clients(value, params);
3901
3902                if (err < 0)
3903                        break;
3904        }
3905
3906        return og_cmd_legacy_send(params, "InventarioSoftware",
3907                                  CLIENTE_OCUPADO);
3908}
3909
[1a8ada1]3910static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
3911{
3912        char buf[4096] = {};
3913        int err = 0, len;
3914        const char *key;
3915        json_t *value;
3916        TRAMA *msg;
3917
3918        if (json_typeof(element) != JSON_OBJECT)
3919                return -1;
3920
3921        json_object_foreach(element, key, value) {
3922                if (!strcmp(key, "disk"))
[c87a1db]3923                        err = og_json_parse_string(value, &params->disk);
[1a8ada1]3924                else if (!strcmp(key, "partition"))
[c87a1db]3925                        err = og_json_parse_string(value, &params->partition);
[1a8ada1]3926                else if (!strcmp(key, "name"))
[c87a1db]3927                        err = og_json_parse_string(value, &params->name);
[1a8ada1]3928                else if (!strcmp(key, "repository"))
[c87a1db]3929                        err = og_json_parse_string(value, &params->repository);
[1a8ada1]3930                else if (!strcmp(key, "clients"))
3931                        err = og_json_parse_clients(value, params);
3932                else if (!strcmp(key, "id"))
[c87a1db]3933                        err = og_json_parse_string(value, &params->id);
[1a8ada1]3934                else if (!strcmp(key, "code"))
[c87a1db]3935                        err = og_json_parse_string(value, &params->code);
[1a8ada1]3936
3937                if (err < 0)
3938                        break;
3939        }
3940
3941        len = snprintf(buf, sizeof(buf),
3942                        "nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
3943                        params->disk, params->partition, params->code,
3944                        params->id, params->name, params->repository);
3945
3946        msg = og_msg_alloc(buf, len);
3947        if (!msg)
3948                return -1;
3949
3950        og_send_cmd((char **)params->ips_array, params->ips_array_len,
3951                    CLIENTE_OCUPADO, msg);
3952
3953        og_msg_free(msg);
3954
3955        return 0;
3956}
3957
[1dde02e]3958static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
3959{
3960        char buf[4096] = {};
3961        int err = 0, len;
3962        const char *key;
3963        json_t *value;
3964        TRAMA *msg;
3965
3966        if (json_typeof(element) != JSON_OBJECT)
3967                return -1;
3968
3969        json_object_foreach(element, key, value) {
3970                if (!strcmp(key, "disk"))
3971                        err = og_json_parse_string(value, &params->disk);
3972                else if (!strcmp(key, "partition"))
3973                        err = og_json_parse_string(value, &params->partition);
3974                else if (!strcmp(key, "name"))
3975                        err = og_json_parse_string(value, &params->name);
3976                else if (!strcmp(key, "repository"))
3977                        err = og_json_parse_string(value, &params->repository);
3978                else if (!strcmp(key, "clients"))
3979                        err = og_json_parse_clients(value, params);
3980                else if (!strcmp(key, "type"))
3981                        err = og_json_parse_string(value, &params->type);
3982                else if (!strcmp(key, "profile"))
3983                        err = og_json_parse_string(value, &params->profile);
3984                else if (!strcmp(key, "id"))
3985                        err = og_json_parse_string(value, &params->id);
3986
3987                if (err < 0)
3988                        break;
3989        }
3990
3991        len = snprintf(buf, sizeof(buf),
3992                       "nfn=RestaurarImagen\ridi=%s\rdsk=%s\rpar=%s\rifs=%s\r"
3993                       "nci=%s\ripr=%s\rptc=%s\r",
3994                       params->id, params->disk, params->partition,
3995                       params->profile, params->name,
3996                       params->repository, params->type);
3997
3998        msg = og_msg_alloc(buf, len);
3999        if (!msg)
4000                return -1;
4001
4002        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4003                    CLIENTE_OCUPADO, msg);
4004
4005        og_msg_free(msg);
4006
4007        return 0;
4008}
4009
[dbcc83d]4010static int og_cmd_setup_image(json_t *element, struct og_msg_params *params)
4011{
4012        char buf[4096] = {};
4013        int err = 0, len;
4014        const char *key;
4015        json_t *value;
4016        TRAMA *msg;
4017
4018        if (json_typeof(element) != JSON_OBJECT)
4019                return -1;
4020
4021        json_object_foreach(element, key, value) {
4022                if (!strcmp(key, "clients"))
4023                        err = og_json_parse_clients(value, params);
4024                else if (!strcmp(key, "disk"))
4025                        err = og_json_parse_string(value, &params->disk);
4026                else if (!strcmp(key, "cache"))
4027                        err = og_json_parse_string(value, &params->cache);
4028                else if (!strcmp(key, "cache_size"))
4029                        err = og_json_parse_string(value, &params->cache_size);
4030                else if (!strcmp(key, "partition_setup"))
4031                        err = og_json_parse_partition_setup(value, params->partition_setup);
4032
4033                if (err < 0)
4034                        break;
4035        }
4036
4037        len = snprintf(buf, sizeof(buf),
4038                        "nfn=Configurar\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!",
4039                        params->disk, params->disk, params->cache, params->cache_size);
4040
4041        for (unsigned int i = 0; i < OG_PARTITION_MAX; ++i) {
4042                const og_partition *part = params->partition_setup + i;
4043
4044                len += snprintf(buf + strlen(buf), sizeof(buf),
4045                        "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%",
4046                        part->number, part->code, part->filesystem, part->size, part->format);
4047        }
4048
4049        msg = og_msg_alloc(buf, len + 1);
4050        if (!msg)
4051                return -1;
4052
4053        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4054                        CLIENTE_OCUPADO, msg);
4055
4056        og_msg_free(msg);
4057
4058        return 0;
4059}
4060
[01e77f4]4061static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params)
4062{
4063        char buf[4096] = {};
4064        int err = 0, len;
4065        const char *key;
4066        json_t *value;
4067        TRAMA *msg;
4068
4069        if (json_typeof(element) != JSON_OBJECT)
4070                return -1;
4071
4072        json_object_foreach(element, key, value) {
4073                if (!strcmp(key, "clients"))
4074                        err = og_json_parse_clients(value, params);
4075                else if (!strcmp(key, "disk"))
4076                        err = og_json_parse_string(value, &params->disk);
4077                else if (!strcmp(key, "partition"))
4078                        err = og_json_parse_string(value, &params->partition);
4079                else if (!strcmp(key, "code"))
4080                        err = og_json_parse_string(value, &params->code);
4081                else if (!strcmp(key, "id"))
4082                        err = og_json_parse_string(value, &params->id);
4083                else if (!strcmp(key, "name"))
4084                        err = og_json_parse_string(value, &params->name);
4085                else if (!strcmp(key, "repository"))
4086                        err = og_json_parse_string(value, &params->repository);
4087                else if (!strcmp(key, "sync_params"))
4088                        err = og_json_parse_sync_params(value, &(params->sync_setup));
4089
4090                if (err < 0)
4091                        break;
4092        }
4093
4094        len = snprintf(buf, sizeof(buf),
4095                       "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r"
4096                       "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r"
4097                       "cpc=%s\rbpc=%s\rnba=%s\r",
4098                       params->disk, params->partition, params->code, params->id,
4099                       params->name, params->repository, params->sync_setup.sync,
4100                       params->sync_setup.diff, params->sync_setup.remove,
4101                       params->sync_setup.compress, params->sync_setup.cleanup,
4102                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4103                       params->sync_setup.remove_dst);
4104
4105        msg = og_msg_alloc(buf, len);
4106        if (!msg)
4107                return -1;
4108
4109        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4110                    CLIENTE_OCUPADO, msg);
4111
4112        og_msg_free(msg);
4113
4114        return 0;
4115}
4116
[f61fd9a]4117static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params)
4118{
4119        char buf[4096] = {};
4120        int err = 0, len;
4121        const char *key;
4122        json_t *value;
4123        TRAMA *msg;
4124
4125        if (json_typeof(element) != JSON_OBJECT)
4126                return -1;
4127
4128        json_object_foreach(element, key, value) {
4129                if (!strcmp(key, "clients"))
4130                        err = og_json_parse_clients(value, params);
4131                else if (!strcmp(key, "disk"))
4132                        err = og_json_parse_string(value, &params->disk);
4133                else if (!strcmp(key, "partition"))
4134                        err = og_json_parse_string(value, &params->partition);
4135                else if (!strcmp(key, "id"))
4136                        err = og_json_parse_string(value, &params->id);
4137                else if (!strcmp(key, "name"))
4138                        err = og_json_parse_string(value, &params->name);
4139                else if (!strcmp(key, "repository"))
4140                        err = og_json_parse_string(value, &params->repository);
4141                else if (!strcmp(key, "profile"))
4142                        err = og_json_parse_string(value, &params->profile);
4143                else if (!strcmp(key, "type"))
4144                        err = og_json_parse_string(value, &params->type);
4145                else if (!strcmp(key, "sync_params"))
4146                        err = og_json_parse_sync_params(value, &(params->sync_setup));
4147
4148                if (err < 0)
4149                        break;
4150        }
4151
4152        len = snprintf(buf, sizeof(buf),
4153                       "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4154                           "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r"
4155                           "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
4156                       params->disk, params->partition, params->id, params->name,
4157                           params->repository, params->profile, params->sync_setup.path,
4158                           params->sync_setup.method, params->sync_setup.sync, params->type,
4159                           params->sync_setup.diff, params->sync_setup.remove,
4160                       params->sync_setup.compress, params->sync_setup.cleanup,
4161                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4162                       params->sync_setup.remove_dst);
4163
4164        msg = og_msg_alloc(buf, len);
4165        if (!msg)
4166                return -1;
4167
4168        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4169                    CLIENTE_OCUPADO, msg);
4170
4171        og_msg_free(msg);
4172
4173        return 0;
4174}
4175
[7dc8fdb]4176static int og_client_method_not_found(struct og_client *cli)
4177{
4178        /* To meet RFC 7231, this function MUST generate an Allow header field
4179         * containing the correct methods. For example: "Allow: POST\r\n"
4180         */
4181        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
4182                     "Content-Length: 0\r\n\r\n";
4183
4184        send(og_client_socket(cli), buf, strlen(buf), 0);
4185
4186        return -1;
4187}
4188
[c1c89e1]4189static int og_client_bad_request(struct og_client *cli)
4190{
4191        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
4192
4193        send(og_client_socket(cli), buf, strlen(buf), 0);
4194
4195        return -1;
4196}
4197
[95e6520]4198static int og_client_not_found(struct og_client *cli)
4199{
4200        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
4201
4202        send(og_client_socket(cli), buf, strlen(buf), 0);
4203
4204        return -1;
4205}
4206
[fd30540]4207static int og_client_not_authorized(struct og_client *cli)
4208{
[66001f0]4209        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
4210                     "WWW-Authenticate: Basic\r\n"
4211                     "Content-Length: 0\r\n\r\n";
[fd30540]4212
4213        send(og_client_socket(cli), buf, strlen(buf), 0);
4214
4215        return -1;
4216}
4217
[15685e6]4218static int og_server_internal_error(struct og_client *cli)
4219{
4220        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
4221                     "Content-Length: 0\r\n\r\n";
4222
4223        send(og_client_socket(cli), buf, strlen(buf), 0);
4224
4225        return -1;
4226}
4227
[e80c85f]4228#define OG_MSG_RESPONSE_MAXLEN  65536
4229
[7b6fcdb]4230static int og_client_ok(struct og_client *cli, char *buf_reply)
[95e6520]4231{
[e80c85f]4232        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
[fbc30b2]4233        int err = 0, len;
[7b6fcdb]4234
[fbc30b2]4235        len = snprintf(buf, sizeof(buf),
4236                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
4237                       strlen(buf_reply), buf_reply);
[15685e6]4238        if (len >= (int)sizeof(buf))
4239                err = og_server_internal_error(cli);
[95e6520]4240
4241        send(og_client_socket(cli), buf, strlen(buf), 0);
4242
[fbc30b2]4243        return err;
[95e6520]4244}
4245
4246enum og_rest_method {
4247        OG_METHOD_GET   = 0,
4248        OG_METHOD_POST,
4249};
4250
4251static int og_client_state_process_payload_rest(struct og_client *cli)
4252{
[e80c85f]4253        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
[95e6520]4254        struct og_msg_params params = {};
4255        enum og_rest_method method;
[eb6aa82]4256        const char *cmd, *body;
[95e6520]4257        json_error_t json_err;
4258        json_t *root = NULL;
4259        int err = 0;
4260
[84a2563]4261        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
4262               inet_ntoa(cli->addr.sin_addr),
4263               ntohs(cli->addr.sin_port), cli->buf);
4264
[95e6520]4265        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
4266                method = OG_METHOD_GET;
4267                cmd = cli->buf + strlen("GET") + 2;
4268        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
4269                method = OG_METHOD_POST;
4270                cmd = cli->buf + strlen("POST") + 2;
4271        } else
[7dc8fdb]4272                return og_client_method_not_found(cli);
[95e6520]4273
4274        body = strstr(cli->buf, "\r\n\r\n") + 4;
4275
[fd30540]4276        if (strcmp(cli->auth_token, auth_token)) {
4277                syslog(LOG_ERR, "wrong Authentication key\n");
4278                return og_client_not_authorized(cli);
4279        }
4280
[eb6aa82]4281        if (cli->content_length) {
[95e6520]4282                root = json_loads(body, 0, &json_err);
4283                if (!root) {
4284                        syslog(LOG_ERR, "malformed json line %d: %s\n",
4285                               json_err.line, json_err.text);
4286                        return og_client_not_found(cli);
4287                }
4288        }
4289
4290        if (!strncmp(cmd, "clients", strlen("clients"))) {
[7b6fcdb]4291                if (method != OG_METHOD_POST &&
4292                    method != OG_METHOD_GET)
[7dc8fdb]4293                        return og_client_method_not_found(cli);
[7b6fcdb]4294
4295                if (method == OG_METHOD_POST && !root) {
[95e6520]4296                        syslog(LOG_ERR, "command clients with no payload\n");
[c1c89e1]4297                        return og_client_bad_request(cli);
[95e6520]4298                }
[7b6fcdb]4299                switch (method) {
4300                case OG_METHOD_POST:
4301                        err = og_cmd_post_clients(root, &params);
4302                        break;
4303                case OG_METHOD_GET:
4304                        err = og_cmd_get_clients(root, &params, buf_reply);
4305                        break;
4306                }
[5797e0b]4307        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
4308                if (method != OG_METHOD_POST)
[7dc8fdb]4309                        return og_client_method_not_found(cli);
[5797e0b]4310
4311                if (!root) {
4312                        syslog(LOG_ERR, "command wol with no payload\n");
[c1c89e1]4313                        return og_client_bad_request(cli);
[5797e0b]4314                }
4315                err = og_cmd_wol(root, &params);
[7e4e5b5]4316        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
4317                if (method != OG_METHOD_POST)
[7dc8fdb]4318                        return og_client_method_not_found(cli);
[7e4e5b5]4319
4320                if (!root) {
4321                        syslog(LOG_ERR, "command run with no payload\n");
[c1c89e1]4322                        return og_client_bad_request(cli);
[7e4e5b5]4323                }
4324                err = og_cmd_run_post(root, &params);
[c6020f2]4325        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
4326                if (method != OG_METHOD_POST)
[7dc8fdb]4327                        return og_client_method_not_found(cli);
[c6020f2]4328
4329                if (!root) {
4330                        syslog(LOG_ERR, "command output with no payload\n");
[c1c89e1]4331                        return og_client_bad_request(cli);
[c6020f2]4332                }
4333
4334                err = og_cmd_run_get(root, &params, buf_reply);
[7ab5f0c]4335        } else if (!strncmp(cmd, "session", strlen("session"))) {
4336                if (method != OG_METHOD_POST)
[7dc8fdb]4337                        return og_client_method_not_found(cli);
[7ab5f0c]4338
4339                if (!root) {
4340                        syslog(LOG_ERR, "command session with no payload\n");
[c1c89e1]4341                        return og_client_bad_request(cli);
[7ab5f0c]4342                }
4343                err = og_cmd_session(root, &params);
[23fed47]4344        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
4345                if (method != OG_METHOD_POST)
[7dc8fdb]4346                        return og_client_method_not_found(cli);
[23fed47]4347
4348                if (!root) {
4349                        syslog(LOG_ERR, "command poweroff with no payload\n");
[c1c89e1]4350                        return og_client_bad_request(cli);
[23fed47]4351                }
4352                err = og_cmd_poweroff(root, &params);
[5f0191d]4353        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
4354                if (method != OG_METHOD_POST)
[7dc8fdb]4355                        return og_client_method_not_found(cli);
[5f0191d]4356
4357                if (!root) {
4358                        syslog(LOG_ERR, "command reboot with no payload\n");
[c1c89e1]4359                        return og_client_bad_request(cli);
[5f0191d]4360                }
4361                err = og_cmd_reboot(root, &params);
[1e6c889]4362        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
4363                if (method != OG_METHOD_POST)
[7dc8fdb]4364                        return og_client_method_not_found(cli);
[1e6c889]4365
4366                if (!root) {
4367                        syslog(LOG_ERR, "command stop with no payload\n");
[c1c89e1]4368                        return og_client_bad_request(cli);
[1e6c889]4369                }
4370                err = og_cmd_stop(root, &params);
[17f55b4]4371        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
4372                if (method != OG_METHOD_POST)
[7dc8fdb]4373                        return og_client_method_not_found(cli);
[17f55b4]4374
4375                if (!root) {
4376                        syslog(LOG_ERR, "command refresh with no payload\n");
[c1c89e1]4377                        return og_client_bad_request(cli);
[17f55b4]4378                }
4379                err = og_cmd_refresh(root, &params);
[6b30dbc]4380        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4381                if (method != OG_METHOD_POST)
[7dc8fdb]4382                        return og_client_method_not_found(cli);
[6b30dbc]4383
4384                if (!root) {
4385                        syslog(LOG_ERR, "command hardware with no payload\n");
[c1c89e1]4386                        return og_client_bad_request(cli);
[6b30dbc]4387                }
4388                err = og_cmd_hardware(root, &params);
[b4a9fdd]4389        } else if (!strncmp(cmd, "software", strlen("software"))) {
4390                if (method != OG_METHOD_POST)
[7dc8fdb]4391                        return og_client_method_not_found(cli);
[b4a9fdd]4392
4393                if (!root) {
4394                        syslog(LOG_ERR, "command software with no payload\n");
[c1c89e1]4395                        return og_client_bad_request(cli);
[b4a9fdd]4396                }
4397                err = og_cmd_software(root, &params);
[01e77f4]4398        } else if (!strncmp(cmd, "image/create/basic",
4399                            strlen("image/create/basic"))) {
4400                if (method != OG_METHOD_POST)
4401                        return og_client_method_not_found(cli);
4402
4403                if (!root) {
4404                        syslog(LOG_ERR, "command create with no payload\n");
4405                        return og_client_bad_request(cli);
4406                }
4407                err = og_cmd_create_basic_image(root, &params);
[1a8ada1]4408        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4409                if (method != OG_METHOD_POST)
4410                        return og_client_method_not_found(cli);
4411
4412                if (!root) {
4413                        syslog(LOG_ERR, "command create with no payload\n");
4414                        return og_client_bad_request(cli);
4415                }
4416                err = og_cmd_create_image(root, &params);
[f61fd9a]4417        } else if (!strncmp(cmd, "image/restore/basic",
4418                                strlen("image/restore/basic"))) {
4419                if (method != OG_METHOD_POST)
4420                        return og_client_method_not_found(cli);
4421
4422                if (!root) {
4423                        syslog(LOG_ERR, "command create with no payload\n");
4424                        return og_client_bad_request(cli);
4425                }
4426                err = og_cmd_restore_basic_image(root, &params);
[1dde02e]4427        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4428                if (method != OG_METHOD_POST)
4429                        return og_client_method_not_found(cli);
4430
4431                if (!root) {
4432                        syslog(LOG_ERR, "command create with no payload\n");
4433                        return og_client_bad_request(cli);
4434                }
4435                err = og_cmd_restore_image(root, &params);
[dbcc83d]4436        } else if (!strncmp(cmd, "image/setup", strlen("image/setup"))) {
4437                if (method != OG_METHOD_POST)
4438                        return og_client_method_not_found(cli);
4439
4440                if (!root) {
4441                        syslog(LOG_ERR, "command create with no payload\n");
4442                        return og_client_bad_request(cli);
4443                }
4444                err = og_cmd_setup_image(root, &params);
[95e6520]4445        } else {
[7c67487]4446                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
[95e6520]4447                err = og_client_not_found(cli);
4448        }
4449
[7b6fcdb]4450        if (root)
4451                json_decref(root);
[95e6520]4452
[a12af6a]4453        if (err < 0)
4454                return err;
4455
4456        err = og_client_ok(cli, buf_reply);
4457        if (err < 0) {
4458                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4459                       inet_ntoa(cli->addr.sin_addr),
4460                       ntohs(cli->addr.sin_port));
4461        }
[95e6520]4462
4463        return err;
4464}
4465
4466static int og_client_state_recv_hdr_rest(struct og_client *cli)
4467{
[eb6aa82]4468        char *ptr;
[95e6520]4469
[eb6aa82]4470        ptr = strstr(cli->buf, "\r\n\r\n");
4471        if (!ptr)
[95e6520]4472                return 0;
4473
[eb6aa82]4474        cli->msg_len = ptr - cli->buf + 4;
4475
4476        ptr = strstr(cli->buf, "Content-Length: ");
4477        if (ptr) {
4478                sscanf(ptr, "Content-Length: %i[^\r\n]", &cli->content_length);
[36ad006]4479                if (cli->content_length < 0)
4480                        return -1;
[eb6aa82]4481                cli->msg_len += cli->content_length;
4482        }
4483
[fd30540]4484        ptr = strstr(cli->buf, "Authorization: ");
4485        if (ptr)
[64e6537]4486                sscanf(ptr, "Authorization: %63[^\r\n]", cli->auth_token);
[fd30540]4487
[95e6520]4488        return 1;
4489}
4490
[107b17a]4491static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
4492{
4493        struct og_client *cli;
4494        int ret;
[212280e]4495
4496        cli = container_of(io, struct og_client, io);
4497
[f09aca6]4498        if (events & EV_ERROR) {
4499                syslog(LOG_ERR, "unexpected error event from client %s:%hu\n",
4500                               inet_ntoa(cli->addr.sin_addr),
4501                               ntohs(cli->addr.sin_port));
4502                goto close;
4503        }
4504
[212280e]4505        ret = recv(io->fd, cli->buf + cli->buf_len,
4506                   sizeof(cli->buf) - cli->buf_len, 0);
[f09aca6]4507        if (ret <= 0) {
4508                if (ret < 0) {
4509                        syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n",
4510                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
4511                               strerror(errno));
4512                } else {
[2ed3a0c]4513                        syslog(LOG_DEBUG, "closed connection by %s:%hu\n",
[f09aca6]4514                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
4515                }
[212280e]4516                goto close;
[f09aca6]4517        }
4518
4519        if (cli->keepalive_idx >= 0)
4520                return;
[212280e]4521
4522        ev_timer_again(loop, &cli->timer);
4523
4524        cli->buf_len += ret;
[20dcb0a]4525        if (cli->buf_len >= sizeof(cli->buf)) {
4526                syslog(LOG_ERR, "client request from %s:%hu is too long\n",
4527                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
4528                goto close;
4529        }
[212280e]4530
4531        switch (cli->state) {
4532        case OG_CLIENT_RECEIVING_HEADER:
[95e6520]4533                if (cli->rest)
4534                        ret = og_client_state_recv_hdr_rest(cli);
4535                else
4536                        ret = og_client_state_recv_hdr(cli);
4537
[d491dfd]4538                if (ret < 0)
[212280e]4539                        goto close;
[d491dfd]4540                if (!ret)
4541                        return;
[212280e]4542
4543                cli->state = OG_CLIENT_RECEIVING_PAYLOAD;
4544                /* Fall through. */
4545        case OG_CLIENT_RECEIVING_PAYLOAD:
4546                /* Still not enough data to process request. */
4547                if (cli->buf_len < cli->msg_len)
4548                        return;
4549
4550                cli->state = OG_CLIENT_PROCESSING_REQUEST;
4551                /* fall through. */
4552        case OG_CLIENT_PROCESSING_REQUEST:
[a12af6a]4553                if (cli->rest) {
[95e6520]4554                        ret = og_client_state_process_payload_rest(cli);
[a12af6a]4555                        if (ret < 0) {
4556                                syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n",
4557                                       inet_ntoa(cli->addr.sin_addr),
4558                                       ntohs(cli->addr.sin_port));
4559                        }
4560                } else {
[95e6520]4561                        ret = og_client_state_process_payload(cli);
[a12af6a]4562                }
[107b17a]4563                if (ret < 0)
[212280e]4564                        goto close;
4565
[f09aca6]4566                if (cli->keepalive_idx < 0) {
[2ed3a0c]4567                        syslog(LOG_DEBUG, "server closing connection to %s:%hu\n",
[f09aca6]4568                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[212280e]4569                        goto close;
[f09aca6]4570                } else {
[2ed3a0c]4571                        syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n",
[f09aca6]4572                               inet_ntoa(cli->addr.sin_addr),
4573                               ntohs(cli->addr.sin_port));
4574                        og_client_keepalive(loop, cli);
4575                        og_client_reset_state(cli);
4576                }
[212280e]4577                break;
[ef6e3d2]4578        default:
4579                syslog(LOG_ERR, "unknown state, critical internal error\n");
4580                goto close;
[8e0216a]4581        }
[212280e]4582        return;
4583close:
4584        ev_timer_stop(loop, &cli->timer);
[f09aca6]4585        og_client_release(loop, cli);
[8e0216a]4586}
4587
[212280e]4588static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events)
4589{
4590        struct og_client *cli;
4591
4592        cli = container_of(timer, struct og_client, timer);
[f09aca6]4593        if (cli->keepalive_idx >= 0) {
[212280e]4594                ev_timer_again(loop, &cli->timer);
4595                return;
4596        }
[f09aca6]4597        syslog(LOG_ERR, "timeout request for client %s:%hu\n",
4598               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[ef6e3d2]4599
[f09aca6]4600        og_client_release(loop, cli);
[212280e]4601}
4602
[95e6520]4603static int socket_s, socket_rest;
4604
[212280e]4605static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io,
4606                                int events)
4607{
4608        struct sockaddr_in client_addr;
4609        socklen_t addrlen = sizeof(client_addr);
4610        struct og_client *cli;
4611        int client_sd;
4612
4613        if (events & EV_ERROR)
4614                return;
4615
4616        client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen);
4617        if (client_sd < 0) {
[b56cbeb]4618                syslog(LOG_ERR, "cannot accept client connection\n");
[212280e]4619                return;
4620        }
4621
4622        cli = (struct og_client *)calloc(1, sizeof(struct og_client));
4623        if (!cli) {
4624                close(client_sd);
4625                return;
4626        }
[ef6e3d2]4627        memcpy(&cli->addr, &client_addr, sizeof(client_addr));
[f09aca6]4628        cli->keepalive_idx = -1;
[ef6e3d2]4629
[95e6520]4630        if (io->fd == socket_rest)
4631                cli->rest = true;
4632
[2ed3a0c]4633        syslog(LOG_DEBUG, "connection from client %s:%hu\n",
[f09aca6]4634               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[212280e]4635
4636        ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ);
4637        ev_io_start(loop, &cli->io);
4638        ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.);
4639        ev_timer_start(loop, &cli->timer);
4640}
4641
[e3e4e6f]4642static int og_socket_server_init(const char *port)
4643{
4644        struct sockaddr_in local;
4645        int sd, on = 1;
4646
4647        sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
4648        if (sd < 0) {
4649                syslog(LOG_ERR, "cannot create main socket\n");
4650                return -1;
4651        }
4652        setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
4653
4654        local.sin_addr.s_addr = htonl(INADDR_ANY);
4655        local.sin_family = AF_INET;
4656        local.sin_port = htons(atoi(port));
4657
4658        if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) {
[8b1bedd]4659                close(sd);
[e3e4e6f]4660                syslog(LOG_ERR, "cannot bind socket\n");
4661                return -1;
4662        }
4663
4664        listen(sd, 250);
4665
4666        return sd;
4667}
4668
[212280e]4669int main(int argc, char *argv[])
4670{
[95e6520]4671        struct ev_io ev_io_server, ev_io_server_rest;
[212280e]4672        struct ev_loop *loop = ev_default_loop(0);
4673        int i;
[b9eb98b]4674
[9fc0037]4675        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
4676                exit(EXIT_FAILURE);
4677
[57c8c50]4678        openlog("ogAdmServer", LOG_PID, LOG_DAEMON);
[ef6e3d2]4679
[b9eb98b]4680        /*--------------------------------------------------------------------------------------------------------
4681         Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
4682         ---------------------------------------------------------------------------------------------------------*/
4683        if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución
4684                exit(EXIT_FAILURE);
4685
4686        if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
4687                exit(EXIT_FAILURE);
4688        }
4689
4690        /*--------------------------------------------------------------------------------------------------------
4691         // Inicializa array de información de los clientes
4692         ---------------------------------------------------------------------------------------------------------*/
4693        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
4694                tbsockets[i].ip[0] = '\0';
[f09aca6]4695                tbsockets[i].cli = NULL;
[b9eb98b]4696        }
4697        /*--------------------------------------------------------------------------------------------------------
4698         Creación y configuración del socket del servicio
4699         ---------------------------------------------------------------------------------------------------------*/
[e3e4e6f]4700        socket_s = og_socket_server_init(puerto);
4701        if (socket_s < 0)
[b9eb98b]4702                exit(EXIT_FAILURE);
[212280e]4703
4704        ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ);
4705        ev_io_start(loop, &ev_io_server);
4706
[95e6520]4707        socket_rest = og_socket_server_init("8888");
4708        if (socket_rest < 0)
4709                exit(EXIT_FAILURE);
4710
4711        ev_io_init(&ev_io_server_rest, og_server_accept_cb, socket_rest, EV_READ);
4712        ev_io_start(loop, &ev_io_server_rest);
4713
[b9eb98b]4714        infoLog(1); // Inicio de sesión
[212280e]4715
[effbcea]4716        /* old log file has been deprecated. */
4717        og_log(97, false);
4718
[ef6e3d2]4719        syslog(LOG_INFO, "Waiting for connections\n");
4720
[212280e]4721        while (1)
4722                ev_loop(loop, 0);
4723
[b9eb98b]4724        exit(EXIT_SUCCESS);
4725}
Note: See TracBrowser for help on using the repository browser.