source: ogServer-Git/sources/ogAdmServer.c @ 0b9465f

Last change on this file since 0b9465f was cf7bbda, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#971 move ogAdmLib to ogAdmServer

Move remaining ogAdmLib code to ogAdmServer

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