source: ogServer-Git/sources/ogAdmServer.cpp @ 2baf362

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

#896: Send multicast WoL through a specific interface

  • New parameter in ogAdmServer config file for setting an interface.
  • ogAdmServer multicast WoL now search the interface of the config file in the

system, if the interface is found in the system the destination IP of the
packet change to a broadcast address of a specific range of addresses.

  • Property mode set to 100644
File size: 125.4 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// ________________________________________________________________________________________________________
1311// Función: enviaComando
1312//
1313//      Descripción:
1314//              Envía un comando a los clientes
1315//      Parámetros:
1316//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1317//              - estado: Estado en el se deja al cliente mientras se ejecuta el comando
1318//      Devuelve:
1319//              true: Si el proceso es correcto
1320//              false: En caso de ocurrir algún error
1321// ________________________________________________________________________________________________________
1322bool enviaComando(TRAMA* ptrTrama, const char *estado)
1323{
1324        char *iph, *Ipes, *ptrIpes[MAXIMOS_CLIENTES];
1325        int i, idx, lon;
1326
1327        iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP
1328        lon = strlen(iph); // Calcula longitud de la cadena de direccion/es IPE/S
1329        Ipes = (char*) reservaMemoria(lon + 1);
1330        if (Ipes == NULL) {
1331                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
1332                return false;
1333        }
1334       
1335        strcpy(Ipes, iph); // Copia cadena de IPES
1336        liberaMemoria(iph);
1337
1338        lon = splitCadena(ptrIpes, Ipes, ';');
1339        FINCADaINTRO(ptrTrama);
1340        for (i = 0; i < lon; i++) {
1341                if (clienteDisponible(ptrIpes[i], &idx)) { // Si el cliente puede recibir comandos
1342                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
1343
1344                        strcpy(tbsockets[idx].estado, estado); // Actualiza el estado del cliente
1345                        if (!mandaTrama(&sock, ptrTrama)) {
1346                                syslog(LOG_ERR, "failed to send response to %s:%s\n",
1347                                       ptrIpes[i], strerror(errno));
1348                                return false;
1349                        }
1350                        //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad
1351                }
1352        }
1353        liberaMemoria(Ipes);
1354        return true;
1355}
1356//______________________________________________________________________________________________________
1357// Función: respuestaConsola
1358//
1359//      Descripción:
1360//              Envia una respuesta a la consola sobre el resultado de la ejecución de un comando
1361//      Parámetros:
1362//              - socket_c: (Salida) Socket utilizado para el envío
1363//              - res: Resultado del envío del comando
1364//      Devuelve:
1365//              true: Si el proceso es correcto
1366//              false: En caso de ocurrir algún error
1367// ________________________________________________________________________________________________________
1368bool respuestaConsola(int socket_c, TRAMA *ptrTrama, int res)
1369{
1370        initParametros(ptrTrama,0);
1371        sprintf(ptrTrama->parametros, "res=%d\r", res);
1372        if (!mandaTrama(&socket_c, ptrTrama)) {
1373                syslog(LOG_ERR, "%s:%d failed to send response: %s\n",
1374                       __func__, __LINE__, strerror(errno));
1375                return false;
1376        }
1377        return true;
1378}
1379// ________________________________________________________________________________________________________
1380// Función: Arrancar
1381//
1382//      Descripción:
1383//              Procesa el comando Arrancar
1384//      Parámetros:
1385//              - socket_c: Socket de la consola al envió el mensaje
1386//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1387//      Devuelve:
1388//              true: Si el proceso es correcto
1389//              false: En caso de ocurrir algún error
1390// ________________________________________________________________________________________________________
1391static bool Arrancar(TRAMA* ptrTrama, struct og_client *cli)
1392{
1393        char *iph,*mac,*mar;
1394        bool res;
1395
1396        iph = copiaParametro("iph",ptrTrama); // Toma dirección/es IP
1397        mac = copiaParametro("mac",ptrTrama); // Toma dirección/es MAC
1398        mar = copiaParametro("mar",ptrTrama); // Método de arranque (Broadcast o Unicast)
1399
1400        res=Levanta(iph,mac,mar);
1401
1402        liberaMemoria(iph);
1403        liberaMemoria(mac);
1404        liberaMemoria(mar);
1405
1406        if(!res){
1407                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1408                return false;
1409        }
1410
1411        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
1412                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1413                return false;
1414        }
1415        respuestaConsola(og_client_socket(cli), ptrTrama, true);
1416        return true;
1417}
1418// ________________________________________________________________________________________________________
1419// Función: Levanta
1420//
1421//      Descripción:
1422//              Enciende ordenadores a través de la red cuyas macs se pasan como parámetro
1423//      Parámetros:
1424//              - iph: Cadena de direcciones ip separadas por ";"
1425//              - mac: Cadena de direcciones mac separadas por ";"
1426//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
1427//      Devuelve:
1428//              true: Si el proceso es correcto
1429//              false: En caso de ocurrir algún error
1430// ________________________________________________________________________________________________________
1431bool Levanta(char *iph, char *mac, char *mar)
1432{
1433        char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES];
1434        unsigned int on = 1;
1435        sockaddr_in local;
1436        int i, lon, res;
1437        SOCKET s;
1438
1439        /* Creación de socket para envío de magig packet */
1440        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1441        if (s < 0) {
1442                syslog(LOG_ERR, "cannot create socket for magic packet\n");
1443                return false;
1444        }
1445        res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on,
1446                         sizeof(on));
1447        if (res < 0) {
1448                syslog(LOG_ERR, "cannot set broadcast socket\n");
1449                return false;
1450        }
1451        memset(&local, 0, sizeof(local));
1452        local.sin_family = AF_INET;
1453        local.sin_port = htons(PUERTO_WAKEUP);
1454        local.sin_addr.s_addr = htonl(INADDR_ANY);
1455
1456        lon = splitCadena(ptrIP, iph, ';');
1457        lon = splitCadena(ptrMacs, mac, ';');
1458        for (i = 0; i < lon; i++) {
1459                if (!WakeUp(&s,ptrIP[i],ptrMacs[i],mar)) {
1460                        syslog(LOG_ERR, "problem sending magic packet\n");
1461                        close(s);
1462                        return false;
1463                }
1464        }
1465        close(s);
1466        return true;
1467}
1468
1469#define OG_WOL_SEQUENCE         6
1470#define OG_WOL_MACADDR_LEN      6
1471#define OG_WOL_REPEAT           16
1472
1473struct wol_msg {
1474        char secuencia_FF[OG_WOL_SEQUENCE];
1475        char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN];
1476};
1477
1478static bool wake_up_broadcast(int sd, struct sockaddr_in *client,
1479                              const struct wol_msg *msg)
1480{
1481        struct sockaddr_in *broadcast_addr;
1482        struct ifaddrs *ifaddr, *ifa;
1483        int ret;
1484
1485        if (getifaddrs(&ifaddr) < 0) {
1486                syslog(LOG_ERR, "cannot get list of addresses\n");
1487                return false;
1488        }
1489
1490        client->sin_addr.s_addr = htonl(INADDR_BROADCAST);
1491
1492        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1493                if (ifa->ifa_addr == NULL ||
1494                    ifa->ifa_addr->sa_family != AF_INET ||
1495                    strcmp(ifa->ifa_name, interface) != 0)
1496                        continue;
1497
1498                broadcast_addr =
1499                        (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr;
1500                client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr;
1501                break;
1502        }
1503        free(ifaddr);
1504
1505        ret = sendto(sd, msg, sizeof(*msg), 0,
1506                     (sockaddr *)client, sizeof(*client));
1507        if (ret < 0) {
1508                syslog(LOG_ERR, "failed to send broadcast wol\n");
1509                return false;
1510        }
1511
1512        return true;
1513}
1514
1515static bool wake_up_unicast(int sd, struct sockaddr_in *client,
1516                            const struct wol_msg *msg,
1517                            const struct in_addr *addr)
1518{
1519        int ret;
1520
1521        client->sin_addr.s_addr = addr->s_addr;
1522
1523        ret = sendto(sd, msg, sizeof(*msg), 0,
1524                     (sockaddr *)client, sizeof(*client));
1525        if (ret < 0) {
1526                syslog(LOG_ERR, "failed to send unicast wol\n");
1527                return false;
1528        }
1529
1530        return true;
1531}
1532
1533enum wol_delivery_type {
1534        OG_WOL_BROADCAST = 1,
1535        OG_WOL_UNICAST = 2
1536};
1537
1538//_____________________________________________________________________________________________________________
1539// Función: WakeUp
1540//
1541//       Descripción:
1542//              Enciende el ordenador cuya MAC se pasa como parámetro
1543//      Parámetros:
1544//              - s : Socket para enviar trama magic packet
1545//              - iph : Cadena con la dirección ip
1546//              - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX
1547//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
1548//      Devuelve:
1549//              true: Si el proceso es correcto
1550//              false: En caso de ocurrir algún error
1551//_____________________________________________________________________________________________________________
1552//
1553bool WakeUp(SOCKET *s, char* iph, char *mac, char *mar)
1554{
1555        char HDaddress_bin[OG_WOL_MACADDR_LEN];
1556        struct sockaddr_in WakeUpCliente;
1557        struct wol_msg Trama_WakeUp;
1558        struct in_addr addr;
1559        bool ret;
1560        int i;
1561
1562        for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF)
1563                Trama_WakeUp.secuencia_FF[i] = 0xFF;
1564
1565        sscanf(mac, "%02x%02x%02x%02x%02x%02x",
1566               (unsigned int *)&HDaddress_bin[0],
1567               (unsigned int *)&HDaddress_bin[1],
1568               (unsigned int *)&HDaddress_bin[2],
1569               (unsigned int *)&HDaddress_bin[3],
1570               (unsigned int *)&HDaddress_bin[4],
1571               (unsigned int *)&HDaddress_bin[5]);
1572
1573        for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC
1574                memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6);
1575
1576        /* Creación de socket del cliente que recibe la trama magic packet */
1577        WakeUpCliente.sin_family = AF_INET;
1578        WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP);
1579
1580        switch (atoi(mar)) {
1581        case OG_WOL_BROADCAST:
1582                ret = wake_up_broadcast(*s, &WakeUpCliente, &Trama_WakeUp);
1583                break;
1584        case OG_WOL_UNICAST:
1585                if (inet_aton(iph, &addr) < 0) {
1586                        syslog(LOG_ERR, "bad IP address for unicast wol\n");
1587                        ret = false;
1588                        break;
1589                }
1590                ret = wake_up_unicast(*s, &WakeUpCliente, &Trama_WakeUp, &addr);
1591                break;
1592        default:
1593                syslog(LOG_ERR, "unknown wol type\n");
1594                ret = false;
1595                break;
1596        }
1597        return ret;
1598}
1599// ________________________________________________________________________________________________________
1600// Función: RESPUESTA_Arrancar
1601//
1602//      Descripción:
1603//              Respuesta del cliente al comando Arrancar
1604//      Parámetros:
1605//              - socket_c: Socket del cliente que envió el mensaje
1606//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1607//      Devuelve:
1608//              true: Si el proceso es correcto
1609//              false: En caso de ocurrir algún error
1610// ________________________________________________________________________________________________________
1611static bool RESPUESTA_Arrancar(TRAMA* ptrTrama, struct og_client *cli)
1612{
1613        char msglog[LONSTD];
1614        Database db;
1615        Table tbl;
1616        int i;
1617        char *iph, *ido;
1618        char *tpc;
1619
1620        if (!db.Open(usuario, pasguor, datasource, catalog)) {
1621                db.GetErrorErrStr(msglog);
1622                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1623                       __func__, __LINE__, msglog);
1624                return false;
1625        }
1626
1627        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1628        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1629
1630        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1631                liberaMemoria(iph);
1632                liberaMemoria(ido);
1633                syslog(LOG_ERR, "failed to register notification\n");
1634                return false;
1635        }
1636
1637        tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.)
1638        if (clienteExistente(iph, &i)) // Actualiza estado
1639                strcpy(tbsockets[i].estado, tpc);
1640               
1641        liberaMemoria(iph);
1642        liberaMemoria(ido);
1643        liberaMemoria(tpc);
1644       
1645        db.Close(); // Cierra conexión
1646        return true;
1647}
1648// ________________________________________________________________________________________________________
1649// Función: Apagar
1650//
1651//      Descripción:
1652//              Procesa el comando Apagar
1653//      Parámetros:
1654//              - socket_c: Socket de la consola al envió el mensaje
1655//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1656//      Devuelve:
1657//              true: Si el proceso es correcto
1658//              false: En caso de ocurrir algún error
1659// ________________________________________________________________________________________________________
1660static bool Apagar(TRAMA* ptrTrama, struct og_client *cli)
1661{
1662        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
1663                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1664                return false;
1665        }
1666        respuestaConsola(og_client_socket(cli), ptrTrama, true);
1667        return true;
1668}
1669// ________________________________________________________________________________________________________
1670// Función: RESPUESTA_Apagar
1671//
1672//      Descripción:
1673//              Respuesta del cliente al comando Apagar
1674//      Parámetros:
1675//              - socket_c: Socket del cliente que envió el mensaje
1676//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1677//      Devuelve:
1678//              true: Si el proceso es correcto
1679//              false: En caso de ocurrir algún error
1680// ________________________________________________________________________________________________________
1681static bool RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli)
1682{
1683        char msglog[LONSTD];
1684        Database db;
1685        Table tbl;
1686        int i;
1687        char *iph, *ido;
1688
1689        if (!db.Open(usuario, pasguor, datasource, catalog)) {
1690                db.GetErrorErrStr(msglog);
1691                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1692                       __func__, __LINE__, msglog);
1693                return false;
1694        }
1695
1696        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1697        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1698
1699        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1700                liberaMemoria(iph);
1701                liberaMemoria(ido);
1702                syslog(LOG_ERR, "failed to register notification\n");
1703                return false; // Error al registrar notificacion
1704        }
1705
1706        if (clienteExistente(iph, &i)) // Actualiza estado
1707                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
1708       
1709        liberaMemoria(iph);
1710        liberaMemoria(ido);
1711       
1712        db.Close(); // Cierra conexión
1713        return true;
1714}
1715// ________________________________________________________________________________________________________
1716// Función: Reiniciar
1717//
1718//      Descripción:
1719//              Procesa el comando Reiniciar
1720//      Parámetros:
1721//              - socket_c: Socket de la consola al envió el mensaje
1722//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1723//      Devuelve:
1724//              true: Si el proceso es correcto
1725//              false: En caso de ocurrir algún error
1726// ________________________________________________________________________________________________________
1727static bool Reiniciar(TRAMA* ptrTrama, struct og_client *cli)
1728{
1729        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
1730                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1731                return false;
1732        }
1733        respuestaConsola(og_client_socket(cli), ptrTrama, true);
1734        return true;
1735}
1736// ________________________________________________________________________________________________________
1737// Función: RESPUESTA_Reiniciar
1738//
1739//      Descripción:
1740//              Respuesta del cliente al comando Reiniciar
1741//      Parámetros:
1742//              - socket_c: Socket del cliente que envió el mensaje
1743//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1744//      Devuelve:
1745//              true: Si el proceso es correcto
1746//              false: En caso de ocurrir algún error
1747// ________________________________________________________________________________________________________
1748static bool RESPUESTA_Reiniciar(TRAMA* ptrTrama, struct og_client *cli)
1749{
1750        char msglog[LONSTD];
1751        Database db;
1752        Table tbl;
1753        int i;
1754        char *iph, *ido;
1755
1756        if (!db.Open(usuario, pasguor, datasource, catalog)) {
1757                db.GetErrorErrStr(msglog);
1758                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1759                       __func__, __LINE__, msglog);
1760                return false;
1761        }
1762
1763        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1764        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1765
1766        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1767                liberaMemoria(iph);
1768                liberaMemoria(ido);
1769                syslog(LOG_ERR, "failed to register notification\n");
1770                return false; // Error al registrar notificacion
1771        }
1772
1773        if (clienteExistente(iph, &i)) // Actualiza estado
1774                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
1775       
1776        liberaMemoria(iph);
1777        liberaMemoria(ido);
1778
1779        db.Close(); // Cierra conexión
1780        return true;
1781}
1782// ________________________________________________________________________________________________________
1783// Función: IniciarSesion
1784//
1785//      Descripción:
1786//              Procesa el comando Iniciar Sesión
1787//      Parámetros:
1788//              - socket_c: Socket de la consola al envió el mensaje
1789//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1790//      Devuelve:
1791//              true: Si el proceso es correcto
1792//              false: En caso de ocurrir algún error
1793// ________________________________________________________________________________________________________
1794static bool IniciarSesion(TRAMA* ptrTrama, struct og_client *cli)
1795{
1796        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
1797                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1798                return false;
1799        }
1800        respuestaConsola(og_client_socket(cli), ptrTrama, true);
1801        return true;
1802}
1803// ________________________________________________________________________________________________________
1804// Función: RESPUESTA_IniciarSesion
1805//
1806//      Descripción:
1807//              Respuesta del cliente al comando Iniciar Sesión
1808//      Parámetros:
1809//              - socket_c: Socket del cliente que envió el mensaje
1810//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1811//      Devuelve:
1812//              true: Si el proceso es correcto
1813//              false: En caso de ocurrir algún error
1814// ________________________________________________________________________________________________________
1815static bool RESPUESTA_IniciarSesion(TRAMA* ptrTrama, struct og_client *cli)
1816{
1817        char msglog[LONSTD];
1818        Database db;
1819        Table tbl;
1820        int i;
1821        char *iph, *ido;
1822
1823        if (!db.Open(usuario, pasguor, datasource, catalog)) {
1824                db.GetErrorErrStr(msglog);
1825                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1826                       __func__, __LINE__, msglog);
1827                return false;
1828        }
1829
1830        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1831        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1832
1833        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1834                liberaMemoria(iph);
1835                liberaMemoria(ido);
1836                syslog(LOG_ERR, "failed to register notification\n");
1837                return false; // Error al registrar notificacion
1838        }
1839
1840        if (clienteExistente(iph, &i)) // Actualiza estado
1841                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
1842               
1843        liberaMemoria(iph);
1844        liberaMemoria(ido);
1845               
1846        db.Close(); // Cierra conexión
1847        return true;
1848}
1849// ________________________________________________________________________________________________________
1850// Función: CrearImagen
1851//
1852//      Descripción:
1853//              Crea una imagen de una partición de un disco y la guarda o bien en un repositorio
1854//      Parámetros:
1855//              - socket_c: Socket de la consola al envió el mensaje
1856//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1857//      Devuelve:
1858//              true: Si el proceso es correcto
1859//              false: En caso de ocurrir algún error
1860// ________________________________________________________________________________________________________
1861static bool CrearImagen(TRAMA* ptrTrama, struct og_client *cli)
1862{
1863        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
1864                respuestaConsola(og_client_socket(cli), ptrTrama, false);
1865                return false;
1866        }
1867        respuestaConsola(og_client_socket(cli), ptrTrama, true);
1868        return true;
1869}
1870// ________________________________________________________________________________________________________
1871// Función: RESPUESTA_CrearImagen
1872//
1873//      Descripción:
1874//              Respuesta del cliente al comando CrearImagen
1875//      Parámetros:
1876//              - socket_c: Socket del cliente que envió el mensaje
1877//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1878//      Devuelve:
1879//              true: Si el proceso es correcto
1880//              false: En caso de ocurrir algún error
1881// ________________________________________________________________________________________________________
1882static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli)
1883{
1884        char msglog[LONSTD];
1885        Database db;
1886        Table tbl;
1887        char *iph, *dsk, *par, *cpt, *ipr, *ido;
1888        char *idi;
1889        bool res;
1890
1891        if (!db.Open(usuario, pasguor, datasource, catalog)) {
1892                db.GetErrorErrStr(msglog);
1893                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1894                       __func__, __LINE__, msglog);
1895                return false;
1896        }
1897
1898        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1899        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1900
1901        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1902                liberaMemoria(iph);
1903                liberaMemoria(ido);
1904                syslog(LOG_ERR, "failed to register notification\n");
1905                return false; // Error al registrar notificacion
1906        }
1907
1908        // Acciones posteriores
1909        idi = copiaParametro("idi",ptrTrama);
1910        dsk = copiaParametro("dsk",ptrTrama);
1911        par = copiaParametro("par",ptrTrama);
1912        cpt = copiaParametro("cpt",ptrTrama);
1913        ipr = copiaParametro("ipr",ptrTrama);
1914
1915        res=actualizaCreacionImagen(db, tbl, idi, dsk, par, cpt, ipr, ido);
1916
1917        liberaMemoria(idi);
1918        liberaMemoria(par);
1919        liberaMemoria(cpt);
1920        liberaMemoria(ipr);
1921
1922        if(!res){
1923                syslog(LOG_ERR, "Problem processing update\n");
1924                db.Close();
1925                return false;
1926        }
1927
1928        db.Close(); // Cierra conexión
1929        return true;
1930}
1931// ________________________________________________________________________________________________________
1932// Función: actualizaCreacionImagen
1933//
1934//      Descripción:
1935//              Esta función actualiza la base de datos con el resultado de la creación de una imagen
1936//      Parámetros:
1937//              - db: Objeto base de datos (ya operativo)
1938//              - tbl: Objeto tabla
1939//              - idi: Identificador de la imagen
1940//              - dsk: Disco de donde se creó
1941//              - par: Partición de donde se creó
1942//              - cpt: Código de partición
1943//              - ipr: Ip del repositorio
1944//              - ido: Identificador del ordenador modelo
1945//      Devuelve:
1946//              true: Si el proceso es correcto
1947//              false: En caso de ocurrir algún error
1948// ________________________________________________________________________________________________________
1949bool actualizaCreacionImagen(Database db, Table tbl, char *idi, char *dsk,
1950                             char *par, char *cpt, char *ipr, char *ido)
1951{
1952        char msglog[LONSTD], sqlstr[LONSQL];
1953        int idr,ifs;
1954
1955        /* Toma identificador del repositorio correspondiente al ordenador modelo */
1956        snprintf(sqlstr, LONSQL,
1957                        "SELECT repositorios.idrepositorio"
1958                        "  FROM repositorios"
1959                        "  LEFT JOIN ordenadores USING (idrepositorio)"
1960                        " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido);
1961
1962        if (!db.Execute(sqlstr, tbl)) {
1963                db.GetErrorErrStr(msglog);
1964                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1965                       __func__, __LINE__, msglog);
1966                return false;
1967        }
1968        if (!tbl.Get("idrepositorio", idr)) { // Toma dato
1969                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
1970                og_info(msglog);
1971                return false;
1972        }
1973
1974        /* Toma identificador del perfilsoftware */
1975        snprintf(sqlstr, LONSQL,
1976                        "SELECT idperfilsoft"
1977                        "  FROM ordenadores_particiones"
1978                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par);
1979
1980        if (!db.Execute(sqlstr, tbl)) {
1981                db.GetErrorErrStr(msglog);
1982                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1983                       __func__, __LINE__, msglog);
1984                return false;
1985        }
1986        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
1987                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
1988                og_info(msglog);
1989                return false;
1990        }
1991
1992        /* Actualizar los datos de la imagen */
1993        snprintf(sqlstr, LONSQL,
1994                "UPDATE imagenes"
1995                "   SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
1996                "       idperfilsoft=%d, idrepositorio=%d,"
1997                "       fechacreacion=NOW(), revision=revision+1"
1998                " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi);
1999
2000        if (!db.Execute(sqlstr, tbl)) {
2001                db.GetErrorErrStr(msglog);
2002                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2003                       __func__, __LINE__, msglog);
2004                return false;
2005        }
2006        /* Actualizar los datos en el cliente */
2007        snprintf(sqlstr, LONSQL,
2008                "UPDATE ordenadores_particiones"
2009                "   SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
2010                "       fechadespliegue=NOW()"
2011                " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
2012                idi, idi, ido, dsk, par);
2013        if (!db.Execute(sqlstr, tbl)) {
2014                db.GetErrorErrStr(msglog);
2015                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2016                       __func__, __LINE__, msglog);
2017                return false;
2018        }
2019        return true;
2020}
2021// ________________________________________________________________________________________________________
2022// Función: CrearImagenBasica
2023//
2024//      Descripción:
2025//              Crea una imagen basica usando sincronización
2026//      Parámetros:
2027//              - socket_c: Socket de la consola al envió el mensaje
2028//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2029//      Devuelve:
2030//              true: Si el proceso es correcto
2031//              false: En caso de ocurrir algún error
2032// ________________________________________________________________________________________________________
2033static bool CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
2034{
2035        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2036                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2037                return false;
2038        }
2039        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2040        return true;
2041}
2042// ________________________________________________________________________________________________________
2043// Función: RESPUESTA_CrearImagenBasica
2044//
2045//      Descripción:
2046//              Respuesta del cliente al comando CrearImagenBasica
2047//      Parámetros:
2048//              - socket_c: Socket del cliente que envió el mensaje
2049//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2050//      Devuelve:
2051//              true: Si el proceso es correcto
2052//              false: En caso de ocurrir algún error
2053// ________________________________________________________________________________________________________
2054static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
2055{
2056        // La misma respuesta que la creación de imagen monolítica
2057        return RESPUESTA_CrearImagen(ptrTrama, cli);
2058}
2059// ________________________________________________________________________________________________________
2060// Función: CrearSoftIncremental
2061//
2062//      Descripción:
2063//              Crea una imagen incremental entre una partición de un disco y una imagen ya creada guardandola en el
2064//              mismo repositorio y en la misma carpeta donde está la imagen básica
2065//      Parámetros:
2066//              - socket_c: Socket de la consola al envió el mensaje
2067//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2068//      Devuelve:
2069//              true: Si el proceso es correcto
2070//              false: En caso de ocurrir algún error
2071// ________________________________________________________________________________________________________
2072static bool CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
2073{
2074        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2075                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2076                return false;
2077        }
2078        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2079        return true;
2080}
2081// ________________________________________________________________________________________________________
2082// Función: RESPUESTA_CrearSoftIncremental
2083//
2084//      Descripción:
2085//              Respuesta del cliente al comando crearImagenDiferencial
2086//      Parámetros:
2087//              - socket_c: Socket del cliente que envió el mensaje
2088//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2089//      Devuelve:
2090//              true: Si el proceso es correcto
2091//              false: En caso de ocurrir algún error
2092// ________________________________________________________________________________________________________
2093static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
2094{
2095        Database db;
2096        Table tbl;
2097        char *iph,*par,*ido,*idf;
2098        int ifs;
2099        char msglog[LONSTD],sqlstr[LONSQL];
2100
2101        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2102                db.GetErrorErrStr(msglog);
2103                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2104                       __func__, __LINE__, msglog);
2105                return false;
2106        }
2107
2108        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2109        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2110
2111        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2112                liberaMemoria(iph);
2113                liberaMemoria(ido);
2114                syslog(LOG_ERR, "failed to register notification\n");
2115                return false;
2116        }
2117
2118        par = copiaParametro("par",ptrTrama);
2119
2120        /* Toma identificador del perfilsoftware creado por el inventario de software */
2121        sprintf(sqlstr,"SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s",ido,par);
2122       
2123        liberaMemoria(iph);
2124        liberaMemoria(ido);     
2125        liberaMemoria(par);     
2126
2127        if (!db.Execute(sqlstr, tbl)) {
2128                db.GetErrorErrStr(msglog);
2129                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2130                       __func__, __LINE__, msglog);
2131                return false;
2132        }
2133        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
2134                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2135                og_info(msglog);
2136                return false;
2137        }
2138
2139        /* Actualizar los datos de la imagen */
2140        idf = copiaParametro("idf",ptrTrama);
2141        sprintf(sqlstr,"UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s",ifs,idf);
2142        liberaMemoria(idf);     
2143
2144        if (!db.Execute(sqlstr, tbl)) {
2145                db.GetErrorErrStr(msglog);
2146                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2147                       __func__, __LINE__, msglog);
2148                return false;
2149        }
2150        db.Close(); // Cierra conexión
2151        return true;
2152}
2153// ________________________________________________________________________________________________________
2154// Función: RestaurarImagen
2155//
2156//      Descripción:
2157//              Restaura una imagen en una partición
2158//      Parámetros:
2159//              - socket_c: Socket de la consola al envió el mensaje
2160//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2161//      Devuelve:
2162//              true: Si el proceso es correcto
2163//              false: En caso de ocurrir algún error
2164// ________________________________________________________________________________________________________
2165static bool RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli)
2166{
2167        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2168                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2169                return false;
2170        }
2171        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2172        return true;
2173}
2174// ________________________________________________________________________________________________________
2175// Función: RestaurarImagenBasica
2176//
2177//      Descripción:
2178//              Restaura una imagen básica en una partición
2179//      Parámetros:
2180//              - socket_c: Socket de la consola al envió el mensaje
2181//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2182//      Devuelve:
2183//              true: Si el proceso es correcto
2184//              false: En caso de ocurrir algún error
2185// ________________________________________________________________________________________________________
2186static bool RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
2187{
2188        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2189                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2190                return false;
2191        }
2192        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2193        return true;
2194}
2195// ________________________________________________________________________________________________________
2196// Función: RestaurarSoftIncremental
2197//
2198//      Descripción:
2199//              Restaura una imagen básica junto con software incremental en una partición
2200//      Parámetros:
2201//              - socket_c: Socket de la consola al envió el mensaje
2202//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2203//      Devuelve:
2204//              true: Si el proceso es correcto
2205//              false: En caso de ocurrir algún error
2206// ________________________________________________________________________________________________________
2207static bool RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
2208{
2209        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2210                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2211                return false;
2212        }
2213        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2214        return true;
2215}
2216// ________________________________________________________________________________________________________
2217// Función: RESPUESTA_RestaurarImagen
2218//
2219//      Descripción:
2220//              Respuesta del cliente al comando RestaurarImagen
2221//      Parámetros:
2222//              - socket_c: Socket del cliente que envió el mensaje
2223//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2224//      Devuelve:
2225//              true: Si el proceso es correcto
2226//              false: En caso de ocurrir algún error
2227// ________________________________________________________________________________________________________
2228//
2229static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli)
2230{
2231        char msglog[LONSTD];
2232        Database db;
2233        Table tbl;
2234        bool res;
2235        char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg;
2236
2237        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2238                db.GetErrorErrStr(msglog);
2239                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2240                       __func__, __LINE__, msglog);
2241                return false;
2242        }
2243
2244        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2245        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2246
2247        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2248                liberaMemoria(iph);
2249                liberaMemoria(ido);
2250                syslog(LOG_ERR, "failed to register notification\n");
2251                return false;
2252        }
2253
2254        // Acciones posteriores
2255        idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen
2256        dsk = copiaParametro("dsk",ptrTrama); // Número de disco
2257        par = copiaParametro("par",ptrTrama); // Número de partición
2258        ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido
2259        cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos
2260        if(cfg){
2261                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
2262                liberaMemoria(cfg);     
2263        }
2264        res=actualizaRestauracionImagen(db, tbl, idi, dsk, par, ido, ifs);
2265       
2266        liberaMemoria(iph);
2267        liberaMemoria(ido);
2268        liberaMemoria(idi);
2269        liberaMemoria(par);
2270        liberaMemoria(ifs);
2271
2272        if(!res){
2273                syslog(LOG_ERR, "Problem after restoring image\n");
2274                db.Close();
2275                return false;
2276        }
2277
2278        db.Close(); // Cierra conexión
2279        return true;
2280}
2281// ________________________________________________________________________________________________________
2282//
2283// Función: RESPUESTA_RestaurarImagenBasica
2284//
2285//      Descripción:
2286//              Respuesta del cliente al comando RestaurarImagen
2287//      Parámetros:
2288//              - socket_c: Socket del cliente que envió el mensaje
2289//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2290//      Devuelve:
2291//              true: Si el proceso es correcto
2292//              false: En caso de ocurrir algún error
2293// ________________________________________________________________________________________________________
2294//
2295static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
2296{
2297        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
2298}
2299// ________________________________________________________________________________________________________
2300// Función: RESPUESTA_RestaurarSoftIncremental
2301//
2302//      Descripción:
2303//              Respuesta del cliente al comando RestaurarSoftIncremental
2304//      Parámetros:
2305//              - socket_c: Socket del cliente que envió el mensaje
2306//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2307//      Devuelve:
2308//              true: Si el proceso es correcto
2309//              false: En caso de ocurrir algún error
2310// ________________________________________________________________________________________________________
2311static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
2312{
2313        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
2314}
2315// ________________________________________________________________________________________________________
2316// Función: actualizaRestauracionImagen
2317//
2318//      Descripción:
2319//              Esta función actualiza la base de datos con el resultado de la restauración de una imagen
2320//      Parámetros:
2321//              - db: Objeto base de datos (ya operativo)
2322//              - tbl: Objeto tabla
2323//              - idi: Identificador de la imagen
2324//              - dsk: Disco de donde se restauró
2325//              - par: Partición de donde se restauró
2326//              - ido: Identificador del cliente donde se restauró
2327//              - ifs: Identificador del perfil software contenido      en la imagen
2328//      Devuelve:
2329//              true: Si el proceso es correcto
2330//              false: En caso de ocurrir algún error
2331// ________________________________________________________________________________________________________
2332bool actualizaRestauracionImagen(Database db, Table tbl, char *idi,
2333                                 char *dsk, char *par, char *ido, char *ifs)
2334{
2335        char msglog[LONSTD], sqlstr[LONSQL];
2336
2337        /* Actualizar los datos de la imagen */
2338        snprintf(sqlstr, LONSQL,
2339                        "UPDATE ordenadores_particiones"
2340                        "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
2341                        "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
2342                        "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
2343                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par);
2344
2345        if (!db.Execute(sqlstr, tbl)) {
2346                db.GetErrorErrStr(msglog);
2347                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2348                       __func__, __LINE__, msglog);
2349                return false;
2350        }
2351        return true;
2352}
2353// ________________________________________________________________________________________________________
2354// Función: Configurar
2355//
2356//      Descripción:
2357//              Configura la tabla de particiones
2358//      Parámetros:
2359//              - socket_c: Socket de la consola al envió el mensaje
2360//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2361//      Devuelve:
2362//              true: Si el proceso es correcto
2363//              false: En caso de ocurrir algún error
2364// ________________________________________________________________________________________________________
2365static bool Configurar(TRAMA* ptrTrama, struct og_client *cli)
2366{
2367        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2368                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2369                return false;
2370        }
2371        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2372        return true;
2373}
2374// ________________________________________________________________________________________________________
2375// Función: RESPUESTA_Configurar
2376//
2377//      Descripción:
2378//              Respuesta del cliente al comando Configurar
2379//      Parámetros:
2380//              - socket_c: Socket del cliente que envió el mensaje
2381//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2382//      Devuelve:
2383//              true: Si el proceso es correcto
2384//              false: En caso de ocurrir algún error
2385// ________________________________________________________________________________________________________
2386//
2387static bool RESPUESTA_Configurar(TRAMA* ptrTrama, struct og_client *ci)
2388{
2389        char msglog[LONSTD];
2390        Database db;
2391        Table tbl;
2392        bool res;
2393        char *iph, *ido,*cfg;
2394
2395        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2396                db.GetErrorErrStr(msglog);
2397                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2398                       __func__, __LINE__, msglog);
2399                return false;
2400        }
2401
2402        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2403        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2404
2405        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2406                liberaMemoria(iph);
2407                liberaMemoria(ido);
2408                syslog(LOG_ERR, "failed to register notification\n");
2409                return false;
2410        }
2411
2412        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
2413        res=actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
2414       
2415        liberaMemoria(iph);
2416        liberaMemoria(ido);     
2417        liberaMemoria(cfg);     
2418
2419        if(!res){
2420                syslog(LOG_ERR, "Problem updating client configuration\n");
2421                return false;
2422        }
2423
2424        db.Close(); // Cierra conexión
2425        return true;
2426}
2427// ________________________________________________________________________________________________________
2428// Función: EjecutarScript
2429//
2430//      Descripción:
2431//              Ejecuta un script de código
2432//      Parámetros:
2433//              - socket_c: Socket de la consola al envió el mensaje
2434//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2435//      Devuelve:
2436//              true: Si el proceso es correcto
2437//              false: En caso de ocurrir algún error
2438// ________________________________________________________________________________________________________
2439static bool EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
2440{
2441        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2442                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2443                return false;
2444        }
2445        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2446        return true;
2447}
2448// ________________________________________________________________________________________________________
2449// Función: RESPUESTA_EjecutarScript
2450//
2451//      Descripción:
2452//              Respuesta del cliente al comando EjecutarScript
2453//      Parámetros:
2454//              - socket_c: Socket del cliente que envió el mensaje
2455//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2456//      Devuelve:
2457//              true: Si el proceso es correcto
2458//              false: En caso de ocurrir algún error
2459// ________________________________________________________________________________________________________
2460static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
2461{
2462        char msglog[LONSTD];
2463        Database db;
2464        Table tbl;
2465        char *iph, *ido,*cfg;
2466
2467        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2468                db.GetErrorErrStr(msglog);
2469                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2470                       __func__, __LINE__, msglog);
2471                return false;
2472        }
2473
2474        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2475        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2476
2477        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2478                liberaMemoria(iph);
2479                liberaMemoria(ido);
2480                syslog(LOG_ERR, "failed to register notification\n");
2481                return false;
2482        }
2483       
2484        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
2485        if(cfg){
2486                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
2487                liberaMemoria(cfg);     
2488        }
2489
2490        liberaMemoria(iph);
2491        liberaMemoria(ido);
2492
2493       
2494        db.Close(); // Cierra conexión
2495        return true;
2496}
2497// ________________________________________________________________________________________________________
2498// Función: InventarioHardware
2499//
2500//      Descripción:
2501//              Solicita al cliente un inventario de su hardware
2502//      Parámetros:
2503//              - socket_c: Socket de la consola al envió el mensaje
2504//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2505//      Devuelve:
2506//              true: Si el proceso es correcto
2507//              false: En caso de ocurrir algún error
2508// ________________________________________________________________________________________________________
2509static bool InventarioHardware(TRAMA* ptrTrama, struct og_client *cli)
2510{
2511        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2512                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2513                return false;
2514        }
2515        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2516        return true;
2517}
2518// ________________________________________________________________________________________________________
2519// Función: RESPUESTA_InventarioHardware
2520//
2521//      Descripción:
2522//              Respuesta del cliente al comando InventarioHardware
2523//      Parámetros:
2524//              - socket_c: Socket del cliente que envió el mensaje
2525//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2526//      Devuelve:
2527//              true: Si el proceso es correcto
2528//              false: En caso de ocurrir algún error
2529// ________________________________________________________________________________________________________
2530static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli)
2531{
2532        char msglog[LONSTD];
2533        Database db;
2534        Table tbl;
2535        bool res;
2536        char *iph, *ido, *idc, *npc, *hrd, *buffer;
2537
2538        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2539                db.GetErrorErrStr(msglog);
2540                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2541                       __func__, __LINE__, msglog);
2542                return false;
2543        }
2544
2545        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente
2546        ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente
2547
2548        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2549                liberaMemoria(iph);
2550                liberaMemoria(ido);
2551                syslog(LOG_ERR, "failed to register notification\n");
2552                return false;
2553        }
2554        // Lee archivo de inventario enviado anteriormente
2555        hrd = copiaParametro("hrd",ptrTrama);
2556        buffer = rTrim(leeArchivo(hrd));
2557       
2558        npc = copiaParametro("npc",ptrTrama); 
2559        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro
2560       
2561        if (buffer) 
2562                res=actualizaHardware(db, tbl, buffer, ido, npc, idc);
2563       
2564        liberaMemoria(iph);
2565        liberaMemoria(ido);                     
2566        liberaMemoria(npc);                     
2567        liberaMemoria(idc);             
2568        liberaMemoria(buffer);         
2569       
2570        if(!res){
2571                syslog(LOG_ERR, "Problem updating client configuration\n");
2572                return false;
2573        }
2574               
2575        db.Close(); // Cierra conexión
2576        return true;
2577}
2578// ________________________________________________________________________________________________________
2579// Función: actualizaHardware
2580//
2581//              Descripción:
2582//                      Actualiza la base de datos con la configuracion hardware del cliente
2583//              Parámetros:
2584//                      - db: Objeto base de datos (ya operativo)
2585//                      - tbl: Objeto tabla
2586//                      - hrd: cadena con el inventario hardware
2587//                      - ido: Identificador del ordenador
2588//                      - npc: Nombre del ordenador
2589//                      - idc: Identificador del centro o Unidad organizativa
2590// ________________________________________________________________________________________________________
2591//
2592bool actualizaHardware(Database db, Table tbl, char *hrd, char *ido, char *npc,
2593                       char *idc)
2594{
2595        char msglog[LONSTD], sqlstr[LONSQL];
2596        int idtipohardware, idperfilhard;
2597        int lon, i, j, aux;
2598        bool retval;
2599        char *whard;
2600        int tbidhardware[MAXHARDWARE];
2601        char *tbHardware[MAXHARDWARE],*dualHardware[2], descripcion[250], strInt[LONINT], *idhardwares;
2602
2603        /* Toma Centro (Unidad Organizativa) */
2604        sprintf(sqlstr, "SELECT * FROM ordenadores WHERE idordenador=%s", ido);
2605
2606        if (!db.Execute(sqlstr, tbl)) {
2607                db.GetErrorErrStr(msglog);
2608                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2609                       __func__, __LINE__, msglog);
2610                return false;
2611        }
2612        if (!tbl.Get("idperfilhard", idperfilhard)) { // Toma dato
2613                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2614                og_info(msglog);
2615                return false;
2616        }
2617        whard=escaparCadena(hrd); // Codificar comillas simples
2618        if(!whard)
2619                return false;
2620        /* Recorre componentes hardware*/
2621        lon = splitCadena(tbHardware, whard, '\n');
2622        if (lon > MAXHARDWARE)
2623                lon = MAXHARDWARE; // Limita el número de componentes hardware
2624        /*
2625         for (i=0;i<lon;i++){
2626         sprintf(msglog,"Linea de inventario: %s",tbHardware[i]);
2627         RegistraLog(msglog,false);
2628         }
2629         */
2630        for (i = 0; i < lon; i++) {
2631                splitCadena(dualHardware, rTrim(tbHardware[i]), '=');
2632                //sprintf(msglog,"nemonico: %s",dualHardware[0]);
2633                //RegistraLog(msglog,false);
2634                //sprintf(msglog,"valor: %s",dualHardware[1]);
2635                //RegistraLog(msglog,false);
2636                sprintf(sqlstr, "SELECT idtipohardware,descripcion FROM tipohardwares "
2637                        " WHERE nemonico='%s'", dualHardware[0]);
2638                if (!db.Execute(sqlstr, tbl)) {
2639                        db.GetErrorErrStr(msglog);
2640                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2641                               __func__, __LINE__, msglog);
2642                        return false;
2643                }
2644                if (tbl.ISEOF()) { //  Tipo de Hardware NO existente
2645                        sprintf(msglog, "%s: %s)", tbErrores[54], dualHardware[0]);
2646                        og_info(msglog);
2647                        return false;
2648                } else { //  Tipo de Hardware Existe
2649                        if (!tbl.Get("idtipohardware", idtipohardware)) { // Toma dato
2650                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2651                                og_info(msglog);
2652                                return false;
2653                        }
2654                        if (!tbl.Get("descripcion", descripcion)) { // Toma dato
2655                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2656                                og_info(msglog);
2657                                return false;
2658                        }
2659
2660                        sprintf(sqlstr, "SELECT idhardware FROM hardwares "
2661                                " WHERE idtipohardware=%d AND descripcion='%s'",
2662                                        idtipohardware, dualHardware[1]);
2663
2664                        if (!db.Execute(sqlstr, tbl)) {
2665                                db.GetErrorErrStr(msglog);
2666                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2667                                       __func__, __LINE__, msglog);
2668                                return false;
2669                        }
2670
2671                        if (tbl.ISEOF()) { //  Hardware NO existente
2672                                sprintf(sqlstr, "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) "
2673                                                        " VALUES(%d,'%s',%s,0)", idtipohardware,
2674                                                dualHardware[1], idc);
2675                                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2676                                        db.GetErrorErrStr(msglog); // Error al acceder al registro
2677                                        og_info(msglog);
2678                                        return false;
2679                                }
2680                                // Recupera el identificador del hardware
2681                                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2682                                if (!db.Execute(sqlstr, tbl)) {
2683                                        db.GetErrorErrStr(msglog);
2684                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2685                                               __func__, __LINE__, msglog);
2686                                        return false;
2687                                }
2688                                if (!tbl.ISEOF()) { // Si existe registro
2689                                        if (!tbl.Get("identificador", tbidhardware[i])) {
2690                                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2691                                                og_info(msglog);
2692                                                return false;
2693                                        }
2694                                }
2695                        } else {
2696                                if (!tbl.Get("idhardware", tbidhardware[i])) { // Toma dato
2697                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
2698                                        og_info(msglog);
2699                                        return false;
2700                                }
2701                        }
2702                }
2703        }
2704        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2705
2706        for (i = 0; i < lon - 1; i++) {
2707                for (j = i + 1; j < lon; j++) {
2708                        if (tbidhardware[i] > tbidhardware[j]) {
2709                                aux = tbidhardware[i];
2710                                tbidhardware[i] = tbidhardware[j];
2711                                tbidhardware[j] = aux;
2712                        }
2713                }
2714        }
2715        /* Crea cadena de identificadores de componentes hardware separados por coma */
2716        sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2717        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2718        idhardwares = reservaMemoria(sizeof(aux) * lon + lon);
2719        if (idhardwares == NULL) {
2720                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
2721                return false;
2722        }
2723        aux = sprintf(idhardwares, "%d", tbidhardware[0]);
2724        for (i = 1; i < lon; i++)
2725                aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]);
2726
2727        if (!cuestionPerfilHardware(db, tbl, idc, ido, idperfilhard, idhardwares,
2728                        npc, tbidhardware, lon)) {
2729                syslog(LOG_ERR, "Problem updating client hardware\n");
2730                retval=false;
2731        }
2732        else {
2733                retval=true;
2734        }
2735        liberaMemoria(whard);
2736        liberaMemoria(idhardwares);
2737        return (retval);
2738}
2739// ________________________________________________________________________________________________________
2740// Función: cuestionPerfilHardware
2741//
2742//              Descripción:
2743//                      Comprueba existencia de perfil hardware y actualización de éste para el ordenador
2744//              Parámetros:
2745//                      - db: Objeto base de datos (ya operativo)
2746//                      - tbl: Objeto tabla
2747//                      - idc: Identificador de la Unidad organizativa donde se encuentra el cliente
2748//                      - ido: Identificador del ordenador
2749//                      - tbidhardware: Identificador del tipo de hardware
2750//                      - con: Número de componentes detectados para configurar un el perfil hardware
2751//                      - npc: Nombre del cliente
2752// ________________________________________________________________________________________________________
2753bool cuestionPerfilHardware(Database db, Table tbl, char *idc, char *ido,
2754                int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware,
2755                int lon)
2756{
2757        char msglog[LONSTD], *sqlstr;
2758        int i;
2759        int nwidperfilhard;
2760
2761        sqlstr = reservaMemoria(strlen(idhardwares)+LONSQL); // Reserva para escribir sentencia SQL
2762        if (sqlstr == NULL) {
2763                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
2764                return false;
2765        }
2766        // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados
2767        sprintf(sqlstr, "SELECT idperfilhard FROM"
2768                " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard,"
2769                "       group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )"
2770                "       ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares"
2771                " FROM  perfileshard_hardwares"
2772                " GROUP BY perfileshard_hardwares.idperfilhard) AS temp"
2773                " WHERE idhardwares LIKE '%s'", idhardwares);
2774
2775        if (!db.Execute(sqlstr, tbl)) {
2776                db.GetErrorErrStr(msglog);
2777                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2778                       __func__, __LINE__, msglog);
2779                liberaMemoria(sqlstr);
2780                return false;
2781        }
2782        if (tbl.ISEOF()) { // No existe un perfil hardware con esos componentes de componentes hardware, lo crea
2783                sprintf(sqlstr, "INSERT perfileshard  (descripcion,idcentro,grupoid)"
2784                                " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc);
2785                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2786                        db.GetErrorErrStr(msglog);
2787                        og_info(msglog);
2788                        liberaMemoria(sqlstr);
2789                        return false;
2790                }
2791                // Recupera el identificador del nuevo perfil hardware
2792                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2793                if (!db.Execute(sqlstr, tbl)) { // Error al leer
2794                        db.GetErrorErrStr(msglog);
2795                        og_info(msglog);
2796                        liberaMemoria(sqlstr);
2797                        return false;
2798                }
2799                if (!tbl.ISEOF()) { // Si existe registro
2800                        if (!tbl.Get("identificador", nwidperfilhard)) {
2801                                tbl.GetErrorErrStr(msglog);
2802                                og_info(msglog);
2803                                liberaMemoria(sqlstr);
2804                                return false;
2805                        }
2806                }
2807                // Crea la relación entre perfiles y componenetes hardware
2808                for (i = 0; i < lon; i++) {
2809                        sprintf(sqlstr, "INSERT perfileshard_hardwares  (idperfilhard,idhardware)"
2810                                                " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]);
2811                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2812                                db.GetErrorErrStr(msglog);
2813                                og_info(msglog);
2814                                liberaMemoria(sqlstr);
2815                                return false;
2816                        }
2817                }
2818        } else { // Existe un perfil con todos esos componentes
2819                if (!tbl.Get("idperfilhard", nwidperfilhard)) {
2820                        tbl.GetErrorErrStr(msglog);
2821                        og_info(msglog);
2822                        liberaMemoria(sqlstr);
2823                        return false;
2824                }
2825        }
2826        if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles
2827                // Actualiza el identificador del perfil hardware del ordenador
2828                sprintf(sqlstr, "UPDATE ordenadores SET idperfilhard=%d"
2829                        " WHERE idordenador=%s", nwidperfilhard, ido);
2830                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2831                        db.GetErrorErrStr(msglog);
2832                        og_info(msglog);
2833                        liberaMemoria(sqlstr);
2834                        return false;
2835                }
2836        }
2837        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
2838        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN "
2839                " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN"
2840                " (SELECT DISTINCT idperfilhard from ordenadores))");
2841        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2842                db.GetErrorErrStr(msglog);
2843                og_info(msglog);
2844                liberaMemoria(sqlstr);
2845                return false;
2846        }
2847
2848        /* Eliminar Perfiles hardware que quedan húerfanos */
2849        sprintf(sqlstr, "DELETE FROM perfileshard WHERE idperfilhard NOT IN"
2850                        " (SELECT DISTINCT idperfilhard FROM ordenadores)");
2851        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2852                db.GetErrorErrStr(msglog);
2853                og_info(msglog);
2854                liberaMemoria(sqlstr);
2855                return false;
2856        }
2857        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
2858        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN"
2859                        " (SELECT idperfilhard FROM perfileshard)");
2860        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2861                db.GetErrorErrStr(msglog);
2862                og_info(msglog);
2863                liberaMemoria(sqlstr);
2864                return false;
2865        }
2866        liberaMemoria(sqlstr);
2867        return true;
2868}
2869// ________________________________________________________________________________________________________
2870// Función: InventarioSoftware
2871//
2872//      Descripción:
2873//              Solicita al cliente un inventario de su software
2874//      Parámetros:
2875//              - socket_c: Socket de la consola al envió el mensaje
2876//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2877//      Devuelve:
2878//              true: Si el proceso es correcto
2879//              false: En caso de ocurrir algún error
2880// ________________________________________________________________________________________________________
2881static bool InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli)
2882{
2883        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
2884                respuestaConsola(og_client_socket(cli), ptrTrama, false);
2885                return false;
2886        }
2887        respuestaConsola(og_client_socket(cli), ptrTrama, true);
2888        return true;
2889}
2890// ________________________________________________________________________________________________________
2891// Función: RESPUESTA_InventarioSoftware
2892//
2893//      Descripción:
2894//              Respuesta del cliente al comando InventarioSoftware
2895//      Parámetros:
2896//              - socket_c: Socket del cliente que envió el mensaje
2897//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2898//      Devuelve:
2899//              true: Si el proceso es correcto
2900//              false: En caso de ocurrir algún error
2901// ________________________________________________________________________________________________________
2902static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli)
2903{
2904        char msglog[LONSTD];
2905        Database db;
2906        Table tbl;
2907        bool res;
2908        char *iph, *ido, *npc, *idc, *par, *sft, *buffer;
2909
2910        if (!db.Open(usuario, pasguor, datasource, catalog)) {
2911                db.GetErrorErrStr(msglog);
2912                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2913                       __func__, __LINE__, msglog);
2914                return false;
2915        }
2916
2917        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2918        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2919
2920        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
2921                liberaMemoria(iph);
2922                liberaMemoria(ido);
2923                syslog(LOG_ERR, "failed to register notification\n");
2924                return false;
2925        }
2926
2927        npc = copiaParametro("npc",ptrTrama); 
2928        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro 
2929        par = copiaParametro("par",ptrTrama);
2930        sft = copiaParametro("sft",ptrTrama);
2931
2932        buffer = rTrim(leeArchivo(sft));
2933        if (buffer)
2934                res=actualizaSoftware(db, tbl, buffer, par, ido, npc, idc);
2935
2936        liberaMemoria(iph);
2937        liberaMemoria(ido);     
2938        liberaMemoria(npc);     
2939        liberaMemoria(idc);     
2940        liberaMemoria(par);     
2941        liberaMemoria(sft);     
2942
2943        if(!res){
2944                syslog(LOG_ERR, "cannot update software\n");
2945                return false;
2946        }
2947
2948        db.Close(); // Cierra conexión
2949        return true;
2950}
2951// ________________________________________________________________________________________________________
2952// Función: actualizaSoftware
2953//
2954//      Descripción:
2955//              Actualiza la base de datos con la configuración software del cliente
2956//      Parámetros:
2957//              - db: Objeto base de datos (ya operativo)
2958//              - tbl: Objeto tabla
2959//              - sft: cadena con el inventario software
2960//              - par: Número de la partición
2961//              - ido: Identificador del ordenador del cliente en la tabla
2962//              - npc: Nombre del ordenador
2963//              - idc: Identificador del centro o Unidad organizativa
2964//      Devuelve:
2965//              true: Si el proceso es correcto
2966//              false: En caso de ocurrir algún error
2967//
2968//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
2969// ________________________________________________________________________________________________________
2970bool actualizaSoftware(Database db, Table tbl, char *sft, char *par,char *ido,
2971                       char *npc, char *idc)
2972{
2973        int i, j, lon, aux, idperfilsoft, idnombreso;
2974        bool retval;
2975        char *wsft;
2976        int tbidsoftware[MAXSOFTWARE];
2977        char *tbSoftware[MAXSOFTWARE],msglog[LONSTD], sqlstr[LONSQL], strInt[LONINT], *idsoftwares;
2978
2979        /* Toma Centro (Unidad Organizativa) y perfil software */
2980        sprintf(sqlstr, "SELECT idperfilsoft,numpar"
2981                " FROM ordenadores_particiones"
2982                " WHERE idordenador=%s", ido);
2983
2984        if (!db.Execute(sqlstr, tbl)) {
2985                db.GetErrorErrStr(msglog);
2986                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2987                       __func__, __LINE__, msglog);
2988                return false;
2989        }
2990        idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software
2991        while (!tbl.ISEOF()) { // Recorre particiones
2992                if (!tbl.Get("numpar", aux)) {
2993                        tbl.GetErrorErrStr(msglog);
2994                        og_info(msglog);
2995                        return false;
2996                }
2997                if (aux == atoi(par)) { // Se encuentra la partición
2998                        if (!tbl.Get("idperfilsoft", idperfilsoft)) {
2999                                tbl.GetErrorErrStr(msglog);
3000                                og_info(msglog);
3001                                return false;
3002                        }
3003                        break;
3004                }
3005                tbl.MoveNext();
3006        }
3007        wsft=escaparCadena(sft); // Codificar comillas simples
3008        if(!wsft)
3009                return false;
3010
3011        /* Recorre componentes software*/
3012        lon = splitCadena(tbSoftware, wsft, '\n');
3013
3014        if (lon == 0)
3015                return true; // No hay lineas que procesar
3016        if (lon > MAXSOFTWARE)
3017                lon = MAXSOFTWARE; // Limita el número de componentes software
3018
3019        for (i = 0; i < lon; i++) {
3020                // Primera línea es el sistema operativo: se obtiene identificador
3021                if (i == 0) {
3022                        idnombreso = checkDato(db, tbl, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso");
3023                        continue;
3024                }
3025
3026                sprintf(sqlstr,
3027                                "SELECT idsoftware FROM softwares WHERE descripcion ='%s'",
3028                                rTrim(tbSoftware[i]));
3029
3030                if (!db.Execute(sqlstr, tbl)) {
3031                        db.GetErrorErrStr(msglog);
3032                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3033                               __func__, __LINE__, msglog);
3034                        return false;
3035                }
3036
3037                if (tbl.ISEOF()) { //  Software NO existente
3038                        sprintf(sqlstr, "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)"
3039                                                " VALUES(2,'%s',%s,0)", tbSoftware[i], idc);
3040
3041                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3042                                db.GetErrorErrStr(msglog); // Error al acceder al registro
3043                                og_info(msglog);
3044                                return false;
3045                        }
3046                        // Recupera el identificador del software
3047                        sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
3048                        if (!db.Execute(sqlstr, tbl)) { // Error al leer
3049                                db.GetErrorErrStr(msglog); // Error al acceder al registro
3050                                og_info(msglog);
3051                                return false;
3052                        }
3053                        if (!tbl.ISEOF()) { // Si existe registro
3054                                if (!tbl.Get("identificador", tbidsoftware[i])) {
3055                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
3056                                        og_info(msglog);
3057                                        return false;
3058                                }
3059                        }
3060                } else {
3061                        if (!tbl.Get("idsoftware", tbidsoftware[i])) { // Toma dato
3062                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
3063                                og_info(msglog);
3064                                return false;
3065                        }
3066                }
3067        }
3068
3069        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
3070
3071        for (i = 0; i < lon - 1; i++) {
3072                for (j = i + 1; j < lon; j++) {
3073                        if (tbidsoftware[i] > tbidsoftware[j]) {
3074                                aux = tbidsoftware[i];
3075                                tbidsoftware[i] = tbidsoftware[j];
3076                                tbidsoftware[j] = aux;
3077                        }
3078                }
3079        }
3080        /* Crea cadena de identificadores de componentes software separados por coma */
3081        sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
3082        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
3083        idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon);
3084        if (idsoftwares == NULL) {
3085                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
3086                return false;
3087        }
3088        aux = sprintf(idsoftwares, "%d", tbidsoftware[0]);
3089        for (i = 1; i < lon; i++)
3090                aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]);
3091
3092        // Comprueba existencia de perfil software y actualización de éste para el ordenador
3093        if (!cuestionPerfilSoftware(db, tbl, idc, ido, idperfilsoft, idnombreso, idsoftwares, 
3094                        npc, par, tbidsoftware, lon)) {
3095                syslog(LOG_ERR, "cannot update software\n");
3096                og_info(msglog);
3097                retval=false;
3098        }
3099        else {
3100                retval=true;
3101        }
3102        liberaMemoria(wsft);
3103        liberaMemoria(idsoftwares);
3104        return (retval);
3105}
3106// ________________________________________________________________________________________________________
3107// Función: CuestionPerfilSoftware
3108//
3109//      Parámetros:
3110//              - db: Objeto base de datos (ya operativo)
3111//              - tbl: Objeto tabla
3112//              - idcentro: Identificador del centro en la tabla
3113//              - ido: Identificador del ordenador del cliente en la tabla
3114//              - idnombreso: Identificador del sistema operativo
3115//              - idsoftwares: Cadena con los identificadores de componentes software separados por comas
3116//              - npc: Nombre del ordenador del cliente
3117//              - particion: Número de la partición
3118//              - tbidsoftware: Array con los identificadores de componentes software
3119//              - lon: Número de componentes
3120//      Devuelve:
3121//              true: Si el proceso es correcto
3122//              false: En caso de ocurrir algún error
3123//
3124//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
3125//_________________________________________________________________________________________________________
3126bool cuestionPerfilSoftware(Database db, Table tbl, char *idc, char *ido,
3127                            int idperfilsoftware, int idnombreso,
3128                            char *idsoftwares, char *npc, char *par,
3129                            int *tbidsoftware, int lon)
3130{
3131        char *sqlstr, msglog[LONSTD];
3132        int i, nwidperfilsoft;
3133
3134        sqlstr = reservaMemoria(strlen(idsoftwares)+LONSQL); // Reserva para escribir sentencia SQL
3135        if (sqlstr == NULL) {
3136                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
3137                return false;
3138        }
3139        // Busca perfil soft del ordenador que contenga todos los componentes software encontrados
3140        sprintf(sqlstr, "SELECT idperfilsoft FROM"
3141                " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft,"
3142                "       group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )"
3143                "       ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares"
3144                " FROM  perfilessoft_softwares"
3145                " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp"
3146                " WHERE idsoftwares LIKE '%s'", idsoftwares);
3147
3148        if (!db.Execute(sqlstr, tbl)) {
3149                db.GetErrorErrStr(msglog);
3150                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3151                       __func__, __LINE__, msglog);
3152                liberaMemoria(sqlstr);
3153                return false;
3154        }
3155        if (tbl.ISEOF()) { // No existe un perfil software con esos componentes de componentes software, lo crea
3156                sprintf(sqlstr, "INSERT perfilessoft  (descripcion, idcentro, grupoid, idnombreso)"
3157                                " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso);
3158                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3159                        db.GetErrorErrStr(msglog);
3160                        og_info(msglog);
3161                        return false;
3162                }
3163                // Recupera el identificador del nuevo perfil software
3164                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
3165                if (!db.Execute(sqlstr, tbl)) { // Error al leer
3166                        tbl.GetErrorErrStr(msglog);
3167                        og_info(msglog);
3168                        liberaMemoria(sqlstr);
3169                        return false;
3170                }
3171                if (!tbl.ISEOF()) { // Si existe registro
3172                        if (!tbl.Get("identificador", nwidperfilsoft)) {
3173                                tbl.GetErrorErrStr(msglog);
3174                                og_info(msglog);
3175                                liberaMemoria(sqlstr);
3176                                return false;
3177                        }
3178                }
3179                // Crea la relación entre perfiles y componenetes software
3180                for (i = 0; i < lon; i++) {
3181                        sprintf(sqlstr, "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)"
3182                                                " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]);
3183                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3184                                db.GetErrorErrStr(msglog);
3185                                og_info(msglog);
3186                                liberaMemoria(sqlstr);
3187                                return false;
3188                        }
3189                }
3190        } else { // Existe un perfil con todos esos componentes
3191                if (!tbl.Get("idperfilsoft", nwidperfilsoft)) {
3192                        tbl.GetErrorErrStr(msglog);
3193                        og_info(msglog);
3194                        liberaMemoria(sqlstr);
3195                        return false;
3196                }
3197        }
3198
3199        if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
3200                // Actualiza el identificador del perfil software del ordenador
3201                sprintf(sqlstr, "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
3202                                " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
3203                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3204                        db.GetErrorErrStr(msglog);
3205                        og_info(msglog);
3206                        liberaMemoria(sqlstr);
3207                        return false;
3208                }
3209        }
3210
3211        /* DEPURACIÓN DE PERFILES SOFTWARE */
3212
3213         /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
3214        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\
3215                " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\
3216                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\
3217                " (SELECT DISTINCT idperfilsoft from imagenes))");
3218        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3219                db.GetErrorErrStr(msglog);
3220                og_info(msglog);
3221                liberaMemoria(sqlstr);
3222                return false;
3223        }
3224        /* Eliminar Perfiles software que quedan húerfanos */
3225        sprintf(sqlstr, "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN"
3226                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\
3227                " AND  idperfilsoft NOT IN"\
3228                " (SELECT DISTINCT idperfilsoft from imagenes)");
3229        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3230                db.GetErrorErrStr(msglog);
3231                og_info(msglog);
3232                liberaMemoria(sqlstr);
3233                return false;
3234        }
3235        /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
3236        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN"
3237                        " (SELECT idperfilsoft from perfilessoft)");
3238        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
3239                db.GetErrorErrStr(msglog);
3240                og_info(msglog);
3241                liberaMemoria(sqlstr);
3242                return false;
3243        }
3244        liberaMemoria(sqlstr);
3245        return true;
3246}
3247// ________________________________________________________________________________________________________
3248// Función: enviaArchivo
3249//
3250//      Descripción:
3251//              Envia un archivo por la red, por bloques
3252//      Parámetros:
3253//              - socket_c: Socket del cliente que envió el mensaje
3254//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
3255//      Devuelve:
3256//              true: Si el proceso es correcto
3257//              false: En caso de ocurrir algún error
3258// ________________________________________________________________________________________________________
3259static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli)
3260{
3261        int socket_c = og_client_socket(cli);
3262        char *nfl;
3263
3264        // Toma parámetros
3265        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
3266        if (!sendArchivo(&socket_c, nfl)) {
3267                liberaMemoria(nfl);
3268                syslog(LOG_ERR, "Problem sending file\n");
3269                return false;
3270        }
3271        liberaMemoria(nfl);
3272        return true;
3273}
3274// ________________________________________________________________________________________________________
3275// Función: enviaArchivo
3276//
3277//      Descripción:
3278//              Envia un archivo por la red, por bloques
3279//      Parámetros:
3280//              - socket_c: Socket del cliente que envió el mensaje
3281//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
3282//      Devuelve:
3283//              true: Si el proceso es correcto
3284//              false: En caso de ocurrir algún error
3285// ________________________________________________________________________________________________________
3286static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli)
3287{
3288        int socket_c = og_client_socket(cli);
3289        char *nfl;
3290
3291        // Toma parámetros
3292        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
3293        ptrTrama->tipo = MSG_NOTIFICACION;
3294        enviaFlag(&socket_c, ptrTrama);
3295        if (!recArchivo(&socket_c, nfl)) {
3296                liberaMemoria(nfl);
3297                syslog(LOG_ERR, "Problem receiving file\n");
3298                return false;
3299        }
3300        liberaMemoria(nfl);
3301        return true;
3302}
3303// ________________________________________________________________________________________________________
3304// Función: envioProgramacion
3305//
3306//      Descripción:
3307//              Envia un comando de actualización a todos los ordenadores que han sido programados con
3308//              alguna acción para que entren en el bucle de comandos pendientes y las ejecuten
3309//      Parámetros:
3310//              - socket_c: Socket del cliente que envió el mensaje
3311//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
3312//      Devuelve:
3313//              true: Si el proceso es correcto
3314//              false: En caso de ocurrir algún error
3315// ________________________________________________________________________________________________________
3316static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli)
3317{
3318        char sqlstr[LONSQL], msglog[LONSTD];
3319        char *idp,iph[LONIP],mac[LONMAC];
3320        Database db;
3321        Table tbl;
3322        int idx,idcomando;
3323
3324        if (!db.Open(usuario, pasguor, datasource, catalog)) {
3325                db.GetErrorErrStr(msglog);
3326                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
3327                       __func__, __LINE__, msglog);
3328                return false;
3329        }
3330
3331        idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones
3332
3333        sprintf(sqlstr, "SELECT ordenadores.ip,ordenadores.mac,acciones.idcomando FROM acciones "\
3334                        " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\
3335                        " WHERE acciones.idprogramacion=%s",idp);
3336       
3337        liberaMemoria(idp);
3338
3339        if (!db.Execute(sqlstr, tbl)) {
3340                db.GetErrorErrStr(msglog);
3341                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3342                       __func__, __LINE__, msglog);
3343                return false;
3344        }
3345        db.Close();
3346        if(tbl.ISEOF())
3347                return true; // No existen registros
3348
3349        /* Prepara la trama de actualizacion */
3350
3351        initParametros(ptrTrama,0);
3352        ptrTrama->tipo=MSG_COMANDO;
3353        sprintf(ptrTrama->parametros, "nfn=Actualizar\r");
3354
3355        while (!tbl.ISEOF()) { // Recorre particiones
3356                if (!tbl.Get("ip", iph)) {
3357                        tbl.GetErrorErrStr(msglog);
3358                        syslog(LOG_ERR, "cannot find ip column in table: %s\n",
3359                               msglog);
3360                        return false;
3361                }
3362                if (!tbl.Get("idcomando", idcomando)) {
3363                        tbl.GetErrorErrStr(msglog);
3364                        syslog(LOG_ERR, "cannot find idcomando column in table: %s\n",
3365                               msglog);
3366                        return false;
3367                }
3368                if(idcomando==1){ // Arrancar
3369                        if (!tbl.Get("mac", mac)) {
3370                                tbl.GetErrorErrStr(msglog);
3371                                syslog(LOG_ERR, "cannot find mac column in table: %s\n",
3372                                       msglog);
3373                                return false;
3374                        }
3375
3376                        // Se manda por broadcast y por unicast
3377                        if (!Levanta(iph, mac, (char*)"1"))
3378                                return false;
3379
3380                        if (!Levanta(iph, mac, (char*)"2"))
3381                                return false;
3382
3383                }
3384                if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos
3385                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
3386
3387                        strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente
3388                        if (!mandaTrama(&sock, ptrTrama)) {
3389                                syslog(LOG_ERR, "failed to send response: %s\n",
3390                                       strerror(errno));
3391                                return false;
3392                        }
3393                        //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad
3394                }
3395                tbl.MoveNext();
3396        }
3397        return true; // No existen registros
3398}
3399
3400// This object stores function handler for messages
3401static struct {
3402        const char *nf; // Nombre de la función
3403        bool (*fcn)(TRAMA *, struct og_client *cli);
3404} tbfuncionesServer[] = {
3405        { "Sondeo",                             Sondeo,                 },
3406        { "respuestaSondeo",                    respuestaSondeo,        },
3407        { "ConsolaRemota",                      ConsolaRemota,          },
3408        { "EcoConsola",                         EcoConsola,             },
3409        { "Actualizar",                         Actualizar,             },
3410        { "Purgar",                             Purgar,                 },
3411        { "InclusionCliente",                   InclusionCliente,       },
3412        { "InclusionClienteWinLnx",             InclusionClienteWinLnx, },
3413        { "AutoexecCliente",                    AutoexecCliente,        },
3414        { "ComandosPendientes",                 ComandosPendientes,     },
3415        { "DisponibilidadComandos",             DisponibilidadComandos, },
3416        { "Arrancar",                           Arrancar,               },
3417        { "RESPUESTA_Arrancar",                 RESPUESTA_Arrancar,     },
3418        { "Apagar",                             Apagar,                 },
3419        { "RESPUESTA_Apagar",                   RESPUESTA_Apagar,       },
3420        { "Reiniciar",                          Reiniciar,              },
3421        { "RESPUESTA_Reiniciar",                RESPUESTA_Reiniciar,    },
3422        { "IniciarSesion",                      IniciarSesion,          },
3423        { "RESPUESTA_IniciarSesion",            RESPUESTA_IniciarSesion, },
3424        { "CrearImagen",                        CrearImagen,            },
3425        { "RESPUESTA_CrearImagen",              RESPUESTA_CrearImagen,  },
3426        { "CrearImagenBasica",                  CrearImagenBasica,      },
3427        { "RESPUESTA_CrearImagenBasica",        RESPUESTA_CrearImagenBasica, },
3428        { "CrearSoftIncremental",               CrearSoftIncremental,   },
3429        { "RESPUESTA_CrearSoftIncremental",     RESPUESTA_CrearSoftIncremental, },
3430        { "RestaurarImagen",                    RestaurarImagen,        },
3431        { "RESPUESTA_RestaurarImagen",          RESPUESTA_RestaurarImagen },
3432        { "RestaurarImagenBasica",              RestaurarImagenBasica, },
3433        { "RESPUESTA_RestaurarImagenBasica",    RESPUESTA_RestaurarImagenBasica, },
3434        { "RestaurarSoftIncremental",           RestaurarSoftIncremental, },
3435        { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, },
3436        { "Configurar",                         Configurar,             },
3437        { "RESPUESTA_Configurar",               RESPUESTA_Configurar,   },
3438        { "EjecutarScript",                     EjecutarScript,         },
3439        { "RESPUESTA_EjecutarScript",           RESPUESTA_EjecutarScript, },
3440        { "InventarioHardware",                 InventarioHardware,     },
3441        { "RESPUESTA_InventarioHardware",       RESPUESTA_InventarioHardware, },
3442        { "InventarioSoftware",                 InventarioSoftware      },
3443        { "RESPUESTA_InventarioSoftware",       RESPUESTA_InventarioSoftware, },
3444        { "enviaArchivo",                       enviaArchivo,           },
3445        { "recibeArchivo",                      recibeArchivo,          },
3446        { "envioProgramacion",                  envioProgramacion,      },
3447        { NULL,                                 NULL,                   },
3448};
3449
3450// ________________________________________________________________________________________________________
3451// Función: gestionaTrama
3452//
3453//              Descripción:
3454//                      Procesa las tramas recibidas .
3455//              Parametros:
3456//                      - s : Socket usado para comunicaciones
3457//      Devuelve:
3458//              true: Si el proceso es correcto
3459//              false: En caso de ocurrir algún error
3460// ________________________________________________________________________________________________________
3461static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli)
3462{
3463        int i, res;
3464        char *nfn;
3465
3466        if (ptrTrama){
3467                INTROaFINCAD(ptrTrama);
3468                nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función
3469
3470                for (i = 0; tbfuncionesServer[i].fcn; i++) {
3471                        if (!strncmp(tbfuncionesServer[i].nf, nfn,
3472                                     strlen(tbfuncionesServer[i].nf))) {
3473                                res = tbfuncionesServer[i].fcn(ptrTrama, cli);
3474                                if (!res) {
3475                                        syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n",
3476                                               tbfuncionesServer[i].nf,
3477                                               inet_ntoa(cli->addr.sin_addr),
3478                                               ntohs(cli->addr.sin_port));
3479                                } else {
3480                                        syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n",
3481                                               tbfuncionesServer[i].nf,
3482                                               inet_ntoa(cli->addr.sin_addr),
3483                                               ntohs(cli->addr.sin_port));
3484                                }
3485                                break;
3486                        }
3487                }
3488                if (!tbfuncionesServer[i].fcn)
3489                        syslog(LOG_ERR, "unknown request %s from client %s:%hu\n",
3490                               nfn, inet_ntoa(cli->addr.sin_addr),
3491                               ntohs(cli->addr.sin_port));
3492
3493                liberaMemoria(nfn);
3494        }
3495}
3496
3497static void og_client_release(struct ev_loop *loop, struct og_client *cli)
3498{
3499        if (cli->keepalive_idx >= 0) {
3500                syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n",
3501                       inet_ntoa(cli->addr.sin_addr),
3502                       ntohs(cli->addr.sin_port), cli->keepalive_idx);
3503                tbsockets[cli->keepalive_idx].cli = NULL;
3504        }
3505
3506        ev_io_stop(loop, &cli->io);
3507        close(cli->io.fd);
3508        free(cli);
3509}
3510
3511static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli)
3512{
3513        struct og_client *old_cli;
3514
3515        old_cli = tbsockets[cli->keepalive_idx].cli;
3516        if (old_cli && old_cli != cli) {
3517                syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n",
3518                       inet_ntoa(old_cli->addr.sin_addr),
3519                       ntohs(old_cli->addr.sin_port));
3520
3521                og_client_release(loop, old_cli);
3522        }
3523        tbsockets[cli->keepalive_idx].cli = cli;
3524}
3525
3526static void og_client_reset_state(struct og_client *cli)
3527{
3528        cli->state = OG_CLIENT_RECEIVING_HEADER;
3529        cli->buf_len = 0;
3530}
3531
3532static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
3533{
3534        char hdrlen[LONHEXPRM];
3535        struct og_client *cli;
3536        TRAMA *ptrTrama;
3537        int ret, len;
3538        char *data;
3539
3540        cli = container_of(io, struct og_client, io);
3541
3542        if (events & EV_ERROR) {
3543                syslog(LOG_ERR, "unexpected error event from client %s:%hu\n",
3544                               inet_ntoa(cli->addr.sin_addr),
3545                               ntohs(cli->addr.sin_port));
3546                goto close;
3547        }
3548
3549        ret = recv(io->fd, cli->buf + cli->buf_len,
3550                   sizeof(cli->buf) - cli->buf_len, 0);
3551        if (ret <= 0) {
3552                if (ret < 0) {
3553                        syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n",
3554                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
3555                               strerror(errno));
3556                } else {
3557                        syslog(LOG_DEBUG, "closed connection by %s:%hu\n",
3558                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
3559                }
3560                goto close;
3561        }
3562
3563        if (cli->keepalive_idx >= 0)
3564                return;
3565
3566        ev_timer_again(loop, &cli->timer);
3567
3568        cli->buf_len += ret;
3569
3570        switch (cli->state) {
3571        case OG_CLIENT_RECEIVING_HEADER:
3572                /* Still too short to validate protocol fingerprint and message
3573                 * length.
3574                 */
3575                if (cli->buf_len < 15 + LONHEXPRM)
3576                        return;
3577
3578                if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) {
3579                        syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n",
3580                               inet_ntoa(cli->addr.sin_addr),
3581                               ntohs(cli->addr.sin_port));
3582                        goto close;
3583                }
3584
3585                memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM);
3586                cli->msg_len = strtol(hdrlen, NULL, 16);
3587
3588                /* Header announces more that we can fit into buffer. */
3589                if (cli->msg_len >= sizeof(cli->buf)) {
3590                        syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n",
3591                               cli->msg_len, inet_ntoa(cli->addr.sin_addr),
3592                               ntohs(cli->addr.sin_port));
3593                        goto close;
3594                }
3595
3596                cli->state = OG_CLIENT_RECEIVING_PAYLOAD;
3597                /* Fall through. */
3598        case OG_CLIENT_RECEIVING_PAYLOAD:
3599                /* Still not enough data to process request. */
3600                if (cli->buf_len < cli->msg_len)
3601                        return;
3602
3603                cli->state = OG_CLIENT_PROCESSING_REQUEST;
3604                /* fall through. */
3605        case OG_CLIENT_PROCESSING_REQUEST:
3606                syslog(LOG_DEBUG, "processing request from %s:%hu\n",
3607                       inet_ntoa(cli->addr.sin_addr),
3608                       ntohs(cli->addr.sin_port));
3609
3610                len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM);
3611                data = desencriptar(&cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM], &len);
3612
3613                ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA));
3614                if (!ptrTrama) {
3615                        syslog(LOG_ERR, "OOM\n");
3616                        goto close;
3617                }
3618
3619                initParametros(ptrTrama, len);
3620                memcpy(ptrTrama, cli->buf, LONGITUD_CABECERATRAMA);
3621                memcpy(ptrTrama->parametros, data, len);
3622                ptrTrama->lonprm = len;
3623
3624                gestionaTrama(ptrTrama, cli);
3625
3626                liberaMemoria(ptrTrama->parametros);
3627                liberaMemoria(ptrTrama);
3628
3629                if (cli->keepalive_idx < 0) {
3630                        syslog(LOG_DEBUG, "server closing connection to %s:%hu\n",
3631                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
3632                        goto close;
3633                } else {
3634                        syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n",
3635                               inet_ntoa(cli->addr.sin_addr),
3636                               ntohs(cli->addr.sin_port));
3637                        og_client_keepalive(loop, cli);
3638                        og_client_reset_state(cli);
3639                }
3640                break;
3641        default:
3642                syslog(LOG_ERR, "unknown state, critical internal error\n");
3643                goto close;
3644        }
3645        return;
3646close:
3647        ev_timer_stop(loop, &cli->timer);
3648        og_client_release(loop, cli);
3649}
3650
3651static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events)
3652{
3653        struct og_client *cli;
3654
3655        cli = container_of(timer, struct og_client, timer);
3656        if (cli->keepalive_idx >= 0) {
3657                ev_timer_again(loop, &cli->timer);
3658                return;
3659        }
3660        syslog(LOG_ERR, "timeout request for client %s:%hu\n",
3661               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
3662
3663        og_client_release(loop, cli);
3664}
3665
3666static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io,
3667                                int events)
3668{
3669        struct sockaddr_in client_addr;
3670        socklen_t addrlen = sizeof(client_addr);
3671        struct og_client *cli;
3672        int client_sd;
3673
3674        if (events & EV_ERROR)
3675                return;
3676
3677        client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen);
3678        if (client_sd < 0) {
3679                syslog(LOG_ERR, "cannot accept client connection\n");
3680                return;
3681        }
3682
3683        cli = (struct og_client *)calloc(1, sizeof(struct og_client));
3684        if (!cli) {
3685                close(client_sd);
3686                return;
3687        }
3688        memcpy(&cli->addr, &client_addr, sizeof(client_addr));
3689        cli->keepalive_idx = -1;
3690
3691        syslog(LOG_DEBUG, "connection from client %s:%hu\n",
3692               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
3693
3694        ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ);
3695        ev_io_start(loop, &cli->io);
3696        ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.);
3697        ev_timer_start(loop, &cli->timer);
3698}
3699
3700int main(int argc, char *argv[])
3701{
3702        struct ev_loop *loop = ev_default_loop(0);
3703        struct ev_io ev_io_server;
3704        struct sockaddr_in local;
3705        int socket_s;
3706        int activo=1;
3707        int i;
3708
3709        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
3710                exit(EXIT_FAILURE);
3711
3712        openlog("ogAdmServer", LOG_PID, LOG_DAEMON);
3713
3714        /*--------------------------------------------------------------------------------------------------------
3715         Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
3716         ---------------------------------------------------------------------------------------------------------*/
3717        if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución
3718                exit(EXIT_FAILURE);
3719
3720        if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
3721                exit(EXIT_FAILURE);
3722        }
3723
3724        /*--------------------------------------------------------------------------------------------------------
3725         // Inicializa array de información de los clientes
3726         ---------------------------------------------------------------------------------------------------------*/
3727        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
3728                tbsockets[i].ip[0] = '\0';
3729                tbsockets[i].cli = NULL;
3730        }
3731        /*--------------------------------------------------------------------------------------------------------
3732         Creación y configuración del socket del servicio
3733         ---------------------------------------------------------------------------------------------------------*/
3734        socket_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Crea socket del servicio
3735        setsockopt(socket_s, SOL_SOCKET, SO_REUSEPORT, &activo, sizeof(int));
3736        if (socket_s < 0) {
3737                syslog(LOG_ERR, "cannot create main socket\n");
3738                exit(EXIT_FAILURE);
3739        }
3740
3741        local.sin_addr.s_addr = htonl(INADDR_ANY); // Configura el socket del servicio
3742        local.sin_family = AF_INET;
3743        local.sin_port = htons(atoi(puerto));
3744
3745        if (bind(socket_s, (struct sockaddr *) &local, sizeof(local)) < 0) {
3746                syslog(LOG_ERR, "cannot bind socket\n");
3747                exit(EXIT_FAILURE);
3748        }
3749
3750        listen(socket_s, 250); // Pone a escuchar al socket
3751
3752        ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ);
3753        ev_io_start(loop, &ev_io_server);
3754
3755        infoLog(1); // Inicio de sesión
3756
3757        /* old log file has been deprecated. */
3758        og_log(97, false);
3759
3760        syslog(LOG_INFO, "Waiting for connections\n");
3761
3762        while (1)
3763                ev_loop(loop, 0);
3764
3765        exit(EXIT_SUCCESS);
3766}
Note: See TracBrowser for help on using the repository browser.