source: ogServer-Git/sources/ogAdmServer.c @ 130b6ff

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

#942 Add weeks and week days to the schedule API

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