source: ogServer-Git/src/rest.c @ d6789f1

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

#980 Refactor GET /scopes backend

This improves style and fixes some memleaks.

Co-authored-by: OpenGnSys Support Team <soporte-og@…>

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