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

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

#942 return error if API REST parser fails

Return error if json parser fails, ignore unknown json attributes.
Missing uninitialized error value.

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