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

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

#915 add og_send_cmd()

Add new function to check and send commands to the clients. This new
function takes an array of IP addresses (string) and send commands to
the clients.

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