source: admin/Sources/Services/ogAdmServer/sources/ogAdmServer.cpp @ 39b84ff

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

#580 ignore SIGPIPE signal

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

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