source: ogServer-Git/sources/ogAdmServer.c @ e81d230

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

#971 remove obsolete code

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