source: ogServer-Git/src/rest.c @ 85d0928

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

#802 add uefi folder for post_modes pxe template lookup

When executing og_cmd_post_modes ogServer is looking up for the template
related to the mode coming as a parameter. This lookup is only done for
the bios boot mode. (ie. /opt/opengnsys/tftpboot/menu.lst/templates/)

Templates can be created for a given boot mode, for example you can
create a UEFI-only template (it.
/opt/opengnsys/tftpboot/grub/templates).

When a UEFI only template was coming as a parameter to og_cmd_post_modes
the file can't be located because the UEFI template folder is never
tested.

Add UEFI folder to the lookup of pxe templates, try this folder if bios
mode fails.

PS: Later on a bash script "setclientmode" is to be executed, which will
take its own way of updating these pxe files (ie. templates/../), this
script updates every boot mode if an available template is found.

  • 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\ripr=%s\rifs=%s\rptc=%s\r",
2348                   img.disk, img.part, img.image_id, img.name, img.repo,
2349                   software_id_str, restore_type_str) != 7)
2350                return -1;
2351
2352        restore_type = json_string(restore_type_str);
2353        software_id = json_string(software_id_str);
2354        image_id = json_string(img.image_id);
2355        partition = json_string(img.part);
2356        name = json_string(img.name);
2357        repo = json_string(img.repo);
2358        disk = json_string(img.disk);
2359
2360        root = json_object();
2361        if (!root)
2362                return -1;
2363        json_object_set_new(root, "profile", software_id);
2364        json_object_set_new(root, "partition", partition);
2365        json_object_set_new(root, "type", restore_type);
2366        json_object_set_new(root, "repository", repo);
2367        json_object_set_new(root, "id", image_id);
2368        json_object_set_new(root, "name", name);
2369        json_object_set_new(root, "disk", disk);
2370
2371        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2372
2373        return 0;
2374}
2375
2376static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2377{
2378        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
2379        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
2380        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2381        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2382        json_t *part, *code, *fs, *size, *format;
2383        unsigned int partition_len = 0;
2384        const char *in_ptr;
2385        char cache_str[2];
2386
2387        if (sscanf(input, "dsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2388                   disk_str, cache_str, cache_size_str) != 3)
2389                return -1;
2390
2391        in_ptr = strstr(input, "!") + 1;
2392        while (strlen(in_ptr) > 0) {
2393                if(sscanf(in_ptr,
2394                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2395                          part_cfg[partition_len].partition,
2396                          part_cfg[partition_len].code,
2397                          part_cfg[partition_len].filesystem,
2398                          part_cfg[partition_len].size,
2399                          part_cfg[partition_len].format) != 5)
2400                        return -1;
2401                in_ptr = strstr(in_ptr, "%") + 1;
2402                partition_len++;
2403        }
2404
2405        root = json_object();
2406        if (!root)
2407                return -1;
2408
2409        cache_size = json_string(cache_size_str);
2410        cache = json_string(cache_str);
2411        partition_setup = json_array();
2412        disk = json_string(disk_str);
2413
2414        for (unsigned int i = 0; i < partition_len; ++i) {
2415                object = json_object();
2416                if (!object) {
2417                        json_decref(root);
2418                        return -1;
2419                }
2420
2421                part = json_string(part_cfg[i].partition);
2422                fs = json_string(part_cfg[i].filesystem);
2423                format = json_string(part_cfg[i].format);
2424                code = json_string(part_cfg[i].code);
2425                size = json_string(part_cfg[i].size);
2426
2427                json_object_set_new(object, "partition", part);
2428                json_object_set_new(object, "filesystem", fs);
2429                json_object_set_new(object, "format", format);
2430                json_object_set_new(object, "code", code);
2431                json_object_set_new(object, "size", size);
2432
2433                json_array_append_new(partition_setup, object);
2434        }
2435
2436        json_object_set_new(root, "partition_setup", partition_setup);
2437        json_object_set_new(root, "cache_size", cache_size);
2438        json_object_set_new(root, "cache", cache);
2439        json_object_set_new(root, "disk", disk);
2440
2441        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2442
2443        return 0;
2444}
2445
2446static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2447{
2448        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2449
2450        return 0;
2451}
2452
2453static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2454{
2455        char legacy_cmd[32] = {};
2456        int err = -1;
2457
2458        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2459                syslog(LOG_ERR, "malformed database legacy input\n");
2460                return -1;
2461        }
2462        input = strchr(input, '\r') + 1;
2463
2464        if (!strcmp(legacy_cmd, "Arrancar")) {
2465                err = og_cmd_legacy_wol(input, cmd);
2466        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2467                err = og_cmd_legacy_shell_run(input, cmd);
2468        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2469                err = og_cmd_legacy_session(input, cmd);
2470        } else if (!strcmp(legacy_cmd, "Apagar")) {
2471                err = og_cmd_legacy_poweroff(input, cmd);
2472        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2473                err = og_cmd_legacy_refresh(input, cmd);
2474        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2475                err = og_cmd_legacy_reboot(input, cmd);
2476        } else if (!strcmp(legacy_cmd, "Purgar")) {
2477                err = og_cmd_legacy_stop(input, cmd);
2478        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2479                err = og_cmd_legacy_hardware(input, cmd);
2480        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2481                err = og_cmd_legacy_software(input, cmd);
2482        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2483                err = og_cmd_legacy_image_create(input, cmd);
2484        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2485                err = og_cmd_legacy_image_restore(input, cmd);
2486        } else if (!strcmp(legacy_cmd, "Configurar")) {
2487                err = og_cmd_legacy_setup(input, cmd);
2488        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2489                   !strcmp(legacy_cmd, "Actualizar")) {
2490                err = og_cmd_legacy_run_schedule(input, cmd);
2491        }
2492
2493        return err;
2494}
2495
2496static int og_dbi_add_action(const struct og_dbi *dbi, const struct og_task *task,
2497                             struct og_cmd *cmd)
2498{
2499        char start_date_string[24];
2500        struct tm *start_date;
2501        const char *msglog;
2502        dbi_result result;
2503        time_t now;
2504
2505        time(&now);
2506        start_date = localtime(&now);
2507
2508        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2509                start_date->tm_year + 1900, start_date->tm_mon + 1,
2510                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2511                start_date->tm_sec);
2512        result = dbi_conn_queryf(dbi->conn,
2513                                "INSERT INTO acciones (idordenador, "
2514                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2515                                "sesion, idcomando, parametros, fechahorareg, "
2516                                "estado, resultado, ambito, idambito, "
2517                                "restrambito, idprocedimiento, idcentro, "
2518                                "idprogramacion) "
2519                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2520                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2521                                cmd->client_id, EJECUCION_TAREA, task->task_id,
2522                                "", cmd->ip, 0, task->command_id,
2523                                task->params, start_date_string,
2524                                ACCION_INICIADA, ACCION_SINRESULTADO,
2525                                task->type_scope, task->scope, "",
2526                                task->procedure_id, task->center_id,
2527                                task->schedule_id);
2528        if (!result) {
2529                dbi_conn_error(dbi->conn, &msglog);
2530                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2531                       __func__, __LINE__, msglog);
2532                return -1;
2533        }
2534        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
2535        dbi_result_free(result);
2536
2537        return 0;
2538}
2539
2540static int og_queue_task_command(struct og_dbi *dbi, const struct og_task *task,
2541                                 char *query)
2542{
2543        struct og_cmd *cmd;
2544        const char *msglog;
2545        dbi_result result;
2546
2547        result = dbi_conn_queryf(dbi->conn, query);
2548        if (!result) {
2549                dbi_conn_error(dbi->conn, &msglog);
2550                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2551                       __func__, __LINE__, msglog);
2552                return -1;
2553        }
2554
2555        while (dbi_result_next_row(result)) {
2556                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2557                if (!cmd) {
2558                        dbi_result_free(result);
2559                        return -1;
2560                }
2561
2562                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2563                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2564                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2565
2566                og_cmd_legacy(task->params, cmd);
2567
2568                if (task->procedure_id) {
2569                        if (og_dbi_add_action(dbi, task, cmd)) {
2570                                dbi_result_free(result);
2571                                return -1;
2572                        }
2573                } else {
2574                        cmd->id = task->task_id;
2575                }
2576
2577                list_add_tail(&cmd->list, &cmd_list);
2578        }
2579
2580        dbi_result_free(result);
2581
2582        return 0;
2583}
2584
2585static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2586                                       char *query)
2587{
2588
2589        const char *msglog;
2590        dbi_result result;
2591
2592        result = dbi_conn_queryf(dbi->conn, query);
2593        if (!result) {
2594                dbi_conn_error(dbi->conn, &msglog);
2595                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2596                       __func__, __LINE__, msglog);
2597                return -1;
2598        }
2599
2600        while (dbi_result_next_row(result)) {
2601                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2602
2603                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2604                                "WHERE grupoid=%d", group_id);
2605                if (og_queue_task_group_clients(dbi, task, query)) {
2606                        dbi_result_free(result);
2607                        return -1;
2608                }
2609
2610                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2611                              "WHERE grupoid=%d", group_id);
2612                if (og_queue_task_command(dbi, task, query)) {
2613                        dbi_result_free(result);
2614                        return -1;
2615                }
2616
2617        }
2618
2619        dbi_result_free(result);
2620
2621        return 0;
2622}
2623
2624static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2625                                          struct og_task *task, char *query)
2626{
2627
2628        const char *msglog;
2629        dbi_result result;
2630
2631        result = dbi_conn_queryf(dbi->conn, query);
2632        if (!result) {
2633                dbi_conn_error(dbi->conn, &msglog);
2634                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2635                       __func__, __LINE__, msglog);
2636                return -1;
2637        }
2638
2639        while (dbi_result_next_row(result)) {
2640                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2641
2642                sprintf(query, "SELECT idgrupo FROM grupos "
2643                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2644                if (og_queue_task_group_classrooms(dbi, task, query)) {
2645                        dbi_result_free(result);
2646                        return -1;
2647                }
2648
2649                sprintf(query,
2650                        "SELECT ip,mac,idordenador "
2651                        "FROM ordenadores INNER JOIN aulas "
2652                        "WHERE ordenadores.idaula=aulas.idaula "
2653                        "AND aulas.grupoid=%d",
2654                        group_id);
2655                if (og_queue_task_command(dbi, task, query)) {
2656                        dbi_result_free(result);
2657                        return -1;
2658                }
2659
2660        }
2661
2662        dbi_result_free(result);
2663
2664        return 0;
2665}
2666
2667static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2668{
2669        char query[4096];
2670
2671        switch (task->type_scope) {
2672                case AMBITO_CENTROS:
2673                        sprintf(query,
2674                                "SELECT ip,mac,idordenador "
2675                                "FROM ordenadores INNER JOIN aulas "
2676                                "WHERE ordenadores.idaula=aulas.idaula "
2677                                "AND idcentro=%d",
2678                                task->scope);
2679                        return og_queue_task_command(dbi, task, query);
2680                case AMBITO_GRUPOSAULAS:
2681                        sprintf(query,
2682                                "SELECT idgrupo FROM grupos "
2683                                "WHERE idgrupo=%i AND tipo=%d",
2684                                task->scope, AMBITO_GRUPOSAULAS);
2685                        return og_queue_task_group_classrooms(dbi, task, query);
2686                case AMBITO_AULAS:
2687                        sprintf(query,
2688                                "SELECT ip,mac,idordenador FROM ordenadores "
2689                                "WHERE idaula=%d",
2690                                task->scope);
2691                        return og_queue_task_command(dbi, task, query);
2692                case AMBITO_GRUPOSORDENADORES:
2693                        sprintf(query,
2694                                "SELECT idgrupo FROM gruposordenadores "
2695                                "WHERE idgrupo = %d",
2696                                task->scope);
2697                        return og_queue_task_group_clients(dbi, task, query);
2698                case AMBITO_ORDENADORES:
2699                        sprintf(query,
2700                                "SELECT ip, mac, idordenador FROM ordenadores "
2701                                "WHERE idordenador = %d",
2702                                task->scope);
2703                        return og_queue_task_command(dbi, task, query);
2704        }
2705        return 0;
2706}
2707
2708int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2709{
2710        uint32_t procedure_id;
2711        const char *msglog;
2712        dbi_result result;
2713
2714        result = dbi_conn_queryf(dbi->conn,
2715                        "SELECT parametros, procedimientoid, idcomando "
2716                        "FROM procedimientos_acciones "
2717                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2718        if (!result) {
2719                dbi_conn_error(dbi->conn, &msglog);
2720                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2721                       __func__, __LINE__, msglog);
2722                return -1;
2723        }
2724
2725        while (dbi_result_next_row(result)) {
2726                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2727                if (procedure_id > 0) {
2728                        task->procedure_id = procedure_id;
2729                        if (og_dbi_queue_procedure(dbi, task))
2730                                return -1;
2731                        continue;
2732                }
2733
2734                task->params    = strdup(dbi_result_get_string(result, "parametros"));
2735                task->command_id = dbi_result_get_uint(result, "idcomando");
2736                if (og_queue_task_clients(dbi, task))
2737                        return -1;
2738        }
2739
2740        dbi_result_free(result);
2741
2742        return 0;
2743}
2744
2745static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
2746                             uint32_t schedule_id)
2747{
2748        struct og_task task = {};
2749        uint32_t task_id_next;
2750        const char *msglog;
2751        dbi_result result;
2752
2753        task.schedule_id = schedule_id;
2754
2755        result = dbi_conn_queryf(dbi->conn,
2756                        "SELECT tareas_acciones.orden, "
2757                                "tareas_acciones.idprocedimiento, "
2758                                "tareas_acciones.tareaid, "
2759                                "tareas.idtarea, "
2760                                "tareas.idcentro, "
2761                                "tareas.ambito, "
2762                                "tareas.idambito, "
2763                                "tareas.restrambito "
2764                        " FROM tareas"
2765                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
2766                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
2767        if (!result) {
2768                dbi_conn_error(dbi->conn, &msglog);
2769                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2770                       __func__, __LINE__, msglog);
2771                return -1;
2772        }
2773
2774        while (dbi_result_next_row(result)) {
2775                task_id_next = dbi_result_get_uint(result, "tareaid");
2776
2777                if (task_id_next > 0) {
2778                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
2779                                return -1;
2780
2781                        continue;
2782                }
2783                task.task_id = dbi_result_get_uint(result, "idtarea");
2784                task.center_id = dbi_result_get_uint(result, "idcentro");
2785                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
2786                task.type_scope = dbi_result_get_uint(result, "ambito");
2787                task.scope = dbi_result_get_uint(result, "idambito");
2788                task.filtered_scope = dbi_result_get_string(result, "restrambito");
2789
2790                og_dbi_queue_procedure(dbi, &task);
2791        }
2792
2793        dbi_result_free(result);
2794
2795        return 0;
2796}
2797
2798static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
2799                                uint32_t schedule_id)
2800{
2801        struct og_task task = {};
2802        const char *msglog;
2803        dbi_result result;
2804        char query[4096];
2805
2806        result = dbi_conn_queryf(dbi->conn,
2807                        "SELECT idaccion, idcentro, idordenador, parametros "
2808                        "FROM acciones "
2809                        "WHERE sesion = %u", task_id);
2810        if (!result) {
2811                dbi_conn_error(dbi->conn, &msglog);
2812                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2813                       __func__, __LINE__, msglog);
2814                return -1;
2815        }
2816
2817        while (dbi_result_next_row(result)) {
2818                task.task_id = dbi_result_get_uint(result, "idaccion");
2819                task.center_id = dbi_result_get_uint(result, "idcentro");
2820                task.scope = dbi_result_get_uint(result, "idordenador");
2821                task.params = strdup(dbi_result_get_string(result, "parametros"));
2822
2823                sprintf(query,
2824                        "SELECT ip, mac, idordenador FROM ordenadores "
2825                        "WHERE idordenador = %d",
2826                        task.scope);
2827                if (og_queue_task_command(dbi, &task, query)) {
2828                        dbi_result_free(result);
2829                        return -1;
2830                }
2831        }
2832
2833        dbi_result_free(result);
2834
2835        return 0;
2836}
2837
2838int og_dbi_update_action(uint32_t id, bool success)
2839{
2840        char end_date_string[24];
2841        struct tm *end_date;
2842        const char *msglog;
2843        struct og_dbi *dbi;
2844        uint8_t status = 2;
2845        dbi_result result;
2846        time_t now;
2847
2848        if (!id)
2849                return 0;
2850
2851        dbi = og_dbi_open(&ogconfig.db);
2852        if (!dbi) {
2853                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2854                       __func__, __LINE__);
2855                return -1;
2856        }
2857
2858        time(&now);
2859        end_date = localtime(&now);
2860
2861        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2862                end_date->tm_year + 1900, end_date->tm_mon + 1,
2863                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
2864                end_date->tm_sec);
2865        result = dbi_conn_queryf(dbi->conn,
2866                                 "UPDATE acciones SET fechahorafin='%s', "
2867                                 "estado=%d, resultado=%d WHERE idaccion=%d",
2868                                 end_date_string, ACCION_FINALIZADA,
2869                                 status - success, id);
2870
2871        if (!result) {
2872                dbi_conn_error(dbi->conn, &msglog);
2873                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2874                       __func__, __LINE__, msglog);
2875                og_dbi_close(dbi);
2876                return -1;
2877        }
2878        dbi_result_free(result);
2879        og_dbi_close(dbi);
2880
2881        return 0;
2882}
2883
2884void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
2885                     enum og_schedule_type type)
2886{
2887        struct og_msg_params params = {};
2888        bool duplicated = false;
2889        struct og_cmd *cmd, *next;
2890        struct og_dbi *dbi;
2891        unsigned int i;
2892
2893        dbi = og_dbi_open(&ogconfig.db);
2894        if (!dbi) {
2895                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2896                       __func__, __LINE__);
2897                return;
2898        }
2899
2900        switch (type) {
2901        case OG_SCHEDULE_TASK:
2902                og_dbi_queue_task(dbi, task_id, schedule_id);
2903                break;
2904        case OG_SCHEDULE_PROCEDURE:
2905        case OG_SCHEDULE_COMMAND:
2906                og_dbi_queue_command(dbi, task_id, schedule_id);
2907                break;
2908        }
2909        og_dbi_close(dbi);
2910
2911        list_for_each_entry(cmd, &cmd_list, list) {
2912                for (i = 0; i < params.ips_array_len; i++) {
2913                        if (!strncmp(cmd->ip, params.ips_array[i],
2914                                     OG_DB_IP_MAXLEN)) {
2915                                duplicated = true;
2916                                break;
2917                        }
2918                }
2919
2920                if (!duplicated)
2921                        params.ips_array[params.ips_array_len++] = cmd->ip;
2922                else
2923                        duplicated = false;
2924        }
2925
2926        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2927                if (cmd->type != OG_CMD_WOL)
2928                        continue;
2929
2930                if (Levanta((char **)cmd->params.ips_array,
2931                            (char **)cmd->params.mac_array,
2932                            (char **)cmd->params.netmask_array,
2933                            cmd->params.ips_array_len,
2934                            (char *)cmd->params.wol_type))
2935                        og_dbi_update_action(cmd->id, true);
2936
2937                list_del(&cmd->list);
2938                og_cmd_free(cmd);
2939        }
2940
2941        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
2942}
2943
2944static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
2945{
2946        struct og_cmd *cmd;
2947        struct og_dbi *dbi;
2948        const char *key;
2949        json_t *value;
2950        int err;
2951
2952        if (json_typeof(element) != JSON_OBJECT)
2953                return -1;
2954
2955        json_object_foreach(element, key, value) {
2956                if (!strcmp(key, "task")) {
2957                        err = og_json_parse_string(value, &params->task_id);
2958                        params->flags |= OG_REST_PARAM_TASK;
2959                }
2960
2961                if (err < 0)
2962                        break;
2963        }
2964
2965        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
2966                return -1;
2967
2968        dbi = og_dbi_open(&ogconfig.db);
2969        if (!dbi) {
2970                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2971                           __func__, __LINE__);
2972                return -1;
2973        }
2974
2975        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
2976        og_dbi_close(dbi);
2977
2978        list_for_each_entry(cmd, &cmd_list, list)
2979                params->ips_array[params->ips_array_len++] = cmd->ip;
2980
2981        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2982                               NULL);
2983}
2984
2985static int og_dbi_scope_get_computer(struct og_dbi *dbi, json_t *array,
2986                                     uint32_t room_id)
2987{
2988        const char *computer_name, *computer_ip;
2989        uint32_t computer_id;
2990        const char *msglog;
2991        dbi_result result;
2992        json_t *computer;
2993
2994        result = dbi_conn_queryf(dbi->conn,
2995                                 "SELECT idordenador, nombreordenador, ip "
2996                                 "FROM ordenadores WHERE idaula=%d",
2997                                 room_id);
2998        if (!result) {
2999                dbi_conn_error(dbi->conn, &msglog);
3000                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3001                       __func__, __LINE__, msglog);
3002                return -1;
3003        }
3004
3005        while (dbi_result_next_row(result)) {
3006                computer_id = dbi_result_get_uint(result, "idordenador");
3007                computer_name = dbi_result_get_string(result, "nombreordenador");
3008                computer_ip = dbi_result_get_string(result, "ip");
3009
3010                computer = json_object();
3011                if (!computer) {
3012                        dbi_result_free(result);
3013                        return -1;
3014                }
3015
3016                json_object_set_new(computer, "name", json_string(computer_name));
3017                json_object_set_new(computer, "type", json_string("computer"));
3018                json_object_set_new(computer, "id", json_integer(computer_id));
3019                json_object_set_new(computer, "scope", json_array());
3020                json_object_set_new(computer, "ip", json_string(computer_ip));
3021                json_array_append(array, computer);
3022                json_decref(computer);
3023        }
3024        dbi_result_free(result);
3025
3026        return 0;
3027}
3028
3029static int og_dbi_scope_get_room(struct og_dbi *dbi, json_t *array,
3030                                 uint32_t center_id)
3031{
3032        char room_name[OG_DB_ROOM_NAME_MAXLEN + 1] = {};
3033        json_t *room, *room_array;
3034        const char *msglog;
3035        dbi_result result;
3036        uint32_t room_id;
3037
3038        result = dbi_conn_queryf(dbi->conn,
3039                                 "SELECT idaula, nombreaula FROM aulas WHERE "
3040                                 "idcentro=%d",
3041                                 center_id);
3042        if (!result) {
3043                dbi_conn_error(dbi->conn, &msglog);
3044                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3045                       __func__, __LINE__, msglog);
3046                return -1;
3047        }
3048
3049        while (dbi_result_next_row(result)) {
3050                room_id = dbi_result_get_uint(result, "idaula");
3051                strncpy(room_name,
3052                        dbi_result_get_string(result, "nombreaula"),
3053                        OG_DB_CENTER_NAME_MAXLEN);
3054
3055                room = json_object();
3056                if (!room) {
3057                        dbi_result_free(result);
3058                        return -1;
3059                }
3060
3061                json_object_set_new(room, "name", json_string(room_name));
3062                json_object_set_new(room, "type", json_string("room"));
3063                json_object_set_new(room, "id", json_integer(room_id));
3064                json_object_set_new(room, "scope", json_array());
3065                json_array_append(array, room);
3066                json_decref(room);
3067
3068                room_array = json_object_get(room, "scope");
3069                if (!room_array) {
3070                        dbi_result_free(result);
3071                        return -1;
3072                }
3073
3074                if (og_dbi_scope_get_computer(dbi, room_array, room_id)) {
3075                        dbi_result_free(result);
3076                        return -1;
3077                }
3078        }
3079        dbi_result_free(result);
3080
3081        return 0;
3082}
3083
3084static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
3085{
3086        char center_name[OG_DB_CENTER_NAME_MAXLEN + 1] = {};
3087        json_t *center, *array_room;
3088        const char *msglog;
3089        uint32_t center_id;
3090        dbi_result result;
3091
3092        result = dbi_conn_queryf(dbi->conn,
3093                                 "SELECT nombrecentro, idcentro FROM centros");
3094        if (!result) {
3095                dbi_conn_error(dbi->conn, &msglog);
3096                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3097                       __func__, __LINE__, msglog);
3098                return -1;
3099        }
3100
3101        while (dbi_result_next_row(result)) {
3102                center_id = dbi_result_get_uint(result, "idcentro");
3103                strncpy(center_name,
3104                        dbi_result_get_string(result, "nombrecentro"),
3105                        OG_DB_CENTER_NAME_MAXLEN);
3106
3107                center = json_object();
3108                if (!center) {
3109                        dbi_result_free(result);
3110                        return -1;
3111                }
3112
3113                array_room = json_array();
3114                if (!array_room) {
3115                        dbi_result_free(result);
3116                        json_decref(center);
3117                        return -1;
3118                }
3119
3120                json_object_set_new(center, "name", json_string(center_name));
3121                json_object_set_new(center, "type", json_string("center"));
3122                json_object_set_new(center, "id", json_integer(center_id));
3123                json_object_set_new(center, "scope", array_room);
3124                json_array_append(array, center);
3125                json_decref(center);
3126
3127                if (og_dbi_scope_get_room(dbi, array_room, center_id)) {
3128                        dbi_result_free(result);
3129                        return -1;
3130                }
3131        }
3132
3133        dbi_result_free(result);
3134
3135        return 0;
3136}
3137
3138static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
3139                            char *buffer_reply)
3140{
3141        struct og_buffer og_buffer = {
3142                .data = buffer_reply
3143        };
3144        json_t *root, *array;
3145        struct og_dbi *dbi;
3146
3147        root = json_object();
3148        if (!root)
3149                return -1;
3150
3151        array = json_array();
3152        if (!array) {
3153                json_decref(root);
3154                return -1;
3155        }
3156        json_object_set_new(root, "scope", array);
3157
3158        dbi = og_dbi_open(&ogconfig.db);
3159        if (!dbi) {
3160                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3161                       __func__, __LINE__);
3162                json_decref(root);
3163                return -1;
3164        }
3165
3166        if (og_dbi_scope_get(dbi, array)) {
3167                og_dbi_close(dbi);
3168                json_decref(root);
3169                return -1;
3170        }
3171
3172        og_dbi_close(dbi);
3173
3174        json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
3175        json_decref(root);
3176
3177        return 0;
3178}
3179
3180int og_dbi_schedule_get(void)
3181{
3182        uint32_t schedule_id, task_id;
3183        struct og_schedule_time time;
3184        struct og_dbi *dbi;
3185        const char *msglog;
3186        dbi_result result;
3187
3188        dbi = og_dbi_open(&ogconfig.db);
3189        if (!dbi) {
3190                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3191                       __func__, __LINE__);
3192                return -1;
3193        }
3194
3195        result = dbi_conn_queryf(dbi->conn,
3196                                 "SELECT idprogramacion, tipoaccion, identificador, "
3197                                 "sesion, annos, meses, diario, dias, semanas, horas, "
3198                                 "ampm, minutos FROM programaciones "
3199                                 "WHERE suspendida = 0");
3200        if (!result) {
3201                dbi_conn_error(dbi->conn, &msglog);
3202                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3203                       __func__, __LINE__, msglog);
3204                og_dbi_close(dbi);
3205                return -1;
3206        }
3207
3208        while (dbi_result_next_row(result)) {
3209                memset(&time, 0, sizeof(time));
3210                schedule_id = dbi_result_get_uint(result, "idprogramacion");
3211                task_id = dbi_result_get_uint(result, "identificador");
3212                time.years = dbi_result_get_uint(result, "annos");
3213                time.months = dbi_result_get_uint(result, "meses");
3214                time.weeks = dbi_result_get_uint(result, "semanas");
3215                time.week_days = dbi_result_get_uint(result, "dias");
3216                time.days = dbi_result_get_uint(result, "diario");
3217                time.hours = dbi_result_get_uint(result, "horas");
3218                time.am_pm = dbi_result_get_uint(result, "ampm");
3219                time.minutes = dbi_result_get_uint(result, "minutos");
3220                time.on_start = true;
3221
3222                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
3223                                   &time);
3224        }
3225
3226        dbi_result_free(result);
3227        og_dbi_close(dbi);
3228
3229        return 0;
3230}
3231
3232static int og_dbi_schedule_create(struct og_dbi *dbi,
3233                                  struct og_msg_params *params,
3234                                  uint32_t *schedule_id,
3235                                  enum og_schedule_type schedule_type)
3236{
3237        uint8_t suspended = 0;
3238        uint32_t session = 0;
3239        const char *msglog;
3240        dbi_result result;
3241        uint8_t type;
3242
3243        switch (schedule_type) {
3244        case OG_SCHEDULE_TASK:
3245                type = 3;
3246                break;
3247        case OG_SCHEDULE_PROCEDURE:
3248                type = 2;
3249                break;
3250        case OG_SCHEDULE_COMMAND:
3251                session = atoi(params->task_id);
3252                type = 1;
3253                break;
3254        }
3255
3256        result = dbi_conn_queryf(dbi->conn,
3257                                 "INSERT INTO programaciones (tipoaccion,"
3258                                 " identificador, nombrebloque, annos, meses,"
3259                                 " semanas, dias, diario, horas, ampm, minutos,"
3260                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
3261                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
3262                                 type, params->task_id, params->name,
3263                                 params->time.years, params->time.months,
3264                                 params->time.weeks, params->time.week_days,
3265                                 params->time.days, params->time.hours,
3266                                 params->time.am_pm, params->time.minutes,
3267                                 suspended, session);
3268        if (!result) {
3269                dbi_conn_error(dbi->conn, &msglog);
3270                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3271                       __func__, __LINE__, msglog);
3272                return -1;
3273        }
3274        dbi_result_free(result);
3275
3276        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
3277
3278        return 0;
3279}
3280
3281static int og_dbi_schedule_update(struct og_dbi *dbi,
3282                                  struct og_msg_params *params)
3283{
3284        const char *msglog;
3285        dbi_result result;
3286        uint8_t type = 3;
3287
3288        result = dbi_conn_queryf(dbi->conn,
3289                                 "UPDATE programaciones SET tipoaccion=%d, "
3290                                 "identificador='%s', nombrebloque='%s', "
3291                                 "annos=%d, meses=%d, "
3292                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
3293                                 "WHERE idprogramacion='%s'",
3294                                 type, params->task_id, params->name,
3295                                 params->time.years, params->time.months,
3296                                 params->time.days, params->time.hours,
3297                                 params->time.am_pm, params->time.minutes,
3298                                 params->id);
3299
3300        if (!result) {
3301                dbi_conn_error(dbi->conn, &msglog);
3302                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3303                       __func__, __LINE__, msglog);
3304                return -1;
3305        }
3306        dbi_result_free(result);
3307
3308        return 0;
3309}
3310
3311static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
3312{
3313        const char *msglog;
3314        dbi_result result;
3315
3316        result = dbi_conn_queryf(dbi->conn,
3317                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
3318                                 id);
3319        if (!result) {
3320                dbi_conn_error(dbi->conn, &msglog);
3321                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3322                       __func__, __LINE__, msglog);
3323                return -1;
3324        }
3325        dbi_result_free(result);
3326
3327        return 0;
3328}
3329
3330struct og_db_schedule {
3331        uint32_t                id;
3332        uint32_t                task_id;
3333        const char              *name;
3334        struct og_schedule_time time;
3335        uint32_t                week_days;
3336        uint32_t                weeks;
3337        uint32_t                suspended;
3338        uint32_t                session;
3339};
3340
3341static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
3342                                    const char *task_id, const char *schedule_id)
3343{
3344        struct og_db_schedule schedule;
3345        json_t *obj, *array;
3346        const char *msglog;
3347        dbi_result result;
3348        int err = 0;
3349
3350        if (task_id) {
3351                result = dbi_conn_queryf(dbi->conn,
3352                                         "SELECT idprogramacion,"
3353                                         "       identificador, nombrebloque,"
3354                                         "       annos, meses, diario, dias,"
3355                                         "       semanas, horas, ampm,"
3356                                         "       minutos,suspendida, sesion "
3357                                         "FROM programaciones "
3358                                         "WHERE identificador=%d",
3359                                         atoi(task_id));
3360        } else if (schedule_id) {
3361                result = dbi_conn_queryf(dbi->conn,
3362                                         "SELECT idprogramacion,"
3363                                         "       identificador, nombrebloque,"
3364                                         "       annos, meses, diario, dias,"
3365                                         "       semanas, horas, ampm,"
3366                                         "       minutos,suspendida, sesion "
3367                                         "FROM programaciones "
3368                                         "WHERE idprogramacion=%d",
3369                                         atoi(schedule_id));
3370        } else {
3371                result = dbi_conn_queryf(dbi->conn,
3372                                         "SELECT idprogramacion,"
3373                                         "       identificador, nombrebloque,"
3374                                         "       annos, meses, diario, dias,"
3375                                         "       semanas, horas, ampm,"
3376                                         "       minutos,suspendida, sesion "
3377                                         "FROM programaciones");
3378        }
3379
3380        if (!result) {
3381                dbi_conn_error(dbi->conn, &msglog);
3382                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3383                       __func__, __LINE__, msglog);
3384                return -1;
3385        }
3386
3387        array = json_array();
3388        if (!array)
3389                return -1;
3390
3391        while (dbi_result_next_row(result)) {
3392                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3393                schedule.task_id = dbi_result_get_uint(result, "identificador");
3394                schedule.name = dbi_result_get_string(result, "nombrebloque");
3395                schedule.time.years = dbi_result_get_uint(result, "annos");
3396                schedule.time.months = dbi_result_get_uint(result, "meses");
3397                schedule.time.days = dbi_result_get_uint(result, "diario");
3398                schedule.time.hours = dbi_result_get_uint(result, "horas");
3399                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3400                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3401                schedule.week_days = dbi_result_get_uint(result, "dias");
3402                schedule.weeks = dbi_result_get_uint(result, "semanas");
3403                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3404                schedule.session = dbi_result_get_uint(result, "sesion");
3405
3406                obj = json_object();
3407                if (!obj) {
3408                        err = -1;
3409                        break;
3410                }
3411                json_object_set_new(obj, "id", json_integer(schedule.id));
3412                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3413                json_object_set_new(obj, "name", json_string(schedule.name));
3414                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3415                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3416                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3417                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3418                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3419                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3420                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3421                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3422                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3423                json_object_set_new(obj, "session", json_integer(schedule.session));
3424
3425                json_array_append_new(array, obj);
3426        }
3427
3428        json_object_set_new(root, "schedule", array);
3429
3430        dbi_result_free(result);
3431
3432        return err;
3433}
3434
3435static int og_task_schedule_create(struct og_msg_params *params)
3436{
3437        enum og_schedule_type type;
3438        uint32_t schedule_id;
3439        struct og_dbi *dbi;
3440        int err;
3441
3442        if (!strcmp(params->type, "task"))
3443                type = OG_SCHEDULE_TASK;
3444        else if (!strcmp(params->type, "procedure"))
3445                type = OG_SCHEDULE_PROCEDURE;
3446        else if (!strcmp(params->type, "command"))
3447                type = OG_SCHEDULE_COMMAND;
3448        else
3449                return -1;
3450
3451        dbi = og_dbi_open(&ogconfig.db);
3452        if (!dbi) {
3453                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3454                       __func__, __LINE__);
3455                return -1;
3456        }
3457
3458        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3459        if (err < 0) {
3460                og_dbi_close(dbi);
3461                return -1;
3462        }
3463        og_schedule_create(schedule_id, atoi(params->task_id), type,
3464                           &params->time);
3465        og_schedule_refresh(og_loop);
3466        og_dbi_close(dbi);
3467
3468        return 0;
3469}
3470
3471static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3472{
3473        const char *key;
3474        json_t *value;
3475        int err;
3476
3477        if (json_typeof(element) != JSON_OBJECT)
3478                return -1;
3479
3480        json_object_foreach(element, key, value) {
3481                if (!strcmp(key, "task")) {
3482                        err = og_json_parse_string(value, &params->task_id);
3483                        params->flags |= OG_REST_PARAM_TASK;
3484                } else if (!strcmp(key, "name")) {
3485                        err = og_json_parse_string(value, &params->name);
3486                        params->flags |= OG_REST_PARAM_NAME;
3487                } else if (!strcmp(key, "when")) {
3488                        err = og_json_parse_time_params(value, params);
3489                } else if (!strcmp(key, "type")) {
3490                        err = og_json_parse_string(value, &params->type);
3491                        params->flags |= OG_REST_PARAM_TYPE;
3492                }
3493
3494                if (err < 0)
3495                        break;
3496        }
3497
3498        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3499                                            OG_REST_PARAM_NAME |
3500                                            OG_REST_PARAM_TIME_YEARS |
3501                                            OG_REST_PARAM_TIME_MONTHS |
3502                                            OG_REST_PARAM_TIME_WEEKS |
3503                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3504                                            OG_REST_PARAM_TIME_DAYS |
3505                                            OG_REST_PARAM_TIME_HOURS |
3506                                            OG_REST_PARAM_TIME_MINUTES |
3507                                            OG_REST_PARAM_TIME_AM_PM |
3508                                            OG_REST_PARAM_TYPE))
3509                return -1;
3510
3511        return og_task_schedule_create(params);
3512}
3513
3514static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3515{
3516        struct og_dbi *dbi;
3517        const char *key;
3518        json_t *value;
3519        int err;
3520
3521        if (json_typeof(element) != JSON_OBJECT)
3522                return -1;
3523
3524        json_object_foreach(element, key, value) {
3525                if (!strcmp(key, "id")) {
3526                        err = og_json_parse_string(value, &params->id);
3527                        params->flags |= OG_REST_PARAM_ID;
3528                } else if (!strcmp(key, "task")) {
3529                        err = og_json_parse_string(value, &params->task_id);
3530                        params->flags |= OG_REST_PARAM_TASK;
3531                } else if (!strcmp(key, "name")) {
3532                        err = og_json_parse_string(value, &params->name);
3533                        params->flags |= OG_REST_PARAM_NAME;
3534                } else if (!strcmp(key, "when"))
3535                        err = og_json_parse_time_params(value, params);
3536
3537                if (err < 0)
3538                        break;
3539        }
3540
3541        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3542                                            OG_REST_PARAM_TASK |
3543                                            OG_REST_PARAM_NAME |
3544                                            OG_REST_PARAM_TIME_YEARS |
3545                                            OG_REST_PARAM_TIME_MONTHS |
3546                                            OG_REST_PARAM_TIME_DAYS |
3547                                            OG_REST_PARAM_TIME_HOURS |
3548                                            OG_REST_PARAM_TIME_MINUTES |
3549                                            OG_REST_PARAM_TIME_AM_PM))
3550                return -1;
3551
3552        dbi = og_dbi_open(&ogconfig.db);
3553        if (!dbi) {
3554                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3555                           __func__, __LINE__);
3556                return -1;
3557        }
3558
3559        err = og_dbi_schedule_update(dbi, params);
3560        og_dbi_close(dbi);
3561
3562        if (err < 0)
3563                return err;
3564
3565        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3566                           &params->time);
3567        og_schedule_refresh(og_loop);
3568
3569        return err;
3570}
3571
3572static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3573{
3574        struct og_dbi *dbi;
3575        const char *key;
3576        json_t *value;
3577        int err;
3578
3579        if (json_typeof(element) != JSON_OBJECT)
3580                return -1;
3581
3582        json_object_foreach(element, key, value) {
3583                if (!strcmp(key, "id")) {
3584                        err = og_json_parse_string(value, &params->id);
3585                        params->flags |= OG_REST_PARAM_ID;
3586                } else {
3587                        return -1;
3588                }
3589
3590                if (err < 0)
3591                        break;
3592        }
3593
3594        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3595                return -1;
3596
3597        dbi = og_dbi_open(&ogconfig.db);
3598        if (!dbi) {
3599                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3600                           __func__, __LINE__);
3601                return -1;
3602        }
3603
3604        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3605        og_dbi_close(dbi);
3606
3607        og_schedule_delete(og_loop, atoi(params->id));
3608
3609        return err;
3610}
3611
3612static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3613                               char *buffer_reply)
3614{
3615        struct og_buffer og_buffer = {
3616                .data   = buffer_reply,
3617        };
3618        json_t *schedule_root;
3619        struct og_dbi *dbi;
3620        const char *key;
3621        json_t *value;
3622        int err;
3623
3624        if (element) {
3625                if (json_typeof(element) != JSON_OBJECT)
3626                        return -1;
3627
3628                json_object_foreach(element, key, value) {
3629                        if (!strcmp(key, "task")) {
3630                                err = og_json_parse_string(value,
3631                                                           &params->task_id);
3632                        } else if (!strcmp(key, "id")) {
3633                                err = og_json_parse_string(value, &params->id);
3634                        } else {
3635                                return -1;
3636                        }
3637
3638                        if (err < 0)
3639                                break;
3640                }
3641        }
3642
3643        dbi = og_dbi_open(&ogconfig.db);
3644        if (!dbi) {
3645                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3646                           __func__, __LINE__);
3647                return -1;
3648        }
3649
3650        schedule_root = json_object();
3651        if (!schedule_root) {
3652                og_dbi_close(dbi);
3653                return -1;
3654        }
3655
3656        err = og_dbi_schedule_get_json(dbi, schedule_root,
3657                                       params->task_id, params->id);
3658        og_dbi_close(dbi);
3659
3660        if (err >= 0)
3661                json_dump_callback(schedule_root, og_json_dump_clients, &og_buffer, 0);
3662
3663        json_decref(schedule_root);
3664
3665        return err;
3666}
3667
3668static int og_client_method_not_found(struct og_client *cli)
3669{
3670        /* To meet RFC 7231, this function MUST generate an Allow header field
3671         * containing the correct methods. For example: "Allow: POST\r\n"
3672         */
3673        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
3674                     "Content-Length: 0\r\n\r\n";
3675
3676        send(og_client_socket(cli), buf, strlen(buf), 0);
3677
3678        return -1;
3679}
3680
3681static int og_client_bad_request(struct og_client *cli)
3682{
3683        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
3684
3685        send(og_client_socket(cli), buf, strlen(buf), 0);
3686
3687        return -1;
3688}
3689
3690static int og_client_not_found(struct og_client *cli)
3691{
3692        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
3693
3694        send(og_client_socket(cli), buf, strlen(buf), 0);
3695
3696        return -1;
3697}
3698
3699static int og_client_not_authorized(struct og_client *cli)
3700{
3701        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
3702                     "WWW-Authenticate: Basic\r\n"
3703                     "Content-Length: 0\r\n\r\n";
3704
3705        send(og_client_socket(cli), buf, strlen(buf), 0);
3706
3707        return -1;
3708}
3709
3710static int og_server_internal_error(struct og_client *cli)
3711{
3712        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
3713                     "Content-Length: 0\r\n\r\n";
3714
3715        send(og_client_socket(cli), buf, strlen(buf), 0);
3716
3717        return -1;
3718}
3719
3720#define OG_MSG_RESPONSE_MAXLEN  65536
3721
3722static int og_client_ok(struct og_client *cli, char *buf_reply)
3723{
3724        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
3725        int err = 0, len;
3726
3727        len = snprintf(buf, sizeof(buf),
3728                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
3729                       strlen(buf_reply), buf_reply);
3730        if (len >= (int)sizeof(buf))
3731                err = og_server_internal_error(cli);
3732
3733        send(og_client_socket(cli), buf, strlen(buf), 0);
3734
3735        return err;
3736}
3737
3738int og_client_state_process_payload_rest(struct og_client *cli)
3739{
3740        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
3741        struct og_msg_params params = {};
3742        enum og_rest_method method;
3743        const char *cmd, *body;
3744        json_error_t json_err;
3745        json_t *root = NULL;
3746        int err = 0;
3747
3748        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
3749               inet_ntoa(cli->addr.sin_addr),
3750               ntohs(cli->addr.sin_port), cli->buf);
3751
3752        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
3753                method = OG_METHOD_GET;
3754                cmd = cli->buf + strlen("GET") + 2;
3755        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
3756                method = OG_METHOD_POST;
3757                cmd = cli->buf + strlen("POST") + 2;
3758        } else
3759                return og_client_method_not_found(cli);
3760
3761        body = strstr(cli->buf, "\r\n\r\n") + 4;
3762
3763        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
3764                syslog(LOG_ERR, "wrong Authentication key\n");
3765                return og_client_not_authorized(cli);
3766        }
3767
3768        if (cli->content_length) {
3769                root = json_loads(body, 0, &json_err);
3770                if (!root) {
3771                        syslog(LOG_ERR, "malformed json line %d: %s\n",
3772                               json_err.line, json_err.text);
3773                        return og_client_not_found(cli);
3774                }
3775        }
3776
3777        if (!strncmp(cmd, "clients", strlen("clients"))) {
3778                if (method != OG_METHOD_POST &&
3779                    method != OG_METHOD_GET)
3780                        return og_client_method_not_found(cli);
3781
3782                if (method == OG_METHOD_POST && !root) {
3783                        syslog(LOG_ERR, "command clients with no payload\n");
3784                        return og_client_bad_request(cli);
3785                }
3786                switch (method) {
3787                case OG_METHOD_POST:
3788                        err = og_cmd_post_clients(root, &params);
3789                        break;
3790                case OG_METHOD_GET:
3791                        err = og_cmd_get_clients(root, &params, buf_reply);
3792                        break;
3793                default:
3794                        return og_client_bad_request(cli);
3795                }
3796        } else if (!strncmp(cmd, "client/setup",
3797                            strlen("client/setup"))) {
3798                if (method != OG_METHOD_GET)
3799                        return og_client_method_not_found(cli);
3800
3801                if (!root) {
3802                        syslog(LOG_ERR,
3803                               "command client partitions with no payload\n");
3804                        return og_client_bad_request(cli);
3805                }
3806
3807                err = og_cmd_get_client_setup(root, &params, buf_reply);
3808        } else if (!strncmp(cmd, "client/info",
3809                            strlen("client/info"))) {
3810                if (method != OG_METHOD_GET)
3811                        return og_client_method_not_found(cli);
3812
3813                if (!root) {
3814                        syslog(LOG_ERR,
3815                               "command client info with no payload\n");
3816                        return og_client_bad_request(cli);
3817                }
3818
3819                err = og_cmd_get_client_info(root, &params, buf_reply);
3820        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
3821                if (method != OG_METHOD_POST)
3822                        return og_client_method_not_found(cli);
3823
3824                if (!root) {
3825                        syslog(LOG_ERR,
3826                               "command client info with no payload\n");
3827                        return og_client_bad_request(cli);
3828                }
3829
3830                err = og_cmd_post_client_add(root, &params, buf_reply);
3831        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
3832                if (method != OG_METHOD_POST)
3833                        return og_client_method_not_found(cli);
3834
3835                if (!root) {
3836                        syslog(LOG_ERR,
3837                               "command client delete with no payload\n");
3838                        return og_client_bad_request(cli);
3839                }
3840
3841                err = og_cmd_post_client_delete(root, &params);
3842        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
3843                if (method != OG_METHOD_POST)
3844                        return og_client_method_not_found(cli);
3845
3846                if (!root) {
3847                        syslog(LOG_ERR, "command wol with no payload\n");
3848                        return og_client_bad_request(cli);
3849                }
3850                err = og_cmd_wol(root, &params);
3851        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
3852                if (method != OG_METHOD_POST)
3853                        return og_client_method_not_found(cli);
3854
3855                if (!root) {
3856                        syslog(LOG_ERR, "command run with no payload\n");
3857                        return og_client_bad_request(cli);
3858                }
3859                err = og_cmd_run_post(root, &params);
3860        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
3861                if (method != OG_METHOD_POST)
3862                        return og_client_method_not_found(cli);
3863
3864                if (!root) {
3865                        syslog(LOG_ERR, "command output with no payload\n");
3866                        return og_client_bad_request(cli);
3867                }
3868
3869                err = og_cmd_run_get(root, &params, buf_reply);
3870        } else if (!strncmp(cmd, "session", strlen("session"))) {
3871                if (method != OG_METHOD_POST && method != OG_METHOD_GET)
3872                        return og_client_method_not_found(cli);
3873
3874                if (!root) {
3875                        syslog(LOG_ERR, "command session with no payload\n");
3876                        return og_client_bad_request(cli);
3877                }
3878
3879                if (method == OG_METHOD_POST)
3880                        err = og_cmd_session(root, &params);
3881                else
3882                        err = og_cmd_get_session(root, &params, buf_reply);
3883        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
3884                if (method != OG_METHOD_GET)
3885                        return og_client_method_not_found(cli);
3886
3887                if (root) {
3888                        syslog(LOG_ERR, "command scopes with payload\n");
3889                        return og_client_bad_request(cli);
3890                }
3891
3892                err = og_cmd_scope_get(root, &params, buf_reply);
3893        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
3894                if (method != OG_METHOD_POST)
3895                        return og_client_method_not_found(cli);
3896
3897                if (!root) {
3898                        syslog(LOG_ERR, "command poweroff with no payload\n");
3899                        return og_client_bad_request(cli);
3900                }
3901                err = og_cmd_poweroff(root, &params);
3902        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
3903                if (method != OG_METHOD_POST)
3904                        return og_client_method_not_found(cli);
3905
3906                if (!root) {
3907                        syslog(LOG_ERR, "command reboot with no payload\n");
3908                        return og_client_bad_request(cli);
3909                }
3910                err = og_cmd_reboot(root, &params);
3911        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
3912                if (method != OG_METHOD_GET && method != OG_METHOD_POST)
3913                        return og_client_method_not_found(cli);
3914
3915                if (method == OG_METHOD_POST && !root) {
3916                        syslog(LOG_ERR, "command mode with no payload\n");
3917                        return og_client_bad_request(cli);
3918                }
3919
3920                if (method == OG_METHOD_GET)
3921                        err = og_cmd_get_modes(root, &params, buf_reply);
3922                else if (method == OG_METHOD_POST)
3923                        err = og_cmd_post_modes(root, &params);
3924        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
3925                if (method != OG_METHOD_POST)
3926                        return og_client_method_not_found(cli);
3927
3928                if (!root) {
3929                        syslog(LOG_ERR, "command stop with no payload\n");
3930                        return og_client_bad_request(cli);
3931                }
3932                err = og_cmd_stop(root, &params);
3933        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
3934                if (method != OG_METHOD_POST)
3935                        return og_client_method_not_found(cli);
3936
3937                if (!root) {
3938                        syslog(LOG_ERR, "command refresh with no payload\n");
3939                        return og_client_bad_request(cli);
3940                }
3941                err = og_cmd_refresh(root, &params);
3942        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
3943                if (method != OG_METHOD_GET && method != OG_METHOD_POST)
3944                        return og_client_method_not_found(cli);
3945
3946                if (!root) {
3947                        syslog(LOG_ERR, "command hardware with no payload\n");
3948                        return og_client_bad_request(cli);
3949                }
3950
3951                if (method == OG_METHOD_GET)
3952                        err = og_cmd_get_hardware(root, &params, buf_reply);
3953                else if (method == OG_METHOD_POST)
3954                        err = og_cmd_hardware(root, &params);
3955        } else if (!strncmp(cmd, "software", strlen("software"))) {
3956                if (method != OG_METHOD_POST && method != OG_METHOD_GET)
3957                        return og_client_method_not_found(cli);
3958
3959                if (!root) {
3960                        syslog(LOG_ERR, "command software with no payload\n");
3961                        return og_client_bad_request(cli);
3962                }
3963
3964                if (method == OG_METHOD_POST)
3965                        err = og_cmd_software(root, &params);
3966                else
3967                        err = og_cmd_get_software(root, &params, buf_reply);
3968        } else if (!strncmp(cmd, "images", strlen("images"))) {
3969                if (method != OG_METHOD_GET)
3970                        return og_client_method_not_found(cli);
3971
3972                if (!root)
3973                        err = og_cmd_images(buf_reply);
3974                else
3975                        return og_client_method_not_found(cli);
3976        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
3977                if (method != OG_METHOD_POST)
3978                        return og_client_method_not_found(cli);
3979
3980                if (!root) {
3981                        syslog(LOG_ERR, "command create with no payload\n");
3982                        return og_client_bad_request(cli);
3983                }
3984                err = og_cmd_create_image(root, &params);
3985        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
3986                if (method != OG_METHOD_POST)
3987                        return og_client_method_not_found(cli);
3988
3989                if (!root) {
3990                        syslog(LOG_ERR, "command create with no payload\n");
3991                        return og_client_bad_request(cli);
3992                }
3993                err = og_cmd_restore_image(root, &params);
3994        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
3995                if (method != OG_METHOD_POST)
3996                        return og_client_method_not_found(cli);
3997
3998                if (!root) {
3999                        syslog(LOG_ERR, "command create with no payload\n");
4000                        return og_client_bad_request(cli);
4001                }
4002                err = og_cmd_setup(root, &params);
4003        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4004                if (method != OG_METHOD_POST)
4005                        return og_client_method_not_found(cli);
4006
4007                if (!root) {
4008                        syslog(LOG_ERR, "command create with no payload\n");
4009                        return og_client_bad_request(cli);
4010                }
4011
4012                err = og_cmd_run_schedule(root, &params);
4013        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
4014                if (method != OG_METHOD_POST)
4015                        return og_client_method_not_found(cli);
4016
4017                if (!root) {
4018                        syslog(LOG_ERR, "command task with no payload\n");
4019                        return og_client_bad_request(cli);
4020                }
4021                err = og_cmd_task_post(root, &params);
4022        } else if (!strncmp(cmd, "schedule/create",
4023                            strlen("schedule/create"))) {
4024                if (method != OG_METHOD_POST)
4025                        return og_client_method_not_found(cli);
4026
4027                if (!root) {
4028                        syslog(LOG_ERR, "command task with no payload\n");
4029                        return og_client_bad_request(cli);
4030                }
4031                err = og_cmd_schedule_create(root, &params);
4032        } else if (!strncmp(cmd, "schedule/delete",
4033                            strlen("schedule/delete"))) {
4034                if (method != OG_METHOD_POST)
4035                        return og_client_method_not_found(cli);
4036
4037                if (!root) {
4038                        syslog(LOG_ERR, "command task with no payload\n");
4039                        return og_client_bad_request(cli);
4040                }
4041                err = og_cmd_schedule_delete(root, &params);
4042        } else if (!strncmp(cmd, "schedule/update",
4043                            strlen("schedule/update"))) {
4044                if (method != OG_METHOD_POST)
4045                        return og_client_method_not_found(cli);
4046
4047                if (!root) {
4048                        syslog(LOG_ERR, "command task with no payload\n");
4049                        return og_client_bad_request(cli);
4050                }
4051                err = og_cmd_schedule_update(root, &params);
4052        } else if (!strncmp(cmd, "schedule/get",
4053                            strlen("schedule/get"))) {
4054                if (method != OG_METHOD_POST)
4055                        return og_client_method_not_found(cli);
4056
4057                err = og_cmd_schedule_get(root, &params, buf_reply);
4058        } else {
4059                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
4060                err = og_client_not_found(cli);
4061        }
4062
4063        if (root)
4064                json_decref(root);
4065
4066        if (err < 0)
4067                return og_client_bad_request(cli);
4068
4069        err = og_client_ok(cli, buf_reply);
4070        if (err < 0) {
4071                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4072                       inet_ntoa(cli->addr.sin_addr),
4073                       ntohs(cli->addr.sin_port));
4074        }
4075
4076        return err;
4077}
Note: See TracBrowser for help on using the repository browser.