source: ogServer-Git/sources/ogAdmServer.cpp @ 507c75c

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

#915 Pass array of addresses to WakeUp?()

To reuse this function to the REST API.

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