source: ogServer-Git/sources/ogAdmServer.cpp @ 7ab5f0c

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

#915 add POST session command to REST API in ogAdmServer

Start a session on client (through POST method):

curl -X POST http://127.0.0.1:8888/session -d @session.json

Request

POST /session
{"clients": [ "192.168.2.1" ] }

Reply:

200 OK

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