source: ogServer-Git/sources/ogAdmServer.c @ 16e45fa

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

#980 add procedure auto execution

Users can configure clients to execute a procedure at start.

This commit adapt this functionality to new functions and behaviour
of the ogAdmServer.

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