source: ogServer-Git/sources/ogAdmServer.cpp @ 99c6c62

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

#915 remove Actualizar(), Purgar(), Reiniciar() and IniciarSesion?()

The new REST API obsoletes the following commands:

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