source: ogServer-Git/src/rest.c @ 829f8d8

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

#997 Remove unnecessary strdup in og_dbi_queue_*

After executing an scheduled command/proc/task valgrind reported
leaks inside og_dbi_queue_{command,procedure,task}. String
duplication is not being freed after using them.

==21281== 36 bytes in 1 blocks are definitely lost in loss record 470 of
592
...
==21281== by 0x113DCB: og_dbi_queue_procedure (rest.c:2748)
==21281== by 0x113F91: og_dbi_queue_task (rest.c:2804)
==21281== by 0x114392: og_schedule_run (rest.c:2916)
==21281== by 0x112059: og_agent_timer_cb (schedule.c:441)
...
==21281== by 0x10E2A5: main (main.c:100)

These strdup are not necessary because the dbi result is not freed
before using them, it's safe to use the dbi result's reference to
this string.

Fix previous memleaks when executing scheduled commands, procedures
and tasks.

  • Property mode set to 100644
File size: 108.0 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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                        break;
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                else
1451                        err = -1;
1452
1453                if (err < 0)
1454                        break;
1455        }
1456
1457        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1458                return -1;
1459
1460        dbi = og_dbi_open(&ogconfig.db);
1461        if (!dbi) {
1462                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1463                       __func__, __LINE__);
1464                return -1;
1465        }
1466
1467        for (i = 0; i < params->ips_array_len; i++) {
1468                result = dbi_conn_queryf(dbi->conn,
1469                                         "DELETE FROM ordenadores WHERE ip='%s'",
1470                                         params->ips_array[i]);
1471
1472                if (!result) {
1473                        dbi_conn_error(dbi->conn, &msglog);
1474                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1475                               __func__, __LINE__, msglog);
1476                        og_dbi_close(dbi);
1477                        return -1;
1478                }
1479
1480                dbi_result_free(result);
1481        }
1482
1483        og_dbi_close(dbi);
1484        return 0;
1485}
1486
1487static int og_cmd_stop(json_t *element, struct og_msg_params *params)
1488{
1489        const char *key;
1490        json_t *value;
1491        int err = 0;
1492
1493        if (json_typeof(element) != JSON_OBJECT)
1494                return -1;
1495
1496        json_object_foreach(element, key, value) {
1497                if (!strcmp(key, "clients"))
1498                        err = og_json_parse_clients(value, params);
1499
1500                if (err < 0)
1501                        break;
1502        }
1503
1504        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1505                return -1;
1506
1507        return og_send_request(OG_METHOD_POST, OG_CMD_STOP, params, NULL);
1508}
1509
1510static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
1511{
1512        const char *key;
1513        json_t *value;
1514        int err = 0;
1515
1516        if (json_typeof(element) != JSON_OBJECT)
1517                return -1;
1518
1519        json_object_foreach(element, key, value) {
1520                if (!strcmp(key, "clients"))
1521                        err = og_json_parse_clients(value, params);
1522
1523                if (err < 0)
1524                        break;
1525        }
1526
1527        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1528                return -1;
1529
1530        return og_send_request(OG_METHOD_GET, OG_CMD_HARDWARE, params, NULL);
1531}
1532
1533static int og_cmd_get_hardware(json_t *element, struct og_msg_params *params,
1534                               char *buffer_reply)
1535{
1536        const char *key, *msglog, *hw_item, *hw_type;
1537        json_t *value, *root, *array, *item;
1538        struct og_dbi *dbi;
1539        dbi_result result;
1540        int err = 0;
1541
1542        struct og_buffer og_buffer = {
1543                .data = buffer_reply
1544        };
1545
1546        json_object_foreach(element, key, value) {
1547                if (!strcmp(key, "client"))
1548                        err = og_json_parse_clients(value, params);
1549                else
1550                        err = -1;
1551
1552                if (err < 0)
1553                        return err;
1554        }
1555
1556        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1557                return -1;
1558
1559        dbi = og_dbi_open(&ogconfig.db);
1560        if (!dbi) {
1561                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1562                       __func__, __LINE__);
1563                return -1;
1564        }
1565
1566        result = dbi_conn_queryf(dbi->conn,
1567                                 "SELECT hardwares.descripcion AS item, "
1568                                 "       tipohardwares.descripcion AS type "
1569                                 "FROM hardwares "
1570                                 "INNER JOIN perfileshard_hardwares "
1571                                 "    ON hardwares.idhardware = perfileshard_hardwares.idhardware "
1572                                 "INNER JOIN ordenadores "
1573                                 "    ON perfileshard_hardwares.idperfilhard = ordenadores.idperfilhard "
1574                                 "INNER JOIN tipohardwares "
1575                                 "    ON hardwares.idtipohardware = tipohardwares.idtipohardware "
1576                                 "WHERE ordenadores.ip = '%s'",
1577                                 params->ips_array[0]);
1578        if (!result) {
1579                dbi_conn_error(dbi->conn, &msglog);
1580                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1581                       __func__, __LINE__, msglog);
1582                og_dbi_close(dbi);
1583                return -1;
1584        }
1585
1586        array = json_array();
1587        if (!array) {
1588                dbi_result_free(result);
1589                og_dbi_close(dbi);
1590                return -1;
1591        }
1592
1593        while (dbi_result_next_row(result)) {
1594                item = json_object();
1595                if (!item) {
1596                        dbi_result_free(result);
1597                        og_dbi_close(dbi);
1598                        json_decref(array);
1599                        return -1;
1600                }
1601
1602                hw_item = dbi_result_get_string(result, "item");
1603                hw_type = dbi_result_get_string(result, "type");
1604
1605                json_object_set_new(item, "type", json_string(hw_type));
1606                json_object_set_new(item, "description", json_string(hw_item));
1607                json_array_append_new(array, item);
1608        }
1609
1610        dbi_result_free(result);
1611        og_dbi_close(dbi);
1612
1613        root = json_object();
1614        if (!root){
1615                json_decref(array);
1616                return -1;
1617        }
1618
1619        json_object_set_new(root, "hardware", array);
1620
1621        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
1622        json_decref(root);
1623        return 0;
1624}
1625
1626static int og_cmd_software(json_t *element, struct og_msg_params *params)
1627{
1628        json_t *clients, *value;
1629        const char *key;
1630        int err = 0;
1631
1632        if (json_typeof(element) != JSON_OBJECT)
1633                return -1;
1634
1635        json_object_foreach(element, key, value) {
1636                if (!strcmp(key, "clients"))
1637                        err = og_json_parse_clients(value, params);
1638                else if (!strcmp(key, "disk")) {
1639                        err = og_json_parse_string(value, &params->disk);
1640                        params->flags |= OG_REST_PARAM_DISK;
1641                }
1642                else if (!strcmp(key, "partition")) {
1643                        err = og_json_parse_string(value, &params->partition);
1644                        params->flags |= OG_REST_PARAM_PARTITION;
1645                }
1646
1647                if (err < 0)
1648                        break;
1649        }
1650
1651        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1652                                            OG_REST_PARAM_DISK |
1653                                            OG_REST_PARAM_PARTITION))
1654                return -1;
1655
1656        clients = json_copy(element);
1657        json_object_del(clients, "clients");
1658
1659        return og_send_request(OG_METHOD_GET, OG_CMD_SOFTWARE, params, clients);
1660}
1661
1662static int og_cmd_get_software(json_t *element, struct og_msg_params *params,
1663                               char *buffer_reply)
1664{
1665        json_t *value, *software, *root;
1666        const char *key, *msglog, *name;
1667        uint64_t disk, partition;
1668        uint64_t flags = 0;
1669        struct og_dbi *dbi;
1670        dbi_result result;
1671        int err = 0;
1672
1673        struct og_buffer og_buffer = {
1674                .data = buffer_reply
1675        };
1676
1677        if (json_typeof(element) != JSON_OBJECT)
1678                return -1;
1679
1680        json_object_foreach(element, key, value) {
1681                if (!strcmp(key, "client")) {
1682                        err = og_json_parse_clients(value, params);
1683                } else if (!strcmp(key, "disk")) {
1684                        err = og_json_parse_uint64(value, &disk);
1685                        flags |= OG_REST_PARAM_DISK;
1686                } else if (!strcmp(key, "partition")) {
1687                        err = og_json_parse_uint64(value, &partition);
1688                        flags |= OG_REST_PARAM_PARTITION;
1689                }
1690
1691                if (err < 0)
1692                        break;
1693        }
1694
1695        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR) ||
1696            !og_flags_validate(flags, OG_REST_PARAM_DISK |
1697                                      OG_REST_PARAM_PARTITION))
1698                return -1;
1699
1700        dbi = og_dbi_open(&ogconfig.db);
1701        if (!dbi) {
1702                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1703                       __func__, __LINE__);
1704                return -1;
1705        }
1706
1707        result = dbi_conn_queryf(dbi->conn,
1708                                 "SELECT s.descripcion "
1709                                 "FROM softwares s "
1710                                 "INNER JOIN perfilessoft_softwares pss "
1711                                 "ON s.idsoftware = pss.idsoftware "
1712                                 "INNER JOIN ordenadores_particiones op "
1713                                 "ON pss.idperfilsoft = op.idperfilsoft "
1714                                 "INNER JOIN ordenadores o "
1715                                 "ON o.idordenador = op.idordenador "
1716                                 "WHERE o.ip='%s' AND "
1717                                 "      op.numdisk=%lu AND "
1718                                 "      op.numpar=%lu",
1719                                 params->ips_array[0], disk, partition);
1720        if (!result) {
1721                dbi_conn_error(dbi->conn, &msglog);
1722                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1723                       __func__, __LINE__, msglog);
1724                return -1;
1725        }
1726        software = json_array();
1727        if (!software) {
1728                dbi_result_free(result);
1729                og_dbi_close(dbi);
1730                return -1;
1731        }
1732
1733        while (dbi_result_next_row(result)) {
1734                name = dbi_result_get_string(result, "descripcion");
1735                json_array_append_new(software, json_string(name));
1736        }
1737
1738        dbi_result_free(result);
1739        og_dbi_close(dbi);
1740
1741        root = json_object();
1742        if (!root) {
1743                json_decref(software);
1744                return -1;
1745        }
1746        json_object_set_new(root, "software", software);
1747
1748        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
1749        json_decref(root);
1750        return 0;
1751}
1752
1753#define OG_IMAGE_TYPE_MAXLEN    4
1754
1755static int og_get_image_stats(const char *name,
1756                              struct stat *image_stats)
1757{
1758        const char *dir = ogconfig.repo.dir;
1759        char filename[PATH_MAX + 1];
1760
1761        snprintf(filename, sizeof(filename), "%s/%s.img", dir, name);
1762        if (stat(filename, image_stats) < 0) {
1763                syslog(LOG_ERR, "%s image does not exists", name);
1764                return -1;
1765        }
1766        return 0;
1767}
1768
1769static json_t *og_json_disk_alloc()
1770{
1771        const char *dir = ogconfig.repo.dir;
1772        struct statvfs buffer;
1773        json_t *disk_json;
1774        int ret;
1775
1776        ret = statvfs(dir, &buffer);
1777        if (ret)
1778                return NULL;
1779
1780        disk_json = json_object();
1781        if (!disk_json)
1782                return NULL;
1783
1784        json_object_set_new(disk_json, "total",
1785                            json_integer(buffer.f_blocks * buffer.f_frsize));
1786        json_object_set_new(disk_json, "free",
1787                            json_integer(buffer.f_bfree * buffer.f_frsize));
1788
1789        return disk_json;
1790}
1791
1792#define OG_PERMS_IRWX (S_IRWXU | S_IRWXG | S_IRWXO)
1793#define OG_PERMS_MAXLEN 4
1794
1795static json_t *og_json_image_alloc(struct og_image *image)
1796{
1797        char perms_string[OG_PERMS_MAXLEN];
1798        json_t *image_json;
1799        char *modified;
1800        uint16_t perms;
1801
1802        image_json = json_object();
1803        if (!image_json)
1804                return NULL;
1805
1806        perms = image->image_stats.st_mode & OG_PERMS_IRWX;
1807        snprintf(perms_string, sizeof(perms_string), "%o", perms);
1808
1809        modified = ctime(&image->image_stats.st_mtime);
1810        modified[strlen(modified) - 1] = '\0';
1811
1812        json_object_set_new(image_json, "name",
1813                            json_string(image->name));
1814        json_object_set_new(image_json, "datasize",
1815                            json_integer(image->datasize));
1816        json_object_set_new(image_json, "size",
1817                            json_integer(image->image_stats.st_size));
1818        json_object_set_new(image_json, "modified",
1819                            json_string(modified));
1820        json_object_set_new(image_json, "permissions",
1821                            json_string(perms_string));
1822        json_object_set_new(image_json, "software_id",
1823                            json_integer(image->software_id));
1824        json_object_set_new(image_json, "type",
1825                            json_integer(image->type));
1826        json_object_set_new(image_json, "id",
1827                            json_integer(image->id));
1828
1829        return image_json;
1830}
1831
1832static int og_cmd_images(char *buffer_reply)
1833{
1834        json_t *root, *images, *image_json, *disk_json;
1835        struct og_buffer og_buffer = {
1836                .data = buffer_reply
1837        };
1838        struct og_image image;
1839        struct og_dbi *dbi;
1840        dbi_result result;
1841
1842        root = json_object();
1843        if (!root)
1844                return -1;
1845
1846        images = json_array();
1847        if (!images) {
1848                json_decref(root);
1849                return -1;
1850        }
1851
1852        json_object_set_new(root, "images", images);
1853
1854        dbi = og_dbi_open(&ogconfig.db);
1855        if (!dbi) {
1856                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1857                       __func__, __LINE__);
1858                json_decref(root);
1859                return -1;
1860        }
1861
1862        result = dbi_conn_queryf(dbi->conn,
1863                                 "SELECT i.nombreca, o.nombreordenador, "
1864                                 "       i.clonator, i.compressor, "
1865                                 "       i.filesystem, i.datasize, "
1866                                 "       i.idperfilsoft, i.tipo, "
1867                                 "       i.idimagen "
1868                                 "FROM imagenes i "
1869                                 "LEFT JOIN ordenadores o "
1870                                 "ON i.idordenador = o.idordenador");
1871
1872        while (dbi_result_next_row(result)) {
1873                image = (struct og_image){0};
1874                image.datasize = dbi_result_get_ulonglong(result, "datasize");
1875                image.software_id = dbi_result_get_ulonglong(result, "idperfilsoft");
1876                image.type = dbi_result_get_ulonglong(result, "tipo");
1877                image.id = dbi_result_get_ulonglong(result, "idimagen");
1878                snprintf(image.name, sizeof(image.name), "%s",
1879                         dbi_result_get_string(result, "nombreca"));
1880
1881                if (og_get_image_stats(image.name, &image.image_stats)) {
1882                        continue;
1883                }
1884
1885                image_json = og_json_image_alloc(&image);
1886                if (!image_json) {
1887                        dbi_result_free(result);
1888                        og_dbi_close(dbi);
1889                        json_decref(root);
1890                        return -1;
1891                }
1892
1893                json_array_append_new(images, image_json);
1894        }
1895
1896        dbi_result_free(result);
1897        og_dbi_close(dbi);
1898
1899        disk_json = og_json_disk_alloc();
1900        if (!disk_json) {
1901                syslog(LOG_ERR, "cannot allocate disk json");
1902                json_decref(root);
1903                return -1;
1904        }
1905
1906        json_object_set_new(root, "disk", disk_json);
1907
1908        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
1909        json_decref(root);
1910
1911        return 0;
1912}
1913
1914static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
1915{
1916        char new_image_id[OG_DB_INT_MAXLEN + 1];
1917        struct og_image image = {};
1918        json_t *value, *clients;
1919        struct og_dbi *dbi;
1920        const char *key;
1921        int err = 0;
1922
1923        if (json_typeof(element) != JSON_OBJECT)
1924                return -1;
1925
1926        json_object_foreach(element, key, value) {
1927                if (!strcmp(key, "disk")) {
1928                        err = og_json_parse_string(value, &params->disk);
1929                        params->flags |= OG_REST_PARAM_DISK;
1930                } else if (!strcmp(key, "partition")) {
1931                        err = og_json_parse_string(value, &params->partition);
1932                        params->flags |= OG_REST_PARAM_PARTITION;
1933                } else if (!strcmp(key, "name")) {
1934                        err = og_json_parse_string(value, &params->name);
1935                        params->flags |= OG_REST_PARAM_NAME;
1936                } else if (!strcmp(key, "repository")) {
1937                        err = og_json_parse_string(value, &params->repository);
1938                        params->flags |= OG_REST_PARAM_REPO;
1939                } else if (!strcmp(key, "clients")) {
1940                        err = og_json_parse_clients(value, params);
1941                } else if (!strcmp(key, "id")) {
1942                        err = og_json_parse_string(value, &params->id);
1943                        params->flags |= OG_REST_PARAM_ID;
1944                } else if (!strcmp(key, "code")) {
1945                        err = og_json_parse_string(value, &params->code);
1946                        params->flags |= OG_REST_PARAM_CODE;
1947                } else if (!strcmp(key, "description")) {
1948                        err = og_json_parse_string_copy(value,
1949                                                        image.description,
1950                                                        sizeof(image.description));
1951                } else if (!strcmp(key, "group_id")) {
1952                        err = og_json_parse_uint64(value, &image.group_id);
1953                } else if (!strcmp(key, "center_id")) {
1954                        err = og_json_parse_uint64(value, &image.center_id);
1955                }
1956
1957
1958                if (err < 0)
1959                        break;
1960        }
1961
1962        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1963                                            OG_REST_PARAM_DISK |
1964                                            OG_REST_PARAM_PARTITION |
1965                                            OG_REST_PARAM_CODE |
1966                                            OG_REST_PARAM_ID |
1967                                            OG_REST_PARAM_NAME |
1968                                            OG_REST_PARAM_REPO))
1969                return -1;
1970
1971        /* If there is a description, this means the image is not in the DB. */
1972        if (image.description[0]) {
1973                snprintf(image.name, sizeof(image.name), "%s", params->name);
1974
1975                dbi = og_dbi_open(&ogconfig.db);
1976                if (!dbi) {
1977                        syslog(LOG_ERR,
1978                               "cannot open connection database (%s:%d)\n",
1979                               __func__, __LINE__);
1980                        return -1;
1981                }
1982
1983                err = og_dbi_add_image(dbi, &image);
1984
1985                og_dbi_close(dbi);
1986                if (err < 0)
1987                        return err;
1988
1989                snprintf(new_image_id, sizeof(new_image_id), "%u", err);
1990                params->id = new_image_id;
1991        }
1992
1993        clients = json_copy(element);
1994        json_object_del(clients, "clients");
1995
1996        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
1997                               clients);
1998}
1999
2000static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
2001{
2002        json_t *clients, *value;
2003        const char *key;
2004        int err = 0;
2005
2006        if (json_typeof(element) != JSON_OBJECT)
2007                return -1;
2008
2009        json_object_foreach(element, key, value) {
2010                if (!strcmp(key, "disk")) {
2011                        err = og_json_parse_string(value, &params->disk);
2012                        params->flags |= OG_REST_PARAM_DISK;
2013                } else if (!strcmp(key, "partition")) {
2014                        err = og_json_parse_string(value, &params->partition);
2015                        params->flags |= OG_REST_PARAM_PARTITION;
2016                } else if (!strcmp(key, "name")) {
2017                        err = og_json_parse_string(value, &params->name);
2018                        params->flags |= OG_REST_PARAM_NAME;
2019                } else if (!strcmp(key, "repository")) {
2020                        err = og_json_parse_string(value, &params->repository);
2021                        params->flags |= OG_REST_PARAM_REPO;
2022                } else if (!strcmp(key, "clients")) {
2023                        err = og_json_parse_clients(value, params);
2024                } else if (!strcmp(key, "type")) {
2025                        err = og_json_parse_string(value, &params->type);
2026                        params->flags |= OG_REST_PARAM_TYPE;
2027                } else if (!strcmp(key, "profile")) {
2028                        err = og_json_parse_string(value, &params->profile);
2029                        params->flags |= OG_REST_PARAM_PROFILE;
2030                } else if (!strcmp(key, "id")) {
2031                        err = og_json_parse_string(value, &params->id);
2032                        params->flags |= OG_REST_PARAM_ID;
2033                }
2034
2035                if (err < 0)
2036                        break;
2037        }
2038
2039        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2040                                            OG_REST_PARAM_DISK |
2041                                            OG_REST_PARAM_PARTITION |
2042                                            OG_REST_PARAM_NAME |
2043                                            OG_REST_PARAM_REPO |
2044                                            OG_REST_PARAM_TYPE |
2045                                            OG_REST_PARAM_PROFILE |
2046                                            OG_REST_PARAM_ID))
2047                return -1;
2048
2049        clients = json_copy(element);
2050        json_object_del(clients, "clients");
2051
2052        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
2053                               clients);
2054}
2055
2056static int og_cmd_setup(json_t *element, struct og_msg_params *params)
2057{
2058        json_t *value, *clients;
2059        const char *key;
2060        int err = 0;
2061
2062        if (json_typeof(element) != JSON_OBJECT)
2063                return -1;
2064
2065        json_object_foreach(element, key, value) {
2066                if (!strcmp(key, "clients")) {
2067                        err = og_json_parse_clients(value, params);
2068                } else if (!strcmp(key, "type")) {
2069                        err = og_json_parse_string(value, &params->type);
2070                        params->flags |= OG_REST_PARAM_TYPE;
2071                } else if (!strcmp(key, "disk")) {
2072                        err = og_json_parse_string(value, &params->disk);
2073                        params->flags |= OG_REST_PARAM_DISK;
2074                } else if (!strcmp(key, "cache")) {
2075                        err = og_json_parse_string(value, &params->cache);
2076                        params->flags |= OG_REST_PARAM_CACHE;
2077                } else if (!strcmp(key, "cache_size")) {
2078                        err = og_json_parse_string(value, &params->cache_size);
2079                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
2080                } else if (!strcmp(key, "partition_setup")) {
2081                        err = og_json_parse_partition_setup(value, params);
2082                }
2083
2084                if (err < 0)
2085                        break;
2086        }
2087
2088        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2089                                            OG_REST_PARAM_TYPE |
2090                                            OG_REST_PARAM_DISK |
2091                                            OG_REST_PARAM_CACHE |
2092                                            OG_REST_PARAM_CACHE_SIZE |
2093                                            OG_REST_PARAM_PART_0 |
2094                                            OG_REST_PARAM_PART_1 |
2095                                            OG_REST_PARAM_PART_2 |
2096                                            OG_REST_PARAM_PART_3))
2097                return -1;
2098
2099        clients = json_copy(element);
2100        json_object_del(clients, "clients");
2101
2102        return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
2103}
2104
2105static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
2106{
2107        const char *key;
2108        json_t *value;
2109        int err = 0;
2110
2111        json_object_foreach(element, key, value) {
2112                if (!strcmp(key, "clients"))
2113                        err = og_json_parse_clients(value, params);
2114
2115                if (err < 0)
2116                        break;
2117        }
2118
2119        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
2120                return -1;
2121
2122        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2123                               NULL);
2124}
2125
2126static LIST_HEAD(cmd_list);
2127
2128const struct og_cmd *og_cmd_find(const char *client_ip)
2129{
2130        struct og_cmd *cmd, *next;
2131
2132        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2133                if (strcmp(cmd->ip, client_ip))
2134                        continue;
2135
2136                list_del(&cmd->list);
2137                return cmd;
2138        }
2139
2140        return NULL;
2141}
2142
2143void og_cmd_free(const struct og_cmd *cmd)
2144{
2145        struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
2146        int i;
2147
2148        for (i = 0; i < params->ips_array_len; i++) {
2149                free((void *)params->netmask_array[i]);
2150                free((void *)params->ips_array[i]);
2151                free((void *)params->mac_array[i]);
2152        }
2153        free((void *)params->wol_type);
2154
2155        if (cmd->json)
2156                json_decref(cmd->json);
2157
2158        free((void *)cmd->ip);
2159        free((void *)cmd->mac);
2160        free((void *)cmd);
2161}
2162
2163static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
2164                        enum og_cmd_type type, json_t *root)
2165{
2166        cmd->type = type;
2167        cmd->method = method;
2168        cmd->params.ips_array[0] = strdup(cmd->ip);
2169        cmd->params.ips_array_len = 1;
2170        cmd->json = root;
2171}
2172
2173static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
2174{
2175        char wol_type[2] = {};
2176        const char *msglog;
2177        struct og_dbi *dbi;
2178        dbi_result result;
2179
2180        if (sscanf(input, "mar=%s", wol_type) != 1) {
2181                syslog(LOG_ERR, "malformed database legacy input\n");
2182                return -1;
2183        }
2184
2185        dbi = og_dbi_open(&ogconfig.db);
2186        if (!dbi) {
2187                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2188                       __func__, __LINE__);
2189                return -1;
2190        }
2191
2192        result = dbi_conn_queryf(dbi->conn,
2193                                 "SELECT mascara FROM ordenadores "
2194                                 "WHERE ip = '%s'", cmd->ip);
2195        if (!result) {
2196                dbi_conn_error(dbi->conn, &msglog);
2197                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2198                       __func__, __LINE__, msglog);
2199                og_dbi_close(dbi);
2200                return -1;
2201        }
2202        dbi_result_next_row(result);
2203
2204        og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
2205        cmd->params.netmask_array[0] = dbi_result_get_string_copy(result,
2206                                                                  "mascara");
2207        cmd->params.mac_array[0] = strdup(cmd->mac);
2208        cmd->params.wol_type = strdup(wol_type);
2209
2210        dbi_result_free(result);
2211        og_dbi_close(dbi);
2212
2213        return 0;
2214}
2215
2216static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
2217{
2218        json_t *root, *script, *echo;
2219
2220        script = json_string(input + 4);
2221        echo = json_boolean(false);
2222
2223        root = json_object();
2224        if (!root)
2225                return -1;
2226        json_object_set_new(root, "run", script);
2227        json_object_set_new(root, "echo", echo);
2228
2229        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
2230
2231        return 0;
2232}
2233
2234static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
2235{
2236        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2237        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2238        json_t *root, *disk, *partition;
2239
2240        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2241                return -1;
2242        partition = json_string(part_str);
2243        disk = json_string(disk_str);
2244
2245        root = json_object();
2246        if (!root)
2247                return -1;
2248        json_object_set_new(root, "partition", partition);
2249        json_object_set_new(root, "disk", disk);
2250
2251        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
2252
2253        return 0;
2254}
2255
2256static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
2257{
2258        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
2259
2260        return 0;
2261}
2262
2263static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
2264{
2265        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
2266
2267        return 0;
2268}
2269
2270static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
2271{
2272        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
2273
2274        return 0;
2275}
2276
2277static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
2278{
2279        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
2280
2281        return 0;
2282}
2283
2284static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
2285{
2286        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
2287
2288        return 0;
2289}
2290
2291static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
2292{
2293        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2294        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2295        json_t *root, *disk, *partition;
2296
2297        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2298                return -1;
2299        partition = json_string(part_str);
2300        disk = json_string(disk_str);
2301
2302        root = json_object();
2303        if (!root)
2304                return -1;
2305        json_object_set_new(root, "partition", partition);
2306        json_object_set_new(root, "disk", disk);
2307
2308        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, root);
2309
2310        return 0;
2311}
2312
2313static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
2314{
2315        json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
2316        struct og_image_legacy img = {};
2317
2318        if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
2319                   img.disk, img.part, img.code, img.image_id, img.name,
2320                   img.repo) != 6)
2321                return -1;
2322        image_id = json_string(img.image_id);
2323        partition = json_string(img.part);
2324        code = json_string(img.code);
2325        name = json_string(img.name);
2326        repo = json_string(img.repo);
2327        disk = json_string(img.disk);
2328
2329        root = json_object();
2330        if (!root)
2331                return -1;
2332        json_object_set_new(root, "partition", partition);
2333        json_object_set_new(root, "repository", repo);
2334        json_object_set_new(root, "id", image_id);
2335        json_object_set_new(root, "code", code);
2336        json_object_set_new(root, "name", name);
2337        json_object_set_new(root, "disk", disk);
2338
2339        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
2340
2341        return 0;
2342}
2343
2344#define OG_DB_RESTORE_TYPE_MAXLEN       64
2345
2346static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
2347{
2348        json_t *root, *disk, *partition, *image_id, *name, *repo;
2349        char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
2350        char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
2351        json_t *software_id, *restore_type;
2352        struct og_image_legacy img = {};
2353
2354        if (sscanf(input,
2355                   "dsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
2356                   "ipr=%s\rifs=%s\rptc=%[^\r]\r",
2357                   img.disk, img.part, img.image_id, img.name, img.repo,
2358                   software_id_str, restore_type_str) != 7)
2359                return -1;
2360
2361        restore_type = json_string(restore_type_str);
2362        software_id = json_string(software_id_str);
2363        image_id = json_string(img.image_id);
2364        partition = json_string(img.part);
2365        name = json_string(img.name);
2366        repo = json_string(img.repo);
2367        disk = json_string(img.disk);
2368
2369        root = json_object();
2370        if (!root)
2371                return -1;
2372        json_object_set_new(root, "profile", software_id);
2373        json_object_set_new(root, "partition", partition);
2374        json_object_set_new(root, "type", restore_type);
2375        json_object_set_new(root, "repository", repo);
2376        json_object_set_new(root, "id", image_id);
2377        json_object_set_new(root, "name", name);
2378        json_object_set_new(root, "disk", disk);
2379
2380        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2381
2382        return 0;
2383}
2384
2385#define OG_PARTITION_TABLE_TYPE_MAXLEN 5
2386
2387static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2388{
2389        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
2390        char part_table_type_str[OG_PARTITION_TABLE_TYPE_MAXLEN + 1];
2391        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
2392        json_t *part_table_type, *part, *code, *fs, *size, *format;
2393        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2394        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2395        unsigned int partition_len = 0;
2396        const char *in_ptr;
2397        char cache_str[2];
2398
2399        if (sscanf(input, "ttp=%s\rdsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2400                   part_table_type_str, disk_str, cache_str, cache_size_str) != 4)
2401                return -1;
2402
2403        in_ptr = strstr(input, "!") + 1;
2404        while (strlen(in_ptr) > 0) {
2405                if(sscanf(in_ptr,
2406                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2407                          part_cfg[partition_len].partition,
2408                          part_cfg[partition_len].code,
2409                          part_cfg[partition_len].filesystem,
2410                          part_cfg[partition_len].size,
2411                          part_cfg[partition_len].format) != 5)
2412                        return -1;
2413                in_ptr = strstr(in_ptr, "%") + 1;
2414                partition_len++;
2415        }
2416
2417        root = json_object();
2418        if (!root)
2419                return -1;
2420
2421        part_table_type = json_string(part_table_type_str);
2422        cache_size = json_string(cache_size_str);
2423        cache = json_string(cache_str);
2424        partition_setup = json_array();
2425        disk = json_string(disk_str);
2426
2427        for (unsigned int i = 0; i < partition_len; ++i) {
2428                object = json_object();
2429                if (!object) {
2430                        json_decref(root);
2431                        return -1;
2432                }
2433
2434                part = json_string(part_cfg[i].partition);
2435                fs = json_string(part_cfg[i].filesystem);
2436                format = json_string(part_cfg[i].format);
2437                code = json_string(part_cfg[i].code);
2438                size = json_string(part_cfg[i].size);
2439
2440                json_object_set_new(object, "partition", part);
2441                json_object_set_new(object, "filesystem", fs);
2442                json_object_set_new(object, "format", format);
2443                json_object_set_new(object, "code", code);
2444                json_object_set_new(object, "size", size);
2445
2446                json_array_append_new(partition_setup, object);
2447        }
2448
2449        json_object_set_new(root, "partition_setup", partition_setup);
2450        json_object_set_new(root, "cache_size", cache_size);
2451        json_object_set_new(root, "type", part_table_type);
2452        json_object_set_new(root, "cache", cache);
2453        json_object_set_new(root, "disk", disk);
2454
2455        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2456
2457        return 0;
2458}
2459
2460static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2461{
2462        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2463
2464        return 0;
2465}
2466
2467static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2468{
2469        char legacy_cmd[32] = {};
2470        int err = -1;
2471
2472        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2473                syslog(LOG_ERR, "malformed database legacy input\n");
2474                return -1;
2475        }
2476        input = strchr(input, '\r') + 1;
2477
2478        if (!strcmp(legacy_cmd, "Arrancar")) {
2479                err = og_cmd_legacy_wol(input, cmd);
2480        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2481                err = og_cmd_legacy_shell_run(input, cmd);
2482        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2483                err = og_cmd_legacy_session(input, cmd);
2484        } else if (!strcmp(legacy_cmd, "Apagar")) {
2485                err = og_cmd_legacy_poweroff(input, cmd);
2486        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2487                err = og_cmd_legacy_refresh(input, cmd);
2488        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2489                err = og_cmd_legacy_reboot(input, cmd);
2490        } else if (!strcmp(legacy_cmd, "Purgar")) {
2491                err = og_cmd_legacy_stop(input, cmd);
2492        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2493                err = og_cmd_legacy_hardware(input, cmd);
2494        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2495                err = og_cmd_legacy_software(input, cmd);
2496        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2497                err = og_cmd_legacy_image_create(input, cmd);
2498        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2499                err = og_cmd_legacy_image_restore(input, cmd);
2500        } else if (!strcmp(legacy_cmd, "Configurar")) {
2501                err = og_cmd_legacy_setup(input, cmd);
2502        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2503                   !strcmp(legacy_cmd, "Actualizar")) {
2504                err = og_cmd_legacy_run_schedule(input, cmd);
2505        }
2506
2507        return err;
2508}
2509
2510static int og_dbi_add_action(const struct og_dbi *dbi, const struct og_task *task,
2511                             struct og_cmd *cmd)
2512{
2513        char start_date_string[24];
2514        struct tm *start_date;
2515        const char *msglog;
2516        dbi_result result;
2517        time_t now;
2518
2519        time(&now);
2520        start_date = localtime(&now);
2521
2522        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2523                start_date->tm_year + 1900, start_date->tm_mon + 1,
2524                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2525                start_date->tm_sec);
2526        result = dbi_conn_queryf(dbi->conn,
2527                                "INSERT INTO acciones (idordenador, "
2528                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2529                                "sesion, idcomando, parametros, fechahorareg, "
2530                                "estado, resultado, ambito, idambito, "
2531                                "restrambito, idprocedimiento, idcentro, "
2532                                "idprogramacion) "
2533                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2534                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2535                                cmd->client_id, EJECUCION_TAREA, task->task_id,
2536                                "", cmd->ip, 0, task->command_id,
2537                                task->params, start_date_string,
2538                                ACCION_INICIADA, ACCION_SINRESULTADO,
2539                                task->type_scope, task->scope, "",
2540                                task->procedure_id, task->center_id,
2541                                task->schedule_id);
2542        if (!result) {
2543                dbi_conn_error(dbi->conn, &msglog);
2544                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2545                       __func__, __LINE__, msglog);
2546                return -1;
2547        }
2548        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
2549        dbi_result_free(result);
2550
2551        return 0;
2552}
2553
2554static int og_queue_task_command(struct og_dbi *dbi, const struct og_task *task,
2555                                 char *query)
2556{
2557        struct og_cmd *cmd;
2558        const char *msglog;
2559        dbi_result result;
2560
2561        result = dbi_conn_queryf(dbi->conn, query);
2562        if (!result) {
2563                dbi_conn_error(dbi->conn, &msglog);
2564                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2565                       __func__, __LINE__, msglog);
2566                return -1;
2567        }
2568
2569        while (dbi_result_next_row(result)) {
2570                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2571                if (!cmd) {
2572                        dbi_result_free(result);
2573                        return -1;
2574                }
2575
2576                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2577                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2578                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2579
2580                og_cmd_legacy(task->params, cmd);
2581
2582                if (task->procedure_id) {
2583                        if (og_dbi_add_action(dbi, task, cmd)) {
2584                                dbi_result_free(result);
2585                                return -1;
2586                        }
2587                } else {
2588                        cmd->id = task->task_id;
2589                }
2590
2591                list_add_tail(&cmd->list, &cmd_list);
2592        }
2593
2594        dbi_result_free(result);
2595
2596        return 0;
2597}
2598
2599static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2600                                       char *query)
2601{
2602
2603        const char *msglog;
2604        dbi_result result;
2605
2606        result = dbi_conn_queryf(dbi->conn, query);
2607        if (!result) {
2608                dbi_conn_error(dbi->conn, &msglog);
2609                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2610                       __func__, __LINE__, msglog);
2611                return -1;
2612        }
2613
2614        while (dbi_result_next_row(result)) {
2615                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2616
2617                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2618                                "WHERE grupoid=%d", group_id);
2619                if (og_queue_task_group_clients(dbi, task, query)) {
2620                        dbi_result_free(result);
2621                        return -1;
2622                }
2623
2624                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2625                              "WHERE grupoid=%d", group_id);
2626                if (og_queue_task_command(dbi, task, query)) {
2627                        dbi_result_free(result);
2628                        return -1;
2629                }
2630
2631        }
2632
2633        dbi_result_free(result);
2634
2635        return 0;
2636}
2637
2638static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2639                                          struct og_task *task, char *query)
2640{
2641
2642        const char *msglog;
2643        dbi_result result;
2644
2645        result = dbi_conn_queryf(dbi->conn, query);
2646        if (!result) {
2647                dbi_conn_error(dbi->conn, &msglog);
2648                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2649                       __func__, __LINE__, msglog);
2650                return -1;
2651        }
2652
2653        while (dbi_result_next_row(result)) {
2654                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2655
2656                sprintf(query, "SELECT idgrupo FROM grupos "
2657                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2658                if (og_queue_task_group_classrooms(dbi, task, query)) {
2659                        dbi_result_free(result);
2660                        return -1;
2661                }
2662
2663                sprintf(query,
2664                        "SELECT ip,mac,idordenador "
2665                        "FROM ordenadores INNER JOIN aulas "
2666                        "WHERE ordenadores.idaula=aulas.idaula "
2667                        "AND aulas.grupoid=%d",
2668                        group_id);
2669                if (og_queue_task_command(dbi, task, query)) {
2670                        dbi_result_free(result);
2671                        return -1;
2672                }
2673
2674        }
2675
2676        dbi_result_free(result);
2677
2678        return 0;
2679}
2680
2681static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2682{
2683        char query[4096];
2684
2685        switch (task->type_scope) {
2686                case AMBITO_CENTROS:
2687                        sprintf(query,
2688                                "SELECT ip,mac,idordenador "
2689                                "FROM ordenadores INNER JOIN aulas "
2690                                "WHERE ordenadores.idaula=aulas.idaula "
2691                                "AND idcentro=%d",
2692                                task->scope);
2693                        return og_queue_task_command(dbi, task, query);
2694                case AMBITO_GRUPOSAULAS:
2695                        sprintf(query,
2696                                "SELECT idgrupo FROM grupos "
2697                                "WHERE idgrupo=%i AND tipo=%d",
2698                                task->scope, AMBITO_GRUPOSAULAS);
2699                        return og_queue_task_group_classrooms(dbi, task, query);
2700                case AMBITO_AULAS:
2701                        sprintf(query,
2702                                "SELECT ip,mac,idordenador FROM ordenadores "
2703                                "WHERE idaula=%d",
2704                                task->scope);
2705                        return og_queue_task_command(dbi, task, query);
2706                case AMBITO_GRUPOSORDENADORES:
2707                        sprintf(query,
2708                                "SELECT idgrupo FROM gruposordenadores "
2709                                "WHERE idgrupo = %d",
2710                                task->scope);
2711                        return og_queue_task_group_clients(dbi, task, query);
2712                case AMBITO_ORDENADORES:
2713                        sprintf(query,
2714                                "SELECT ip, mac, idordenador FROM ordenadores "
2715                                "WHERE idordenador = %d",
2716                                task->scope);
2717                        return og_queue_task_command(dbi, task, query);
2718        }
2719        return 0;
2720}
2721
2722int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2723{
2724        uint32_t procedure_id;
2725        const char *msglog;
2726        dbi_result result;
2727
2728        result = dbi_conn_queryf(dbi->conn,
2729                        "SELECT parametros, procedimientoid, idcomando "
2730                        "FROM procedimientos_acciones "
2731                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2732        if (!result) {
2733                dbi_conn_error(dbi->conn, &msglog);
2734                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2735                       __func__, __LINE__, msglog);
2736                return -1;
2737        }
2738
2739        while (dbi_result_next_row(result)) {
2740                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2741                if (procedure_id > 0) {
2742                        task->procedure_id = procedure_id;
2743                        if (og_dbi_queue_procedure(dbi, task))
2744                                return -1;
2745                        continue;
2746                }
2747
2748                task->params = dbi_result_get_string(result, "parametros");
2749                task->command_id = dbi_result_get_uint(result, "idcomando");
2750                if (og_queue_task_clients(dbi, task))
2751                        return -1;
2752        }
2753
2754        dbi_result_free(result);
2755
2756        return 0;
2757}
2758
2759static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
2760                             uint32_t schedule_id)
2761{
2762        struct og_task task = {};
2763        uint32_t task_id_next;
2764        const char *msglog;
2765        dbi_result result;
2766
2767        task.schedule_id = schedule_id;
2768
2769        result = dbi_conn_queryf(dbi->conn,
2770                        "SELECT tareas_acciones.orden, "
2771                                "tareas_acciones.idprocedimiento, "
2772                                "tareas_acciones.tareaid, "
2773                                "tareas.idtarea, "
2774                                "tareas.idcentro, "
2775                                "tareas.ambito, "
2776                                "tareas.idambito, "
2777                                "tareas.restrambito "
2778                        " FROM tareas"
2779                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
2780                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
2781        if (!result) {
2782                dbi_conn_error(dbi->conn, &msglog);
2783                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2784                       __func__, __LINE__, msglog);
2785                return -1;
2786        }
2787
2788        while (dbi_result_next_row(result)) {
2789                task_id_next = dbi_result_get_uint(result, "tareaid");
2790
2791                if (task_id_next > 0) {
2792                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
2793                                return -1;
2794
2795                        continue;
2796                }
2797                task.task_id = dbi_result_get_uint(result, "idtarea");
2798                task.center_id = dbi_result_get_uint(result, "idcentro");
2799                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
2800                task.type_scope = dbi_result_get_uint(result, "ambito");
2801                task.scope = dbi_result_get_uint(result, "idambito");
2802                task.filtered_scope = dbi_result_get_string(result, "restrambito");
2803
2804                og_dbi_queue_procedure(dbi, &task);
2805        }
2806
2807        dbi_result_free(result);
2808
2809        return 0;
2810}
2811
2812static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
2813                                uint32_t schedule_id)
2814{
2815        struct og_task task = {};
2816        const char *msglog;
2817        dbi_result result;
2818        char query[4096];
2819
2820        result = dbi_conn_queryf(dbi->conn,
2821                        "SELECT idaccion, idcentro, idordenador, parametros "
2822                        "FROM acciones "
2823                        "WHERE sesion = %u", task_id);
2824        if (!result) {
2825                dbi_conn_error(dbi->conn, &msglog);
2826                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2827                       __func__, __LINE__, msglog);
2828                return -1;
2829        }
2830
2831        while (dbi_result_next_row(result)) {
2832                task.task_id = dbi_result_get_uint(result, "idaccion");
2833                task.center_id = dbi_result_get_uint(result, "idcentro");
2834                task.scope = dbi_result_get_uint(result, "idordenador");
2835                task.params = dbi_result_get_string(result, "parametros");
2836
2837                sprintf(query,
2838                        "SELECT ip, mac, idordenador FROM ordenadores "
2839                        "WHERE idordenador = %d",
2840                        task.scope);
2841                if (og_queue_task_command(dbi, &task, query)) {
2842                        dbi_result_free(result);
2843                        return -1;
2844                }
2845        }
2846
2847        dbi_result_free(result);
2848
2849        return 0;
2850}
2851
2852int og_dbi_update_action(uint32_t id, bool success)
2853{
2854        char end_date_string[24];
2855        struct tm *end_date;
2856        const char *msglog;
2857        struct og_dbi *dbi;
2858        uint8_t status = 2;
2859        dbi_result result;
2860        time_t now;
2861
2862        if (!id)
2863                return 0;
2864
2865        dbi = og_dbi_open(&ogconfig.db);
2866        if (!dbi) {
2867                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2868                       __func__, __LINE__);
2869                return -1;
2870        }
2871
2872        time(&now);
2873        end_date = localtime(&now);
2874
2875        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2876                end_date->tm_year + 1900, end_date->tm_mon + 1,
2877                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
2878                end_date->tm_sec);
2879        result = dbi_conn_queryf(dbi->conn,
2880                                 "UPDATE acciones SET fechahorafin='%s', "
2881                                 "estado=%d, resultado=%d WHERE idaccion=%d",
2882                                 end_date_string, ACCION_FINALIZADA,
2883                                 status - success, id);
2884
2885        if (!result) {
2886                dbi_conn_error(dbi->conn, &msglog);
2887                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2888                       __func__, __LINE__, msglog);
2889                og_dbi_close(dbi);
2890                return -1;
2891        }
2892        dbi_result_free(result);
2893        og_dbi_close(dbi);
2894
2895        return 0;
2896}
2897
2898void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
2899                     enum og_schedule_type type)
2900{
2901        struct og_msg_params params = {};
2902        bool duplicated = false;
2903        struct og_cmd *cmd, *next;
2904        struct og_dbi *dbi;
2905        unsigned int i;
2906
2907        dbi = og_dbi_open(&ogconfig.db);
2908        if (!dbi) {
2909                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2910                       __func__, __LINE__);
2911                return;
2912        }
2913
2914        switch (type) {
2915        case OG_SCHEDULE_TASK:
2916                og_dbi_queue_task(dbi, task_id, schedule_id);
2917                break;
2918        case OG_SCHEDULE_PROCEDURE:
2919        case OG_SCHEDULE_COMMAND:
2920                og_dbi_queue_command(dbi, task_id, schedule_id);
2921                break;
2922        }
2923        og_dbi_close(dbi);
2924
2925        list_for_each_entry(cmd, &cmd_list, list) {
2926                for (i = 0; i < params.ips_array_len; i++) {
2927                        if (!strncmp(cmd->ip, params.ips_array[i],
2928                                     OG_DB_IP_MAXLEN)) {
2929                                duplicated = true;
2930                                break;
2931                        }
2932                }
2933
2934                if (!duplicated)
2935                        params.ips_array[params.ips_array_len++] = strdup(cmd->ip);
2936                else
2937                        duplicated = false;
2938        }
2939
2940        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2941                if (cmd->type != OG_CMD_WOL)
2942                        continue;
2943
2944                if (Levanta((char **)cmd->params.ips_array,
2945                            (char **)cmd->params.mac_array,
2946                            (char **)cmd->params.netmask_array,
2947                            cmd->params.ips_array_len,
2948                            (char *)cmd->params.wol_type))
2949                        og_dbi_update_action(cmd->id, true);
2950
2951                list_del(&cmd->list);
2952                og_cmd_free(cmd);
2953        }
2954
2955        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
2956
2957        for (i = 0; i < params.ips_array_len; i++)
2958                free((void *)params.ips_array[i]);
2959}
2960
2961static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
2962{
2963        struct og_cmd *cmd;
2964        struct og_dbi *dbi;
2965        const char *key;
2966        json_t *value;
2967        int err;
2968
2969        if (json_typeof(element) != JSON_OBJECT)
2970                return -1;
2971
2972        json_object_foreach(element, key, value) {
2973                if (!strcmp(key, "task")) {
2974                        err = og_json_parse_string(value, &params->task_id);
2975                        params->flags |= OG_REST_PARAM_TASK;
2976                }
2977
2978                if (err < 0)
2979                        break;
2980        }
2981
2982        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
2983                return -1;
2984
2985        dbi = og_dbi_open(&ogconfig.db);
2986        if (!dbi) {
2987                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2988                           __func__, __LINE__);
2989                return -1;
2990        }
2991
2992        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
2993        og_dbi_close(dbi);
2994
2995        list_for_each_entry(cmd, &cmd_list, list)
2996                params->ips_array[params->ips_array_len++] = cmd->ip;
2997
2998        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2999                               NULL);
3000}
3001
3002static int og_dbi_scope_get_computer(struct og_dbi *dbi, json_t *array,
3003                                     uint32_t room_id)
3004{
3005        const char *computer_name, *computer_ip;
3006        uint32_t computer_id;
3007        const char *msglog;
3008        dbi_result result;
3009        json_t *computer;
3010
3011        result = dbi_conn_queryf(dbi->conn,
3012                                 "SELECT idordenador, nombreordenador, ip "
3013                                 "FROM ordenadores WHERE idaula=%d",
3014                                 room_id);
3015        if (!result) {
3016                dbi_conn_error(dbi->conn, &msglog);
3017                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3018                       __func__, __LINE__, msglog);
3019                return -1;
3020        }
3021
3022        while (dbi_result_next_row(result)) {
3023                computer_id = dbi_result_get_uint(result, "idordenador");
3024                computer_name = dbi_result_get_string(result, "nombreordenador");
3025                computer_ip = dbi_result_get_string(result, "ip");
3026
3027                computer = json_object();
3028                if (!computer) {
3029                        dbi_result_free(result);
3030                        return -1;
3031                }
3032
3033                json_object_set_new(computer, "name", json_string(computer_name));
3034                json_object_set_new(computer, "type", json_string("computer"));
3035                json_object_set_new(computer, "id", json_integer(computer_id));
3036                json_object_set_new(computer, "scope", json_array());
3037                json_object_set_new(computer, "ip", json_string(computer_ip));
3038                json_array_append(array, computer);
3039                json_decref(computer);
3040        }
3041        dbi_result_free(result);
3042
3043        return 0;
3044}
3045
3046static int og_dbi_scope_get_room(struct og_dbi *dbi, json_t *array,
3047                                 uint32_t center_id)
3048{
3049        char room_name[OG_DB_ROOM_NAME_MAXLEN + 1] = {};
3050        json_t *room, *room_array;
3051        const char *msglog;
3052        dbi_result result;
3053        uint32_t room_id;
3054
3055        result = dbi_conn_queryf(dbi->conn,
3056                                 "SELECT idaula, nombreaula FROM aulas WHERE "
3057                                 "idcentro=%d",
3058                                 center_id);
3059        if (!result) {
3060                dbi_conn_error(dbi->conn, &msglog);
3061                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3062                       __func__, __LINE__, msglog);
3063                return -1;
3064        }
3065
3066        while (dbi_result_next_row(result)) {
3067                room_id = dbi_result_get_uint(result, "idaula");
3068                strncpy(room_name,
3069                        dbi_result_get_string(result, "nombreaula"),
3070                        OG_DB_CENTER_NAME_MAXLEN);
3071
3072                room = json_object();
3073                if (!room) {
3074                        dbi_result_free(result);
3075                        return -1;
3076                }
3077
3078                json_object_set_new(room, "name", json_string(room_name));
3079                json_object_set_new(room, "type", json_string("room"));
3080                json_object_set_new(room, "id", json_integer(room_id));
3081                json_object_set_new(room, "scope", json_array());
3082                json_array_append(array, room);
3083                json_decref(room);
3084
3085                room_array = json_object_get(room, "scope");
3086                if (!room_array) {
3087                        dbi_result_free(result);
3088                        return -1;
3089                }
3090
3091                if (og_dbi_scope_get_computer(dbi, room_array, room_id)) {
3092                        dbi_result_free(result);
3093                        return -1;
3094                }
3095        }
3096        dbi_result_free(result);
3097
3098        return 0;
3099}
3100
3101static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
3102{
3103        char center_name[OG_DB_CENTER_NAME_MAXLEN + 1] = {};
3104        json_t *center, *array_room;
3105        const char *msglog;
3106        uint32_t center_id;
3107        dbi_result result;
3108
3109        result = dbi_conn_queryf(dbi->conn,
3110                                 "SELECT nombrecentro, idcentro FROM centros");
3111        if (!result) {
3112                dbi_conn_error(dbi->conn, &msglog);
3113                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3114                       __func__, __LINE__, msglog);
3115                return -1;
3116        }
3117
3118        while (dbi_result_next_row(result)) {
3119                center_id = dbi_result_get_uint(result, "idcentro");
3120                strncpy(center_name,
3121                        dbi_result_get_string(result, "nombrecentro"),
3122                        OG_DB_CENTER_NAME_MAXLEN);
3123
3124                center = json_object();
3125                if (!center) {
3126                        dbi_result_free(result);
3127                        return -1;
3128                }
3129
3130                array_room = json_array();
3131                if (!array_room) {
3132                        dbi_result_free(result);
3133                        json_decref(center);
3134                        return -1;
3135                }
3136
3137                json_object_set_new(center, "name", json_string(center_name));
3138                json_object_set_new(center, "type", json_string("center"));
3139                json_object_set_new(center, "id", json_integer(center_id));
3140                json_object_set_new(center, "scope", array_room);
3141                json_array_append(array, center);
3142                json_decref(center);
3143
3144                if (og_dbi_scope_get_room(dbi, array_room, center_id)) {
3145                        dbi_result_free(result);
3146                        return -1;
3147                }
3148        }
3149
3150        dbi_result_free(result);
3151
3152        return 0;
3153}
3154
3155static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
3156                            char *buffer_reply)
3157{
3158        struct og_buffer og_buffer = {
3159                .data = buffer_reply
3160        };
3161        json_t *root, *array;
3162        struct og_dbi *dbi;
3163
3164        root = json_object();
3165        if (!root)
3166                return -1;
3167
3168        array = json_array();
3169        if (!array) {
3170                json_decref(root);
3171                return -1;
3172        }
3173        json_object_set_new(root, "scope", array);
3174
3175        dbi = og_dbi_open(&ogconfig.db);
3176        if (!dbi) {
3177                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3178                       __func__, __LINE__);
3179                json_decref(root);
3180                return -1;
3181        }
3182
3183        if (og_dbi_scope_get(dbi, array)) {
3184                og_dbi_close(dbi);
3185                json_decref(root);
3186                return -1;
3187        }
3188
3189        og_dbi_close(dbi);
3190
3191        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
3192        json_decref(root);
3193
3194        return 0;
3195}
3196
3197int og_dbi_schedule_get(void)
3198{
3199        uint32_t schedule_id, task_id;
3200        struct og_schedule_time time;
3201        struct og_dbi *dbi;
3202        const char *msglog;
3203        dbi_result result;
3204
3205        dbi = og_dbi_open(&ogconfig.db);
3206        if (!dbi) {
3207                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3208                       __func__, __LINE__);
3209                return -1;
3210        }
3211
3212        result = dbi_conn_queryf(dbi->conn,
3213                                 "SELECT idprogramacion, tipoaccion, identificador, "
3214                                 "sesion, annos, meses, diario, dias, semanas, horas, "
3215                                 "ampm, minutos FROM programaciones "
3216                                 "WHERE suspendida = 0");
3217        if (!result) {
3218                dbi_conn_error(dbi->conn, &msglog);
3219                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3220                       __func__, __LINE__, msglog);
3221                og_dbi_close(dbi);
3222                return -1;
3223        }
3224
3225        while (dbi_result_next_row(result)) {
3226                memset(&time, 0, sizeof(time));
3227                schedule_id = dbi_result_get_uint(result, "idprogramacion");
3228                task_id = dbi_result_get_uint(result, "identificador");
3229                time.years = dbi_result_get_uint(result, "annos");
3230                time.months = dbi_result_get_uint(result, "meses");
3231                time.weeks = dbi_result_get_uint(result, "semanas");
3232                time.week_days = dbi_result_get_uint(result, "dias");
3233                time.days = dbi_result_get_uint(result, "diario");
3234                time.hours = dbi_result_get_uint(result, "horas");
3235                time.am_pm = dbi_result_get_uint(result, "ampm");
3236                time.minutes = dbi_result_get_uint(result, "minutos");
3237                time.check_stale = true;
3238
3239                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
3240                                   &time);
3241        }
3242
3243        dbi_result_free(result);
3244        og_dbi_close(dbi);
3245
3246        return 0;
3247}
3248
3249static int og_dbi_schedule_create(struct og_dbi *dbi,
3250                                  struct og_msg_params *params,
3251                                  uint32_t *schedule_id,
3252                                  enum og_schedule_type schedule_type)
3253{
3254        uint8_t suspended = 0;
3255        uint32_t session = 0;
3256        const char *msglog;
3257        dbi_result result;
3258        uint8_t type;
3259
3260        switch (schedule_type) {
3261        case OG_SCHEDULE_TASK:
3262                type = 3;
3263                break;
3264        case OG_SCHEDULE_PROCEDURE:
3265                type = 2;
3266                break;
3267        case OG_SCHEDULE_COMMAND:
3268                session = atoi(params->task_id);
3269                type = 1;
3270                break;
3271        }
3272
3273        result = dbi_conn_queryf(dbi->conn,
3274                                 "INSERT INTO programaciones (tipoaccion,"
3275                                 " identificador, nombrebloque, annos, meses,"
3276                                 " semanas, dias, diario, horas, ampm, minutos,"
3277                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
3278                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
3279                                 type, params->task_id, params->name,
3280                                 params->time.years, params->time.months,
3281                                 params->time.weeks, params->time.week_days,
3282                                 params->time.days, params->time.hours,
3283                                 params->time.am_pm, params->time.minutes,
3284                                 suspended, session);
3285        if (!result) {
3286                dbi_conn_error(dbi->conn, &msglog);
3287                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3288                       __func__, __LINE__, msglog);
3289                return -1;
3290        }
3291        dbi_result_free(result);
3292
3293        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
3294
3295        return 0;
3296}
3297
3298static int og_dbi_schedule_update(struct og_dbi *dbi,
3299                                  struct og_msg_params *params)
3300{
3301        const char *msglog;
3302        dbi_result result;
3303        uint8_t type = 3;
3304
3305        result = dbi_conn_queryf(dbi->conn,
3306                                 "UPDATE programaciones SET tipoaccion=%d, "
3307                                 "identificador='%s', nombrebloque='%s', "
3308                                 "annos=%d, meses=%d, "
3309                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
3310                                 "WHERE idprogramacion='%s'",
3311                                 type, params->task_id, params->name,
3312                                 params->time.years, params->time.months,
3313                                 params->time.days, params->time.hours,
3314                                 params->time.am_pm, params->time.minutes,
3315                                 params->id);
3316
3317        if (!result) {
3318                dbi_conn_error(dbi->conn, &msglog);
3319                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3320                       __func__, __LINE__, msglog);
3321                return -1;
3322        }
3323        dbi_result_free(result);
3324
3325        return 0;
3326}
3327
3328static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
3329{
3330        const char *msglog;
3331        dbi_result result;
3332
3333        result = dbi_conn_queryf(dbi->conn,
3334                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
3335                                 id);
3336        if (!result) {
3337                dbi_conn_error(dbi->conn, &msglog);
3338                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3339                       __func__, __LINE__, msglog);
3340                return -1;
3341        }
3342        dbi_result_free(result);
3343
3344        return 0;
3345}
3346
3347struct og_db_schedule {
3348        uint32_t                id;
3349        uint32_t                task_id;
3350        const char              *name;
3351        struct og_schedule_time time;
3352        uint32_t                week_days;
3353        uint32_t                weeks;
3354        uint32_t                suspended;
3355        uint32_t                session;
3356};
3357
3358static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
3359                                    const char *task_id, const char *schedule_id)
3360{
3361        struct og_db_schedule schedule;
3362        json_t *obj, *array;
3363        const char *msglog;
3364        dbi_result result;
3365        int err = 0;
3366
3367        if (task_id) {
3368                result = dbi_conn_queryf(dbi->conn,
3369                                         "SELECT idprogramacion,"
3370                                         "       identificador, nombrebloque,"
3371                                         "       annos, meses, diario, dias,"
3372                                         "       semanas, horas, ampm,"
3373                                         "       minutos,suspendida, sesion "
3374                                         "FROM programaciones "
3375                                         "WHERE identificador=%d",
3376                                         atoi(task_id));
3377        } else if (schedule_id) {
3378                result = dbi_conn_queryf(dbi->conn,
3379                                         "SELECT idprogramacion,"
3380                                         "       identificador, nombrebloque,"
3381                                         "       annos, meses, diario, dias,"
3382                                         "       semanas, horas, ampm,"
3383                                         "       minutos,suspendida, sesion "
3384                                         "FROM programaciones "
3385                                         "WHERE idprogramacion=%d",
3386                                         atoi(schedule_id));
3387        } else {
3388                result = dbi_conn_queryf(dbi->conn,
3389                                         "SELECT idprogramacion,"
3390                                         "       identificador, nombrebloque,"
3391                                         "       annos, meses, diario, dias,"
3392                                         "       semanas, horas, ampm,"
3393                                         "       minutos,suspendida, sesion "
3394                                         "FROM programaciones");
3395        }
3396
3397        if (!result) {
3398                dbi_conn_error(dbi->conn, &msglog);
3399                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3400                       __func__, __LINE__, msglog);
3401                return -1;
3402        }
3403
3404        array = json_array();
3405        if (!array)
3406                return -1;
3407
3408        while (dbi_result_next_row(result)) {
3409                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3410                schedule.task_id = dbi_result_get_uint(result, "identificador");
3411                schedule.name = dbi_result_get_string(result, "nombrebloque");
3412                schedule.time.years = dbi_result_get_uint(result, "annos");
3413                schedule.time.months = dbi_result_get_uint(result, "meses");
3414                schedule.time.days = dbi_result_get_uint(result, "diario");
3415                schedule.time.hours = dbi_result_get_uint(result, "horas");
3416                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3417                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3418                schedule.week_days = dbi_result_get_uint(result, "dias");
3419                schedule.weeks = dbi_result_get_uint(result, "semanas");
3420                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3421                schedule.session = dbi_result_get_uint(result, "sesion");
3422
3423                obj = json_object();
3424                if (!obj) {
3425                        err = -1;
3426                        break;
3427                }
3428                json_object_set_new(obj, "id", json_integer(schedule.id));
3429                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3430                json_object_set_new(obj, "name", json_string(schedule.name));
3431                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3432                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3433                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3434                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3435                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3436                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3437                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3438                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3439                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3440                json_object_set_new(obj, "session", json_integer(schedule.session));
3441
3442                json_array_append_new(array, obj);
3443        }
3444
3445        json_object_set_new(root, "schedule", array);
3446
3447        dbi_result_free(result);
3448
3449        return err;
3450}
3451
3452static int og_task_schedule_create(struct og_msg_params *params)
3453{
3454        enum og_schedule_type type;
3455        uint32_t schedule_id;
3456        struct og_dbi *dbi;
3457        int err;
3458
3459        if (!strcmp(params->type, "task"))
3460                type = OG_SCHEDULE_TASK;
3461        else if (!strcmp(params->type, "procedure"))
3462                type = OG_SCHEDULE_PROCEDURE;
3463        else if (!strcmp(params->type, "command"))
3464                type = OG_SCHEDULE_COMMAND;
3465        else
3466                return -1;
3467
3468        dbi = og_dbi_open(&ogconfig.db);
3469        if (!dbi) {
3470                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3471                       __func__, __LINE__);
3472                return -1;
3473        }
3474
3475        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3476        if (err < 0) {
3477                og_dbi_close(dbi);
3478                return -1;
3479        }
3480        og_schedule_create(schedule_id, atoi(params->task_id), type,
3481                           &params->time);
3482        og_schedule_refresh(og_loop);
3483        og_dbi_close(dbi);
3484
3485        return 0;
3486}
3487
3488static uint32_t og_tm_years_mask(struct tm *tm)
3489{
3490        int i, j = 0;
3491
3492        for (i = 2010; i < 2026; i++, j++) {
3493                if (tm->tm_year + 1900 == i)
3494                        break;
3495        }
3496
3497        return (1 << j);
3498}
3499
3500static uint32_t og_tm_months_mask(struct tm *tm)
3501{
3502        return 1 << tm->tm_mon;
3503}
3504
3505static uint32_t og_tm_hours_mask(struct tm *tm)
3506{
3507        return 1 << (tm->tm_hour - 12);
3508}
3509
3510static uint32_t og_tm_ampm(struct tm *tm)
3511{
3512        return tm->tm_hour < 12 ? 0 : 1;
3513}
3514
3515static uint32_t og_tm_days_mask(struct tm *tm)
3516{
3517        return 1 << (tm->tm_mday - 1);
3518}
3519
3520static void og_schedule_time_now(struct og_schedule_time *ogtime)
3521{
3522        struct tm *tm;
3523        time_t now;
3524
3525        now = time(NULL);
3526        tm = localtime(&now);
3527
3528        ogtime->years = og_tm_years_mask(tm);
3529        ogtime->months = og_tm_months_mask(tm);
3530        ogtime->weeks = 0;
3531        ogtime->week_days = 0;
3532        ogtime->days =  og_tm_days_mask(tm);
3533        ogtime->hours = og_tm_hours_mask(tm);
3534        ogtime->am_pm = og_tm_ampm(tm);
3535        ogtime->minutes = tm->tm_min;
3536}
3537
3538static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3539{
3540        bool when = false;
3541        const char *key;
3542        json_t *value;
3543        int err;
3544
3545        if (json_typeof(element) != JSON_OBJECT)
3546                return -1;
3547
3548        json_object_foreach(element, key, value) {
3549                if (!strcmp(key, "task")) {
3550                        err = og_json_parse_string(value, &params->task_id);
3551                        params->flags |= OG_REST_PARAM_TASK;
3552                } else if (!strcmp(key, "name")) {
3553                        err = og_json_parse_string(value, &params->name);
3554                        params->flags |= OG_REST_PARAM_NAME;
3555                } else if (!strcmp(key, "when")) {
3556                        err = og_json_parse_time_params(value, params);
3557                        when = true;
3558                } else if (!strcmp(key, "type")) {
3559                        err = og_json_parse_string(value, &params->type);
3560                        params->flags |= OG_REST_PARAM_TYPE;
3561                }
3562
3563                if (err < 0)
3564                        break;
3565        }
3566
3567        if (!when) {
3568                params->time.check_stale = false;
3569                og_schedule_time_now(&params->time);
3570                params->flags |= OG_REST_PARAM_TIME_YEARS |
3571                                 OG_REST_PARAM_TIME_MONTHS |
3572                                 OG_REST_PARAM_TIME_WEEKS |
3573                                 OG_REST_PARAM_TIME_WEEK_DAYS |
3574                                 OG_REST_PARAM_TIME_DAYS |
3575                                 OG_REST_PARAM_TIME_HOURS |
3576                                 OG_REST_PARAM_TIME_AM_PM |
3577                                 OG_REST_PARAM_TIME_MINUTES;
3578        } else {
3579                params->time.check_stale = true;
3580        }
3581
3582        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3583                                            OG_REST_PARAM_NAME |
3584                                            OG_REST_PARAM_TIME_YEARS |
3585                                            OG_REST_PARAM_TIME_MONTHS |
3586                                            OG_REST_PARAM_TIME_WEEKS |
3587                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3588                                            OG_REST_PARAM_TIME_DAYS |
3589                                            OG_REST_PARAM_TIME_HOURS |
3590                                            OG_REST_PARAM_TIME_MINUTES |
3591                                            OG_REST_PARAM_TIME_AM_PM |
3592                                            OG_REST_PARAM_TYPE))
3593                return -1;
3594
3595        return og_task_schedule_create(params);
3596}
3597
3598static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3599{
3600        struct og_dbi *dbi;
3601        const char *key;
3602        json_t *value;
3603        int err;
3604
3605        if (json_typeof(element) != JSON_OBJECT)
3606                return -1;
3607
3608        json_object_foreach(element, key, value) {
3609                if (!strcmp(key, "id")) {
3610                        err = og_json_parse_string(value, &params->id);
3611                        params->flags |= OG_REST_PARAM_ID;
3612                } else if (!strcmp(key, "task")) {
3613                        err = og_json_parse_string(value, &params->task_id);
3614                        params->flags |= OG_REST_PARAM_TASK;
3615                } else if (!strcmp(key, "name")) {
3616                        err = og_json_parse_string(value, &params->name);
3617                        params->flags |= OG_REST_PARAM_NAME;
3618                } else if (!strcmp(key, "when"))
3619                        err = og_json_parse_time_params(value, params);
3620
3621                if (err < 0)
3622                        break;
3623        }
3624
3625        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3626                                            OG_REST_PARAM_TASK |
3627                                            OG_REST_PARAM_NAME |
3628                                            OG_REST_PARAM_TIME_YEARS |
3629                                            OG_REST_PARAM_TIME_MONTHS |
3630                                            OG_REST_PARAM_TIME_DAYS |
3631                                            OG_REST_PARAM_TIME_HOURS |
3632                                            OG_REST_PARAM_TIME_MINUTES |
3633                                            OG_REST_PARAM_TIME_AM_PM))
3634                return -1;
3635
3636        dbi = og_dbi_open(&ogconfig.db);
3637        if (!dbi) {
3638                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3639                           __func__, __LINE__);
3640                return -1;
3641        }
3642
3643        err = og_dbi_schedule_update(dbi, params);
3644        og_dbi_close(dbi);
3645
3646        if (err < 0)
3647                return err;
3648
3649        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3650                           &params->time);
3651        og_schedule_refresh(og_loop);
3652
3653        return err;
3654}
3655
3656static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3657{
3658        struct og_dbi *dbi;
3659        const char *key;
3660        json_t *value;
3661        int err;
3662
3663        if (json_typeof(element) != JSON_OBJECT)
3664                return -1;
3665
3666        json_object_foreach(element, key, value) {
3667                if (!strcmp(key, "id")) {
3668                        err = og_json_parse_string(value, &params->id);
3669                        params->flags |= OG_REST_PARAM_ID;
3670                } else {
3671                        return -1;
3672                }
3673
3674                if (err < 0)
3675                        break;
3676        }
3677
3678        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3679                return -1;
3680
3681        dbi = og_dbi_open(&ogconfig.db);
3682        if (!dbi) {
3683                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3684                           __func__, __LINE__);
3685                return -1;
3686        }
3687
3688        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3689        og_dbi_close(dbi);
3690
3691        og_schedule_delete(og_loop, atoi(params->id));
3692
3693        return err;
3694}
3695
3696static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3697                               char *buffer_reply)
3698{
3699        struct og_buffer og_buffer = {
3700                .data   = buffer_reply,
3701        };
3702        json_t *schedule_root;
3703        struct og_dbi *dbi;
3704        const char *key;
3705        json_t *value;
3706        int err;
3707
3708        if (element) {
3709                if (json_typeof(element) != JSON_OBJECT)
3710                        return -1;
3711
3712                json_object_foreach(element, key, value) {
3713                        if (!strcmp(key, "task")) {
3714                                err = og_json_parse_string(value,
3715                                                           &params->task_id);
3716                        } else if (!strcmp(key, "id")) {
3717                                err = og_json_parse_string(value, &params->id);
3718                        } else {
3719                                return -1;
3720                        }
3721
3722                        if (err < 0)
3723                                break;
3724                }
3725        }
3726
3727        dbi = og_dbi_open(&ogconfig.db);
3728        if (!dbi) {
3729                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3730                           __func__, __LINE__);
3731                return -1;
3732        }
3733
3734        schedule_root = json_object();
3735        if (!schedule_root) {
3736                og_dbi_close(dbi);
3737                return -1;
3738        }
3739
3740        err = og_dbi_schedule_get_json(dbi, schedule_root,
3741                                       params->task_id, params->id);
3742        og_dbi_close(dbi);
3743
3744        if (err >= 0)
3745                json_dump_callback(schedule_root, og_json_dump_clients, &og_buffer, 0);
3746
3747        json_decref(schedule_root);
3748
3749        return err;
3750}
3751
3752static int og_client_method_not_found(struct og_client *cli)
3753{
3754        /* To meet RFC 7231, this function MUST generate an Allow header field
3755         * containing the correct methods. For example: "Allow: POST\r\n"
3756         */
3757        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
3758                     "Content-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_bad_request(struct og_client *cli)
3766{
3767        char buf[] = "HTTP/1.1 400 Bad Request\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_found(struct og_client *cli)
3775{
3776        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
3777
3778        send(og_client_socket(cli), buf, strlen(buf), 0);
3779
3780        return -1;
3781}
3782
3783static int og_client_not_authorized(struct og_client *cli)
3784{
3785        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
3786                     "WWW-Authenticate: Basic\r\n"
3787                     "Content-Length: 0\r\n\r\n";
3788
3789        send(og_client_socket(cli), buf, strlen(buf), 0);
3790
3791        return -1;
3792}
3793
3794static int og_server_internal_error(struct og_client *cli)
3795{
3796        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
3797                     "Content-Length: 0\r\n\r\n";
3798
3799        send(og_client_socket(cli), buf, strlen(buf), 0);
3800
3801        return -1;
3802}
3803
3804#define OG_MSG_RESPONSE_MAXLEN  65536
3805
3806static int og_client_ok(struct og_client *cli, char *buf_reply)
3807{
3808        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
3809        int err = 0, len;
3810
3811        len = snprintf(buf, sizeof(buf),
3812                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
3813                       strlen(buf_reply), buf_reply);
3814        if (len >= (int)sizeof(buf))
3815                err = og_server_internal_error(cli);
3816
3817        send(og_client_socket(cli), buf, strlen(buf), 0);
3818
3819        return err;
3820}
3821
3822int og_client_state_process_payload_rest(struct og_client *cli)
3823{
3824        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
3825        struct og_msg_params params = {};
3826        enum og_rest_method method;
3827        const char *cmd, *body;
3828        json_error_t json_err;
3829        json_t *root = NULL;
3830        int err = 0;
3831
3832        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
3833               inet_ntoa(cli->addr.sin_addr),
3834               ntohs(cli->addr.sin_port), cli->buf);
3835
3836        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
3837                method = OG_METHOD_GET;
3838                cmd = cli->buf + strlen("GET") + 2;
3839        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
3840                method = OG_METHOD_POST;
3841                cmd = cli->buf + strlen("POST") + 2;
3842        } else
3843                return og_client_method_not_found(cli);
3844
3845        body = strstr(cli->buf, "\r\n\r\n") + 4;
3846
3847        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
3848                syslog(LOG_ERR, "wrong Authentication key\n");
3849                return og_client_not_authorized(cli);
3850        }
3851
3852        if (cli->content_length) {
3853                root = json_loads(body, 0, &json_err);
3854                if (!root) {
3855                        syslog(LOG_ERR, "malformed json line %d: %s\n",
3856                               json_err.line, json_err.text);
3857                        return og_client_not_found(cli);
3858                }
3859        }
3860
3861        if (!strncmp(cmd, "clients", strlen("clients"))) {
3862                if (method != OG_METHOD_POST &&
3863                    method != OG_METHOD_GET) {
3864                        err = og_client_method_not_found(cli);
3865                        goto err_process_rest_payload;
3866                }
3867
3868                if (method == OG_METHOD_POST && !root) {
3869                        syslog(LOG_ERR, "command clients with no payload\n");
3870                        err = og_client_bad_request(cli);
3871                        goto err_process_rest_payload;
3872                }
3873                switch (method) {
3874                case OG_METHOD_POST:
3875                        err = og_cmd_post_clients(root, &params);
3876                        break;
3877                case OG_METHOD_GET:
3878                        err = og_cmd_get_clients(root, &params, buf_reply);
3879                        break;
3880                default:
3881                        err = og_client_bad_request(cli);
3882                        goto err_process_rest_payload;
3883                }
3884        } else if (!strncmp(cmd, "client/setup",
3885                            strlen("client/setup"))) {
3886                if (method != OG_METHOD_GET) {
3887                        err = og_client_method_not_found(cli);
3888                        goto err_process_rest_payload;
3889                }
3890
3891                if (!root) {
3892                        syslog(LOG_ERR,
3893                               "command client partitions with no payload\n");
3894                        err = og_client_bad_request(cli);
3895                        goto err_process_rest_payload;
3896                }
3897
3898                err = og_cmd_get_client_setup(root, &params, buf_reply);
3899        } else if (!strncmp(cmd, "client/info",
3900                            strlen("client/info"))) {
3901                if (method != OG_METHOD_GET) {
3902                        err = og_client_method_not_found(cli);
3903                        goto err_process_rest_payload;
3904                }
3905                if (!root) {
3906                        syslog(LOG_ERR,
3907                               "command client info with no payload\n");
3908                        err = og_client_bad_request(cli);
3909                        goto err_process_rest_payload;
3910                }
3911
3912                err = og_cmd_get_client_info(root, &params, buf_reply);
3913        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
3914                if (method != OG_METHOD_POST) {
3915                        err = og_client_method_not_found(cli);
3916                        goto err_process_rest_payload;
3917                }
3918
3919                if (!root) {
3920                        syslog(LOG_ERR,
3921                               "command client info with no payload\n");
3922                        err = og_client_bad_request(cli);
3923                        goto err_process_rest_payload;
3924                }
3925
3926                err = og_cmd_post_client_add(root, &params, buf_reply);
3927        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
3928                if (method != OG_METHOD_POST) {
3929                        err = og_client_method_not_found(cli);
3930                        goto err_process_rest_payload;
3931                }
3932
3933                if (!root) {
3934                        syslog(LOG_ERR,
3935                               "command client delete with no payload\n");
3936                        err = og_client_bad_request(cli);
3937                        goto err_process_rest_payload;
3938                }
3939
3940                err = og_cmd_post_client_delete(root, &params);
3941        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
3942                if (method != OG_METHOD_POST) {
3943                        err = og_client_method_not_found(cli);
3944                        goto err_process_rest_payload;
3945                }
3946
3947                if (!root) {
3948                        syslog(LOG_ERR, "command wol with no payload\n");
3949                        err = og_client_bad_request(cli);
3950                        goto err_process_rest_payload;
3951                }
3952                err = og_cmd_wol(root, &params);
3953        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
3954                if (method != OG_METHOD_POST) {
3955                        err = og_client_method_not_found(cli);
3956                        goto err_process_rest_payload;
3957                }
3958
3959                if (!root) {
3960                        syslog(LOG_ERR, "command run with no payload\n");
3961                        err = og_client_bad_request(cli);
3962                        goto err_process_rest_payload;
3963                }
3964                err = og_cmd_run_post(root, &params);
3965        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
3966                if (method != OG_METHOD_POST) {
3967                        err = og_client_method_not_found(cli);
3968                        goto err_process_rest_payload;
3969                }
3970
3971                if (!root) {
3972                        syslog(LOG_ERR, "command output with no payload\n");
3973                        err = og_client_bad_request(cli);
3974                        goto err_process_rest_payload;
3975                }
3976
3977                err = og_cmd_run_get(root, &params, buf_reply);
3978        } else if (!strncmp(cmd, "session", strlen("session"))) {
3979                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
3980                        err = og_client_method_not_found(cli);
3981                        goto err_process_rest_payload;
3982                }
3983
3984                if (!root) {
3985                        syslog(LOG_ERR, "command session with no payload\n");
3986                        err = og_client_bad_request(cli);
3987                        goto err_process_rest_payload;
3988                }
3989
3990                if (method == OG_METHOD_POST)
3991                        err = og_cmd_session(root, &params);
3992                else
3993                        err = og_cmd_get_session(root, &params, buf_reply);
3994        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
3995                if (method != OG_METHOD_GET) {
3996                        err = og_client_method_not_found(cli);
3997                        goto err_process_rest_payload;
3998                }
3999
4000                if (root) {
4001                        syslog(LOG_ERR, "command scopes with payload\n");
4002                        err = og_client_bad_request(cli);
4003                        goto err_process_rest_payload;
4004                }
4005
4006                err = og_cmd_scope_get(root, &params, buf_reply);
4007        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
4008                if (method != OG_METHOD_POST) {
4009                        err = og_client_method_not_found(cli);
4010                        goto err_process_rest_payload;
4011                }
4012
4013                if (!root) {
4014                        syslog(LOG_ERR, "command poweroff with no payload\n");
4015                        err = og_client_bad_request(cli);
4016                        goto err_process_rest_payload;
4017                }
4018                err = og_cmd_poweroff(root, &params);
4019        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
4020                if (method != OG_METHOD_POST) {
4021                        err = og_client_method_not_found(cli);
4022                        goto err_process_rest_payload;
4023                }
4024
4025                if (!root) {
4026                        syslog(LOG_ERR, "command reboot with no payload\n");
4027                        err = og_client_bad_request(cli);
4028                        goto err_process_rest_payload;
4029                }
4030                err = og_cmd_reboot(root, &params);
4031        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
4032                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
4033                        err = og_client_method_not_found(cli);
4034                        goto err_process_rest_payload;
4035                }
4036
4037                if (method == OG_METHOD_POST && !root) {
4038                        syslog(LOG_ERR, "command mode with no payload\n");
4039                        err = og_client_bad_request(cli);
4040                        goto err_process_rest_payload;
4041                }
4042
4043                if (method == OG_METHOD_GET)
4044                        err = og_cmd_get_modes(root, &params, buf_reply);
4045                else if (method == OG_METHOD_POST)
4046                        err = og_cmd_post_modes(root, &params);
4047        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
4048                if (method != OG_METHOD_POST) {
4049                        err = og_client_method_not_found(cli);
4050                        goto err_process_rest_payload;
4051                }
4052
4053                if (!root) {
4054                        syslog(LOG_ERR, "command stop with no payload\n");
4055                        err = og_client_bad_request(cli);
4056                        goto err_process_rest_payload;
4057                }
4058                err = og_cmd_stop(root, &params);
4059        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
4060                if (method != OG_METHOD_POST) {
4061                        err = og_client_method_not_found(cli);
4062                        goto err_process_rest_payload;
4063                }
4064
4065                if (!root) {
4066                        syslog(LOG_ERR, "command refresh with no payload\n");
4067                        err = og_client_bad_request(cli);
4068                        goto err_process_rest_payload;
4069                }
4070                err = og_cmd_refresh(root, &params);
4071        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4072                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
4073                        err = og_client_method_not_found(cli);
4074                        goto err_process_rest_payload;
4075                }
4076
4077                if (!root) {
4078                        syslog(LOG_ERR, "command hardware with no payload\n");
4079                        err = og_client_bad_request(cli);
4080                        goto err_process_rest_payload;
4081                }
4082
4083                if (method == OG_METHOD_GET)
4084                        err = og_cmd_get_hardware(root, &params, buf_reply);
4085                else if (method == OG_METHOD_POST)
4086                        err = og_cmd_hardware(root, &params);
4087        } else if (!strncmp(cmd, "software", strlen("software"))) {
4088                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
4089                        err = og_client_method_not_found(cli);
4090                        goto err_process_rest_payload;
4091                }
4092
4093                if (!root) {
4094                        syslog(LOG_ERR, "command software with no payload\n");
4095                        err = og_client_bad_request(cli);
4096                        goto err_process_rest_payload;
4097                }
4098
4099                if (method == OG_METHOD_POST)
4100                        err = og_cmd_software(root, &params);
4101                else
4102                        err = og_cmd_get_software(root, &params, buf_reply);
4103        } else if (!strncmp(cmd, "images", strlen("images"))) {
4104                if (method != OG_METHOD_GET) {
4105                        err = og_client_method_not_found(cli);
4106                        goto err_process_rest_payload;
4107                }
4108
4109                if (root) {
4110                        err = og_client_method_not_found(cli);
4111                        goto err_process_rest_payload;
4112                }
4113
4114                err = og_cmd_images(buf_reply);
4115        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4116                if (method != OG_METHOD_POST) {
4117                        err = og_client_method_not_found(cli);
4118                        goto err_process_rest_payload;
4119                }
4120
4121                if (!root) {
4122                        syslog(LOG_ERR, "command create with no payload\n");
4123                        err = og_client_bad_request(cli);
4124                        goto err_process_rest_payload;
4125                }
4126                err = og_cmd_create_image(root, &params);
4127        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4128                if (method != OG_METHOD_POST) {
4129                        err = og_client_method_not_found(cli);
4130                        goto err_process_rest_payload;
4131                }
4132
4133                if (!root) {
4134                        syslog(LOG_ERR, "command create with no payload\n");
4135                        err = og_client_bad_request(cli);
4136                        goto err_process_rest_payload;
4137                }
4138                err = og_cmd_restore_image(root, &params);
4139        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
4140                if (method != OG_METHOD_POST) {
4141                        err = og_client_method_not_found(cli);
4142                        goto err_process_rest_payload;
4143                }
4144
4145                if (!root) {
4146                        syslog(LOG_ERR, "command create with no payload\n");
4147                        err = og_client_bad_request(cli);
4148                        goto err_process_rest_payload;
4149                }
4150                err = og_cmd_setup(root, &params);
4151        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4152                if (method != OG_METHOD_POST) {
4153                        err = og_client_method_not_found(cli);
4154                        goto err_process_rest_payload;
4155                }
4156
4157                if (!root) {
4158                        syslog(LOG_ERR, "command create with no payload\n");
4159                        err = og_client_bad_request(cli);
4160                        goto err_process_rest_payload;
4161                }
4162
4163                err = og_cmd_run_schedule(root, &params);
4164        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
4165                if (method != OG_METHOD_POST) {
4166                        err = og_client_method_not_found(cli);
4167                        goto err_process_rest_payload;
4168                }
4169
4170                if (!root) {
4171                        syslog(LOG_ERR, "command task with no payload\n");
4172                        err = og_client_bad_request(cli);
4173                        goto err_process_rest_payload;
4174                }
4175                err = og_cmd_task_post(root, &params);
4176        } else if (!strncmp(cmd, "schedule/create",
4177                            strlen("schedule/create"))) {
4178                if (method != OG_METHOD_POST) {
4179                        err = og_client_method_not_found(cli);
4180                        goto err_process_rest_payload;
4181                }
4182
4183                if (!root) {
4184                        syslog(LOG_ERR, "command task with no payload\n");
4185                        err = og_client_bad_request(cli);
4186                        goto err_process_rest_payload;
4187                }
4188                err = og_cmd_schedule_create(root, &params);
4189        } else if (!strncmp(cmd, "schedule/delete",
4190                            strlen("schedule/delete"))) {
4191                if (method != OG_METHOD_POST) {
4192                        err = og_client_method_not_found(cli);
4193                        goto err_process_rest_payload;
4194                }
4195
4196                if (!root) {
4197                        syslog(LOG_ERR, "command task with no payload\n");
4198                        err = og_client_bad_request(cli);
4199                        goto err_process_rest_payload;
4200                }
4201                err = og_cmd_schedule_delete(root, &params);
4202        } else if (!strncmp(cmd, "schedule/update",
4203                            strlen("schedule/update"))) {
4204                if (method != OG_METHOD_POST) {
4205                        err = og_client_method_not_found(cli);
4206                        goto err_process_rest_payload;
4207                }
4208
4209                if (!root) {
4210                        syslog(LOG_ERR, "command task with no payload\n");
4211                        err = og_client_bad_request(cli);
4212                        goto err_process_rest_payload;
4213                }
4214                err = og_cmd_schedule_update(root, &params);
4215        } else if (!strncmp(cmd, "schedule/get",
4216                            strlen("schedule/get"))) {
4217                if (method != OG_METHOD_POST) {
4218                        err = og_client_method_not_found(cli);
4219                        goto err_process_rest_payload;
4220                }
4221
4222                err = og_cmd_schedule_get(root, &params, buf_reply);
4223        } else {
4224                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
4225                err = og_client_not_found(cli);
4226        }
4227
4228        json_decref(root);
4229
4230        if (err < 0)
4231                return og_client_bad_request(cli);
4232
4233        err = og_client_ok(cli, buf_reply);
4234        if (err < 0) {
4235                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4236                       inet_ntoa(cli->addr.sin_addr),
4237                       ntohs(cli->addr.sin_port));
4238        }
4239
4240        return err;
4241
4242err_process_rest_payload:
4243        json_decref(root);
4244
4245        return err;
4246}
Note: See TracBrowser for help on using the repository browser.