source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.cpp @ 3673737

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 3673737 was 4797e93, checked in by OpenGnSys Support Team <soporte-og@…>, 6 years ago

#580 ignore SIGPIPE signal

This signal is received when socket hit connection reset by peer
state, which may happen in transient network failures.

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