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

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

Add GET /hardware REST request

This patch implements HTTP GET /hardware request which returns a list of
the hardware associated with a particular computer.

Request: GET /hardware
{

"scope": {

"id": 6,
"type": "computer"

}

}

Response: 200 OK
{

"hardware": [

{

"type": "Microprocesadores",
"description": "CPU arch:x86 target:x86_64 cores:4"

},
{

"type": "Memorias",
"description": "QEMU 4096MiB"

},
{

"type": "Tarjetas gráficas",
"description": "Red Hat, Inc Virtio GPU"

},
{

"type": "Tarjetas de Red",
"description": "Intel Corporation 82540EM Gigabit Ethernet Controller

QEMU Virtual Machine"

},
{

"type": "Controladores IDE",
"description": "Intel Corporation 82371SB PIIX3 IDE II?

Qemu virtual machine"

}

]

}

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