source: ogServer-Git/src/rest.c @ 76e6375

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

#1004 Fix memleak in og_cmd_images

image_json object is created to store the json representation of
an image returned by the database. This object is going to be appended
to a json list that will compose the overall root json object.

Use json_array_append_new to let "images" steal the reference of
image_json so when further decref(root) there is no json reference
hanging around.

  • Property mode set to 100644
File size: 106.7 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    = strdup(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 = strdup(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.on_start = 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 int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3489{
3490        const char *key;
3491        json_t *value;
3492        int err;
3493
3494        if (json_typeof(element) != JSON_OBJECT)
3495                return -1;
3496
3497        json_object_foreach(element, key, value) {
3498                if (!strcmp(key, "task")) {
3499                        err = og_json_parse_string(value, &params->task_id);
3500                        params->flags |= OG_REST_PARAM_TASK;
3501                } else if (!strcmp(key, "name")) {
3502                        err = og_json_parse_string(value, &params->name);
3503                        params->flags |= OG_REST_PARAM_NAME;
3504                } else if (!strcmp(key, "when")) {
3505                        err = og_json_parse_time_params(value, params);
3506                } else if (!strcmp(key, "type")) {
3507                        err = og_json_parse_string(value, &params->type);
3508                        params->flags |= OG_REST_PARAM_TYPE;
3509                }
3510
3511                if (err < 0)
3512                        break;
3513        }
3514
3515        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3516                                            OG_REST_PARAM_NAME |
3517                                            OG_REST_PARAM_TIME_YEARS |
3518                                            OG_REST_PARAM_TIME_MONTHS |
3519                                            OG_REST_PARAM_TIME_WEEKS |
3520                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3521                                            OG_REST_PARAM_TIME_DAYS |
3522                                            OG_REST_PARAM_TIME_HOURS |
3523                                            OG_REST_PARAM_TIME_MINUTES |
3524                                            OG_REST_PARAM_TIME_AM_PM |
3525                                            OG_REST_PARAM_TYPE))
3526                return -1;
3527
3528        return og_task_schedule_create(params);
3529}
3530
3531static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3532{
3533        struct og_dbi *dbi;
3534        const char *key;
3535        json_t *value;
3536        int err;
3537
3538        if (json_typeof(element) != JSON_OBJECT)
3539                return -1;
3540
3541        json_object_foreach(element, key, value) {
3542                if (!strcmp(key, "id")) {
3543                        err = og_json_parse_string(value, &params->id);
3544                        params->flags |= OG_REST_PARAM_ID;
3545                } else if (!strcmp(key, "task")) {
3546                        err = og_json_parse_string(value, &params->task_id);
3547                        params->flags |= OG_REST_PARAM_TASK;
3548                } else if (!strcmp(key, "name")) {
3549                        err = og_json_parse_string(value, &params->name);
3550                        params->flags |= OG_REST_PARAM_NAME;
3551                } else if (!strcmp(key, "when"))
3552                        err = og_json_parse_time_params(value, params);
3553
3554                if (err < 0)
3555                        break;
3556        }
3557
3558        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3559                                            OG_REST_PARAM_TASK |
3560                                            OG_REST_PARAM_NAME |
3561                                            OG_REST_PARAM_TIME_YEARS |
3562                                            OG_REST_PARAM_TIME_MONTHS |
3563                                            OG_REST_PARAM_TIME_DAYS |
3564                                            OG_REST_PARAM_TIME_HOURS |
3565                                            OG_REST_PARAM_TIME_MINUTES |
3566                                            OG_REST_PARAM_TIME_AM_PM))
3567                return -1;
3568
3569        dbi = og_dbi_open(&ogconfig.db);
3570        if (!dbi) {
3571                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3572                           __func__, __LINE__);
3573                return -1;
3574        }
3575
3576        err = og_dbi_schedule_update(dbi, params);
3577        og_dbi_close(dbi);
3578
3579        if (err < 0)
3580                return err;
3581
3582        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3583                           &params->time);
3584        og_schedule_refresh(og_loop);
3585
3586        return err;
3587}
3588
3589static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3590{
3591        struct og_dbi *dbi;
3592        const char *key;
3593        json_t *value;
3594        int err;
3595
3596        if (json_typeof(element) != JSON_OBJECT)
3597                return -1;
3598
3599        json_object_foreach(element, key, value) {
3600                if (!strcmp(key, "id")) {
3601                        err = og_json_parse_string(value, &params->id);
3602                        params->flags |= OG_REST_PARAM_ID;
3603                } else {
3604                        return -1;
3605                }
3606
3607                if (err < 0)
3608                        break;
3609        }
3610
3611        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3612                return -1;
3613
3614        dbi = og_dbi_open(&ogconfig.db);
3615        if (!dbi) {
3616                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3617                           __func__, __LINE__);
3618                return -1;
3619        }
3620
3621        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3622        og_dbi_close(dbi);
3623
3624        og_schedule_delete(og_loop, atoi(params->id));
3625
3626        return err;
3627}
3628
3629static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3630                               char *buffer_reply)
3631{
3632        struct og_buffer og_buffer = {
3633                .data   = buffer_reply,
3634        };
3635        json_t *schedule_root;
3636        struct og_dbi *dbi;
3637        const char *key;
3638        json_t *value;
3639        int err;
3640
3641        if (element) {
3642                if (json_typeof(element) != JSON_OBJECT)
3643                        return -1;
3644
3645                json_object_foreach(element, key, value) {
3646                        if (!strcmp(key, "task")) {
3647                                err = og_json_parse_string(value,
3648                                                           &params->task_id);
3649                        } else if (!strcmp(key, "id")) {
3650                                err = og_json_parse_string(value, &params->id);
3651                        } else {
3652                                return -1;
3653                        }
3654
3655                        if (err < 0)
3656                                break;
3657                }
3658        }
3659
3660        dbi = og_dbi_open(&ogconfig.db);
3661        if (!dbi) {
3662                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3663                           __func__, __LINE__);
3664                return -1;
3665        }
3666
3667        schedule_root = json_object();
3668        if (!schedule_root) {
3669                og_dbi_close(dbi);
3670                return -1;
3671        }
3672
3673        err = og_dbi_schedule_get_json(dbi, schedule_root,
3674                                       params->task_id, params->id);
3675        og_dbi_close(dbi);
3676
3677        if (err >= 0)
3678                json_dump_callback(schedule_root, og_json_dump_clients, &og_buffer, 0);
3679
3680        json_decref(schedule_root);
3681
3682        return err;
3683}
3684
3685static int og_client_method_not_found(struct og_client *cli)
3686{
3687        /* To meet RFC 7231, this function MUST generate an Allow header field
3688         * containing the correct methods. For example: "Allow: POST\r\n"
3689         */
3690        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
3691                     "Content-Length: 0\r\n\r\n";
3692
3693        send(og_client_socket(cli), buf, strlen(buf), 0);
3694
3695        return -1;
3696}
3697
3698static int og_client_bad_request(struct og_client *cli)
3699{
3700        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
3701
3702        send(og_client_socket(cli), buf, strlen(buf), 0);
3703
3704        return -1;
3705}
3706
3707static int og_client_not_found(struct og_client *cli)
3708{
3709        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
3710
3711        send(og_client_socket(cli), buf, strlen(buf), 0);
3712
3713        return -1;
3714}
3715
3716static int og_client_not_authorized(struct og_client *cli)
3717{
3718        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
3719                     "WWW-Authenticate: Basic\r\n"
3720                     "Content-Length: 0\r\n\r\n";
3721
3722        send(og_client_socket(cli), buf, strlen(buf), 0);
3723
3724        return -1;
3725}
3726
3727static int og_server_internal_error(struct og_client *cli)
3728{
3729        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
3730                     "Content-Length: 0\r\n\r\n";
3731
3732        send(og_client_socket(cli), buf, strlen(buf), 0);
3733
3734        return -1;
3735}
3736
3737#define OG_MSG_RESPONSE_MAXLEN  65536
3738
3739static int og_client_ok(struct og_client *cli, char *buf_reply)
3740{
3741        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
3742        int err = 0, len;
3743
3744        len = snprintf(buf, sizeof(buf),
3745                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
3746                       strlen(buf_reply), buf_reply);
3747        if (len >= (int)sizeof(buf))
3748                err = og_server_internal_error(cli);
3749
3750        send(og_client_socket(cli), buf, strlen(buf), 0);
3751
3752        return err;
3753}
3754
3755int og_client_state_process_payload_rest(struct og_client *cli)
3756{
3757        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
3758        struct og_msg_params params = {};
3759        enum og_rest_method method;
3760        const char *cmd, *body;
3761        json_error_t json_err;
3762        json_t *root = NULL;
3763        int err = 0;
3764
3765        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
3766               inet_ntoa(cli->addr.sin_addr),
3767               ntohs(cli->addr.sin_port), cli->buf);
3768
3769        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
3770                method = OG_METHOD_GET;
3771                cmd = cli->buf + strlen("GET") + 2;
3772        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
3773                method = OG_METHOD_POST;
3774                cmd = cli->buf + strlen("POST") + 2;
3775        } else
3776                return og_client_method_not_found(cli);
3777
3778        body = strstr(cli->buf, "\r\n\r\n") + 4;
3779
3780        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
3781                syslog(LOG_ERR, "wrong Authentication key\n");
3782                return og_client_not_authorized(cli);
3783        }
3784
3785        if (cli->content_length) {
3786                root = json_loads(body, 0, &json_err);
3787                if (!root) {
3788                        syslog(LOG_ERR, "malformed json line %d: %s\n",
3789                               json_err.line, json_err.text);
3790                        return og_client_not_found(cli);
3791                }
3792        }
3793
3794        if (!strncmp(cmd, "clients", strlen("clients"))) {
3795                if (method != OG_METHOD_POST &&
3796                    method != OG_METHOD_GET) {
3797                        err = og_client_method_not_found(cli);
3798                        goto err_process_rest_payload;
3799                }
3800
3801                if (method == OG_METHOD_POST && !root) {
3802                        syslog(LOG_ERR, "command clients with no payload\n");
3803                        err = og_client_bad_request(cli);
3804                        goto err_process_rest_payload;
3805                }
3806                switch (method) {
3807                case OG_METHOD_POST:
3808                        err = og_cmd_post_clients(root, &params);
3809                        break;
3810                case OG_METHOD_GET:
3811                        err = og_cmd_get_clients(root, &params, buf_reply);
3812                        break;
3813                default:
3814                        err = og_client_bad_request(cli);
3815                        goto err_process_rest_payload;
3816                }
3817        } else if (!strncmp(cmd, "client/setup",
3818                            strlen("client/setup"))) {
3819                if (method != OG_METHOD_GET) {
3820                        err = og_client_method_not_found(cli);
3821                        goto err_process_rest_payload;
3822                }
3823
3824                if (!root) {
3825                        syslog(LOG_ERR,
3826                               "command client partitions with no payload\n");
3827                        err = og_client_bad_request(cli);
3828                        goto err_process_rest_payload;
3829                }
3830
3831                err = og_cmd_get_client_setup(root, &params, buf_reply);
3832        } else if (!strncmp(cmd, "client/info",
3833                            strlen("client/info"))) {
3834                if (method != OG_METHOD_GET) {
3835                        err = og_client_method_not_found(cli);
3836                        goto err_process_rest_payload;
3837                }
3838                if (!root) {
3839                        syslog(LOG_ERR,
3840                               "command client info with no payload\n");
3841                        err = og_client_bad_request(cli);
3842                        goto err_process_rest_payload;
3843                }
3844
3845                err = og_cmd_get_client_info(root, &params, buf_reply);
3846        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
3847                if (method != OG_METHOD_POST) {
3848                        err = og_client_method_not_found(cli);
3849                        goto err_process_rest_payload;
3850                }
3851
3852                if (!root) {
3853                        syslog(LOG_ERR,
3854                               "command client info with no payload\n");
3855                        err = og_client_bad_request(cli);
3856                        goto err_process_rest_payload;
3857                }
3858
3859                err = og_cmd_post_client_add(root, &params, buf_reply);
3860        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
3861                if (method != OG_METHOD_POST) {
3862                        err = og_client_method_not_found(cli);
3863                        goto err_process_rest_payload;
3864                }
3865
3866                if (!root) {
3867                        syslog(LOG_ERR,
3868                               "command client delete with no payload\n");
3869                        err = og_client_bad_request(cli);
3870                        goto err_process_rest_payload;
3871                }
3872
3873                err = og_cmd_post_client_delete(root, &params);
3874        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
3875                if (method != OG_METHOD_POST) {
3876                        err = og_client_method_not_found(cli);
3877                        goto err_process_rest_payload;
3878                }
3879
3880                if (!root) {
3881                        syslog(LOG_ERR, "command wol with no payload\n");
3882                        err = og_client_bad_request(cli);
3883                        goto err_process_rest_payload;
3884                }
3885                err = og_cmd_wol(root, &params);
3886        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
3887                if (method != OG_METHOD_POST) {
3888                        err = og_client_method_not_found(cli);
3889                        goto err_process_rest_payload;
3890                }
3891
3892                if (!root) {
3893                        syslog(LOG_ERR, "command run with no payload\n");
3894                        err = og_client_bad_request(cli);
3895                        goto err_process_rest_payload;
3896                }
3897                err = og_cmd_run_post(root, &params);
3898        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
3899                if (method != OG_METHOD_POST) {
3900                        err = og_client_method_not_found(cli);
3901                        goto err_process_rest_payload;
3902                }
3903
3904                if (!root) {
3905                        syslog(LOG_ERR, "command output with no payload\n");
3906                        err = og_client_bad_request(cli);
3907                        goto err_process_rest_payload;
3908                }
3909
3910                err = og_cmd_run_get(root, &params, buf_reply);
3911        } else if (!strncmp(cmd, "session", strlen("session"))) {
3912                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
3913                        err = og_client_method_not_found(cli);
3914                        goto err_process_rest_payload;
3915                }
3916
3917                if (!root) {
3918                        syslog(LOG_ERR, "command session with no payload\n");
3919                        err = og_client_bad_request(cli);
3920                        goto err_process_rest_payload;
3921                }
3922
3923                if (method == OG_METHOD_POST)
3924                        err = og_cmd_session(root, &params);
3925                else
3926                        err = og_cmd_get_session(root, &params, buf_reply);
3927        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
3928                if (method != OG_METHOD_GET) {
3929                        err = og_client_method_not_found(cli);
3930                        goto err_process_rest_payload;
3931                }
3932
3933                if (root) {
3934                        syslog(LOG_ERR, "command scopes with payload\n");
3935                        err = og_client_bad_request(cli);
3936                        goto err_process_rest_payload;
3937                }
3938
3939                err = og_cmd_scope_get(root, &params, buf_reply);
3940        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
3941                if (method != OG_METHOD_POST) {
3942                        err = og_client_method_not_found(cli);
3943                        goto err_process_rest_payload;
3944                }
3945
3946                if (!root) {
3947                        syslog(LOG_ERR, "command poweroff with no payload\n");
3948                        err = og_client_bad_request(cli);
3949                        goto err_process_rest_payload;
3950                }
3951                err = og_cmd_poweroff(root, &params);
3952        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
3953                if (method != OG_METHOD_POST) {
3954                        err = og_client_method_not_found(cli);
3955                        goto err_process_rest_payload;
3956                }
3957
3958                if (!root) {
3959                        syslog(LOG_ERR, "command reboot with no payload\n");
3960                        err = og_client_bad_request(cli);
3961                        goto err_process_rest_payload;
3962                }
3963                err = og_cmd_reboot(root, &params);
3964        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
3965                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
3966                        err = og_client_method_not_found(cli);
3967                        goto err_process_rest_payload;
3968                }
3969
3970                if (method == OG_METHOD_POST && !root) {
3971                        syslog(LOG_ERR, "command mode with no payload\n");
3972                        err = og_client_bad_request(cli);
3973                        goto err_process_rest_payload;
3974                }
3975
3976                if (method == OG_METHOD_GET)
3977                        err = og_cmd_get_modes(root, &params, buf_reply);
3978                else if (method == OG_METHOD_POST)
3979                        err = og_cmd_post_modes(root, &params);
3980        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
3981                if (method != OG_METHOD_POST) {
3982                        err = og_client_method_not_found(cli);
3983                        goto err_process_rest_payload;
3984                }
3985
3986                if (!root) {
3987                        syslog(LOG_ERR, "command stop with no payload\n");
3988                        err = og_client_bad_request(cli);
3989                        goto err_process_rest_payload;
3990                }
3991                err = og_cmd_stop(root, &params);
3992        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
3993                if (method != OG_METHOD_POST) {
3994                        err = og_client_method_not_found(cli);
3995                        goto err_process_rest_payload;
3996                }
3997
3998                if (!root) {
3999                        syslog(LOG_ERR, "command refresh with no payload\n");
4000                        err = og_client_bad_request(cli);
4001                        goto err_process_rest_payload;
4002                }
4003                err = og_cmd_refresh(root, &params);
4004        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4005                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
4006                        err = og_client_method_not_found(cli);
4007                        goto err_process_rest_payload;
4008                }
4009
4010                if (!root) {
4011                        syslog(LOG_ERR, "command hardware with no payload\n");
4012                        err = og_client_bad_request(cli);
4013                        goto err_process_rest_payload;
4014                }
4015
4016                if (method == OG_METHOD_GET)
4017                        err = og_cmd_get_hardware(root, &params, buf_reply);
4018                else if (method == OG_METHOD_POST)
4019                        err = og_cmd_hardware(root, &params);
4020        } else if (!strncmp(cmd, "software", strlen("software"))) {
4021                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
4022                        err = og_client_method_not_found(cli);
4023                        goto err_process_rest_payload;
4024                }
4025
4026                if (!root) {
4027                        syslog(LOG_ERR, "command software with no payload\n");
4028                        err = og_client_bad_request(cli);
4029                        goto err_process_rest_payload;
4030                }
4031
4032                if (method == OG_METHOD_POST)
4033                        err = og_cmd_software(root, &params);
4034                else
4035                        err = og_cmd_get_software(root, &params, buf_reply);
4036        } else if (!strncmp(cmd, "images", strlen("images"))) {
4037                if (method != OG_METHOD_GET) {
4038                        err = og_client_method_not_found(cli);
4039                        goto err_process_rest_payload;
4040                }
4041
4042                if (root) {
4043                        err = og_client_method_not_found(cli);
4044                        goto err_process_rest_payload;
4045                }
4046
4047                err = og_cmd_images(buf_reply);
4048        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4049                if (method != OG_METHOD_POST) {
4050                        err = og_client_method_not_found(cli);
4051                        goto err_process_rest_payload;
4052                }
4053
4054                if (!root) {
4055                        syslog(LOG_ERR, "command create with no payload\n");
4056                        err = og_client_bad_request(cli);
4057                        goto err_process_rest_payload;
4058                }
4059                err = og_cmd_create_image(root, &params);
4060        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4061                if (method != OG_METHOD_POST) {
4062                        err = og_client_method_not_found(cli);
4063                        goto err_process_rest_payload;
4064                }
4065
4066                if (!root) {
4067                        syslog(LOG_ERR, "command create with no payload\n");
4068                        err = og_client_bad_request(cli);
4069                        goto err_process_rest_payload;
4070                }
4071                err = og_cmd_restore_image(root, &params);
4072        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
4073                if (method != OG_METHOD_POST) {
4074                        err = og_client_method_not_found(cli);
4075                        goto err_process_rest_payload;
4076                }
4077
4078                if (!root) {
4079                        syslog(LOG_ERR, "command create with no payload\n");
4080                        err = og_client_bad_request(cli);
4081                        goto err_process_rest_payload;
4082                }
4083                err = og_cmd_setup(root, &params);
4084        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4085                if (method != OG_METHOD_POST) {
4086                        err = og_client_method_not_found(cli);
4087                        goto err_process_rest_payload;
4088                }
4089
4090                if (!root) {
4091                        syslog(LOG_ERR, "command create with no payload\n");
4092                        err = og_client_bad_request(cli);
4093                        goto err_process_rest_payload;
4094                }
4095
4096                err = og_cmd_run_schedule(root, &params);
4097        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
4098                if (method != OG_METHOD_POST) {
4099                        err = og_client_method_not_found(cli);
4100                        goto err_process_rest_payload;
4101                }
4102
4103                if (!root) {
4104                        syslog(LOG_ERR, "command task with no payload\n");
4105                        err = og_client_bad_request(cli);
4106                        goto err_process_rest_payload;
4107                }
4108                err = og_cmd_task_post(root, &params);
4109        } else if (!strncmp(cmd, "schedule/create",
4110                            strlen("schedule/create"))) {
4111                if (method != OG_METHOD_POST) {
4112                        err = og_client_method_not_found(cli);
4113                        goto err_process_rest_payload;
4114                }
4115
4116                if (!root) {
4117                        syslog(LOG_ERR, "command task with no payload\n");
4118                        err = og_client_bad_request(cli);
4119                        goto err_process_rest_payload;
4120                }
4121                err = og_cmd_schedule_create(root, &params);
4122        } else if (!strncmp(cmd, "schedule/delete",
4123                            strlen("schedule/delete"))) {
4124                if (method != OG_METHOD_POST) {
4125                        err = og_client_method_not_found(cli);
4126                        goto err_process_rest_payload;
4127                }
4128
4129                if (!root) {
4130                        syslog(LOG_ERR, "command task with no payload\n");
4131                        err = og_client_bad_request(cli);
4132                        goto err_process_rest_payload;
4133                }
4134                err = og_cmd_schedule_delete(root, &params);
4135        } else if (!strncmp(cmd, "schedule/update",
4136                            strlen("schedule/update"))) {
4137                if (method != OG_METHOD_POST) {
4138                        err = og_client_method_not_found(cli);
4139                        goto err_process_rest_payload;
4140                }
4141
4142                if (!root) {
4143                        syslog(LOG_ERR, "command task with no payload\n");
4144                        err = og_client_bad_request(cli);
4145                        goto err_process_rest_payload;
4146                }
4147                err = og_cmd_schedule_update(root, &params);
4148        } else if (!strncmp(cmd, "schedule/get",
4149                            strlen("schedule/get"))) {
4150                if (method != OG_METHOD_POST) {
4151                        err = og_client_method_not_found(cli);
4152                        goto err_process_rest_payload;
4153                }
4154
4155                err = og_cmd_schedule_get(root, &params, buf_reply);
4156        } else {
4157                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
4158                err = og_client_not_found(cli);
4159        }
4160
4161        json_decref(root);
4162
4163        if (err < 0)
4164                return og_client_bad_request(cli);
4165
4166        err = og_client_ok(cli, buf_reply);
4167        if (err < 0) {
4168                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4169                       inet_ntoa(cli->addr.sin_addr),
4170                       ntohs(cli->addr.sin_port));
4171        }
4172
4173        return err;
4174
4175err_process_rest_payload:
4176        json_decref(root);
4177
4178        return err;
4179}
Note: See TracBrowser for help on using the repository browser.