source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.cpp @ 588d1eb

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

#898 Remove unused encryption and decryption routines

Remove dead code to encrypt and decrypt the message.

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