source: ogServer-Git/src/rest.c @ 8015f85

Last change on this file since 8015f85 was 8015f85, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

#915 Add GET /oglive/test REST API function

This function returns the installed and available ogLiveS in the server
to be booted from.

Request:
GET /oglive/list
NO BODY

Response
200 OK
{

"oglive": [

{

"distribution": "bionic",
"kernel": "5.4.0-40-generic",
"architecture": "amd64",
"revision": "r20200629",
"directory": "ogLive-5.4.0-r20200629",
"iso": "ogLive-bionic-5.4.0-40-generic-amd64-r20200629.85eceaf.iso"

},
{

"distribution": "bionic",
"kernel": "5.0.0-27-generic",
"architecture": "amd64",
"revision": "r20190830",
"directory": "ogLive-5.0.0-r20190830",
"iso": "ogLive-bionic-5.0.0-27-generic-amd64-r20190830.7208cc9.iso"

}

],
"default": 0

}

This commit also adds tests for GET /oglive/test.

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