source: ogServer-Git/src/rest.c @ 0e4857a

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

#1019 Fix restore-image legacy string parser

UMA reports that the restore image command (in queue mode) does not work,
the non-queue mode works fine though.

WebConsole? stores queued commands in the database using the deprecated
SocketHidra? legacy string format and ogServer parses them with sscanf().
The restore-image command has the field "ptc" which stores a string
with whitespaces, however, ogServer expects no whitespaces ("%s").

Update parser to read until carriage return, whitespaces included.

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