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

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

#942 Add POST /client/add HTTP REST method

This method adds a new client. This new client's IP cannot be duplicated
in the DB.

Request:
POST /client/add
{

"boot": "19pxeADMIN",
"center": 0,
"hardware_id": 0,
"id": 2,
"ip": "192.168.56.12",
"livedir": "ogLive",
"mac": "0800270E6512",
"maintenance": true,
"name": "pc12",
"netdriver": "generic",
"netiface": "eth1",
"netmask": "255.255.255.0",
"remote": false,
"repo_id": 1,
"room": 1,
"serial_number": ""

}

Response:
200 OK

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