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

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

#941 use dbi layer from buscaComandos()

  • Property mode set to 100644
File size: 157.6 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"
[0fbdcf2]11#include "dbi.h"
[212280e]12#include <ev.h>
[ef6e3d2]13#include <syslog.h>
[2baf362]14#include <sys/ioctl.h>
15#include <ifaddrs.h>
[c6020f2]16#include <sys/types.h>
17#include <sys/stat.h>
18#include <fcntl.h>
[95e6520]19#include <jansson.h>
[2427e9d]20
21static char usuario[LONPRM]; // Usuario de acceso a la base de datos
22static char pasguor[LONPRM]; // Password del usuario
23static char datasource[LONPRM]; // Dirección IP del gestor de base de datos
24static char catalog[LONPRM]; // Nombre de la base de datos
[2baf362]25static char interface[LONPRM]; // Interface name
[fd30540]26static char auth_token[LONPRM]; // API token
[2427e9d]27
[0fbdcf2]28static struct og_dbi_config dbi_config = {
29        .user           = usuario,
30        .passwd         = pasguor,
31        .host           = datasource,
32        .database       = catalog,
33};
34
[b9eb98b]35//________________________________________________________________________________________________________
36//      Función: tomaConfiguracion
37//
38//      Descripción:
39//              Lee el fichero de configuración del servicio
40//      Parámetros:
41//              filecfg : Ruta completa al fichero de configuración
42//      Devuelve:
[9dea2d6]43//              true: Si el proceso es correcto
44//              false: En caso de ocurrir algún error
[b9eb98b]45//________________________________________________________________________________________________________
[59fb4d5]46static bool tomaConfiguracion(const char *filecfg)
47{
[20fa7b9]48        char buf[1024], *line;
49        char *key, *value;
50        FILE *fcfg;
[b9eb98b]51
52        if (filecfg == NULL || strlen(filecfg) == 0) {
[b56cbeb]53                syslog(LOG_ERR, "No configuration file has been specified\n");
[9dea2d6]54                return false;
[b9eb98b]55        }
56
57        fcfg = fopen(filecfg, "rt");
58        if (fcfg == NULL) {
[b56cbeb]59                syslog(LOG_ERR, "Cannot open configuration file `%s'\n",
60                       filecfg);
[9dea2d6]61                return false;
[b9eb98b]62        }
63
64        servidoradm[0] = (char) NULL; //inicializar variables globales
65
[20fa7b9]66        line = fgets(buf, sizeof(buf), fcfg);
67        while (line != NULL) {
68                const char *delim = "=";
69
70                line[strlen(line) - 1] = '\0';
71
72                key = strtok(line, delim);
73                value = strtok(NULL, delim);
74
75                if (!strcmp(StrToUpper(key), "SERVIDORADM"))
76                        snprintf(servidoradm, sizeof(servidoradm), "%s", value);
77                else if (!strcmp(StrToUpper(key), "PUERTO"))
78                        snprintf(puerto, sizeof(puerto), "%s", value);
79                else if (!strcmp(StrToUpper(key), "USUARIO"))
80                        snprintf(usuario, sizeof(usuario), "%s", value);
81                else if (!strcmp(StrToUpper(key), "PASSWORD"))
82                        snprintf(pasguor, sizeof(pasguor), "%s", value);
83                else if (!strcmp(StrToUpper(key), "DATASOURCE"))
84                        snprintf(datasource, sizeof(datasource), "%s", value);
85                else if (!strcmp(StrToUpper(key), "CATALOG"))
86                        snprintf(catalog, sizeof(catalog), "%s", value);
[2baf362]87                else if (!strcmp(StrToUpper(key), "INTERFACE"))
88                        snprintf(interface, sizeof(interface), "%s", value);
[fd30540]89                else if (!strcmp(StrToUpper(key), "APITOKEN"))
90                        snprintf(auth_token, sizeof(auth_token), "%s", value);
[20fa7b9]91
92                line = fgets(buf, sizeof(buf), fcfg);
[b9eb98b]93        }
[20fa7b9]94
[a927e14]95        fclose(fcfg);
96
[aff4cfd]97        if (!servidoradm[0]) {
[b56cbeb]98                syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n");
[9dea2d6]99                return false;
[b9eb98b]100        }
[aff4cfd]101        if (!puerto[0]) {
[b56cbeb]102                syslog(LOG_ERR, "Missing PUERTO in configuration file\n");
[9dea2d6]103                return false;
[b9eb98b]104        }
[aff4cfd]105        if (!usuario[0]) {
[b56cbeb]106                syslog(LOG_ERR, "Missing USUARIO in configuration file\n");
[9dea2d6]107                return false;
[b9eb98b]108        }
[aff4cfd]109        if (!pasguor[0]) {
[b56cbeb]110                syslog(LOG_ERR, "Missing PASSWORD in configuration file\n");
[9dea2d6]111                return false;
[b9eb98b]112        }
[aff4cfd]113        if (!datasource[0]) {
[b56cbeb]114                syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n");
[9dea2d6]115                return false;
[b9eb98b]116        }
[aff4cfd]117        if (!catalog[0]) {
[b56cbeb]118                syslog(LOG_ERR, "Missing CATALOG in configuration file\n");
[9dea2d6]119                return false;
[b9eb98b]120        }
[2baf362]121        if (!interface[0])
122                syslog(LOG_ERR, "Missing INTERFACE in configuration file\n");
[eb99080]123
[9dea2d6]124        return true;
[b9eb98b]125}
[eb99080]126
[212280e]127enum og_client_state {
128        OG_CLIENT_RECEIVING_HEADER      = 0,
129        OG_CLIENT_RECEIVING_PAYLOAD,
130        OG_CLIENT_PROCESSING_REQUEST,
131};
132
[20dcb0a]133#define OG_MSG_REQUEST_MAXLEN   4096
134
[212280e]135/* Shut down connection if there is no complete message after 10 seconds. */
136#define OG_CLIENT_TIMEOUT       10
137
138struct og_client {
139        struct ev_io            io;
140        struct ev_timer         timer;
[ef6e3d2]141        struct sockaddr_in      addr;
[212280e]142        enum og_client_state    state;
[20dcb0a]143        char                    buf[OG_MSG_REQUEST_MAXLEN];
[212280e]144        unsigned int            buf_len;
145        unsigned int            msg_len;
[f09aca6]146        int                     keepalive_idx;
[95e6520]147        bool                    rest;
[36ad006]148        int                     content_length;
[fd30540]149        char                    auth_token[64];
[212280e]150};
151
152static inline int og_client_socket(const struct og_client *cli)
153{
154        return cli->io.fd;
155}
156
[b9eb98b]157// ________________________________________________________________________________________________________
158// Función: clienteDisponible
159//
160//      Descripción:
161//              Comprueba la disponibilidad del cliente para recibir comandos interactivos
162//      Parametros:
163//              - ip : La ip del cliente a buscar
164//              - idx: (Salida)  Indice que ocupa el cliente, de estar ya registrado
165//      Devuelve:
[9dea2d6]166//              true: Si el cliente está disponible
167//              false: En caso contrario
[b9eb98b]168// ________________________________________________________________________________________________________
[59fb4d5]169bool clienteDisponible(char *ip, int* idx)
170{
[b9eb98b]171        int estado;
172
173        if (clienteExistente(ip, idx)) {
174                estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado
175                if (estado == 0)
[9dea2d6]176                        return false;
[b9eb98b]177
178                estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado
179                if (estado == 0)
[9dea2d6]180                        return false;
[b9eb98b]181
182                estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión
183                if (estado == 0)
[9dea2d6]184                        return false;
[b9eb98b]185
[9dea2d6]186                return true; // En caso contrario el cliente está disponible
[b9eb98b]187        }
[9dea2d6]188        return false; // Cliente no está registrado en el sistema
[b9eb98b]189}
190// ________________________________________________________________________________________________________
191// Función: clienteExistente
192//
193//      Descripción:
194//              Comprueba si el cliente está registrado en la tabla de socket del sistema
195//      Parametros:
196//              - ip : La ip del cliente a buscar
197//              - idx:(Salida)  Indice que ocupa el cliente, de estar ya registrado
198//      Devuelve:
[9dea2d6]199//              true: Si el cliente está registrado
200//              false: En caso contrario
[b9eb98b]201// ________________________________________________________________________________________________________
[59fb4d5]202bool clienteExistente(char *ip, int* idx)
203{
[b9eb98b]204        int i;
205        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
206                if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena
207                        *idx = i;
[9dea2d6]208                        return true;
[b9eb98b]209                }
210        }
[9dea2d6]211        return false;
[b9eb98b]212}
213// ________________________________________________________________________________________________________
214// Función: hayHueco
215//
216//      Descripción:
[9dea2d6]217//              Esta función devuelve true o false dependiendo de que haya hueco en la tabla de sockets para un nuevo cliente.
[b9eb98b]218//      Parametros:
219//              - idx:   Primer indice libre que se podrn utilizar
220//      Devuelve:
[9dea2d6]221//              true: Si el proceso es correcto
222//              false: En caso de ocurrir algún error
[b9eb98b]223// ________________________________________________________________________________________________________
[59fb4d5]224static bool hayHueco(int *idx)
225{
[b9eb98b]226        int i;
227
228        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
229                if (strncmp(tbsockets[i].ip, "\0", 1) == 0) { // Hay un hueco
230                        *idx = i;
[9dea2d6]231                        return true;
[b9eb98b]232                }
233        }
[9dea2d6]234        return false;
[b9eb98b]235}
236// ________________________________________________________________________________________________________
[6fc28cd]237// Función: InclusionClienteWin
238//
239//      Descripción:
240//              Esta función incorpora el socket de un nuevo cliente Windows o Linux a la tabla de clientes
241//      Parámetros:
242//              - socket_c: Socket del cliente que envió el mensaje
243//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
244//      Devuelve:
[9dea2d6]245//              true: Si el proceso es correcto
246//              false: En caso de ocurrir algún error
[6fc28cd]247// ________________________________________________________________________________________________________
[212280e]248static bool InclusionClienteWinLnx(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]249{
[212280e]250        int socket_c = og_client_socket(cli);
[6fc28cd]251        int res,idordenador,lon;
252        char nombreordenador[LONFIL];
[212280e]253
254        res = procesoInclusionClienteWinLnx(socket_c, ptrTrama, &idordenador,
255                                            nombreordenador);
256
[6fc28cd]257        // Prepara la trama de respuesta
258
259        initParametros(ptrTrama,0);
260        ptrTrama->tipo=MSG_RESPUESTA;
261        lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionClienteWinLnx\r");
262        lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador);
263        lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador);       
264        lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", res);   
[b56cbeb]265
[07d2b73]266        if (!mandaTrama(&socket_c, ptrTrama)) {
[b56cbeb]267                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
268                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
269                       strerror(errno));
[9dea2d6]270                return false;
[6fc28cd]271        }
[9dea2d6]272        return true;
[6fc28cd]273}
274// ________________________________________________________________________________________________________
275// Función: procesoInclusionClienteWinLnx
276//
277//      Descripción:
278//              Implementa el proceso de inclusión en el sistema del Cliente Windows o Linux
279//      Parámetros de entrada:
280//              - socket_c: Socket del cliente que envió el mensaje
281//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
282//      Parámetros de salida:
283//              - ido: Identificador del ordenador
284//              - nombreordenador: Nombre del ordenador
285//      Devuelve:
286//              Código del error producido en caso de ocurrir algún error, 0 si el proceso es correcto
287// ________________________________________________________________________________________________________
[59fb4d5]288bool procesoInclusionClienteWinLnx(int socket_c, TRAMA *ptrTrama, int *idordenador, char *nombreordenador)
[6fc28cd]289 {
[0fbdcf2]290        struct og_dbi *dbi;
291        const char *msglog;
292        dbi_result result;
[6fc28cd]293        char *iph;
[9764185]294
[6fc28cd]295        // Toma parámetros
296        iph = copiaParametro("iph",ptrTrama); // Toma ip
297
[0fbdcf2]298        dbi = og_dbi_open(&dbi_config);
299        if (!dbi) {
300                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
301                       __func__, __LINE__);
302                goto err_dbi_open;
[6fc28cd]303        }
304
[0fbdcf2]305        result = dbi_conn_queryf(dbi->conn,
[6fc28cd]306                        "SELECT idordenador,nombreordenador FROM ordenadores "
307                                " WHERE ordenadores.ip = '%s'", iph);
[0fbdcf2]308        if (!result) {
309                dbi_conn_error(dbi->conn, &msglog);
[b56cbeb]310                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
311                       __func__, __LINE__, msglog);
[0fbdcf2]312                goto err_query_fail;
[6fc28cd]313        }
314
[0fbdcf2]315        if (!dbi_result_next_row(result)) {
[b56cbeb]316                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
317                       __func__, __LINE__);
[0fbdcf2]318                dbi_result_free(result);
319                goto err_query_fail;
[6fc28cd]320        }
321
[b56cbeb]322        syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph);
323
[0fbdcf2]324        *idordenador = dbi_result_get_uint(result, "idordenador");
325        nombreordenador = (char *)dbi_result_get_string(result, "nombreordenador");
326
327        dbi_result_free(result);
328        og_dbi_close(dbi);
[162d780]329
[6fc28cd]330        if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets
[eb99080]331                liberaMemoria(iph);
[b56cbeb]332                syslog(LOG_ERR, "client table is full\n");
[162d780]333                return false;
[6fc28cd]334        }
[eb99080]335        liberaMemoria(iph);
[162d780]336        return true;
[0fbdcf2]337
338err_query_fail:
339        og_dbi_close(dbi);
340err_dbi_open:
341        liberaMemoria(iph);
342        return false;
[6fc28cd]343}
344// ________________________________________________________________________________________________________
[b9eb98b]345// Función: InclusionCliente
346//
347//      Descripción:
348//              Esta función incorpora el socket de un nuevo cliente a la tabla de clientes y le devuelve alguna de sus propiedades:
349//              nombre, identificador, tamaño de la caché , etc ...
350//      Parámetros:
351//              - socket_c: Socket del cliente que envió el mensaje
352//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
353//      Devuelve:
[9dea2d6]354//              true: Si el proceso es correcto
355//              false: En caso de ocurrir algún error
[b9eb98b]356// ________________________________________________________________________________________________________
[212280e]357static bool InclusionCliente(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]358{
[212280e]359        int socket_c = og_client_socket(cli);
360
[b56cbeb]361        if (!procesoInclusionCliente(cli, ptrTrama)) {
[b9eb98b]362                initParametros(ptrTrama,0);
363                strcpy(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\rres=0\r");
[07d2b73]364                if (!mandaTrama(&socket_c, ptrTrama)) {
[b56cbeb]365                        syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
366                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
367                               strerror(errno));
[9dea2d6]368                        return false;
[b9eb98b]369                }
370        }
[9dea2d6]371        return true;
[59fb4d5]372}
[b9eb98b]373// ________________________________________________________________________________________________________
374// Función: procesoInclusionCliente
375//
376//      Descripción:
377//              Implementa el proceso de inclusión en el sistema del Cliente
378//      Parámetros:
379//              - socket_c: Socket del cliente que envió el mensaje
380//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
381//      Devuelve:
[9dea2d6]382//              true: Si el proceso es correcto
383//              false: En caso de ocurrir algún error
[b9eb98b]384// ________________________________________________________________________________________________________
[b56cbeb]385bool procesoInclusionCliente(struct og_client *cli, TRAMA *ptrTrama)
[59fb4d5]386{
[b56cbeb]387        int socket_c = og_client_socket(cli);
[b9eb98b]388        char msglog[LONSTD], sqlstr[LONSQL];
389        Database db;
390        Table tbl;
391
392        char *iph, *cfg;
393        char nombreordenador[LONFIL];
394        int lon, resul, idordenador, idmenu, cache, idproautoexec, idaula, idcentro;
395
396        // Toma parámetros
397        iph = copiaParametro("iph",ptrTrama); // Toma ip
398        cfg = copiaParametro("cfg",ptrTrama); // Toma configuracion
399
[b56cbeb]400        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[466106d]401                liberaMemoria(iph);
402                liberaMemoria(cfg);
[b9eb98b]403                db.GetErrorErrStr(msglog);
[b56cbeb]404                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
405                       __func__, __LINE__, msglog);
[9dea2d6]406                return false;
[b9eb98b]407        }
408
409        // Recupera los datos del cliente
410        sprintf(sqlstr,
411                        "SELECT ordenadores.*,aulas.idaula,centros.idcentro FROM ordenadores "
412                                " INNER JOIN aulas ON aulas.idaula=ordenadores.idaula"
413                                " INNER JOIN centros ON centros.idcentro=aulas.idcentro"
414                                " WHERE ordenadores.ip = '%s'", iph);
415
[b56cbeb]416        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]417                db.GetErrorErrStr(msglog);
[b56cbeb]418                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
419                       __func__, __LINE__, msglog);
[9dea2d6]420                return false;
[b9eb98b]421        }
422
[b56cbeb]423        if (tbl.ISEOF()) {
424                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
425                       __func__, __LINE__);
[9dea2d6]426                return false;
[b9eb98b]427        }
428
[b56cbeb]429        syslog(LOG_DEBUG, "Client %s requesting inclusion\n", iph);
430
[b9eb98b]431        if (!tbl.Get("idordenador", idordenador)) {
432                tbl.GetErrorErrStr(msglog);
[9764185]433                og_info(msglog);
[9dea2d6]434                return false;
[b9eb98b]435        }
436        if (!tbl.Get("nombreordenador", nombreordenador)) {
437                tbl.GetErrorErrStr(msglog);
[9764185]438                og_info(msglog);
[9dea2d6]439                return false;
[b9eb98b]440        }
441        if (!tbl.Get("idmenu", idmenu)) {
442                tbl.GetErrorErrStr(msglog);
[9764185]443                og_info(msglog);
[9dea2d6]444                return false;
[b9eb98b]445        }
446        if (!tbl.Get("cache", cache)) {
447                tbl.GetErrorErrStr(msglog);
[9764185]448                og_info(msglog);
[9dea2d6]449                return false;
[b9eb98b]450        }
451        if (!tbl.Get("idproautoexec", idproautoexec)) {
452                tbl.GetErrorErrStr(msglog);
[9764185]453                og_info(msglog);
[9dea2d6]454                return false;
[b9eb98b]455        }
456        if (!tbl.Get("idaula", idaula)) {
457                tbl.GetErrorErrStr(msglog);
[9764185]458                og_info(msglog);
[9dea2d6]459                return false;
[b9eb98b]460        }
461        if (!tbl.Get("idcentro", idcentro)) {
462                tbl.GetErrorErrStr(msglog);
[9764185]463                og_info(msglog);
[9dea2d6]464                return false;
[b9eb98b]465        }
466
467        resul = actualizaConfiguracion(db, tbl, cfg, idordenador); // Actualiza la configuración del ordenador
[eb99080]468        liberaMemoria(cfg);
[b9eb98b]469        db.Close();
470
471        if (!resul) {
[eb99080]472                liberaMemoria(iph);
[b56cbeb]473                syslog(LOG_ERR, "Cannot add client to database\n");
[9dea2d6]474                return false;
[b9eb98b]475        }
476
477        if (!registraCliente(iph)) { // Incluyendo al cliente en la tabla de sokets
[eb99080]478                liberaMemoria(iph);
[b56cbeb]479                syslog(LOG_ERR, "client table is full\n");
[9dea2d6]480                return false;
[b9eb98b]481        }
482
483        /*------------------------------------------------------------------------------------------------------------------------------
484         Prepara la trama de respuesta
485         -------------------------------------------------------------------------------------------------------------------------------*/
486        initParametros(ptrTrama,0);
487        ptrTrama->tipo=MSG_RESPUESTA;
488        lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_InclusionCliente\r");
489        lon += sprintf(ptrTrama->parametros + lon, "ido=%d\r", idordenador);
490        lon += sprintf(ptrTrama->parametros + lon, "npc=%s\r", nombreordenador);
491        lon += sprintf(ptrTrama->parametros + lon, "che=%d\r", cache);
492        lon += sprintf(ptrTrama->parametros + lon, "exe=%d\r", idproautoexec);
493        lon += sprintf(ptrTrama->parametros + lon, "ida=%d\r", idaula);
494        lon += sprintf(ptrTrama->parametros + lon, "idc=%d\r", idcentro);
495        lon += sprintf(ptrTrama->parametros + lon, "res=%d\r", 1); // Confirmación proceso correcto
496
[07d2b73]497        if (!mandaTrama(&socket_c, ptrTrama)) {
[b56cbeb]498                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
499                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
500                       strerror(errno));
[9dea2d6]501                return false;
[b9eb98b]502        }
[eb99080]503        liberaMemoria(iph);
[9dea2d6]504        return true;
[b9eb98b]505}
506// ________________________________________________________________________________________________________
507// Función: actualizaConfiguracion
508//
509//      Descripción:
510//              Esta función actualiza la base de datos con la configuracion de particiones de un cliente
511//      Parámetros:
512//              - db: Objeto base de datos (ya operativo)
513//              - tbl: Objeto tabla
514//              - cfg: cadena con una Configuración
515//              - ido: Identificador del ordenador cliente
516//      Devuelve:
[9dea2d6]517//              true: Si el proceso es correcto
518//              false: En caso de ocurrir algún error
[b9eb98b]519//      Especificaciones:
520//              Los parametros de la configuración son:
521//                      par= Número de partición
522//                      cpt= Codigo o tipo de partición
523//                      sfi= Sistema de ficheros que está implementado en la partición
524//                      soi= Nombre del sistema de ficheros instalado en la partición
525//                      tam= Tamaño de la partición
526// ________________________________________________________________________________________________________
[59fb4d5]527bool actualizaConfiguracion(Database db, Table tbl, char *cfg, int ido)
[b9eb98b]528{
529        char msglog[LONSTD], sqlstr[LONSQL];
[827bac5]530        int lon, p, c,i, dato, swu, idsoi, idsfi,k;
[3de93a9]531        char *ptrPar[MAXPAR], *ptrCfg[7], *ptrDual[2], tbPar[LONSTD];
[24df599]532        char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración.
[b9eb98b]533
[9a2dc88]534        lon = 0;
[b9eb98b]535        p = splitCadena(ptrPar, cfg, '\n');
536        for (i = 0; i < p; i++) {
537                c = splitCadena(ptrCfg, ptrPar[i], '\t');
[24df599]538
539                // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD.
540                if (i == 0 && c == 1) {
541                        splitCadena(ptrDual, ptrCfg[0], '=');
542                        ser = ptrDual[1];
543                        if (strlen(ser) > 0) {
544                                // Solo actualizar si número de serie no existía.
545                                sprintf(sqlstr, "UPDATE ordenadores SET numserie='%s'"
[b502279]546                                                " WHERE idordenador=%d AND numserie IS NULL",
[24df599]547                                                ser, ido);
548                                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
549                                        db.GetErrorErrStr(msglog);
[9764185]550                                        og_info(msglog);
[9dea2d6]551                                        return false;
[24df599]552                                }
553                        }
554                        continue;
555                }
556
557                // Distribución de particionado.
[c4b75b1]558                disk = par = cpt = sfi = soi = tam = uso = NULL;
[24df599]559
[b9eb98b]560                splitCadena(ptrDual, ptrCfg[0], '=');
[99f74d8]561                disk = ptrDual[1]; // Número de disco
[b9eb98b]562
563                splitCadena(ptrDual, ptrCfg[1], '=');
[99f74d8]564                par = ptrDual[1]; // Número de partición
565
[d1e9613]566                k=splitCadena(ptrDual, ptrCfg[2], '=');
567                if(k==2){
568                        cpt = ptrDual[1]; // Código de partición
569                }else{
[24df599]570                        cpt = (char*)"0";
[d1e9613]571                }
[b9eb98b]572
[99f74d8]573                k=splitCadena(ptrDual, ptrCfg[3], '=');
[b9eb98b]574                if(k==2){
575                        sfi = ptrDual[1]; // Sistema de ficheros
[eb99080]576                        /* Comprueba existencia del s0xistema de ficheros instalado */
[b9eb98b]577                        idsfi = checkDato(db, tbl, sfi, "sistemasficheros", "descripcion","idsistemafichero");
578                }
579                else
580                        idsfi=0;
581
[99f74d8]582                k=splitCadena(ptrDual, ptrCfg[4], '=');
[b9eb98b]583                if(k==2){ // Sistema operativo detecdtado
584                        soi = ptrDual[1]; // Nombre del S.O. instalado
585                        /* Comprueba existencia del sistema operativo instalado */
586                        idsoi = checkDato(db, tbl, soi, "nombresos", "nombreso", "idnombreso");
587                }
588                else
589                        idsoi=0;
590
[99f74d8]591                splitCadena(ptrDual, ptrCfg[5], '=');
[b9eb98b]592                tam = ptrDual[1]; // Tamaño de la partición
593
[c4b75b1]594                splitCadena(ptrDual, ptrCfg[6], '=');
595                uso = ptrDual[1]; // Porcentaje de uso del S.F.
596
[9a2dc88]597                lon += sprintf(tbPar + lon, "(%s, %s),", disk, par);
[b9eb98b]598
[1845104]599                sprintf(sqlstr, "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso"
[c4b75b1]600                                "  FROM ordenadores_particiones"
601                                " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[99f74d8]602                                ido, disk, par);
[e1ca941]603
604
[b56cbeb]605                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]606                        db.GetErrorErrStr(msglog);
[b56cbeb]607                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
608                               __func__, __LINE__, msglog);
[9dea2d6]609                        return false;
[b9eb98b]610                }
611                if (tbl.ISEOF()) { // Si no existe el registro
[c4b75b1]612                        sprintf(sqlstr, "INSERT INTO ordenadores_particiones(idordenador,numdisk,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)"
613                                        " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)",
614                                        ido, disk, par, cpt, tam, uso, idsfi, idsoi);
[e1ca941]615
616
[b9eb98b]617                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
618                                db.GetErrorErrStr(msglog);
[9764185]619                                og_info(msglog);
[9dea2d6]620                                return false;
[b9eb98b]621                        }
622                } else { // Existe el registro
[9dea2d6]623                        swu = true; // Se supone que algún dato ha cambiado
[1845104]624                        if (!tbl.Get("tamano", dato)) { // Toma dato
[b9eb98b]625                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]626                                og_info(msglog);
[9dea2d6]627                                return false;
[b9eb98b]628                        }
[1845104]629                        if (atoi(tam) == dato) { // Parámetro tamaño igual al almacenado
630                                if (!tbl.Get("idsistemafichero", dato)) { // Toma dato
[b9eb98b]631                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]632                                        og_info(msglog);
[9dea2d6]633                                        return false;
[b9eb98b]634                                }
[1845104]635                                if (idsfi == dato) { // Parámetro sistema de fichero igual al almacenado
636                                        if (!tbl.Get("idnombreso", dato)) { // Toma dato
[b9eb98b]637                                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]638                                                og_info(msglog);
[9dea2d6]639                                                return false;
[b9eb98b]640                                        }
[1845104]641                                        if (idsoi == dato) { // Parámetro sistema operativo distinto al almacenado
642                                                swu = false; // Todos los parámetros de la partición son iguales, no se actualiza
[b9eb98b]643                                        }
644                                }
645                        }
646                        if (swu) { // Hay que actualizar los parámetros de la partición
647                                sprintf(sqlstr, "UPDATE ordenadores_particiones SET "
648                                        " codpar=0x%s,"
649                                        " tamano=%s,"
[c4b75b1]650                                        " uso=%s,"
[b9eb98b]651                                        " idsistemafichero=%d,"
652                                        " idnombreso=%d,"
[599c505]653                                        " idimagen=0,"
654                                        " idperfilsoft=0,"
655                                        " fechadespliegue=NULL"
[99f74d8]656                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[c4b75b1]657                                        cpt, tam, uso, idsfi, idsoi, ido, disk, par);
[d56675d]658                        } else {  // Actualizar porcentaje de uso.
659                                sprintf(sqlstr, "UPDATE ordenadores_particiones SET "
[696c5bb]660                                        " codpar=0x%s,"
[d56675d]661                                        " uso=%s"
662                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
[696c5bb]663                                        cpt, uso, ido, disk, par);
[d56675d]664                        }
[b56cbeb]665                        if (!db.Execute(sqlstr, tbl)) {
[d56675d]666                                db.GetErrorErrStr(msglog);
[b56cbeb]667                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
668                                       __func__, __LINE__, msglog);
[9dea2d6]669                                return false;
[b9eb98b]670                        }
671                }
672        }
[9a2dc88]673        lon += sprintf(tbPar + lon, "(0,0)");
[b9eb98b]674        // Eliminar particiones almacenadas que ya no existen
[9a2dc88]675        sprintf(sqlstr, "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)",
676                        ido, tbPar);
[b56cbeb]677        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]678                db.GetErrorErrStr(msglog);
[b56cbeb]679                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
680                       __func__, __LINE__, msglog);
[9dea2d6]681                return false;
[b9eb98b]682        }
[9dea2d6]683        return true;
[b9eb98b]684}
685// ________________________________________________________________________________________________________
686// Función: checkDato
687//
688//      Descripción:
689//               Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en
690//              cualquier caso el identificador del registro existenet o del insertado
691//      Parámetros:
692//              - db: Objeto base de datos (ya operativo)
693//              - tbl: Objeto tabla
694//              - dato: Dato
695//              - tabla: Nombre de la tabla
696//              - nomdato: Nombre del dato en la tabla
697//              - nomidentificador: Nombre del identificador en la tabla
698//      Devuelve:
699//              El identificador del registro existente o el del insertado
700//
701//      Especificaciones:
702//              En caso de producirse algún error se devuelve el valor 0
703// ________________________________________________________________________________________________________
704
[59fb4d5]705int checkDato(Database db, Table tbl, char *dato, const char *tabla,
706                     const char *nomdato, const char *nomidentificador)
707{
[b9eb98b]708        char msglog[LONSTD], sqlstr[LONSQL];
709        int identificador;
710
711        if (strlen(dato) == 0)
712                return (0); // EL dato no tiene valor
713        sprintf(sqlstr, "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador,
714                        tabla, nomdato, dato);
715
716        // Ejecuta consulta
[b56cbeb]717        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]718                db.GetErrorErrStr(msglog);
[b56cbeb]719                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
720                       __func__, __LINE__, msglog);
[b9eb98b]721                return (0);
722        }
723        if (tbl.ISEOF()) { //  Software NO existente
[bde1389]724                sprintf(sqlstr, "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato);
[b9eb98b]725                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
726                        db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]727                        og_info(msglog);
[b9eb98b]728                        return (0);
729                }
730                // Recupera el identificador del software
731                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
732                if (!db.Execute(sqlstr, tbl)) { // Error al leer
733                        db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]734                        og_info(msglog);
[b9eb98b]735                        return (0);
736                }
737                if (!tbl.ISEOF()) { // Si existe registro
738                        if (!tbl.Get("identificador", identificador)) {
739                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]740                                og_info(msglog);
[b9eb98b]741                                return (0);
742                        }
743                }
744        } else {
745                if (!tbl.Get(nomidentificador, identificador)) { // Toma dato
746                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]747                        og_info(msglog);
[b9eb98b]748                        return (0);
749                }
750        }
751        return (identificador);
752}
753// ________________________________________________________________________________________________________
754// Función: registraCliente
755//
756//      Descripción:
757//               Incluye al cliente en la tabla de sokets
758//      Parámetros:
759//              - iph: Dirección ip del cliente
760//      Devuelve:
[9dea2d6]761//              true: Si el proceso es correcto
762//              false: En caso de ocurrir algún error
[b9eb98b]763// ________________________________________________________________________________________________________
[59fb4d5]764bool registraCliente(char *iph)
765{
[b9eb98b]766        int idx;
767
768        if (!clienteExistente(iph, &idx)) { // Si no existe la IP ...
769                if (!hayHueco(&idx)) { // Busca hueco para el nuevo cliente
[9dea2d6]770                        return false; // No hay huecos
[b9eb98b]771                }
772        }
773        strcpy(tbsockets[idx].ip, iph); // Copia IP
774        strcpy(tbsockets[idx].estado, CLIENTE_INICIANDO); // Actualiza el estado del cliente
[9dea2d6]775        return true;
[b9eb98b]776}
777// ________________________________________________________________________________________________________
778// Función: AutoexecCliente
779//
780//      Descripción:
781//              Envía archivo de autoexec al cliente
782//      Parámetros:
783//              - socket_c: Socket del cliente que envió el mensaje
784//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
785//      Devuelve:
[9dea2d6]786//              true: Si el proceso es correcto
787//              false: En caso de ocurrir algún error
[b9eb98b]788// ________________________________________________________________________________________________________
[212280e]789static bool AutoexecCliente(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]790{
[212280e]791        int socket_c = og_client_socket(cli);
[b9eb98b]792        int lon;
[ecff994]793        char *iph, *exe;
[b9eb98b]794        FILE *fileexe;
795        char fileautoexec[LONPRM];
796        char parametros[LONGITUD_PARAMETROS];
[ecff994]797        struct og_dbi *dbi;
[b9eb98b]798
799        iph = copiaParametro("iph",ptrTrama); // Toma dirección IP del cliente
800        exe = copiaParametro("exe",ptrTrama); // Toma identificador del procedimiento inicial
801
802        sprintf(fileautoexec, "/tmp/Sautoexec-%s", iph);
[eb99080]803        liberaMemoria(iph);
[b9eb98b]804        fileexe = fopen(fileautoexec, "wb"); // Abre fichero de script
805        if (fileexe == NULL) {
[b56cbeb]806                syslog(LOG_ERR, "cannot create temporary file\n");
[9dea2d6]807                return false;
[b9eb98b]808        }
809
[ecff994]810        dbi = og_dbi_open(&dbi_config);
811        if (!dbi) {
812                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
813                       __func__, __LINE__);
[9dea2d6]814                return false;
[b9eb98b]815        }
816        initParametros(ptrTrama,0);
[ecff994]817        if (recorreProcedimientos(dbi, parametros, fileexe, exe)) {
[b9eb98b]818                lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r");
819                lon += sprintf(ptrTrama->parametros + lon, "nfl=%s\r", fileautoexec);
820                lon += sprintf(ptrTrama->parametros + lon, "res=1\r");
821        } else {
822                lon = sprintf(ptrTrama->parametros, "nfn=RESPUESTA_AutoexecCliente\r");
823                lon += sprintf(ptrTrama->parametros + lon, "res=0\r");
824        }
825
[ecff994]826        og_dbi_close(dbi);
[b9eb98b]827        fclose(fileexe);
828
[07d2b73]829        if (!mandaTrama(&socket_c, ptrTrama)) {
[eb99080]830                liberaMemoria(exe);
[b56cbeb]831                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
832                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
833                       strerror(errno));
[9dea2d6]834                return false;
[b9eb98b]835        }
[eb99080]836        liberaMemoria(exe);
[9dea2d6]837        return true;
[b9eb98b]838}
839// ________________________________________________________________________________________________________
840// Función: recorreProcedimientos
841//
842//      Descripción:
843//              Crea un archivo con el código de un procedimiento separando cada comando  por un salto de linea
844//      Parámetros:
845//              Database db,char* parametros,FILE* fileexe,char* idp
846//      Devuelve:
[9dea2d6]847//              true: Si el proceso es correcto
848//              false: En caso de ocurrir algún error
[b9eb98b]849// ________________________________________________________________________________________________________
[ecff994]850bool recorreProcedimientos(struct og_dbi *dbi, char *parametros, FILE *fileexe, char *idp)
[59fb4d5]851{
[ecff994]852        char idprocedimiento[LONPRM];
[b9eb98b]853        int procedimientoid, lsize;
[ecff994]854        const char *msglog, *param;
855        dbi_result result;
[b9eb98b]856
[ecff994]857        result = dbi_conn_queryf(dbi->conn,
[b9eb98b]858                        "SELECT procedimientoid,parametros FROM procedimientos_acciones"
859                                " WHERE idprocedimiento=%s ORDER BY orden", idp);
[ecff994]860        if (!result) {
861                dbi_conn_error(dbi->conn, &msglog);
[b56cbeb]862                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
863                       __func__, __LINE__, msglog);
[9dea2d6]864                return false;
[b9eb98b]865        }
[ecff994]866        while (dbi_result_next_row(result)) {
867                procedimientoid = dbi_result_get_uint(result, "procedimientoid");
[b9eb98b]868                if (procedimientoid > 0) { // Procedimiento recursivo
869                        sprintf(idprocedimiento, "%d", procedimientoid);
[ecff994]870                        if (!recorreProcedimientos(dbi, parametros, fileexe, idprocedimiento)) {
[9dea2d6]871                                return false;
[b9eb98b]872                        }
873                } else {
[ecff994]874                        param = dbi_result_get_string(result, "parametros");
875                        sprintf(parametros, "%s@", param);
[b9eb98b]876                        lsize = strlen(parametros);
877                        fwrite(parametros, 1, lsize, fileexe); // Escribe el código a ejecutar
878                }
879        }
[ecff994]880        dbi_result_free(result);
881
[9dea2d6]882        return true;
[b9eb98b]883}
884// ________________________________________________________________________________________________________
885// Función: ComandosPendientes
886//
887//      Descripción:
888//              Esta función busca en la base de datos,comandos pendientes de ejecutar por un  ordenador  concreto
889//      Parámetros:
890//              - socket_c: Socket del cliente que envió el mensaje
891//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
892//      Devuelve:
[9dea2d6]893//              true: Si el proceso es correcto
894//              false: En caso de ocurrir algún error
[b9eb98b]895// ________________________________________________________________________________________________________
[212280e]896static bool ComandosPendientes(TRAMA *ptrTrama, struct og_client *cli)
[eb99080]897{
[212280e]898        int socket_c = og_client_socket(cli);
[eb99080]899        char *ido,*iph,pids[LONPRM];
[b9eb98b]900        int ids, idx;
901
[eb99080]902        iph = copiaParametro("iph",ptrTrama); // Toma dirección IP
[b9eb98b]903        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
904
905        if (!clienteExistente(iph, &idx)) { // Busca índice del cliente
[eb99080]906                liberaMemoria(iph);
907                liberaMemoria(ido);
[b56cbeb]908                syslog(LOG_ERR, "client does not exist\n");
[9dea2d6]909                return false;
[b9eb98b]910        }
911        if (buscaComandos(ido, ptrTrama, &ids)) { // Existen comandos pendientes
912                ptrTrama->tipo = MSG_COMANDO;
913                sprintf(pids, "\rids=%d\r", ids);
914                strcat(ptrTrama->parametros, pids);
915                strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO);
916        } else {
917                initParametros(ptrTrama,0);
918                strcpy(ptrTrama->parametros, "nfn=NoComandosPtes\r");
919        }
[07d2b73]920        if (!mandaTrama(&socket_c, ptrTrama)) {
[eb99080]921                liberaMemoria(iph);
[b56cbeb]922                liberaMemoria(ido);
923                syslog(LOG_ERR, "failed to send response to %s:%hu reason=%s\n",
924                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
925                       strerror(errno));
[9dea2d6]926                return false;
[b9eb98b]927        }
[eb99080]928        liberaMemoria(iph);
929        liberaMemoria(ido);     
[9dea2d6]930        return true;
[b9eb98b]931}
932// ________________________________________________________________________________________________________
933// Función: buscaComandos
934//
935//      Descripción:
936//              Busca en la base de datos,comandos pendientes de ejecutar por el cliente
937//      Parámetros:
938//              - ido: Identificador del ordenador
939//              - cmd: Parámetros del comando (Salida)
[eb99080]940//              - ids: Identificador de la sesion(Salida)
[b9eb98b]941//      Devuelve:
[9dea2d6]942//              true: Si el proceso es correcto
943//              false: En caso de ocurrir algún error
[b9eb98b]944// ________________________________________________________________________________________________________
[f74067f]945bool buscaComandos(char *ido, TRAMA *ptrTrama, int *ids)
[b9eb98b]946{
[ad70969]947        const char *param, *msglog;
948        struct og_dbi *dbi;
949        dbi_result result;
950        unsigned int lonprm;
[b9eb98b]951
[ad70969]952        dbi = og_dbi_open(&dbi_config);
953        if (!dbi) {
954                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
955                       __func__, __LINE__);
956                goto err_dbi_open;
[b9eb98b]957        }
[ad70969]958        result = dbi_conn_queryf(dbi->conn,
959                        "SELECT sesion, parametros"\
960                        " FROM acciones WHERE idordenador=%s AND estado='%d'"\
961                        " ORDER BY idaccion", ido, ACCION_INICIADA);
962        if (!result) {
963                dbi_conn_error(dbi->conn, &msglog);
[b56cbeb]964                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
965                       __func__, __LINE__, msglog);
[ad70969]966                goto err_query_fail;
[b9eb98b]967        }
[ad70969]968        if (!dbi_result_next_row(result)) {
969                dbi_result_free(result);
970                og_dbi_close(dbi);
[9dea2d6]971                return false; // No hay comandos pendientes
[b9eb98b]972        }
[ad70969]973
974        *ids = dbi_result_get_uint(result, "sesion");
975        param = dbi_result_get_string(result, "parametros");
976        lonprm = strlen(param);
977
978        if(!initParametros(ptrTrama,lonprm + LONGITUD_PARAMETROS)){
979                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
980                goto err_init_params;
981        }
982        sprintf(ptrTrama->parametros, "%s", param);
983
984        dbi_result_free(result);
985        og_dbi_close(dbi);
986
[9dea2d6]987        return true; // Hay comandos pendientes, se toma el primero de la cola
[ad70969]988
989err_init_params:
990        dbi_result_free(result);
991err_query_fail:
992        og_dbi_close(dbi);
993err_dbi_open:
994        return false;
[b9eb98b]995}
996// ________________________________________________________________________________________________________
997// Función: DisponibilidadComandos
998//
999//      Descripción:
1000//              Esta función habilita a un cliente para recibir comandos desde la consola
1001//      Parámetros:
1002//              - socket_c: Socket del cliente que envió el mensaje
1003//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1004//      Devuelve:
[9dea2d6]1005//              true: Si el proceso es correcto
1006//              false: En caso de ocurrir algún error
[b9eb98b]1007// ________________________________________________________________________________________________________
[eb99080]1008//
[212280e]1009static bool DisponibilidadComandos(TRAMA *ptrTrama, struct og_client *cli)
[eb99080]1010{
1011        char *iph, *tpc;
[f09aca6]1012        int idx;
[b9eb98b]1013
[eb99080]1014        iph = copiaParametro("iph",ptrTrama); // Toma ip
[b9eb98b]1015        if (!clienteExistente(iph, &idx)) { // Busca índice del cliente
[eb99080]1016                liberaMemoria(iph);
[b56cbeb]1017                syslog(LOG_ERR, "client does not exist\n");
[9dea2d6]1018                return false;
[b9eb98b]1019        }
[eb99080]1020        tpc = copiaParametro("tpc",ptrTrama); // Tipo de cliente (Plataforma y S.O.)
[b9eb98b]1021        strcpy(tbsockets[idx].estado, tpc);
[f09aca6]1022        cli->keepalive_idx = idx;
[eb99080]1023        liberaMemoria(iph);
1024        liberaMemoria(tpc);             
[9dea2d6]1025        return true;
[b9eb98b]1026}
1027// ________________________________________________________________________________________________________
1028// Función: respuestaEstandar
1029//
1030//      Descripción:
1031//              Esta función actualiza la base de datos con el resultado de la ejecución de un comando con seguimiento
1032//      Parámetros:
1033//              - res: resultado de la ejecución del comando
1034//              - der: Descripción del error si hubiese habido
1035//              - iph: Dirección IP
[eb99080]1036//              - ids: identificador de la sesión
[b9eb98b]1037//              - ido: Identificador del ordenador que notifica
1038//              - db: Objeto base de datos (operativo)
1039//              - tbl: Objeto tabla
1040//      Devuelve:
[9dea2d6]1041//              true: Si el proceso es correcto
1042//              false: En caso de ocurrir algún error
[b9eb98b]1043// ________________________________________________________________________________________________________
[59fb4d5]1044static bool respuestaEstandar(TRAMA *ptrTrama, char *iph, char *ido, Database db,
1045                Table tbl)
1046{
[b9eb98b]1047        char msglog[LONSTD], sqlstr[LONSQL];
1048        char *res, *ids, *der;
1049        char fechafin[LONPRM];
1050        struct tm* st;
[eb99080]1051        int idaccion;
[b9eb98b]1052
[8082efd]1053        ids = copiaParametro("ids",ptrTrama);
1054        res = copiaParametro("res",ptrTrama);
[b9eb98b]1055
[8082efd]1056        if (ids == NULL) {
1057                if (atoi(res) == ACCION_FALLIDA) {
1058                        liberaMemoria(res);
1059                        return false;
1060                }
1061                liberaMemoria(res);
[9dea2d6]1062                return true;
[8082efd]1063        }
[9dea2d6]1064
[8082efd]1065        if (atoi(ids) == 0) {
[eb99080]1066                liberaMemoria(ids);
[8082efd]1067                if (atoi(res) == ACCION_FALLIDA) {
1068                        liberaMemoria(res);
1069                        return false;
1070                }
1071                liberaMemoria(res);
[9dea2d6]1072                return true;
[eb99080]1073        }
[b9eb98b]1074
1075        sprintf(sqlstr,
[eb99080]1076                        "SELECT * FROM acciones WHERE idordenador=%s"
1077                        " AND sesion=%s ORDER BY idaccion", ido,ids);
1078
1079        liberaMemoria(ids);
1080
[b56cbeb]1081        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1082                db.GetErrorErrStr(msglog);
[b56cbeb]1083                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1084                       __func__, __LINE__, msglog);
[9dea2d6]1085                return false;
[b9eb98b]1086        }
[b56cbeb]1087        if (tbl.ISEOF()) {
1088                syslog(LOG_ERR, "no actions available\n");
[9dea2d6]1089                return true;
[b9eb98b]1090        }
[eb99080]1091        if (!tbl.Get("idaccion", idaccion)) { // Toma identificador de la accion
1092                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1093                og_info(msglog);
[9dea2d6]1094                return false;
[eb99080]1095        }
[b9eb98b]1096        st = tomaHora();
1097        sprintf(fechafin, "%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1,
1098                        st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
1099
[eb99080]1100        der = copiaParametro("der",ptrTrama); // Toma descripción del error (si hubiera habido)
1101       
[28cc16b]1102        sprintf(sqlstr,
1103                        "UPDATE acciones"\
1104                        "   SET resultado='%s',estado='%d',fechahorafin='%s',descrinotificacion='%s'"\
[eb99080]1105                        " WHERE idordenador=%s AND idaccion=%d",
1106                        res, ACCION_FINALIZADA, fechafin, der, ido, idaccion);
1107                       
[b9eb98b]1108        if (!db.Execute(sqlstr, tbl)) { // Error al actualizar
[eb99080]1109                liberaMemoria(res);
1110                liberaMemoria(der);
[b9eb98b]1111                db.GetErrorErrStr(msglog);
[9764185]1112                og_info(msglog);
[9dea2d6]1113                return false;
[b9eb98b]1114        }
[eb99080]1115       
1116        liberaMemoria(der);
[b9eb98b]1117
[a245411]1118        if (atoi(res) == ACCION_FALLIDA) {
1119                liberaMemoria(res);
1120                return false;
1121        }
1122
[28cc16b]1123        liberaMemoria(res);
[9dea2d6]1124        return true;
[b9eb98b]1125}
[e979fd2]1126
1127static bool og_send_cmd(char *ips_array[], int ips_array_len,
1128                        const char *state, TRAMA *ptrTrama)
1129{
1130        int i, idx;
1131
1132        for (i = 0; i < ips_array_len; i++) {
1133                if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos
1134                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
1135
1136                        strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente
[3e8fcf0]1137                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[e979fd2]1138                                syslog(LOG_ERR, "failed to send response to %s:%s\n",
1139                                       ips_array[i], strerror(errno));
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        }
[8322fd6]1289        freeifaddrs(ifaddr);
[2baf362]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{
[429bd36]1341        unsigned int macaddr[OG_WOL_MACADDR_LEN];
[2baf362]1342        char HDaddress_bin[OG_WOL_MACADDR_LEN];
1343        struct sockaddr_in WakeUpCliente;
1344        struct wol_msg Trama_WakeUp;
1345        struct in_addr addr;
1346        bool ret;
1347        int i;
[b9eb98b]1348
1349        for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF)
1350                Trama_WakeUp.secuencia_FF[i] = 0xFF;
1351
[63a3d4d]1352        sscanf(mac, "%02x%02x%02x%02x%02x%02x",
[429bd36]1353               &macaddr[0], &macaddr[1], &macaddr[2],
1354               &macaddr[3], &macaddr[4], &macaddr[5]);
1355
1356        for (i = 0; i < 6; i++)
1357                HDaddress_bin[i] = (uint8_t)macaddr[i];
[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: RESPUESTA_Apagar
1436//
1437//      Descripción:
1438//              Respuesta del cliente al comando Apagar
1439//      Parámetros:
1440//              - socket_c: Socket del cliente que 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 RESPUESTA_Apagar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1447{
[b9eb98b]1448        char msglog[LONSTD];
1449        Database db;
1450        Table tbl;
1451        int i;
1452        char *iph, *ido;
1453
[b56cbeb]1454        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1455                db.GetErrorErrStr(msglog);
[b56cbeb]1456                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1457                       __func__, __LINE__, msglog);
[9dea2d6]1458                return false;
[b9eb98b]1459        }
1460
1461        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1462        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1463
1464        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1465                liberaMemoria(iph);
1466                liberaMemoria(ido);
[b56cbeb]1467                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1468                return false; // Error al registrar notificacion
[b9eb98b]1469        }
1470
1471        if (clienteExistente(iph, &i)) // Actualiza estado
1472                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1473       
1474        liberaMemoria(iph);
1475        liberaMemoria(ido);
1476       
[b9eb98b]1477        db.Close(); // Cierra conexión
[9dea2d6]1478        return true;
[b9eb98b]1479}
1480// ________________________________________________________________________________________________________
1481// Función: RESPUESTA_Reiniciar
1482//
1483//      Descripción:
1484//              Respuesta del cliente al comando Reiniciar
1485//      Parámetros:
1486//              - socket_c: Socket del cliente que envió el mensaje
1487//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1488//      Devuelve:
[9dea2d6]1489//              true: Si el proceso es correcto
1490//              false: En caso de ocurrir algún error
[b9eb98b]1491// ________________________________________________________________________________________________________
[212280e]1492static bool RESPUESTA_Reiniciar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1493{
[b9eb98b]1494        char msglog[LONSTD];
1495        Database db;
1496        Table tbl;
1497        int i;
1498        char *iph, *ido;
1499
[b56cbeb]1500        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1501                db.GetErrorErrStr(msglog);
[b56cbeb]1502                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1503                       __func__, __LINE__, msglog);
[9dea2d6]1504                return false;
[b9eb98b]1505        }
1506
1507        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1508        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1509
1510        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1511                liberaMemoria(iph);
1512                liberaMemoria(ido);
[b56cbeb]1513                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1514                return false; // Error al registrar notificacion
[b9eb98b]1515        }
1516
1517        if (clienteExistente(iph, &i)) // Actualiza estado
1518                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1519       
1520        liberaMemoria(iph);
1521        liberaMemoria(ido);
[b9eb98b]1522
1523        db.Close(); // Cierra conexión
[9dea2d6]1524        return true;
[b9eb98b]1525}
1526// ________________________________________________________________________________________________________
1527// Función: RESPUESTA_IniciarSesion
1528//
1529//      Descripción:
1530//              Respuesta del cliente al comando Iniciar Sesión
1531//      Parámetros:
1532//              - socket_c: Socket del cliente que envió el mensaje
1533//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1534//      Devuelve:
[9dea2d6]1535//              true: Si el proceso es correcto
1536//              false: En caso de ocurrir algún error
[b9eb98b]1537// ________________________________________________________________________________________________________
[212280e]1538static bool RESPUESTA_IniciarSesion(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1539{
[b9eb98b]1540        char msglog[LONSTD];
1541        Database db;
1542        Table tbl;
1543        int i;
1544        char *iph, *ido;
1545
[b56cbeb]1546        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1547                db.GetErrorErrStr(msglog);
[b56cbeb]1548                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1549                       __func__, __LINE__, msglog);
[9dea2d6]1550                return false;
[b9eb98b]1551        }
1552
1553        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1554        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1555
1556        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1557                liberaMemoria(iph);
1558                liberaMemoria(ido);
[b56cbeb]1559                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1560                return false; // Error al registrar notificacion
[b9eb98b]1561        }
1562
1563        if (clienteExistente(iph, &i)) // Actualiza estado
1564                strcpy(tbsockets[i].estado, CLIENTE_APAGADO);
[eb99080]1565               
1566        liberaMemoria(iph);
1567        liberaMemoria(ido);
1568               
[b9eb98b]1569        db.Close(); // Cierra conexión
[9dea2d6]1570        return true;
[b9eb98b]1571}
1572// ________________________________________________________________________________________________________
1573// Función: RESPUESTA_CrearImagen
1574//
1575//      Descripción:
1576//              Respuesta del cliente al comando CrearImagen
1577//      Parámetros:
1578//              - socket_c: Socket del cliente que envió el mensaje
1579//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1580//      Devuelve:
[9dea2d6]1581//              true: Si el proceso es correcto
1582//              false: En caso de ocurrir algún error
[b9eb98b]1583// ________________________________________________________________________________________________________
[212280e]1584static bool RESPUESTA_CrearImagen(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1585{
[b9eb98b]1586        char msglog[LONSTD];
1587        Database db;
1588        Table tbl;
[599c505]1589        char *iph, *dsk, *par, *cpt, *ipr, *ido;
[b9eb98b]1590        char *idi;
[f74067f]1591        bool res;
[b9eb98b]1592
[b56cbeb]1593        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1594                db.GetErrorErrStr(msglog);
[b56cbeb]1595                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1596                       __func__, __LINE__, msglog);
[9dea2d6]1597                return false;
[b9eb98b]1598        }
1599
1600        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1601        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1602
1603        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1604                liberaMemoria(iph);
1605                liberaMemoria(ido);
[b56cbeb]1606                syslog(LOG_ERR, "failed to register notification\n");
[9dea2d6]1607                return false; // Error al registrar notificacion
[b9eb98b]1608        }
1609
1610        // Acciones posteriores
1611        idi = copiaParametro("idi",ptrTrama);
[599c505]1612        dsk = copiaParametro("dsk",ptrTrama);
[b9eb98b]1613        par = copiaParametro("par",ptrTrama);
1614        cpt = copiaParametro("cpt",ptrTrama);
1615        ipr = copiaParametro("ipr",ptrTrama);
1616
[599c505]1617        res=actualizaCreacionImagen(db, tbl, idi, dsk, par, cpt, ipr, ido);
[eb99080]1618
1619        liberaMemoria(idi);
1620        liberaMemoria(par);
1621        liberaMemoria(cpt);
1622        liberaMemoria(ipr);
[b56cbeb]1623
[eb99080]1624        if(!res){
[b56cbeb]1625                syslog(LOG_ERR, "Problem processing update\n");
1626                db.Close();
[9dea2d6]1627                return false;
[b9eb98b]1628        }
1629
1630        db.Close(); // Cierra conexión
[9dea2d6]1631        return true;
[b9eb98b]1632}
1633// ________________________________________________________________________________________________________
1634// Función: actualizaCreacionImagen
1635//
1636//      Descripción:
1637//              Esta función actualiza la base de datos con el resultado de la creación de una imagen
1638//      Parámetros:
1639//              - db: Objeto base de datos (ya operativo)
1640//              - tbl: Objeto tabla
1641//              - idi: Identificador de la imagen
[599c505]1642//              - dsk: Disco de donde se creó
[b9eb98b]1643//              - par: Partición de donde se creó
1644//              - cpt: Código de partición
1645//              - ipr: Ip del repositorio
1646//              - ido: Identificador del ordenador modelo
1647//      Devuelve:
[9dea2d6]1648//              true: Si el proceso es correcto
1649//              false: En caso de ocurrir algún error
[b9eb98b]1650// ________________________________________________________________________________________________________
[59fb4d5]1651bool actualizaCreacionImagen(Database db, Table tbl, char *idi, char *dsk,
1652                             char *par, char *cpt, char *ipr, char *ido)
1653{
[b9eb98b]1654        char msglog[LONSTD], sqlstr[LONSQL];
[ed05cd5]1655        int idr,ifs;
[b9eb98b]1656
[80d1dfd]1657        /* Toma identificador del repositorio correspondiente al ordenador modelo */
[599c505]1658        snprintf(sqlstr, LONSQL,
1659                        "SELECT repositorios.idrepositorio"
[80d1dfd]1660                        "  FROM repositorios"
1661                        "  LEFT JOIN ordenadores USING (idrepositorio)"
1662                        " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido);
[b9eb98b]1663
[b56cbeb]1664        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1665                db.GetErrorErrStr(msglog);
[b56cbeb]1666                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1667                       __func__, __LINE__, msglog);
[9dea2d6]1668                return false;
[b9eb98b]1669        }
1670        if (!tbl.Get("idrepositorio", idr)) { // Toma dato
1671                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1672                og_info(msglog);
[9dea2d6]1673                return false;
[b9eb98b]1674        }
1675
1676        /* Toma identificador del perfilsoftware */
[599c505]1677        snprintf(sqlstr, LONSQL,
1678                        "SELECT idperfilsoft"
1679                        "  FROM ordenadores_particiones"
1680                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par);
[b9eb98b]1681
[b56cbeb]1682        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1683                db.GetErrorErrStr(msglog);
[b56cbeb]1684                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1685                       __func__, __LINE__, msglog);
[9dea2d6]1686                return false;
[b9eb98b]1687        }
1688        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
1689                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1690                og_info(msglog);
[9dea2d6]1691                return false;
[b9eb98b]1692        }
1693
1694        /* Actualizar los datos de la imagen */
[599c505]1695        snprintf(sqlstr, LONSQL,
[faee12e]1696                "UPDATE imagenes"
1697                "   SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
1698                "       idperfilsoft=%d, idrepositorio=%d,"
1699                "       fechacreacion=NOW(), revision=revision+1"
1700                " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi);
[b9eb98b]1701
[b56cbeb]1702        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]1703                db.GetErrorErrStr(msglog);
[b56cbeb]1704                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1705                       __func__, __LINE__, msglog);
[9dea2d6]1706                return false;
[b9eb98b]1707        }
[faee12e]1708        /* Actualizar los datos en el cliente */
1709        snprintf(sqlstr, LONSQL,
1710                "UPDATE ordenadores_particiones"
[ed05cd5]1711                "   SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
1712                "       fechadespliegue=NOW()"
[faee12e]1713                " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
[ed05cd5]1714                idi, idi, ido, dsk, par);
[b56cbeb]1715        if (!db.Execute(sqlstr, tbl)) {
[faee12e]1716                db.GetErrorErrStr(msglog);
[b56cbeb]1717                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1718                       __func__, __LINE__, msglog);
[9dea2d6]1719                return false;
[faee12e]1720        }
[9dea2d6]1721        return true;
[b9eb98b]1722}
1723// ________________________________________________________________________________________________________
[eb99080]1724// Función: CrearImagenBasica
1725//
1726//      Descripción:
1727//              Crea una imagen basica usando sincronización
1728//      Parámetros:
1729//              - socket_c: Socket de la consola al envió el mensaje
1730//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1731//      Devuelve:
[9dea2d6]1732//              true: Si el proceso es correcto
1733//              false: En caso de ocurrir algún error
[eb99080]1734// ________________________________________________________________________________________________________
[212280e]1735static bool CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1736{
[eb99080]1737        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1738                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1739                return false;
[eb99080]1740        }
[212280e]1741        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1742        return true;
[eb99080]1743}
1744// ________________________________________________________________________________________________________
1745// Función: RESPUESTA_CrearImagenBasica
1746//
1747//      Descripción:
1748//              Respuesta del cliente al comando CrearImagenBasica
1749//      Parámetros:
1750//              - socket_c: Socket del cliente que envió el mensaje
1751//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1752//      Devuelve:
[9dea2d6]1753//              true: Si el proceso es correcto
1754//              false: En caso de ocurrir algún error
[eb99080]1755// ________________________________________________________________________________________________________
[212280e]1756static bool RESPUESTA_CrearImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1757{
[212280e]1758        // La misma respuesta que la creación de imagen monolítica
1759        return RESPUESTA_CrearImagen(ptrTrama, cli);
[eb99080]1760}
1761// ________________________________________________________________________________________________________
1762// Función: CrearSoftIncremental
1763//
1764//      Descripción:
1765//              Crea una imagen incremental entre una partición de un disco y una imagen ya creada guardandola en el
1766//              mismo repositorio y en la misma carpeta donde está la imagen básica
1767//      Parámetros:
1768//              - socket_c: Socket de la consola al envió el mensaje
1769//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1770//      Devuelve:
[9dea2d6]1771//              true: Si el proceso es correcto
1772//              false: En caso de ocurrir algún error
[eb99080]1773// ________________________________________________________________________________________________________
[212280e]1774static bool CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1775{
[eb99080]1776        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1777                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1778                return false;
[eb99080]1779        }
[212280e]1780        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1781        return true;
[eb99080]1782}
1783// ________________________________________________________________________________________________________
1784// Función: RESPUESTA_CrearSoftIncremental
1785//
1786//      Descripción:
1787//              Respuesta del cliente al comando crearImagenDiferencial
1788//      Parámetros:
1789//              - socket_c: Socket del cliente que envió el mensaje
1790//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1791//      Devuelve:
[9dea2d6]1792//              true: Si el proceso es correcto
1793//              false: En caso de ocurrir algún error
[eb99080]1794// ________________________________________________________________________________________________________
[212280e]1795static bool RESPUESTA_CrearSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1796{
1797        Database db;
1798        Table tbl;
1799        char *iph,*par,*ido,*idf;
1800        int ifs;
1801        char msglog[LONSTD],sqlstr[LONSQL];
1802
[b56cbeb]1803        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[eb99080]1804                db.GetErrorErrStr(msglog);
[b56cbeb]1805                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1806                       __func__, __LINE__, msglog);
[9dea2d6]1807                return false;
[eb99080]1808        }
1809
1810        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1811        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1812
1813        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
1814                liberaMemoria(iph);
[b56cbeb]1815                liberaMemoria(ido);
1816                syslog(LOG_ERR, "failed to register notification\n");
1817                return false;
[eb99080]1818        }
1819
1820        par = copiaParametro("par",ptrTrama);
1821
1822        /* Toma identificador del perfilsoftware creado por el inventario de software */
1823        sprintf(sqlstr,"SELECT idperfilsoft FROM ordenadores_particiones WHERE idordenador=%s AND numpar=%s",ido,par);
1824       
1825        liberaMemoria(iph);
1826        liberaMemoria(ido);     
1827        liberaMemoria(par);     
[b56cbeb]1828
1829        if (!db.Execute(sqlstr, tbl)) {
[eb99080]1830                db.GetErrorErrStr(msglog);
[b56cbeb]1831                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1832                       __func__, __LINE__, msglog);
[9dea2d6]1833                return false;
[eb99080]1834        }
1835        if (!tbl.Get("idperfilsoft", ifs)) { // Toma dato
1836                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]1837                og_info(msglog);
[9dea2d6]1838                return false;
[eb99080]1839        }
1840
1841        /* Actualizar los datos de la imagen */
1842        idf = copiaParametro("idf",ptrTrama);
1843        sprintf(sqlstr,"UPDATE imagenes SET idperfilsoft=%d WHERE idimagen=%s",ifs,idf);
1844        liberaMemoria(idf);     
[b56cbeb]1845
1846        if (!db.Execute(sqlstr, tbl)) {
[eb99080]1847                db.GetErrorErrStr(msglog);
[b56cbeb]1848                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1849                       __func__, __LINE__, msglog);
[9dea2d6]1850                return false;
[eb99080]1851        }
1852        db.Close(); // Cierra conexión
[9dea2d6]1853        return true;
[eb99080]1854}
1855// ________________________________________________________________________________________________________
1856// Función: RestaurarImagenBasica
1857//
1858//      Descripción:
1859//              Restaura una imagen básica en una partición
1860//      Parámetros:
1861//              - socket_c: Socket de la consola al envió el mensaje
1862//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1863//      Devuelve:
[9dea2d6]1864//              true: Si el proceso es correcto
1865//              false: En caso de ocurrir algún error
[eb99080]1866// ________________________________________________________________________________________________________
[212280e]1867static bool RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1868{
[eb99080]1869        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1870                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1871                return false;
[eb99080]1872        }
[212280e]1873        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1874        return true;
[eb99080]1875}
1876// ________________________________________________________________________________________________________
1877// Función: RestaurarSoftIncremental
1878//
1879//      Descripción:
1880//              Restaura una imagen básica junto con software incremental en una partición
1881//      Parámetros:
1882//              - socket_c: Socket de la consola al envió el mensaje
1883//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1884//      Devuelve:
[9dea2d6]1885//              true: Si el proceso es correcto
1886//              false: En caso de ocurrir algún error
[eb99080]1887// ________________________________________________________________________________________________________
[212280e]1888static bool RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1889{
[eb99080]1890        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]1891                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]1892                return false;
[eb99080]1893        }
[212280e]1894        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]1895        return true;
[eb99080]1896}
1897// ________________________________________________________________________________________________________
[b9eb98b]1898// Función: RESPUESTA_RestaurarImagen
1899//
1900//      Descripción:
1901//              Respuesta del cliente al comando RestaurarImagen
1902//      Parámetros:
1903//              - socket_c: Socket del cliente que 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// ________________________________________________________________________________________________________
[eb99080]1909//
[212280e]1910static bool RESPUESTA_RestaurarImagen(TRAMA* ptrTrama, struct og_client *cli)
[eb99080]1911{
[b9eb98b]1912        char msglog[LONSTD];
1913        Database db;
1914        Table tbl;
[f74067f]1915        bool res;
[6ee505f]1916        char *iph, *ido, *idi, *dsk, *par, *ifs, *cfg;
[b9eb98b]1917
[b56cbeb]1918        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]1919                db.GetErrorErrStr(msglog);
[b56cbeb]1920                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
1921                       __func__, __LINE__, msglog);
[9dea2d6]1922                return false;
[b9eb98b]1923        }
1924
1925        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
1926        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
1927
1928        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]1929                liberaMemoria(iph);
[b56cbeb]1930                liberaMemoria(ido);
1931                syslog(LOG_ERR, "failed to register notification\n");
1932                return false;
[b9eb98b]1933        }
1934
1935        // Acciones posteriores
1936        idi = copiaParametro("idi",ptrTrama); // Toma identificador de la imagen
[599c505]1937        dsk = copiaParametro("dsk",ptrTrama); // Número de disco
[b9eb98b]1938        par = copiaParametro("par",ptrTrama); // Número de partición
1939        ifs = copiaParametro("ifs",ptrTrama); // Identificador del perfil software contenido
[6ee505f]1940        cfg = copiaParametro("cfg",ptrTrama); // Configuración de discos
1941        if(cfg){
1942                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
1943                liberaMemoria(cfg);     
1944        }
[599c505]1945        res=actualizaRestauracionImagen(db, tbl, idi, dsk, par, ido, ifs);
[eb99080]1946       
1947        liberaMemoria(iph);
[6ee505f]1948        liberaMemoria(ido);
[eb99080]1949        liberaMemoria(idi);
1950        liberaMemoria(par);
1951        liberaMemoria(ifs);
1952
1953        if(!res){
[b56cbeb]1954                syslog(LOG_ERR, "Problem after restoring image\n");
1955                db.Close();
[9dea2d6]1956                return false;
[b9eb98b]1957        }
1958
1959        db.Close(); // Cierra conexión
[9dea2d6]1960        return true;
[b9eb98b]1961}
1962// ________________________________________________________________________________________________________
[eb99080]1963//
1964// Función: RESPUESTA_RestaurarImagenBasica
1965//
1966//      Descripción:
1967//              Respuesta del cliente al comando RestaurarImagen
1968//      Parámetros:
1969//              - socket_c: Socket del cliente que envió el mensaje
1970//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1971//      Devuelve:
[9dea2d6]1972//              true: Si el proceso es correcto
1973//              false: En caso de ocurrir algún error
[eb99080]1974// ________________________________________________________________________________________________________
1975//
[212280e]1976static bool RESPUESTA_RestaurarImagenBasica(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1977{
[212280e]1978        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[eb99080]1979}
1980// ________________________________________________________________________________________________________
1981// Función: RESPUESTA_RestaurarSoftIncremental
1982//
1983//      Descripción:
1984//              Respuesta del cliente al comando RestaurarSoftIncremental
1985//      Parámetros:
1986//              - socket_c: Socket del cliente que envió el mensaje
1987//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
1988//      Devuelve:
[9dea2d6]1989//              true: Si el proceso es correcto
1990//              false: En caso de ocurrir algún error
[eb99080]1991// ________________________________________________________________________________________________________
[212280e]1992static bool RESPUESTA_RestaurarSoftIncremental(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]1993{
[212280e]1994        return RESPUESTA_RestaurarImagen(ptrTrama, cli);
[eb99080]1995}
1996// ________________________________________________________________________________________________________
[b9eb98b]1997// Función: actualizaRestauracionImagen
1998//
1999//      Descripción:
[eb99080]2000//              Esta función actualiza la base de datos con el resultado de la restauración de una imagen
[b9eb98b]2001//      Parámetros:
2002//              - db: Objeto base de datos (ya operativo)
2003//              - tbl: Objeto tabla
2004//              - idi: Identificador de la imagen
[599c505]2005//              - dsk: Disco de donde se restauró
[b9eb98b]2006//              - par: Partición de donde se restauró
2007//              - ido: Identificador del cliente donde se restauró
2008//              - ifs: Identificador del perfil software contenido      en la imagen
2009//      Devuelve:
[9dea2d6]2010//              true: Si el proceso es correcto
2011//              false: En caso de ocurrir algún error
[b9eb98b]2012// ________________________________________________________________________________________________________
[59fb4d5]2013bool actualizaRestauracionImagen(Database db, Table tbl, char *idi,
2014                                 char *dsk, char *par, char *ido, char *ifs)
2015{
[b9eb98b]2016        char msglog[LONSTD], sqlstr[LONSQL];
2017
2018        /* Actualizar los datos de la imagen */
[599c505]2019        snprintf(sqlstr, LONSQL,
2020                        "UPDATE ordenadores_particiones"
[60bbc25]2021                        "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
[9e3c02a]2022                        "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
2023                        "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
[c20cf9c]2024                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par);
[b9eb98b]2025
[b56cbeb]2026        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2027                db.GetErrorErrStr(msglog);
[b56cbeb]2028                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2029                       __func__, __LINE__, msglog);
[9dea2d6]2030                return false;
[b9eb98b]2031        }
[9dea2d6]2032        return true;
[b9eb98b]2033}
2034// ________________________________________________________________________________________________________
2035// Función: Configurar
2036//
2037//      Descripción:
2038//              Configura la tabla de particiones
2039//      Parámetros:
2040//              - socket_c: Socket de la consola al envió el mensaje
2041//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2042//      Devuelve:
[9dea2d6]2043//              true: Si el proceso es correcto
2044//              false: En caso de ocurrir algún error
[b9eb98b]2045// ________________________________________________________________________________________________________
[212280e]2046static bool Configurar(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2047{
[b9eb98b]2048        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]2049                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]2050                return false;
[b9eb98b]2051        }
[212280e]2052        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]2053        return true;
[b9eb98b]2054}
2055// ________________________________________________________________________________________________________
2056// Función: RESPUESTA_Configurar
2057//
2058//      Descripción:
2059//              Respuesta del cliente al comando Configurar
2060//      Parámetros:
2061//              - socket_c: Socket del cliente que envió el mensaje
2062//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2063//      Devuelve:
[9dea2d6]2064//              true: Si el proceso es correcto
2065//              false: En caso de ocurrir algún error
[b9eb98b]2066// ________________________________________________________________________________________________________
[eb99080]2067//
[212280e]2068static bool RESPUESTA_Configurar(TRAMA* ptrTrama, struct og_client *ci)
[eb99080]2069{
[b9eb98b]2070        char msglog[LONSTD];
2071        Database db;
2072        Table tbl;
[f74067f]2073        bool res;
[b9eb98b]2074        char *iph, *ido,*cfg;
2075
[b56cbeb]2076        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2077                db.GetErrorErrStr(msglog);
[b56cbeb]2078                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2079                       __func__, __LINE__, msglog);
[9dea2d6]2080                return false;
[b9eb98b]2081        }
2082
2083        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2084        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2085
2086        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2087                liberaMemoria(iph);
[b56cbeb]2088                liberaMemoria(ido);
2089                syslog(LOG_ERR, "failed to register notification\n");
2090                return false;
[b9eb98b]2091        }
2092
2093        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
[eb99080]2094        res=actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
2095       
2096        liberaMemoria(iph);
2097        liberaMemoria(ido);     
2098        liberaMemoria(cfg);     
[b56cbeb]2099
2100        if(!res){
2101                syslog(LOG_ERR, "Problem updating client configuration\n");
2102                return false;
[b9eb98b]2103        }
[b56cbeb]2104
[b9eb98b]2105        db.Close(); // Cierra conexión
[9dea2d6]2106        return true;
[b9eb98b]2107}
2108// ________________________________________________________________________________________________________
2109// Función: EjecutarScript
2110//
2111//      Descripción:
2112//              Ejecuta un script de código
2113//      Parámetros:
2114//              - socket_c: Socket de la consola al envió el mensaje
2115//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2116//      Devuelve:
[9dea2d6]2117//              true: Si el proceso es correcto
2118//              false: En caso de ocurrir algún error
[b9eb98b]2119// ________________________________________________________________________________________________________
[212280e]2120static bool EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2121{
[b9eb98b]2122        if (!enviaComando(ptrTrama, CLIENTE_OCUPADO)) {
[212280e]2123                respuestaConsola(og_client_socket(cli), ptrTrama, false);
[9dea2d6]2124                return false;
[b9eb98b]2125        }
[212280e]2126        respuestaConsola(og_client_socket(cli), ptrTrama, true);
[9dea2d6]2127        return true;
[b9eb98b]2128}
2129// ________________________________________________________________________________________________________
2130// Función: RESPUESTA_EjecutarScript
2131//
2132//      Descripción:
2133//              Respuesta del cliente al comando EjecutarScript
2134//      Parámetros:
2135//              - socket_c: Socket del cliente que envió el mensaje
2136//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2137//      Devuelve:
[9dea2d6]2138//              true: Si el proceso es correcto
2139//              false: En caso de ocurrir algún error
[b9eb98b]2140// ________________________________________________________________________________________________________
[212280e]2141static bool RESPUESTA_EjecutarScript(TRAMA* ptrTrama, struct og_client *cli)
[827bac5]2142{
[b9eb98b]2143        char msglog[LONSTD];
2144        Database db;
2145        Table tbl;
[827bac5]2146        char *iph, *ido,*cfg;
[b9eb98b]2147
[b56cbeb]2148        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2149                db.GetErrorErrStr(msglog);
[b56cbeb]2150                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2151                       __func__, __LINE__, msglog);
[9dea2d6]2152                return false;
[b9eb98b]2153        }
2154
2155        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2156        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2157
2158        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2159                liberaMemoria(iph);
[b56cbeb]2160                liberaMemoria(ido);
2161                syslog(LOG_ERR, "failed to register notification\n");
2162                return false;
[b9eb98b]2163        }
[eb99080]2164       
[827bac5]2165        cfg = copiaParametro("cfg",ptrTrama); // Toma configuración de particiones
[1c04180]2166        if(cfg){
[24df599]2167                actualizaConfiguracion(db, tbl, cfg, atoi(ido)); // Actualiza la configuración del ordenador
[1c04180]2168                liberaMemoria(cfg);     
2169        }
[827bac5]2170
[eb99080]2171        liberaMemoria(iph);
[827bac5]2172        liberaMemoria(ido);
[1c04180]2173
[eb99080]2174       
[b9eb98b]2175        db.Close(); // Cierra conexión
[9dea2d6]2176        return true;
[b9eb98b]2177}
2178// ________________________________________________________________________________________________________
2179// Función: RESPUESTA_InventarioHardware
2180//
2181//      Descripción:
2182//              Respuesta del cliente al comando InventarioHardware
2183//      Parámetros:
2184//              - socket_c: Socket del cliente que envió el mensaje
2185//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2186//      Devuelve:
[9dea2d6]2187//              true: Si el proceso es correcto
2188//              false: En caso de ocurrir algún error
[b9eb98b]2189// ________________________________________________________________________________________________________
[212280e]2190static bool RESPUESTA_InventarioHardware(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2191{
[b9eb98b]2192        char msglog[LONSTD];
2193        Database db;
2194        Table tbl;
[f74067f]2195        bool res;
[b9eb98b]2196        char *iph, *ido, *idc, *npc, *hrd, *buffer;
2197
[b56cbeb]2198        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2199                db.GetErrorErrStr(msglog);
[b56cbeb]2200                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2201                       __func__, __LINE__, msglog);
[9dea2d6]2202                return false;
[b9eb98b]2203        }
[eb99080]2204
[b9eb98b]2205        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip del cliente
2206        ido = copiaParametro("ido",ptrTrama); // Toma identificador del cliente
2207
2208        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2209                liberaMemoria(iph);
[b56cbeb]2210                liberaMemoria(ido);
2211                syslog(LOG_ERR, "failed to register notification\n");
2212                return false;
[b9eb98b]2213        }
2214        // Lee archivo de inventario enviado anteriormente
2215        hrd = copiaParametro("hrd",ptrTrama);
2216        buffer = rTrim(leeArchivo(hrd));
[eb99080]2217       
2218        npc = copiaParametro("npc",ptrTrama); 
2219        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro
2220       
2221        if (buffer) 
2222                res=actualizaHardware(db, tbl, buffer, ido, npc, idc);
2223       
2224        liberaMemoria(iph);
2225        liberaMemoria(ido);                     
2226        liberaMemoria(npc);                     
2227        liberaMemoria(idc);             
2228        liberaMemoria(buffer);         
2229       
2230        if(!res){
[b56cbeb]2231                syslog(LOG_ERR, "Problem updating client configuration\n");
[9dea2d6]2232                return false;
[b9eb98b]2233        }
[eb99080]2234               
[b9eb98b]2235        db.Close(); // Cierra conexión
[9dea2d6]2236        return true;
[b9eb98b]2237}
2238// ________________________________________________________________________________________________________
2239// Función: actualizaHardware
2240//
2241//              Descripción:
2242//                      Actualiza la base de datos con la configuracion hardware del cliente
2243//              Parámetros:
2244//                      - db: Objeto base de datos (ya operativo)
2245//                      - tbl: Objeto tabla
2246//                      - hrd: cadena con el inventario hardware
2247//                      - ido: Identificador del ordenador
2248//                      - npc: Nombre del ordenador
2249//                      - idc: Identificador del centro o Unidad organizativa
2250// ________________________________________________________________________________________________________
[eb99080]2251//
[59fb4d5]2252bool actualizaHardware(Database db, Table tbl, char *hrd, char *ido, char *npc,
2253                       char *idc)
[eb99080]2254{
[b9eb98b]2255        char msglog[LONSTD], sqlstr[LONSQL];
2256        int idtipohardware, idperfilhard;
2257        int lon, i, j, aux;
[7f46c45]2258        bool retval;
[eb99080]2259        char *whard;
[b9eb98b]2260        int tbidhardware[MAXHARDWARE];
[eb99080]2261        char *tbHardware[MAXHARDWARE],*dualHardware[2], descripcion[250], strInt[LONINT], *idhardwares;
[b9eb98b]2262
2263        /* Toma Centro (Unidad Organizativa) */
2264        sprintf(sqlstr, "SELECT * FROM ordenadores WHERE idordenador=%s", ido);
2265
[b56cbeb]2266        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2267                db.GetErrorErrStr(msglog);
[b56cbeb]2268                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2269                       __func__, __LINE__, msglog);
[9dea2d6]2270                return false;
[b9eb98b]2271        }
2272        if (!tbl.Get("idperfilhard", idperfilhard)) { // Toma dato
2273                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2274                og_info(msglog);
[9dea2d6]2275                return false;
[b9eb98b]2276        }
[eb99080]2277        whard=escaparCadena(hrd); // Codificar comillas simples
2278        if(!whard)
[9dea2d6]2279                return false;
[b9eb98b]2280        /* Recorre componentes hardware*/
[eb99080]2281        lon = splitCadena(tbHardware, whard, '\n');
[b9eb98b]2282        if (lon > MAXHARDWARE)
2283                lon = MAXHARDWARE; // Limita el número de componentes hardware
2284        /*
2285         for (i=0;i<lon;i++){
2286         sprintf(msglog,"Linea de inventario: %s",tbHardware[i]);
[9dea2d6]2287         RegistraLog(msglog,false);
[b9eb98b]2288         }
2289         */
2290        for (i = 0; i < lon; i++) {
2291                splitCadena(dualHardware, rTrim(tbHardware[i]), '=');
2292                //sprintf(msglog,"nemonico: %s",dualHardware[0]);
[9dea2d6]2293                //RegistraLog(msglog,false);
[b9eb98b]2294                //sprintf(msglog,"valor: %s",dualHardware[1]);
[9dea2d6]2295                //RegistraLog(msglog,false);
[b9eb98b]2296                sprintf(sqlstr, "SELECT idtipohardware,descripcion FROM tipohardwares "
2297                        " WHERE nemonico='%s'", dualHardware[0]);
[b56cbeb]2298                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2299                        db.GetErrorErrStr(msglog);
[b56cbeb]2300                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2301                               __func__, __LINE__, msglog);
[9dea2d6]2302                        return false;
[b9eb98b]2303                }
2304                if (tbl.ISEOF()) { //  Tipo de Hardware NO existente
2305                        sprintf(msglog, "%s: %s)", tbErrores[54], dualHardware[0]);
[9764185]2306                        og_info(msglog);
[9dea2d6]2307                        return false;
[b9eb98b]2308                } else { //  Tipo de Hardware Existe
2309                        if (!tbl.Get("idtipohardware", idtipohardware)) { // Toma dato
2310                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2311                                og_info(msglog);
[9dea2d6]2312                                return false;
[b9eb98b]2313                        }
2314                        if (!tbl.Get("descripcion", descripcion)) { // Toma dato
2315                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2316                                og_info(msglog);
[9dea2d6]2317                                return false;
[b9eb98b]2318                        }
2319
2320                        sprintf(sqlstr, "SELECT idhardware FROM hardwares "
2321                                " WHERE idtipohardware=%d AND descripcion='%s'",
2322                                        idtipohardware, dualHardware[1]);
2323
[b56cbeb]2324                        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2325                                db.GetErrorErrStr(msglog);
[b56cbeb]2326                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2327                                       __func__, __LINE__, msglog);
[9dea2d6]2328                                return false;
[b9eb98b]2329                        }
2330
2331                        if (tbl.ISEOF()) { //  Hardware NO existente
[bde1389]2332                                sprintf(sqlstr, "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) "
[b9eb98b]2333                                                        " VALUES(%d,'%s',%s,0)", idtipohardware,
2334                                                dualHardware[1], idc);
2335                                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2336                                        db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2337                                        og_info(msglog);
[9dea2d6]2338                                        return false;
[b9eb98b]2339                                }
2340                                // Recupera el identificador del hardware
2341                                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
[b56cbeb]2342                                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2343                                        db.GetErrorErrStr(msglog);
[b56cbeb]2344                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2345                                               __func__, __LINE__, msglog);
[9dea2d6]2346                                        return false;
[b9eb98b]2347                                }
2348                                if (!tbl.ISEOF()) { // Si existe registro
2349                                        if (!tbl.Get("identificador", tbidhardware[i])) {
2350                                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2351                                                og_info(msglog);
[9dea2d6]2352                                                return false;
[b9eb98b]2353                                        }
2354                                }
2355                        } else {
2356                                if (!tbl.Get("idhardware", tbidhardware[i])) { // Toma dato
2357                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2358                                        og_info(msglog);
[9dea2d6]2359                                        return false;
[b9eb98b]2360                                }
2361                        }
2362                }
2363        }
2364        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2365
2366        for (i = 0; i < lon - 1; i++) {
2367                for (j = i + 1; j < lon; j++) {
2368                        if (tbidhardware[i] > tbidhardware[j]) {
2369                                aux = tbidhardware[i];
2370                                tbidhardware[i] = tbidhardware[j];
2371                                tbidhardware[j] = aux;
2372                        }
2373                }
2374        }
2375        /* Crea cadena de identificadores de componentes hardware separados por coma */
2376        sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2377        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2378        idhardwares = reservaMemoria(sizeof(aux) * lon + lon);
2379        if (idhardwares == NULL) {
[b56cbeb]2380                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2381                return false;
[b9eb98b]2382        }
2383        aux = sprintf(idhardwares, "%d", tbidhardware[0]);
2384        for (i = 1; i < lon; i++)
2385                aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]);
2386
2387        if (!cuestionPerfilHardware(db, tbl, idc, ido, idperfilhard, idhardwares,
2388                        npc, tbidhardware, lon)) {
[b56cbeb]2389                syslog(LOG_ERR, "Problem updating client hardware\n");
[9dea2d6]2390                retval=false;
[b9eb98b]2391        }
[7f46c45]2392        else {
[9dea2d6]2393                retval=true;
[7f46c45]2394        }
[eb99080]2395        liberaMemoria(whard);
[7f46c45]2396        liberaMemoria(idhardwares);
2397        return (retval);
[b9eb98b]2398}
2399// ________________________________________________________________________________________________________
2400// Función: cuestionPerfilHardware
2401//
2402//              Descripción:
2403//                      Comprueba existencia de perfil hardware y actualización de éste para el ordenador
2404//              Parámetros:
2405//                      - db: Objeto base de datos (ya operativo)
2406//                      - tbl: Objeto tabla
2407//                      - idc: Identificador de la Unidad organizativa donde se encuentra el cliente
2408//                      - ido: Identificador del ordenador
2409//                      - tbidhardware: Identificador del tipo de hardware
2410//                      - con: Número de componentes detectados para configurar un el perfil hardware
2411//                      - npc: Nombre del cliente
2412// ________________________________________________________________________________________________________
[59fb4d5]2413bool cuestionPerfilHardware(Database db, Table tbl, char *idc, char *ido,
2414                int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware,
[b9eb98b]2415                int lon)
2416{
2417        char msglog[LONSTD], *sqlstr;
2418        int i;
2419        int nwidperfilhard;
2420
2421        sqlstr = reservaMemoria(strlen(idhardwares)+LONSQL); // Reserva para escribir sentencia SQL
2422        if (sqlstr == NULL) {
[b56cbeb]2423                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2424                return false;
[b9eb98b]2425        }
2426        // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados
2427        sprintf(sqlstr, "SELECT idperfilhard FROM"
2428                " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard,"
2429                "       group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )"
2430                "       ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares"
2431                " FROM  perfileshard_hardwares"
2432                " GROUP BY perfileshard_hardwares.idperfilhard) AS temp"
2433                " WHERE idhardwares LIKE '%s'", idhardwares);
[b56cbeb]2434
2435        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2436                db.GetErrorErrStr(msglog);
[b56cbeb]2437                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2438                       __func__, __LINE__, msglog);
[7f46c45]2439                liberaMemoria(sqlstr);
[9dea2d6]2440                return false;
[b9eb98b]2441        }
2442        if (tbl.ISEOF()) { // No existe un perfil hardware con esos componentes de componentes hardware, lo crea
2443                sprintf(sqlstr, "INSERT perfileshard  (descripcion,idcentro,grupoid)"
[bde1389]2444                                " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc);
[b9eb98b]2445                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2446                        db.GetErrorErrStr(msglog);
[9764185]2447                        og_info(msglog);
[7f46c45]2448                        liberaMemoria(sqlstr);
[9dea2d6]2449                        return false;
[b9eb98b]2450                }
2451                // Recupera el identificador del nuevo perfil hardware
2452                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2453                if (!db.Execute(sqlstr, tbl)) { // Error al leer
2454                        db.GetErrorErrStr(msglog);
[9764185]2455                        og_info(msglog);
[7f46c45]2456                        liberaMemoria(sqlstr);
[9dea2d6]2457                        return false;
[b9eb98b]2458                }
2459                if (!tbl.ISEOF()) { // Si existe registro
2460                        if (!tbl.Get("identificador", nwidperfilhard)) {
2461                                tbl.GetErrorErrStr(msglog);
[9764185]2462                                og_info(msglog);
[7f46c45]2463                                liberaMemoria(sqlstr);
[9dea2d6]2464                                return false;
[b9eb98b]2465                        }
2466                }
2467                // Crea la relación entre perfiles y componenetes hardware
2468                for (i = 0; i < lon; i++) {
[bde1389]2469                        sprintf(sqlstr, "INSERT perfileshard_hardwares  (idperfilhard,idhardware)"
[b9eb98b]2470                                                " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]);
2471                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2472                                db.GetErrorErrStr(msglog);
[9764185]2473                                og_info(msglog);
[7f46c45]2474                                liberaMemoria(sqlstr);
[9dea2d6]2475                                return false;
[b9eb98b]2476                        }
2477                }
2478        } else { // Existe un perfil con todos esos componentes
2479                if (!tbl.Get("idperfilhard", nwidperfilhard)) {
2480                        tbl.GetErrorErrStr(msglog);
[9764185]2481                        og_info(msglog);
[7f46c45]2482                        liberaMemoria(sqlstr);
[9dea2d6]2483                        return false;
[b9eb98b]2484                }
2485        }
2486        if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles
2487                // Actualiza el identificador del perfil hardware del ordenador
2488                sprintf(sqlstr, "UPDATE ordenadores SET idperfilhard=%d"
2489                        " WHERE idordenador=%s", nwidperfilhard, ido);
2490                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2491                        db.GetErrorErrStr(msglog);
[9764185]2492                        og_info(msglog);
[7f46c45]2493                        liberaMemoria(sqlstr);
[9dea2d6]2494                        return false;
[b9eb98b]2495                }
2496        }
2497        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
2498        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN "
2499                " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN"
2500                " (SELECT DISTINCT idperfilhard from ordenadores))");
2501        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2502                db.GetErrorErrStr(msglog);
[9764185]2503                og_info(msglog);
[7f46c45]2504                liberaMemoria(sqlstr);
[9dea2d6]2505                return false;
[b9eb98b]2506        }
2507
2508        /* Eliminar Perfiles hardware que quedan húerfanos */
2509        sprintf(sqlstr, "DELETE FROM perfileshard WHERE idperfilhard NOT IN"
[7f46c45]2510                        " (SELECT DISTINCT idperfilhard FROM ordenadores)");
[b9eb98b]2511        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2512                db.GetErrorErrStr(msglog);
[9764185]2513                og_info(msglog);
[7f46c45]2514                liberaMemoria(sqlstr);
[9dea2d6]2515                return false;
[b9eb98b]2516        }
2517        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
[7f46c45]2518        sprintf(sqlstr, "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN"
2519                        " (SELECT idperfilhard FROM perfileshard)");
[b9eb98b]2520        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2521                db.GetErrorErrStr(msglog);
[9764185]2522                og_info(msglog);
[7f46c45]2523                liberaMemoria(sqlstr);
[9dea2d6]2524                return false;
[b9eb98b]2525        }
[7f46c45]2526        liberaMemoria(sqlstr);
[9dea2d6]2527        return true;
[b9eb98b]2528}
2529// ________________________________________________________________________________________________________
2530// Función: RESPUESTA_InventarioSoftware
2531//
2532//      Descripción:
2533//              Respuesta del cliente al comando InventarioSoftware
2534//      Parámetros:
2535//              - socket_c: Socket del cliente que envió el mensaje
2536//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2537//      Devuelve:
[9dea2d6]2538//              true: Si el proceso es correcto
2539//              false: En caso de ocurrir algún error
[b9eb98b]2540// ________________________________________________________________________________________________________
[212280e]2541static bool RESPUESTA_InventarioSoftware(TRAMA* ptrTrama, struct og_client *cli)
[59fb4d5]2542{
[b9eb98b]2543        char msglog[LONSTD];
2544        Database db;
2545        Table tbl;
[f74067f]2546        bool res;
[b9eb98b]2547        char *iph, *ido, *npc, *idc, *par, *sft, *buffer;
2548
[b56cbeb]2549        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2550                db.GetErrorErrStr(msglog);
[b56cbeb]2551                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2552                       __func__, __LINE__, msglog);
[9dea2d6]2553                return false;
[b9eb98b]2554        }
2555
2556        iph = copiaParametro("iph",ptrTrama); // Toma dirección ip
2557        ido = copiaParametro("ido",ptrTrama); // Toma identificador del ordenador
2558
2559        if (!respuestaEstandar(ptrTrama, iph, ido, db, tbl)) {
[eb99080]2560                liberaMemoria(iph);
[b56cbeb]2561                liberaMemoria(ido);
2562                syslog(LOG_ERR, "failed to register notification\n");
2563                return false;
[b9eb98b]2564        }
[b56cbeb]2565
[eb99080]2566        npc = copiaParametro("npc",ptrTrama); 
2567        idc = copiaParametro("idc",ptrTrama); // Toma identificador del Centro 
[b9eb98b]2568        par = copiaParametro("par",ptrTrama);
2569        sft = copiaParametro("sft",ptrTrama);
2570
2571        buffer = rTrim(leeArchivo(sft));
[eb99080]2572        if (buffer)
2573                res=actualizaSoftware(db, tbl, buffer, par, ido, npc, idc);
2574
2575        liberaMemoria(iph);
2576        liberaMemoria(ido);     
2577        liberaMemoria(npc);     
2578        liberaMemoria(idc);     
2579        liberaMemoria(par);     
2580        liberaMemoria(sft);     
2581
2582        if(!res){
[b56cbeb]2583                syslog(LOG_ERR, "cannot update software\n");
[9dea2d6]2584                return false;
[b56cbeb]2585        }
2586
[b9eb98b]2587        db.Close(); // Cierra conexión
[9dea2d6]2588        return true;
[b9eb98b]2589}
2590// ________________________________________________________________________________________________________
2591// Función: actualizaSoftware
2592//
2593//      Descripción:
2594//              Actualiza la base de datos con la configuración software del cliente
2595//      Parámetros:
2596//              - db: Objeto base de datos (ya operativo)
2597//              - tbl: Objeto tabla
2598//              - sft: cadena con el inventario software
2599//              - par: Número de la partición
2600//              - ido: Identificador del ordenador del cliente en la tabla
2601//              - npc: Nombre del ordenador
2602//              - idc: Identificador del centro o Unidad organizativa
2603//      Devuelve:
[9dea2d6]2604//              true: Si el proceso es correcto
2605//              false: En caso de ocurrir algún error
[8712fd9]2606//
2607//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
[b9eb98b]2608// ________________________________________________________________________________________________________
[59fb4d5]2609bool actualizaSoftware(Database db, Table tbl, char *sft, char *par,char *ido,
2610                       char *npc, char *idc)
[eb99080]2611{
[8712fd9]2612        int i, j, lon, aux, idperfilsoft, idnombreso;
[7f46c45]2613        bool retval;
[eb99080]2614        char *wsft;
[b9eb98b]2615        int tbidsoftware[MAXSOFTWARE];
[eb99080]2616        char *tbSoftware[MAXSOFTWARE],msglog[LONSTD], sqlstr[LONSQL], strInt[LONINT], *idsoftwares;
[b9eb98b]2617
2618        /* Toma Centro (Unidad Organizativa) y perfil software */
2619        sprintf(sqlstr, "SELECT idperfilsoft,numpar"
2620                " FROM ordenadores_particiones"
2621                " WHERE idordenador=%s", ido);
2622
[b56cbeb]2623        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2624                db.GetErrorErrStr(msglog);
[b56cbeb]2625                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2626                       __func__, __LINE__, msglog);
[9dea2d6]2627                return false;
[b9eb98b]2628        }
2629        idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software
2630        while (!tbl.ISEOF()) { // Recorre particiones
2631                if (!tbl.Get("numpar", aux)) {
2632                        tbl.GetErrorErrStr(msglog);
[9764185]2633                        og_info(msglog);
[9dea2d6]2634                        return false;
[b9eb98b]2635                }
2636                if (aux == atoi(par)) { // Se encuentra la partición
2637                        if (!tbl.Get("idperfilsoft", idperfilsoft)) {
2638                                tbl.GetErrorErrStr(msglog);
[9764185]2639                                og_info(msglog);
[9dea2d6]2640                                return false;
[b9eb98b]2641                        }
2642                        break;
2643                }
2644                tbl.MoveNext();
2645        }
[eb99080]2646        wsft=escaparCadena(sft); // Codificar comillas simples
2647        if(!wsft)
[9dea2d6]2648                return false;
[b9eb98b]2649
2650        /* Recorre componentes software*/
[eb99080]2651        lon = splitCadena(tbSoftware, wsft, '\n');
2652
[b9eb98b]2653        if (lon == 0)
[9dea2d6]2654                return true; // No hay lineas que procesar
[b9eb98b]2655        if (lon > MAXSOFTWARE)
2656                lon = MAXSOFTWARE; // Limita el número de componentes software
2657
2658        for (i = 0; i < lon; i++) {
[8712fd9]2659                // Primera línea es el sistema operativo: se obtiene identificador
2660                if (i == 0) {
2661                        idnombreso = checkDato(db, tbl, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso");
2662                        continue;
2663                }
2664
[b9eb98b]2665                sprintf(sqlstr,
2666                                "SELECT idsoftware FROM softwares WHERE descripcion ='%s'",
2667                                rTrim(tbSoftware[i]));
2668
[b56cbeb]2669                if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2670                        db.GetErrorErrStr(msglog);
[b56cbeb]2671                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2672                               __func__, __LINE__, msglog);
[9dea2d6]2673                        return false;
[b9eb98b]2674                }
2675
2676                if (tbl.ISEOF()) { //  Software NO existente
[bde1389]2677                        sprintf(sqlstr, "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)"
[b9eb98b]2678                                                " VALUES(2,'%s',%s,0)", tbSoftware[i], idc);
2679
2680                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2681                                db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2682                                og_info(msglog);
[9dea2d6]2683                                return false;
[b9eb98b]2684                        }
2685                        // Recupera el identificador del software
2686                        sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2687                        if (!db.Execute(sqlstr, tbl)) { // Error al leer
2688                                db.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2689                                og_info(msglog);
[9dea2d6]2690                                return false;
[b9eb98b]2691                        }
2692                        if (!tbl.ISEOF()) { // Si existe registro
2693                                if (!tbl.Get("identificador", tbidsoftware[i])) {
2694                                        tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2695                                        og_info(msglog);
[9dea2d6]2696                                        return false;
[b9eb98b]2697                                }
2698                        }
2699                } else {
2700                        if (!tbl.Get("idsoftware", tbidsoftware[i])) { // Toma dato
2701                                tbl.GetErrorErrStr(msglog); // Error al acceder al registro
[9764185]2702                                og_info(msglog);
[9dea2d6]2703                                return false;
[b9eb98b]2704                        }
2705                }
2706        }
2707
2708        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
2709
2710        for (i = 0; i < lon - 1; i++) {
2711                for (j = i + 1; j < lon; j++) {
2712                        if (tbidsoftware[i] > tbidsoftware[j]) {
2713                                aux = tbidsoftware[i];
2714                                tbidsoftware[i] = tbidsoftware[j];
2715                                tbidsoftware[j] = aux;
2716                        }
2717                }
2718        }
2719        /* Crea cadena de identificadores de componentes software separados por coma */
2720        sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
2721        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
2722        idsoftwares = reservaMemoria((sizeof(aux)+1) * lon + lon);
2723        if (idsoftwares == NULL) {
[b56cbeb]2724                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2725                return false;
[b9eb98b]2726        }
2727        aux = sprintf(idsoftwares, "%d", tbidsoftware[0]);
2728        for (i = 1; i < lon; i++)
2729                aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]);
2730
2731        // Comprueba existencia de perfil software y actualización de éste para el ordenador
[8712fd9]2732        if (!cuestionPerfilSoftware(db, tbl, idc, ido, idperfilsoft, idnombreso, idsoftwares, 
[b9eb98b]2733                        npc, par, tbidsoftware, lon)) {
[b56cbeb]2734                syslog(LOG_ERR, "cannot update software\n");
[9764185]2735                og_info(msglog);
[9dea2d6]2736                retval=false;
[b9eb98b]2737        }
[7f46c45]2738        else {
[9dea2d6]2739                retval=true;
[7f46c45]2740        }
[eb99080]2741        liberaMemoria(wsft);
[7f46c45]2742        liberaMemoria(idsoftwares);
2743        return (retval);
[b9eb98b]2744}
2745// ________________________________________________________________________________________________________
2746// Función: CuestionPerfilSoftware
2747//
2748//      Parámetros:
2749//              - db: Objeto base de datos (ya operativo)
2750//              - tbl: Objeto tabla
2751//              - idcentro: Identificador del centro en la tabla
2752//              - ido: Identificador del ordenador del cliente en la tabla
[8712fd9]2753//              - idnombreso: Identificador del sistema operativo
[b9eb98b]2754//              - idsoftwares: Cadena con los identificadores de componentes software separados por comas
2755//              - npc: Nombre del ordenador del cliente
2756//              - particion: Número de la partición
2757//              - tbidsoftware: Array con los identificadores de componentes software
2758//              - lon: Número de componentes
2759//      Devuelve:
[9dea2d6]2760//              true: Si el proceso es correcto
2761//              false: En caso de ocurrir algún error
[8712fd9]2762//
2763//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
2764//_________________________________________________________________________________________________________
[59fb4d5]2765bool cuestionPerfilSoftware(Database db, Table tbl, char *idc, char *ido,
2766                            int idperfilsoftware, int idnombreso,
2767                            char *idsoftwares, char *npc, char *par,
2768                            int *tbidsoftware, int lon)
2769{
[b9eb98b]2770        char *sqlstr, msglog[LONSTD];
2771        int i, nwidperfilsoft;
2772
2773        sqlstr = reservaMemoria(strlen(idsoftwares)+LONSQL); // Reserva para escribir sentencia SQL
2774        if (sqlstr == NULL) {
[b56cbeb]2775                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
[9dea2d6]2776                return false;
[b9eb98b]2777        }
2778        // Busca perfil soft del ordenador que contenga todos los componentes software encontrados
2779        sprintf(sqlstr, "SELECT idperfilsoft FROM"
2780                " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft,"
2781                "       group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )"
2782                "       ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares"
2783                " FROM  perfilessoft_softwares"
2784                " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp"
2785                " WHERE idsoftwares LIKE '%s'", idsoftwares);
[b56cbeb]2786
2787        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2788                db.GetErrorErrStr(msglog);
[b56cbeb]2789                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2790                       __func__, __LINE__, msglog);
[7f46c45]2791                liberaMemoria(sqlstr);
[9dea2d6]2792                return false;
[b9eb98b]2793        }
2794        if (tbl.ISEOF()) { // No existe un perfil software con esos componentes de componentes software, lo crea
[8712fd9]2795                sprintf(sqlstr, "INSERT perfilessoft  (descripcion, idcentro, grupoid, idnombreso)"
2796                                " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso);
[b9eb98b]2797                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2798                        db.GetErrorErrStr(msglog);
[9764185]2799                        og_info(msglog);
[9dea2d6]2800                        return false;
[b9eb98b]2801                }
2802                // Recupera el identificador del nuevo perfil software
2803                sprintf(sqlstr, "SELECT LAST_INSERT_ID() as identificador");
2804                if (!db.Execute(sqlstr, tbl)) { // Error al leer
2805                        tbl.GetErrorErrStr(msglog);
[9764185]2806                        og_info(msglog);
[7f46c45]2807                        liberaMemoria(sqlstr);
[9dea2d6]2808                        return false;
[b9eb98b]2809                }
2810                if (!tbl.ISEOF()) { // Si existe registro
2811                        if (!tbl.Get("identificador", nwidperfilsoft)) {
2812                                tbl.GetErrorErrStr(msglog);
[9764185]2813                                og_info(msglog);
[7f46c45]2814                                liberaMemoria(sqlstr);
[9dea2d6]2815                                return false;
[b9eb98b]2816                        }
2817                }
2818                // Crea la relación entre perfiles y componenetes software
2819                for (i = 0; i < lon; i++) {
[7f46c45]2820                        sprintf(sqlstr, "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)"
[b9eb98b]2821                                                " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]);
2822                        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2823                                db.GetErrorErrStr(msglog);
[9764185]2824                                og_info(msglog);
[7f46c45]2825                                liberaMemoria(sqlstr);
[9dea2d6]2826                                return false;
[b9eb98b]2827                        }
2828                }
2829        } else { // Existe un perfil con todos esos componentes
2830                if (!tbl.Get("idperfilsoft", nwidperfilsoft)) {
2831                        tbl.GetErrorErrStr(msglog);
[9764185]2832                        og_info(msglog);
[7f46c45]2833                        liberaMemoria(sqlstr);
[9dea2d6]2834                        return false;
[b9eb98b]2835                }
2836        }
2837
2838        if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
2839                // Actualiza el identificador del perfil software del ordenador
[7f46c45]2840                sprintf(sqlstr, "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
2841                                " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
[b9eb98b]2842                if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2843                        db.GetErrorErrStr(msglog);
[9764185]2844                        og_info(msglog);
[7f46c45]2845                        liberaMemoria(sqlstr);
[9dea2d6]2846                        return false;
[b9eb98b]2847                }
2848        }
2849
2850        /* DEPURACIÓN DE PERFILES SOFTWARE */
2851
2852         /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
2853        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\
2854                " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\
2855                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\
2856                " (SELECT DISTINCT idperfilsoft from imagenes))");
2857        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2858                db.GetErrorErrStr(msglog);
[9764185]2859                og_info(msglog);
[7f46c45]2860                liberaMemoria(sqlstr);
[9dea2d6]2861                return false;
[b9eb98b]2862        }
2863        /* Eliminar Perfiles software que quedan húerfanos */
2864        sprintf(sqlstr, "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN"
2865                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\
2866                " AND  idperfilsoft NOT IN"\
2867                " (SELECT DISTINCT idperfilsoft from imagenes)");
2868        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2869                db.GetErrorErrStr(msglog);
[9764185]2870                og_info(msglog);
[7f46c45]2871                liberaMemoria(sqlstr);
[9dea2d6]2872                return false;
[b9eb98b]2873        }
2874        /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
[7f46c45]2875        sprintf(sqlstr, "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN"
2876                        " (SELECT idperfilsoft from perfilessoft)");
[b9eb98b]2877        if (!db.Execute(sqlstr, tbl)) { // Error al insertar
2878                db.GetErrorErrStr(msglog);
[9764185]2879                og_info(msglog);
[7f46c45]2880                liberaMemoria(sqlstr);
[9dea2d6]2881                return false;
[b9eb98b]2882        }
[7f46c45]2883        liberaMemoria(sqlstr);
[9dea2d6]2884        return true;
[b9eb98b]2885}
2886// ________________________________________________________________________________________________________
2887// Función: enviaArchivo
2888//
2889//      Descripción:
2890//              Envia un archivo por la red, por bloques
2891//      Parámetros:
2892//              - socket_c: Socket del cliente que envió el mensaje
2893//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2894//      Devuelve:
[9dea2d6]2895//              true: Si el proceso es correcto
2896//              false: En caso de ocurrir algún error
[b9eb98b]2897// ________________________________________________________________________________________________________
[212280e]2898static bool enviaArchivo(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]2899{
[212280e]2900        int socket_c = og_client_socket(cli);
[b9eb98b]2901        char *nfl;
2902
2903        // Toma parámetros
2904        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
[07d2b73]2905        if (!sendArchivo(&socket_c, nfl)) {
[eb99080]2906                liberaMemoria(nfl);
[b56cbeb]2907                syslog(LOG_ERR, "Problem sending file\n");
[9dea2d6]2908                return false;
[b9eb98b]2909        }
[eb99080]2910        liberaMemoria(nfl);
[9dea2d6]2911        return true;
[b9eb98b]2912}
2913// ________________________________________________________________________________________________________
2914// Función: enviaArchivo
2915//
2916//      Descripción:
2917//              Envia un archivo por la red, por bloques
2918//      Parámetros:
2919//              - socket_c: Socket del cliente que envió el mensaje
2920//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2921//      Devuelve:
[9dea2d6]2922//              true: Si el proceso es correcto
2923//              false: En caso de ocurrir algún error
[b9eb98b]2924// ________________________________________________________________________________________________________
[212280e]2925static bool recibeArchivo(TRAMA *ptrTrama, struct og_client *cli)
[59fb4d5]2926{
[212280e]2927        int socket_c = og_client_socket(cli);
[b9eb98b]2928        char *nfl;
2929
2930        // Toma parámetros
2931        nfl = copiaParametro("nfl",ptrTrama); // Toma nombre completo del archivo
2932        ptrTrama->tipo = MSG_NOTIFICACION;
[07d2b73]2933        enviaFlag(&socket_c, ptrTrama);
2934        if (!recArchivo(&socket_c, nfl)) {
[eb99080]2935                liberaMemoria(nfl);
[b56cbeb]2936                syslog(LOG_ERR, "Problem receiving file\n");
[9dea2d6]2937                return false;
[b9eb98b]2938        }
[eb99080]2939        liberaMemoria(nfl);
[9dea2d6]2940        return true;
[b9eb98b]2941}
2942// ________________________________________________________________________________________________________
2943// Función: envioProgramacion
2944//
2945//      Descripción:
2946//              Envia un comando de actualización a todos los ordenadores que han sido programados con
2947//              alguna acción para que entren en el bucle de comandos pendientes y las ejecuten
2948//      Parámetros:
2949//              - socket_c: Socket del cliente que envió el mensaje
2950//              - ptrTrama: Trama recibida por el servidor con el contenido y los parámetros
2951//      Devuelve:
[9dea2d6]2952//              true: Si el proceso es correcto
2953//              false: En caso de ocurrir algún error
[b9eb98b]2954// ________________________________________________________________________________________________________
[212280e]2955static bool envioProgramacion(TRAMA *ptrTrama, struct og_client *cli)
[b9eb98b]2956{
[507c75c]2957        char *ptrIP[MAXIMOS_CLIENTES],*ptrMacs[MAXIMOS_CLIENTES];
[b9eb98b]2958        char sqlstr[LONSQL], msglog[LONSTD];
[24df599]2959        char *idp,iph[LONIP],mac[LONMAC];
[b9eb98b]2960        Database db;
2961        Table tbl;
[507c75c]2962        int idx,idcomando,lon;
[b9eb98b]2963
[b56cbeb]2964        if (!db.Open(usuario, pasguor, datasource, catalog)) {
[b9eb98b]2965                db.GetErrorErrStr(msglog);
[b56cbeb]2966                syslog(LOG_ERR, "cannot open connection database (%s:%d) %s\n",
2967                       __func__, __LINE__, msglog);
[9dea2d6]2968                return false;
[b9eb98b]2969        }
2970
[eb99080]2971        idp = copiaParametro("idp",ptrTrama); // Toma identificador de la programación de la tabla acciones
[b9eb98b]2972
2973        sprintf(sqlstr, "SELECT ordenadores.ip,ordenadores.mac,acciones.idcomando FROM acciones "\
2974                        " INNER JOIN ordenadores ON ordenadores.ip=acciones.ip"\
2975                        " WHERE acciones.idprogramacion=%s",idp);
[eb99080]2976       
2977        liberaMemoria(idp);
[b56cbeb]2978
2979        if (!db.Execute(sqlstr, tbl)) {
[b9eb98b]2980                db.GetErrorErrStr(msglog);
[b56cbeb]2981                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2982                       __func__, __LINE__, msglog);
[9dea2d6]2983                return false;
[b9eb98b]2984        }
[fcc271f]2985        db.Close();
[b9eb98b]2986        if(tbl.ISEOF())
[9dea2d6]2987                return true; // No existen registros
[b9eb98b]2988
2989        /* Prepara la trama de actualizacion */
2990
2991        initParametros(ptrTrama,0);
2992        ptrTrama->tipo=MSG_COMANDO;
2993        sprintf(ptrTrama->parametros, "nfn=Actualizar\r");
2994
2995        while (!tbl.ISEOF()) { // Recorre particiones
2996                if (!tbl.Get("ip", iph)) {
2997                        tbl.GetErrorErrStr(msglog);
[a1d02f4]2998                        syslog(LOG_ERR, "cannot find ip column in table: %s\n",
2999                               msglog);
[9dea2d6]3000                        return false;
[b9eb98b]3001                }
3002                if (!tbl.Get("idcomando", idcomando)) {
3003                        tbl.GetErrorErrStr(msglog);
[a1d02f4]3004                        syslog(LOG_ERR, "cannot find idcomando column in table: %s\n",
3005                               msglog);
[9dea2d6]3006                        return false;
[b9eb98b]3007                }
3008                if(idcomando==1){ // Arrancar
3009                        if (!tbl.Get("mac", mac)) {
3010                                tbl.GetErrorErrStr(msglog);
[a1d02f4]3011                                syslog(LOG_ERR, "cannot find mac column in table: %s\n",
3012                                       msglog);
[9dea2d6]3013                                return false;
[b9eb98b]3014                        }
[599c505]3015
[507c75c]3016                        lon = splitCadena(ptrIP, iph, ';');
3017                        lon = splitCadena(ptrMacs, mac, ';');
3018
[ad4ae52]3019                        // Se manda por broadcast y por unicast
[507c75c]3020                        if (!Levanta(ptrIP, ptrMacs, lon, (char*)"1"))
[9dea2d6]3021                                return false;
[ad4ae52]3022
[507c75c]3023                        if (!Levanta(ptrIP, ptrMacs, lon, (char*)"2"))
[9dea2d6]3024                                return false;
[ad4ae52]3025
[b9eb98b]3026                }
3027                if (clienteDisponible(iph, &idx)) { // Si el cliente puede recibir comandos
[f09aca6]3028                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
3029
[b9eb98b]3030                        strcpy(tbsockets[idx].estado, CLIENTE_OCUPADO); // Actualiza el estado del cliente
[3e8fcf0]3031                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
[b56cbeb]3032                                syslog(LOG_ERR, "failed to send response: %s\n",
3033                                       strerror(errno));
[b9eb98b]3034                        }
[b937298]3035                        //close(tbsockets[idx].sock); // Cierra el socket del cliente hasta nueva disponibilidad
[b9eb98b]3036                }
3037                tbl.MoveNext();
3038        }
[9dea2d6]3039        return true; // No existen registros
[b9eb98b]3040}
[8e0216a]3041
3042// This object stores function handler for messages
3043static struct {
3044        const char *nf; // Nombre de la función
[212280e]3045        bool (*fcn)(TRAMA *, struct og_client *cli);
[4665749]3046} tbfuncionesServer[] = {
[8e0216a]3047        { "InclusionCliente",                   InclusionCliente,       },
3048        { "InclusionClienteWinLnx",             InclusionClienteWinLnx, },
3049        { "AutoexecCliente",                    AutoexecCliente,        },
3050        { "ComandosPendientes",                 ComandosPendientes,     },
3051        { "DisponibilidadComandos",             DisponibilidadComandos, },
3052        { "RESPUESTA_Arrancar",                 RESPUESTA_Arrancar,     },
3053        { "RESPUESTA_Apagar",                   RESPUESTA_Apagar,       },
3054        { "RESPUESTA_Reiniciar",                RESPUESTA_Reiniciar,    },
3055        { "RESPUESTA_IniciarSesion",            RESPUESTA_IniciarSesion, },
3056        { "RESPUESTA_CrearImagen",              RESPUESTA_CrearImagen,  },
3057        { "CrearImagenBasica",                  CrearImagenBasica,      },
3058        { "RESPUESTA_CrearImagenBasica",        RESPUESTA_CrearImagenBasica, },
3059        { "CrearSoftIncremental",               CrearSoftIncremental,   },
3060        { "RESPUESTA_CrearSoftIncremental",     RESPUESTA_CrearSoftIncremental, },
3061        { "RESPUESTA_RestaurarImagen",          RESPUESTA_RestaurarImagen },
3062        { "RestaurarImagenBasica",              RestaurarImagenBasica, },
3063        { "RESPUESTA_RestaurarImagenBasica",    RESPUESTA_RestaurarImagenBasica, },
3064        { "RestaurarSoftIncremental",           RestaurarSoftIncremental, },
3065        { "RESPUESTA_RestaurarSoftIncremental", RESPUESTA_RestaurarSoftIncremental, },
3066        { "Configurar",                         Configurar,             },
3067        { "RESPUESTA_Configurar",               RESPUESTA_Configurar,   },
3068        { "EjecutarScript",                     EjecutarScript,         },
3069        { "RESPUESTA_EjecutarScript",           RESPUESTA_EjecutarScript, },
3070        { "RESPUESTA_InventarioHardware",       RESPUESTA_InventarioHardware, },
3071        { "RESPUESTA_InventarioSoftware",       RESPUESTA_InventarioSoftware, },
3072        { "enviaArchivo",                       enviaArchivo,           },
3073        { "recibeArchivo",                      recibeArchivo,          },
3074        { "envioProgramacion",                  envioProgramacion,      },
[4665749]3075        { NULL,                                 NULL,                   },
[8e0216a]3076};
3077
3078// ________________________________________________________________________________________________________
3079// Función: gestionaTrama
3080//
3081//              Descripción:
3082//                      Procesa las tramas recibidas .
3083//              Parametros:
3084//                      - s : Socket usado para comunicaciones
3085//      Devuelve:
[9dea2d6]3086//              true: Si el proceso es correcto
3087//              false: En caso de ocurrir algún error
[8e0216a]3088// ________________________________________________________________________________________________________
[b56cbeb]3089static void gestionaTrama(TRAMA *ptrTrama, struct og_client *cli)
[8e0216a]3090{
3091        int i, res;
3092        char *nfn;
3093
3094        if (ptrTrama){
3095                INTROaFINCAD(ptrTrama);
3096                nfn = copiaParametro("nfn",ptrTrama); // Toma nombre de la función
3097
[212280e]3098                for (i = 0; tbfuncionesServer[i].fcn; i++) {
3099                        if (!strncmp(tbfuncionesServer[i].nf, nfn,
3100                                     strlen(tbfuncionesServer[i].nf))) {
3101                                res = tbfuncionesServer[i].fcn(ptrTrama, cli);
[b56cbeb]3102                                if (!res) {
3103                                        syslog(LOG_ERR, "Failed handling of %s for client %s:%hu\n",
3104                                               tbfuncionesServer[i].nf,
3105                                               inet_ntoa(cli->addr.sin_addr),
3106                                               ntohs(cli->addr.sin_port));
3107                                } else {
3108                                        syslog(LOG_DEBUG, "Successful handling of %s for client %s:%hu\n",
3109                                               tbfuncionesServer[i].nf,
3110                                               inet_ntoa(cli->addr.sin_addr),
3111                                               ntohs(cli->addr.sin_port));
3112                                }
[212280e]3113                                break;
[8e0216a]3114                        }
3115                }
[ef6e3d2]3116                if (!tbfuncionesServer[i].fcn)
[f09aca6]3117                        syslog(LOG_ERR, "unknown request %s from client %s:%hu\n",
3118                               nfn, inet_ntoa(cli->addr.sin_addr),
3119                               ntohs(cli->addr.sin_port));
[ef6e3d2]3120
[8e0216a]3121                liberaMemoria(nfn);
[212280e]3122        }
3123}
3124
[f09aca6]3125static void og_client_release(struct ev_loop *loop, struct og_client *cli)
3126{
3127        if (cli->keepalive_idx >= 0) {
[2ed3a0c]3128                syslog(LOG_DEBUG, "closing keepalive connection for %s:%hu in slot %d\n",
[f09aca6]3129                       inet_ntoa(cli->addr.sin_addr),
3130                       ntohs(cli->addr.sin_port), cli->keepalive_idx);
3131                tbsockets[cli->keepalive_idx].cli = NULL;
3132        }
3133
3134        ev_io_stop(loop, &cli->io);
3135        close(cli->io.fd);
3136        free(cli);
3137}
3138
3139static void og_client_keepalive(struct ev_loop *loop, struct og_client *cli)
3140{
3141        struct og_client *old_cli;
3142
3143        old_cli = tbsockets[cli->keepalive_idx].cli;
3144        if (old_cli && old_cli != cli) {
[2ed3a0c]3145                syslog(LOG_DEBUG, "closing old keepalive connection for %s:%hu\n",
[f09aca6]3146                       inet_ntoa(old_cli->addr.sin_addr),
3147                       ntohs(old_cli->addr.sin_port));
3148
3149                og_client_release(loop, old_cli);
3150        }
3151        tbsockets[cli->keepalive_idx].cli = cli;
3152}
3153
3154static void og_client_reset_state(struct og_client *cli)
3155{
3156        cli->state = OG_CLIENT_RECEIVING_HEADER;
3157        cli->buf_len = 0;
3158}
3159
[d491dfd]3160static int og_client_state_recv_hdr(struct og_client *cli)
[212280e]3161{
3162        char hdrlen[LONHEXPRM];
[d491dfd]3163
3164        /* Still too short to validate protocol fingerprint and message
3165         * length.
3166         */
3167        if (cli->buf_len < 15 + LONHEXPRM)
3168                return 0;
3169
3170        if (strncmp(cli->buf, "@JMMLCAMDJ_MCDJ", 15)) {
3171                syslog(LOG_ERR, "bad fingerprint from client %s:%hu, closing\n",
3172                       inet_ntoa(cli->addr.sin_addr),
3173                       ntohs(cli->addr.sin_port));
3174                return -1;
3175        }
3176
3177        memcpy(hdrlen, &cli->buf[LONGITUD_CABECERATRAMA], LONHEXPRM);
3178        cli->msg_len = strtol(hdrlen, NULL, 16);
3179
3180        /* Header announces more that we can fit into buffer. */
3181        if (cli->msg_len >= sizeof(cli->buf)) {
3182                syslog(LOG_ERR, "too large message %u bytes from %s:%hu\n",
3183                       cli->msg_len, inet_ntoa(cli->addr.sin_addr),
3184                       ntohs(cli->addr.sin_port));
3185                return -1;
3186        }
3187
3188        return 1;
3189}
3190
[2226378]3191static TRAMA *og_msg_alloc(char *data, unsigned int len)
[d491dfd]3192{
[212280e]3193        TRAMA *ptrTrama;
[107b17a]3194
3195        ptrTrama = (TRAMA *)reservaMemoria(sizeof(TRAMA));
3196        if (!ptrTrama) {
3197                syslog(LOG_ERR, "OOM\n");
[2226378]3198                return NULL;
[107b17a]3199        }
3200
3201        initParametros(ptrTrama, len);
[2226378]3202        memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA);
[107b17a]3203        memcpy(ptrTrama->parametros, data, len);
3204        ptrTrama->lonprm = len;
3205
[2226378]3206        return ptrTrama;
3207}
[107b17a]3208
[2226378]3209static void og_msg_free(TRAMA *ptrTrama)
3210{
[107b17a]3211        liberaMemoria(ptrTrama->parametros);
3212        liberaMemoria(ptrTrama);
[2226378]3213}
3214
3215static int og_client_state_process_payload(struct og_client *cli)
3216{
3217        TRAMA *ptrTrama;
3218        char *data;
3219        int len;
3220
3221        len = cli->msg_len - (LONGITUD_CABECERATRAMA + LONHEXPRM);
3222        data = &cli->buf[LONGITUD_CABECERATRAMA + LONHEXPRM];
3223
3224        ptrTrama = og_msg_alloc(data, len);
3225        if (!ptrTrama)
3226                return -1;
3227
3228        gestionaTrama(ptrTrama, cli);
3229
3230        og_msg_free(ptrTrama);
[107b17a]3231
3232        return 1;
3233}
3234
[881f532]3235#define OG_CLIENTS_MAX  4096
[dbcc83d]3236#define OG_PARTITION_MAX 4
3237
3238struct og_partition {
3239        const char      *number;
3240        const char      *code;
3241        const char      *size;
3242        const char      *filesystem;
3243        const char      *format;
3244};
[881f532]3245
[01e77f4]3246struct og_sync_params {
3247        const char      *sync;
3248        const char      *diff;
3249        const char      *remove;
3250        const char      *compress;
3251        const char      *cleanup;
3252        const char      *cache;
3253        const char      *cleanup_cache;
3254        const char      *remove_dst;
[43c7da8]3255        const char      *diff_id;
3256        const char      *diff_name;
[f61fd9a]3257        const char      *path;
3258        const char      *method;
[01e77f4]3259};
3260
[95e6520]3261struct og_msg_params {
[881f532]3262        const char      *ips_array[OG_CLIENTS_MAX];
3263        const char      *mac_array[OG_CLIENTS_MAX];
[95e6520]3264        unsigned int    ips_array_len;
[5797e0b]3265        const char      *wol_type;
[7e4e5b5]3266        char            run_cmd[4096];
[7ab5f0c]3267        const char      *disk;
3268        const char      *partition;
[1a8ada1]3269        const char      *repository;
3270        const char      *name;
3271        const char      *id;
3272        const char      *code;
[1dde02e]3273        const char      *type;
3274        const char      *profile;
[dbcc83d]3275        const char      *cache;
3276        const char      *cache_size;
[ffd2965]3277        bool            echo;
[dbcc83d]3278        struct og_partition     partition_setup[OG_PARTITION_MAX];
[01e77f4]3279        struct og_sync_params sync_setup;
[54ecdbb]3280        uint64_t        flags;
[95e6520]3281};
3282
[54ecdbb]3283#define OG_REST_PARAM_ADDR                      (1UL << 0)
[ec5fe70]3284#define OG_REST_PARAM_MAC                       (1UL << 1)
3285#define OG_REST_PARAM_WOL_TYPE                  (1UL << 2)
[b403c7a]3286#define OG_REST_PARAM_RUN_CMD                   (1UL << 3)
[8901505]3287#define OG_REST_PARAM_DISK                      (1UL << 4)
3288#define OG_REST_PARAM_PARTITION                 (1UL << 5)
[abe2a88]3289#define OG_REST_PARAM_REPO                      (1UL << 6)
3290#define OG_REST_PARAM_NAME                      (1UL << 7)
3291#define OG_REST_PARAM_ID                        (1UL << 8)
3292#define OG_REST_PARAM_CODE                      (1UL << 9)
[ec4189b]3293#define OG_REST_PARAM_TYPE                      (1UL << 10)
3294#define OG_REST_PARAM_PROFILE                   (1UL << 11)
[3bc3b45]3295#define OG_REST_PARAM_CACHE                     (1UL << 12)
3296#define OG_REST_PARAM_CACHE_SIZE                (1UL << 13)
3297#define OG_REST_PARAM_PART_0                    (1UL << 14)
3298#define OG_REST_PARAM_PART_1                    (1UL << 15)
3299#define OG_REST_PARAM_PART_2                    (1UL << 16)
3300#define OG_REST_PARAM_PART_3                    (1UL << 17)
[82a1d5a]3301#define OG_REST_PARAM_SYNC_SYNC                 (1UL << 18)
3302#define OG_REST_PARAM_SYNC_DIFF                 (1UL << 19)
3303#define OG_REST_PARAM_SYNC_REMOVE               (1UL << 20)
3304#define OG_REST_PARAM_SYNC_COMPRESS             (1UL << 21)
3305#define OG_REST_PARAM_SYNC_CLEANUP              (1UL << 22)
3306#define OG_REST_PARAM_SYNC_CACHE                (1UL << 23)
3307#define OG_REST_PARAM_SYNC_CLEANUP_CACHE        (1UL << 24)
3308#define OG_REST_PARAM_SYNC_REMOVE_DST           (1UL << 25)
3309#define OG_REST_PARAM_SYNC_DIFF_ID              (1UL << 26)
3310#define OG_REST_PARAM_SYNC_DIFF_NAME            (1UL << 27)
3311#define OG_REST_PARAM_SYNC_PATH                 (1UL << 28)
3312#define OG_REST_PARAM_SYNC_METHOD               (1UL << 29)
[ffd2965]3313#define OG_REST_PARAM_ECHO                      (1UL << 30)
[54ecdbb]3314
3315static bool og_msg_params_validate(const struct og_msg_params *params,
3316                                   const uint64_t flags)
3317{
3318        return (params->flags & flags) == flags;
3319}
3320
[95e6520]3321static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
3322{
3323        unsigned int i;
3324        json_t *k;
3325
3326        if (json_typeof(element) != JSON_ARRAY)
3327                return -1;
3328
3329        for (i = 0; i < json_array_size(element); i++) {
3330                k = json_array_get(element, i);
3331                if (json_typeof(k) != JSON_STRING)
3332                        return -1;
3333
3334                params->ips_array[params->ips_array_len++] =
3335                        json_string_value(k);
[54ecdbb]3336
[280df58]3337                params->flags |= OG_REST_PARAM_ADDR;
3338        }
[54ecdbb]3339
[95e6520]3340        return 0;
3341}
3342
[c87a1db]3343static int og_json_parse_string(json_t *element, const char **str)
3344{
3345        if (json_typeof(element) != JSON_STRING)
3346                return -1;
3347
3348        *str = json_string_value(element);
3349        return 0;
3350}
3351
[ffd2965]3352static int og_json_parse_bool(json_t *element, bool *value)
3353{
3354        if (json_typeof(element) == JSON_TRUE)
3355                *value = true;
3356        else if (json_typeof(element) == JSON_FALSE)
3357                *value = false;
3358        else
3359                return -1;
3360
3361        return 0;
3362}
3363
[82a1d5a]3364static int og_json_parse_sync_params(json_t *element,
3365                                     struct og_msg_params *params)
[01e77f4]3366{
3367        const char *key;
3368        json_t *value;
3369        int err = 0;
3370
3371        json_object_foreach(element, key, value) {
[82a1d5a]3372                if (!strcmp(key, "sync")) {
3373                        err = og_json_parse_string(value, &params->sync_setup.sync);
3374                        params->flags |= OG_REST_PARAM_SYNC_SYNC;
3375                } else if (!strcmp(key, "diff")) {
3376                        err = og_json_parse_string(value, &params->sync_setup.diff);
3377                        params->flags |= OG_REST_PARAM_SYNC_DIFF;
3378                } else if (!strcmp(key, "remove")) {
3379                        err = og_json_parse_string(value, &params->sync_setup.remove);
3380                        params->flags |= OG_REST_PARAM_SYNC_REMOVE;
3381                } else if (!strcmp(key, "compress")) {
3382                        err = og_json_parse_string(value, &params->sync_setup.compress);
3383                        params->flags |= OG_REST_PARAM_SYNC_COMPRESS;
3384                } else if (!strcmp(key, "cleanup")) {
3385                        err = og_json_parse_string(value, &params->sync_setup.cleanup);
3386                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP;
3387                } else if (!strcmp(key, "cache")) {
3388                        err = og_json_parse_string(value, &params->sync_setup.cache);
3389                        params->flags |= OG_REST_PARAM_SYNC_CACHE;
3390                } else if (!strcmp(key, "cleanup_cache")) {
3391                        err = og_json_parse_string(value, &params->sync_setup.cleanup_cache);
3392                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP_CACHE;
3393                } else if (!strcmp(key, "remove_dst")) {
3394                        err = og_json_parse_string(value, &params->sync_setup.remove_dst);
3395                        params->flags |= OG_REST_PARAM_SYNC_REMOVE_DST;
3396                } else if (!strcmp(key, "diff_id")) {
3397                        err = og_json_parse_string(value, &params->sync_setup.diff_id);
3398                        params->flags |= OG_REST_PARAM_SYNC_DIFF_ID;
3399                } else if (!strcmp(key, "diff_name")) {
3400                        err = og_json_parse_string(value, &params->sync_setup.diff_name);
3401                        params->flags |= OG_REST_PARAM_SYNC_DIFF_NAME;
3402                } else if (!strcmp(key, "path")) {
3403                        err = og_json_parse_string(value, &params->sync_setup.path);
3404                        params->flags |= OG_REST_PARAM_SYNC_PATH;
3405                } else if (!strcmp(key, "method")) {
3406                        err = og_json_parse_string(value, &params->sync_setup.method);
3407                        params->flags |= OG_REST_PARAM_SYNC_METHOD;
3408                }
[01e77f4]3409
3410                if (err != 0)
3411                        return err;
3412        }
3413        return err;
3414}
3415
[3bc3b45]3416#define OG_PARAM_PART_NUMBER                    (1UL << 0)
3417#define OG_PARAM_PART_CODE                      (1UL << 1)
3418#define OG_PARAM_PART_FILESYSTEM                (1UL << 2)
3419#define OG_PARAM_PART_SIZE                      (1UL << 3)
3420#define OG_PARAM_PART_FORMAT                    (1UL << 4)
3421
3422static int og_json_parse_partition(json_t *element,
3423                                   struct og_msg_params *params,
3424                                   unsigned int i)
[e3af7ee]3425{
[3bc3b45]3426        struct og_partition *part = &params->partition_setup[i];
3427        uint64_t flags = 0UL;
[e3af7ee]3428        const char *key;
3429        json_t *value;
3430        int err = 0;
3431
3432        json_object_foreach(element, key, value) {
[3bc3b45]3433                if (!strcmp(key, "partition")) {
[e3af7ee]3434                        err = og_json_parse_string(value, &part->number);
[3bc3b45]3435                        flags |= OG_PARAM_PART_NUMBER;
3436                } else if (!strcmp(key, "code")) {
[e3af7ee]3437                        err = og_json_parse_string(value, &part->code);
[3bc3b45]3438                        flags |= OG_PARAM_PART_CODE;
3439                } else if (!strcmp(key, "filesystem")) {
[e3af7ee]3440                        err = og_json_parse_string(value, &part->filesystem);
[3bc3b45]3441                        flags |= OG_PARAM_PART_FILESYSTEM;
3442                } else if (!strcmp(key, "size")) {
[e3af7ee]3443                        err = og_json_parse_string(value, &part->size);
[3bc3b45]3444                        flags |= OG_PARAM_PART_SIZE;
3445                } else if (!strcmp(key, "format")) {
[e3af7ee]3446                        err = og_json_parse_string(value, &part->format);
[3bc3b45]3447                        flags |= OG_PARAM_PART_FORMAT;
3448                }
[e3af7ee]3449
3450                if (err < 0)
3451                        return err;
3452        }
[3bc3b45]3453
3454        if (flags != (OG_PARAM_PART_NUMBER |
3455                      OG_PARAM_PART_CODE |
3456                      OG_PARAM_PART_FILESYSTEM |
3457                      OG_PARAM_PART_SIZE |
3458                      OG_PARAM_PART_FORMAT))
3459                return -1;
3460
3461        params->flags |= (OG_REST_PARAM_PART_0 << i);
3462
[e3af7ee]3463        return err;
[dbcc83d]3464}
3465
[3bc3b45]3466static int og_json_parse_partition_setup(json_t *element,
3467                                         struct og_msg_params *params)
[dbcc83d]3468{
3469        unsigned int i;
3470        json_t *k;
3471
3472        if (json_typeof(element) != JSON_ARRAY)
3473                return -1;
3474
3475        for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
3476                k = json_array_get(element, i);
3477
3478                if (json_typeof(k) != JSON_OBJECT)
3479                        return -1;
3480
[3bc3b45]3481                if (og_json_parse_partition(k, params, i) != 0)
[e3af7ee]3482                        return -1;
[dbcc83d]3483        }
3484        return 0;
3485}
3486
[40023ff]3487static int og_cmd_legacy_send(struct og_msg_params *params, const char *cmd,
3488                              const char *state)
[95e6520]3489{
3490        char buf[4096] = {};
3491        int len, err = 0;
3492        TRAMA *msg;
3493
[40023ff]3494        len = snprintf(buf, sizeof(buf), "nfn=%s\r", cmd);
[95e6520]3495
3496        msg = og_msg_alloc(buf, len);
3497        if (!msg)
3498                return -1;
3499
3500        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
[40023ff]3501                         state, msg))
[95e6520]3502                err = -1;
3503
3504        og_msg_free(msg);
3505
3506        return err;
3507}
3508
3509static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
3510{
3511        const char *key;
3512        json_t *value;
3513        int err = 0;
3514
3515        if (json_typeof(element) != JSON_OBJECT)
3516                return -1;
3517
3518        json_object_foreach(element, key, value) {
3519                if (!strcmp(key, "clients"))
3520                        err = og_json_parse_clients(value, params);
3521
3522                if (err < 0)
3523                        break;
3524        }
3525
[54ecdbb]3526        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3527                return -1;
3528
[40023ff]3529        return og_cmd_legacy_send(params, "Sondeo", CLIENTE_APAGADO);
[95e6520]3530}
3531
[7b6fcdb]3532struct og_buffer {
3533        char    *data;
3534        int     len;
3535};
3536
3537static int og_json_dump_clients(const char *buffer, size_t size, void *data)
3538{
3539        struct og_buffer *og_buffer = (struct og_buffer *)data;
3540
3541        memcpy(og_buffer->data + og_buffer->len, buffer, size);
3542        og_buffer->len += size;
3543
3544        return 0;
3545}
3546
3547static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
3548                              char *buffer_reply)
3549{
3550        json_t *root, *array, *addr, *state, *object;
3551        struct og_buffer og_buffer = {
3552                .data   = buffer_reply,
3553        };
3554        int i;
3555
3556        array = json_array();
3557        if (!array)
3558                return -1;
3559
3560        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
3561                if (tbsockets[i].ip[0] == '\0')
3562                        continue;
3563
3564                object = json_object();
3565                if (!object) {
3566                        json_decref(array);
3567                        return -1;
3568                }
3569                addr = json_string(tbsockets[i].ip);
3570                if (!addr) {
3571                        json_decref(object);
3572                        json_decref(array);
3573                        return -1;
3574                }
3575                json_object_set_new(object, "addr", addr);
3576
3577                state = json_string(tbsockets[i].estado);
3578                if (!state) {
3579                        json_decref(object);
3580                        json_decref(array);
3581                        return -1;
3582                }
3583                json_object_set_new(object, "state", state);
3584
3585                json_array_append_new(array, object);
3586        }
3587        root = json_pack("{s:o}", "clients", array);
3588        if (!root) {
3589                json_decref(array);
3590                return -1;
3591        }
3592
[7e6ba45]3593        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[7b6fcdb]3594        json_decref(root);
3595
3596        return 0;
3597}
3598
[5797e0b]3599static int og_json_parse_target(json_t *element, struct og_msg_params *params)
3600{
3601        const char *key;
3602        json_t *value;
3603
3604        if (json_typeof(element) != JSON_OBJECT) {
3605                return -1;
3606        }
3607
3608        json_object_foreach(element, key, value) {
3609                if (!strcmp(key, "addr")) {
3610                        if (json_typeof(value) != JSON_STRING)
3611                                return -1;
3612
3613                        params->ips_array[params->ips_array_len] =
3614                                json_string_value(value);
[ec5fe70]3615
3616                        params->flags |= OG_REST_PARAM_ADDR;
[5797e0b]3617                } else if (!strcmp(key, "mac")) {
3618                        if (json_typeof(value) != JSON_STRING)
3619                                return -1;
3620
3621                        params->mac_array[params->ips_array_len] =
3622                                json_string_value(value);
[ec5fe70]3623
3624                        params->flags |= OG_REST_PARAM_MAC;
[5797e0b]3625                }
3626        }
3627
3628        return 0;
3629}
3630
3631static int og_json_parse_targets(json_t *element, struct og_msg_params *params)
3632{
3633        unsigned int i;
3634        json_t *k;
3635        int err;
3636
3637        if (json_typeof(element) != JSON_ARRAY)
3638                return -1;
3639
3640        for (i = 0; i < json_array_size(element); i++) {
3641                k = json_array_get(element, i);
3642
3643                if (json_typeof(k) != JSON_OBJECT)
3644                        return -1;
3645
3646                err = og_json_parse_target(k, params);
3647                if (err < 0)
3648                        return err;
3649
3650                params->ips_array_len++;
3651        }
3652        return 0;
3653}
3654
3655static int og_json_parse_type(json_t *element, struct og_msg_params *params)
3656{
3657        const char *type;
3658
3659        if (json_typeof(element) != JSON_STRING)
3660                return -1;
3661
3662        params->wol_type = json_string_value(element);
3663
3664        type = json_string_value(element);
3665        if (!strcmp(type, "unicast"))
3666                params->wol_type = "2";
3667        else if (!strcmp(type, "broadcast"))
3668                params->wol_type = "1";
3669
[ec5fe70]3670        params->flags |= OG_REST_PARAM_WOL_TYPE;
3671
[5797e0b]3672        return 0;
3673}
3674
3675static int og_cmd_wol(json_t *element, struct og_msg_params *params)
3676{
3677        const char *key;
3678        json_t *value;
3679        int err = 0;
3680
3681        if (json_typeof(element) != JSON_OBJECT)
3682                return -1;
3683
3684        json_object_foreach(element, key, value) {
3685                if (!strcmp(key, "clients")) {
3686                        err = og_json_parse_targets(value, params);
3687                } else if (!strcmp(key, "type")) {
3688                        err = og_json_parse_type(value, params);
3689                }
3690
3691                if (err < 0)
3692                        break;
3693        }
3694
[ec5fe70]3695        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3696                                            OG_REST_PARAM_MAC |
3697                                            OG_REST_PARAM_WOL_TYPE))
3698                return -1;
3699
[5797e0b]3700        if (!Levanta((char **)params->ips_array, (char **)params->mac_array,
3701                     params->ips_array_len, (char *)params->wol_type))
3702                return -1;
3703
3704        return 0;
3705}
3706
[7e4e5b5]3707static int og_json_parse_run(json_t *element, struct og_msg_params *params)
3708{
3709        if (json_typeof(element) != JSON_STRING)
3710                return -1;
3711
3712        snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
3713                 json_string_value(element));
3714
[b403c7a]3715        params->flags |= OG_REST_PARAM_RUN_CMD;
3716
[7e4e5b5]3717        return 0;
3718}
3719
3720static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
3721{
3722        char buf[4096] = {}, iph[4096] = {};
3723        int err = 0, len;
3724        const char *key;
3725        unsigned int i;
3726        json_t *value;
3727        TRAMA *msg;
3728
3729        if (json_typeof(element) != JSON_OBJECT)
3730                return -1;
3731
3732        json_object_foreach(element, key, value) {
3733                if (!strcmp(key, "clients"))
3734                        err = og_json_parse_clients(value, params);
[ffd2965]3735                else if (!strcmp(key, "run"))
[7e4e5b5]3736                        err = og_json_parse_run(value, params);
[ffd2965]3737                else if (!strcmp(key, "echo")) {
3738                        err = og_json_parse_bool(value, &params->echo);
3739                        params->flags |= OG_REST_PARAM_ECHO;
3740                }
[7e4e5b5]3741
3742                if (err < 0)
3743                        break;
3744        }
3745
[b403c7a]3746        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
[ffd2965]3747                                            OG_REST_PARAM_RUN_CMD |
3748                                            OG_REST_PARAM_ECHO))
[b403c7a]3749                return -1;
3750
[7e4e5b5]3751        for (i = 0; i < params->ips_array_len; i++) {
3752                len = snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3753                               params->ips_array[i]);
3754        }
[ffd2965]3755
3756        if (params->echo) {
3757                len = snprintf(buf, sizeof(buf),
3758                               "nfn=ConsolaRemota\riph=%s\rscp=%s\r",
3759                               iph, params->run_cmd);
3760        } else {
3761                len = snprintf(buf, sizeof(buf),
3762                               "nfn=EjecutarScript\riph=%s\rscp=%s\r",
3763                               iph, params->run_cmd);
3764        }
[7e4e5b5]3765
3766        msg = og_msg_alloc(buf, len);
3767        if (!msg)
3768                return -1;
3769
3770        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3771                         CLIENTE_OCUPADO, msg))
3772                err = -1;
3773
3774        og_msg_free(msg);
3775
3776        if (err < 0)
3777                return err;
3778
3779        for (i = 0; i < params->ips_array_len; i++) {
3780                char filename[4096];
3781                FILE *f;
3782
3783                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3784                f = fopen(filename, "wt");
3785                fclose(f);
3786        }
3787
3788        return 0;
3789}
3790
[c6020f2]3791static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
3792                          char *buffer_reply)
3793{
3794        struct og_buffer og_buffer = {
3795                .data   = buffer_reply,
3796        };
3797        json_t *root, *value, *array;
3798        const char *key;
3799        unsigned int i;
3800        int err = 0;
3801
3802        if (json_typeof(element) != JSON_OBJECT)
3803                return -1;
3804
3805        json_object_foreach(element, key, value) {
3806                if (!strcmp(key, "clients"))
3807                        err = og_json_parse_clients(value, params);
3808
3809                if (err < 0)
3810                        return err;
3811        }
3812
[61059e1]3813        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3814                return -1;
3815
[c6020f2]3816        array = json_array();
3817        if (!array)
3818                return -1;
3819
3820        for (i = 0; i < params->ips_array_len; i++) {
3821                json_t *object, *output, *addr;
3822                char data[4096] = {};
3823                char filename[4096];
3824                int fd, numbytes;
3825
3826                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
3827
3828                fd = open(filename, O_RDONLY);
3829                if (!fd)
3830                        return -1;
3831
3832                numbytes = read(fd, data, sizeof(data));
3833                if (numbytes < 0) {
3834                        close(fd);
3835                        return -1;
3836                }
3837                data[sizeof(data) - 1] = '\0';
3838                close(fd);
3839
3840                object = json_object();
3841                if (!object) {
3842                        json_decref(array);
3843                        return -1;
3844                }
3845                addr = json_string(params->ips_array[i]);
3846                if (!addr) {
3847                        json_decref(object);
3848                        json_decref(array);
3849                        return -1;
3850                }
3851                json_object_set_new(object, "addr", addr);
3852
3853                output = json_string(data);
3854                if (!output) {
3855                        json_decref(object);
3856                        json_decref(array);
3857                        return -1;
3858                }
3859                json_object_set_new(object, "output", output);
3860
3861                json_array_append_new(array, object);
3862        }
3863
3864        root = json_pack("{s:o}", "clients", array);
3865        if (!root)
3866                return -1;
3867
[7e6ba45]3868        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
[c6020f2]3869        json_decref(root);
3870
3871        return 0;
3872}
3873
[7ab5f0c]3874static int og_cmd_session(json_t *element, struct og_msg_params *params)
3875{
3876        char buf[4096], iph[4096];
3877        int err = 0, len;
3878        const char *key;
3879        unsigned int i;
3880        json_t *value;
3881        TRAMA *msg;
3882
3883        if (json_typeof(element) != JSON_OBJECT)
3884                return -1;
3885
3886        json_object_foreach(element, key, value) {
[8901505]3887                if (!strcmp(key, "clients")) {
[7ab5f0c]3888                        err = og_json_parse_clients(value, params);
[8901505]3889                } else if (!strcmp(key, "disk")) {
[c87a1db]3890                        err = og_json_parse_string(value, &params->disk);
[8901505]3891                        params->flags |= OG_REST_PARAM_DISK;
3892                } else if (!strcmp(key, "partition")) {
[c87a1db]3893                        err = og_json_parse_string(value, &params->partition);
[8901505]3894                        params->flags |= OG_REST_PARAM_PARTITION;
3895                }
[7ab5f0c]3896
3897                if (err < 0)
3898                        return err;
3899        }
3900
[8901505]3901        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
3902                                            OG_REST_PARAM_DISK |
3903                                            OG_REST_PARAM_PARTITION))
3904                return -1;
3905
[7ab5f0c]3906        for (i = 0; i < params->ips_array_len; i++) {
3907                snprintf(iph + strlen(iph), sizeof(iph), "%s;",
3908                         params->ips_array[i]);
3909        }
3910        len = snprintf(buf, sizeof(buf),
3911                       "nfn=IniciarSesion\riph=%s\rdsk=%s\rpar=%s\r",
3912                       iph, params->disk, params->partition);
3913
3914        msg = og_msg_alloc(buf, len);
3915        if (!msg)
3916                return -1;
3917
3918        if (!og_send_cmd((char **)params->ips_array, params->ips_array_len,
3919                         CLIENTE_APAGADO, msg))
3920                err = -1;
3921
3922        og_msg_free(msg);
3923
3924        return 0;
3925}
3926
[23fed47]3927static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
3928{
3929        const char *key;
3930        json_t *value;
3931        int err = 0;
3932
3933        if (json_typeof(element) != JSON_OBJECT)
3934                return -1;
3935
3936        json_object_foreach(element, key, value) {
3937                if (!strcmp(key, "clients"))
3938                        err = og_json_parse_clients(value, params);
3939
3940                if (err < 0)
3941                        break;
3942        }
3943
[acf9cdf]3944        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3945                return -1;
3946
[23fed47]3947        return og_cmd_legacy_send(params, "Apagar", CLIENTE_OCUPADO);
3948}
3949
[17f55b4]3950static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
3951{
3952        const char *key;
3953        json_t *value;
3954        int err = 0;
3955
3956        if (json_typeof(element) != JSON_OBJECT)
3957                return -1;
3958
3959        json_object_foreach(element, key, value) {
3960                if (!strcmp(key, "clients"))
3961                        err = og_json_parse_clients(value, params);
3962
3963                if (err < 0)
3964                        break;
3965        }
3966
[93028bd]3967        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3968                return -1;
3969
[17f55b4]3970        return og_cmd_legacy_send(params, "Actualizar", CLIENTE_APAGADO);
3971}
3972
[5f0191d]3973static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
3974{
3975        const char *key;
3976        json_t *value;
3977        int err = 0;
3978
3979        if (json_typeof(element) != JSON_OBJECT)
3980                return -1;
3981
3982        json_object_foreach(element, key, value) {
3983                if (!strcmp(key, "clients"))
3984                        err = og_json_parse_clients(value, params);
3985
3986                if (err < 0)
3987                        break;
3988        }
3989
[0a41d5d]3990        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
3991                return -1;
3992
[5f0191d]3993        return og_cmd_legacy_send(params, "Reiniciar", CLIENTE_OCUPADO);
3994}
3995
[1e6c889]3996static int og_cmd_stop(json_t *element, struct og_msg_params *params)
3997{
3998        const char *key;
3999        json_t *value;
4000        int err = 0;
4001
4002        if (json_typeof(element) != JSON_OBJECT)
4003                return -1;
4004
4005        json_object_foreach(element, key, value) {
4006                if (!strcmp(key, "clients"))
4007                        err = og_json_parse_clients(value, params);
4008
4009                if (err < 0)
4010                        break;
4011        }
4012
[bc1b958]4013        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
4014                return -1;
4015
[1e6c889]4016        return og_cmd_legacy_send(params, "Purgar", CLIENTE_APAGADO);
4017}
4018
[6b30dbc]4019static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
4020{
4021        const char *key;
4022        json_t *value;
4023        int err = 0;
4024
4025        if (json_typeof(element) != JSON_OBJECT)
4026                return -1;
4027
4028        json_object_foreach(element, key, value) {
4029                if (!strcmp(key, "clients"))
4030                        err = og_json_parse_clients(value, params);
4031
4032                if (err < 0)
4033                        break;
4034        }
4035
[7803e13]4036        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
4037                return -1;
4038
[6b30dbc]4039        return og_cmd_legacy_send(params, "InventarioHardware",
4040                                  CLIENTE_OCUPADO);
4041}
4042
[b4a9fdd]4043static int og_cmd_software(json_t *element, struct og_msg_params *params)
4044{
[61bbcd9]4045        char buf[4096] = {};
4046        int err = 0, len;
[b4a9fdd]4047        const char *key;
4048        json_t *value;
[61bbcd9]4049        TRAMA *msg;
[b4a9fdd]4050
4051        if (json_typeof(element) != JSON_OBJECT)
4052                return -1;
4053
4054        json_object_foreach(element, key, value) {
4055                if (!strcmp(key, "clients"))
4056                        err = og_json_parse_clients(value, params);
[1a1ecf7]4057                else if (!strcmp(key, "disk")) {
[61bbcd9]4058                        err = og_json_parse_string(value, &params->disk);
[1a1ecf7]4059                        params->flags |= OG_REST_PARAM_DISK;
4060                }
4061                else if (!strcmp(key, "partition")) {
[61bbcd9]4062                        err = og_json_parse_string(value, &params->partition);
[1a1ecf7]4063                        params->flags |= OG_REST_PARAM_PARTITION;
4064                }
[b4a9fdd]4065
4066                if (err < 0)
4067                        break;
4068        }
4069
[1a1ecf7]4070        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4071                                            OG_REST_PARAM_DISK |
4072                                            OG_REST_PARAM_PARTITION))
4073                return -1;
4074
[61bbcd9]4075        len = snprintf(buf, sizeof(buf),
4076                       "nfn=InventarioSoftware\rdsk=%s\rpar=%s\r",
4077                       params->disk, params->partition);
4078
4079        msg = og_msg_alloc(buf, len);
4080        if (!msg)
4081                return -1;
4082
4083        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4084                    CLIENTE_OCUPADO, msg);
4085
4086        og_msg_free(msg);
4087
4088        return 0;
[b4a9fdd]4089}
4090
[1a8ada1]4091static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
4092{
4093        char buf[4096] = {};
4094        int err = 0, len;
4095        const char *key;
4096        json_t *value;
4097        TRAMA *msg;
4098
4099        if (json_typeof(element) != JSON_OBJECT)
4100                return -1;
4101
4102        json_object_foreach(element, key, value) {
[abe2a88]4103                if (!strcmp(key, "disk")) {
[c87a1db]4104                        err = og_json_parse_string(value, &params->disk);
[abe2a88]4105                        params->flags |= OG_REST_PARAM_DISK;
4106                } else if (!strcmp(key, "partition")) {
[c87a1db]4107                        err = og_json_parse_string(value, &params->partition);
[abe2a88]4108                        params->flags |= OG_REST_PARAM_PARTITION;
4109                } else if (!strcmp(key, "name")) {
[c87a1db]4110                        err = og_json_parse_string(value, &params->name);
[abe2a88]4111                        params->flags |= OG_REST_PARAM_NAME;
4112                } else if (!strcmp(key, "repository")) {
[c87a1db]4113                        err = og_json_parse_string(value, &params->repository);
[abe2a88]4114                        params->flags |= OG_REST_PARAM_REPO;
4115                } else if (!strcmp(key, "clients")) {
[1a8ada1]4116                        err = og_json_parse_clients(value, params);
[abe2a88]4117                } else if (!strcmp(key, "id")) {
[c87a1db]4118                        err = og_json_parse_string(value, &params->id);
[abe2a88]4119                        params->flags |= OG_REST_PARAM_ID;
4120                } else if (!strcmp(key, "code")) {
[c87a1db]4121                        err = og_json_parse_string(value, &params->code);
[abe2a88]4122                        params->flags |= OG_REST_PARAM_CODE;
4123                }
[1a8ada1]4124
4125                if (err < 0)
4126                        break;
4127        }
4128
[abe2a88]4129        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4130                                            OG_REST_PARAM_DISK |
4131                                            OG_REST_PARAM_PARTITION |
4132                                            OG_REST_PARAM_CODE |
4133                                            OG_REST_PARAM_ID |
4134                                            OG_REST_PARAM_NAME |
4135                                            OG_REST_PARAM_REPO))
4136                return -1;
4137
[1a8ada1]4138        len = snprintf(buf, sizeof(buf),
4139                        "nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
4140                        params->disk, params->partition, params->code,
4141                        params->id, params->name, params->repository);
4142
4143        msg = og_msg_alloc(buf, len);
4144        if (!msg)
4145                return -1;
4146
4147        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4148                    CLIENTE_OCUPADO, msg);
4149
4150        og_msg_free(msg);
4151
4152        return 0;
4153}
4154
[1dde02e]4155static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
4156{
4157        char buf[4096] = {};
4158        int err = 0, len;
4159        const char *key;
4160        json_t *value;
4161        TRAMA *msg;
4162
4163        if (json_typeof(element) != JSON_OBJECT)
4164                return -1;
4165
4166        json_object_foreach(element, key, value) {
[ec4189b]4167                if (!strcmp(key, "disk")) {
[1dde02e]4168                        err = og_json_parse_string(value, &params->disk);
[ec4189b]4169                        params->flags |= OG_REST_PARAM_DISK;
4170                } else if (!strcmp(key, "partition")) {
[1dde02e]4171                        err = og_json_parse_string(value, &params->partition);
[ec4189b]4172                        params->flags |= OG_REST_PARAM_PARTITION;
4173                } else if (!strcmp(key, "name")) {
[1dde02e]4174                        err = og_json_parse_string(value, &params->name);
[ec4189b]4175                        params->flags |= OG_REST_PARAM_NAME;
4176                } else if (!strcmp(key, "repository")) {
[1dde02e]4177                        err = og_json_parse_string(value, &params->repository);
[ec4189b]4178                        params->flags |= OG_REST_PARAM_REPO;
4179                } else if (!strcmp(key, "clients")) {
[1dde02e]4180                        err = og_json_parse_clients(value, params);
[ec4189b]4181                } else if (!strcmp(key, "type")) {
[1dde02e]4182                        err = og_json_parse_string(value, &params->type);
[ec4189b]4183                        params->flags |= OG_REST_PARAM_TYPE;
4184                } else if (!strcmp(key, "profile")) {
[1dde02e]4185                        err = og_json_parse_string(value, &params->profile);
[ec4189b]4186                        params->flags |= OG_REST_PARAM_PROFILE;
4187                } else if (!strcmp(key, "id")) {
[1dde02e]4188                        err = og_json_parse_string(value, &params->id);
[ec4189b]4189                        params->flags |= OG_REST_PARAM_ID;
4190                }
[1dde02e]4191
4192                if (err < 0)
4193                        break;
4194        }
4195
[ec4189b]4196        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4197                                            OG_REST_PARAM_DISK |
4198                                            OG_REST_PARAM_PARTITION |
4199                                            OG_REST_PARAM_NAME |
4200                                            OG_REST_PARAM_REPO |
4201                                            OG_REST_PARAM_TYPE |
4202                                            OG_REST_PARAM_PROFILE |
4203                                            OG_REST_PARAM_ID))
4204                return -1;
4205
[1dde02e]4206        len = snprintf(buf, sizeof(buf),
4207                       "nfn=RestaurarImagen\ridi=%s\rdsk=%s\rpar=%s\rifs=%s\r"
4208                       "nci=%s\ripr=%s\rptc=%s\r",
4209                       params->id, params->disk, params->partition,
4210                       params->profile, params->name,
4211                       params->repository, params->type);
4212
4213        msg = og_msg_alloc(buf, len);
4214        if (!msg)
4215                return -1;
4216
4217        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4218                    CLIENTE_OCUPADO, msg);
4219
4220        og_msg_free(msg);
4221
4222        return 0;
4223}
4224
[6c91d14]4225static int og_cmd_setup(json_t *element, struct og_msg_params *params)
[dbcc83d]4226{
4227        char buf[4096] = {};
4228        int err = 0, len;
4229        const char *key;
4230        json_t *value;
4231        TRAMA *msg;
4232
4233        if (json_typeof(element) != JSON_OBJECT)
4234                return -1;
4235
4236        json_object_foreach(element, key, value) {
[3bc3b45]4237                if (!strcmp(key, "clients")) {
[dbcc83d]4238                        err = og_json_parse_clients(value, params);
[3bc3b45]4239                } else if (!strcmp(key, "disk")) {
[dbcc83d]4240                        err = og_json_parse_string(value, &params->disk);
[3bc3b45]4241                        params->flags |= OG_REST_PARAM_DISK;
4242                } else if (!strcmp(key, "cache")) {
[dbcc83d]4243                        err = og_json_parse_string(value, &params->cache);
[3bc3b45]4244                        params->flags |= OG_REST_PARAM_CACHE;
4245                } else if (!strcmp(key, "cache_size")) {
[dbcc83d]4246                        err = og_json_parse_string(value, &params->cache_size);
[3bc3b45]4247                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
4248                } else if (!strcmp(key, "partition_setup")) {
4249                        err = og_json_parse_partition_setup(value, params);
4250                }
[dbcc83d]4251
4252                if (err < 0)
4253                        break;
4254        }
4255
[3bc3b45]4256        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4257                                            OG_REST_PARAM_DISK |
4258                                            OG_REST_PARAM_CACHE |
4259                                            OG_REST_PARAM_CACHE_SIZE |
4260                                            OG_REST_PARAM_PART_0 |
4261                                            OG_REST_PARAM_PART_1 |
4262                                            OG_REST_PARAM_PART_2 |
4263                                            OG_REST_PARAM_PART_3))
4264                return -1;
4265
[dbcc83d]4266        len = snprintf(buf, sizeof(buf),
4267                        "nfn=Configurar\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!",
4268                        params->disk, params->disk, params->cache, params->cache_size);
4269
4270        for (unsigned int i = 0; i < OG_PARTITION_MAX; ++i) {
[3bc3b45]4271                const struct og_partition *part = &params->partition_setup[i];
[dbcc83d]4272
4273                len += snprintf(buf + strlen(buf), sizeof(buf),
4274                        "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%",
4275                        part->number, part->code, part->filesystem, part->size, part->format);
4276        }
4277
4278        msg = og_msg_alloc(buf, len + 1);
4279        if (!msg)
4280                return -1;
4281
4282        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4283                        CLIENTE_OCUPADO, msg);
4284
4285        og_msg_free(msg);
4286
4287        return 0;
4288}
4289
[2f7e9da]4290static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
4291{
4292        const char *key;
4293        json_t *value;
[723f110]4294        int err = 0;
[2f7e9da]4295
4296        json_object_foreach(element, key, value) {
4297                if (!strcmp(key, "clients"))
4298                        err = og_json_parse_clients(value, params);
4299
4300                if (err < 0)
4301                        break;
4302        }
4303
[6066b32]4304        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
4305                return -1;
4306
[723f110]4307        og_cmd_legacy_send(params, "EjecutaComandosPendientes", CLIENTE_OCUPADO);
[2f7e9da]4308
4309        return 0;
4310}
4311
[01e77f4]4312static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params)
4313{
4314        char buf[4096] = {};
4315        int err = 0, len;
4316        const char *key;
4317        json_t *value;
4318        TRAMA *msg;
4319
4320        if (json_typeof(element) != JSON_OBJECT)
4321                return -1;
4322
4323        json_object_foreach(element, key, value) {
[82a1d5a]4324                if (!strcmp(key, "clients")) {
[01e77f4]4325                        err = og_json_parse_clients(value, params);
[82a1d5a]4326                } else if (!strcmp(key, "disk")) {
[01e77f4]4327                        err = og_json_parse_string(value, &params->disk);
[82a1d5a]4328                        params->flags |= OG_REST_PARAM_DISK;
4329                } else if (!strcmp(key, "partition")) {
[01e77f4]4330                        err = og_json_parse_string(value, &params->partition);
[82a1d5a]4331                        params->flags |= OG_REST_PARAM_PARTITION;
4332                } else if (!strcmp(key, "code")) {
[01e77f4]4333                        err = og_json_parse_string(value, &params->code);
[82a1d5a]4334                        params->flags |= OG_REST_PARAM_CODE;
4335                } else if (!strcmp(key, "id")) {
[01e77f4]4336                        err = og_json_parse_string(value, &params->id);
[82a1d5a]4337                        params->flags |= OG_REST_PARAM_ID;
4338                } else if (!strcmp(key, "name")) {
[01e77f4]4339                        err = og_json_parse_string(value, &params->name);
[82a1d5a]4340                        params->flags |= OG_REST_PARAM_NAME;
4341                } else if (!strcmp(key, "repository")) {
[01e77f4]4342                        err = og_json_parse_string(value, &params->repository);
[82a1d5a]4343                        params->flags |= OG_REST_PARAM_REPO;
4344                } else if (!strcmp(key, "sync_params")) {
4345                        err = og_json_parse_sync_params(value, params);
4346                }
[01e77f4]4347
4348                if (err < 0)
4349                        break;
4350        }
4351
[82a1d5a]4352        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4353                                            OG_REST_PARAM_DISK |
4354                                            OG_REST_PARAM_PARTITION |
4355                                            OG_REST_PARAM_CODE |
4356                                            OG_REST_PARAM_ID |
4357                                            OG_REST_PARAM_NAME |
4358                                            OG_REST_PARAM_REPO |
4359                                            OG_REST_PARAM_SYNC_SYNC |
4360                                            OG_REST_PARAM_SYNC_DIFF |
4361                                            OG_REST_PARAM_SYNC_REMOVE |
4362                                            OG_REST_PARAM_SYNC_COMPRESS |
4363                                            OG_REST_PARAM_SYNC_CLEANUP |
4364                                            OG_REST_PARAM_SYNC_CACHE |
4365                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4366                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4367                return -1;
4368
[01e77f4]4369        len = snprintf(buf, sizeof(buf),
4370                       "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r"
4371                       "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r"
4372                       "cpc=%s\rbpc=%s\rnba=%s\r",
4373                       params->disk, params->partition, params->code, params->id,
4374                       params->name, params->repository, params->sync_setup.sync,
4375                       params->sync_setup.diff, params->sync_setup.remove,
4376                       params->sync_setup.compress, params->sync_setup.cleanup,
4377                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4378                       params->sync_setup.remove_dst);
4379
4380        msg = og_msg_alloc(buf, len);
4381        if (!msg)
4382                return -1;
4383
4384        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4385                    CLIENTE_OCUPADO, msg);
4386
4387        og_msg_free(msg);
4388
4389        return 0;
4390}
4391
[43c7da8]4392static int og_cmd_create_incremental_image(json_t *element, struct og_msg_params *params)
4393{
4394        char buf[4096] = {};
4395        int err = 0, len;
4396        const char *key;
4397        json_t *value;
4398        TRAMA *msg;
4399
4400        if (json_typeof(element) != JSON_OBJECT)
4401                return -1;
4402
4403        json_object_foreach(element, key, value) {
4404                if (!strcmp(key, "clients"))
4405                        err = og_json_parse_clients(value, params);
[6a0e5fa]4406                else if (!strcmp(key, "disk")) {
[43c7da8]4407                        err = og_json_parse_string(value, &params->disk);
[6a0e5fa]4408                        params->flags |= OG_REST_PARAM_DISK;
4409                } else if (!strcmp(key, "partition")) {
[43c7da8]4410                        err = og_json_parse_string(value, &params->partition);
[6a0e5fa]4411                        params->flags |= OG_REST_PARAM_PARTITION;
4412                } else if (!strcmp(key, "id")) {
[43c7da8]4413                        err = og_json_parse_string(value, &params->id);
[6a0e5fa]4414                        params->flags |= OG_REST_PARAM_ID;
4415                } else if (!strcmp(key, "name")) {
[43c7da8]4416                        err = og_json_parse_string(value, &params->name);
[6a0e5fa]4417                        params->flags |= OG_REST_PARAM_NAME;
4418                } else if (!strcmp(key, "repository")) {
[43c7da8]4419                        err = og_json_parse_string(value, &params->repository);
[6a0e5fa]4420                        params->flags |= OG_REST_PARAM_REPO;
4421                } else if (!strcmp(key, "sync_params")) {
4422                        err = og_json_parse_sync_params(value, params);
4423                }
[43c7da8]4424
4425                if (err < 0)
4426                        break;
4427        }
4428
[6a0e5fa]4429        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4430                                            OG_REST_PARAM_DISK |
4431                                            OG_REST_PARAM_PARTITION |
4432                                            OG_REST_PARAM_ID |
4433                                            OG_REST_PARAM_NAME |
4434                                            OG_REST_PARAM_REPO |
4435                                            OG_REST_PARAM_SYNC_SYNC |
4436                                            OG_REST_PARAM_SYNC_PATH |
4437                                            OG_REST_PARAM_SYNC_DIFF |
4438                                            OG_REST_PARAM_SYNC_DIFF_ID |
4439                                            OG_REST_PARAM_SYNC_DIFF_NAME |
4440                                            OG_REST_PARAM_SYNC_REMOVE |
4441                                            OG_REST_PARAM_SYNC_COMPRESS |
4442                                            OG_REST_PARAM_SYNC_CLEANUP |
4443                                            OG_REST_PARAM_SYNC_CACHE |
4444                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4445                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4446                return -1;
4447
[43c7da8]4448        len = snprintf(buf, sizeof(buf),
4449                       "nfn=CrearSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4450                       "rti=%s\ripr=%s\ridf=%s\rncf=%s\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\r"
4451                       "bpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
4452                       params->disk, params->partition, params->id, params->name,
4453                       params->sync_setup.path, params->repository, params->sync_setup.diff_id,
4454                       params->sync_setup.diff_name, params->sync_setup.sync,
4455                       params->sync_setup.diff, params->sync_setup.remove_dst,
4456                       params->sync_setup.compress, params->sync_setup.cleanup,
4457                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4458                       params->sync_setup.remove_dst);
4459
4460        msg = og_msg_alloc(buf, len);
4461        if (!msg)
4462                return -1;
4463
4464        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4465                    CLIENTE_OCUPADO, msg);
4466
4467        og_msg_free(msg);
4468
4469        return 0;
4470}
4471
[f61fd9a]4472static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params)
4473{
4474        char buf[4096] = {};
4475        int err = 0, len;
4476        const char *key;
4477        json_t *value;
4478        TRAMA *msg;
4479
4480        if (json_typeof(element) != JSON_OBJECT)
4481                return -1;
4482
4483        json_object_foreach(element, key, value) {
[f51c245]4484                if (!strcmp(key, "clients")) {
[f61fd9a]4485                        err = og_json_parse_clients(value, params);
[f51c245]4486                } else if (!strcmp(key, "disk")) {
[f61fd9a]4487                        err = og_json_parse_string(value, &params->disk);
[f51c245]4488                        params->flags |= OG_REST_PARAM_DISK;
4489                } else if (!strcmp(key, "partition")) {
[f61fd9a]4490                        err = og_json_parse_string(value, &params->partition);
[f51c245]4491                        params->flags |= OG_REST_PARAM_PARTITION;
4492                } else if (!strcmp(key, "id")) {
[f61fd9a]4493                        err = og_json_parse_string(value, &params->id);
[f51c245]4494                        params->flags |= OG_REST_PARAM_ID;
4495                } else if (!strcmp(key, "name")) {
[f61fd9a]4496                        err = og_json_parse_string(value, &params->name);
[f51c245]4497                        params->flags |= OG_REST_PARAM_NAME;
4498                } else if (!strcmp(key, "repository")) {
[f61fd9a]4499                        err = og_json_parse_string(value, &params->repository);
[f51c245]4500                        params->flags |= OG_REST_PARAM_REPO;
4501                } else if (!strcmp(key, "profile")) {
[f61fd9a]4502                        err = og_json_parse_string(value, &params->profile);
[f51c245]4503                        params->flags |= OG_REST_PARAM_PROFILE;
4504                } else if (!strcmp(key, "type")) {
[f61fd9a]4505                        err = og_json_parse_string(value, &params->type);
[f51c245]4506                        params->flags |= OG_REST_PARAM_TYPE;
4507                } else if (!strcmp(key, "sync_params")) {
4508                        err = og_json_parse_sync_params(value, params);
4509                }
[f61fd9a]4510
4511                if (err < 0)
4512                        break;
4513        }
4514
[f51c245]4515        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4516                                            OG_REST_PARAM_DISK |
4517                                            OG_REST_PARAM_PARTITION |
4518                                            OG_REST_PARAM_ID |
4519                                            OG_REST_PARAM_NAME |
4520                                            OG_REST_PARAM_REPO |
4521                                            OG_REST_PARAM_PROFILE |
4522                                            OG_REST_PARAM_TYPE |
4523                                            OG_REST_PARAM_SYNC_PATH |
4524                                            OG_REST_PARAM_SYNC_METHOD |
4525                                            OG_REST_PARAM_SYNC_SYNC |
4526                                            OG_REST_PARAM_SYNC_DIFF |
4527                                            OG_REST_PARAM_SYNC_REMOVE |
4528                                            OG_REST_PARAM_SYNC_COMPRESS |
4529                                            OG_REST_PARAM_SYNC_CLEANUP |
4530                                            OG_REST_PARAM_SYNC_CACHE |
4531                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4532                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4533                return -1;
4534
[f61fd9a]4535        len = snprintf(buf, sizeof(buf),
4536                       "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4537                           "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r"
4538                           "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
4539                       params->disk, params->partition, params->id, params->name,
4540                           params->repository, params->profile, params->sync_setup.path,
4541                           params->sync_setup.method, params->sync_setup.sync, params->type,
4542                           params->sync_setup.diff, params->sync_setup.remove,
4543                       params->sync_setup.compress, params->sync_setup.cleanup,
4544                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4545                       params->sync_setup.remove_dst);
4546
4547        msg = og_msg_alloc(buf, len);
4548        if (!msg)
4549                return -1;
4550
4551        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4552                    CLIENTE_OCUPADO, msg);
4553
4554        og_msg_free(msg);
4555
4556        return 0;
4557}
4558
[d52c6d0]4559static int og_cmd_restore_incremental_image(json_t *element, struct og_msg_params *params)
4560{
4561        char buf[4096] = {};
4562        int err = 0, len;
4563        const char *key;
4564        json_t *value;
4565        TRAMA *msg;
4566
4567        if (json_typeof(element) != JSON_OBJECT)
4568                return -1;
4569
4570        json_object_foreach(element, key, value) {
[4f78553]4571                if (!strcmp(key, "clients")) {
[d52c6d0]4572                        err = og_json_parse_clients(value, params);
[4f78553]4573                } else if (!strcmp(key, "disk")) {
[d52c6d0]4574                        err = og_json_parse_string(value, &params->disk);
[4f78553]4575                        params->flags |= OG_REST_PARAM_DISK;
4576                } else if (!strcmp(key, "partition")) {
[d52c6d0]4577                        err = og_json_parse_string(value, &params->partition);
[4f78553]4578                        params->flags |= OG_REST_PARAM_PARTITION;
4579                } else if (!strcmp(key, "id")) {
[d52c6d0]4580                        err = og_json_parse_string(value, &params->id);
[4f78553]4581                        params->flags |= OG_REST_PARAM_ID;
4582                } else if (!strcmp(key, "name")) {
[d52c6d0]4583                        err = og_json_parse_string(value, &params->name);
[4f78553]4584                        params->flags |= OG_REST_PARAM_NAME;
4585                } else if (!strcmp(key, "repository")) {
[d52c6d0]4586                        err = og_json_parse_string(value, &params->repository);
[4f78553]4587                        params->flags |= OG_REST_PARAM_REPO;
4588                } else if (!strcmp(key, "profile")) {
[d52c6d0]4589                        err = og_json_parse_string(value, &params->profile);
[4f78553]4590                        params->flags |= OG_REST_PARAM_PROFILE;
4591                } else if (!strcmp(key, "type")) {
[d52c6d0]4592                        err = og_json_parse_string(value, &params->type);
[4f78553]4593                        params->flags |= OG_REST_PARAM_TYPE;
4594                } else if (!strcmp(key, "sync_params")) {
4595                        err = og_json_parse_sync_params(value, params);
4596                }
[d52c6d0]4597
4598                if (err < 0)
4599                        break;
4600        }
4601
[4f78553]4602        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4603                                            OG_REST_PARAM_DISK |
4604                                            OG_REST_PARAM_PARTITION |
4605                                            OG_REST_PARAM_ID |
4606                                            OG_REST_PARAM_NAME |
4607                                            OG_REST_PARAM_REPO |
4608                                            OG_REST_PARAM_PROFILE |
4609                                            OG_REST_PARAM_TYPE |
4610                                            OG_REST_PARAM_SYNC_DIFF_ID |
4611                                            OG_REST_PARAM_SYNC_DIFF_NAME |
4612                                            OG_REST_PARAM_SYNC_PATH |
4613                                            OG_REST_PARAM_SYNC_METHOD |
4614                                            OG_REST_PARAM_SYNC_SYNC |
4615                                            OG_REST_PARAM_SYNC_DIFF |
4616                                            OG_REST_PARAM_SYNC_REMOVE |
4617                                            OG_REST_PARAM_SYNC_COMPRESS |
4618                                            OG_REST_PARAM_SYNC_CLEANUP |
4619                                            OG_REST_PARAM_SYNC_CACHE |
4620                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
4621                                            OG_REST_PARAM_SYNC_REMOVE_DST))
4622                return -1;
4623
[d52c6d0]4624        len = snprintf(buf, sizeof(buf),
4625                       "nfn=RestaurarSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
4626                           "ipr=%s\rifs=%s\ridf=%s\rncf=%s\rrti=%s\rmet=%s\rmsy=%s\r"
4627                           "tpt=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\r"
4628                           "nba=%s\r",
4629                       params->disk, params->partition, params->id, params->name,
4630                           params->repository, params->profile, params->sync_setup.diff_id,
4631                           params->sync_setup.diff_name, params->sync_setup.path,
4632                           params->sync_setup.method, params->sync_setup.sync, params->type,
4633                           params->sync_setup.diff, params->sync_setup.remove,
4634                       params->sync_setup.compress, params->sync_setup.cleanup,
4635                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
4636                       params->sync_setup.remove_dst);
4637
4638        msg = og_msg_alloc(buf, len);
4639        if (!msg)
4640                return -1;
4641
4642        og_send_cmd((char **)params->ips_array, params->ips_array_len,
4643                    CLIENTE_OCUPADO, msg);
4644
4645        og_msg_free(msg);
4646
4647        return 0;
4648}
4649
[7dc8fdb]4650static int og_client_method_not_found(struct og_client *cli)
4651{
4652        /* To meet RFC 7231, this function MUST generate an Allow header field
4653         * containing the correct methods. For example: "Allow: POST\r\n"
4654         */
4655        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
4656                     "Content-Length: 0\r\n\r\n";
4657
4658        send(og_client_socket(cli), buf, strlen(buf), 0);
4659
4660        return -1;
4661}
4662
[c1c89e1]4663static int og_client_bad_request(struct og_client *cli)
4664{
4665        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
4666
4667        send(og_client_socket(cli), buf, strlen(buf), 0);
4668
4669        return -1;
4670}
4671
[95e6520]4672static int og_client_not_found(struct og_client *cli)
4673{
4674        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
4675
4676        send(og_client_socket(cli), buf, strlen(buf), 0);
4677
4678        return -1;
4679}
4680
[fd30540]4681static int og_client_not_authorized(struct og_client *cli)
4682{
[66001f0]4683        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
4684                     "WWW-Authenticate: Basic\r\n"
4685                     "Content-Length: 0\r\n\r\n";
[fd30540]4686
4687        send(og_client_socket(cli), buf, strlen(buf), 0);
4688
4689        return -1;
4690}
4691
[15685e6]4692static int og_server_internal_error(struct og_client *cli)
4693{
4694        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
4695                     "Content-Length: 0\r\n\r\n";
4696
4697        send(og_client_socket(cli), buf, strlen(buf), 0);
4698
4699        return -1;
4700}
4701
[e80c85f]4702#define OG_MSG_RESPONSE_MAXLEN  65536
4703
[7b6fcdb]4704static int og_client_ok(struct og_client *cli, char *buf_reply)
[95e6520]4705{
[e80c85f]4706        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
[fbc30b2]4707        int err = 0, len;
[7b6fcdb]4708
[fbc30b2]4709        len = snprintf(buf, sizeof(buf),
4710                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
4711                       strlen(buf_reply), buf_reply);
[15685e6]4712        if (len >= (int)sizeof(buf))
4713                err = og_server_internal_error(cli);
[95e6520]4714
4715        send(og_client_socket(cli), buf, strlen(buf), 0);
4716
[fbc30b2]4717        return err;
[95e6520]4718}
4719
4720enum og_rest_method {
4721        OG_METHOD_GET   = 0,
4722        OG_METHOD_POST,
4723};
4724
4725static int og_client_state_process_payload_rest(struct og_client *cli)
4726{
[e80c85f]4727        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
[95e6520]4728        struct og_msg_params params = {};
4729        enum og_rest_method method;
[eb6aa82]4730        const char *cmd, *body;
[95e6520]4731        json_error_t json_err;
4732        json_t *root = NULL;
4733        int err = 0;
4734
[84a2563]4735        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
4736               inet_ntoa(cli->addr.sin_addr),
4737               ntohs(cli->addr.sin_port), cli->buf);
4738
[95e6520]4739        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
4740                method = OG_METHOD_GET;
4741                cmd = cli->buf + strlen("GET") + 2;
4742        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
4743                method = OG_METHOD_POST;
4744                cmd = cli->buf + strlen("POST") + 2;
4745        } else
[7dc8fdb]4746                return og_client_method_not_found(cli);
[95e6520]4747
4748        body = strstr(cli->buf, "\r\n\r\n") + 4;
4749
[fd30540]4750        if (strcmp(cli->auth_token, auth_token)) {
4751                syslog(LOG_ERR, "wrong Authentication key\n");
4752                return og_client_not_authorized(cli);
4753        }
4754
[eb6aa82]4755        if (cli->content_length) {
[95e6520]4756                root = json_loads(body, 0, &json_err);
4757                if (!root) {
4758                        syslog(LOG_ERR, "malformed json line %d: %s\n",
4759                               json_err.line, json_err.text);
4760                        return og_client_not_found(cli);
4761                }
4762        }
4763
4764        if (!strncmp(cmd, "clients", strlen("clients"))) {
[7b6fcdb]4765                if (method != OG_METHOD_POST &&
4766                    method != OG_METHOD_GET)
[7dc8fdb]4767                        return og_client_method_not_found(cli);
[7b6fcdb]4768
4769                if (method == OG_METHOD_POST && !root) {
[95e6520]4770                        syslog(LOG_ERR, "command clients with no payload\n");
[c1c89e1]4771                        return og_client_bad_request(cli);
[95e6520]4772                }
[7b6fcdb]4773                switch (method) {
4774                case OG_METHOD_POST:
4775                        err = og_cmd_post_clients(root, &params);
4776                        break;
4777                case OG_METHOD_GET:
4778                        err = og_cmd_get_clients(root, &params, buf_reply);
4779                        break;
4780                }
[5797e0b]4781        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
4782                if (method != OG_METHOD_POST)
[7dc8fdb]4783                        return og_client_method_not_found(cli);
[5797e0b]4784
4785                if (!root) {
4786                        syslog(LOG_ERR, "command wol with no payload\n");
[c1c89e1]4787                        return og_client_bad_request(cli);
[5797e0b]4788                }
4789                err = og_cmd_wol(root, &params);
[7e4e5b5]4790        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
4791                if (method != OG_METHOD_POST)
[7dc8fdb]4792                        return og_client_method_not_found(cli);
[7e4e5b5]4793
4794                if (!root) {
4795                        syslog(LOG_ERR, "command run with no payload\n");
[c1c89e1]4796                        return og_client_bad_request(cli);
[7e4e5b5]4797                }
4798                err = og_cmd_run_post(root, &params);
[c6020f2]4799        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
4800                if (method != OG_METHOD_POST)
[7dc8fdb]4801                        return og_client_method_not_found(cli);
[c6020f2]4802
4803                if (!root) {
4804                        syslog(LOG_ERR, "command output with no payload\n");
[c1c89e1]4805                        return og_client_bad_request(cli);
[c6020f2]4806                }
4807
4808                err = og_cmd_run_get(root, &params, buf_reply);
[7ab5f0c]4809        } else if (!strncmp(cmd, "session", strlen("session"))) {
4810                if (method != OG_METHOD_POST)
[7dc8fdb]4811                        return og_client_method_not_found(cli);
[7ab5f0c]4812
4813                if (!root) {
4814                        syslog(LOG_ERR, "command session with no payload\n");
[c1c89e1]4815                        return og_client_bad_request(cli);
[7ab5f0c]4816                }
4817                err = og_cmd_session(root, &params);
[23fed47]4818        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
4819                if (method != OG_METHOD_POST)
[7dc8fdb]4820                        return og_client_method_not_found(cli);
[23fed47]4821
4822                if (!root) {
4823                        syslog(LOG_ERR, "command poweroff with no payload\n");
[c1c89e1]4824                        return og_client_bad_request(cli);
[23fed47]4825                }
4826                err = og_cmd_poweroff(root, &params);
[5f0191d]4827        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
4828                if (method != OG_METHOD_POST)
[7dc8fdb]4829                        return og_client_method_not_found(cli);
[5f0191d]4830
4831                if (!root) {
4832                        syslog(LOG_ERR, "command reboot with no payload\n");
[c1c89e1]4833                        return og_client_bad_request(cli);
[5f0191d]4834                }
4835                err = og_cmd_reboot(root, &params);
[1e6c889]4836        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
4837                if (method != OG_METHOD_POST)
[7dc8fdb]4838                        return og_client_method_not_found(cli);
[1e6c889]4839
4840                if (!root) {
4841                        syslog(LOG_ERR, "command stop with no payload\n");
[c1c89e1]4842                        return og_client_bad_request(cli);
[1e6c889]4843                }
4844                err = og_cmd_stop(root, &params);
[17f55b4]4845        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
4846                if (method != OG_METHOD_POST)
[7dc8fdb]4847                        return og_client_method_not_found(cli);
[17f55b4]4848
4849                if (!root) {
4850                        syslog(LOG_ERR, "command refresh with no payload\n");
[c1c89e1]4851                        return og_client_bad_request(cli);
[17f55b4]4852                }
4853                err = og_cmd_refresh(root, &params);
[6b30dbc]4854        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4855                if (method != OG_METHOD_POST)
[7dc8fdb]4856                        return og_client_method_not_found(cli);
[6b30dbc]4857
4858                if (!root) {
4859                        syslog(LOG_ERR, "command hardware with no payload\n");
[c1c89e1]4860                        return og_client_bad_request(cli);
[6b30dbc]4861                }
4862                err = og_cmd_hardware(root, &params);
[b4a9fdd]4863        } else if (!strncmp(cmd, "software", strlen("software"))) {
4864                if (method != OG_METHOD_POST)
[7dc8fdb]4865                        return og_client_method_not_found(cli);
[b4a9fdd]4866
4867                if (!root) {
4868                        syslog(LOG_ERR, "command software with no payload\n");
[c1c89e1]4869                        return og_client_bad_request(cli);
[b4a9fdd]4870                }
4871                err = og_cmd_software(root, &params);
[01e77f4]4872        } else if (!strncmp(cmd, "image/create/basic",
4873                            strlen("image/create/basic"))) {
4874                if (method != OG_METHOD_POST)
4875                        return og_client_method_not_found(cli);
4876
4877                if (!root) {
4878                        syslog(LOG_ERR, "command create with no payload\n");
4879                        return og_client_bad_request(cli);
4880                }
4881                err = og_cmd_create_basic_image(root, &params);
[43c7da8]4882        } else if (!strncmp(cmd, "image/create/incremental",
4883                            strlen("image/create/incremental"))) {
4884                if (method != OG_METHOD_POST)
4885                        return og_client_method_not_found(cli);
4886
4887                if (!root) {
4888                        syslog(LOG_ERR, "command create with no payload\n");
4889                        return og_client_bad_request(cli);
4890                }
4891                err = og_cmd_create_incremental_image(root, &params);
[1a8ada1]4892        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4893                if (method != OG_METHOD_POST)
4894                        return og_client_method_not_found(cli);
4895
4896                if (!root) {
4897                        syslog(LOG_ERR, "command create with no payload\n");
4898                        return og_client_bad_request(cli);
4899                }
4900                err = og_cmd_create_image(root, &params);
[f61fd9a]4901        } else if (!strncmp(cmd, "image/restore/basic",
4902                                strlen("image/restore/basic"))) {
4903                if (method != OG_METHOD_POST)
4904                        return og_client_method_not_found(cli);
4905
4906                if (!root) {
4907                        syslog(LOG_ERR, "command create with no payload\n");
4908                        return og_client_bad_request(cli);
4909                }
4910                err = og_cmd_restore_basic_image(root, &params);
[d52c6d0]4911        } else if (!strncmp(cmd, "image/restore/incremental",
4912                                strlen("image/restore/incremental"))) {
4913                if (method != OG_METHOD_POST)
4914                        return og_client_method_not_found(cli);
4915
4916                if (!root) {
4917                        syslog(LOG_ERR, "command create with no payload\n");
4918                        return og_client_bad_request(cli);
4919                }
4920                err = og_cmd_restore_incremental_image(root, &params);
[1dde02e]4921        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4922                if (method != OG_METHOD_POST)
4923                        return og_client_method_not_found(cli);
4924
4925                if (!root) {
4926                        syslog(LOG_ERR, "command create with no payload\n");
4927                        return og_client_bad_request(cli);
4928                }
4929                err = og_cmd_restore_image(root, &params);
[6c91d14]4930        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
[dbcc83d]4931                if (method != OG_METHOD_POST)
4932                        return og_client_method_not_found(cli);
4933
4934                if (!root) {
4935                        syslog(LOG_ERR, "command create with no payload\n");
4936                        return og_client_bad_request(cli);
4937                }
[6c91d14]4938                err = og_cmd_setup(root, &params);
[2f7e9da]4939        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4940                if (method != OG_METHOD_POST)
4941                        return og_client_method_not_found(cli);
4942
4943                if (!root) {
4944                        syslog(LOG_ERR, "command create with no payload\n");
4945                        return og_client_bad_request(cli);
4946                }
4947
4948                err = og_cmd_run_schedule(root, &params);
[95e6520]4949        } else {
[7c67487]4950                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
[95e6520]4951                err = og_client_not_found(cli);
4952        }
4953
[7b6fcdb]4954        if (root)
4955                json_decref(root);
[95e6520]4956
[a12af6a]4957        if (err < 0)
[8fa082d]4958                return og_client_bad_request(cli);
[a12af6a]4959
4960        err = og_client_ok(cli, buf_reply);
4961        if (err < 0) {
4962                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4963                       inet_ntoa(cli->addr.sin_addr),
4964                       ntohs(cli->addr.sin_port));
4965        }
[95e6520]4966
4967        return err;
4968}
4969
4970static int og_client_state_recv_hdr_rest(struct og_client *cli)
4971{
[eb6aa82]4972        char *ptr;
[95e6520]4973
[eb6aa82]4974        ptr = strstr(cli->buf, "\r\n\r\n");
4975        if (!ptr)
[95e6520]4976                return 0;
4977
[eb6aa82]4978        cli->msg_len = ptr - cli->buf + 4;
4979
4980        ptr = strstr(cli->buf, "Content-Length: ");
4981        if (ptr) {
4982                sscanf(ptr, "Content-Length: %i[^\r\n]", &cli->content_length);
[36ad006]4983                if (cli->content_length < 0)
4984                        return -1;
[eb6aa82]4985                cli->msg_len += cli->content_length;
4986        }
4987
[fd30540]4988        ptr = strstr(cli->buf, "Authorization: ");
4989        if (ptr)
[64e6537]4990                sscanf(ptr, "Authorization: %63[^\r\n]", cli->auth_token);
[fd30540]4991
[95e6520]4992        return 1;
4993}
4994
[107b17a]4995static void og_client_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
4996{
4997        struct og_client *cli;
4998        int ret;
[212280e]4999
5000        cli = container_of(io, struct og_client, io);
5001
[f09aca6]5002        if (events & EV_ERROR) {
5003                syslog(LOG_ERR, "unexpected error event from client %s:%hu\n",
5004                               inet_ntoa(cli->addr.sin_addr),
5005                               ntohs(cli->addr.sin_port));
5006                goto close;
5007        }
5008
[212280e]5009        ret = recv(io->fd, cli->buf + cli->buf_len,
5010                   sizeof(cli->buf) - cli->buf_len, 0);
[f09aca6]5011        if (ret <= 0) {
5012                if (ret < 0) {
5013                        syslog(LOG_ERR, "error reading from client %s:%hu (%s)\n",
5014                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
5015                               strerror(errno));
5016                } else {
[2ed3a0c]5017                        syslog(LOG_DEBUG, "closed connection by %s:%hu\n",
[f09aca6]5018                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
5019                }
[212280e]5020                goto close;
[f09aca6]5021        }
5022
5023        if (cli->keepalive_idx >= 0)
5024                return;
[212280e]5025
5026        ev_timer_again(loop, &cli->timer);
5027
5028        cli->buf_len += ret;
[20dcb0a]5029        if (cli->buf_len >= sizeof(cli->buf)) {
5030                syslog(LOG_ERR, "client request from %s:%hu is too long\n",
5031                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
5032                goto close;
5033        }
[212280e]5034
5035        switch (cli->state) {
5036        case OG_CLIENT_RECEIVING_HEADER:
[95e6520]5037                if (cli->rest)
5038                        ret = og_client_state_recv_hdr_rest(cli);
5039                else
5040                        ret = og_client_state_recv_hdr(cli);
5041
[d491dfd]5042                if (ret < 0)
[212280e]5043                        goto close;
[d491dfd]5044                if (!ret)
5045                        return;
[212280e]5046
5047                cli->state = OG_CLIENT_RECEIVING_PAYLOAD;
5048                /* Fall through. */
5049        case OG_CLIENT_RECEIVING_PAYLOAD:
5050                /* Still not enough data to process request. */
5051                if (cli->buf_len < cli->msg_len)
5052                        return;
5053
5054                cli->state = OG_CLIENT_PROCESSING_REQUEST;
5055                /* fall through. */
5056        case OG_CLIENT_PROCESSING_REQUEST:
[a12af6a]5057                if (cli->rest) {
[95e6520]5058                        ret = og_client_state_process_payload_rest(cli);
[a12af6a]5059                        if (ret < 0) {
5060                                syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n",
5061                                       inet_ntoa(cli->addr.sin_addr),
5062                                       ntohs(cli->addr.sin_port));
5063                        }
5064                } else {
[95e6520]5065                        ret = og_client_state_process_payload(cli);
[a12af6a]5066                }
[107b17a]5067                if (ret < 0)
[212280e]5068                        goto close;
5069
[f09aca6]5070                if (cli->keepalive_idx < 0) {
[2ed3a0c]5071                        syslog(LOG_DEBUG, "server closing connection to %s:%hu\n",
[f09aca6]5072                               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[212280e]5073                        goto close;
[f09aca6]5074                } else {
[2ed3a0c]5075                        syslog(LOG_DEBUG, "leaving client %s:%hu in keepalive mode\n",
[f09aca6]5076                               inet_ntoa(cli->addr.sin_addr),
5077                               ntohs(cli->addr.sin_port));
5078                        og_client_keepalive(loop, cli);
5079                        og_client_reset_state(cli);
5080                }
[212280e]5081                break;
[ef6e3d2]5082        default:
5083                syslog(LOG_ERR, "unknown state, critical internal error\n");
5084                goto close;
[8e0216a]5085        }
[212280e]5086        return;
5087close:
5088        ev_timer_stop(loop, &cli->timer);
[f09aca6]5089        og_client_release(loop, cli);
[8e0216a]5090}
5091
[212280e]5092static void og_client_timer_cb(struct ev_loop *loop, ev_timer *timer, int events)
5093{
5094        struct og_client *cli;
5095
5096        cli = container_of(timer, struct og_client, timer);
[f09aca6]5097        if (cli->keepalive_idx >= 0) {
[212280e]5098                ev_timer_again(loop, &cli->timer);
5099                return;
5100        }
[f09aca6]5101        syslog(LOG_ERR, "timeout request for client %s:%hu\n",
5102               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[ef6e3d2]5103
[f09aca6]5104        og_client_release(loop, cli);
[212280e]5105}
5106
[95e6520]5107static int socket_s, socket_rest;
5108
[212280e]5109static void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io,
5110                                int events)
5111{
5112        struct sockaddr_in client_addr;
5113        socklen_t addrlen = sizeof(client_addr);
5114        struct og_client *cli;
5115        int client_sd;
5116
5117        if (events & EV_ERROR)
5118                return;
5119
5120        client_sd = accept(io->fd, (struct sockaddr *)&client_addr, &addrlen);
5121        if (client_sd < 0) {
[b56cbeb]5122                syslog(LOG_ERR, "cannot accept client connection\n");
[212280e]5123                return;
5124        }
5125
5126        cli = (struct og_client *)calloc(1, sizeof(struct og_client));
5127        if (!cli) {
5128                close(client_sd);
5129                return;
5130        }
[ef6e3d2]5131        memcpy(&cli->addr, &client_addr, sizeof(client_addr));
[f09aca6]5132        cli->keepalive_idx = -1;
[ef6e3d2]5133
[95e6520]5134        if (io->fd == socket_rest)
5135                cli->rest = true;
5136
[2ed3a0c]5137        syslog(LOG_DEBUG, "connection from client %s:%hu\n",
[f09aca6]5138               inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
[212280e]5139
5140        ev_io_init(&cli->io, og_client_read_cb, client_sd, EV_READ);
5141        ev_io_start(loop, &cli->io);
5142        ev_timer_init(&cli->timer, og_client_timer_cb, OG_CLIENT_TIMEOUT, 0.);
5143        ev_timer_start(loop, &cli->timer);
5144}
5145
[e3e4e6f]5146static int og_socket_server_init(const char *port)
5147{
5148        struct sockaddr_in local;
5149        int sd, on = 1;
5150
5151        sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
5152        if (sd < 0) {
5153                syslog(LOG_ERR, "cannot create main socket\n");
5154                return -1;
5155        }
5156        setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
5157
5158        local.sin_addr.s_addr = htonl(INADDR_ANY);
5159        local.sin_family = AF_INET;
5160        local.sin_port = htons(atoi(port));
5161
5162        if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) {
[8b1bedd]5163                close(sd);
[e3e4e6f]5164                syslog(LOG_ERR, "cannot bind socket\n");
5165                return -1;
5166        }
5167
5168        listen(sd, 250);
5169
5170        return sd;
5171}
5172
[212280e]5173int main(int argc, char *argv[])
5174{
[95e6520]5175        struct ev_io ev_io_server, ev_io_server_rest;
[212280e]5176        struct ev_loop *loop = ev_default_loop(0);
5177        int i;
[b9eb98b]5178
[9fc0037]5179        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
5180                exit(EXIT_FAILURE);
5181
[57c8c50]5182        openlog("ogAdmServer", LOG_PID, LOG_DAEMON);
[ef6e3d2]5183
[b9eb98b]5184        /*--------------------------------------------------------------------------------------------------------
5185         Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
5186         ---------------------------------------------------------------------------------------------------------*/
5187        if (!validacionParametros(argc, argv, 1)) // Valida parámetros de ejecución
5188                exit(EXIT_FAILURE);
5189
5190        if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
5191                exit(EXIT_FAILURE);
5192        }
5193
5194        /*--------------------------------------------------------------------------------------------------------
5195         // Inicializa array de información de los clientes
5196         ---------------------------------------------------------------------------------------------------------*/
5197        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
5198                tbsockets[i].ip[0] = '\0';
[f09aca6]5199                tbsockets[i].cli = NULL;
[b9eb98b]5200        }
5201        /*--------------------------------------------------------------------------------------------------------
5202         Creación y configuración del socket del servicio
5203         ---------------------------------------------------------------------------------------------------------*/
[e3e4e6f]5204        socket_s = og_socket_server_init(puerto);
5205        if (socket_s < 0)
[b9eb98b]5206                exit(EXIT_FAILURE);
[212280e]5207
5208        ev_io_init(&ev_io_server, og_server_accept_cb, socket_s, EV_READ);
5209        ev_io_start(loop, &ev_io_server);
5210
[95e6520]5211        socket_rest = og_socket_server_init("8888");
5212        if (socket_rest < 0)
5213                exit(EXIT_FAILURE);
5214
5215        ev_io_init(&ev_io_server_rest, og_server_accept_cb, socket_rest, EV_READ);
5216        ev_io_start(loop, &ev_io_server_rest);
5217
[b9eb98b]5218        infoLog(1); // Inicio de sesión
[212280e]5219
[effbcea]5220        /* old log file has been deprecated. */
5221        og_log(97, false);
5222
[ef6e3d2]5223        syslog(LOG_INFO, "Waiting for connections\n");
5224
[212280e]5225        while (1)
5226                ev_loop(loop, 0);
5227
[b9eb98b]5228        exit(EXIT_SUCCESS);
5229}
Note: See TracBrowser for help on using the repository browser.