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

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

#915 add og_msg_alloc() and og_msg_free()

Add function to allocate and release the legacy message format.

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