source: ogServer-Git/src/rest.c @ 532b081

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

#980 Fix POST /modes to use 'setclientmode' script

Now POST /modes does not only write to the database, it also uses the
external bash script 'setclientmode' to generate configured PXE
templates for each machine.

NOTE: This fix requires that room and computer names are unique in the
OpenGnsys DB. This behaviour is inherited from the previous
'setclientmode' script but, eventually, it should be replaced for an
actual scope selector.

  • Property mode set to 100644
File size: 96.5 KB
Line 
1/*
2 * Copyright (C) 2020 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation, version 3.
7 */
8
9#include "ogAdmServer.h"
10#include "dbi.h"
11#include "utils.h"
12#include "list.h"
13#include "rest.h"
14#include "cfg.h"
15#include "schedule.h"
16#include <ev.h>
17#include <syslog.h>
18#include <sys/ioctl.h>
19#include <ifaddrs.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <jansson.h>
24#include <dirent.h>
25#include <time.h>
26#include <stdlib.h>
27
28struct ev_loop *og_loop;
29
30static TRAMA *og_msg_alloc(char *data, unsigned int len)
31{
32        TRAMA *ptrTrama;
33
34        ptrTrama = calloc(1, sizeof(TRAMA));
35        if (!ptrTrama) {
36                syslog(LOG_ERR, "OOM\n");
37                return NULL;
38        }
39
40        initParametros(ptrTrama, len);
41        memcpy(ptrTrama, "@JMMLCAMDJ_MCDJ", LONGITUD_CABECERATRAMA);
42        memcpy(ptrTrama->parametros, data, len);
43        ptrTrama->lonprm = len;
44
45        return ptrTrama;
46}
47
48static void og_msg_free(TRAMA *ptrTrama)
49{
50        free(ptrTrama->parametros);
51        free(ptrTrama);
52}
53
54static bool og_send_cmd(char *ips_array[], int ips_array_len,
55                        const char *state, TRAMA *ptrTrama)
56{
57        int i, idx;
58
59        for (i = 0; i < ips_array_len; i++) {
60                if (clienteDisponible(ips_array[i], &idx)) { // Si el cliente puede recibir comandos
61                        int sock = tbsockets[idx].cli ? tbsockets[idx].cli->io.fd : -1;
62
63                        strcpy(tbsockets[idx].estado, state); // Actualiza el estado del cliente
64                        if (sock >= 0 && !mandaTrama(&sock, ptrTrama)) {
65                                syslog(LOG_ERR, "failed to send response to %s:%s\n",
66                                       ips_array[i], strerror(errno));
67                        }
68                }
69        }
70        return true;
71}
72
73#define OG_REST_PARAM_ADDR                      (1UL << 0)
74#define OG_REST_PARAM_MAC                       (1UL << 1)
75#define OG_REST_PARAM_WOL_TYPE                  (1UL << 2)
76#define OG_REST_PARAM_RUN_CMD                   (1UL << 3)
77#define OG_REST_PARAM_DISK                      (1UL << 4)
78#define OG_REST_PARAM_PARTITION                 (1UL << 5)
79#define OG_REST_PARAM_REPO                      (1UL << 6)
80#define OG_REST_PARAM_NAME                      (1UL << 7)
81#define OG_REST_PARAM_ID                        (1UL << 8)
82#define OG_REST_PARAM_CODE                      (1UL << 9)
83#define OG_REST_PARAM_TYPE                      (1UL << 10)
84#define OG_REST_PARAM_PROFILE                   (1UL << 11)
85#define OG_REST_PARAM_CACHE                     (1UL << 12)
86#define OG_REST_PARAM_CACHE_SIZE                (1UL << 13)
87#define OG_REST_PARAM_PART_0                    (1UL << 14)
88#define OG_REST_PARAM_PART_1                    (1UL << 15)
89#define OG_REST_PARAM_PART_2                    (1UL << 16)
90#define OG_REST_PARAM_PART_3                    (1UL << 17)
91#define OG_REST_PARAM_SYNC_SYNC                 (1UL << 18)
92#define OG_REST_PARAM_SYNC_DIFF                 (1UL << 19)
93#define OG_REST_PARAM_SYNC_REMOVE               (1UL << 20)
94#define OG_REST_PARAM_SYNC_COMPRESS             (1UL << 21)
95#define OG_REST_PARAM_SYNC_CLEANUP              (1UL << 22)
96#define OG_REST_PARAM_SYNC_CACHE                (1UL << 23)
97#define OG_REST_PARAM_SYNC_CLEANUP_CACHE        (1UL << 24)
98#define OG_REST_PARAM_SYNC_REMOVE_DST           (1UL << 25)
99#define OG_REST_PARAM_SYNC_DIFF_ID              (1UL << 26)
100#define OG_REST_PARAM_SYNC_DIFF_NAME            (1UL << 27)
101#define OG_REST_PARAM_SYNC_PATH                 (1UL << 28)
102#define OG_REST_PARAM_SYNC_METHOD               (1UL << 29)
103#define OG_REST_PARAM_ECHO                      (1UL << 30)
104#define OG_REST_PARAM_TASK                      (1UL << 31)
105#define OG_REST_PARAM_TIME_YEARS                (1UL << 32)
106#define OG_REST_PARAM_TIME_MONTHS               (1UL << 33)
107#define OG_REST_PARAM_TIME_WEEKS                (1UL << 34)
108#define OG_REST_PARAM_TIME_WEEK_DAYS            (1UL << 35)
109#define OG_REST_PARAM_TIME_DAYS                 (1UL << 36)
110#define OG_REST_PARAM_TIME_HOURS                (1UL << 37)
111#define OG_REST_PARAM_TIME_AM_PM                (1UL << 38)
112#define OG_REST_PARAM_TIME_MINUTES              (1UL << 39)
113#define OG_REST_PARAM_NETMASK                   (1UL << 40)
114#define OG_REST_PARAM_SCOPE                     (1UL << 41)
115#define OG_REST_PARAM_MODE                      (1UL << 42)
116
117static LIST_HEAD(client_list);
118
119void og_client_add(struct og_client *cli)
120{
121        list_add(&cli->list, &client_list);
122}
123
124static struct og_client *og_client_find(const char *ip)
125{
126        struct og_client *client;
127        struct in_addr addr;
128        int res;
129
130        res = inet_aton(ip, &addr);
131        if (!res) {
132                syslog(LOG_ERR, "Invalid IP string: %s\n", ip);
133                return NULL;
134        }
135
136        list_for_each_entry(client, &client_list, list) {
137                if (client->addr.sin_addr.s_addr == addr.s_addr && client->agent) {
138                        return client;
139                }
140        }
141
142        return NULL;
143}
144
145static const char *og_client_status(const struct og_client *cli)
146{
147        if (cli->last_cmd != OG_CMD_UNSPEC)
148                return "BSY";
149
150        switch (cli->status) {
151        case OG_CLIENT_STATUS_BUSY:
152                return "BSY";
153        case OG_CLIENT_STATUS_OGLIVE:
154                return "OPG";
155        case OG_CLIENT_STATUS_VIRTUAL:
156                return "VDI";
157        default:
158                return "OFF";
159        }
160}
161
162static bool og_msg_params_validate(const struct og_msg_params *params,
163                                   const uint64_t flags)
164{
165        return (params->flags & flags) == flags;
166}
167
168static bool og_flags_validate(const uint64_t flags,
169                              const uint64_t required_flags)
170{
171        return (flags & required_flags) == required_flags;
172}
173
174static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
175{
176        unsigned int i;
177        json_t *k;
178
179        if (json_typeof(element) != JSON_ARRAY)
180                return -1;
181
182        for (i = 0; i < json_array_size(element); i++) {
183                k = json_array_get(element, i);
184                if (json_typeof(k) != JSON_STRING)
185                        return -1;
186
187                params->ips_array[params->ips_array_len++] =
188                        json_string_value(k);
189
190                params->flags |= OG_REST_PARAM_ADDR;
191        }
192
193        return 0;
194}
195
196static int og_json_parse_sync_params(json_t *element,
197                                     struct og_msg_params *params)
198{
199        const char *key;
200        json_t *value;
201        int err = 0;
202
203        json_object_foreach(element, key, value) {
204                if (!strcmp(key, "sync")) {
205                        err = og_json_parse_string(value, &params->sync_setup.sync);
206                        params->flags |= OG_REST_PARAM_SYNC_SYNC;
207                } else if (!strcmp(key, "diff")) {
208                        err = og_json_parse_string(value, &params->sync_setup.diff);
209                        params->flags |= OG_REST_PARAM_SYNC_DIFF;
210                } else if (!strcmp(key, "remove")) {
211                        err = og_json_parse_string(value, &params->sync_setup.remove);
212                        params->flags |= OG_REST_PARAM_SYNC_REMOVE;
213                } else if (!strcmp(key, "compress")) {
214                        err = og_json_parse_string(value, &params->sync_setup.compress);
215                        params->flags |= OG_REST_PARAM_SYNC_COMPRESS;
216                } else if (!strcmp(key, "cleanup")) {
217                        err = og_json_parse_string(value, &params->sync_setup.cleanup);
218                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP;
219                } else if (!strcmp(key, "cache")) {
220                        err = og_json_parse_string(value, &params->sync_setup.cache);
221                        params->flags |= OG_REST_PARAM_SYNC_CACHE;
222                } else if (!strcmp(key, "cleanup_cache")) {
223                        err = og_json_parse_string(value, &params->sync_setup.cleanup_cache);
224                        params->flags |= OG_REST_PARAM_SYNC_CLEANUP_CACHE;
225                } else if (!strcmp(key, "remove_dst")) {
226                        err = og_json_parse_string(value, &params->sync_setup.remove_dst);
227                        params->flags |= OG_REST_PARAM_SYNC_REMOVE_DST;
228                } else if (!strcmp(key, "diff_id")) {
229                        err = og_json_parse_string(value, &params->sync_setup.diff_id);
230                        params->flags |= OG_REST_PARAM_SYNC_DIFF_ID;
231                } else if (!strcmp(key, "diff_name")) {
232                        err = og_json_parse_string(value, &params->sync_setup.diff_name);
233                        params->flags |= OG_REST_PARAM_SYNC_DIFF_NAME;
234                } else if (!strcmp(key, "path")) {
235                        err = og_json_parse_string(value, &params->sync_setup.path);
236                        params->flags |= OG_REST_PARAM_SYNC_PATH;
237                } else if (!strcmp(key, "method")) {
238                        err = og_json_parse_string(value, &params->sync_setup.method);
239                        params->flags |= OG_REST_PARAM_SYNC_METHOD;
240                }
241
242                if (err != 0)
243                        return err;
244        }
245        return err;
246}
247
248static int og_json_parse_partition_setup(json_t *element,
249                                         struct og_msg_params *params)
250{
251        unsigned int i;
252        json_t *k;
253
254        if (json_typeof(element) != JSON_ARRAY)
255                return -1;
256
257        for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
258                k = json_array_get(element, i);
259
260                if (json_typeof(k) != JSON_OBJECT)
261                        return -1;
262
263                if (og_json_parse_partition(k, &params->partition_setup[i],
264                                            OG_PARAM_PART_NUMBER |
265                                            OG_PARAM_PART_CODE |
266                                            OG_PARAM_PART_FILESYSTEM |
267                                            OG_PARAM_PART_SIZE |
268                                            OG_PARAM_PART_FORMAT) < 0)
269                        return -1;
270
271                params->flags |= (OG_REST_PARAM_PART_0 << i);
272        }
273        return 0;
274}
275
276static int og_json_parse_time_params(json_t *element,
277                                     struct og_msg_params *params)
278{
279        const char *key;
280        json_t *value;
281        int err = 0;
282
283        json_object_foreach(element, key, value) {
284                if (!strcmp(key, "years")) {
285                        err = og_json_parse_uint(value, &params->time.years);
286                        params->flags |= OG_REST_PARAM_TIME_YEARS;
287                } else if (!strcmp(key, "months")) {
288                        err = og_json_parse_uint(value, &params->time.months);
289                        params->flags |= OG_REST_PARAM_TIME_MONTHS;
290                } else if (!strcmp(key, "weeks")) {
291                        err = og_json_parse_uint(value, &params->time.weeks);
292                        params->flags |= OG_REST_PARAM_TIME_WEEKS;
293                } else if (!strcmp(key, "week_days")) {
294                        err = og_json_parse_uint(value, &params->time.week_days);
295                        params->flags |= OG_REST_PARAM_TIME_WEEK_DAYS;
296                } else if (!strcmp(key, "days")) {
297                        err = og_json_parse_uint(value, &params->time.days);
298                        params->flags |= OG_REST_PARAM_TIME_DAYS;
299                } else if (!strcmp(key, "hours")) {
300                        err = og_json_parse_uint(value, &params->time.hours);
301                        params->flags |= OG_REST_PARAM_TIME_HOURS;
302                } else if (!strcmp(key, "am_pm")) {
303                        err = og_json_parse_uint(value, &params->time.am_pm);
304                        params->flags |= OG_REST_PARAM_TIME_AM_PM;
305                } else if (!strcmp(key, "minutes")) {
306                        err = og_json_parse_uint(value, &params->time.minutes);
307                        params->flags |= OG_REST_PARAM_TIME_MINUTES;
308                }
309                if (err != 0)
310                        return err;
311        }
312
313        return err;
314}
315
316static const char *og_cmd_to_uri[OG_CMD_MAX] = {
317        [OG_CMD_WOL]            = "wol",
318        [OG_CMD_PROBE]          = "probe",
319        [OG_CMD_SHELL_RUN]      = "shell/run",
320        [OG_CMD_SESSION]        = "session",
321        [OG_CMD_POWEROFF]       = "poweroff",
322        [OG_CMD_REFRESH]        = "refresh",
323        [OG_CMD_REBOOT]         = "reboot",
324        [OG_CMD_STOP]           = "stop",
325        [OG_CMD_HARDWARE]       = "hardware",
326        [OG_CMD_SOFTWARE]       = "software",
327        [OG_CMD_IMAGE_CREATE]   = "image/create",
328        [OG_CMD_IMAGE_RESTORE]  = "image/restore",
329        [OG_CMD_SETUP]          = "setup",
330        [OG_CMD_RUN_SCHEDULE]   = "run/schedule",
331};
332
333static bool og_client_is_busy(const struct og_client *cli,
334                              enum og_cmd_type type)
335{
336        switch (type) {
337        case OG_CMD_REBOOT:
338        case OG_CMD_POWEROFF:
339        case OG_CMD_STOP:
340                break;
341        default:
342                if (cli->last_cmd != OG_CMD_UNSPEC)
343                        return true;
344                break;
345        }
346
347        return false;
348}
349
350int og_send_request(enum og_rest_method method, enum og_cmd_type type,
351                    const struct og_msg_params *params,
352                    const json_t *data)
353{
354        const char *content_type = "Content-Type: application/json";
355        char content [OG_MSG_REQUEST_MAXLEN - 700] = {};
356        char buf[OG_MSG_REQUEST_MAXLEN] = {};
357        unsigned int content_length;
358        char method_str[5] = {};
359        struct og_client *cli;
360        const char *uri;
361        unsigned int i;
362        int client_sd;
363
364        if (method == OG_METHOD_GET)
365                snprintf(method_str, 5, "GET");
366        else if (method == OG_METHOD_POST)
367                snprintf(method_str, 5, "POST");
368        else
369                return -1;
370
371        if (!data)
372                content_length = 0;
373        else
374                content_length = json_dumpb(data, content,
375                                            OG_MSG_REQUEST_MAXLEN - 700,
376                                            JSON_COMPACT);
377
378        uri = og_cmd_to_uri[type];
379        snprintf(buf, OG_MSG_REQUEST_MAXLEN,
380                 "%s /%s HTTP/1.1\r\nContent-Length: %d\r\n%s\r\n\r\n%s",
381                 method_str, uri, content_length, content_type, content);
382
383        for (i = 0; i < params->ips_array_len; i++) {
384                cli = og_client_find(params->ips_array[i]);
385                if (!cli)
386                        continue;
387
388                if (og_client_is_busy(cli, type))
389                        continue;
390
391                client_sd = cli->io.fd;
392                if (client_sd < 0) {
393                        syslog(LOG_INFO, "Client %s not conected\n",
394                               params->ips_array[i]);
395                        continue;
396                }
397
398                if (send(client_sd, buf, strlen(buf), 0) < 0)
399                        continue;
400
401                cli->last_cmd = type;
402        }
403
404        return 0;
405}
406
407static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
408{
409        const char *key;
410        json_t *value;
411        int err = 0;
412
413        if (json_typeof(element) != JSON_OBJECT)
414                return -1;
415
416        json_object_foreach(element, key, value) {
417                if (!strcmp(key, "clients"))
418                        err = og_json_parse_clients(value, params);
419
420                if (err < 0)
421                        break;
422        }
423
424        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
425                return -1;
426
427        return og_send_request(OG_METHOD_POST, OG_CMD_PROBE, params, NULL);
428}
429
430struct og_buffer {
431        char    *data;
432        int     len;
433};
434
435static int og_json_dump_clients(const char *buffer, size_t size, void *data)
436{
437        struct og_buffer *og_buffer = (struct og_buffer *)data;
438
439        memcpy(og_buffer->data + og_buffer->len, buffer, size);
440        og_buffer->len += size;
441
442        return 0;
443}
444
445static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
446                              char *buffer_reply)
447{
448        json_t *root, *array, *addr, *state, *object;
449        struct og_client *client;
450        struct og_buffer og_buffer = {
451                .data   = buffer_reply,
452        };
453
454        array = json_array();
455        if (!array)
456                return -1;
457
458        list_for_each_entry(client, &client_list, list) {
459                if (!client->agent)
460                        continue;
461
462                object = json_object();
463                if (!object) {
464                        json_decref(array);
465                        return -1;
466                }
467                addr = json_string(inet_ntoa(client->addr.sin_addr));
468                if (!addr) {
469                        json_decref(object);
470                        json_decref(array);
471                        return -1;
472                }
473                json_object_set_new(object, "addr", addr);
474                state = json_string(og_client_status(client));
475                if (!state) {
476                        json_decref(object);
477                        json_decref(array);
478                        return -1;
479                }
480                json_object_set_new(object, "state", state);
481                json_array_append_new(array, object);
482        }
483        root = json_pack("{s:o}", "clients", array);
484        if (!root) {
485                json_decref(array);
486                return -1;
487        }
488
489        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
490        json_decref(root);
491
492        return 0;
493}
494
495static int og_json_parse_target(json_t *element, struct og_msg_params *params)
496{
497        const char *key;
498        json_t *value;
499
500        if (json_typeof(element) != JSON_OBJECT) {
501                return -1;
502        }
503
504        json_object_foreach(element, key, value) {
505                if (!strcmp(key, "addr")) {
506                        if (json_typeof(value) != JSON_STRING)
507                                return -1;
508
509                        params->ips_array[params->ips_array_len] =
510                                json_string_value(value);
511
512                        params->flags |= OG_REST_PARAM_ADDR;
513                } else if (!strcmp(key, "mac")) {
514                        if (json_typeof(value) != JSON_STRING)
515                                return -1;
516
517                        params->mac_array[params->ips_array_len] =
518                                json_string_value(value);
519
520                        params->flags |= OG_REST_PARAM_MAC;
521                } else if (!strcmp(key, "netmask")) {
522                        if (json_typeof(value) != JSON_STRING)
523                                return -1;
524
525                        params->netmask_array[params->ips_array_len] =
526                                json_string_value(value);
527
528                        params->flags |= OG_REST_PARAM_NETMASK;
529                }
530        }
531
532        return 0;
533}
534
535static int og_json_parse_targets(json_t *element, struct og_msg_params *params)
536{
537        unsigned int i;
538        json_t *k;
539        int err;
540
541        if (json_typeof(element) != JSON_ARRAY)
542                return -1;
543
544        for (i = 0; i < json_array_size(element); i++) {
545                k = json_array_get(element, i);
546
547                if (json_typeof(k) != JSON_OBJECT)
548                        return -1;
549
550                err = og_json_parse_target(k, params);
551                if (err < 0)
552                        return err;
553
554                params->ips_array_len++;
555        }
556        return 0;
557}
558
559static int og_json_parse_type(json_t *element, struct og_msg_params *params)
560{
561        const char *type;
562
563        if (json_typeof(element) != JSON_STRING)
564                return -1;
565
566        params->wol_type = json_string_value(element);
567
568        type = json_string_value(element);
569        if (!strcmp(type, "unicast"))
570                params->wol_type = "2";
571        else if (!strcmp(type, "broadcast"))
572                params->wol_type = "1";
573
574        params->flags |= OG_REST_PARAM_WOL_TYPE;
575
576        return 0;
577}
578
579static int og_cmd_wol(json_t *element, struct og_msg_params *params)
580{
581        const char *key;
582        json_t *value;
583        int err = 0;
584
585        if (json_typeof(element) != JSON_OBJECT)
586                return -1;
587
588        json_object_foreach(element, key, value) {
589                if (!strcmp(key, "clients")) {
590                        err = og_json_parse_targets(value, params);
591                } else if (!strcmp(key, "type")) {
592                        err = og_json_parse_type(value, params);
593                }
594
595                if (err < 0)
596                        break;
597        }
598
599        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
600                                            OG_REST_PARAM_MAC |
601                                            OG_REST_PARAM_NETMASK |
602                                            OG_REST_PARAM_WOL_TYPE))
603                return -1;
604
605        if (!Levanta((char **)params->ips_array, (char **)params->mac_array,
606                     (char **)params->netmask_array, params->ips_array_len,
607                     (char *)params->wol_type))
608                return -1;
609
610        return 0;
611}
612
613static int og_json_parse_run(json_t *element, struct og_msg_params *params)
614{
615        if (json_typeof(element) != JSON_STRING)
616                return -1;
617
618        snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
619                 json_string_value(element));
620
621        params->flags |= OG_REST_PARAM_RUN_CMD;
622
623        return 0;
624}
625
626static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
627{
628        json_t *value, *clients;
629        const char *key;
630        unsigned int i;
631        int err = 0;
632
633        if (json_typeof(element) != JSON_OBJECT)
634                return -1;
635
636        json_object_foreach(element, key, value) {
637                if (!strcmp(key, "clients"))
638                        err = og_json_parse_clients(value, params);
639                else if (!strcmp(key, "run"))
640                        err = og_json_parse_run(value, params);
641                else if (!strcmp(key, "echo")) {
642                        err = og_json_parse_bool(value, &params->echo);
643                        params->flags |= OG_REST_PARAM_ECHO;
644                }
645
646                if (err < 0)
647                        break;
648        }
649
650        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
651                                            OG_REST_PARAM_RUN_CMD |
652                                            OG_REST_PARAM_ECHO))
653                return -1;
654
655        clients = json_copy(element);
656        json_object_del(clients, "clients");
657
658        err = og_send_request(OG_METHOD_POST, OG_CMD_SHELL_RUN, params, clients);
659        if (err < 0)
660                return err;
661
662        for (i = 0; i < params->ips_array_len; i++) {
663                char filename[4096];
664                FILE *f;
665
666                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
667                f = fopen(filename, "wt");
668                fclose(f);
669        }
670
671        return 0;
672}
673
674static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
675                          char *buffer_reply)
676{
677        struct og_buffer og_buffer = {
678                .data   = buffer_reply,
679        };
680        json_t *root, *value, *array;
681        const char *key;
682        unsigned int i;
683        int err = 0;
684
685        if (json_typeof(element) != JSON_OBJECT)
686                return -1;
687
688        json_object_foreach(element, key, value) {
689                if (!strcmp(key, "clients"))
690                        err = og_json_parse_clients(value, params);
691
692                if (err < 0)
693                        return err;
694        }
695
696        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
697                return -1;
698
699        array = json_array();
700        if (!array)
701                return -1;
702
703        for (i = 0; i < params->ips_array_len; i++) {
704                json_t *object, *output, *addr;
705                char data[4096] = {};
706                char filename[4096];
707                int fd, numbytes;
708
709                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
710
711                fd = open(filename, O_RDONLY);
712                if (!fd)
713                        return -1;
714
715                numbytes = read(fd, data, sizeof(data));
716                if (numbytes < 0) {
717                        close(fd);
718                        return -1;
719                }
720                data[sizeof(data) - 1] = '\0';
721                close(fd);
722
723                object = json_object();
724                if (!object) {
725                        json_decref(array);
726                        return -1;
727                }
728                addr = json_string(params->ips_array[i]);
729                if (!addr) {
730                        json_decref(object);
731                        json_decref(array);
732                        return -1;
733                }
734                json_object_set_new(object, "addr", addr);
735
736                output = json_string(data);
737                if (!output) {
738                        json_decref(object);
739                        json_decref(array);
740                        return -1;
741                }
742                json_object_set_new(object, "output", output);
743
744                json_array_append_new(array, object);
745        }
746
747        root = json_pack("{s:o}", "clients", array);
748        if (!root)
749                return -1;
750
751        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
752        json_decref(root);
753
754        return 0;
755}
756
757static int og_cmd_session(json_t *element, struct og_msg_params *params)
758{
759        json_t *clients, *value;
760        const char *key;
761        int err = 0;
762
763        if (json_typeof(element) != JSON_OBJECT)
764                return -1;
765
766        json_object_foreach(element, key, value) {
767                if (!strcmp(key, "clients")) {
768                        err = og_json_parse_clients(value, params);
769                } else if (!strcmp(key, "disk")) {
770                        err = og_json_parse_string(value, &params->disk);
771                        params->flags |= OG_REST_PARAM_DISK;
772                } else if (!strcmp(key, "partition")) {
773                        err = og_json_parse_string(value, &params->partition);
774                        params->flags |= OG_REST_PARAM_PARTITION;
775                }
776
777                if (err < 0)
778                        return err;
779        }
780
781        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
782                                            OG_REST_PARAM_DISK |
783                                            OG_REST_PARAM_PARTITION))
784                return -1;
785
786        clients = json_copy(element);
787        json_object_del(clients, "clients");
788
789        return og_send_request(OG_METHOD_POST, OG_CMD_SESSION, params, clients);
790}
791
792static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
793{
794        const char *key;
795        json_t *value;
796        int err = 0;
797
798        if (json_typeof(element) != JSON_OBJECT)
799                return -1;
800
801        json_object_foreach(element, key, value) {
802                if (!strcmp(key, "clients"))
803                        err = og_json_parse_clients(value, params);
804
805                if (err < 0)
806                        break;
807        }
808
809        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
810                return -1;
811
812        return og_send_request(OG_METHOD_POST, OG_CMD_POWEROFF, params, NULL);
813}
814
815static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
816{
817        const char *key;
818        json_t *value;
819        int err = 0;
820
821        if (json_typeof(element) != JSON_OBJECT)
822                return -1;
823
824        json_object_foreach(element, key, value) {
825                if (!strcmp(key, "clients"))
826                        err = og_json_parse_clients(value, params);
827
828                if (err < 0)
829                        break;
830        }
831
832        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
833                return -1;
834
835        return og_send_request(OG_METHOD_GET, OG_CMD_REFRESH, params, NULL);
836}
837
838static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
839{
840        const char *key;
841        json_t *value;
842        int err = 0;
843
844        if (json_typeof(element) != JSON_OBJECT)
845                return -1;
846
847        json_object_foreach(element, key, value) {
848                if (!strcmp(key, "clients"))
849                        err = og_json_parse_clients(value, params);
850
851                if (err < 0)
852                        break;
853        }
854
855        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
856                return -1;
857
858        return og_send_request(OG_METHOD_POST, OG_CMD_REBOOT, params, NULL);
859}
860
861#define OG_TFTP_TMPL_PATH "/opt/opengnsys/tftpboot/menu.lst/templates"
862
863static int og_cmd_get_modes(json_t *element, struct og_msg_params *params,
864                            char *buffer_reply)
865{
866        struct og_buffer og_buffer = {
867                .data = buffer_reply
868        };
869        json_t *root, *modes;
870        struct dirent *dent;
871        DIR *d = NULL;
872
873        root = json_object();
874        if (!root)
875                return -1;
876
877        modes = json_array();
878        if (!modes) {
879                json_decref(root);
880                return -1;
881        }
882
883        d = opendir(OG_TFTP_TMPL_PATH);
884        if (!d) {
885                json_decref(modes);
886                json_decref(root);
887                syslog(LOG_ERR, "Cannot open directory %s\n",
888                       OG_TFTP_TMPL_PATH);
889                return -1;
890        }
891
892        dent = readdir(d);
893        while (dent) {
894                if (dent->d_type != DT_REG) {
895                        dent = readdir(d);
896                        continue;
897                }
898                json_array_append_new(modes, json_string(dent->d_name));
899                dent = readdir(d);
900        }
901
902        json_object_set_new(root, "modes", modes);
903        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
904        json_decref(root);
905        closedir(d);
906
907        return 0;
908}
909
910static int og_change_db_mode(struct og_dbi *dbi, const char *mac,
911                             const char * mode)
912{
913        const char *msglog;
914        dbi_result result;
915
916        result = dbi_conn_queryf(dbi->conn,
917                                 "UPDATE ordenadores SET arranque='%s' "
918                                 "WHERE mac='%s'",
919                                 mode, mac);
920
921        if (!result) {
922                dbi_conn_error(dbi->conn, &msglog);
923                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
924                       __func__, __LINE__, msglog);
925                return -1;
926        }
927
928        dbi_result_free(result);
929        return 0;
930}
931
932static int og_set_client_mode(struct og_dbi *dbi, const char *mac,
933                              const char *mode, const char *template_name,
934                              const char *scope_name)
935{
936        char filename[PATH_MAX + 1] = "/tmp/mode_params_XXXXXX";
937        char cmd_params[PATH_MAX + 1] = {};
938        char params[PATH_MAX + 1] = "\0";
939        const char *msglog;
940        dbi_result result;
941        unsigned int i;
942        char cmd[200];
943        int numbytes;
944        int err = 0;
945        int fd;
946
947        result = dbi_conn_queryf(dbi->conn,
948                "SELECT ' LANG=%s', ' ip=', CONCAT_WS(':', ordenadores.ip, (SELECT (@serverip:=ipserveradm) FROM entornos LIMIT 1), aulas.router, aulas.netmask, ordenadores.nombreordenador, ordenadores.netiface, 'none'), ' group=', REPLACE(TRIM(aulas.nombreaula), ' ', '_'), ' ogrepo=', (@repoip:=IFNULL(repositorios.ip, '')), ' oglive=', @serverip, ' oglog=', @serverip, ' ogshare=', @serverip, ' oglivedir=', ordenadores.oglivedir, ' ogprof=', IF(ordenadores.idordenador=aulas.idordprofesor, 'true', 'false'), IF(perfileshard.descripcion<>'', CONCAT(' hardprofile=', REPLACE(TRIM(perfileshard.descripcion), ' ', '_')), ''), IF(aulas.ntp<>'', CONCAT(' ogntp=', aulas.ntp), ''), IF(aulas.dns<>'', CONCAT(' ogdns=', aulas.dns), ''), IF(aulas.proxy<>'', CONCAT(' ogproxy=', aulas.proxy), ''), IF(entidades.ogunit=1 AND NOT centros.directorio='', CONCAT(' ogunit=', centros.directorio), ''), CASE WHEN menus.resolucion IS NULL THEN '' WHEN menus.resolucion <= '999' THEN CONCAT(' vga=', menus.resolucion) WHEN menus.resolucion LIKE '%:%' THEN CONCAT(' video=', menus.resolucion) ELSE menus.resolucion END FROM ordenadores JOIN aulas USING(idaula) JOIN centros USING(idcentro) JOIN entidades USING(identidad) LEFT JOIN repositorios USING(idrepositorio) LEFT JOIN perfileshard USING(idperfilhard) LEFT JOIN menus USING(idmenu) WHERE ordenadores.mac='%s'", getenv("LANG"), mac);
949
950        if (dbi_result_get_numrows(result) != 1) {
951                dbi_conn_error(dbi->conn, &msglog);
952                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
953                       __FILE__, __LINE__, msglog);
954                dbi_result_free(result);
955                return -1;
956        }
957        dbi_result_next_row(result);
958
959        for (i = 1; i <= dbi_result_get_numfields(result); ++i)
960                strcat(params, dbi_result_get_string_idx(result, i));
961
962        dbi_result_free(result);
963
964        snprintf(cmd_params, sizeof(cmd_params),
965                 "MODE_FILE='%s'\nMAC='%s'\nDATA='%s'\n"
966                 "MODE='PERM'\nTEMPLATE_NAME='%s'",
967                 mode, mac, params, template_name);
968
969        fd = mkstemp(filename);
970        if (fd < 0) {
971                syslog(LOG_ERR, "cannot generate temp file (%s:%d)\n",
972                       __func__, __LINE__);
973                return -1;
974        }
975
976        numbytes = write(fd, cmd_params, strlen(cmd_params) + 1);
977        close(fd);
978
979        if (numbytes < 0) {
980                syslog(LOG_ERR, "cannot write file\n");
981                unlink(filename);
982                return -1;
983        }
984
985        snprintf(cmd, sizeof(cmd), "/opt/opengnsys/bin/setclientmode %s",
986                 filename);
987
988        err = system(cmd);
989        unlink(filename);
990        if (err != 0) {
991                syslog(LOG_ERR, "failed script execution (%s:%d)\n",
992                       __func__, __LINE__);
993                return -1;
994        }
995
996        if (og_change_db_mode(dbi, mac, mode) < 0) {
997                syslog(LOG_ERR, "failed to change db mode (%s:%d)\n",
998                       __func__, __LINE__);
999                return -1;
1000        }
1001
1002        return 0;
1003}
1004
1005static int og_cmd_post_modes(json_t *element, struct og_msg_params *params)
1006{
1007        const char *mode_str, *mac, *scope_name;
1008        char template_file[PATH_MAX + 1] = {};
1009        char template_name[PATH_MAX + 1] = {};
1010        char first_line[PATH_MAX + 1] = {};
1011        struct og_dbi *dbi;
1012        uint64_t flags = 0;
1013        dbi_result result;
1014        const char *key;
1015        json_t *value;
1016        int err = 0;
1017        FILE *f;
1018
1019        json_object_foreach(element, key, value) {
1020                if (!strcmp(key, "scope_name")) {
1021                        err = og_json_parse_string(value, &scope_name);
1022                        flags |= OG_REST_PARAM_SCOPE;
1023                } else if (!strcmp(key, "mode")) {
1024                        err = og_json_parse_string(value, &mode_str);
1025                        flags |= OG_REST_PARAM_MODE;
1026                } else {
1027                        err = -1;
1028                }
1029
1030                if (err < 0)
1031                        break;
1032        }
1033
1034        if (!og_flags_validate(flags, OG_REST_PARAM_SCOPE |
1035                                      OG_REST_PARAM_MODE))
1036                return -1;
1037
1038        snprintf(template_file, sizeof(template_file), "%s/%s",
1039                 OG_TFTP_TMPL_PATH, mode_str);
1040        f = fopen(template_file, "r");
1041        if (!f) {
1042                syslog(LOG_ERR, "cannot open file (%s:%d)\n",
1043                       __func__, __LINE__);
1044                return -1;
1045        }
1046
1047        if (!fgets(first_line, sizeof(first_line), f)) {
1048                fclose(f);
1049                syslog(LOG_ERR, "cannot read file (%s:%d)\n",
1050                       __func__, __LINE__);
1051                return -1;
1052        }
1053
1054        fclose(f);
1055
1056        if (sscanf(first_line, "##NO-TOCAR-ESTA-LINEA %s", template_name) != 1) {
1057                syslog(LOG_ERR, "malformed template: %s", first_line);
1058                return -1;
1059        }
1060
1061        dbi = og_dbi_open(&dbi_config);
1062        if (!dbi) {
1063                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1064                       __func__, __LINE__);
1065                return -1;
1066        }
1067
1068        result = dbi_conn_queryf(dbi->conn,
1069                                 "SELECT mac FROM ordenadores "
1070                                 "JOIN aulas USING (idaula) "
1071                                 "WHERE aulas.nombreaula='%s' OR "
1072                                 "nombreordenador='%s'",
1073                                 scope_name, scope_name);
1074
1075        while (dbi_result_next_row(result)) {
1076                mac = dbi_result_get_string(result, "mac");
1077                err = og_set_client_mode(dbi, mac, mode_str,
1078                                         template_name, scope_name);
1079                if (err != 0) {
1080                        dbi_result_free(result);
1081                        og_dbi_close(dbi);
1082                        return -1;
1083                }
1084        }
1085
1086        dbi_result_free(result);
1087        og_dbi_close(dbi);
1088
1089        return 0;
1090}
1091
1092static int og_cmd_stop(json_t *element, struct og_msg_params *params)
1093{
1094        const char *key;
1095        json_t *value;
1096        int err = 0;
1097
1098        if (json_typeof(element) != JSON_OBJECT)
1099                return -1;
1100
1101        json_object_foreach(element, key, value) {
1102                if (!strcmp(key, "clients"))
1103                        err = og_json_parse_clients(value, params);
1104
1105                if (err < 0)
1106                        break;
1107        }
1108
1109        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1110                return -1;
1111
1112        return og_send_request(OG_METHOD_POST, OG_CMD_STOP, params, NULL);
1113}
1114
1115static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
1116{
1117        const char *key;
1118        json_t *value;
1119        int err = 0;
1120
1121        if (json_typeof(element) != JSON_OBJECT)
1122                return -1;
1123
1124        json_object_foreach(element, key, value) {
1125                if (!strcmp(key, "clients"))
1126                        err = og_json_parse_clients(value, params);
1127
1128                if (err < 0)
1129                        break;
1130        }
1131
1132        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1133                return -1;
1134
1135        return og_send_request(OG_METHOD_GET, OG_CMD_HARDWARE, params, NULL);
1136}
1137
1138static int og_cmd_get_hardware(json_t *element, struct og_msg_params *params,
1139                               char *buffer_reply)
1140{
1141        const char *key, *msglog, *hw_item, *hw_type;
1142        json_t *value, *root, *array, *item;
1143        struct og_scope scope = {};
1144        uint64_t flags = 0;
1145        struct og_dbi *dbi;
1146        dbi_result result;
1147        int err = 0;
1148
1149        struct og_buffer og_buffer = {
1150                .data = buffer_reply
1151        };
1152
1153        json_object_foreach(element, key, value) {
1154                if (!strcmp(key, "scope")) {
1155                        err = og_json_parse_scope(value, &scope,
1156                                                  OG_PARAM_SCOPE_ID |
1157                                                  OG_PARAM_SCOPE_TYPE);
1158                        flags |= OG_REST_PARAM_SCOPE;
1159                } else {
1160                        err = -1;
1161                }
1162
1163                if (err < 0)
1164                        return err;
1165        }
1166
1167        if (!og_flags_validate(flags, OG_REST_PARAM_SCOPE))
1168                return -1;
1169
1170        if (strcmp(scope.type, "computer")) {
1171                syslog(LOG_ERR, "incorrect scope type\n");
1172                return -1;
1173        }
1174
1175        dbi = og_dbi_open(&dbi_config);
1176        if (!dbi) {
1177                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1178                       __func__, __LINE__);
1179                return -1;
1180        }
1181
1182        result = dbi_conn_queryf(dbi->conn,
1183                                 "SELECT hardwares.descripcion AS item, "
1184                                 "       tipohardwares.descripcion AS type "
1185                                 "FROM hardwares "
1186                                 "INNER JOIN perfileshard_hardwares "
1187                                 "    ON hardwares.idhardware = perfileshard_hardwares.idhardware "
1188                                 "INNER JOIN ordenadores "
1189                                 "    ON perfileshard_hardwares.idperfilhard = ordenadores.idperfilhard "
1190                                 "INNER JOIN tipohardwares "
1191                                 "    ON hardwares.idtipohardware = tipohardwares.idtipohardware "
1192                                 "WHERE ordenadores.idordenador = %u",
1193                                 scope.id);
1194        if (!result) {
1195                dbi_conn_error(dbi->conn, &msglog);
1196                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1197                       __func__, __LINE__, msglog);
1198                og_dbi_close(dbi);
1199                return -1;
1200        }
1201
1202        array = json_array();
1203        if (!array) {
1204                dbi_result_free(result);
1205                og_dbi_close(dbi);
1206                return -1;
1207        }
1208
1209        while (dbi_result_next_row(result)) {
1210                item = json_object();
1211                if (!item) {
1212                        dbi_result_free(result);
1213                        og_dbi_close(dbi);
1214                        json_decref(array);
1215                        return -1;
1216                }
1217
1218                hw_item = dbi_result_get_string(result, "item");
1219                hw_type = dbi_result_get_string(result, "type");
1220
1221                json_object_set_new(item, "type", json_string(hw_type));
1222                json_object_set_new(item, "description", json_string(hw_item));
1223                json_array_append_new(array, item);
1224        }
1225
1226        dbi_result_free(result);
1227        og_dbi_close(dbi);
1228
1229        root = json_object();
1230        if (!root){
1231                json_decref(array);
1232                return -1;
1233        }
1234
1235        json_object_set_new(root, "hardware", array);
1236
1237        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
1238        json_decref(root);
1239        return 0;
1240}
1241
1242static int og_cmd_software(json_t *element, struct og_msg_params *params)
1243{
1244        json_t *clients, *value;
1245        const char *key;
1246        int err = 0;
1247
1248        if (json_typeof(element) != JSON_OBJECT)
1249                return -1;
1250
1251        json_object_foreach(element, key, value) {
1252                if (!strcmp(key, "clients"))
1253                        err = og_json_parse_clients(value, params);
1254                else if (!strcmp(key, "disk")) {
1255                        err = og_json_parse_string(value, &params->disk);
1256                        params->flags |= OG_REST_PARAM_DISK;
1257                }
1258                else if (!strcmp(key, "partition")) {
1259                        err = og_json_parse_string(value, &params->partition);
1260                        params->flags |= OG_REST_PARAM_PARTITION;
1261                }
1262
1263                if (err < 0)
1264                        break;
1265        }
1266
1267        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1268                                            OG_REST_PARAM_DISK |
1269                                            OG_REST_PARAM_PARTITION))
1270                return -1;
1271
1272        clients = json_copy(element);
1273        json_object_del(clients, "clients");
1274
1275        return og_send_request(OG_METHOD_POST, OG_CMD_SOFTWARE, params, clients);
1276}
1277
1278static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
1279{
1280        json_t *value, *clients;
1281        const char *key;
1282        int err = 0;
1283
1284        if (json_typeof(element) != JSON_OBJECT)
1285                return -1;
1286
1287        json_object_foreach(element, key, value) {
1288                if (!strcmp(key, "disk")) {
1289                        err = og_json_parse_string(value, &params->disk);
1290                        params->flags |= OG_REST_PARAM_DISK;
1291                } else if (!strcmp(key, "partition")) {
1292                        err = og_json_parse_string(value, &params->partition);
1293                        params->flags |= OG_REST_PARAM_PARTITION;
1294                } else if (!strcmp(key, "name")) {
1295                        err = og_json_parse_string(value, &params->name);
1296                        params->flags |= OG_REST_PARAM_NAME;
1297                } else if (!strcmp(key, "repository")) {
1298                        err = og_json_parse_string(value, &params->repository);
1299                        params->flags |= OG_REST_PARAM_REPO;
1300                } else if (!strcmp(key, "clients")) {
1301                        err = og_json_parse_clients(value, params);
1302                } else if (!strcmp(key, "id")) {
1303                        err = og_json_parse_string(value, &params->id);
1304                        params->flags |= OG_REST_PARAM_ID;
1305                } else if (!strcmp(key, "code")) {
1306                        err = og_json_parse_string(value, &params->code);
1307                        params->flags |= OG_REST_PARAM_CODE;
1308                }
1309
1310                if (err < 0)
1311                        break;
1312        }
1313
1314        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1315                                            OG_REST_PARAM_DISK |
1316                                            OG_REST_PARAM_PARTITION |
1317                                            OG_REST_PARAM_CODE |
1318                                            OG_REST_PARAM_ID |
1319                                            OG_REST_PARAM_NAME |
1320                                            OG_REST_PARAM_REPO))
1321                return -1;
1322
1323        clients = json_copy(element);
1324        json_object_del(clients, "clients");
1325
1326        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
1327                               clients);
1328}
1329
1330static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
1331{
1332        json_t *clients, *value;
1333        const char *key;
1334        int err = 0;
1335
1336        if (json_typeof(element) != JSON_OBJECT)
1337                return -1;
1338
1339        json_object_foreach(element, key, value) {
1340                if (!strcmp(key, "disk")) {
1341                        err = og_json_parse_string(value, &params->disk);
1342                        params->flags |= OG_REST_PARAM_DISK;
1343                } else if (!strcmp(key, "partition")) {
1344                        err = og_json_parse_string(value, &params->partition);
1345                        params->flags |= OG_REST_PARAM_PARTITION;
1346                } else if (!strcmp(key, "name")) {
1347                        err = og_json_parse_string(value, &params->name);
1348                        params->flags |= OG_REST_PARAM_NAME;
1349                } else if (!strcmp(key, "repository")) {
1350                        err = og_json_parse_string(value, &params->repository);
1351                        params->flags |= OG_REST_PARAM_REPO;
1352                } else if (!strcmp(key, "clients")) {
1353                        err = og_json_parse_clients(value, params);
1354                } else if (!strcmp(key, "type")) {
1355                        err = og_json_parse_string(value, &params->type);
1356                        params->flags |= OG_REST_PARAM_TYPE;
1357                } else if (!strcmp(key, "profile")) {
1358                        err = og_json_parse_string(value, &params->profile);
1359                        params->flags |= OG_REST_PARAM_PROFILE;
1360                } else if (!strcmp(key, "id")) {
1361                        err = og_json_parse_string(value, &params->id);
1362                        params->flags |= OG_REST_PARAM_ID;
1363                }
1364
1365                if (err < 0)
1366                        break;
1367        }
1368
1369        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1370                                            OG_REST_PARAM_DISK |
1371                                            OG_REST_PARAM_PARTITION |
1372                                            OG_REST_PARAM_NAME |
1373                                            OG_REST_PARAM_REPO |
1374                                            OG_REST_PARAM_TYPE |
1375                                            OG_REST_PARAM_PROFILE |
1376                                            OG_REST_PARAM_ID))
1377                return -1;
1378
1379        clients = json_copy(element);
1380        json_object_del(clients, "clients");
1381
1382        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
1383                               clients);
1384}
1385
1386static int og_cmd_setup(json_t *element, struct og_msg_params *params)
1387{
1388        json_t *value, *clients;
1389        const char *key;
1390        int err = 0;
1391
1392        if (json_typeof(element) != JSON_OBJECT)
1393                return -1;
1394
1395        json_object_foreach(element, key, value) {
1396                if (!strcmp(key, "clients")) {
1397                        err = og_json_parse_clients(value, params);
1398                } else if (!strcmp(key, "disk")) {
1399                        err = og_json_parse_string(value, &params->disk);
1400                        params->flags |= OG_REST_PARAM_DISK;
1401                } else if (!strcmp(key, "cache")) {
1402                        err = og_json_parse_string(value, &params->cache);
1403                        params->flags |= OG_REST_PARAM_CACHE;
1404                } else if (!strcmp(key, "cache_size")) {
1405                        err = og_json_parse_string(value, &params->cache_size);
1406                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
1407                } else if (!strcmp(key, "partition_setup")) {
1408                        err = og_json_parse_partition_setup(value, params);
1409                }
1410
1411                if (err < 0)
1412                        break;
1413        }
1414
1415        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1416                                            OG_REST_PARAM_DISK |
1417                                            OG_REST_PARAM_CACHE |
1418                                            OG_REST_PARAM_CACHE_SIZE |
1419                                            OG_REST_PARAM_PART_0 |
1420                                            OG_REST_PARAM_PART_1 |
1421                                            OG_REST_PARAM_PART_2 |
1422                                            OG_REST_PARAM_PART_3))
1423                return -1;
1424
1425        clients = json_copy(element);
1426        json_object_del(clients, "clients");
1427
1428        return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
1429}
1430
1431static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
1432{
1433        const char *key;
1434        json_t *value;
1435        int err = 0;
1436
1437        json_object_foreach(element, key, value) {
1438                if (!strcmp(key, "clients"))
1439                        err = og_json_parse_clients(value, params);
1440
1441                if (err < 0)
1442                        break;
1443        }
1444
1445        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1446                return -1;
1447
1448        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
1449                               NULL);
1450}
1451
1452static int og_cmd_create_basic_image(json_t *element, struct og_msg_params *params)
1453{
1454        char buf[4096] = {};
1455        int err = 0, len;
1456        const char *key;
1457        json_t *value;
1458        TRAMA *msg;
1459
1460        if (json_typeof(element) != JSON_OBJECT)
1461                return -1;
1462
1463        json_object_foreach(element, key, value) {
1464                if (!strcmp(key, "clients")) {
1465                        err = og_json_parse_clients(value, params);
1466                } else if (!strcmp(key, "disk")) {
1467                        err = og_json_parse_string(value, &params->disk);
1468                        params->flags |= OG_REST_PARAM_DISK;
1469                } else if (!strcmp(key, "partition")) {
1470                        err = og_json_parse_string(value, &params->partition);
1471                        params->flags |= OG_REST_PARAM_PARTITION;
1472                } else if (!strcmp(key, "code")) {
1473                        err = og_json_parse_string(value, &params->code);
1474                        params->flags |= OG_REST_PARAM_CODE;
1475                } else if (!strcmp(key, "id")) {
1476                        err = og_json_parse_string(value, &params->id);
1477                        params->flags |= OG_REST_PARAM_ID;
1478                } else if (!strcmp(key, "name")) {
1479                        err = og_json_parse_string(value, &params->name);
1480                        params->flags |= OG_REST_PARAM_NAME;
1481                } else if (!strcmp(key, "repository")) {
1482                        err = og_json_parse_string(value, &params->repository);
1483                        params->flags |= OG_REST_PARAM_REPO;
1484                } else if (!strcmp(key, "sync_params")) {
1485                        err = og_json_parse_sync_params(value, params);
1486                }
1487
1488                if (err < 0)
1489                        break;
1490        }
1491
1492        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1493                                            OG_REST_PARAM_DISK |
1494                                            OG_REST_PARAM_PARTITION |
1495                                            OG_REST_PARAM_CODE |
1496                                            OG_REST_PARAM_ID |
1497                                            OG_REST_PARAM_NAME |
1498                                            OG_REST_PARAM_REPO |
1499                                            OG_REST_PARAM_SYNC_SYNC |
1500                                            OG_REST_PARAM_SYNC_DIFF |
1501                                            OG_REST_PARAM_SYNC_REMOVE |
1502                                            OG_REST_PARAM_SYNC_COMPRESS |
1503                                            OG_REST_PARAM_SYNC_CLEANUP |
1504                                            OG_REST_PARAM_SYNC_CACHE |
1505                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
1506                                            OG_REST_PARAM_SYNC_REMOVE_DST))
1507                return -1;
1508
1509        len = snprintf(buf, sizeof(buf),
1510                       "nfn=CrearImagenBasica\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\r"
1511                       "nci=%s\ripr=%s\rrti=\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\r"
1512                       "cpc=%s\rbpc=%s\rnba=%s\r",
1513                       params->disk, params->partition, params->code, params->id,
1514                       params->name, params->repository, params->sync_setup.sync,
1515                       params->sync_setup.diff, params->sync_setup.remove,
1516                       params->sync_setup.compress, params->sync_setup.cleanup,
1517                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
1518                       params->sync_setup.remove_dst);
1519
1520        msg = og_msg_alloc(buf, len);
1521        if (!msg)
1522                return -1;
1523
1524        og_send_cmd((char **)params->ips_array, params->ips_array_len,
1525                    CLIENTE_OCUPADO, msg);
1526
1527        og_msg_free(msg);
1528
1529        return 0;
1530}
1531
1532static int og_cmd_create_incremental_image(json_t *element, struct og_msg_params *params)
1533{
1534        char buf[4096] = {};
1535        int err = 0, len;
1536        const char *key;
1537        json_t *value;
1538        TRAMA *msg;
1539
1540        if (json_typeof(element) != JSON_OBJECT)
1541                return -1;
1542
1543        json_object_foreach(element, key, value) {
1544                if (!strcmp(key, "clients"))
1545                        err = og_json_parse_clients(value, params);
1546                else if (!strcmp(key, "disk")) {
1547                        err = og_json_parse_string(value, &params->disk);
1548                        params->flags |= OG_REST_PARAM_DISK;
1549                } else if (!strcmp(key, "partition")) {
1550                        err = og_json_parse_string(value, &params->partition);
1551                        params->flags |= OG_REST_PARAM_PARTITION;
1552                } else if (!strcmp(key, "id")) {
1553                        err = og_json_parse_string(value, &params->id);
1554                        params->flags |= OG_REST_PARAM_ID;
1555                } else if (!strcmp(key, "name")) {
1556                        err = og_json_parse_string(value, &params->name);
1557                        params->flags |= OG_REST_PARAM_NAME;
1558                } else if (!strcmp(key, "repository")) {
1559                        err = og_json_parse_string(value, &params->repository);
1560                        params->flags |= OG_REST_PARAM_REPO;
1561                } else if (!strcmp(key, "sync_params")) {
1562                        err = og_json_parse_sync_params(value, params);
1563                }
1564
1565                if (err < 0)
1566                        break;
1567        }
1568
1569        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1570                                            OG_REST_PARAM_DISK |
1571                                            OG_REST_PARAM_PARTITION |
1572                                            OG_REST_PARAM_ID |
1573                                            OG_REST_PARAM_NAME |
1574                                            OG_REST_PARAM_REPO |
1575                                            OG_REST_PARAM_SYNC_SYNC |
1576                                            OG_REST_PARAM_SYNC_PATH |
1577                                            OG_REST_PARAM_SYNC_DIFF |
1578                                            OG_REST_PARAM_SYNC_DIFF_ID |
1579                                            OG_REST_PARAM_SYNC_DIFF_NAME |
1580                                            OG_REST_PARAM_SYNC_REMOVE |
1581                                            OG_REST_PARAM_SYNC_COMPRESS |
1582                                            OG_REST_PARAM_SYNC_CLEANUP |
1583                                            OG_REST_PARAM_SYNC_CACHE |
1584                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
1585                                            OG_REST_PARAM_SYNC_REMOVE_DST))
1586                return -1;
1587
1588        len = snprintf(buf, sizeof(buf),
1589                       "nfn=CrearSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
1590                       "rti=%s\ripr=%s\ridf=%s\rncf=%s\rmsy=%s\rwhl=%s\reli=%s\rcmp=%s\r"
1591                       "bpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
1592                       params->disk, params->partition, params->id, params->name,
1593                       params->sync_setup.path, params->repository, params->sync_setup.diff_id,
1594                       params->sync_setup.diff_name, params->sync_setup.sync,
1595                       params->sync_setup.diff, params->sync_setup.remove_dst,
1596                       params->sync_setup.compress, params->sync_setup.cleanup,
1597                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
1598                       params->sync_setup.remove_dst);
1599
1600        msg = og_msg_alloc(buf, len);
1601        if (!msg)
1602                return -1;
1603
1604        og_send_cmd((char **)params->ips_array, params->ips_array_len,
1605                    CLIENTE_OCUPADO, msg);
1606
1607        og_msg_free(msg);
1608
1609        return 0;
1610}
1611
1612static int og_cmd_restore_basic_image(json_t *element, struct og_msg_params *params)
1613{
1614        char buf[4096] = {};
1615        int err = 0, len;
1616        const char *key;
1617        json_t *value;
1618        TRAMA *msg;
1619
1620        if (json_typeof(element) != JSON_OBJECT)
1621                return -1;
1622
1623        json_object_foreach(element, key, value) {
1624                if (!strcmp(key, "clients")) {
1625                        err = og_json_parse_clients(value, params);
1626                } else if (!strcmp(key, "disk")) {
1627                        err = og_json_parse_string(value, &params->disk);
1628                        params->flags |= OG_REST_PARAM_DISK;
1629                } else if (!strcmp(key, "partition")) {
1630                        err = og_json_parse_string(value, &params->partition);
1631                        params->flags |= OG_REST_PARAM_PARTITION;
1632                } else if (!strcmp(key, "id")) {
1633                        err = og_json_parse_string(value, &params->id);
1634                        params->flags |= OG_REST_PARAM_ID;
1635                } else if (!strcmp(key, "name")) {
1636                        err = og_json_parse_string(value, &params->name);
1637                        params->flags |= OG_REST_PARAM_NAME;
1638                } else if (!strcmp(key, "repository")) {
1639                        err = og_json_parse_string(value, &params->repository);
1640                        params->flags |= OG_REST_PARAM_REPO;
1641                } else if (!strcmp(key, "profile")) {
1642                        err = og_json_parse_string(value, &params->profile);
1643                        params->flags |= OG_REST_PARAM_PROFILE;
1644                } else if (!strcmp(key, "type")) {
1645                        err = og_json_parse_string(value, &params->type);
1646                        params->flags |= OG_REST_PARAM_TYPE;
1647                } else if (!strcmp(key, "sync_params")) {
1648                        err = og_json_parse_sync_params(value, params);
1649                }
1650
1651                if (err < 0)
1652                        break;
1653        }
1654
1655        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1656                                            OG_REST_PARAM_DISK |
1657                                            OG_REST_PARAM_PARTITION |
1658                                            OG_REST_PARAM_ID |
1659                                            OG_REST_PARAM_NAME |
1660                                            OG_REST_PARAM_REPO |
1661                                            OG_REST_PARAM_PROFILE |
1662                                            OG_REST_PARAM_TYPE |
1663                                            OG_REST_PARAM_SYNC_PATH |
1664                                            OG_REST_PARAM_SYNC_METHOD |
1665                                            OG_REST_PARAM_SYNC_SYNC |
1666                                            OG_REST_PARAM_SYNC_DIFF |
1667                                            OG_REST_PARAM_SYNC_REMOVE |
1668                                            OG_REST_PARAM_SYNC_COMPRESS |
1669                                            OG_REST_PARAM_SYNC_CLEANUP |
1670                                            OG_REST_PARAM_SYNC_CACHE |
1671                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
1672                                            OG_REST_PARAM_SYNC_REMOVE_DST))
1673                return -1;
1674
1675        len = snprintf(buf, sizeof(buf),
1676                       "nfn=RestaurarImagenBasica\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
1677                           "ipr=%s\rifs=%s\rrti=%s\rmet=%s\rmsy=%s\rtpt=%s\rwhl=%s\r"
1678                           "eli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\rnba=%s\r",
1679                       params->disk, params->partition, params->id, params->name,
1680                           params->repository, params->profile, params->sync_setup.path,
1681                           params->sync_setup.method, params->sync_setup.sync, params->type,
1682                           params->sync_setup.diff, params->sync_setup.remove,
1683                       params->sync_setup.compress, params->sync_setup.cleanup,
1684                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
1685                       params->sync_setup.remove_dst);
1686
1687        msg = og_msg_alloc(buf, len);
1688        if (!msg)
1689                return -1;
1690
1691        og_send_cmd((char **)params->ips_array, params->ips_array_len,
1692                    CLIENTE_OCUPADO, msg);
1693
1694        og_msg_free(msg);
1695
1696        return 0;
1697}
1698
1699static int og_cmd_restore_incremental_image(json_t *element, struct og_msg_params *params)
1700{
1701        char buf[4096] = {};
1702        int err = 0, len;
1703        const char *key;
1704        json_t *value;
1705        TRAMA *msg;
1706
1707        if (json_typeof(element) != JSON_OBJECT)
1708                return -1;
1709
1710        json_object_foreach(element, key, value) {
1711                if (!strcmp(key, "clients")) {
1712                        err = og_json_parse_clients(value, params);
1713                } else if (!strcmp(key, "disk")) {
1714                        err = og_json_parse_string(value, &params->disk);
1715                        params->flags |= OG_REST_PARAM_DISK;
1716                } else if (!strcmp(key, "partition")) {
1717                        err = og_json_parse_string(value, &params->partition);
1718                        params->flags |= OG_REST_PARAM_PARTITION;
1719                } else if (!strcmp(key, "id")) {
1720                        err = og_json_parse_string(value, &params->id);
1721                        params->flags |= OG_REST_PARAM_ID;
1722                } else if (!strcmp(key, "name")) {
1723                        err = og_json_parse_string(value, &params->name);
1724                        params->flags |= OG_REST_PARAM_NAME;
1725                } else if (!strcmp(key, "repository")) {
1726                        err = og_json_parse_string(value, &params->repository);
1727                        params->flags |= OG_REST_PARAM_REPO;
1728                } else if (!strcmp(key, "profile")) {
1729                        err = og_json_parse_string(value, &params->profile);
1730                        params->flags |= OG_REST_PARAM_PROFILE;
1731                } else if (!strcmp(key, "type")) {
1732                        err = og_json_parse_string(value, &params->type);
1733                        params->flags |= OG_REST_PARAM_TYPE;
1734                } else if (!strcmp(key, "sync_params")) {
1735                        err = og_json_parse_sync_params(value, params);
1736                }
1737
1738                if (err < 0)
1739                        break;
1740        }
1741
1742        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1743                                            OG_REST_PARAM_DISK |
1744                                            OG_REST_PARAM_PARTITION |
1745                                            OG_REST_PARAM_ID |
1746                                            OG_REST_PARAM_NAME |
1747                                            OG_REST_PARAM_REPO |
1748                                            OG_REST_PARAM_PROFILE |
1749                                            OG_REST_PARAM_TYPE |
1750                                            OG_REST_PARAM_SYNC_DIFF_ID |
1751                                            OG_REST_PARAM_SYNC_DIFF_NAME |
1752                                            OG_REST_PARAM_SYNC_PATH |
1753                                            OG_REST_PARAM_SYNC_METHOD |
1754                                            OG_REST_PARAM_SYNC_SYNC |
1755                                            OG_REST_PARAM_SYNC_DIFF |
1756                                            OG_REST_PARAM_SYNC_REMOVE |
1757                                            OG_REST_PARAM_SYNC_COMPRESS |
1758                                            OG_REST_PARAM_SYNC_CLEANUP |
1759                                            OG_REST_PARAM_SYNC_CACHE |
1760                                            OG_REST_PARAM_SYNC_CLEANUP_CACHE |
1761                                            OG_REST_PARAM_SYNC_REMOVE_DST))
1762                return -1;
1763
1764        len = snprintf(buf, sizeof(buf),
1765                       "nfn=RestaurarSoftIncremental\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
1766                           "ipr=%s\rifs=%s\ridf=%s\rncf=%s\rrti=%s\rmet=%s\rmsy=%s\r"
1767                           "tpt=%s\rwhl=%s\reli=%s\rcmp=%s\rbpi=%s\rcpc=%s\rbpc=%s\r"
1768                           "nba=%s\r",
1769                       params->disk, params->partition, params->id, params->name,
1770                           params->repository, params->profile, params->sync_setup.diff_id,
1771                           params->sync_setup.diff_name, params->sync_setup.path,
1772                           params->sync_setup.method, params->sync_setup.sync, params->type,
1773                           params->sync_setup.diff, params->sync_setup.remove,
1774                       params->sync_setup.compress, params->sync_setup.cleanup,
1775                       params->sync_setup.cache, params->sync_setup.cleanup_cache,
1776                       params->sync_setup.remove_dst);
1777
1778        msg = og_msg_alloc(buf, len);
1779        if (!msg)
1780                return -1;
1781
1782        og_send_cmd((char **)params->ips_array, params->ips_array_len,
1783                    CLIENTE_OCUPADO, msg);
1784
1785        og_msg_free(msg);
1786
1787        return 0;
1788}
1789
1790static LIST_HEAD(cmd_list);
1791
1792const struct og_cmd *og_cmd_find(const char *client_ip)
1793{
1794        struct og_cmd *cmd, *next;
1795
1796        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
1797                if (strcmp(cmd->ip, client_ip))
1798                        continue;
1799
1800                list_del(&cmd->list);
1801                return cmd;
1802        }
1803
1804        return NULL;
1805}
1806
1807void og_cmd_free(const struct og_cmd *cmd)
1808{
1809        struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
1810        int i;
1811
1812        for (i = 0; i < params->ips_array_len; i++) {
1813                free((void *)params->ips_array[i]);
1814                free((void *)params->mac_array[i]);
1815        }
1816        free((void *)params->wol_type);
1817
1818        if (cmd->json)
1819                json_decref(cmd->json);
1820
1821        free((void *)cmd->ip);
1822        free((void *)cmd->mac);
1823        free((void *)cmd);
1824}
1825
1826static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
1827                        enum og_cmd_type type, json_t *root)
1828{
1829        cmd->type = type;
1830        cmd->method = method;
1831        cmd->params.ips_array[0] = strdup(cmd->ip);
1832        cmd->params.ips_array_len = 1;
1833        cmd->json = root;
1834}
1835
1836static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
1837{
1838        char wol_type[2] = {};
1839
1840        if (sscanf(input, "mar=%s", wol_type) != 1) {
1841                syslog(LOG_ERR, "malformed database legacy input\n");
1842                return -1;
1843        }
1844
1845        og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
1846        cmd->params.mac_array[0] = strdup(cmd->mac);
1847        cmd->params.wol_type = strdup(wol_type);
1848
1849        return 0;
1850}
1851
1852static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
1853{
1854        json_t *root, *script, *echo;
1855
1856        script = json_string(input + 4);
1857        echo = json_boolean(false);
1858
1859        root = json_object();
1860        if (!root)
1861                return -1;
1862        json_object_set_new(root, "run", script);
1863        json_object_set_new(root, "echo", echo);
1864
1865        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
1866
1867        return 0;
1868}
1869
1870static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
1871{
1872        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
1873        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
1874        json_t *root, *disk, *partition;
1875
1876        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
1877                return -1;
1878        partition = json_string(part_str);
1879        disk = json_string(disk_str);
1880
1881        root = json_object();
1882        if (!root)
1883                return -1;
1884        json_object_set_new(root, "partition", partition);
1885        json_object_set_new(root, "disk", disk);
1886
1887        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
1888
1889        return 0;
1890}
1891
1892static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
1893{
1894        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
1895
1896        return 0;
1897}
1898
1899static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
1900{
1901        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
1902
1903        return 0;
1904}
1905
1906static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
1907{
1908        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
1909
1910        return 0;
1911}
1912
1913static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
1914{
1915        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
1916
1917        return 0;
1918}
1919
1920static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
1921{
1922        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
1923
1924        return 0;
1925}
1926
1927static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
1928{
1929        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, NULL);
1930
1931        return 0;
1932}
1933
1934static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
1935{
1936        json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
1937        struct og_image_legacy img = {};
1938
1939        if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
1940                   img.disk, img.part, img.code, img.image_id, img.name,
1941                   img.repo) != 6)
1942                return -1;
1943        image_id = json_string(img.image_id);
1944        partition = json_string(img.part);
1945        code = json_string(img.code);
1946        name = json_string(img.name);
1947        repo = json_string(img.repo);
1948        disk = json_string(img.disk);
1949
1950        root = json_object();
1951        if (!root)
1952                return -1;
1953        json_object_set_new(root, "partition", partition);
1954        json_object_set_new(root, "repository", repo);
1955        json_object_set_new(root, "id", image_id);
1956        json_object_set_new(root, "code", code);
1957        json_object_set_new(root, "name", name);
1958        json_object_set_new(root, "disk", disk);
1959
1960        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
1961
1962        return 0;
1963}
1964
1965#define OG_DB_RESTORE_TYPE_MAXLEN       64
1966
1967static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
1968{
1969        json_t *root, *disk, *partition, *image_id, *name, *repo;
1970        char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
1971        char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
1972        json_t *software_id, *restore_type;
1973        struct og_image_legacy img = {};
1974
1975        if (sscanf(input,
1976                   "dsk=%s\rpar=%s\ridi=%s\rnci=%s\ripr=%s\rifs=%s\rptc=%s\r",
1977                   img.disk, img.part, img.image_id, img.name, img.repo,
1978                   software_id_str, restore_type_str) != 7)
1979                return -1;
1980
1981        restore_type = json_string(restore_type_str);
1982        software_id = json_string(software_id_str);
1983        image_id = json_string(img.image_id);
1984        partition = json_string(img.part);
1985        name = json_string(img.name);
1986        repo = json_string(img.repo);
1987        disk = json_string(img.disk);
1988
1989        root = json_object();
1990        if (!root)
1991                return -1;
1992        json_object_set_new(root, "profile", software_id);
1993        json_object_set_new(root, "partition", partition);
1994        json_object_set_new(root, "type", restore_type);
1995        json_object_set_new(root, "repository", repo);
1996        json_object_set_new(root, "id", image_id);
1997        json_object_set_new(root, "name", name);
1998        json_object_set_new(root, "disk", disk);
1999
2000        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2001
2002        return 0;
2003}
2004
2005static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2006{
2007        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
2008        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
2009        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2010        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2011        json_t *part, *code, *fs, *size, *format;
2012        unsigned int partition_len = 0;
2013        const char *in_ptr;
2014        char cache_str[2];
2015
2016        if (sscanf(input, "dsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2017                   disk_str, cache_str, cache_size_str) != 3)
2018                return -1;
2019
2020        in_ptr = strstr(input, "!") + 1;
2021        while (strlen(in_ptr) > 0) {
2022                if(sscanf(in_ptr,
2023                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2024                          part_cfg[partition_len].partition,
2025                          part_cfg[partition_len].code,
2026                          part_cfg[partition_len].filesystem,
2027                          part_cfg[partition_len].size,
2028                          part_cfg[partition_len].format) != 5)
2029                        return -1;
2030                in_ptr = strstr(in_ptr, "%") + 1;
2031                partition_len++;
2032        }
2033
2034        root = json_object();
2035        if (!root)
2036                return -1;
2037
2038        cache_size = json_string(cache_size_str);
2039        cache = json_string(cache_str);
2040        partition_setup = json_array();
2041        disk = json_string(disk_str);
2042
2043        for (unsigned int i = 0; i < partition_len; ++i) {
2044                object = json_object();
2045                if (!object) {
2046                        json_decref(root);
2047                        return -1;
2048                }
2049
2050                part = json_string(part_cfg[i].partition);
2051                fs = json_string(part_cfg[i].filesystem);
2052                format = json_string(part_cfg[i].format);
2053                code = json_string(part_cfg[i].code);
2054                size = json_string(part_cfg[i].size);
2055
2056                json_object_set_new(object, "partition", part);
2057                json_object_set_new(object, "filesystem", fs);
2058                json_object_set_new(object, "format", format);
2059                json_object_set_new(object, "code", code);
2060                json_object_set_new(object, "size", size);
2061
2062                json_array_append_new(partition_setup, object);
2063        }
2064
2065        json_object_set_new(root, "partition_setup", partition_setup);
2066        json_object_set_new(root, "cache_size", cache_size);
2067        json_object_set_new(root, "cache", cache);
2068        json_object_set_new(root, "disk", disk);
2069
2070        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2071
2072        return 0;
2073}
2074
2075static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2076{
2077        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2078
2079        return 0;
2080}
2081
2082static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2083{
2084        char legacy_cmd[32] = {};
2085        int err = -1;
2086
2087        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2088                syslog(LOG_ERR, "malformed database legacy input\n");
2089                return -1;
2090        }
2091        input = strchr(input, '\r') + 1;
2092
2093        if (!strcmp(legacy_cmd, "Arrancar")) {
2094                err = og_cmd_legacy_wol(input, cmd);
2095        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2096                err = og_cmd_legacy_shell_run(input, cmd);
2097        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2098                err = og_cmd_legacy_session(input, cmd);
2099        } else if (!strcmp(legacy_cmd, "Apagar")) {
2100                err = og_cmd_legacy_poweroff(input, cmd);
2101        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2102                err = og_cmd_legacy_refresh(input, cmd);
2103        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2104                err = og_cmd_legacy_reboot(input, cmd);
2105        } else if (!strcmp(legacy_cmd, "Purgar")) {
2106                err = og_cmd_legacy_stop(input, cmd);
2107        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2108                err = og_cmd_legacy_hardware(input, cmd);
2109        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2110                err = og_cmd_legacy_software(input, cmd);
2111        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2112                err = og_cmd_legacy_image_create(input, cmd);
2113        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2114                err = og_cmd_legacy_image_restore(input, cmd);
2115        } else if (!strcmp(legacy_cmd, "Configurar")) {
2116                err = og_cmd_legacy_setup(input, cmd);
2117        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2118                   !strcmp(legacy_cmd, "Actualizar")) {
2119                err = og_cmd_legacy_run_schedule(input, cmd);
2120        }
2121
2122        return err;
2123}
2124
2125static int og_dbi_add_action(const struct og_dbi *dbi, const struct og_task *task,
2126                             struct og_cmd *cmd)
2127{
2128        char start_date_string[24];
2129        struct tm *start_date;
2130        const char *msglog;
2131        dbi_result result;
2132        time_t now;
2133
2134        time(&now);
2135        start_date = localtime(&now);
2136
2137        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2138                start_date->tm_year + 1900, start_date->tm_mon + 1,
2139                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2140                start_date->tm_sec);
2141        result = dbi_conn_queryf(dbi->conn,
2142                                "INSERT INTO acciones (idordenador, "
2143                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2144                                "sesion, idcomando, parametros, fechahorareg, "
2145                                "estado, resultado, ambito, idambito, "
2146                                "restrambito, idprocedimiento, idcentro, "
2147                                "idprogramacion) "
2148                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2149                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2150                                cmd->client_id, EJECUCION_TAREA, task->task_id,
2151                                "", cmd->ip, 0, task->command_id,
2152                                task->params, start_date_string,
2153                                ACCION_INICIADA, ACCION_SINRESULTADO,
2154                                task->type_scope, task->scope, "",
2155                                task->procedure_id, task->center_id,
2156                                task->schedule_id);
2157        if (!result) {
2158                dbi_conn_error(dbi->conn, &msglog);
2159                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2160                       __func__, __LINE__, msglog);
2161                return -1;
2162        }
2163        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
2164        dbi_result_free(result);
2165
2166        return 0;
2167}
2168
2169static int og_queue_task_command(struct og_dbi *dbi, const struct og_task *task,
2170                                 char *query)
2171{
2172        struct og_cmd *cmd;
2173        const char *msglog;
2174        dbi_result result;
2175
2176        result = dbi_conn_queryf(dbi->conn, query);
2177        if (!result) {
2178                dbi_conn_error(dbi->conn, &msglog);
2179                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2180                       __func__, __LINE__, msglog);
2181                return -1;
2182        }
2183
2184        while (dbi_result_next_row(result)) {
2185                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2186                if (!cmd) {
2187                        dbi_result_free(result);
2188                        return -1;
2189                }
2190
2191                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2192                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2193                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2194
2195                og_cmd_legacy(task->params, cmd);
2196
2197                if (task->procedure_id) {
2198                        if (og_dbi_add_action(dbi, task, cmd)) {
2199                                dbi_result_free(result);
2200                                return -1;
2201                        }
2202                } else {
2203                        cmd->id = task->task_id;
2204                }
2205
2206                list_add_tail(&cmd->list, &cmd_list);
2207        }
2208
2209        dbi_result_free(result);
2210
2211        return 0;
2212}
2213
2214static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2215                                       char *query)
2216{
2217
2218        const char *msglog;
2219        dbi_result result;
2220
2221        result = dbi_conn_queryf(dbi->conn, query);
2222        if (!result) {
2223                dbi_conn_error(dbi->conn, &msglog);
2224                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2225                       __func__, __LINE__, msglog);
2226                return -1;
2227        }
2228
2229        while (dbi_result_next_row(result)) {
2230                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2231
2232                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2233                                "WHERE grupoid=%d", group_id);
2234                if (og_queue_task_group_clients(dbi, task, query)) {
2235                        dbi_result_free(result);
2236                        return -1;
2237                }
2238
2239                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2240                              "WHERE grupoid=%d", group_id);
2241                if (og_queue_task_command(dbi, task, query)) {
2242                        dbi_result_free(result);
2243                        return -1;
2244                }
2245
2246        }
2247
2248        dbi_result_free(result);
2249
2250        return 0;
2251}
2252
2253static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2254                                          struct og_task *task, char *query)
2255{
2256
2257        const char *msglog;
2258        dbi_result result;
2259
2260        result = dbi_conn_queryf(dbi->conn, query);
2261        if (!result) {
2262                dbi_conn_error(dbi->conn, &msglog);
2263                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2264                       __func__, __LINE__, msglog);
2265                return -1;
2266        }
2267
2268        while (dbi_result_next_row(result)) {
2269                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2270
2271                sprintf(query, "SELECT idgrupo FROM grupos "
2272                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2273                if (og_queue_task_group_classrooms(dbi, task, query)) {
2274                        dbi_result_free(result);
2275                        return -1;
2276                }
2277
2278                sprintf(query,
2279                        "SELECT ip,mac,idordenador "
2280                        "FROM ordenadores INNER JOIN aulas "
2281                        "WHERE ordenadores.idaula=aulas.idaula "
2282                        "AND aulas.grupoid=%d",
2283                        group_id);
2284                if (og_queue_task_command(dbi, task, query)) {
2285                        dbi_result_free(result);
2286                        return -1;
2287                }
2288
2289        }
2290
2291        dbi_result_free(result);
2292
2293        return 0;
2294}
2295
2296static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2297{
2298        char query[4096];
2299
2300        switch (task->type_scope) {
2301                case AMBITO_CENTROS:
2302                        sprintf(query,
2303                                "SELECT ip,mac,idordenador "
2304                                "FROM ordenadores INNER JOIN aulas "
2305                                "WHERE ordenadores.idaula=aulas.idaula "
2306                                "AND idcentro=%d",
2307                                task->scope);
2308                        return og_queue_task_command(dbi, task, query);
2309                case AMBITO_GRUPOSAULAS:
2310                        sprintf(query,
2311                                "SELECT idgrupo FROM grupos "
2312                                "WHERE idgrupo=%i AND tipo=%d",
2313                                task->scope, AMBITO_GRUPOSAULAS);
2314                        return og_queue_task_group_classrooms(dbi, task, query);
2315                case AMBITO_AULAS:
2316                        sprintf(query,
2317                                "SELECT ip,mac,idordenador FROM ordenadores "
2318                                "WHERE idaula=%d",
2319                                task->scope);
2320                        return og_queue_task_command(dbi, task, query);
2321                case AMBITO_GRUPOSORDENADORES:
2322                        sprintf(query,
2323                                "SELECT idgrupo FROM gruposordenadores "
2324                                "WHERE idgrupo = %d",
2325                                task->scope);
2326                        return og_queue_task_group_clients(dbi, task, query);
2327                case AMBITO_ORDENADORES:
2328                        sprintf(query,
2329                                "SELECT ip, mac, idordenador FROM ordenadores "
2330                                "WHERE idordenador = %d",
2331                                task->scope);
2332                        return og_queue_task_command(dbi, task, query);
2333        }
2334        return 0;
2335}
2336
2337int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2338{
2339        uint32_t procedure_id;
2340        const char *msglog;
2341        dbi_result result;
2342
2343        result = dbi_conn_queryf(dbi->conn,
2344                        "SELECT parametros, procedimientoid, idcomando "
2345                        "FROM procedimientos_acciones "
2346                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2347        if (!result) {
2348                dbi_conn_error(dbi->conn, &msglog);
2349                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2350                       __func__, __LINE__, msglog);
2351                return -1;
2352        }
2353
2354        while (dbi_result_next_row(result)) {
2355                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2356                if (procedure_id > 0) {
2357                        task->procedure_id = procedure_id;
2358                        if (og_dbi_queue_procedure(dbi, task))
2359                                return -1;
2360                        continue;
2361                }
2362
2363                task->params    = strdup(dbi_result_get_string(result, "parametros"));
2364                task->command_id = dbi_result_get_uint(result, "idcomando");
2365                if (og_queue_task_clients(dbi, task))
2366                        return -1;
2367        }
2368
2369        dbi_result_free(result);
2370
2371        return 0;
2372}
2373
2374static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
2375                             uint32_t schedule_id)
2376{
2377        struct og_task task = {};
2378        uint32_t task_id_next;
2379        const char *msglog;
2380        dbi_result result;
2381
2382        task.schedule_id = schedule_id;
2383
2384        result = dbi_conn_queryf(dbi->conn,
2385                        "SELECT tareas_acciones.orden, "
2386                                "tareas_acciones.idprocedimiento, "
2387                                "tareas_acciones.tareaid, "
2388                                "tareas.idtarea, "
2389                                "tareas.idcentro, "
2390                                "tareas.ambito, "
2391                                "tareas.idambito, "
2392                                "tareas.restrambito "
2393                        " FROM tareas"
2394                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
2395                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
2396        if (!result) {
2397                dbi_conn_error(dbi->conn, &msglog);
2398                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2399                       __func__, __LINE__, msglog);
2400                return -1;
2401        }
2402
2403        while (dbi_result_next_row(result)) {
2404                task_id_next = dbi_result_get_uint(result, "tareaid");
2405
2406                if (task_id_next > 0) {
2407                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
2408                                return -1;
2409
2410                        continue;
2411                }
2412                task.task_id = dbi_result_get_uint(result, "idtarea");
2413                task.center_id = dbi_result_get_uint(result, "idcentro");
2414                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
2415                task.type_scope = dbi_result_get_uint(result, "ambito");
2416                task.scope = dbi_result_get_uint(result, "idambito");
2417                task.filtered_scope = dbi_result_get_string(result, "restrambito");
2418
2419                og_dbi_queue_procedure(dbi, &task);
2420        }
2421
2422        dbi_result_free(result);
2423
2424        return 0;
2425}
2426
2427static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
2428                                uint32_t schedule_id)
2429{
2430        struct og_task task = {};
2431        const char *msglog;
2432        dbi_result result;
2433        char query[4096];
2434
2435        result = dbi_conn_queryf(dbi->conn,
2436                        "SELECT idaccion, idcentro, idordenador, parametros "
2437                        "FROM acciones "
2438                        "WHERE sesion = %u", task_id);
2439        if (!result) {
2440                dbi_conn_error(dbi->conn, &msglog);
2441                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2442                       __func__, __LINE__, msglog);
2443                return -1;
2444        }
2445
2446        while (dbi_result_next_row(result)) {
2447                task.task_id = dbi_result_get_uint(result, "idaccion");
2448                task.center_id = dbi_result_get_uint(result, "idcentro");
2449                task.scope = dbi_result_get_uint(result, "idordenador");
2450                task.params = strdup(dbi_result_get_string(result, "parametros"));
2451
2452                sprintf(query,
2453                        "SELECT ip, mac, idordenador FROM ordenadores "
2454                        "WHERE idordenador = %d",
2455                        task.scope);
2456                if (og_queue_task_command(dbi, &task, query)) {
2457                        dbi_result_free(result);
2458                        return -1;
2459                }
2460        }
2461
2462        dbi_result_free(result);
2463
2464        return 0;
2465}
2466
2467int og_dbi_update_action(uint32_t id, bool success)
2468{
2469        char end_date_string[24];
2470        struct tm *end_date;
2471        const char *msglog;
2472        struct og_dbi *dbi;
2473        uint8_t status = 2;
2474        dbi_result result;
2475        time_t now;
2476
2477        if (!id)
2478                return 0;
2479
2480        dbi = og_dbi_open(&dbi_config);
2481        if (!dbi) {
2482                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2483                       __func__, __LINE__);
2484                return -1;
2485        }
2486
2487        time(&now);
2488        end_date = localtime(&now);
2489
2490        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2491                end_date->tm_year + 1900, end_date->tm_mon + 1,
2492                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
2493                end_date->tm_sec);
2494        result = dbi_conn_queryf(dbi->conn,
2495                                 "UPDATE acciones SET fechahorafin='%s', "
2496                                 "estado=%d, resultado=%d WHERE idaccion=%d",
2497                                 end_date_string, ACCION_FINALIZADA,
2498                                 status - success, id);
2499
2500        if (!result) {
2501                dbi_conn_error(dbi->conn, &msglog);
2502                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2503                       __func__, __LINE__, msglog);
2504                og_dbi_close(dbi);
2505                return -1;
2506        }
2507        dbi_result_free(result);
2508        og_dbi_close(dbi);
2509
2510        return 0;
2511}
2512
2513void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
2514                     enum og_schedule_type type)
2515{
2516        struct og_msg_params params = {};
2517        bool duplicated = false;
2518        struct og_cmd *cmd, *next;
2519        struct og_dbi *dbi;
2520        unsigned int i;
2521
2522        dbi = og_dbi_open(&dbi_config);
2523        if (!dbi) {
2524                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2525                       __func__, __LINE__);
2526                return;
2527        }
2528
2529        switch (type) {
2530        case OG_SCHEDULE_TASK:
2531                og_dbi_queue_task(dbi, task_id, schedule_id);
2532                break;
2533        case OG_SCHEDULE_PROCEDURE:
2534        case OG_SCHEDULE_COMMAND:
2535                og_dbi_queue_command(dbi, task_id, schedule_id);
2536                break;
2537        }
2538        og_dbi_close(dbi);
2539
2540        list_for_each_entry(cmd, &cmd_list, list) {
2541                for (i = 0; i < params.ips_array_len; i++) {
2542                        if (!strncmp(cmd->ip, params.ips_array[i],
2543                                     OG_DB_IP_MAXLEN)) {
2544                                duplicated = true;
2545                                break;
2546                        }
2547                }
2548
2549                if (!duplicated)
2550                        params.ips_array[params.ips_array_len++] = cmd->ip;
2551                else
2552                        duplicated = false;
2553        }
2554
2555        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2556                if (cmd->type != OG_CMD_WOL)
2557                        continue;
2558
2559                if (Levanta((char **)cmd->params.ips_array,
2560                            (char **)cmd->params.mac_array,
2561                            (char **)cmd->params.netmask_array,
2562                            cmd->params.ips_array_len,
2563                            (char *)cmd->params.wol_type))
2564                        og_dbi_update_action(cmd->id, true);
2565
2566                list_del(&cmd->list);
2567                og_cmd_free(cmd);
2568        }
2569
2570        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
2571}
2572
2573static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
2574{
2575        struct og_cmd *cmd;
2576        struct og_dbi *dbi;
2577        const char *key;
2578        json_t *value;
2579        int err;
2580
2581        if (json_typeof(element) != JSON_OBJECT)
2582                return -1;
2583
2584        json_object_foreach(element, key, value) {
2585                if (!strcmp(key, "task")) {
2586                        err = og_json_parse_string(value, &params->task_id);
2587                        params->flags |= OG_REST_PARAM_TASK;
2588                }
2589
2590                if (err < 0)
2591                        break;
2592        }
2593
2594        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
2595                return -1;
2596
2597        dbi = og_dbi_open(&dbi_config);
2598        if (!dbi) {
2599                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2600                           __func__, __LINE__);
2601                return -1;
2602        }
2603
2604        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
2605        og_dbi_close(dbi);
2606
2607        list_for_each_entry(cmd, &cmd_list, list)
2608                params->ips_array[params->ips_array_len++] = cmd->ip;
2609
2610        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2611                               NULL);
2612}
2613
2614static int og_dbi_scope_get_computer(struct og_dbi *dbi, json_t *array,
2615                                     uint32_t room_id)
2616{
2617        char computer_name[OG_DB_COMPUTER_NAME_MAXLEN + 1] = {};
2618        uint32_t computer_id;
2619        const char *msglog;
2620        dbi_result result;
2621        json_t *computer;
2622
2623        result = dbi_conn_queryf(dbi->conn,
2624                                 "SELECT idordenador, nombreordenador, ip "
2625                                 "FROM ordenadores WHERE idaula=%d",
2626                                 room_id);
2627        if (!result) {
2628                dbi_conn_error(dbi->conn, &msglog);
2629                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2630                       __func__, __LINE__, msglog);
2631                return -1;
2632        }
2633
2634        while (dbi_result_next_row(result)) {
2635                computer_id = dbi_result_get_uint(result, "idordenador");
2636                strncpy(computer_name,
2637                        dbi_result_get_string(result, "nombreordenador"),
2638                        OG_DB_CENTER_NAME_MAXLEN);
2639
2640                computer = json_object();
2641                if (!computer) {
2642                        dbi_result_free(result);
2643                        return -1;
2644                }
2645
2646                json_object_set_new(computer, "name", json_string(computer_name));
2647                json_object_set_new(computer, "type", json_string("computer"));
2648                json_object_set_new(computer, "id", json_integer(computer_id));
2649                json_object_set_new(computer, "scope", json_array());
2650                json_array_append(array, computer);
2651                json_decref(computer);
2652        }
2653        dbi_result_free(result);
2654
2655        return 0;
2656}
2657
2658static int og_dbi_scope_get_room(struct og_dbi *dbi, json_t *array,
2659                                 uint32_t center_id)
2660{
2661        char room_name[OG_DB_ROOM_NAME_MAXLEN + 1] = {};
2662        json_t *room, *room_array;
2663        const char *msglog;
2664        dbi_result result;
2665        uint32_t room_id;
2666
2667        result = dbi_conn_queryf(dbi->conn,
2668                                 "SELECT idaula, nombreaula FROM aulas WHERE "
2669                                 "idcentro=%d",
2670                                 center_id);
2671        if (!result) {
2672                dbi_conn_error(dbi->conn, &msglog);
2673                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2674                       __func__, __LINE__, msglog);
2675                return -1;
2676        }
2677
2678        while (dbi_result_next_row(result)) {
2679                room_id = dbi_result_get_uint(result, "idaula");
2680                strncpy(room_name,
2681                        dbi_result_get_string(result, "nombreaula"),
2682                        OG_DB_CENTER_NAME_MAXLEN);
2683
2684                room = json_object();
2685                if (!room) {
2686                        dbi_result_free(result);
2687                        return -1;
2688                }
2689
2690                json_object_set_new(room, "name", json_string(room_name));
2691                json_object_set_new(room, "type", json_string("room"));
2692                json_object_set_new(room, "id", json_integer(room_id));
2693                json_object_set_new(room, "scope", json_array());
2694                json_array_append(array, room);
2695                json_decref(room);
2696
2697                room_array = json_object_get(room, "scope");
2698                if (!room_array) {
2699                        dbi_result_free(result);
2700                        return -1;
2701                }
2702
2703                if (og_dbi_scope_get_computer(dbi, room_array, room_id)) {
2704                        dbi_result_free(result);
2705                        return -1;
2706                }
2707        }
2708        dbi_result_free(result);
2709
2710        return 0;
2711}
2712
2713static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
2714{
2715        char center_name[OG_DB_CENTER_NAME_MAXLEN + 1] = {};
2716        json_t *center, *array_room;
2717        const char *msglog;
2718        uint32_t center_id;
2719        dbi_result result;
2720
2721        result = dbi_conn_queryf(dbi->conn,
2722                                 "SELECT nombrecentro, idcentro FROM centros");
2723        if (!result) {
2724                dbi_conn_error(dbi->conn, &msglog);
2725                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2726                       __func__, __LINE__, msglog);
2727                return -1;
2728        }
2729
2730        while (dbi_result_next_row(result)) {
2731                center_id = dbi_result_get_uint(result, "idcentro");
2732                strncpy(center_name,
2733                        dbi_result_get_string(result, "nombrecentro"),
2734                        OG_DB_CENTER_NAME_MAXLEN);
2735
2736                center = json_object();
2737                if (!center) {
2738                        dbi_result_free(result);
2739                        return -1;
2740                }
2741
2742                array_room = json_array();
2743                if (!array_room) {
2744                        dbi_result_free(result);
2745                        json_decref(center);
2746                        return -1;
2747                }
2748
2749                json_object_set_new(center, "name", json_string(center_name));
2750                json_object_set_new(center, "type", json_string("center"));
2751                json_object_set_new(center, "id", json_integer(center_id));
2752                json_object_set_new(center, "scope", array_room);
2753                json_array_append(array, center);
2754                json_decref(center);
2755
2756                if (og_dbi_scope_get_room(dbi, array_room, center_id)) {
2757                        dbi_result_free(result);
2758                        return -1;
2759                }
2760        }
2761
2762        dbi_result_free(result);
2763
2764        return 0;
2765}
2766
2767static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
2768                            char *buffer_reply)
2769{
2770        struct og_buffer og_buffer = {
2771                .data = buffer_reply
2772        };
2773        json_t *root, *array;
2774        struct og_dbi *dbi;
2775
2776        root = json_object();
2777        if (!root)
2778                return -1;
2779
2780        array = json_array();
2781        if (!array) {
2782                json_decref(root);
2783                return -1;
2784        }
2785        json_object_set_new(root, "scope", array);
2786
2787        dbi = og_dbi_open(&dbi_config);
2788        if (!dbi) {
2789                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2790                       __func__, __LINE__);
2791                json_decref(root);
2792                return -1;
2793        }
2794
2795        if (og_dbi_scope_get(dbi, array)) {
2796                og_dbi_close(dbi);
2797                json_decref(root);
2798                return -1;
2799        }
2800
2801        og_dbi_close(dbi);
2802
2803        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
2804        json_decref(root);
2805
2806        return 0;
2807}
2808
2809int og_dbi_schedule_get(void)
2810{
2811        uint32_t schedule_id, task_id;
2812        struct og_schedule_time time;
2813        struct og_dbi *dbi;
2814        const char *msglog;
2815        dbi_result result;
2816
2817        dbi = og_dbi_open(&dbi_config);
2818        if (!dbi) {
2819                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2820                       __func__, __LINE__);
2821                return -1;
2822        }
2823
2824        result = dbi_conn_queryf(dbi->conn,
2825                                 "SELECT idprogramacion, tipoaccion, identificador, "
2826                                 "sesion, annos, meses, diario, dias, semanas, horas, "
2827                                 "ampm, minutos FROM programaciones "
2828                                 "WHERE suspendida = 0");
2829        if (!result) {
2830                dbi_conn_error(dbi->conn, &msglog);
2831                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2832                       __func__, __LINE__, msglog);
2833                og_dbi_close(dbi);
2834                return -1;
2835        }
2836
2837        while (dbi_result_next_row(result)) {
2838                memset(&time, 0, sizeof(time));
2839                schedule_id = dbi_result_get_uint(result, "idprogramacion");
2840                task_id = dbi_result_get_uint(result, "identificador");
2841                time.years = dbi_result_get_uint(result, "annos");
2842                time.months = dbi_result_get_uint(result, "meses");
2843                time.weeks = dbi_result_get_uint(result, "semanas");
2844                time.week_days = dbi_result_get_uint(result, "dias");
2845                time.days = dbi_result_get_uint(result, "diario");
2846                time.hours = dbi_result_get_uint(result, "horas");
2847                time.am_pm = dbi_result_get_uint(result, "ampm");
2848                time.minutes = dbi_result_get_uint(result, "minutos");
2849                time.on_start = true;
2850
2851                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
2852                                   &time);
2853        }
2854
2855        dbi_result_free(result);
2856        og_dbi_close(dbi);
2857
2858        return 0;
2859}
2860
2861static int og_dbi_schedule_create(struct og_dbi *dbi,
2862                                  struct og_msg_params *params,
2863                                  uint32_t *schedule_id,
2864                                  enum og_schedule_type schedule_type)
2865{
2866        uint8_t suspended = 0;
2867        uint32_t session = 0;
2868        const char *msglog;
2869        dbi_result result;
2870        uint8_t type;
2871
2872        switch (schedule_type) {
2873        case OG_SCHEDULE_TASK:
2874                type = 3;
2875                break;
2876        case OG_SCHEDULE_PROCEDURE:
2877                type = 2;
2878                break;
2879        case OG_SCHEDULE_COMMAND:
2880                session = atoi(params->task_id);
2881                type = 1;
2882                break;
2883        }
2884
2885        result = dbi_conn_queryf(dbi->conn,
2886                                 "INSERT INTO programaciones (tipoaccion,"
2887                                 " identificador, nombrebloque, annos, meses,"
2888                                 " semanas, dias, diario, horas, ampm, minutos,"
2889                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
2890                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
2891                                 type, params->task_id, params->name,
2892                                 params->time.years, params->time.months,
2893                                 params->time.weeks, params->time.week_days,
2894                                 params->time.days, params->time.hours,
2895                                 params->time.am_pm, params->time.minutes,
2896                                 suspended, session);
2897        if (!result) {
2898                dbi_conn_error(dbi->conn, &msglog);
2899                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2900                       __func__, __LINE__, msglog);
2901                return -1;
2902        }
2903        dbi_result_free(result);
2904
2905        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
2906
2907        return 0;
2908}
2909
2910static int og_dbi_schedule_update(struct og_dbi *dbi,
2911                                  struct og_msg_params *params)
2912{
2913        const char *msglog;
2914        dbi_result result;
2915        uint8_t type = 3;
2916
2917        result = dbi_conn_queryf(dbi->conn,
2918                                 "UPDATE programaciones SET tipoaccion=%d, "
2919                                 "identificador='%s', nombrebloque='%s', "
2920                                 "annos=%d, meses=%d, "
2921                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
2922                                 "WHERE idprogramacion='%s'",
2923                                 type, params->task_id, params->name,
2924                                 params->time.years, params->time.months,
2925                                 params->time.days, params->time.hours,
2926                                 params->time.am_pm, params->time.minutes,
2927                                 params->id);
2928
2929        if (!result) {
2930                dbi_conn_error(dbi->conn, &msglog);
2931                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2932                       __func__, __LINE__, msglog);
2933                return -1;
2934        }
2935        dbi_result_free(result);
2936
2937        return 0;
2938}
2939
2940static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
2941{
2942        const char *msglog;
2943        dbi_result result;
2944
2945        result = dbi_conn_queryf(dbi->conn,
2946                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
2947                                 id);
2948        if (!result) {
2949                dbi_conn_error(dbi->conn, &msglog);
2950                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2951                       __func__, __LINE__, msglog);
2952                return -1;
2953        }
2954        dbi_result_free(result);
2955
2956        return 0;
2957}
2958
2959struct og_db_schedule {
2960        uint32_t                id;
2961        uint32_t                task_id;
2962        const char              *name;
2963        struct og_schedule_time time;
2964        uint32_t                week_days;
2965        uint32_t                weeks;
2966        uint32_t                suspended;
2967        uint32_t                session;
2968};
2969
2970static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
2971                                    const char *task_id, const char *schedule_id)
2972{
2973        struct og_db_schedule schedule;
2974        json_t *obj, *array;
2975        const char *msglog;
2976        dbi_result result;
2977        int err = 0;
2978
2979        if (task_id) {
2980                result = dbi_conn_queryf(dbi->conn,
2981                                         "SELECT idprogramacion,"
2982                                         "       identificador, nombrebloque,"
2983                                         "       annos, meses, diario, dias,"
2984                                         "       semanas, horas, ampm,"
2985                                         "       minutos,suspendida, sesion "
2986                                         "FROM programaciones "
2987                                         "WHERE identificador=%d",
2988                                         atoi(task_id));
2989        } else if (schedule_id) {
2990                result = dbi_conn_queryf(dbi->conn,
2991                                         "SELECT idprogramacion,"
2992                                         "       identificador, nombrebloque,"
2993                                         "       annos, meses, diario, dias,"
2994                                         "       semanas, horas, ampm,"
2995                                         "       minutos,suspendida, sesion "
2996                                         "FROM programaciones "
2997                                         "WHERE idprogramacion=%d",
2998                                         atoi(schedule_id));
2999        } else {
3000                result = dbi_conn_queryf(dbi->conn,
3001                                         "SELECT idprogramacion,"
3002                                         "       identificador, nombrebloque,"
3003                                         "       annos, meses, diario, dias,"
3004                                         "       semanas, horas, ampm,"
3005                                         "       minutos,suspendida, sesion "
3006                                         "FROM programaciones");
3007        }
3008
3009        if (!result) {
3010                dbi_conn_error(dbi->conn, &msglog);
3011                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3012                       __func__, __LINE__, msglog);
3013                return -1;
3014        }
3015
3016        array = json_array();
3017        if (!array)
3018                return -1;
3019
3020        while (dbi_result_next_row(result)) {
3021                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3022                schedule.task_id = dbi_result_get_uint(result, "identificador");
3023                schedule.name = dbi_result_get_string(result, "nombrebloque");
3024                schedule.time.years = dbi_result_get_uint(result, "annos");
3025                schedule.time.months = dbi_result_get_uint(result, "meses");
3026                schedule.time.days = dbi_result_get_uint(result, "diario");
3027                schedule.time.hours = dbi_result_get_uint(result, "horas");
3028                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3029                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3030                schedule.week_days = dbi_result_get_uint(result, "dias");
3031                schedule.weeks = dbi_result_get_uint(result, "semanas");
3032                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3033                schedule.session = dbi_result_get_uint(result, "sesion");
3034
3035                obj = json_object();
3036                if (!obj) {
3037                        err = -1;
3038                        break;
3039                }
3040                json_object_set_new(obj, "id", json_integer(schedule.id));
3041                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3042                json_object_set_new(obj, "name", json_string(schedule.name));
3043                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3044                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3045                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3046                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3047                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3048                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3049                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3050                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3051                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3052                json_object_set_new(obj, "session", json_integer(schedule.session));
3053
3054                json_array_append_new(array, obj);
3055        }
3056
3057        json_object_set_new(root, "schedule", array);
3058
3059        dbi_result_free(result);
3060
3061        return err;
3062}
3063
3064static int og_task_schedule_create(struct og_msg_params *params)
3065{
3066        enum og_schedule_type type;
3067        uint32_t schedule_id;
3068        struct og_dbi *dbi;
3069        int err;
3070
3071        if (!strcmp(params->type, "task"))
3072                type = OG_SCHEDULE_TASK;
3073        else if (!strcmp(params->type, "procedure"))
3074                type = OG_SCHEDULE_PROCEDURE;
3075        else if (!strcmp(params->type, "command"))
3076                type = OG_SCHEDULE_COMMAND;
3077        else
3078                return -1;
3079
3080        dbi = og_dbi_open(&dbi_config);
3081        if (!dbi) {
3082                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3083                       __func__, __LINE__);
3084                return -1;
3085        }
3086
3087        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3088        if (err < 0) {
3089                og_dbi_close(dbi);
3090                return -1;
3091        }
3092        og_schedule_create(schedule_id, atoi(params->task_id), type,
3093                           &params->time);
3094        og_schedule_refresh(og_loop);
3095        og_dbi_close(dbi);
3096
3097        return 0;
3098}
3099
3100static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3101{
3102        const char *key;
3103        json_t *value;
3104        int err;
3105
3106        if (json_typeof(element) != JSON_OBJECT)
3107                return -1;
3108
3109        json_object_foreach(element, key, value) {
3110                if (!strcmp(key, "task")) {
3111                        err = og_json_parse_string(value, &params->task_id);
3112                        params->flags |= OG_REST_PARAM_TASK;
3113                } else if (!strcmp(key, "name")) {
3114                        err = og_json_parse_string(value, &params->name);
3115                        params->flags |= OG_REST_PARAM_NAME;
3116                } else if (!strcmp(key, "when")) {
3117                        err = og_json_parse_time_params(value, params);
3118                } else if (!strcmp(key, "type")) {
3119                        err = og_json_parse_string(value, &params->type);
3120                        params->flags |= OG_REST_PARAM_TYPE;
3121                }
3122
3123                if (err < 0)
3124                        break;
3125        }
3126
3127        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3128                                            OG_REST_PARAM_NAME |
3129                                            OG_REST_PARAM_TIME_YEARS |
3130                                            OG_REST_PARAM_TIME_MONTHS |
3131                                            OG_REST_PARAM_TIME_WEEKS |
3132                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3133                                            OG_REST_PARAM_TIME_DAYS |
3134                                            OG_REST_PARAM_TIME_HOURS |
3135                                            OG_REST_PARAM_TIME_MINUTES |
3136                                            OG_REST_PARAM_TIME_AM_PM |
3137                                            OG_REST_PARAM_TYPE))
3138                return -1;
3139
3140        return og_task_schedule_create(params);
3141}
3142
3143static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3144{
3145        struct og_dbi *dbi;
3146        const char *key;
3147        json_t *value;
3148        int err;
3149
3150        if (json_typeof(element) != JSON_OBJECT)
3151                return -1;
3152
3153        json_object_foreach(element, key, value) {
3154                if (!strcmp(key, "id")) {
3155                        err = og_json_parse_string(value, &params->id);
3156                        params->flags |= OG_REST_PARAM_ID;
3157                } else if (!strcmp(key, "task")) {
3158                        err = og_json_parse_string(value, &params->task_id);
3159                        params->flags |= OG_REST_PARAM_TASK;
3160                } else if (!strcmp(key, "name")) {
3161                        err = og_json_parse_string(value, &params->name);
3162                        params->flags |= OG_REST_PARAM_NAME;
3163                } else if (!strcmp(key, "when"))
3164                        err = og_json_parse_time_params(value, params);
3165
3166                if (err < 0)
3167                        break;
3168        }
3169
3170        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3171                                            OG_REST_PARAM_TASK |
3172                                            OG_REST_PARAM_NAME |
3173                                            OG_REST_PARAM_TIME_YEARS |
3174                                            OG_REST_PARAM_TIME_MONTHS |
3175                                            OG_REST_PARAM_TIME_DAYS |
3176                                            OG_REST_PARAM_TIME_HOURS |
3177                                            OG_REST_PARAM_TIME_MINUTES |
3178                                            OG_REST_PARAM_TIME_AM_PM))
3179                return -1;
3180
3181        dbi = og_dbi_open(&dbi_config);
3182        if (!dbi) {
3183                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3184                           __func__, __LINE__);
3185                return -1;
3186        }
3187
3188        err = og_dbi_schedule_update(dbi, params);
3189        og_dbi_close(dbi);
3190
3191        if (err < 0)
3192                return err;
3193
3194        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3195                           &params->time);
3196        og_schedule_refresh(og_loop);
3197
3198        return err;
3199}
3200
3201static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3202{
3203        struct og_dbi *dbi;
3204        const char *key;
3205        json_t *value;
3206        int err;
3207
3208        if (json_typeof(element) != JSON_OBJECT)
3209                return -1;
3210
3211        json_object_foreach(element, key, value) {
3212                if (!strcmp(key, "id")) {
3213                        err = og_json_parse_string(value, &params->id);
3214                        params->flags |= OG_REST_PARAM_ID;
3215                } else {
3216                        return -1;
3217                }
3218
3219                if (err < 0)
3220                        break;
3221        }
3222
3223        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3224                return -1;
3225
3226        dbi = og_dbi_open(&dbi_config);
3227        if (!dbi) {
3228                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3229                           __func__, __LINE__);
3230                return -1;
3231        }
3232
3233        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3234        og_dbi_close(dbi);
3235
3236        og_schedule_delete(og_loop, atoi(params->id));
3237
3238        return err;
3239}
3240
3241static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3242                               char *buffer_reply)
3243{
3244        struct og_buffer og_buffer = {
3245                .data   = buffer_reply,
3246        };
3247        json_t *schedule_root;
3248        struct og_dbi *dbi;
3249        const char *key;
3250        json_t *value;
3251        int err;
3252
3253        if (element) {
3254                if (json_typeof(element) != JSON_OBJECT)
3255                        return -1;
3256
3257                json_object_foreach(element, key, value) {
3258                        if (!strcmp(key, "task")) {
3259                                err = og_json_parse_string(value,
3260                                                           &params->task_id);
3261                        } else if (!strcmp(key, "id")) {
3262                                err = og_json_parse_string(value, &params->id);
3263                        } else {
3264                                return -1;
3265                        }
3266
3267                        if (err < 0)
3268                                break;
3269                }
3270        }
3271
3272        dbi = og_dbi_open(&dbi_config);
3273        if (!dbi) {
3274                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3275                           __func__, __LINE__);
3276                return -1;
3277        }
3278
3279        schedule_root = json_object();
3280        if (!schedule_root) {
3281                og_dbi_close(dbi);
3282                return -1;
3283        }
3284
3285        err = og_dbi_schedule_get_json(dbi, schedule_root,
3286                                       params->task_id, params->id);
3287        og_dbi_close(dbi);
3288
3289        if (err >= 0)
3290                json_dump_callback(schedule_root, og_json_dump_clients, &og_buffer, 0);
3291
3292        json_decref(schedule_root);
3293
3294        return err;
3295}
3296
3297static int og_client_method_not_found(struct og_client *cli)
3298{
3299        /* To meet RFC 7231, this function MUST generate an Allow header field
3300         * containing the correct methods. For example: "Allow: POST\r\n"
3301         */
3302        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
3303                     "Content-Length: 0\r\n\r\n";
3304
3305        send(og_client_socket(cli), buf, strlen(buf), 0);
3306
3307        return -1;
3308}
3309
3310static int og_client_bad_request(struct og_client *cli)
3311{
3312        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
3313
3314        send(og_client_socket(cli), buf, strlen(buf), 0);
3315
3316        return -1;
3317}
3318
3319static int og_client_not_found(struct og_client *cli)
3320{
3321        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
3322
3323        send(og_client_socket(cli), buf, strlen(buf), 0);
3324
3325        return -1;
3326}
3327
3328static int og_client_not_authorized(struct og_client *cli)
3329{
3330        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
3331                     "WWW-Authenticate: Basic\r\n"
3332                     "Content-Length: 0\r\n\r\n";
3333
3334        send(og_client_socket(cli), buf, strlen(buf), 0);
3335
3336        return -1;
3337}
3338
3339static int og_server_internal_error(struct og_client *cli)
3340{
3341        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
3342                     "Content-Length: 0\r\n\r\n";
3343
3344        send(og_client_socket(cli), buf, strlen(buf), 0);
3345
3346        return -1;
3347}
3348
3349#define OG_MSG_RESPONSE_MAXLEN  65536
3350
3351static int og_client_ok(struct og_client *cli, char *buf_reply)
3352{
3353        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
3354        int err = 0, len;
3355
3356        len = snprintf(buf, sizeof(buf),
3357                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
3358                       strlen(buf_reply), buf_reply);
3359        if (len >= (int)sizeof(buf))
3360                err = og_server_internal_error(cli);
3361
3362        send(og_client_socket(cli), buf, strlen(buf), 0);
3363
3364        return err;
3365}
3366
3367int og_client_state_process_payload_rest(struct og_client *cli)
3368{
3369        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
3370        struct og_msg_params params = {};
3371        enum og_rest_method method;
3372        const char *cmd, *body;
3373        json_error_t json_err;
3374        json_t *root = NULL;
3375        int err = 0;
3376
3377        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
3378               inet_ntoa(cli->addr.sin_addr),
3379               ntohs(cli->addr.sin_port), cli->buf);
3380
3381        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
3382                method = OG_METHOD_GET;
3383                cmd = cli->buf + strlen("GET") + 2;
3384        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
3385                method = OG_METHOD_POST;
3386                cmd = cli->buf + strlen("POST") + 2;
3387        } else
3388                return og_client_method_not_found(cli);
3389
3390        body = strstr(cli->buf, "\r\n\r\n") + 4;
3391
3392        if (strcmp(cli->auth_token, auth_token)) {
3393                syslog(LOG_ERR, "wrong Authentication key\n");
3394                return og_client_not_authorized(cli);
3395        }
3396
3397        if (cli->content_length) {
3398                root = json_loads(body, 0, &json_err);
3399                if (!root) {
3400                        syslog(LOG_ERR, "malformed json line %d: %s\n",
3401                               json_err.line, json_err.text);
3402                        return og_client_not_found(cli);
3403                }
3404        }
3405
3406        if (!strncmp(cmd, "clients", strlen("clients"))) {
3407                if (method != OG_METHOD_POST &&
3408                    method != OG_METHOD_GET)
3409                        return og_client_method_not_found(cli);
3410
3411                if (method == OG_METHOD_POST && !root) {
3412                        syslog(LOG_ERR, "command clients with no payload\n");
3413                        return og_client_bad_request(cli);
3414                }
3415                switch (method) {
3416                case OG_METHOD_POST:
3417                        err = og_cmd_post_clients(root, &params);
3418                        break;
3419                case OG_METHOD_GET:
3420                        err = og_cmd_get_clients(root, &params, buf_reply);
3421                        break;
3422                default:
3423                        return og_client_bad_request(cli);
3424                }
3425        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
3426                if (method != OG_METHOD_POST)
3427                        return og_client_method_not_found(cli);
3428
3429                if (!root) {
3430                        syslog(LOG_ERR, "command wol with no payload\n");
3431                        return og_client_bad_request(cli);
3432                }
3433                err = og_cmd_wol(root, &params);
3434        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
3435                if (method != OG_METHOD_POST)
3436                        return og_client_method_not_found(cli);
3437
3438                if (!root) {
3439                        syslog(LOG_ERR, "command run with no payload\n");
3440                        return og_client_bad_request(cli);
3441                }
3442                err = og_cmd_run_post(root, &params);
3443        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
3444                if (method != OG_METHOD_POST)
3445                        return og_client_method_not_found(cli);
3446
3447                if (!root) {
3448                        syslog(LOG_ERR, "command output with no payload\n");
3449                        return og_client_bad_request(cli);
3450                }
3451
3452                err = og_cmd_run_get(root, &params, buf_reply);
3453        } else if (!strncmp(cmd, "session", strlen("session"))) {
3454                if (method != OG_METHOD_POST)
3455                        return og_client_method_not_found(cli);
3456
3457                if (!root) {
3458                        syslog(LOG_ERR, "command session with no payload\n");
3459                        return og_client_bad_request(cli);
3460                }
3461                err = og_cmd_session(root, &params);
3462        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
3463                if (method != OG_METHOD_GET)
3464                        return og_client_method_not_found(cli);
3465
3466                err = og_cmd_scope_get(root, &params, buf_reply);
3467        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
3468                if (method != OG_METHOD_POST)
3469                        return og_client_method_not_found(cli);
3470
3471                if (!root) {
3472                        syslog(LOG_ERR, "command poweroff with no payload\n");
3473                        return og_client_bad_request(cli);
3474                }
3475                err = og_cmd_poweroff(root, &params);
3476        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
3477                if (method != OG_METHOD_POST)
3478                        return og_client_method_not_found(cli);
3479
3480                if (!root) {
3481                        syslog(LOG_ERR, "command reboot with no payload\n");
3482                        return og_client_bad_request(cli);
3483                }
3484                err = og_cmd_reboot(root, &params);
3485        } else if (!strncmp(cmd, "modes", strlen("modes"))) {
3486                if (method != OG_METHOD_GET && method != OG_METHOD_POST)
3487                        return og_client_method_not_found(cli);
3488
3489                if (method == OG_METHOD_POST && !root) {
3490                        syslog(LOG_ERR, "command modes with no payload\n");
3491                        return og_client_bad_request(cli);
3492                }
3493
3494                if (method == OG_METHOD_GET)
3495                        err = og_cmd_get_modes(root, &params, buf_reply);
3496                else if (method == OG_METHOD_POST)
3497                        err = og_cmd_post_modes(root, &params);
3498        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
3499                if (method != OG_METHOD_POST)
3500                        return og_client_method_not_found(cli);
3501
3502                if (!root) {
3503                        syslog(LOG_ERR, "command stop with no payload\n");
3504                        return og_client_bad_request(cli);
3505                }
3506                err = og_cmd_stop(root, &params);
3507        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
3508                if (method != OG_METHOD_POST)
3509                        return og_client_method_not_found(cli);
3510
3511                if (!root) {
3512                        syslog(LOG_ERR, "command refresh with no payload\n");
3513                        return og_client_bad_request(cli);
3514                }
3515                err = og_cmd_refresh(root, &params);
3516        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
3517                if (method != OG_METHOD_GET && method != OG_METHOD_POST)
3518                        return og_client_method_not_found(cli);
3519
3520                if (!root) {
3521                        syslog(LOG_ERR, "command hardware with no payload\n");
3522                        return og_client_bad_request(cli);
3523                }
3524
3525                if (method == OG_METHOD_GET)
3526                        err = og_cmd_get_hardware(root, &params, buf_reply);
3527                else if (method == OG_METHOD_POST)
3528                        err = og_cmd_hardware(root, &params);
3529        } else if (!strncmp(cmd, "software", strlen("software"))) {
3530                if (method != OG_METHOD_POST)
3531                        return og_client_method_not_found(cli);
3532
3533                if (!root) {
3534                        syslog(LOG_ERR, "command software with no payload\n");
3535                        return og_client_bad_request(cli);
3536                }
3537                err = og_cmd_software(root, &params);
3538        } else if (!strncmp(cmd, "image/create/basic",
3539                            strlen("image/create/basic"))) {
3540                if (method != OG_METHOD_POST)
3541                        return og_client_method_not_found(cli);
3542
3543                if (!root) {
3544                        syslog(LOG_ERR, "command create with no payload\n");
3545                        return og_client_bad_request(cli);
3546                }
3547                err = og_cmd_create_basic_image(root, &params);
3548        } else if (!strncmp(cmd, "image/create/incremental",
3549                            strlen("image/create/incremental"))) {
3550                if (method != OG_METHOD_POST)
3551                        return og_client_method_not_found(cli);
3552
3553                if (!root) {
3554                        syslog(LOG_ERR, "command create with no payload\n");
3555                        return og_client_bad_request(cli);
3556                }
3557                err = og_cmd_create_incremental_image(root, &params);
3558        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
3559                if (method != OG_METHOD_POST)
3560                        return og_client_method_not_found(cli);
3561
3562                if (!root) {
3563                        syslog(LOG_ERR, "command create with no payload\n");
3564                        return og_client_bad_request(cli);
3565                }
3566                err = og_cmd_create_image(root, &params);
3567        } else if (!strncmp(cmd, "image/restore/basic",
3568                                strlen("image/restore/basic"))) {
3569                if (method != OG_METHOD_POST)
3570                        return og_client_method_not_found(cli);
3571
3572                if (!root) {
3573                        syslog(LOG_ERR, "command create with no payload\n");
3574                        return og_client_bad_request(cli);
3575                }
3576                err = og_cmd_restore_basic_image(root, &params);
3577        } else if (!strncmp(cmd, "image/restore/incremental",
3578                                strlen("image/restore/incremental"))) {
3579                if (method != OG_METHOD_POST)
3580                        return og_client_method_not_found(cli);
3581
3582                if (!root) {
3583                        syslog(LOG_ERR, "command create with no payload\n");
3584                        return og_client_bad_request(cli);
3585                }
3586                err = og_cmd_restore_incremental_image(root, &params);
3587        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
3588                if (method != OG_METHOD_POST)
3589                        return og_client_method_not_found(cli);
3590
3591                if (!root) {
3592                        syslog(LOG_ERR, "command create with no payload\n");
3593                        return og_client_bad_request(cli);
3594                }
3595                err = og_cmd_restore_image(root, &params);
3596        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
3597                if (method != OG_METHOD_POST)
3598                        return og_client_method_not_found(cli);
3599
3600                if (!root) {
3601                        syslog(LOG_ERR, "command create with no payload\n");
3602                        return og_client_bad_request(cli);
3603                }
3604                err = og_cmd_setup(root, &params);
3605        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
3606                if (method != OG_METHOD_POST)
3607                        return og_client_method_not_found(cli);
3608
3609                if (!root) {
3610                        syslog(LOG_ERR, "command create with no payload\n");
3611                        return og_client_bad_request(cli);
3612                }
3613
3614                err = og_cmd_run_schedule(root, &params);
3615        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
3616                if (method != OG_METHOD_POST)
3617                        return og_client_method_not_found(cli);
3618
3619                if (!root) {
3620                        syslog(LOG_ERR, "command task with no payload\n");
3621                        return og_client_bad_request(cli);
3622                }
3623                err = og_cmd_task_post(root, &params);
3624        } else if (!strncmp(cmd, "schedule/create",
3625                            strlen("schedule/create"))) {
3626                if (method != OG_METHOD_POST)
3627                        return og_client_method_not_found(cli);
3628
3629                if (!root) {
3630                        syslog(LOG_ERR, "command task with no payload\n");
3631                        return og_client_bad_request(cli);
3632                }
3633                err = og_cmd_schedule_create(root, &params);
3634        } else if (!strncmp(cmd, "schedule/delete",
3635                            strlen("schedule/delete"))) {
3636                if (method != OG_METHOD_POST)
3637                        return og_client_method_not_found(cli);
3638
3639                if (!root) {
3640                        syslog(LOG_ERR, "command task with no payload\n");
3641                        return og_client_bad_request(cli);
3642                }
3643                err = og_cmd_schedule_delete(root, &params);
3644        } else if (!strncmp(cmd, "schedule/update",
3645                            strlen("schedule/update"))) {
3646                if (method != OG_METHOD_POST)
3647                        return og_client_method_not_found(cli);
3648
3649                if (!root) {
3650                        syslog(LOG_ERR, "command task with no payload\n");
3651                        return og_client_bad_request(cli);
3652                }
3653                err = og_cmd_schedule_update(root, &params);
3654        } else if (!strncmp(cmd, "schedule/get",
3655                            strlen("schedule/get"))) {
3656                if (method != OG_METHOD_POST)
3657                        return og_client_method_not_found(cli);
3658
3659                err = og_cmd_schedule_get(root, &params, buf_reply);
3660        } else {
3661                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
3662                err = og_client_not_found(cli);
3663        }
3664
3665        if (root)
3666                json_decref(root);
3667
3668        if (err < 0)
3669                return og_client_bad_request(cli);
3670
3671        err = og_client_ok(cli, buf_reply);
3672        if (err < 0) {
3673                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
3674                       inet_ntoa(cli->addr.sin_addr),
3675                       ntohs(cli->addr.sin_port));
3676        }
3677
3678        return err;
3679}
Note: See TracBrowser for help on using the repository browser.