source: ogServer-Git/src/rest.c @ 41bc66d

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

#997 Fix og_tm_hours_mask

Tests for e68fefe were made after 00pm (12:00) so we did not cover <12:00 cases
for immediate commands that are logged (scheduled for the exact moment
they are processed and ignored the fact they are stale so they are executed
right away)

In addition, libdbi was complaining about the data type used to
represent the hours, they were not being inserted properly. From syslog:

failed to query database (og_dbi_schedule_create:3288) 1264: Out of
range value for column 'horas' at row 1

Fix og_tm_hours_mask so <12:00 immediate schedule is handled correctly.
Change return type to uint16_t, as the 'hours' column type is smallint(4)

Fixes e68fefe ("#997 Set stale check flag when processing schedule/create")

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