source: ogServer-Git/src/rest.c @ 608709f

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

#980 Add GET /modes REST request

This patch implements HTTP GET /modes request which returns all modes available
for clients:

Request: GET /modes HTTP/1.0
Response: 200 OK
{

"modes": [

"pxe",
"10",
"13",
"00unknown",
"11",
"19pxeADMIN",
"12"

]

}

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