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

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

#1004 Add GET /images

This commit adds GET /images to the ogServer REST API.

This call returns information of all the images in ogServer.

Example response:

{

"images": [

{

"filename": "ubuntu.img",
"datasize": 2150400000,
"size": 613476223,
"modified": "Wed Sep 23 10:37:36 2020",
"permissions": "744"

},
{

"filename": "test.img",
"datasize": 2150400000,
"size": 613236475,
"modified": "Tue Sep 29 08:57:47 2020",
"permissions": "744"

}

],
"disk": {

"total": 52573995008,
"free": 39624544256

}

}

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