source: ogServer-Git/sources/rest.c @ f6f1f18

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

#971 split socket core logic and main files

Extract socket core and main from ogAdmServer file.

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